Binder refactoring, Monster refactoring
This commit is contained in:
@@ -9,43 +9,44 @@ uses
|
||||
Myc.Data.Scalar,
|
||||
Myc.Data.Value,
|
||||
Myc.Ast.Nodes,
|
||||
Myc.Ast.Visitor,
|
||||
Myc.Ast.Binding,
|
||||
Myc.Ast.Scope;
|
||||
|
||||
type
|
||||
// The standard AST evaluator for production use.
|
||||
TEvaluatorVisitor = class(TAstVisitor, IEvaluatorVisitor)
|
||||
// This class inherits directly from TInterfacedObject as it is an
|
||||
// Interpreter (AST -> TDataValue), not a Transformer (AST -> IAstNode).
|
||||
TEvaluatorVisitor = class(TInterfacedObject, IAstVisitor, IEvaluatorVisitor)
|
||||
private
|
||||
FScope: IExecutionScope;
|
||||
class var
|
||||
procedure HandleTCO(var ResultValue: TDataValue);
|
||||
|
||||
protected
|
||||
function VisitConstant(const Node: IConstantNode): TDataValue; override;
|
||||
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
|
||||
function VisitKeyword(const Node: IKeywordNode): TDataValue; override;
|
||||
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; override;
|
||||
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; override;
|
||||
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
|
||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
|
||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
|
||||
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override;
|
||||
function VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue; override;
|
||||
function VisitUnquote(const Node: IUnquoteNode): TDataValue; override;
|
||||
function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue; override;
|
||||
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
|
||||
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue; override;
|
||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
|
||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
|
||||
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
|
||||
function VisitIndexer(const Node: IIndexerNode): TDataValue; override;
|
||||
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
|
||||
function VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue; override;
|
||||
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override;
|
||||
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; override;
|
||||
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override;
|
||||
function VisitRecurNode(const Node: IRecurNode): TDataValue; override;
|
||||
// IAstVisitor methods made virtual for TDebugEvaluatorVisitor to override
|
||||
function VisitConstant(const Node: IConstantNode): TDataValue; virtual;
|
||||
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; virtual;
|
||||
function VisitKeyword(const Node: IKeywordNode): TDataValue; virtual;
|
||||
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; virtual;
|
||||
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; virtual;
|
||||
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; virtual;
|
||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; virtual;
|
||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; virtual;
|
||||
function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; virtual;
|
||||
function VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue; virtual;
|
||||
function VisitUnquote(const Node: IUnquoteNode): TDataValue; virtual;
|
||||
function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue; virtual;
|
||||
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; virtual;
|
||||
function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue; virtual;
|
||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; virtual;
|
||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; virtual;
|
||||
function VisitAssignment(const Node: IAssignmentNode): TDataValue; virtual;
|
||||
function VisitIndexer(const Node: IIndexerNode): TDataValue; virtual;
|
||||
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; virtual;
|
||||
function VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue; virtual;
|
||||
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; virtual;
|
||||
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; virtual;
|
||||
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; virtual;
|
||||
function VisitRecurNode(const Node: IRecurNode): TDataValue; virtual;
|
||||
|
||||
function IsTruthy(const AValue: TDataValue): Boolean; inline;
|
||||
|
||||
@@ -68,11 +69,12 @@ implementation
|
||||
uses
|
||||
System.TypInfo,
|
||||
System.Generics.Defaults,
|
||||
Myc.Ast, // Added
|
||||
Myc.Data.Keyword,
|
||||
Myc.Data.Decimal,
|
||||
Myc.Data.Series,
|
||||
Myc.Data.Scalar.JSON,
|
||||
Myc.Ast.Binding.Nodes;
|
||||
Myc.Data.Scalar.JSON;
|
||||
// Myc.Ast.Binding.Nodes; // Removed
|
||||
|
||||
// Helper type for TCO via trampolining.
|
||||
type
|
||||
@@ -206,7 +208,7 @@ end;
|
||||
|
||||
function TEvaluatorVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
||||
var
|
||||
boundNode: TBoundLambdaExpressionNode;
|
||||
boundNode: TLambdaExpressionNode; // Changed
|
||||
capturedCells: TArray<IValueCell>;
|
||||
i: Integer;
|
||||
sourceAddresses: TArray<TResolvedAddress>;
|
||||
@@ -214,7 +216,7 @@ var
|
||||
visitorFactory: TEvaluatorFactory;
|
||||
begin
|
||||
// Cast to the bound node to access binder-specific information.
|
||||
boundNode := Node as TBoundLambdaExpressionNode;
|
||||
boundNode := Node as TLambdaExpressionNode; // Changed
|
||||
|
||||
// Create the closure by capturing the value cells of all upvalues from the current scope.
|
||||
sourceAddresses := boundNode.Upvalues;
|
||||
@@ -257,13 +259,13 @@ begin
|
||||
|
||||
// Capture the closure itself in slot 0 for 'recur' to find it.
|
||||
adr.SlotIndex := 0;
|
||||
lambdaScope[adr] := closure;
|
||||
lambdaScope[adr] := TDataValue(closure); // Explicit cast
|
||||
|
||||
// Populate the scope with the actual parameters passed to the function.
|
||||
for i := 0 to High(ArgValues) do
|
||||
begin
|
||||
// Parameters in a bound lambda must be bound identifiers.
|
||||
adr.SlotIndex := (params[i] as TBoundIdentifierNode).Address.SlotIndex;
|
||||
adr.SlotIndex := (params[i] as TIdentifierNode).Address.SlotIndex; // Changed
|
||||
lambdaScope[adr] := ArgValues[i];
|
||||
end;
|
||||
|
||||
@@ -273,7 +275,7 @@ begin
|
||||
end;
|
||||
|
||||
// The result of visiting a lambda node is the callable closure itself.
|
||||
Result := closure;
|
||||
Result := TDataValue(closure); // Explicit cast
|
||||
end;
|
||||
|
||||
function TEvaluatorVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
|
||||
@@ -303,7 +305,7 @@ function TEvaluatorVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDa
|
||||
var
|
||||
calleeValue: TDataValue;
|
||||
argValues: TArray<TDataValue>;
|
||||
boundNode: TBoundFunctionCallNode;
|
||||
boundNode: TFunctionCallNode; // Changed
|
||||
begin
|
||||
calleeValue := Node.Callee.Accept(Self);
|
||||
if calleeValue.Kind <> vkMethod then
|
||||
@@ -314,7 +316,7 @@ begin
|
||||
for var i := 0 to High(argNodes) do
|
||||
argValues[i] := argNodes[i].Accept(Self);
|
||||
|
||||
boundNode := Node as TBoundFunctionCallNode;
|
||||
boundNode := Node as TFunctionCallNode; // Changed
|
||||
if boundNode.IsTailCall then
|
||||
begin
|
||||
// This is a tail call. Return a thunk to be processed by the trampoline.
|
||||
@@ -363,7 +365,7 @@ var
|
||||
itemValue, lookbackValue, seriesVar: TDataValue;
|
||||
lookback: Int64;
|
||||
begin
|
||||
seriesVar := FScope[(Node.Series as TBoundIdentifierNode).Address];
|
||||
seriesVar := FScope[(Node.Series as TIdentifierNode).Address]; // Changed
|
||||
itemValue := Node.Value.Accept(Self);
|
||||
lookback := -1;
|
||||
|
||||
@@ -397,7 +399,7 @@ begin
|
||||
// Evaluate the new value.
|
||||
Result := Node.Value.Accept(Self);
|
||||
// Assign it. The scope's SetValues implementation now handles boxing correctly.
|
||||
FScope[(Node.Identifier as TBoundIdentifierNode).Address] := Result;
|
||||
FScope[(Node.Identifier as TIdentifierNode).Address] := Result; // Changed
|
||||
end;
|
||||
|
||||
function TEvaluatorVisitor.VisitConstant(const Node: IConstantNode): TDataValue;
|
||||
@@ -408,7 +410,7 @@ end;
|
||||
function TEvaluatorVisitor.VisitKeyword(const Node: IKeywordNode): TDataValue;
|
||||
begin
|
||||
// Return the keyword as a TScalar value
|
||||
Result := TDataValue(TScalar.FromKeyword(Node.Value));
|
||||
Result := TDataValue(TScalar.FromKeyword(Node.Value)); // Explicit cast
|
||||
end;
|
||||
|
||||
function TEvaluatorVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
|
||||
@@ -434,7 +436,7 @@ end;
|
||||
function TEvaluatorVisitor.VisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
||||
begin
|
||||
// The scope's GetValues implementation now handles unboxing automatically.
|
||||
Result := FScope[(Node as TBoundIdentifierNode).Address];
|
||||
Result := FScope[(Node as TIdentifierNode).Address]; // Changed
|
||||
end;
|
||||
|
||||
function TEvaluatorVisitor.VisitIndexer(const Node: IIndexerNode): TDataValue;
|
||||
@@ -458,7 +460,7 @@ begin
|
||||
series := baseValue.AsSeries;
|
||||
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]);
|
||||
Result := series.Items[Integer(index)];
|
||||
Result := TDataValue(series.Items[Integer(index)]); // Explicit cast
|
||||
end;
|
||||
vkRecordSeries:
|
||||
begin
|
||||
@@ -487,7 +489,7 @@ begin
|
||||
case baseValue.Kind of
|
||||
vkRecordSeries: Result := TDataValue.FromSeries(baseValue.AsRecordSeries[Node.Member.Value]);
|
||||
|
||||
vkRecord: Result := baseValue.AsRecord[Node.Member.Value];
|
||||
vkRecord: Result := TDataValue(baseValue.AsRecord[Node.Member.Value]); // Explicit cast
|
||||
|
||||
// --- NEW GENERIC PATH ---
|
||||
vkGenericRecord:
|
||||
@@ -509,10 +511,10 @@ var
|
||||
i: Integer;
|
||||
begin
|
||||
// Check which type the binder created
|
||||
if Node is TBoundGenericRecordLiteralNode then
|
||||
if Node is TGenericRecordLiteralNode then // Changed
|
||||
begin
|
||||
// --- NEW GENERIC PATH ---
|
||||
var boundNode := Node as TBoundGenericRecordLiteralNode;
|
||||
var boundNode := Node as TGenericRecordLiteralNode; // Changed
|
||||
var genFields: TArray<TPair<IKeyword, TDataValue>>;
|
||||
SetLength(genFields, Length(boundNode.Fields));
|
||||
|
||||
@@ -530,10 +532,10 @@ begin
|
||||
var dynRec := TDynamicRecord.Create(genFields);
|
||||
Result := TDataValue.FromGenericRecord(dynRec);
|
||||
end
|
||||
else if Node is TBoundRecordLiteralNode then
|
||||
else if Node is TRecordLiteralNode then // Changed
|
||||
begin
|
||||
// --- EXISTING SCALAR PATH ---
|
||||
var boundNode := Node as TBoundRecordLiteralNode;
|
||||
var boundNode := Node as TRecordLiteralNode; // Changed
|
||||
var values: TArray<TScalar.TValue>;
|
||||
SetLength(values, Length(boundNode.Fields));
|
||||
|
||||
@@ -554,7 +556,7 @@ end;
|
||||
function TEvaluatorVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
|
||||
var
|
||||
address: TResolvedAddress;
|
||||
boundNode: TBoundVariableDeclarationNode;
|
||||
boundNode: TVariableDeclarationNode; // Changed
|
||||
begin
|
||||
// First, evaluate the initializer to get the variable's initial value.
|
||||
if Assigned(Node.Initializer) then
|
||||
@@ -562,9 +564,9 @@ begin
|
||||
else
|
||||
Result := TDataValue.Void;
|
||||
|
||||
// After binding, all declaration nodes are TBoundVariableDeclarationNode
|
||||
boundNode := Node as TBoundVariableDeclarationNode;
|
||||
address := (boundNode.Identifier as TBoundIdentifierNode).Address;
|
||||
// After binding, all declaration nodes are TVariableDeclarationNode
|
||||
boundNode := Node as TVariableDeclarationNode; // Changed
|
||||
address := (boundNode.Identifier as TIdentifierNode).Address; // Changed
|
||||
|
||||
// Check the IsBoxed flag set by the binder.
|
||||
if boundNode.IsBoxed then
|
||||
@@ -599,7 +601,7 @@ begin
|
||||
+ ' and '
|
||||
+ rightValue.AsScalar.Kind.ToString
|
||||
+ ' .');
|
||||
Result := resScalar;
|
||||
Result := TDataValue(resScalar); // Explicit cast
|
||||
end;
|
||||
|
||||
function TEvaluatorVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
|
||||
@@ -614,7 +616,7 @@ begin
|
||||
var res: TScalar;
|
||||
if not TScalar.TryUnaryOperation(Node.Operator, rightValue.AsScalar, res) then
|
||||
raise ENotSupportedException.Create('Unary operation not supported for scalar type' + rightValue.AsScalar.Kind.ToString + '.');
|
||||
Result := res;
|
||||
Result := TDataValue(res); // Explicit cast
|
||||
end;
|
||||
|
||||
function TEvaluatorVisitor.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
||||
@@ -649,7 +651,7 @@ var
|
||||
seriesValue: TDataValue;
|
||||
len: Int64;
|
||||
begin
|
||||
seriesValue := FScope[(Node.Series as TBoundIdentifierNode).Address];
|
||||
seriesValue := FScope[(Node.Series as TIdentifierNode).Address]; // Changed
|
||||
|
||||
case seriesValue.Kind of
|
||||
vkSeries: len := seriesValue.AsSeries.Count;
|
||||
@@ -658,7 +660,7 @@ begin
|
||||
raise EArgumentException.CreateFmt('Cannot get length of type %s.', [GetEnumName(TypeInfo(TDataValueKind), Ord(seriesValue.Kind))]);
|
||||
end;
|
||||
|
||||
Result := TScalar.FromInt64(len);
|
||||
Result := TDataValue(TScalar.FromInt64(len)); // Explicit cast
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
Reference in New Issue
Block a user