Refactoring for immutable nodes
This commit is contained in:
+158
-115
@@ -33,7 +33,7 @@ type
|
||||
class function Nop: IAstNode; static;
|
||||
|
||||
// --- Factory functions ---
|
||||
class function Constant(const AValue: TDataValue): IConstantNode; overload; static;
|
||||
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;
|
||||
@@ -71,13 +71,18 @@ type
|
||||
): IAddSeriesItemNode; static;
|
||||
class function SeriesLength(const ASeries: IIdentifierNode): ISeriesLengthNode; static;
|
||||
|
||||
class function BoundIdentifier(AName: string; const Address: TResolvedAddress): IBoundIdentifierNode; static;
|
||||
class function BoundIdentifier(
|
||||
AName: string;
|
||||
const Address: TResolvedAddress;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IBoundIdentifierNode; static;
|
||||
end;
|
||||
|
||||
// Common base class for AST nodes to reduce boilerplate.
|
||||
TAstNode = class(TInterfacedObject, IAstNode)
|
||||
private
|
||||
function GetKind: TAstNodeKind; virtual; abstract;
|
||||
function GetIsTyped: Boolean; virtual;
|
||||
public
|
||||
constructor Create;
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; virtual; abstract;
|
||||
@@ -112,6 +117,7 @@ type
|
||||
function AsBoundIdentifierNode: IBoundIdentifierNode; virtual;
|
||||
function AsTypedNode: IAstTypedNode; virtual;
|
||||
|
||||
property IsTyped: Boolean read GetIsTyped;
|
||||
property Kind: TAstNodeKind read GetKind;
|
||||
end;
|
||||
|
||||
@@ -119,59 +125,13 @@ type
|
||||
private
|
||||
FStaticType: IStaticType;
|
||||
function GetStaticType: IStaticType;
|
||||
function GetIsTyped: Boolean; override;
|
||||
public
|
||||
constructor Create(const AStaticType: IStaticType);
|
||||
function AsTypedNode: IAstTypedNode; override;
|
||||
property StaticType: IStaticType read GetStaticType;
|
||||
end;
|
||||
|
||||
TConstantNode = class(TAstTypedNode, IConstantNode)
|
||||
private
|
||||
FValue: TDataValue;
|
||||
function GetValue: TDataValue;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AValue: TDataValue; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsConstant: IConstantNode; override;
|
||||
property Value: TDataValue read GetValue; // Value ist immutable
|
||||
end;
|
||||
|
||||
TIdentifierNode = class(TAstTypedNode, IIdentifierNode)
|
||||
private
|
||||
FName: string;
|
||||
function GetName: string;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AName: string; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsIdentifier: IIdentifierNode; override;
|
||||
property Name: string read FName; // Name ist immutable
|
||||
end;
|
||||
|
||||
TBoundIdentifierNode = class(TIdentifierNode, IBoundIdentifierNode)
|
||||
private
|
||||
FAddress: TResolvedAddress;
|
||||
function GetAddress: TResolvedAddress;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AName: string; const AAddress: TResolvedAddress; const AStaticType: IStaticType);
|
||||
function AsBoundIdentifierNode: IBoundIdentifierNode; override;
|
||||
property Address: TResolvedAddress read GetAddress;
|
||||
end;
|
||||
|
||||
TKeywordNode = class(TAstTypedNode, IKeywordNode)
|
||||
private
|
||||
FValue: IKeyword;
|
||||
function GetValue: IKeyword;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AValue: IKeyword);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsKeyword: IKeywordNode; override;
|
||||
property Value: IKeyword read FValue; // Value ist immutable
|
||||
end;
|
||||
|
||||
TBinaryExpressionNode = class(TAstTypedNode, IBinaryExpressionNode)
|
||||
private
|
||||
FLeft: IAstNode;
|
||||
@@ -263,60 +223,6 @@ type
|
||||
property HasNestedLambdas: Boolean read FHasNestedLambdas write FHasNestedLambdas;
|
||||
end;
|
||||
|
||||
TMacroDefinitionNode = class(TAstNode, IMacroDefinitionNode)
|
||||
private
|
||||
FName: IIdentifierNode;
|
||||
FParameters: TArray<IIdentifierNode>;
|
||||
FBody: IAstNode;
|
||||
function GetName: IIdentifierNode;
|
||||
function GetParameters: TArray<IIdentifierNode>;
|
||||
function GetBody: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AName: IIdentifierNode; const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsMacroDefinition: IMacroDefinitionNode; override;
|
||||
property Name: IIdentifierNode read GetName;
|
||||
property Parameters: TArray<IIdentifierNode> read FParameters;
|
||||
property Body: IAstNode read FBody;
|
||||
end;
|
||||
|
||||
TQuasiquoteNode = class(TAstNode, IQuasiquoteNode)
|
||||
private
|
||||
FExpression: IAstNode;
|
||||
function GetExpression: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AExpression: IAstNode);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsQuasiquote: IQuasiquoteNode; override;
|
||||
property Expression: IAstNode read GetExpression;
|
||||
end;
|
||||
|
||||
TUnquoteNode = class(TAstNode, IUnquoteNode)
|
||||
private
|
||||
FExpression: IAstNode;
|
||||
function GetExpression: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AExpression: IAstNode);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsUnquote: IUnquoteNode; override;
|
||||
property Expression: IAstNode read GetExpression;
|
||||
end;
|
||||
|
||||
TUnquoteSplicingNode = class(TAstNode, IUnquoteSplicingNode)
|
||||
private
|
||||
FExpression: IQuasiquoteNode;
|
||||
function GetExpression: IQuasiquoteNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AExpression: IQuasiquoteNode);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsUnquoteSplicing: IUnquoteSplicingNode; override;
|
||||
property Expression: IQuasiquoteNode read GetExpression;
|
||||
end;
|
||||
|
||||
TFunctionCallNode = class(TAstTypedNode, IFunctionCallNode)
|
||||
private
|
||||
FCallee: IAstNode;
|
||||
@@ -349,16 +255,16 @@ type
|
||||
TMacroExpansionNode = class(TAstTypedNode, IMacroExpansionNode)
|
||||
private
|
||||
FCallNode: IFunctionCallNode;
|
||||
FExpandedBody: IAstNode;
|
||||
FExpandedBody: IAstTypedNode;
|
||||
function GetCallNode: IFunctionCallNode;
|
||||
function GetExpandedBody: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const ACallNode: IFunctionCallNode; const AExpandedBody: IAstNode; const AStaticType: IStaticType);
|
||||
constructor Create(const ACallNode: IFunctionCallNode; const AExpandedBody: IAstTypedNode);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsMacroExpansion: IMacroExpansionNode; override;
|
||||
property CallNode: IFunctionCallNode read GetCallNode;
|
||||
property ExpandedBody: IAstNode read FExpandedBody;
|
||||
property ExpandedBody: IAstTypedNode read FExpandedBody;
|
||||
end;
|
||||
|
||||
TBlockExpressionNode = class(TAstTypedNode, IBlockExpressionNode)
|
||||
@@ -508,8 +414,108 @@ implementation
|
||||
uses
|
||||
System.Generics.Defaults;
|
||||
|
||||
// Added Nop
|
||||
type
|
||||
TConstantNode = class(TAstTypedNode, IConstantNode)
|
||||
private
|
||||
FValue: TDataValue;
|
||||
function GetValue: TDataValue;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AValue: TDataValue; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsConstant: IConstantNode; override;
|
||||
property Value: TDataValue read GetValue;
|
||||
end;
|
||||
|
||||
TIdentifierNode = class(TAstTypedNode, IIdentifierNode)
|
||||
private
|
||||
FName: string;
|
||||
function GetName: string;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AName: string; const AStaticType: IStaticType);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsIdentifier: IIdentifierNode; override;
|
||||
property Name: string read FName;
|
||||
end;
|
||||
|
||||
TBoundIdentifierNode = class(TIdentifierNode, IBoundIdentifierNode)
|
||||
private
|
||||
FAddress: TResolvedAddress;
|
||||
function GetAddress: TResolvedAddress;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AName: string; const AAddress: TResolvedAddress; const AStaticType: IStaticType);
|
||||
function AsBoundIdentifierNode: IBoundIdentifierNode; override;
|
||||
property Address: TResolvedAddress read GetAddress;
|
||||
end;
|
||||
|
||||
TKeywordNode = class(TAstTypedNode, IKeywordNode)
|
||||
private
|
||||
FValue: IKeyword;
|
||||
function GetValue: IKeyword;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AValue: IKeyword);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsKeyword: IKeywordNode; override;
|
||||
property Value: IKeyword read FValue; // Value ist immutable
|
||||
end;
|
||||
|
||||
TMacroDefinitionNode = class(TAstNode, IMacroDefinitionNode)
|
||||
private
|
||||
FName: IIdentifierNode;
|
||||
FParameters: TArray<IIdentifierNode>;
|
||||
FBody: IAstNode;
|
||||
function GetName: IIdentifierNode;
|
||||
function GetParameters: TArray<IIdentifierNode>;
|
||||
function GetBody: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AName: IIdentifierNode; const AParameters: TArray<IIdentifierNode>; const ABody: IAstNode);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsMacroDefinition: IMacroDefinitionNode; override;
|
||||
property Name: IIdentifierNode read GetName;
|
||||
property Parameters: TArray<IIdentifierNode> read FParameters;
|
||||
property Body: IAstNode read FBody;
|
||||
end;
|
||||
|
||||
TQuasiquoteNode = class(TAstNode, IQuasiquoteNode)
|
||||
private
|
||||
FExpression: IAstNode;
|
||||
function GetExpression: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AExpression: IAstNode);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsQuasiquote: IQuasiquoteNode; override;
|
||||
property Expression: IAstNode read GetExpression;
|
||||
end;
|
||||
|
||||
TUnquoteNode = class(TAstNode, IUnquoteNode)
|
||||
private
|
||||
FExpression: IAstNode;
|
||||
function GetExpression: IAstNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AExpression: IAstNode);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsUnquote: IUnquoteNode; override;
|
||||
property Expression: IAstNode read GetExpression;
|
||||
end;
|
||||
|
||||
TUnquoteSplicingNode = class(TAstNode, IUnquoteSplicingNode)
|
||||
private
|
||||
FExpression: IQuasiquoteNode;
|
||||
function GetExpression: IQuasiquoteNode;
|
||||
function GetKind: TAstNodeKind; override;
|
||||
public
|
||||
constructor Create(const AExpression: IQuasiquoteNode);
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||
function AsUnquoteSplicing: IUnquoteSplicingNode; override;
|
||||
property Expression: IQuasiquoteNode read GetExpression;
|
||||
end;
|
||||
|
||||
TNopNode = class(TAstNode, INopNode)
|
||||
private
|
||||
function GetKind: TAstNodeKind; override;
|
||||
@@ -574,14 +580,28 @@ begin
|
||||
Result := TBlockExpressionNode.Create(AExpressions, TTypes.Unknown);
|
||||
end;
|
||||
|
||||
class function TAst.Constant(const AValue: TDataValue): IConstantNode;
|
||||
class function TAst.Constant(const AValue: TDataValue; const AStaticType: IStaticType = nil): IConstantNode;
|
||||
begin
|
||||
Result := TConstantNode.Create(AValue, TTypes.Unknown);
|
||||
var constType := AStaticType;
|
||||
|
||||
if constType = nil then
|
||||
begin
|
||||
case AValue.Kind of
|
||||
TDataValueKind.vkScalar: constType := TTypes.FromScalarKind(AValue.AsScalar.Kind);
|
||||
TDataValueKind.vkText: constType := TTypes.Text;
|
||||
TDataValueKind.vkVoid: constType := TTypes.Void;
|
||||
else
|
||||
constType := TTypes.Unknown;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Create a new node with the correct type
|
||||
Result := TConstantNode.Create(AValue, constType);
|
||||
end;
|
||||
|
||||
class function TAst.Constant(const AValue: String): IConstantNode;
|
||||
begin
|
||||
Result := TConstantNode.Create(AValue, TTypes.Unknown);
|
||||
Result := TConstantNode.Create(AValue, TTypes.Text);
|
||||
end;
|
||||
|
||||
class constructor TAst.Create;
|
||||
@@ -594,9 +614,19 @@ begin
|
||||
FLibraries.Free;
|
||||
end;
|
||||
|
||||
class function TAst.BoundIdentifier(AName: string; const Address: TResolvedAddress): IBoundIdentifierNode;
|
||||
class function TAst.BoundIdentifier(
|
||||
AName: string;
|
||||
const Address: TResolvedAddress;
|
||||
const AStaticType: IStaticType = nil
|
||||
): IBoundIdentifierNode;
|
||||
begin
|
||||
Result := TBoundIdentifierNode.Create(AName, Address, TTypes.Unknown);
|
||||
Result :=
|
||||
TBoundIdentifierNode.Create(
|
||||
AName,
|
||||
Address,
|
||||
if AStaticType <> nil then AStaticType
|
||||
else TTypes.Unknown
|
||||
);
|
||||
end;
|
||||
|
||||
class procedure TAst.RegisterLibrary(const AProc: TRegisterLibraryProc);
|
||||
@@ -645,7 +675,10 @@ end;
|
||||
|
||||
class function TAst.MacroExpansionNode(const AOriginalCallNode: IFunctionCallNode; const AExpandedBody: IAstNode): IMacroExpansionNode;
|
||||
begin
|
||||
Result := TMacroExpansionNode.Create(AOriginalCallNode, AExpandedBody, TTypes.Unknown);
|
||||
if AExpandedBody.IsTyped then
|
||||
Result := TMacroExpansionNode.Create(AOriginalCallNode, AExpandedBody.AsTypedNode)
|
||||
else
|
||||
Result := TMacroExpansionNode.Create(AOriginalCallNode, Block([]));
|
||||
end;
|
||||
|
||||
class function TAst.MemberAccess(const ABase: IAstNode; const AMember: IKeywordNode): IMemberAccessNode;
|
||||
@@ -871,6 +904,11 @@ begin
|
||||
raise ETypeException.Create('Node is not a VariableDeclaration');
|
||||
end;
|
||||
|
||||
function TAstNode.GetIsTyped: Boolean;
|
||||
begin
|
||||
Result := false;
|
||||
end;
|
||||
|
||||
{ TAstTypedNode }
|
||||
|
||||
constructor TAstTypedNode.Create(const AStaticType: IStaticType);
|
||||
@@ -885,6 +923,11 @@ begin
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
function TAstTypedNode.GetIsTyped: Boolean;
|
||||
begin
|
||||
Result := true;
|
||||
end;
|
||||
|
||||
function TAstTypedNode.GetStaticType: IStaticType;
|
||||
begin
|
||||
Result := FStaticType;
|
||||
@@ -1334,10 +1377,10 @@ end;
|
||||
|
||||
{ TMacroExpansionNode }
|
||||
|
||||
constructor TMacroExpansionNode.Create(const ACallNode: IFunctionCallNode; const AExpandedBody: IAstNode; const AStaticType: IStaticType);
|
||||
constructor TMacroExpansionNode.Create(const ACallNode: IFunctionCallNode; const AExpandedBody: IAstTypedNode);
|
||||
begin
|
||||
// Copy properties from the original call node
|
||||
inherited Create(AStaticType);
|
||||
inherited Create(AExpandedBody.StaticType);
|
||||
FExpandedBody := AExpandedBody;
|
||||
FCallNode := ACallNode;
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user