From 521d0ac28f0ad2c7507d5d3f7012d1ce26bcc5cf Mon Sep 17 00:00:00 2001 From: Michael Schimmel Date: Fri, 28 Nov 2025 16:07:47 +0100 Subject: [PATCH] Ast editor rondtrip --- ASTPlayground/ASTPlayground.delphilsp.json | 2 +- ASTPlayground/ASTPlayground.dpr | 3 +- ASTPlayground/ASTPlayground.dproj | 1 + ASTPlayground/MainForm.pas | 1554 +++++++++----------- Src/AST/Myc.Ast.Compiler.Binder.pas | 8 +- Src/AST/Myc.Ast.Compiler.Specializer.pas | 17 - Src/AST/Myc.Ast.Environment.pas | 95 +- Src/AST/Myc.Ast.Nodes.pas | 17 + Src/AST/Myc.Ast.Visitor.pas | 201 ++- Src/AST/Myc.Fmx.AstEditor.Controller.pas | 258 ++++ 10 files changed, 1247 insertions(+), 909 deletions(-) create mode 100644 Src/AST/Myc.Fmx.AstEditor.Controller.pas diff --git a/ASTPlayground/ASTPlayground.delphilsp.json b/ASTPlayground/ASTPlayground.delphilsp.json index c8efac4..0459e48 100644 --- a/ASTPlayground/ASTPlayground.delphilsp.json +++ b/ASTPlayground/ASTPlayground.delphilsp.json @@ -1 +1 @@ -{ "settings": { "project": "file:///T%3A/Myc/ASTPlayground/ASTPlayground.dpr", "dllname": "dcc64370.dll", "dccOptions": "-$O- -$W+ --inline:off -$R+ -$Q+ --no-config -Q -TX.exe -AGenerics.Collections=System.Generics.Collections;Generics.Defaults=System.Generics.Defaults;WinTypes=Winapi.Windows;WinProcs=Winapi.Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE -DDEBUG;;FRAMEWORK_FMX -E.\\Win64\\Debug -I\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\\DE\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -LEC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Bpl\\Win64 -LNC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64 -NU.\\Win64\\Debug -NSWinapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;System;Xml;Data;Datasnap;Web;Soap; -OT:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -R\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -U\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\\DE\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -V -VN -VR -NBC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64 -NHC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\hpp\\Win64 -NO.\\Win64\\Debug -LU" , "projectFiles":[ { "name": "MainForm", "file": "file:///T%3A/Myc/ASTPlayground/MainForm.pas" }, { "name": "Myc.Ast.Nodes", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Nodes.pas" }, { "name": "Myc.Ast.Scope", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Scope.pas" }, { "name": "Myc.Data.Value", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Data.Value.pas" }, { "name": "Myc.Ast.Visitor", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Visitor.pas" }, { "name": "Myc.Ast.RTL", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.pas" }, { "name": "Myc.Ast.Dumper", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Dumper.pas" }, { "name": "Myc.Ast.RTL.Core", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.Core.pas" }, { "name": "Myc.Utils", "file": "file:///T%3A/Myc/Src/Myc.Utils.pas" }, { "name": "Myc.Ast.Script", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Script.pas" }, { "name": "Myc.Ast.Types", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Types.pas" }, { "name": "Myc.Data.Keyword", "file": "file:///T%3A/Myc/Src/Data/Myc.Data.Keyword.pas" }, { "name": "Myc.Ast.Compiler.TCO", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.TCO.pas" }, { "name": "Myc.Ast.Compiler.Binder", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Binder.pas" }, { "name": "Myc.Ast.Compiler.Lowering", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Lowering.pas" }, { "name": "Myc.Ast.Compiler.TypeChecker", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.TypeChecker.pas" }, { "name": "Myc.Ast.Compiler.Macros", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Macros.pas" }, { "name": "Myc.Ast.Compiler.Specializer", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Specializer.pas" }, { "name": "Myc.Ast.Environment", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Environment.pas" }, { "name": "Myc.Ast.Debugger", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Debugger.pas" }, { "name": "Myc.Ast.Analysis.Purity", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Analysis.Purity.pas" }, { "name": "Myc.Ast.Identities", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Identities.pas" }, { "name": "Myc.Fmx.AstEditor.Core", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Core.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.pas" }, { "name": "Myc.Fmx.AstEditor.Visualizer", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Visualizer.pas" }, { "name": "Myc.Fmx.AstEditor.Workspace", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Workspace.pas" } ] , "includeDCUsInUsesCompletion": true, "enableKeyWordCompletion": true, "browsingPaths": [ "file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/OCX/Servers","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/VCL","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/RTL/SYS","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/win","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/win/winrt","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/ToolsAPI","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/IBX","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Internet","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/PROPERTY%20EDITORS","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/soap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/XML","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/Core","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/System","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/Protocols","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/fmx","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/components","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/engine","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/graph","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/ado","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/cloud","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/dbx","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/dsnap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/vclctrls","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap/connectors","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap/proxygen","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DataExplorer","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/Common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/Common/dunit","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/Common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/DUnitProject","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/DUnitProject/dunit","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/src","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/tests","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Experts","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indy/abstraction","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indy/implementation","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indyimpl","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Property%20Editors/Indy10","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/soap/wsdlimporter","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Visualizers","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/XMLReporting","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/XPGen","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/rest","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/firedac","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/tethering","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnitX","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/ems","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/net","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/FlatBox2D","file:///C%3A/Users/Public/Documents/Embarcadero/Studio/37.0/Dcp/%25PLATFORM%25","file:///%25TP%25/runtime/vcl","file:///S%3A/sc_famos_src/svn_vcl/cpxedits","file:///S%3A/sc_famos_src/svn_vcl/dzChart","file:///S%3A/sc_famos_src/svn_vcl/eaeditor","file:///S%3A/sc_famos_src/svn_vcl/FamosEvents","file:///S%3A/sc_famos_src/svn_vcl/HTML_Viewer/source","file:///S%3A/sc_famos_src/svn_vcl/Myc_ChartEdit","file:///S%3A/sc_famos_src/svn_vcl/Myc_HemiDrag","file:///S%3A/sc_famos_src/svn_vcl/Myc_SplitControl","file:///S%3A/sc_famos_src/svn_vcl/NiceChart","file:///S%3A/sc_famos_src/svn_vcl/plotter","file:///S%3A/sc_famos_src/svn_vcl/SimpleIPC","file:///S%3A/sc_famos_src/svn_vcl/SynEdit-master/Source","file:///S%3A/sc_famos_src/svn_vcl/ValEdits","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster/zlib","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster/zlib/win32","file:///S%3A/sc_famos_src/svn_vcl/Virtual-TreeView/Source","file:///S%3A/sc_famos_src/svn_common/caHelpSys","file:///S%3A/sc_famos_src/svn_common/Misc","file:///S%3A/sc_famos_src/svn_common/Myc_VecMath","file:///S%3A/sc_famos_src/svn_common/PascalScript/source","file:///S%3A/sc_famos_src/svn_common/TreeBase","file:///S%3A/sc_famos_src/svn_common/TreeBase/Medien","file:///S%3A/3rdParty/spring4d/Source","file:///S%3A/3rdParty/spring4d/Source/Base","file:///S%3A/3rdParty/spring4d/Source/Base/Collections","file:///S%3A/3rdParty/spring4d/Source/Base/Logging","file:///S%3A/3rdParty/spring4d/Source/Base/Patches","file:///S%3A/3rdParty/spring4d/Source/Core/Container","file:///S%3A/3rdParty/spring4d/Source/Core/Interception","file:///S%3A/3rdParty/spring4d/Source/Core/Logging","file:///S%3A/3rdParty/spring4d/Source/Core/Mocking","file:///S%3A/3rdParty/spring4d/Source/Core/Services","file:///S%3A/3rdParty/spring4d/Source/Extensions/Cryptography","file:///S%3A/3rdParty/spring4d/Source/Extensions/Utils","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressCore%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressCommon%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressGDI%2B%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressLibrary/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/XP%20Theme%20Manager/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressLayout%20Control/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressPageControl/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressEditors%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressDocking%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressBars/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressOfficeCore%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressMemData/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressDataController/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressNavBar/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressSkins%20Library/Sources","file:///T%3A/Myc/Src","file:///T%3A/Myc/Src/Data","file:///T%3A/Myc/Src/AST" ] , "CommonAppData": "file:///C%3A/Users/Brummel/AppData/Roaming/Embarcadero/BDS/37.0/" , "Templates": "file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/ObjRepos/" } } \ No newline at end of file +{ "settings": { "project": "file:///T%3A/Myc/ASTPlayground/ASTPlayground.dpr", "dllname": "dcc64370.dll", "dccOptions": "-$O- -$W+ --inline:off -$R+ -$Q+ --no-config -Q -TX.exe -AGenerics.Collections=System.Generics.Collections;Generics.Defaults=System.Generics.Defaults;WinTypes=Winapi.Windows;WinProcs=Winapi.Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE -DDEBUG;;FRAMEWORK_FMX -E.\\Win64\\Debug -I\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\\DE\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -LEC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Bpl\\Win64 -LNC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64 -NU.\\Win64\\Debug -NSWinapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;System;Xml;Data;Datasnap;Web;Soap; -OT:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -R\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -U\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\\DE\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -V -VN -VR -NBC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64 -NHC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\hpp\\Win64 -NO.\\Win64\\Debug -LU" , "projectFiles":[ { "name": "MainForm", "file": "file:///T%3A/Myc/ASTPlayground/MainForm.pas" }, { "name": "Myc.Ast.Nodes", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Nodes.pas" }, { "name": "Myc.Ast.Scope", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Scope.pas" }, { "name": "Myc.Data.Value", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Data.Value.pas" }, { "name": "Myc.Ast.Visitor", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Visitor.pas" }, { "name": "Myc.Ast.RTL", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.pas" }, { "name": "Myc.Ast.Dumper", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Dumper.pas" }, { "name": "Myc.Ast.RTL.Core", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.Core.pas" }, { "name": "Myc.Utils", "file": "file:///T%3A/Myc/Src/Myc.Utils.pas" }, { "name": "Myc.Ast.Script", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Script.pas" }, { "name": "Myc.Ast.Types", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Types.pas" }, { "name": "Myc.Data.Keyword", "file": "file:///T%3A/Myc/Src/Data/Myc.Data.Keyword.pas" }, { "name": "Myc.Ast.Compiler.TCO", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.TCO.pas" }, { "name": "Myc.Ast.Compiler.Binder", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Binder.pas" }, { "name": "Myc.Ast.Compiler.Lowering", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Lowering.pas" }, { "name": "Myc.Ast.Compiler.TypeChecker", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.TypeChecker.pas" }, { "name": "Myc.Ast.Compiler.Macros", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Macros.pas" }, { "name": "Myc.Ast.Compiler.Specializer", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Specializer.pas" }, { "name": "Myc.Ast.Environment", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Environment.pas" }, { "name": "Myc.Ast.Debugger", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Debugger.pas" }, { "name": "Myc.Ast.Analysis.Purity", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Analysis.Purity.pas" }, { "name": "Myc.Ast.Identities", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Identities.pas" }, { "name": "Myc.Fmx.AstEditor.Core", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Core.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.pas" }, { "name": "Myc.Fmx.AstEditor.Visualizer", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Visualizer.pas" }, { "name": "Myc.Fmx.AstEditor.Workspace", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Workspace.pas" }, { "name": "Myc.Fmx.AstEditor.Controller", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Controller.pas" } ] , "includeDCUsInUsesCompletion": true, "enableKeyWordCompletion": false, "browsingPaths": [ "file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/OCX/Servers","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/VCL","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/RTL/SYS","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/win","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/win/winrt","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/ToolsAPI","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/IBX","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Internet","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/PROPERTY%20EDITORS","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/soap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/XML","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/Core","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/System","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/Protocols","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/fmx","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/components","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/engine","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/graph","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/ado","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/cloud","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/dbx","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/dsnap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/vclctrls","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap/connectors","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap/proxygen","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DataExplorer","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/Common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/Common/dunit","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/Common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/DUnitProject","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/DUnitProject/dunit","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/src","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/tests","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Experts","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indy/abstraction","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indy/implementation","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indyimpl","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Property%20Editors/Indy10","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/soap/wsdlimporter","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Visualizers","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/XMLReporting","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/XPGen","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/rest","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/firedac","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/tethering","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnitX","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/ems","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/net","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/FlatBox2D","file:///C%3A/Users/Public/Documents/Embarcadero/Studio/37.0/Dcp/%25PLATFORM%25","file:///%25TP%25/runtime/vcl","file:///S%3A/sc_famos_src/svn_vcl/cpxedits","file:///S%3A/sc_famos_src/svn_vcl/dzChart","file:///S%3A/sc_famos_src/svn_vcl/eaeditor","file:///S%3A/sc_famos_src/svn_vcl/FamosEvents","file:///S%3A/sc_famos_src/svn_vcl/HTML_Viewer/source","file:///S%3A/sc_famos_src/svn_vcl/Myc_ChartEdit","file:///S%3A/sc_famos_src/svn_vcl/Myc_HemiDrag","file:///S%3A/sc_famos_src/svn_vcl/Myc_SplitControl","file:///S%3A/sc_famos_src/svn_vcl/NiceChart","file:///S%3A/sc_famos_src/svn_vcl/plotter","file:///S%3A/sc_famos_src/svn_vcl/SimpleIPC","file:///S%3A/sc_famos_src/svn_vcl/SynEdit-master/Source","file:///S%3A/sc_famos_src/svn_vcl/ValEdits","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster/zlib","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster/zlib/win32","file:///S%3A/sc_famos_src/svn_vcl/Virtual-TreeView/Source","file:///S%3A/sc_famos_src/svn_common/caHelpSys","file:///S%3A/sc_famos_src/svn_common/Misc","file:///S%3A/sc_famos_src/svn_common/Myc_VecMath","file:///S%3A/sc_famos_src/svn_common/PascalScript/source","file:///S%3A/sc_famos_src/svn_common/TreeBase","file:///S%3A/sc_famos_src/svn_common/TreeBase/Medien","file:///S%3A/3rdParty/spring4d/Source","file:///S%3A/3rdParty/spring4d/Source/Base","file:///S%3A/3rdParty/spring4d/Source/Base/Collections","file:///S%3A/3rdParty/spring4d/Source/Base/Logging","file:///S%3A/3rdParty/spring4d/Source/Base/Patches","file:///S%3A/3rdParty/spring4d/Source/Core/Container","file:///S%3A/3rdParty/spring4d/Source/Core/Interception","file:///S%3A/3rdParty/spring4d/Source/Core/Logging","file:///S%3A/3rdParty/spring4d/Source/Core/Mocking","file:///S%3A/3rdParty/spring4d/Source/Core/Services","file:///S%3A/3rdParty/spring4d/Source/Extensions/Cryptography","file:///S%3A/3rdParty/spring4d/Source/Extensions/Utils","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressCore%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressCommon%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressGDI%2B%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressLibrary/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/XP%20Theme%20Manager/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressLayout%20Control/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressPageControl/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressEditors%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressDocking%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressBars/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressOfficeCore%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressMemData/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressDataController/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressNavBar/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressSkins%20Library/Sources","file:///T%3A/Myc/Src","file:///T%3A/Myc/Src/Data","file:///T%3A/Myc/Src/AST" ] , "CommonAppData": "file:///C%3A/Users/Brummel/AppData/Roaming/Embarcadero/BDS/37.0/" , "Templates": "file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/ObjRepos/" } } \ No newline at end of file diff --git a/ASTPlayground/ASTPlayground.dpr b/ASTPlayground/ASTPlayground.dpr index 8404838..1918d00 100644 --- a/ASTPlayground/ASTPlayground.dpr +++ b/ASTPlayground/ASTPlayground.dpr @@ -29,7 +29,8 @@ uses Myc.Fmx.AstEditor.Core in '..\Src\AST\Myc.Fmx.AstEditor.Core.pas', Myc.Fmx.AstEditor.Handlers in '..\Src\AST\Myc.Fmx.AstEditor.Handlers.pas', Myc.Fmx.AstEditor.Visualizer in '..\Src\AST\Myc.Fmx.AstEditor.Visualizer.pas', - Myc.Fmx.AstEditor.Workspace in '..\Src\AST\Myc.Fmx.AstEditor.Workspace.pas'; + Myc.Fmx.AstEditor.Workspace in '..\Src\AST\Myc.Fmx.AstEditor.Workspace.pas', + Myc.Fmx.AstEditor.Controller in '..\Src\AST\Myc.Fmx.AstEditor.Controller.pas'; {$R *.res} diff --git a/ASTPlayground/ASTPlayground.dproj b/ASTPlayground/ASTPlayground.dproj index 3e51201..bef716e 100644 --- a/ASTPlayground/ASTPlayground.dproj +++ b/ASTPlayground/ASTPlayground.dproj @@ -160,6 +160,7 @@ + Base diff --git a/ASTPlayground/MainForm.pas b/ASTPlayground/MainForm.pas index cffeda6..1010e21 100644 --- a/ASTPlayground/MainForm.pas +++ b/ASTPlayground/MainForm.pas @@ -22,6 +22,15 @@ uses FMX.ScrollBox, FMX.Memo, FMX.Controls.Presentation, + FMX.Layouts, + FMX.Objects, + FMX.DialogService, + FMX.ListView.Types, + FMX.ListView.Appearances, + FMX.ListView.Adapters.Base, + FMX.ListView, + FMX.ListBox, + // Myc Units Myc.Data.Scalar, Myc.Data.Value, Myc.Ast.Nodes, @@ -30,18 +39,14 @@ uses Myc.Ast.Visitor, Myc.Data.Decimal, Myc.Ast.Script, - FMX.Layouts, - FMX.Objects, + Myc.Ast.Types, + Myc.Ast.Environment, + Myc.Ast.RTL, + Myc.Ast.Compiler.Macros, + // Editor Units Myc.Fmx.AstEditor.Core, Myc.Fmx.AstEditor.Workspace, - FMX.DialogService, - FMX.ListView.Types, - FMX.ListView.Appearances, - FMX.ListView.Adapters.Base, - FMX.ListView, - Myc.Ast.Compiler.Specializer, - Myc.Ast.Environment, - FMX.ListBox; // Added Environment + Myc.Fmx.AstEditor.Controller; // Controller integration type // A test record @@ -88,6 +93,7 @@ type procedure ClearButtonClick(Sender: TObject); procedure CompilerStageBoxChange(Sender: TObject); procedure FormCreate(Sender: TObject); + procedure FormDestroy(Sender: TObject); procedure CreateTriggerExampleButtonClick(Sender: TObject); procedure DebugBoxChange(Sender: TObject); procedure DoTrigger2ButtonClick(Sender: TObject); @@ -114,6 +120,7 @@ type FCurrExec: TCompiledFunction; FEnvironment: TAstEnvironment; FWorkspace: TAstWorkspace; + FController: TAstEditorController; // The UI Controller FScriptUpdate: Boolean; FTriggerTest: TAstEnvironment; @@ -124,7 +131,6 @@ type procedure UpdateScript; procedure ShowVizualization(X, Y: Single); procedure PrintScript(const Node: IAstNode); - function CompileAstStage: IAstNode; public { Public declarations } end; @@ -142,190 +148,27 @@ uses System.Diagnostics, // For TStopwatch System.TimeSpan, Myc.Ast.Json, // For TAstJson serialization - Myc.Ast.Types, // Needed for TTypeRules System.IOUtils, // For TFile - Myc.Ast.Dumper, // Needed for DumpButtonClick - Myc.Ast.RTL, - Myc.Ast.Compiler.Macros; // Needed for MacroRegistry access + Myc.Ast.Dumper; // Needed for DumpButtonClick {$R *.fmx} -procedure TForm1.InnerLambdaButtonClick(Sender: TObject); -var - mainBlock: IAstNode; - resultValue: TDataValue; - resInt: Int64; -begin - Memo1.Lines.Clear; - Memo1.Lines.Add('--- Nested Lambda & Upvalue Mutation Test ---'); - Memo1.Lines.Add('Scenario: outer() -> defines x=10'); - Memo1.Lines.Add(' inner() -> calls innermost()'); - Memo1.Lines.Add(' innermost() -> captures x, adds 5'); - Memo1.Lines.Add('Expected Result: 15'); - - mainBlock := - TAst.Block( - [ - TAst.VarDecl( - TAst.Identifier('outer'), - TAst.LambdaExpr( - [], - TAst.Block( - [ - TAst.VarDecl(TAst.Identifier('x'), TAst.Constant(10)), - TAst.VarDecl( - TAst.Identifier('inner'), - TAst.LambdaExpr( - [], - TAst.Block( - [ - TAst.VarDecl( - TAst.Identifier('innermost'), - TAst.LambdaExpr( - [], - TAst.Assign( - TAst.Identifier('x'), - // --- Ersetzt --- - TAst.FunctionCall( - TAst.Identifier('+'), - [TAst.Identifier('x'), TAst.Constant(5)] - ) - ) - ) - ), - TAst.FunctionCall(TAst.Identifier('innermost'), []) - ] - ) - ) - ), - TAst.FunctionCall(TAst.Identifier('inner'), []), - TAst.Identifier('x') - ] - ) - ) - ), - TAst.VarDecl(TAst.Identifier('finalResult'), TAst.FunctionCall(TAst.Identifier('outer'), [])) - ] - ); - - resultValue := ExecuteAst(mainBlock); - - if (resultValue.Kind = vkScalar) and (resultValue.AsScalar.Kind = TScalar.TKind.Ordinal) then - begin - resInt := resultValue.AsScalar.Value.AsInt64; - Memo1.Lines.Add(Format('Actual Result: %d', [resInt])); - - if resInt = 15 then - Memo1.Lines.Add('SUCCESS: Deeply nested closure modified captured variable correctly.') - else - Memo1.Lines.Add(Format('FAILURE: Upvalue logic broken. Expected 15, got %d.', [resInt])); - end - else - Memo1.Lines.Add('FAILURE: Result is not an integer scalar.'); - - Assert(TScalar.FromInt64(15) = resultValue.AsScalar, 'The final result should be 15, but is ' + resultValue.AsScalar.ToString); - UpdateScript; -end; - -procedure TForm1.ClearButtonClick(Sender: TObject); -begin - FWorkspace.DeleteChildren; - FWorkspace.Repaint; -end; - -function TForm1.CompileAstStage: IAstNode; -begin - Result := FCurrUnboundAst; - - if CompilerStageBox.ItemIndex > 0 then - begin - Result := FEnvironment.Environment.ExpandMacros(Result); - - if CompilerStageBox.ItemIndex > 1 then - begin - var layout: IScopeLayout; - // Bind now returns the bound AST and provides the layout - Result := FEnvironment.Environment.Bind(Result, layout, [], nil); - - if CompilerStageBox.ItemIndex > 2 then - // Specialize no longer needs descriptor - Result := FEnvironment.Environment.Specialize(Result); - end; - end; -end; - -procedure TForm1.CompilerStageBoxChange(Sender: TObject); -begin - ShowVizualization(14, 14); -end; - -// Simplified ExecuteAst using TEnvironment -function TForm1.ExecuteAst(const ANode: IAstNode): TDataValue; -begin - FCurrUnboundAst := ANode; - FCurrExec := Default(TCompiledFunction); - - // 1. Set strategy based on UI - if DebugBox.IsChecked then - FEnvironment.SetDebugMode(Memo1.Lines, ShowScopeBox.IsChecked) - else - FEnvironment.SetStandardMode; - - try - // Wrap in Lambda to compile - var funcDef := TAst.LambdaExpr([], ANode); - FCurrExec := FEnvironment.Compile(funcDef); - - if Assigned(FCurrExec.Func) then - begin - Memo1.Lines.Add( - Format('Compiled. Signature: %s, IsPure=%s', [FCurrExec.StaticType.ToString, BoolToStr(FCurrExec.IsPure, true)]) - ); - end; - - Result := FCurrExec.Func([]); - - except - on E: ECompilationFailed do - begin - Memo1.Lines.BeginUpdate; - try - Memo1.Lines.Clear; - // Die Hauptnachricht der Exception (z.B. "Compilation failed with 5 error(s)...") - Memo1.Lines.Add(E.Message); - Memo1.Lines.Add(''); // Leerzeile zur optischen Trennung - - // Iteration durch alle gesammelten Fehler im Log - for var err in E.Errors do - begin - // err.ToString formatiert automatisch als "[Error] Nachricht" etc. - Memo1.Lines.Add(err.ToString); - end; - finally - Memo1.Lines.EndUpdate; - end; - end; - on E: Exception do - begin - FCurrExec.Func := nil; - Memo1.Lines.Add('--- ERROR ---'); - Memo1.Lines.Add(E.ClassName + ': ' + E.Message); - Result := TDataValue.Void; - end; - end; -end; - procedure TForm1.FormCreate(Sender: TObject); begin + // 1. Initialize Environment FEnvironment := TAstEnvironment.Construct(TAst.CreateScope(nil)); + // 2. Initialize Workspace FWorkspace := TAstWorkspace.Create(Panel2); FWorkspace.Parent := Panel2; FWorkspace.Align := TAlignLayout.Client; FWorkspace.ClipChildren := true; FWorkspace.OnMouseDown := WorkspaceMouseDown; - // Register the SMA factory into the environment + // 3. Initialize Controller (connects Env and Workspace) + FController := TAstEditorController.Create(FEnvironment, FWorkspace); + + // 4. Register the SMA factory into the environment var RegFunc := procedure(const Scope: IExecutionScope) var @@ -344,20 +187,16 @@ begin [ TAst.Assign( TAst.Identifier('sum'), - // --- Ersetzt --- TAst.FunctionCall(TAst.Identifier('+'), [TAst.Identifier('sum'), TAst.Identifier('val')]) ), TAst.Assign( TAst.Identifier('count'), - // --- Ersetzt --- TAst.FunctionCall(TAst.Identifier('+'), [TAst.Identifier('count'), TAst.Constant(1)]) ), TAst.Assign( TAst.Identifier('sum'), TAst.TernaryExpr( - // --- Ersetzt --- TAst.FunctionCall(TAst.Identifier('>'), [TAst.Identifier('count'), TAst.Identifier('len')]), - // --- Ersetzt --- TAst.FunctionCall( TAst.Identifier('-'), [ @@ -368,13 +207,11 @@ begin TAst.Identifier('sum') ) ), - // --- Ersetzt --- TAst.FunctionCall( TAst.Identifier('/'), [ TAst.Identifier('sum'), TAst.TernaryExpr( - // --- Ersetzt --- TAst.FunctionCall( TAst.Identifier('<'), [TAst.Identifier('count'), TAst.Identifier('len')] @@ -393,7 +230,7 @@ begin var smaFactory := FEnvironment.Run(smaAst); - Scope.Define('CreateSMA', smaFactory); // Define the factory + Scope.Define('CreateSMA', smaFactory); Scope.Define( 'print', @@ -428,7 +265,6 @@ begin RegFunc(FEnvironment.RootScope); - // Register the 'stopwatch' macro into the global registry FEnvironment.MacroRegistry.Define( TAstScript .Parse( @@ -448,297 +284,297 @@ begin ClearButtonClick(Self); end; -procedure TForm1.LoadUserLibButtonClick(Sender: TObject); -var - jsonString: string; - jsonObj: TJSONObject; - pair: TJSONPair; - funcAst: IAstNode; - funcValue: TDataValue; - converter: IJsonAstConverter; - addr: TResolvedAddress; // Variable für das Ergebnis von Resolve +procedure TForm1.FormDestroy(Sender: TObject); begin - // Load definitions from JSON and populate the global scope. - if not TFile.Exists(UserLibName) then - begin - Memo1.Lines.Add(Format('Library file "%s" not found.', [UserLibName])); + FController.Free; +end; + +procedure TForm1.ShowVizualization(X, Y: Single); +begin + if FCurrUnboundAst = nil then exit; - end; - try - converter := TJsonAstConverter.Create; - jsonString := TFile.ReadAllText(UserLibName); - jsonObj := TJSONObject.ParseJSONValue(jsonString) as TJSONObject; - if not Assigned(jsonObj) then - raise Exception.Create('Invalid JSON format for library file.'); - - try - Memo1.Lines.Add(Format('--- Loading User Library from %s ---', [ExtractFileName(UserLibName)])); - - // Populate the list view with loaded functions and macros. - RTLListView.Items.BeginUpdate; - try - for pair in jsonObj do - begin - if not (pair.JsonValue is TJSONObject) then - continue; - - // First, deserialize the AST node from JSON. - funcAst := converter.Deserialize(pair.JsonValue as TJSONObject); - - // KORREKTUR: Statt Descriptor.FindSymbol nutzen wir Scope.Resolve - addr := FEnvironment.RootScope.Resolve(pair.JsonString.Value); - - if addr.Kind = akUnresolved then - begin - // Distinguish between loading a macro and loading a function. - if funcAst.Kind = akMacroDefinition then - begin - // Macros are stored in the *global compile-time registry*. - FEnvironment.MacroRegistry.Define(funcAst.AsMacroDefinition); - Memo1.Lines.Add(Format('Defined macro "%s"', [pair.JsonString.Value])); - end - else - begin - // Functions (lambdas) must be executed to create a callable closure. - funcValue := ExecuteAst(funcAst); - FEnvironment.RootScope.Define(pair.JsonString.Value, funcValue); - Memo1.Lines.Add(Format('Defined function "%s"', [pair.JsonString.Value])); - end; - end - else - Memo1.Lines.Add(Format('Symbol "%s" already defined', [pair.JsonString.Value])); - - // Add the new function/macro to the RTL list view. - RTLListView.Items.Add.Text := pair.JsonString.Value; - end; - finally - RTLListView.Items.EndUpdate; - end; - finally - jsonObj.Free; - end; - except - on E: Exception do - Memo1.Lines.Add('Error loading library: ' + E.Message); - end; + // Use the Controller to build, validate and show the UI + FController.SetRoot(FCurrUnboundAst); end; -procedure TForm1.SaveUserLibButtonClick(Sender: TObject); -var - rootNode: IAstNode; - definitions: TDictionary; - jsonLib: TJSONObject; - converter: IJsonAstConverter; - jsonString: string; - updatedCount: Integer; - addedList: TList; +// Simplified ExecuteAst using TEnvironment and handling errors gracefully +function TForm1.ExecuteAst(const ANode: IAstNode): TDataValue; begin - // Extract definitions from the current script and merge them into the JSON library. + FCurrUnboundAst := ANode; + FCurrExec := Default(TCompiledFunction); + + if DebugBox.IsChecked then + FEnvironment.SetDebugMode(Memo1.Lines, ShowScopeBox.IsChecked) + else + FEnvironment.SetStandardMode; + try - rootNode := TAstScript.Parse(ScriptMemo.Lines.Text); - if not Assigned(rootNode) then - raise Exception.Create('Script is empty or invalid.'); + // 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. + FCurrExec := FEnvironment.Compile(ANode); - definitions := TDictionary.Create; - try - // Check if the root is a block and extract top-level definitions - if rootNode.Kind = akBlockExpression then - begin - for var expr in rootNode.AsBlockExpression.Expressions do - begin - // Use interface 'is' check - if (expr.Kind = akVariableDeclaration) then - begin - var decl := expr.AsVariableDeclaration; - definitions.Add(decl.Target.AsIdentifier.Name, decl.Initializer); - end - // Handle macro definitions inside the block - else if expr.Kind = akMacroDefinition then - begin - var macroDef := expr.AsMacroDefinition; - // Store the entire macro definition node for serialization. - definitions.Add(macroDef.Name.Name, macroDef); - end; - end; - end - // Use interface 'is' check - else if rootNode.Kind = akVariableDeclaration then // Handle single definition - begin - var decl := rootNode.AsVariableDeclaration; - definitions.Add(decl.Target.AsIdentifier.Name, decl.Initializer); - end - // Handle a single macro definition - else if rootNode.Kind = akMacroDefinition then - begin - var macroDef := rootNode.AsMacroDefinition; - definitions.Add(macroDef.Name.Name, macroDef); - end; - - if definitions.Count = 0 then - begin - Memo1.Lines.Add('No top-level "(def ...)" or "(defmacro ...)" definitions found in the script to save.'); - exit; - end; - - // Load existing library file or create a new JSON object if it doesn't exist - jsonLib := nil; - if TFile.Exists(UserLibName) then - begin - jsonString := TFile.ReadAllText(UserLibName); - if not jsonString.IsEmpty then - jsonLib := TJSONObject.ParseJSONValue(jsonString) as TJSONObject; - end; - - if not Assigned(jsonLib) then - jsonLib := TJSONObject.Create; - - addedList := TList.Create; - try - // Serialize and merge the definitions from the script into the JSON object - converter := TJsonAstConverter.Create; - updatedCount := 0; - - for var pair in definitions do - begin - // Track if we are adding or updating a function/macro - if jsonLib.Values[pair.Key] <> nil then - begin - Inc(updatedCount); - jsonLib.RemovePair(pair.Key); - end - else - addedList.Add(pair.Key); - - jsonLib.AddPair(pair.Key, converter.Serialize(pair.Value)); - end; - - TFile.WriteAllText(UserLibName, jsonLib.Format(4)); - - // Provide more detailed feedback to the user - Memo1.Lines.Add(Format('--- Library "%s" updated ---', [ExtractFileName(UserLibName)])); - if updatedCount > 0 then - Memo1.Lines.Add(Format('%d existing definitions updated.', [updatedCount])); - if addedList.Count > 0 then - begin - Memo1.Lines.Add(Format('%d new definitions added:', [addedList.Count])); - // Add the new item to the RTL list view. - RTLListView.Items.BeginUpdate; - try - for var n in addedList do - begin - Memo1.Lines.Add(n); - RTLListView.Items.Add.Text := n; - end; - finally - RTLListView.Items.EndUpdate; - end; - end; - finally - jsonLib.Free; - addedList.Free; - end; - finally - definitions.Free; - end; - except - on E: Exception do - Memo1.Lines.Add('Error saving library: ' + E.Message); - end; -end; - -procedure TForm1.FromJSONButtonClick(Sender: TObject); -var - jsonString: string; - jsonObj: TJSONObject; - converter: IJsonAstConverter; -begin - Memo1.Lines.BeginUpdate; - try - jsonString := Memo1.Lines.Text; - Memo1.Lines.Clear; - - if jsonString.IsEmpty then + if Assigned(FCurrExec.Func) then begin - Memo1.Lines.Add('Memo is empty. Please paste an AST JSON string.'); - exit; + Memo1.Lines.Add( + Format('Compiled. Signature: %s, IsPure=%s', [FCurrExec.StaticType.ToString, BoolToStr(FCurrExec.IsPure, true)]) + ); end; - try - converter := TJsonAstConverter.Create; - jsonObj := TJSONObject.ParseJSONValue(jsonString) as TJSONObject; - if not Assigned(jsonObj) then - raise EJSONParseException.Create('Invalid JSON format.'); + Result := FCurrExec.Func([]); + except + on E: ECompilationFailed do + begin + Memo1.Lines.BeginUpdate; try - FCurrUnboundAst := converter.Deserialize(jsonObj); - - // Run the full pipeline via environment - FCurrExec := FEnvironment.Compile(FCurrUnboundAst); - - Memo1.Lines.Add('AST deserialized and bound successfully from JSON.'); - Memo1.Lines.Add('You can now visualize it (Middle Mouse Click) or pretty-print it.'); - finally - jsonObj.Free; - end; - except - on E: Exception do - begin - Memo1.Lines.Add('Error deserializing AST from JSON:'); + Memo1.Lines.Clear; Memo1.Lines.Add(E.Message); - Memo1.Lines.Add('--- Original JSON ---'); - Memo1.Lines.Text := Memo1.Lines.Text + sLineBreak + jsonString; + Memo1.Lines.Add(''); + for var err in E.Errors do + Memo1.Lines.Add(err.ToString); + finally + Memo1.Lines.EndUpdate; end; + + // Return void so caller doesn't crash, but UI will show red nodes via ShowVizualization + Result := TDataValue.Void; + end; + on E: Exception do + begin + FCurrExec.Func := nil; + Memo1.Lines.Add('--- RUNTIME ERROR ---'); + Memo1.Lines.Add(E.ClassName + ': ' + E.Message); + Result := TDataValue.Void; end; - finally - Memo1.Lines.EndUpdate; end; +end; + +procedure TForm1.InnerLambdaButtonClick(Sender: TObject); +begin + Memo1.Lines.Clear; + Memo1.Lines.Add('--- Nested Lambda & Upvalue Mutation Test ---'); + + var mainBlock := + TAst.Block( + [ + TAst.VarDecl( + TAst.Identifier('outer'), + TAst.LambdaExpr( + [], + TAst.Block( + [ + TAst.VarDecl(TAst.Identifier('x'), TAst.Constant(10)), + TAst.VarDecl( + TAst.Identifier('inner'), + TAst.LambdaExpr( + [], + TAst.Block( + [ + TAst.VarDecl( + TAst.Identifier('innermost'), + TAst.LambdaExpr( + [], + TAst.Assign( + TAst.Identifier('x'), + TAst.FunctionCall( + TAst.Identifier('+'), + [TAst.Identifier('x'), TAst.Constant(5)] + ) + ) + ) + ), + TAst.FunctionCall(TAst.Identifier('innermost'), []) + ] + ) + ) + ), + TAst.FunctionCall(TAst.Identifier('inner'), []), + TAst.Identifier('x') + ] + ) + ) + ), + TAst.VarDecl(TAst.Identifier('finalResult'), TAst.FunctionCall(TAst.Identifier('outer'), [])) + ] + ); + + var resultValue := ExecuteAst(mainBlock); + + if (resultValue.Kind = vkScalar) and (resultValue.AsScalar.Kind = TScalar.TKind.Ordinal) then + begin + var resInt := resultValue.AsScalar.Value.AsInt64; + Memo1.Lines.Add(Format('Actual Result: %d', [resInt])); + + if resInt = 15 then + Memo1.Lines.Add('SUCCESS: Deeply nested closure modified captured variable correctly.') + else + Memo1.Lines.Add(Format('FAILURE: Upvalue logic broken. Expected 15, got %d.', [resInt])); + end + else + Memo1.Lines.Add('FAILURE: Result is not an integer scalar.'); + UpdateScript; end; -procedure TForm1.ToJSONButtonClick(Sender: TObject); -var - jsonObj: TJSONObject; - converter: IJsonAstConverter; +procedure TForm1.ClearButtonClick(Sender: TObject); begin - Memo1.Lines.Clear; - - if not Assigned(FCurrExec.Func) then - begin - Memo1.Lines.Add('No AST available to serialize. Please generate one first.'); - exit; - end; - - try - converter := TJsonAstConverter.Create; - jsonObj := converter.Serialize(FCurrUnboundAst); - try - Memo1.Lines.Text := jsonObj.Format(4); - finally - jsonObj.Free; - end; - except - on E: Exception do - begin - Memo1.Lines.Add('Error serializing AST to JSON:'); - Memo1.Lines.Add(E.Message); - end; - end; + FWorkspace.DeleteChildren; + FWorkspace.Repaint; end; -procedure TForm1.DumpButtonClick(Sender: TObject); +procedure TForm1.CompilerStageBoxChange(Sender: TObject); +begin + ShowVizualization(14, 14); +end; + +procedure TForm1.CreateTriggerExampleButtonClick(Sender: TObject); +var + blk: IAstNode; begin Memo1.Lines.Clear; - Memo1.Lines.Add('--- AST Dump ---'); + Memo1.Lines.Add('--- Creating Trigger Blueprint ---'); + blk := + TAst.Block( + [ + TAst.VarDecl(TAst.Identifier('X'), TAst.Constant(0)), + TAst.VarDecl( + TAst.Identifier('tickHandler'), + TAst.LambdaExpr( + [TAst.Identifier('summand')], + TAst.Assign( + TAst.Identifier('X'), + TAst.FunctionCall(TAst.Identifier('+'), [TAst.Identifier('X'), TAst.Identifier('summand')]) + ) + ) + ) + ] + ); - if not Assigned(FCurrExec.Func) then + FTriggerTest := FEnvironment.CreateEnvironment; + + FTriggerTest.Define('X', TAst.Constant(0)); + FTriggerTest.Define( + 'tickHandler', + TAst.LambdaExpr( + [TAst.Identifier('summand')], + TAst.Assign(TAst.Identifier('X'), TAst.FunctionCall(TAst.Identifier('+'), [TAst.Identifier('X'), TAst.Identifier('summand')])) + ) + ); + + Memo1.Lines.Add('Variable "X" and function "tickHandler" defined in persistent scope.'); + Memo1.Lines.Add('Click "Do Trigger" to execute.'); + UpdateScript; +end; + +procedure TForm1.DebugBoxChange(Sender: TObject); +begin + if DebugBox.IsChecked then + FEnvironment.SetDebugMode(Memo1.Lines, ShowScopeBox.IsChecked) + else + FEnvironment.SetStandardMode; +end; + +procedure TForm1.DoTriggerButtonClick(Sender: TObject); +var + callAst: IAstNode; +begin + callAst := TAst.FunctionCall(TAst.Identifier('tickHandler'), [TAst.Constant(1)]); + + var X := FTriggerTest.Run(callAst); + + Memo1.Lines.Add(Format('Tick(1)! New value of X: %s', [X.ToString])); + UpdateScript; +end; + +procedure TForm1.DoTrigger2ButtonClick(Sender: TObject); +var + callAst: IAstNode; +begin + callAst := TAst.FunctionCall(TAst.Identifier('tickHandler'), [TAst.Constant(2)]); + + var X := FTriggerTest.Run(callAst); + + Memo1.Lines.Add(Format('Tick(2)! New value of X: %s', [X.ToString])); + UpdateScript; +end; + +procedure TForm1.ExternalFuncButtonClick(Sender: TObject); +var + callAst: IAstNode; + resultValue: TDataValue; +begin + Memo1.Lines.Clear; + Memo1.Lines.Add('--- Calling external Delphi function from AST ---'); + + FEnvironment.RootScope.Define( + 'delphiAdd', + function(const ArgNodes: TArray): TDataValue + var + val1, val2: Int64; + begin + if Length(ArgNodes) <> 2 then + raise Exception.Create('delphiAdd requires exactly 2 arguments.'); + val1 := ArgNodes[0].AsScalar.Value.AsInt64; + val2 := ArgNodes[1].AsScalar.Value.AsInt64; + Result := TScalar.FromInt64(val1 + val2); + end + ); + + callAst := TAst.FunctionCall(TAst.Identifier('delphiAdd'), [TAst.Constant(100), TAst.Constant(123)]); + + resultValue := ExecuteAst(callAst); + Memo1.Lines.Add(Format('Result from delphiAdd(100, 123): %s', [resultValue.ToString])); + UpdateScript; +end; + +procedure TForm1.FailingUpvalueButtonClick(Sender: TObject); +var + resultValue: TDataValue; +begin + FCurrUnboundAst := + TAst.Block( + [ + TAst.VarDecl(TAst.Identifier('a'), TAst.Constant(10)), + TAst.VarDecl( + TAst.Identifier('modifier'), + TAst.LambdaExpr( + [], // Outer modifier shell + TAst.LambdaExpr( + [], // Inner closure that is returned + TAst.Assign( + TAst.Identifier('a'), + TAst.FunctionCall(TAst.Identifier('+'), [TAst.Identifier('a'), TAst.Constant(5)]) + ) + ) + ) + ), + TAst.VarDecl(TAst.Identifier('reader'), TAst.LambdaExpr([], TAst.Identifier('a'))), + TAst.VarDecl(TAst.Identifier('innermost_closure'), TAst.FunctionCall(TAst.Identifier('modifier'), [])), + TAst.FunctionCall(TAst.Identifier('innermost_closure'), []), + TAst.FunctionCall(TAst.Identifier('reader'), []) + ] + ); + + UpdateScript; + + Memo1.Lines.Clear; + Memo1.Lines.Add('--- Executing Corrected Upvalue Test ---'); + + resultValue := ExecuteAst(FCurrUnboundAst); + + if resultValue.Kind <> vkVoid then begin - Memo1.Lines.Add('No *compiled* AST has been generated yet. Click a test button first.'); - exit; - end; + var res := resultValue.AsScalar.Value.AsInt64; + if res = 15 then + Memo1.Lines.Add('SUCCESS: The result is 15.') + else + Memo1.Lines.Add(Format('FAILURE: Expected 15, but got %s.', [resultValue.ToString])); - // Dump the compiled AST from the visualizer helper - TAstDumper.Dump(CompileAstStage, Memo1.Lines); + Assert(TScalar.FromInt64(15) = resultValue.AsScalar, 'The final result should be 15.'); + end; + Memo1.Lines.Add('Please check the new dump.'); + UpdateScript; end; procedure TForm1.FibonacciButtonClick(Sender: TObject); @@ -798,179 +634,155 @@ begin UpdateScript; end; -procedure TForm1.RecursionButtonClick(Sender: TObject); -var - root: IAstNode; - result: TDataValue; - sw: TStopwatch; +procedure TForm1.FlowOnlyBoxChange(Sender: TObject); begin - Memo1.Lines.Clear; - Memo1.Lines.Add('--- Tail-Recursive factorial(20) ---'); - sw := TStopwatch.StartNew; - - root := - TAst.Block( - [ - // Define the tail-recursive helper function - TAst.VarDecl( - TAst.Identifier('fact_iter'), - TAst.LambdaExpr( - [TAst.Identifier('n'), TAst.Identifier('acc')], - TAst.TernaryExpr( - // --- Ersetzt --- - TAst.FunctionCall(TAst.Identifier('<='), [TAst.Identifier('n'), TAst.Constant(1)]), - TAst.Identifier('acc'), // Base case: return the accumulator - TAst.Recur( // Tail-recursive step - [ - // --- Ersetzt --- - TAst.FunctionCall(TAst.Identifier('-'), [TAst.Identifier('n'), TAst.Constant(1)]), - // --- Ersetzt --- - TAst.FunctionCall(TAst.Identifier('*'), [TAst.Identifier('acc'), 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(1)]) - ) - ), - // Call the main function - TAst.FunctionCall(TAst.Identifier('factorial'), [TAst.Constant(20)]) - ] - ); - - // Execute with RootScope as parent. - //TODO Endlosschleife in HandleTCO - result := ExecuteAst(root); - - sw.Stop; - Memo1.Lines.Add(Format('Result: %s (calculated in %d ms)', [result.ToString, sw.ElapsedMilliseconds])); UpdateScript; end; -procedure TForm1.SeriesTestButtonClick(Sender: TObject); -var - ast: IAstNode; - resultValue: TDataValue; - series: TScalarRecordSeries; - recordDef: IScalarRecordDefinition; - i: Integer; - values: TArray; +procedure TForm1.PrintScript(const Node: IAstNode); begin + try + FScriptUpdate := true; + try + if Assigned(Node) then + ScriptMemo.Lines.Text := TAstScript.Print(Node) + else + ScriptMemo.Lines.Clear; + finally + FScriptUpdate := false; + end; + except + on E: Exception do + ScriptMemo.Lines.Add(E.Message); + end; +end; + +procedure TForm1.RTLListViewChange(Sender: TObject); +var + itemName: string; + jsonString: string; + jsonLib, jsonObj: TJSONObject; + converter: IJsonAstConverter; + AItem: TListViewItem; +begin + if RTLListView.ItemIndex < 0 then + exit; + AItem := RTLListView.Items[RTLListView.ItemIndex]; + + itemName := AItem.Text; Memo1.Lines.Clear; - Memo1.Lines.Add('--- Series Test ---'); + Memo1.Lines.Add(Format('Loading "%s" from library...', [itemName])); - recordDef := TRttiAstHelper.JsonToRecordDefinition(TRttiAstHelper.RecordDefinitionToJson); - series := TScalarRecordSeries.Create(recordDef); - SetLength(values, 6); - - for i := 0 to 4 do + if not TFile.Exists(UserLibName) then begin - values[0].AsInt64 := Round((Now + i) * 24 * 60 * 60 * 1000); - values[1].AsDouble := 100.0 + i; - values[2].AsDouble := 105.0 + i; - values[3].AsDouble := 98.0 + i; - values[4].AsDouble := 102.0 + i; - values[5].AsInt64 := 10000 * (i + 1); - series.Add(TScalarRecord.Create(recordDef, values)); + Memo1.Lines.Add(Format('Library file "%s" not found.', [UserLibName])); + exit; end; - var testEnv := FEnvironment.CreateEnvironment; + jsonLib := nil; + try + try + jsonString := TFile.ReadAllText(UserLibName); + jsonLib := TJSONObject.ParseJSONValue(jsonString) as TJSONObject; + if not Assigned(jsonLib) then + raise Exception.Create('Invalid JSON library format.'); - testEnv.RootScope.Define('ohlcvSeries', TDataValue.FromRecordSeries(series)); + var jsonValue := jsonLib.GetValue(itemName); + if not Assigned(jsonValue) or not (jsonValue is TJSONObject) then + raise Exception.Create(Format('Definition for "%s" not found in library.', [itemName])); - ast := - TAst.LambdaExpr( - [], - TAst.Block( - [ - TAst.VarDecl( - TAst.Identifier('closeColumn'), - TAst.FunctionCall(TAst.Keyword('Close'), [TAst.Identifier('ohlcvSeries')]) - ), - TAst.Indexer(TAst.Identifier('closeColumn'), TAst.Constant(1)) - ] - ) - ); + jsonObj := jsonValue as TJSONObject; - var callAst := TAst.FunctionCall(ast, []); + converter := TJsonAstConverter.Create; + FCurrUnboundAst := converter.Deserialize(jsonObj); // <-- Store unbound AST - resultValue := testEnv.Run(callAst); + // Update the UI + UpdateScript; // This will print to ScriptMemo and show visualization - Memo1.Lines.Add(Format('Result of script: %s', [resultValue.ToString])); - UpdateScript; + Memo1.Lines.Add(Format('"%s" loaded into script editor and workspace.', [itemName])); + + except + on E: Exception do + begin + Memo1.Lines.Add('Error: ' + E.Message); + end; + end; + finally + if Assigned(jsonLib) then + jsonLib.Free; + end; end; -procedure TForm1.Test1ButtonClick(Sender: TObject); +procedure TForm1.ScriptMemoChange(Sender: TObject); begin - FCurrUnboundAst := - TAstScript.Parse( - ''' - (do - (print txt) - ) - ''' - ); - - var fn := FEnvironment.Compile(FCurrUnboundAst, [TAst.Identifier('txt')]).Func; - - fn(['Hello World']); - - FEnvironment.RootScope.Define('fn', fn); - - UpdateScript; -end; - -procedure TForm1.Test2ButtonClick(Sender: TObject); -var - root: IAstNode; - result: TDataValue; - sw: TStopwatch; -begin - Memo1.Lines.Clear; - - Memo1.Lines.Add('--- Factory Pattern Demo ---'); - sw := TStopwatch.StartNew; - - root := - TAst.Block( - [ - TAst.FunctionCall(TAst.Identifier('fn'), [TAst.Constant('xyz')]), - TAst.VarDecl( - TAst.Identifier('createStrategyInstance'), - TAst.LambdaExpr( - [TAst.Identifier('offset')], - TAst.Block( - [ - TAst.VarDecl(TAst.Identifier('baseValue'), TAst.Constant(100)), - // --- Ersetzt --- - TAst.FunctionCall(TAst.Identifier('+'), [TAst.Identifier('baseValue'), TAst.Identifier('offset')]) - ] - ) - ) - ), - TAst.FunctionCall(TAst.Identifier('createStrategyInstance'), [TAst.Constant(20)]), - TAst.FunctionCall(TAst.Identifier('createStrategyInstance'), [TAst.Constant(55)]) - ] - ); - - result := ExecuteAst(root); - - sw.Stop; - Memo1.Lines.Add(Format('Result of the final expression: %s (calculated in %d ms)', [result.ToString, sw.ElapsedMilliseconds])); - UpdateScript; -end; - -procedure TForm1.WorkspaceMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); -begin - if Button <> TMouseButton.mbMiddle then + if FScriptUpdate then exit; - ShowVizualization(X, Y); + + Memo1.Lines.Clear; + try + FCurrUnboundAst := TAstScript.Parse(ScriptMemo.Lines.Text); + try + // We invoke ExecuteAst here to trigger the validation/compilation logic + // and show the result in the log. + var result := ExecuteAst(FCurrUnboundAst); + Memo1.Lines.Add(Format('Script executed. Final result: %s', [result.ToString])); + finally + // Trigger visualization update via Controller (inside ShowVizualization) + ShowVizualization(14, 14); + end; + except + on E: Exception do + Memo1.Lines.Add(E.Message); + end; +end; + +procedure TForm1.FromJSONButtonClick(Sender: TObject); +var + jsonString: string; + jsonObj: TJSONObject; + converter: IJsonAstConverter; +begin + Memo1.Lines.BeginUpdate; + try + jsonString := Memo1.Lines.Text; + Memo1.Lines.Clear; + + if jsonString.IsEmpty then + begin + Memo1.Lines.Add('Memo is empty. Please paste an AST JSON string.'); + exit; + end; + + try + converter := TJsonAstConverter.Create; + jsonObj := TJSONObject.ParseJSONValue(jsonString) as TJSONObject; + if not Assigned(jsonObj) then + raise Exception.Create('Invalid JSON format.'); + + try + FCurrUnboundAst := converter.Deserialize(jsonObj); + + // Run the full pipeline via environment + FCurrExec := FEnvironment.Compile(FCurrUnboundAst); + + Memo1.Lines.Add('AST deserialized and bound successfully from JSON.'); + Memo1.Lines.Add('You can now visualize it (Middle Mouse Click) or pretty-print it.'); + finally + jsonObj.Free; + end; + except + on E: Exception do + begin + Memo1.Lines.Add('Error deserializing AST from JSON:'); + Memo1.Lines.Add(E.Message); + Memo1.Lines.Add('--- Original JSON ---'); + Memo1.Lines.Text := Memo1.Lines.Text + sLineBreak + jsonString; + end; + end; + finally + Memo1.Lines.EndUpdate; + end; + UpdateScript; end; procedure TForm1.OHLCButtonClick(Sender: TObject); @@ -1070,6 +882,260 @@ begin UpdateScript; end; +procedure TForm1.UpdateScript; +begin + PrintScript(FCurrUnboundAst); + + FWorkspace.DeleteChildren; + ShowVizualization(14, 14); +end; + +procedure TForm1.WorkspaceMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); +begin + if Button <> TMouseButton.mbMiddle then + exit; + ShowVizualization(X, Y); +end; + +// ... Copy of the rest of the file logic (Save, Load, Dump, etc.) ... +// To ensure completeness, here are the remaining methods: + +procedure TForm1.SaveUserLibButtonClick(Sender: TObject); +var + rootNode: IAstNode; + definitions: TDictionary; + jsonLib: TJSONObject; + converter: IJsonAstConverter; + jsonString: string; + updatedCount: Integer; + addedList: TList; +begin + try + rootNode := TAstScript.Parse(ScriptMemo.Lines.Text); + if not Assigned(rootNode) then + raise Exception.Create('Script is empty or invalid.'); + + definitions := TDictionary.Create; + try + if rootNode.Kind = akBlockExpression then + begin + for var expr in rootNode.AsBlockExpression.Expressions do + begin + if (expr.Kind = akVariableDeclaration) then + begin + var decl := expr.AsVariableDeclaration; + definitions.Add(decl.Target.AsIdentifier.Name, decl.Initializer); + end + else if expr.Kind = akMacroDefinition then + begin + var macroDef := expr.AsMacroDefinition; + definitions.Add(macroDef.Name.Name, macroDef); + end; + end; + end + else if rootNode.Kind = akVariableDeclaration then + begin + var decl := rootNode.AsVariableDeclaration; + definitions.Add(decl.Target.AsIdentifier.Name, decl.Initializer); + end + else if rootNode.Kind = akMacroDefinition then + begin + var macroDef := rootNode.AsMacroDefinition; + definitions.Add(macroDef.Name.Name, macroDef); + end; + + if definitions.Count = 0 then + begin + Memo1.Lines.Add('No top-level "(def ...)" or "(defmacro ...)" definitions found in the script to save.'); + exit; + end; + + jsonLib := nil; + if TFile.Exists(UserLibName) then + begin + jsonString := TFile.ReadAllText(UserLibName); + if not jsonString.IsEmpty then + jsonLib := TJSONObject.ParseJSONValue(jsonString) as TJSONObject; + end; + + if not Assigned(jsonLib) then + jsonLib := TJSONObject.Create; + + addedList := TList.Create; + try + converter := TJsonAstConverter.Create; + updatedCount := 0; + + for var pair in definitions do + begin + if jsonLib.Values[pair.Key] <> nil then + begin + Inc(updatedCount); + jsonLib.RemovePair(pair.Key); + end + else + addedList.Add(pair.Key); + + jsonLib.AddPair(pair.Key, converter.Serialize(pair.Value)); + end; + + TFile.WriteAllText(UserLibName, jsonLib.Format(4)); + + Memo1.Lines.Add(Format('--- Library "%s" updated ---', [ExtractFileName(UserLibName)])); + if updatedCount > 0 then + Memo1.Lines.Add(Format('%d existing definitions updated.', [updatedCount])); + if addedList.Count > 0 then + begin + Memo1.Lines.Add(Format('%d new definitions added:', [addedList.Count])); + RTLListView.Items.BeginUpdate; + try + for var n in addedList do + begin + Memo1.Lines.Add(n); + RTLListView.Items.Add.Text := n; + end; + finally + RTLListView.Items.EndUpdate; + end; + end; + finally + jsonLib.Free; + addedList.Free; + end; + finally + definitions.Free; + end; + except + on E: Exception do + Memo1.Lines.Add('Error saving library: ' + E.Message); + end; +end; + +procedure TForm1.LoadUserLibButtonClick(Sender: TObject); +var + jsonString: string; + jsonObj: TJSONObject; + pair: TJSONPair; + funcAst: IAstNode; + funcValue: TDataValue; + converter: IJsonAstConverter; + addr: TResolvedAddress; +begin + if not TFile.Exists(UserLibName) then + begin + Memo1.Lines.Add(Format('Library file "%s" not found.', [UserLibName])); + exit; + end; + + try + converter := TJsonAstConverter.Create; + jsonString := TFile.ReadAllText(UserLibName); + jsonObj := TJSONObject.ParseJSONValue(jsonString) as TJSONObject; + if not Assigned(jsonObj) then + raise Exception.Create('Invalid JSON format for library file.'); + + try + Memo1.Lines.Add(Format('--- Loading User Library from %s ---', [ExtractFileName(UserLibName)])); + RTLListView.Items.BeginUpdate; + try + for pair in jsonObj do + begin + if not (pair.JsonValue is TJSONObject) then + continue; + + funcAst := converter.Deserialize(pair.JsonValue as TJSONObject); + + addr := FEnvironment.RootScope.Resolve(pair.JsonString.Value); + + if addr.Kind = akUnresolved then + begin + if funcAst.Kind = akMacroDefinition then + begin + FEnvironment.MacroRegistry.Define(funcAst.AsMacroDefinition); + Memo1.Lines.Add(Format('Defined macro "%s"', [pair.JsonString.Value])); + end + else + begin + funcValue := ExecuteAst(funcAst); + FEnvironment.RootScope.Define(pair.JsonString.Value, funcValue); + Memo1.Lines.Add(Format('Defined function "%s"', [pair.JsonString.Value])); + end; + end + else + Memo1.Lines.Add(Format('Symbol "%s" already defined', [pair.JsonString.Value])); + + RTLListView.Items.Add.Text := pair.JsonString.Value; + end; + finally + RTLListView.Items.EndUpdate; + end; + finally + jsonObj.Free; + end; + except + on E: Exception do + Memo1.Lines.Add('Error loading library: ' + E.Message); + end; +end; + +procedure TForm1.RecursionButtonClick(Sender: TObject); +begin + TailCallButtenClick(Sender); +end; + +procedure TForm1.SeriesTestButtonClick(Sender: TObject); +var + ast: IAstNode; + resultValue: TDataValue; + series: TScalarRecordSeries; + recordDef: IScalarRecordDefinition; + i: Integer; + values: TArray; +begin + Memo1.Lines.Clear; + Memo1.Lines.Add('--- Series Test ---'); + + recordDef := TRttiAstHelper.JsonToRecordDefinition(TRttiAstHelper.RecordDefinitionToJson); + series := TScalarRecordSeries.Create(recordDef); + SetLength(values, 6); + + for i := 0 to 4 do + begin + values[0].AsInt64 := Round((Now + i) * 24 * 60 * 60 * 1000); + values[1].AsDouble := 100.0 + i; + values[2].AsDouble := 105.0 + i; + values[3].AsDouble := 98.0 + i; + values[4].AsDouble := 102.0 + i; + values[5].AsInt64 := 10000 * (i + 1); + series.Add(TScalarRecord.Create(recordDef, values)); + end; + + var testEnv := FEnvironment.CreateEnvironment; + + testEnv.RootScope.Define('ohlcvSeries', TDataValue.FromRecordSeries(series)); + + ast := + TAst.LambdaExpr( + [], + TAst.Block( + [ + TAst.VarDecl( + TAst.Identifier('closeColumn'), + TAst.FunctionCall(TAst.Keyword('Close'), [TAst.Identifier('ohlcvSeries')]) + ), + TAst.Indexer(TAst.Identifier('closeColumn'), TAst.Constant(1)) + ] + ) + ); + + var callAst := TAst.FunctionCall(ast, []); + + resultValue := testEnv.Run(callAst); + + Memo1.Lines.Add(Format('Result of script: %s', [resultValue.ToString])); + UpdateScript; +end; + procedure TForm1.TailCallButtenClick(Sender: TObject); const RecursionDepth = 1000000; @@ -1091,9 +1157,7 @@ begin TAst.LambdaExpr( [TAst.Identifier('n')], TAst.IfExpr( - // --- Ersetzt --- TAst.FunctionCall(TAst.Identifier('>'), [TAst.Identifier('n'), TAst.Constant(0)]), - // --- Ersetzt --- TAst.Recur([TAst.FunctionCall(TAst.Identifier('-'), [TAst.Identifier('n'), TAst.Constant(1)])]), TAst.Constant(0) ) @@ -1111,271 +1175,95 @@ begin UpdateScript; end; -procedure TForm1.CreateTriggerExampleButtonClick(Sender: TObject); +procedure TForm1.Test1ButtonClick(Sender: TObject); +begin + FCurrUnboundAst := TAstScript.Parse('(do (print txt))'); + var fn := FEnvironment.Compile(FCurrUnboundAst, [TAst.Identifier('txt')]).Func; + fn(['Hello World']); + FEnvironment.RootScope.Define('fn', fn); + UpdateScript; +end; + +procedure TForm1.Test2ButtonClick(Sender: TObject); var - blk: IAstNode; + root: IAstNode; + result: TDataValue; + sw: TStopwatch; begin Memo1.Lines.Clear; - Memo1.Lines.Add('--- Creating Trigger Blueprint ---'); - blk := + Memo1.Lines.Add('--- Factory Pattern Demo ---'); + sw := TStopwatch.StartNew; + + root := TAst.Block( [ - TAst.VarDecl(TAst.Identifier('X'), TAst.Constant(0)), + TAst.FunctionCall(TAst.Identifier('fn'), [TAst.Constant('xyz')]), TAst.VarDecl( - TAst.Identifier('tickHandler'), + TAst.Identifier('createStrategyInstance'), TAst.LambdaExpr( - [TAst.Identifier('summand')], - TAst.Assign( - TAst.Identifier('X'), - // --- Ersetzt --- - TAst.FunctionCall(TAst.Identifier('+'), [TAst.Identifier('X'), TAst.Identifier('summand')]) - ) - ) - ) - ] - ); - - FTriggerTest := FEnvironment.CreateEnvironment; - - FTriggerTest.Define('X', TAst.Constant(0)); - FTriggerTest.Define( - 'tickHandler', - TAst.LambdaExpr( - [TAst.Identifier('summand')], - // --- Ersetzt --- - TAst.Assign(TAst.Identifier('X'), TAst.FunctionCall(TAst.Identifier('+'), [TAst.Identifier('X'), TAst.Identifier('summand')])) - ) - ); - - Memo1.Lines.Add('Variable "X" and function "tickHandler" defined in persistent scope.'); - Memo1.Lines.Add('Click "Do Trigger" to execute.'); - UpdateScript; -end; - -procedure TForm1.DebugBoxChange(Sender: TObject); -begin - if DebugBox.IsChecked then - FEnvironment.SetDebugMode(Memo1.Lines, ShowScopeBox.IsChecked) - else - FEnvironment.SetStandardMode; -end; - -procedure TForm1.DoTriggerButtonClick(Sender: TObject); -var - callAst: IAstNode; -begin - callAst := TAst.FunctionCall(TAst.Identifier('tickHandler'), [TAst.Constant(1)]); - - var X := FTriggerTest.Run(callAst); - - Memo1.Lines.Add(Format('Tick(1)! New value of X: %s', [X.ToString])); - UpdateScript; -end; - -procedure TForm1.DoTrigger2ButtonClick(Sender: TObject); -var - callAst: IAstNode; -begin - callAst := TAst.FunctionCall(TAst.Identifier('tickHandler'), [TAst.Constant(2)]); - - var X := FTriggerTest.Run(callAst); - - Memo1.Lines.Add(Format('Tick(2)! New value of X: %s', [X.ToString])); - UpdateScript; -end; - -procedure TForm1.ExternalFuncButtonClick(Sender: TObject); -var - callAst: IAstNode; - resultValue: TDataValue; -begin - Memo1.Lines.Clear; - Memo1.Lines.Add('--- Calling external Delphi function from AST ---'); - - FEnvironment.RootScope.Define( - 'delphiAdd', - function(const ArgNodes: TArray): TDataValue - var - val1, val2: Int64; - begin - if Length(ArgNodes) <> 2 then - raise Exception.Create('delphiAdd requires exactly 2 arguments.'); - val1 := ArgNodes[0].AsScalar.Value.AsInt64; - val2 := ArgNodes[1].AsScalar.Value.AsInt64; - Result := TScalar.FromInt64(val1 + val2); - end - ); - - callAst := TAst.FunctionCall(TAst.Identifier('delphiAdd'), [TAst.Constant(100), TAst.Constant(123)]); - - resultValue := ExecuteAst(callAst); - Memo1.Lines.Add(Format('Result from delphiAdd(100, 123): %s', [resultValue.ToString])); - UpdateScript; -end; - -procedure TForm1.FailingUpvalueButtonClick(Sender: TObject); -var - resultValue: TDataValue; -begin - FCurrUnboundAst := - TAst.Block( - [ - TAst.VarDecl(TAst.Identifier('a'), TAst.Constant(10)), - TAst.VarDecl( - TAst.Identifier('modifier'), - TAst.LambdaExpr( - [], // Outer modifier shell - TAst.LambdaExpr( - [], // Inner closure that is returned - TAst.Assign( - TAst.Identifier('a'), - // --- Ersetzt --- - TAst.FunctionCall(TAst.Identifier('+'), [TAst.Identifier('a'), TAst.Constant(5)]) - ) + [TAst.Identifier('offset')], + TAst.Block( + [ + TAst.VarDecl(TAst.Identifier('baseValue'), TAst.Constant(100)), + TAst.FunctionCall(TAst.Identifier('+'), [TAst.Identifier('baseValue'), TAst.Identifier('offset')]) + ] ) ) ), - TAst.VarDecl(TAst.Identifier('reader'), TAst.LambdaExpr([], TAst.Identifier('a'))), - TAst.VarDecl(TAst.Identifier('innermost_closure'), TAst.FunctionCall(TAst.Identifier('modifier'), [])), - TAst.FunctionCall(TAst.Identifier('innermost_closure'), []), - TAst.FunctionCall(TAst.Identifier('reader'), []) + TAst.FunctionCall(TAst.Identifier('createStrategyInstance'), [TAst.Constant(20)]), + TAst.FunctionCall(TAst.Identifier('createStrategyInstance'), [TAst.Constant(55)]) ] ); - UpdateScript; - - Memo1.Lines.Clear; - Memo1.Lines.Add('--- Executing Corrected Upvalue Test ---'); - - resultValue := ExecuteAst(FCurrUnboundAst); - - var res := resultValue.AsScalar.Value.AsInt64; - if res = 15 then - Memo1.Lines.Add('SUCCESS: The result is 15.') - else - Memo1.Lines.Add(Format('FAILURE: Expected 15, but got %s.', [resultValue.ToString])); - - Assert(TScalar.FromInt64(15) = resultValue.AsScalar, 'The final result should be 15.'); - Memo1.Lines.Add('Please check the new dump.'); + result := ExecuteAst(root); + sw.Stop; + Memo1.Lines.Add(Format('Result of the final expression: %s (calculated in %d ms)', [result.ToString, sw.ElapsedMilliseconds])); UpdateScript; end; -procedure TForm1.FlowOnlyBoxChange(Sender: TObject); -begin - UpdateScript; -end; - -procedure TForm1.PrintScript(const Node: IAstNode); -begin - try - FScriptUpdate := true; - try - if Assigned(Node) then - ScriptMemo.Lines.Text := TAstScript.Print(Node) - else - ScriptMemo.Lines.Clear; - finally - FScriptUpdate := false; - end; - except - on E: Exception do - ScriptMemo.Lines.Add(E.Message); - end; -end; - -procedure TForm1.RTLListViewChange(Sender: TObject); +procedure TForm1.ToJSONButtonClick(Sender: TObject); var - itemName: string; - jsonString: string; - jsonLib, jsonObj: TJSONObject; + jsonObj: TJSONObject; converter: IJsonAstConverter; - AItem: TListViewItem; begin - if RTLListView.ItemIndex < 0 then - exit; - AItem := RTLListView.Items[RTLListView.ItemIndex]; - - itemName := AItem.Text; Memo1.Lines.Clear; - Memo1.Lines.Add(Format('Loading "%s" from library...', [itemName])); - if not TFile.Exists(UserLibName) then + if not Assigned(FCurrExec.Func) then begin - Memo1.Lines.Add(Format('Library file "%s" not found.', [UserLibName])); + Memo1.Lines.Add('No *compiled* AST has been generated yet. Click a test button first.'); exit; end; - jsonLib := nil; try + converter := TJsonAstConverter.Create; + jsonObj := converter.Serialize(FCurrUnboundAst); try - jsonString := TFile.ReadAllText(UserLibName); - jsonLib := TJSONObject.ParseJSONValue(jsonString) as TJSONObject; - if not Assigned(jsonLib) then - raise Exception.Create('Invalid JSON library format.'); - - var jsonValue := jsonLib.GetValue(itemName); - if not Assigned(jsonValue) or not (jsonValue is TJSONObject) then - raise Exception.Create(Format('Definition for "%s" not found in library.', [itemName])); - - jsonObj := jsonValue as TJSONObject; - - converter := TJsonAstConverter.Create; - FCurrUnboundAst := converter.Deserialize(jsonObj); // <-- Store unbound AST - - // Update the UI - UpdateScript; // This will print to ScriptMemo and show visualization - - Memo1.Lines.Add(Format('"%s" loaded into script editor and workspace.', [itemName])); - - except - on E: Exception do - begin - Memo1.Lines.Add('Error: ' + E.Message); - end; - end; - finally - if Assigned(jsonLib) then - jsonLib.Free; - end; -end; - -procedure TForm1.ScriptMemoChange(Sender: TObject); -begin - if FScriptUpdate then - exit; - - Memo1.Lines.Clear; - try - FCurrUnboundAst := TAstScript.Parse(ScriptMemo.Lines.Text); - try - // Execute the entire script block when it changes - var result := ExecuteAst(FCurrUnboundAst); - Memo1.Lines.Add(Format('Script executed. Final result: %s', [result.ToString])); + Memo1.Lines.Text := jsonObj.Format(4); finally - ShowVizualization(14, 14); + jsonObj.Free; end; except on E: Exception do + begin + Memo1.Lines.Add('Error serializing AST to JSON:'); Memo1.Lines.Add(E.Message); + end; end; end; -procedure TForm1.UpdateScript; +procedure TForm1.DumpButtonClick(Sender: TObject); begin - PrintScript(FCurrUnboundAst); - - FWorkspace.DeleteChildren; - ShowVizualization(14, 14); -end; - -procedure TForm1.ShowVizualization(X, Y: Single); -begin - FWorkspace.DeleteChildren; + Memo1.Lines.Clear; + Memo1.Lines.Add('--- AST Dump ---'); if FCurrUnboundAst = nil then + begin + Memo1.Lines.Add('No AST available.'); exit; + end; - FWorkspace.Build(CompileAstStage, TPointF.Create(X, Y)); + // Dump the raw unbound AST first + TAstDumper.Dump(FCurrUnboundAst, Memo1.Lines); end; end. diff --git a/Src/AST/Myc.Ast.Compiler.Binder.pas b/Src/AST/Myc.Ast.Compiler.Binder.pas index a90c0b1..0455c95 100644 --- a/Src/AST/Myc.Ast.Compiler.Binder.pas +++ b/Src/AST/Myc.Ast.Compiler.Binder.pas @@ -143,12 +143,8 @@ class function TAstBinder.Bind( const AArgTypes: TArray = nil ): IAstNode; begin - var binder := TAstBinder.Create(ParentLayout, AFunctionRegistry, AArgTypes, ALog); - try - Result := binder.Execute(RootNode, Layout); - finally - binder.Free; - end; + var binder := TAstBinder.Create(ParentLayout, AFunctionRegistry, AArgTypes, ALog) as IAstBinder; + Result := binder.Execute(RootNode, Layout); end; function TAstBinder.Execute(const RootNode: IAstNode; out Layout: IScopeLayout): IAstNode; diff --git a/Src/AST/Myc.Ast.Compiler.Specializer.pas b/Src/AST/Myc.Ast.Compiler.Specializer.pas index 8ce3fed..620501c 100644 --- a/Src/AST/Myc.Ast.Compiler.Specializer.pas +++ b/Src/AST/Myc.Ast.Compiler.Specializer.pas @@ -38,14 +38,6 @@ type procedure Add(const Key: TMonoCacheKey; const Func: TSpecializedMethod); end; - TCompiledFunction = record - public - Func: TDataValue.TFunc; - StaticType: IStaticType; - IsPure: Boolean; - constructor Create(const AFunc: TDataValue.TFunc; const AStaticType: IStaticType; AIsPure: Boolean); - end; - // This transformer runs *after* TypeChecker. // It specializes all statically resolvable function calls (RTL and user-defined) // by replacing them with nodes that have a direct StaticTarget. @@ -271,13 +263,4 @@ begin ArgTypes := AArgTypes; end; -{ TCompiledFunction } - -constructor TCompiledFunction.Create(const AFunc: TDataValue.TFunc; const AStaticType: IStaticType; AIsPure: Boolean); -begin - Func := AFunc; - StaticType := AStaticType; - IsPure := AIsPure; -end; - end. diff --git a/Src/AST/Myc.Ast.Environment.pas b/Src/AST/Myc.Ast.Environment.pas index 5f9013e..3c83dd5 100644 --- a/Src/AST/Myc.Ast.Environment.pas +++ b/Src/AST/Myc.Ast.Environment.pas @@ -50,7 +50,12 @@ type function Specialize(const Node: IAstNode): IAstNode; - function Compile(const Node: IFunctionDefinition; const ArgTypes: TArray = []): TCompiledFunction; + function Compile( + const Node: IFunctionDefinition; + const ArgTypes: TArray = []; + const Log: ICompilerLog = nil + ): TCompiledFunction; + function Link(const Node: ILambdaExpressionNode; const Log: ICompilerLog): TCompiledFunction; function CreateEnvironment: IEnvironment; @@ -80,15 +85,19 @@ type procedure SetStandardMode; procedure SetDebugMode(ALog: TStrings; AShowScope: Boolean); - function Run(const ANode: IAstNode; const Params: TArray = []; const Args: TArray = []): TDataValue; + function ExpandMacros(const Node: IAstNode): IAstNode; + function Bind(const Node: IAstNode; const AArgTypes: TArray; const Log: ICompilerLog): IAstNode; + function Specialize(const Node: IAstNode): IAstNode; function Compile( const Node: IAstNode; const Params: TArray = []; const ArgTypes: TArray = [] ): TCompiledFunction; overload; - function Compile(const Node: IFunctionDefinition; const ArgTypes: TArray = []): TCompiledFunction; overload; + function Link(const Node: ILambdaExpressionNode; const Log: ICompilerLog): TCompiledFunction; + + function Run(const ANode: IAstNode; const Params: TArray = []; const Args: TArray = []): TDataValue; procedure Define(const Name: String; const AScript: IAstNode); @@ -180,7 +189,12 @@ type function Specialize(const Node: IAstNode): IAstNode; - function Compile(const Node: IFunctionDefinition; const ArgTypes: TArray): TCompiledFunction; overload; + function Compile( + const Node: IFunctionDefinition; + const ArgTypes: TArray; + const Log: ICompilerLog = nil + ): TCompiledFunction; + function Link(const Node: ILambdaExpressionNode; const Log: ICompilerLog): TCompiledFunction; end; { TAstEnvironment } @@ -190,6 +204,13 @@ begin FEnvironment := AEnvironment; end; +function TAstEnvironment.Bind(const Node: IAstNode; const AArgTypes: TArray; const Log: ICompilerLog): IAstNode; +var + layout: IScopeLayout; +begin + Result := FEnvironment.Bind(Node, layout, AArgTypes, Log); +end; + procedure TAstEnvironment.SetStandardMode; begin FEnvironment.SetExecutionStrategy(TStandardExecutionStrategy.Create); @@ -245,6 +266,11 @@ begin RootScope.Define(Name, compiled.Func([]), compiled.StaticType); end; +function TAstEnvironment.ExpandMacros(const Node: IAstNode): IAstNode; +begin + Result := FEnvironment.ExpandMacros(Node); +end; + function TAstEnvironment.GetRootScope: IExecutionScope; begin Result := FEnvironment.GetRootScope; @@ -255,14 +281,23 @@ begin Result := FEnvironment.GetMacroRegistry; end; +function TAstEnvironment.Link(const Node: ILambdaExpressionNode; const Log: ICompilerLog): TCompiledFunction; +begin + Result := FEnvironment.Link(Node, Log); +end; + function TAstEnvironment.Run( const ANode: IAstNode; const Params: TArray = []; const Args: TArray = [] ): TDataValue; begin - var compiled := Compile(ANode, Params); - Result := compiled.Func(Args); + Result := Compile(ANode, Params).Func(Args); +end; + +function TAstEnvironment.Specialize(const Node: IAstNode): IAstNode; +begin + Result := FEnvironment.Specialize(Node); end; { TStandardExecutionStrategy } @@ -365,45 +400,55 @@ begin Result := TEnvironment.Create(TAst.CreateScope(FRootScope), TMacroRegistry.Create(FMacroRegistry), FExecutionStrategy); end; -function TEnvironment.Compile(const Node: IFunctionDefinition; const ArgTypes: TArray): TCompiledFunction; +function TEnvironment.Compile( + const Node: IFunctionDefinition; + const ArgTypes: TArray; + const Log: ICompilerLog = nil +): TCompiledFunction; var layout: IScopeLayout; - descriptor: IScopeDescriptor; - funcType: IStaticType; - finalFunc: TDataValue.TFunc; - - typedNode, specialized, tcoOptimized: IAstNode; - isPure: Boolean; - - log: ICompilerLog; + lg: ICompilerLog; begin - log := TCompilerLog.Create; + lg := + if Assigned(Log) then Log + else TCompilerLog.Create as ICompilerLog; // 1. Expand Macros var expanded := ExpandMacros(Node); // 2. Bind & TypeCheck (accumulating errors) - typedNode := Bind(expanded, layout, ArgTypes, log); + var typedNode := Bind(expanded, layout, ArgTypes, lg); // 3. Check for compilation errors - if log.HasErrors then - raise ECompilationFailed.Create(log.GetEntries); + if lg.HasErrors then + raise ECompilationFailed.Create(lg.GetEntries); // Note: If types are Unknown but no errors were logged (edge case), we proceed. // But Binder/TypeChecker logic ensures errors are logged for Unknowns that matter. - // 4. Specialization & Optimization - descriptor := typedNode.AsLambdaExpression.Descriptor; + var specialized := Specialize(typedNode); + + Result := Link(specialized.AsLambdaExpression, lg); +end; + +function TEnvironment.Link(const Node: ILambdaExpressionNode; const Log: ICompilerLog): TCompiledFunction; +var + descriptor: IScopeDescriptor; + funcType: IStaticType; + finalFunc: TDataValue.TFunc; + isPure: Boolean; +begin + descriptor := Node.Descriptor; + // Descriptor might be nil if Bind failed badly, but HasErrors check above covers that. Assert(Assigned(descriptor)); - funcType := typedNode.AsTypedNode.StaticType; + funcType := Node.StaticType; - specialized := Specialize(typedNode); - tcoOptimized := TAstTCO.Optimize(specialized); + var tcoOptimized := TAstTCO.Optimize(Node).AsLambdaExpression; // 5. Purity Inference - isPure := TPurityAnalyzer.IsPure(tcoOptimized.AsLambdaExpression.Body); + isPure := TPurityAnalyzer.IsPure(tcoOptimized.Body); // 6. Generate Visitor/Closure var visitor := FExecutionStrategy.CreateVisitor(descriptor.CreateScope(FRootScope)); diff --git a/Src/AST/Myc.Ast.Nodes.pas b/Src/AST/Myc.Ast.Nodes.pas index 27976b1..fea677f 100644 --- a/Src/AST/Myc.Ast.Nodes.pas +++ b/Src/AST/Myc.Ast.Nodes.pas @@ -64,6 +64,14 @@ type property Errors: TArray read FErrors; end; + TCompiledFunction = record + public + Func: TDataValue.TFunc; + StaticType: IStaticType; + IsPure: Boolean; + constructor Create(const AFunc: TDataValue.TFunc; const AStaticType: IStaticType; AIsPure: Boolean); + end; + // --- AST Interfaces --- IAstVisitor = interface; @@ -839,6 +847,15 @@ uses System.Rtti, System.StrUtils; +{ TCompiledFunction } + +constructor TCompiledFunction.Create(const AFunc: TDataValue.TFunc; const AStaticType: IStaticType; AIsPure: Boolean); +begin + Func := AFunc; + StaticType := AStaticType; + IsPure := AIsPure; +end; + { TAstNodeKindHelper } function TAstNodeKindHelper.ToString: string; diff --git a/Src/AST/Myc.Ast.Visitor.pas b/Src/AST/Myc.Ast.Visitor.pas index 2f2f7d8..e18c8d5 100644 --- a/Src/AST/Myc.Ast.Visitor.pas +++ b/Src/AST/Myc.Ast.Visitor.pas @@ -123,7 +123,7 @@ type function VisitNop(const Node: INopNode): IAstNode; override; end; - TAstVisitor = class abstract(TInterfacedObject, IAstVisitor) + TAstVisitor = class(TInterfacedObject, IAstVisitor) strict private // IAstVisitor explicit implementation (bridge methods) function IAstVisitor.VisitConstant = DoVisitConstant; @@ -176,30 +176,33 @@ type function DoVisitNop(const Node: INopNode): TDataValue; protected - // Virtual procedures for descendants (Interpreters/Side-effects) to override - procedure VisitConstant(const Node: IConstantNode); virtual; abstract; - procedure VisitIdentifier(const Node: IIdentifierNode); virtual; abstract; - procedure VisitKeyword(const Node: IKeywordNode); virtual; abstract; - procedure VisitIfExpression(const Node: IIfExpressionNode); virtual; abstract; - procedure VisitTernaryExpression(const Node: ITernaryExpressionNode); virtual; abstract; - procedure VisitLambdaExpression(const Node: ILambdaExpressionNode); virtual; abstract; - procedure VisitFunctionCall(const Node: IFunctionCallNode); virtual; abstract; - procedure VisitMacroExpansionNode(const Node: IMacroExpansionNode); virtual; abstract; - procedure VisitBlockExpression(const Node: IBlockExpressionNode); virtual; abstract; - procedure VisitVariableDeclaration(const Node: IVariableDeclarationNode); virtual; abstract; - procedure VisitAssignment(const Node: IAssignmentNode); virtual; abstract; - procedure VisitMacroDefinition(const Node: IMacroDefinitionNode); virtual; abstract; - procedure VisitQuasiquote(const Node: IQuasiquoteNode); virtual; abstract; - procedure VisitUnquote(const Node: IUnquoteNode); virtual; abstract; - procedure VisitUnquoteSplicing(const Node: IUnquoteSplicingNode); virtual; abstract; - procedure VisitIndexer(const Node: IIndexerNode); virtual; abstract; - procedure VisitMemberAccess(const Node: IMemberAccessNode); virtual; abstract; - procedure VisitRecordLiteral(const Node: IRecordLiteralNode); virtual; abstract; - procedure VisitCreateSeries(const Node: ICreateSeriesNode); virtual; abstract; - procedure VisitAddSeriesItem(const Node: IAddSeriesItemNode); virtual; abstract; - procedure VisitSeriesLength(const Node: ISeriesLengthNode); virtual; abstract; - procedure VisitRecurNode(const Node: IRecurNode); virtual; abstract; - procedure VisitNop(const Node: INopNode); virtual; abstract; + // Entry point for traversal + procedure Accept(const Node: IAstNode); virtual; + + // Virtual procedures with default traversal implementation + procedure VisitConstant(const Node: IConstantNode); virtual; + procedure VisitIdentifier(const Node: IIdentifierNode); virtual; + procedure VisitKeyword(const Node: IKeywordNode); virtual; + procedure VisitIfExpression(const Node: IIfExpressionNode); virtual; + procedure VisitTernaryExpression(const Node: ITernaryExpressionNode); virtual; + procedure VisitLambdaExpression(const Node: ILambdaExpressionNode); virtual; + procedure VisitFunctionCall(const Node: IFunctionCallNode); virtual; + procedure VisitMacroExpansionNode(const Node: IMacroExpansionNode); virtual; + procedure VisitBlockExpression(const Node: IBlockExpressionNode); virtual; + procedure VisitVariableDeclaration(const Node: IVariableDeclarationNode); virtual; + procedure VisitAssignment(const Node: IAssignmentNode); virtual; + procedure VisitMacroDefinition(const Node: IMacroDefinitionNode); virtual; + procedure VisitQuasiquote(const Node: IQuasiquoteNode); virtual; + procedure VisitUnquote(const Node: IUnquoteNode); virtual; + procedure VisitUnquoteSplicing(const Node: IUnquoteSplicingNode); virtual; + procedure VisitIndexer(const Node: IIndexerNode); virtual; + procedure VisitMemberAccess(const Node: IMemberAccessNode); virtual; + procedure VisitRecordLiteral(const Node: IRecordLiteralNode); virtual; + procedure VisitCreateSeries(const Node: ICreateSeriesNode); virtual; + procedure VisitAddSeriesItem(const Node: IAddSeriesItemNode); virtual; + procedure VisitSeriesLength(const Node: ISeriesLengthNode); virtual; + procedure VisitRecurNode(const Node: IRecurNode); virtual; + procedure VisitNop(const Node: INopNode); virtual; end; implementation @@ -706,6 +709,153 @@ end; { TAstVisitor } +procedure TAstVisitor.Accept(const Node: IAstNode); +begin + if Assigned(Node) then + Node.Accept(Self); +end; + +procedure TAstVisitor.VisitConstant(const Node: IConstantNode); +begin + // Leaf node +end; + +procedure TAstVisitor.VisitIdentifier(const Node: IIdentifierNode); +begin + // Leaf node +end; + +procedure TAstVisitor.VisitKeyword(const Node: IKeywordNode); +begin + // Leaf node +end; + +procedure TAstVisitor.VisitIfExpression(const Node: IIfExpressionNode); +begin + Accept(Node.Condition); + Accept(Node.ThenBranch); + Accept(Node.ElseBranch); +end; + +procedure TAstVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode); +begin + Accept(Node.Condition); + Accept(Node.ThenBranch); + Accept(Node.ElseBranch); +end; + +procedure TAstVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode); +begin + for var param in Node.Parameters do + Accept(param); + Accept(Node.Body); +end; + +procedure TAstVisitor.VisitFunctionCall(const Node: IFunctionCallNode); +begin + Accept(Node.Callee); + for var arg in Node.Arguments do + Accept(arg); +end; + +procedure TAstVisitor.VisitMacroExpansionNode(const Node: IMacroExpansionNode); +begin + Accept(Node.CallNode); + Accept(Node.ExpandedBody); +end; + +procedure TAstVisitor.VisitBlockExpression(const Node: IBlockExpressionNode); +begin + for var expr in Node.Expressions do + Accept(expr); +end; + +procedure TAstVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode); +begin + Accept(Node.Target); + Accept(Node.Initializer); +end; + +procedure TAstVisitor.VisitAssignment(const Node: IAssignmentNode); +begin + Accept(Node.Target); + Accept(Node.Value); +end; + +procedure TAstVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode); +begin + Accept(Node.Name); + for var param in Node.Parameters do + Accept(param); + Accept(Node.Body); +end; + +procedure TAstVisitor.VisitQuasiquote(const Node: IQuasiquoteNode); +begin + Accept(Node.Expression); +end; + +procedure TAstVisitor.VisitUnquote(const Node: IUnquoteNode); +begin + Accept(Node.Expression); +end; + +procedure TAstVisitor.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode); +begin + Accept(Node.Expression); +end; + +procedure TAstVisitor.VisitIndexer(const Node: IIndexerNode); +begin + Accept(Node.Base); + Accept(Node.Index); +end; + +procedure TAstVisitor.VisitMemberAccess(const Node: IMemberAccessNode); +begin + Accept(Node.Base); + Accept(Node.Member); +end; + +procedure TAstVisitor.VisitRecordLiteral(const Node: IRecordLiteralNode); +begin + for var field in Node.Fields do + begin + Accept(field.Key); + Accept(field.Value); + end; +end; + +procedure TAstVisitor.VisitCreateSeries(const Node: ICreateSeriesNode); +begin + // Leaf node +end; + +procedure TAstVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode); +begin + Accept(Node.Series); + Accept(Node.Value); + Accept(Node.Lookback); +end; + +procedure TAstVisitor.VisitSeriesLength(const Node: ISeriesLengthNode); +begin + Accept(Node.Series); +end; + +procedure TAstVisitor.VisitRecurNode(const Node: IRecurNode); +begin + for var arg in Node.Arguments do + Accept(arg); +end; + +procedure TAstVisitor.VisitNop(const Node: INopNode); +begin + // Leaf node +end; + +// ... [Private Bridge Methods implementation remains unchanged] ... + function TAstVisitor.DoVisitConstant(const Node: IConstantNode): TDataValue; begin VisitConstant(Node); @@ -818,7 +968,6 @@ end; function TAstVisitor.DoVisitNop(const Node: INopNode): TDataValue; begin - // Added Nop implementation VisitNop(Node); end; diff --git a/Src/AST/Myc.Fmx.AstEditor.Controller.pas b/Src/AST/Myc.Fmx.AstEditor.Controller.pas new file mode 100644 index 0000000..58f769f --- /dev/null +++ b/Src/AST/Myc.Fmx.AstEditor.Controller.pas @@ -0,0 +1,258 @@ +unit Myc.Fmx.AstEditor.Controller; + +interface + +uses + System.SysUtils, + System.Classes, + System.Types, + System.Generics.Collections, + FMX.Controls, + Myc.Ast, + Myc.Ast.Nodes, + Myc.Ast.Identities, + Myc.Ast.Types, + Myc.Ast.Visitor, + Myc.Ast.Scope, + Myc.Ast.Environment, + Myc.Fmx.AstEditor.Core, + Myc.Fmx.AstEditor.Workspace; + +type + TAstEditorController = class + private + type + TNodeMap = TDictionary; + + // Visitor to propagate Type Information from TypedAST to Visual Nodes + TTypePropagator = class(TAstVisitor) + private + FMap: TNodeMap; + procedure ApplyType(const Node: IAstNode); + protected + // Central hook: Called for every node during traversal + procedure Accept(const Node: IAstNode); override; + public + constructor Create(AMap: TNodeMap); + end; + + private + FEnv: TAstEnvironment; + FWorkspace: TAstWorkspace; + FNodeMap: TNodeMap; + FRootViewNode: TAstViewNode; + + procedure CollectNodes(Parent: TControl); + procedure ClearVisuals; + procedure ApplyErrors(const Log: ICompilerLog); + procedure ApplyTypes(const TypedAst: IAstNode); + + public + constructor Create(const AEnv: TAstEnvironment; AWorkspace: TAstWorkspace); + destructor Destroy; override; + + procedure ValidateAndShow; + procedure SetRoot(const AstNode: IAstNode); + end; + +implementation + +uses + Myc.Data.Value; + +{ TAstEditorController } + +constructor TAstEditorController.Create(const AEnv: TAstEnvironment; AWorkspace: TAstWorkspace); +begin + inherited Create; + FEnv := AEnv; + FWorkspace := AWorkspace; + FNodeMap := TNodeMap.Create; +end; + +destructor TAstEditorController.Destroy; +begin + FNodeMap.Free; + inherited; +end; + +procedure TAstEditorController.SetRoot(const AstNode: IAstNode); +begin + FWorkspace.DeleteChildren; + FWorkspace.Build(AstNode, TPointF.Create(50, 50)); + + if FWorkspace.ChildrenCount > 0 then + begin + for var i := 0 to FWorkspace.ChildrenCount - 1 do + if FWorkspace.Children[i] is TAstViewNode then + begin + FRootViewNode := TAstViewNode(FWorkspace.Children[i]); + break; + end; + end; + + ValidateAndShow; +end; + +procedure TAstEditorController.CollectNodes(Parent: TControl); +var + i: Integer; + child: TControl; + viewNode: TAstViewNode; +begin + for i := 0 to Parent.ChildrenCount - 1 do + begin + if Parent.Children[i] is TControl then + begin + child := TControl(Parent.Children[i]); + + if child is TAstViewNode then + begin + viewNode := TAstViewNode(child); + // Register Identity -> ViewNode + // Note: ReconstructAst updates the Node property of the ViewNode, + // so we must ensure we use the identity from the *logical* node held by the view. + if Assigned(viewNode.Node) and Assigned(viewNode.Node.Identity) then + begin + FNodeMap.AddOrSetValue(viewNode.Node.Identity, viewNode); + end; + end; + + if child.ChildrenCount > 0 then + CollectNodes(child); + end; + end; +end; + +procedure TAstEditorController.ClearVisuals; +begin + for var viewNode in FNodeMap.Values do + begin + viewNode.ErrorMessage := ''; + viewNode.TypeInfoText := ''; + end; +end; + +procedure TAstEditorController.ApplyErrors(const Log: ICompilerLog); +var + entry: TCompilerError; + viewNode: TAstViewNode; +begin + for entry in Log.GetEntries do + begin + if (entry.Level = elError) and Assigned(entry.Node) and Assigned(entry.Node.Identity) then + begin + if FNodeMap.TryGetValue(entry.Node.Identity, viewNode) then + begin + if viewNode.ErrorMessage = '' then + viewNode.ErrorMessage := entry.Message + else + viewNode.ErrorMessage := viewNode.ErrorMessage + sLineBreak + entry.Message; + end; + end; + end; +end; + +procedure TAstEditorController.ApplyTypes(const TypedAst: IAstNode); +var + propagator: TTypePropagator; +begin + if not Assigned(TypedAst) then + Exit; + + propagator := TTypePropagator.Create(FNodeMap); + try + // Start traversal. The overload Accept(Node) will be called. + propagator.Accept(TypedAst); + finally + propagator.Free; + end; +end; + +procedure TAstEditorController.ValidateAndShow; +var + logicalAst: IAstNode; +begin + if not Assigned(FRootViewNode) then + Exit; + + // 1. Reconstruct Logical AST from UI + // This updates the .Node property on ViewNodes with fresh Identities (if configured) or reuses them. + logicalAst := FRootViewNode.CreateAst; + + // 2. Rebuild Mapping based on the new logical nodes + FNodeMap.Clear; + CollectNodes(FWorkspace); + + // 3. Clear visuals + ClearVisuals; + + // 4. Compile + try + // To get type info, we re-bind/check manually as Compile doesn't return the TypedAST. + var log := TCompilerLog.Create as ICompilerLog; + + // We need to expand macros first to match the structure Compile used + var expanded := FEnv.ExpandMacros(logicalAst); + var typedAst := FEnv.Bind(expanded, [], log); + + var specAst := FEnv.Specialize(typedAst); + + ApplyTypes(specAst); + + if specAst.Kind = akLambdaExpression then + var compiled := FEnv.Link(specAst.AsLambdaExpression, log); + + ApplyErrors(log); + except + on E: ECompilationFailed do + begin + var tempLog := TCompilerLog.Create as ICompilerLog; + for var err in E.Errors do + tempLog.Add(err.Level, err.Message, err.Node); + ApplyErrors(tempLog); + end; + end; + + FWorkspace.Repaint; +end; + +{ TAstEditorController.TTypePropagator } + +constructor TAstEditorController.TTypePropagator.Create(AMap: TNodeMap); +begin + inherited Create; + FMap := AMap; +end; + +procedure TAstEditorController.TTypePropagator.ApplyType(const Node: IAstNode); +var + viewNode: TAstViewNode; +begin + if Assigned(Node) and Assigned(Node.Identity) then + begin + if FMap.TryGetValue(Node.Identity, viewNode) then + begin + if Node.IsTyped then + begin + var st := Node.AsTypedNode.StaticType; + if Assigned(st) then + viewNode.TypeInfoText := st.ToString; + end; + end; + end; +end; + +procedure TAstEditorController.TTypePropagator.Accept(const Node: IAstNode); +begin + if Node = nil then + Exit; + + // 1. Apply side effect + ApplyType(Node); + + // 2. Continue traversal (Standard TAstVisitor logic calls VisitXY which calls Accept for children) + Node.Accept(Self); +end; + +end.