From f1735e267844fa33c116e123fbe6021fb2e343fb Mon Sep 17 00:00:00 2001 From: Michael Schimmel Date: Wed, 29 Oct 2025 23:07:49 +0100 Subject: [PATCH] New visualizer --- ASTPlayground/ASTPlayground.delphilsp.json | 2 +- ASTPlayground/ASTPlayground.dpr | 3 +- ASTPlayground/ASTPlayground.dproj | 1 - ASTPlayground/MainForm.pas | 1 - ASTPlayground/Myc.Fmx.AstEditor.Node.pas | 1848 ++++++++++++++++- ASTPlayground/Myc.Fmx.AstEditor.Workspace.pas | 5 +- ASTPlayground/Myc.Fmx.AstVisualizer.pas | 232 +-- Src/AST/Myc.Ast.pas | 4 +- Src/Data/Myc.Data.Value.pas | 3 +- 9 files changed, 1932 insertions(+), 167 deletions(-) diff --git a/ASTPlayground/ASTPlayground.delphilsp.json b/ASTPlayground/ASTPlayground.delphilsp.json index 8662a1a..bbbb104 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.Evaluator", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Evaluator.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.Debugger", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Debugger.pas" }, { "name": "Myc.Ast.Visitor", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Visitor.pas" }, { "name": "Myc.Ast.Binding", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Binding.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.Fmx.AstVisualizer", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Fmx.AstVisualizer.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.Evaluator", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Evaluator.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.Debugger", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Debugger.pas" }, { "name": "Myc.Ast.Visitor", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Visitor.pas" }, { "name": "Myc.Ast.Binding", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Binding.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" } ] , "includeDCUsInUsesCompletion": true, "enableKeyWordCompletion": false, "browsingPaths": [ "file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/OCX/Servers","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/VCL","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/RTL/SYS","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/win","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/win/winrt","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/ToolsAPI","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/IBX","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Internet","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/PROPERTY%20EDITORS","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/soap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/XML","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/Core","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/System","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/Protocols","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/fmx","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/components","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/engine","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/graph","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/ado","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/cloud","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/dbx","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/dsnap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/vclctrls","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap/connectors","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap/proxygen","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DataExplorer","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/Common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/Common/dunit","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/Common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/DUnitProject","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/DUnitProject/dunit","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/src","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/tests","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Experts","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indy/abstraction","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indy/implementation","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indyimpl","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Property%20Editors/Indy10","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/soap/wsdlimporter","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Visualizers","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/XMLReporting","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/XPGen","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/rest","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/firedac","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/tethering","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnitX","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/ems","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/net","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/FlatBox2D","file:///C%3A/Users/Public/Documents/Embarcadero/Studio/37.0/Dcp/%25PLATFORM%25","file:///%25TP%25/runtime/vcl","file:///S%3A/sc_famos_src/svn_vcl/cpxedits","file:///S%3A/sc_famos_src/svn_vcl/dzChart","file:///S%3A/sc_famos_src/svn_vcl/eaeditor","file:///S%3A/sc_famos_src/svn_vcl/FamosEvents","file:///S%3A/sc_famos_src/svn_vcl/HTML_Viewer/source","file:///S%3A/sc_famos_src/svn_vcl/Myc_ChartEdit","file:///S%3A/sc_famos_src/svn_vcl/Myc_HemiDrag","file:///S%3A/sc_famos_src/svn_vcl/Myc_SplitControl","file:///S%3A/sc_famos_src/svn_vcl/NiceChart","file:///S%3A/sc_famos_src/svn_vcl/plotter","file:///S%3A/sc_famos_src/svn_vcl/SimpleIPC","file:///S%3A/sc_famos_src/svn_vcl/SynEdit-master/Source","file:///S%3A/sc_famos_src/svn_vcl/ValEdits","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster/zlib","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster/zlib/win32","file:///S%3A/sc_famos_src/svn_vcl/Virtual-TreeView/Source","file:///S%3A/sc_famos_src/svn_common/caHelpSys","file:///S%3A/sc_famos_src/svn_common/Misc","file:///S%3A/sc_famos_src/svn_common/Myc_VecMath","file:///S%3A/sc_famos_src/svn_common/PascalScript/source","file:///S%3A/sc_famos_src/svn_common/TreeBase","file:///S%3A/sc_famos_src/svn_common/TreeBase/Medien","file:///S%3A/3rdParty/spring4d/Source","file:///S%3A/3rdParty/spring4d/Source/Base","file:///S%3A/3rdParty/spring4d/Source/Base/Collections","file:///S%3A/3rdParty/spring4d/Source/Base/Logging","file:///S%3A/3rdParty/spring4d/Source/Base/Patches","file:///S%3A/3rdParty/spring4d/Source/Core/Container","file:///S%3A/3rdParty/spring4d/Source/Core/Interception","file:///S%3A/3rdParty/spring4d/Source/Core/Logging","file:///S%3A/3rdParty/spring4d/Source/Core/Mocking","file:///S%3A/3rdParty/spring4d/Source/Core/Services","file:///S%3A/3rdParty/spring4d/Source/Extensions/Cryptography","file:///S%3A/3rdParty/spring4d/Source/Extensions/Utils","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressCore%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressCommon%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressGDI%2B%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressLibrary/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/XP%20Theme%20Manager/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressLayout%20Control/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressPageControl/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressEditors%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressDocking%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressBars/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressOfficeCore%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressMemData/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressDataController/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressNavBar/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressSkins%20Library/Sources","file:///T%3A/Myc/Src","file:///T%3A/Myc/Src/Data","file:///T%3A/Myc/Src/AST" ] , "CommonAppData": "file:///C%3A/Users/Brummel/AppData/Roaming/Embarcadero/BDS/37.0/" , "Templates": "file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/ObjRepos/" } } \ No newline at end of file diff --git a/ASTPlayground/ASTPlayground.dpr b/ASTPlayground/ASTPlayground.dpr index 7341e7d..36976ee 100644 --- a/ASTPlayground/ASTPlayground.dpr +++ b/ASTPlayground/ASTPlayground.dpr @@ -20,8 +20,7 @@ uses 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', - Myc.Fmx.AstVisualizer in 'Myc.Fmx.AstVisualizer.pas'; + Myc.Ast.Types in '..\Src\AST\Myc.Ast.Types.pas'; {$R *.res} diff --git a/ASTPlayground/ASTPlayground.dproj b/ASTPlayground/ASTPlayground.dproj index 0372725..aa0dad9 100644 --- a/ASTPlayground/ASTPlayground.dproj +++ b/ASTPlayground/ASTPlayground.dproj @@ -151,7 +151,6 @@ - Base diff --git a/ASTPlayground/MainForm.pas b/ASTPlayground/MainForm.pas index 3655b38..6e197a4 100644 --- a/ASTPlayground/MainForm.pas +++ b/ASTPlayground/MainForm.pas @@ -36,7 +36,6 @@ uses FMX.Layouts, FMX.Objects, Myc.Ast.Debugger, - Myc.Fmx.AstVisualizer, Myc.Fmx.AstEditor.Node, Myc.Fmx.AstEditor.Workspace, FMX.DialogService, diff --git a/ASTPlayground/Myc.Fmx.AstEditor.Node.pas b/ASTPlayground/Myc.Fmx.AstEditor.Node.pas index f878c3b..127007a 100644 --- a/ASTPlayground/Myc.Fmx.AstEditor.Node.pas +++ b/ASTPlayground/Myc.Fmx.AstEditor.Node.pas @@ -8,14 +8,134 @@ uses System.UITypes, System.Types, System.Math.Vectors, + System.Math, + System.Generics.Defaults, + System.Generics.Collections, FMX.Types, FMX.Controls, FMX.Objects, - FMX.Graphics; + FMX.Graphics, + FMX.StdCtrls, + Myc.Data.Scalar, + Myc.Data.Value, + Myc.Ast.Nodes, + Myc.Ast.Visitor, + Myc.Ast, + Myc.Fmx.AstEditor.Workspace; + +const + cNodePadding = 10; + cTitleTopPadding = 2; + cTitleBottomPadding = 4; + cMinNodeWidth = 10; + cMinNodeHeight = 10; type + TAuraNode = class; + + 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; + + 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): TDataValue; override; + function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override; + function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; override; + function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; override; + function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override; + function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override; + function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override; + function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override; + function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue; override; + function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override; + function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override; + function VisitAssignment(const Node: IAssignmentNode): TDataValue; override; + function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override; + function VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue; override; + function VisitUnquote(const Node: IUnquoteNode): TDataValue; override; + function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue; override; + function VisitIndexer(const Node: IIndexerNode): TDataValue; override; + function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override; + function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override; + function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; override; + function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override; + function VisitRecurNode(const Node: IRecurNode): TDataValue; 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(TStyledControl) + TAuraNode = class(TAutoFitControl) private FBackgroundColor: TAlphaColor; // Flag to indicate if the control is currently being dragged. @@ -28,7 +148,8 @@ type FBorderRadius: Single; // If true, the node is drawn without a border and with a transparent background. FFrameless: Boolean; - + FVisualizer: IAstVisualizer; + function AddLabel(const Txt: String): TLabel; procedure SetBackgroundColor(const Value: TAlphaColor); procedure SetBorderColor(const Value: TAlphaColor); procedure SetBorderWidth(const Value: Single); @@ -39,9 +160,17 @@ type 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; + property Visualizer: IAstVisualizer read FVisualizer; + procedure SetupNode; virtual; public - constructor Create(AOwner: TComponent); override; + constructor Create(const AVisualizer: IAstVisualizer); reintroduce; destructor Destroy; override; + + procedure AfterConstruction; override; + + // Creates an AST from the visualization + function CreateAst: IAstNode; virtual; + published // Custom border properties property BorderColor: TAlphaColor read FBorderColor write SetBorderColor; @@ -60,9 +189,6 @@ type property DragMode default TDragMode.dmManual; property Enabled; property Height; - property HelpContext; - property HelpKeyword; - property HelpType; property Hint; property HitTest default True; property Locked; @@ -75,7 +201,6 @@ type property RotationCenter; property Scale; property Size; - property StyleLookup; property Visible; property Width; property OnClick; @@ -88,13 +213,684 @@ type property OnMouseLeave; end; + TAuraConstantNode = class(TAuraNode) + private + FNode: IConstantNode; + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IConstantNode); + + function CreateAst: IAstNode; override; + + property Node: IConstantNode read FNode; + end; + + TAuraIdentifierNode = class(TAuraNode) + private + FNode: IIdentifierNode; + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IIdentifierNode); + function CreateAst: IAstNode; override; + + property Node: IIdentifierNode read FNode; + end; + + TAuraBinaryExpressionNode = class(TAuraNode) + private + FNode: IBinaryExpressionNode; + function GetLeftNode: TAuraNode; + function GetRightNode: TAuraNode; + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IBinaryExpressionNode); + function CreateAst: IAstNode; override; + + property LeftNode: TAuraNode read GetLeftNode; + property RightNode: TAuraNode read GetRightNode; + + property Node: IBinaryExpressionNode read FNode; + end; + + TAuraBlockExpressionNode = class(TAuraNode) + private + FNode: IBlockExpressionNode; + FChildNodes: TList; // To store children for CreateAst + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IBlockExpressionNode); + destructor Destroy; override; + function CreateAst: IAstNode; override; + property Node: IBlockExpressionNode read FNode; + end; + + TAuraUnaryExpressionNode = class(TAuraNode) + private + FNode: IUnaryExpressionNode; + FChildNode: TAuraNode; // Stores the single child + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IUnaryExpressionNode); + function CreateAst: IAstNode; override; + property Node: IUnaryExpressionNode read FNode; + end; + + TAuraIfExpressionNode = class(TAuraNode) + private + FNode: IIfExpressionNode; + FConditionNode: TAuraNode; + FThenNode: TAuraNode; + FElseNode: TAuraNode; // Can be nil + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IIfExpressionNode); + function CreateAst: IAstNode; override; + property Node: IIfExpressionNode read FNode; + end; + + TAuraTernaryExpressionNode = class(TAuraNode) + private + FNode: ITernaryExpressionNode; + FConditionNode: TAuraNode; + FThenNode: TAuraNode; + FElseNode: TAuraNode; + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: ITernaryExpressionNode); + function CreateAst: IAstNode; override; + property Node: ITernaryExpressionNode read FNode; + end; + + TAuraLambdaExpressionNode = class(TAuraNode) + private + FNode: ILambdaExpressionNode; + FBodyNode: TAuraNode; + FParamLabels: TList; // To store param labels + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: ILambdaExpressionNode); + destructor Destroy; override; + function CreateAst: IAstNode; override; + property Node: ILambdaExpressionNode read FNode; + end; + + TAuraFunctionCallNode = class(TAuraNode) + private + FNode: IFunctionCallNode; + FCalleeNode: TAuraNode; + FArgumentNodes: TList; + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IFunctionCallNode); + destructor Destroy; override; + function CreateAst: IAstNode; override; + property Node: IFunctionCallNode read FNode; + end; + + TAuraMacroExpansionNode = class(TAuraNode) + private + FNode: IMacroExpansionNode; + FExpandedBodyNode: TAuraNode; + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IMacroExpansionNode); + function CreateAst: IAstNode; override; + property Node: IMacroExpansionNode read FNode; + end; + + TAuraRecurNode = class(TAuraNode) + private + FNode: IRecurNode; + FArgumentNodes: TList; + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IRecurNode); + destructor Destroy; override; + function CreateAst: IAstNode; override; + property Node: IRecurNode read FNode; + end; + + TAuraVariableDeclarationNode = class(TAuraNode) + private + FNode: IVariableDeclarationNode; + FInitializerNode: TAuraNode; // Can be nil + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IVariableDeclarationNode); + function CreateAst: IAstNode; override; + property Node: IVariableDeclarationNode read FNode; + end; + + TAuraAssignmentNode = class(TAuraNode) + private + FNode: IAssignmentNode; + FValueNode: TAuraNode; + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IAssignmentNode); + function CreateAst: IAstNode; override; + property Node: IAssignmentNode read FNode; + end; + + TAuraMacroDefinitionNode = class(TAuraNode) + private + FNode: IMacroDefinitionNode; + FBodyNode: TAuraNode; + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IMacroDefinitionNode); + function CreateAst: IAstNode; override; + property Node: IMacroDefinitionNode read FNode; + end; + + TAuraQuasiquoteNode = class(TAuraNode) + private + FNode: IQuasiquoteNode; + FExpressionNode: TAuraNode; + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IQuasiquoteNode); + function CreateAst: IAstNode; override; + property Node: IQuasiquoteNode read FNode; + end; + + TAuraUnquoteNode = class(TAuraNode) + private + FNode: IUnquoteNode; + FExpressionNode: TAuraNode; + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IUnquoteNode); + function CreateAst: IAstNode; override; + property Node: IUnquoteNode read FNode; + end; + + TAuraUnquoteSplicingNode = class(TAuraNode) + private + FNode: IUnquoteSplicingNode; + FExpressionNode: TAuraNode; + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IUnquoteSplicingNode); + function CreateAst: IAstNode; override; + property Node: IUnquoteSplicingNode read FNode; + end; + + TAuraIndexerNode = class(TAuraNode) + private + FNode: IIndexerNode; + FBaseNode: TAuraNode; + FIndexNode: TAuraNode; + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IIndexerNode); + function CreateAst: IAstNode; override; + property Node: IIndexerNode read FNode; + end; + + TAuraMemberAccessNode = class(TAuraNode) + private + FNode: IMemberAccessNode; + FBaseNode: TAuraNode; + // FMemberNode is handled by a label, store Base only + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IMemberAccessNode); + function CreateAst: IAstNode; override; + property Node: IMemberAccessNode read FNode; + end; + + TAuraCreateSeriesNode = class(TAuraNode) + private + FNode: ICreateSeriesNode; + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: ICreateSeriesNode); + function CreateAst: IAstNode; override; + property Node: ICreateSeriesNode read FNode; + end; + + TAuraAddSeriesItemNode = class(TAuraNode) + private + FNode: IAddSeriesItemNode; + FValueNode: TAuraNode; + FLookbackNode: TAuraNode; // Can be nil + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: IAddSeriesItemNode); + function CreateAst: IAstNode; override; + property Node: IAddSeriesItemNode read FNode; + end; + + TAuraSeriesLengthNode = class(TAuraNode) + private + FNode: ISeriesLengthNode; + protected + procedure SetupNode; override; + public + constructor Create(const AVisualizer: IAstVisualizer; const ANode: ISeriesLengthNode); + function CreateAst: IAstNode; override; + property Node: ISeriesLengthNode read FNode; + 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; + +// 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; + +function TAstVisualizer.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraAddSeriesItemNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitAssignment(const Node: IAssignmentNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraAssignmentNode.Create(Self, Node)); +end; + +// --- Visitor Implementations --- + +function TAstVisualizer.VisitConstant(const Node: IConstantNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraConstantNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitIdentifier(const Node: IIdentifierNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraIdentifierNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraBinaryExpressionNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraBlockExpressionNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraCreateSeriesNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraFunctionCallNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraUnaryExpressionNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitIfExpression(const Node: IIfExpressionNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraIfExpressionNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitIndexer(const Node: IIndexerNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraIndexerNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraLambdaExpressionNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraMacroDefinitionNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraMacroExpansionNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraMemberAccessNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraQuasiquoteNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitRecurNode(const Node: IRecurNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraRecurNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraSeriesLengthNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraTernaryExpressionNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitUnquote(const Node: IUnquoteNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraUnquoteNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraUnquoteSplicingNode.Create(Self, Node)); +end; + +function TAstVisualizer.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; +begin + Result := TDataValue.FromGeneric(TAuraVariableDeclarationNode.Create(Self, Node)); +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(AOwner: TComponent); +constructor TAuraNode.Create(const AVisualizer: IAstVisualizer); begin - inherited Create(AOwner); + inherited Create(AVisualizer.Workspace); + + Parent := AVisualizer.ParentControl; + + FVisualizer := AVisualizer.Clone(Self, AVisualizer.ExprDepth); + FIsDragging := False; // Default border settings @@ -106,13 +902,27 @@ begin // Default state for frameless mode FFrameless := False; - Width := 80; - Height := 45; + // 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; @@ -120,6 +930,37 @@ begin inherited; end; +function TAuraNode.AddLabel(const Txt: String): TLabel; +begin + Result := TLabel.Create(Self); // Owner is the node itself + Result.Parent := Self; + + 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 + Result := TAst.Block([]); +end; + procedure TAuraNode.Paint; var rect: TRectF; @@ -260,4 +1101,987 @@ begin Repaint; end; +procedure TAuraNode.SetupNode; +begin + +end; + +{ TAuraConstantNode } + +constructor TAuraConstantNode.Create(const AVisualizer: IAstVisualizer; const ANode: IConstantNode); +begin + inherited Create(AVisualizer); + FNode := ANode; +end; + +function TAuraConstantNode.CreateAst: IAstNode; +begin + Result := FNode; +end; + +procedure TAuraConstantNode.SetupNode; +var + valueStr: string; + isConcise: Boolean; +begin + 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 + Frameless := true; + AddLabel(valueStr); + end + else + begin + // Use standard framed node with Title label + Value label + Frameless := False; + Orientation := loVertical; + + var titleLabel := AddLabel('Const'); + titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; + + // Value Label + var valueLabel := AddLabel(valueStr); + valueLabel.AutoSize := False; // ***Important: Disable AutoSize when Align=Client*** + valueLabel.WordWrap := True; // Allow wrapping for long text + end; + finally + EndUpdate; + end; +end; + +{ TAuraIdentifierNode } + +constructor TAuraIdentifierNode.Create(const AVisualizer: IAstVisualizer; const ANode: IIdentifierNode); +begin + inherited Create(AVisualizer); + FNode := ANode; +end; + +function TAuraIdentifierNode.CreateAst: IAstNode; +begin + Result := TAst.Identifier(FNode.Name); +end; + +procedure TAuraIdentifierNode.SetupNode; +begin + BeginUpdate; + try + Frameless := true; // Identifiers are frameless + AddLabel(FNode.Name); // Add label with the identifier name + finally + EndUpdate; + end; +end; + +{ TAuraBinaryExpressionNode } + +constructor TAuraBinaryExpressionNode.Create(const AVisualizer: IAstVisualizer; const ANode: IBinaryExpressionNode); +begin + inherited Create(AVisualizer); + FNode := ANode; +end; + +function TAuraBinaryExpressionNode.CreateAst: IAstNode; +begin + Result := TAst.BinaryExpr(LeftNode.CreateAst, FNode.Operator, RightNode.CreateAst); +end; + +function TAuraBinaryExpressionNode.GetLeftNode: TAuraNode; +begin + Result := Children[0] as TAuraNode; +end; + +function TAuraBinaryExpressionNode.GetRightNode: TAuraNode; +begin + Result := Children[2] as TAuraNode; +end; + +procedure TAuraBinaryExpressionNode.SetupNode; +begin + var visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1); + + BeginUpdate; + try + Frameless := true; // Generally make binary expressions frameless containers + Orientation := loHorizontal; + + visu.CallAccept(FNode.Left); + + // 2. Operator Label + AddLabel(FNode.Operator.ToString); + + // 3. RightNode Expression Node (Visited Recursively) + visu.CallAccept(FNode.Right); + finally + EndUpdate; + end; +end; + +{ TAuraBlockExpressionNode } + +constructor TAuraBlockExpressionNode.Create(const AVisualizer: IAstVisualizer; const ANode: IBlockExpressionNode); +begin + inherited Create(AVisualizer); + FNode := ANode; + FChildNodes := TList.Create; +end; + +destructor TAuraBlockExpressionNode.Destroy; +begin + FChildNodes.Free; + inherited Destroy; +end; + +function TAuraBlockExpressionNode.CreateAst: 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.Constant(TDataValue.Void); // Or handle error + end; + Result := TAst.Block(exprs); +end; + +procedure TAuraBlockExpressionNode.SetupNode; +var + visu: IAstVisualizer; + childNode: TAuraNode; + expr: IAstNode; + titleLabel: TLabel; + i: Integer; + returnContainer: TAutoFitControl; + visuReturn: IAstVisualizer; +begin + // This visualizer parents children directly to Self + visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1); + + BeginUpdate; + try + Frameless := true; + Orientation := loVertical; + Alignment := laFlush; // Align all child rows to the left + + for i := 0 to High(FNode.Expressions) do + begin + expr := FNode.Expressions[i]; + + if i = High(FNode.Expressions) then + begin + // Last expression: create a horizontal container for "return [expr]" + returnContainer := TAutoFitControl.Create(Self); + returnContainer.Parent := Self; // Parent is the main block node + returnContainer.Orientation := loHorizontal; + returnContainer.Alignment := laCenter; // Center "return" label vertically next to the expression + returnContainer.HitTest := False; // Pass clicks through + + // Add "return" label to the container + titleLabel := AddLabel('return'); // Use AddLabel from TAuraNode (Self) + titleLabel.Parent := returnContainer; // Set parent to the new container + titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; + + // Create a new visualizer targeting this container + visuReturn := FVisualizer.Clone(returnContainer, FVisualizer.ExprDepth + 1); + + // Add the expression node to the container + childNode := visuReturn.CallAccept(expr); + FChildNodes.Add(childNode); // Store for CreateAst + end + else + begin + // Not the last expression, add directly to Self + childNode := visu.CallAccept(expr); + FChildNodes.Add(childNode); // Store for CreateAst + end; + end; + finally + EndUpdate; + end; +end; + +{ TAuraUnaryExpressionNode } + +constructor TAuraUnaryExpressionNode.Create(const AVisualizer: IAstVisualizer; const ANode: IUnaryExpressionNode); +begin + inherited Create(AVisualizer); + FNode := ANode; +end; + +function TAuraUnaryExpressionNode.CreateAst: IAstNode; +begin + Result := TAst.UnaryExpr(FNode.Operator, FChildNode.CreateAst); +end; + +procedure TAuraUnaryExpressionNode.SetupNode; +var + visu: IAstVisualizer; + titleLabel: TLabel; +begin + visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1); + + BeginUpdate; + try + // Vertical layout, framed + Frameless := False; + Orientation := loVertical; + + // Title + titleLabel := AddLabel('Unary Op: ' + FNode.Operator.ToString); + titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; + + // Child + FChildNode := visu.CallAccept(FNode.Right); + finally + EndUpdate; + end; +end; + +{ TAuraIfExpressionNode } + +constructor TAuraIfExpressionNode.Create(const AVisualizer: IAstVisualizer; const ANode: IIfExpressionNode); +begin + inherited Create(AVisualizer); + FNode := ANode; + FElseNode := nil; +end; + +function TAuraIfExpressionNode.CreateAst: IAstNode; +var + elseAst: IAstNode; +begin + if Assigned(FElseNode) then + elseAst := FElseNode.CreateAst + else + elseAst := nil; + + Result := TAst.IfExpr(FConditionNode.CreateAst, FThenNode.CreateAst, elseAst); +end; + +procedure TAuraIfExpressionNode.SetupNode; +var + visu: IAstVisualizer; + titleLabel: TLabel; +begin + visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1); + + BeginUpdate; + try + Frameless := False; + Orientation := loVertical; + + titleLabel := AddLabel('if'); + titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; + + // Add children + FConditionNode := visu.CallAccept(FNode.Condition); + FThenNode := visu.CallAccept(FNode.ThenBranch); + if Assigned(FNode.ElseBranch) then + FElseNode := visu.CallAccept(FNode.ElseBranch); + + finally + EndUpdate; + end; +end; + +{ TAuraTernaryExpressionNode } + +constructor TAuraTernaryExpressionNode.Create(const AVisualizer: IAstVisualizer; const ANode: ITernaryExpressionNode); +begin + inherited Create(AVisualizer); + FNode := ANode; +end; + +function TAuraTernaryExpressionNode.CreateAst: IAstNode; +begin + Result := TAst.TernaryExpr(FConditionNode.CreateAst, FThenNode.CreateAst, FElseNode.CreateAst); +end; + +procedure TAuraTernaryExpressionNode.SetupNode; +var + visu: IAstVisualizer; +begin + visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1); + + BeginUpdate; + try + Frameless := True; // Horizontal layout + Orientation := loHorizontal; + + FConditionNode := visu.CallAccept(FNode.Condition); + AddLabel('?'); + FThenNode := visu.CallAccept(FNode.ThenBranch); + AddLabel(':'); + FElseNode := visu.CallAccept(FNode.ElseBranch); + finally + EndUpdate; + end; +end; + +{ TAuraLambdaExpressionNode } + +constructor TAuraLambdaExpressionNode.Create(const AVisualizer: IAstVisualizer; const ANode: ILambdaExpressionNode); +begin + inherited Create(AVisualizer); + FNode := ANode; + FParamLabels := TList.Create; +end; + +destructor TAuraLambdaExpressionNode.Destroy; +begin + FParamLabels.Free; + inherited Destroy; +end; + +function TAuraLambdaExpressionNode.CreateAst: IAstNode; +var + params: TArray; + i: Integer; +begin + // Re-use FNode.Parameters which is the source of truth + SetLength(params, Length(FNode.Parameters)); + for i := 0 to High(FNode.Parameters) do + params[i] := TAst.Identifier(FNode.Parameters[i].Name); + + Result := TAst.LambdaExpr(params, FBodyNode.CreateAst); +end; + +procedure TAuraLambdaExpressionNode.SetupNode; +var + visu: IAstVisualizer; + titleContainer: TAutoFitControl; + paramLabel: TLabel; + i: Integer; +begin + visu := FVisualizer.Clone(Self, 0); + + BeginUpdate; + try + Frameless := False; + Orientation := loVertical; // Main node is vertical + Alignment := laFlush; + BackgroundColor := $090000ff; + + // Create a horizontal container for the title/params + titleContainer := TAutoFitControl.Create(Self); + titleContainer.Parent := Self; + titleContainer.Orientation := loHorizontal; + titleContainer.HitTest := False; // Pass clicks to parent + + // 1. Lambda Symbol Label (Title) + paramLabel := AddLabel(WideChar($03BB)); // Lambda + paramLabel.Parent := titleContainer; // Add to title container + paramLabel.Font.Style := paramLabel.Font.Style + [TFontStyle.fsBold]; + + // 2. Add Parameters + paramLabel := AddLabel('('); + paramLabel.Parent := titleContainer; + FParamLabels.Add(paramLabel); + + for i := 0 to High(FNode.Parameters) do + begin + paramLabel := AddLabel(FNode.Parameters[i].Name); + paramLabel.Parent := titleContainer; + FParamLabels.Add(paramLabel); + + if i < High(FNode.Parameters) then + begin + paramLabel := AddLabel(','); + paramLabel.Parent := titleContainer; + FParamLabels.Add(paramLabel); + end; + end; + + paramLabel := AddLabel(')'); + paramLabel.Parent := titleContainer; + FParamLabels.Add(paramLabel); + + // 3. Body + FBodyNode := visu.CallAccept(FNode.Body); + FBodyNode.Frameless := false; + + finally + EndUpdate; + end; +end; + +{ TAuraFunctionCallNode } + +constructor TAuraFunctionCallNode.Create(const AVisualizer: IAstVisualizer; const ANode: IFunctionCallNode); +begin + inherited Create(AVisualizer); + FNode := ANode; + FArgumentNodes := TList.Create; +end; + +destructor TAuraFunctionCallNode.Destroy; +begin + FArgumentNodes.Free; + inherited Destroy; +end; + +function TAuraFunctionCallNode.CreateAst: 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(FCalleeNode.CreateAst, args); +end; + +procedure TAuraFunctionCallNode.SetupNode; +var + visu: IAstVisualizer; + i: Integer; + argNode: TAuraNode; +begin + visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1); + + BeginUpdate; + try + Frameless := True; // Horizontal layout + Orientation := loHorizontal; + + var callLabel := AddLabel('call '); + callLabel.Font.Style := callLabel.Font.Style + [TFontStyle.fsBold]; + + // Callee + FCalleeNode := visu.CallAccept(FNode.Callee); + + // Arguments + if Length(FNode.Arguments) > 0 then + begin + AddLabel('('); + + for i := 0 to High(FNode.Arguments) do + begin + argNode := visu.CallAccept(FNode.Arguments[i]); + FArgumentNodes.Add(argNode); + + if i < High(FNode.Arguments) then + AddLabel(','); + end; + + AddLabel(')'); + end; + finally + EndUpdate; + end; +end; + +{ TAuraMacroExpansionNode } + +constructor TAuraMacroExpansionNode.Create(const AVisualizer: IAstVisualizer; const ANode: IMacroExpansionNode); +begin + inherited Create(AVisualizer); + FNode := ANode; +end; + +function TAuraMacroExpansionNode.CreateAst: IAstNode; +begin + // Re-create the node using the original FNode (which is an IFunctionCallNode) + // and the CreateAst of the expanded body. + Result := TAst.MacroExpansionNode(FNode, FExpandedBodyNode.CreateAst); +end; + +procedure TAuraMacroExpansionNode.SetupNode; +var + visu: IAstVisualizer; + titleLabel: TLabel; +begin + visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1); + + BeginUpdate; + try + Frameless := False; + Orientation := loVertical; + + titleLabel := AddLabel('Macro Expansion'); + titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; + + FExpandedBodyNode := visu.CallAccept(FNode.ExpandedBody); + finally + EndUpdate; + end; +end; + +{ TAuraRecurNode } + +constructor TAuraRecurNode.Create(const AVisualizer: IAstVisualizer; const ANode: IRecurNode); +begin + inherited Create(AVisualizer); + FNode := ANode; + FArgumentNodes := TList.Create; +end; + +destructor TAuraRecurNode.Destroy; +begin + FArgumentNodes.Free; + inherited Destroy; +end; + +function TAuraRecurNode.CreateAst: 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(args); +end; + +procedure TAuraRecurNode.SetupNode; +var + visu: IAstVisualizer; + i: Integer; + argNode: TAuraNode; + titleLabel: TLabel; +begin + visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1); + + BeginUpdate; + try + Frameless := True; // Horizontal layout + Orientation := loHorizontal; + + // 1. 'recur' keyword + titleLabel := AddLabel(WideChar($03BB)); + titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; + + // 2. Arguments + AddLabel('('); + + for i := 0 to High(FNode.Arguments) do + begin + argNode := visu.CallAccept(FNode.Arguments[i]); + FArgumentNodes.Add(argNode); + + if i < High(FNode.Arguments) then + AddLabel(','); + end; + + AddLabel(')'); + finally + EndUpdate; + end; +end; + +{ TAuraVariableDeclarationNode } + +constructor TAuraVariableDeclarationNode.Create(const AVisualizer: IAstVisualizer; const ANode: IVariableDeclarationNode); +begin + inherited Create(AVisualizer); + FNode := ANode; + FInitializerNode := nil; +end; + +function TAuraVariableDeclarationNode.CreateAst: IAstNode; +var + initAst: IAstNode; +begin + if Assigned(FInitializerNode) then + initAst := FInitializerNode.CreateAst + else + initAst := nil; + + // Re-create the identifier node from the original FNode + Result := TAst.VarDecl(TAst.Identifier(FNode.Identifier.Name), initAst); +end; + +procedure TAuraVariableDeclarationNode.SetupNode; +var + visu: IAstVisualizer; + varLabel: TLabel; +begin + visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1); + + BeginUpdate; + try + Frameless := True; // Horizontal layout + Orientation := loHorizontal; + + varLabel := AddLabel('var'); + varLabel.Font.Style := varLabel.Font.Style + [TFontStyle.fsBold]; + + // Add identifier name as a label + AddLabel(FNode.Identifier.Name); + + if Assigned(FNode.Initializer) then + begin + AddLabel(':='); + FInitializerNode := visu.CallAccept(FNode.Initializer); + end; + finally + EndUpdate; + end; +end; + +{ TAuraAssignmentNode } + +constructor TAuraAssignmentNode.Create(const AVisualizer: IAstVisualizer; const ANode: IAssignmentNode); +begin + inherited Create(AVisualizer); + FNode := ANode; +end; + +function TAuraAssignmentNode.CreateAst: IAstNode; +begin + // Re-create identifier from FNode + Result := TAst.Assign(TAst.Identifier(FNode.Identifier.Name), FValueNode.CreateAst); +end; + +procedure TAuraAssignmentNode.SetupNode; +var + visu: IAstVisualizer; +begin + visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1); + + BeginUpdate; + try + Frameless := True; // Horizontal layout + Orientation := loHorizontal; + + // Add identifier name as a label + AddLabel(FNode.Identifier.Name); + + AddLabel(':='); + + FValueNode := visu.CallAccept(FNode.Value); + finally + EndUpdate; + end; +end; + +{ TAuraMacroDefinitionNode } + +constructor TAuraMacroDefinitionNode.Create(const AVisualizer: IAstVisualizer; const ANode: IMacroDefinitionNode); +begin + inherited Create(AVisualizer); + FNode := ANode; +end; + +function TAuraMacroDefinitionNode.CreateAst: IAstNode; +begin + // This assumes FBodyNode will create a valid IQuasiquoteNode. + Result := + TAst.MacroDef( + TAst.Identifier(FNode.Name.Name), + FNode.Parameters, // Re-use original parameters + IQuasiquoteNode(FBodyNode.CreateAst) + ); +end; + +procedure TAuraMacroDefinitionNode.SetupNode; +var + visu: IAstVisualizer; + titleLabel: TLabel; + paramStr: string; + i: Integer; +begin + visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1); + + BeginUpdate; + try + Frameless := False; + Orientation := loVertical; + + // Build parameter string + paramStr := ''; + for i := 0 to High(FNode.Parameters) do + begin + if i > 0 then + paramStr := paramStr + ', '; + paramStr := paramStr + FNode.Parameters[i].Name; + end; + + titleLabel := AddLabel('Macro Def: ' + FNode.Name.Name + ' (' + paramStr + ')'); + titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; + + FBodyNode := visu.CallAccept(FNode.Body); + finally + EndUpdate; + end; +end; + +{ TAuraQuasiquoteNode } + +constructor TAuraQuasiquoteNode.Create(const AVisualizer: IAstVisualizer; const ANode: IQuasiquoteNode); +begin + inherited Create(AVisualizer); + FNode := ANode; +end; + +function TAuraQuasiquoteNode.CreateAst: IAstNode; +begin + Result := TAst.Quasiquote(FExpressionNode.CreateAst); +end; + +procedure TAuraQuasiquoteNode.SetupNode; +var + visu: IAstVisualizer; + titleLabel: TLabel; +begin + visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1); + BeginUpdate; + try + Frameless := False; + Orientation := loVertical; + titleLabel := AddLabel('Quasiquote'); + titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; + FExpressionNode := visu.CallAccept(FNode.Expression); + finally + EndUpdate; + end; +end; + +{ TAuraUnquoteNode } + +constructor TAuraUnquoteNode.Create(const AVisualizer: IAstVisualizer; const ANode: IUnquoteNode); +begin + inherited Create(AVisualizer); + FNode := ANode; +end; + +function TAuraUnquoteNode.CreateAst: IAstNode; +begin + Result := TAst.Unquote(FExpressionNode.CreateAst); +end; + +procedure TAuraUnquoteNode.SetupNode; +var + visu: IAstVisualizer; +begin + visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1); + BeginUpdate; + try + Frameless := True; // Horizontal layout + Orientation := loHorizontal; + + var leftBracket := AddLabel('<'); + leftBracket.Padding.Right := 0; + leftBracket.Margins.Right := 0; + + visu.CallAccept(FNode.Expression); + + var rightBracket := AddLabel('>'); + rightBracket.Padding.Left := 0; + rightBracket.Margins.Left := 0; + finally + EndUpdate; + end; +end; + +{ TAuraUnquoteSplicingNode } + +constructor TAuraUnquoteSplicingNode.Create(const AVisualizer: IAstVisualizer; const ANode: IUnquoteSplicingNode); +begin + inherited Create(AVisualizer); + FNode := ANode; +end; + +function TAuraUnquoteSplicingNode.CreateAst: IAstNode; +begin + Result := TAst.UnquoteSplicing(FExpressionNode.CreateAst); +end; + +procedure TAuraUnquoteSplicingNode.SetupNode; +var + visu: IAstVisualizer; + titleLabel: TLabel; +begin + visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1); + BeginUpdate; + try + Frameless := False; + Orientation := loVertical; + titleLabel := AddLabel('Unquote-Splicing'); + titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; + FExpressionNode := visu.CallAccept(FNode.Expression); + finally + EndUpdate; + end; +end; + +{ TAuraIndexerNode } + +constructor TAuraIndexerNode.Create(const AVisualizer: IAstVisualizer; const ANode: IIndexerNode); +begin + inherited Create(AVisualizer); + FNode := ANode; +end; + +function TAuraIndexerNode.CreateAst: IAstNode; +begin + Result := TAst.Indexer(FBaseNode.CreateAst, FIndexNode.CreateAst); +end; + +procedure TAuraIndexerNode.SetupNode; +var + visu: IAstVisualizer; +begin + visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1); + BeginUpdate; + try + Frameless := True; // Horizontal layout: Base[Index] + Orientation := loHorizontal; + + FBaseNode := visu.CallAccept(FNode.Base); + AddLabel('['); + FIndexNode := visu.CallAccept(FNode.Index); + AddLabel(']'); + finally + EndUpdate; + end; +end; + +{ TAuraMemberAccessNode } + +constructor TAuraMemberAccessNode.Create(const AVisualizer: IAstVisualizer; const ANode: IMemberAccessNode); +begin + inherited Create(AVisualizer); + FNode := ANode; +end; + +function TAuraMemberAccessNode.CreateAst: IAstNode; +begin + // Re-create identifier from FNode + Result := TAst.MemberAccess(FBaseNode.CreateAst, TAst.Identifier(FNode.Member.Name)); +end; + +procedure TAuraMemberAccessNode.SetupNode; +var + visu: IAstVisualizer; +begin + visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1); + BeginUpdate; + try + Frameless := True; // Horizontal layout: Base.Member + Orientation := loHorizontal; + + FBaseNode := visu.CallAccept(FNode.Base); + AddLabel('.'); + + // Add member name as a label + AddLabel(FNode.Member.Name); + finally + EndUpdate; + end; +end; + +{ TAuraCreateSeriesNode } + +constructor TAuraCreateSeriesNode.Create(const AVisualizer: IAstVisualizer; const ANode: ICreateSeriesNode); +begin + inherited Create(AVisualizer); + FNode := ANode; +end; + +function TAuraCreateSeriesNode.CreateAst: IAstNode; +begin + Result := TAst.CreateSeries(FNode.Definition); +end; + +procedure TAuraCreateSeriesNode.SetupNode; +var + titleLabel: TLabel; +begin + BeginUpdate; + try + Frameless := False; // Leaf node, but framed + Orientation := loVertical; + titleLabel := AddLabel('Create Series: ' + FNode.Definition); + titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; + finally + EndUpdate; + end; +end; + +{ TAuraAddSeriesItemNode } + +constructor TAuraAddSeriesItemNode.Create(const AVisualizer: IAstVisualizer; const ANode: IAddSeriesItemNode); +begin + inherited Create(AVisualizer); + FNode := ANode; + FLookbackNode := nil; +end; + +function TAuraAddSeriesItemNode.CreateAst: IAstNode; +var + lookbackAst: IAstNode; +begin + if Assigned(FLookbackNode) then + lookbackAst := FLookbackNode.CreateAst + else + lookbackAst := nil; + + Result := TAst.AddSeriesItem(TAst.Identifier(FNode.Series.Name), FValueNode.CreateAst, lookbackAst); +end; + +procedure TAuraAddSeriesItemNode.SetupNode; +var + visu: IAstVisualizer; + titleLabel: TLabel; +begin + visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1); + BeginUpdate; + try + Frameless := False; + Orientation := loVertical; + + titleLabel := AddLabel('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 + EndUpdate; + end; +end; + +{ TAuraSeriesLengthNode } + +constructor TAuraSeriesLengthNode.Create(const AVisualizer: IAstVisualizer; const ANode: ISeriesLengthNode); +begin + inherited Create(AVisualizer); + FNode := ANode; +end; + +function TAuraSeriesLengthNode.CreateAst: IAstNode; +begin + Result := TAst.SeriesLength(TAst.Identifier(FNode.Series.Name)); +end; + +procedure TAuraSeriesLengthNode.SetupNode; +var + titleLabel: TLabel; +begin + BeginUpdate; + try + Frameless := False; // Leaf node, but framed + Orientation := loVertical; + titleLabel := AddLabel('Length of: ' + FNode.Series.Name); + titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold]; + finally + EndUpdate; + end; +end; + end. diff --git a/ASTPlayground/Myc.Fmx.AstEditor.Workspace.pas b/ASTPlayground/Myc.Fmx.AstEditor.Workspace.pas index e9f818d..34026d5 100644 --- a/ASTPlayground/Myc.Fmx.AstEditor.Workspace.pas +++ b/ASTPlayground/Myc.Fmx.AstEditor.Workspace.pas @@ -91,7 +91,7 @@ implementation uses System.Math, FMX.Platform, - Myc.Fmx.AstVisualizer; + Myc.Fmx.AstEditor.Node; { TPinConnection } @@ -111,7 +111,8 @@ end; procedure TAuraWorkspace.Build(const RootNode: IAstNode; const Position: TPointF); begin - RootNode.Accept(TAstVisualizer.CreateVisitor(Self, Position)); + var visu := TAstVisualizer.Create(Self, Self, 0) as IAstVisualizer; + visu.CallAccept(RootNode); end; procedure TAuraWorkspace.DoDeleteChildren; diff --git a/ASTPlayground/Myc.Fmx.AstVisualizer.pas b/ASTPlayground/Myc.Fmx.AstVisualizer.pas index 6b1f7bf..6c6d4fd 100644 --- a/ASTPlayground/Myc.Fmx.AstVisualizer.pas +++ b/ASTPlayground/Myc.Fmx.AstVisualizer.pas @@ -1,4 +1,4 @@ -unit Myc.Fmx.AstVisualizer; +unit Myc.Fmx.AstVisualizer deprecated; interface @@ -25,14 +25,13 @@ uses type // Visits the AST and creates visual TAuraNode representations on a TAuraWorkspace. - TAstVisualizer = class(TAstVisitor) + TAstVisualizer = class(TAstVisitor, IAstVisualizer) private - FWorkspace: TAuraWorkspace; - FParentControl: TControl; // The current parent FMX control for newly created nodes - FCurrentPos: TPointF; // Current position for the next node relative to FParentControl - FNodeVerticalGap: Single; // Vertical gap between nodes + FCurrentPos: TPointF; FExprDepth: Integer; - + FWorkspace: TAuraWorkspace; + FNodeVerticalGap: Single; + FParentControl: TControl; // Helper to create and initialize a TAuraNode for a given AST node. function CreateNode(const Node: IAstNode): TAuraNode; function AddLabel(const ParentNode: TAuraNode; const Txt: String): TLabel; @@ -44,7 +43,12 @@ type // Calls Accept on the node and returns the resulting TAuraNode. function CallAccept(const Node: IAstNode): TAuraNode; - + function GetCurrentPos: TPointF; + function GetExprDepth: Integer; + function GetParentControl: TControl; + procedure SetCurrentPos(const Value: TPointF); + procedure SetExprDepth(const Value: Integer); + procedure SetParentControl(const Value: TControl); protected // Visitor implementations for each AST node type. function VisitConstant(const Node: IConstantNode): TDataValue; override; @@ -71,10 +75,22 @@ type function VisitRecurNode(const Node: IRecurNode): TDataValue; override; public - constructor Create(AWorkspace: TAuraWorkspace; AParentControl: TControl; const AStartPosition: TPointF); + constructor Create( + AWorkspace: TAuraWorkspace; + AParentControl: TControl; + const AStartPosition: TPointF; + ANodeVerticalGap: Single = 15; + AExprDepth: Integer = 0 + ); destructor Destroy; override; + function Clone: IAstVisualizer; + class function CreateVisitor(AWorkspace: TAuraWorkspace; const StartPosition: TPointF): IAstVisitor; + + property CurrentPos: TPointF read GetCurrentPos write SetCurrentPos; + property ExprDepth: Integer read GetExprDepth write SetExprDepth; + property ParentControl: TControl read GetParentControl write SetParentControl; end; implementation @@ -89,24 +105,25 @@ uses Myc.Fmx.AstEditor.Text; const - cNodePadding = 10; // Reduced padding - cTitleTopPadding = 2; - cTitleBottomPadding = 4; cChildAreaTopPadding = 5; cNodeVerticalGap = 10; // Reduced gap - cMinNodeWidth = 10; - cMinNodeHeight = 10; { TAstVisualizer } -constructor TAstVisualizer.Create(AWorkspace: TAuraWorkspace; AParentControl: TControl; const AStartPosition: TPointF); +constructor TAstVisualizer.Create( + AWorkspace: TAuraWorkspace; + AParentControl: TControl; + const AStartPosition: TPointF; + ANodeVerticalGap: Single = 15; + AExprDepth: Integer = 0 +); begin inherited Create; FWorkspace := AWorkspace; FParentControl := AParentControl; FCurrentPos := AStartPosition; - FNodeVerticalGap := 15; // Vertical gap between child nodes - FExprDepth := 0; + FNodeVerticalGap := ANodeVerticalGap; + FExprDepth := AExprDepth; end; destructor TAstVisualizer.Destroy; @@ -264,6 +281,26 @@ begin end; end; +function TAstVisualizer.Clone: IAstVisualizer; +begin + Result := TAstVisualizer.Create(FWorkspace, FParentControl, FCurrentPos, FNodeVerticalGap, FExprDepth); +end; + +function TAstVisualizer.GetCurrentPos: TPointF; +begin + Result := FCurrentPos; +end; + +function TAstVisualizer.GetExprDepth: Integer; +begin + Result := FExprDepth; +end; + +function TAstVisualizer.GetParentControl: TControl; +begin + Result := FParentControl; +end; + // Generic processing logic for AST nodes with children. Returns the created TAuraNode. function TAstVisualizer.ProcessStub(const ATitle: string; const ANode: IAstNode; const AChildren: TArray): TAuraNode; var @@ -308,157 +345,62 @@ begin Result := auraNode; // Return the created node end; +procedure TAstVisualizer.SetCurrentPos(const Value: TPointF); +begin + FCurrentPos := Value; +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): TDataValue; -var - auraNode: TAuraNode; - valueStr: string; - isConcise: Boolean; begin - valueStr := Node.Value.ToString; - // Check if it's a number or a single-line text and not excessively long - isConcise := ((Node.Value.Kind = TDataValueKind.vkScalar) or (Pos(sLineBreak, valueStr) = 0)) and (Length(valueStr) < 40); + var auraNode := TAuraConstantNode.CreateConstantNode(FWorkspace, Node, Self); - auraNode := CreateNode(Node); // Create node without title - auraNode.BeginUpdate; - try - if isConcise then - begin - // Display value directly in a centered label, frameless node - auraNode.Frameless := true; - AddLabel(auraNode, valueStr); - end - else - begin - // Use standard framed node with Title label + Value label - auraNode.Frameless := False; - - // Title Label - var titleLabelHeight := AddTitleLabel(auraNode, 'Constant'); - - // Value Label - var valueLabel := AddLabel(auraNode, valueStr); - valueLabel.Position.Y := valueLabel.Position.Y + titleLabelHeight; - valueLabel.AutoSize := False; // ***Important: Disable AutoSize when Align=Client*** - valueLabel.WordWrap := True; // Allow wrapping for long text - end; - - AdjustParentNodeSize(auraNode, []); // Adjust based on labels' sizes - finally - auraNode.EndUpdate; - end; // Move current position down for the next sibling node FCurrentPos.Y := FCurrentPos.Y + auraNode.Height + FNodeVerticalGap; + Result := TDataValue.FromGeneric(auraNode); // Return the created node end; function TAstVisualizer.VisitIdentifier(const Node: IIdentifierNode): TDataValue; var - auraNode: TAuraNode; + auraNode: TAuraIdentifierNode; // Use specific type begin - // Leaf node, direct creation without ProcessStub - auraNode := CreateNode(Node); - auraNode.Frameless := True; // Make identifiers frameless like concise constants - auraNode.BeginUpdate; - try - auraNode.Frameless := true; - AddLabel(auraNode, Node.Name); - AdjustParentNodeSize(auraNode, []); // Fallback just in case - finally - auraNode.EndUpdate; - end; + // Create the specific node type using its factory + auraNode := TAuraIdentifierNode.CreateIdentifierNode(FWorkspace, Node, Self); + + // Move current position down for the next sibling node FCurrentPos.Y := FCurrentPos.Y + auraNode.Height + FNodeVerticalGap; - Result := TDataValue.FromGeneric(auraNode); // Return the created node + + Result := TDataValue.FromGeneric(auraNode); // Return as generic TAuraNode end; function TAstVisualizer.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; var - auraNode: TAuraNode; - leftNode: TAuraNode; // Use TAuraNode directly - operatorLabel: TLabel; - rightNode: TAuraNode; // Use TAuraNode directly - savedParent: TControl; + auraNode: TAuraBinaryExpressionNode; // Use specific type savedPos: TPointF; - currentX: Single; // Track horizontal position - maxHeightInRow: Single; // Track max height for row alignment - yPos: Single; // Y position for elements in this row begin - // Create the main node, frameless as it primarily serves as a container - auraNode := CreateNode(Node); - auraNode.BeginUpdate; - inc(FExprDepth); - try - auraNode.Frameless := true; + // Store position before creating the node + savedPos := FCurrentPos; - // Start position for children inside the node - currentX := cNodePadding; - yPos := cNodePadding; // Initial Y position - maxHeightInRow := 0; + // Create the specific node type using its factory + auraNode := TAuraBinaryExpressionNode.CreateBinaryExpressionNode(FWorkspace, Node, Self); - // 1. Left Expression Node (Visited Recursively) - savedParent := FParentControl; - savedPos := FCurrentPos; // Store original position for siblings - FParentControl := auraNode; // Children are added to this node - FCurrentPos := TPointF.Create(currentX, yPos); // Set position for the child node + // Move current position down for the next sibling node + // Use the position saved *before* creating this node, plus the node's final height + FCurrentPos.Y := savedPos.Y + auraNode.Height + FNodeVerticalGap; - leftNode := CallAccept(Node.Left); // Use CallAccept and store result - - if Assigned(leftNode) then - begin - // Update currentX based on the right edge of the left control + gap - currentX := leftNode.Position.X + leftNode.Width + leftNode.Margins.Right + cNodePadding; - maxHeightInRow := Max(maxHeightInRow, leftNode.Height + leftNode.Margins.Top + leftNode.Margins.Bottom); - end; - - // 2. Operator Label - operatorLabel := AddLabel(auraNode, Node.Operator.ToString); - operatorLabel.Position.Point := TPointF.Create(currentX, yPos); // Position next to left operand - currentX := operatorLabel.Position.X + operatorLabel.Width + operatorLabel.Margins.Right + cNodePadding; // Update X pos - maxHeightInRow := Max(maxHeightInRow, operatorLabel.Height + operatorLabel.Margins.Top + operatorLabel.Margins.Bottom); - - // 3. Right Expression Node (Visited Recursively) - // FParentControl is already auraNode - FCurrentPos := TPointF.Create(currentX, yPos); // Set position for the child node - - rightNode := CallAccept(Node.Right); // Use CallAccept and store result - - if Assigned(rightNode) then - begin - // Update currentX based on the right edge of the right control - currentX := rightNode.Position.X + rightNode.Width + rightNode.Margins.Right; - maxHeightInRow := Max(maxHeightInRow, rightNode.Height + rightNode.Margins.Top + rightNode.Margins.Bottom); - end; - - FParentControl := savedParent; // Restore parent for siblings - FCurrentPos := savedPos; // Restore position for siblings - - // --- Adjust parent size --- - auraNode.Width := Max(cMinNodeWidth, currentX + cNodePadding); // Total width needed + right padding - auraNode.Height := Max(cMinNodeHeight, maxHeightInRow + 2 * cNodePadding); // Max height + top/bottom padding - - // --- Optional Vertical Centering --- - var centerOffsetY: Single := (auraNode.Height / 2); - if Assigned(leftNode) then - leftNode.Position.Y := - centerOffsetY - (leftNode.Height + leftNode.Margins.Top + leftNode.Margins.Bottom) / 2 + leftNode.Margins.Top; - if Assigned(operatorLabel) then - operatorLabel.Position.Y := - centerOffsetY - - (operatorLabel.Height + operatorLabel.Margins.Top + operatorLabel.Margins.Bottom) / 2 - + operatorLabel.Margins.Top; - if Assigned(rightNode) then - rightNode.Position.Y := - centerOffsetY - (rightNode.Height + rightNode.Margins.Top + rightNode.Margins.Bottom) / 2 + rightNode.Margins.Top; - // --- End Optional Vertical Centering --- - - finally - dec(FExprDepth); - auraNode.EndUpdate; - end; - // Move current position down for the next sibling node in the outer scope - FCurrentPos.Y := savedPos.Y + auraNode.Height + FNodeVerticalGap; // Use savedPos.Y for vertical alignment with siblings - Result := TDataValue.FromGeneric(auraNode); // Return the created node + Result := TDataValue.FromGeneric(auraNode); // Return as generic TAuraNode end; function TAstVisualizer.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; diff --git a/Src/AST/Myc.Ast.pas b/Src/AST/Myc.Ast.pas index 658ebe7..527c605 100644 --- a/Src/AST/Myc.Ast.pas +++ b/Src/AST/Myc.Ast.pas @@ -105,7 +105,7 @@ type function GetOperator: TScalar.TBinaryOp; function GetRight: IAstNode; public - constructor Create(ALeft: IAstNode; AOperator: TScalar.TBinaryOp; ARight: IAstNode); + constructor Create(const ALeft: IAstNode; AOperator: TScalar.TBinaryOp; const ARight: IAstNode); function Accept(const Visitor: IAstVisitor): TDataValue; override; end; @@ -369,7 +369,7 @@ end; { TBinaryExpressionNode } -constructor TBinaryExpressionNode.Create(ALeft: IAstNode; AOperator: TScalar.TBinaryOp; ARight: IAstNode); +constructor TBinaryExpressionNode.Create(const ALeft: IAstNode; AOperator: TScalar.TBinaryOp; const ARight: IAstNode); begin inherited Create; FLeft := ALeft; diff --git a/Src/Data/Myc.Data.Value.pas b/Src/Data/Myc.Data.Value.pas index f7fc619..fca96e2 100644 --- a/Src/Data/Myc.Data.Value.pas +++ b/Src/Data/Myc.Data.Value.pas @@ -143,7 +143,8 @@ begin if FKind <> vkGeneric then raise EInvalidCast.Create('Cannot read value as generic of ' + String(PTypeInfo(TypeInfo(T)).Name) + '.'); {$ifdef DEBUG} - if TVal(FInterface).TypeHandle <> TypeInfo(T) then + var val := TVal(FInterface); + if val.TypeHandle <> TypeInfo(T) then raise EInvalidCast.Create('Generic type is not a ' + String(PTypeInfo(TypeInfo(T)).Name) + '.'); {$endif} Result := TVal(FInterface).Value;