AST development
This commit is contained in:
@@ -25,6 +25,7 @@ type
|
||||
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; virtual;
|
||||
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; virtual;
|
||||
function VisitIfExpression(const Node: IIfExpressionNode): TAstValue; virtual;
|
||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue; virtual;
|
||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; virtual;
|
||||
function VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; virtual;
|
||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; virtual;
|
||||
@@ -52,6 +53,7 @@ type
|
||||
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue; override;
|
||||
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue; override;
|
||||
function VisitIfExpression(const Node: IIfExpressionNode): TAstValue; override;
|
||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue; override;
|
||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue; override;
|
||||
function VisitFunctionCall(const Node: IFunctionCallNode): TAstValue; override;
|
||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue; override;
|
||||
@@ -170,15 +172,13 @@ end;
|
||||
function TEvaluatorVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue;
|
||||
var
|
||||
varName: string;
|
||||
initValue: TAstValue;
|
||||
begin
|
||||
varName := Node.Identifier.Name;
|
||||
if Assigned(Node.Initializer) then
|
||||
initValue := Node.Initializer.Accept(Self)
|
||||
Result := Node.Initializer.Accept(Self)
|
||||
else
|
||||
initValue := TAstValue.Void;
|
||||
FScope.SetValue(varName, initValue);
|
||||
Result := TAstValue.Void;
|
||||
Result := TAstValue.Void;
|
||||
FScope.SetValue(varName, Result);
|
||||
end;
|
||||
|
||||
function TEvaluatorVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue;
|
||||
@@ -210,7 +210,7 @@ begin
|
||||
if (arguments.Count <> Length(closure.Parameters)) then
|
||||
raise EArgumentException.CreateFmt('Argument count mismatch: expected %d, got %d', [Length(closure.Parameters), arguments.Count]);
|
||||
|
||||
callScope := T_ExecutionScope.Create(closure.ClosureScope);
|
||||
callScope := TExecutionScope.Create(closure.ClosureScope);
|
||||
|
||||
for i := 0 to arguments.Count - 1 do
|
||||
begin
|
||||
@@ -219,6 +219,13 @@ begin
|
||||
end;
|
||||
|
||||
innerVisitor := Self.CreateVisitorForScope(callScope);
|
||||
|
||||
// Introduce 'Result' variable for imperative-style assignments within the closure.
|
||||
callScope.SetValue('Result', TAstValue.Void);
|
||||
|
||||
// The return value of the function is the value of its body expression.
|
||||
// This supports both functional-style returns (direct value) and
|
||||
// imperative-style returns (via an assignment, which also returns the value).
|
||||
Result := closure.Body.Accept(innerVisitor);
|
||||
end;
|
||||
|
||||
@@ -314,6 +321,17 @@ begin
|
||||
Result := Node.ElseBranch.Accept(Self);
|
||||
end;
|
||||
|
||||
function TEvaluatorVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue;
|
||||
var
|
||||
conditionValue: TAstValue;
|
||||
begin
|
||||
conditionValue := Node.Condition.Accept(Self);
|
||||
if IsTruthy(conditionValue) then
|
||||
Result := Node.ThenBranch.Accept(Self)
|
||||
else
|
||||
Result := Node.ElseBranch.Accept(Self);
|
||||
end;
|
||||
|
||||
function TEvaluatorVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue;
|
||||
var
|
||||
expression: IExpressionNode;
|
||||
@@ -457,6 +475,18 @@ begin
|
||||
AppendLine(Format('} -> %s', [Result.ToString]));
|
||||
end;
|
||||
|
||||
function TDebugEvaluatorVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue;
|
||||
begin
|
||||
AppendLine('TernaryExpr{');
|
||||
Indent;
|
||||
try
|
||||
Result := inherited VisitTernaryExpression(Node);
|
||||
finally
|
||||
Unindent;
|
||||
end;
|
||||
AppendLine(Format('} -> %s', [Result.ToString]));
|
||||
end;
|
||||
|
||||
function TDebugEvaluatorVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue;
|
||||
begin
|
||||
AppendLine('LambdaExpr{');
|
||||
|
||||
+42
-24
@@ -33,6 +33,8 @@ type
|
||||
IBinaryExpressionNode = interface;
|
||||
IUnaryExpressionNode = interface;
|
||||
IIfExpressionNode = interface;
|
||||
// Added forward declaration for the new ternary expression node.
|
||||
ITernaryExpressionNode = interface;
|
||||
ILambdaExpressionNode = interface;
|
||||
IFunctionCallNode = interface;
|
||||
IBlockExpressionNode = interface;
|
||||
@@ -55,9 +57,25 @@ type
|
||||
|
||||
TAstValue = record
|
||||
private
|
||||
FKind: TAstValueKind;
|
||||
FScalar: TScalar;
|
||||
FInterface: IInterface;
|
||||
type
|
||||
IVal<T> = interface
|
||||
['{70210CAF-0857-4BF1-8254-B8239A155A02}']
|
||||
function GetValue: T;
|
||||
property Value: T read GetValue;
|
||||
end;
|
||||
|
||||
TVal<T> = class(TInterfacedObject, IVal<T>)
|
||||
private
|
||||
FValue: T;
|
||||
function GetValue: T;
|
||||
public
|
||||
constructor Create(const AValue: T);
|
||||
end;
|
||||
|
||||
var
|
||||
FKind: TAstValueKind;
|
||||
FScalar: TScalar;
|
||||
FInterface: IInterface;
|
||||
function GetKind: TAstValueKind; inline;
|
||||
function GetIsVoid: Boolean; inline;
|
||||
public
|
||||
@@ -93,6 +111,8 @@ type
|
||||
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue;
|
||||
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue;
|
||||
function VisitIfExpression(const Node: IIfExpressionNode): TAstValue;
|
||||
// Added visitor method for the new ternary expression node.
|
||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue;
|
||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue;
|
||||
function VisitFunctionCall(const Node: IFunctionCallNode): TAstValue;
|
||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue;
|
||||
@@ -141,6 +161,7 @@ type
|
||||
property Right: IExpressionNode read GetRight;
|
||||
end;
|
||||
|
||||
// Represents an if-statement for control flow.
|
||||
IIfExpressionNode = interface(IExpressionNode)
|
||||
{$region 'private'}
|
||||
function GetCondition: IExpressionNode;
|
||||
@@ -152,6 +173,18 @@ type
|
||||
property ElseBranch: IExpressionNode read GetElseBranch;
|
||||
end;
|
||||
|
||||
// Represents a ternary expression (e.g., condition ? true_expr : false_expr) for value selection.
|
||||
ITernaryExpressionNode = interface(IExpressionNode)
|
||||
{$region 'private'}
|
||||
function GetCondition: IExpressionNode;
|
||||
function GetThenBranch: IExpressionNode;
|
||||
function GetElseBranch: IExpressionNode;
|
||||
{$endregion}
|
||||
property Condition: IExpressionNode read GetCondition;
|
||||
property ThenBranch: IExpressionNode read GetThenBranch;
|
||||
property ElseBranch: IExpressionNode read GetElseBranch;
|
||||
end;
|
||||
|
||||
ILambdaExpressionNode = interface(IExpressionNode)
|
||||
{$region 'private'}
|
||||
function GetParameters: TArray<IIdentifierNode>;
|
||||
@@ -200,31 +233,15 @@ implementation
|
||||
uses
|
||||
System.Classes;
|
||||
|
||||
type
|
||||
// Private interface to encapsulate a non scalar value for reference counting.
|
||||
IAstValue<T> = interface
|
||||
function GetValue: string;
|
||||
property Value: string read GetValue;
|
||||
end;
|
||||
|
||||
// Implementation of the text value interface.
|
||||
TAstValue<T> = class(TInterfacedObject, IAstValue<T>)
|
||||
private
|
||||
FValue: string;
|
||||
function GetValue: string;
|
||||
public
|
||||
constructor Create(const AValue: string);
|
||||
end;
|
||||
|
||||
{ TAstValue }
|
||||
|
||||
constructor TAstValue<T>.Create(const AValue: string);
|
||||
constructor TAstValue.TVal<T>.Create(const AValue: T);
|
||||
begin
|
||||
inherited Create;
|
||||
FValue := AValue;
|
||||
end;
|
||||
|
||||
function TAstValue<T>.GetValue: string;
|
||||
function TAstValue.TVal<T>.GetValue: T;
|
||||
begin
|
||||
Result := FValue;
|
||||
end;
|
||||
@@ -255,7 +272,8 @@ function TAstValue.AsText: String;
|
||||
begin
|
||||
if (FKind <> avkText) then
|
||||
raise EInvalidCast.Create('Cannot read value as Text.');
|
||||
Result := IAstValue<String>(FInterface).Value;
|
||||
|
||||
Result := (FInterface as IVal<String>).Value;
|
||||
end;
|
||||
|
||||
class function TAstValue.FromClosure(const AValue: IEvaluatorClosure): TAstValue;
|
||||
@@ -275,7 +293,7 @@ end;
|
||||
class function TAstValue.FromText(const AValue: String): TAstValue;
|
||||
begin
|
||||
Result.FKind := avkText;
|
||||
Result.FInterface := TAstValue<String>.Create(AValue);
|
||||
Result.FInterface := TVal<String>.Create(AValue);
|
||||
Result.FScalar := Default(TScalar);
|
||||
end;
|
||||
|
||||
@@ -313,7 +331,7 @@ begin
|
||||
case Self of
|
||||
boAdd: Result := '+';
|
||||
boSubtract: Result := '-';
|
||||
boMultiply: Result := #$2A2F;
|
||||
boMultiply: Result := '*';
|
||||
boDivide: Result := '/';
|
||||
boEqual: Result := '==';
|
||||
boNotEqual: Result := '!=';
|
||||
|
||||
@@ -27,6 +27,7 @@ type
|
||||
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue;
|
||||
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue;
|
||||
function VisitIfExpression(const Node: IIfExpressionNode): TAstValue;
|
||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue;
|
||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue;
|
||||
function VisitFunctionCall(const Node: IFunctionCallNode): TAstValue;
|
||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue;
|
||||
@@ -128,6 +129,26 @@ begin
|
||||
Result := TAstValue.Void;
|
||||
end;
|
||||
|
||||
function TPrettyPrintVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue;
|
||||
begin
|
||||
AppendLine('TernaryExpr');
|
||||
Indent;
|
||||
AppendLine('Condition:');
|
||||
Indent;
|
||||
Node.Condition.Accept(Self);
|
||||
Unindent;
|
||||
AppendLine('Then:');
|
||||
Indent;
|
||||
Node.ThenBranch.Accept(Self);
|
||||
Unindent;
|
||||
AppendLine('Else:');
|
||||
Indent;
|
||||
Node.ElseBranch.Accept(Self);
|
||||
Unindent;
|
||||
Unindent;
|
||||
Result := TAstValue.Void;
|
||||
end;
|
||||
|
||||
function TPrettyPrintVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue;
|
||||
var
|
||||
param: IIdentifierNode;
|
||||
|
||||
+12
-12
@@ -9,7 +9,7 @@ uses
|
||||
Myc.Ast.Nodes;
|
||||
|
||||
type
|
||||
T_ExecutionScope = class(TInterfacedObject, IExecutionScope)
|
||||
TExecutionScope = class(TInterfacedObject, IExecutionScope)
|
||||
private
|
||||
FParent: IExecutionScope;
|
||||
FVariables: TDictionary<string, TAstValue>;
|
||||
@@ -29,27 +29,27 @@ type
|
||||
|
||||
implementation
|
||||
|
||||
{ T_ExecutionScope }
|
||||
{ TExecutionScope }
|
||||
|
||||
constructor T_ExecutionScope.Create(AParent: IExecutionScope);
|
||||
constructor TExecutionScope.Create(AParent: IExecutionScope);
|
||||
begin
|
||||
inherited Create;
|
||||
FParent := AParent;
|
||||
FVariables := TDictionary<string, TAstValue>.Create;
|
||||
end;
|
||||
|
||||
destructor T_ExecutionScope.Destroy;
|
||||
destructor TExecutionScope.Destroy;
|
||||
begin
|
||||
FVariables.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function T_ExecutionScope.GetParent: IExecutionScope;
|
||||
function TExecutionScope.GetParent: IExecutionScope;
|
||||
begin
|
||||
Result := FParent;
|
||||
end;
|
||||
|
||||
procedure T_ExecutionScope.AssignValue(const Name: string; const Value: TAstValue);
|
||||
procedure TExecutionScope.AssignValue(const Name: string; const Value: TAstValue);
|
||||
begin
|
||||
if FVariables.ContainsKey(Name) then
|
||||
FVariables.AddOrSetValue(Name, Value)
|
||||
@@ -59,14 +59,14 @@ begin
|
||||
raise Exception.CreateFmt('Cannot assign to undeclared variable "%s".', [Name]);
|
||||
end;
|
||||
|
||||
procedure T_ExecutionScope.Clear;
|
||||
procedure TExecutionScope.Clear;
|
||||
begin
|
||||
FVariables.Clear;
|
||||
if Assigned(FParent) then
|
||||
FParent.Clear;
|
||||
end;
|
||||
|
||||
procedure T_ExecutionScope.DumpScope(const ABuilder: TStringBuilder; AIndent: Integer);
|
||||
procedure TExecutionScope.DumpScope(const ABuilder: TStringBuilder; AIndent: Integer);
|
||||
var
|
||||
pair: TPair<string, TAstValue>;
|
||||
indentStr: string;
|
||||
@@ -88,11 +88,11 @@ begin
|
||||
// As FParent is now an interface, we must cast it back to the class to call the private DumpScope.
|
||||
// This indicates that DumpScope should perhaps be part of the interface or handled differently.
|
||||
// For now, we use a cast to keep the functionality.
|
||||
(FParent as T_ExecutionScope).DumpScope(ABuilder, AIndent + 2);
|
||||
(FParent as TExecutionScope).DumpScope(ABuilder, AIndent + 2);
|
||||
end;
|
||||
end;
|
||||
|
||||
function T_ExecutionScope.Dump: string;
|
||||
function TExecutionScope.Dump: string;
|
||||
var
|
||||
builder: TStringBuilder;
|
||||
begin
|
||||
@@ -106,7 +106,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function T_ExecutionScope.FindValue(const Name: string; out Value: TAstValue): Boolean;
|
||||
function TExecutionScope.FindValue(const Name: string; out Value: TAstValue): Boolean;
|
||||
begin
|
||||
Result := FVariables.TryGetValue(Name, Value);
|
||||
if not Result and Assigned(FParent) then
|
||||
@@ -115,7 +115,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure T_ExecutionScope.SetValue(const Name: string; const Value: TAstValue);
|
||||
procedure TExecutionScope.SetValue(const Name: string; const Value: TAstValue);
|
||||
begin
|
||||
FVariables.AddOrSetValue(Name, Value);
|
||||
end;
|
||||
|
||||
@@ -22,11 +22,17 @@ type
|
||||
const ACondition: IExpressionNode;
|
||||
const AThenBranch, AElseBranch: IExpressionNode
|
||||
): IIfExpressionNode; static;
|
||||
// Added factory function for the new ternary expression node.
|
||||
class function TernaryExpr(
|
||||
const ACondition: IExpressionNode;
|
||||
const AThenBranch, AElseBranch: IExpressionNode
|
||||
): ITernaryExpressionNode; static;
|
||||
class function LambdaExpr(const AParameters: TArray<IIdentifierNode>; const ABody: IExpressionNode): ILambdaExpressionNode; static;
|
||||
class function FunctionCall(const ACallee: IExpressionNode; const AArguments: array of IExpressionNode): IFunctionCallNode; static;
|
||||
class function Block(const AExpressions: array of IExpressionNode): IBlockExpressionNode; static;
|
||||
class function VarDecl(const AIdentifier: IIdentifierNode; AInitializer: IExpressionNode): IVariableDeclarationNode; static;
|
||||
class function Assign(const AIdentifier: IIdentifierNode; const AValue: IExpressionNode): IAssignmentNode; static;
|
||||
class function AssignResult(const AValue: IExpressionNode): IAssignmentNode; static;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@@ -103,6 +109,20 @@ type
|
||||
function Accept(const Visitor: IAstVisitor): TAstValue; override;
|
||||
end;
|
||||
|
||||
{ TTernaryExpressionNode }
|
||||
TTernaryExpressionNode = class(TAstNode, ITernaryExpressionNode)
|
||||
private
|
||||
FCondition: IExpressionNode;
|
||||
FThenBranch: IExpressionNode;
|
||||
FElseBranch: IExpressionNode;
|
||||
function GetCondition: IExpressionNode;
|
||||
function GetThenBranch: IExpressionNode;
|
||||
function GetElseBranch: IExpressionNode;
|
||||
public
|
||||
constructor Create(const ACondition, AThenBranch, AElseBranch: IExpressionNode);
|
||||
function Accept(const Visitor: IAstVisitor): TAstValue; override;
|
||||
end;
|
||||
|
||||
{ TLambdaExpressionNode }
|
||||
TLambdaExpressionNode = class(TAstNode, ILambdaExpressionNode)
|
||||
private
|
||||
@@ -283,6 +303,36 @@ begin
|
||||
Result := FThenBranch;
|
||||
end;
|
||||
|
||||
{ TTernaryExpressionNode }
|
||||
|
||||
constructor TTernaryExpressionNode.Create(const ACondition, AThenBranch, AElseBranch: IExpressionNode);
|
||||
begin
|
||||
inherited Create;
|
||||
FCondition := ACondition;
|
||||
FThenBranch := AThenBranch;
|
||||
FElseBranch := AElseBranch;
|
||||
end;
|
||||
|
||||
function TTernaryExpressionNode.Accept(const Visitor: IAstVisitor): TAstValue;
|
||||
begin
|
||||
Result := Visitor.VisitTernaryExpression(Self);
|
||||
end;
|
||||
|
||||
function TTernaryExpressionNode.GetCondition: IExpressionNode;
|
||||
begin
|
||||
Result := FCondition;
|
||||
end;
|
||||
|
||||
function TTernaryExpressionNode.GetElseBranch: IExpressionNode;
|
||||
begin
|
||||
Result := FElseBranch;
|
||||
end;
|
||||
|
||||
function TTernaryExpressionNode.GetThenBranch: IExpressionNode;
|
||||
begin
|
||||
Result := FThenBranch;
|
||||
end;
|
||||
|
||||
{ TLambdaExpressionNode }
|
||||
|
||||
constructor TLambdaExpressionNode.Create(const AParameters: TArray<IIdentifierNode>; const ABody: IExpressionNode);
|
||||
@@ -424,6 +474,11 @@ begin
|
||||
Result := TAssignmentNode.Create(AIdentifier, AValue);
|
||||
end;
|
||||
|
||||
class function TAst.AssignResult(const AValue: IExpressionNode): IAssignmentNode;
|
||||
begin
|
||||
Result := Assign(TAst.Identifier('Result'), AValue);
|
||||
end;
|
||||
|
||||
class function TAst.Block(const AExpressions: array of IExpressionNode): IBlockExpressionNode;
|
||||
begin
|
||||
Result := TBlockExpressionNode.Create(AExpressions);
|
||||
@@ -454,6 +509,11 @@ begin
|
||||
Result := TIfExpressionNode.Create(ACondition, AThenBranch, AElseBranch);
|
||||
end;
|
||||
|
||||
class function TAst.TernaryExpr(const ACondition, AThenBranch, AElseBranch: IExpressionNode): ITernaryExpressionNode;
|
||||
begin
|
||||
Result := TTernaryExpressionNode.Create(ACondition, AThenBranch, AElseBranch);
|
||||
end;
|
||||
|
||||
class function TAst.LambdaExpr(const AParameters: TArray<IIdentifierNode>; const ABody: IExpressionNode): ILambdaExpressionNode;
|
||||
begin
|
||||
Result := TLambdaExpressionNode.Create(AParameters, ABody);
|
||||
|
||||
Reference in New Issue
Block a user