AST refactoring

This commit is contained in:
Michael Schimmel
2025-08-29 10:01:03 +02:00
parent fa9328a183
commit d2c00c6033
4 changed files with 79 additions and 45 deletions
+1 -1
View File
@@ -312,7 +312,7 @@ begin
result := root.Accept(visitor); result := root.Accept(visitor);
sw.Stop; sw.Stop;
if not result.IsUndefined then if not result.IsVoid then
Memo1.Lines.Add(Format('Result: %s (calculated in %d ms)', [result.ToString, sw.ElapsedMilliseconds])) Memo1.Lines.Add(Format('Result: %s (calculated in %d ms)', [result.ToString, sw.ElapsedMilliseconds]))
else else
Memo1.Lines.Add(Format('<undefined result> (calculated in %d ms)', [sw.ElapsedMilliseconds])); Memo1.Lines.Add(Format('<undefined result> (calculated in %d ms)', [sw.ElapsedMilliseconds]));
+10 -12
View File
@@ -176,9 +176,9 @@ begin
if Assigned(Node.Initializer) then if Assigned(Node.Initializer) then
initValue := Node.Initializer.Accept(Self) initValue := Node.Initializer.Accept(Self)
else else
initValue := TAstValue.Undefined; initValue := TAstValue.Void;
FScope.SetValue(varName, initValue); FScope.SetValue(varName, initValue);
Result := TAstValue.Undefined; Result := TAstValue.Void;
end; end;
function TEvaluatorVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; function TEvaluatorVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue;
@@ -202,16 +202,13 @@ begin
calleeValue := Node.Callee.Accept(Self); calleeValue := Node.Callee.Accept(Self);
arguments := Node.Arguments; arguments := Node.Arguments;
if not calleeValue.IsClosure then if calleeValue.Kind <> avkClosure then
begin
raise EArgumentException.Create('Expression is not a callable closure.'); raise EArgumentException.Create('Expression is not a callable closure.');
end;
closure := calleeValue.AsClosure; closure := calleeValue.AsClosure;
if (arguments.Count <> Length(closure.Parameters)) then if (arguments.Count <> Length(closure.Parameters)) then
begin
raise EArgumentException.CreateFmt('Argument count mismatch: expected %d, got %d', [Length(closure.Parameters), arguments.Count]); raise EArgumentException.CreateFmt('Argument count mismatch: expected %d, got %d', [Length(closure.Parameters), arguments.Count]);
end;
callScope := T_ExecutionScope.Create(closure.ClosureScope); callScope := T_ExecutionScope.Create(closure.ClosureScope);
@@ -236,7 +233,10 @@ begin
leftValue := Node.Left.Accept(Self); leftValue := Node.Left.Accept(Self);
rightValue := Node.Right.Accept(Self); rightValue := Node.Right.Accept(Self);
if not leftValue.IsScalar or not rightValue.IsScalar then if leftValue.Kind <> rightValue.Kind then
raise ENotSupportedException.Create('Binary operations are only supported for compatible types.');
if leftValue.Kind <> avkScalar then
begin begin
raise ENotSupportedException.Create('Binary operations are only supported for scalar types.'); raise ENotSupportedException.Create('Binary operations are only supported for scalar types.');
end; end;
@@ -284,10 +284,8 @@ var
rightScalar: TScalar; rightScalar: TScalar;
begin begin
rightValue := Node.Right.Accept(Self); rightValue := Node.Right.Accept(Self);
if not rightValue.IsScalar then if rightValue.Kind <> avkScalar then
begin
raise ENotSupportedException.Create('Unary operations are only supported for scalar types.'); raise ENotSupportedException.Create('Unary operations are only supported for scalar types.');
end;
rightScalar := rightValue.AsScalar; rightScalar := rightValue.AsScalar;
@@ -321,7 +319,7 @@ var
expression: IExpressionNode; expression: IExpressionNode;
lastValue: TAstValue; lastValue: TAstValue;
begin begin
lastValue := TAstValue.Undefined; lastValue := TAstValue.Void;
for expression in Node.Expressions do for expression in Node.Expressions do
begin begin
lastValue := expression.Accept(Self); lastValue := expression.Accept(Self);
+58 -22
View File
@@ -20,7 +20,8 @@ type
function ToString: string; function ToString: string;
end; end;
TAstValueKind = (avkUndefined, avkScalar, avkClosure); // Added avkText to represent a string value.
TAstValueKind = (avkUndefined, avkScalar, avkClosure, avkText);
// --- Forward Declarations to break cycles --- // --- Forward Declarations to break cycles ---
IExecutionScope = interface; IExecutionScope = interface;
@@ -56,23 +57,21 @@ type
private private
FKind: TAstValueKind; FKind: TAstValueKind;
FScalar: TScalar; FScalar: TScalar;
FClosure: IEvaluatorClosure; FInterface: IInterface;
function GetKind: TAstValueKind; inline; function GetKind: TAstValueKind; inline;
function GetIsScalar: Boolean; inline; function GetIsVoid: Boolean; inline;
function GetIsClosure: Boolean; inline;
function GetIsUndefined: Boolean; inline;
public public
class operator Initialize(out Dest: TAstValue); class operator Initialize(out Dest: TAstValue);
class function Undefined: TAstValue; static; class function Void: TAstValue; static;
class function FromScalar(const AValue: TScalar): TAstValue; static; class function FromScalar(const AValue: TScalar): TAstValue; static;
class function FromClosure(const AValue: IEvaluatorClosure): TAstValue; static; class function FromClosure(const AValue: IEvaluatorClosure): TAstValue; static;
class function FromText(const AValue: String): TAstValue; static;
function AsScalar: TScalar; function AsScalar: TScalar;
function AsClosure: IEvaluatorClosure; function AsClosure: IEvaluatorClosure;
function AsText: String;
function ToString: String; function ToString: String;
property IsVoid: Boolean read GetIsVoid;
property Kind: TAstValueKind read GetKind; property Kind: TAstValueKind read GetKind;
property IsScalar: Boolean read GetIsScalar;
property IsClosure: Boolean read GetIsClosure;
property IsUndefined: Boolean read GetIsUndefined;
end; end;
IExecutionScope = interface(IInterface) IExecutionScope = interface(IInterface)
@@ -198,19 +197,51 @@ type
implementation implementation
uses
System.Classes;
type
// Private interface to encapsulate a string value for reference counting.
IAstTextValue = interface(IInterface)
function GetValue: string;
property Value: string read GetValue;
end;
// Implementation of the text value interface.
TAstTextValue = class(TInterfacedObject, IAstTextValue)
private
FValue: string;
function GetValue: string;
public
constructor Create(const AValue: string);
end;
{ TAstTextValue }
constructor TAstTextValue.Create(const AValue: string);
begin
inherited Create;
FValue := AValue;
end;
function TAstTextValue.GetValue: string;
begin
Result := FValue;
end;
{ TAstValue } { TAstValue }
class operator TAstValue.Initialize(out Dest: TAstValue); class operator TAstValue.Initialize(out Dest: TAstValue);
begin begin
Dest.FKind := avkUndefined; Dest.FKind := avkUndefined;
Dest.FClosure := nil; Dest.FInterface := nil;
end; end;
function TAstValue.AsClosure: IEvaluatorClosure; function TAstValue.AsClosure: IEvaluatorClosure;
begin begin
if (FKind <> avkClosure) then if (FKind <> avkClosure) then
raise EInvalidCast.Create('Cannot read value as a Closure.'); raise EInvalidCast.Create('Cannot read value as a Closure.');
Result := FClosure; Result := IEvaluatorClosure(FInterface);
end; end;
function TAstValue.AsScalar: TScalar; function TAstValue.AsScalar: TScalar;
@@ -220,10 +251,17 @@ begin
Result := FScalar; Result := FScalar;
end; end;
function TAstValue.AsText: String;
begin
if (FKind <> avkText) then
raise EInvalidCast.Create('Cannot read value as Text.');
Result := IAstTextValue(FInterface).Value;
end;
class function TAstValue.FromClosure(const AValue: IEvaluatorClosure): TAstValue; class function TAstValue.FromClosure(const AValue: IEvaluatorClosure): TAstValue;
begin begin
Result.FKind := avkClosure; Result.FKind := avkClosure;
Result.FClosure := AValue; Result.FInterface := AValue;
Result.FScalar := Default(TScalar); Result.FScalar := Default(TScalar);
end; end;
@@ -231,20 +269,17 @@ class function TAstValue.FromScalar(const AValue: TScalar): TAstValue;
begin begin
Result.FKind := avkScalar; Result.FKind := avkScalar;
Result.FScalar := AValue; Result.FScalar := AValue;
Result.FClosure := nil; Result.FInterface := nil;
end; end;
function TAstValue.GetIsClosure: Boolean; class function TAstValue.FromText(const AValue: String): TAstValue;
begin begin
Result := FKind = avkClosure; Result.FKind := avkText;
Result.FInterface := TAstTextValue.Create(AValue);
Result.FScalar := Default(TScalar);
end; end;
function TAstValue.GetIsScalar: Boolean; function TAstValue.GetIsVoid: Boolean;
begin
Result := FKind = avkScalar;
end;
function TAstValue.GetIsUndefined: Boolean;
begin begin
Result := FKind = avkUndefined; Result := FKind = avkUndefined;
end; end;
@@ -259,13 +294,14 @@ begin
case FKind of case FKind of
avkScalar: Result := FScalar.ToString; avkScalar: Result := FScalar.ToString;
avkClosure: Result := '<closure>'; avkClosure: Result := '<closure>';
avkText: Result := AsText;
avkUndefined: Result := '<void>'; avkUndefined: Result := '<void>';
else else
Result := '[Unknown AstValue]'; Result := '[Unknown AstValue]';
end; end;
end; end;
class function TAstValue.Undefined: TAstValue; class function TAstValue.Void: TAstValue;
begin begin
Result := Default(TAstValue); Result := Default(TAstValue);
end; end;
+10 -10
View File
@@ -80,13 +80,13 @@ end;
function TPrettyPrintVisitor.VisitConstant(const Node: IConstantNode): TAstValue; function TPrettyPrintVisitor.VisitConstant(const Node: IConstantNode): TAstValue;
begin begin
AppendLine(Format('Constant (%s)', [Node.Value.ToString])); AppendLine(Format('Constant (%s)', [Node.Value.ToString]));
Result := TAstValue.Undefined; Result := TAstValue.Void;
end; end;
function TPrettyPrintVisitor.VisitIdentifier(const Node: IIdentifierNode): TAstValue; function TPrettyPrintVisitor.VisitIdentifier(const Node: IIdentifierNode): TAstValue;
begin begin
AppendLine(Format('Identifier (%s)', [Node.Name])); AppendLine(Format('Identifier (%s)', [Node.Name]));
Result := TAstValue.Undefined; Result := TAstValue.Void;
end; end;
function TPrettyPrintVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; function TPrettyPrintVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue;
@@ -96,7 +96,7 @@ begin
Node.Left.Accept(Self); Node.Left.Accept(Self);
Node.Right.Accept(Self); Node.Right.Accept(Self);
Unindent; Unindent;
Result := TAstValue.Undefined; Result := TAstValue.Void;
end; end;
function TPrettyPrintVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; function TPrettyPrintVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue;
@@ -105,7 +105,7 @@ begin
Indent; Indent;
Node.Right.Accept(Self); Node.Right.Accept(Self);
Unindent; Unindent;
Result := TAstValue.Undefined; Result := TAstValue.Void;
end; end;
function TPrettyPrintVisitor.VisitIfExpression(const Node: IIfExpressionNode): TAstValue; function TPrettyPrintVisitor.VisitIfExpression(const Node: IIfExpressionNode): TAstValue;
@@ -125,7 +125,7 @@ begin
Node.ElseBranch.Accept(Self); Node.ElseBranch.Accept(Self);
Unindent; Unindent;
Unindent; Unindent;
Result := TAstValue.Undefined; Result := TAstValue.Void;
end; end;
function TPrettyPrintVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; function TPrettyPrintVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue;
@@ -148,7 +148,7 @@ begin
Node.Body.Accept(Self); Node.Body.Accept(Self);
Unindent; Unindent;
Unindent; Unindent;
Result := TAstValue.Undefined; Result := TAstValue.Void;
end; end;
function TPrettyPrintVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; function TPrettyPrintVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TAstValue;
@@ -167,7 +167,7 @@ begin
arg.Accept(Self); arg.Accept(Self);
Unindent; Unindent;
Unindent; Unindent;
Result := TAstValue.Undefined; Result := TAstValue.Void;
end; end;
function TPrettyPrintVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; function TPrettyPrintVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue;
@@ -179,7 +179,7 @@ begin
for expr in Node.Expressions do for expr in Node.Expressions do
expr.Accept(Self); expr.Accept(Self);
Unindent; Unindent;
Result := TAstValue.Undefined; Result := TAstValue.Void;
end; end;
function TPrettyPrintVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue; function TPrettyPrintVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue;
@@ -191,7 +191,7 @@ begin
Node.Initializer.Accept(Self); Node.Initializer.Accept(Self);
Unindent; Unindent;
end; end;
Result := TAstValue.Undefined; Result := TAstValue.Void;
end; end;
function TPrettyPrintVisitor.VisitAssignment(const Node: IAssignmentNode): TAstValue; function TPrettyPrintVisitor.VisitAssignment(const Node: IAssignmentNode): TAstValue;
@@ -201,7 +201,7 @@ begin
Indent; Indent;
Node.Value.Accept(Self); Node.Value.Accept(Self);
Unindent; Unindent;
Result := TAstValue.Undefined; Result := TAstValue.Void;
end; end;
end. end.