AST refactoring
This commit is contained in:
+129
-1
@@ -34,7 +34,15 @@ type
|
||||
RecursionButton: TButton;
|
||||
ShowScopeBox: TCheckBox;
|
||||
FibonacciButton: TButton;
|
||||
CrerateTriggerExampleButton: TButton;
|
||||
DoTriggerButton: TButton;
|
||||
DoTrigger2Button: TButton;
|
||||
procedure FormDestroy(Sender: TObject);
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure CrerateTriggerExampleButtonClick(Sender: TObject);
|
||||
procedure DebugButtonClick(Sender: TObject);
|
||||
procedure DoTrigger2ButtonClick(Sender: TObject);
|
||||
procedure DoTriggerButtonClick(Sender: TObject);
|
||||
procedure FibonacciButtonClick(Sender: TObject);
|
||||
procedure PrettyPrintButtonClick(Sender: TObject);
|
||||
procedure RecursionButtonClick(Sender: TObject);
|
||||
@@ -43,6 +51,7 @@ type
|
||||
private
|
||||
// Stores the last AST generated by Test1 or Test2 button clicks.
|
||||
FLastAst: IAstNode;
|
||||
FGScope: TExecutionScope;
|
||||
public
|
||||
{ Public declarations }
|
||||
end;
|
||||
@@ -57,6 +66,16 @@ uses
|
||||
|
||||
{$R *.fmx}
|
||||
|
||||
procedure TForm1.FormDestroy(Sender: TObject);
|
||||
begin
|
||||
FGScope.Free;
|
||||
end;
|
||||
|
||||
procedure TForm1.FormCreate(Sender: TObject);
|
||||
begin
|
||||
FGScope := TExecutionScope.Create(nil);
|
||||
end;
|
||||
|
||||
procedure TForm1.DebugButtonClick(Sender: TObject);
|
||||
var
|
||||
scope: TExecutionScope;
|
||||
@@ -71,7 +90,7 @@ begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
scope := TExecutionScope.Create(nil);
|
||||
scope := TExecutionScope.Create(FGScope);
|
||||
try
|
||||
Memo1.Lines.Clear;
|
||||
Memo1.Lines.Add('--- Debug Evaluator Trace ---');
|
||||
@@ -113,6 +132,8 @@ var
|
||||
result20, result30, result40: Int64;
|
||||
time20, time30, time40: Int64;
|
||||
begin
|
||||
FGScope.Clear;
|
||||
|
||||
Memo1.Lines.Clear;
|
||||
Memo1.Lines.Add('--- Native Delphi Fibonacci Performance ---');
|
||||
Memo1.Lines.Add('Calculating fib(30) and fib(40)...');
|
||||
@@ -227,6 +248,8 @@ var
|
||||
result: TAstValue;
|
||||
sw: TStopwatch;
|
||||
begin
|
||||
FGScope.Clear;
|
||||
|
||||
sw := TStopwatch.Create;
|
||||
Memo1.Lines.Clear;
|
||||
Memo1.Lines.Add('--- Recursive factorial(20) ---');
|
||||
@@ -280,6 +303,8 @@ var
|
||||
result: TAstValue;
|
||||
sw: TStopwatch;
|
||||
begin
|
||||
FGScope.Clear;
|
||||
|
||||
sw := TStopwatch.Create;
|
||||
Memo1.Lines.Clear;
|
||||
Memo1.Lines.Add('--- Simple AST Execution ---');
|
||||
@@ -320,6 +345,8 @@ var
|
||||
result: TAstValue;
|
||||
sw: TStopwatch;
|
||||
begin
|
||||
FGScope.Clear;
|
||||
|
||||
sw := TStopwatch.Create;
|
||||
Memo1.Lines.Clear;
|
||||
Memo1.Lines.Add('--- Factory Pattern Demo ---');
|
||||
@@ -361,4 +388,105 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TForm1.CrerateTriggerExampleButtonClick(Sender: TObject);
|
||||
var
|
||||
lambdaAst: ILambdaExpressionNode;
|
||||
visitor: IAstVisitor;
|
||||
closureValue: TAstValue;
|
||||
begin
|
||||
FGScope.Clear;
|
||||
|
||||
// Create an AST that gets a "tick" in DoTriggerButtonClick.
|
||||
// This simulates a simple Blueprint-like event system.
|
||||
// It maintains state via a persistent execution scope.
|
||||
|
||||
Memo1.Lines.Clear;
|
||||
Memo1.Lines.Add('--- Creating Trigger Blueprint ---');
|
||||
|
||||
// 1. Initialize the variable 'X' to 0 directly in the scope.
|
||||
FGScope.SetValue('X', TAstValue.FromScalar(TScalar.FromInt64(0)));
|
||||
|
||||
// 2. Create a lambda that takes the summand as an argument.
|
||||
// AST for: (summand) => { X = X + summand; }
|
||||
// Using the new Assignment node to modify 'X' in its parent scope.
|
||||
lambdaAst :=
|
||||
TAst.LambdaExpr(
|
||||
[TAst.Identifier('summand')],
|
||||
TAst.Assign(TAst.Identifier('X'), TAst.BinaryExpr(TAst.Identifier('X'), boAdd, TAst.Identifier('summand')))
|
||||
);
|
||||
|
||||
// 3. Evaluate the lambda to create a closure and store it in the scope.
|
||||
// The closure captures the scope where 'X' is defined.
|
||||
visitor := TEvaluatorVisitor.Create(FGScope);
|
||||
closureValue := lambdaAst.Accept(visitor);
|
||||
FGScope.SetValue('tickHandler', closureValue);
|
||||
|
||||
// FLastAst is not used for this parameterized example.
|
||||
FLastAst := lambdaAst;
|
||||
|
||||
Memo1.Lines.Add('Variable "X" initialized to 0 in persistent scope.');
|
||||
Memo1.Lines.Add('Blueprint function "tickHandler(summand)" created.');
|
||||
Memo1.Lines.Add('Click "Do Trigger" or "Do Trigger 2" to execute.');
|
||||
end;
|
||||
|
||||
procedure TForm1.DoTriggerButtonClick(Sender: TObject);
|
||||
var
|
||||
visitor: IAstVisitor;
|
||||
currentValue: TAstValue;
|
||||
callAst: IFunctionCallNode;
|
||||
begin
|
||||
// A "tick" executes the stored AST using the persistent scope.
|
||||
|
||||
// Create an AST to call the stored handler with argument 1.
|
||||
// AST for: tickHandler(1)
|
||||
callAst := TAst.FunctionCall(TAst.Identifier('tickHandler'), [TAst.Constant(TScalar.FromInt64(1))]);
|
||||
|
||||
// Execute the call AST.
|
||||
visitor := TEvaluatorVisitor.Create(FGScope);
|
||||
callAst.Accept(visitor);
|
||||
|
||||
FLastAst := callAst;
|
||||
|
||||
// Get the updated value of 'X' from the scope and display it.
|
||||
if FGScope.FindValue('X', currentValue) then
|
||||
begin
|
||||
Memo1.Lines.Add(Format('Tick(1)! New value of X: %s', [currentValue.ToString]));
|
||||
end
|
||||
else
|
||||
begin
|
||||
// This should not happen if setup was correct.
|
||||
Memo1.Lines.Add('Error: Variable "X" not found in scope.');
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TForm1.DoTrigger2ButtonClick(Sender: TObject);
|
||||
var
|
||||
visitor: IAstVisitor;
|
||||
currentValue: TAstValue;
|
||||
callAst: IFunctionCallNode;
|
||||
begin
|
||||
// A "tick" that adds 2, using the same blueprint function.
|
||||
|
||||
// Create an AST to call the stored handler with argument 2.
|
||||
// AST for: tickHandler(2)
|
||||
callAst := TAst.FunctionCall(TAst.Identifier('tickHandler'), [TAst.Constant(TScalar.FromInt64(2))]);
|
||||
|
||||
FLastAst := callAst;
|
||||
|
||||
// Execute the call AST.
|
||||
visitor := TEvaluatorVisitor.Create(FGScope);
|
||||
callAst.Accept(visitor);
|
||||
|
||||
// Get the updated value of 'X' from the scope and display it.
|
||||
if FGScope.FindValue('X', currentValue) then
|
||||
begin
|
||||
Memo1.Lines.Add(Format('Tick(2)! New value of X: %s', [currentValue.ToString]));
|
||||
end
|
||||
else
|
||||
begin
|
||||
// This should not happen if setup was correct.
|
||||
Memo1.Lines.Add('Error: Variable "X" not found in scope.');
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
Reference in New Issue
Block a user