Pipes refactoring, Fixes in type checker

This commit is contained in:
Michael Schimmel
2026-02-13 23:34:39 +01:00
parent 19cdb2f004
commit dc46a2dd2d
10 changed files with 341 additions and 285 deletions
+62 -22
View File
@@ -38,6 +38,7 @@ uses
Myc.Ast,
Myc.Ast.Visitor,
Myc.Data.Decimal,
Myc.Data.Stream,
Myc.Ast.Script,
Myc.Ast.Types,
Myc.Ast.Environment,
@@ -92,6 +93,9 @@ type
CompilerStageBox: TComboBox;
SaveTestBtn: TButton;
SaveScriptButton: TButton;
Timer1: TTimer;
WatchLabel: TLabel;
procedure FormDestroy(Sender: TObject);
procedure InnerLambdaButtonClick(Sender: TObject);
procedure ClearButtonClick(Sender: TObject);
procedure CompilerStageBoxChange(Sender: TObject);
@@ -118,14 +122,17 @@ type
procedure LoadUserLibButtonClick(Sender: TObject);
procedure RTLListViewChange(Sender: TObject);
procedure SaveScriptButtonClick(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
FCurrUnboundAst: IAstNode;
FCurrCompiled: ILambdaExpressionNode;
FCurrExec: TCompiledFunction;
FCurrLambda: ILambdaExpressionNode;
FCurrCompiled: TCompiledFunction;
FCurrExec: TDataValue;
FEnvironment: TAstEnvironment;
FAstEditor: TAstEditor; // Die Komponente (Facade)
FScriptUpdate: Boolean;
FTriggerTest: TAstEnvironment;
FSim: IFinanceSimulator;
procedure AstEditorMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
@@ -152,12 +159,18 @@ uses
Myc.Trade.Broker,
System.Diagnostics, // For TStopwatch
System.TimeSpan,
Myc.Data.Keyword,
Myc.Ast.Json, // For TAstJson serialization
System.IOUtils, // For TFile
Myc.Ast.Dumper; // Needed for DumpButtonClick
{$R *.fmx}
procedure TForm1.FormDestroy(Sender: TObject);
begin
FSim := nil;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
// 1. Initialize Environment
@@ -262,6 +275,28 @@ begin
end
);
Scope.Define(
'watch',
function(const Args: TArray<TDataValue>): TDataValue
var
str: TStringBuilder;
begin
str := TStringBuilder.Create;
try
for var i := 0 to High(Args) do
begin
if Args[i].Kind = vkText then
str.Append(Args[i].AsText)
else
str.Append(Args[i].ToString);
end;
WatchLabel.Text := str.ToString;
finally
str.Free;
end;
end
);
Scope.Define(
'timestamp',
function(const Args: TArray<TDataValue>): TDataValue
@@ -291,13 +326,11 @@ begin
CompilerStageBox.BringToFront;
ClearButtonClick(Self);
FSim := TFinanceSimulator.Create;
FSim.CreateOHLCSeries(FEnvironment.RootScope, 'dax');
if FileExists(SrcName) then
ScriptMemo.Lines.LoadFromFile(SrcName);
// Memo1.Lines.Add(TAstSchema.GenerateFullSystemPrompt(FEnvironment.RootScope));
// "Dieses JSON-Objekt betest du in das Feld response_schema (Gemini) oder json_schema (OpenAI) ein."
// Memo1.Lines.Add(TAstSchema.GenerateFullSchema.ToJSON);
end;
procedure TForm1.ShowVizualization;
@@ -313,7 +346,7 @@ end;
function TForm1.ExecuteAst(const ANode: IAstNode): TDataValue;
begin
FCurrUnboundAst := ANode;
FCurrExec := Default(TCompiledFunction);
FCurrCompiled := Default(TCompiledFunction);
if DebugBox.IsChecked then
FEnvironment.SetDebugMode(Memo1.Lines, ShowScopeBox.IsChecked)
@@ -323,17 +356,18 @@ begin
try
// Use Compile directly. Errors will be raised as ECompilationFailed.
// We catch them to print to log, but allow flow to continue so UI can be updated.
FCurrCompiled := FEnvironment.Compile(ANode);
FCurrExec := FEnvironment.Link(FCurrCompiled);
FCurrLambda := FEnvironment.Compile(ANode);
FCurrCompiled := FEnvironment.Link(FCurrLambda);
if Assigned(FCurrExec.Func) then
if Assigned(FCurrCompiled.Func) then
begin
Memo1.Lines.Add(
Format('Compiled. Signature: %s, IsPure=%s', [FCurrExec.StaticType.ToString, BoolToStr(FCurrExec.IsPure, true)])
Format('Compiled. Signature: %s, IsPure=%s', [FCurrCompiled.StaticType.ToString, BoolToStr(FCurrCompiled.IsPure, true)])
);
end;
Result := FCurrExec.Func([]);
FCurrExec := FCurrCompiled.Func([]);
Result := FCurrExec;
except
on E: ECompilationFailed do
@@ -354,7 +388,7 @@ begin
end;
on E: Exception do
begin
FCurrExec.Func := nil;
FCurrCompiled.Func := nil;
Memo1.Lines.Add('--- RUNTIME ERROR ---');
Memo1.Lines.Add(E.ClassName + ': ' + E.Message);
Result := TDataValue.Void;
@@ -617,8 +651,8 @@ begin
Memo1.Lines.Add('--- Naive recursive fib with AST---');
FCurrCompiled := TestEnv.Compile(TAst.FunctionCall(TAst.Identifier('fib'), [TAst.Constant(25)]));
var fibExec := TestEnv.Link(FCurrCompiled).Func;
FCurrLambda := TestEnv.Compile(TAst.FunctionCall(TAst.Identifier('fib'), [TAst.Constant(25)]));
var fibExec := TestEnv.Link(FCurrLambda).Func;
sw := TStopwatch.StartNew;
result := fibExec([]);
@@ -781,8 +815,8 @@ begin
// Die Pipeline nutzt den Environment-Helper (Managed Record)
// Compile akzeptiert IAstNode und erzeugt intern ein Lambda
FCurrCompiled := FEnvironment.Compile(FCurrUnboundAst);
FCurrExec := FEnvironment.Link(FCurrCompiled);
FCurrLambda := FEnvironment.Compile(FCurrUnboundAst);
FCurrCompiled := FEnvironment.Link(FCurrLambda);
Memo1.Lines.Clear;
Memo1.Lines.Add('AST deserialized and bound successfully from JSON.');
@@ -1196,8 +1230,8 @@ end;
procedure TForm1.Test1ButtonClick(Sender: TObject);
begin
FCurrUnboundAst := TAstScript.Parse('(do (print txt))');
FCurrCompiled := FEnvironment.Compile(FCurrUnboundAst, [TAst.Identifier('txt')]);
var fn := FEnvironment.Link(FCurrCompiled).Func;
FCurrLambda := FEnvironment.Compile(FCurrUnboundAst, [TAst.Identifier('txt')]);
var fn := FEnvironment.Link(FCurrLambda).Func;
fn(['Hello World']);
FEnvironment.RootScope.Define('fn', fn);
UpdateScript;
@@ -1280,14 +1314,14 @@ begin
Memo1.Lines.Clear;
Memo1.Lines.Add('--- AST Dump ---');
if FCurrCompiled = nil then
if FCurrLambda = nil then
begin
Memo1.Lines.Add('No compiled AST available.');
exit;
end;
// Dump the raw unbound AST first
TAstDumper.Dump(FCurrCompiled, Memo1.Lines);
TAstDumper.Dump(FCurrLambda, Memo1.Lines);
end;
procedure TForm1.SaveScriptButtonClick(Sender: TObject);
@@ -1295,6 +1329,12 @@ begin
ScriptMemo.Lines.SaveToFile(SrcName);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if Assigned(FSim) then
FSim.AddRandomCandle(FEnvironment.RootScope, 'dax');
end;
initialization
TAst.RegisterLibrary(RegisterBroker);