Finished node immutability

This commit is contained in:
Michael Schimmel
2025-11-05 18:33:29 +01:00
parent 1f0eef7698
commit 5003cfd899
5 changed files with 71 additions and 80 deletions
+59 -42
View File
@@ -120,6 +120,8 @@ type
): IMemberAccessNode; static;
class function RecordLiteral(
const AFields: TArray<TRecordFieldLiteral>;
const AScalarDefinition: IScalarRecordDefinition = nil;
const AGenericDefinition: IGenericRecordDefinition = nil;
const AStaticType: IStaticType = nil
): IRecordLiteralNode; static;
class function CreateSeries(const ADefinition: String; const AStaticType: IStaticType = nil): ICreateSeriesNode; static;
@@ -133,6 +135,14 @@ type
end;
implementation
uses
System.Generics.Defaults;
type
// --- Concrete Class Definitions moved to implementation ---
// Common base class for AST nodes to reduce boilerplate.
TAstNode = class(TInterfacedObject, IAstNode)
private
@@ -186,38 +196,6 @@ type
property StaticType: IStaticType read GetStaticType;
end;
// TRecordLiteralNode is still needed in the interface
// for TGenericRecordLiteralNode
TRecordLiteralNode = class(TAstTypedNode, IRecordLiteralNode)
private
FFields: TArray<TRecordFieldLiteral>;
FDefinition: IScalarRecordDefinition;
function GetFields: TArray<TRecordFieldLiteral>;
function GetKind: TAstNodeKind; override;
public
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;
property Definition: IScalarRecordDefinition read FDefinition write FDefinition;
end;
TGenericRecordLiteralNode = class(TRecordLiteralNode, IRecordLiteralNode)
private
FGenericDefinition: IGenericRecordDefinition;
public
constructor Create(const AFields: TArray<TRecordFieldLiteral>; const AStaticType: IStaticType);
property GenericDefinition: IGenericRecordDefinition read FGenericDefinition write FGenericDefinition;
end;
implementation
uses
System.Generics.Defaults;
type
// --- Concrete Class Definitions moved to implementation ---
TLambdaExpressionNode = class(TAstTypedNode, ILambdaExpressionNode)
private
FParameters: TArray<IIdentifierNode>;
@@ -580,6 +558,31 @@ type
property Series: IIdentifierNode read FSeries;
end;
// TRecordLiteralNode is still needed in the interface
// for TGenericRecordLiteralNode
TRecordLiteralNode = class(TAstTypedNode, IRecordLiteralNode)
private
FFields: TArray<TRecordFieldLiteral>;
FScalarDefinition: IScalarRecordDefinition;
FGenericDefinition: IGenericRecordDefinition;
function GetFields: TArray<TRecordFieldLiteral>;
function GetGenericDefinition: IGenericRecordDefinition;
function GetKind: TAstNodeKind; override;
function GetScalarDefinition: IScalarRecordDefinition;
public
constructor Create(
const AFields: TArray<TRecordFieldLiteral>;
const AScalarDefinition: IScalarRecordDefinition;
const AGenericDefinition: IGenericRecordDefinition;
const AStaticType: IStaticType
);
function Accept(const Visitor: IAstVisitor): TDataValue; override;
function AsRecordLiteral: IRecordLiteralNode; override;
property Fields: TArray<TRecordFieldLiteral> read FFields;
property ScalarDefinition: IScalarRecordDefinition read GetScalarDefinition;
property GenericDefinition: IGenericRecordDefinition read GetGenericDefinition;
end;
TNopNode = class(TAstNode, INopNode)
private
function GetKind: TAstNodeKind; override;
@@ -882,14 +885,18 @@ begin
);
end;
class function TAst.RecordLiteral(const AFields: TArray<TRecordFieldLiteral>; const AStaticType: IStaticType = nil): IRecordLiteralNode;
class function TAst.RecordLiteral(
const AFields: TArray<TRecordFieldLiteral>;
const AScalarDefinition: IScalarRecordDefinition = nil;
const AGenericDefinition: IGenericRecordDefinition = nil;
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(
TRecordLiteralNode.Create(
AFields,
AScalarDefinition,
AGenericDefinition,
if AStaticType <> nil then AStaticType
else TTypes.Unknown
);
@@ -1870,10 +1877,17 @@ end;
{ TRecordLiteralNode }
constructor TRecordLiteralNode.Create(const AFields: TArray<TRecordFieldLiteral>; const AStaticType: IStaticType);
constructor TRecordLiteralNode.Create(
const AFields: TArray<TRecordFieldLiteral>;
const AScalarDefinition: IScalarRecordDefinition;
const AGenericDefinition: IGenericRecordDefinition;
const AStaticType: IStaticType
);
begin
inherited Create(AStaticType);
FFields := AFields;
FGenericDefinition := AGenericDefinition;
FScalarDefinition := AScalarDefinition;
end;
function TRecordLiteralNode.Accept(const Visitor: IAstVisitor): TDataValue;
@@ -1891,16 +1905,19 @@ begin
Result := FFields;
end;
function TRecordLiteralNode.GetGenericDefinition: IGenericRecordDefinition;
begin
Result := FGenericDefinition;
end;
function TRecordLiteralNode.GetKind: TAstNodeKind;
begin
Result := akRecordLiteral;
end;
{ TGenericRecordLiteralNode }
constructor TGenericRecordLiteralNode.Create(const AFields: TArray<TRecordFieldLiteral>; const AStaticType: IStaticType);
function TRecordLiteralNode.GetScalarDefinition: IScalarRecordDefinition;
begin
inherited Create(AFields, AStaticType);
Result := FScalarDefinition;
end;
{ TCreateSeriesNode }