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.