TDataValue as new global variant type

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