AST development

This commit is contained in:
Michael Schimmel
2025-09-01 19:24:22 +02:00
parent 3b3d94291d
commit 375e64411b
8 changed files with 864 additions and 297 deletions
+42 -24
View File
@@ -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 := '!=';