diff --git a/ASTPlayground/MainForm.pas b/ASTPlayground/MainForm.pas index a501bc1..da98df4 100644 --- a/ASTPlayground/MainForm.pas +++ b/ASTPlayground/MainForm.pas @@ -451,9 +451,9 @@ begin definitions := TDictionary.Create; try // Check if the root is a block and extract top-level definitions - if rootNode is TBlockExpressionNode then + if rootNode.Kind = akBlockExpression then begin - for var expr in (rootNode as TBlockExpressionNode).Expressions do + for var expr in rootNode.AsBlockExpression.Expressions do begin if expr is TVariableDeclarationNode then begin diff --git a/Src/AST/Myc.Ast.Compiler.TCO.pas b/Src/AST/Myc.Ast.Compiler.TCO.pas index 2e0a84e..1a0fec6 100644 --- a/Src/AST/Myc.Ast.Compiler.TCO.pas +++ b/Src/AST/Myc.Ast.Compiler.TCO.pas @@ -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; 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; diff --git a/Src/AST/Myc.Ast.Lowering.pas b/Src/AST/Myc.Ast.Lowering.pas index c86e8f5..37c1388 100644 --- a/Src/AST/Myc.Ast.Lowering.pas +++ b/Src/AST/Myc.Ast.Lowering.pas @@ -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; diff --git a/Src/AST/Myc.Ast.MacroExpander.pas b/Src/AST/Myc.Ast.MacroExpander.pas index 9799d17..0dfbc9d 100644 --- a/Src/AST/Myc.Ast.MacroExpander.pas +++ b/Src/AST/Myc.Ast.MacroExpander.pas @@ -122,8 +122,8 @@ begin if (not evaluatedSpliceValue.IsVoid) and (evaluatedSpliceValue.Kind = vkInterface) then begin nodeToSplice := evaluatedSpliceValue.AsIntf; - 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); diff --git a/Src/AST/Myc.Ast.TypeChecker.pas b/Src/AST/Myc.Ast.TypeChecker.pas index b8fa83b..c2f9990 100644 --- a/Src/AST/Myc.Ast.TypeChecker.pas +++ b/Src/AST/Myc.Ast.TypeChecker.pas @@ -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. diff --git a/Src/AST/Myc.Ast.Visitor.pas b/Src/AST/Myc.Ast.Visitor.pas index 9163787..9aa5c08 100644 --- a/Src/AST/Myc.Ast.Visitor.pas +++ b/Src/AST/Myc.Ast.Visitor.pas @@ -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; 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; - 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; 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; - 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 } diff --git a/Src/AST/Myc.Ast.pas b/Src/AST/Myc.Ast.pas index fd68908..d99e306 100644 --- a/Src/AST/Myc.Ast.pas +++ b/Src/AST/Myc.Ast.pas @@ -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; 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; + const ABody: IAstNode; + const AStaticType: IStaticType = nil + ): ILambdaExpressionNode; static; class function MacroDef( const AName: IIdentifierNode; const AParameters: TArray; @@ -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): IFunctionCallNode; static; + class function FunctionCall( + const ACallee: IAstNode; + const AArguments: TArray; + 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): 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; + 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; @@ -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 read FParameters write FParameters; + property Body: IAstNode read FBody write FBody; + property Parameters: TArray read FParameters; property ScopeDescriptor: IScopeDescriptor read FScopeDescriptor write FScopeDescriptor; property Upvalues: TArray read FUpvalues write FUpvalues; property HasNestedLambdas: Boolean read FHasNestedLambdas write FHasNestedLambdas; @@ -235,35 +207,11 @@ type constructor Create(const ACallee: IAstNode; const AArguments: TArray; 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 read FArguments write FArguments; // Writeable + property Callee: IAstNode read FCallee; + property Arguments: TArray read FArguments; property IsTailCall: Boolean read FIsTailCall write FIsTailCall; end; - TRecurNode = class(TAstTypedNode, IRecurNode) - private - FArguments: TArray; - function GetArguments: TArray; - function GetKind: TAstNodeKind; override; - public - constructor Create(const AArguments: TArray; const AStaticType: IStaticType); - function Accept(const Visitor: IAstVisitor): TDataValue; override; - function AsRecur: IRecurNode; override; - property Arguments: TArray read FArguments write FArguments; // Writeable - end; - - TBlockExpressionNode = class(TAstTypedNode, IBlockExpressionNode) - private - FExpressions: TArray; - function GetExpressions: TArray; - 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 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; const AStaticType: IStaticType); function Accept(const Visitor: IAstVisitor): TDataValue; override; function AsRecordLiteral: IRecordLiteralNode; override; - property Fields: TArray read FFields write FFields; // Writeable + property Fields: TArray 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; + function GetArguments: TArray; + function GetKind: TAstNodeKind; override; + public + constructor Create(const AArguments: TArray; const AStaticType: IStaticType); + function Accept(const Visitor: IAstVisitor): TDataValue; override; + function AsRecur: IRecurNode; override; + property Arguments: TArray read FArguments; + end; + + TBlockExpressionNode = class(TAstTypedNode, IBlockExpressionNode) + private + FExpressions: TArray; + function GetExpressions: TArray; + 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 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): IFunctionCallNode; +class function TAst.FunctionCall( + const ACallee: IAstNode; + const AArguments: TArray; + 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; const ABody: IAstNode): ILambdaExpressionNode; +class function TAst.LambdaExpr( + const AParameters: TArray; + 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; + i: Integer; begin - var args: TArray; 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): IRecordLiteralNode; +class function TAst.RecordLiteral(const AFields: TArray; 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;