AST Types

This commit is contained in:
Michael Schimmel
2025-10-25 19:19:55 +02:00
parent 5a289492a3
commit 85f2e02893
2 changed files with 40 additions and 142 deletions
+21 -142
View File
@@ -94,102 +94,52 @@ type
): IAstNode; static;
end;
// New base class for all bound nodes
TBoundNode = class abstract(TInterfacedObject, IAstNode)
public
function Accept(const Visitor: IAstVisitor): TDataValue; virtual; abstract;
end;
// Concrete bound identifier node
TBoundIdentifierNode = class(TBoundNode, IIdentifierNode)
TBoundIdentifierNode = class(TIdentifierNode)
private
FSource: IIdentifierNode; // The original Node.
FAddress: TResolvedAddress;
function GetName: string;
public
constructor Create(const ASource: IIdentifierNode; const AAddress: TResolvedAddress);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
constructor Create(const AUnboundNode: IIdentifierNode; const AAddress: TResolvedAddress);
property Address: TResolvedAddress read FAddress;
property Name: string read GetName;
property Source: IIdentifierNode read FSource;
end;
// Bound variable declaration node
TBoundVariableDeclarationNode = class(TBoundNode, IVariableDeclarationNode)
TBoundVariableDeclarationNode = class(TVariableDeclarationNode)
private
FSource: IVariableDeclarationNode;
FIdentifier: IIdentifierNode;
FInitializer: IAstNode;
FIsBoxed: Boolean;
function GetIdentifier: IIdentifierNode;
function GetInitializer: IAstNode;
public
constructor Create(
const ASource: IVariableDeclarationNode;
const AIdentifier: IIdentifierNode; // This is the bound identifier
AInitializer: IAstNode; // This is the bound initializer
AIsBoxed: Boolean
);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
constructor Create(const AIdentifier: IIdentifierNode; AInitializer: IAstNode; AIsBoxed: Boolean);
property IsBoxed: Boolean read FIsBoxed;
property Source: IVariableDeclarationNode read FSource;
// IVariableDeclarationNode implementation
property Identifier: IIdentifierNode read GetIdentifier;
property Initializer: IAstNode read GetInitializer;
end;
// Bound lambda expression node
TBoundLambdaExpressionNode = class(TBoundNode, ILambdaExpressionNode)
TBoundLambdaExpressionNode = class(TLambdaExpressionNode)
private
FSource: ILambdaExpressionNode;
FParameters: TArray<IIdentifierNode>; // Bound parameters
FBody: IAstNode; // Bound body
FScopeDescriptor: IScopeDescriptor;
FUpvalues: TArray<TResolvedAddress>;
FHasNestedLambdas: Boolean;
function GetBody: IAstNode;
function GetParameters: TArray<IIdentifierNode>;
public
constructor Create(
const ASource: ILambdaExpressionNode;
const ABody: IAstNode; // Bound body
const AParameters: TArray<IIdentifierNode>; // Bound parameters
const AUnboundNode: ILambdaExpressionNode;
const ABody: IAstNode;
const AParameters: TArray<IIdentifierNode>;
const AScopeDescriptor: IScopeDescriptor;
const AUpvalues: TArray<TResolvedAddress>;
AHasNestedLambdas: Boolean
);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
property ScopeDescriptor: IScopeDescriptor read FScopeDescriptor;
property Upvalues: TArray<TResolvedAddress> read FUpvalues;
property HasNestedLambdas: Boolean read FHasNestedLambdas;
property Source: ILambdaExpressionNode read FSource;
// ILambdaExpressionNode implementation
property Parameters: TArray<IIdentifierNode> read GetParameters;
property Body: IAstNode read GetBody;
end;
// Bound function call node
TBoundFunctionCallNode = class(TBoundNode, IFunctionCallNode)
TBoundFunctionCallNode = class(TFunctionCallNode)
private
FSource: IFunctionCallNode;
FCallee: IAstNode; // Bound callee
FArguments: TArray<IAstNode>; // Bound arguments
FIsTailCall: Boolean;
function GetArguments: TArray<IAstNode>;
function GetCallee: IAstNode;
public
constructor Create(
const ASource: IFunctionCallNode;
const ACallee: IAstNode; // Bound callee
const AArguments: TArray<IAstNode>; // Bound arguments
const AUnboundNode: IFunctionCallNode;
const ACallee: IAstNode;
const AArguments: TArray<IAstNode>;
AIsTailCall: Boolean
);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
property IsTailCall: Boolean read FIsTailCall;
property Source: IFunctionCallNode read FSource;
// IFunctionCallNode implementation
property Callee: IAstNode read GetCallee;
property Arguments: TArray<IAstNode> read GetArguments;
end;
implementation
@@ -317,57 +267,22 @@ begin
end;
{ TBoundIdentifierNode }
constructor TBoundIdentifierNode.Create(const ASource: IIdentifierNode; const AAddress: TResolvedAddress);
constructor TBoundIdentifierNode.Create(const AUnboundNode: IIdentifierNode; const AAddress: TResolvedAddress);
begin
inherited Create;
FSource := ASource;
inherited Create(AUnboundNode.Name);
FAddress := AAddress;
end;
function TBoundIdentifierNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitIdentifier(Self);
end;
function TBoundIdentifierNode.GetName: string;
begin
Result := FSource.Name;
end;
{ TBoundVariableDeclarationNode }
constructor TBoundVariableDeclarationNode.Create(
const ASource: IVariableDeclarationNode;
const AIdentifier: IIdentifierNode;
AInitializer: IAstNode;
AIsBoxed: Boolean
);
constructor TBoundVariableDeclarationNode.Create(const AIdentifier: IIdentifierNode; AInitializer: IAstNode; AIsBoxed: Boolean);
begin
inherited Create;
FSource := ASource;
FIdentifier := AIdentifier;
FInitializer := AInitializer;
inherited Create(AIdentifier, AInitializer);
FIsBoxed := AIsBoxed;
end;
function TBoundVariableDeclarationNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitVariableDeclaration(Self);
end;
function TBoundVariableDeclarationNode.GetIdentifier: IIdentifierNode;
begin
Result := FIdentifier;
end;
function TBoundVariableDeclarationNode.GetInitializer: IAstNode;
begin
Result := FInitializer;
end;
{ TBoundLambdaExpressionNode }
constructor TBoundLambdaExpressionNode.Create(
const ASource: ILambdaExpressionNode;
const AUnboundNode: ILambdaExpressionNode;
const ABody: IAstNode;
const AParameters: TArray<IIdentifierNode>;
const AScopeDescriptor: IScopeDescriptor;
@@ -375,60 +290,24 @@ constructor TBoundLambdaExpressionNode.Create(
AHasNestedLambdas: Boolean
);
begin
inherited Create;
FSource := ASource;
FBody := ABody;
FParameters := AParameters;
inherited Create(AParameters, ABody);
FScopeDescriptor := AScopeDescriptor;
FUpvalues := AUpvalues;
FHasNestedLambdas := AHasNestedLambdas;
end;
function TBoundLambdaExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitLambdaExpression(Self);
end;
function TBoundLambdaExpressionNode.GetBody: IAstNode;
begin
Result := FBody;
end;
function TBoundLambdaExpressionNode.GetParameters: TArray<IIdentifierNode>;
begin
Result := FParameters;
end;
{ TBoundFunctionCallNode }
constructor TBoundFunctionCallNode.Create(
const ASource: IFunctionCallNode;
const AUnboundNode: IFunctionCallNode;
const ACallee: IAstNode;
const AArguments: TArray<IAstNode>;
AIsTailCall: Boolean
);
begin
inherited Create;
FSource := ASource;
FCallee := ACallee;
FArguments := AArguments;
inherited Create(ACallee, AArguments);
FIsTailCall := AIsTailCall;
end;
function TBoundFunctionCallNode.Accept(const Visitor: IAstVisitor): TDataValue;
begin
Result := Visitor.VisitFunctionCall(Self);
end;
function TBoundFunctionCallNode.GetArguments: TArray<IAstNode>;
begin
Result := FArguments;
end;
function TBoundFunctionCallNode.GetCallee: IAstNode;
begin
Result := FCallee;
end;
{ TResolvedAddressComparer }
function TResolvedAddressComparer.Equals(const Left, Right: TResolvedAddress): Boolean;
begin
@@ -894,7 +773,7 @@ begin
address := TResolvedAddress.Create(akLocalOrParent, 0, slotIndex);
boundIdentifier := TBoundIdentifierNode.Create(Node.Identifier, address);
isBoxed := (FBoxedDeclarations <> nil) and FBoxedDeclarations.Contains(Node);
boundDecl := TBoundVariableDeclarationNode.Create(Node, boundIdentifier, initializer, isBoxed);
boundDecl := TBoundVariableDeclarationNode.Create(boundIdentifier, initializer, isBoxed);
Result := TDataValue.FromIntf<IVariableDeclarationNode>(boundDecl);
end;
+19
View File
@@ -10,6 +10,7 @@ uses
Myc.Data.Scalar,
Myc.Data.Value,
Myc.Ast.Nodes,
Myc.Ast.Types,
Myc.Ast.Scope;
type
@@ -67,8 +68,12 @@ type
// Common base class for AST nodes to reduce boilerplate.
TAstNode = class(TInterfacedObject, IAstNode)
private
FStaticType: IStaticType;
public
constructor Create;
function Accept(const Visitor: IAstVisitor): TDataValue; virtual; abstract;
property StaticType: IStaticType read FStaticType write FStaticType;
end;
TConstantNode = class(TAstNode, IConstantNode)
@@ -324,6 +329,14 @@ begin
if not (AValue.Kind in [vkScalar, vkText, vkVoid]) then
raise EArgumentException.Create('IConstantNode only supports Scalar, Text, and Void values.');
FValue := AValue;
case AValue.Kind of
vkScalar: StaticType := TTypes.FromScalarKind(AValue.AsScalar.Kind);
vkText: StaticType := TTypes.Text;
vkVoid: StaticType := TTypes.Void;
else
StaticType := TTypes.Unknown; // Should not happen due to validation above
end;
end;
function TConstantNode.Accept(const Visitor: IAstVisitor): TDataValue;
@@ -988,4 +1001,10 @@ begin
Result := TVariableDeclarationNode.Create(AIdentifier, AInitializer);
end;
constructor TAstNode.Create;
begin
inherited;
FStaticType := TTypes.Unknown;
end;
end.