Macro expander integrated in binder
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -1,6 +1,7 @@
|
||||
program ASTPlayground;
|
||||
|
||||
uses
|
||||
FastMM5,
|
||||
System.StartUpCopy,
|
||||
FMX.Forms,
|
||||
MainForm in 'MainForm.pas' {Form1},
|
||||
@@ -19,8 +20,7 @@ uses
|
||||
Myc.Fmx.AstEditor.Workspace in 'Myc.Fmx.AstEditor.Workspace.pas',
|
||||
Myc.Fmx.AstEditor.Text in 'Myc.Fmx.AstEditor.Text.pas',
|
||||
Myc.Utils in '..\Src\Myc.Utils.pas',
|
||||
Myc.Ast.Script in '..\Src\AST\Myc.Ast.Script.pas',
|
||||
Myc.Ast.MacroExpander in '..\Src\AST\Myc.Ast.MacroExpander.pas';
|
||||
Myc.Ast.Script in '..\Src\AST\Myc.Ast.Script.pas';
|
||||
|
||||
{$R *.res}
|
||||
|
||||
|
||||
@@ -134,7 +134,6 @@
|
||||
</DelphiCompile>
|
||||
<DCCReference Include="MainForm.pas">
|
||||
<Form>Form1</Form>
|
||||
<FormType>fmx</FormType>
|
||||
</DCCReference>
|
||||
<DCCReference Include="..\Src\AST\Myc.Ast.Evaluator.pas"/>
|
||||
<DCCReference Include="..\Src\AST\Myc.Ast.Nodes.pas"/>
|
||||
@@ -152,7 +151,6 @@
|
||||
<DCCReference Include="Myc.Fmx.AstEditor.Text.pas"/>
|
||||
<DCCReference Include="..\Src\Myc.Utils.pas"/>
|
||||
<DCCReference Include="..\Src\AST\Myc.Ast.Script.pas"/>
|
||||
<DCCReference Include="..\Src\AST\Myc.Ast.MacroExpander.pas"/>
|
||||
<BuildConfiguration Include="Base">
|
||||
<Key>Base</Key>
|
||||
</BuildConfiguration>
|
||||
|
||||
@@ -20,7 +20,6 @@ object Form1: TForm1
|
||||
Position.Y = 32.000000000000000000
|
||||
TabOrder = 1
|
||||
Text = 'Test 1'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = Test1ButtonClick
|
||||
end
|
||||
object Test2Button: TButton
|
||||
@@ -28,7 +27,6 @@ object Form1: TForm1
|
||||
Position.Y = 62.000000000000000000
|
||||
TabOrder = 2
|
||||
Text = 'Test 2'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = Test2ButtonClick
|
||||
end
|
||||
object PrettyPrintButton: TButton
|
||||
@@ -36,7 +34,6 @@ object Form1: TForm1
|
||||
Position.Y = 479.000000000000000000
|
||||
TabOrder = 3
|
||||
Text = 'Print'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = PrettyPrintButtonClick
|
||||
end
|
||||
object RecursionButton: TButton
|
||||
@@ -47,7 +44,6 @@ object Form1: TForm1
|
||||
Size.PlatformDefault = False
|
||||
TabOrder = 4
|
||||
Text = 'Recursion'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = RecursionButtonClick
|
||||
end
|
||||
object ShowScopeBox: TCheckBox
|
||||
@@ -61,7 +57,6 @@ object Form1: TForm1
|
||||
Position.Y = 122.000000000000000000
|
||||
TabOrder = 7
|
||||
Text = 'Fibonacci'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = FibonacciButtonClick
|
||||
end
|
||||
object CrerateTriggerExampleButton: TButton
|
||||
@@ -69,7 +64,6 @@ object Form1: TForm1
|
||||
Position.Y = 168.000000000000000000
|
||||
TabOrder = 8
|
||||
Text = 'TriggerTest'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = CreateTriggerExampleButtonClick
|
||||
end
|
||||
object DoTriggerButton: TButton
|
||||
@@ -77,13 +71,11 @@ object Form1: TForm1
|
||||
Position.Y = 198.000000000000000000
|
||||
TabOrder = 9
|
||||
Text = 'Trigger!'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = DoTriggerButtonClick
|
||||
object DoTrigger2Button: TButton
|
||||
Position.Y = 30.000000000000000000
|
||||
TabOrder = 5
|
||||
Text = 'Trigger2'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = DoTrigger2ButtonClick
|
||||
end
|
||||
end
|
||||
@@ -95,7 +87,6 @@ object Form1: TForm1
|
||||
Size.PlatformDefault = False
|
||||
TabOrder = 10
|
||||
Text = 'Clear'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = ClearButtonClick
|
||||
end
|
||||
object FlowOnlyBox: TCheckBox
|
||||
@@ -113,7 +104,6 @@ object Form1: TForm1
|
||||
Size.PlatformDefault = False
|
||||
TabOrder = 13
|
||||
Text = 'Series'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = SeriesTestButtonClick
|
||||
end
|
||||
object OHLCButton: TButton
|
||||
@@ -121,7 +111,6 @@ object Form1: TForm1
|
||||
Position.Y = 288.000000000000000000
|
||||
TabOrder = 14
|
||||
Text = 'OHLC'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = OHLCButtonClick
|
||||
end
|
||||
object DebugBox: TCheckBox
|
||||
@@ -135,7 +124,6 @@ object Form1: TForm1
|
||||
Position.Y = 602.000000000000000000
|
||||
TabOrder = 16
|
||||
Text = 'From JSON'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = FromJSONButtonClick
|
||||
end
|
||||
object ToJSONButton: TButton
|
||||
@@ -143,7 +131,6 @@ object Form1: TForm1
|
||||
Position.Y = 632.000000000000000000
|
||||
TabOrder = 17
|
||||
Text = 'To JSON'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = ToJSONButtonClick
|
||||
end
|
||||
object ExternalFuncButton: TButton
|
||||
@@ -151,7 +138,6 @@ object Form1: TForm1
|
||||
Position.Y = 318.000000000000000000
|
||||
TabOrder = 18
|
||||
Text = 'External Func'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = ExternalFuncButtonClick
|
||||
end
|
||||
object InnerLambdaButton: TButton
|
||||
@@ -159,7 +145,6 @@ object Form1: TForm1
|
||||
Position.Y = 348.000000000000000000
|
||||
TabOrder = 19
|
||||
Text = 'Inner Lambda'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = InnerLambdaButtonClick
|
||||
end
|
||||
object DumpButton: TButton
|
||||
@@ -167,7 +152,6 @@ object Form1: TForm1
|
||||
Position.Y = 509.000000000000000000
|
||||
TabOrder = 20
|
||||
Text = 'Dump'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = DumpButtonClick
|
||||
end
|
||||
object FailingUpvalueButton: TButton
|
||||
@@ -175,7 +159,6 @@ object Form1: TForm1
|
||||
Position.Y = 378.000000000000000000
|
||||
TabOrder = 22
|
||||
Text = 'Upvalue'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = FailingUpvalueButtonClick
|
||||
end
|
||||
object TailCallButten: TButton
|
||||
@@ -183,7 +166,6 @@ object Form1: TForm1
|
||||
Position.Y = 406.000000000000000000
|
||||
TabOrder = 23
|
||||
Text = 'Tail calls'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = TailCallButtenClick
|
||||
end
|
||||
object SaveUserLibButton: TButton
|
||||
@@ -191,7 +173,6 @@ object Form1: TForm1
|
||||
Position.Y = 680.000000000000000000
|
||||
TabOrder = 24
|
||||
Text = 'Save Lib'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = SaveUserLibButtonClick
|
||||
end
|
||||
object LoadUserLibButton: TButton
|
||||
@@ -199,7 +180,6 @@ object Form1: TForm1
|
||||
Position.Y = 710.000000000000000000
|
||||
TabOrder = 25
|
||||
Text = 'LoadLib'
|
||||
TextSettings.Trimming = None
|
||||
OnClick = LoadUserLibButtonClick
|
||||
end
|
||||
end
|
||||
|
||||
+23
-29
@@ -33,7 +33,6 @@ uses
|
||||
Myc.Ast.Binding,
|
||||
Myc.Ast.RTL,
|
||||
Myc.Ast.Script,
|
||||
Myc.Ast.MacroExpander,
|
||||
FMX.Layouts,
|
||||
FMX.Objects,
|
||||
Myc.Ast.Debugger,
|
||||
@@ -114,7 +113,7 @@ type
|
||||
FTriggerScope: IExecutionScope;
|
||||
FScriptUpdate: Boolean;
|
||||
procedure WorkspaceMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
|
||||
function CreateEvaluator(Scope: IExecutionScope): IEvaluatorVisitor;
|
||||
function CreateEvaluator(const Scope: IExecutionScope): IEvaluatorVisitor;
|
||||
// Helper function to encapsulate the Bind -> Evaluate pattern
|
||||
function ExecuteAst(const ANode: IAstNode; const AParentScope: IExecutionScope): TDataValue;
|
||||
procedure UpdateScript;
|
||||
@@ -212,31 +211,26 @@ end;
|
||||
function TForm1.ExecuteAst(const ANode: IAstNode; const AParentScope: IExecutionScope): TDataValue;
|
||||
var
|
||||
binder: IAstBinder;
|
||||
scriptScope: IExecutionScope;
|
||||
boundAst: IAstNode;
|
||||
descriptor: IScopeDescriptor;
|
||||
evalScope: IExecutionScope;
|
||||
visitor: IEvaluatorVisitor;
|
||||
begin
|
||||
var macroExpander :=
|
||||
TMacroExpander.Create(
|
||||
function(const ANode: IAstNode): TDataValue
|
||||
begin
|
||||
var binder := TAstBinder.Create(AParentScope) as IAstBinder;
|
||||
// The new, streamlined pipeline: The binder handles macro expansion internally.
|
||||
|
||||
var descriptor: IScopeDescriptor;
|
||||
var boundAst := binder.Execute(ANode, descriptor);
|
||||
// Step 1: Create a binder, passing the evaluator factory for compile-time evaluations.
|
||||
binder := TAstBinder.Create(AParentScope, CreateEvaluator);
|
||||
|
||||
var evalScope := descriptor.CreateScope(AParentScope);
|
||||
var evaluator := CreateEvaluator(evalScope);
|
||||
boundAst := binder.Execute(ANode, descriptor);
|
||||
|
||||
Result := evaluator.Execute(boundAst);
|
||||
end)
|
||||
as IMacroExpander;
|
||||
// Store the final bound AST for visualization and debugging.
|
||||
FCurrAst := ANode;
|
||||
FCurrDesc := descriptor;
|
||||
|
||||
binder := TAstBinder.Create(AParentScope);
|
||||
FCurrAst := binder.Execute(macroExpander.Execute(ANode), FCurrDesc);
|
||||
|
||||
scriptScope := FCurrDesc.CreateScope(AParentScope);
|
||||
visitor := CreateEvaluator(scriptScope);
|
||||
Result := visitor.Execute(FCurrAst);
|
||||
// Step 2: Create the final scope and evaluator for runtime execution.
|
||||
evalScope := descriptor.CreateScope(AParentScope);
|
||||
visitor := CreateEvaluator(evalScope);
|
||||
Result := visitor.Execute(boundAst);
|
||||
end;
|
||||
|
||||
procedure TForm1.FormCreate(Sender: TObject);
|
||||
@@ -307,7 +301,7 @@ begin
|
||||
)
|
||||
);
|
||||
|
||||
binder := TAstBinder.Create(Scope);
|
||||
binder := TAstBinder.Create(Scope, CreateEvaluator);
|
||||
boundSmaAst := binder.Execute(smaAst, smaDescriptor);
|
||||
|
||||
smaScope := smaDescriptor.CreateScope(Scope);
|
||||
@@ -496,7 +490,7 @@ begin
|
||||
raise EJSONParseException.Create('Invalid JSON format.');
|
||||
|
||||
try
|
||||
var binder := TAstBinder.Create(FGScope);
|
||||
var binder := TAstBinder.Create(FGScope, CreateEvaluator);
|
||||
var unboundAst := converter.Deserialize(jsonObj);
|
||||
FCurrAst := binder.Execute(unboundAst, FCurrDesc);
|
||||
Memo1.Lines.Add('AST deserialized successfully from JSON.');
|
||||
@@ -566,7 +560,7 @@ begin
|
||||
end;
|
||||
|
||||
// Re-bind the current AST against the global scope to ensure up-to-date binding info for the dump.
|
||||
binder := TAstBinder.Create(FGScope);
|
||||
binder := TAstBinder.Create(FGScope, CreateEvaluator);
|
||||
boundNode := binder.Execute(FCurrAst, FCurrDesc);
|
||||
TAstDumper.Dump(boundNode, Memo1.Lines);
|
||||
end;
|
||||
@@ -608,7 +602,7 @@ begin
|
||||
]
|
||||
);
|
||||
|
||||
binder := TAstBinder.Create(FGScope);
|
||||
binder := TAstBinder.Create(FGScope, CreateEvaluator);
|
||||
var desc: IScopeDescriptor;
|
||||
boundFibAst := binder.Execute(fibAst, desc);
|
||||
fibScope := desc.CreateScope(FGScope);
|
||||
@@ -902,7 +896,7 @@ begin
|
||||
);
|
||||
|
||||
// 1. Bind and execute the setup script.
|
||||
binder := TAstBinder.Create(FGScope);
|
||||
binder := TAstBinder.Create(FGScope, CreateEvaluator);
|
||||
boundSetupAst := binder.Execute(setupAst, setupDescriptor);
|
||||
|
||||
scope := setupDescriptor.CreateScope(FGScope);
|
||||
@@ -915,7 +909,7 @@ begin
|
||||
callAst := TAst.FunctionCall(TAst.Identifier('maCrossStrategy'), [currentSeriesIdent]);
|
||||
|
||||
// 3. Re-bind the call AST within the now-populated scope to resolve the new variable.
|
||||
binder := TAstBinder.Create(scope);
|
||||
binder := TAstBinder.Create(scope, CreateEvaluator);
|
||||
boundCallAst := binder.Execute(callAst, callDescriptor);
|
||||
|
||||
// 4. Get the address of 'current_series' from the new descriptor.
|
||||
@@ -1041,7 +1035,7 @@ begin
|
||||
]
|
||||
);
|
||||
|
||||
binder := TAstBinder.Create(FGScope);
|
||||
binder := TAstBinder.Create(FGScope, CreateEvaluator);
|
||||
FCurrAst := binder.Execute(blk, FCurrDesc);
|
||||
FTriggerScope := FCurrDesc.CreateScope(FGScope);
|
||||
|
||||
@@ -1053,7 +1047,7 @@ begin
|
||||
UpdateScript;
|
||||
end;
|
||||
|
||||
function TForm1.CreateEvaluator(Scope: IExecutionScope): IEvaluatorVisitor;
|
||||
function TForm1.CreateEvaluator(const Scope: IExecutionScope): IEvaluatorVisitor;
|
||||
begin
|
||||
if DebugBox.IsChecked then
|
||||
Result := TDebugEvaluatorVisitor.Create(Scope, Memo1.Lines, ShowScopeBox.IsChecked)
|
||||
|
||||
Reference in New Issue
Block a user