Beginning Editor

This commit is contained in:
Michael Schimmel
2025-09-08 18:59:04 +02:00
parent 7e4ecb2ff9
commit a9cc9633a2
14 changed files with 1582 additions and 288 deletions
+3 -1
View File
@@ -8,7 +8,9 @@ uses
Myc.Ast.Printer in '..\Src\AST\Myc.Ast.Printer.pas',
Myc.Ast.Nodes in '..\Src\AST\Myc.Ast.Nodes.pas',
Myc.Ast.Scope in '..\Src\AST\Myc.Ast.Scope.pas',
Myc.Ast.Visualizer in 'Myc.Ast.Visualizer.pas';
Myc.Ast.Visualizer in 'Myc.Ast.Visualizer.pas',
Myc.Ast.ViewModel in '..\Src\AST\Myc.Ast.ViewModel.pas',
Myc.Ast.Persistence in '..\Src\AST\Myc.Ast.Persistence.pas';
{$R *.res}
+14
View File
@@ -140,6 +140,8 @@
<DCCReference Include="..\Src\AST\Myc.Ast.Nodes.pas"/>
<DCCReference Include="..\Src\AST\Myc.Ast.Scope.pas"/>
<DCCReference Include="Myc.Ast.Visualizer.pas"/>
<DCCReference Include="..\Src\AST\Myc.Ast.ViewModel.pas"/>
<DCCReference Include="..\Src\AST\Myc.Ast.Persistence.pas"/>
<BuildConfiguration Include="Base">
<Key>Base</Key>
</BuildConfiguration>
@@ -189,6 +191,18 @@
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="Win64\Debug\ASTPlayground.exe" Configuration="Debug" Class="ProjectOutput">
<Platform Name="Win64">
<RemoteName>ASTPlayground.exe</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="Win64\Debug\ASTPlayground.rsm" Configuration="Debug" Class="DebugSymbols">
<Platform Name="Win64">
<RemoteName>ASTPlayground.rsm</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="Win64\Release\ASTPlayground.exe" Configuration="Release" Class="ProjectOutput">
<Platform Name="Win64">
<RemoteName>ASTPlayground.exe</RemoteName>
+16
View File
@@ -130,6 +130,22 @@ object Form1: TForm1
TabOrder = 15
Text = 'Debug'
end
object FromJSONButton: TButton
Position.X = 24.000000000000000000
Position.Y = 520.000000000000000000
TabOrder = 16
Text = 'From JSON'
TextSettings.Trimming = None
OnClick = FromJSONButtonClick
end
object ToJSONButton: TButton
Position.X = 24.000000000000000000
Position.Y = 550.000000000000000000
TabOrder = 17
Text = 'To JSON'
TextSettings.Trimming = None
OnClick = ToJSONButtonClick
end
end
object Panel2: TPanel
Align = Client
+68 -9
View File
@@ -27,6 +27,7 @@ uses
Myc.Ast,
Myc.Ast.Evaluator,
Myc.Ast.Printer,
Myc.Ast.Persistence,
FMX.Layouts,
FMX.Objects,
Myc.Ast.Scope; // Added for TExecutionScope
@@ -60,6 +61,8 @@ type
SeriesTestButton: TButton;
OHLCButton: TButton;
DebugBox: TCheckBox;
FromJSONButton: TButton;
ToJSONButton: TButton;
procedure ClearButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure CreateTriggerExampleButtonClick(Sender: TObject);
@@ -72,15 +75,17 @@ type
procedure SeriesTestButtonClick(Sender: TObject);
procedure Test1ButtonClick(Sender: TObject);
procedure Test2ButtonClick(Sender: TObject);
procedure FromJSONButtonClick(Sender: TObject);
procedure ToJSONButtonClick(Sender: TObject);
private
// Stores the last AST generated by Test1 or Test2 button clicks.
FLastAst: IExpressionNode;
FLastAst: IAstNode;
FGScope: IExecutionScope;
FWorkspace: TAuraWorkspace;
function CreateVisitor(const AScope: IExecutionScope): IAstVisitor;
procedure WorkspaceMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
// New helper function to encapsulate the Bind -> Evaluate pattern
function ExecuteAst(const ANode: IExpressionNode; const AParentScope: IExecutionScope): TAstValue;
function ExecuteAst(const ANode: IAstNode; const AParentScope: IExecutionScope): TAstValue;
public
{ Public declarations }
end;
@@ -120,7 +125,7 @@ begin
Result := TEvaluatorVisitor.Create(AScope);
end;
function TForm1.ExecuteAst(const ANode: IExpressionNode; const AParentScope: IExecutionScope): TAstValue;
function TForm1.ExecuteAst(const ANode: IAstNode; const AParentScope: IExecutionScope): TAstValue;
var
scriptScope: IExecutionScope;
begin
@@ -144,7 +149,7 @@ end;
procedure TForm1.FibonacciButtonClick(Sender: TObject);
var
root: IExpressionNode;
root: IAstNode;
result: TAstValue;
sw: TStopwatch;
begin
@@ -208,7 +213,7 @@ end;
procedure TForm1.RecursionButtonClick(Sender: TObject);
var
root: IExpressionNode;
root: IAstNode;
result: TAstValue;
sw: TStopwatch;
begin
@@ -252,7 +257,7 @@ end;
procedure TForm1.SeriesTestButtonClick(Sender: TObject);
var
scope: IExecutionScope;
ast, callAst: IExpressionNode;
ast, callAst: IAstNode;
resultValue: TAstValue;
series: TScalarRecordSeries;
recordDef: TScalarRecordDefinition;
@@ -308,7 +313,7 @@ end;
procedure TForm1.Test1ButtonClick(Sender: TObject);
var
main, callAst: IExpressionNode;
main, callAst: IAstNode;
result: TAstValue;
sw: TStopwatch;
begin
@@ -342,7 +347,7 @@ end;
procedure TForm1.Test2ButtonClick(Sender: TObject);
var
root: IExpressionNode;
root: IAstNode;
result: TAstValue;
sw: TStopwatch;
begin
@@ -584,7 +589,7 @@ var
procedure TForm1.CreateTriggerExampleButtonClick(Sender: TObject);
var
blk: IExpressionNode;
blk: IAstNode;
begin
// This is a setup script, so its goal is to create and populate FGScope.
Memo1.Lines.Clear;
@@ -640,4 +645,58 @@ begin
Memo1.Lines.Add(Format('Tick(2)! New value of X: %s', [X.ToString]));
end;
procedure TForm1.FromJSONButtonClick(Sender: TObject);
begin
// Reads an AST JSON string from the memo and deserializes it into FLastAst.
if Memo1.Lines.Text.IsEmpty then
begin
Memo1.Lines.Text := 'Memo is empty. Paste an AST JSON structure here first.';
exit;
end;
try
Memo1.Lines.Insert(0, '--- Deserializing AST from JSON ---');
FLastAst := TAstProjectPersistence.JsonStringToAstNode(Memo1.Lines.Text);
if Assigned(FLastAst) then
begin
Memo1.Lines.Add('--- Deserialization successful. ---');
Memo1.Lines.Add('Middle-click on the right panel to visualize the new AST.');
end
else
begin
Memo1.Lines.Add('--- Deserialization failed. Invalid JSON or data structure. ---');
end;
except
on E: Exception do
begin
Memo1.Lines.Add('--- ERROR during deserialization ---');
Memo1.Lines.Add(E.ClassName + ': ' + E.Message);
end;
end;
end;
procedure TForm1.ToJSONButtonClick(Sender: TObject);
begin
// Serializes the current FLastAst to a JSON string and displays it in the memo.
Memo1.Lines.Clear;
Memo1.Lines.Add('--- Serializing AST to JSON ---');
if not Assigned(FLastAst) then
begin
Memo1.Lines.Add('No AST available to serialize. Generate one first.');
exit;
end;
try
Memo1.Lines.Text := TAstProjectPersistence.AstNodeToJsonString(FLastAst);
except
on E: Exception do
begin
Memo1.Lines.Clear;
Memo1.Lines.Add('--- ERROR during serialization ---');
Memo1.Lines.Add(E.ClassName + ': ' + E.Message);
end;
end;
end;
end.
+6 -6
View File
@@ -225,7 +225,7 @@ type
const ChildVisitorProc: TChildVisitorProc
): TAuraNode;
function VisitOperatorNode(
const InputExpressions: TArray<IExpressionNode>;
const InputExpressions: TArray<IAstNode>;
const CreateParentProc: TCreateParentNodeProc;
Alignment: TVerticalAlignment = vaCenter
): TAuraNode;
@@ -1073,7 +1073,7 @@ end;
function TAstToAuraNodeVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAstValue;
var
details: string;
inputs: TArray<IExpressionNode>;
inputs: TArray<IAstNode>;
begin
if (FMode = vmControlFlow) and TryGetDescr(Node, details) then
begin
@@ -1235,7 +1235,7 @@ begin
false,
procedure(const Visitor: IAstVisitor)
var
expression: IExpressionNode;
expression: IAstNode;
begin
for expression in Node.Expressions do
expression.Accept(Visitor);
@@ -1391,7 +1391,7 @@ end;
function TAstToAuraNodeVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TAstValue;
var
inputExpressions: TArray<IExpressionNode>;
inputExpressions: TArray<IAstNode>;
begin
var details: String;
if (FMode = vmControlFlow) and TryGetDescr(Node, details) then
@@ -1665,13 +1665,13 @@ begin
end;
function TAstToAuraNodeVisitor.VisitOperatorNode(
const InputExpressions: TArray<IExpressionNode>;
const InputExpressions: TArray<IAstNode>;
const CreateParentProc: TCreateParentNodeProc;
Alignment: TVerticalAlignment
): TAuraNode;
var
inputResults: TAuraNodeResultList;
inputNode: IExpressionNode;
inputNode: IAstNode;
startPosition: TPointF;
endY, maxChildWidth: Single;
parentNode: TAuraNode;