RECUR keyword added
This commit is contained in:
+59
-90
@@ -21,9 +21,6 @@ uses
|
||||
FMX.ScrollBox,
|
||||
FMX.Memo,
|
||||
FMX.Controls.Presentation,
|
||||
Myc.Fmx.AstEditor,
|
||||
Myc.Fmx.AstEditor.Node,
|
||||
Myc.Fmx.AstEditor.Workspace,
|
||||
Myc.Data.Scalar,
|
||||
Myc.Data.Value,
|
||||
Myc.Ast.Nodes,
|
||||
@@ -36,7 +33,10 @@ uses
|
||||
Myc.Ast.RTL,
|
||||
FMX.Layouts,
|
||||
FMX.Objects,
|
||||
Myc.Ast.Debugger;
|
||||
Myc.Ast.Debugger,
|
||||
Myc.Fmx.AstEditor,
|
||||
Myc.Fmx.AstEditor.Node,
|
||||
Myc.Fmx.AstEditor.Workspace;
|
||||
|
||||
type
|
||||
// A test record
|
||||
@@ -281,31 +281,42 @@ var
|
||||
sw: TStopwatch;
|
||||
begin
|
||||
// Create a setup script to define a memoize-compatible 'fib' function globally.
|
||||
// This is rewritten to be tail-recursive using the 'recur' keyword.
|
||||
var fibAst :=
|
||||
TAst.Block(
|
||||
[
|
||||
// 1. var fib; (Declare the name so it can be captured by the lambda. Initializer is nil)
|
||||
// 1. var fib_iter = lambda(n, a, b) { ... }; (The tail-recursive part)
|
||||
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')),
|
||||
// 2. var fib_impl = lambda(n) { ... fib(n-1) + fib(n-2) ... };
|
||||
// 3. fib = lambda(n) { fib_iter(n, 0, 1) }; (The public-facing function)
|
||||
TAst.Assign(
|
||||
TAst.Identifier('fib'),
|
||||
TAst.LambdaExpr(
|
||||
[TAst.Identifier('n')],
|
||||
TAst.TernaryExpr(
|
||||
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)))]
|
||||
),
|
||||
boAdd,
|
||||
TAst.FunctionCall(
|
||||
TAst.Identifier('Self'),
|
||||
[TAst.BinaryExpr(TAst.Identifier('n'), boSubtract, TAst.Constant(TScalar.FromInt64(2)))]
|
||||
)
|
||||
)
|
||||
TAst.FunctionCall(
|
||||
TAst.Identifier('fib_iter'),
|
||||
[TAst.Identifier('n'), TAst.Constant(TScalar.FromInt64(0)), TAst.Constant(TScalar.FromInt64(1))]
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -314,10 +325,10 @@ begin
|
||||
|
||||
var fibScope := TAstBinder.Bind(fibAst, FGScope).CreateScope(FGScope);
|
||||
var visitor := CreateVisitor(fibScope);
|
||||
Result := visitor.Execute(fibAst);
|
||||
visitor.Execute(fibAst);
|
||||
|
||||
Memo1.Lines.Clear;
|
||||
Memo1.Lines.Add('--- Recursive fib with AST---');
|
||||
Memo1.Lines.Add('--- Tail-Recursive fib with AST---');
|
||||
sw := TStopwatch.StartNew;
|
||||
|
||||
root := TAst.FunctionCall(TAst.Identifier('fib'), [TAst.Constant(TScalar.FromInt64(30))]);
|
||||
@@ -330,7 +341,7 @@ begin
|
||||
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)---');
|
||||
Memo1.Lines.Add('--- Memoized tail-recursive fib with AST (using global fib)---');
|
||||
sw := TStopwatch.StartNew;
|
||||
|
||||
root :=
|
||||
@@ -375,30 +386,39 @@ var
|
||||
sw: TStopwatch;
|
||||
begin
|
||||
Memo1.Lines.Clear;
|
||||
Memo1.Lines.Add('--- Recursive factorial(20) ---');
|
||||
Memo1.Lines.Add('--- Tail-Recursive factorial(20) ---');
|
||||
sw := TStopwatch.StartNew;
|
||||
|
||||
// Rewritten to be tail-recursive to use 'recur'
|
||||
root :=
|
||||
TAst.Block(
|
||||
[
|
||||
// Define the tail-recursive helper function
|
||||
TAst.VarDecl(
|
||||
TAst.Identifier('factorial'),
|
||||
TAst.Identifier('fact_iter'),
|
||||
TAst.LambdaExpr(
|
||||
[TAst.Identifier('n')],
|
||||
[TAst.Identifier('n'), TAst.Identifier('acc')],
|
||||
TAst.TernaryExpr(
|
||||
TAst.BinaryExpr(TAst.Identifier('n'), boLess, TAst.Constant(TScalar.FromInt64(2))),
|
||||
TAst.Constant(TScalar.FromInt64(1)),
|
||||
TAst.BinaryExpr(
|
||||
TAst.Identifier('n'),
|
||||
boMultiply,
|
||||
TAst.FunctionCall(
|
||||
TAst.Identifier('Self'),
|
||||
[TAst.BinaryExpr(TAst.Identifier('n'), boSubtract, TAst.Constant(TScalar.FromInt64(1)))]
|
||||
)
|
||||
TAst.BinaryExpr(TAst.Identifier('n'), boLessOrEqual, TAst.Constant(TScalar.FromInt64(1))),
|
||||
TAst.Identifier('acc'), // Base case: return the accumulator
|
||||
TAst.Recur( // Tail-recursive step
|
||||
[
|
||||
TAst.BinaryExpr(TAst.Identifier('n'), boSubtract, TAst.Constant(TScalar.FromInt64(1))),
|
||||
TAst.BinaryExpr(TAst.Identifier('acc'), boMultiply, TAst.Identifier('n'))
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
// Define the public-facing factorial function
|
||||
TAst.VarDecl(
|
||||
TAst.Identifier('factorial'),
|
||||
TAst.LambdaExpr(
|
||||
[TAst.Identifier('n')],
|
||||
TAst.FunctionCall(TAst.Identifier('fact_iter'), [TAst.Identifier('n'), TAst.Constant(TScalar.FromInt64(1))])
|
||||
)
|
||||
),
|
||||
// Call the main function
|
||||
TAst.FunctionCall(TAst.Identifier('factorial'), [TAst.Constant(TScalar.FromInt64(20))])
|
||||
]
|
||||
);
|
||||
@@ -566,54 +586,6 @@ begin
|
||||
var setupAst :=
|
||||
TAst.Block(
|
||||
[
|
||||
// TAst.VarDecl(
|
||||
// TAst.Identifier('CreateSMA'),
|
||||
// TAst.LambdaExpr(
|
||||
// [TAst.Identifier('len')],
|
||||
// TAst.Block(
|
||||
// [
|
||||
// TAst.VarDecl(TAst.Identifier('sum'), TAst.Constant(TScalar.FromDouble(0.0))),
|
||||
// TAst.VarDecl(TAst.Identifier('count'), TAst.Constant(TScalar.FromInt64(0))),
|
||||
// TAst.LambdaExpr(
|
||||
// [TAst.Identifier('series'), TAst.Identifier('val')],
|
||||
// TAst.Block(
|
||||
// [
|
||||
// TAst.Assign(
|
||||
// TAst.Identifier('sum'),
|
||||
// TAst.BinaryExpr(TAst.Identifier('sum'), boAdd, TAst.Identifier('val'))
|
||||
// ),
|
||||
// TAst.Assign(
|
||||
// TAst.Identifier('count'),
|
||||
// TAst.BinaryExpr(TAst.Identifier('count'), boAdd, TAst.Constant(TScalar.FromInt64(1)))
|
||||
// ),
|
||||
// TAst.IfExpr(
|
||||
// TAst.BinaryExpr(TAst.Identifier('count'), boGreater, TAst.Identifier('len')),
|
||||
// TAst.Assign(
|
||||
// TAst.Identifier('sum'),
|
||||
// TAst.BinaryExpr(
|
||||
// TAst.Identifier('sum'),
|
||||
// boSubtract,
|
||||
// TAst.Indexer(TAst.Identifier('series'), TAst.Identifier('len'))
|
||||
// )
|
||||
// ),
|
||||
// nil
|
||||
// ),
|
||||
// TAst.BinaryExpr(
|
||||
// TAst.Identifier('sum'),
|
||||
// boDivide,
|
||||
// TAst.TernaryExpr(
|
||||
// TAst.BinaryExpr(TAst.Identifier('count'), boLess, TAst.Identifier('len')),
|
||||
// TAst.Identifier('count'),
|
||||
// TAst.Identifier('len')
|
||||
// )
|
||||
// )
|
||||
// ]
|
||||
// )
|
||||
// )
|
||||
// ]
|
||||
// )
|
||||
// )
|
||||
// ),
|
||||
TAst.VarDecl(
|
||||
TAst.Identifier('smaFast'),
|
||||
TAst.FunctionCall(TAst.Identifier('CreateSMA'), [TAst.Constant(TScalar.FromInt64(smaFastLength))])
|
||||
@@ -961,14 +933,11 @@ begin
|
||||
TAst.Identifier('countDown'),
|
||||
TAst.LambdaExpr(
|
||||
[TAst.Identifier('n')],
|
||||
// if (n > 0) then Self(n-1) else 'done'
|
||||
// if (n > 0) then recur(n-1) else 'done'
|
||||
TAst.IfExpr(
|
||||
TAst.BinaryExpr(TAst.Identifier('n'), boGreater, TAst.Constant(TScalar.FromInt64(0))),
|
||||
// This is the tail call position.
|
||||
TAst.FunctionCall(
|
||||
TAst.Identifier('Self'),
|
||||
[TAst.BinaryExpr(TAst.Identifier('n'), boSubtract, TAst.Constant(TScalar.FromInt64(1)))]
|
||||
),
|
||||
// This is the tail call position, now using recur.
|
||||
TAst.Recur([TAst.BinaryExpr(TAst.Identifier('n'), boSubtract, TAst.Constant(TScalar.FromInt64(1)))]),
|
||||
// Base case of the recursion
|
||||
TAst.Constant(TScalar.FromString('done'))
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user