This commit is contained in:
Michael Schimmel
2026-01-04 17:06:59 +01:00
parent 8914d59607
commit a4afae6f39
10 changed files with 655 additions and 211 deletions
File diff suppressed because one or more lines are too long
+4 -4
View File
@@ -840,7 +840,7 @@ begin
var lastClose := 1000.0; var lastClose := 1000.0;
Randomize; Randomize;
var recDef := TRttiAstHelper.JsonToRecordDefinition(TRttiAstHelper.RecordDefinitionToJson<TOHLCV>); var recDef := TRttiAstHelper.JsonToRecordDefinition(TRttiAstHelper.RecordDefinitionToJson<TOHLCV>);
var series := TDataValue.FromRecordSeries(TScalarRecordSeries.Create(recDef)); var series := TScalarRecordSeries.Create(recDef) as IWriteableScalarRecordSeries;
var nw := Now; var nw := Now;
var ohlcvRec: TOHLCV; var ohlcvRec: TOHLCV;
for var i := 1 to numRecs do for var i := 1 to numRecs do
@@ -862,9 +862,9 @@ begin
values[5].AsInt64 := ohlcvRec.Volume; values[5].AsInt64 := ohlcvRec.Volume;
recordValue := TScalarRecord.Create(recDef, values); recordValue := TScalarRecord.Create(recDef, values);
series.AsRecordSeries.Add(recordValue, lookback); series.Add(recordValue, lookback);
if series.AsRecordSeries.TotalCount >= smaSlowLength then if series.TotalCount >= smaSlowLength then
begin begin
env.RootScope[seriesAddress] := series; env.RootScope[seriesAddress] := series;
@@ -1111,7 +1111,7 @@ begin
var testEnv := FEnvironment.CreateEnvironment; var testEnv := FEnvironment.CreateEnvironment;
testEnv.RootScope.Define('ohlcvSeries', TDataValue.FromRecordSeries(series)); testEnv.RootScope.Define('ohlcvSeries', series);
ast := ast :=
TAst.LambdaExpr( TAst.LambdaExpr(
-4
View File
@@ -121,7 +121,3 @@ Die Matrix-Invariante erfordert exakt gleiche Formen der Unterelemente.
* Konsolidierung von `IArgumentList`, `IParameterList` etc. zu einer allgemeinen Tupel-Repräsentation. * Konsolidierung von `IArgumentList`, `IParameterList` etc. zu einer allgemeinen Tupel-Repräsentation.
---
Soll ich nun mit der Implementierung der Typ-Erweiterungen in `Myc.Ast.Types.pas` beginnen?
+1 -1
View File
@@ -248,7 +248,7 @@ begin
raise ESpecializerException.CreateFmt('Internal Error: Failed to compile specialization for "%s"', [funcName]); raise ESpecializerException.CreateFmt('Internal Error: Failed to compile specialization for "%s"', [funcName]);
// 6b. Store in cache // 6b. Store in cache
var returnType := compiled.StaticType.Signatures[0].ReturnType; var returnType := compiled.StaticType.AsMethod.Signatures[0].ReturnType;
specializedMethod := TSpecializedMethod.Create(compiled.Func, returnType, compiled.IsPure); specializedMethod := TSpecializedMethod.Create(compiled.Func, returnType, compiled.IsPure);
FMonomorphCache.Add(key, specializedMethod); FMonomorphCache.Add(key, specializedMethod);
+11 -11
View File
@@ -542,7 +542,7 @@ begin
if not hasUnknownArgs then if not hasUnknownArgs then
begin begin
bestSig := nil; bestSig := nil;
for var sig in calleeType.Signatures do for var sig in calleeType.AsMethod.Signatures do
begin begin
if Length(sig.ParamTypes) <> Length(argTypes) then if Length(sig.ParamTypes) <> Length(argTypes) then
continue; continue;
@@ -603,9 +603,9 @@ begin
elemType := TTypes.Unknown; elemType := TTypes.Unknown;
if baseType.Kind = stSeries then if baseType.Kind = stSeries then
elemType := baseType.ElementType elemType := baseType.AsSeries.ElementType
else if baseType.Kind = stRecordSeries then else if baseType.Kind = stRecordSeries then
elemType := TTypes.CreateRecord(baseType.Definition); elemType := TTypes.CreateRecord(baseType.AsRecord.Definition);
elemType := ApplyOptionality(elemType, isOpt); elemType := ApplyOptionality(elemType, isOpt);
Result := TAst.Indexer(Node.Identity, newBase, newIndex, elemType); Result := TAst.Indexer(Node.Identity, newBase, newIndex, elemType);
@@ -626,10 +626,10 @@ begin
if (baseType.Kind = stRecord) or (baseType.Kind = stRecordSeries) then if (baseType.Kind = stRecord) or (baseType.Kind = stRecordSeries) then
begin begin
idx := baseType.Definition.IndexOf(M.Member.Value); idx := baseType.AsRecord.Definition.IndexOf(M.Member.Value);
if idx >= 0 then if idx >= 0 then
begin begin
var fieldType := TTypes.FromScalarKind(baseType.Definition[idx]); var fieldType := TTypes.FromScalarKind(baseType.AsRecord.Definition[idx]);
if baseType.Kind = stRecordSeries then if baseType.Kind = stRecordSeries then
resType := TTypes.CreateSeries(fieldType) resType := TTypes.CreateSeries(fieldType)
else else
@@ -768,7 +768,7 @@ begin
else if (sourceType.Kind = stRecordSeries) then else if (sourceType.Kind = stRecordSeries) then
begin begin
// 2. Verify Selectors exist in Record Definition // 2. Verify Selectors exist in Record Definition
var def := sourceType.Definition; var def := sourceType.AsRecord.Definition;
for var sel in P.Selectors do for var sel in P.Selectors do
begin begin
if def.IndexOf(sel.Value) < 0 then if def.IndexOf(sel.Value) < 0 then
@@ -816,7 +816,7 @@ begin
if streamType.Kind = stRecordSeries then if streamType.Kind = stRecordSeries then
begin begin
// Extract field type from definition // Extract field type from definition
var def := streamType.Definition; var def := streamType.AsRecord.Definition;
var idx := def.IndexOf(sel.Value); var idx := def.IndexOf(sel.Value);
if idx >= 0 then if idx >= 0 then
inferredType := TTypes.FromScalarKind(def[idx]); inferredType := TTypes.FromScalarKind(def[idx]);
@@ -824,8 +824,8 @@ begin
else if streamType.Kind = stSeries then else if streamType.Kind = stSeries then
begin begin
// If simple series, use its element type // If simple series, use its element type
if Assigned(streamType.ElementType) then if Assigned(streamType.AsSeries.ElementType) then
inferredType := streamType.ElementType inferredType := streamType.AsSeries.ElementType
else else
inferredType := TTypes.Ordinal; // Fallback default inferredType := TTypes.Ordinal; // Fallback default
end; end;
@@ -879,13 +879,13 @@ begin
var typedLambda := Accept(preTypedLambda).AsLambdaExpression; var typedLambda := Accept(preTypedLambda).AsLambdaExpression;
// 4. Infer Pipe Return Type & Validate Strictness // 4. Infer Pipe Return Type & Validate Strictness
var lambdaRetType := typedLambda.AsTypedNode.StaticType.Signatures[0].ReturnType; var lambdaRetType := typedLambda.AsTypedNode.StaticType.AsMethod.Signatures[0].ReturnType;
var pipeType: IStaticType; var pipeType: IStaticType;
if lambdaRetType.Kind = stRecord then if lambdaRetType.Kind = stRecord then
begin begin
// Valid: Record -> RecordSeries // Valid: Record -> RecordSeries
pipeType := TTypes.CreateRecordSeries(lambdaRetType.Definition); pipeType := TTypes.CreateRecordSeries(lambdaRetType.AsRecord.Definition);
end end
else else
begin begin
+1 -1
View File
@@ -446,7 +446,7 @@ begin
end; end;
end; end;
lambdaFunc := Visit(N.Transformation).AsMethod(); lambdaFunc := Visit(N.Transformation).AsMethod();
var outputDef := N.StaticType.Definition; var outputDef := N.StaticType.AsRecord.Definition;
var pipeAdapter: TPipeStream.TPipeLambda := var pipeAdapter: TPipeStream.TPipeLambda :=
function(const S: array of ISeries; out R: array of TScalar.TValue): Boolean function(const S: array of ISeries; out R: array of TScalar.TValue): Boolean
var var
-1
View File
@@ -588,7 +588,6 @@ var
predicateResult: TDataValue; predicateResult: TDataValue;
indexSeries: ISeries; indexSeries: ISeries;
mapperFunc: TDataValue.TFunc; mapperFunc: TDataValue.TFunc;
finalSeries: ISeries;
begin begin
if Length(Args) <> 2 then if Length(Args) <> 2 then
raise EArgumentException.Create('Where requires exactly two arguments: a series and a predicate function.'); raise EArgumentException.Create('Where requires exactly two arguments: a series and a predicate function.');
+592 -171
View File
File diff suppressed because it is too large Load Diff
+33 -5
View File
@@ -75,10 +75,9 @@ type
class operator Implicit(const AValue: TDataValue): TScalar; overload; inline; class operator Implicit(const AValue: TDataValue): TScalar; overload; inline;
class operator Implicit(const AValue: String): TDataValue; overload; inline; class operator Implicit(const AValue: String): TDataValue; overload; inline;
class operator Implicit(const AValue: TDataValue.TFunc): TDataValue; overload; inline; class operator Implicit(const AValue: TDataValue.TFunc): TDataValue; overload; inline;
class operator Implicit(const AValue: ITuple<TDataValue>): TDataValue; overload; inline;
class operator Implicit(const AValue: IKeywordMapping<TScalar>): TDataValue; overload; inline; class operator Implicit(const AValue: IKeywordMapping<TScalar>): TDataValue; overload; inline;
class operator Implicit(const AValue: IKeywordMapping<TDataValue>): TDataValue; overload; inline; class operator Implicit(const AValue: IKeywordMapping<TDataValue>): TDataValue; overload; inline;
class operator Implicit(const AValue: IWriteableScalarRecordSeries): TDataValue; overload; inline; class operator Implicit(const AValue: IWriteableScalarRecordSeries): TDataValue; overload; inline;
class operator Implicit(const AValue: ISeries): TDataValue; overload; inline; class operator Implicit(const AValue: ISeries): TDataValue; overload; inline;
class operator Implicit(const AValue: IStream): TDataValue; overload; inline; class operator Implicit(const AValue: IStream): TDataValue; overload; inline;
@@ -102,6 +101,7 @@ type
function AsScalar: TScalar; inline; function AsScalar: TScalar; inline;
function AsMethod: TFunc; inline; function AsMethod: TFunc; inline;
function AsText: String; inline; function AsText: String; inline;
function AsTuple: ITuple<TDataValue>; inline;
function AsRecordSeries: IWriteableScalarRecordSeries; inline; function AsRecordSeries: IWriteableScalarRecordSeries; inline;
function AsScalarRecord: IKeywordMapping<TScalar>; inline; function AsScalarRecord: IKeywordMapping<TScalar>; inline;
function AsRecord: IKeywordMapping<TDataValue>; inline; function AsRecord: IKeywordMapping<TDataValue>; inline;
@@ -364,6 +364,13 @@ begin
Result := (FInterface as TVal<String>).Value; Result := (FInterface as TVal<String>).Value;
end; end;
function TDataValue.AsTuple: ITuple<TDataValue>;
begin
if (FKind <> vkTuple) then
raise EInvalidCast.Create('Cannot read value as Tuple.');
Result := ITuple<TDataValue>(FInterface);
end;
function TDataValue.ToString: String; function TDataValue.ToString: String;
var var
sb: TStringBuilder; sb: TStringBuilder;
@@ -371,6 +378,7 @@ var
first: Boolean; first: Boolean;
i: Integer; i: Integer;
begin begin
first := True;
case FKind of case FKind of
vkScalar: Result := FScalar.ToString; vkScalar: Result := FScalar.ToString;
vkText: Result := '"' + AsText + '"'; vkText: Result := '"' + AsText + '"';
@@ -379,13 +387,29 @@ begin
var series := AsSeries; var series := AsSeries;
Result := Format('<series[%d]>', [series.Count]); Result := Format('<series[%d]>', [series.Count]);
end; end;
vkTuple:
begin
var tuple := AsTuple;
sb := TStringBuilder.Create;
try
for i := 0 to tuple.Count - 1 do
begin
if not first then
sb.Append(',');
sb.Append(tuple[i].Kind.ToString);
first := False;
end;
Result := Format('<tuple[%s]>', [sb.ToString]);
finally
sb.Free;
end;
end;
vkRecordSeries: vkRecordSeries:
begin begin
var series := AsRecordSeries; var series := AsRecordSeries;
sb := TStringBuilder.Create; sb := TStringBuilder.Create;
try try
sb.Append('{'); sb.Append('{');
first := True;
for i := 0 to series.Def.Count - 1 do for i := 0 to series.Def.Count - 1 do
begin begin
if not first then if not first then
@@ -405,7 +429,6 @@ begin
sb := TStringBuilder.Create; sb := TStringBuilder.Create;
try try
sb.Append('{'); sb.Append('{');
first := True;
for i := 0 to rec.Count - 1 do for i := 0 to rec.Count - 1 do
begin begin
if not first then if not first then
@@ -425,7 +448,6 @@ begin
sb := TStringBuilder.Create; sb := TStringBuilder.Create;
try try
sb.Append('{'); sb.Append('{');
first := True;
for i := 0 to rec.Count - 1 do for i := 0 to rec.Count - 1 do
begin begin
if not first then if not first then
@@ -479,6 +501,12 @@ begin
Result.FInterface := AValue; Result.FInterface := AValue;
end; end;
class operator TDataValue.Implicit(const AValue: ITuple<TDataValue>): TDataValue;
begin
Result.FKind := vkTuple;
Result.FInterface := AValue;
end;
{ TMapSeries } { TMapSeries }
constructor TMapSeries.Create(const ASourceSeries: ISeries; const AMapperFunc: TDataValue.TFunc); constructor TMapSeries.Create(const ASourceSeries: ISeries; const AMapperFunc: TDataValue.TFunc);
+3 -3
View File
@@ -301,7 +301,7 @@ var
staticType: IStaticType; staticType: IStaticType;
genRec: IGenericRecordDefinition; genRec: IGenericRecordDefinition;
idx: Integer; idx: Integer;
methodType: IStaticType; methodType: IMethodType;
begin begin
// Verify that IMainService was analyzed correctly into an AST definition // Verify that IMainService was analyzed correctly into an AST definition
staticType := TRtlTypeRegistry.GetStaticType(TypeInfo(IMainService)); staticType := TRtlTypeRegistry.GetStaticType(TypeInfo(IMainService));
@@ -309,13 +309,13 @@ begin
Assert.AreNotEqual(TStaticTypeKind.stUnknown, staticType.Kind, 'Type should be known'); Assert.AreNotEqual(TStaticTypeKind.stUnknown, staticType.Kind, 'Type should be known');
Assert.AreEqual(TStaticTypeKind.stGenericRecord, staticType.Kind, 'Interface should map to GenericRecord'); Assert.AreEqual(TStaticTypeKind.stGenericRecord, staticType.Kind, 'Interface should map to GenericRecord');
genRec := staticType.GenericDefinition; genRec := staticType.AsGenericRecord.GenericDefinition;
// Check 'Add' method existence // Check 'Add' method existence
idx := genRec.IndexOf(Myc.Data.Keyword.TKeywordRegistry.Intern('Add')); idx := genRec.IndexOf(Myc.Data.Keyword.TKeywordRegistry.Intern('Add'));
Assert.IsTrue(idx >= 0, 'Method Add should exist in type definition'); Assert.IsTrue(idx >= 0, 'Method Add should exist in type definition');
methodType := genRec.Items[idx]; methodType := genRec.Items[idx].AsMethod;
Assert.AreEqual(TStaticTypeKind.stMethod, methodType.Kind); Assert.AreEqual(TStaticTypeKind.stMethod, methodType.Kind);
// Add has 2 args (Ordinal, Ordinal) -> Ordinal // Add has 2 args (Ordinal, Ordinal) -> Ordinal
Assert.AreEqual(Int64(2), Length(methodType.Signatures[0].ParamTypes)); Assert.AreEqual(Int64(2), Length(methodType.Signatures[0].ParamTypes));