Added user library

This commit is contained in:
Michael Schimmel
2025-09-24 10:03:10 +02:00
parent 5a1919ec07
commit 624af31243
14 changed files with 585 additions and 305 deletions
+14 -29
View File
@@ -51,8 +51,6 @@ type
function Execute(const RootNode: IAstNode; out Descriptor: IScopeDescriptor): IAstNode;
class function CreateDescriptor(const Scope: IExecutionScope): IScopeDescriptor; static;
// The binder overrides specific transform methods to enrich the AST.
function TransformIdentifier(const Node: IIdentifierNode): IIdentifierNode; override;
function TransformVariableDeclaration(const Node: IVariableDeclarationNode): IVariableDeclarationNode; override;
@@ -186,22 +184,10 @@ begin
inherited Destroy;
end;
class function TAstBinder.CreateDescriptor(const Scope: IExecutionScope): IScopeDescriptor;
begin
if Scope is TExecutionScope then
begin
var res := TScopeDescriptor.Create(CreateDescriptor(Scope.Parent));
res.PopulateFromScope(Scope as TExecutionScope);
Result := res;
end
else
Result := TScopeDescriptor.Create(nil);
end;
constructor TAstBinder.Create(const AInitialScope: IExecutionScope);
begin
inherited Create;
FCurrentDescriptor := CreateDescriptor(AInitialScope);
FCurrentDescriptor := AInitialScope.CreateDescriptor;
FUpvalueStack := TObjectStack<TUpvalueMapping>.Create(True);
FNestedLambdaCount := 0;
FIsTailStack := TStack<Boolean>.Create;
@@ -230,7 +216,7 @@ end;
procedure TAstBinder.EnterScope;
begin
FCurrentDescriptor := TScopeDescriptor.Create(FCurrentDescriptor);
FCurrentDescriptor := TScope.CreateDescriptor(FCurrentDescriptor);
end;
function TAstBinder.Execute(const RootNode: IAstNode; out Descriptor: IScopeDescriptor): IAstNode;
@@ -270,30 +256,29 @@ end;
function TAstBinder.TransformIdentifier(const Node: IIdentifierNode): IIdentifierNode;
var
depth, idx: Integer;
adr: TResolvedAddress;
begin
if FCurrentDescriptor.FindSymbol(Node.Name, depth, idx) then
adr := FCurrentDescriptor.FindSymbol(Node.Name);
if adr.Kind = akLocalOrParent then
begin
if (depth > 0) and (FUpvalueStack.Count > 0) then
if (adr.ScopeDepth > 0) and (FUpvalueStack.Count > 0) then
begin
var upvalue := FUpvalueStack.Peek;
dec(depth);
var originalAddress := TResolvedAddress.Create(akLocalOrParent, depth, idx);
// up to outer scope
dec(adr.ScopeDepth);
var upvalueIndex: Integer;
if not upvalue.Map.TryGetValue(originalAddress, upvalueIndex) then
if not upvalue.Map.TryGetValue(adr, upvalueIndex) then
begin
upvalueIndex := upvalue.Map.Count;
upvalue.Map.Add(originalAddress, upvalueIndex);
upvalue.Map.Add(adr, upvalueIndex);
end;
var address := TResolvedAddress.Create(akUpvalue, 0, upvalueIndex);
Result := TBoundIdentifierNode.Create(Node, address);
Result := TBoundIdentifierNode.Create(Node, TResolvedAddress.Create(akUpvalue, 0, upvalueIndex));
end
else
begin
var address := TResolvedAddress.Create(akLocalOrParent, depth, idx);
Result := TBoundIdentifierNode.Create(Node, address);
end
Result := TBoundIdentifierNode.Create(Node, adr);
end
else
raise Exception.CreateFmt('Undefined identifier: "%s"', [Node.Name]);
+10 -9
View File
@@ -27,16 +27,8 @@ type
procedure Log(const Text: string); overload;
procedure LogFmt(const Fmt: string; const Args: array of const); overload;
function FormatAddress(const Addr: TResolvedAddress): string;
public
// Creates a new instance of the AST dumper.
constructor Create(const AOutput: TStrings);
// Traverses the given root node and writes the structural information into the output.
class procedure Dump(const RootNode: IAstNode; const Output: TStrings);
procedure Execute(const RootNode: IAstNode);
// IAstVisitor implementation
protected
function VisitConstant(const Node: IConstantNode): TDataValue; override;
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; override;
@@ -54,6 +46,15 @@ type
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override;
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; override;
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override;
public
// Creates a new instance of the AST dumper.
constructor Create(const AOutput: TStrings);
// Traverses the given root node and writes the structural information into the output.
class procedure Dump(const RootNode: IAstNode; const Output: TStrings);
procedure Execute(const RootNode: IAstNode);
end;
implementation
+13 -13
View File
@@ -28,18 +28,6 @@ type
procedure HandleTCO(var ResultValue: TDataValue);
protected
function IsTruthy(const AValue: TDataValue): Boolean; inline;
// Returns a closure that can create the correct type of visitor for a lambda's body.
function CreateVisitorFactory: TVisitorFactory; virtual;
property Scope: IExecutionScope read FScope;
public
constructor Create(const AScope: IExecutionScope);
// Executes an AST with proper TCO handling. This is the main entry point.
function Execute(const RootNode: IAstNode): TDataValue;
function VisitConstant(const Node: IConstantNode): TDataValue; override;
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; override;
@@ -57,6 +45,18 @@ type
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; override;
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override;
function VisitRecurNode(const Node: IRecurNode): TDataValue; override;
function IsTruthy(const AValue: TDataValue): Boolean; inline;
// Returns a closure that can create the correct type of visitor for a lambda's body.
function CreateVisitorFactory: TVisitorFactory; virtual;
property Scope: IExecutionScope read FScope;
public
constructor Create(const AScope: IExecutionScope);
// Executes an AST with proper TCO handling. This is the main entry point.
function Execute(const RootNode: IAstNode): TDataValue;
end;
// Registers native Delphi functions into a scope.
@@ -207,7 +207,7 @@ begin
if (Length(ArgValues) <> Length(params)) then
raise EArgumentException.CreateFmt('Argument count mismatch: expected %d, got %d', [Length(params), Length(ArgValues)]);
lambdaScope := TExecutionScope.Create(closureScope, scopeDescriptor, capturedCells);
lambdaScope := TScope.CreateScope(closureScope, scopeDescriptor, capturedCells);
adr.Kind := akLocalOrParent;
adr.ScopeDepth := 0;
+44 -99
View File
@@ -4,29 +4,23 @@ interface
uses
System.SysUtils,
System.Generics.Collections,
System.JSON,
Myc.Data.Scalar,
Myc.Data.Value,
Myc.Ast,
Myc.Ast.Visitor,
Myc.Ast.Nodes;
type
// TAstJson provides static methods for serializing and deserializing an AST to/from JSON.
TAstJson = record
public
class function Serialize(const ANode: IAstNode): string; static;
class function Deserialize(const AJson: string): IAstNode; static;
IJsonAstConverter = interface
function Serialize(const RootNode: IAstNode): TJSONObject;
function Deserialize(const AJson: TJSONObject): IAstNode;
end;
implementation
uses
System.JSON,
System.Generics.Collections,
Myc.Ast,
Myc.Data.Scalar,
Myc.Data.Value;
type
// TJsonAstConverter implements the visitor pattern for serialization
// and uses factory functions for deserialization.
TJsonAstConverter = class(TInterfacedObject, IAstVisitor)
TJsonAstConverter = class(TAstVisitor, IJsonAstConverter)
private
FJsonObjectStack: TStack<TJSONObject>;
procedure DataValueToJson(const AValue: TDataValue; const AParent: TJSONObject; const AName: string);
@@ -52,31 +46,33 @@ type
function JsonToSeriesLengthNode(const AObj: TJSONObject): ISeriesLengthNode;
protected
// IAstVisitor implementation for serialization
function VisitConstant(const Node: IConstantNode): TDataValue;
function VisitIdentifier(const Node: IIdentifierNode): TDataValue;
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
function VisitRecurNode(const Node: IRecurNode): TDataValue;
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
function VisitAssignment(const Node: IAssignmentNode): TDataValue;
function VisitIndexer(const Node: IIndexerNode): TDataValue;
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
function VisitConstant(const Node: IConstantNode): TDataValue; override;
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; override;
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; override;
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
function VisitRecurNode(const Node: IRecurNode): TDataValue; override;
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
function VisitIndexer(const Node: IIndexerNode): TDataValue; override;
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override;
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; override;
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override;
function Serialize(const RootNode: IAstNode): TJSONObject;
function Deserialize(const AJson: TJSONObject): IAstNode;
public
constructor Create;
destructor Destroy; override;
function Execute(const RootNode: IAstNode): TDataValue;
function Serialize(const ANode: IAstNode): string;
function Deserialize(const AJson: string): IAstNode;
end;
implementation
{ TJsonAstConverter }
constructor TJsonAstConverter.Create;
@@ -91,48 +87,9 @@ begin
inherited;
end;
function TJsonAstConverter.Serialize(const ANode: IAstNode): string;
var
rootObj: TJSONObject;
function TJsonAstConverter.Deserialize(const AJson: TJSONObject): IAstNode;
begin
if not Assigned(ANode) then
exit('');
FJsonObjectStack.Clear;
ANode.Accept(Self);
if FJsonObjectStack.Count <> 1 then
raise EInvalidOpException.Create('JSON serialization stack is corrupt.');
rootObj := FJsonObjectStack.Pop;
try
Result := rootObj.Format(4);
finally
rootObj.Free;
end;
end;
function TJsonAstConverter.Deserialize(const AJson: string): IAstNode;
var
jsonValue: TJSONValue;
begin
if AJson.IsEmpty then
exit(nil);
jsonValue := TJSONObject.ParseJSONValue(AJson);
if jsonValue = nil then
raise EJSONParseException.Create('Invalid JSON format.');
try
Result := JsonToNode(jsonValue);
finally
jsonValue.Free;
end;
end;
function TJsonAstConverter.Execute(const RootNode: IAstNode): TDataValue;
begin
Result := RootNode.Accept(Self);
Result := JsonToNode(AJson);
end;
{ TJsonAstConverter - IAstVisitor for Serialization }
@@ -782,30 +739,18 @@ begin
raise ENotSupportedException.CreateFmt('Unsupported NodeType "%s" for JSON deserialization.', [nodeType]);
end;
{ TAstJson }
class function TAstJson.Deserialize(const AJson: string): IAstNode;
var
converter: TJsonAstConverter;
function TJsonAstConverter.Serialize(const RootNode: IAstNode): TJSONObject;
begin
converter := TJsonAstConverter.Create;
try
Result := converter.Deserialize(AJson);
finally
converter.Free;
end;
end;
FJsonObjectStack.Clear;
if not Assigned(RootNode) then
exit(nil);
class function TAstJson.Serialize(const ANode: IAstNode): string;
var
converter: TJsonAstConverter;
begin
converter := TJsonAstConverter.Create;
try
Result := converter.Serialize(ANode);
finally
converter.Free;
end;
RootNode.Accept(Self);
if FJsonObjectStack.Count <> 1 then
raise EInvalidOpException.Create('JSON serialization stack is corrupt.');
Result := FJsonObjectStack.Pop;
end;
end.
-32
View File
@@ -29,8 +29,6 @@ type
IAddSeriesItemNode = interface;
ISeriesLengthNode = interface;
IRecurNode = interface;
IExecutionScope = interface;
IScopeDescriptor = interface;
// --- Concrete Type Definitions ---
@@ -55,36 +53,6 @@ type
property Value: TDataValue read GetValue write SetValue;
end;
IExecutionScope = interface
{$region 'private'}
function GetParent: IExecutionScope;
function GetValues(const Address: TResolvedAddress): TDataValue;
procedure SetValues(const Address: TResolvedAddress; const Value: TDataValue);
{$endregion}
procedure Define(const Name: string; const Value: TDataValue);
function Dump: string;
procedure Clear;
function Capture(const Address: TResolvedAddress): IValueCell;
property Values[const Address: TResolvedAddress]: TDataValue read GetValues write SetValues; default;
property Parent: IExecutionScope read GetParent;
end;
IScopeDescriptor = interface
{$region 'private'}
function GetParent: IScopeDescriptor;
function GetSlotCount: Integer;
function GetSymbols: TDictionary<string, Integer>;
{$endregion}
function CreateScope(const AParent: IExecutionScope): IExecutionScope;
function Define(const Name: string): Integer;
function FindSymbol(const Name: string; out Depth, Index: Integer): Boolean;
property Parent: IScopeDescriptor read GetParent;
property SlotCount: Integer read GetSlotCount;
property Symbols: TDictionary<string, Integer> read GetSymbols;
end;
IAstVisitor = interface
function VisitConstant(const Node: IConstantNode): TDataValue;
function VisitIdentifier(const Node: IIdentifierNode): TDataValue;
+1
View File
@@ -26,6 +26,7 @@ implementation
uses
System.Rtti,
System.TypInfo,
Myc.Ast.Scope,
Myc.Ast.RTL.Core;
//--------------------------------------------------------------------------------------------------
+95 -14
View File
@@ -9,6 +9,58 @@ uses
Myc.Data.Value,
Myc.Ast.Nodes;
type
IExecutionScope = interface;
IScopeDescriptor = interface;
IExecutionScope = interface
{$region 'private'}
function GetParent: IExecutionScope;
function GetValues(const Address: TResolvedAddress): TDataValue;
procedure SetValues(const Address: TResolvedAddress; const Value: TDataValue);
{$endregion}
procedure Define(const Name: string; const Value: TDataValue);
function Dump: string;
procedure Clear;
function Capture(const Address: TResolvedAddress): IValueCell;
function CreateDescriptor: IScopeDescriptor;
property Values[const Address: TResolvedAddress]: TDataValue read GetValues write SetValues; default;
property Parent: IExecutionScope read GetParent;
end;
// Describes the layout of a scope: variable names and their slot indices.
// This is generated by the binder and used to create TExecutionScope instances at runtime.
IScopeDescriptor = interface
{$region 'private'}
function GetParent: IScopeDescriptor;
function GetSlotCount: Integer;
function GetSymbols: TDictionary<string, Integer>;
{$endregion}
function CreateScope(const AParent: IExecutionScope): IExecutionScope;
function Define(const Name: string): Integer;
function FindSymbol(const Name: string): TResolvedAddress;
property Parent: IScopeDescriptor read GetParent;
property SlotCount: Integer read GetSlotCount;
property Symbols: TDictionary<string, Integer> read GetSymbols;
end;
TScope = record
class function CreateScope(
const Parent: IExecutionScope;
const Descriptor: IScopeDescriptor;
const CapturedUpvalues: TArray<IValueCell>
): IExecutionScope; static;
class function CreateDescriptor(const Parent: IScopeDescriptor): IScopeDescriptor; static;
end;
implementation
uses
System.Generics.Defaults;
type
TExecutionScope = class(TInterfacedObject, IExecutionScope)
type
@@ -54,14 +106,13 @@ type
function Dump: string;
procedure Define(const Name: string; const Value: TDataValue);
function Capture(const Address: TResolvedAddress): IValueCell;
function CreateDescriptor: IScopeDescriptor;
property Names: TDictionary<string, Integer> read FNames;
property NameStrings: TList<string> read FNameStrings;
property NameToIndex: TDictionary<Integer, Integer> read GetNameToIndex;
property Parent: IExecutionScope read FParent;
end;
// Describes the layout of a scope: variable names and their slot indices.
// This is generated by the binder and used to create TExecutionScope instances at runtime.
TScopeDescriptor = class(TInterfacedObject, IScopeDescriptor)
private
FParent: IScopeDescriptor;
@@ -72,18 +123,14 @@ type
public
constructor Create(const AParent: IScopeDescriptor);
destructor Destroy; override;
class function CreateDescriptor(const Scope: IExecutionScope): IScopeDescriptor; static;
function Define(const Name: string): Integer;
function FindSymbol(const Name: string; out Depth, Index: Integer): Boolean;
function FindSymbol(const Name: string): TResolvedAddress;
function CreateScope(const Parent: IExecutionScope): IExecutionScope;
procedure PopulateFromScope(Scope: TExecutionScope);
property Symbols: TDictionary<string, Integer> read FSymbols;
end;
implementation
uses
System.Generics.Defaults;
{ TValueCell }
constructor TExecutionScope.TValueCell.Create(const AValue: TDataValue);
@@ -185,6 +232,11 @@ begin
end;
end;
function TExecutionScope.CreateDescriptor: IScopeDescriptor;
begin
Result := TScopeDescriptor.CreateDescriptor(Self);
end;
procedure TExecutionScope.Define(const Name: string; const Value: TDataValue);
var
id: Integer;
@@ -373,6 +425,18 @@ begin
inherited;
end;
class function TScopeDescriptor.CreateDescriptor(const Scope: IExecutionScope): IScopeDescriptor;
begin
if Scope is TExecutionScope then
begin
var res := TScopeDescriptor.Create(CreateDescriptor(Scope.Parent));
res.PopulateFromScope(Scope as TExecutionScope);
Result := res;
end
else
Result := TScopeDescriptor.Create(nil);
end;
function TScopeDescriptor.CreateScope(const Parent: IExecutionScope): IExecutionScope;
begin
// Creates a runtime scope instance based on this descriptor's layout.
@@ -385,20 +449,23 @@ begin
FSymbols.Add(Name, Result);
end;
function TScopeDescriptor.FindSymbol(const Name: string; out Depth, Index: Integer): Boolean;
function TScopeDescriptor.FindSymbol(const Name: string): TResolvedAddress;
var
currentDescriptor: TScopeDescriptor;
begin
Depth := 0;
Result.Kind := akUnresolved;
Result.ScopeDepth := 0;
currentDescriptor := Self;
while currentDescriptor <> nil do
begin
if currentDescriptor.FSymbols.TryGetValue(Name, Index) then
exit(True);
inc(Depth);
if currentDescriptor.FSymbols.TryGetValue(Name, Result.SlotIndex) then
begin
Result.Kind := akLocalOrParent;
exit;
end;
inc(Result.ScopeDepth);
currentDescriptor := currentDescriptor.FParent as TScopeDescriptor;
end;
Result := False;
end;
function TScopeDescriptor.GetParent: IScopeDescriptor;
@@ -428,4 +495,18 @@ begin
end;
end;
class function TScope.CreateDescriptor(const Parent: IScopeDescriptor): IScopeDescriptor;
begin
Result := TScopeDescriptor.Create(Parent);
end;
class function TScope.CreateScope(
const Parent: IExecutionScope;
const Descriptor: IScopeDescriptor;
const CapturedUpvalues: TArray<IValueCell>
): IExecutionScope;
begin
Result := TExecutionScope.Create(Parent, Descriptor, CapturedUpvalues);
end;
end.
+20 -20
View File
@@ -12,7 +12,7 @@ uses
type
// A fully abstract base class for any visitor of the AST.
TAstVisitor = class abstract(TInterfacedObject, IAstVisitor)
public
protected
function VisitConstant(const Node: IConstantNode): TDataValue; virtual; abstract;
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; virtual; abstract;
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; virtual; abstract;
@@ -45,6 +45,25 @@ type
FDone: Boolean;
protected
// Final Visit methods - these should not be overridden. They call the virtual Transform methods.
function VisitConstant(const Node: IConstantNode): TDataValue; override; final;
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override; final;
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; override; final;
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; override; final;
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override; final;
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override; final;
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override; final;
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override; final;
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override; final;
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override; final;
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override; final;
function VisitIndexer(const Node: IIndexerNode): TDataValue; override; final;
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override; final;
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override; final;
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; override; final;
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override; final;
function VisitRecurNode(const Node: IRecurNode): TDataValue; override; final;
// Dispatch methods for each node type. Derived classes override these to change the transformation.
function TransformConstant(const Node: IConstantNode): IConstantNode; virtual;
function TransformIdentifier(const Node: IIdentifierNode): IIdentifierNode; virtual;
@@ -73,25 +92,6 @@ type
public
// This is the main entry point for the transformer, returning a transformed node.
function Execute(const RootNode: IAstNode): IAstNode;
// Final Visit methods - these should not be overridden. They call the virtual Transform methods.
function VisitConstant(const Node: IConstantNode): TDataValue; override; final;
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override; final;
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; override; final;
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; override; final;
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override; final;
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override; final;
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override; final;
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override; final;
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override; final;
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override; final;
function VisitAssignment(const Node: IAssignmentNode): TDataValue; override; final;
function VisitIndexer(const Node: IIndexerNode): TDataValue; override; final;
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override; final;
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override; final;
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; override; final;
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override; final;
function VisitRecurNode(const Node: IRecurNode): TDataValue; override; final;
end;
// TAstTraverser simply inherits the identity-transform (cloning) behavior from TAstTransformer.
+4 -1
View File
@@ -171,6 +171,7 @@ type
constructor Create(const AExpressions: array of IAstNode);
destructor Destroy; override;
function Accept(const Visitor: IAstVisitor): TDataValue; override;
property Expressions: TList<IAstNode> read FExpressions;
end;
TVariableDeclarationNode = class(TAstNode, IVariableDeclarationNode)
@@ -182,6 +183,8 @@ type
public
constructor Create(const AIdentifier: IIdentifierNode; AInitializer: IAstNode);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
property Identifier: IIdentifierNode read FIdentifier;
property Initializer: IAstNode read FInitializer;
end;
TAssignmentNode = class(TAstNode, IAssignmentNode)
@@ -731,7 +734,7 @@ class function TAst.CreateScope(Parent: IExecutionScope; const Descriptor: IScop
var
proc: TRegisterLibraryProc;
begin
Result := TExecutionScope.Create(Parent, Descriptor, nil);
Result := TScope.CreateScope(Parent, Descriptor, nil);
if Parent = nil then
begin