Anonymous recursions

This commit is contained in:
Michael Schimmel
2025-09-19 23:53:48 +02:00
parent 28558614f0
commit e03155179a
7 changed files with 126 additions and 49 deletions
+2 -1
View File
@@ -19,7 +19,8 @@ uses
Myc.Ast.Binding in '..\Src\AST\Myc.Ast.Binding.pas',
Myc.Ast.RTL in '..\Src\AST\Myc.Ast.RTL.pas',
Myc.Ast.Dumper in '..\Src\AST\Myc.Ast.Dumper.pas',
Myc.Ast.RTL.Core in '..\Src\AST\Myc.Ast.RTL.Core.pas';
Myc.Ast.RTL.Core in '..\Src\AST\Myc.Ast.RTL.Core.pas',
Myc.Utils in '..\Src\Myc.Utils.pas';
{$R *.res}
+1
View File
@@ -151,6 +151,7 @@
<DCCReference Include="..\Src\AST\Myc.Ast.RTL.pas"/>
<DCCReference Include="..\Src\AST\Myc.Ast.Dumper.pas"/>
<DCCReference Include="..\Src\AST\Myc.Ast.RTL.Core.pas"/>
<DCCReference Include="..\Src\Myc.Utils.pas"/>
<BuildConfiguration Include="Base">
<Key>Base</Key>
</BuildConfiguration>
+42 -14
View File
@@ -31,6 +31,9 @@ uses
Myc.Ast.Evaluator,
Myc.Ast.Printer,
Myc.Ast.Dumper,
Myc.Data.Decimal,
Myc.Ast.Binding,
Myc.Ast.RTL,
FMX.Layouts,
FMX.Objects,
Myc.Ast.Debugger;
@@ -110,8 +113,6 @@ implementation
uses
Myc.Data.Scalar.JSON,
Myc.Data.Decimal,
Myc.Ast.Binding,
System.Diagnostics, // For TStopwatch
Myc.Ast.Json; // For TAstJson serialization
@@ -184,9 +185,6 @@ begin
resultValue := ExecuteAst(mainBlock, FGScope);
//TODO Dieses Assert löst aus:
// "The final result should be 15, but is 10 (T:\Myc\ASTPlayground\MainForm.pas, line 186)"
Assert(TScalar.FromInteger(15) = resultValue.AsScalar, 'The final result should be 15, but is ' + resultValue.AsScalar.ToString);
end;
@@ -282,14 +280,14 @@ var
result: TDataValue;
sw: TStopwatch;
begin
Memo1.Lines.Clear;
Memo1.Lines.Add('--- Recursive fib with AST---');
sw := TStopwatch.StartNew;
root :=
// Create a setup script to define a memoize-compatible 'fib' function globally.
var fibAst :=
TAst.Block(
[
TAst.VarDecl(
// 1. var fib; (Declare the name so it can be captured by the lambda. Initializer is nil)
TAst.VarDecl(TAst.Identifier('fib')),
// 2. var fib_impl = lambda(n) { ... fib(n-1) + fib(n-2) ... };
TAst.Assign(
TAst.Identifier('fib'),
TAst.LambdaExpr(
[TAst.Identifier('n')],
@@ -297,6 +295,7 @@ begin
TAst.BinaryExpr(TAst.Identifier('n'), boLess, TAst.Constant(TScalar.FromInt64(2))),
TAst.Identifier('n'),
TAst.BinaryExpr(
// Recursive calls now use the re-bindable name 'fib' instead of 'Self'
TAst.FunctionCall(
TAst.Identifier('Self'),
[TAst.BinaryExpr(TAst.Identifier('n'), boSubtract, TAst.Constant(TScalar.FromInt64(1)))]
@@ -309,14 +308,43 @@ begin
)
)
)
),
)
]
);
var fibScope := TAstBinder.Bind(fibAst, FGScope).CreateScope(FGScope);
var visitor := CreateVisitor(fibScope);
Result := visitor.Execute(fibAst);
Memo1.Lines.Clear;
Memo1.Lines.Add('--- Recursive fib with AST---');
sw := TStopwatch.StartNew;
root := TAst.FunctionCall(TAst.Identifier('fib'), [TAst.Constant(TScalar.FromInt64(30))]);
FLastAst := root;
// Execute with fibScope as parent. The helper function handles debug/prod switching.
result := ExecuteAst(root, fibScope);
sw.Stop;
Memo1.Lines.Add(Format('Result: fib(30) %s (calculated in %d ms)', [result.ToString, sw.ElapsedMilliseconds]));
Memo1.Lines.Add('');
Memo1.Lines.Add('--- Memoized recursive fib with AST (using global fib)---');
sw := TStopwatch.StartNew;
root :=
TAst.Block(
[
// Create a memoized version by calling the RTL function on the global 'fib'
TAst.Assign(TAst.Identifier('fib'), TAst.FunctionCall(TAst.Identifier('Memoize'), [TAst.Identifier('fib')])),
// Call the memoized function
TAst.FunctionCall(TAst.Identifier('fib'), [TAst.Constant(TScalar.FromInt64(30))])
]
);
FLastAst := root;
// Execute with FGScope as parent. The helper function handles debug/prod switching.
result := ExecuteAst(root, FGScope);
result := ExecuteAst(root, fibScope);
sw.Stop;
Memo1.Lines.Add(Format('Result: fib(30) %s (calculated in %d ms)', [result.ToString, sw.ElapsedMilliseconds]));