AST refactoring
This commit is contained in:
@@ -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]));
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user