diff --git a/ASTPlayground/ASTPlayground.delphilsp.json b/ASTPlayground/ASTPlayground.delphilsp.json
index 2f9040e..c8efac4 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.Fmx.AstEditor.Node", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Fmx.AstEditor.Node.pas" }, { "name": "Myc.Fmx.AstEditor.Workspace", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Fmx.AstEditor.Workspace.pas" }, { "name": "Myc.Fmx.AstEditor.Text", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Fmx.AstEditor.Text.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" } ] , "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
+{ "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
diff --git a/ASTPlayground/ASTPlayground.dpr b/ASTPlayground/ASTPlayground.dpr
index afcbf5b..8404838 100644
--- a/ASTPlayground/ASTPlayground.dpr
+++ b/ASTPlayground/ASTPlayground.dpr
@@ -12,9 +12,6 @@ uses
Myc.Ast.RTL in '..\Src\AST\Myc.Ast.RTL.pas',
Myc.Ast.Dumper in '..\Src\AST\Myc.Ast.Dumper.pas',
Myc.Ast.RTL.Core in '..\Src\AST\Myc.Ast.RTL.Core.pas',
- Myc.Fmx.AstEditor.Node in 'Myc.Fmx.AstEditor.Node.pas',
- Myc.Fmx.AstEditor.Workspace in 'Myc.Fmx.AstEditor.Workspace.pas',
- Myc.Fmx.AstEditor.Text in 'Myc.Fmx.AstEditor.Text.pas',
Myc.Utils in '..\Src\Myc.Utils.pas',
Myc.Ast.Script in '..\Src\AST\Myc.Ast.Script.pas',
Myc.Ast.Types in '..\Src\AST\Myc.Ast.Types.pas',
@@ -28,7 +25,11 @@ uses
Myc.Ast.Environment in '..\Src\AST\Myc.Ast.Environment.pas',
Myc.Ast.Debugger in '..\Src\AST\Myc.Ast.Debugger.pas',
Myc.Ast.Analysis.Purity in '..\Src\AST\Myc.Ast.Analysis.Purity.pas',
- Myc.Ast.Identities in '..\Src\AST\Myc.Ast.Identities.pas';
+ Myc.Ast.Identities in '..\Src\AST\Myc.Ast.Identities.pas',
+ 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';
{$R *.res}
diff --git a/ASTPlayground/ASTPlayground.dproj b/ASTPlayground/ASTPlayground.dproj
index 261a978..3e51201 100644
--- a/ASTPlayground/ASTPlayground.dproj
+++ b/ASTPlayground/ASTPlayground.dproj
@@ -142,9 +142,6 @@
-
-
-
@@ -159,6 +156,10 @@
+
+
+
+
Base
diff --git a/ASTPlayground/MainForm.pas b/ASTPlayground/MainForm.pas
index c826914..54af9c6 100644
--- a/ASTPlayground/MainForm.pas
+++ b/ASTPlayground/MainForm.pas
@@ -32,7 +32,7 @@ uses
Myc.Ast.Script,
FMX.Layouts,
FMX.Objects,
- Myc.Fmx.AstEditor.Node,
+ Myc.Fmx.AstEditor.Core,
Myc.Fmx.AstEditor.Workspace,
FMX.DialogService,
FMX.ListView.Types,
diff --git a/ASTPlayground/Myc.Fmx.AstEditor.Node.pas b/ASTPlayground/Myc.Fmx.AstEditor.Node.pas
deleted file mode 100644
index 07df5a4..0000000
--- a/ASTPlayground/Myc.Fmx.AstEditor.Node.pas
+++ /dev/null
@@ -1,2361 +0,0 @@
-unit Myc.Fmx.AstEditor.Node;
-
-interface
-
-uses
- System.SysUtils,
- System.Classes,
- System.UITypes,
- System.Types,
- System.Math.Vectors,
- System.Math,
- System.Generics.Defaults,
- System.Generics.Collections,
- FMX.Types,
- FMX.Controls,
- FMX.Objects,
- FMX.Graphics,
- FMX.StdCtrls,
- Myc.Data.Scalar,
- Myc.Data.Value,
- Myc.Data.Keyword,
- Myc.Ast.Nodes,
- Myc.Ast.Visitor,
- Myc.Ast.Identities, // NEU: Für Casts
- Myc.Ast,
- Myc.Fmx.AstEditor.Workspace;
-
-const
- cNodePadding = 10;
- cTitleTopPadding = 2;
- cTitleBottomPadding = 4;
- cMinNodeWidth = 10;
- cMinNodeHeight = 10;
-
-type
- TAuraNode = class; // Forward declaration
-
- // This aggregate interface encapsulates all node-specific logic.
- IAuraNodeHandler = interface
- ['{B66291B7-14A1-4638-927A-05B1623C83A6}']
- // Gets the original logical AST node
- function GetAstNode: IAstNode;
- // Creates the specific FMX UI for this node
- procedure BuildUI(OwnerNode: TAuraNode);
- // Reconstructs the logical AST node from the FMX UI state
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- // The original logical AST node
- property Node: IAstNode read GetAstNode;
- end;
-
- IAstVisualizer = interface
- {$region 'private'}
- function GetExprDepth: Integer;
- function GetParentControl: TControl;
- {$endregion}
-
- function Clone(ParentControl: TControl; ExprDepth: Integer): IAstVisualizer;
- function CallAccept(const Node: IAstNode): TAuraNode;
- function GetWorkspace: TAuraWorkspace;
-
- property ExprDepth: Integer read GetExprDepth;
- property ParentControl: TControl read GetParentControl;
- property Workspace: TAuraWorkspace read GetWorkspace;
- end;
-
- // Inherits from the new generic TAstVisitor
- TAstVisualizer = class(TAstVisitor, IAstVisualizer)
- private
- FExprDepth: Integer;
- FParentControl: TControl;
- FWorkspace: TAuraWorkspace;
- // Calls Accept on the node and returns the resulting TAuraNode.
- function CallAccept(const Node: IAstNode): TAuraNode;
- function GetExprDepth: Integer;
- function GetParentControl: TControl;
- function GetWorkspace: TAuraWorkspace;
- procedure SetExprDepth(const Value: Integer);
- procedure SetParentControl(const Value: TControl);
- protected
- // Visitor implementations for each AST node type.
- function VisitConstant(const Node: IConstantNode): TAuraNode; override;
- function VisitIdentifier(const Node: IIdentifierNode): TAuraNode; override;
- function VisitKeyword(const Node: IKeywordNode): TAuraNode; override;
- function VisitIfExpression(const Node: IIfExpressionNode): TAuraNode; override;
- function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAuraNode; override;
- function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAuraNode; override;
- function VisitFunctionCall(const Node: IFunctionCallNode): TAuraNode; override;
- function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TAuraNode; override;
- function VisitBlockExpression(const Node: IBlockExpressionNode): TAuraNode; override;
- function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAuraNode; override;
- function VisitAssignment(const Node: IAssignmentNode): TAuraNode; override;
- function VisitMacroDefinition(const Node: IMacroDefinitionNode): TAuraNode; override;
- function VisitQuasiquote(const Node: IQuasiquoteNode): TAuraNode; override;
- function VisitUnquote(const Node: IUnquoteNode): TAuraNode; override;
- function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TAuraNode; override;
- function VisitIndexer(const Node: IIndexerNode): TAuraNode; override;
- function VisitMemberAccess(const Node: IMemberAccessNode): TAuraNode; override;
- function VisitRecordLiteral(const Node: IRecordLiteralNode): TAuraNode; override;
- function VisitCreateSeries(const Node: ICreateSeriesNode): TAuraNode; override;
- function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAuraNode; override;
- function VisitSeriesLength(const Node: ISeriesLengthNode): TAuraNode; override;
- function VisitRecurNode(const Node: IRecurNode): TAuraNode; override;
- function VisitNop(const Node: INopNode): TAuraNode; override;
-
- public
- constructor Create(AWorkspace: TAuraWorkspace; AParentControl: TControl; AExprDepth: Integer);
- destructor Destroy; override;
-
- function Clone(ParentControl: TControl; ExprDepth: Integer): IAstVisualizer;
-
- property ExprDepth: Integer read GetExprDepth write SetExprDepth;
- property ParentControl: TControl read GetParentControl write SetParentControl;
- property Workspace: TAuraWorkspace read GetWorkspace;
- end;
-
- // Defines the layout direction for children within TAutoFitControl
- TLayoutOrientation = (loVertical, loHorizontal);
-
- // Defines the alignment of children on the cross-axis
- TLayoutAlignment = (laCenter, laFlush);
-
- // A styled control that automatically adjusts its size to fit its children, including padding.
- TAutoFitControl = class(TStyledControl)
- private
- FUpdatingOwnSize: Boolean; // Recursion guard
- FNeedRecalcSize: Boolean; // Flag for EndUpdate
- FOrientation: TLayoutOrientation; // Storage for Orientation
- FAlignment: TLayoutAlignment; // Storage for Alignment
- procedure RecalcOwnSize;
- procedure SetOrientation(const Value: TLayoutOrientation);
- procedure SetAlignment(const Value: TLayoutAlignment);
- protected
-
- // Called by children when their size, position, or visibility changes
- procedure ParentContentChanged; override;
- // Called when our own padding changes
- procedure PaddingChanged; override;
- // Called after children list has changed (add/remove)
- procedure ChangeChildren; override;
- // Initial calculation after loading
- procedure Loaded; override;
- // Handle pending recalc after updates
- procedure DoEndUpdate; override;
- public
- constructor Create(AOwner: TComponent); override;
-
- published
- // Make Padding published if needed
- property Padding;
- property Orientation: TLayoutOrientation read FOrientation write SetOrientation default TLayoutOrientation.loHorizontal;
- property Alignment: TLayoutAlignment read FAlignment write SetAlignment default TLayoutAlignment.laCenter;
- end;
-
- // A movable panel with a custom-painted border. Content (like title) is added externally.
- TAuraNode = class(TAutoFitControl)
- private
- FBackgroundColor: TAlphaColor;
- // Flag to indicate if the control is currently being dragged.
- FIsDragging: Boolean;
- // Stores the mouse coordinates at the beginning of the drag operation.
- FDownPos: TPointF;
- // Properties for the custom-drawn border.
- FBorderColor: TAlphaColor;
- FBorderWidth: Single;
- FBorderRadius: Single;
- // If true, the node is drawn without a border and with a transparent background.
- FFrameless: Boolean;
- FVisualizer: IAstVisualizer;
- FHandler: IAuraNodeHandler; // *** NEW: Strategy/Aggregate ***
- procedure SetBackgroundColor(const Value: TAlphaColor);
- procedure SetBorderColor(const Value: TAlphaColor);
- procedure SetBorderWidth(const Value: Single);
- procedure SetBorderRadius(const Value: Single);
- procedure SetFrameless(const Value: Boolean);
- function GetNode: IAstNode;
- protected
- procedure Paint; override;
- procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Single); override;
- procedure MouseMove(Shift: TShiftState; X, Y: Single); override;
- procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Single); override;
- procedure SetupNode;
-
- function AddLabel(Parent: TControl; const Txt: String): TLabel;
- function AddContainer(Parent: TControl; Orientation: TLayoutOrientation; Alignment: TLayoutAlignment): TAutoFitControl;
- function AddExpr(Parent: TControl; const Title: String; const Node: IAstNode): TAuraNode;
-
- public
- constructor Create(const AVisualizer: IAstVisualizer; const AHandler: IAuraNodeHandler); reintroduce;
- destructor Destroy; override;
-
- procedure AfterConstruction; override;
-
- // *** CHANGED: Now non-virtual, delegates to handler ***
- function CreateAst: IAstNode;
-
- property Visualizer: IAstVisualizer read FVisualizer;
- // *** NEW: Access to the original logical node via the handler ***
- property Node: IAstNode read GetNode;
-
- published
- // Custom border properties
- property BorderColor: TAlphaColor read FBorderColor write SetBorderColor;
- property BorderWidth: Single read FBorderWidth write SetBorderWidth;
- property BorderRadius: Single read FBorderRadius write SetBorderRadius;
- property BackgroundColor: TAlphaColor read FBackgroundColor write SetBackgroundColor;
-
- // Behavior properties
- property Frameless: Boolean read FFrameless write SetFrameless;
-
- // Standard control properties
- property Align;
- property Anchors;
- property ClipChildren default True;
- property Cursor default crDefault;
- property DragMode default TDragMode.dmManual;
- property Enabled;
- property Height;
- property Hint;
- property HitTest default True;
- property Locked;
- property Margins;
- property Opacity;
- property Padding;
- property PopupMenu;
- property Position;
- property RotationAngle;
- property RotationCenter;
- property Scale;
- property Size;
- property Visible;
- property Width;
- property OnClick;
- property OnDblClick;
- property OnMouseDown;
- property OnMouseMove;
- property OnMouseUp;
- property OnMouseWheel;
- property OnMouseEnter;
- property OnMouseLeave;
- end;
-
-implementation
-
-// We declare the handler classes here in the implementation
-// as they are private details of the visualizer.
-
-type
- { TConstantNodeHandler }
- TConstantNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IConstantNode;
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IConstantNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraIdentifierNode }
- TIdentifierNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IIdentifierNode;
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IIdentifierNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraKeywordNode }
- TKeywordNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IKeywordNode;
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IKeywordNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraBlockExpressionNode }
- TBlockExpressionNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IBlockExpressionNode;
- FChildNodes: TList; // To store children for CreateAst
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IBlockExpressionNode);
- destructor Destroy; override;
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraIfExpressionNode }
- TIfExpressionNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IIfExpressionNode;
- FConditionNode: TAuraNode;
- FThenNode: TAuraNode;
- FElseNode: TAuraNode; // Can be nil
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IIfExpressionNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraTernaryExpressionNode }
- TTernaryExpressionNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: ITernaryExpressionNode;
- FConditionNode: TAuraNode;
- FThenNode: TAuraNode;
- FElseNode: TAuraNode;
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: ITernaryExpressionNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraLambdaExpressionNode }
- TLambdaExpressionNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: ILambdaExpressionNode;
- FBodyNode: TAuraNode;
- FParamLabels: TList; // To store param labels
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: ILambdaExpressionNode);
- destructor Destroy; override;
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraFunctionCallNode }
- TFunctionCallNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IFunctionCallNode;
- FCalleeNode: TAuraNode;
- FArgumentNodes: TList;
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IFunctionCallNode);
- destructor Destroy; override;
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraMacroExpansionNode }
- TMacroExpansionNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IMacroExpansionNode;
- FExpandedBodyNode: TAuraNode;
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IMacroExpansionNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraRecurNode }
- TRecurNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IRecurNode;
- FArgumentNodes: TList;
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IRecurNode);
- destructor Destroy; override;
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraVariableDeclarationNode }
- TVariableDeclarationNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IVariableDeclarationNode;
- FTargetNode: TAuraNode;
- FInitializerNode: TAuraNode; // Can be nil
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IVariableDeclarationNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraAssignmentNode }
- TAssignmentNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IAssignmentNode;
- FTargetNode: TAuraNode;
- FValueNode: TAuraNode;
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IAssignmentNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraMacroDefinitionNode }
- TMacroDefinitionNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IMacroDefinitionNode;
- FBodyNode: TAuraNode;
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IMacroDefinitionNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraQuasiquoteNode }
- TQuasiquoteNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IQuasiquoteNode;
- FExpressionNode: TAuraNode;
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IQuasiquoteNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraUnquoteNode }
- TUnquoteNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IUnquoteNode;
- FExpressionNode: TAuraNode;
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IUnquoteNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraUnquoteSplicingNode }
- TUnquoteSplicingNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IUnquoteSplicingNode;
- FExpressionNode: TAuraNode;
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IUnquoteSplicingNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraIndexerNode }
- TIndexerNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IIndexerNode;
- FBaseNode: TAuraNode;
- FIndexNode: TAuraNode;
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IIndexerNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraMemberAccessNode }
- TMemberAccessNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IMemberAccessNode;
- FBaseNode: TAuraNode;
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IMemberAccessNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraRecordLiteralNode }
- TRecordLiteralNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IRecordLiteralNode;
- FFieldNodes: TDictionary; // Map KeyName -> ValueNode
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IRecordLiteralNode);
- destructor Destroy; override;
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraCreateSeriesNode }
- TCreateSeriesNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: ICreateSeriesNode;
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: ICreateSeriesNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraAddSeriesItemNode }
- TAddSeriesItemNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: IAddSeriesItemNode;
- FValueNode: TAuraNode;
- FLookbackNode: TAuraNode; // Can be nil
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: IAddSeriesItemNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraSeriesLengthNode }
- TSeriesLengthNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: ISeriesLengthNode;
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: ISeriesLengthNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
- { TAuraNopNode }
- TNopNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
- private
- FNode: INopNode;
- function GetAstNode: IAstNode;
- public
- constructor Create(const ANode: INopNode);
- procedure BuildUI(OwnerNode: TAuraNode);
- function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
- end;
-
-{ TAstVisualizer }
-
-constructor TAstVisualizer.Create(AWorkspace: TAuraWorkspace; AParentControl: TControl; AExprDepth: Integer);
-begin
- inherited Create;
- FWorkspace := AWorkspace;
- FParentControl := AParentControl;
- FExprDepth := AExprDepth;
-end;
-
-destructor TAstVisualizer.Destroy;
-begin
- inherited;
-end;
-
-// Calls Accept on the node and returns the resulting TAuraNode.
-function TAstVisualizer.CallAccept(const Node: IAstNode): TAuraNode;
-var
- DataValue: TDataValue;
-begin
- if not Assigned(Node) then
- Exit(nil); // Handle nil input node gracefully
-
- DataValue := Node.Accept(Self);
-
- // Check if the result is actually a TAuraNode before casting
- if DataValue.Kind = TDataValueKind.vkGeneric then
- begin
- // Assuming the visitor correctly returns TAuraNode wrapped in TDataValue.
- Result := DataValue.AsGeneric;
- end
- else
- begin
- Result := nil;
- end;
-end;
-
-function TAstVisualizer.Clone(ParentControl: TControl; ExprDepth: Integer): IAstVisualizer;
-begin
- Result := TAstVisualizer.Create(FWorkspace, ParentControl, ExprDepth);
-end;
-
-function TAstVisualizer.GetExprDepth: Integer;
-begin
- Result := FExprDepth;
-end;
-
-function TAstVisualizer.GetParentControl: TControl;
-begin
- Result := FParentControl;
-end;
-
-function TAstVisualizer.GetWorkspace: TAuraWorkspace;
-begin
- Result := FWorkspace;
-end;
-
-procedure TAstVisualizer.SetExprDepth(const Value: Integer);
-begin
- FExprDepth := Value;
-end;
-
-procedure TAstVisualizer.SetParentControl(const Value: TControl);
-begin
- FParentControl := Value;
-end;
-
-// --- Visitor Implementations ---
-
-function TAstVisualizer.VisitConstant(const Node: IConstantNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TConstantNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitIdentifier(const Node: IIdentifierNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TIdentifierNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitKeyword(const Node: IKeywordNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TKeywordNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitBlockExpression(const Node: IBlockExpressionNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TBlockExpressionNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitIfExpression(const Node: IIfExpressionNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TIfExpressionNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitTernaryExpression(const Node: ITernaryExpressionNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TTernaryExpressionNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TLambdaExpressionNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitFunctionCall(const Node: IFunctionCallNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TFunctionCallNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TMacroExpansionNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TVariableDeclarationNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitAssignment(const Node: IAssignmentNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TAssignmentNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitMacroDefinition(const Node: IMacroDefinitionNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TMacroDefinitionNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitQuasiquote(const Node: IQuasiquoteNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TQuasiquoteNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitUnquote(const Node: IUnquoteNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TUnquoteNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TUnquoteSplicingNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitIndexer(const Node: IIndexerNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TIndexerNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitMemberAccess(const Node: IMemberAccessNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TMemberAccessNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitRecordLiteral(const Node: IRecordLiteralNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TRecordLiteralNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitCreateSeries(const Node: ICreateSeriesNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TCreateSeriesNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TAddSeriesItemNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitSeriesLength(const Node: ISeriesLengthNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TSeriesLengthNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitRecurNode(const Node: IRecurNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TRecurNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-function TAstVisualizer.VisitNop(const Node: INopNode): TAuraNode;
-var
- Handler: IAuraNodeHandler;
-begin
- Handler := TNopNodeHandler.Create(Node);
- Result := TAuraNode.Create(Self, Handler);
-end;
-
-{ TAutoFitControl }
-
-constructor TAutoFitControl.Create(AOwner: TComponent);
-begin
- inherited Create(AOwner);
- HitTest := True;
- FOrientation := TLayoutOrientation.loHorizontal;
- FAlignment := TLayoutAlignment.laCenter; // Default alignment
-end;
-
-procedure TAutoFitControl.SetAlignment(const Value: TLayoutAlignment);
-begin
- if FAlignment <> Value then
- begin
- FAlignment := Value;
- RecalcOwnSize; // Re-layout on alignment change
- end;
-end;
-
-procedure TAutoFitControl.SetOrientation(const Value: TLayoutOrientation);
-begin
- if FOrientation <> Value then
- begin
- FOrientation := Value;
- RecalcOwnSize; // Recalculate layout when orientation changes
- end;
-end;
-
-procedure TAutoFitControl.RecalcOwnSize;
-var
- I: Integer;
- Child: TControl;
- ChildrenToLayout: TList; // Still used to filter relevant children
- CurrentX, CurrentY: Single;
- RequiredWidth, RequiredHeight: Single;
- ChildWidthWithMargins, ChildHeightWithMargins: Single;
- HasVisibleChild: Boolean;
-begin
- if FUpdatingOwnSize then
- Exit;
- if IsUpdating then
- begin
- FNeedRecalcSize := True;
- Exit;
- end;
-
- FUpdatingOwnSize := True;
- ChildrenToLayout := nil;
- try
- RequiredWidth := Padding.Left + Padding.Right;
- RequiredHeight := Padding.Top + Padding.Bottom;
- CurrentX := Padding.Left;
- CurrentY := Padding.Top;
- HasVisibleChild := False;
-
- // Collect relevant children
- ChildrenToLayout := TList.Create;
- for I := 0 to ChildrenCount - 1 do
- begin
- if Children[I] is TControl then
- begin
- Child := TControl(Children[I]);
- if Child.Visible and (Child.Align = TAlignLayout.None) then
- begin
- ChildrenToLayout.Add(Child);
- HasVisibleChild := True;
- end;
- end;
- end;
-
- if HasVisibleChild then
- begin
- // Perform layout based on orientation
- if FOrientation = TLayoutOrientation.loVertical then
- begin
- // Pass 1: Calculate total height and max width. Set Y pos.
- for Child in ChildrenToLayout do
- begin
- // Store Y position
- Child.Position.Y := CurrentY + Child.Margins.Top;
- CurrentY := Child.Position.Y + Child.Height + Child.Margins.Bottom;
-
- // Calculate max width
- ChildWidthWithMargins := Padding.Left + Child.Margins.Left + Child.Width + Child.Margins.Right + Padding.Right;
- RequiredWidth := System.Math.Max(RequiredWidth, ChildWidthWithMargins);
- end;
- RequiredHeight := CurrentY + Padding.Bottom;
-
- // Pass 2: Align children horizontally based on FAlignment
- if FAlignment = TLayoutAlignment.laFlush then
- begin
- // Flush (left-aligned)
- for Child in ChildrenToLayout do
- begin
- Child.Position.X := Padding.Left + Child.Margins.Left;
- end;
- end
- else
- begin
- // Center-aligned
- var contentWidth := RequiredWidth - Padding.Left - Padding.Right;
- for Child in ChildrenToLayout do
- begin
- var childTotalWidth := Child.Width + Child.Margins.Left + Child.Margins.Right;
- var childX := Padding.Left + ((contentWidth - childTotalWidth) / 2) + Child.Margins.Left;
- Child.Position.X := childX;
- end;
- end;
- end
- else // loHorizontal
- begin
- // Pass 1: Calculate total width and max height. Set X pos.
- for Child in ChildrenToLayout do
- begin
- // Store X position
- Child.Position.X := CurrentX + Child.Margins.Left;
- CurrentX := Child.Position.X + Child.Width + Child.Margins.Right;
-
- // Calculate max height
- ChildHeightWithMargins := Padding.Top + Child.Margins.Top + Child.Height + Child.Margins.Bottom + Padding.Bottom;
- RequiredHeight := System.Math.Max(RequiredHeight, ChildHeightWithMargins);
- end;
- RequiredWidth := CurrentX + Padding.Right;
-
- // Pass 2: Align children vertically based on FAlignment
- if FAlignment = TLayoutAlignment.laFlush then
- begin
- // Flush (top-aligned)
- for Child in ChildrenToLayout do
- begin
- Child.Position.Y := Padding.Top + Child.Margins.Top;
- end;
- end
- else
- begin
- // Center-aligned
- var contentHeight := RequiredHeight - Padding.Top - Padding.Bottom;
- for Child in ChildrenToLayout do
- begin
- var childTotalHeight := Child.Height + Child.Margins.Top + Child.Margins.Bottom;
- var childY := Padding.Top + ((contentHeight - childTotalHeight) / 2) + Child.Margins.Top;
- Child.Position.Y := childY;
- end;
- end;
- end;
- end
- else
- begin
- RequiredWidth := Padding.Left + Padding.Right;
- RequiredHeight := Padding.Top + Padding.Bottom;
- end;
-
- RequiredWidth := System.Math.Max(0, RequiredWidth);
- RequiredHeight := System.Math.Max(0, RequiredHeight);
-
- if not SameValue(RequiredWidth, Width, TEpsilon.Position) or not SameValue(RequiredHeight, Height, TEpsilon.Position) then
- begin
- FSize.SetSizeWithoutNotification(TSizeF.Create(RequiredWidth, RequiredHeight));
- HandleSizeChanged;
- end;
-
- finally
- ChildrenToLayout.Free;
- FUpdatingOwnSize := False;
- end;
-end;
-
-procedure TAutoFitControl.Loaded;
-begin
- inherited Loaded;
- // Perform initial size calculation after all children are loaded
- RecalcOwnSize;
-end;
-
-procedure TAutoFitControl.ChangeChildren;
-begin
- inherited ChangeChildren;
- // Recalculate size when children are added or removed
- RecalcOwnSize;
-end;
-
-procedure TAutoFitControl.PaddingChanged;
-begin
- inherited PaddingChanged;
- // Recalculate size when padding changes
- RecalcOwnSize;
-end;
-
-procedure TAutoFitControl.ParentContentChanged;
-begin
- inherited ParentContentChanged;
- // Recalculate size when a child signals a potential layout change
- RecalcOwnSize;
-end;
-
-procedure TAutoFitControl.DoEndUpdate;
-begin
- inherited;
- // If a recalc was deferred during BeginUpdate/EndUpdate, do it now
- if FNeedRecalcSize then
- begin
- FNeedRecalcSize := False;
- RecalcOwnSize;
- end;
-end;
-
-{ TAuraNode }
-
-constructor TAuraNode.Create(const AVisualizer: IAstVisualizer; const AHandler: IAuraNodeHandler);
-begin
- inherited Create(AVisualizer.Workspace);
-
- Parent := AVisualizer.ParentControl;
-
- FVisualizer := AVisualizer.Clone(Self, AVisualizer.ExprDepth);
- FHandler := AHandler; // *** Store the injected handler ***
-
- FIsDragging := False;
-
- // Default border settings
- FBorderColor := TAlphaColors.Gray;
- FBorderWidth := 1;
- FBorderRadius := 9; // Rounded corners by default
- FBackgroundColor := $080a0a0a;
-
- // Default state for frameless mode
- FFrameless := False;
-
- // Set a default minimum size, will be adjusted later
- Width := cMinNodeWidth;
- Height := cMinNodeHeight;
-
- // The panel must be able to receive mouse events.
- HitTest := True; // Make sure HitTest is True to receive mouse events
- // Clip children to the panel's bounds.
- ClipChildren := True;
-
- Margins.Left := 4;
- Margins.Top := 4;
- Margins.Right := 4;
- Margins.Bottom := 4;
- Padding.Left := 3;
- Padding.Top := 3;
- Padding.Right := 3;
- Padding.Bottom := 3;
-
- var cn: cardinal := $ea - (7 * FVisualizer.ExprDepth);
- var c: cardinal := $ff000000 or (cn shl 16) or (cn shl 8) or cn;
- BackgroundColor := c;
-end;
-
-destructor TAuraNode.Destroy;
-begin
- FHandler := nil; // Release the handler interface
- inherited;
-end;
-
-function TAuraNode.AddContainer(Parent: TControl; Orientation: TLayoutOrientation; Alignment: TLayoutAlignment): TAutoFitControl;
-begin
- Result := TAutoFitControl.Create(Self);
- Result.Parent := Parent;
- Result.Orientation := Orientation;
- Result.Alignment := Alignment;
- Result.HitTest := False; // Pass clicks to parent
-end;
-
-function TAuraNode.AddExpr(Parent: TControl; const Title: String; const Node: IAstNode): TAuraNode;
-begin
- var cont := AddContainer(Parent, loHorizontal, laCenter);
-
- var lbl := AddLabel(cont, Title);
- lbl.Font.Style := lbl.Font.Style + [TFontStyle.fsBold];
-
- Result := FVisualizer.Clone(cont, FVisualizer.ExprDepth + 1).CallAccept(Node);
-end;
-
-function TAuraNode.AddLabel(Parent: TControl; const Txt: String): TLabel;
-begin
- Result := TLabel.Create(Self); // Owner is the node itself
- Result.Parent := Parent;
-
- Result.Position.Point := TPoint.Create(cNodePadding, cNodePadding);
- Result.Margins.Left := cNodePadding;
- Result.Margins.Right := cNodePadding;
- Result.Margins.Top := cTitleTopPadding;
- Result.Margins.Bottom := cTitleBottomPadding;
- Result.WordWrap := false;
- Result.AutoSize := True; // Let label determine its own size initially (do NOT use Align, because it will override AutoSize)
- Result.HitTest := False; // Title label should not intercept clicks intended for the node
-
- Result.StyledSettings := Result.StyledSettings - [TStyledSetting.Style]; // Tell FMX not to manage Font.Style via styles
-
- Result.Text := Txt;
- Result.ApplyStyleLookup;
-end;
-
-procedure TAuraNode.AfterConstruction;
-begin
- inherited;
- SetupNode;
-end;
-
-function TAuraNode.CreateAst: IAstNode;
-begin
- // *** CHANGED: Delegate AST reconstruction to the handler ***
- if Assigned(FHandler) then
- Result := FHandler.ReconstructAst(Self)
- else
- Result := TAst.Nop; // Fallback if handler is missing
-end;
-
-function TAuraNode.GetNode: IAstNode;
-begin
- // *** NEW: Get the logical node from the handler ***
- if Assigned(FHandler) then
- Result := FHandler.Node
- else
- Result := nil;
-end;
-
-procedure TAuraNode.Paint;
-var
- rect: TRectF;
-begin
- inherited; // Allow styled painting to occur first (if any)
-
- // Clear background before drawing custom border/fill
- Canvas.Fill.Kind := TBrushKind.None; // Make sure default fill is cleared if needed
-
- if FFrameless then
- begin
- Canvas.Fill.Kind := TBrushKind.Solid;
- Canvas.Fill.Color := FBackgroundColor;
- Canvas.Stroke.Kind := TBrushKind.None;
- Canvas.FillRect(TRectF.Create(0, 0, Width, Height), 0, 0, [], 1.0);
- Canvas.Stroke.Kind := TBrushKind.Solid;
- Canvas.Stroke.Color := FBorderColor;
- Canvas.Stroke.Thickness := FBorderWidth;
- Canvas.Stroke.Dash := TStrokeDash.Dot;
- Canvas.DrawRect(TRectF.Create(0, 0, Width, Height), 0, 0, [], 1.0);
- end
- else
- begin
- // Draw background fill first
- Canvas.Fill.Kind := TBrushKind.Solid;
- Canvas.Fill.Color := FBackgroundColor;
- rect := TRectF.Create(0, 0, Width, Height);
- // Inflate inwards slightly if border exists to avoid overlap issues
- if (FBorderWidth > 0) then
- rect.Inflate(-FBorderWidth / 2, -FBorderWidth / 2);
- Canvas.FillRect(rect, FBorderRadius, FBorderRadius, AllCorners, 1.0, TCornerType.Round);
-
- // Custom painting for the border
- if (FBorderWidth > 0) and (FBorderColor <> TAlphaColors.Null) then
- begin
- rect := TRectF.Create(0, 0, Width, Height);
- // Inflate inwards so the border is fully visible within the control's bounds
- rect.Inflate(-FBorderWidth / 2, -FBorderWidth / 2);
-
- Canvas.Stroke.Kind := TBrushKind.Solid;
- Canvas.Stroke.Color := FBorderColor;
- Canvas.Stroke.Thickness := FBorderWidth;
- Canvas.Stroke.Dash := TStrokeDash.Solid;
- Canvas.DrawRect(rect, FBorderRadius, FBorderRadius, AllCorners, 1.0, TCornerType.Round);
- end;
- end;
-end;
-
-procedure TAuraNode.SetBorderColor(const Value: TAlphaColor);
-begin
- if FBorderColor <> Value then
- begin
- FBorderColor := Value;
- Repaint;
- end;
-end;
-
-procedure TAuraNode.SetBorderRadius(const Value: Single);
-begin
- if FBorderRadius <> Value then
- begin
- FBorderRadius := Value;
- Repaint;
- end;
-end;
-
-procedure TAuraNode.SetBorderWidth(const Value: Single);
-begin
- if FBorderWidth <> Value then
- begin
- FBorderWidth := Value;
- Repaint;
- end;
-end;
-
-procedure TAuraNode.SetFrameless(const Value: Boolean);
-begin
- if FFrameless <> Value then
- begin
- FFrameless := Value;
- Repaint;
- end;
-end;
-
-procedure TAuraNode.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Single);
-begin
- inherited;
- if Button = TMouseButton.mbLeft then
- begin
- // Only start dragging if the click is on the node itself, not its children
- var LControl := ObjectAtPoint(LocalToScreen(TPointF.Create(X, Y)));
- if Assigned(LControl) and (LControl.GetObject = Self) then
- begin
- FIsDragging := True;
- FDownPos := TPointF.Create(X, Y);
- Capture;
- BringToFront; // Bring node to front when dragging starts
- end
- else
- FIsDragging := False; // Ensure dragging stops if click is on a child
- end;
-end;
-
-procedure TAuraNode.MouseMove(Shift: TShiftState; X, Y: Single);
-begin
- inherited;
-
- if FIsDragging then
- begin
- var deltaX := X - FDownPos.X;
- var deltaY := Y - FDownPos.Y;
-
- Position.X := Position.X + deltaX;
- Position.Y := Position.Y + deltaY;
-
- if ParentControl <> nil then
- ParentControl.Repaint; // Repaint the workspace to update connections
- end;
-end;
-
-procedure TAuraNode.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Single);
-begin
- inherited;
- if (Button = TMouseButton.mbLeft) and (FIsDragging) then
- begin
- ReleaseCapture;
- FIsDragging := False;
- if ParentControl <> nil then // Repaint one last time after drag ends
- ParentControl.Repaint;
- end;
-end;
-
-procedure TAuraNode.SetBackgroundColor(const Value: TAlphaColor);
-begin
- FBackgroundColor := Value;
- Repaint;
-end;
-
-procedure TAuraNode.SetupNode;
-begin
- if Assigned(FHandler) then
- FHandler.BuildUI(Self);
-end;
-
-{ TConstantNodeHandler }
-
-constructor TConstantNodeHandler.Create(const ANode: IConstantNode);
-begin
- inherited Create;
- FNode := ANode;
-end;
-
-function TConstantNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TConstantNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- valueStr: string;
- isConcise: Boolean;
-begin
- OwnerNode.BeginUpdate;
- try
- valueStr := FNode.Value.ToString;
- // Check if it's a number or a single-line text and not excessively long
- isConcise := ((FNode.Value.Kind = TDataValueKind.vkScalar) or (Pos(sLineBreak, valueStr) = 0)) and (Length(valueStr) < 40);
-
- if isConcise then
- begin
- // Display value directly in a centered label, frameless node
- OwnerNode.Frameless := true;
- OwnerNode.AddLabel(OwnerNode, valueStr);
- end
- else
- begin
- // Use standard framed node with Title label + Value label
- OwnerNode.Frameless := False;
- OwnerNode.Orientation := loVertical;
-
- var titleLabel := OwnerNode.AddLabel(OwnerNode, 'Const');
- titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
-
- // Value Label
- var valueLabel := OwnerNode.AddLabel(OwnerNode, valueStr);
- valueLabel.AutoSize := False;
- valueLabel.WordWrap := True;
- end;
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TConstantNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-begin
- // Reuse Identity: FNode.Identity.AsConstant
- Result := TAst.Constant(FNode.Identity.AsConstant, FNode.StaticType);
-end;
-
-{ TIdentifierNodeHandler }
-
-constructor TIdentifierNodeHandler.Create(const ANode: IIdentifierNode);
-begin
- inherited Create;
- FNode := ANode;
-end;
-
-function TIdentifierNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TIdentifierNodeHandler.BuildUI(OwnerNode: TAuraNode);
-begin
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := true; // Identifiers are frameless
- OwnerNode.AddLabel(OwnerNode, FNode.Name); // Add label with the identifier name
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TIdentifierNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-begin
- // Reusing identity guarantees the same name and source location
- Result := TAst.Identifier(FNode.Identity.AsNamed, FNode.Address, FNode.StaticType);
-end;
-
-{ TKeywordNodeHandler }
-
-constructor TKeywordNodeHandler.Create(const ANode: IKeywordNode);
-begin
- inherited Create;
- FNode := ANode;
-end;
-
-function TKeywordNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TKeywordNodeHandler.BuildUI(OwnerNode: TAuraNode);
-begin
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := true;
- var lbl := OwnerNode.AddLabel(OwnerNode, ':' + FNode.Value.Name);
- lbl.StyledSettings := lbl.StyledSettings - [TStyledSetting.FontColor];
- lbl.FontColor := TAlphaColors.Mediumvioletred;
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TKeywordNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-begin
- Result := TAst.Keyword(FNode.Identity.AsKeyword);
-end;
-
-{ TBlockExpressionNodeHandler }
-
-constructor TBlockExpressionNodeHandler.Create(const ANode: IBlockExpressionNode);
-begin
- inherited Create;
- FNode := ANode;
- FChildNodes := TList.Create;
-end;
-
-destructor TBlockExpressionNodeHandler.Destroy;
-begin
- FChildNodes.Free;
- inherited Destroy;
-end;
-
-function TBlockExpressionNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TBlockExpressionNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- visu: IAstVisualizer;
- childNode: TAuraNode;
- expr: IAstNode;
- titleLabel: TLabel;
- i: Integer;
- returnContainer: TAutoFitControl;
- visuReturn: IAstVisualizer;
-begin
- visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := true;
- OwnerNode.Orientation := loVertical;
- OwnerNode.Alignment := laFlush;
-
- for i := 0 to High(FNode.Expressions) do
- begin
- expr := FNode.Expressions[i];
-
- if i = High(FNode.Expressions) then
- begin
- returnContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter);
- titleLabel := OwnerNode.AddLabel(returnContainer, 'return');
- titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
- visuReturn := OwnerNode.Visualizer.Clone(returnContainer, OwnerNode.Visualizer.ExprDepth + 1);
- childNode := visuReturn.CallAccept(expr);
- FChildNodes.Add(childNode);
- end
- else
- begin
- childNode := visu.CallAccept(expr);
- FChildNodes.Add(childNode);
- end;
- end;
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TBlockExpressionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-var
- exprs: TArray;
- childNode: TAuraNode;
- i: Integer;
-begin
- SetLength(exprs, FChildNodes.Count);
- for i := 0 to FChildNodes.Count - 1 do
- begin
- childNode := FChildNodes[i];
- if Assigned(childNode) then
- exprs[i] := childNode.CreateAst
- else
- exprs[i] := TAst.Nop; // Use Nop as placeholder
- end;
-
- // Reuse structural identity
- Result := TAst.Block(FNode.Identity, exprs, FNode.StaticType);
-end;
-
-{ TIfExpressionNodeHandler }
-
-constructor TIfExpressionNodeHandler.Create(const ANode: IIfExpressionNode);
-begin
- inherited Create;
- FNode := ANode;
- FElseNode := nil;
-end;
-
-function TIfExpressionNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TIfExpressionNodeHandler.BuildUI(OwnerNode: TAuraNode);
-begin
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := False;
- OwnerNode.Orientation := loVertical;
- OwnerNode.Alignment := laFlush;
-
- FConditionNode := OwnerNode.AddExpr(OwnerNode, 'if', FNode.Condition);
- FThenNode := OwnerNode.AddExpr(OwnerNode, 'then', FNode.ThenBranch);
- if Assigned(FNode.ElseBranch) then
- FElseNode := OwnerNode.AddExpr(OwnerNode, 'else', FNode.ElseBranch);
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TIfExpressionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-var
- elseAst: IAstNode;
-begin
- if Assigned(FElseNode) then
- elseAst := FElseNode.CreateAst
- else
- elseAst := nil;
-
- Result := TAst.IfExpr(FNode.Identity, FConditionNode.CreateAst, FThenNode.CreateAst, elseAst, FNode.StaticType);
-end;
-
-{ TTernaryExpressionNodeHandler }
-
-constructor TTernaryExpressionNodeHandler.Create(const ANode: ITernaryExpressionNode);
-begin
- inherited Create;
- FNode := ANode;
-end;
-
-function TTernaryExpressionNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TTernaryExpressionNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- visu: IAstVisualizer;
-begin
- visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := True;
- OwnerNode.Orientation := loHorizontal;
- FConditionNode := visu.CallAccept(FNode.Condition);
- OwnerNode.AddLabel(OwnerNode, '?');
- FThenNode := visu.CallAccept(FNode.ThenBranch);
- OwnerNode.AddLabel(OwnerNode, ':');
- FElseNode := visu.CallAccept(FNode.ElseBranch);
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TTernaryExpressionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-begin
- Result := TAst.TernaryExpr(FNode.Identity, FConditionNode.CreateAst, FThenNode.CreateAst, FElseNode.CreateAst, FNode.StaticType);
-end;
-
-{ TLambdaExpressionNodeHandler }
-
-constructor TLambdaExpressionNodeHandler.Create(const ANode: ILambdaExpressionNode);
-begin
- inherited Create;
- FNode := ANode;
- FParamLabels := TList.Create;
-end;
-
-destructor TLambdaExpressionNodeHandler.Destroy;
-begin
- FParamLabels.Free;
- inherited Destroy;
-end;
-
-function TLambdaExpressionNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TLambdaExpressionNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- visu: IAstVisualizer;
- titleContainer: TAutoFitControl;
- paramLabel: TLabel;
- i: Integer;
-begin
- visu := OwnerNode.Visualizer.Clone(OwnerNode, 0); // Reset depth for body
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := False;
- OwnerNode.Orientation := loVertical;
- OwnerNode.Alignment := laFlush;
- OwnerNode.BackgroundColor := $090000ff;
-
- titleContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter);
-
- paramLabel := OwnerNode.AddLabel(titleContainer, 'fn'); // ASCII replacement for Lambda
- paramLabel.Font.Style := paramLabel.Font.Style + [TFontStyle.fsBold];
- FParamLabels.Add(paramLabel); // Add to list (though not really needed for CreateAst)
-
- paramLabel := OwnerNode.AddLabel(titleContainer, '(');
- FParamLabels.Add(paramLabel);
-
- for i := 0 to High(FNode.Parameters) do
- begin
- paramLabel := OwnerNode.AddLabel(titleContainer, FNode.Parameters[i].Name);
- FParamLabels.Add(paramLabel);
-
- if i < High(FNode.Parameters) then
- begin
- paramLabel := OwnerNode.AddLabel(titleContainer, ',');
- FParamLabels.Add(paramLabel);
- end;
- end;
-
- paramLabel := OwnerNode.AddLabel(titleContainer, ')');
- FParamLabels.Add(paramLabel);
-
- FBodyNode := visu.CallAccept(FNode.Body);
- FBodyNode.Frameless := false;
-
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TLambdaExpressionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-begin
- // Params are read from FNode (assuming they are not editable via UI labels for now)
- // Reuse Identity & Metadata
- Result :=
- TAst.LambdaExpr(
- FNode.Identity,
- FNode.Parameters,
- FBodyNode.CreateAst,
- FNode.Layout,
- FNode.Descriptor,
- FNode.Upvalues,
- FNode.HasNestedLambdas,
- FNode.IsPure,
- FNode.StaticType
- );
-end;
-
-{ TFunctionCallNodeHandler }
-
-constructor TFunctionCallNodeHandler.Create(const ANode: IFunctionCallNode);
-begin
- inherited Create;
- FNode := ANode;
- FArgumentNodes := TList.Create;
-end;
-
-destructor TFunctionCallNodeHandler.Destroy;
-begin
- FArgumentNodes.Free;
- inherited Destroy;
-end;
-
-function TFunctionCallNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TFunctionCallNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- visu: IAstVisualizer;
- i: Integer;
- argNode: TAuraNode;
-begin
- visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := True;
- OwnerNode.Orientation := loHorizontal;
-
- var callLabel := OwnerNode.AddLabel(OwnerNode, 'call ');
- callLabel.Font.Style := callLabel.Font.Style + [TFontStyle.fsBold];
-
- FCalleeNode := visu.CallAccept(FNode.Callee);
-
- if Length(FNode.Arguments) > 0 then
- begin
- OwnerNode.AddLabel(OwnerNode, '(');
- for i := 0 to High(FNode.Arguments) do
- begin
- argNode := visu.CallAccept(FNode.Arguments[i]);
- FArgumentNodes.Add(argNode);
- if i < High(FNode.Arguments) then
- OwnerNode.AddLabel(OwnerNode, ',');
- end;
- OwnerNode.AddLabel(OwnerNode, ')');
- end;
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TFunctionCallNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-var
- args: TArray;
- i: Integer;
-begin
- SetLength(args, FArgumentNodes.Count);
- for i := 0 to FArgumentNodes.Count - 1 do
- args[i] := FArgumentNodes[i].CreateAst;
-
- Result :=
- TAst.FunctionCall(
- FNode.Identity,
- FCalleeNode.CreateAst,
- args,
- FNode.StaticType,
- FNode.IsTailCall,
- FNode.StaticTarget,
- FNode.IsTargetPure
- );
-end;
-
-{ TMacroExpansionNodeHandler }
-
-constructor TMacroExpansionNodeHandler.Create(const ANode: IMacroExpansionNode);
-begin
- inherited Create;
- FNode := ANode;
-end;
-
-function TMacroExpansionNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TMacroExpansionNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- visu: IAstVisualizer;
- titleLabel: TLabel;
-begin
- visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := False;
- OwnerNode.Orientation := loVertical;
- titleLabel := OwnerNode.AddLabel(OwnerNode, 'Macro Expansion');
- titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
- FExpandedBodyNode := visu.CallAccept(FNode.ExpandedBody);
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TMacroExpansionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-begin
- Result :=
- TAst.MacroExpansionNode(
- FNode.Identity,
- FNode.CallNode,
- FExpandedBodyNode.CreateAst.AsTypedNode // TODO: Check if AsTypedNode is correct/safe
- );
-end;
-
-{ TRecurNodeHandler }
-
-constructor TRecurNodeHandler.Create(const ANode: IRecurNode);
-begin
- inherited Create;
- FNode := ANode;
- FArgumentNodes := TList.Create;
-end;
-
-destructor TRecurNodeHandler.Destroy;
-begin
- FArgumentNodes.Free;
- inherited Destroy;
-end;
-
-function TRecurNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TRecurNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- visu: IAstVisualizer;
- i: Integer;
- argNode: TAuraNode;
- titleLabel: TLabel;
-begin
- visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := True;
- OwnerNode.Orientation := loHorizontal;
-
- titleLabel := OwnerNode.AddLabel(OwnerNode, 'recur'); // ASCII text
- titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
-
- OwnerNode.AddLabel(OwnerNode, '(');
- for i := 0 to High(FNode.Arguments) do
- begin
- argNode := visu.CallAccept(FNode.Arguments[i]);
- FArgumentNodes.Add(argNode);
- if i < High(FNode.Arguments) then
- OwnerNode.AddLabel(OwnerNode, ',');
- end;
- OwnerNode.AddLabel(OwnerNode, ')');
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TRecurNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-var
- args: TArray;
- i: Integer;
-begin
- SetLength(args, FArgumentNodes.Count);
- for i := 0 to FArgumentNodes.Count - 1 do
- args[i] := FArgumentNodes[i].CreateAst;
- Result := TAst.Recur(FNode.Identity, args, FNode.StaticType);
-end;
-
-{ TVariableDeclarationNodeHandler }
-
-constructor TVariableDeclarationNodeHandler.Create(const ANode: IVariableDeclarationNode);
-begin
- inherited Create;
- FNode := ANode;
- FInitializerNode := nil;
-end;
-
-function TVariableDeclarationNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TVariableDeclarationNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- visu: IAstVisualizer;
- varLabel: TLabel;
-begin
- visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := True;
- OwnerNode.Orientation := loHorizontal;
-
- varLabel := OwnerNode.AddLabel(OwnerNode, 'var');
-
- varLabel.Font.Style := varLabel.Font.Style + [TFontStyle.fsBold];
- FTargetNode := visu.CallAccept(FNode.Target);
-
- if Assigned(FNode.Initializer) then
- begin
- OwnerNode.AddLabel(OwnerNode, ':=');
- FInitializerNode := visu.CallAccept(FNode.Initializer);
- end;
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TVariableDeclarationNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-var
- initAst: IAstNode;
-begin
- if Assigned(FInitializerNode) then
- initAst := FInitializerNode.CreateAst
- else
- initAst := nil;
- Result := TAst.VarDecl(FNode.Identity, FTargetNode.CreateAst, initAst, FNode.StaticType, FNode.IsBoxed);
-end;
-
-{ TAssignmentNodeHandler }
-
-constructor TAssignmentNodeHandler.Create(const ANode: IAssignmentNode);
-begin
- inherited Create;
- FNode := ANode;
-end;
-
-function TAssignmentNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TAssignmentNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- visu: IAstVisualizer;
-begin
- visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := True;
- OwnerNode.Orientation := loHorizontal;
- FTargetNode := visu.CallAccept(FNode.Target);
- OwnerNode.AddLabel(OwnerNode, ':=');
- FValueNode := visu.CallAccept(FNode.Value);
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TAssignmentNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-begin
- Result := TAst.Assign(FNode.Identity, FTargetNode.CreateAst, FValueNode.CreateAst, FNode.StaticType);
-end;
-
-{ TMacroDefinitionNodeHandler }
-
-constructor TMacroDefinitionNodeHandler.Create(const ANode: IMacroDefinitionNode);
-begin
- inherited Create;
- FNode := ANode;
-end;
-
-function TMacroDefinitionNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TMacroDefinitionNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- visu: IAstVisualizer;
- titleLabel: TLabel;
- paramStr: string;
- i: Integer;
-begin
- visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := False;
- OwnerNode.Orientation := loVertical;
-
- paramStr := '';
- for i := 0 to High(FNode.Parameters) do
- begin
- if i > 0 then
- paramStr := paramStr + ', ';
- paramStr := paramStr + FNode.Parameters[i].Name;
- end;
-
- titleLabel := OwnerNode.AddLabel(OwnerNode, 'Macro Def: ' + FNode.Name.Name + ' (' + paramStr + ')');
- titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
-
- FBodyNode := visu.CallAccept(FNode.Body);
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TMacroDefinitionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-begin
- // Note: Identifier is recreated from raw name here, losing Location if we don't be careful.
- // Ideally FNode.Name would be reused.
- // For now, we reconstruct the MacroDef using the original identity and parameters.
- Result :=
- TAst.MacroDef(
- FNode.Identity,
- FNode.Name, // Reuse Identifier Node
- FNode.Parameters, // Reuse Parameters
- FBodyNode.CreateAst
- );
-end;
-
-{ TQuasiquoteNodeHandler }
-
-constructor TQuasiquoteNodeHandler.Create(const ANode: IQuasiquoteNode);
-begin
- inherited Create;
- FNode := ANode;
-end;
-
-function TQuasiquoteNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TQuasiquoteNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- visu: IAstVisualizer;
- titleLabel: TLabel;
-begin
- visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := False;
- OwnerNode.Orientation := loVertical;
- titleLabel := OwnerNode.AddLabel(OwnerNode, 'Quasiquote');
- titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
- FExpressionNode := visu.CallAccept(FNode.Expression);
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TQuasiquoteNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-begin
- Result := TAst.Quasiquote(FNode.Identity, FExpressionNode.CreateAst);
-end;
-
-{ TUnquoteNodeHandler }
-
-constructor TUnquoteNodeHandler.Create(const ANode: IUnquoteNode);
-begin
- inherited Create;
- FNode := ANode;
-end;
-
-function TUnquoteNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TUnquoteNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- visu: IAstVisualizer;
-begin
- visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := True;
- OwnerNode.Orientation := loHorizontal;
-
- var leftBracket := OwnerNode.AddLabel(OwnerNode, '<');
- leftBracket.Padding.Right := 0;
- leftBracket.Margins.Right := 0;
-
- FExpressionNode := visu.CallAccept(FNode.Expression);
-
- var rightBracket := OwnerNode.AddLabel(OwnerNode, '>');
- rightBracket.Padding.Left := 0;
- rightBracket.Margins.Left := 0;
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TUnquoteNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-begin
- Result := TAst.Unquote(FNode.Identity, FExpressionNode.CreateAst);
-end;
-
-{ TUnquoteSplicingNodeHandler }
-
-constructor TUnquoteSplicingNodeHandler.Create(const ANode: IUnquoteSplicingNode);
-begin
- inherited Create;
- FNode := ANode;
-end;
-
-function TUnquoteSplicingNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TUnquoteSplicingNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- visu: IAstVisualizer;
- titleLabel: TLabel;
-begin
- visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := False;
- OwnerNode.Orientation := loVertical;
- titleLabel := OwnerNode.AddLabel(OwnerNode, 'Unquote-Splicing');
- titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
- // Note: FNode.Expression is a IQuasiquoteNode
- FExpressionNode := visu.CallAccept(FNode.Expression);
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TUnquoteSplicingNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-begin
- // Note: We assume the child node is still a QuasiquoteNode. If user changed it to something else,
- // this cast might fail or we need validation logic.
- Result := TAst.UnquoteSplicing(FNode.Identity, FExpressionNode.CreateAst.AsQuasiquote);
-end;
-
-{ TIndexerNodeHandler }
-
-constructor TIndexerNodeHandler.Create(const ANode: IIndexerNode);
-begin
- inherited Create;
- FNode := ANode;
-end;
-
-function TIndexerNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TIndexerNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- visu: IAstVisualizer;
-begin
- visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := True;
- OwnerNode.Orientation := loHorizontal;
- FBaseNode := visu.CallAccept(FNode.Base);
- OwnerNode.AddLabel(OwnerNode, '[');
- FIndexNode := visu.CallAccept(FNode.Index);
- OwnerNode.AddLabel(OwnerNode, ']');
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TIndexerNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-begin
- Result := TAst.Indexer(FNode.Identity, FBaseNode.CreateAst, FIndexNode.CreateAst, FNode.StaticType);
-end;
-
-{ TMemberAccessNodeHandler }
-
-constructor TMemberAccessNodeHandler.Create(const ANode: IMemberAccessNode);
-begin
- inherited Create;
- FNode := ANode;
-end;
-
-function TMemberAccessNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TMemberAccessNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- visu: IAstVisualizer;
-begin
- visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := True;
- OwnerNode.Orientation := loHorizontal;
- FBaseNode := visu.CallAccept(FNode.Base);
- OwnerNode.AddLabel(OwnerNode, '.');
- OwnerNode.AddLabel(OwnerNode, FNode.Member.Value.Name);
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TMemberAccessNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-begin
- // Reuse Identifier, Reuse Member Keyword (via TAst.Keyword with Identity)
- Result := TAst.MemberAccess(FNode.Identity, FBaseNode.CreateAst, TAst.Keyword(FNode.Member.Identity.AsKeyword), FNode.StaticType);
-end;
-
-{ TRecordLiteralNodeHandler }
-
-constructor TRecordLiteralNodeHandler.Create(const ANode: IRecordLiteralNode);
-begin
- inherited Create;
- FNode := ANode;
- FFieldNodes := TDictionary.Create;
-end;
-
-destructor TRecordLiteralNodeHandler.Destroy;
-begin
- FFieldNodes.Free;
- inherited Destroy;
-end;
-
-function TRecordLiteralNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TRecordLiteralNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- field: TRecordFieldLiteral;
- fieldContainer: TAutoFitControl;
- valueNode: TAuraNode;
- keyLabel: TLabel;
-begin
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := False;
- OwnerNode.Orientation := loVertical;
- OwnerNode.Alignment := laFlush;
-
- if Length(FNode.Fields) = 0 then
- begin
- OwnerNode.AddLabel(OwnerNode, '{}');
- end
- else
- begin
- for field in FNode.Fields do
- begin
- fieldContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter);
- keyLabel := OwnerNode.AddLabel(fieldContainer, ':' + field.Key.Value.Name);
- keyLabel.Font.Style := keyLabel.Font.Style + [TFontStyle.fsBold];
- keyLabel.StyledSettings := keyLabel.StyledSettings - [TStyledSetting.FontColor];
- keyLabel.FontColor := TAlphaColors.Mediumvioletred;
-
- valueNode := OwnerNode.Visualizer.Clone(fieldContainer, OwnerNode.Visualizer.ExprDepth + 1).CallAccept(field.Value);
- FFieldNodes.Add(field.Key.Value, valueNode);
- end;
- end;
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TRecordLiteralNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-var
- fields: TArray;
- i: Integer;
- valueNode: TAuraNode;
- pair: TPair;
-begin
- SetLength(fields, FFieldNodes.Count);
- i := 0;
- for pair in FFieldNodes do
- begin
- valueNode := pair.Value;
- // Note: We construct a new keyword node here for the key, losing location unless we stored it.
- // For simplicity, we use Creation Path for the Key, but Reuse Identity for the RecordLiteral itself.
- fields[i] := TRecordFieldLiteral.Create(TAst.Keyword(pair.Key.Name), valueNode.CreateAst);
- inc(i);
- end;
- Result := TAst.RecordLiteral(FNode.Identity, fields, FNode.ScalarDefinition, FNode.GenericDefinition, FNode.StaticType);
-end;
-
-{ TCreateSeriesNodeHandler }
-
-constructor TCreateSeriesNodeHandler.Create(const ANode: ICreateSeriesNode);
-begin
- inherited Create;
- FNode := ANode;
-end;
-
-function TCreateSeriesNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TCreateSeriesNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- titleLabel: TLabel;
-begin
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := False;
- OwnerNode.Orientation := loVertical;
- titleLabel := OwnerNode.AddLabel(OwnerNode, 'Create Series: ' + FNode.Definition);
- titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TCreateSeriesNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-begin
- // Identity.AsDefinition check needed? Or trust CreateSeries overload
- Result := TAst.CreateSeries(FNode.Identity.AsDefinition, FNode.StaticType);
-end;
-
-{ TAddSeriesItemNodeHandler }
-
-constructor TAddSeriesItemNodeHandler.Create(const ANode: IAddSeriesItemNode);
-begin
- inherited Create;
- FNode := ANode;
- FLookbackNode := nil;
-end;
-
-function TAddSeriesItemNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TAddSeriesItemNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- visu: IAstVisualizer;
- titleLabel: TLabel;
-begin
- visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := False;
- OwnerNode.Orientation := loVertical;
-
- titleLabel := OwnerNode.AddLabel(OwnerNode, 'Add Item to: ' + FNode.Series.Name);
- titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
-
- FValueNode := visu.CallAccept(FNode.Value);
- if Assigned(FNode.Lookback) then
- FLookbackNode := visu.CallAccept(FNode.Lookback);
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TAddSeriesItemNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-var
- lookbackAst: IAstNode;
-begin
- if Assigned(FLookbackNode) then
- lookbackAst := FLookbackNode.CreateAst
- else
- lookbackAst := nil;
-
- // Reusing identifier identity requires access to it.
- // Here we create a new identifier with same name but lose location of series ident.
- // Optimization: FNode.Series is available, we can reuse it!
-
- // Wait, TAst.AddSeriesItem takes IIdentifierNode. We can just reuse FNode.Series?
- // Yes, if the series name is not editable in UI.
-
- Result :=
- TAst.AddSeriesItem(
- FNode.Identity,
- FNode.Series, // Reuse original Series Identifier Node
- FValueNode.CreateAst,
- lookbackAst,
- FNode.StaticType
- );
-end;
-
-{ TSeriesLengthNodeHandler }
-
-constructor TSeriesLengthNodeHandler.Create(const ANode: ISeriesLengthNode);
-begin
- inherited Create;
- FNode := ANode;
-end;
-
-function TSeriesLengthNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TSeriesLengthNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- titleLabel: TLabel;
-begin
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := False;
- OwnerNode.Orientation := loVertical;
- titleLabel := OwnerNode.AddLabel(OwnerNode, 'Length of: ' + FNode.Series.Name);
- titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TSeriesLengthNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-begin
- Result := TAst.SeriesLength(FNode.Identity, FNode.Series, FNode.StaticType);
-end;
-
-{ TNopNodeHandler }
-
-constructor TNopNodeHandler.Create(const ANode: INopNode);
-begin
- inherited Create;
- FNode := ANode;
-end;
-
-function TNopNodeHandler.GetAstNode: IAstNode;
-begin
- Result := FNode;
-end;
-
-procedure TNopNodeHandler.BuildUI(OwnerNode: TAuraNode);
-var
- lbl: TLabel;
-begin
- OwnerNode.BeginUpdate;
- try
- OwnerNode.Frameless := true;
- OwnerNode.Alignment := TLayoutAlignment.laCenter;
- OwnerNode.Orientation := TLayoutOrientation.loHorizontal;
- lbl := OwnerNode.AddLabel(OwnerNode, '...');
- lbl.Font.Style := lbl.Font.Style + [TFontStyle.fsBold];
- lbl.Margins.Rect := TRectF.Create(8, 4, 8, 4);
- finally
- OwnerNode.EndUpdate;
- end;
-end;
-
-function TNopNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
-begin
- Result := FNode;
-end;
-
-end.
diff --git a/ASTPlayground/Myc.Fmx.AstEditor.Text.pas b/ASTPlayground/Myc.Fmx.AstEditor.Text.pas
deleted file mode 100644
index 6df89da..0000000
--- a/ASTPlayground/Myc.Fmx.AstEditor.Text.pas
+++ /dev/null
@@ -1,265 +0,0 @@
-unit Myc.Fmx.AstEditor.Text;
-
-interface
-
-uses
- System.SysUtils,
- Myc.Data.Value,
- Myc.Data.Scalar,
- Myc.Ast.Visitor,
- Myc.Ast.Nodes;
-
-type
- // This visitor converts an AST expression subtree into a single string.
- // It inherits from the generic visitor, returning a 'string' for each node.
- TAstToTextVisitor = class(TAstVisitor)
- protected
- function VisitConstant(const Node: IConstantNode): string; override;
- function VisitIdentifier(const Node: IIdentifierNode): string; override;
- function VisitKeyword(const Node: IKeywordNode): string; override;
- function VisitIfExpression(const Node: IIfExpressionNode): string; override;
- function VisitTernaryExpression(const Node: ITernaryExpressionNode): string; override;
- function VisitLambdaExpression(const Node: ILambdaExpressionNode): string; override;
- function VisitMacroDefinition(const Node: IMacroDefinitionNode): string; override;
- function VisitFunctionCall(const Node: IFunctionCallNode): string; override;
- function VisitMacroExpansionNode(const Node: IMacroExpansionNode): string; override;
- function VisitBlockExpression(const Node: IBlockExpressionNode): string; override;
- function VisitVariableDeclaration(const Node: IVariableDeclarationNode): string; override;
- function VisitAssignment(const Node: IAssignmentNode): string; override;
- function VisitIndexer(const Node: IIndexerNode): string; override;
- function VisitMemberAccess(const Node: IMemberAccessNode): string; override;
- function VisitQuasiquote(const Node: IQuasiquoteNode): string; override;
- function VisitUnquote(const Node: IUnquoteNode): string; override;
- function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): string; override;
- function VisitCreateSeries(const Node: ICreateSeriesNode): string; override;
- function VisitAddSeriesItem(const Node: IAddSeriesItemNode): string; override;
- function VisitSeriesLength(const Node: ISeriesLengthNode): string; override;
- function VisitRecurNode(const Node: IRecurNode): string; override;
- function VisitRecordLiteral(const Node: IRecordLiteralNode): string; override;
- end;
-
-implementation
-
-uses
- System.Classes, // For TStringBuilder
- Myc.Data.Keyword;
-
-{ TAstToTextVisitor }
-
-function TAstToTextVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): string;
-var
- seriesStr, valueStr, lookbackStr: string;
-begin
- seriesStr := Accept(Node.Series);
- valueStr := Accept(Node.Value);
- lookbackStr := '';
- if Assigned(Node.Lookback) then
- lookbackStr := ', ' + Accept(Node.Lookback);
- Result := Format('%s.add(%s%s)', [seriesStr, valueStr, lookbackStr]);
-end;
-
-function TAstToTextVisitor.VisitAssignment(const Node: IAssignmentNode): string;
-begin
- Result := Accept(Node.Target) + ' := ' + Accept(Node.Value);
-end;
-
-function TAstToTextVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): string;
-begin
- Result := '{...}';
-end;
-
-function TAstToTextVisitor.VisitConstant(const Node: IConstantNode): string;
-begin
- Result := Node.Value.ToString;
-end;
-
-function TAstToTextVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): string;
-begin
- Result := 'new series(' + Node.Definition + ')';
-end;
-
-function TAstToTextVisitor.VisitFunctionCall(const Node: IFunctionCallNode): string;
-var
- i: Integer;
- sb: TStringBuilder;
- calleeStr: string;
-begin
- calleeStr := Accept(Node.Callee);
-
- sb := TStringBuilder.Create;
- try
- sb.Append(calleeStr);
- sb.Append('(');
- for i := 0 to High(Node.Arguments) do
- begin
- sb.Append(Accept(Node.Arguments[i]));
- if i < High(Node.Arguments) then
- sb.Append(', ');
- end;
- sb.Append(')');
- Result := sb.ToString;
- finally
- sb.Free;
- end;
-end;
-
-function TAstToTextVisitor.VisitMacroExpansionNode(const Node: IMacroExpansionNode): string;
-begin
- // To represent a macro expansion as a single line of text, the most
- // informative representation is the original call itself. We can simply
- // delegate to the VisitFunctionCall implementation to format it.
- Result := VisitFunctionCall(Node.CallNode);
-end;
-
-function TAstToTextVisitor.VisitRecurNode(const Node: IRecurNode): string;
-var
- i: Integer;
- sb: TStringBuilder;
-begin
- sb := TStringBuilder.Create;
- try
- sb.Append('recur(');
- for i := 0 to High(Node.Arguments) do
- begin
- sb.Append(Accept(Node.Arguments[i]));
- if i < High(Node.Arguments) then
- sb.Append(', ');
- end;
- sb.Append(')');
- Result := sb.ToString;
- finally
- sb.Free;
- end;
-end;
-
-function TAstToTextVisitor.VisitIdentifier(const Node: IIdentifierNode): string;
-begin
- Result := Node.Name;
-end;
-
-function TAstToTextVisitor.VisitIfExpression(const Node: IIfExpressionNode): string;
-begin
- Result := Accept(Node.Condition);
-end;
-
-function TAstToTextVisitor.VisitIndexer(const Node: IIndexerNode): string;
-var
- baseStr, indexStr: string;
-begin
- baseStr := Accept(Node.Base);
- indexStr := Accept(Node.Index);
- Result := Format('%s[%s]', [baseStr, indexStr]);
-end;
-
-function TAstToTextVisitor.VisitKeyword(const Node: IKeywordNode): string;
-begin
- Result := ':' + Node.Value.Name;
-end;
-
-function TAstToTextVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): string;
-var
- i: Integer;
- sb: TStringBuilder;
-begin
- sb := TStringBuilder.Create;
- try
- sb.Append(WideChar($03BB) + '('); // Lambda char
- if Length(Node.Parameters) > 0 then
- begin
- for i := 0 to High(Node.Parameters) do
- begin
- sb.Append(Node.Parameters[i].Name);
- if i < High(Node.Parameters) then
- sb.Append(', ');
- end;
- end;
- sb.Append(') => {...}');
- Result := sb.ToString;
- finally
- sb.Free;
- end;
-end;
-
-function TAstToTextVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): string;
-var
- i: Integer;
- sb: TStringBuilder;
-begin
- // Added text representation for macro definitions.
- sb := TStringBuilder.Create;
- try
- sb.Append('defmacro ');
- sb.Append(Node.Name.Name);
- sb.Append('(');
- if Length(Node.Parameters) > 0 then
- begin
- for i := 0 to High(Node.Parameters) do
- begin
- sb.Append(Node.Parameters[i].Name);
- if i < High(Node.Parameters) then
- sb.Append(', ');
- end;
- end;
- sb.Append(') => {...}');
- Result := sb.ToString;
- finally
- sb.Free;
- end;
-end;
-
-function TAstToTextVisitor.VisitMemberAccess(const Node: IMemberAccessNode): string;
-var
- baseStr: string;
-begin
- baseStr := Accept(Node.Base);
- Result := Format('%s.%s', [baseStr, Node.Member.Value.Name]);
-end;
-
-function TAstToTextVisitor.VisitQuasiquote(const Node: IQuasiquoteNode): string;
-begin
- Result := '`' + Accept(Node.Expression);
-end;
-
-function TAstToTextVisitor.VisitRecordLiteral(const Node: IRecordLiteralNode): string;
-begin
- Result := '{...}';
-end;
-
-function TAstToTextVisitor.VisitUnquote(const Node: IUnquoteNode): string;
-begin
- Result := '~' + Accept(Node.Expression);
-end;
-
-function TAstToTextVisitor.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): string;
-begin
- Result := '~@' + Accept(Node.Expression);
-end;
-
-function TAstToTextVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): string;
-var
- seriesStr: string;
-begin
- seriesStr := Accept(Node.Series);
- Result := Format('length(%s)', [seriesStr]);
-end;
-
-function TAstToTextVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): string;
-begin
- var condStr := Accept(Node.Condition);
- var thenStr := Accept(Node.ThenBranch);
- var elseStr := Accept(Node.ElseBranch);
- Result := Format('(%s ? %s : %s)', [condStr, thenStr, elseStr]);
-end;
-
-function TAstToTextVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): string;
-var
- initStr: string;
-begin
- if Assigned(Node.Initializer) then
- initStr := ' := ' + Accept(Node.Initializer)
- else
- initStr := '';
- Result := 'var ' + Accept(Node.Target) + initStr;
-end;
-
-end.
diff --git a/Src/AST/Myc.Fmx.AstEditor.Core.pas b/Src/AST/Myc.Fmx.AstEditor.Core.pas
new file mode 100644
index 0000000..83aee32
--- /dev/null
+++ b/Src/AST/Myc.Fmx.AstEditor.Core.pas
@@ -0,0 +1,706 @@
+unit Myc.Fmx.AstEditor.Core;
+
+interface
+
+uses
+ System.SysUtils,
+ System.Classes,
+ System.UITypes,
+ System.Types,
+ System.Math,
+ System.Math.Vectors,
+ System.Generics.Defaults,
+ System.Generics.Collections,
+ FMX.Types,
+ FMX.Controls,
+ FMX.Objects,
+ FMX.Graphics,
+ FMX.StdCtrls,
+ Myc.Ast.Nodes,
+ Myc.Fmx.AstEditor.Workspace;
+
+const
+ cNodePadding = 10;
+ cTitleTopPadding = 2;
+ cTitleBottomPadding = 4;
+ cMinNodeWidth = 10;
+ cMinNodeHeight = 10;
+
+type
+ TAuraNode = class; // Forward declaration
+
+ // This aggregate interface encapsulates all node-specific logic.
+ IAuraNodeHandler = interface
+ // Gets the original logical AST node
+ function GetAstNode: IAstNode;
+ // Creates the specific FMX UI for this node
+ procedure BuildUI(OwnerNode: TAuraNode);
+ // Reconstructs the logical AST node from the FMX UI state
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+ // The original logical AST node
+ property Node: IAstNode read GetAstNode;
+ end;
+
+ IAstVisualizer = interface
+ {$region 'private'}
+ function GetExprDepth: Integer;
+ function GetParentControl: TControl;
+ function GetWorkspace: TAuraWorkspace;
+ {$endregion}
+
+ function Clone(ParentControl: TControl; ExprDepth: Integer): IAstVisualizer;
+ function CallAccept(const Node: IAstNode): TAuraNode;
+
+ property ExprDepth: Integer read GetExprDepth;
+ property ParentControl: TControl read GetParentControl;
+ property Workspace: TAuraWorkspace read GetWorkspace;
+ end;
+
+ // Defines the layout direction for children within TAutoFitControl
+ TLayoutOrientation = (loVertical, loHorizontal);
+
+ // Defines the alignment of children on the cross-axis
+ TLayoutAlignment = (laCenter, laFlush);
+
+ // A styled control that automatically adjusts its size to fit its children, including padding.
+ TAutoFitControl = class(TStyledControl)
+ private
+ FUpdatingOwnSize: Boolean; // Recursion guard
+ FNeedRecalcSize: Boolean; // Flag for EndUpdate
+ FOrientation: TLayoutOrientation; // Storage for Orientation
+ FAlignment: TLayoutAlignment; // Storage for Alignment
+ procedure RecalcOwnSize;
+ procedure SetOrientation(const Value: TLayoutOrientation);
+ procedure SetAlignment(const Value: TLayoutAlignment);
+ protected
+ procedure ParentContentChanged; override;
+ procedure PaddingChanged; override;
+ procedure ChangeChildren; override;
+ procedure Loaded; override;
+ procedure DoEndUpdate; override;
+ public
+ constructor Create(AOwner: TComponent); override;
+
+ published
+ property Padding;
+ property Orientation: TLayoutOrientation read FOrientation write SetOrientation default TLayoutOrientation.loHorizontal;
+ property Alignment: TLayoutAlignment read FAlignment write SetAlignment default TLayoutAlignment.laCenter;
+ end;
+
+ // A movable panel with a custom-painted border. Content (like title) is added externally.
+ TAuraNode = class(TAutoFitControl)
+ private
+ FBackgroundColor: TAlphaColor;
+ FIsDragging: Boolean;
+ FDownPos: TPointF;
+ FBorderColor: TAlphaColor;
+ FBorderWidth: Single;
+ FBorderRadius: Single;
+ FFrameless: Boolean;
+ FVisualizer: IAstVisualizer;
+ FHandler: IAuraNodeHandler;
+
+ // --- Visual State Fields ---
+ FErrorMessage: string;
+ FTypeInfoText: string;
+
+ procedure SetBackgroundColor(const Value: TAlphaColor);
+ procedure SetBorderColor(const Value: TAlphaColor);
+ procedure SetBorderWidth(const Value: Single);
+ procedure SetBorderRadius(const Value: Single);
+ procedure SetFrameless(const Value: Boolean);
+ function GetNode: IAstNode;
+
+ // New Setters
+ procedure SetErrorMessage(const Value: string);
+ procedure SetTypeInfoText(const Value: string);
+ procedure UpdateVisualState;
+
+ protected
+ procedure Paint; override;
+ procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Single); override;
+ procedure MouseMove(Shift: TShiftState; X, Y: Single); override;
+ procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Single); override;
+ procedure SetupNode;
+
+ public
+ constructor Create(const AVisualizer: IAstVisualizer; const AHandler: IAuraNodeHandler); reintroduce;
+ destructor Destroy; override;
+
+ procedure AfterConstruction; override;
+
+ function AddLabel(Parent: TControl; const Txt: String): TLabel;
+ function AddContainer(Parent: TControl; Orientation: TLayoutOrientation; Alignment: TLayoutAlignment): TAutoFitControl;
+ function AddExpr(Parent: TControl; const Title: String; const Node: IAstNode): TAuraNode;
+
+ function CreateAst: IAstNode;
+
+ property Visualizer: IAstVisualizer read FVisualizer;
+ property Node: IAstNode read GetNode;
+
+ // --- Visual State Properties ---
+ property ErrorMessage: string read FErrorMessage write SetErrorMessage;
+ property TypeInfoText: string read FTypeInfoText write SetTypeInfoText;
+
+ published
+ property BorderColor: TAlphaColor read FBorderColor write SetBorderColor;
+ property BorderWidth: Single read FBorderWidth write SetBorderWidth;
+ property BorderRadius: Single read FBorderRadius write SetBorderRadius;
+ property BackgroundColor: TAlphaColor read FBackgroundColor write SetBackgroundColor;
+ property Frameless: Boolean read FFrameless write SetFrameless;
+
+ property Align;
+ property Anchors;
+ property ClipChildren default True;
+ property Cursor default crDefault;
+ property DragMode default TDragMode.dmManual;
+ property Enabled;
+ property Height;
+ property Hint;
+ property HitTest default True;
+ property Locked;
+ property Margins;
+ property Opacity;
+ property Padding;
+ property PopupMenu;
+ property Position;
+ property RotationAngle;
+ property RotationCenter;
+ property Scale;
+ property Size;
+ property Visible;
+ property Width;
+ property OnClick;
+ property OnDblClick;
+ property OnMouseDown;
+ property OnMouseMove;
+ property OnMouseUp;
+ property OnMouseWheel;
+ property OnMouseEnter;
+ property OnMouseLeave;
+ end;
+
+ // Helper base class to reduce boilerplate in specific handlers
+ TBaseNodeHandler = class(TInterfacedObject, IAuraNodeHandler)
+ protected
+ FNode: T;
+ function GetAstNode: IAstNode;
+ public
+ constructor Create(const ANode: T);
+ procedure BuildUI(OwnerNode: TAuraNode); virtual; abstract;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; virtual; abstract;
+ end;
+
+implementation
+
+uses
+ Myc.Ast;
+
+{ TAutoFitControl }
+
+constructor TAutoFitControl.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+ HitTest := True;
+ FOrientation := TLayoutOrientation.loHorizontal;
+ FAlignment := TLayoutAlignment.laCenter;
+end;
+
+procedure TAutoFitControl.SetAlignment(const Value: TLayoutAlignment);
+begin
+ if FAlignment <> Value then
+ begin
+ FAlignment := Value;
+ RecalcOwnSize;
+ end;
+end;
+
+procedure TAutoFitControl.SetOrientation(const Value: TLayoutOrientation);
+begin
+ if FOrientation <> Value then
+ begin
+ FOrientation := Value;
+ RecalcOwnSize;
+ end;
+end;
+
+procedure TAutoFitControl.RecalcOwnSize;
+var
+ i: Integer;
+ child: TControl;
+ childrenToLayout: TList;
+ currentX, currentY: Single;
+ requiredWidth, requiredHeight: Single;
+ childWidthWithMargins, childHeightWithMargins: Single;
+ hasVisibleChild: Boolean;
+begin
+ if FUpdatingOwnSize then
+ exit;
+ if IsUpdating then
+ begin
+ FNeedRecalcSize := True;
+ exit;
+ end;
+
+ FUpdatingOwnSize := True;
+ childrenToLayout := nil;
+ try
+ requiredWidth := Padding.Left + Padding.Right;
+ requiredHeight := Padding.Top + Padding.Bottom;
+ currentX := Padding.Left;
+ currentY := Padding.Top;
+ hasVisibleChild := False;
+
+ childrenToLayout := TList.Create;
+ for i := 0 to ChildrenCount - 1 do
+ begin
+ if Children[i] is TControl then
+ begin
+ child := TControl(Children[i]);
+ if child.Visible and (child.Align = TAlignLayout.None) then
+ begin
+ childrenToLayout.Add(child);
+ hasVisibleChild := True;
+ end;
+ end;
+ end;
+
+ if hasVisibleChild then
+ begin
+ if FOrientation = TLayoutOrientation.loVertical then
+ begin
+ for child in childrenToLayout do
+ begin
+ child.Position.Y := currentY + child.Margins.Top;
+ currentY := child.Position.Y + child.Height + child.Margins.Bottom;
+
+ childWidthWithMargins := Padding.Left + child.Margins.Left + child.Width + child.Margins.Right + Padding.Right;
+ requiredWidth := System.Math.Max(requiredWidth, childWidthWithMargins);
+ end;
+ requiredHeight := currentY + Padding.Bottom;
+
+ if FAlignment = TLayoutAlignment.laFlush then
+ begin
+ for child in childrenToLayout do
+ begin
+ child.Position.X := Padding.Left + child.Margins.Left;
+ end;
+ end
+ else
+ begin
+ var contentWidth := requiredWidth - Padding.Left - Padding.Right;
+ for child in childrenToLayout do
+ begin
+ var childTotalWidth := child.Width + child.Margins.Left + child.Margins.Right;
+ var childX := Padding.Left + ((contentWidth - childTotalWidth) / 2) + child.Margins.Left;
+ child.Position.X := childX;
+ end;
+ end;
+ end
+ else
+ begin
+ for child in childrenToLayout do
+ begin
+ child.Position.X := currentX + child.Margins.Left;
+ currentX := child.Position.X + child.Width + child.Margins.Right;
+
+ childHeightWithMargins := Padding.Top + child.Margins.Top + child.Height + child.Margins.Bottom + Padding.Bottom;
+ requiredHeight := System.Math.Max(requiredHeight, childHeightWithMargins);
+ end;
+ requiredWidth := currentX + Padding.Right;
+
+ if FAlignment = TLayoutAlignment.laFlush then
+ begin
+ for child in childrenToLayout do
+ begin
+ child.Position.Y := Padding.Top + child.Margins.Top;
+ end;
+ end
+ else
+ begin
+ var contentHeight := requiredHeight - Padding.Top - Padding.Bottom;
+ for child in childrenToLayout do
+ begin
+ var childTotalHeight := child.Height + child.Margins.Top + child.Margins.Bottom;
+ var childY := Padding.Top + ((contentHeight - childTotalHeight) / 2) + child.Margins.Top;
+ child.Position.Y := childY;
+ end;
+ end;
+ end;
+ end
+ else
+ begin
+ requiredWidth := Padding.Left + Padding.Right;
+ requiredHeight := Padding.Top + Padding.Bottom;
+ end;
+
+ requiredWidth := System.Math.Max(0, requiredWidth);
+ requiredHeight := System.Math.Max(0, requiredHeight);
+
+ if not SameValue(requiredWidth, Width, TEpsilon.Position) or not SameValue(requiredHeight, Height, TEpsilon.Position) then
+ begin
+ FSize.SetSizeWithoutNotification(TSizeF.Create(requiredWidth, requiredHeight));
+ HandleSizeChanged;
+ end;
+
+ finally
+ childrenToLayout.Free;
+ FUpdatingOwnSize := False;
+ end;
+end;
+
+procedure TAutoFitControl.Loaded;
+begin
+ inherited Loaded;
+ RecalcOwnSize;
+end;
+
+procedure TAutoFitControl.ChangeChildren;
+begin
+ inherited ChangeChildren;
+ RecalcOwnSize;
+end;
+
+procedure TAutoFitControl.PaddingChanged;
+begin
+ inherited PaddingChanged;
+ RecalcOwnSize;
+end;
+
+procedure TAutoFitControl.ParentContentChanged;
+begin
+ inherited ParentContentChanged;
+ RecalcOwnSize;
+end;
+
+procedure TAutoFitControl.DoEndUpdate;
+begin
+ inherited;
+ if FNeedRecalcSize then
+ begin
+ FNeedRecalcSize := False;
+ RecalcOwnSize;
+ end;
+end;
+
+{ TAuraNode }
+
+constructor TAuraNode.Create(const AVisualizer: IAstVisualizer; const AHandler: IAuraNodeHandler);
+begin
+ inherited Create(AVisualizer.Workspace);
+
+ Parent := AVisualizer.ParentControl;
+
+ FVisualizer := AVisualizer.Clone(Self, AVisualizer.ExprDepth);
+ FHandler := AHandler;
+
+ FIsDragging := False;
+
+ FBorderColor := TAlphaColors.Gray;
+ FBorderWidth := 1;
+ FBorderRadius := 9;
+ FBackgroundColor := $080a0a0a;
+
+ FFrameless := False;
+
+ Width := cMinNodeWidth;
+ Height := cMinNodeHeight;
+
+ HitTest := True;
+ ClipChildren := True;
+
+ Margins.Left := 4;
+ Margins.Top := 4;
+ Margins.Right := 4;
+ Margins.Bottom := 4;
+ Padding.Left := 3;
+ Padding.Top := 3;
+ Padding.Right := 3;
+ Padding.Bottom := 3;
+
+ var cn: Cardinal := $ea - (7 * FVisualizer.ExprDepth);
+ var c: Cardinal := $ff000000 or (cn shl 16) or (cn shl 8) or cn;
+ BackgroundColor := c;
+end;
+
+destructor TAuraNode.Destroy;
+begin
+ FHandler := nil;
+ inherited;
+end;
+
+function TAuraNode.AddContainer(Parent: TControl; Orientation: TLayoutOrientation; Alignment: TLayoutAlignment): TAutoFitControl;
+begin
+ Result := TAutoFitControl.Create(Self);
+ Result.Parent := Parent;
+ Result.Orientation := Orientation;
+ Result.Alignment := Alignment;
+ Result.HitTest := False;
+end;
+
+function TAuraNode.AddExpr(Parent: TControl; const Title: String; const Node: IAstNode): TAuraNode;
+begin
+ var cont := AddContainer(Parent, loHorizontal, laCenter);
+
+ var lbl := AddLabel(cont, Title);
+ lbl.Font.Style := lbl.Font.Style + [TFontStyle.fsBold];
+
+ Result := FVisualizer.Clone(cont, FVisualizer.ExprDepth + 1).CallAccept(Node);
+end;
+
+function TAuraNode.AddLabel(Parent: TControl; const Txt: String): TLabel;
+begin
+ Result := TLabel.Create(Self);
+ Result.Parent := Parent;
+
+ Result.Position.Point := TPoint.Create(cNodePadding, cNodePadding);
+ Result.Margins.Left := cNodePadding;
+ Result.Margins.Right := cNodePadding;
+ Result.Margins.Top := cTitleTopPadding;
+ Result.Margins.Bottom := cTitleBottomPadding;
+ Result.WordWrap := False;
+ Result.AutoSize := True;
+ Result.HitTest := False;
+
+ Result.StyledSettings := Result.StyledSettings - [TStyledSetting.Style];
+
+ Result.Text := Txt;
+ Result.ApplyStyleLookup;
+end;
+
+procedure TAuraNode.AfterConstruction;
+begin
+ inherited;
+ SetupNode;
+end;
+
+function TAuraNode.CreateAst: IAstNode;
+begin
+ if Assigned(FHandler) then
+ Result := FHandler.ReconstructAst(Self)
+ else
+ Result := TAst.Nop;
+end;
+
+function TAuraNode.GetNode: IAstNode;
+begin
+ if Assigned(FHandler) then
+ Result := FHandler.Node
+ else
+ Result := nil;
+end;
+
+procedure TAuraNode.SetErrorMessage(const Value: string);
+begin
+ if FErrorMessage <> Value then
+ begin
+ FErrorMessage := Value;
+ UpdateVisualState;
+ Repaint;
+ end;
+end;
+
+procedure TAuraNode.SetTypeInfoText(const Value: string);
+begin
+ if FTypeInfoText <> Value then
+ begin
+ FTypeInfoText := Value;
+ UpdateVisualState;
+ // Type Info usually doesn't change painting, just hint
+ end;
+end;
+
+procedure TAuraNode.UpdateVisualState;
+begin
+ if FErrorMessage <> '' then
+ begin
+ Hint := 'Error: ' + FErrorMessage;
+ ShowHint := True;
+ end
+ else if FTypeInfoText <> '' then
+ begin
+ Hint := 'Type: ' + FTypeInfoText;
+ ShowHint := True;
+ end
+ else
+ begin
+ Hint := '';
+ ShowHint := False;
+ end;
+end;
+
+procedure TAuraNode.Paint;
+var
+ rect: TRectF;
+ effBorderColor: TAlphaColor;
+ effBorderWidth: Single;
+ effDash: TStrokeDash;
+begin
+ inherited;
+
+ Canvas.Fill.Kind := TBrushKind.None;
+
+ // Determine styles based on state (Error > Standard)
+ if FErrorMessage <> '' then
+ begin
+ effBorderColor := TAlphaColors.Red;
+ effBorderWidth := 2.0;
+ effDash := TStrokeDash.Solid;
+ end
+ else
+ begin
+ effBorderColor := FBorderColor;
+ effBorderWidth := FBorderWidth;
+ if FFrameless then
+ effDash := TStrokeDash.Dot
+ else
+ effDash := TStrokeDash.Solid;
+ end;
+
+ if FFrameless and (FErrorMessage = '') then
+ begin
+ // Standard frameless drawing (only if no error)
+ Canvas.Fill.Kind := TBrushKind.Solid;
+ Canvas.Fill.Color := FBackgroundColor;
+ Canvas.Stroke.Kind := TBrushKind.None;
+ Canvas.FillRect(TRectF.Create(0, 0, Width, Height), 0, 0, [], 1.0);
+ Canvas.Stroke.Kind := TBrushKind.Solid;
+ Canvas.Stroke.Color := effBorderColor;
+ Canvas.Stroke.Thickness := effBorderWidth;
+ Canvas.Stroke.Dash := effDash;
+ Canvas.DrawRect(TRectF.Create(0, 0, Width, Height), 0, 0, [], 1.0);
+ end
+ else
+ begin
+ // Draw background fill first
+ Canvas.Fill.Kind := TBrushKind.Solid;
+ Canvas.Fill.Color := FBackgroundColor;
+ rect := TRectF.Create(0, 0, Width, Height);
+ if (effBorderWidth > 0) then
+ rect.Inflate(-effBorderWidth / 2, -effBorderWidth / 2);
+ Canvas.FillRect(rect, FBorderRadius, FBorderRadius, AllCorners, 1.0, TCornerType.Round);
+
+ // Draw border (Custom or Error)
+ if (effBorderWidth > 0) and (effBorderColor <> TAlphaColors.Null) then
+ begin
+ rect := TRectF.Create(0, 0, Width, Height);
+ rect.Inflate(-effBorderWidth / 2, -effBorderWidth / 2);
+
+ Canvas.Stroke.Kind := TBrushKind.Solid;
+ Canvas.Stroke.Color := effBorderColor;
+ Canvas.Stroke.Thickness := effBorderWidth;
+ Canvas.Stroke.Dash := effDash;
+ Canvas.DrawRect(rect, FBorderRadius, FBorderRadius, AllCorners, 1.0, TCornerType.Round);
+ end;
+ end;
+end;
+
+procedure TAuraNode.SetBorderColor(const Value: TAlphaColor);
+begin
+ if FBorderColor <> Value then
+ begin
+ FBorderColor := Value;
+ Repaint;
+ end;
+end;
+
+procedure TAuraNode.SetBorderRadius(const Value: Single);
+begin
+ if FBorderRadius <> Value then
+ begin
+ FBorderRadius := Value;
+ Repaint;
+ end;
+end;
+
+procedure TAuraNode.SetBorderWidth(const Value: Single);
+begin
+ if FBorderWidth <> Value then
+ begin
+ FBorderWidth := Value;
+ Repaint;
+ end;
+end;
+
+procedure TAuraNode.SetFrameless(const Value: Boolean);
+begin
+ if FFrameless <> Value then
+ begin
+ FFrameless := Value;
+ Repaint;
+ end;
+end;
+
+procedure TAuraNode.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Single);
+begin
+ inherited;
+ if Button = TMouseButton.mbLeft then
+ begin
+ var lControl := ObjectAtPoint(LocalToScreen(TPointF.Create(X, Y)));
+ if Assigned(lControl) and (lControl.GetObject = Self) then
+ begin
+ FIsDragging := True;
+ FDownPos := TPointF.Create(X, Y);
+ Capture;
+ BringToFront;
+ end
+ else
+ FIsDragging := False;
+ end;
+end;
+
+procedure TAuraNode.MouseMove(Shift: TShiftState; X, Y: Single);
+begin
+ inherited;
+
+ if FIsDragging then
+ begin
+ var deltaX := X - FDownPos.X;
+ var deltaY := Y - FDownPos.Y;
+
+ Position.X := Position.X + deltaX;
+ Position.Y := Position.Y + deltaY;
+
+ if ParentControl <> nil then
+ ParentControl.Repaint;
+ end;
+end;
+
+procedure TAuraNode.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Single);
+begin
+ inherited;
+ if (Button = TMouseButton.mbLeft) and (FIsDragging) then
+ begin
+ ReleaseCapture;
+ FIsDragging := False;
+ if ParentControl <> nil then
+ ParentControl.Repaint;
+ end;
+end;
+
+procedure TAuraNode.SetBackgroundColor(const Value: TAlphaColor);
+begin
+ FBackgroundColor := Value;
+ Repaint;
+end;
+
+procedure TAuraNode.SetupNode;
+begin
+ if Assigned(FHandler) then
+ FHandler.BuildUI(Self);
+end;
+
+{ TBaseNodeHandler }
+
+constructor TBaseNodeHandler.Create(const ANode: T);
+begin
+ inherited Create;
+ FNode := ANode;
+end;
+
+function TBaseNodeHandler.GetAstNode: IAstNode;
+begin
+ Result := FNode;
+end;
+
+end.
diff --git a/Src/AST/Myc.Fmx.AstEditor.Handlers.pas b/Src/AST/Myc.Fmx.AstEditor.Handlers.pas
new file mode 100644
index 0000000..0b028c3
--- /dev/null
+++ b/Src/AST/Myc.Fmx.AstEditor.Handlers.pas
@@ -0,0 +1,1085 @@
+unit Myc.Fmx.AstEditor.Handlers;
+
+interface
+
+uses
+ System.SysUtils,
+ System.Classes,
+ System.UITypes,
+ System.Generics.Collections,
+ System.Types,
+ FMX.Types,
+ FMX.Controls,
+ FMX.StdCtrls,
+ FMX.Graphics,
+ Myc.Data.Value,
+ Myc.Data.Keyword,
+ Myc.Ast,
+ Myc.Ast.Nodes,
+ Myc.Ast.Identities,
+ Myc.Fmx.AstEditor.Core;
+
+type
+ // --- Basic Handlers ---
+
+ TConstantNodeHandler = class(TBaseNodeHandler)
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ TIdentifierNodeHandler = class(TBaseNodeHandler)
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ TKeywordNodeHandler = class(TBaseNodeHandler)
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ TNopNodeHandler = class(TBaseNodeHandler)
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ // --- Logic & Control Flow ---
+
+ TBlockExpressionNodeHandler = class(TBaseNodeHandler)
+ private
+ FChildNodes: TList;
+ public
+ constructor Create(const ANode: IBlockExpressionNode);
+ destructor Destroy; override;
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ TIfExpressionNodeHandler = class(TBaseNodeHandler)
+ private
+ FConditionNode: TAuraNode;
+ FThenNode: TAuraNode;
+ FElseNode: TAuraNode;
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ TTernaryExpressionNodeHandler = class(TBaseNodeHandler)
+ private
+ FConditionNode: TAuraNode;
+ FThenNode: TAuraNode;
+ FElseNode: TAuraNode;
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ // --- Functions & Calls ---
+
+ TLambdaExpressionNodeHandler = class(TBaseNodeHandler)
+ private
+ FBodyNode: TAuraNode;
+ FParamLabels: TList;
+ public
+ constructor Create(const ANode: ILambdaExpressionNode);
+ destructor Destroy; override;
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ TFunctionCallNodeHandler = class(TBaseNodeHandler)
+ private
+ FCalleeNode: TAuraNode;
+ FArgumentNodes: TList;
+ public
+ constructor Create(const ANode: IFunctionCallNode);
+ destructor Destroy; override;
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ TMacroExpansionNodeHandler = class(TBaseNodeHandler)
+ private
+ FExpandedBodyNode: TAuraNode;
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ TRecurNodeHandler = class(TBaseNodeHandler)
+ private
+ FArgumentNodes: TList;
+ public
+ constructor Create(const ANode: IRecurNode);
+ destructor Destroy; override;
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ // --- Declarations & Assignments ---
+
+ TVariableDeclarationNodeHandler = class(TBaseNodeHandler)
+ private
+ FTargetNode: TAuraNode;
+ FInitializerNode: TAuraNode;
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ TAssignmentNodeHandler = class(TBaseNodeHandler)
+ private
+ FTargetNode: TAuraNode;
+ FValueNode: TAuraNode;
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ TMacroDefinitionNodeHandler = class(TBaseNodeHandler)
+ private
+ FBodyNode: TAuraNode;
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ // --- Metaprogramming ---
+
+ TQuasiquoteNodeHandler = class(TBaseNodeHandler)
+ private
+ FExpressionNode: TAuraNode;
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ TUnquoteNodeHandler = class(TBaseNodeHandler)
+ private
+ FExpressionNode: TAuraNode;
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ TUnquoteSplicingNodeHandler = class(TBaseNodeHandler)
+ private
+ FExpressionNode: TAuraNode;
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ // --- Data Access & Structures ---
+
+ TIndexerNodeHandler = class(TBaseNodeHandler)
+ private
+ FBaseNode: TAuraNode;
+ FIndexNode: TAuraNode;
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ TMemberAccessNodeHandler = class(TBaseNodeHandler)
+ private
+ FBaseNode: TAuraNode;
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ TRecordLiteralNodeHandler = class(TBaseNodeHandler)
+ private
+ FFieldNodes: TDictionary;
+ public
+ constructor Create(const ANode: IRecordLiteralNode);
+ destructor Destroy; override;
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ // --- Series Operations ---
+
+ TCreateSeriesNodeHandler = class(TBaseNodeHandler)
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ TAddSeriesItemNodeHandler = class(TBaseNodeHandler)
+ private
+ FValueNode: TAuraNode;
+ FLookbackNode: TAuraNode;
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+ TSeriesLengthNodeHandler = class(TBaseNodeHandler)
+ public
+ procedure BuildUI(OwnerNode: TAuraNode); override;
+ function ReconstructAst(OwnerNode: TAuraNode): IAstNode; override;
+ end;
+
+implementation
+
+{ TConstantNodeHandler }
+
+procedure TConstantNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ valueStr: string;
+ isConcise: Boolean;
+ titleLabel: TLabel;
+ valueLabel: TLabel;
+begin
+ OwnerNode.BeginUpdate;
+ try
+ valueStr := FNode.Value.ToString;
+ isConcise := ((FNode.Value.Kind = TDataValueKind.vkScalar) or (Pos(sLineBreak, valueStr) = 0)) and (Length(valueStr) < 40);
+
+ if isConcise then
+ begin
+ OwnerNode.Frameless := True;
+ OwnerNode.AddLabel(OwnerNode, valueStr);
+ end
+ else
+ begin
+ OwnerNode.Frameless := False;
+ OwnerNode.Orientation := loVertical;
+
+ titleLabel := OwnerNode.AddLabel(OwnerNode, 'Const');
+ titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
+
+ valueLabel := OwnerNode.AddLabel(OwnerNode, valueStr);
+ valueLabel.AutoSize := False;
+ valueLabel.WordWrap := True;
+ end;
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TConstantNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+begin
+ Result := TAst.Constant(FNode.Identity.AsConstant, FNode.StaticType);
+end;
+
+{ TIdentifierNodeHandler }
+
+procedure TIdentifierNodeHandler.BuildUI(OwnerNode: TAuraNode);
+begin
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := True;
+ OwnerNode.AddLabel(OwnerNode, FNode.Name);
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TIdentifierNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+begin
+ Result := TAst.Identifier(FNode.Identity.AsNamed, FNode.Address, FNode.StaticType);
+end;
+
+{ TKeywordNodeHandler }
+
+procedure TKeywordNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ lbl: TLabel;
+begin
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := True;
+ lbl := OwnerNode.AddLabel(OwnerNode, ':' + FNode.Value.Name);
+ lbl.StyledSettings := lbl.StyledSettings - [TStyledSetting.FontColor];
+ lbl.FontColor := TAlphaColors.Mediumvioletred;
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TKeywordNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+begin
+ Result := TAst.Keyword(FNode.Identity.AsKeyword);
+end;
+
+{ TNopNodeHandler }
+
+procedure TNopNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ lbl: TLabel;
+begin
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := True;
+ OwnerNode.Alignment := TLayoutAlignment.laCenter;
+ OwnerNode.Orientation := TLayoutOrientation.loHorizontal;
+ lbl := OwnerNode.AddLabel(OwnerNode, '...');
+ lbl.Font.Style := lbl.Font.Style + [TFontStyle.fsBold];
+ lbl.Margins.Rect := TRectF.Create(8, 4, 8, 4);
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TNopNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+begin
+ Result := FNode;
+end;
+
+{ TBlockExpressionNodeHandler }
+
+constructor TBlockExpressionNodeHandler.Create(const ANode: IBlockExpressionNode);
+begin
+ inherited Create(ANode);
+ FChildNodes := TList.Create;
+end;
+
+destructor TBlockExpressionNodeHandler.Destroy;
+begin
+ FChildNodes.Free;
+ inherited;
+end;
+
+procedure TBlockExpressionNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ visu: IAstVisualizer;
+ childNode: TAuraNode;
+ expr: IAstNode;
+ titleLabel: TLabel;
+ i: Integer;
+ returnContainer: TAutoFitControl;
+ visuReturn: IAstVisualizer;
+begin
+ visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := True;
+ OwnerNode.Orientation := loVertical;
+ OwnerNode.Alignment := laFlush;
+
+ for i := 0 to High(FNode.Expressions) do
+ begin
+ expr := FNode.Expressions[i];
+
+ if i = High(FNode.Expressions) then
+ begin
+ returnContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter);
+ titleLabel := OwnerNode.AddLabel(returnContainer, 'return');
+ titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
+ visuReturn := OwnerNode.Visualizer.Clone(returnContainer, OwnerNode.Visualizer.ExprDepth + 1);
+ childNode := visuReturn.CallAccept(expr);
+ FChildNodes.Add(childNode);
+ end
+ else
+ begin
+ childNode := visu.CallAccept(expr);
+ FChildNodes.Add(childNode);
+ end;
+ end;
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TBlockExpressionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+var
+ exprs: TArray;
+ childNode: TAuraNode;
+ i: Integer;
+begin
+ SetLength(exprs, FChildNodes.Count);
+ for i := 0 to FChildNodes.Count - 1 do
+ begin
+ childNode := FChildNodes[i];
+ if Assigned(childNode) then
+ exprs[i] := childNode.CreateAst
+ else
+ exprs[i] := TAst.Nop;
+ end;
+
+ Result := TAst.Block(FNode.Identity, exprs, FNode.StaticType);
+end;
+
+{ TIfExpressionNodeHandler }
+
+procedure TIfExpressionNodeHandler.BuildUI(OwnerNode: TAuraNode);
+begin
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := False;
+ OwnerNode.Orientation := loVertical;
+ OwnerNode.Alignment := laFlush;
+
+ FConditionNode := OwnerNode.AddExpr(OwnerNode, 'if', FNode.Condition);
+ FThenNode := OwnerNode.AddExpr(OwnerNode, 'then', FNode.ThenBranch);
+ if Assigned(FNode.ElseBranch) then
+ FElseNode := OwnerNode.AddExpr(OwnerNode, 'else', FNode.ElseBranch);
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TIfExpressionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+var
+ elseAst: IAstNode;
+begin
+ if Assigned(FElseNode) then
+ elseAst := FElseNode.CreateAst
+ else
+ elseAst := nil;
+
+ Result := TAst.IfExpr(FNode.Identity, FConditionNode.CreateAst, FThenNode.CreateAst, elseAst, FNode.StaticType);
+end;
+
+{ TTernaryExpressionNodeHandler }
+
+procedure TTernaryExpressionNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ visu: IAstVisualizer;
+begin
+ visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := True;
+ OwnerNode.Orientation := loHorizontal;
+ FConditionNode := visu.CallAccept(FNode.Condition);
+ OwnerNode.AddLabel(OwnerNode, '?');
+ FThenNode := visu.CallAccept(FNode.ThenBranch);
+ OwnerNode.AddLabel(OwnerNode, ':');
+ FElseNode := visu.CallAccept(FNode.ElseBranch);
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TTernaryExpressionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+begin
+ Result := TAst.TernaryExpr(FNode.Identity, FConditionNode.CreateAst, FThenNode.CreateAst, FElseNode.CreateAst, FNode.StaticType);
+end;
+
+{ TLambdaExpressionNodeHandler }
+
+constructor TLambdaExpressionNodeHandler.Create(const ANode: ILambdaExpressionNode);
+begin
+ inherited Create(ANode);
+ FParamLabels := TList.Create;
+end;
+
+destructor TLambdaExpressionNodeHandler.Destroy;
+begin
+ FParamLabels.Free;
+ inherited;
+end;
+
+procedure TLambdaExpressionNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ visu: IAstVisualizer;
+ titleContainer: TAutoFitControl;
+ paramLabel: TLabel;
+ i: Integer;
+begin
+ visu := OwnerNode.Visualizer.Clone(OwnerNode, 0);
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := False;
+ OwnerNode.Orientation := loVertical;
+ OwnerNode.Alignment := laFlush;
+ OwnerNode.BackgroundColor := $090000ff;
+
+ titleContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter);
+
+ paramLabel := OwnerNode.AddLabel(titleContainer, 'fn');
+ paramLabel.Font.Style := paramLabel.Font.Style + [TFontStyle.fsBold];
+ FParamLabels.Add(paramLabel);
+
+ paramLabel := OwnerNode.AddLabel(titleContainer, '(');
+ FParamLabels.Add(paramLabel);
+
+ for i := 0 to High(FNode.Parameters) do
+ begin
+ paramLabel := OwnerNode.AddLabel(titleContainer, FNode.Parameters[i].Name);
+ FParamLabels.Add(paramLabel);
+
+ if i < High(FNode.Parameters) then
+ begin
+ paramLabel := OwnerNode.AddLabel(titleContainer, ',');
+ FParamLabels.Add(paramLabel);
+ end;
+ end;
+
+ paramLabel := OwnerNode.AddLabel(titleContainer, ')');
+ FParamLabels.Add(paramLabel);
+
+ FBodyNode := visu.CallAccept(FNode.Body);
+ FBodyNode.Frameless := False;
+
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TLambdaExpressionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+begin
+ Result :=
+ TAst.LambdaExpr(
+ FNode.Identity,
+ FNode.Parameters,
+ FBodyNode.CreateAst,
+ FNode.Layout,
+ FNode.Descriptor,
+ FNode.Upvalues,
+ FNode.HasNestedLambdas,
+ FNode.IsPure,
+ FNode.StaticType
+ );
+end;
+
+{ TFunctionCallNodeHandler }
+
+constructor TFunctionCallNodeHandler.Create(const ANode: IFunctionCallNode);
+begin
+ inherited Create(ANode);
+ FArgumentNodes := TList.Create;
+end;
+
+destructor TFunctionCallNodeHandler.Destroy;
+begin
+ FArgumentNodes.Free;
+ inherited;
+end;
+
+procedure TFunctionCallNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ visu: IAstVisualizer;
+ i: Integer;
+ argNode: TAuraNode;
+ callLabel: TLabel;
+begin
+ visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := True;
+ OwnerNode.Orientation := loHorizontal;
+
+ callLabel := OwnerNode.AddLabel(OwnerNode, 'call ');
+ callLabel.Font.Style := callLabel.Font.Style + [TFontStyle.fsBold];
+
+ FCalleeNode := visu.CallAccept(FNode.Callee);
+
+ if Length(FNode.Arguments) > 0 then
+ begin
+ OwnerNode.AddLabel(OwnerNode, '(');
+ for i := 0 to High(FNode.Arguments) do
+ begin
+ argNode := visu.CallAccept(FNode.Arguments[i]);
+ FArgumentNodes.Add(argNode);
+ if i < High(FNode.Arguments) then
+ OwnerNode.AddLabel(OwnerNode, ',');
+ end;
+ OwnerNode.AddLabel(OwnerNode, ')');
+ end;
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TFunctionCallNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+var
+ args: TArray;
+ i: Integer;
+begin
+ SetLength(args, FArgumentNodes.Count);
+ for i := 0 to FArgumentNodes.Count - 1 do
+ args[i] := FArgumentNodes[i].CreateAst;
+
+ Result :=
+ TAst.FunctionCall(
+ FNode.Identity,
+ FCalleeNode.CreateAst,
+ args,
+ FNode.StaticType,
+ FNode.IsTailCall,
+ FNode.StaticTarget,
+ FNode.IsTargetPure
+ );
+end;
+
+{ TMacroExpansionNodeHandler }
+
+procedure TMacroExpansionNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ visu: IAstVisualizer;
+ titleLabel: TLabel;
+begin
+ visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := False;
+ OwnerNode.Orientation := loVertical;
+ titleLabel := OwnerNode.AddLabel(OwnerNode, 'Macro Expansion');
+ titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
+ FExpandedBodyNode := visu.CallAccept(FNode.ExpandedBody);
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TMacroExpansionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+begin
+ Result := TAst.MacroExpansionNode(FNode.Identity, FNode.CallNode, FExpandedBodyNode.CreateAst.AsTypedNode);
+end;
+
+{ TRecurNodeHandler }
+
+constructor TRecurNodeHandler.Create(const ANode: IRecurNode);
+begin
+ inherited Create(ANode);
+ FArgumentNodes := TList.Create;
+end;
+
+destructor TRecurNodeHandler.Destroy;
+begin
+ FArgumentNodes.Free;
+ inherited;
+end;
+
+procedure TRecurNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ visu: IAstVisualizer;
+ i: Integer;
+ argNode: TAuraNode;
+ titleLabel: TLabel;
+begin
+ visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := True;
+ OwnerNode.Orientation := loHorizontal;
+
+ titleLabel := OwnerNode.AddLabel(OwnerNode, 'recur');
+ titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
+
+ OwnerNode.AddLabel(OwnerNode, '(');
+ for i := 0 to High(FNode.Arguments) do
+ begin
+ argNode := visu.CallAccept(FNode.Arguments[i]);
+ FArgumentNodes.Add(argNode);
+ if i < High(FNode.Arguments) then
+ OwnerNode.AddLabel(OwnerNode, ',');
+ end;
+ OwnerNode.AddLabel(OwnerNode, ')');
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TRecurNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+var
+ args: TArray;
+ i: Integer;
+begin
+ SetLength(args, FArgumentNodes.Count);
+ for i := 0 to FArgumentNodes.Count - 1 do
+ args[i] := FArgumentNodes[i].CreateAst;
+ Result := TAst.Recur(FNode.Identity, args, FNode.StaticType);
+end;
+
+{ TVariableDeclarationNodeHandler }
+
+procedure TVariableDeclarationNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ visu: IAstVisualizer;
+ varLabel: TLabel;
+begin
+ visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := True;
+ OwnerNode.Orientation := loHorizontal;
+
+ varLabel := OwnerNode.AddLabel(OwnerNode, 'var');
+
+ varLabel.Font.Style := varLabel.Font.Style + [TFontStyle.fsBold];
+ FTargetNode := visu.CallAccept(FNode.Target);
+
+ if Assigned(FNode.Initializer) then
+ begin
+ OwnerNode.AddLabel(OwnerNode, ':=');
+ FInitializerNode := visu.CallAccept(FNode.Initializer);
+ end
+ else
+ FInitializerNode := nil;
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TVariableDeclarationNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+var
+ initAst: IAstNode;
+begin
+ if Assigned(FInitializerNode) then
+ initAst := FInitializerNode.CreateAst
+ else
+ initAst := nil;
+ Result := TAst.VarDecl(FNode.Identity, FTargetNode.CreateAst, initAst, FNode.StaticType, FNode.IsBoxed);
+end;
+
+{ TAssignmentNodeHandler }
+
+procedure TAssignmentNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ visu: IAstVisualizer;
+begin
+ visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := True;
+ OwnerNode.Orientation := loHorizontal;
+ FTargetNode := visu.CallAccept(FNode.Target);
+ OwnerNode.AddLabel(OwnerNode, ':=');
+ FValueNode := visu.CallAccept(FNode.Value);
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TAssignmentNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+begin
+ Result := TAst.Assign(FNode.Identity, FTargetNode.CreateAst, FValueNode.CreateAst, FNode.StaticType);
+end;
+
+{ TMacroDefinitionNodeHandler }
+
+procedure TMacroDefinitionNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ visu: IAstVisualizer;
+ titleLabel: TLabel;
+ paramStr: string;
+ i: Integer;
+begin
+ visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := False;
+ OwnerNode.Orientation := loVertical;
+
+ paramStr := '';
+ for i := 0 to High(FNode.Parameters) do
+ begin
+ if i > 0 then
+ paramStr := paramStr + ', ';
+ paramStr := paramStr + FNode.Parameters[i].Name;
+ end;
+
+ titleLabel := OwnerNode.AddLabel(OwnerNode, 'Macro Def: ' + FNode.Name.Name + ' (' + paramStr + ')');
+ titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
+
+ FBodyNode := visu.CallAccept(FNode.Body);
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TMacroDefinitionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+begin
+ Result := TAst.MacroDef(FNode.Identity, FNode.Name, FNode.Parameters, FBodyNode.CreateAst);
+end;
+
+{ TQuasiquoteNodeHandler }
+
+procedure TQuasiquoteNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ visu: IAstVisualizer;
+ titleLabel: TLabel;
+begin
+ visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := False;
+ OwnerNode.Orientation := loVertical;
+ titleLabel := OwnerNode.AddLabel(OwnerNode, 'Quasiquote');
+ titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
+ FExpressionNode := visu.CallAccept(FNode.Expression);
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TQuasiquoteNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+begin
+ Result := TAst.Quasiquote(FNode.Identity, FExpressionNode.CreateAst);
+end;
+
+{ TUnquoteNodeHandler }
+
+procedure TUnquoteNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ visu: IAstVisualizer;
+ leftBracket, rightBracket: TLabel;
+begin
+ visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := True;
+ OwnerNode.Orientation := loHorizontal;
+
+ leftBracket := OwnerNode.AddLabel(OwnerNode, '<');
+ leftBracket.Padding.Right := 0;
+ leftBracket.Margins.Right := 0;
+
+ FExpressionNode := visu.CallAccept(FNode.Expression);
+
+ rightBracket := OwnerNode.AddLabel(OwnerNode, '>');
+ rightBracket.Padding.Left := 0;
+ rightBracket.Margins.Left := 0;
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TUnquoteNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+begin
+ Result := TAst.Unquote(FNode.Identity, FExpressionNode.CreateAst);
+end;
+
+{ TUnquoteSplicingNodeHandler }
+
+procedure TUnquoteSplicingNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ visu: IAstVisualizer;
+ titleLabel: TLabel;
+begin
+ visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := False;
+ OwnerNode.Orientation := loVertical;
+ titleLabel := OwnerNode.AddLabel(OwnerNode, 'Unquote-Splicing');
+ titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
+ FExpressionNode := visu.CallAccept(FNode.Expression);
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TUnquoteSplicingNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+begin
+ Result := TAst.UnquoteSplicing(FNode.Identity, FExpressionNode.CreateAst.AsQuasiquote);
+end;
+
+{ TIndexerNodeHandler }
+
+procedure TIndexerNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ visu: IAstVisualizer;
+begin
+ visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := True;
+ OwnerNode.Orientation := loHorizontal;
+ FBaseNode := visu.CallAccept(FNode.Base);
+ OwnerNode.AddLabel(OwnerNode, '[');
+ FIndexNode := visu.CallAccept(FNode.Index);
+ OwnerNode.AddLabel(OwnerNode, ']');
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TIndexerNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+begin
+ Result := TAst.Indexer(FNode.Identity, FBaseNode.CreateAst, FIndexNode.CreateAst, FNode.StaticType);
+end;
+
+{ TMemberAccessNodeHandler }
+
+procedure TMemberAccessNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ visu: IAstVisualizer;
+begin
+ visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := True;
+ OwnerNode.Orientation := loHorizontal;
+ FBaseNode := visu.CallAccept(FNode.Base);
+ OwnerNode.AddLabel(OwnerNode, '.');
+ OwnerNode.AddLabel(OwnerNode, FNode.Member.Value.Name);
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TMemberAccessNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+begin
+ // Reuse Identifier, Reuse Member Keyword (via TAst.Keyword with Identity)
+ Result := TAst.MemberAccess(FNode.Identity, FBaseNode.CreateAst, TAst.Keyword(FNode.Member.Identity.AsKeyword), FNode.StaticType);
+end;
+
+{ TRecordLiteralNodeHandler }
+
+constructor TRecordLiteralNodeHandler.Create(const ANode: IRecordLiteralNode);
+begin
+ inherited Create(ANode);
+ FFieldNodes := TDictionary.Create;
+end;
+
+destructor TRecordLiteralNodeHandler.Destroy;
+begin
+ FFieldNodes.Free;
+ inherited;
+end;
+
+procedure TRecordLiteralNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ field: TRecordFieldLiteral;
+ fieldContainer: TAutoFitControl;
+ valueNode: TAuraNode;
+ keyLabel: TLabel;
+begin
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := False;
+ OwnerNode.Orientation := loVertical;
+ OwnerNode.Alignment := laFlush;
+
+ if Length(FNode.Fields) = 0 then
+ begin
+ OwnerNode.AddLabel(OwnerNode, '{}');
+ end
+ else
+ begin
+ for field in FNode.Fields do
+ begin
+ fieldContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter);
+ keyLabel := OwnerNode.AddLabel(fieldContainer, ':' + field.Key.Value.Name);
+ keyLabel.Font.Style := keyLabel.Font.Style + [TFontStyle.fsBold];
+ keyLabel.StyledSettings := keyLabel.StyledSettings - [TStyledSetting.FontColor];
+ keyLabel.FontColor := TAlphaColors.Mediumvioletred;
+
+ valueNode := OwnerNode.Visualizer.Clone(fieldContainer, OwnerNode.Visualizer.ExprDepth + 1).CallAccept(field.Value);
+ FFieldNodes.Add(field.Key.Value, valueNode);
+ end;
+ end;
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TRecordLiteralNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+var
+ fields: TArray;
+ i: Integer;
+ valueNode: TAuraNode;
+ pair: TPair;
+begin
+ SetLength(fields, FFieldNodes.Count);
+ i := 0;
+ for pair in FFieldNodes do
+ begin
+ valueNode := pair.Value;
+ fields[i] := TRecordFieldLiteral.Create(TAst.Keyword(pair.Key.Name), valueNode.CreateAst);
+ inc(i);
+ end;
+ Result := TAst.RecordLiteral(FNode.Identity, fields, FNode.ScalarDefinition, FNode.GenericDefinition, FNode.StaticType);
+end;
+
+{ TCreateSeriesNodeHandler }
+
+procedure TCreateSeriesNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ titleLabel: TLabel;
+begin
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := False;
+ OwnerNode.Orientation := loVertical;
+ titleLabel := OwnerNode.AddLabel(OwnerNode, 'Create Series: ' + FNode.Definition);
+ titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TCreateSeriesNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+begin
+ Result := TAst.CreateSeries(FNode.Identity.AsDefinition, FNode.StaticType);
+end;
+
+{ TAddSeriesItemNodeHandler }
+
+procedure TAddSeriesItemNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ visu: IAstVisualizer;
+ titleLabel: TLabel;
+begin
+ visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := False;
+ OwnerNode.Orientation := loVertical;
+
+ titleLabel := OwnerNode.AddLabel(OwnerNode, 'Add Item to: ' + FNode.Series.Name);
+ titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
+
+ FValueNode := visu.CallAccept(FNode.Value);
+ if Assigned(FNode.Lookback) then
+ FLookbackNode := visu.CallAccept(FNode.Lookback)
+ else
+ FLookbackNode := nil;
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TAddSeriesItemNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+var
+ lookbackAst: IAstNode;
+begin
+ if Assigned(FLookbackNode) then
+ lookbackAst := FLookbackNode.CreateAst
+ else
+ lookbackAst := nil;
+
+ Result :=
+ TAst.AddSeriesItem(
+ FNode.Identity,
+ FNode.Series, // Reuse original Series Identifier Node
+ FValueNode.CreateAst,
+ lookbackAst,
+ FNode.StaticType
+ );
+end;
+
+{ TSeriesLengthNodeHandler }
+
+procedure TSeriesLengthNodeHandler.BuildUI(OwnerNode: TAuraNode);
+var
+ titleLabel: TLabel;
+begin
+ OwnerNode.BeginUpdate;
+ try
+ OwnerNode.Frameless := False;
+ OwnerNode.Orientation := loVertical;
+ titleLabel := OwnerNode.AddLabel(OwnerNode, 'Length of: ' + FNode.Series.Name);
+ titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
+ finally
+ OwnerNode.EndUpdate;
+ end;
+end;
+
+function TSeriesLengthNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
+begin
+ Result := TAst.SeriesLength(FNode.Identity, FNode.Series, FNode.StaticType);
+end;
+
+end.
diff --git a/Src/AST/Myc.Fmx.AstEditor.Visualizer.pas b/Src/AST/Myc.Fmx.AstEditor.Visualizer.pas
new file mode 100644
index 0000000..e38decd
--- /dev/null
+++ b/Src/AST/Myc.Fmx.AstEditor.Visualizer.pas
@@ -0,0 +1,249 @@
+unit Myc.Fmx.AstEditor.Visualizer;
+
+interface
+
+uses
+ System.SysUtils,
+ System.Classes,
+ FMX.Controls,
+ Myc.Data.Value,
+ Myc.Ast.Nodes,
+ Myc.Ast.Visitor,
+ Myc.Fmx.AstEditor.Workspace,
+ Myc.Fmx.AstEditor.Core,
+ Myc.Fmx.AstEditor.Handlers;
+
+type
+ // Inherits from the generic TAstVisitor
+ TAstVisualizer = class(TAstVisitor, IAstVisualizer)
+ private
+ FExprDepth: Integer;
+ FParentControl: TControl;
+ FWorkspace: TAuraWorkspace;
+ function CallAccept(const Node: IAstNode): TAuraNode;
+ function GetExprDepth: Integer;
+ function GetParentControl: TControl;
+ function GetWorkspace: TAuraWorkspace;
+ procedure SetExprDepth(const Value: Integer);
+ procedure SetParentControl(const Value: TControl);
+ protected
+ // Visitor implementations for each AST node type.
+ function VisitConstant(const Node: IConstantNode): TAuraNode; override;
+ function VisitIdentifier(const Node: IIdentifierNode): TAuraNode; override;
+ function VisitKeyword(const Node: IKeywordNode): TAuraNode; override;
+ function VisitIfExpression(const Node: IIfExpressionNode): TAuraNode; override;
+ function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAuraNode; override;
+ function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAuraNode; override;
+ function VisitFunctionCall(const Node: IFunctionCallNode): TAuraNode; override;
+ function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TAuraNode; override;
+ function VisitBlockExpression(const Node: IBlockExpressionNode): TAuraNode; override;
+ function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAuraNode; override;
+ function VisitAssignment(const Node: IAssignmentNode): TAuraNode; override;
+ function VisitMacroDefinition(const Node: IMacroDefinitionNode): TAuraNode; override;
+ function VisitQuasiquote(const Node: IQuasiquoteNode): TAuraNode; override;
+ function VisitUnquote(const Node: IUnquoteNode): TAuraNode; override;
+ function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TAuraNode; override;
+ function VisitIndexer(const Node: IIndexerNode): TAuraNode; override;
+ function VisitMemberAccess(const Node: IMemberAccessNode): TAuraNode; override;
+ function VisitRecordLiteral(const Node: IRecordLiteralNode): TAuraNode; override;
+ function VisitCreateSeries(const Node: ICreateSeriesNode): TAuraNode; override;
+ function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAuraNode; override;
+ function VisitSeriesLength(const Node: ISeriesLengthNode): TAuraNode; override;
+ function VisitRecurNode(const Node: IRecurNode): TAuraNode; override;
+ function VisitNop(const Node: INopNode): TAuraNode; override;
+
+ public
+ constructor Create(AWorkspace: TAuraWorkspace; AParentControl: TControl; AExprDepth: Integer);
+ destructor Destroy; override;
+
+ function Clone(ParentControl: TControl; ExprDepth: Integer): IAstVisualizer;
+
+ property ExprDepth: Integer read GetExprDepth write SetExprDepth;
+ property ParentControl: TControl read GetParentControl write SetParentControl;
+ property Workspace: TAuraWorkspace read GetWorkspace;
+ end;
+
+implementation
+
+{ TAstVisualizer }
+
+constructor TAstVisualizer.Create(AWorkspace: TAuraWorkspace; AParentControl: TControl; AExprDepth: Integer);
+begin
+ inherited Create;
+ FWorkspace := AWorkspace;
+ FParentControl := AParentControl;
+ FExprDepth := AExprDepth;
+end;
+
+destructor TAstVisualizer.Destroy;
+begin
+ inherited;
+end;
+
+function TAstVisualizer.CallAccept(const Node: IAstNode): TAuraNode;
+var
+ dataValue: TDataValue;
+begin
+ if not Assigned(Node) then
+ exit(nil);
+
+ dataValue := Node.Accept(Self);
+
+ if dataValue.Kind = TDataValueKind.vkGeneric then
+ begin
+ Result := dataValue.AsGeneric;
+ end
+ else
+ begin
+ Result := nil;
+ end;
+end;
+
+function TAstVisualizer.Clone(ParentControl: TControl; ExprDepth: Integer): IAstVisualizer;
+begin
+ Result := TAstVisualizer.Create(FWorkspace, ParentControl, ExprDepth);
+end;
+
+function TAstVisualizer.GetExprDepth: Integer;
+begin
+ Result := FExprDepth;
+end;
+
+function TAstVisualizer.GetParentControl: TControl;
+begin
+ Result := FParentControl;
+end;
+
+function TAstVisualizer.GetWorkspace: TAuraWorkspace;
+begin
+ Result := FWorkspace;
+end;
+
+procedure TAstVisualizer.SetExprDepth(const Value: Integer);
+begin
+ FExprDepth := Value;
+end;
+
+procedure TAstVisualizer.SetParentControl(const Value: TControl);
+begin
+ FParentControl := Value;
+end;
+
+// --- Visitor Implementations ---
+
+function TAstVisualizer.VisitConstant(const Node: IConstantNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TConstantNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitIdentifier(const Node: IIdentifierNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TIdentifierNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitKeyword(const Node: IKeywordNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TKeywordNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitBlockExpression(const Node: IBlockExpressionNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TBlockExpressionNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitIfExpression(const Node: IIfExpressionNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TIfExpressionNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitTernaryExpression(const Node: ITernaryExpressionNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TTernaryExpressionNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TLambdaExpressionNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitFunctionCall(const Node: IFunctionCallNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TFunctionCallNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TMacroExpansionNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TVariableDeclarationNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitAssignment(const Node: IAssignmentNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TAssignmentNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitMacroDefinition(const Node: IMacroDefinitionNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TMacroDefinitionNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitQuasiquote(const Node: IQuasiquoteNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TQuasiquoteNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitUnquote(const Node: IUnquoteNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TUnquoteNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TUnquoteSplicingNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitIndexer(const Node: IIndexerNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TIndexerNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitMemberAccess(const Node: IMemberAccessNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TMemberAccessNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitRecordLiteral(const Node: IRecordLiteralNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TRecordLiteralNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitCreateSeries(const Node: ICreateSeriesNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TCreateSeriesNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TAddSeriesItemNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitSeriesLength(const Node: ISeriesLengthNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TSeriesLengthNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitRecurNode(const Node: IRecurNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TRecurNodeHandler.Create(Node));
+end;
+
+function TAstVisualizer.VisitNop(const Node: INopNode): TAuraNode;
+begin
+ Result := TAuraNode.Create(Self, TNopNodeHandler.Create(Node));
+end;
+
+end.
diff --git a/ASTPlayground/Myc.Fmx.AstEditor.Workspace.pas b/Src/AST/Myc.Fmx.AstEditor.Workspace.pas
similarity index 90%
rename from ASTPlayground/Myc.Fmx.AstEditor.Workspace.pas
rename to Src/AST/Myc.Fmx.AstEditor.Workspace.pas
index 06a7290..1a9bec8 100644
--- a/ASTPlayground/Myc.Fmx.AstEditor.Workspace.pas
+++ b/Src/AST/Myc.Fmx.AstEditor.Workspace.pas
@@ -91,7 +91,8 @@ implementation
uses
System.Math,
FMX.Platform,
- Myc.Fmx.AstEditor.Node;
+ Myc.Fmx.AstEditor.Core,
+ Myc.Fmx.AstEditor.Visualizer;
{ TPinConnection }
@@ -112,7 +113,10 @@ end;
procedure TAuraWorkspace.Build(const RootNode: IAstNode; const Position: TPointF);
begin
var visu := TAstVisualizer.Create(Self, Self, 0) as IAstVisualizer;
- visu.CallAccept(RootNode);
+ var node := visu.CallAccept(RootNode);
+
+ if Assigned(node) then
+ node.Position.Point := Position;
end;
procedure TAuraWorkspace.DoDeleteChildren;
@@ -125,7 +129,7 @@ function TAuraWorkspace.GetChildrenMatrix(var Matrix: TMatrix; var Simple: Boole
begin
Matrix := TMatrix.CreateScaling(FZoom, FZoom) * TMatrix.CreateTranslation(FPanning.cx, FPanning.cy);
Simple := (FZoom = 1.0) and (FPanning.cx = 0) and (FPanning.cy = 0);
- Result := true;
+ Result := True;
end;
procedure TAuraWorkspace.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Single);
@@ -225,15 +229,15 @@ end;
function TAuraWorkspace.Zoom(Factor: Single): Boolean;
var
- MouseService: IFMXMouseService;
+ mouseService: IFMXMouseService;
begin
- Result := TPlatformServices.Current.SupportsPlatformService(IFMXMouseService, MouseService);
+ Result := TPlatformServices.Current.SupportsPlatformService(IFMXMouseService, mouseService);
if Result then
begin
- var MousePos := ScreenToLocal(MouseService.GetMousePos);
+ var mousePos := ScreenToLocal(mouseService.GetMousePos);
Factor := Max(0.2, Min(3.0, Factor));
- FPanning.cx := MousePos.X * (1 - Factor / FZoom) + FPanning.cx * (Factor / FZoom);
- FPanning.cy := MousePos.Y * (1 - Factor / FZoom) + FPanning.cy * (Factor / FZoom);
+ FPanning.cx := mousePos.X * (1 - Factor / FZoom) + FPanning.cx * (Factor / FZoom);
+ FPanning.cy := mousePos.Y * (1 - Factor / FZoom) + FPanning.cy * (Factor / FZoom);
FZoom := Factor;
RecalcAbsolute;
RecalcUpdateRect;
diff --git a/Src/AST/Test.Myc.Ast.Compiler.Binder.pas b/Test/Test.Myc.Ast.Compiler.Binder.pas
similarity index 100%
rename from Src/AST/Test.Myc.Ast.Compiler.Binder.pas
rename to Test/Test.Myc.Ast.Compiler.Binder.pas