Refactoring node to be immutable

This commit is contained in:
Michael Schimmel
2025-11-05 15:15:12 +01:00
parent 218bd9f506
commit 25984fe61a
7 changed files with 537 additions and 371 deletions
+14 -21
View File
@@ -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;
+3 -3
View File
@@ -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;
+2 -2
View File
@@ -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);
+12 -12
View File
@@ -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
View File
@@ -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
View File
@@ -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;