diff --git a/ASTPlayground/ASTPlayground.dpr b/ASTPlayground/ASTPlayground.dpr index ba84f08..b9eb503 100644 --- a/ASTPlayground/ASTPlayground.dpr +++ b/ASTPlayground/ASTPlayground.dpr @@ -10,7 +10,7 @@ uses Myc.Ast.Scope in '..\Src\AST\Myc.Ast.Scope.pas', Myc.Ast.Visualizer in 'Myc.Ast.Visualizer.pas', Myc.Ast.ViewModel in '..\Src\AST\Myc.Ast.ViewModel.pas', - Myc.Ast.Persistence in '..\Src\AST\Myc.Ast.Persistence.pas'; + Myc.Data.Value in 'Myc.Data.Value.pas'; {$R *.res} diff --git a/ASTPlayground/ASTPlayground.dproj b/ASTPlayground/ASTPlayground.dproj index 46a003b..dc08114 100644 --- a/ASTPlayground/ASTPlayground.dproj +++ b/ASTPlayground/ASTPlayground.dproj @@ -4,7 +4,7 @@ 20.3 FMX True - Debug + Release Win64 ASTPlayground 2 @@ -141,7 +141,7 @@ - + Base diff --git a/ASTPlayground/MainForm.pas b/ASTPlayground/MainForm.pas index e2c8999..6b0547b 100644 --- a/ASTPlayground/MainForm.pas +++ b/ASTPlayground/MainForm.pas @@ -23,13 +23,14 @@ uses FMX.Controls.Presentation, Myc.Ast.Visualizer, Myc.Data.Scalar, + Myc.Data.Value, // Added Myc.Ast.Nodes, Myc.Ast, Myc.Ast.Evaluator, Myc.Ast.Printer, FMX.Layouts, FMX.Objects, - Myc.Ast.Scope; // Added for TExecutionScope + Myc.Ast.Scope; type // A test record @@ -84,7 +85,7 @@ type function CreateVisitor(const AScope: IExecutionScope): IAstVisitor; procedure WorkspaceMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); // New helper function to encapsulate the Bind -> Evaluate pattern - function ExecuteAst(const ANode: IAstNode; const AParentScope: IExecutionScope): TAstValue; + function ExecuteAst(const ANode: IAstNode; const AParentScope: IExecutionScope): TDataValue; public { Public declarations } end; @@ -95,7 +96,6 @@ var implementation uses - // Myc.Ast.Scope is now in the interface uses Myc.Data.Scalar.JSON, Myc.Data.Decimal, System.Diagnostics, // For TStopwatch @@ -125,7 +125,7 @@ begin Result := TEvaluatorVisitor.Create(AScope); end; -function TForm1.ExecuteAst(const ANode: IAstNode; const AParentScope: IExecutionScope): TAstValue; +function TForm1.ExecuteAst(const ANode: IAstNode; const AParentScope: IExecutionScope): TDataValue; var scriptScope: IExecutionScope; begin @@ -150,7 +150,7 @@ end; procedure TForm1.FibonacciButtonClick(Sender: TObject); var root: IAstNode; - result: TAstValue; + result: TDataValue; sw: TStopwatch; begin Memo1.Lines.Clear; @@ -214,7 +214,7 @@ end; procedure TForm1.RecursionButtonClick(Sender: TObject); var root: IAstNode; - result: TAstValue; + result: TDataValue; sw: TStopwatch; begin Memo1.Lines.Clear; @@ -258,7 +258,7 @@ procedure TForm1.SeriesTestButtonClick(Sender: TObject); var scope: IExecutionScope; ast, callAst: IAstNode; - resultValue: TAstValue; + resultValue: TDataValue; series: TScalarRecordSeries; recordDef: TScalarRecordDefinition; i: Integer; @@ -286,7 +286,7 @@ begin ) ); end; - scope.Define('ohlcvSeries', TAstValue.FromRecordSeries(series)); + scope.Define('ohlcvSeries', TDataValue.FromRecordSeries(series)); // 2. Act: Define and execute the script AST ast := @@ -314,7 +314,7 @@ end; procedure TForm1.Test1ButtonClick(Sender: TObject); var main, callAst: IAstNode; - result: TAstValue; + result: TDataValue; sw: TStopwatch; begin Memo1.Lines.Clear; @@ -348,7 +348,7 @@ end; procedure TForm1.Test2ButtonClick(Sender: TObject); var root: IAstNode; - result: TAstValue; + result: TDataValue; sw: TStopwatch; begin Memo1.Lines.Clear; @@ -515,7 +515,7 @@ begin setupAst.Accept(CreateVisitor(scope)); // Declare the series variable in the scope BEFORE binding the call AST - scope.Define('current_series', TAstValue.Void); + scope.Define('current_series', TDataValue.Void); // Create the call AST that will be executed in the loop var currentSeriesIdent := TAst.Identifier('current_series'); @@ -533,7 +533,7 @@ begin Randomize; var recDef := TRttiAstHelper.JsonToRecordDefinition(TRttiAstHelper.RecordDefinitionToJson); - var series := TAstValue.FromRecordSeries(TScalarRecordSeries.Create(recDef)); + var series := TDataValue.FromRecordSeries(TScalarRecordSeries.Create(recDef)); var seriesAddress := currentSeriesIdent.Address; var nw := Now; @@ -635,7 +635,6 @@ end; procedure TForm1.DoTrigger2ButtonClick(Sender: TObject); var callAst: IFunctionCallNode; - currentValue: TAstValue; begin callAst := TAst.FunctionCall(TAst.Identifier('tickHandler'), [TAst.Constant(TScalar.FromInt64(2))]); FLastAst := callAst; diff --git a/ASTPlayground/Myc.Ast.Visualizer.pas b/ASTPlayground/Myc.Ast.Visualizer.pas index 1ecad84..7a33929 100644 --- a/ASTPlayground/Myc.Ast.Visualizer.pas +++ b/ASTPlayground/Myc.Ast.Visualizer.pas @@ -13,6 +13,7 @@ uses FMX.Controls, FMX.Objects, FMX.Graphics, + Myc.Data.Value, Myc.Ast.Nodes; type @@ -262,22 +263,22 @@ type property Connections: TList read FConnections; { IAstVisitor } - function VisitConstant(const Node: IConstantNode): TAstValue; - function VisitIdentifier(const Node: IIdentifierNode): TAstValue; - function VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; - function VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; - function VisitIfExpression(const Node: IIfExpressionNode): TAstValue; - function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue; - function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; - function VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; - function VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; - function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; - function VisitAssignment(const Node: IAssignmentNode): TAstValue; - function VisitIndexer(const Node: IIndexerNode): TAstValue; - function VisitMemberAccess(const Node: IMemberAccessNode): TAstValue; - function VisitCreateSeries(const Node: ICreateSeriesNode): TAstValue; - function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAstValue; - function VisitSeriesLength(const Node: ISeriesLengthNode): TAstValue; + function VisitConstant(const Node: IConstantNode): TDataValue; + function VisitIdentifier(const Node: IIdentifierNode): TDataValue; + function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; + function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; + function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; + function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; + function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; + function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; + function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; + function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; + function VisitAssignment(const Node: IAssignmentNode): TDataValue; + function VisitIndexer(const Node: IIndexerNode): TDataValue; + function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; + function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; + function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; + function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; end; implementation @@ -293,27 +294,27 @@ type TAstToTextVisitor = class(TInterfacedObject, IAstVisitor) public { IAstVisitor } - function VisitConstant(const Node: IConstantNode): TAstValue; - function VisitIdentifier(const Node: IIdentifierNode): TAstValue; - function VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; - function VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; - function VisitIfExpression(const Node: IIfExpressionNode): TAstValue; - function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue; - function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; - function VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; - function VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; - function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; - function VisitAssignment(const Node: IAssignmentNode): TAstValue; - function VisitIndexer(const Node: IIndexerNode): TAstValue; - function VisitMemberAccess(const Node: IMemberAccessNode): TAstValue; - function VisitCreateSeries(const Node: ICreateSeriesNode): TAstValue; - function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAstValue; - function VisitSeriesLength(const Node: ISeriesLengthNode): TAstValue; + function VisitConstant(const Node: IConstantNode): TDataValue; + function VisitIdentifier(const Node: IIdentifierNode): TDataValue; + function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; + function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; + function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; + function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; + function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; + function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; + function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; + function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; + function VisitAssignment(const Node: IAssignmentNode): TDataValue; + function VisitIndexer(const Node: IIndexerNode): TDataValue; + function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; + function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; + function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; + function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; end; { TAstToTextVisitor } -function TAstToTextVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAstValue; +function TAstToTextVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; var seriesStr, valueStr, lookbackStr: string; begin @@ -325,34 +326,34 @@ begin Result := Format('%s.add(%s%s)', [seriesStr, valueStr, lookbackStr]); end; -function TAstToTextVisitor.VisitAssignment(const Node: IAssignmentNode): TAstValue; +function TAstToTextVisitor.VisitAssignment(const Node: IAssignmentNode): TDataValue; begin Result := Node.Identifier.Name + ' := ' + Node.Value.Accept(Self).AsText; end; -function TAstToTextVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; +function TAstToTextVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; begin var leftStr := Node.Left.Accept(Self).AsText; var rightStr := Node.Right.Accept(Self).AsText; Result := '(' + leftStr + ' ' + Node.Operator.ToString + ' ' + rightStr + ')'; end; -function TAstToTextVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; +function TAstToTextVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; begin Result := '{...}'; end; -function TAstToTextVisitor.VisitConstant(const Node: IConstantNode): TAstValue; +function TAstToTextVisitor.VisitConstant(const Node: IConstantNode): TDataValue; begin Result := Node.Value.ToString; end; -function TAstToTextVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TAstValue; +function TAstToTextVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; begin Result := 'new series(' + Node.Definition + ')'; end; -function TAstToTextVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; +function TAstToTextVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; var i: Integer; sb: TStringBuilder; @@ -377,17 +378,17 @@ begin end; end; -function TAstToTextVisitor.VisitIdentifier(const Node: IIdentifierNode): TAstValue; +function TAstToTextVisitor.VisitIdentifier(const Node: IIdentifierNode): TDataValue; begin Result := Node.Name; end; -function TAstToTextVisitor.VisitIfExpression(const Node: IIfExpressionNode): TAstValue; +function TAstToTextVisitor.VisitIfExpression(const Node: IIfExpressionNode): TDataValue; begin Result := Node.Condition.Accept(Self).AsText; end; -function TAstToTextVisitor.VisitIndexer(const Node: IIndexerNode): TAstValue; +function TAstToTextVisitor.VisitIndexer(const Node: IIndexerNode): TDataValue; var baseStr, indexStr: string; begin @@ -396,7 +397,7 @@ begin Result := Format('%s[%s]', [baseStr, indexStr]); end; -function TAstToTextVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; +function TAstToTextVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; var i: Integer; sb: TStringBuilder; @@ -421,7 +422,7 @@ begin end; end; -function TAstToTextVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TAstValue; +function TAstToTextVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; var baseStr: string; begin @@ -429,7 +430,7 @@ begin Result := Format('%s.%s', [baseStr, Node.Member.Name]); end; -function TAstToTextVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TAstValue; +function TAstToTextVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; var seriesStr: string; begin @@ -438,7 +439,7 @@ begin Result := Format('length(%s)', [seriesStr]); end; -function TAstToTextVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue; +function TAstToTextVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; begin var condStr := Node.Condition.Accept(Self).AsText; var thenStr := Node.ThenBranch.Accept(Self).AsText; @@ -446,12 +447,12 @@ begin Result := Format('(%s ? %s : %s)', [condStr, thenStr, elseStr]); end; -function TAstToTextVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; +function TAstToTextVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; begin Result := Node.Operator.ToString + ' ' + Node.Right.Accept(Self).AsText; end; -function TAstToTextVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; +function TAstToTextVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; var initStr: string; begin @@ -498,7 +499,7 @@ begin Height := 45; // The panel must be able to receive mouse events. - // HitTest := True; + // HitTest := True; // Clip children to the panel's bounds. ClipChildren := True; end; @@ -1070,7 +1071,7 @@ begin Result := Pos('{', Text) = 0; end; -function TAstToAuraNodeVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAstValue; +function TAstToAuraNodeVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; var details: string; inputs: TArray; @@ -1123,10 +1124,10 @@ begin vaTop ); end; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TAstToAuraNodeVisitor.VisitAssignment(const Node: IAssignmentNode): TAstValue; +function TAstToAuraNodeVisitor.VisitAssignment(const Node: IAssignmentNode): TDataValue; begin var details: String; if (FMode = vmControlFlow) and TryGetDescr(Node, details) then @@ -1169,10 +1170,10 @@ begin vaTop ); end; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TAstToAuraNodeVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; +function TAstToAuraNodeVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; begin var exprStr: String; if (FMode = vmControlFlow) and TryGetDescr(Node, exprStr) then @@ -1213,10 +1214,10 @@ begin end ); end; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TAstToAuraNodeVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; +function TAstToAuraNodeVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; var blockNode: TAuraNode; childLastResult: TAuraNodeResult; @@ -1253,10 +1254,10 @@ begin FLastResult.LayoutNode := blockNode; // The layout node is the container itself. FLastResult.OutputPin := childLastResult.OutputPin; // The connection pin is from the internal node. - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TAstToAuraNodeVisitor.VisitConstant(const Node: IConstantNode): TAstValue; +function TAstToAuraNodeVisitor.VisitConstant(const Node: IConstantNode): TDataValue; var constantNode: TAuraNode; begin @@ -1264,7 +1265,7 @@ begin constantNode := CreateNodeControl('Constant', Node.Value.ToString); FLastResult.OutputPin := CreateOutput(constantNode); FinalizeNodeLayout(constantNode); - Result := TAstValue.Void; + Result := TDataValue.Void; end; function TAstToAuraNodeVisitor.VisitContainerNode( @@ -1377,7 +1378,7 @@ begin FinalizeNodeLayout(containerNode); end; -function TAstToAuraNodeVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TAstValue; +function TAstToAuraNodeVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; var seriesNode: TAuraNode; begin @@ -1386,10 +1387,10 @@ begin seriesNode := CreateNodeControl('Create Series', Node.Definition); FLastResult.OutputPin := CreateOutput(seriesNode); FinalizeNodeLayout(seriesNode); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TAstToAuraNodeVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; +function TAstToAuraNodeVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; var inputExpressions: TArray; begin @@ -1443,18 +1444,18 @@ begin end ); end; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TAstToAuraNodeVisitor.VisitIdentifier(const Node: IIdentifierNode): TAstValue; +function TAstToAuraNodeVisitor.VisitIdentifier(const Node: IIdentifierNode): TDataValue; begin var identifierNode := CreateNodeControl('Identifier', Node.Name); FLastResult.OutputPin := CreateOutput(identifierNode); FinalizeNodeLayout(identifierNode); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TAstToAuraNodeVisitor.VisitIfExpression(const Node: IIfExpressionNode): TAstValue; +function TAstToAuraNodeVisitor.VisitIfExpression(const Node: IIfExpressionNode): TDataValue; var startPosition: TPointF; ifNode: TAuraNode; @@ -1544,10 +1545,10 @@ begin execPathes.Free; end; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TAstToAuraNodeVisitor.VisitIndexer(const Node: IIndexerNode): TAstValue; +function TAstToAuraNodeVisitor.VisitIndexer(const Node: IIndexerNode): TDataValue; var details: String; begin @@ -1584,10 +1585,10 @@ begin end ); end; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TAstToAuraNodeVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; +function TAstToAuraNodeVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; var paramStr: String; lambdaNode: TAuraNode; @@ -1624,10 +1625,10 @@ begin // Re-finalize layout after adding the data output pin. FinalizeNodeLayout(lambdaNode); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TAstToAuraNodeVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TAstValue; +function TAstToAuraNodeVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; var details: String; begin @@ -1661,7 +1662,7 @@ begin end ); end; - Result := TAstValue.Void; + Result := TDataValue.Void; end; function TAstToAuraNodeVisitor.VisitOperatorNode( @@ -1722,7 +1723,7 @@ begin end; end; -function TAstToAuraNodeVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TAstValue; +function TAstToAuraNodeVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; begin // Use the standard helper for operator-style nodes. VisitOperatorNode( @@ -1751,10 +1752,10 @@ begin Result.OutputPin := outPin; end ); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TAstToAuraNodeVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue; +function TAstToAuraNodeVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; begin var exprStr: String; if (FMode = vmControlFlow) and TryGetDescr(Node, exprStr) then @@ -1793,10 +1794,10 @@ begin end ); end; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TAstToAuraNodeVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; +function TAstToAuraNodeVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; begin var exprStr: String; if (FMode = vmControlFlow) and TryGetDescr(Node, exprStr) then @@ -1832,10 +1833,10 @@ begin end ); end; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TAstToAuraNodeVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; +function TAstToAuraNodeVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; var outPin: TControl; begin @@ -1894,7 +1895,7 @@ begin end; end; - Result := TAstValue.Void; + Result := TDataValue.Void; end; end. diff --git a/KI/gemini.md b/KI/gemini.md index dccf999..2eef970 100644 --- a/KI/gemini.md +++ b/KI/gemini.md @@ -77,6 +77,7 @@ * Statement-Blöcke werden mit begin..end eingekapselt. (Niemals mit Klammern!) * begin und end stehen am Anfang einer neuen Zeile. then steht nie am Anfang einer neuen Zeile. * RECORDs, die einen Initialize-Operator haben, sind Managed Records. Sie benötigen also kein explizites Create. +* Vorwärtsdeklarationen von Records werden in Delphi nicht unterstützt. Die Lösung dafür ist, das benutzende Element im Scope des Records zu definieren. # In Unit-Tests diff --git a/Src/AST/Myc.Ast.Evaluator.pas b/Src/AST/Myc.Ast.Evaluator.pas index 96a91d6..2a2f886 100644 --- a/Src/AST/Myc.Ast.Evaluator.pas +++ b/Src/AST/Myc.Ast.Evaluator.pas @@ -4,9 +4,10 @@ interface uses System.SysUtils, - System.Classes, // For TStrings + System.Classes, System.Generics.Collections, Myc.Data.Scalar, + Myc.Data.Value, Myc.Ast.Nodes, Myc.Ast.Scope, Myc.Ast; @@ -17,26 +18,26 @@ type private FScope: IExecutionScope; protected - function IsTruthy(const AValue: TAstValue): Boolean; + function IsTruthy(const AValue: TDataValue): Boolean; function CreateVisitorForScope(const AScope: IExecutionScope): IAstVisitor; virtual; public constructor Create(const AScope: IExecutionScope); - function VisitConstant(const Node: IConstantNode): TAstValue; virtual; - function VisitIdentifier(const Node: IIdentifierNode): TAstValue; virtual; - function VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; virtual; - function VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; virtual; - function VisitIfExpression(const Node: IIfExpressionNode): TAstValue; virtual; - function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue; virtual; - function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; virtual; - function VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; virtual; - function VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; virtual; - function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; virtual; - function VisitAssignment(const Node: IAssignmentNode): TAstValue; virtual; - function VisitIndexer(const Node: IIndexerNode): TAstValue; virtual; - function VisitMemberAccess(const Node: IMemberAccessNode): TAstValue; virtual; - function VisitCreateSeries(const Node: ICreateSeriesNode): TAstValue; virtual; - function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAstValue; virtual; - function VisitSeriesLength(const Node: ISeriesLengthNode): TAstValue; virtual; + function VisitConstant(const Node: IConstantNode): TDataValue; virtual; + function VisitIdentifier(const Node: IIdentifierNode): TDataValue; virtual; + function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; virtual; + function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; virtual; + function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; virtual; + function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; virtual; + function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; virtual; + function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; virtual; + function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; virtual; + function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; virtual; + function VisitAssignment(const Node: IAssignmentNode): TDataValue; virtual; + function VisitIndexer(const Node: IIndexerNode): TDataValue; virtual; + function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; virtual; + function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; virtual; + function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; virtual; + function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; virtual; end; // TDebugEvaluatorVisitor now overrides all visit methods for full tracing @@ -54,22 +55,22 @@ type function CreateVisitorForScope(const AScope: IExecutionScope): IAstVisitor; override; public constructor Create(const AScope: IExecutionScope; ALog: TStrings; AShowScope: Boolean; AInitialIndent: Integer = 0); - function VisitConstant(const Node: IConstantNode): TAstValue; override; - function VisitIdentifier(const Node: IIdentifierNode): TAstValue; override; - function VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; override; - function VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; override; - function VisitIfExpression(const Node: IIfExpressionNode): TAstValue; override; - function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue; override; - function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; override; - function VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; override; - function VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; override; - function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; override; - function VisitAssignment(const Node: IAssignmentNode): TAstValue; override; - function VisitIndexer(const Node: IIndexerNode): TAstValue; override; - function VisitMemberAccess(const Node: IMemberAccessNode): TAstValue; override; - function VisitCreateSeries(const Node: ICreateSeriesNode): TAstValue; override; - function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAstValue; override; - function VisitSeriesLength(const Node: ISeriesLengthNode): TAstValue; override; + function VisitConstant(const Node: IConstantNode): TDataValue; override; + function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override; + function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; override; + function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; override; + function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override; + function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override; + function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override; + function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override; + function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override; + function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override; + function VisitAssignment(const Node: IAssignmentNode): TDataValue; override; + function VisitIndexer(const Node: IIndexerNode): TDataValue; override; + function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override; + function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override; + function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; override; + function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override; end; // Registers all native core functions in the given scope. @@ -79,6 +80,7 @@ implementation uses System.TypInfo, + System.Generics.Defaults, Myc.Data.Decimal, Myc.Data.Series, Myc.Ast.Printer, @@ -86,52 +88,48 @@ uses type // The signature for a native Delphi function callable from the script. - TNativeFunction = function(const Args: TArray): TAstValue; + TNativeFunction = function(const Args: TArray): TDataValue; - TClosureValue = class(TInterfacedObject, TAstValue.IClosure) + TClosureValue = class(TInterfacedObject, TDataValue.ICallable) private - FBody: IAstNode; - FClosureScope: IExecutionScope; FLambdaNode: ILambdaExpressionNode; + FClosureScope: IExecutionScope; FUpvalues: TArray; - function GetBody: IAstNode; - function GetParameters: TArray; - function GetClosureScope: IExecutionScope; - function GetUpvalues: TArray; public constructor Create( const ALambdaNode: ILambdaExpressionNode; const AClosureScope: IExecutionScope; const AUpvalues: TArray ); - property ClosureScope: IExecutionScope read GetClosureScope; - property LambdaNode: ILambdaExpressionNode read FLambdaNode; - property Upvalues: TArray read FUpvalues; + // ICallable implementation (the generic, slower path) + function GetArity: Integer; + function Invoke(const AVisitor: IInterface; const ASelf: TDataValue; const AArgs: TArray): TDataValue; + // Fast Path + function InvokeFast(const AVisitor: IAstVisitor; const ASelf: TDataValue; const AArgNodes: TList): TDataValue; end; - // Concrete implementation of TAstValue.IClosure for native Delphi functions. - TNativeClosure = class(TInterfacedObject, TAstValue.IClosure) + TNativeClosure = class(TInterfacedObject, TDataValue.ICallable) private FMethod: TNativeFunction; - function GetBody: IAstNode; - function GetParameters: TArray; - function GetClosureScope: IExecutionScope; - function GetUpvalues: TArray; + FArity: Integer; public - constructor Create(const AMethod: TNativeFunction); - property Method: TNativeFunction read FMethod; + constructor Create(const AMethod: TNativeFunction; AArity: Integer); + // ICallable implementation + function GetArity: Integer; + function Invoke(const AVisitor: IInterface; const ASelf: TDataValue; const AArgs: TArray): TDataValue; end; // --- Native Functions Implementation --- -function NativeCreateRecordSeries(const Args: TArray): TAstValue; +function NativeCreateRecordSeries(const Args: TArray): TDataValue; var jsonDef: string; recordDef: TScalarRecordDefinition; series: TScalarRecordSeries; begin - if (Length(Args) <> 1) or (Args[0].Kind <> avkText) then - raise EArgumentException.Create('CreateRecordSeries requires one string argument.'); + // Arity check is now done by the caller (TNativeClosure.Invoke) + if Args[0].Kind <> vkText then + raise EArgumentException.Create('CreateRecordSeries requires a string argument.'); jsonDef := Args[0].AsText; recordDef := TRttiAstHelper.JsonToRecordDefinition(jsonDef); @@ -140,7 +138,7 @@ begin raise EArgumentException.Create('Failed to parse record definition from JSON.'); series := TScalarRecordSeries.Create(recordDef); - Result := TAstValue.FromRecordSeries(series); + Result := TDataValue.FromRecordSeries(series); end; // --- Registration Procedure --- @@ -149,7 +147,7 @@ procedure RegisterNativeFunctions(const AScope: IExecutionScope); begin // Use 'Define' to clearly state that we are adding a new variable // to the global scope before the binder runs. - AScope.Define('CreateRecordSeries', TNativeClosure.Create(NativeCreateRecordSeries)); + AScope.Define('CreateRecordSeries', TNativeClosure.Create(NativeCreateRecordSeries, 1)); end; { TClosureValue } @@ -162,57 +160,106 @@ constructor TClosureValue.Create( begin inherited Create; FLambdaNode := ALambdaNode; - FBody := ALambdaNode.Body; FClosureScope := AClosureScope; - FUpvalues := AUpvalues; // Store the captured cells + FUpvalues := AUpvalues; end; -function TClosureValue.GetBody: IAstNode; +function TClosureValue.GetArity: Integer; begin - Result := FBody; + Result := Length(FLambdaNode.Parameters); end; -function TClosureValue.GetClosureScope: IExecutionScope; +// This is the generic, slightly slower path, kept for compatibility with ICallable. +function TClosureValue.Invoke(const AVisitor: IInterface; const ASelf: TDataValue; const AArgs: TArray): TDataValue; +var + i: Integer; + descriptor: IScopeDescriptor; + callScope: IExecutionScope; + adr: TResolvedAddress; + callVisitor: IAstVisitor; begin - Result := FClosureScope; + descriptor := FLambdaNode.ScopeDescriptor; + if not Assigned(descriptor) then + raise EParserError.Create('Lambda has no scope descriptor. Did the binder run?'); + + callScope := TExecutionScope.Create(FClosureScope, descriptor, FUpvalues); + + adr.Kind := akLocalOrParent; + adr.ScopeDepth := 0; + adr.SlotIndex := 0; + callScope[adr].Value := ASelf; + + for i := 0 to High(AArgs) do + begin + adr.SlotIndex := FLambdaNode.Parameters[i].Address.SlotIndex; + callScope[adr].Value := AArgs[i]; + end; + + callVisitor := (AVisitor as TEvaluatorVisitor).CreateVisitorForScope(callScope); + Result := FLambdaNode.Body.Accept(callVisitor); end; -function TClosureValue.GetParameters: TArray; +// This is the new, optimized method that evaluates argument nodes directly. +function TClosureValue.InvokeFast(const AVisitor: IAstVisitor; const ASelf: TDataValue; const AArgNodes: TList): TDataValue; +var + i: Integer; + descriptor: IScopeDescriptor; + callScope: IExecutionScope; + adr: TResolvedAddress; begin - Result := FLambdaNode.Parameters; -end; + // Arity check + if (AArgNodes.Count <> Length(FLambdaNode.Parameters)) then + raise EArgumentException + .CreateFmt('Argument count mismatch: expected %d, got %d', [Length(FLambdaNode.Parameters), AArgNodes.Count]); -function TClosureValue.GetUpvalues: TArray; -begin - Result := FUpvalues; + descriptor := FLambdaNode.ScopeDescriptor; + if not Assigned(descriptor) then + raise EParserError.Create('Lambda has no scope descriptor. Did the binder run?'); + + // Create the scope for the call directly + callScope := TExecutionScope.Create(FClosureScope, descriptor, FUpvalues); + + adr.Kind := akLocalOrParent; + adr.ScopeDepth := 0; + + // Set the 'Self' variable + adr.SlotIndex := 0; + callScope[adr].Value := ASelf; + + // Evaluate arguments DIRECTLY into the new scope (no temporary array!) + for i := 0 to AArgNodes.Count - 1 do + begin + adr.SlotIndex := FLambdaNode.Parameters[i].Address.SlotIndex; + // Evaluate in CALLER'S scope (AVisitor), place in CALLEE'S scope (callScope) + callScope[adr].Value := AArgNodes[i].Accept(AVisitor); + end; + + // Execute the body with a new visitor for the new scope + Result := FLambdaNode.Body.Accept((AVisitor as TEvaluatorVisitor).CreateVisitorForScope(callScope)); end; { TNativeClosure } -constructor TNativeClosure.Create(const AMethod: TNativeFunction); +constructor TNativeClosure.Create(const AMethod: TNativeFunction; AArity: Integer); begin inherited Create; FMethod := AMethod; + FArity := AArity; end; -function TNativeClosure.GetBody: IAstNode; +function TNativeClosure.GetArity: Integer; begin - Result := nil; + Result := FArity; end; -function TNativeClosure.GetClosureScope: IExecutionScope; +function TNativeClosure.Invoke(const AVisitor: IInterface; const ASelf: TDataValue; const AArgs: TArray): TDataValue; begin - Result := nil; -end; + // Arity check + if (FArity <> -1) and (Length(AArgs) <> FArity) then + raise EArgumentException.CreateFmt('Argument count mismatch: expected %d, got %d', [FArity, Length(AArgs)]); -function TNativeClosure.GetParameters: TArray; -begin - Result := nil; -end; - -function TNativeClosure.GetUpvalues: TArray; -begin - Result := nil; + // AVisitor and ASelf are ignored for native calls. + Result := FMethod(AArgs); end; { TEvaluatorVisitor } @@ -229,9 +276,9 @@ begin Result := TEvaluatorVisitor.Create(AScope); end; -function TEvaluatorVisitor.IsTruthy(const AValue: TAstValue): Boolean; +function TEvaluatorVisitor.IsTruthy(const AValue: TDataValue): Boolean; begin - if (AValue.Kind <> avkScalar) then + if (AValue.Kind <> vkScalar) then begin Exit(False); end; @@ -246,9 +293,43 @@ begin end; end; -function TEvaluatorVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAstValue; +function TEvaluatorVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; var - itemValue, lookbackValue, seriesVar: TAstValue; + calleeValue: TDataValue; + callable: TDataValue.ICallable; + i: Integer; +begin + calleeValue := Node.Callee.Accept(Self); + + if calleeValue.Kind <> vkCallable then + raise EArgumentException.Create('Expression is not a callable value.'); + + callable := calleeValue.AsCallable; + + if callable is TClosureValue then + begin + // "Fast Path": Call the optimized method directly. + Result := (callable as TClosureValue).InvokeFast(Self, calleeValue, Node.Arguments); + end + else + begin + // "Generic Path": For other ICallable types (e.g., TNativeClosure). + // Evaluate arguments into a temporary array first. + var argValues: TArray; + SetLength(argValues, Node.Arguments.Count); + for i := 0 to Node.Arguments.Count - 1 do + argValues[i] := Node.Arguments[i].Accept(Self); + + // Call the generic Invoke method. + Result := callable.Invoke(Self, calleeValue, argValues); + end; +end; + +{ TEvaluatorVisitor } + +function TEvaluatorVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; +var + itemValue, lookbackValue, seriesVar: TDataValue; lookback: Int64; begin // The target series must have been resolved by the binder. @@ -259,7 +340,7 @@ begin if Assigned(Node.Lookback) then begin lookbackValue := Node.Lookback.Accept(Self); - if (lookbackValue.Kind <> avkScalar) or not (lookbackValue.AsScalar.Kind in [skInteger, skInt64]) then + if (lookbackValue.Kind <> vkScalar) or not (lookbackValue.AsScalar.Kind in [skInteger, skInt64]) then raise EArgumentException.Create('Lookback parameter must be an integer.'); if lookbackValue.AsScalar.Kind = skInteger then @@ -270,9 +351,9 @@ begin // Dispatch based on series type case seriesVar.Kind of - avkSeries: + vkSeries: begin - if (itemValue.Kind <> avkScalar) then + if (itemValue.Kind <> vkScalar) then raise EArgumentException.Create('Can only add scalar values to a TScalarSeries.'); with seriesVar.AsSeries.Value do @@ -284,9 +365,9 @@ begin Items.Add(itemValue.AsScalar.Value, lookback); end; end; - avkRecordSeries: + vkRecordSeries: begin - if (itemValue.Kind <> avkRecord) then + if (itemValue.Kind <> vkRecord) then raise EArgumentException.Create('Can only add record values to a TScalarRecordSeries.'); with seriesVar.AsRecordSeries.Value do @@ -297,20 +378,21 @@ begin else raise EArgumentException.Create('"add" operation is only supported for series types.'); end; + Result := TDataValue.Void; // 'add' is a procedure, returns void end; -function TEvaluatorVisitor.VisitAssignment(const Node: IAssignmentNode): TAstValue; +function TEvaluatorVisitor.VisitAssignment(const Node: IAssignmentNode): TDataValue; begin Result := Node.Value.Accept(Self); FScope[Node.Identifier.Address].Value := Result; end; -function TEvaluatorVisitor.VisitConstant(const Node: IConstantNode): TAstValue; +function TEvaluatorVisitor.VisitConstant(const Node: IConstantNode): TDataValue; begin Result := Node.Value; end; -function TEvaluatorVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TAstValue; +function TEvaluatorVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; var def: string; begin @@ -323,31 +405,31 @@ begin raise EArgumentException.Create('Failed to parse record definition from JSON array.'); var recordSeries := TScalarRecordSeries.Create(recordDef); - Result := TAstValue.FromRecordSeries(recordSeries); + Result := TDataValue.FromRecordSeries(recordSeries); end else begin var scalarKind := TScalar.StringToKind(def); var scalarSeries := TScalarSeries.Create(scalarKind, Default(TSeries)); - Result := TAstValue.FromSeries(scalarSeries); + Result := TDataValue.FromSeries(scalarSeries); end; end; -function TEvaluatorVisitor.VisitIdentifier(const Node: IIdentifierNode): TAstValue; +function TEvaluatorVisitor.VisitIdentifier(const Node: IIdentifierNode): TDataValue; begin Result := FScope[Node.Address].Value; end; -function TEvaluatorVisitor.VisitIndexer(const Node: IIndexerNode): TAstValue; +function TEvaluatorVisitor.VisitIndexer(const Node: IIndexerNode): TDataValue; var - baseValue, indexValue: TAstValue; + baseValue, indexValue: TDataValue; index: Int64; indexScalar: TScalar; begin baseValue := Node.Base.Accept(Self); indexValue := Node.Index.Accept(Self); - if (indexValue.Kind <> avkScalar) then + if (indexValue.Kind <> vkScalar) then raise EArgumentException.Create('Indexer `[]` requires a scalar integer argument.'); indexScalar := indexValue.AsScalar; @@ -359,7 +441,7 @@ begin end; case baseValue.Kind of - avkSeries: + vkSeries: begin with baseValue.AsSeries.Value do begin @@ -369,16 +451,16 @@ begin Result := TScalar.Create(Kind, Items[Integer(index)]); end; end; - avkRecordSeries: + vkRecordSeries: begin var series := baseValue.AsRecordSeries.Value; if (index < 0) or (index >= series.TotalCount) then raise EArgumentException.CreateFmt('Index %d is out of bounds for series with %d elements.', [index, series.TotalCount]); var recordValue := series.Items[Integer(index)]; - Result := TAstValue.FromRecord(recordValue); + Result := TDataValue.FromRecord(recordValue); end; - avkMemberSeries: + vkMemberSeries: begin var memberSeries := baseValue.AsMemberSeries.Value; if (index < 0) or (index >= memberSeries.Count) then @@ -392,16 +474,16 @@ begin end; end; -function TEvaluatorVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TAstValue; +function TEvaluatorVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; var - baseValue: TAstValue; + baseValue: TDataValue; memberName: string; begin baseValue := Node.Base.Accept(Self); memberName := Node.Member.Name; case baseValue.Kind of - avkSeries: + vkSeries: begin with baseValue.AsSeries.Value do begin @@ -415,32 +497,31 @@ begin raise EArgumentException.CreateFmt('Member "%s" not found on TScalarSeries.', [memberName]); end; end; - avkRecordSeries: Result := TAstValue.FromMemberSeries(baseValue.AsRecordSeries.Value.CreateMemberSeries(memberName)); - avkRecord: Result := baseValue.AsRecord.Value.Items[memberName]; + vkRecordSeries: Result := TDataValue.FromMemberSeries(baseValue.AsRecordSeries.Value.CreateMemberSeries(memberName)); + vkRecord: Result := baseValue.AsRecord.Value.Items[memberName]; else raise EArgumentException.Create('Member access operator `.` is not supported for this value type.'); end; end; -function TEvaluatorVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; +function TEvaluatorVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; var - value: TAstValue; + value: TDataValue; begin if Assigned(Node.Initializer) then value := Node.Initializer.Accept(Self) else - value := TAstValue.Void; + value := TDataValue.Void; FScope[Node.Identifier.Address].Value := value; Result := value; end; -function TEvaluatorVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; +function TEvaluatorVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; var capturedCells: TArray; i: Integer; - sourceAddr: TResolvedAddress; sourceAddresses: TArray; begin // The binder has identified the upvalues. Capture the cells from the current scope @@ -453,69 +534,15 @@ begin Result := TClosureValue.Create(Node, FScope, capturedCells); end; -function TEvaluatorVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; +function TEvaluatorVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; var - calleeValue: TAstValue; - closure: TAstValue.IClosure; - i: Integer; -begin - calleeValue := Node.Callee.Accept(Self); - - if calleeValue.Kind <> avkClosure then - raise EArgumentException.Create('Expression is not a callable closure.'); - - closure := calleeValue.AsClosure; - - if closure is TNativeClosure then - begin - var argValues: TArray; - SetLength(argValues, Node.Arguments.Count); - for i := 0 to Node.Arguments.Count - 1 do - argValues[i] := Node.Arguments[i].Accept(Self); - Result := (closure as TNativeClosure).Method(argValues); - end - else if closure is TClosureValue then - begin - if (Node.Arguments.Count <> Length(closure.Parameters)) then - raise EArgumentException - .CreateFmt('Argument count mismatch: expected %d, got %d', [Length(closure.Parameters), Node.Arguments.Count]); - - var descriptor := (closure as TClosureValue).LambdaNode.ScopeDescriptor; - if not Assigned(descriptor) then - raise EParserError.Create('Lambda has no scope descriptor. Did the binder run?'); - - // Create the execution scope for the call, providing the captured upvalues. - var callScope := TExecutionScope.Create(closure.ClosureScope, descriptor, (closure as TClosureValue).Upvalues) as IExecutionScope; - - var adr: TResolvedAddress; - adr.Kind := akLocalOrParent; - adr.ScopeDepth := 0; - - // Slot 0 is 'Self'. - adr.SlotIndex := 0; - callScope[adr].Value := calleeValue; - - for i := 0 to Node.Arguments.Count - 1 do - begin - adr.SlotIndex := closure.Parameters[i].Address.SlotIndex; - callScope[adr].Value := Node.Arguments[i].Accept(Self); - end; - - Result := closure.Body.Accept(CreateVisitorForScope(callScope)); - end - else - raise EArgumentException.Create('Unknown closure implementation type.'); -end; - -function TEvaluatorVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; -var - leftValue, rightValue: TAstValue; + leftValue, rightValue: TDataValue; leftScalar, rightScalar: TScalar; begin leftValue := Node.Left.Accept(Self); rightValue := Node.Right.Accept(Self); - if (leftValue.Kind <> avkScalar) or (rightValue.Kind <> avkScalar) then + if (leftValue.Kind <> vkScalar) or (rightValue.Kind <> vkScalar) then raise ENotSupportedException.Create('Binary operations are only supported for scalar types.'); leftScalar := leftValue.AsScalar; @@ -582,9 +609,9 @@ begin end; end; -function TEvaluatorVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; +function TEvaluatorVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; var - rightValue: TAstValue; + rightValue: TDataValue; rightScalar: TScalar; begin rightValue := Node.Right.Accept(Self); @@ -592,7 +619,7 @@ begin case Node.Operator of uoNegate: begin - if (rightValue.Kind <> avkScalar) then + if (rightValue.Kind <> vkScalar) then raise ENotSupportedException.Create('Unary "-" is only supported for scalar types.'); rightScalar := rightValue.AsScalar; case rightScalar.Kind of @@ -611,9 +638,9 @@ begin end; end; -function TEvaluatorVisitor.VisitIfExpression(const Node: IIfExpressionNode): TAstValue; +function TEvaluatorVisitor.VisitIfExpression(const Node: IIfExpressionNode): TDataValue; var - conditionValue: TAstValue; + conditionValue: TDataValue; begin conditionValue := Node.Condition.Accept(Self); if IsTruthy(conditionValue) then @@ -623,13 +650,13 @@ begin if Assigned(Node.ElseBranch) then Result := Node.ElseBranch.Accept(Self) else - Result := TAstValue.Void; + Result := TDataValue.Void; end; end; -function TEvaluatorVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue; +function TEvaluatorVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; var - conditionValue: TAstValue; + conditionValue: TDataValue; begin conditionValue := Node.Condition.Accept(Self); if IsTruthy(conditionValue) then @@ -638,31 +665,31 @@ begin Result := Node.ElseBranch.Accept(Self); end; -function TEvaluatorVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; +function TEvaluatorVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; var expression: IAstNode; begin // The result of a block is the result of its last expression. - Result := TAstValue.Void; + Result := TDataValue.Void; for expression in Node.Expressions do begin Result := expression.Accept(Self); end; end; -function TEvaluatorVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TAstValue; +function TEvaluatorVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; var - seriesValue: TAstValue; + seriesValue: TDataValue; len: Int64; begin seriesValue := Node.Series.Accept(Self); case seriesValue.Kind of - avkSeries: len := seriesValue.AsSeries.Value.Items.Count; - avkRecordSeries: len := seriesValue.AsRecordSeries.Value.Count; - avkMemberSeries: len := seriesValue.AsMemberSeries.Value.Count; + vkSeries: len := seriesValue.AsSeries.Value.Items.Count; + vkRecordSeries: len := seriesValue.AsRecordSeries.Value.Count; + vkMemberSeries: len := seriesValue.AsMemberSeries.Value.Count; else - raise EArgumentException.CreateFmt('Cannot get length of type %s.', [GetEnumName(TypeInfo(TAstValueKind), Ord(seriesValue.Kind))]); + raise EArgumentException.CreateFmt('Cannot get length of type %s.', [GetEnumName(TypeInfo(TDataValueKind), Ord(seriesValue.Kind))]); end; Result := TScalar.FromInt64(len); @@ -670,7 +697,7 @@ end; { TDebugEvaluatorVisitor } -constructor TDebugEvaluatorVisitor.Create(const AScope: IExecutionScope; ALog: TStrings; AShowScope: Boolean; AInitialIndent: Integer = 0); +constructor TDebugEvaluatorVisitor.Create(const AScope: IExecutionScope; ALog: TStrings; AShowScope: Boolean; AInitialIndent: Integer); begin inherited Create(AScope); Assert(Assigned(ALog)); @@ -738,7 +765,7 @@ begin end; end; -function TDebugEvaluatorVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAstValue; +function TDebugEvaluatorVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; begin AppendLine('AddSeriesItem {'); Indent; @@ -750,7 +777,7 @@ begin AppendLine('} -> (void)'); end; -function TDebugEvaluatorVisitor.VisitAssignment(const Node: IAssignmentNode): TAstValue; +function TDebugEvaluatorVisitor.VisitAssignment(const Node: IAssignmentNode): TDataValue; begin AppendLine(Format('Assignment to "%s" {', [Node.Identifier.Name])); Indent; @@ -762,13 +789,13 @@ begin AppendLine(Format('} -> %s', [Result.ToString])); end; -function TDebugEvaluatorVisitor.VisitConstant(const Node: IConstantNode): TAstValue; +function TDebugEvaluatorVisitor.VisitConstant(const Node: IConstantNode): TDataValue; begin AppendLine(Format('Constant (%s)', [Node.Value.ToString])); Result := inherited VisitConstant(Node); end; -function TDebugEvaluatorVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TAstValue; +function TDebugEvaluatorVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; begin AppendLine('CreateSeries {'); Indent; @@ -780,13 +807,13 @@ begin AppendLine(Format('} -> %s', [Result.ToString])); end; -function TDebugEvaluatorVisitor.VisitIdentifier(const Node: IIdentifierNode): TAstValue; +function TDebugEvaluatorVisitor.VisitIdentifier(const Node: IIdentifierNode): TDataValue; begin Result := inherited VisitIdentifier(Node); AppendLine(Format('Identifier "%s" -> %s', [Node.Name, Result.ToString])); end; -function TDebugEvaluatorVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; +function TDebugEvaluatorVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; begin AppendLine(Format('BinaryExpr "%s" {', [Node.Operator.ToString])); Indent; @@ -798,7 +825,7 @@ begin AppendLine(Format('} -> %s', [Result.ToString])); end; -function TDebugEvaluatorVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; +function TDebugEvaluatorVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; begin AppendLine(Format('UnaryExpr "%s" {', [Node.Operator.ToString])); Indent; @@ -810,7 +837,7 @@ begin AppendLine(Format('} -> %s', [Result.ToString])); end; -function TDebugEvaluatorVisitor.VisitIfExpression(const Node: IIfExpressionNode): TAstValue; +function TDebugEvaluatorVisitor.VisitIfExpression(const Node: IIfExpressionNode): TDataValue; begin AppendLine('IfExpr{'); Indent; @@ -822,7 +849,7 @@ begin AppendLine(Format('} -> %s', [Result.ToString])); end; -function TDebugEvaluatorVisitor.VisitIndexer(const Node: IIndexerNode): TAstValue; +function TDebugEvaluatorVisitor.VisitIndexer(const Node: IIndexerNode): TDataValue; begin AppendLine('Indexer {'); Indent; @@ -834,7 +861,7 @@ begin AppendLine(Format('} -> %s', [Result.ToString])); end; -function TDebugEvaluatorVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TAstValue; +function TDebugEvaluatorVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; begin AppendLine(Format('MemberAccess (Member: %s) {', [Node.Member.Name])); Indent; @@ -846,7 +873,7 @@ begin AppendLine(Format('} -> %s', [Result.ToString])); end; -function TDebugEvaluatorVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue; +function TDebugEvaluatorVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; begin AppendLine('TernaryExpr{'); Indent; @@ -858,7 +885,7 @@ begin AppendLine(Format('} -> %s', [Result.ToString])); end; -function TDebugEvaluatorVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; +function TDebugEvaluatorVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; begin AppendLine('LambdaExpr{'); Indent; @@ -876,7 +903,7 @@ begin AppendLine(Format('} -> %s', [Result.ToString])); end; -function TDebugEvaluatorVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; +function TDebugEvaluatorVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; begin AppendLine('FunctionCall{'); Indent; @@ -889,7 +916,7 @@ begin AppendLine(Format('} -> %s', [Result.ToString])); end; -function TDebugEvaluatorVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; +function TDebugEvaluatorVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; begin AppendLine('Block{'); Indent; @@ -902,7 +929,7 @@ begin AppendLine(Format('} -> %s', [Result.ToString])); end; -function TDebugEvaluatorVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; +function TDebugEvaluatorVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; begin AppendLine(Format('VarDecl %s :=', [Node.Identifier.Name])); Indent; @@ -913,7 +940,7 @@ begin end; end; -function TDebugEvaluatorVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TAstValue; +function TDebugEvaluatorVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; begin AppendLine('SeriesLength {'); Indent; diff --git a/Src/AST/Myc.Ast.JSON.pas b/Src/AST/Myc.Ast.JSON.pas index d45fba8..d23087f 100644 --- a/Src/AST/Myc.Ast.JSON.pas +++ b/Src/AST/Myc.Ast.JSON.pas @@ -20,7 +20,8 @@ uses System.JSON, System.Generics.Collections, Myc.Ast, - Myc.Data.Scalar; + Myc.Data.Scalar, + Myc.Data.Value; // Added for TDataValue type // TJsonAstConverter implements the visitor pattern for serialization @@ -50,22 +51,22 @@ type function JsonToSeriesLengthNode(const AObj: TJSONObject): ISeriesLengthNode; protected // IAstVisitor implementation for serialization - function VisitConstant(const Node: IConstantNode): TAstValue; - function VisitIdentifier(const Node: IIdentifierNode): TAstValue; - function VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; - function VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; - function VisitIfExpression(const Node: IIfExpressionNode): TAstValue; - function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue; - function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; - function VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; - function VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; - function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; - function VisitAssignment(const Node: IAssignmentNode): TAstValue; - function VisitIndexer(const Node: IIndexerNode): TAstValue; - function VisitMemberAccess(const Node: IMemberAccessNode): TAstValue; - function VisitCreateSeries(const Node: ICreateSeriesNode): TAstValue; - function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAstValue; - function VisitSeriesLength(const Node: ISeriesLengthNode): TAstValue; + function VisitConstant(const Node: IConstantNode): TDataValue; + function VisitIdentifier(const Node: IIdentifierNode): TDataValue; + function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; + function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; + function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; + function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; + function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; + function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; + function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; + function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; + function VisitAssignment(const Node: IAssignmentNode): TDataValue; + function VisitIndexer(const Node: IIndexerNode): TDataValue; + function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; + function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; + function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; + function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; public constructor Create; destructor Destroy; override; @@ -147,7 +148,7 @@ begin AParent.AddPair(AName, scalarObj); end; -function TJsonAstConverter.VisitConstant(const Node: IConstantNode): TAstValue; +function TJsonAstConverter.VisitConstant(const Node: IConstantNode): TDataValue; var obj: TJSONObject; begin @@ -155,10 +156,10 @@ begin obj.AddPair('NodeType', TJSONString.Create('Constant')); ScalarToJson(Node.Value, obj, 'Value'); FJsonObjectStack.Push(obj); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TJsonAstConverter.VisitIdentifier(const Node: IIdentifierNode): TAstValue; +function TJsonAstConverter.VisitIdentifier(const Node: IIdentifierNode): TDataValue; var obj: TJSONObject; begin @@ -166,10 +167,10 @@ begin obj.AddPair('NodeType', TJSONString.Create('Identifier')); obj.AddPair('Name', TJSONString.Create(Node.Name)); FJsonObjectStack.Push(obj); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TJsonAstConverter.VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; +function TJsonAstConverter.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; var obj, leftObj, rightObj: TJSONObject; begin @@ -185,10 +186,10 @@ begin obj.AddPair('Left', leftObj); obj.AddPair('Right', rightObj); FJsonObjectStack.Push(obj); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TJsonAstConverter.VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; +function TJsonAstConverter.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; var obj, rightObj: TJSONObject; begin @@ -200,10 +201,10 @@ begin obj.AddPair('Operator', TJSONString.Create(Node.Operator.ToString)); obj.AddPair('Right', rightObj); FJsonObjectStack.Push(obj); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TJsonAstConverter.VisitIfExpression(const Node: IIfExpressionNode): TAstValue; +function TJsonAstConverter.VisitIfExpression(const Node: IIfExpressionNode): TDataValue; var obj, condObj, thenObj, elseObj: TJSONObject; begin @@ -230,10 +231,10 @@ begin obj.AddPair('ElseBranch', TJSONNull.Create); FJsonObjectStack.Push(obj); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TJsonAstConverter.VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue; +function TJsonAstConverter.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; var obj, condObj, thenObj, elseObj: TJSONObject; begin @@ -251,10 +252,10 @@ begin obj.AddPair('ThenBranch', thenObj); obj.AddPair('ElseBranch', elseObj); FJsonObjectStack.Push(obj); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TJsonAstConverter.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; +function TJsonAstConverter.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; var obj, bodyObj: TJSONObject; paramsArray: TJSONArray; @@ -281,10 +282,10 @@ begin obj.AddPair('Parameters', paramsArray); obj.AddPair('Body', bodyObj); FJsonObjectStack.Push(obj); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TJsonAstConverter.VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; +function TJsonAstConverter.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; var obj, calleeObj: TJSONObject; argsArray: TJSONArray; @@ -311,10 +312,10 @@ begin obj.AddPair('Callee', calleeObj); obj.AddPair('Arguments', argsArray); FJsonObjectStack.Push(obj); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TJsonAstConverter.VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; +function TJsonAstConverter.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; var obj: TJSONObject; exprsArray: TJSONArray; @@ -337,10 +338,10 @@ begin obj.AddPair('NodeType', TJSONString.Create('Block')); obj.AddPair('Expressions', exprsArray); FJsonObjectStack.Push(obj); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TJsonAstConverter.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; +function TJsonAstConverter.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; var obj, identObj, initObj: TJSONObject; begin @@ -362,10 +363,10 @@ begin else obj.AddPair('Initializer', TJSONNull.Create); FJsonObjectStack.Push(obj); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TJsonAstConverter.VisitAssignment(const Node: IAssignmentNode): TAstValue; +function TJsonAstConverter.VisitAssignment(const Node: IAssignmentNode): TDataValue; var obj, identObj, valueObj: TJSONObject; begin @@ -380,10 +381,10 @@ begin obj.AddPair('Identifier', identObj); obj.AddPair('Value', valueObj); FJsonObjectStack.Push(obj); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TJsonAstConverter.VisitIndexer(const Node: IIndexerNode): TAstValue; +function TJsonAstConverter.VisitIndexer(const Node: IIndexerNode): TDataValue; var obj, baseObj, indexObj: TJSONObject; begin @@ -398,10 +399,10 @@ begin obj.AddPair('Base', baseObj); obj.AddPair('Index', indexObj); FJsonObjectStack.Push(obj); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TJsonAstConverter.VisitMemberAccess(const Node: IMemberAccessNode): TAstValue; +function TJsonAstConverter.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; var obj, baseObj, memberObj: TJSONObject; begin @@ -416,10 +417,10 @@ begin obj.AddPair('Base', baseObj); obj.AddPair('Member', memberObj); FJsonObjectStack.Push(obj); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TJsonAstConverter.VisitCreateSeries(const Node: ICreateSeriesNode): TAstValue; +function TJsonAstConverter.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; var obj: TJSONObject; begin @@ -427,10 +428,10 @@ begin obj.AddPair('NodeType', TJSONString.Create('CreateSeries')); obj.AddPair('Definition', TJSONString.Create(Node.Definition)); FJsonObjectStack.Push(obj); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TJsonAstConverter.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAstValue; +function TJsonAstConverter.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; var obj, seriesObj, valueObj, lookbackObj: TJSONObject; begin @@ -455,10 +456,10 @@ begin else obj.AddPair('Lookback', TJSONNull.Create); FJsonObjectStack.Push(obj); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TJsonAstConverter.VisitSeriesLength(const Node: ISeriesLengthNode): TAstValue; +function TJsonAstConverter.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; var obj, seriesObj: TJSONObject; begin @@ -469,7 +470,7 @@ begin obj.AddPair('NodeType', TJSONString.Create('SeriesLength')); obj.AddPair('Series', seriesObj); FJsonObjectStack.Push(obj); - Result := TAstValue.Void; + Result := TDataValue.Void; end; { TJsonAstConverter - Deserialization } diff --git a/Src/AST/Myc.Ast.Nodes.pas b/Src/AST/Myc.Ast.Nodes.pas index e34c5df..e9ff5e2 100644 --- a/Src/AST/Myc.Ast.Nodes.pas +++ b/Src/AST/Myc.Ast.Nodes.pas @@ -5,7 +5,8 @@ interface uses System.SysUtils, System.Generics.Collections, - Myc.Data.Scalar; + Myc.Data.Scalar, + Myc.Data.Value; type // Operators and helpers @@ -20,10 +21,6 @@ type function ToString: string; end; - // Added avkMemberSeries to represent a TScalarMemberSeries value. - // Added avkSeries to represent a TScalarSeries value. - TAstValueKind = (avkUndefined, avkScalar, avkClosure, avkText, avkSeries, avkRecordSeries, avkRecord, avkMemberSeries); - // --- Forward Declarations to break cycles --- IAstVisitor = interface; IAstNode = interface; @@ -49,63 +46,14 @@ type // --- Concrete Type Definitions --- - TAstValue = record - type - IClosure = interface - {$region 'private'} - function GetBody: IAstNode; - function GetClosureScope: IExecutionScope; - function GetParameters: TArray; - function GetUpvalues: TArray; - {$endregion} - property Body: IAstNode read GetBody; - property ClosureScope: IExecutionScope read GetClosureScope; - property Parameters: TArray read GetParameters; - property Upvalues: TArray read GetUpvalues; - end; - - TVal = class(TInterfacedObject) - Value: T; - constructor Create(const AValue: T); - end; - - private - var - FKind: TAstValueKind; - FScalar: TScalar; - FInterface: IInterface; - function GetKind: TAstValueKind; inline; - function GetIsVoid: Boolean; inline; - public - class operator Initialize(out Dest: TAstValue); - class function Void: TAstValue; inline; static; - class operator Implicit(const AValue: TScalar): TAstValue; overload; inline; - class operator Implicit(const AValue: TAstValue.IClosure): TAstValue; overload; inline; - class operator Implicit(const AValue: String): TAstValue; overload; inline; - class function FromSeries(const [ref] AValue: TScalarSeries): TAstValue; static; inline; - class function FromRecordSeries(const [ref] AValue: TScalarRecordSeries): TAstValue; static; inline; - class function FromRecord(const [ref] AValue: TScalarRecord): TAstValue; static; inline; - class function FromMemberSeries(const [ref] AValue: TScalarMemberSeries): TAstValue; static; inline; - function AsScalar: TScalar; inline; - function AsClosure: TAstValue.IClosure; inline; - function AsText: String; inline; - function AsRecordSeries: TVal; inline; - function AsRecord: TVal; inline; - function AsMemberSeries: TVal; inline; - function AsSeries: TVal; inline; - function ToString: String; - property IsVoid: Boolean read GetIsVoid; - property Kind: TAstValueKind read GetKind; - end; - - // A managed, reference-counted cell that holds a TAstValue, + // A managed, reference-counted cell that holds a TDataValue, // allowing it to be shared by reference between scopes (for closures). IValueCell = interface {$region 'private'} - function GetValue: TAstValue; - procedure SetValue(const AValue: TAstValue); + function GetValue: TDataValue; + procedure SetValue(const AValue: TDataValue); {$endregion} - property Value: TAstValue read GetValue write SetValue; + property Value: TDataValue read GetValue write SetValue; end; // Defines how an identifier's address was resolved. @@ -125,12 +73,11 @@ type function GetCell(const Address: TResolvedAddress): IValueCell; {$endregion} - procedure Define(const Name: string; const Value: TAstValue); + procedure Define(const Name: string; const Value: TDataValue); function Dump: string; procedure Clear; property Cell[const Address: TResolvedAddress]: IValueCell read GetCell; default; - property Parent: IExecutionScope read GetParent; end; @@ -147,26 +94,26 @@ type end; IAstVisitor = interface - function VisitConstant(const Node: IConstantNode): TAstValue; - function VisitIdentifier(const Node: IIdentifierNode): TAstValue; - function VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; - function VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; - function VisitIfExpression(const Node: IIfExpressionNode): TAstValue; - function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue; - function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; - function VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; - function VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; - function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; - function VisitAssignment(const Node: IAssignmentNode): TAstValue; - function VisitIndexer(const Node: IIndexerNode): TAstValue; - function VisitMemberAccess(const Node: IMemberAccessNode): TAstValue; - function VisitCreateSeries(const Node: ICreateSeriesNode): TAstValue; - function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAstValue; - function VisitSeriesLength(const Node: ISeriesLengthNode): TAstValue; + function VisitConstant(const Node: IConstantNode): TDataValue; + function VisitIdentifier(const Node: IIdentifierNode): TDataValue; + function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; + function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; + function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; + function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; + function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; + function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; + function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; + function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; + function VisitAssignment(const Node: IAssignmentNode): TDataValue; + function VisitIndexer(const Node: IIndexerNode): TDataValue; + function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; + function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; + function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; + function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; end; IAstNode = interface(IInterface) - function Accept(const Visitor: IAstVisitor): TAstValue; + function Accept(const Visitor: IAstVisitor): TDataValue; end; IConstantNode = interface(IAstNode) @@ -207,7 +154,6 @@ type property Right: IAstNode read GetRight; end; - // Represents an if-statement for control flow. IIfExpressionNode = interface(IAstNode) {$region 'private'} function GetCondition: IAstNode; @@ -219,7 +165,6 @@ type property ElseBranch: IAstNode read GetElseBranch; end; - // Represents a ternary expression (e.g., condition ? true_expr : false_expr) for value selection. ITernaryExpressionNode = interface(IAstNode) {$region 'private'} function GetCondition: IAstNode; @@ -278,7 +223,6 @@ type property Value: IAstNode read GetValue; end; - // Represents an index access expression (e.g., series[index]). IIndexerNode = interface(IAstNode) {$region 'private'} function GetBase: IAstNode; @@ -288,7 +232,6 @@ type property Index: IAstNode read GetIndex; end; - // Represents a member access expression (e.g., series.field or record.field). IMemberAccessNode = interface(IAstNode) {$region 'private'} function GetBase: IAstNode; @@ -298,7 +241,6 @@ type property Member: IIdentifierNode read GetMember; end; - // Represents creating a new, empty series (e.g., new series(int)). ICreateSeriesNode = interface(IAstNode) {$region 'private'} function GetDefinition: String; @@ -306,7 +248,6 @@ type property Definition: String read GetDefinition; end; - // Represents adding a value to a series (e.g., my_series.add(value, 100)). IAddSeriesItemNode = interface(IAstNode) {$region 'private'} function GetSeries: IIdentifierNode; @@ -330,153 +271,6 @@ implementation uses System.Classes; -{ TAstValue } - -constructor TAstValue.TVal.Create(const AValue: T); -begin - inherited Create; - Value := AValue; -end; - -{ TAstValue } - -class operator TAstValue.Initialize(out Dest: TAstValue); -begin - Dest.FKind := avkUndefined; - Dest.FInterface := nil; -end; - -function TAstValue.AsClosure: TAstValue.IClosure; -begin - if (FKind <> avkClosure) then - raise EInvalidCast.Create('Cannot read value as a Closure.'); - Result := TAstValue.IClosure(FInterface); -end; - -function TAstValue.AsMemberSeries: TVal; -begin - if (FKind <> avkMemberSeries) then - raise EInvalidCast.Create('Cannot read value as MemberSeries.'); - Result := TVal(FInterface); -end; - -function TAstValue.AsRecord: TVal; -begin - if (FKind <> avkRecord) then - raise EInvalidCast.Create('Cannot read value as Record.'); - Result := (FInterface as TVal); -end; - -function TAstValue.AsRecordSeries: TVal; -begin - if (FKind <> avkRecordSeries) then - raise EInvalidCast.Create('Cannot read value as RecordSeries.'); - Result := TVal(FInterface); -end; - -function TAstValue.AsScalar: TScalar; -begin - if (FKind <> avkScalar) then - raise EInvalidCast.Create('Cannot read value as a Scalar.'); - Result := FScalar; -end; - -// Added support for TScalarSeries -function TAstValue.AsSeries: TVal; -begin - if (FKind <> avkSeries) then - raise EInvalidCast.Create('Cannot read value as Series.'); - Result := TVal(FInterface); -end; - -function TAstValue.AsText: String; -begin - if (FKind <> avkText) then - raise EInvalidCast.Create('Cannot read value as Text.'); - - Result := (FInterface as TVal).Value; -end; - -class operator TAstValue.Implicit(const AValue: TAstValue.IClosure): TAstValue; -begin - Result.FKind := avkClosure; - Result.FInterface := AValue; - Result.FScalar := Default(TScalar); -end; - -class function TAstValue.FromMemberSeries(const [ref] AValue: TScalarMemberSeries): TAstValue; -begin - Result.FKind := avkMemberSeries; - Result.FInterface := TVal.Create(AValue); - Result.FScalar := Default(TScalar); -end; - -class function TAstValue.FromRecord(const [ref] AValue: TScalarRecord): TAstValue; -begin - Result.FKind := avkRecord; - Result.FInterface := TVal.Create(AValue); - Result.FScalar := Default(TScalar); -end; - -class function TAstValue.FromRecordSeries(const [ref] AValue: TScalarRecordSeries): TAstValue; -begin - Result.FKind := avkRecordSeries; - Result.FInterface := TVal.Create(AValue); - Result.FScalar := Default(TScalar); -end; - -class operator TAstValue.Implicit(const AValue: TScalar): TAstValue; -begin - Result.FKind := avkScalar; - Result.FScalar := AValue; - Result.FInterface := nil; -end; - -class function TAstValue.FromSeries(const [ref] AValue: TScalarSeries): TAstValue; -begin - Result.FKind := avkSeries; - Result.FInterface := TVal.Create(AValue); - Result.FScalar := Default(TScalar); -end; - -class operator TAstValue.Implicit(const AValue: String): TAstValue; -begin - Result.FKind := avkText; - Result.FInterface := TVal.Create(AValue); - Result.FScalar := Default(TScalar); -end; - -function TAstValue.GetIsVoid: Boolean; -begin - Result := FKind = avkUndefined; -end; - -function TAstValue.GetKind: TAstValueKind; -begin - Result := FKind; -end; - -function TAstValue.ToString: String; -begin - case FKind of - avkScalar: Result := FScalar.ToString; - avkClosure: Result := ''; - avkText: Result := AsText; - avkSeries: Result := ''; - avkRecordSeries: Result := ''; - avkRecord: Result := ''; - avkMemberSeries: Result := ''; - avkUndefined: Result := ''; - else - Result := '[Unknown AstValue]'; - end; -end; - -class function TAstValue.Void: TAstValue; -begin - Result := Default(TAstValue); -end; - { TResolvedAddress } constructor TResolvedAddress.Create(AKind: TAddressKind; AScopeDepth, ASlotIndex: Integer); diff --git a/Src/AST/Myc.Ast.Printer.pas b/Src/AST/Myc.Ast.Printer.pas index 42588cf..a0ccf70 100644 --- a/Src/AST/Myc.Ast.Printer.pas +++ b/Src/AST/Myc.Ast.Printer.pas @@ -6,6 +6,7 @@ uses System.SysUtils, System.Classes, System.Generics.Collections, + Myc.Data.Value, Myc.Ast.Nodes, Myc.Ast; @@ -22,22 +23,22 @@ type destructor Destroy; override; function GetResult: string; // IAstVisitor - function VisitConstant(const Node: IConstantNode): TAstValue; - function VisitIdentifier(const Node: IIdentifierNode): TAstValue; - function VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; - function VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; - function VisitIfExpression(const Node: IIfExpressionNode): TAstValue; - function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue; - function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; - function VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; - function VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; - function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; - function VisitAssignment(const Node: IAssignmentNode): TAstValue; - function VisitIndexer(const Node: IIndexerNode): TAstValue; - function VisitMemberAccess(const Node: IMemberAccessNode): TAstValue; - function VisitCreateSeries(const Node: ICreateSeriesNode): TAstValue; - function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAstValue; - function VisitSeriesLength(const Node: ISeriesLengthNode): TAstValue; + function VisitConstant(const Node: IConstantNode): TDataValue; + function VisitIdentifier(const Node: IIdentifierNode): TDataValue; + function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; + function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; + function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; + function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; + function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; + function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; + function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; + function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; + function VisitAssignment(const Node: IAssignmentNode): TDataValue; + function VisitIndexer(const Node: IIndexerNode): TDataValue; + function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; + function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; + function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; + function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; end; implementation @@ -83,38 +84,38 @@ begin FBuilder.AppendLine(S); end; -function TPrettyPrintVisitor.VisitConstant(const Node: IConstantNode): TAstValue; +function TPrettyPrintVisitor.VisitConstant(const Node: IConstantNode): TDataValue; begin AppendLine(Format('Constant (%s)', [Node.Value.ToString])); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TPrettyPrintVisitor.VisitIdentifier(const Node: IIdentifierNode): TAstValue; +function TPrettyPrintVisitor.VisitIdentifier(const Node: IIdentifierNode): TDataValue; begin AppendLine(Format('Identifier (%s)', [Node.Name])); - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TPrettyPrintVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; +function TPrettyPrintVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; begin AppendLine(Format('BinaryExpr "%s"', [Node.Operator.ToString])); Indent; Node.Left.Accept(Self); Node.Right.Accept(Self); Unindent; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TPrettyPrintVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; +function TPrettyPrintVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; begin AppendLine(Format('UnaryExpr "%s"', [Node.Operator.ToString])); Indent; Node.Right.Accept(Self); Unindent; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TPrettyPrintVisitor.VisitIfExpression(const Node: IIfExpressionNode): TAstValue; +function TPrettyPrintVisitor.VisitIfExpression(const Node: IIfExpressionNode): TDataValue; begin AppendLine('IfExpr'); Indent; @@ -134,10 +135,10 @@ begin Unindent; end; Unindent; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TPrettyPrintVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue; +function TPrettyPrintVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; begin AppendLine('TernaryExpr'); Indent; @@ -154,10 +155,10 @@ begin Node.ElseBranch.Accept(Self); Unindent; Unindent; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TPrettyPrintVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; +function TPrettyPrintVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; var param: IIdentifierNode; paramNames: TStringList; @@ -177,10 +178,10 @@ begin Node.Body.Accept(Self); Unindent; Unindent; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TPrettyPrintVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; +function TPrettyPrintVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; var arg: IAstNode; begin @@ -196,10 +197,10 @@ begin arg.Accept(Self); Unindent; Unindent; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TPrettyPrintVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; +function TPrettyPrintVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; var expr: IAstNode; begin @@ -208,10 +209,10 @@ begin for expr in Node.Expressions do expr.Accept(Self); Unindent; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TPrettyPrintVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; +function TPrettyPrintVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; begin AppendLine(Format('VarDecl (%s)', [Node.Identifier.Name])); if Assigned(Node.Initializer) then @@ -220,20 +221,20 @@ begin Node.Initializer.Accept(Self); Unindent; end; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TPrettyPrintVisitor.VisitAssignment(const Node: IAssignmentNode): TAstValue; +function TPrettyPrintVisitor.VisitAssignment(const Node: IAssignmentNode): TDataValue; begin // Print the assignment node. AppendLine(Format('Assignment (%s)', [Node.Identifier.Name])); Indent; Node.Value.Accept(Self); Unindent; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TPrettyPrintVisitor.VisitIndexer(const Node: IIndexerNode): TAstValue; +function TPrettyPrintVisitor.VisitIndexer(const Node: IIndexerNode): TDataValue; begin AppendLine('Indexer'); Indent; @@ -246,10 +247,10 @@ begin Node.Index.Accept(Self); Unindent; Unindent; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TPrettyPrintVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TAstValue; +function TPrettyPrintVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; begin AppendLine(Format('MemberAccess (Member: %s)', [Node.Member.Name])); Indent; @@ -258,19 +259,19 @@ begin Node.Base.Accept(Self); Unindent; Unindent; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TPrettyPrintVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TAstValue; +function TPrettyPrintVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; begin AppendLine('CreateSeries'); Indent; AppendLine('Definition: ' + Node.Definition); Unindent; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TPrettyPrintVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAstValue; +function TPrettyPrintVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; begin AppendLine('AddSeriesItem'); Indent; @@ -290,16 +291,16 @@ begin Unindent; end; Unindent; - Result := TAstValue.Void; + Result := TDataValue.Void; end; -function TPrettyPrintVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TAstValue; -var - seriesStr: string; +function TPrettyPrintVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; begin - // Get the string representation of the series identifier by visiting the node. - seriesStr := Node.Series.Accept(Self).ToString; - Result := Format('length(%s)', [seriesStr]); + AppendLine('SeriesLength'); + Indent; + Node.Series.Accept(Self); + Unindent; + Result := TDataValue.Void; end; end. diff --git a/Src/AST/Myc.Ast.Scope.pas b/Src/AST/Myc.Ast.Scope.pas index a212875..f1d9efc 100644 --- a/Src/AST/Myc.Ast.Scope.pas +++ b/Src/AST/Myc.Ast.Scope.pas @@ -6,6 +6,7 @@ uses System.SysUtils, System.Generics.Collections, System.Classes, + Myc.Data.Value, Myc.Ast.Nodes; type @@ -28,7 +29,7 @@ type destructor Destroy; override; procedure Clear; function Dump: string; - procedure Define(const Name: string; const Value: TAstValue); + procedure Define(const Name: string; const Value: TDataValue); property NameToIndex: TDictionary read FNameToIndex; property Parent: IExecutionScope read FParent; property Values: TArray read FValues; @@ -42,19 +43,19 @@ uses type TValueCell = class(TInterfacedObject, IValueCell) private - FValue: TAstValue; - function GetValue: TAstValue; - procedure SetValue(const AValue: TAstValue); + FValue: TDataValue; // <-- Changed from TAstValue + function GetValue: TDataValue; // <-- Changed from TAstValue + procedure SetValue(const AValue: TDataValue); // <-- Changed from TAstValue end; { TValueCell } -function TValueCell.GetValue: TAstValue; +function TValueCell.GetValue: TDataValue; begin Result := FValue; end; -procedure TValueCell.SetValue(const AValue: TAstValue); +procedure TValueCell.SetValue(const AValue: TDataValue); begin FValue := AValue; end; @@ -136,7 +137,7 @@ begin FNameToIndex.Clear; end; -procedure TExecutionScope.Define(const Name: string; const Value: TAstValue); +procedure TExecutionScope.Define(const Name: string; const Value: TDataValue); // <-- Changed from TAstValue var index: Integer; begin diff --git a/Src/AST/Myc.Ast.pas b/Src/AST/Myc.Ast.pas index 07cb07d..c02a574 100644 --- a/Src/AST/Myc.Ast.pas +++ b/Src/AST/Myc.Ast.pas @@ -8,6 +8,7 @@ uses System.Generics.Collections, System.Generics.Defaults, Myc.Data.Scalar, + Myc.Data.Value, Myc.Ast.Nodes, Myc.Ast.Scope; @@ -44,22 +45,22 @@ type // TAstTraverser provides a default AST traversal implementation. TAstTraverser = class abstract(TInterfacedObject, IAstVisitor) public - function VisitConstant(const Node: IConstantNode): TAstValue; virtual; - function VisitIdentifier(const Node: IIdentifierNode): TAstValue; virtual; - function VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; virtual; - function VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; virtual; - function VisitIfExpression(const Node: IIfExpressionNode): TAstValue; virtual; - function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue; virtual; - function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; virtual; - function VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; virtual; - function VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; virtual; - function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; virtual; - function VisitAssignment(const Node: IAssignmentNode): TAstValue; virtual; - function VisitIndexer(const Node: IIndexerNode): TAstValue; virtual; - function VisitMemberAccess(const Node: IMemberAccessNode): TAstValue; virtual; - function VisitCreateSeries(const Node: ICreateSeriesNode): TAstValue; virtual; - function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAstValue; virtual; - function VisitSeriesLength(const Node: ISeriesLengthNode): TAstValue; virtual; + function VisitConstant(const Node: IConstantNode): TDataValue; virtual; + function VisitIdentifier(const Node: IIdentifierNode): TDataValue; virtual; + function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; virtual; + function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; virtual; + function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; virtual; + function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; virtual; + function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; virtual; + function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; virtual; + function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; virtual; + function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; virtual; + function VisitAssignment(const Node: IAssignmentNode): TDataValue; virtual; + function VisitIndexer(const Node: IIndexerNode): TDataValue; virtual; + function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; virtual; + function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; virtual; + function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; virtual; + function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; virtual; end; implementation @@ -86,7 +87,7 @@ type // Common base class for AST nodes to reduce boilerplate. TAstNode = class(TInterfacedObject, IAstNode) public - function Accept(const Visitor: IAstVisitor): TAstValue; virtual; abstract; + function Accept(const Visitor: IAstVisitor): TDataValue; virtual; abstract; end; { TConstantNode } @@ -96,7 +97,7 @@ type function GetValue: TScalar; public constructor Create(AValue: TScalar); - function Accept(const Visitor: IAstVisitor): TAstValue; override; + function Accept(const Visitor: IAstVisitor): TDataValue; override; end; { TIdentifierNode } @@ -111,7 +112,7 @@ type function GetAddress: TResolvedAddress; inline; public constructor Create(AName: string); - function Accept(const Visitor: IAstVisitor): TAstValue; override; + function Accept(const Visitor: IAstVisitor): TDataValue; override; property IsResolved: Boolean read GetIsResolved; property Name: string read FName; property Address: TResolvedAddress read GetAddress; @@ -128,7 +129,7 @@ type function GetRight: IAstNode; public constructor Create(ALeft: IAstNode; AOperator: TBinaryOperator; ARight: IAstNode); - function Accept(const Visitor: IAstVisitor): TAstValue; override; + function Accept(const Visitor: IAstVisitor): TDataValue; override; end; { TUnaryExpressionNode } @@ -140,7 +141,7 @@ type function GetRight: IAstNode; public constructor Create(const AOperator: TUnaryOperator; const ARight: IAstNode); - function Accept(const Visitor: IAstVisitor): TAstValue; override; + function Accept(const Visitor: IAstVisitor): TDataValue; override; end; { TIfExpressionNode } @@ -154,7 +155,7 @@ type function GetElseBranch: IAstNode; public constructor Create(const ACondition, AThenBranch, AElseBranch: IAstNode); - function Accept(const Visitor: IAstVisitor): TAstValue; override; + function Accept(const Visitor: IAstVisitor): TDataValue; override; end; { TTernaryExpressionNode } @@ -168,7 +169,7 @@ type function GetElseBranch: IAstNode; public constructor Create(const ACondition, AThenBranch, AElseBranch: IAstNode); - function Accept(const Visitor: IAstVisitor): TAstValue; override; + function Accept(const Visitor: IAstVisitor): TDataValue; override; end; { TLambdaExpressionNode } @@ -184,7 +185,7 @@ type function GetUpvalues: TArray; public constructor Create(const AParameters: TArray; const ABody: IAstNode); - function Accept(const Visitor: IAstVisitor): TAstValue; override; + function Accept(const Visitor: IAstVisitor): TDataValue; override; property ScopeDescriptor: IScopeDescriptor read GetScopeDescriptor; end; @@ -198,7 +199,7 @@ type public constructor Create(const ACallee: IAstNode; const AArguments: array of IAstNode); destructor Destroy; override; - function Accept(const Visitor: IAstVisitor): TAstValue; override; + function Accept(const Visitor: IAstVisitor): TDataValue; override; end; { TBlockExpressionNode } @@ -209,7 +210,7 @@ type public constructor Create(const AExpressions: array of IAstNode); destructor Destroy; override; - function Accept(const Visitor: IAstVisitor): TAstValue; override; + function Accept(const Visitor: IAstVisitor): TDataValue; override; end; { TVariableDeclarationNode } @@ -221,7 +222,7 @@ type function GetInitializer: IAstNode; public constructor Create(const AIdentifier: IIdentifierNode; AInitializer: IAstNode); - function Accept(const Visitor: IAstVisitor): TAstValue; override; + function Accept(const Visitor: IAstVisitor): TDataValue; override; end; { TAssignmentNode } @@ -233,7 +234,7 @@ type function GetValue: IAstNode; public constructor Create(const AIdentifier: IIdentifierNode; const AValue: IAstNode); - function Accept(const Visitor: IAstVisitor): TAstValue; override; + function Accept(const Visitor: IAstVisitor): TDataValue; override; end; { TIndexerNode } @@ -245,7 +246,7 @@ type function GetIndex: IAstNode; public constructor Create(const ABase: IAstNode; const AIndex: IAstNode); - function Accept(const Visitor: IAstVisitor): TAstValue; override; + function Accept(const Visitor: IAstVisitor): TDataValue; override; end; { TMemberAccessNode } @@ -257,7 +258,7 @@ type function GetMember: IIdentifierNode; public constructor Create(const ABase: IAstNode; const AMember: IIdentifierNode); - function Accept(const Visitor: IAstVisitor): TAstValue; override; + function Accept(const Visitor: IAstVisitor): TDataValue; override; end; { TCreateSeriesNode } @@ -267,7 +268,7 @@ type function GetDefinition: String; public constructor Create(const ADefinition: String); - function Accept(const Visitor: IAstVisitor): TAstValue; override; + function Accept(const Visitor: IAstVisitor): TDataValue; override; end; { TAddSeriesItemNode } @@ -281,7 +282,7 @@ type function GetLookback: IAstNode; public constructor Create(const ASeries: IIdentifierNode; const AValue: IAstNode; const ALookback: IAstNode); - function Accept(const Visitor: IAstVisitor): TAstValue; override; + function Accept(const Visitor: IAstVisitor): TDataValue; override; end; { TSeriesLengthNode } @@ -291,7 +292,7 @@ type function GetSeries: IIdentifierNode; public constructor Create(const ASeries: IIdentifierNode); - function Accept(const Visitor: IAstVisitor): TAstValue; override; + function Accept(const Visitor: IAstVisitor): TDataValue; override; end; TResolvedAddressComparer = class(TEqualityComparer) @@ -312,9 +313,9 @@ type public constructor Create(const AInitialScope: IExecutionScope); destructor Destroy; override; - function VisitIdentifier(const Node: IIdentifierNode): TAstValue; override; - function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; override; - function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; override; + function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override; + function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override; + function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override; property CurrentDescriptor: IScopeDescriptor read FCurrentDescriptor; end; @@ -406,7 +407,7 @@ begin FValue := AValue; end; -function TConstantNode.Accept(const Visitor: IAstVisitor): TAstValue; +function TConstantNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitConstant(Self); end; @@ -424,7 +425,7 @@ begin FName := AName; end; -function TIdentifierNode.Accept(const Visitor: IAstVisitor): TAstValue; +function TIdentifierNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitIdentifier(Self); end; @@ -457,7 +458,7 @@ begin FRight := ARight; end; -function TBinaryExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue; +function TBinaryExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitBinaryExpression(Self); end; @@ -486,7 +487,7 @@ begin FRight := ARight; end; -function TUnaryExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue; +function TUnaryExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitUnaryExpression(Self); end; @@ -511,7 +512,7 @@ begin FElseBranch := AElseBranch; end; -function TIfExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue; +function TIfExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitIfExpression(Self); end; @@ -541,7 +542,7 @@ begin FElseBranch := AElseBranch; end; -function TTernaryExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue; +function TTernaryExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitTernaryExpression(Self); end; @@ -576,7 +577,7 @@ begin Result := FUpvalues; end; -function TLambdaExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue; +function TLambdaExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitLambdaExpression(Self); end; @@ -615,7 +616,7 @@ begin inherited; end; -function TFunctionCallNode.Accept(const Visitor: IAstVisitor): TAstValue; +function TFunctionCallNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitFunctionCall(Self); end; @@ -648,7 +649,7 @@ begin inherited; end; -function TBlockExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue; +function TBlockExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitBlockExpression(Self); end; @@ -667,7 +668,7 @@ begin FInitializer := AInitializer; end; -function TVariableDeclarationNode.Accept(const Visitor: IAstVisitor): TAstValue; +function TVariableDeclarationNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitVariableDeclaration(Self); end; @@ -691,7 +692,7 @@ begin FValue := AValue; end; -function TAssignmentNode.Accept(const Visitor: IAstVisitor): TAstValue; +function TAssignmentNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitAssignment(Self); end; @@ -715,7 +716,7 @@ begin FIndex := AIndex; end; -function TIndexerNode.Accept(const Visitor: IAstVisitor): TAstValue; +function TIndexerNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitIndexer(Self); end; @@ -739,7 +740,7 @@ begin FMember := AMember; end; -function TMemberAccessNode.Accept(const Visitor: IAstVisitor): TAstValue; +function TMemberAccessNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitMemberAccess(Self); end; @@ -762,7 +763,7 @@ begin FDefinition := ADefinition; end; -function TCreateSeriesNode.Accept(const Visitor: IAstVisitor): TAstValue; +function TCreateSeriesNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitCreateSeries(Self); end; @@ -782,7 +783,7 @@ begin FLookback := ALookback; end; -function TAddSeriesItemNode.Accept(const Visitor: IAstVisitor): TAstValue; +function TAddSeriesItemNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitAddSeriesItem(Self); end; @@ -810,7 +811,7 @@ begin FSeries := ASeries; end; -function TSeriesLengthNode.Accept(const Visitor: IAstVisitor): TAstValue; +function TSeriesLengthNode.Accept(const Visitor: IAstVisitor): TDataValue; begin Result := Visitor.VisitSeriesLength(Self); end; @@ -853,7 +854,7 @@ begin FCurrentDescriptor := FCurrentDescriptor.Parent; end; -function TBinder.VisitIdentifier(const Node: IIdentifierNode): TAstValue; +function TBinder.VisitIdentifier(const Node: IIdentifierNode): TDataValue; var depth, idx: Integer; identNode: TIdentifierNode; @@ -894,7 +895,7 @@ begin raise Exception.CreateFmt('Undefined identifier: "%s"', [identNode.Name]); end; -function TBinder.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; +function TBinder.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; var param: IIdentifierNode; upvalueMap: TDictionary; @@ -943,7 +944,7 @@ begin end; end; -function TBinder.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; +function TBinder.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; var slotIndex: Integer; identNode: TIdentifierNode; @@ -1078,7 +1079,7 @@ end; { TAstTraverser } -function TAstTraverser.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAstValue; +function TAstTraverser.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; begin Node.Series.Accept(Self); Node.Value.Accept(Self); @@ -1086,19 +1087,19 @@ begin Node.Lookback.Accept(Self); end; -function TAstTraverser.VisitAssignment(const Node: IAssignmentNode): TAstValue; +function TAstTraverser.VisitAssignment(const Node: IAssignmentNode): TDataValue; begin Node.Value.Accept(Self); Node.Identifier.Accept(Self); end; -function TAstTraverser.VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; +function TAstTraverser.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; begin Node.Left.Accept(Self); Node.Right.Accept(Self); end; -function TAstTraverser.VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; +function TAstTraverser.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; var expr: IAstNode; begin @@ -1106,15 +1107,15 @@ begin expr.Accept(Self); end; -function TAstTraverser.VisitConstant(const Node: IConstantNode): TAstValue; +function TAstTraverser.VisitConstant(const Node: IConstantNode): TDataValue; begin end; -function TAstTraverser.VisitCreateSeries(const Node: ICreateSeriesNode): TAstValue; +function TAstTraverser.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; begin end; -function TAstTraverser.VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; +function TAstTraverser.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; var arg: IAstNode; begin @@ -1123,11 +1124,11 @@ begin arg.Accept(Self); end; -function TAstTraverser.VisitIdentifier(const Node: IIdentifierNode): TAstValue; +function TAstTraverser.VisitIdentifier(const Node: IIdentifierNode): TDataValue; begin end; -function TAstTraverser.VisitIfExpression(const Node: IIfExpressionNode): TAstValue; +function TAstTraverser.VisitIfExpression(const Node: IIfExpressionNode): TDataValue; begin Node.Condition.Accept(Self); Node.ThenBranch.Accept(Self); @@ -1135,13 +1136,13 @@ begin Node.ElseBranch.Accept(Self); end; -function TAstTraverser.VisitIndexer(const Node: IIndexerNode): TAstValue; +function TAstTraverser.VisitIndexer(const Node: IIndexerNode): TDataValue; begin Node.Base.Accept(Self); Node.Index.Accept(Self); end; -function TAstTraverser.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; +function TAstTraverser.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; var param: IIdentifierNode; begin @@ -1150,30 +1151,30 @@ begin Node.Body.Accept(Self); end; -function TAstTraverser.VisitMemberAccess(const Node: IMemberAccessNode): TAstValue; +function TAstTraverser.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; begin // Do not visit the member identifier, as it's not a variable in the current scope. Node.Base.Accept(Self); end; -function TAstTraverser.VisitSeriesLength(const Node: ISeriesLengthNode): TAstValue; +function TAstTraverser.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; begin Node.Series.Accept(Self); end; -function TAstTraverser.VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue; +function TAstTraverser.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; begin Node.Condition.Accept(Self); Node.ThenBranch.Accept(Self); Node.ElseBranch.Accept(Self); end; -function TAstTraverser.VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; +function TAstTraverser.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; begin Node.Right.Accept(Self); end; -function TAstTraverser.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; +function TAstTraverser.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; begin if Assigned(Node.Initializer) then Node.Initializer.Accept(Self); diff --git a/Src/Data/Myc.Data.Value.pas b/Src/Data/Myc.Data.Value.pas new file mode 100644 index 0000000..e32a370 --- /dev/null +++ b/Src/Data/Myc.Data.Value.pas @@ -0,0 +1,208 @@ +unit Myc.Data.Value; + +interface + +uses + System.SysUtils, + Myc.Data.Scalar, + Myc.Data.Series, + Myc.Data.Decimal; + +type + TDataValueKind = (vkVoid, vkScalar, vkCallable, vkText, vkSeries, vkRecordSeries, vkRecord, vkMemberSeries); + + TDataValue = record + public + type + ICallable = interface + function GetArity: Integer; + function Invoke(const AVisitor: IInterface; const ASelf: TDataValue; const AArgs: TArray): TDataValue; + property Arity: Integer read GetArity; + end; + + TVal = class(TInterfacedObject) + Value: T; + constructor Create(const AValue: T); + end; + + private + var + FKind: TDataValueKind; + FScalar: TScalar; + FInterface: IInterface; + function GetKind: TDataValueKind; inline; + function GetIsVoid: Boolean; inline; + public + class operator Initialize(out Dest: TDataValue); + class function Void: TDataValue; inline; static; + + class operator Implicit(const AValue: TScalar): TDataValue; overload; inline; + class operator Implicit(const AValue: ICallable): TDataValue; overload; inline; + class operator Implicit(const AValue: String): TDataValue; overload; inline; + + class function FromSeries(const [ref] AValue: TScalarSeries): TDataValue; static; inline; + class function FromRecordSeries(const [ref] AValue: TScalarRecordSeries): TDataValue; static; inline; + class function FromRecord(const [ref] AValue: TScalarRecord): TDataValue; static; inline; + class function FromMemberSeries(const [ref] AValue: TScalarMemberSeries): TDataValue; static; inline; + + function AsScalar: TScalar; inline; + function AsCallable: ICallable; inline; + function AsText: String; inline; + function AsRecordSeries: TVal; inline; + function AsRecord: TVal; inline; + function AsMemberSeries: TVal; inline; + function AsSeries: TVal; inline; + + function ToString: String; + property IsVoid: Boolean read GetIsVoid; + property Kind: TDataValueKind read GetKind; + end; + +implementation + +{ TDataValue.TVal } + +constructor TDataValue.TVal.Create(const AValue: T); +begin + inherited Create; + Value := AValue; +end; + +{ TDataValue } + +class operator TDataValue.Initialize(out Dest: TDataValue); +begin + Dest.FKind := vkVoid; // Geändert + Dest.FInterface := nil; +end; + +function TDataValue.AsCallable: ICallable; +begin + if (FKind <> vkCallable) then + raise EInvalidCast.Create('Cannot read value as a Callable.'); + Result := ICallable(FInterface); +end; + +function TDataValue.AsMemberSeries: TVal; +begin + if (FKind <> vkMemberSeries) then + raise EInvalidCast.Create('Cannot read value as MemberSeries.'); + Result := TVal(FInterface); +end; + +function TDataValue.AsRecord: TVal; +begin + if (FKind <> vkRecord) then + raise EInvalidCast.Create('Cannot read value as Record.'); + Result := (FInterface as TVal); +end; + +function TDataValue.AsRecordSeries: TVal; +begin + if (FKind <> vkRecordSeries) then + raise EInvalidCast.Create('Cannot read value as RecordSeries.'); + Result := TVal(FInterface); +end; + +function TDataValue.AsScalar: TScalar; +begin + if (FKind <> vkScalar) then + raise EInvalidCast.Create('Cannot read value as a Scalar.'); + Result := FScalar; +end; + +function TDataValue.AsSeries: TVal; +begin + if (FKind <> vkSeries) then + raise EInvalidCast.Create('Cannot read value as Series.'); + Result := TVal(FInterface); +end; + +function TDataValue.AsText: String; +begin + if (FKind <> vkText) then + raise EInvalidCast.Create('Cannot read value as Text.'); + Result := (FInterface as TVal).Value; +end; + +class function TDataValue.FromMemberSeries(const [ref] AValue: TScalarMemberSeries): TDataValue; +begin + Result.FKind := vkMemberSeries; + Result.FInterface := TVal.Create(AValue); + Result.FScalar := Default(TScalar); +end; + +class function TDataValue.FromRecord(const [ref] AValue: TScalarRecord): TDataValue; +begin + Result.FKind := vkRecord; + Result.FInterface := TVal.Create(AValue); + Result.FScalar := Default(TScalar); +end; + +class function TDataValue.FromRecordSeries(const [ref] AValue: TScalarRecordSeries): TDataValue; +begin + Result.FKind := vkRecordSeries; + Result.FInterface := TVal.Create(AValue); + Result.FScalar := Default(TScalar); +end; + +class function TDataValue.FromSeries(const [ref] AValue: TScalarSeries): TDataValue; +begin + Result.FKind := vkSeries; + Result.FInterface := TVal.Create(AValue); + Result.FScalar := Default(TScalar); +end; + +class operator TDataValue.Implicit(const AValue: ICallable): TDataValue; +begin + Result.FKind := vkCallable; + Result.FInterface := AValue; + Result.FScalar := Default(TScalar); +end; + +class operator TDataValue.Implicit(const AValue: TScalar): TDataValue; +begin + Result.FKind := vkScalar; + Result.FScalar := AValue; + Result.FInterface := nil; +end; + +class operator TDataValue.Implicit(const AValue: String): TDataValue; +begin + Result.FKind := vkText; + Result.FInterface := TVal.Create(AValue); + Result.FScalar := Default(TScalar); +end; + +function TDataValue.GetIsVoid: Boolean; +begin + Result := FKind = vkVoid; // Geändert +end; + +function TDataValue.GetKind: TDataValueKind; +begin + Result := FKind; +end; + +function TDataValue.ToString: String; +begin + case FKind of + vkScalar: Result := FScalar.ToString; + vkCallable: Result := ''; + vkText: Result := AsText; + vkSeries: Result := ''; + vkRecordSeries: Result := ''; + vkRecord: Result := ''; + vkMemberSeries: Result := ''; + vkVoid: Result := ''; // Geändert + else + Result := '[Unknown DataValue]'; + end; +end; + +class function TDataValue.Void: TDataValue; +begin + Result := Default(TDataValue); +end; + +end. diff --git a/Test/MycTests.dpr b/Test/MycTests.dpr index 71aeb8c..fc38ed3 100644 --- a/Test/MycTests.dpr +++ b/Test/MycTests.dpr @@ -37,7 +37,7 @@ uses Myc.Ast in '..\Src\AST\Myc.Ast.pas', Myc.Data.Types.JSON in '..\Src\Data\Myc.Data.Types.JSON.pas', TestDataTypes.JSON in '..\Src\Data\TestDataTypes.JSON.pas', - Myc.Data.POD in '..\Src\Data\Myc.Data.POD.pas', + Myc.Data.POD in '..\Src\Data\Myc.Data.Scalar.pas', Myc.Data.Decimal in '..\Src\Data\Myc.Data.Decimal.pas', TestDataDecimal in 'TestDataDecimal.pas', TestDataPOD in 'TestDataPOD.pas'; diff --git a/Test/MycTests.dproj b/Test/MycTests.dproj index 6955d15..ff213a7 100644 --- a/Test/MycTests.dproj +++ b/Test/MycTests.dproj @@ -138,7 +138,9 @@ $(PreBuildEvent)]]> - + + Myc.Data.POD + diff --git a/Test/TestDataPOD.pas b/Test/TestDataPOD.pas index 629b227..831858f 100644 --- a/Test/TestDataPOD.pas +++ b/Test/TestDataPOD.pas @@ -4,7 +4,7 @@ interface uses System.SysUtils, - Myc.Data.POD, + Myc.Data.Scalar, Myc.Data.Decimal, Myc.Data.Series, DUnitX.TestFramework; @@ -30,8 +30,8 @@ type [TestCase('BooleanTrue', 'True,skBoolean')] [TestCase('BooleanFalse', 'False,skBoolean')] [TestCase('Char', 'Z,skChar')] - [TestCase('String', 'Hello World,skString')] - [TestCase('StringTruncated', 'This string is definitely longer than 15 chars,skString')] + [TestCase('String', 'Hello W,skString')] // Max 7 chars + [TestCase('StringTruncated', 'This string is definitely longer than 7 chars,skString')] procedure TestScalarCreation(const AValueStr: string; AExpectedKind: TScalarKind); [Test] @@ -226,13 +226,15 @@ var begin // 1. Create a definition recDef := - [ - TScalarRecordField.Create('ID', skInt64), - TScalarRecordField.Create('Name', skString), - TScalarRecordField.Create('Price', skDecimal) - ]; - Assert.AreEqual(Int64(3), Length(recDef), 'Record definition field count mismatch'); - Assert.AreEqual('Name', recDef[1].Name, 'Record definition field name mismatch'); + TScalarRecordDefinition.Create( + [ + TScalarRecordField.Create('ID', skInt64), + TScalarRecordField.Create('Name', skString), + TScalarRecordField.Create('Price', skDecimal) + ] + ); + Assert.AreEqual(Int64(3), Length(recDef.Fields), 'Record definition field count mismatch'); + Assert.AreEqual('Name', recDef.Fields[1].Name, 'Record definition field name mismatch'); // 2. Create a matching set of values values := [TScalar.FromInt64(99).Value, TScalar.FromString('Product').Value, TScalar.FromDecimal(TDecimal.Create(1995, 2)).Value]; @@ -286,7 +288,7 @@ var retrievedRec: TScalarRecord; begin // 1. Define the structure of the records in the series - recDef := [TScalarRecordField.Create('ID', skInt64), TScalarRecordField.Create('Price', skDecimal)]; + recDef := TScalarRecordDefinition.Create([TScalarRecordField.Create('ID', skInt64), TScalarRecordField.Create('Price', skDecimal)]); // 2. Create the series with the definition series := TScalarRecordSeries.Create(recDef);