Refactoring node to be immutable
This commit is contained in:
@@ -135,55 +135,51 @@ begin
|
||||
if newExprs = Node.Expressions then
|
||||
Result := Node
|
||||
else
|
||||
Result := TBlockExpressionNode.Create(newExprs, Node.StaticType);
|
||||
Result := TAst.Block(newExprs, Node.StaticType);
|
||||
end;
|
||||
|
||||
function TAstTCO.VisitIfExpression(const Node: IIfExpressionNode): IAstNode;
|
||||
var
|
||||
isContextTail: Boolean;
|
||||
N: TIfExpressionNode;
|
||||
newCond, newThen, newElse: IAstNode;
|
||||
begin
|
||||
N := (Node as TIfExpressionNode);
|
||||
isContextTail := FIsTailStack.Peek;
|
||||
|
||||
// Condition is never in tail position
|
||||
FNextIsTail := False;
|
||||
newCond := Accept(N.Condition);
|
||||
newCond := Accept(Node.Condition);
|
||||
|
||||
// Then/Else branches ARE in tail position if the IfExpr is
|
||||
FNextIsTail := isContextTail;
|
||||
newThen := Accept(N.ThenBranch);
|
||||
newElse := Accept(N.ElseBranch);
|
||||
newThen := Accept(Node.ThenBranch);
|
||||
newElse := Accept(Node.ElseBranch);
|
||||
|
||||
if (newCond = N.Condition) and (newThen = N.ThenBranch) and (newElse = N.ElseBranch) then
|
||||
if (newCond = Node.Condition) and (newThen = Node.ThenBranch) and (newElse = Node.ElseBranch) then
|
||||
Result := Node
|
||||
else
|
||||
Result := TIfExpressionNode.Create(newCond, newThen, newElse, N.StaticType);
|
||||
Result := TAst.IfExpr(newCond, newThen, newElse, Node.StaticType);
|
||||
end;
|
||||
|
||||
function TAstTCO.VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode;
|
||||
var
|
||||
isContextTail: Boolean;
|
||||
N: TTernaryExpressionNode;
|
||||
newCond, newThen, newElse: IAstNode;
|
||||
begin
|
||||
N := (Node as TTernaryExpressionNode);
|
||||
isContextTail := FIsTailStack.Peek;
|
||||
|
||||
// Condition is never in tail position
|
||||
FNextIsTail := False;
|
||||
newCond := Accept(N.Condition);
|
||||
newCond := Accept(Node.Condition);
|
||||
|
||||
// Then/Else branches ARE in tail position if the TernaryExpr is
|
||||
FNextIsTail := isContextTail;
|
||||
newThen := Accept(N.ThenBranch);
|
||||
newElse := Accept(N.ElseBranch);
|
||||
newThen := Accept(Node.ThenBranch);
|
||||
newElse := Accept(Node.ElseBranch);
|
||||
|
||||
if (newCond = N.Condition) and (newThen = N.ThenBranch) and (newElse = N.ElseBranch) then
|
||||
if (newCond = Node.Condition) and (newThen = Node.ThenBranch) and (newElse = Node.ElseBranch) then
|
||||
Result := Node
|
||||
else
|
||||
Result := TTernaryExpressionNode.Create(newCond, newThen, newElse, N.StaticType);
|
||||
Result := TAst.TernaryExpr(newCond, newThen, newElse, Node.StaticType);
|
||||
end;
|
||||
|
||||
function TAstTCO.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
|
||||
@@ -216,22 +212,19 @@ end;
|
||||
|
||||
function TAstTCO.VisitRecurNode(const Node: IRecurNode): IAstNode;
|
||||
var
|
||||
N: TRecurNode;
|
||||
newArgs: TArray<IAstNode>;
|
||||
begin
|
||||
if not FIsTailStack.Peek then
|
||||
raise Exception.Create('''recur'' can only be used in a tail position.');
|
||||
|
||||
N := (Node as TRecurNode);
|
||||
|
||||
// Arguments are not in tail position
|
||||
FNextIsTail := False;
|
||||
newArgs := AcceptNodes(N.Arguments);
|
||||
newArgs := AcceptNodes(Node.Arguments);
|
||||
|
||||
if newArgs = N.Arguments then
|
||||
if newArgs = Node.Arguments then
|
||||
Result := Node
|
||||
else
|
||||
Result := TRecurNode.Create(newArgs, N.StaticType);
|
||||
Result := TAst.Recur(newArgs, Node.StaticType);
|
||||
end;
|
||||
|
||||
function TAstTCO.VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode;
|
||||
|
||||
@@ -107,7 +107,7 @@ begin
|
||||
right := Accept(Node.Arguments[1]);
|
||||
|
||||
// Call constructor directly, passing the inferred type
|
||||
Result := TBinaryExpressionNode.Create(left, binaryOp, right, nodeType);
|
||||
Result := TAst.BinaryExpr(left, binaryOp, right, nodeType);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
@@ -118,7 +118,7 @@ begin
|
||||
begin
|
||||
right := Accept(Node.Arguments[0]);
|
||||
// Call constructor directly, passing the inferred type
|
||||
Result := TUnaryExpressionNode.Create(unaryOp, right, nodeType);
|
||||
Result := TAst.UnaryExpr(unaryOp, right, nodeType);
|
||||
exit;
|
||||
end;
|
||||
|
||||
@@ -126,7 +126,7 @@ begin
|
||||
begin
|
||||
right := Accept(Node.Arguments[0]);
|
||||
// Call constructor directly, passing the inferred type
|
||||
Result := TUnaryExpressionNode.Create(TScalar.TUnaryOp.Negate, right, nodeType);
|
||||
Result := TAst.UnaryExpr(TScalar.TUnaryOp.Negate, right, nodeType);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -122,8 +122,8 @@ begin
|
||||
if (not evaluatedSpliceValue.IsVoid) and (evaluatedSpliceValue.Kind = vkInterface) then
|
||||
begin
|
||||
nodeToSplice := evaluatedSpliceValue.AsIntf<IAstNode>;
|
||||
if (nodeToSplice is TBlockExpressionNode) then
|
||||
newList.AddRange((nodeToSplice as TBlockExpressionNode).Expressions)
|
||||
if nodeToSplice.Kind = akBlockExpression then
|
||||
newList.AddRange(nodeToSplice.AsBlockExpression.Expressions)
|
||||
else
|
||||
// Allow splicing single nodes, not just blocks
|
||||
newList.Add(nodeToSplice);
|
||||
|
||||
@@ -128,7 +128,7 @@ begin
|
||||
newArgs[i] := Accept(Node.Arguments[i]);
|
||||
|
||||
// 2. Create new node with inferred type
|
||||
Result := TRecurNode.Create(newArgs, TTypes.Void);
|
||||
Result := TAst.Recur(newArgs, TTypes.Void);
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode;
|
||||
@@ -201,7 +201,7 @@ begin
|
||||
end;
|
||||
|
||||
// 5. Create the new Assignment node
|
||||
Result := TAssignmentNode.Create(newIdent.AsIdentifier, newValue, targetType);
|
||||
Result := TAst.Assign(newIdent.AsIdentifier, newValue, targetType);
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
|
||||
@@ -325,7 +325,7 @@ begin
|
||||
blockType := TTypes.Void;
|
||||
|
||||
// 3. Create new node
|
||||
Result := TBlockExpressionNode.Create(newExprs, blockType);
|
||||
Result := TAst.Block(newExprs, blockType);
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitIfExpression(const Node: IIfExpressionNode): IAstNode;
|
||||
@@ -352,7 +352,7 @@ begin
|
||||
resultType := TTypeRules.Promote(thenType, elseType);
|
||||
|
||||
// 4. Create new node
|
||||
Result := TIfExpressionNode.Create(newCond, newThen, newElse, resultType);
|
||||
Result := TAst.IfExpr(newCond, newThen, newElse, resultType);
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode;
|
||||
@@ -377,7 +377,7 @@ begin
|
||||
resultType := TTypeRules.Promote(thenType, elseType);
|
||||
|
||||
// 4. Create new node
|
||||
Result := TTernaryExpressionNode.Create(newCond, newThen, newElse, resultType);
|
||||
Result := TAst.TernaryExpr(newCond, newThen, newElse, resultType);
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitBinaryExpression(const Node: IBinaryExpressionNode): IAstNode;
|
||||
@@ -397,7 +397,7 @@ begin
|
||||
resultType := TTypeRules.ResolveBinaryOp(Node.Operator, leftType, rightType);
|
||||
|
||||
// 4. Create new node
|
||||
Result := TBinaryExpressionNode.Create(newLeft, Node.Operator, newRight, resultType);
|
||||
Result := TAst.BinaryExpr(newLeft, Node.Operator, newRight, resultType);
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitUnaryExpression(const Node: IUnaryExpressionNode): IAstNode;
|
||||
@@ -415,7 +415,7 @@ begin
|
||||
resultType := TTypeRules.ResolveUnaryOp(Node.Operator, rightType);
|
||||
|
||||
// 4. Create new node
|
||||
Result := TUnaryExpressionNode.Create(Node.Operator, newRight, resultType);
|
||||
Result := TAst.UnaryExpr(Node.Operator, newRight, resultType);
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitMemberAccess(const Node: IMemberAccessNode): IAstNode;
|
||||
@@ -463,7 +463,7 @@ begin
|
||||
end;
|
||||
|
||||
// 4. Create new node
|
||||
Result := TMemberAccessNode.Create(newBase, newMember.AsKeyword, elemType);
|
||||
Result := TAst.MemberAccess(newBase, newMember.AsKeyword, elemType);
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitIndexer(const Node: IIndexerNode): IAstNode;
|
||||
@@ -496,7 +496,7 @@ begin
|
||||
end;
|
||||
|
||||
// 4. Create new node
|
||||
Result := TIndexerNode.Create(newBase, newIndex, elemType);
|
||||
Result := TAst.Indexer(newBase, newIndex, elemType);
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitRecordLiteral(const Node: IRecordLiteralNode): IAstNode;
|
||||
@@ -582,7 +582,7 @@ begin
|
||||
end;
|
||||
|
||||
// Create new node
|
||||
Result := TCreateSeriesNode.Create(Node.Definition, TTypes.CreateSeries(elemType));
|
||||
Result := TAst.CreateSeries(Node.Definition, TTypes.CreateSeries(elemType));
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitAddSeriesItem(const Node: IAddSeriesItemNode): IAstNode;
|
||||
@@ -618,7 +618,7 @@ begin
|
||||
end;
|
||||
|
||||
// 4. Create new node
|
||||
Result := TAddSeriesItemNode.Create(newSeries.AsIdentifier, newValue, newLookback, TTypes.Void);
|
||||
Result := TAst.AddSeriesItem(newSeries.AsIdentifier, newValue, newLookback, TTypes.Void);
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitSeriesLength(const Node: ISeriesLengthNode): IAstNode;
|
||||
@@ -639,7 +639,7 @@ begin
|
||||
raise ETypeException.CreateFmt('"length" requires a series, but got %s', [seriesType.ToString]);
|
||||
|
||||
// 4. Create new node
|
||||
Result := TSeriesLengthNode.Create(newSeries.AsIdentifier, TTypes.Ordinal);
|
||||
Result := TAst.SeriesLength(newSeries.AsIdentifier, TTypes.Ordinal);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
+72
-82
@@ -469,62 +469,58 @@ end;
|
||||
function TAstTransformer.VisitBinaryExpression(const Node: IBinaryExpressionNode): IAstNode;
|
||||
var
|
||||
newLeft, newRight: IAstNode;
|
||||
N: TBinaryExpressionNode;
|
||||
begin
|
||||
N := (Node as TBinaryExpressionNode);
|
||||
newLeft := Accept(N.Left);
|
||||
newRight := Accept(N.Right);
|
||||
newLeft := Accept(Node.Left);
|
||||
newRight := Accept(Node.Right);
|
||||
|
||||
if (newLeft = N.Left) and (newRight = N.Right) then
|
||||
if (newLeft = Node.Left) and (newRight = Node.Right) then
|
||||
Result := Node
|
||||
else
|
||||
Result := TBinaryExpressionNode.Create(newLeft, N.Operator, newRight, N.StaticType);
|
||||
// Use TAst factory instead of concrete class constructor
|
||||
Result := TAst.BinaryExpr(newLeft, Node.Operator, newRight, Node.StaticType);
|
||||
end;
|
||||
|
||||
function TAstTransformer.VisitUnaryExpression(const Node: IUnaryExpressionNode): IAstNode;
|
||||
var
|
||||
newRight: IAstNode;
|
||||
N: TUnaryExpressionNode;
|
||||
begin
|
||||
N := (Node as TUnaryExpressionNode);
|
||||
newRight := Accept(N.Right);
|
||||
newRight := Accept(Node.Right);
|
||||
|
||||
if newRight = N.Right then
|
||||
if newRight = Node.Right then
|
||||
Result := Node
|
||||
else
|
||||
Result := TUnaryExpressionNode.Create(N.Operator, newRight, N.StaticType);
|
||||
// Use TAst factory
|
||||
Result := TAst.UnaryExpr(Node.Operator, newRight, Node.StaticType);
|
||||
end;
|
||||
|
||||
function TAstTransformer.VisitIfExpression(const Node: IIfExpressionNode): IAstNode;
|
||||
var
|
||||
newCond, newThen, newElse: IAstNode;
|
||||
N: TIfExpressionNode;
|
||||
begin
|
||||
N := (Node as TIfExpressionNode);
|
||||
newCond := Accept(N.Condition);
|
||||
newThen := Accept(N.ThenBranch);
|
||||
newElse := Accept(N.ElseBranch); // Accept handles nil
|
||||
newCond := Accept(Node.Condition);
|
||||
newThen := Accept(Node.ThenBranch);
|
||||
newElse := Accept(Node.ElseBranch); // Accept handles nil
|
||||
|
||||
if (newCond = N.Condition) and (newThen = N.ThenBranch) and (newElse = N.ElseBranch) then
|
||||
if (newCond = Node.Condition) and (newThen = Node.ThenBranch) and (newElse = Node.ElseBranch) then
|
||||
Result := Node
|
||||
else
|
||||
Result := TIfExpressionNode.Create(newCond, newThen, newElse, N.StaticType);
|
||||
// Use TAst factory
|
||||
Result := TAst.IfExpr(newCond, newThen, newElse, Node.StaticType);
|
||||
end;
|
||||
|
||||
function TAstTransformer.VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode;
|
||||
var
|
||||
newCond, newThen, newElse: IAstNode;
|
||||
N: TTernaryExpressionNode;
|
||||
begin
|
||||
N := (Node as TTernaryExpressionNode);
|
||||
newCond := Accept(N.Condition);
|
||||
newThen := Accept(N.ThenBranch);
|
||||
newElse := Accept(N.ElseBranch);
|
||||
newCond := Accept(Node.Condition);
|
||||
newThen := Accept(Node.ThenBranch);
|
||||
newElse := Accept(Node.ElseBranch);
|
||||
|
||||
if (newCond = N.Condition) and (newThen = N.ThenBranch) and (newElse = N.ElseBranch) then
|
||||
if (newCond = Node.Condition) and (newThen = Node.ThenBranch) and (newElse = Node.ElseBranch) then
|
||||
Result := Node
|
||||
else
|
||||
Result := TTernaryExpressionNode.Create(newCond, newThen, newElse, N.StaticType);
|
||||
// Use TAst factory
|
||||
Result := TAst.TernaryExpr(newCond, newThen, newElse, Node.StaticType);
|
||||
end;
|
||||
|
||||
function TAstTransformer.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
|
||||
@@ -533,7 +529,7 @@ var
|
||||
newBody: IAstNode;
|
||||
N: TLambdaExpressionNode;
|
||||
begin
|
||||
N := (Node as TLambdaExpressionNode);
|
||||
N := (Node as TLambdaExpressionNode); // This cast is valid
|
||||
newParams := AcceptParameters(N.Parameters);
|
||||
newBody := Accept(N.Body);
|
||||
|
||||
@@ -541,8 +537,9 @@ begin
|
||||
Result := Node
|
||||
else
|
||||
begin
|
||||
Result := TLambdaExpressionNode.Create(newParams, newBody, N.StaticType);
|
||||
// Copy runtime properties
|
||||
// Use TAst factory
|
||||
Result := TAst.LambdaExpr(newParams, newBody, N.StaticType);
|
||||
// Copy runtime properties (cast is valid)
|
||||
(Result as TLambdaExpressionNode).ScopeDescriptor := N.ScopeDescriptor;
|
||||
(Result as TLambdaExpressionNode).Upvalues := N.Upvalues;
|
||||
(Result as TLambdaExpressionNode).HasNestedLambdas := N.HasNestedLambdas;
|
||||
@@ -555,7 +552,7 @@ var
|
||||
newArgs: TArray<IAstNode>;
|
||||
N: TFunctionCallNode;
|
||||
begin
|
||||
N := (Node as TFunctionCallNode);
|
||||
N := (Node as TFunctionCallNode); // This cast is valid
|
||||
newCallee := Accept(N.Callee);
|
||||
newArgs := AcceptNodes(N.Arguments);
|
||||
|
||||
@@ -563,8 +560,9 @@ begin
|
||||
Result := Node
|
||||
else
|
||||
begin
|
||||
Result := TFunctionCallNode.Create(newCallee, newArgs, N.StaticType);
|
||||
// Copy runtime properties
|
||||
// Use TAst factory
|
||||
Result := TAst.FunctionCall(newCallee, newArgs, N.StaticType);
|
||||
// Copy runtime properties (cast is valid)
|
||||
(Result as TFunctionCallNode).IsTailCall := N.IsTailCall;
|
||||
end;
|
||||
end;
|
||||
@@ -585,15 +583,14 @@ end;
|
||||
function TAstTransformer.VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode;
|
||||
var
|
||||
newExprs: TArray<IAstNode>;
|
||||
N: TBlockExpressionNode;
|
||||
begin
|
||||
N := (Node as TBlockExpressionNode);
|
||||
newExprs := AcceptNodes(N.Expressions);
|
||||
newExprs := AcceptNodes(Node.Expressions);
|
||||
|
||||
if newExprs = N.Expressions then
|
||||
if newExprs = Node.Expressions then
|
||||
Result := Node
|
||||
else
|
||||
Result := TBlockExpressionNode.Create(newExprs, N.StaticType);
|
||||
// Use TAst factory
|
||||
Result := TAst.Block(newExprs, Node.StaticType);
|
||||
end;
|
||||
|
||||
function TAstTransformer.VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode;
|
||||
@@ -602,7 +599,7 @@ var
|
||||
newInit: IAstNode;
|
||||
N: TVariableDeclarationNode;
|
||||
begin
|
||||
N := (Node as TVariableDeclarationNode);
|
||||
N := (Node as TVariableDeclarationNode); // This cast is valid
|
||||
newIdent := Accept(N.Identifier).AsIdentifier;
|
||||
newInit := Accept(N.Initializer); // Accept handles nil
|
||||
|
||||
@@ -610,8 +607,9 @@ begin
|
||||
Result := Node
|
||||
else
|
||||
begin
|
||||
Result := TVariableDeclarationNode.Create(newIdent, newInit, N.StaticType);
|
||||
// Copy runtime properties
|
||||
// Use TAst factory
|
||||
Result := TAst.VarDecl(newIdent, newInit, N.StaticType);
|
||||
// Copy runtime properties (cast is valid)
|
||||
(Result as TVariableDeclarationNode).IsBoxed := N.IsBoxed;
|
||||
end;
|
||||
end;
|
||||
@@ -620,16 +618,15 @@ function TAstTransformer.VisitAssignment(const Node: IAssignmentNode): IAstNode;
|
||||
var
|
||||
newIdent: IIdentifierNode;
|
||||
newValue: IAstNode;
|
||||
N: TAssignmentNode;
|
||||
begin
|
||||
N := (Node as TAssignmentNode);
|
||||
newValue := Accept(N.Value);
|
||||
newIdent := Accept(N.Identifier).AsIdentifier;
|
||||
newValue := Accept(Node.Value);
|
||||
newIdent := Accept(Node.Identifier).AsIdentifier;
|
||||
|
||||
if (newValue = N.Value) and (newIdent = N.Identifier) then
|
||||
if (newValue = Node.Value) and (newIdent = Node.Identifier) then
|
||||
Result := Node
|
||||
else
|
||||
Result := TAssignmentNode.Create(newIdent, newValue, N.StaticType);
|
||||
// Use TAst factory
|
||||
Result := TAst.Assign(newIdent, newValue, Node.StaticType);
|
||||
end;
|
||||
|
||||
function TAstTransformer.VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode;
|
||||
@@ -683,32 +680,30 @@ end;
|
||||
function TAstTransformer.VisitIndexer(const Node: IIndexerNode): IAstNode;
|
||||
var
|
||||
newBase, newIndex: IAstNode;
|
||||
N: TIndexerNode;
|
||||
begin
|
||||
N := (Node as TIndexerNode);
|
||||
newBase := Accept(N.Base);
|
||||
newIndex := Accept(N.Index);
|
||||
newBase := Accept(Node.Base);
|
||||
newIndex := Accept(Node.Index);
|
||||
|
||||
if (newBase = N.Base) and (newIndex = N.Index) then
|
||||
if (newBase = Node.Base) and (newIndex = Node.Index) then
|
||||
Result := Node
|
||||
else
|
||||
Result := TIndexerNode.Create(newBase, newIndex, N.StaticType);
|
||||
// Use TAst factory
|
||||
Result := TAst.Indexer(newBase, newIndex, Node.StaticType);
|
||||
end;
|
||||
|
||||
function TAstTransformer.VisitMemberAccess(const Node: IMemberAccessNode): IAstNode;
|
||||
var
|
||||
newBase: IAstNode;
|
||||
newMember: IKeywordNode;
|
||||
N: TMemberAccessNode;
|
||||
begin
|
||||
N := (Node as TMemberAccessNode);
|
||||
newBase := Accept(N.Base);
|
||||
newMember := Accept(N.Member).AsKeyword; // Keyword ist Blattknoten
|
||||
newBase := Accept(Node.Base);
|
||||
newMember := Accept(Node.Member).AsKeyword; // Keyword ist Blattknoten
|
||||
|
||||
if (newBase = N.Base) and (newMember = N.Member) then
|
||||
if (newBase = Node.Base) and (newMember = Node.Member) then
|
||||
Result := Node
|
||||
else
|
||||
Result := TMemberAccessNode.Create(newBase, newMember, N.StaticType);
|
||||
// Use TAst factory
|
||||
Result := TAst.MemberAccess(newBase, newMember, Node.StaticType);
|
||||
end;
|
||||
|
||||
function TAstTransformer.VisitRecordLiteral(const Node: IRecordLiteralNode): IAstNode;
|
||||
@@ -718,7 +713,7 @@ var
|
||||
newFields: TArray<TRecordFieldLiteral>;
|
||||
hasChanged: Boolean;
|
||||
begin
|
||||
N := (Node as TRecordLiteralNode);
|
||||
N := (Node as TRecordLiteralNode); // This cast is valid
|
||||
SetLength(newFields, Length(N.Fields));
|
||||
hasChanged := False;
|
||||
|
||||
@@ -735,16 +730,14 @@ begin
|
||||
else
|
||||
begin
|
||||
// Rebuild the node, preserving its specific type and definitions
|
||||
// Use TAst factory
|
||||
Result := TAst.RecordLiteral(newFields, N.StaticType);
|
||||
|
||||
// Copy runtime properties (casts are valid)
|
||||
if N is TGenericRecordLiteralNode then
|
||||
begin
|
||||
Result := TGenericRecordLiteralNode.Create(newFields, N.StaticType);
|
||||
(Result as TGenericRecordLiteralNode).GenericDefinition := (N as TGenericRecordLiteralNode).GenericDefinition;
|
||||
end
|
||||
(Result as TGenericRecordLiteralNode).GenericDefinition := (N as TGenericRecordLiteralNode).GenericDefinition
|
||||
else
|
||||
begin
|
||||
Result := TRecordLiteralNode.Create(newFields, N.StaticType);
|
||||
(Result as TRecordLiteralNode).Definition := N.Definition;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -757,45 +750,42 @@ function TAstTransformer.VisitAddSeriesItem(const Node: IAddSeriesItemNode): IAs
|
||||
var
|
||||
newSeries: IIdentifierNode;
|
||||
newValue, newLookback: IAstNode;
|
||||
N: TAddSeriesItemNode;
|
||||
begin
|
||||
N := (Node as TAddSeriesItemNode);
|
||||
newSeries := Accept(N.Series).AsIdentifier;
|
||||
newValue := Accept(N.Value);
|
||||
newLookback := Accept(N.Lookback); // Accept handles nil
|
||||
newSeries := Accept(Node.Series).AsIdentifier;
|
||||
newValue := Accept(Node.Value);
|
||||
newLookback := Accept(Node.Lookback); // Accept handles nil
|
||||
|
||||
if (newSeries = N.Series) and (newValue = N.Value) and (newLookback = N.Lookback) then
|
||||
if (newSeries = Node.Series) and (newValue = Node.Value) and (newLookback = Node.Lookback) then
|
||||
Result := Node
|
||||
else
|
||||
Result := TAddSeriesItemNode.Create(newSeries, newValue, newLookback, N.StaticType);
|
||||
// Use TAst factory
|
||||
Result := TAst.AddSeriesItem(newSeries, newValue, newLookback, Node.StaticType);
|
||||
end;
|
||||
|
||||
function TAstTransformer.VisitSeriesLength(const Node: ISeriesLengthNode): IAstNode;
|
||||
var
|
||||
newSeries: IIdentifierNode;
|
||||
N: TSeriesLengthNode;
|
||||
begin
|
||||
N := (Node as TSeriesLengthNode);
|
||||
newSeries := Accept(N.Series).AsIdentifier;
|
||||
newSeries := Accept(Node.Series).AsIdentifier;
|
||||
|
||||
if newSeries = N.Series then
|
||||
if newSeries = Node.Series then
|
||||
Result := Node
|
||||
else
|
||||
Result := TSeriesLengthNode.Create(newSeries, N.StaticType);
|
||||
// Use TAst factory
|
||||
Result := TAst.SeriesLength(newSeries, Node.StaticType);
|
||||
end;
|
||||
|
||||
function TAstTransformer.VisitRecurNode(const Node: IRecurNode): IAstNode;
|
||||
var
|
||||
newArgs: TArray<IAstNode>;
|
||||
N: TRecurNode;
|
||||
begin
|
||||
N := (Node as TRecurNode);
|
||||
newArgs := AcceptNodes(N.Arguments);
|
||||
newArgs := AcceptNodes(Node.Arguments);
|
||||
|
||||
if newArgs = N.Arguments then
|
||||
if newArgs = Node.Arguments then
|
||||
Result := Node
|
||||
else
|
||||
Result := TRecurNode.Create(newArgs, N.StaticType);
|
||||
// Use TAst factory
|
||||
Result := TAst.Recur(newArgs, Node.StaticType);
|
||||
end;
|
||||
|
||||
{ TAstVisitor }
|
||||
|
||||
+432
-249
@@ -36,12 +36,33 @@ type
|
||||
class function Constant(const AValue: TDataValue; const AStaticType: IStaticType = nil): IConstantNode; overload; static;
|
||||
class function Constant(const AValue: String): IConstantNode; overload; static;
|
||||
class function Keyword(const AName: string): IKeywordNode; static;
|
||||
class function Identifier(AName: string): IIdentifierNode; static;
|
||||
class function BinaryExpr(ALeft: IAstNode; AOperator: TScalar.TBinaryOp; ARight: IAstNode): IBinaryExpressionNode; static;
|
||||
class function UnaryExpr(const AOperator: TScalar.TUnaryOp; const ARight: IAstNode): IUnaryExpressionNode; static;
|
||||
class function IfExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): IIfExpressionNode; static;
|
||||
class function TernaryExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): ITernaryExpressionNode; static;
|
||||
class function LambdaExpr(const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode): ILambdaExpressionNode; static;
|
||||
class function Identifier(AName: string; const AStaticType: IStaticType = nil): IIdentifierNode; static;
|
||||
class function BinaryExpr(
|
||||
ALeft: IAstNode;
|
||||
AOperator: TScalar.TBinaryOp;
|
||||
ARight: IAstNode;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IBinaryExpressionNode; static;
|
||||
class function UnaryExpr(
|
||||
const AOperator: TScalar.TUnaryOp;
|
||||
const ARight: IAstNode;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IUnaryExpressionNode; static;
|
||||
class function IfExpr(
|
||||
const ACondition: IAstNode;
|
||||
const AThenBranch, AElseBranch: IAstNode;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IIfExpressionNode; static;
|
||||
class function TernaryExpr(
|
||||
const ACondition: IAstNode;
|
||||
const AThenBranch, AElseBranch: IAstNode;
|
||||
const AStaticType: IStaticType = nil
|
||||
): ITernaryExpressionNode; static;
|
||||
class function LambdaExpr(
|
||||
const AParameters: TArray<IIdentifierNode>;
|
||||
const ABody: IAstNode;
|
||||
const AStaticType: IStaticType = nil
|
||||
): ILambdaExpressionNode; static;
|
||||
class function MacroDef(
|
||||
const AName: IIdentifierNode;
|
||||
const AParameters: TArray<IIdentifierNode>;
|
||||
@@ -50,26 +71,46 @@ type
|
||||
class function Quasiquote(const AExpression: IAstNode): IQuasiquoteNode; static;
|
||||
class function Unquote(const AExpression: IAstNode): IUnquoteNode; static;
|
||||
class function UnquoteSplicing(const AExpression: IQuasiquoteNode): IUnquoteSplicingNode; static;
|
||||
class function FunctionCall(const ACallee: IAstNode; const AArguments: TArray<IAstNode>): IFunctionCallNode; static;
|
||||
class function FunctionCall(
|
||||
const ACallee: IAstNode;
|
||||
const AArguments: TArray<IAstNode>;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IFunctionCallNode; static;
|
||||
class function MacroExpansionNode(
|
||||
const AOriginalCallNode: IFunctionCallNode;
|
||||
const AExpandedBody: IAstNode
|
||||
): IMacroExpansionNode; static;
|
||||
class function Recur(const AArguments: array of IAstNode): IRecurNode; static;
|
||||
class function Block(const AExpressions: array of IAstNode): IBlockExpressionNode; static;
|
||||
class function VarDecl(const AIdentifier: IIdentifierNode; AInitializer: IAstNode = nil): IVariableDeclarationNode; static;
|
||||
class function Assign(const AIdentifier: IIdentifierNode; const AValue: IAstNode): IAssignmentNode; static;
|
||||
class function Recur(const AArguments: array of IAstNode; const AStaticType: IStaticType = nil): IRecurNode; static;
|
||||
class function Block(const AExpressions: array of IAstNode; const AStaticType: IStaticType = nil): IBlockExpressionNode; static;
|
||||
class function VarDecl(
|
||||
const AIdentifier: IIdentifierNode;
|
||||
AInitializer: IAstNode = nil;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IVariableDeclarationNode; static;
|
||||
class function Assign(
|
||||
const AIdentifier: IIdentifierNode;
|
||||
const AValue: IAstNode;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IAssignmentNode; static;
|
||||
class function AssignResult(const AValue: IAstNode): IAssignmentNode; static; deprecated;
|
||||
class function Indexer(const ABase: IAstNode; const AIndex: IAstNode): IIndexerNode; static;
|
||||
class function MemberAccess(const ABase: IAstNode; const AMember: IKeywordNode): IMemberAccessNode; static;
|
||||
class function RecordLiteral(const AFields: TArray<TRecordFieldLiteral>): IRecordLiteralNode; static;
|
||||
class function CreateSeries(const ADefinition: String): ICreateSeriesNode; static;
|
||||
class function Indexer(const ABase: IAstNode; const AIndex: IAstNode; const AStaticType: IStaticType = nil): IIndexerNode; static;
|
||||
class function MemberAccess(
|
||||
const ABase: IAstNode;
|
||||
const AMember: IKeywordNode;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IMemberAccessNode; static;
|
||||
class function RecordLiteral(
|
||||
const AFields: TArray<TRecordFieldLiteral>;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IRecordLiteralNode; static;
|
||||
class function CreateSeries(const ADefinition: String; const AStaticType: IStaticType = nil): ICreateSeriesNode; static;
|
||||
class function AddSeriesItem(
|
||||
const ASeries: IIdentifierNode;
|
||||
const AValue: IAstNode;
|
||||
const ALookback: IAstNode = nil
|
||||
const ALookback: IAstNode = nil;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IAddSeriesItemNode; static;
|
||||
class function SeriesLength(const ASeries: IIdentifierNode): ISeriesLengthNode; static;
|
||||
class function SeriesLength(const ASeries: IIdentifierNode; const AStaticType: IStaticType = nil): ISeriesLengthNode; static;
|
||||
|
||||
class function BoundIdentifier(
|
||||
AName: string;
|
||||
@@ -132,75 +173,6 @@ type
|
||||
property StaticType: IStaticType read GetStaticType;
|
||||
end;
|
||||
|
||||
TBinaryExpressionNode = class(TAstTypedNode, IBinaryExpressionNode)
|
||||
private
|
||||
FLeft: IAstNode;
|
||||
FOperator: TScalar.TBinaryOp;
|
||||
FRight: IAstNode;
|
||||
function GetLeft: IAstNode;
|
||||
function GetOperator: TScalar.TBinaryOp;
|
||||
function GetRight: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const ALeft: IAstNode; AOperator: TScalar.TBinaryOp; const ARight: IAstNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsBinaryExpression: IBinaryExpressionNode; override;
|
||||
property Left: IAstNode read FLeft write FLeft; // Writeable
|
||||
property Operator: TScalar.TBinaryOp read FOperator write FOperator; // Writeable
|
||||
property Right: IAstNode read FRight write FRight; // Writeable
|
||||
end;
|
||||
|
||||
TUnaryExpressionNode = class(TAstTypedNode, IUnaryExpressionNode)
|
||||
private
|
||||
FOperator: TScalar.TUnaryOp;
|
||||
FRight: IAstNode;
|
||||
function GetOperator: TScalar.TUnaryOp;
|
||||
function GetRight: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AOperator: TScalar.TUnaryOp; const ARight: IAstNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsUnaryExpression: IUnaryExpressionNode; override;
|
||||
property Operator: TScalar.TUnaryOp read FOperator write FOperator; // Writeable
|
||||
property Right: IAstNode read FRight write FRight; // Writeable
|
||||
end;
|
||||
|
||||
TIfExpressionNode = class(TAstTypedNode, IIfExpressionNode)
|
||||
private
|
||||
FCondition: IAstNode;
|
||||
FThenBranch: IAstNode;
|
||||
FElseBranch: IAstNode;
|
||||
function GetCondition: IAstNode;
|
||||
function GetThenBranch: IAstNode;
|
||||
function GetElseBranch: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const ACondition, AThenBranch, AElseBranch: IAstNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsIfExpression: IIfExpressionNode; override;
|
||||
property Condition: IAstNode read FCondition write FCondition; // Writeable
|
||||
property ThenBranch: IAstNode read FThenBranch write FThenBranch; // Writeable
|
||||
property ElseBranch: IAstNode read FElseBranch write FElseBranch; // Writeable
|
||||
end;
|
||||
|
||||
TTernaryExpressionNode = class(TAstTypedNode, ITernaryExpressionNode)
|
||||
private
|
||||
FCondition: IAstNode;
|
||||
FThenBranch: IAstNode;
|
||||
FElseBranch: IAstNode;
|
||||
function GetCondition: IAstNode;
|
||||
function GetThenBranch: IAstNode;
|
||||
function GetElseBranch: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const ACondition, AThenBranch, AElseBranch: IAstNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsTernaryExpression: ITernaryExpressionNode; override;
|
||||
property Condition: IAstNode read FCondition write FCondition; // Writeable
|
||||
property ThenBranch: IAstNode read FThenBranch write FThenBranch; // Writeable
|
||||
property ElseBranch: IAstNode read FElseBranch write FElseBranch; // Writeable
|
||||
end;
|
||||
|
||||
TLambdaExpressionNode = class(TAstTypedNode, ILambdaExpressionNode)
|
||||
private
|
||||
FParameters: TArray<IIdentifierNode>;
|
||||
@@ -216,8 +188,8 @@ type
|
||||
destructor Destroy; override;
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsLambdaExpression: ILambdaExpressionNode; override;
|
||||
property Body: IAstNode read FBody write FBody; // Writeable
|
||||
property Parameters: TArray<IIdentifierNode> read FParameters write FParameters;
|
||||
property Body: IAstNode read FBody write FBody;
|
||||
property Parameters: TArray<IIdentifierNode> read FParameters;
|
||||
property ScopeDescriptor: IScopeDescriptor read FScopeDescriptor write FScopeDescriptor;
|
||||
property Upvalues: TArray<TResolvedAddress> read FUpvalues write FUpvalues;
|
||||
property HasNestedLambdas: Boolean read FHasNestedLambdas write FHasNestedLambdas;
|
||||
@@ -235,35 +207,11 @@ type
|
||||
constructor Create(const ACallee: IAstNode; const AArguments: TArray<IAstNode>; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsFunctionCall: IFunctionCallNode; override;
|
||||
property Callee: IAstNode read FCallee write FCallee; // Writeable
|
||||
property Arguments: TArray<IAstNode> read FArguments write FArguments; // Writeable
|
||||
property Callee: IAstNode read FCallee;
|
||||
property Arguments: TArray<IAstNode> read FArguments;
|
||||
property IsTailCall: Boolean read FIsTailCall write FIsTailCall;
|
||||
end;
|
||||
|
||||
TRecurNode = class(TAstTypedNode, IRecurNode)
|
||||
private
|
||||
FArguments: TArray<IAstNode>;
|
||||
function GetArguments: TArray<IAstNode>;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AArguments: TArray<IAstNode>; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsRecur: IRecurNode; override;
|
||||
property Arguments: TArray<IAstNode> read FArguments write FArguments; // Writeable
|
||||
end;
|
||||
|
||||
TBlockExpressionNode = class(TAstTypedNode, IBlockExpressionNode)
|
||||
private
|
||||
FExpressions: TArray<IAstNode>;
|
||||
function GetExpressions: TArray<IAstNode>;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AExpressions: array of IAstNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsBlockExpression: IBlockExpressionNode; override;
|
||||
property Expressions: TArray<IAstNode> read FExpressions write FExpressions; // Writeable
|
||||
end;
|
||||
|
||||
TVariableDeclarationNode = class(TAstTypedNode, IVariableDeclarationNode)
|
||||
private
|
||||
FIdentifier: IIdentifierNode;
|
||||
@@ -276,54 +224,9 @@ type
|
||||
constructor Create(const AIdentifier: IIdentifierNode; AInitializer: IAstNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsVariableDeclaration: IVariableDeclarationNode; override;
|
||||
property Identifier: IIdentifierNode read FIdentifier write FIdentifier; // Writeable
|
||||
property Initializer: IAstNode read FInitializer write FInitializer; // Writeable
|
||||
property IsBoxed: Boolean read FIsBoxed write FIsBoxed;
|
||||
end;
|
||||
|
||||
TAssignmentNode = class(TAstTypedNode, IAssignmentNode)
|
||||
private
|
||||
FIdentifier: IIdentifierNode;
|
||||
FValue: IAstNode;
|
||||
function GetIdentifier: IIdentifierNode;
|
||||
function GetValue: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AIdentifier: IIdentifierNode; const AValue: IAstNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsAssignment: IAssignmentNode; override;
|
||||
property Identifier: IIdentifierNode read FIdentifier write FIdentifier;
|
||||
property Value: IAstNode read FValue write FValue; // Writeable
|
||||
end;
|
||||
|
||||
TIndexerNode = class(TAstTypedNode, IIndexerNode)
|
||||
private
|
||||
FBase: IAstNode;
|
||||
FIndex: IAstNode;
|
||||
function GetBase: IAstNode;
|
||||
function GetIndex: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const ABase: IAstNode; const AIndex: IAstNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsIndexer: IIndexerNode; override;
|
||||
property Base: IAstNode read FBase write FBase; // Writeable
|
||||
property Index: IAstNode read FIndex write FIndex; // Writeable
|
||||
end;
|
||||
|
||||
TMemberAccessNode = class(TAstTypedNode, IMemberAccessNode)
|
||||
private
|
||||
FBase: IAstNode;
|
||||
FMember: IKeywordNode;
|
||||
function GetBase: IAstNode;
|
||||
function GetMember: IKeywordNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const ABase: IAstNode; const AMember: IKeywordNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsMemberAccess: IMemberAccessNode; override;
|
||||
property Base: IAstNode read FBase write FBase; // Writeable
|
||||
property Member: IKeywordNode read FMember write FMember;
|
||||
property Initializer: IAstNode read FInitializer write FInitializer;
|
||||
property IsBoxed: Boolean read FIsBoxed write FIsBoxed;
|
||||
end;
|
||||
|
||||
TRecordLiteralNode = class(TAstTypedNode, IRecordLiteralNode)
|
||||
@@ -336,7 +239,7 @@ type
|
||||
constructor Create(const AFields: TArray<TRecordFieldLiteral>; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsRecordLiteral: IRecordLiteralNode; override;
|
||||
property Fields: TArray<TRecordFieldLiteral> read FFields write FFields; // Writeable
|
||||
property Fields: TArray<TRecordFieldLiteral> read FFields;
|
||||
property Definition: IScalarRecordDefinition read FDefinition write FDefinition;
|
||||
end;
|
||||
|
||||
@@ -348,52 +251,6 @@ type
|
||||
property GenericDefinition: IGenericRecordDefinition read FGenericDefinition write FGenericDefinition;
|
||||
end;
|
||||
|
||||
TCreateSeriesNode = class(TAstTypedNode, ICreateSeriesNode)
|
||||
private
|
||||
FDefinition: String;
|
||||
function GetDefinition: String;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const ADefinition: String; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsCreateSeries: ICreateSeriesNode; override;
|
||||
end;
|
||||
|
||||
TAddSeriesItemNode = class(TAstTypedNode, IAddSeriesItemNode)
|
||||
private
|
||||
FSeries: IIdentifierNode;
|
||||
FValue: IAstNode;
|
||||
FLookback: IAstNode;
|
||||
function GetSeries: IIdentifierNode;
|
||||
function GetValue: IAstNode;
|
||||
function GetLookback: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(
|
||||
const ASeries: IIdentifierNode;
|
||||
const AValue: IAstNode;
|
||||
const ALookback: IAstNode;
|
||||
const AStaticType: IStaticType
|
||||
);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsAddSeriesItem: IAddSeriesItemNode; override;
|
||||
property Series: IIdentifierNode read FSeries write FSeries;
|
||||
property Value: IAstNode read FValue write FValue; // Writeable
|
||||
property Lookback: IAstNode read FLookback write FLookback; // Writeable
|
||||
end;
|
||||
|
||||
TSeriesLengthNode = class(TAstTypedNode, ISeriesLengthNode)
|
||||
private
|
||||
FSeries: IIdentifierNode;
|
||||
function GetSeries: IIdentifierNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const ASeries: IIdentifierNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsSeriesLength: ISeriesLengthNode; override;
|
||||
property Series: IIdentifierNode read FSeries write FSeries;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
@@ -516,6 +373,191 @@ type
|
||||
property ExpandedBody: IAstTypedNode read FExpandedBody;
|
||||
end;
|
||||
|
||||
TRecurNode = class(TAstTypedNode, IRecurNode)
|
||||
private
|
||||
FArguments: TArray<IAstNode>;
|
||||
function GetArguments: TArray<IAstNode>;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AArguments: TArray<IAstNode>; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsRecur: IRecurNode; override;
|
||||
property Arguments: TArray<IAstNode> read FArguments;
|
||||
end;
|
||||
|
||||
TBlockExpressionNode = class(TAstTypedNode, IBlockExpressionNode)
|
||||
private
|
||||
FExpressions: TArray<IAstNode>;
|
||||
function GetExpressions: TArray<IAstNode>;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AExpressions: array of IAstNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsBlockExpression: IBlockExpressionNode; override;
|
||||
property Expressions: TArray<IAstNode> read FExpressions;
|
||||
end;
|
||||
|
||||
TBinaryExpressionNode = class(TAstTypedNode, IBinaryExpressionNode)
|
||||
private
|
||||
FLeft: IAstNode;
|
||||
FOperator: TScalar.TBinaryOp;
|
||||
FRight: IAstNode;
|
||||
function GetLeft: IAstNode;
|
||||
function GetOperator: TScalar.TBinaryOp;
|
||||
function GetRight: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const ALeft: IAstNode; AOperator: TScalar.TBinaryOp; const ARight: IAstNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsBinaryExpression: IBinaryExpressionNode; override;
|
||||
property Left: IAstNode read FLeft;
|
||||
property Operator: TScalar.TBinaryOp read FOperator;
|
||||
property Right: IAstNode read FRight;
|
||||
end;
|
||||
|
||||
TUnaryExpressionNode = class(TAstTypedNode, IUnaryExpressionNode)
|
||||
private
|
||||
FOperator: TScalar.TUnaryOp;
|
||||
FRight: IAstNode;
|
||||
function GetOperator: TScalar.TUnaryOp;
|
||||
function GetRight: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AOperator: TScalar.TUnaryOp; const ARight: IAstNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsUnaryExpression: IUnaryExpressionNode; override;
|
||||
property Operator: TScalar.TUnaryOp read FOperator;
|
||||
property Right: IAstNode read FRight;
|
||||
end;
|
||||
|
||||
TIfExpressionNode = class(TAstTypedNode, IIfExpressionNode)
|
||||
private
|
||||
FCondition: IAstNode;
|
||||
FThenBranch: IAstNode;
|
||||
FElseBranch: IAstNode;
|
||||
function GetCondition: IAstNode;
|
||||
function GetThenBranch: IAstNode;
|
||||
function GetElseBranch: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const ACondition, AThenBranch, AElseBranch: IAstNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsIfExpression: IIfExpressionNode; override;
|
||||
property Condition: IAstNode read FCondition;
|
||||
property ThenBranch: IAstNode read FThenBranch;
|
||||
property ElseBranch: IAstNode read FElseBranch;
|
||||
end;
|
||||
|
||||
TTernaryExpressionNode = class(TAstTypedNode, ITernaryExpressionNode)
|
||||
private
|
||||
FCondition: IAstNode;
|
||||
FThenBranch: IAstNode;
|
||||
FElseBranch: IAstNode;
|
||||
function GetCondition: IAstNode;
|
||||
function GetThenBranch: IAstNode;
|
||||
function GetElseBranch: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const ACondition, AThenBranch, AElseBranch: IAstNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsTernaryExpression: ITernaryExpressionNode; override;
|
||||
property Condition: IAstNode read FCondition;
|
||||
property ThenBranch: IAstNode read FThenBranch;
|
||||
property ElseBranch: IAstNode read FElseBranch;
|
||||
end;
|
||||
|
||||
TAssignmentNode = class(TAstTypedNode, IAssignmentNode)
|
||||
private
|
||||
FIdentifier: IIdentifierNode;
|
||||
FValue: IAstNode;
|
||||
function GetIdentifier: IIdentifierNode;
|
||||
function GetValue: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AIdentifier: IIdentifierNode; const AValue: IAstNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsAssignment: IAssignmentNode; override;
|
||||
property Identifier: IIdentifierNode read FIdentifier;
|
||||
property Value: IAstNode read FValue;
|
||||
end;
|
||||
|
||||
TIndexerNode = class(TAstTypedNode, IIndexerNode)
|
||||
private
|
||||
FBase: IAstNode;
|
||||
FIndex: IAstNode;
|
||||
function GetBase: IAstNode;
|
||||
function GetIndex: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const ABase: IAstNode; const AIndex: IAstNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsIndexer: IIndexerNode; override;
|
||||
property Base: IAstNode read FBase;
|
||||
property Index: IAstNode read FIndex;
|
||||
end;
|
||||
|
||||
TMemberAccessNode = class(TAstTypedNode, IMemberAccessNode)
|
||||
private
|
||||
FBase: IAstNode;
|
||||
FMember: IKeywordNode;
|
||||
function GetBase: IAstNode;
|
||||
function GetMember: IKeywordNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const ABase: IAstNode; const AMember: IKeywordNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsMemberAccess: IMemberAccessNode; override;
|
||||
property Base: IAstNode read FBase;
|
||||
property Member: IKeywordNode read FMember;
|
||||
end;
|
||||
|
||||
TCreateSeriesNode = class(TAstTypedNode, ICreateSeriesNode)
|
||||
private
|
||||
FDefinition: String;
|
||||
function GetDefinition: String;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const ADefinition: String; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsCreateSeries: ICreateSeriesNode; override;
|
||||
property Definition: String read FDefinition;
|
||||
end;
|
||||
|
||||
TAddSeriesItemNode = class(TAstTypedNode, IAddSeriesItemNode)
|
||||
private
|
||||
FSeries: IIdentifierNode;
|
||||
FValue: IAstNode;
|
||||
FLookback: IAstNode;
|
||||
function GetSeries: IIdentifierNode;
|
||||
function GetValue: IAstNode;
|
||||
function GetLookback: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(
|
||||
const ASeries: IIdentifierNode;
|
||||
const AValue: IAstNode;
|
||||
const ALookback: IAstNode;
|
||||
const AStaticType: IStaticType
|
||||
);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsAddSeriesItem: IAddSeriesItemNode; override;
|
||||
property Series: IIdentifierNode read FSeries;
|
||||
property Value: IAstNode read FValue;
|
||||
property Lookback: IAstNode read FLookback;
|
||||
end;
|
||||
|
||||
TSeriesLengthNode = class(TAstTypedNode, ISeriesLengthNode)
|
||||
private
|
||||
FSeries: IIdentifierNode;
|
||||
function GetSeries: IIdentifierNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const ASeries: IIdentifierNode; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsSeriesLength: ISeriesLengthNode; override;
|
||||
property Series: IIdentifierNode read FSeries;
|
||||
end;
|
||||
|
||||
TNopNode = class(TAstNode, INopNode)
|
||||
private
|
||||
function GetKind: TAstNodeKind; override;
|
||||
@@ -539,28 +581,56 @@ begin
|
||||
libProc(Result);
|
||||
end;
|
||||
|
||||
class function TAst.CreateSeries(const ADefinition: String): ICreateSeriesNode;
|
||||
class function TAst.CreateSeries(const ADefinition: String; const AStaticType: IStaticType = nil): ICreateSeriesNode;
|
||||
begin
|
||||
Result := TCreateSeriesNode.Create(ADefinition, TTypes.Unknown);
|
||||
Result :=
|
||||
TCreateSeriesNode.Create(
|
||||
ADefinition,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Unknown
|
||||
);
|
||||
end;
|
||||
|
||||
class function TAst.AddSeriesItem(
|
||||
const ASeries: IIdentifierNode;
|
||||
const AValue: IAstNode;
|
||||
const ALookback: IAstNode = nil
|
||||
const ALookback: IAstNode = nil;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IAddSeriesItemNode;
|
||||
begin
|
||||
Result := TAddSeriesItemNode.Create(ASeries, AValue, ALookback, TTypes.Unknown);
|
||||
Result :=
|
||||
TAddSeriesItemNode.Create(
|
||||
ASeries,
|
||||
AValue,
|
||||
ALookback,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Void
|
||||
);
|
||||
end;
|
||||
|
||||
class function TAst.SeriesLength(const ASeries: IIdentifierNode): ISeriesLengthNode;
|
||||
class function TAst.SeriesLength(const ASeries: IIdentifierNode; const AStaticType: IStaticType = nil): ISeriesLengthNode;
|
||||
begin
|
||||
Result := TSeriesLengthNode.Create(ASeries, TTypes.Unknown);
|
||||
Result :=
|
||||
TSeriesLengthNode.Create(
|
||||
ASeries,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Ordinal
|
||||
);
|
||||
end;
|
||||
|
||||
class function TAst.Assign(const AIdentifier: IIdentifierNode; const AValue: IAstNode): IAssignmentNode;
|
||||
class function TAst.Assign(
|
||||
const AIdentifier: IIdentifierNode;
|
||||
const AValue: IAstNode;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IAssignmentNode;
|
||||
begin
|
||||
Result := TAssignmentNode.Create(AIdentifier, AValue, TTypes.Unknown);
|
||||
Result :=
|
||||
TAssignmentNode.Create(
|
||||
AIdentifier,
|
||||
AValue,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Unknown
|
||||
);
|
||||
end;
|
||||
|
||||
class function TAst.AssignResult(const AValue: IAstNode): IAssignmentNode;
|
||||
@@ -570,14 +640,31 @@ begin
|
||||
Result := TAssignmentNode.Create(TAst.Identifier('Result'), AValue, TTypes.Unknown);
|
||||
end;
|
||||
|
||||
class function TAst.BinaryExpr(ALeft: IAstNode; AOperator: TScalar.TBinaryOp; ARight: IAstNode): IBinaryExpressionNode;
|
||||
class function TAst.BinaryExpr(
|
||||
ALeft: IAstNode;
|
||||
AOperator: TScalar.TBinaryOp;
|
||||
ARight: IAstNode;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IBinaryExpressionNode;
|
||||
begin
|
||||
Result := TBinaryExpressionNode.Create(ALeft, AOperator, ARight, TTypes.Unknown);
|
||||
Result :=
|
||||
TBinaryExpressionNode.Create(
|
||||
ALeft,
|
||||
AOperator,
|
||||
ARight,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Unknown
|
||||
);
|
||||
end;
|
||||
|
||||
class function TAst.Block(const AExpressions: array of IAstNode): IBlockExpressionNode;
|
||||
class function TAst.Block(const AExpressions: array of IAstNode; const AStaticType: IStaticType = nil): IBlockExpressionNode;
|
||||
begin
|
||||
Result := TBlockExpressionNode.Create(AExpressions, TTypes.Unknown);
|
||||
Result :=
|
||||
TBlockExpressionNode.Create(
|
||||
AExpressions,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Unknown
|
||||
);
|
||||
end;
|
||||
|
||||
class function TAst.Constant(const AValue: TDataValue; const AStaticType: IStaticType = nil): IConstantNode;
|
||||
@@ -634,24 +721,56 @@ begin
|
||||
FLibraries.Add(AProc);
|
||||
end;
|
||||
|
||||
class function TAst.FunctionCall(const ACallee: IAstNode; const AArguments: TArray<IAstNode>): IFunctionCallNode;
|
||||
class function TAst.FunctionCall(
|
||||
const ACallee: IAstNode;
|
||||
const AArguments: TArray<IAstNode>;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IFunctionCallNode;
|
||||
begin
|
||||
Result := TFunctionCallNode.Create(ACallee, AArguments, TTypes.Unknown);
|
||||
Result :=
|
||||
TFunctionCallNode.Create(
|
||||
ACallee,
|
||||
AArguments,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Unknown
|
||||
);
|
||||
end;
|
||||
|
||||
class function TAst.Identifier(AName: string): IIdentifierNode;
|
||||
class function TAst.Identifier(AName: string; const AStaticType: IStaticType = nil): IIdentifierNode;
|
||||
begin
|
||||
Result := TIdentifierNode.Create(AName, TTypes.Unknown);
|
||||
Result :=
|
||||
TIdentifierNode.Create(
|
||||
AName,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Unknown
|
||||
);
|
||||
end;
|
||||
|
||||
class function TAst.IfExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): IIfExpressionNode;
|
||||
class function TAst.IfExpr(
|
||||
const ACondition: IAstNode;
|
||||
const AThenBranch, AElseBranch: IAstNode;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IIfExpressionNode;
|
||||
begin
|
||||
Result := TIfExpressionNode.Create(ACondition, AThenBranch, AElseBranch, TTypes.Unknown);
|
||||
Result :=
|
||||
TIfExpressionNode.Create(
|
||||
ACondition,
|
||||
AThenBranch,
|
||||
AElseBranch,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Unknown
|
||||
);
|
||||
end;
|
||||
|
||||
class function TAst.Indexer(const ABase: IAstNode; const AIndex: IAstNode): IIndexerNode;
|
||||
class function TAst.Indexer(const ABase: IAstNode; const AIndex: IAstNode; const AStaticType: IStaticType = nil): IIndexerNode;
|
||||
begin
|
||||
Result := TIndexerNode.Create(ABase, AIndex, TTypes.Unknown);
|
||||
Result :=
|
||||
TIndexerNode.Create(
|
||||
ABase,
|
||||
AIndex,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Unknown
|
||||
);
|
||||
end;
|
||||
|
||||
class function TAst.Keyword(const AName: string): IKeywordNode;
|
||||
@@ -659,9 +778,19 @@ begin
|
||||
Result := TKeywordNode.Create(TKeywordRegistry.Intern(AName));
|
||||
end;
|
||||
|
||||
class function TAst.LambdaExpr(const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode): ILambdaExpressionNode;
|
||||
class function TAst.LambdaExpr(
|
||||
const AParameters: TArray<IIdentifierNode>;
|
||||
const ABody: IAstNode;
|
||||
const AStaticType: IStaticType = nil
|
||||
): ILambdaExpressionNode;
|
||||
begin
|
||||
Result := TLambdaExpressionNode.Create(AParameters, ABody, TTypes.Unknown);
|
||||
Result :=
|
||||
TLambdaExpressionNode.Create(
|
||||
AParameters,
|
||||
ABody,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Unknown
|
||||
);
|
||||
end;
|
||||
|
||||
class function TAst.MacroDef(
|
||||
@@ -675,15 +804,26 @@ end;
|
||||
|
||||
class function TAst.MacroExpansionNode(const AOriginalCallNode: IFunctionCallNode; const AExpandedBody: IAstNode): IMacroExpansionNode;
|
||||
begin
|
||||
if AExpandedBody.IsTyped then
|
||||
Result := TMacroExpansionNode.Create(AOriginalCallNode, AExpandedBody.AsTypedNode)
|
||||
else
|
||||
Result := TMacroExpansionNode.Create(AOriginalCallNode, Block([]));
|
||||
// A MacroExpansionNode MUST have a typed body.
|
||||
if not AExpandedBody.IsTyped then
|
||||
raise ETypeException.Create('MacroExpansionNode cannot be created with an untyped body.');
|
||||
|
||||
Result := TMacroExpansionNode.Create(AOriginalCallNode, AExpandedBody.AsTypedNode);
|
||||
end;
|
||||
|
||||
class function TAst.MemberAccess(const ABase: IAstNode; const AMember: IKeywordNode): IMemberAccessNode;
|
||||
class function TAst.MemberAccess(
|
||||
const ABase: IAstNode;
|
||||
const AMember: IKeywordNode;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IMemberAccessNode;
|
||||
begin
|
||||
Result := TMemberAccessNode.Create(ABase, AMember, TTypes.Unknown);
|
||||
Result :=
|
||||
TMemberAccessNode.Create(
|
||||
ABase,
|
||||
AMember,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Unknown
|
||||
);
|
||||
end;
|
||||
|
||||
class function TAst.Nop: IAstNode;
|
||||
@@ -697,31 +837,64 @@ begin
|
||||
Result := TQuasiquoteNode.Create(AExpression);
|
||||
end;
|
||||
|
||||
class function TAst.Recur(const AArguments: array of IAstNode): IRecurNode;
|
||||
class function TAst.Recur(const AArguments: array of IAstNode; const AStaticType: IStaticType = nil): IRecurNode;
|
||||
var
|
||||
args: TArray<IAstNode>;
|
||||
i: Integer;
|
||||
begin
|
||||
var args: TArray<IAstNode>;
|
||||
SetLength(args, Length(AArguments));
|
||||
for var i := 0 to High(AArguments) do
|
||||
for i := 0 to High(AArguments) do
|
||||
args[i] := AArguments[i];
|
||||
Result := TRecurNode.Create(args, TTypes.Unknown);
|
||||
Result :=
|
||||
TRecurNode.Create(
|
||||
args,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Void
|
||||
);
|
||||
end;
|
||||
|
||||
class function TAst.RecordLiteral(const AFields: TArray<TRecordFieldLiteral>): IRecordLiteralNode;
|
||||
class function TAst.RecordLiteral(const AFields: TArray<TRecordFieldLiteral>; const AStaticType: IStaticType = nil): IRecordLiteralNode;
|
||||
begin
|
||||
// By default, the parser creates the generic (most flexible) node type.
|
||||
// The TypeChecker (Phase 3) is responsible for "lowering" this to a
|
||||
// TRecordLiteralNode if it determines all fields are scalar.
|
||||
Result := TGenericRecordLiteralNode.Create(AFields, TTypes.Unknown);
|
||||
Result :=
|
||||
TGenericRecordLiteralNode.Create(
|
||||
AFields,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Unknown
|
||||
);
|
||||
end;
|
||||
|
||||
class function TAst.TernaryExpr(const ACondition: IAstNode; const AThenBranch, AElseBranch: IAstNode): ITernaryExpressionNode;
|
||||
class function TAst.TernaryExpr(
|
||||
const ACondition: IAstNode;
|
||||
const AThenBranch, AElseBranch: IAstNode;
|
||||
const AStaticType: IStaticType = nil
|
||||
): ITernaryExpressionNode;
|
||||
begin
|
||||
Result := TTernaryExpressionNode.Create(ACondition, AThenBranch, AElseBranch, TTypes.Unknown);
|
||||
Result :=
|
||||
TTernaryExpressionNode.Create(
|
||||
ACondition,
|
||||
AThenBranch,
|
||||
AElseBranch,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Unknown
|
||||
);
|
||||
end;
|
||||
|
||||
class function TAst.UnaryExpr(const AOperator: TScalar.TUnaryOp; const ARight: IAstNode): IUnaryExpressionNode;
|
||||
class function TAst.UnaryExpr(
|
||||
const AOperator: TScalar.TUnaryOp;
|
||||
const ARight: IAstNode;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IUnaryExpressionNode;
|
||||
begin
|
||||
Result := TUnaryExpressionNode.Create(AOperator, ARight, TTypes.Unknown);
|
||||
Result :=
|
||||
TUnaryExpressionNode.Create(
|
||||
AOperator,
|
||||
ARight,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Unknown
|
||||
);
|
||||
end;
|
||||
|
||||
class function TAst.Unquote(const AExpression: IAstNode): IUnquoteNode;
|
||||
@@ -734,9 +907,19 @@ begin
|
||||
Result := TUnquoteSplicingNode.Create(AExpression);
|
||||
end;
|
||||
|
||||
class function TAst.VarDecl(const AIdentifier: IIdentifierNode; AInitializer: IAstNode = nil): IVariableDeclarationNode;
|
||||
class function TAst.VarDecl(
|
||||
const AIdentifier: IIdentifierNode;
|
||||
AInitializer: IAstNode = nil;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IVariableDeclarationNode;
|
||||
begin
|
||||
Result := TVariableDeclarationNode.Create(AIdentifier, AInitializer, TTypes.Unknown);
|
||||
Result :=
|
||||
TVariableDeclarationNode.Create(
|
||||
AIdentifier,
|
||||
AInitializer,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Unknown
|
||||
);
|
||||
end;
|
||||
|
||||
{ TNopNode }
|
||||
@@ -1379,7 +1562,7 @@ end;
|
||||
|
||||
constructor TMacroExpansionNode.Create(const ACallNode: IFunctionCallNode; const AExpandedBody: IAstTypedNode);
|
||||
begin
|
||||
// Copy properties from the original call node
|
||||
// The StaticType of the wrapper *is* the StaticType of the body
|
||||
inherited Create(AExpandedBody.StaticType);
|
||||
FExpandedBody := AExpandedBody;
|
||||
FCallNode := ACallNode;
|
||||
|
||||
Reference in New Issue
Block a user