RECUR keyword added
This commit is contained in:
+29
-36
@@ -280,77 +280,70 @@ var
|
|||||||
result: TDataValue;
|
result: TDataValue;
|
||||||
sw: TStopwatch;
|
sw: TStopwatch;
|
||||||
begin
|
begin
|
||||||
// Create a setup script to define a memoize-compatible 'fib' function globally.
|
// This script defines a naive, slow recursive 'fib' function.
|
||||||
// This is rewritten to be tail-recursive using the 'recur' keyword.
|
// The lambda captures its own name ('fib') from the parent scope to perform recursion.
|
||||||
var fibAst :=
|
var fibAst :=
|
||||||
TAst.Block(
|
TAst.Block(
|
||||||
[
|
[
|
||||||
// 1. var fib_iter = lambda(n, a, b) { ... }; (The tail-recursive part)
|
// 1. var fib; (Declare the name so it can be captured by the lambda)
|
||||||
TAst.VarDecl(
|
|
||||||
TAst.Identifier('fib_iter'),
|
|
||||||
TAst.LambdaExpr(
|
|
||||||
[TAst.Identifier('n'), TAst.Identifier('a'), TAst.Identifier('b')],
|
|
||||||
TAst.TernaryExpr(
|
|
||||||
TAst.BinaryExpr(TAst.Identifier('n'), boEqual, TAst.Constant(TScalar.FromInt64(0))),
|
|
||||||
TAst.Identifier('a'), // Base case 1
|
|
||||||
TAst.TernaryExpr(
|
|
||||||
TAst.BinaryExpr(TAst.Identifier('n'), boEqual, TAst.Constant(TScalar.FromInt64(1))),
|
|
||||||
TAst.Identifier('b'), // Base case 2
|
|
||||||
TAst.Recur( // Tail-recursive step
|
|
||||||
[
|
|
||||||
TAst.BinaryExpr(TAst.Identifier('n'), boSubtract, TAst.Constant(TScalar.FromInt64(1))),
|
|
||||||
TAst.Identifier('b'),
|
|
||||||
TAst.BinaryExpr(TAst.Identifier('a'), boAdd, TAst.Identifier('b'))
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
// 2. var fib;
|
|
||||||
TAst.VarDecl(TAst.Identifier('fib')),
|
TAst.VarDecl(TAst.Identifier('fib')),
|
||||||
// 3. fib = lambda(n) { fib_iter(n, 0, 1) }; (The public-facing function)
|
// 2. fib = lambda(n) { ... fib(n-1) + fib(n-2) ... };
|
||||||
TAst.Assign(
|
TAst.Assign(
|
||||||
TAst.Identifier('fib'),
|
TAst.Identifier('fib'),
|
||||||
TAst.LambdaExpr(
|
TAst.LambdaExpr(
|
||||||
[TAst.Identifier('n')],
|
[TAst.Identifier('n')],
|
||||||
TAst.FunctionCall(
|
TAst.TernaryExpr(
|
||||||
TAst.Identifier('fib_iter'),
|
TAst.BinaryExpr(TAst.Identifier('n'), boLess, TAst.Constant(TScalar.FromInt64(2))),
|
||||||
[TAst.Identifier('n'), TAst.Constant(TScalar.FromInt64(0)), TAst.Constant(TScalar.FromInt64(1))]
|
TAst.Identifier('n'),
|
||||||
|
TAst.BinaryExpr(
|
||||||
|
// Naive recursive call using the variable name 'fib'
|
||||||
|
TAst.FunctionCall(
|
||||||
|
TAst.Identifier('fib'),
|
||||||
|
[TAst.BinaryExpr(TAst.Identifier('n'), boSubtract, TAst.Constant(TScalar.FromInt64(1)))]
|
||||||
|
),
|
||||||
|
boAdd,
|
||||||
|
// Second naive recursive call
|
||||||
|
TAst.FunctionCall(
|
||||||
|
TAst.Identifier('fib'),
|
||||||
|
[TAst.BinaryExpr(TAst.Identifier('n'), boSubtract, TAst.Constant(TScalar.FromInt64(2)))]
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Create a new scope and define the 'fib' function within it.
|
||||||
var fibScope := TAstBinder.Bind(fibAst, FGScope).CreateScope(FGScope);
|
var fibScope := TAstBinder.Bind(fibAst, FGScope).CreateScope(FGScope);
|
||||||
var visitor := CreateVisitor(fibScope);
|
var visitor := CreateVisitor(fibScope);
|
||||||
visitor.Execute(fibAst);
|
visitor.Execute(fibAst);
|
||||||
|
|
||||||
Memo1.Lines.Clear;
|
Memo1.Lines.Clear;
|
||||||
Memo1.Lines.Add('--- Tail-Recursive fib with AST---');
|
Memo1.Lines.Add('--- Naive recursive fib with AST---');
|
||||||
sw := TStopwatch.StartNew;
|
sw := TStopwatch.StartNew;
|
||||||
|
|
||||||
root := TAst.FunctionCall(TAst.Identifier('fib'), [TAst.Constant(TScalar.FromInt64(30))]);
|
// The script to execute is just the call to the function.
|
||||||
|
root := TAst.FunctionCall(TAst.Identifier('fib'), [TAst.Constant(TScalar.FromInt64(25))]);
|
||||||
|
|
||||||
FLastAst := root;
|
FLastAst := root;
|
||||||
// Execute with fibScope as parent. The helper function handles debug/prod switching.
|
// Execute within the scope where 'fib' is defined.
|
||||||
result := ExecuteAst(root, fibScope);
|
result := ExecuteAst(root, fibScope);
|
||||||
|
|
||||||
sw.Stop;
|
sw.Stop;
|
||||||
Memo1.Lines.Add(Format('Result: fib(30) %s (calculated in %d ms)', [result.ToString, sw.ElapsedMilliseconds]));
|
Memo1.Lines.Add(Format('Result: fib(30) %s (calculated in %d ms)', [result.ToString, sw.ElapsedMilliseconds]));
|
||||||
|
|
||||||
Memo1.Lines.Add('');
|
Memo1.Lines.Add('');
|
||||||
Memo1.Lines.Add('--- Memoized tail-recursive fib with AST (using global fib)---');
|
Memo1.Lines.Add('--- Memoized naive fib with AST (using global fib)---');
|
||||||
sw := TStopwatch.StartNew;
|
sw := TStopwatch.StartNew;
|
||||||
|
|
||||||
root :=
|
root :=
|
||||||
TAst.Block(
|
TAst.Block(
|
||||||
[
|
[
|
||||||
// Create a memoized version by calling the RTL function on the global 'fib'
|
// Create a memoized version by calling the RTL function on 'fib'
|
||||||
TAst.Assign(TAst.Identifier('fib'), TAst.FunctionCall(TAst.Identifier('Memoize'), [TAst.Identifier('fib')])),
|
TAst.Assign(TAst.Identifier('fib'), TAst.FunctionCall(TAst.Identifier('Memoize'), [TAst.Identifier('fib')])),
|
||||||
// Call the memoized function
|
// Call the new, memoized function
|
||||||
TAst.FunctionCall(TAst.Identifier('fib'), [TAst.Constant(TScalar.FromInt64(30))])
|
TAst.FunctionCall(TAst.Identifier('fib'), [TAst.Constant(TScalar.FromInt64(25))])
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user