diff --git a/ASTPlayground/ASTPlayground.delphilsp.json b/ASTPlayground/ASTPlayground.delphilsp.json
index 83c4b49..455951b 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.Data.Keyword", "file": "file:///T%3A/Myc/Src/Data/Myc.Data.Keyword.pas" }, { "name": "Myc.Ast.Binding.Nodes", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Binding.Nodes.pas" }, { "name": "Myc.Ast.MacroExpander", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.MacroExpander.pas" }, { "name": "Myc.Ast.TypeChecker", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.TypeChecker.pas" }, { "name": "Myc.Ast.Lowering", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Lowering.pas" }, { "name": "Unit1", "file": "file:///T%3A/Myc/ASTPlayground/Unit1.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" }, { "name": "Myc.Data.Keyword", "file": "file:///T%3A/Myc/Src/Data/Myc.Data.Keyword.pas" }, { "name": "Myc.Ast.MacroExpander", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.MacroExpander.pas" }, { "name": "Myc.Ast.TypeChecker", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.TypeChecker.pas" }, { "name": "Myc.Ast.Lowering", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Lowering.pas" }, { "name": "Myc.Ast.Compiler.TCO", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.TCO.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 1a55753..3169ed2 100644
--- a/ASTPlayground/ASTPlayground.dpr
+++ b/ASTPlayground/ASTPlayground.dpr
@@ -22,7 +22,6 @@ uses
Myc.Ast.Script in '..\Src\AST\Myc.Ast.Script.pas',
Myc.Ast.Types in '..\Src\AST\Myc.Ast.Types.pas',
Myc.Data.Keyword in '..\Src\Data\Myc.Data.Keyword.pas',
- Myc.Ast.Binding.Nodes in '..\Src\AST\Myc.Ast.Binding.Nodes.pas',
Myc.Ast.MacroExpander in '..\Src\AST\Myc.Ast.MacroExpander.pas',
Myc.Ast.TypeChecker in '..\Src\AST\Myc.Ast.TypeChecker.pas',
Myc.Ast.Lowering in '..\Src\AST\Myc.Ast.Lowering.pas',
diff --git a/ASTPlayground/ASTPlayground.dproj b/ASTPlayground/ASTPlayground.dproj
index a8cef81..811aca7 100644
--- a/ASTPlayground/ASTPlayground.dproj
+++ b/ASTPlayground/ASTPlayground.dproj
@@ -152,7 +152,6 @@
-
diff --git a/ASTPlayground/MainForm.pas b/ASTPlayground/MainForm.pas
index e538b35..e2b8762 100644
--- a/ASTPlayground/MainForm.pas
+++ b/ASTPlayground/MainForm.pas
@@ -27,6 +27,7 @@ uses
Myc.Ast.Nodes,
Myc.Ast.Scope,
Myc.Ast,
+ Myc.Ast.Visitor,
Myc.Ast.Evaluator,
Myc.Ast.Dumper,
Myc.Data.Decimal,
@@ -262,7 +263,7 @@ begin
FWorkspace.Align := TAlignLayout.Client;
FWorkspace.ClipChildren := true;
FWorkspace.OnMouseDown := WorkspaceMouseDown;
-
+ {
TAst.RegisterLibrary(
procedure(const Scope: IExecutionScope)
var
@@ -356,7 +357,7 @@ begin
);
end
);
-
+ }
ClearButtonClick(Self);
end;
diff --git a/ASTPlayground/Myc.Fmx.AstEditor.Node.pas b/ASTPlayground/Myc.Fmx.AstEditor.Node.pas
index 9e7d32a..6574dfe 100644
--- a/ASTPlayground/Myc.Fmx.AstEditor.Node.pas
+++ b/ASTPlayground/Myc.Fmx.AstEditor.Node.pas
@@ -49,7 +49,8 @@ type
property Workspace: TAuraWorkspace read GetWorkspace;
end;
- TAstVisualizer = class(TAstVisitor, IAstVisualizer)
+ // Inherits from the new generic TAstVisitor
+ TAstVisualizer = class(TAstVisitor, IAstVisualizer)
private
FExprDepth: Integer;
FParentControl: TControl;
@@ -63,30 +64,30 @@ type
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 VisitKeyword(const Node: IKeywordNode): 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 VisitRecordLiteral(const Node: IRecordLiteralNode): 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;
+ function VisitConstant(const Node: IConstantNode): TAuraNode; override;
+ function VisitIdentifier(const Node: IIdentifierNode): TAuraNode; override;
+ function VisitKeyword(const Node: IKeywordNode): TAuraNode; override;
+ function VisitBinaryExpression(const Node: IBinaryExpressionNode): TAuraNode; override;
+ function VisitUnaryExpression(const Node: IUnaryExpressionNode): TAuraNode; override;
+ function VisitIfExpression(const Node: IIfExpressionNode): TAuraNode; override;
+ function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAuraNode; override;
+ function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAuraNode; override;
+ function VisitFunctionCall(const Node: IFunctionCallNode): TAuraNode; override;
+ function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TAuraNode; override;
+ function VisitBlockExpression(const Node: IBlockExpressionNode): TAuraNode; override;
+ function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAuraNode; override;
+ function VisitAssignment(const Node: IAssignmentNode): TAuraNode; override;
+ function VisitMacroDefinition(const Node: IMacroDefinitionNode): TAuraNode; override;
+ function VisitQuasiquote(const Node: IQuasiquoteNode): TAuraNode; override;
+ function VisitUnquote(const Node: IUnquoteNode): TAuraNode; override;
+ function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TAuraNode; override;
+ function VisitIndexer(const Node: IIndexerNode): TAuraNode; override;
+ function VisitMemberAccess(const Node: IMemberAccessNode): TAuraNode; override;
+ function VisitRecordLiteral(const Node: IRecordLiteralNode): TAuraNode; override;
+ function VisitCreateSeries(const Node: ICreateSeriesNode): TAuraNode; override;
+ function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAuraNode; override;
+ function VisitSeriesLength(const Node: ISeriesLengthNode): TAuraNode; override;
+ function VisitRecurNode(const Node: IRecurNode): TAuraNode; override;
public
constructor Create(AWorkspace: TAuraWorkspace; AParentControl: TControl; AExprDepth: Integer);
@@ -593,126 +594,126 @@ begin
FParentControl := Value;
end;
-function TAstVisualizer.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
+function TAstVisualizer.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraAddSeriesItemNode.Create(Self, Node));
+ Result := TAuraAddSeriesItemNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitAssignment(const Node: IAssignmentNode): TDataValue;
+function TAstVisualizer.VisitAssignment(const Node: IAssignmentNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraAssignmentNode.Create(Self, Node));
+ Result := TAuraAssignmentNode.Create(Self, Node);
end;
// --- Visitor Implementations ---
-function TAstVisualizer.VisitConstant(const Node: IConstantNode): TDataValue;
+function TAstVisualizer.VisitConstant(const Node: IConstantNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraConstantNode.Create(Self, Node));
+ Result := TAuraConstantNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitIdentifier(const Node: IIdentifierNode): TDataValue;
+function TAstVisualizer.VisitIdentifier(const Node: IIdentifierNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraIdentifierNode.Create(Self, Node));
+ Result := TAuraIdentifierNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitKeyword(const Node: IKeywordNode): TDataValue;
+function TAstVisualizer.VisitKeyword(const Node: IKeywordNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraKeywordNode.Create(Self, Node));
+ Result := TAuraKeywordNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
+function TAstVisualizer.VisitBinaryExpression(const Node: IBinaryExpressionNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraBinaryExpressionNode.Create(Self, Node));
+ Result := TAuraBinaryExpressionNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
+function TAstVisualizer.VisitBlockExpression(const Node: IBlockExpressionNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraBlockExpressionNode.Create(Self, Node));
+ Result := TAuraBlockExpressionNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
+function TAstVisualizer.VisitCreateSeries(const Node: ICreateSeriesNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraCreateSeriesNode.Create(Self, Node));
+ Result := TAuraCreateSeriesNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
+function TAstVisualizer.VisitFunctionCall(const Node: IFunctionCallNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraFunctionCallNode.Create(Self, Node));
+ Result := TAuraFunctionCallNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
+function TAstVisualizer.VisitUnaryExpression(const Node: IUnaryExpressionNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraUnaryExpressionNode.Create(Self, Node));
+ Result := TAuraUnaryExpressionNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
+function TAstVisualizer.VisitIfExpression(const Node: IIfExpressionNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraIfExpressionNode.Create(Self, Node));
+ Result := TAuraIfExpressionNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitIndexer(const Node: IIndexerNode): TDataValue;
+function TAstVisualizer.VisitIndexer(const Node: IIndexerNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraIndexerNode.Create(Self, Node));
+ Result := TAuraIndexerNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
+function TAstVisualizer.VisitLambdaExpression(const Node: ILambdaExpressionNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraLambdaExpressionNode.Create(Self, Node));
+ Result := TAuraLambdaExpressionNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
+function TAstVisualizer.VisitMacroDefinition(const Node: IMacroDefinitionNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraMacroDefinitionNode.Create(Self, Node));
+ Result := TAuraMacroDefinitionNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
+function TAstVisualizer.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraMacroExpansionNode.Create(Self, Node));
+ Result := TAuraMacroExpansionNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
+function TAstVisualizer.VisitMemberAccess(const Node: IMemberAccessNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraMemberAccessNode.Create(Self, Node));
+ Result := TAuraMemberAccessNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue;
+function TAstVisualizer.VisitRecordLiteral(const Node: IRecordLiteralNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraRecordLiteralNode.Create(Self, Node));
+ Result := TAuraRecordLiteralNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue;
+function TAstVisualizer.VisitQuasiquote(const Node: IQuasiquoteNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraQuasiquoteNode.Create(Self, Node));
+ Result := TAuraQuasiquoteNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitRecurNode(const Node: IRecurNode): TDataValue;
+function TAstVisualizer.VisitRecurNode(const Node: IRecurNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraRecurNode.Create(Self, Node));
+ Result := TAuraRecurNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
+function TAstVisualizer.VisitSeriesLength(const Node: ISeriesLengthNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraSeriesLengthNode.Create(Self, Node));
+ Result := TAuraSeriesLengthNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
+function TAstVisualizer.VisitTernaryExpression(const Node: ITernaryExpressionNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraTernaryExpressionNode.Create(Self, Node));
+ Result := TAuraTernaryExpressionNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitUnquote(const Node: IUnquoteNode): TDataValue;
+function TAstVisualizer.VisitUnquote(const Node: IUnquoteNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraUnquoteNode.Create(Self, Node));
+ Result := TAuraUnquoteNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue;
+function TAstVisualizer.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraUnquoteSplicingNode.Create(Self, Node));
+ Result := TAuraUnquoteSplicingNode.Create(Self, Node);
end;
-function TAstVisualizer.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
+function TAstVisualizer.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAuraNode;
begin
- Result := TDataValue.FromGeneric(TAuraVariableDeclarationNode.Create(Self, Node));
+ Result := TAuraVariableDeclarationNode.Create(Self, Node);
end;
{ TAutoFitControl }
@@ -1517,16 +1518,8 @@ begin
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);
+ Result := TAst.LambdaExpr(FNode.Parameters, FBodyNode.CreateAst);
end;
procedure TAuraLambdaExpressionNode.SetupNode;
@@ -1966,7 +1959,7 @@ end;
function TAuraUnquoteSplicingNode.CreateAst: IAstNode;
begin
- Result := TAst.UnquoteSplicing(FExpressionNode.CreateAst);
+ Result := TAst.UnquoteSplicing(FExpressionNode.CreateAst.AsQuasiquote);
end;
procedure TAuraUnquoteSplicingNode.SetupNode;
diff --git a/ASTPlayground/Myc.Fmx.AstEditor.Text.pas b/ASTPlayground/Myc.Fmx.AstEditor.Text.pas
index aca8548..f5db6f9 100644
--- a/ASTPlayground/Myc.Fmx.AstEditor.Text.pas
+++ b/ASTPlayground/Myc.Fmx.AstEditor.Text.pas
@@ -11,82 +11,89 @@ uses
type
// This visitor converts an AST expression subtree into a single string.
- TAstToTextVisitor = class(TAstVisitor)
- public
- 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 VisitMacroDefinition(const Node: IMacroDefinitionNode): 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 VisitIndexer(const Node: IIndexerNode): TDataValue; override;
- function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
- function VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue; override;
- function VisitUnquote(const Node: IUnquoteNode): TDataValue; override;
- function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): 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;
+ // It inherits from the generic visitor, returning a 'string' for each node.
+ TAstToTextVisitor = class(TAstVisitor)
+ protected
+ function VisitConstant(const Node: IConstantNode): string; override;
+ function VisitIdentifier(const Node: IIdentifierNode): string; override;
+ function VisitKeyword(const Node: IKeywordNode): string; override;
+ function VisitBinaryExpression(const Node: IBinaryExpressionNode): string; override;
+ function VisitUnaryExpression(const Node: IUnaryExpressionNode): string; override;
+ function VisitIfExpression(const Node: IIfExpressionNode): string; override;
+ function VisitTernaryExpression(const Node: ITernaryExpressionNode): string; override;
+ function VisitLambdaExpression(const Node: ILambdaExpressionNode): string; override;
+ function VisitMacroDefinition(const Node: IMacroDefinitionNode): string; override;
+ function VisitFunctionCall(const Node: IFunctionCallNode): string; override;
+ function VisitMacroExpansionNode(const Node: IMacroExpansionNode): string; override;
+ function VisitBlockExpression(const Node: IBlockExpressionNode): string; override;
+ function VisitVariableDeclaration(const Node: IVariableDeclarationNode): string; override;
+ function VisitAssignment(const Node: IAssignmentNode): string; override;
+ function VisitIndexer(const Node: IIndexerNode): string; override;
+ function VisitMemberAccess(const Node: IMemberAccessNode): string; override;
+ function VisitQuasiquote(const Node: IQuasiquoteNode): string; override;
+ function VisitUnquote(const Node: IUnquoteNode): string; override;
+ function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): string; override;
+ function VisitCreateSeries(const Node: ICreateSeriesNode): string; override;
+ function VisitAddSeriesItem(const Node: IAddSeriesItemNode): string; override;
+ function VisitSeriesLength(const Node: ISeriesLengthNode): string; override;
+ function VisitRecurNode(const Node: IRecurNode): string; override;
+ function VisitRecordLiteral(const Node: IRecordLiteralNode): string; override;
end;
implementation
+uses
+ System.Classes, // For TStringBuilder
+ Myc.Data.Keyword;
+
{ TAstToTextVisitor }
-function TAstToTextVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
+function TAstToTextVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): string;
var
seriesStr, valueStr, lookbackStr: string;
begin
- seriesStr := Node.Series.Accept(Self).AsText;
- valueStr := Node.Value.Accept(Self).AsText;
+ seriesStr := Accept(Node.Series);
+ valueStr := Accept(Node.Value);
lookbackStr := '';
if Assigned(Node.Lookback) then
- lookbackStr := ', ' + Node.Lookback.Accept(Self).AsText;
+ lookbackStr := ', ' + Accept(Node.Lookback);
Result := Format('%s.add(%s%s)', [seriesStr, valueStr, lookbackStr]);
end;
-function TAstToTextVisitor.VisitAssignment(const Node: IAssignmentNode): TDataValue;
+function TAstToTextVisitor.VisitAssignment(const Node: IAssignmentNode): string;
begin
- Result := Node.Identifier.Name + ' := ' + Node.Value.Accept(Self).AsText;
+ Result := Node.Identifier.Name + ' := ' + Accept(Node.Value);
end;
-function TAstToTextVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
+function TAstToTextVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): string;
begin
- var leftStr := Node.Left.Accept(Self).AsText;
- var rightStr := Node.Right.Accept(Self).AsText;
+ var leftStr := Accept(Node.Left);
+ var rightStr := Accept(Node.Right);
Result := '(' + leftStr + ' ' + Node.Operator.ToString + ' ' + rightStr + ')';
end;
-function TAstToTextVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
+function TAstToTextVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): string;
begin
Result := '{...}';
end;
-function TAstToTextVisitor.VisitConstant(const Node: IConstantNode): TDataValue;
+function TAstToTextVisitor.VisitConstant(const Node: IConstantNode): string;
begin
Result := Node.Value.ToString;
end;
-function TAstToTextVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
+function TAstToTextVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): string;
begin
Result := 'new series(' + Node.Definition + ')';
end;
-function TAstToTextVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
+function TAstToTextVisitor.VisitFunctionCall(const Node: IFunctionCallNode): string;
var
i: Integer;
sb: TStringBuilder;
calleeStr: string;
begin
- calleeStr := Node.Callee.Accept(Self).AsText;
+ calleeStr := Accept(Node.Callee);
sb := TStringBuilder.Create;
try
@@ -94,7 +101,7 @@ begin
sb.Append('(');
for i := 0 to High(Node.Arguments) do
begin
- sb.Append(Node.Arguments[i].Accept(Self).AsText);
+ sb.Append(Accept(Node.Arguments[i]));
if i < High(Node.Arguments) then
sb.Append(', ');
end;
@@ -105,7 +112,7 @@ begin
end;
end;
-function TAstToTextVisitor.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
+function TAstToTextVisitor.VisitMacroExpansionNode(const Node: IMacroExpansionNode): string;
begin
// To represent a macro expansion as a single line of text, the most
// informative representation is the original call itself. We can simply
@@ -113,7 +120,7 @@ begin
Result := VisitFunctionCall(Node);
end;
-function TAstToTextVisitor.VisitRecurNode(const Node: IRecurNode): TDataValue;
+function TAstToTextVisitor.VisitRecurNode(const Node: IRecurNode): string;
var
i: Integer;
sb: TStringBuilder;
@@ -123,7 +130,7 @@ begin
sb.Append('recur(');
for i := 0 to High(Node.Arguments) do
begin
- sb.Append(Node.Arguments[i].Accept(Self).AsText);
+ sb.Append(Accept(Node.Arguments[i]));
if i < High(Node.Arguments) then
sb.Append(', ');
end;
@@ -134,33 +141,38 @@ begin
end;
end;
-function TAstToTextVisitor.VisitIdentifier(const Node: IIdentifierNode): TDataValue;
+function TAstToTextVisitor.VisitIdentifier(const Node: IIdentifierNode): string;
begin
Result := Node.Name;
end;
-function TAstToTextVisitor.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
+function TAstToTextVisitor.VisitIfExpression(const Node: IIfExpressionNode): string;
begin
- Result := Node.Condition.Accept(Self).AsText;
+ Result := Accept(Node.Condition);
end;
-function TAstToTextVisitor.VisitIndexer(const Node: IIndexerNode): TDataValue;
+function TAstToTextVisitor.VisitIndexer(const Node: IIndexerNode): string;
var
baseStr, indexStr: string;
begin
- baseStr := Node.Base.Accept(Self).AsText;
- indexStr := Node.Index.Accept(Self).AsText;
+ baseStr := Accept(Node.Base);
+ indexStr := Accept(Node.Index);
Result := Format('%s[%s]', [baseStr, indexStr]);
end;
-function TAstToTextVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
+function TAstToTextVisitor.VisitKeyword(const Node: IKeywordNode): string;
+begin
+ Result := ':' + Node.Value.Name;
+end;
+
+function TAstToTextVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): string;
var
i: Integer;
sb: TStringBuilder;
begin
sb := TStringBuilder.Create;
try
- sb.Append(#$03BB + '(');
+ sb.Append(WideChar($03BB) + '('); // Lambda char
if Length(Node.Parameters) > 0 then
begin
for i := 0 to High(Node.Parameters) do
@@ -177,7 +189,7 @@ begin
end;
end;
-function TAstToTextVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
+function TAstToTextVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): string;
var
i: Integer;
sb: TStringBuilder;
@@ -204,56 +216,61 @@ begin
end;
end;
-function TAstToTextVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
+function TAstToTextVisitor.VisitMemberAccess(const Node: IMemberAccessNode): string;
var
baseStr: string;
begin
- baseStr := Node.Base.Accept(Self).AsText;
+ baseStr := Accept(Node.Base);
Result := Format('%s.%s', [baseStr, Node.Member.Value.Name]);
end;
-function TAstToTextVisitor.VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue;
+function TAstToTextVisitor.VisitQuasiquote(const Node: IQuasiquoteNode): string;
begin
- Result := '`' + Node.Expression.Accept(Self).AsText;
+ Result := '`' + Accept(Node.Expression);
end;
-function TAstToTextVisitor.VisitUnquote(const Node: IUnquoteNode): TDataValue;
+function TAstToTextVisitor.VisitRecordLiteral(const Node: IRecordLiteralNode): string;
begin
- Result := '~' + Node.Expression.Accept(Self).AsText;
+ Result := '{...}';
end;
-function TAstToTextVisitor.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue;
+function TAstToTextVisitor.VisitUnquote(const Node: IUnquoteNode): string;
begin
- Result := '~@' + Node.Expression.Accept(Self).AsText;
+ Result := '~' + Accept(Node.Expression);
end;
-function TAstToTextVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
+function TAstToTextVisitor.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): string;
+begin
+ Result := '~@' + Accept(Node.Expression);
+end;
+
+function TAstToTextVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): string;
var
seriesStr: string;
begin
- seriesStr := Node.Series.Accept(Self).AsText;
+ seriesStr := Accept(Node.Series);
Result := Format('length(%s)', [seriesStr]);
end;
-function TAstToTextVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
+function TAstToTextVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): string;
begin
- var condStr := Node.Condition.Accept(Self).AsText;
- var thenStr := Node.ThenBranch.Accept(Self).AsText;
- var elseStr := Node.ElseBranch.Accept(Self).AsText;
+ var condStr := Accept(Node.Condition);
+ var thenStr := Accept(Node.ThenBranch);
+ var elseStr := Accept(Node.ElseBranch);
Result := Format('(%s ? %s : %s)', [condStr, thenStr, elseStr]);
end;
-function TAstToTextVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
+function TAstToTextVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): string;
begin
- Result := Node.Operator.ToString + ' ' + Node.Right.Accept(Self).AsText;
+ Result := Node.Operator.ToString + ' ' + Accept(Node.Right);
end;
-function TAstToTextVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
+function TAstToTextVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): string;
var
initStr: string;
begin
if Assigned(Node.Initializer) then
- initStr := ' := ' + Node.Initializer.Accept(Self).AsText
+ initStr := ' := ' + Accept(Node.Initializer)
else
initStr := '';
Result := 'var ' + Node.Identifier.Name + initStr;
diff --git a/Src/AST/Myc.Ast.Analyzer.pas b/Src/AST/Myc.Ast.Analyzer.pas
index d45c8ef..a63406d 100644
--- a/Src/AST/Myc.Ast.Analyzer.pas
+++ b/Src/AST/Myc.Ast.Analyzer.pas
@@ -9,7 +9,8 @@ uses
Myc.Ast.Nodes,
Myc.Ast.Visitor,
Myc.Ast.Scope,
- Myc.Data.Value;
+ Myc.Data.Value,
+ Myc.Ast;
type
// This visitor analyzes the AST to find all variables that need to be "lifted" or "boxed"
@@ -17,23 +18,28 @@ type
TUpvalueAnalyzer = class(TAstTransformer)
private
FBoxedDeclarations: THashSet;
- FCurrentScope: IScopeDescriptor;
+ FCurrentDescriptor: IScopeDescriptor;
FDeclarationMap: TDictionary>;
procedure MarkDeclarationForBoxing(const AName: string);
protected
// Overridden Visit methods to perform analysis during traversal.
- function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
- function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
- function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
+ function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override;
+ function VisitIdentifier(const Node: IIdentifierNode): IAstNode; override;
+ function VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode; override;
public
constructor Create(const AParent: IScopeDescriptor);
destructor Destroy; override;
+
+ // Added Execute method
+ function Execute(const ARootNode: IAstNode): IAstNode;
+
class function Analyze(const ARootNode: IAstNode; const AParent: IScopeDescriptor): THashSet; static;
end;
implementation
uses
+ System.Generics.Defaults,
Myc.Ast.Types;
{ TUpvalueAnalyzer }
@@ -42,22 +48,28 @@ constructor TUpvalueAnalyzer.Create(const AParent: IScopeDescriptor);
begin
inherited Create;
FBoxedDeclarations := THashSet.Create;
- FDeclarationMap := TDictionary>.Create;
- FCurrentScope := TScope.CreateDescriptor(AParent);
+ FDeclarationMap :=
+ TObjectDictionary>
+ .Create([doOwnsValues], TEqualityComparer.Default);
+ FCurrentDescriptor := TScope.CreateDescriptor(AParent);
end;
destructor TUpvalueAnalyzer.Destroy;
begin
- for var dict in FDeclarationMap.Values do
- dict.Free;
FDeclarationMap.Free;
FBoxedDeclarations.Free;
inherited Destroy;
end;
+function TUpvalueAnalyzer.Execute(const ARootNode: IAstNode): IAstNode;
+begin
+ // Accept will call the Visit... methods and traverse the tree
+ Result := Accept(ARootNode);
+end;
+
class function TUpvalueAnalyzer.Analyze(const ARootNode: IAstNode; const AParent: IScopeDescriptor): THashSet;
var
- analyzer: TUpvalueAnalyzer;
+ analyzer: TUpvalueAnalyzer; // Changed to concrete type
begin
if not Assigned(ARootNode) then
exit(THashSet.Create);
@@ -78,12 +90,12 @@ var
declarationScope: IScopeDescriptor;
i: Integer;
begin
- symbol := FCurrentScope.FindSymbol(AName);
+ symbol := FCurrentDescriptor.FindSymbol(AName);
if symbol.Address.Kind <> akLocalOrParent then
exit;
// Walk up the scope chain to find the scope where the variable was declared.
- declarationScope := FCurrentScope;
+ declarationScope := FCurrentDescriptor;
for i := 1 to symbol.Address.ScopeDepth do
begin
if not Assigned(declarationScope.Parent) then
@@ -101,13 +113,13 @@ begin
end;
end;
-function TUpvalueAnalyzer.VisitIdentifier(const Node: IIdentifierNode): TDataValue;
+function TUpvalueAnalyzer.VisitIdentifier(const Node: IIdentifierNode): IAstNode;
var
symbol: TResolvedSymbol;
begin
- if Assigned(FCurrentScope) then
+ if Assigned(FCurrentDescriptor) then
begin
- symbol := FCurrentScope.FindSymbol(Node.Name);
+ symbol := FCurrentDescriptor.FindSymbol(Node.Name);
if (symbol.Address.Kind = akLocalOrParent) and (symbol.Address.ScopeDepth > 0) then
begin
@@ -116,54 +128,62 @@ begin
end;
end;
- // As a traverser, return the original node wrapped in a TDataValue.
- Result := TDataValue.FromIntf(Node);
+ // This is a leaf node, do not call inherited.
+ Result := Node;
end;
-function TUpvalueAnalyzer.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
+function TUpvalueAnalyzer.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
+var
+ N: TLambdaExpressionNode;
begin
+ N := (Node as TLambdaExpressionNode);
+
// A lambda creates a new lexical scope, inheriting from the current one.
- FCurrentScope := TScope.CreateDescriptor(FCurrentScope);
+ FCurrentDescriptor := TScope.CreateDescriptor(FCurrentDescriptor);
try
// Define the lambda's parameters within its new scope.
// We use TTypes.Unknown as type inference hasn't run yet.
- for var param in Node.Parameters do
- FCurrentScope.Define(param.Name, TTypes.Unknown);
+ for var param in N.Parameters do
+ FCurrentDescriptor.Define(Accept(param).AsIdentifier.Name, TTypes.Unknown);
// Traverse the lambda body within the new scope context.
- Node.Body.Accept(Self);
+ N.Body := Accept(N.Body); // Manual traversal
- // We do not transform, just analyze. Return the original node wrapped.
- Result := TDataValue.FromIntf(Node);
+ Result := N;
finally
// Restore the parent scope after leaving the lambda.
- FCurrentScope := FCurrentScope.Parent;
+ FCurrentDescriptor := FCurrentDescriptor.Parent;
end;
end;
-function TUpvalueAnalyzer.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
+function TUpvalueAnalyzer.VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode;
var
scopeDeclarations: TDictionary;
+ N: TVariableDeclarationNode;
begin
+ N := (Node as TVariableDeclarationNode);
+
// Traverse the initializer first. It's evaluated in the current scope
// before the new variable is defined.
- if Assigned(Node.Initializer) then
- Node.Initializer.Accept(Self);
+ if Assigned(N.Initializer) then
+ N.Initializer := Accept(N.Initializer);
+
+ // Traverse the identifier
+ Accept(N.Identifier);
// After processing the initializer, define the variable in the current scope.
// We use TTypes.Unknown as type inference hasn't run yet.
- FCurrentScope.Define(Node.Identifier.Name, TTypes.Unknown);
+ FCurrentDescriptor.Define(N.Identifier.Name, TTypes.Unknown);
// Map this declaration node to its scope and name for later lookup.
- if not FDeclarationMap.TryGetValue(FCurrentScope, scopeDeclarations) then
+ if not FDeclarationMap.TryGetValue(FCurrentDescriptor, scopeDeclarations) then
begin
scopeDeclarations := TDictionary.Create;
- FDeclarationMap.Add(FCurrentScope, scopeDeclarations);
+ FDeclarationMap.Add(FCurrentDescriptor, scopeDeclarations);
end;
- scopeDeclarations.Add(Node.Identifier.Name, Node);
+ scopeDeclarations.Add(N.Identifier.Name, N);
- // As a traverser, return the original node wrapped in a TDataValue.
- Result := TDataValue.FromIntf(Node);
+ Result := N;
end;
end.
diff --git a/Src/AST/Myc.Ast.Binding.Nodes.pas b/Src/AST/Myc.Ast.Binding.Nodes.pas
deleted file mode 100644
index c594b9e..0000000
--- a/Src/AST/Myc.Ast.Binding.Nodes.pas
+++ /dev/null
@@ -1,144 +0,0 @@
-unit Myc.Ast.Binding.Nodes;
-
-interface
-
-uses
- System.SysUtils,
- System.Classes,
- System.Generics.Collections,
- Myc.Data.Scalar,
- Myc.Data.Value,
- Myc.Ast.Nodes,
- Myc.Ast.Visitor,
- Myc.Ast.Scope,
- Myc.Ast.Types,
- Myc.Ast;
-
-type
- TBoundIdentifierNode = class(TIdentifierNode)
- private
- FAddress: TResolvedAddress;
- public
- constructor Create(const AUnboundNode: IIdentifierNode; const AAddress: TResolvedAddress);
- property Address: TResolvedAddress read FAddress;
- end;
-
- TBoundVariableDeclarationNode = class(TVariableDeclarationNode)
- private
- FIsBoxed: Boolean;
- public
- constructor Create(const AIdentifier: IIdentifierNode; AInitializer: IAstNode; AIsBoxed: Boolean);
- property IsBoxed: Boolean read FIsBoxed;
- end;
-
- TBoundLambdaExpressionNode = class(TLambdaExpressionNode)
- private
- FScopeDescriptor: IScopeDescriptor;
- FUpvalues: TArray;
- FHasNestedLambdas: Boolean;
- public
- constructor Create(
- const AUnboundNode: ILambdaExpressionNode;
- const ABody: IAstNode;
- const AParameters: TArray;
- const AScopeDescriptor: IScopeDescriptor;
- const AUpvalues: TArray;
- AHasNestedLambdas: Boolean
- );
- property ScopeDescriptor: IScopeDescriptor read FScopeDescriptor;
- property Upvalues: TArray read FUpvalues;
- property HasNestedLambdas: Boolean read FHasNestedLambdas;
- end;
-
- TBoundFunctionCallNode = class(TFunctionCallNode)
- private
- FIsTailCall: Boolean;
- public
- constructor Create(
- const AUnboundNode: IFunctionCallNode;
- const ACallee: IAstNode;
- const AArguments: TArray;
- AIsTailCall: Boolean
- );
- property IsTailCall: Boolean read FIsTailCall;
- end;
-
- TBoundRecordLiteralNode = class(TRecordLiteralNode)
- private
- FDefinition: IScalarRecordDefinition;
- public
- constructor Create(const AFields: TArray; const ADef: IScalarRecordDefinition);
- property Definition: IScalarRecordDefinition read FDefinition write FDefinition;
- end;
-
- // Represents a bound record literal that maps to a generic (non-scalar) record
- TBoundGenericRecordLiteralNode = class(TRecordLiteralNode)
- private
- FDefinition: IGenericRecordDefinition;
- public
- constructor Create(const AFields: TArray; const ADef: IGenericRecordDefinition);
- property Definition: IGenericRecordDefinition read FDefinition write FDefinition;
- end;
-
-implementation
-
-uses
- Myc.Data.Keyword;
-
-{ TBoundIdentifierNode }
-constructor TBoundIdentifierNode.Create(const AUnboundNode: IIdentifierNode; const AAddress: TResolvedAddress);
-begin
- inherited Create(AUnboundNode.Name);
- FAddress := AAddress;
-end;
-
-{ TBoundVariableDeclarationNode }
-constructor TBoundVariableDeclarationNode.Create(const AIdentifier: IIdentifierNode; AInitializer: IAstNode; AIsBoxed: Boolean);
-begin
- inherited Create(AIdentifier, AInitializer);
- FIsBoxed := AIsBoxed;
-end;
-
-{ TBoundLambdaExpressionNode }
-constructor TBoundLambdaExpressionNode.Create(
- const AUnboundNode: ILambdaExpressionNode;
- const ABody: IAstNode;
- const AParameters: TArray;
- const AScopeDescriptor: IScopeDescriptor;
- const AUpvalues: TArray;
- AHasNestedLambdas: Boolean
-);
-begin
- inherited Create(AParameters, ABody);
- FScopeDescriptor := AScopeDescriptor;
- FUpvalues := AUpvalues;
- FHasNestedLambdas := AHasNestedLambdas;
-end;
-
-{ TBoundFunctionCallNode }
-constructor TBoundFunctionCallNode.Create(
- const AUnboundNode: IFunctionCallNode;
- const ACallee: IAstNode;
- const AArguments: TArray;
- AIsTailCall: Boolean
-);
-begin
- inherited Create(ACallee, AArguments);
- FIsTailCall := AIsTailCall;
-end;
-
-{ TBoundGenericRecordLiteralNode }
-constructor TBoundGenericRecordLiteralNode.Create(const AFields: TArray; const ADef: IGenericRecordDefinition);
-begin
- inherited Create(AFields);
- FDefinition := ADef;
-end;
-
-{ TBoundRecordLiteralNode }
-constructor TBoundRecordLiteralNode.Create(const AFields: TArray; const ADef: IScalarRecordDefinition);
-begin
- inherited Create(AFields);
- FDefinition := ADef;
-end;
-
-end.
diff --git a/Src/AST/Myc.Ast.Binding.pas b/Src/AST/Myc.Ast.Binding.pas
index 721476c..b052954 100644
--- a/Src/AST/Myc.Ast.Binding.pas
+++ b/Src/AST/Myc.Ast.Binding.pas
@@ -36,30 +36,24 @@ type
procedure EnterScope;
procedure ExitScope;
function IsValidIdentifier(const Name: string): Boolean;
- function SetType(const NodeData: TDataValue; const AType: IStaticType): TDataValue; overload;
protected
- function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
- function VisitKeyword(const Node: IKeywordNode): TDataValue; override;
- function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
- function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
- function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
- function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override;
- function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
- function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue; override;
- function VisitRecurNode(const Node: IRecurNode): TDataValue; override;
- function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
- function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
- function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
- function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; override;
- function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; override;
- function VisitConstant(const Node: IConstantNode): TDataValue; override;
- function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
- function VisitIndexer(const Node: IIndexerNode): TDataValue; override;
- function VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue; override;
- function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override;
- function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; override;
- function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override;
+ // --- Core Binding Logic (Mutators) ---
+ function VisitIdentifier(const Node: IIdentifierNode): IAstNode; override;
+ function VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode; override;
+ function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override;
+ // --- Transformation Logic ---
+ function VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; override;
+
+ // --- Standard Traversal (Use inherited) ---
+ function VisitKeyword(const Node: IKeywordNode): IAstNode; override;
+ function VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode; override;
+ function VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode; override;
+ function VisitRecurNode(const Node: IRecurNode): IAstNode; override;
+ function VisitConstant(const Node: IConstantNode): IAstNode; override;
+ function VisitCreateSeries(const Node: ICreateSeriesNode): IAstNode; override;
+ function VisitAddSeriesItem(const Node: IAddSeriesItemNode): IAstNode; override;
+ function VisitSeriesLength(const Node: ISeriesLengthNode): IAstNode; override;
public
constructor Create(const AInitialScope: IExecutionScope);
@@ -78,8 +72,7 @@ implementation
uses
System.Generics.Defaults,
System.Character,
- Myc.Data.Keyword,
- Myc.Ast.Binding.Nodes;
+ Myc.Data.Keyword;
type
TResolvedAddressComparer = class(TEqualityComparer)
@@ -111,7 +104,7 @@ begin
FInitialScope := AInitialScope;
FCurrentDescriptor := AInitialScope.CreateDescriptor;
- FUpvalueStack := TObjectStack.Create(True);
+ FUpvalueStack := TObjectStack.Create(True); // Use Comparer
FNestedLambdaCount := 0;
FBoxedDeclarations := nil;
end;
@@ -123,13 +116,6 @@ begin
inherited;
end;
-function TAstBinder.SetType(const NodeData: TDataValue; const AType: IStaticType): TDataValue;
-begin
- if (not NodeData.IsVoid) and (NodeData.Kind = vkInterface) then
- (NodeData.AsIntf as TAstNode).StaticType := AType;
- Result := NodeData;
-end;
-
class function TAstBinder.Bind(const InitialScope: IExecutionScope; const RootNode: IAstNode; out Descriptor: IScopeDescriptor): IAstNode;
begin
var binder := TAstBinder.Create(InitialScope) as IAstBinder;
@@ -165,40 +151,42 @@ end;
function TAstBinder.Execute(const RootNode: IAstNode; out Descriptor: IScopeDescriptor): IAstNode;
begin
+ // Pre-pass: Find all variables that need boxing
FBoxedDeclarations := TUpvalueAnalyzer.Analyze(RootNode, FCurrentDescriptor.Parent);
try
EnterScope;
try
- var transformedValue := Accept(RootNode);
- if transformedValue.IsVoid then
- Result := TAst.Block([])
- else
- Result := transformedValue.AsIntf;
+ // Main pass: Run the mutator
+ Result := Accept(RootNode); // Accept returns IAstNode
+ if not Assigned(Result) then
+ Result := TAst.Block([]);
+ // Set the type of the root expression (e.g., the final 'do' block)
(Result as TAstNode).StaticType := TTypes.Unknown;
Descriptor := FCurrentDescriptor;
finally
ExitScope;
end;
finally
+ FBoxedDeclarations.Free; // Free the set
+ FBoxedDeclarations := nil;
end;
end;
-function TAstBinder.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
+function TAstBinder.VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode;
begin
+ // Macros are compile-time only. The Binder (Phase 2) should not see them.
raise Exception.Create('TMyAstBinder: MacroDefinition node encountered.');
end;
-function TAstBinder.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
+function TAstBinder.VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode;
begin
+ // The MacroExpander (Phase 1) should have unwrapped this.
+ // We only visit the *expanded* body.
Result := Accept(Node.ExpandedBody);
end;
-function TAstBinder.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
-var
- boundCall: TBoundFunctionCallNode;
- callee: IAstNode;
- args: TArray;
+function TAstBinder.VisitFunctionCall(const Node: IFunctionCallNode): IAstNode;
begin
// --- Transformation: Keyword-as-Function ---
if (Node.Callee is TKeywordNode) then
@@ -209,105 +197,44 @@ begin
'Keyword :%s expects exactly one argument (the record/map), but got %d',
[keywordNode.Value.Name, Length(Node.Arguments)]);
- var baseNode := Accept(Node.Arguments[0]).AsIntf;
+ // Manually visit the argument, as we are replacing this node
+ var baseNode := Accept(Node.Arguments[0]);
var memberAccessNode := TAst.MemberAccess(baseNode, keywordNode);
+ // Visit the *new* node to bind it
Result := Accept(memberAccessNode);
exit;
end;
// --- Default: Bind as a standard function call ---
- callee := Accept(Node.Callee).AsIntf;
- args := AcceptNodes(Node.Arguments);
+ // Use the inherited implementation to visit children (Callee, Arguments)
+ // and mutate their properties in place.
+ Result := inherited VisitFunctionCall(Node);
- // Create the node, always marking IsTailCall as false.
- // The Lowerer (Phase 4) will set this flag correctly.
- boundCall := TBoundFunctionCallNode.Create(Node, callee, args, False);
-
- Result := SetType(TDataValue.FromIntf(boundCall), TTypes.Unknown);
+ // Set metadata for *this* node
+ (Node as TFunctionCallNode).IsTailCall := False; // Default, TCO (Phase 5) will set this
end;
-function TAstBinder.VisitAssignment(const Node: IAssignmentNode): TDataValue;
-var
- boundIdentifier, boundValue: IAstNode;
- boundNode: IAssignmentNode;
-begin
- boundIdentifier := Accept(Node.Identifier).AsIntf;
- boundValue := Accept(Node.Value).AsIntf;
- boundNode := TAst.Assign(boundIdentifier as TBoundIdentifierNode, boundValue);
- Result := SetType(TDataValue.FromIntf(boundNode), TTypes.Unknown);
-end;
-
-function TAstBinder.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
-var
- left, right: IAstNode;
- boundNode: IBinaryExpressionNode;
-begin
- left := Accept(Node.Left).AsIntf;
- right := Accept(Node.Right).AsIntf;
- boundNode := TAst.BinaryExpr(left, Node.Operator, right);
- Result := SetType(TDataValue.FromIntf(boundNode), TTypes.Unknown);
-end;
-
-function TAstBinder.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
-var
- exprs: TArray;
- i: Integer;
- transformedValue: TDataValue;
- exprList: TList;
- boundNode: IBlockExpressionNode;
-begin
- exprList := TList.Create;
- try
- for i := 0 to High(Node.Expressions) do
- begin
- transformedValue := Accept(Node.Expressions[i]);
- if not transformedValue.IsVoid then
- exprList.Add(transformedValue.AsIntf);
- end;
- exprs := exprList.ToArray;
- finally
- exprList.Free;
- end;
-
- if (Length(exprs) = Length(Node.Expressions)) then
- begin
- var same := True;
- for i := 0 to High(exprs) do
- if exprs[i] <> Node.Expressions[i] then
- begin
- same := False;
- break;
- end;
- if same then
- boundNode := Node
- else
- boundNode := TAst.Block(exprs);
- end
- else
- boundNode := TAst.Block(exprs);
-
- Result := SetType(TDataValue.FromIntf(boundNode), TTypes.Unknown);
-end;
-
-function TAstBinder.VisitConstant(const Node: IConstantNode): TDataValue;
+function TAstBinder.VisitConstant(const Node: IConstantNode): IAstNode;
begin
+ // Set type (Phase 3)
case Node.Value.Kind of
- TDataValueKind.vkScalar:
- Result := SetType(TDataValue.FromIntf(Node), TTypes.FromScalarKind(Node.Value.AsScalar.Kind));
- TDataValueKind.vkText: Result := SetType(TDataValue.FromIntf(Node), TTypes.Text);
- TDataValueKind.vkVoid: Result := SetType(TDataValue.FromIntf(Node), TTypes.Void);
+ TDataValueKind.vkScalar: (Node as TAstNode).StaticType := TTypes.FromScalarKind(Node.Value.AsScalar.Kind);
+ TDataValueKind.vkText: (Node as TAstNode).StaticType := TTypes.Text;
+ TDataValueKind.vkVoid: (Node as TAstNode).StaticType := TTypes.Void;
else
- Result := SetType(TDataValue.FromIntf(Node), TTypes.Unknown);
+ (Node as TAstNode).StaticType := TTypes.Unknown;
end;
+ Result := Node;
end;
-function TAstBinder.VisitKeyword(const Node: IKeywordNode): TDataValue;
+function TAstBinder.VisitKeyword(const Node: IKeywordNode): IAstNode;
begin
- Result := SetType(TDataValue.FromIntf(Node), TTypes.Keyword);
+ (Node as TAstNode).StaticType := TTypes.Keyword;
+ Result := Node;
end;
-function TAstBinder.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
+function TAstBinder.VisitCreateSeries(const Node: ICreateSeriesNode): IAstNode;
var
elemType: IStaticType;
begin
@@ -317,197 +244,100 @@ begin
on E: Exception do
elemType := TTypes.Unknown;
end;
- Result := SetType(TDataValue.FromIntf(Node), TTypes.CreateSeries(elemType));
+ (Node as TAstNode).StaticType := TTypes.CreateSeries(elemType);
+ Result := Node;
end;
-function TAstBinder.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
-var
- seriesNode, valueNode, lookbackNode: IAstNode;
+function TAstBinder.VisitAddSeriesItem(const Node: IAddSeriesItemNode): IAstNode;
begin
- seriesNode := Accept(Node.Series).AsIntf;
- valueNode := Accept(Node.Value).AsIntf;
- if Node.Lookback <> nil then
- lookbackNode := Accept(Node.Lookback).AsIntf
- else
- lookbackNode := nil;
-
- var boundNode := TAst.AddSeriesItem(seriesNode as TIdentifierNode, valueNode, lookbackNode);
- Result := SetType(TDataValue.FromIntf(boundNode), TTypes.Void);
+ // Visit children
+ Result := inherited VisitAddSeriesItem(Node);
+ (Node as TAstNode).StaticType := TTypes.Void;
end;
-function TAstBinder.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
+function TAstBinder.VisitSeriesLength(const Node: ISeriesLengthNode): IAstNode;
begin
- Accept(Node.Series);
- Result := SetType(TDataValue.FromIntf(Node), TTypes.Ordinal);
+ // Visit children
+ Result := inherited VisitSeriesLength(Node);
+ (Node as TAstNode).StaticType := TTypes.Ordinal;
end;
-function TAstBinder.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
-var
- condition, thenBranch, elseBranch: IAstNode;
- boundNode: IIfExpressionNode;
-begin
- condition := Accept(Node.Condition).AsIntf;
- thenBranch := Accept(Node.ThenBranch).AsIntf;
- if Assigned(Node.ElseBranch) then
- elseBranch := Accept(Node.ElseBranch).AsIntf
- else
- elseBranch := nil;
-
- if (condition <> Node.Condition) or (thenBranch <> Node.ThenBranch) or (elseBranch <> Node.ElseBranch) then
- boundNode := TAst.IfExpr(condition, thenBranch, elseBranch)
- else
- boundNode := Node;
-
- Result := SetType(TDataValue.FromIntf(boundNode), TTypes.Unknown);
-end;
-
-function TAstBinder.VisitIndexer(const Node: IIndexerNode): TDataValue;
-var
- baseNode, indexNode: IAstNode;
- boundNode: IIndexerNode;
-begin
- baseNode := Accept(Node.Base).AsIntf;
- indexNode := Accept(Node.Index).AsIntf;
- boundNode := TAst.Indexer(baseNode, indexNode);
- Result := SetType(TDataValue.FromIntf(boundNode), TTypes.Unknown);
-end;
-
-function TAstBinder.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
-var
- baseNode: IAstNode;
- boundNode: IMemberAccessNode;
-begin
- baseNode := Accept(Node.Base).AsIntf;
- boundNode := TAst.MemberAccess(baseNode, Node.Member);
- Result := SetType(TDataValue.FromIntf(boundNode), TTypes.Unknown);
-end;
-
-function TAstBinder.VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue;
-var
- i: Integer;
- boundFields: TArray;
- valNode: IAstNode;
- valType: IStaticType;
- allScalar: Boolean;
-begin
- SetLength(boundFields, Length(Node.Fields));
- allScalar := True;
-
- for i := 0 to High(Node.Fields) do
- begin
- valNode := Accept(Node.Fields[i].Value).AsIntf;
- valType := (valNode as TAstNode).StaticType;
-
- if not (valType.Kind in [stOrdinal, stFloat, stKeyword, stUnknown]) then
- allScalar := False;
-
- boundFields[i] := TRecordFieldLiteral.Create(Node.Fields[i].Key, valNode);
- end;
-
- if allScalar then
- begin
- var boundNode := TBoundRecordLiteralNode.Create(boundFields, nil);
- Result := SetType(TDataValue.FromIntf(boundNode), TTypes.Unknown);
- end
- else
- begin
- var genBoundNode := TBoundGenericRecordLiteralNode.Create(boundFields, nil);
- Result := SetType(TDataValue.FromIntf(genBoundNode), TTypes.Unknown);
- end;
-end;
-
-function TAstBinder.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
+function TAstBinder.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
var
i: integer;
- boundParams: TArray;
- boundBody: IAstNode;
- lambdaScope: IScopeDescriptor;
- upvalues: TArray;
- hasNestedLambdas: Boolean;
- lastNestedLambdaCount: Integer;
- boundLambda: ILambdaExpressionNode;
+ N: TLambdaExpressionNode;
+ adr: TResolvedAddress;
begin
+ N := (Node as TLambdaExpressionNode);
+
+ // We do *not* call inherited, as we must manage the scope manually.
+
FUpvalueStack.Push(TUpvalueMapping.Create(TResolvedAddressComparer.Create));
try
EnterScope;
try
+ // Define (slot 0)
FCurrentDescriptor.Define('', TTypes.Unknown);
- SetLength(boundParams, Length(Node.Parameters));
- for i := 0 to High(Node.Parameters) do
+ // Define parameters
+ for i := 0 to High(N.Parameters) do
begin
- var paramNode := Node.Parameters[i];
+ var paramNode := N.Parameters[i];
var slotIndex := FCurrentDescriptor.Define(paramNode.Name, TTypes.Unknown);
- var address := TResolvedAddress.Create(akLocalOrParent, 0, slotIndex);
- boundParams[i] := TBoundIdentifierNode.Create(paramNode, address);
- (boundParams[i] as TAstNode).StaticType := TTypes.Unknown;
+ adr := TResolvedAddress.Create(akLocalOrParent, 0, slotIndex);
+
+ // Mutate the parameter node with its address
+ (paramNode as TIdentifierNode).Address := adr;
+ (paramNode as TAstNode).StaticType := TTypes.Unknown;
end;
- lastNestedLambdaCount := FNestedLambdaCount;
- boundBody := Accept(Node.Body).AsIntf;
- hasNestedLambdas := FNestedLambdaCount > lastNestedLambdaCount;
- lambdaScope := FCurrentDescriptor;
+ // Visit the body *within the new scope*
+ var lastNestedLambdaCount := FNestedLambdaCount;
+ N.Body := Accept(N.Body);
+ N.HasNestedLambdas := FNestedLambdaCount > lastNestedLambdaCount;
+
+ // Save the descriptor for the evaluator
+ N.ScopeDescriptor := FCurrentDescriptor;
finally
ExitScope;
end;
+ // --- Extract Upvalues ---
var upvalueMapping := FUpvalueStack.Peek;
var sortedPairs := upvalueMapping.ToArray;
+ // Sort by index (Value)
TArray.Sort>(
sortedPairs,
TComparer>.Construct(
function(const Left, Right: TPair): Integer begin Result := Left.Value - Right.Value; end
)
);
- SetLength(upvalues, Length(sortedPairs));
- for i := 0 to High(sortedPairs) do
- upvalues[i] := sortedPairs[i].Key;
+
+ var uvArr: TArray;
+ SetLength(uvArr, Length(sortedPairs));
+ for i := 0 to High(uvArr) do
+ uvArr[i] := sortedPairs[i].Key;
+ N.Upvalues := uvArr;
+
finally
FUpvalueStack.Pop;
end;
inc(FNestedLambdaCount);
- boundLambda := TBoundLambdaExpressionNode.Create(Node, boundBody, boundParams, lambdaScope, upvalues, hasNestedLambdas);
- Result := SetType(TDataValue.FromIntf(boundLambda), TTypes.Unknown);
+ // Type will be set by TypeChecker
+ Result := Node;
end;
-function TAstBinder.VisitRecurNode(const Node: IRecurNode): TDataValue;
+function TAstBinder.VisitRecurNode(const Node: IRecurNode): IAstNode;
begin
- var boundNode := TAst.Recur(AcceptNodes(Node.Arguments));
- Result := SetType(TDataValue.FromIntf(boundNode), TTypes.Void);
+ // Visit children
+ Result := inherited VisitRecurNode(Node);
+ (Node as TAstNode).StaticType := TTypes.Void; // Recur never returns a value
end;
-function TAstBinder.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
-var
- condition, thenBranch, elseBranch: IAstNode;
- boundNode: ITernaryExpressionNode;
-begin
- condition := Accept(Node.Condition).AsIntf;
- thenBranch := Accept(Node.ThenBranch).AsIntf;
- elseBranch := Accept(Node.ElseBranch).AsIntf;
-
- if (condition <> Node.Condition) or (thenBranch <> Node.ThenBranch) or (elseBranch <> Node.ElseBranch) then
- boundNode := TAst.TernaryExpr(condition, thenBranch, elseBranch)
- else
- boundNode := Node;
-
- Result := SetType(TDataValue.FromIntf(boundNode), TTypes.Unknown);
-end;
-
-function TAstBinder.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
-var
- right: IAstNode;
- boundNode: IUnaryExpressionNode;
-begin
- right := Accept(Node.Right).AsIntf;
- boundNode := TAst.UnaryExpr(Node.Operator, right);
- Result := SetType(TDataValue.FromIntf(boundNode), TTypes.Unknown);
-end;
-
-function TAstBinder.VisitIdentifier(const Node: IIdentifierNode): TDataValue;
+function TAstBinder.VisitIdentifier(const Node: IIdentifierNode): IAstNode;
var
symbol: TResolvedSymbol;
- boundNode: IIdentifierNode;
adr: TResolvedAddress;
begin
symbol := FCurrentDescriptor.FindSymbol(Node.Name);
@@ -517,52 +347,64 @@ begin
begin
if (adr.ScopeDepth > 0) and (FUpvalueStack.Count > 0) then
begin
- // Handle Upvalue
- var upvalue := FUpvalueStack.Peek;
+ // --- Handle Upvalue ---
+ var upvalueMap := FUpvalueStack.Peek;
+ // Adjust address to be relative to the captured scope
dec(adr.ScopeDepth);
+
var upvalueIndex: Integer;
- if not upvalue.TryGetValue(adr, upvalueIndex) then
+ if not upvalueMap.TryGetValue(adr, upvalueIndex) then
begin
- upvalueIndex := upvalue.Count;
- upvalue.Add(adr, upvalueIndex);
+ // This is a new upvalue for this lambda
+ upvalueIndex := upvalueMap.Count;
+ upvalueMap.Add(adr, upvalueIndex);
end;
- boundNode := TBoundIdentifierNode.Create(Node, TResolvedAddress.Create(akUpvalue, 0, upvalueIndex));
+
+ // Mutate the node to point to the Upvalue slot
+ (Node as TIdentifierNode).Address := TResolvedAddress.Create(akUpvalue, 0, upvalueIndex);
end
else
- // Handle LocalOrParent
- boundNode := TBoundIdentifierNode.Create(Node, adr);
+ begin
+ // --- Handle LocalOrParent ---
+ // Mutate the node to point to the Local/Parent slot
+ (Node as TIdentifierNode).Address := adr;
+ end;
- Result := SetType(TDataValue.FromIntf(boundNode), symbol.StaticType);
+ (Node as TAstNode).StaticType := symbol.StaticType; // Set type from scope
end
else
raise Exception.CreateFmt('Undefined identifier: "%s"', [Node.Name]);
+
+ Result := Node;
end;
-function TAstBinder.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
+function TAstBinder.VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode;
var
- initializer: IAstNode;
slotIndex: Integer;
address: TResolvedAddress;
- boundIdentifier: IIdentifierNode;
- isBoxed: Boolean;
- boundDecl: IVariableDeclarationNode;
+ N: TVariableDeclarationNode;
begin
- if not IsValidIdentifier(Node.Identifier.Name) then
- raise Exception.CreateFmt('Invalid identifier name: "%s".', [Node.Identifier.Name]);
+ N := (Node as TVariableDeclarationNode);
- initializer := nil;
- if Node.Initializer <> nil then
- initializer := Accept(Node.Initializer).AsIntf;
+ if not IsValidIdentifier(N.Identifier.Name) then
+ raise Exception.CreateFmt('Invalid identifier name: "%s".', [N.Identifier.Name]);
- slotIndex := FCurrentDescriptor.Define(Node.Identifier.Name, TTypes.Unknown);
+ // 1. Visit initializer *first*
+ if Assigned(N.Initializer) then
+ N.Initializer := Accept(N.Initializer);
+
+ // 2. Define variable in *current* scope
+ slotIndex := FCurrentDescriptor.Define(N.Identifier.Name, TTypes.Unknown);
address := TResolvedAddress.Create(akLocalOrParent, 0, slotIndex);
- boundIdentifier := TBoundIdentifierNode.Create(Node.Identifier, address);
- (boundIdentifier as TAstNode).StaticType := TTypes.Unknown;
- isBoxed := (FBoxedDeclarations <> nil) and FBoxedDeclarations.Contains(Node);
- boundDecl := TBoundVariableDeclarationNode.Create(boundIdentifier, initializer, isBoxed);
+ // 3. Mutate the Identifier node (which is NOT visited by inherited call)
+ (N.Identifier as TIdentifierNode).Address := address;
+ (N.Identifier as TAstNode).StaticType := TTypes.Unknown; // TypeChecker will set this
- Result := SetType(TDataValue.FromIntf(boundDecl), TTypes.Unknown);
+ // 4. Mutate this declaration node
+ N.IsBoxed := (FBoxedDeclarations <> nil) and FBoxedDeclarations.Contains(Node);
+
+ Result := Node;
end;
end.
diff --git a/Src/AST/Myc.Ast.Compiler.TCO.pas b/Src/AST/Myc.Ast.Compiler.TCO.pas
index 8a73343..718c766 100644
--- a/Src/AST/Myc.Ast.Compiler.TCO.pas
+++ b/Src/AST/Myc.Ast.Compiler.TCO.pas
@@ -11,8 +11,7 @@ uses
Myc.Ast.Visitor,
Myc.Ast.Scope,
Myc.Ast.Types,
- Myc.Ast,
- Myc.Ast.Binding.Nodes;
+ Myc.Ast;
type
IAstTCO = interface(IAstVisitor)
@@ -21,22 +20,27 @@ type
// This transformer runs *after* the Lowerer (Phase 4).
// Its sole responsibility is to identify tail calls (TCO)
- // and set the `IsTailCall` flag on TBoundFunctionCallNode.
+ // and set the `IsTailCall` flag on TFunctionCallNode.
TAstTCO = class(TAstTransformer, IAstTCO)
private
FIsTailStack: TStack;
FNextIsTail: Boolean;
protected
- function Accept(const Node: IAstNode): TDataValue; override;
+ function Accept(const Node: IAstNode): IAstNode; override;
// Overrides for TCO propagation
- function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
- function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
- function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
- function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
- function VisitRecurNode(const Node: IRecurNode): TDataValue; override;
- function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue; override;
+ function VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode; override;
+ function VisitIfExpression(const Node: IIfExpressionNode): IAstNode; override;
+ function VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode; override;
+ function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override;
+ function VisitRecurNode(const Node: IRecurNode): IAstNode; override;
+ function VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode; override;
+
+ // Operands are never in tail position.
+ function VisitBinaryExpression(const Node: IBinaryExpressionNode): IAstNode; override;
+ function VisitUnaryExpression(const Node: IUnaryExpressionNode): IAstNode; override;
+
// The core TCO logic
- function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
+ function VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; override;
public
constructor Create;
destructor Destroy; override;
@@ -70,140 +74,169 @@ end;
function TAstTCO.Execute(const RootNode: IAstNode): IAstNode;
begin
- var transformedValue := Accept(RootNode);
- if transformedValue.IsVoid then
- Result := TAst.Block([])
- else
- Result := transformedValue.AsIntf;
+ Result := Accept(RootNode); // Use IAstNode-returning Accept
+ if not Assigned(Result) then
+ Result := TAst.Block([]);
end;
-function TAstTCO.Accept(const Node: IAstNode): TDataValue;
+function TAstTCO.Accept(const Node: IAstNode): IAstNode;
begin
- if (not Assigned(Node)) or Done then
+ if (not Assigned(Node)) then
+ begin
+ Result := nil;
exit;
+ end;
FIsTailStack.Push(FNextIsTail);
try
+ // Call inherited Accept, which handles the data unwrapping
Result := inherited Accept(Node);
finally
FNextIsTail := FIsTailStack.Pop;
end;
end;
-function TAstTCO.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
+function TAstTCO.VisitBinaryExpression(const Node: IBinaryExpressionNode): IAstNode;
+begin
+ // Operands are never in tail position.
+ FNextIsTail := False;
+
+ // Call inherited, which will visit Left and Right with FNextIsTail = False
+ Result := inherited VisitBinaryExpression(Node);
+end;
+
+function TAstTCO.VisitUnaryExpression(const Node: IUnaryExpressionNode): IAstNode;
+begin
+ // Operand is never in tail position.
+ FNextIsTail := False;
+
+ // Call inherited, which will visit Right with FNextIsTail = False
+ Result := inherited VisitUnaryExpression(Node);
+end;
+
+function TAstTCO.VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode;
var
i: Integer;
isContextTail: Boolean;
+ N: TBlockExpressionNode;
begin
+ N := (Node as TBlockExpressionNode);
isContextTail := FIsTailStack.Peek;
- for i := 0 to High(Node.Expressions) do
+
+ // We must manually iterate here to set FNextIsTail for each child
+ for i := 0 to High(N.Expressions) do
begin
// Only the last expression in a block is in tail position
- FNextIsTail := isContextTail and (i = High(Node.Expressions));
- Accept(Node.Expressions[i]);
+ FNextIsTail := isContextTail and (i = High(N.Expressions));
+ N.Expressions[i] := Accept(N.Expressions[i]);
end;
- Result := TDataValue.FromIntf(Node);
+ Result := N;
end;
-function TAstTCO.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
+function TAstTCO.VisitIfExpression(const Node: IIfExpressionNode): IAstNode;
var
isContextTail: Boolean;
+ N: TIfExpressionNode;
begin
+ N := (Node as TIfExpressionNode);
isContextTail := FIsTailStack.Peek;
// Condition is never in tail position
FNextIsTail := False;
- Accept(Node.Condition);
+ N.Condition := Accept(N.Condition);
// Then/Else branches ARE in tail position if the IfExpr is
FNextIsTail := isContextTail;
- Accept(Node.ThenBranch);
- if Assigned(Node.ElseBranch) then
- Accept(Node.ElseBranch);
+ N.ThenBranch := Accept(N.ThenBranch);
+ N.ElseBranch := Accept(N.ElseBranch);
- Result := TDataValue.FromIntf(Node);
+ Result := N;
end;
-function TAstTCO.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
+function TAstTCO.VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode;
var
isContextTail: Boolean;
+ N: TTernaryExpressionNode;
begin
+ N := (Node as TTernaryExpressionNode);
isContextTail := FIsTailStack.Peek;
// Condition is never in tail position
FNextIsTail := False;
- Accept(Node.Condition);
+ N.Condition := Accept(N.Condition);
// Then/Else branches ARE in tail position if the TernaryExpr is
FNextIsTail := isContextTail;
- Accept(Node.ThenBranch);
- Accept(Node.ElseBranch);
+ N.ThenBranch := Accept(N.ThenBranch);
+ N.ElseBranch := Accept(N.ElseBranch);
- Result := TDataValue.FromIntf(Node);
+ Result := N;
end;
-function TAstTCO.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
+function TAstTCO.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
+var
+ N: TLambdaExpressionNode;
begin
- // Parameters are never in tail position
- FNextIsTail := False;
- AcceptNodes(Node.Parameters);
+ N := (Node as TLambdaExpressionNode);
// The body of a lambda is *always* a tail position (relative to the lambda)
FNextIsTail := True;
- Accept(Node.Body);
+ N.Body := Accept(N.Body);
- Result := TDataValue.FromIntf(Node);
+ Result := N;
end;
-function TAstTCO.VisitRecurNode(const Node: IRecurNode): TDataValue;
+function TAstTCO.VisitRecurNode(const Node: IRecurNode): IAstNode;
+var
+ N: TRecurNode;
begin
if not FIsTailStack.Peek then
raise Exception.Create('''recur'' can only be used in a tail position.');
+ N := (Node as TRecurNode);
+
// Arguments are not in tail position
FNextIsTail := False;
- AcceptNodes(Node.Arguments);
+ N.Arguments := AcceptNodes(N.Arguments, function(Node: IAstNode): IAstNode begin exit(Node) end);
- Result := TDataValue.FromIntf(Node);
+ Result := N;
end;
-function TAstTCO.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
+function TAstTCO.VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode;
+var
+ N: TMacroExpansionNode;
begin
+ N := (Node as TMacroExpansionNode);
+
// Propagate tail call status to the expanded body
FNextIsTail := FIsTailStack.Peek;
- Accept(Node.ExpandedBody);
+ N.ExpandedBody := Accept(N.ExpandedBody);
// Also visit the original call nodes, though they are not in tail pos
FNextIsTail := False;
- Accept(Node.Callee);
- AcceptNodes(Node.Arguments);
+ N.Callee := Accept(N.Callee);
+ N.Arguments := AcceptNodes(N.Arguments, function(Node: IAstNode): IAstNode begin exit(Node) end);
- Result := TDataValue.FromIntf(Node);
+ Result := N;
end;
-function TAstTCO.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
+function TAstTCO.VisitFunctionCall(const Node: IFunctionCallNode): IAstNode;
var
- callee: IAstNode;
- args: TArray;
isTailCall: Boolean;
+ N: TFunctionCallNode;
begin
isTailCall := FIsTailStack.Peek;
+ N := (Node as TFunctionCallNode);
// Arguments are not in tail position
FNextIsTail := False;
- callee := Accept(Node.Callee).AsIntf;
- args := AcceptNodes(Node.Arguments);
+ N.Callee := Accept(N.Callee);
+ N.Arguments := AcceptNodes(N.Arguments, function(Node: IAstNode): IAstNode begin exit(Node) end);
- // If TCO status changed, we MUST rebuild the node.
- var boundNode := (Node as TBoundFunctionCallNode);
- if (boundNode.IsTailCall <> isTailCall) or (callee <> Node.Callee) or (args <> Node.Arguments) then
- begin
- var newBoundCall := TBoundFunctionCallNode.Create(Node, callee, args, isTailCall);
- (newBoundCall as TAstNode).StaticType := (Node as TAstNode).StaticType;
- Result := TDataValue.FromIntf(newBoundCall);
- end
- else
- Result := TDataValue.FromIntf(Node); // No change
+ // Mutate the node with the TCO status
+ N.IsTailCall := isTailCall;
+
+ Result := N;
end;
end.
diff --git a/Src/AST/Myc.Ast.Dumper.pas b/Src/AST/Myc.Ast.Dumper.pas
index c17ec29..3766b24 100644
--- a/Src/AST/Myc.Ast.Dumper.pas
+++ b/Src/AST/Myc.Ast.Dumper.pas
@@ -9,7 +9,8 @@ uses
Myc.Ast.Nodes,
Myc.Ast.Visitor,
Myc.Data.Value,
- Myc.Data.Scalar;
+ Myc.Data.Scalar,
+ Myc.Ast;
type
// Dumps a bound AST into a human-readable format for debugging purposes.
@@ -18,7 +19,8 @@ type
procedure Execute(const RootNode: IAstNode);
end;
- TAstDumper = class(TAstVisitor)
+ // Inherits from the new non-generic TAstVisitor base class
+ TAstDumper = class(TAstVisitor, IAstDumper)
private
FOutput: TStrings;
FIndent: Integer;
@@ -29,30 +31,31 @@ type
function FormatAddress(const Addr: TResolvedAddress): string;
protected
- function VisitConstant(const Node: IConstantNode): TDataValue; override;
- function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
- function VisitKeyword(const Node: IKeywordNode): 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 VisitRecurNode(const Node: IRecurNode): 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 VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue; override;
- function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override;
- function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; override;
- function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override;
+ // Override abstract procedures from TAstVisitor
+ procedure VisitConstant(const Node: IConstantNode); override;
+ procedure VisitIdentifier(const Node: IIdentifierNode); override;
+ procedure VisitKeyword(const Node: IKeywordNode); override;
+ procedure VisitBinaryExpression(const Node: IBinaryExpressionNode); override;
+ procedure VisitUnaryExpression(const Node: IUnaryExpressionNode); override;
+ procedure VisitIfExpression(const Node: IIfExpressionNode); override;
+ procedure VisitTernaryExpression(const Node: ITernaryExpressionNode); override;
+ procedure VisitLambdaExpression(const Node: ILambdaExpressionNode); override;
+ procedure VisitFunctionCall(const Node: IFunctionCallNode); override;
+ procedure VisitMacroExpansionNode(const Node: IMacroExpansionNode); override;
+ procedure VisitRecurNode(const Node: IRecurNode); override;
+ procedure VisitBlockExpression(const Node: IBlockExpressionNode); override;
+ procedure VisitVariableDeclaration(const Node: IVariableDeclarationNode); override;
+ procedure VisitAssignment(const Node: IAssignmentNode); override;
+ procedure VisitMacroDefinition(const Node: IMacroDefinitionNode); override;
+ procedure VisitQuasiquote(const Node: IQuasiquoteNode); override;
+ procedure VisitUnquote(const Node: IUnquoteNode); override;
+ procedure VisitUnquoteSplicing(const Node: IUnquoteSplicingNode); override;
+ procedure VisitIndexer(const Node: IIndexerNode); override;
+ procedure VisitMemberAccess(const Node: IMemberAccessNode); override;
+ procedure VisitRecordLiteral(const Node: IRecordLiteralNode); override;
+ procedure VisitCreateSeries(const Node: ICreateSeriesNode); override;
+ procedure VisitAddSeriesItem(const Node: IAddSeriesItemNode); override;
+ procedure VisitSeriesLength(const Node: ISeriesLengthNode); override;
public
// Creates a new instance of the AST dumper.
@@ -67,8 +70,8 @@ type
implementation
uses
- Myc.Data.Keyword,
- Myc.Ast.Binding.Nodes;
+ Myc.Data.Keyword;
+// Myc.Ast.Binding.Nodes; // Removed
{ TAstDumper }
@@ -132,47 +135,45 @@ begin
end;
end;
-function TAstDumper.VisitConstant(const Node: IConstantNode): TDataValue;
+procedure TAstDumper.VisitConstant(const Node: IConstantNode);
begin
LogFmt('Constant: %s', [Node.Value.ToString]);
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitIdentifier(const Node: IIdentifierNode): TDataValue;
+procedure TAstDumper.VisitIdentifier(const Node: IIdentifierNode);
+var
+ N: TIdentifierNode;
begin
- if Node is TBoundIdentifierNode then
- LogFmt('Identifier: %s -> %s', [Node.Name, FormatAddress((Node as TBoundIdentifierNode).Address)])
+ N := (Node as TIdentifierNode);
+ if N.Address.Kind <> akUnresolved then
+ LogFmt('Identifier: %s -> %s', [N.Name, FormatAddress(N.Address)])
else
- LogFmt('Identifier: %s (unbound)', [Node.Name]);
- Result := TDataValue.Void;
+ LogFmt('Identifier: %s (unbound)', [N.Name]);
end;
-function TAstDumper.VisitKeyword(const Node: IKeywordNode): TDataValue;
+procedure TAstDumper.VisitKeyword(const Node: IKeywordNode);
begin
LogFmt('Keyword: :%s', [Node.Value.Name]);
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
+procedure TAstDumper.VisitBinaryExpression(const Node: IBinaryExpressionNode);
begin
LogFmt('BinaryExpression: %s', [Node.Operator.ToString]);
Indent;
Node.Left.Accept(Self);
Node.Right.Accept(Self);
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
+procedure TAstDumper.VisitUnaryExpression(const Node: IUnaryExpressionNode);
begin
LogFmt('UnaryExpression: %s', [Node.Operator.ToString]);
Indent;
Node.Right.Accept(Self);
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
+procedure TAstDumper.VisitIfExpression(const Node: IIfExpressionNode);
begin
Log('IfExpression');
Indent;
@@ -186,10 +187,9 @@ begin
Node.ElseBranch.Accept(Self);
end;
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
+procedure TAstDumper.VisitTernaryExpression(const Node: ITernaryExpressionNode);
begin
Log('TernaryExpression');
Indent;
@@ -200,25 +200,24 @@ begin
Log('Else:');
Node.ElseBranch.Accept(Self);
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
+procedure TAstDumper.VisitLambdaExpression(const Node: ILambdaExpressionNode);
var
- param: IIdentifierNode;
upvalueAddr: TResolvedAddress;
pair: TPair;
- boundNode: TBoundLambdaExpressionNode;
+ boundNode: TLambdaExpressionNode;
begin
- if Node is TBoundLambdaExpressionNode then
+ boundNode := Node as TLambdaExpressionNode;
+
+ if Assigned(boundNode.ScopeDescriptor) then
begin
- boundNode := Node as TBoundLambdaExpressionNode;
LogFmt('LambdaExpression (HasNested: %s)', [boundNode.HasNestedLambdas.ToString(TUseBoolStrs.True)]);
Indent;
Log('Parameters:');
Indent;
- for param in boundNode.Parameters do
+ for var param in boundNode.Parameters do
param.Accept(Self);
Unindent;
@@ -248,38 +247,35 @@ begin
Indent;
Log('Parameters:');
Indent;
- for param in Node.Parameters do
+ for var param in Node.Parameters do
param.Accept(Self);
Unindent;
Log('Body:');
Node.Body.Accept(Self);
Unindent;
end;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
+procedure TAstDumper.VisitFunctionCall(const Node: IFunctionCallNode);
var
arg: IAstNode;
+ N: TFunctionCallNode;
begin
- if Node is TBoundFunctionCallNode then
- LogFmt('FunctionCall (IsTailCall: %s)', [(Node as TBoundFunctionCallNode).IsTailCall.ToString(TUseBoolStrs.True)])
- else
- Log('FunctionCall (unbound)');
+ N := (Node as TFunctionCallNode);
+ LogFmt('FunctionCall (IsTailCall: %s)', [N.IsTailCall.ToString(TUseBoolStrs.True)]);
Indent;
Log('Callee:');
- Node.Callee.Accept(Self);
- LogFmt('Arguments (%d):', [Length(Node.Arguments)]);
+ N.Callee.Accept(Self);
+ LogFmt('Arguments (%d):', [Length(N.Arguments)]);
Indent;
- for arg in Node.Arguments do
+ for arg in N.Arguments do
arg.Accept(Self);
Unindent;
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
+procedure TAstDumper.VisitMacroExpansionNode(const Node: IMacroExpansionNode);
var
arg: IAstNode;
begin
@@ -303,10 +299,9 @@ begin
Unindent;
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitRecurNode(const Node: IRecurNode): TDataValue;
+procedure TAstDumper.VisitRecurNode(const Node: IRecurNode);
var
arg: IAstNode;
begin
@@ -319,10 +314,9 @@ begin
arg.Accept(Self);
Unindent;
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
+procedure TAstDumper.VisitBlockExpression(const Node: IBlockExpressionNode);
var
expr: IAstNode;
begin
@@ -331,28 +325,26 @@ begin
for expr in Node.Expressions do
expr.Accept(Self);
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
+procedure TAstDumper.VisitVariableDeclaration(const Node: IVariableDeclarationNode);
+var
+ N: TVariableDeclarationNode;
begin
- if Node is TBoundVariableDeclarationNode then
- LogFmt('VariableDeclaration (IsBoxed: %s)', [(Node as TBoundVariableDeclarationNode).IsBoxed.ToString(TUseBoolStrs.True)])
- else
- Log('VariableDeclaration (unbound)');
+ N := (Node as TVariableDeclarationNode);
+ LogFmt('VariableDeclaration (IsBoxed: %s)', [N.IsBoxed.ToString(TUseBoolStrs.True)]);
Indent;
- Node.Identifier.Accept(Self);
- if Assigned(Node.Initializer) then
+ N.Identifier.Accept(Self);
+ if Assigned(N.Initializer) then
begin
Log('Initializer:');
- Node.Initializer.Accept(Self);
+ N.Initializer.Accept(Self);
end;
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitAssignment(const Node: IAssignmentNode): TDataValue;
+procedure TAstDumper.VisitAssignment(const Node: IAssignmentNode);
begin
Log('Assignment');
Indent;
@@ -360,12 +352,9 @@ begin
Log('Value:');
Node.Value.Accept(Self);
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
-var
- param: IIdentifierNode;
+procedure TAstDumper.VisitMacroDefinition(const Node: IMacroDefinitionNode);
begin
Log('MacroDefinition');
Indent;
@@ -377,7 +366,7 @@ begin
Log('Parameters:');
Indent;
- for param in Node.Parameters do
+ for var param in Node.Parameters do
param.Accept(Self);
Unindent;
@@ -387,37 +376,33 @@ begin
Unindent;
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue;
+procedure TAstDumper.VisitQuasiquote(const Node: IQuasiquoteNode);
begin
Log('Quasiquote');
Indent;
Node.Expression.Accept(Self);
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitUnquote(const Node: IUnquoteNode): TDataValue;
+procedure TAstDumper.VisitUnquote(const Node: IUnquoteNode);
begin
Log('Unquote');
Indent;
Node.Expression.Accept(Self);
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue;
+procedure TAstDumper.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode);
begin
Log('UnquoteSplicing');
Indent;
Node.Expression.Accept(Self);
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitIndexer(const Node: IIndexerNode): TDataValue;
+procedure TAstDumper.VisitIndexer(const Node: IIndexerNode);
begin
Log('Indexer');
Indent;
@@ -426,10 +411,9 @@ begin
Log('Index:');
Node.Index.Accept(Self);
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
+procedure TAstDumper.VisitMemberAccess(const Node: IMemberAccessNode);
begin
Log('MemberAccess');
Indent;
@@ -438,10 +422,9 @@ begin
Log('Member:');
Node.Member.Accept(Self);
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue;
+procedure TAstDumper.VisitRecordLiteral(const Node: IRecordLiteralNode);
var
field: TRecordFieldLiteral;
begin
@@ -455,16 +438,14 @@ begin
Unindent;
end;
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
+procedure TAstDumper.VisitCreateSeries(const Node: ICreateSeriesNode);
begin
LogFmt('CreateSeries: %s', [Node.Definition]);
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
+procedure TAstDumper.VisitAddSeriesItem(const Node: IAddSeriesItemNode);
begin
Log('AddSeriesItem');
Indent;
@@ -478,17 +459,15 @@ begin
Node.Lookback.Accept(Self);
end;
Unindent;
- Result := TDataValue.Void;
end;
-function TAstDumper.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
+procedure TAstDumper.VisitSeriesLength(const Node: ISeriesLengthNode);
begin
Log('SeriesLength');
Indent;
Log('Series:');
Node.Series.Accept(Self);
Unindent;
- Result := TDataValue.Void;
end;
end.
diff --git a/Src/AST/Myc.Ast.Evaluator.pas b/Src/AST/Myc.Ast.Evaluator.pas
index ccb1259..8dad58a 100644
--- a/Src/AST/Myc.Ast.Evaluator.pas
+++ b/Src/AST/Myc.Ast.Evaluator.pas
@@ -9,43 +9,44 @@ uses
Myc.Data.Scalar,
Myc.Data.Value,
Myc.Ast.Nodes,
- Myc.Ast.Visitor,
- Myc.Ast.Binding,
Myc.Ast.Scope;
type
// The standard AST evaluator for production use.
- TEvaluatorVisitor = class(TAstVisitor, IEvaluatorVisitor)
+ // This class inherits directly from TInterfacedObject as it is an
+ // Interpreter (AST -> TDataValue), not a Transformer (AST -> IAstNode).
+ TEvaluatorVisitor = class(TInterfacedObject, IAstVisitor, IEvaluatorVisitor)
private
FScope: IExecutionScope;
class var
procedure HandleTCO(var ResultValue: TDataValue);
protected
- function VisitConstant(const Node: IConstantNode): TDataValue; override;
- function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
- function VisitKeyword(const Node: IKeywordNode): 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 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 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 VisitIndexer(const Node: IIndexerNode): TDataValue; override;
- function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
- function VisitRecordLiteral(const Node: IRecordLiteralNode): 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;
+ // IAstVisitor methods made virtual for TDebugEvaluatorVisitor to override
+ function VisitConstant(const Node: IConstantNode): TDataValue; virtual;
+ function VisitIdentifier(const Node: IIdentifierNode): TDataValue; virtual;
+ function VisitKeyword(const Node: IKeywordNode): TDataValue; virtual;
+ function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; virtual;
+ function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; virtual;
+ function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; virtual;
+ function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; virtual;
+ function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; virtual;
+ function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; virtual;
+ function VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue; virtual;
+ function VisitUnquote(const Node: IUnquoteNode): TDataValue; virtual;
+ function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue; virtual;
+ function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; virtual;
+ function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue; virtual;
+ function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; virtual;
+ function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; virtual;
+ function VisitAssignment(const Node: IAssignmentNode): TDataValue; virtual;
+ function VisitIndexer(const Node: IIndexerNode): TDataValue; virtual;
+ function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; virtual;
+ function VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue; virtual;
+ function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; virtual;
+ function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; virtual;
+ function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; virtual;
+ function VisitRecurNode(const Node: IRecurNode): TDataValue; virtual;
function IsTruthy(const AValue: TDataValue): Boolean; inline;
@@ -68,11 +69,12 @@ implementation
uses
System.TypInfo,
System.Generics.Defaults,
+ Myc.Ast, // Added
Myc.Data.Keyword,
Myc.Data.Decimal,
Myc.Data.Series,
- Myc.Data.Scalar.JSON,
- Myc.Ast.Binding.Nodes;
+ Myc.Data.Scalar.JSON;
+// Myc.Ast.Binding.Nodes; // Removed
// Helper type for TCO via trampolining.
type
@@ -206,7 +208,7 @@ end;
function TEvaluatorVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
var
- boundNode: TBoundLambdaExpressionNode;
+ boundNode: TLambdaExpressionNode; // Changed
capturedCells: TArray;
i: Integer;
sourceAddresses: TArray;
@@ -214,7 +216,7 @@ var
visitorFactory: TEvaluatorFactory;
begin
// Cast to the bound node to access binder-specific information.
- boundNode := Node as TBoundLambdaExpressionNode;
+ boundNode := Node as TLambdaExpressionNode; // Changed
// Create the closure by capturing the value cells of all upvalues from the current scope.
sourceAddresses := boundNode.Upvalues;
@@ -257,13 +259,13 @@ begin
// Capture the closure itself in slot 0 for 'recur' to find it.
adr.SlotIndex := 0;
- lambdaScope[adr] := closure;
+ lambdaScope[adr] := TDataValue(closure); // Explicit cast
// Populate the scope with the actual parameters passed to the function.
for i := 0 to High(ArgValues) do
begin
// Parameters in a bound lambda must be bound identifiers.
- adr.SlotIndex := (params[i] as TBoundIdentifierNode).Address.SlotIndex;
+ adr.SlotIndex := (params[i] as TIdentifierNode).Address.SlotIndex; // Changed
lambdaScope[adr] := ArgValues[i];
end;
@@ -273,7 +275,7 @@ begin
end;
// The result of visiting a lambda node is the callable closure itself.
- Result := closure;
+ Result := TDataValue(closure); // Explicit cast
end;
function TEvaluatorVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
@@ -303,7 +305,7 @@ function TEvaluatorVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDa
var
calleeValue: TDataValue;
argValues: TArray;
- boundNode: TBoundFunctionCallNode;
+ boundNode: TFunctionCallNode; // Changed
begin
calleeValue := Node.Callee.Accept(Self);
if calleeValue.Kind <> vkMethod then
@@ -314,7 +316,7 @@ begin
for var i := 0 to High(argNodes) do
argValues[i] := argNodes[i].Accept(Self);
- boundNode := Node as TBoundFunctionCallNode;
+ boundNode := Node as TFunctionCallNode; // Changed
if boundNode.IsTailCall then
begin
// This is a tail call. Return a thunk to be processed by the trampoline.
@@ -363,7 +365,7 @@ var
itemValue, lookbackValue, seriesVar: TDataValue;
lookback: Int64;
begin
- seriesVar := FScope[(Node.Series as TBoundIdentifierNode).Address];
+ seriesVar := FScope[(Node.Series as TIdentifierNode).Address]; // Changed
itemValue := Node.Value.Accept(Self);
lookback := -1;
@@ -397,7 +399,7 @@ begin
// Evaluate the new value.
Result := Node.Value.Accept(Self);
// Assign it. The scope's SetValues implementation now handles boxing correctly.
- FScope[(Node.Identifier as TBoundIdentifierNode).Address] := Result;
+ FScope[(Node.Identifier as TIdentifierNode).Address] := Result; // Changed
end;
function TEvaluatorVisitor.VisitConstant(const Node: IConstantNode): TDataValue;
@@ -408,7 +410,7 @@ end;
function TEvaluatorVisitor.VisitKeyword(const Node: IKeywordNode): TDataValue;
begin
// Return the keyword as a TScalar value
- Result := TDataValue(TScalar.FromKeyword(Node.Value));
+ Result := TDataValue(TScalar.FromKeyword(Node.Value)); // Explicit cast
end;
function TEvaluatorVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
@@ -434,7 +436,7 @@ end;
function TEvaluatorVisitor.VisitIdentifier(const Node: IIdentifierNode): TDataValue;
begin
// The scope's GetValues implementation now handles unboxing automatically.
- Result := FScope[(Node as TBoundIdentifierNode).Address];
+ Result := FScope[(Node as TIdentifierNode).Address]; // Changed
end;
function TEvaluatorVisitor.VisitIndexer(const Node: IIndexerNode): TDataValue;
@@ -458,7 +460,7 @@ begin
series := baseValue.AsSeries;
if (index < 0) or (index >= series.TotalCount) then
raise EArgumentException.CreateFmt('Index %d is out of bounds for series with %d elements.', [index, series.TotalCount]);
- Result := series.Items[Integer(index)];
+ Result := TDataValue(series.Items[Integer(index)]); // Explicit cast
end;
vkRecordSeries:
begin
@@ -487,7 +489,7 @@ begin
case baseValue.Kind of
vkRecordSeries: Result := TDataValue.FromSeries(baseValue.AsRecordSeries[Node.Member.Value]);
- vkRecord: Result := baseValue.AsRecord[Node.Member.Value];
+ vkRecord: Result := TDataValue(baseValue.AsRecord[Node.Member.Value]); // Explicit cast
// --- NEW GENERIC PATH ---
vkGenericRecord:
@@ -509,10 +511,10 @@ var
i: Integer;
begin
// Check which type the binder created
- if Node is TBoundGenericRecordLiteralNode then
+ if Node is TGenericRecordLiteralNode then // Changed
begin
// --- NEW GENERIC PATH ---
- var boundNode := Node as TBoundGenericRecordLiteralNode;
+ var boundNode := Node as TGenericRecordLiteralNode; // Changed
var genFields: TArray>;
SetLength(genFields, Length(boundNode.Fields));
@@ -530,10 +532,10 @@ begin
var dynRec := TDynamicRecord.Create(genFields);
Result := TDataValue.FromGenericRecord(dynRec);
end
- else if Node is TBoundRecordLiteralNode then
+ else if Node is TRecordLiteralNode then // Changed
begin
// --- EXISTING SCALAR PATH ---
- var boundNode := Node as TBoundRecordLiteralNode;
+ var boundNode := Node as TRecordLiteralNode; // Changed
var values: TArray;
SetLength(values, Length(boundNode.Fields));
@@ -554,7 +556,7 @@ end;
function TEvaluatorVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
var
address: TResolvedAddress;
- boundNode: TBoundVariableDeclarationNode;
+ boundNode: TVariableDeclarationNode; // Changed
begin
// First, evaluate the initializer to get the variable's initial value.
if Assigned(Node.Initializer) then
@@ -562,9 +564,9 @@ begin
else
Result := TDataValue.Void;
- // After binding, all declaration nodes are TBoundVariableDeclarationNode
- boundNode := Node as TBoundVariableDeclarationNode;
- address := (boundNode.Identifier as TBoundIdentifierNode).Address;
+ // After binding, all declaration nodes are TVariableDeclarationNode
+ boundNode := Node as TVariableDeclarationNode; // Changed
+ address := (boundNode.Identifier as TIdentifierNode).Address; // Changed
// Check the IsBoxed flag set by the binder.
if boundNode.IsBoxed then
@@ -599,7 +601,7 @@ begin
+ ' and '
+ rightValue.AsScalar.Kind.ToString
+ ' .');
- Result := resScalar;
+ Result := TDataValue(resScalar); // Explicit cast
end;
function TEvaluatorVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
@@ -614,7 +616,7 @@ begin
var res: TScalar;
if not TScalar.TryUnaryOperation(Node.Operator, rightValue.AsScalar, res) then
raise ENotSupportedException.Create('Unary operation not supported for scalar type' + rightValue.AsScalar.Kind.ToString + '.');
- Result := res;
+ Result := TDataValue(res); // Explicit cast
end;
function TEvaluatorVisitor.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
@@ -649,7 +651,7 @@ var
seriesValue: TDataValue;
len: Int64;
begin
- seriesValue := FScope[(Node.Series as TBoundIdentifierNode).Address];
+ seriesValue := FScope[(Node.Series as TIdentifierNode).Address]; // Changed
case seriesValue.Kind of
vkSeries: len := seriesValue.AsSeries.Count;
@@ -658,7 +660,7 @@ begin
raise EArgumentException.CreateFmt('Cannot get length of type %s.', [GetEnumName(TypeInfo(TDataValueKind), Ord(seriesValue.Kind))]);
end;
- Result := TScalar.FromInt64(len);
+ Result := TDataValue(TScalar.FromInt64(len)); // Explicit cast
end;
end.
diff --git a/Src/AST/Myc.Ast.JSON.pas b/Src/AST/Myc.Ast.JSON.pas
index af963f8..bce60c7 100644
--- a/Src/AST/Myc.Ast.JSON.pas
+++ b/Src/AST/Myc.Ast.JSON.pas
@@ -20,9 +20,9 @@ type
// TJsonAstConverter implements the visitor pattern for serialization
// and uses factory functions for deserialization.
- TJsonAstConverter = class(TAstVisitor, IJsonAstConverter)
+ // Inherits from the new generic visitor base class
+ TJsonAstConverter = class(TAstVisitor, IJsonAstConverter)
private
- FJsonObjectStack: TStack;
procedure DataValueToJson(const AValue: TDataValue; const AParent: TJSONObject; const AName: string);
function JsonToNode(const AJson: TJSONValue; const ExpectedType: String = ''): IAstNode;
function JsonToDataValue(const AObj: TJSONObject; const AName: string): TDataValue;
@@ -52,37 +52,36 @@ type
function JsonToAddSeriesItemNode(const AObj: TJSONObject): IAddSeriesItemNode;
function JsonToSeriesLengthNode(const AObj: TJSONObject): ISeriesLengthNode;
protected
- // IAstVisitor implementation for serialization
- function VisitConstant(const Node: IConstantNode): TDataValue; override;
- function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
- function VisitKeyword(const Node: IKeywordNode): 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 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 VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
- function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue; override;
- function VisitRecurNode(const Node: IRecurNode): TDataValue; override;
- function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
- function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
- function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
- function VisitIndexer(const Node: IIndexerNode): TDataValue; override;
- function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
- function VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue; override;
- function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; override;
- function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; override;
- function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override;
+ // IAstVisitor implementation for serialization (T = TJSONObject)
+ function VisitConstant(const Node: IConstantNode): TJSONObject; override;
+ function VisitIdentifier(const Node: IIdentifierNode): TJSONObject; override;
+ function VisitKeyword(const Node: IKeywordNode): TJSONObject; override;
+ function VisitBinaryExpression(const Node: IBinaryExpressionNode): TJSONObject; override;
+ function VisitUnaryExpression(const Node: IUnaryExpressionNode): TJSONObject; override;
+ function VisitIfExpression(const Node: IIfExpressionNode): TJSONObject; override;
+ function VisitTernaryExpression(const Node: ITernaryExpressionNode): TJSONObject; override;
+ function VisitLambdaExpression(const Node: ILambdaExpressionNode): TJSONObject; override;
+ function VisitMacroDefinition(const Node: IMacroDefinitionNode): TJSONObject; override;
+ function VisitQuasiquote(const Node: IQuasiquoteNode): TJSONObject; override;
+ function VisitUnquote(const Node: IUnquoteNode): TJSONObject; override;
+ function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TJSONObject; override;
+ function VisitFunctionCall(const Node: IFunctionCallNode): TJSONObject; override;
+ function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TJSONObject; override;
+ function VisitRecurNode(const Node: IRecurNode): TJSONObject; override;
+ function VisitBlockExpression(const Node: IBlockExpressionNode): TJSONObject; override;
+ function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TJSONObject; override;
+ function VisitAssignment(const Node: IAssignmentNode): TJSONObject; override;
+ function VisitIndexer(const Node: IIndexerNode): TJSONObject; override;
+ function VisitMemberAccess(const Node: IMemberAccessNode): TJSONObject; override;
+ function VisitRecordLiteral(const Node: IRecordLiteralNode): TJSONObject; override;
+ function VisitCreateSeries(const Node: ICreateSeriesNode): TJSONObject; override;
+ function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TJSONObject; override;
+ function VisitSeriesLength(const Node: ISeriesLengthNode): TJSONObject; override;
function Serialize(const RootNode: IAstNode): TJSONObject;
function Deserialize(const AJson: TJSONObject): IAstNode;
public
constructor Create;
- destructor Destroy; override;
end;
implementation
@@ -95,13 +94,7 @@ uses
constructor TJsonAstConverter.Create;
begin
inherited;
- FJsonObjectStack := TStack.Create;
-end;
-
-destructor TJsonAstConverter.Destroy;
-begin
- FJsonObjectStack.Free;
- inherited;
+ // FJsonObjectStack removed
end;
function TJsonAstConverter.Deserialize(const AJson: TJSONObject): IAstNode;
@@ -145,506 +138,322 @@ begin
AParent.AddPair(AName, valObj);
end;
-function TJsonAstConverter.VisitConstant(const Node: IConstantNode): TDataValue;
-var
- obj: TJSONObject;
+function TJsonAstConverter.VisitConstant(const Node: IConstantNode): TJSONObject;
begin
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('Constant'));
- DataValueToJson(Node.Value, obj, 'Value');
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('Constant'));
+ DataValueToJson(Node.Value, Result, 'Value');
end;
-function TJsonAstConverter.VisitIdentifier(const Node: IIdentifierNode): TDataValue;
-var
- obj: TJSONObject;
+function TJsonAstConverter.VisitIdentifier(const Node: IIdentifierNode): TJSONObject;
begin
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('Identifier'));
- obj.AddPair('Name', TJSONString.Create(Node.Name));
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('Identifier'));
+ Result.AddPair('Name', TJSONString.Create(Node.Name));
end;
-function TJsonAstConverter.VisitKeyword(const Node: IKeywordNode): TDataValue;
-var
- obj: TJSONObject;
+function TJsonAstConverter.VisitKeyword(const Node: IKeywordNode): TJSONObject;
begin
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('Keyword'));
- obj.AddPair('Name', TJSONString.Create(Node.Value.Name));
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('Keyword'));
+ Result.AddPair('Name', TJSONString.Create(Node.Value.Name));
end;
-function TJsonAstConverter.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
+function TJsonAstConverter.VisitBinaryExpression(const Node: IBinaryExpressionNode): TJSONObject;
var
- obj, leftObj, rightObj: TJSONObject;
+ leftObj, rightObj: TJSONObject;
begin
- Node.Left.Accept(Self);
- Node.Right.Accept(Self);
+ leftObj := Accept(Node.Left);
+ rightObj := Accept(Node.Right);
- rightObj := FJsonObjectStack.Pop;
- leftObj := FJsonObjectStack.Pop;
-
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('BinaryExpr'));
- obj.AddPair('Operator', TJSONString.Create(Node.Operator.ToString));
- obj.AddPair('Left', leftObj);
- obj.AddPair('Right', rightObj);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('BinaryExpr'));
+ Result.AddPair('Operator', TJSONString.Create(Node.Operator.ToString));
+ Result.AddPair('Left', leftObj);
+ Result.AddPair('Right', rightObj);
end;
-function TJsonAstConverter.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
+function TJsonAstConverter.VisitUnaryExpression(const Node: IUnaryExpressionNode): TJSONObject;
var
- obj, rightObj: TJSONObject;
+ rightObj: TJSONObject;
begin
- Node.Right.Accept(Self);
- rightObj := FJsonObjectStack.Pop;
+ rightObj := Accept(Node.Right);
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('UnaryExpr'));
- obj.AddPair('Operator', TJSONString.Create(Node.Operator.ToString));
- obj.AddPair('Right', rightObj);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('UnaryExpr'));
+ Result.AddPair('Operator', TJSONString.Create(Node.Operator.ToString));
+ Result.AddPair('Right', rightObj);
end;
-function TJsonAstConverter.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
+function TJsonAstConverter.VisitIfExpression(const Node: IIfExpressionNode): TJSONObject;
var
- obj, condObj, thenObj, elseObj: TJSONObject;
+ condObj, thenObj, elseObj: TJSONObject;
begin
- Node.Condition.Accept(Self);
- Node.ThenBranch.Accept(Self);
- if Assigned(Node.ElseBranch) then
- Node.ElseBranch.Accept(Self);
+ condObj := Accept(Node.Condition);
+ thenObj := Accept(Node.ThenBranch);
+ elseObj := Accept(Node.ElseBranch); // Accept handles nil
- if Assigned(Node.ElseBranch) then
- elseObj := FJsonObjectStack.Pop
- else
- elseObj := nil;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('IfExpr'));
+ Result.AddPair('Condition', condObj);
+ Result.AddPair('ThenBranch', thenObj);
- thenObj := FJsonObjectStack.Pop;
- condObj := FJsonObjectStack.Pop;
-
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('IfExpr'));
- obj.AddPair('Condition', condObj);
- obj.AddPair('ThenBranch', thenObj);
if Assigned(elseObj) then
- obj.AddPair('ElseBranch', elseObj)
+ Result.AddPair('ElseBranch', elseObj)
else
- obj.AddPair('ElseBranch', TJSONNull.Create);
-
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result.AddPair('ElseBranch', TJSONNull.Create);
end;
-function TJsonAstConverter.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
+function TJsonAstConverter.VisitTernaryExpression(const Node: ITernaryExpressionNode): TJSONObject;
var
- obj, condObj, thenObj, elseObj: TJSONObject;
+ condObj, thenObj, elseObj: TJSONObject;
begin
- Node.Condition.Accept(Self);
- Node.ThenBranch.Accept(Self);
- Node.ElseBranch.Accept(Self);
+ condObj := Accept(Node.Condition);
+ thenObj := Accept(Node.ThenBranch);
+ elseObj := Accept(Node.ElseBranch);
- elseObj := FJsonObjectStack.Pop;
- thenObj := FJsonObjectStack.Pop;
- condObj := FJsonObjectStack.Pop;
-
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('TernaryExpr'));
- obj.AddPair('Condition', condObj);
- obj.AddPair('ThenBranch', thenObj);
- obj.AddPair('ElseBranch', elseObj);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('TernaryExpr'));
+ Result.AddPair('Condition', condObj);
+ Result.AddPair('ThenBranch', thenObj);
+ Result.AddPair('ElseBranch', elseObj);
end;
-function TJsonAstConverter.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
+function TJsonAstConverter.VisitLambdaExpression(const Node: ILambdaExpressionNode): TJSONObject;
var
- obj, bodyObj: TJSONObject;
+ bodyObj: TJSONObject;
paramsArray: TJSONArray;
- tempParams: TArray;
- param: IIdentifierNode;
- i: Integer;
begin
- for param in Node.Parameters do
- param.Accept(Self);
- Node.Body.Accept(Self);
-
- bodyObj := FJsonObjectStack.Pop;
-
- SetLength(tempParams, Length(Node.Parameters));
- for i := High(tempParams) downto 0 do
- tempParams[i] := FJsonObjectStack.Pop;
+ bodyObj := Accept(Node.Body);
paramsArray := TJSONArray.Create;
- for i := 0 to High(tempParams) do
- paramsArray.Add(tempParams[i]);
+ for var param in Node.Parameters do
+ paramsArray.Add(Accept(param));
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('LambdaExpr'));
- obj.AddPair('Parameters', paramsArray);
- obj.AddPair('Body', bodyObj);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('LambdaExpr'));
+ Result.AddPair('Parameters', paramsArray);
+ Result.AddPair('Body', bodyObj);
end;
-function TJsonAstConverter.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
+function TJsonAstConverter.VisitMacroDefinition(const Node: IMacroDefinitionNode): TJSONObject;
var
- obj, nameObj, bodyObj: TJSONObject;
+ nameObj, bodyObj: TJSONObject;
paramsArray: TJSONArray;
- tempParams: TArray;
- param: IIdentifierNode;
- i: Integer;
begin
- Node.Name.Accept(Self);
- for param in Node.Parameters do
- param.Accept(Self);
- Node.Body.Accept(Self);
-
- bodyObj := FJsonObjectStack.Pop;
-
- SetLength(tempParams, Length(Node.Parameters));
- for i := High(tempParams) downto 0 do
- tempParams[i] := FJsonObjectStack.Pop;
-
- nameObj := FJsonObjectStack.Pop;
+ nameObj := Accept(Node.Name);
+ bodyObj := Accept(Node.Body);
paramsArray := TJSONArray.Create;
- for i := 0 to High(tempParams) do
- paramsArray.Add(tempParams[i]);
+ for var param in Node.Parameters do
+ paramsArray.Add(Accept(param));
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('MacroDef'));
- obj.AddPair('Name', nameObj);
- obj.AddPair('Parameters', paramsArray);
- obj.AddPair('Body', bodyObj);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('MacroDef'));
+ Result.AddPair('Name', nameObj);
+ Result.AddPair('Parameters', paramsArray);
+ Result.AddPair('Body', bodyObj);
end;
-function TJsonAstConverter.VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue;
-var
- obj, exprObj: TJSONObject;
+function TJsonAstConverter.VisitQuasiquote(const Node: IQuasiquoteNode): TJSONObject;
begin
- Node.Expression.Accept(Self);
- exprObj := FJsonObjectStack.Pop;
-
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('Quasiquote'));
- obj.AddPair('Expression', exprObj);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('Quasiquote'));
+ Result.AddPair('Expression', Accept(Node.Expression));
end;
-function TJsonAstConverter.VisitUnquote(const Node: IUnquoteNode): TDataValue;
-var
- obj, exprObj: TJSONObject;
+function TJsonAstConverter.VisitUnquote(const Node: IUnquoteNode): TJSONObject;
begin
- Node.Expression.Accept(Self);
- exprObj := FJsonObjectStack.Pop;
-
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('Unquote'));
- obj.AddPair('Expression', exprObj);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('Unquote'));
+ Result.AddPair('Expression', Accept(Node.Expression));
end;
-function TJsonAstConverter.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue;
-var
- obj, exprObj: TJSONObject;
+function TJsonAstConverter.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TJSONObject;
begin
- Node.Expression.Accept(Self);
- exprObj := FJsonObjectStack.Pop;
-
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('UnquoteSplicing'));
- obj.AddPair('Expression', exprObj);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('UnquoteSplicing'));
+ Result.AddPair('Expression', Accept(Node.Expression));
end;
-function TJsonAstConverter.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
+function TJsonAstConverter.VisitFunctionCall(const Node: IFunctionCallNode): TJSONObject;
var
- obj, calleeObj: TJSONObject;
+ calleeObj: TJSONObject;
argsArray: TJSONArray;
- tempArgs: TArray;
arg: IAstNode;
- i: Integer;
begin
- Node.Callee.Accept(Self);
- for arg in Node.Arguments do
- arg.Accept(Self);
-
- SetLength(tempArgs, Length(Node.Arguments));
- for i := High(tempArgs) downto 0 do
- tempArgs[i] := FJsonObjectStack.Pop;
+ calleeObj := Accept(Node.Callee);
argsArray := TJSONArray.Create;
- for i := 0 to High(tempArgs) do
- argsArray.Add(tempArgs[i]);
+ for arg in Node.Arguments do
+ argsArray.Add(Accept(arg));
- calleeObj := FJsonObjectStack.Pop;
-
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('FunctionCall'));
- obj.AddPair('Callee', calleeObj);
- obj.AddPair('Arguments', argsArray);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('FunctionCall'));
+ Result.AddPair('Callee', calleeObj);
+ Result.AddPair('Arguments', argsArray);
end;
-function TJsonAstConverter.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
+function TJsonAstConverter.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TJSONObject;
var
- obj, calleeObj, bodyObj: TJSONObject;
+ calleeObj, bodyObj: TJSONObject;
argsArray: TJSONArray;
- tempArgs: TArray;
arg: IAstNode;
- i: Integer;
begin
- // Serialize all children first: Callee, Arguments, and the new ExpandedBody
- Node.Callee.Accept(Self);
- for arg in Node.Arguments do
- arg.Accept(Self);
- Node.ExpandedBody.Accept(Self);
-
- // Pop children's JSON from stack in reverse order of visitation
- bodyObj := FJsonObjectStack.Pop;
-
- SetLength(tempArgs, Length(Node.Arguments));
- for i := High(tempArgs) downto 0 do
- tempArgs[i] := FJsonObjectStack.Pop;
-
- calleeObj := FJsonObjectStack.Pop;
-
- // Build JSON array for arguments
- argsArray := TJSONArray.Create;
- for var argObj in tempArgs do
- argsArray.Add(argObj);
-
- // Create the final JSON object for this node
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('MacroExpansion'));
- obj.AddPair('Callee', calleeObj);
- obj.AddPair('Arguments', argsArray);
- obj.AddPair('ExpandedBody', bodyObj);
-
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
-end;
-
-function TJsonAstConverter.VisitRecurNode(const Node: IRecurNode): TDataValue;
-var
- obj: TJSONObject;
- argsArray: TJSONArray;
- tempArgs: TArray;
- arg: IAstNode;
- i: Integer;
-begin
- for arg in Node.Arguments do
- arg.Accept(Self);
-
- SetLength(tempArgs, Length(Node.Arguments));
- for i := High(tempArgs) downto 0 do
- tempArgs[i] := FJsonObjectStack.Pop;
+ calleeObj := Accept(Node.Callee);
+ bodyObj := Accept(Node.ExpandedBody);
argsArray := TJSONArray.Create;
- for i := 0 to High(tempArgs) do
- argsArray.Add(tempArgs[i]);
+ for arg in Node.Arguments do
+ argsArray.Add(Accept(arg));
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('Recur'));
- obj.AddPair('Arguments', argsArray);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('MacroExpansion'));
+ Result.AddPair('Callee', calleeObj);
+ Result.AddPair('Arguments', argsArray);
+ Result.AddPair('ExpandedBody', bodyObj);
end;
-function TJsonAstConverter.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
+function TJsonAstConverter.VisitRecurNode(const Node: IRecurNode): TJSONObject;
+var
+ argsArray: TJSONArray;
+ arg: IAstNode;
+begin
+ argsArray := TJSONArray.Create;
+ for arg in Node.Arguments do
+ argsArray.Add(Accept(arg));
+
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('Recur'));
+ Result.AddPair('Arguments', argsArray);
+end;
+
+function TJsonAstConverter.VisitBlockExpression(const Node: IBlockExpressionNode): TJSONObject;
var
- obj: TJSONObject;
exprsArray: TJSONArray;
- tempExprs: TArray;
expr: IAstNode;
- i: Integer;
begin
- for expr in Node.Expressions do
- expr.Accept(Self);
-
- SetLength(tempExprs, Length(Node.Expressions));
- for i := High(tempExprs) downto 0 do
- tempExprs[i] := FJsonObjectStack.Pop;
-
exprsArray := TJSONArray.Create;
- for i := 0 to High(tempExprs) do
- exprsArray.Add(tempExprs[i]);
+ for expr in Node.Expressions do
+ exprsArray.Add(Accept(expr));
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('Block'));
- obj.AddPair('Expressions', exprsArray);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('Block'));
+ Result.AddPair('Expressions', exprsArray);
end;
-function TJsonAstConverter.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
+function TJsonAstConverter.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TJSONObject;
var
- obj, identObj, initObj: TJSONObject;
+ identObj, initObj: TJSONObject;
begin
- Node.Identifier.Accept(Self);
- if Assigned(Node.Initializer) then
- Node.Initializer.Accept(Self);
+ identObj := Accept(Node.Identifier);
+ initObj := Accept(Node.Initializer); // Accept handles nil
- if Assigned(Node.Initializer) then
- initObj := FJsonObjectStack.Pop
- else
- initObj := nil;
- identObj := FJsonObjectStack.Pop;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('VarDecl'));
+ Result.AddPair('Identifier', identObj);
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('VarDecl'));
- obj.AddPair('Identifier', identObj);
if Assigned(initObj) then
- obj.AddPair('Initializer', initObj)
+ Result.AddPair('Initializer', initObj)
else
- obj.AddPair('Initializer', TJSONNull.Create);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result.AddPair('Initializer', TJSONNull.Create);
end;
-function TJsonAstConverter.VisitAssignment(const Node: IAssignmentNode): TDataValue;
+function TJsonAstConverter.VisitAssignment(const Node: IAssignmentNode): TJSONObject;
var
- obj, identObj, valueObj: TJSONObject;
+ identObj, valueObj: TJSONObject;
begin
- Node.Identifier.Accept(Self);
- Node.Value.Accept(Self);
+ identObj := Accept(Node.Identifier);
+ valueObj := Accept(Node.Value);
- valueObj := FJsonObjectStack.Pop;
- identObj := FJsonObjectStack.Pop;
-
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('Assignment'));
- obj.AddPair('Identifier', identObj);
- obj.AddPair('Value', valueObj);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('Assignment'));
+ Result.AddPair('Identifier', identObj);
+ Result.AddPair('Value', valueObj);
end;
-function TJsonAstConverter.VisitIndexer(const Node: IIndexerNode): TDataValue;
+function TJsonAstConverter.VisitIndexer(const Node: IIndexerNode): TJSONObject;
var
- obj, baseObj, indexObj: TJSONObject;
+ baseObj, indexObj: TJSONObject;
begin
- Node.Base.Accept(Self);
- Node.Index.Accept(Self);
+ baseObj := Accept(Node.Base);
+ indexObj := Accept(Node.Index);
- indexObj := FJsonObjectStack.Pop;
- baseObj := FJsonObjectStack.Pop;
-
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('Indexer'));
- obj.AddPair('Base', baseObj);
- obj.AddPair('Index', indexObj);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('Indexer'));
+ Result.AddPair('Base', baseObj);
+ Result.AddPair('Index', indexObj);
end;
-function TJsonAstConverter.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
+function TJsonAstConverter.VisitMemberAccess(const Node: IMemberAccessNode): TJSONObject;
var
- obj, baseObj, memberObj: TJSONObject;
+ baseObj, memberObj: TJSONObject;
begin
- Node.Base.Accept(Self);
- Node.Member.Accept(Self);
+ baseObj := Accept(Node.Base);
+ memberObj := Accept(Node.Member);
- memberObj := FJsonObjectStack.Pop;
- baseObj := FJsonObjectStack.Pop;
-
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('MemberAccess'));
- obj.AddPair('Base', baseObj);
- obj.AddPair('Member', memberObj);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('MemberAccess'));
+ Result.AddPair('Base', baseObj);
+ Result.AddPair('Member', memberObj);
end;
-function TJsonAstConverter.VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue;
+function TJsonAstConverter.VisitRecordLiteral(const Node: IRecordLiteralNode): TJSONObject;
var
- obj, fieldObj: TJSONObject;
fieldsArray: TJSONArray;
field: TRecordFieldLiteral;
+ fieldObj: TJSONObject;
begin
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('RecordLiteral'));
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('RecordLiteral'));
fieldsArray := TJSONArray.Create;
for field in Node.Fields do
begin
- field.Value.Accept(Self); // This pushes the value JSON onto the stack
-
fieldObj := TJSONObject.Create;
fieldObj.AddPair('Name', TJSONString.Create(field.Key.Value.Name));
- fieldObj.AddPair('Value', FJsonObjectStack.Pop);
+ fieldObj.AddPair('Value', Accept(field.Value)); // Get TJSONObject
fieldsArray.Add(fieldObj);
end;
- obj.AddPair('Fields', fieldsArray);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result.AddPair('Fields', fieldsArray);
end;
-function TJsonAstConverter.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
-var
- obj: TJSONObject;
+function TJsonAstConverter.VisitCreateSeries(const Node: ICreateSeriesNode): TJSONObject;
begin
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('CreateSeries'));
- obj.AddPair('Definition', TJSONString.Create(Node.Definition));
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('CreateSeries'));
+ Result.AddPair('Definition', TJSONString.Create(Node.Definition));
end;
-function TJsonAstConverter.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
+function TJsonAstConverter.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TJSONObject;
var
- obj, seriesObj, valueObj, lookbackObj: TJSONObject;
+ seriesObj, valueObj, lookbackObj: TJSONObject;
begin
- Node.Series.Accept(Self);
- Node.Value.Accept(Self);
- if Assigned(Node.Lookback) then
- Node.Lookback.Accept(Self);
+ seriesObj := Accept(Node.Series);
+ valueObj := Accept(Node.Value);
+ lookbackObj := Accept(Node.Lookback); // Accept handles nil
- if Assigned(Node.Lookback) then
- lookbackObj := FJsonObjectStack.Pop
- else
- lookbackObj := nil;
- valueObj := FJsonObjectStack.Pop;
- seriesObj := FJsonObjectStack.Pop;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('AddSeriesItem'));
+ Result.AddPair('Series', seriesObj);
+ Result.AddPair('Value', valueObj);
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('AddSeriesItem'));
- obj.AddPair('Series', seriesObj);
- obj.AddPair('Value', valueObj);
if Assigned(lookbackObj) then
- obj.AddPair('Lookback', lookbackObj)
+ Result.AddPair('Lookback', lookbackObj)
else
- obj.AddPair('Lookback', TJSONNull.Create);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result.AddPair('Lookback', TJSONNull.Create);
end;
-function TJsonAstConverter.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
+function TJsonAstConverter.VisitSeriesLength(const Node: ISeriesLengthNode): TJSONObject;
var
- obj, seriesObj: TJSONObject;
+ seriesObj: TJSONObject;
begin
- Node.Series.Accept(Self);
- seriesObj := FJsonObjectStack.Pop;
+ seriesObj := Accept(Node.Series);
- obj := TJSONObject.Create;
- obj.AddPair('NodeType', TJSONString.Create('SeriesLength'));
- obj.AddPair('Series', seriesObj);
- FJsonObjectStack.Push(obj);
- Result := TDataValue.Void;
+ Result := TJSONObject.Create;
+ Result.AddPair('NodeType', TJSONString.Create('SeriesLength'));
+ Result.AddPair('Series', seriesObj);
end;
{ TJsonAstConverter - Deserialization }
@@ -827,7 +636,7 @@ end;
function TJsonAstConverter.JsonToUnquoteSplicingNode(const AObj: TJSONObject): IUnquoteSplicingNode;
begin
- Result := TAst.UnquoteSplicing(JsonToNode(AObj.GetValue('Expression')));
+ Result := TAst.UnquoteSplicing(JsonToNode(AObj.GetValue('Expression')).AsQuasiquote);
end;
function TJsonAstConverter.JsonToFunctionCallNode(const AObj: TJSONObject): IFunctionCallNode;
@@ -1020,16 +829,12 @@ end;
function TJsonAstConverter.Serialize(const RootNode: IAstNode): TJSONObject;
begin
- FJsonObjectStack.Clear;
if not Assigned(RootNode) then
exit(nil);
- RootNode.Accept(Self);
-
- if FJsonObjectStack.Count <> 1 then
- raise EInvalidOpException.Create('JSON serialization stack is corrupt.');
-
- Result := FJsonObjectStack.Pop;
+ // Call Accept, which returns TDataValue(vkGeneric(TJSONObject))
+ // and unwrap it.
+ Result := RootNode.Accept(Self).AsGeneric;
end;
end.
diff --git a/Src/AST/Myc.Ast.Lowering.pas b/Src/AST/Myc.Ast.Lowering.pas
index d4ec7a7..ee7e2bb 100644
--- a/Src/AST/Myc.Ast.Lowering.pas
+++ b/Src/AST/Myc.Ast.Lowering.pas
@@ -12,8 +12,7 @@ uses
Myc.Ast.Visitor,
Myc.Ast.Scope,
Myc.Ast.Types,
- Myc.Ast,
- Myc.Ast.Binding.Nodes;
+ Myc.Ast;
type
IAstLowerer = interface(IAstVisitor)
@@ -30,7 +29,7 @@ type
function SetType(const Node: IAstNode; const AType: IStaticType): IAstNode;
protected
// Override to find nodes to lower
- function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
+ function VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; override;
public
constructor Create;
destructor Destroy; override;
@@ -50,6 +49,7 @@ uses
constructor TAstLowerer.Create;
var
op: TScalar.TBinaryOp;
+ uOp: TScalar.TUnaryOp; // Added for unary
begin
inherited Create;
@@ -59,7 +59,8 @@ begin
FBinaryOperators.Add(op.ToString, op);
FUnaryOperators := TDictionary.Create;
- FUnaryOperators.Add('not', TScalar.TUnaryOp.Not);
+ for uOp := Low(TScalar.TUnaryOp) to High(TScalar.TUnaryOp) do // Changed
+ FUnaryOperators.Add(uOp.ToString, uOp);
// Note: '-' is handled as a special case in VisitFunctionCall
end;
@@ -78,11 +79,9 @@ end;
function TAstLowerer.Execute(const RootNode: IAstNode): IAstNode;
begin
- var transformedValue := Accept(RootNode);
- if transformedValue.IsVoid then
- Result := TAst.Block([])
- else
- Result := transformedValue.AsIntf;
+ Result := Accept(RootNode); // Use IAstNode-returning Accept
+ if not Assigned(Result) then
+ Result := TAst.Block([]);
if Assigned(Result) then
(Result as TAstNode).StaticType := (Result as TAstNode).StaticType;
@@ -90,25 +89,18 @@ end;
function TAstLowerer.SetType(const Node: IAstNode; const AType: IStaticType): IAstNode;
begin
- (Node as TAstNode).StaticType := AType;
+ if Assigned(Node) then // Add nil check for safety
+ (Node as TAstNode).StaticType := AType;
Result := Node;
end;
-function TAstLowerer.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
+function TAstLowerer.VisitFunctionCall(const Node: IFunctionCallNode): IAstNode;
var
calleeIdentifier: TIdentifierNode;
binaryOp: TScalar.TBinaryOp;
unaryOp: TScalar.TUnaryOp;
left, right: IAstNode;
begin
- // --- Transformation: Keyword-as-Function ---
- // (This logic is correctly handled in TAstBinder)
- if (Node.Callee is TKeywordNode) then
- begin
- // This node should have been transformed by the TAstBinder.
- exit(inherited VisitFunctionCall(Node));
- end;
-
// --- Optimization: Operator Folding ---
if (Node.Callee is TIdentifierNode) then
begin
@@ -118,10 +110,12 @@ begin
begin
if FBinaryOperators.TryGetValue(calleeIdentifier.Name, binaryOp) then
begin
- left := Accept(Node.Arguments[0]).AsIntf;
- right := Accept(Node.Arguments[1]).AsIntf;
+ // Note: We MUST visit children *before* creating the new node
+ left := Accept(Node.Arguments[0]);
+ right := Accept(Node.Arguments[1]);
var binExpr := TAst.BinaryExpr(left, binaryOp, right);
- Result := TDataValue.FromIntf(SetType(binExpr, (Node as TAstNode).StaticType));
+ // Copy metadata (StaticType) from old node to new node
+ Result := SetType(binExpr, (Node as TAstNode).StaticType);
exit;
end;
end;
@@ -130,23 +124,25 @@ begin
begin
if FUnaryOperators.TryGetValue(calleeIdentifier.Name, unaryOp) then
begin
- right := Accept(Node.Arguments[0]).AsIntf;
+ right := Accept(Node.Arguments[0]);
var unExpr := TAst.UnaryExpr(unaryOp, right);
- Result := TDataValue.FromIntf(SetType(unExpr, (Node as TAstNode).StaticType));
+ // Copy metadata
+ Result := SetType(unExpr, (Node as TAstNode).StaticType);
exit;
end;
if (calleeIdentifier.Name = '-') then
begin
- right := Accept(Node.Arguments[0]).AsIntf;
+ right := Accept(Node.Arguments[0]);
var unExpr := TAst.UnaryExpr(TScalar.TUnaryOp.Negate, right);
- Result := TDataValue.FromIntf(SetType(unExpr, (Node as TAstNode).StaticType));
+ // Copy metadata
+ Result := SetType(unExpr, (Node as TAstNode).StaticType);
exit;
end;
end;
end;
- // If no rewrite matched, continue traversal
+ // If no rewrite matched, continue traversal using the base implementation
Result := inherited VisitFunctionCall(Node);
end;
diff --git a/Src/AST/Myc.Ast.MacroExpander.pas b/Src/AST/Myc.Ast.MacroExpander.pas
index 0132c45..dd9f9ab 100644
--- a/Src/AST/Myc.Ast.MacroExpander.pas
+++ b/Src/AST/Myc.Ast.MacroExpander.pas
@@ -12,8 +12,7 @@ uses
Myc.Ast.Visitor,
Myc.Ast.Scope,
Myc.Ast.Types,
- Myc.Ast,
- Myc.Ast.Binding; // Required for TAstBinder.Bind
+ Myc.Ast;
type
IAstMacroExpander = interface(IAstVisitor)
@@ -31,11 +30,12 @@ type
FMacroScope: IExecutionScope;
function TransformAndSpliceNodes(const ANodes: TArray): TArray;
protected
- function VisitUnquote(const Node: IUnquoteNode): TDataValue; override;
- function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue; override;
- function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
- function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
- function VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue; override;
+ // Override the new IAstNode-returning methods
+ function VisitUnquote(const Node: IUnquoteNode): IAstNode; override;
+ function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): IAstNode; override;
+ function VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; override;
+ function VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode; override;
+ function VisitRecordLiteral(const Node: IRecordLiteralNode): IAstNode; override;
public
constructor Create(const AMacroScope: IExecutionScope; const AEvaluate: TEvaluateProc);
class function Expand(const MacroScope: IExecutionScope; const RootNode: IAstNode; const AEvaluate: TEvaluateProc): IAstNode;
@@ -50,11 +50,10 @@ type
FCurrentDescriptor: IScopeDescriptor;
FEvaluatorFactory: TEvaluatorFactory;
protected
- function Accept(const Node: IAstNode): TDataValue; override;
// Finds macro definitions
- function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override;
+ function VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode; override;
// Finds and expands macro calls
- function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
+ function VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; override;
public
constructor Create(const AInitialScope: IExecutionScope; const AEvaluatorFactory: TEvaluatorFactory);
function Execute(const RootNode: IAstNode; out Descriptor: IScopeDescriptor): IAstNode;
@@ -71,6 +70,7 @@ implementation
uses
System.Generics.Defaults,
+ Myc.Ast.Binding, // Required for TAstBinder.Bind
Myc.Ast.Evaluator, // Required for TEvaluatorVisitor.Execute
Myc.Data.Keyword;
@@ -89,14 +89,19 @@ class function TExpansionVisitor.Expand(
const AEvaluate: TEvaluateProc
): IAstNode;
begin
- var expander := TExpansionVisitor.Create(MacroScope, AEvaluate) as IAstTransformer;
- Result := expander.Execute(RootNode);
+ var expander := TExpansionVisitor.Create(MacroScope, AEvaluate);
+ try
+ Result := expander.Accept(RootNode); // Use IAstNode-returning Accept
+ finally
+ expander.Free;
+ end;
end;
function TExpansionVisitor.TransformAndSpliceNodes(const ANodes: TArray): TArray;
var
newList: TList;
nodeToSplice: IAstNode;
+ transformedNode: IAstNode;
begin
newList := TList.Create;
try
@@ -126,9 +131,10 @@ begin
end
else
begin
- var transformedValue := node.Accept(self);
- if not transformedValue.IsVoid then
- newList.Add(transformedValue.AsIntf);
+ // Use the IAstNode-returning Accept helper
+ transformedNode := Self.Accept(node);
+ if Assigned(transformedNode) then
+ newList.Add(transformedNode);
end;
end;
Result := newList.ToArray;
@@ -137,7 +143,7 @@ begin
end;
end;
-function TExpansionVisitor.VisitUnquote(const Node: IUnquoteNode): TDataValue;
+function TExpansionVisitor.VisitUnquote(const Node: IUnquoteNode): IAstNode;
var
value: TDataValue;
expr: IAstNode;
@@ -155,7 +161,7 @@ begin
var argValue := FMacroScope.Values[symbol.Address];
if argValue.Kind = vkInterface then
begin
- Result := argValue;
+ Result := argValue.AsIntf; // Return the node directly
exit;
end;
end;
@@ -167,44 +173,44 @@ begin
// If the result is an AST node (e.g. from a helper function), return it directly.
if value.Kind = vkInterface then
begin
- Result := value;
+ Result := value.AsIntf;
exit;
end;
// If the result is a scalar, text, or void, wrap it in a TConstantNode.
if value.Kind in [vkScalar, vkText, vkVoid] then
begin
- Result := TDataValue.FromIntf(TAst.Constant(value));
+ Result := TAst.Constant(value);
end
else
raise Exception.CreateFmt('Cannot unquote complex runtime value of type %s at compile time.', [value.Kind.ToString]);
end;
-function TExpansionVisitor.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue;
+function TExpansionVisitor.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): IAstNode;
begin
// This should be handled by the caller (VisitFunctionCall / VisitBlockExpression)
raise Exception.Create('Unquote-splicing (`~@`) can only appear inside a list form (e.g., a function call or a `do` block).');
end;
-function TExpansionVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
+function TExpansionVisitor.VisitFunctionCall(const Node: IFunctionCallNode): IAstNode;
var
newArgs: TArray;
transformedCallee: IAstNode;
begin
- transformedCallee := Self.Accept(Node.Callee).AsIntf;
+ transformedCallee := Self.Accept(Node.Callee); // Calls IAstNode helper
newArgs := TransformAndSpliceNodes(Node.Arguments);
- Result := TDataValue.FromIntf(TAst.FunctionCall(transformedCallee, newArgs));
+ Result := TAst.FunctionCall(transformedCallee, newArgs);
end;
-function TExpansionVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
+function TExpansionVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode;
var
newExprs: TArray;
begin
newExprs := TransformAndSpliceNodes(Node.Expressions);
- Result := TDataValue.FromIntf(TAst.Block(newExprs));
+ Result := TAst.Block(newExprs);
end;
-function TExpansionVisitor.VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue;
+function TExpansionVisitor.VisitRecordLiteral(const Node: IRecordLiteralNode): IAstNode;
begin
// Record literals do not support splicing.
// We just use the default TAstTransformer implementation which visits child values.
@@ -238,40 +244,30 @@ end;
function TMacroExpander.Execute(const RootNode: IAstNode; out Descriptor: IScopeDescriptor): IAstNode;
begin
// This executes the transformation (Accept)
- var transformedValue := Accept(RootNode);
+ Result := Accept(RootNode); // Calls the IAstNode-returning helper
- if transformedValue.IsVoid then
- Result := TAst.Block([])
- else
- Result := transformedValue.AsIntf;
+ if not Assigned(Result) then
+ Result := TAst.Block([]); // e.g. if root was (defmacro ...)
Descriptor := FCurrentDescriptor;
end;
-function TMacroExpander.Accept(const Node: IAstNode): TDataValue;
-begin
- // Standard transformer Accept
- if (not Assigned(Node)) or Done then
- exit;
- Result := Node.Accept(Self);
-end;
-
-function TMacroExpander.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
+function TMacroExpander.VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode;
begin
// Register the macro in the current descriptor
FCurrentDescriptor.DefineMacro(Node.Name.Name, Node);
// Remove the (defmacro ...) node from the AST; it's compile-time only.
- Result := TDataValue.Void;
+ Result := nil;
end;
-function TMacroExpander.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
+function TMacroExpander.VisitFunctionCall(const Node: IFunctionCallNode): IAstNode;
var
calleeIdentifier: TIdentifierNode;
macroDef: IMacroDefinitionNode;
i: Integer;
begin
// Check if this is an identifier
- if not (Node.Callee is TIdentifierNode) then
+ if Node.Callee.Kind <> akIdentifier then
exit(inherited VisitFunctionCall(Node));
calleeIdentifier := Node.Callee as TIdentifierNode;
@@ -292,7 +288,7 @@ begin
// 2. Populate scope: Map parameter names to the *un-evaluated* AST nodes
for i := 0 to High(params) do
- expansionScope.Define(params[i].Name, TDataValue.FromIntf(Node.Arguments[i]));
+ expansionScope.Define(params[i].Name, TDataValue.FromIntf(Node.Arguments[i])); // Use FromIntf
// 3. Create the evaluation callback (TEvaluateProc)
var evaluatorProc: TEvaluateProc;
@@ -300,26 +296,33 @@ begin
function(const ANodeToEvaluate: IAstNode): TDataValue
var
subDescriptor: IScopeDescriptor;
+ evalScope: IExecutionScope;
+ evaluator: IEvaluatorVisitor;
+ boundSubAst: IAstNode;
begin
// This is the compile-time evaluation (Binder + Evaluator)
// It runs in the *current* context (FInitialScope + FCurrentDescriptor)
- // not the expansionScope.
var tempInitScope := TScope.CreateScope(FInitialScope.Parent, FCurrentDescriptor, nil);
- var boundSubAst := TAstBinder.Bind(tempInitScope, ANodeToEvaluate, subDescriptor);
- var evalScope := subDescriptor.CreateScope(tempInitScope);
- var evaluator := FEvaluatorFactory(evalScope);
+
+ // Bind (mutates ANodeToEvaluate) and get its descriptor
+ boundSubAst := TAstBinder.Bind(tempInitScope, ANodeToEvaluate, subDescriptor);
+
+ // Create eval scope from the new descriptor
+ evalScope := subDescriptor.CreateScope(tempInitScope);
+
+ evaluator := FEvaluatorFactory(evalScope);
Result := evaluator.Execute(boundSubAst);
end;
// 4. Expand the macro body using the TExpansionVisitor
- var expandedBody := TExpansionVisitor.Expand(expansionScope, macroDef.Body.Expression, evaluatorProc);
+ var expandedBody := TExpansionVisitor.Expand(expansionScope, macroDef.Body.AsUnquoteSplicing.Expression, evaluatorProc);
// 5. Wrap the result in a MacroExpansionNode (for debugging/tracing)
- var macroNode := TMacroExpansionNode.Create(Node, expandedBody);
+ var macroNode := TAst.MacroExpansionNode(Node, expandedBody);
// 6. IMPORTANT: Re-run the expander on the *new* AST fragment
// to handle macros that expand into other macros.
- Result := Self.Accept(macroNode);
+ Result := Self.Accept(macroNode); // Calls the IAstNode helper, returns IAstNode
end;
end.
diff --git a/Src/AST/Myc.Ast.Nodes.pas b/Src/AST/Myc.Ast.Nodes.pas
index ec27a4a..759e84d 100644
--- a/Src/AST/Myc.Ast.Nodes.pas
+++ b/Src/AST/Myc.Ast.Nodes.pas
@@ -38,6 +38,34 @@ type
ISeriesLengthNode = interface;
IRecurNode = interface;
+ // Defines the concrete kinds of AST nodes
+ TAstNodeKind = (
+ akConstant,
+ akIdentifier,
+ akKeyword,
+ akBinaryExpression,
+ akUnaryExpression,
+ akIfExpression,
+ akTernaryExpression,
+ akLambdaExpression,
+ akFunctionCall,
+ akMacroExpansion,
+ akBlockExpression,
+ akVariableDeclaration,
+ akAssignment,
+ akMacroDefinition,
+ akQuasiquote,
+ akUnquote,
+ akUnquoteSplicing,
+ akIndexer,
+ akMemberAccess,
+ akRecordLiteral,
+ akCreateSeries,
+ akAddSeriesItem,
+ akSeriesLength,
+ akRecur
+ );
+
// --- Concrete Type Definitions ---
// Defines how an identifier's address was resolved.
@@ -88,7 +116,37 @@ type
end;
IAstNode = interface(IInterface)
+ {$region 'private'}
+ function GetKind: TAstNodeKind;
+ {$endregion}
function Accept(const Visitor: IAstVisitor): TDataValue;
+
+ function AsConstant: IConstantNode;
+ function AsIdentifier: IIdentifierNode;
+ function AsKeyword: IKeywordNode;
+ function AsBinaryExpression: IBinaryExpressionNode;
+ function AsUnaryExpression: IUnaryExpressionNode;
+ function AsIfExpression: IIfExpressionNode;
+ function AsTernaryExpression: ITernaryExpressionNode;
+ function AsLambdaExpression: ILambdaExpressionNode;
+ function AsFunctionCall: IFunctionCallNode;
+ function AsMacroExpansion: IMacroExpansionNode;
+ function AsBlockExpression: IBlockExpressionNode;
+ function AsVariableDeclaration: IVariableDeclarationNode;
+ function AsAssignment: IAssignmentNode;
+ function AsMacroDefinition: IMacroDefinitionNode;
+ function AsQuasiquote: IQuasiquoteNode;
+ function AsUnquote: IUnquoteNode;
+ function AsUnquoteSplicing: IUnquoteSplicingNode;
+ function AsIndexer: IIndexerNode;
+ function AsMemberAccess: IMemberAccessNode;
+ function AsRecordLiteral: IRecordLiteralNode;
+ function AsCreateSeries: ICreateSeriesNode;
+ function AsAddSeriesItem: IAddSeriesItemNode;
+ function AsSeriesLength: ISeriesLengthNode;
+ function AsRecur: IRecurNode;
+
+ property Kind: TAstNodeKind read GetKind;
end;
IConstantNode = interface(IAstNode)
@@ -221,11 +279,11 @@ type
{$region 'private'}
function GetName: IIdentifierNode;
function GetParameters: TArray;
- function GetBody: IQuasiquoteNode;
+ function GetBody: IAstNode;
{$endregion}
property Name: IIdentifierNode read GetName;
property Parameters: TArray read GetParameters;
- property Body: IQuasiquoteNode read GetBody;
+ property Body: IAstNode read GetBody;
end;
// Represents a quasiquoted expression, e.g., `(a b)
@@ -247,9 +305,9 @@ type
// Represents an unquote-splicing expression, e.g., ~@y
IUnquoteSplicingNode = interface(IAstNode)
{$region 'private'}
- function GetExpression: IAstNode;
+ function GetExpression: IQuasiquoteNode;
{$endregion}
- property Expression: IAstNode read GetExpression;
+ property Expression: IQuasiquoteNode read GetExpression;
end;
IIndexerNode = interface(IAstNode)
diff --git a/Src/AST/Myc.Ast.RTL.Core.pas b/Src/AST/Myc.Ast.RTL.Core.pas
index 014afa1..5942b6c 100644
--- a/Src/AST/Myc.Ast.RTL.Core.pas
+++ b/Src/AST/Myc.Ast.RTL.Core.pas
@@ -278,7 +278,8 @@ begin
raise EArgumentException.Create('The argument to Memoize must be a function.');
// create a managed dictionary
- var cCache: TDataValue := TDictionary.Create;
+ var cCache: TDataValue;
+ cCache.FromObj(TDictionary.Create);
funcToMemoize := Args[0].AsMethod();
diff --git a/Src/AST/Myc.Ast.Script.pas b/Src/AST/Myc.Ast.Script.pas
index 6ed0dec..cd2716d 100644
--- a/Src/AST/Myc.Ast.Script.pas
+++ b/Src/AST/Myc.Ast.Script.pas
@@ -29,7 +29,7 @@ var
atom ::= number | string | identifier | keyword
(* ---------------------------------------------------------------------- *)
- (* ---- Reader-Macros (Syntactic Sugar) ---- *)
+ (* ---- Reader-Macros (Syntactic Sugar) ---- *)
(* ---------------------------------------------------------------------- *)
reader_macro ::= "'" expression (* (quote ...) *)
@@ -38,7 +38,7 @@ var
| "~@" expression (* (unquote-splicing ...) *)
(* ---------------------------------------------------------------------- *)
- (* ---- Lists (S-Expressions) ---- *)
+ (* ---- Lists (S-Expressions) ---- *)
(* ---------------------------------------------------------------------- *)
(* A list is the primary structure for code. Empty lists () are invalid. *)
@@ -64,7 +64,7 @@ var
function_call ::= expression expression*
(* ---------------------------------------------------------------------- *)
- (* ---- Parameter Lists and Records ---- *)
+ (* ---- Parameter Lists and Records ---- *)
(* ---------------------------------------------------------------------- *)
(* A parameter list is *only* valid inside 'fn' and 'defmacro' *)
@@ -181,6 +181,7 @@ type
// --- Internal Printer Implementation ---
+ // Inherits from the new non-generic TAstVisitor
TPrettyPrintVisitor = class(TAstVisitor)
private
FBuilder: TStringBuilder;
@@ -193,32 +194,33 @@ type
constructor Create;
destructor Destroy; override;
function GetResult: string;
- // IAstVisitor
+ // Helper
function Execute(const RootNode: IAstNode): TDataValue;
- function VisitConstant(const Node: IConstantNode): TDataValue; override;
- function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
- function VisitKeyword(const Node: IKeywordNode): 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 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 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 VisitIndexer(const Node: IIndexerNode): TDataValue; override;
- function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
- function VisitRecordLiteral(const Node: IRecordLiteralNode): 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;
+ // Override abstract procedures from TAstVisitor
+ procedure VisitConstant(const Node: IConstantNode); override;
+ procedure VisitIdentifier(const Node: IIdentifierNode); override;
+ procedure VisitKeyword(const Node: IKeywordNode); override;
+ procedure VisitBinaryExpression(const Node: IBinaryExpressionNode); override;
+ procedure VisitUnaryExpression(const Node: IUnaryExpressionNode); override;
+ procedure VisitIfExpression(const Node: IIfExpressionNode); override;
+ procedure VisitTernaryExpression(const Node: ITernaryExpressionNode); override;
+ procedure VisitLambdaExpression(const Node: ILambdaExpressionNode); override;
+ procedure VisitMacroDefinition(const Node: IMacroDefinitionNode); override;
+ procedure VisitQuasiquote(const Node: IQuasiquoteNode); override;
+ procedure VisitUnquote(const Node: IUnquoteNode); override;
+ procedure VisitUnquoteSplicing(const Node: IUnquoteSplicingNode); override;
+ procedure VisitFunctionCall(const Node: IFunctionCallNode); override;
+ procedure VisitMacroExpansionNode(const Node: IMacroExpansionNode); override;
+ procedure VisitBlockExpression(const Node: IBlockExpressionNode); override;
+ procedure VisitVariableDeclaration(const Node: IVariableDeclarationNode); override;
+ procedure VisitAssignment(const Node: IAssignmentNode); override;
+ procedure VisitIndexer(const Node: IIndexerNode); override;
+ procedure VisitMemberAccess(const Node: IMemberAccessNode); override;
+ procedure VisitRecordLiteral(const Node: IRecordLiteralNode); override;
+ procedure VisitCreateSeries(const Node: ICreateSeriesNode); override;
+ procedure VisitAddSeriesItem(const Node: IAddSeriesItemNode); override;
+ procedure VisitSeriesLength(const Node: ISeriesLengthNode); override;
+ procedure VisitRecurNode(const Node: IRecurNode); override;
end;
{ TLexer }
@@ -592,7 +594,7 @@ begin
if (Length(tailNodes) <> 3) or (tailTokens[0].Kind <> tkIdentifier) then
raise Exception.Create('Syntax Error: ''defmacro'' requires a name, a parameter list, and a body.');
- var macroName := IIdentifierNode(tailNodes[0]);
+ var macroName := tailNodes[0].AsIdentifier;
var macroParams := elements[2].Params;
if tailTokens[2].Kind <> tkBacktick then
@@ -670,7 +672,7 @@ begin
begin
NextToken;
expr := ParseExpression;
- Result.Node := TAst.UnquoteSplicing(expr.Node);
+ Result.Node := TAst.UnquoteSplicing(expr.Node.AsQuasiquote);
end
else
begin
@@ -781,7 +783,7 @@ begin
Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitConstant(const Node: IConstantNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitConstant(const Node: IConstantNode);
var
val: TDataValue;
begin
@@ -790,22 +792,19 @@ begin
Append('"' + val.AsText + '"')
else
Append(val.ToString);
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitIdentifier(const Node: IIdentifierNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitIdentifier(const Node: IIdentifierNode);
begin
Append(Node.Name);
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitKeyword(const Node: IKeywordNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitKeyword(const Node: IKeywordNode);
begin
Append(':' + Node.Value.Name);
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode);
begin
Append('(' + Node.Operator.ToString);
Append(' ');
@@ -813,19 +812,17 @@ begin
Append(' ');
Node.Right.Accept(Self);
Append(')');
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode);
begin
Append('(' + Node.Operator.ToString);
Append(' ');
Node.Right.Accept(Self);
Append(')');
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitIfExpression(const Node: IIfExpressionNode);
begin
Append('(if ');
Node.Condition.Accept(Self);
@@ -840,10 +837,9 @@ begin
Unindent;
NewLine;
Append(')');
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode);
begin
Append('(? ');
Node.Condition.Accept(Self);
@@ -855,17 +851,15 @@ begin
Unindent;
NewLine;
Append(')');
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode);
var
- param: IIdentifierNode;
sb: TStringBuilder;
begin
sb := TStringBuilder.Create;
try
- for param in Node.Parameters do
+ for var param in Node.Parameters do
sb.Append(param.Name + ' ');
if sb.Length > 0 then
sb.Remove(sb.Length - 1, 1); // remove trailing space
@@ -881,17 +875,15 @@ begin
Unindent;
NewLine;
Append(')');
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode);
var
- param: IIdentifierNode;
sb: TStringBuilder;
begin
sb := TStringBuilder.Create;
try
- for param in Node.Parameters do
+ for var param in Node.Parameters do
sb.Append(param.Name + ' ');
if sb.Length > 0 then
sb.Remove(sb.Length - 1, 1);
@@ -907,33 +899,29 @@ begin
Unindent;
NewLine;
Append(')');
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitQuasiquote(const Node: IQuasiquoteNode);
begin
Append('`');
Node.Expression.Accept(Self);
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitUnquote(const Node: IUnquoteNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitUnquote(const Node: IUnquoteNode);
begin
Append('~');
Node.Expression.Accept(Self);
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode);
begin
// To handle '~@', we need to check if the expression is an identifier '@'.
// However, the parser logic now handles this, so we just print '~@'.
Append('~@');
Node.Expression.Accept(Self);
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitFunctionCall(const Node: IFunctionCallNode);
var
arg: IAstNode;
begin
@@ -942,7 +930,7 @@ begin
begin
Append('''');
Node.Arguments[0].Accept(Self);
- exit(TDataValue.Void);
+ exit;
end;
Append('(');
@@ -957,17 +945,16 @@ begin
Unindent;
Append(')');
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitMacroExpansionNode(const Node: IMacroExpansionNode);
begin
// For pretty-printing, show the original macro call, not the expanded body.
// Delegate to the regular VisitFunctionCall to print it as such.
- Result := VisitFunctionCall(Node);
+ VisitFunctionCall(Node);
end;
-function TPrettyPrintVisitor.VisitRecurNode(const Node: IRecurNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitRecurNode(const Node: IRecurNode);
var
arg: IAstNode;
begin
@@ -981,10 +968,9 @@ begin
Unindent;
Append(')');
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitBlockExpression(const Node: IBlockExpressionNode);
var
expr: IAstNode;
begin
@@ -998,10 +984,9 @@ begin
Unindent;
NewLine;
Append(')');
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode);
begin
Append('(def ');
Node.Identifier.Accept(Self);
@@ -1011,47 +996,43 @@ begin
Node.Initializer.Accept(Self);
end;
Append(')');
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitAssignment(const Node: IAssignmentNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitAssignment(const Node: IAssignmentNode);
begin
Append('(assign ');
Node.Identifier.Accept(Self);
Append(' ');
Node.Value.Accept(Self);
Append(')');
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitIndexer(const Node: IIndexerNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitIndexer(const Node: IIndexerNode);
begin
Append('(get ');
Node.Base.Accept(Self);
Append(' ');
Node.Index.Accept(Self);
Append(')');
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitMemberAccess(const Node: IMemberAccessNode);
begin
Append('(.');
Node.Member.Accept(Self);
Append(' ');
Node.Base.Accept(Self);
Append(')');
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitRecordLiteral(const Node: IRecordLiteralNode);
var
field: TRecordFieldLiteral;
begin
if Length(Node.Fields) = 0 then
begin
Append('{}');
- exit(TDataValue.Void);
+ exit;
end;
Append('{');
@@ -1066,16 +1047,14 @@ begin
Unindent;
NewLine;
Append('}');
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitCreateSeries(const Node: ICreateSeriesNode);
begin
Append(Format('(new-series "%s")', [Node.Definition]));
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode);
begin
Append('(add-item ');
Node.Series.Accept(Self);
@@ -1087,15 +1066,13 @@ begin
Node.Lookback.Accept(Self);
end;
Append(')');
- Result := TDataValue.Void;
end;
-function TPrettyPrintVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
+procedure TPrettyPrintVisitor.VisitSeriesLength(const Node: ISeriesLengthNode);
begin
Append('(count ');
Node.Series.Accept(Self);
Append(')');
- Result := TDataValue.Void;
end;
{ TAstScript }
diff --git a/Src/AST/Myc.Ast.TypeChecker.pas b/Src/AST/Myc.Ast.TypeChecker.pas
index f06f91a..c49f4d7 100644
--- a/Src/AST/Myc.Ast.TypeChecker.pas
+++ b/Src/AST/Myc.Ast.TypeChecker.pas
@@ -12,8 +12,7 @@ uses
Myc.Ast.Visitor,
Myc.Ast.Scope,
Myc.Ast.Types,
- Myc.Ast,
- Myc.Ast.Binding.Nodes;
+ Myc.Ast;
type
IAstTypeChecker = interface(IAstVisitor)
@@ -27,33 +26,34 @@ type
TTypeChecker = class(TAstTransformer, IAstTypeChecker)
private
FCurrentDescriptor: IScopeDescriptor;
- function SetType(const NodeData: TDataValue; const AType: IStaticType): TDataValue;
+ function SetType(const Node: IAstNode; const AType: IStaticType): IAstNode;
protected
// Override all visit methods to perform type checking
- function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
- function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; override;
- function VisitAssignment(const Node: IAssignmentNode): TDataValue; override;
- function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; override;
- function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; override;
- function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; override;
- function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; override;
- function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; override;
- function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; override;
- function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; override;
- function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; override;
- function VisitIndexer(const Node: IIndexerNode): TDataValue; override;
- function VisitRecordLiteral(const Node: IRecordLiteralNode): 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;
+ function VisitIdentifier(const Node: IIdentifierNode): IAstNode; override;
+ function VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode; override;
+ function VisitAssignment(const Node: IAssignmentNode): IAstNode; override;
+ function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override;
+ function VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; override;
+ function VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode; override;
+ function VisitIfExpression(const Node: IIfExpressionNode): IAstNode; override;
+ function VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode; override;
+ function VisitBinaryExpression(const Node: IBinaryExpressionNode): IAstNode; override;
+ function VisitUnaryExpression(const Node: IUnaryExpressionNode): IAstNode; override;
+ function VisitMemberAccess(const Node: IMemberAccessNode): IAstNode; override;
+ function VisitIndexer(const Node: IIndexerNode): IAstNode; override;
+ function VisitRecordLiteral(const Node: IRecordLiteralNode): IAstNode; override;
+ function VisitCreateSeries(const Node: ICreateSeriesNode): IAstNode; override;
+ function VisitAddSeriesItem(const Node: IAddSeriesItemNode): IAstNode; override;
+ function VisitSeriesLength(const Node: ISeriesLengthNode): IAstNode; override;
+ function VisitRecurNode(const Node: IRecurNode): IAstNode; override;
+
+ // Base cases (types are already set by Binder)
+ function VisitConstant(const Node: IConstantNode): IAstNode; override;
+ function VisitKeyword(const Node: IKeywordNode): IAstNode; override;
- // Base cases (types are already known from binder)
- function VisitConstant(const Node: IConstantNode): TDataValue; override;
- function VisitKeyword(const Node: IKeywordNode): TDataValue; override;
// Compile-time nodes (should not be present)
- function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue; override;
- function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; override;
+ function VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode; override;
+ function VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode; override;
public
constructor Create(const ADescriptor: IScopeDescriptor);
function Execute(const RootNode: IAstNode; const ADescriptor: IScopeDescriptor): IAstNode;
@@ -85,165 +85,166 @@ end;
function TTypeChecker.Execute(const RootNode: IAstNode; const ADescriptor: IScopeDescriptor): IAstNode;
begin
FCurrentDescriptor := ADescriptor;
- var transformedValue := Accept(RootNode);
- if transformedValue.IsVoid then
- Result := TAst.Block([])
- else
- Result := transformedValue.AsIntf;
- (Result as TAstNode).StaticType := (Result as TAstNode).StaticType;
+ Result := Accept(RootNode); // Use IAstNode-returning Accept
+ if not Assigned(Result) then
+ Result := TAst.Block([]);
+
+ // (Result as TAstNode).StaticType is set by the last Visit call
end;
-function TTypeChecker.SetType(const NodeData: TDataValue; const AType: IStaticType): TDataValue;
+function TTypeChecker.SetType(const Node: IAstNode; const AType: IStaticType): IAstNode;
begin
- if (not NodeData.IsVoid) and (NodeData.Kind = vkInterface) then
- (NodeData.AsIntf as TAstNode).StaticType := AType;
- Result := NodeData;
+ if Assigned(Node) then
+ (Node as TAstNode).StaticType := AType;
+ Result := Node;
end;
-function TTypeChecker.VisitConstant(const Node: IConstantNode): TDataValue;
+function TTypeChecker.VisitConstant(const Node: IConstantNode): IAstNode;
begin
// Type was set by Binder, just propagate it up.
- Result := TDataValue.FromIntf(Node);
+ Result := inherited VisitConstant(Node);
end;
-function TTypeChecker.VisitKeyword(const Node: IKeywordNode): TDataValue;
+function TTypeChecker.VisitKeyword(const Node: IKeywordNode): IAstNode;
begin
// Type was set by Binder, just propagate it up.
- Result := TDataValue.FromIntf(Node);
+ Result := inherited VisitKeyword(Node);
end;
-function TTypeChecker.VisitIdentifier(const Node: IIdentifierNode): TDataValue;
+function TTypeChecker.VisitIdentifier(const Node: IIdentifierNode): IAstNode;
begin
// Type was set by Binder (read from scope), just propagate it up.
- Result := TDataValue.FromIntf(Node);
+ Result := inherited VisitIdentifier(Node);
end;
-function TTypeChecker.VisitRecurNode(const Node: IRecurNode): TDataValue;
+function TTypeChecker.VisitRecurNode(const Node: IRecurNode): IAstNode;
begin
// Type was set by Binder (TTypes.Void), just propagate it up.
- Result := TDataValue.FromIntf(Node);
+ Result := inherited VisitRecurNode(Node);
end;
-function TTypeChecker.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
+function TTypeChecker.VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode;
begin
raise Exception.Create('TTypeChecker: MacroDefinition node encountered.');
end;
-function TTypeChecker.VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
+function TTypeChecker.VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode;
begin
- raise Exception.Create('TTypeChecker: MacroExpansionNode node encountered.');
+ // TypeChecker runs *after* expansion, so we just visit the body.
+ Result := Accept(Node.ExpandedBody);
end;
-function TTypeChecker.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
+function TTypeChecker.VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode;
var
- initNode: IAstNode;
initType: IStaticType;
- boundIdent: TBoundIdentifierNode;
+ boundIdent: TIdentifierNode;
adr: TResolvedAddress;
begin
- // 1. Visit the initializer (if it exists) to get its (now-inferred) type.
+ // 1. Visit children first (Identifier is leaf, Initializer is traversed)
+ inherited;
+
+ // 2. Get initializer type
if Assigned(Node.Initializer) then
- begin
- initNode := Accept(Node.Initializer).AsIntf;
- initType := (initNode as TAstNode).StaticType;
- end
+ initType := (Node.Initializer as TAstNode).StaticType
else
initType := TTypes.Void;
- // 2. Get the address from the bound identifier.
- boundIdent := (Node.Identifier as TBoundIdentifierNode);
+ // 3. Get the address from the bound identifier.
+ boundIdent := (Node.Identifier as TIdentifierNode);
adr := boundIdent.Address;
- // 3. Update the type in the scope descriptor (which was set to Unknown by the binder).
+ // 4. Update the type in the scope descriptor (which was set to Unknown by the binder).
FCurrentDescriptor.UpdateType(adr.SlotIndex, initType);
- // 4. Update the static types of the nodes themselves.
+ // 5. Update the static types of the nodes themselves.
(boundIdent as TAstNode).StaticType := initType;
- Result := SetType(TDataValue.FromIntf(Node), initType);
+ Result := SetType(Node, initType);
end;
-function TTypeChecker.VisitAssignment(const Node: IAssignmentNode): TDataValue;
+function TTypeChecker.VisitAssignment(const Node: IAssignmentNode): IAstNode;
var
- boundIdentifier, boundValue: IAstNode;
targetType, sourceType: IStaticType;
begin
- boundIdentifier := Accept(Node.Identifier).AsIntf;
- boundValue := Accept(Node.Value).AsIntf;
+ // 1. Visit children first (Identifier, Value)
+ inherited;
- targetType := (boundIdentifier as TAstNode).StaticType;
- sourceType := (boundValue as TAstNode).StaticType;
+ // 2. Get types
+ targetType := (Node.Identifier as TAstNode).StaticType;
+ sourceType := (Node.Value as TAstNode).StaticType;
+ // 3. Check assignment
if not TTypeRules.CanAssign(targetType, sourceType) then
raise ETypeException.CreateFmt('Cannot assign type %s to %s', [sourceType.ToString, targetType.ToString]);
- Result := SetType(TDataValue.FromIntf(Node), targetType);
+ Result := SetType(Node, targetType);
end;
-function TTypeChecker.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
+function TTypeChecker.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
var
- boundNode: TBoundLambdaExpressionNode;
- boundBody: IAstNode;
+ boundNode: TLambdaExpressionNode;
bodyType, methodType: IStaticType;
paramTypes: TArray;
i: Integer;
+ savedDescriptor: IScopeDescriptor;
begin
- boundNode := (Node as TBoundLambdaExpressionNode);
+ boundNode := (Node as TLambdaExpressionNode);
- // 1. Enter the lambda's scope
+ // 1. Enter the lambda's scope (which Binder already created)
+ savedDescriptor := FCurrentDescriptor;
FCurrentDescriptor := boundNode.ScopeDescriptor;
try
- // 2. Set parameter types (currently Unknown, but required for signature)
+ // 2. Parameters are leaves, so we don't try to evaluate them
+
+ // 3. Get parameter types (currently Unknown, but required for signature)
SetLength(paramTypes, Length(boundNode.Parameters));
for i := 0 to High(boundNode.Parameters) do
paramTypes[i] := (boundNode.Parameters[i] as TAstNode).StaticType; // Propagates Unknown
- // 3. Visit the body to infer its return type
- boundBody := Accept(boundNode.Body).AsIntf;
- bodyType := (boundBody as TAstNode).StaticType;
+ // 4. Visit the body to infer its return type
+ Accept(boundNode.Body);
+ bodyType := (boundNode.Body as TAstNode).StaticType;
- // 4. Create the final method type
+ // 5. Create the final method type
methodType := TTypes.CreateMethod(paramTypes, bodyType);
- // 5. Update the type for (Slot 0) in the descriptor
+ // 6. Update the type for (Slot 0) in the descriptor
FCurrentDescriptor.UpdateType(0, methodType);
finally
- // 6. Restore parent descriptor
- FCurrentDescriptor := FCurrentDescriptor.Parent;
+ // 7. Restore parent descriptor
+ FCurrentDescriptor := savedDescriptor;
end;
- // 7. Set the type of the lambda node itself
- Result := SetType(TDataValue.FromIntf(boundNode), methodType);
+ // 8. Set the type of the lambda node itself
+ Result := SetType(boundNode, methodType);
end;
-function TTypeChecker.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
+function TTypeChecker.VisitFunctionCall(const Node: IFunctionCallNode): IAstNode;
var
- callee: IAstNode;
- args: TArray;
calleeType, retType: IStaticType;
i: Integer;
begin
// 1. Visit children first (bottom-up)
- callee := Accept(Node.Callee).AsIntf;
- args := AcceptNodes(Node.Arguments);
+ inherited;
// 2. Get callee type (now inferred)
- calleeType := (callee as TAstNode).StaticType;
+ calleeType := (Node.Callee as TAstNode).StaticType;
retType := TTypes.Unknown; // Default if not a method
// 3. Perform type checking
if calleeType.Kind = TStaticTypeKind.stMethod then
begin
var signature := calleeType.Signature;
- if Length(args) <> Length(signature.ParamTypes) then
- raise ETypeException.CreateFmt('Function expects %d arguments, but got %d', [Length(signature.ParamTypes), Length(args)]);
+ if Length(Node.Arguments) <> Length(signature.ParamTypes) then
+ raise ETypeException
+ .CreateFmt('Function expects %d arguments, but got %d', [Length(signature.ParamTypes), Length(Node.Arguments)]);
retType := signature.ReturnType;
// Check argument types
- for i := 0 to High(args) do
+ for i := 0 to High(Node.Arguments) do
begin
- var argType := (args[i] as TAstNode).StaticType;
+ var argType := (Node.Arguments[i] as TAstNode).StaticType;
var paramType := signature.ParamTypes[i];
if not TTypeRules.CanAssign(paramType, argType) then
raise ETypeException
@@ -254,99 +255,111 @@ begin
raise ETypeException.CreateFmt('Cannot invoke type %s as a function.', [calleeType.ToString]);
// 4. Set the type for this call node
- Result := SetType(TDataValue.FromIntf(Node), retType);
+ Result := SetType(Node, retType);
end;
-function TTypeChecker.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
+function TTypeChecker.VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode;
var
blockType: IStaticType;
- exprs: TArray;
begin
- exprs := AcceptNodes(Node.Expressions);
+ // 1. Visit children
+ inherited;
- if Length(exprs) > 0 then
- blockType := (exprs[High(exprs)] as TAstNode).StaticType
+ // 2. Type is type of last expression
+ if Length(Node.Expressions) > 0 then
+ blockType := (Node.Expressions[High(Node.Expressions)] as TAstNode).StaticType
else
blockType := TTypes.Void;
- Result := SetType(TDataValue.FromIntf(Node), blockType);
+ Result := SetType(Node, blockType);
end;
-function TTypeChecker.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
+function TTypeChecker.VisitIfExpression(const Node: IIfExpressionNode): IAstNode;
var
- condition, thenBranch, elseBranch: IAstNode;
conditionType, thenType, elseType, resultType: IStaticType;
begin
- condition := Accept(Node.Condition).AsIntf;
- thenBranch := Accept(Node.ThenBranch).AsIntf;
- elseBranch := Accept(Node.ElseBranch).AsIntf; // Accept(nil) returns void
+ // 1. Visit children
+ inherited;
- conditionType := (condition as TAstNode).StaticType;
+ // 2. Check condition
+ conditionType := (Node.Condition as TAstNode).StaticType;
if (conditionType.Kind <> stUnknown) and not TTypeRules.CanAssign(TTypes.Ordinal, conditionType) then
raise ETypeException.CreateFmt('If condition must be Ordinal, but got %s', [conditionType.ToString]);
- thenType := (thenBranch as TAstNode).StaticType;
+ // 3. Promote branch types
+ thenType := (Node.ThenBranch as TAstNode).StaticType;
elseType :=
- if elseBranch <> nil then (elseBranch as TAstNode).StaticType
+ if Node.ElseBranch <> nil then (Node.ElseBranch as TAstNode).StaticType
else TTypes.Void;
resultType := TTypeRules.Promote(thenType, elseType);
- Result := SetType(TDataValue.FromIntf(Node), resultType);
+ Result := SetType(Node, resultType);
end;
-function TTypeChecker.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
+function TTypeChecker.VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode;
var
- condition, thenBranch, elseBranch: IAstNode;
conditionType, thenType, elseType, resultType: IStaticType;
begin
- condition := Accept(Node.Condition).AsIntf;
- thenBranch := Accept(Node.ThenBranch).AsIntf;
- elseBranch := Accept(Node.ElseBranch).AsIntf;
+ // 1. Visit children
+ inherited;
- conditionType := (condition as TAstNode).StaticType;
+ // 2. Check condition
+ conditionType := (Node.Condition as TAstNode).StaticType;
if (conditionType.Kind <> stUnknown) and not TTypeRules.CanAssign(TTypes.Ordinal, conditionType) then
raise ETypeException.CreateFmt('Ternary condition must be Ordinal, but got %s', [conditionType.ToString]);
- thenType := (thenBranch as TAstNode).StaticType;
- elseType := (elseBranch as TAstNode).StaticType;
+ // 3. Promote branch types
+ thenType := (Node.ThenBranch as TAstNode).StaticType;
+ elseType := (Node.ElseBranch as TAstNode).StaticType;
+
resultType := TTypeRules.Promote(thenType, elseType);
- Result := SetType(TDataValue.FromIntf(Node), resultType);
+ Result := SetType(Node, resultType);
end;
-function TTypeChecker.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
+function TTypeChecker.VisitBinaryExpression(const Node: IBinaryExpressionNode): IAstNode;
var
- left, right: IAstNode;
leftType, rightType, resultType: IStaticType;
begin
- left := Accept(Node.Left).AsIntf;
- right := Accept(Node.Right).AsIntf;
- leftType := (left as TAstNode).StaticType;
- rightType := (right as TAstNode).StaticType;
+ // 1. Visit children
+ inherited;
+
+ // 2. Get types
+ leftType := (Node.Left as TAstNode).StaticType;
+ rightType := (Node.Right as TAstNode).StaticType;
+
+ // 3. Resolve
resultType := TTypeRules.ResolveBinaryOp(Node.Operator, leftType, rightType);
- Result := SetType(TDataValue.FromIntf(Node), resultType);
+ Result := SetType(Node, resultType);
end;
-function TTypeChecker.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
+function TTypeChecker.VisitUnaryExpression(const Node: IUnaryExpressionNode): IAstNode;
var
- right: IAstNode;
rightType, resultType: IStaticType;
begin
- right := Accept(Node.Right).AsIntf;
- rightType := (right as TAstNode).StaticType;
+ // 1. Visit children
+ inherited;
+
+ // 2. Get types
+ rightType := (Node.Right as TAstNode).StaticType;
+
+ // 3. Resolve
resultType := TTypeRules.ResolveUnaryOp(Node.Operator, rightType);
- Result := SetType(TDataValue.FromIntf(Node), resultType);
+ Result := SetType(Node, resultType);
end;
-function TTypeChecker.VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
+function TTypeChecker.VisitMemberAccess(const Node: IMemberAccessNode): IAstNode;
var
- baseNode: IAstNode;
baseType, elemType: IStaticType;
fieldIndex: Integer;
begin
- baseNode := Accept(Node.Base).AsIntf;
- baseType := (baseNode as TAstNode).StaticType;
+ // 1. Visit children
+ inherited;
+ // 2. Get types
+ baseType := (Node.Base as TAstNode).StaticType;
elemType := TTypes.Unknown;
+
+ // 3. Resolve
if (baseType.Kind <> TStaticTypeKind.stUnknown) then
begin
if (baseType.Kind = TStaticTypeKind.stRecord) or (baseType.Kind = TStaticTypeKind.stRecordSeries) then
@@ -376,20 +389,22 @@ begin
end;
end;
- Result := SetType(TDataValue.FromIntf(Node), elemType);
+ Result := SetType(Node, elemType);
end;
-function TTypeChecker.VisitIndexer(const Node: IIndexerNode): TDataValue;
+function TTypeChecker.VisitIndexer(const Node: IIndexerNode): IAstNode;
var
- baseNode, indexNode: IAstNode;
baseType, indexType, elemType: IStaticType;
begin
- baseNode := Accept(Node.Base).AsIntf;
- indexNode := Accept(Node.Index).AsIntf;
- baseType := (baseNode as TAstNode).StaticType;
- indexType := (indexNode as TAstNode).StaticType;
+ // 1. Visit children
+ inherited;
+ // 2. Get types
+ baseType := (Node.Base as TAstNode).StaticType;
+ indexType := (Node.Index as TAstNode).StaticType;
elemType := TTypes.Unknown;
+
+ // 3. Resolve
if (baseType.Kind <> TStaticTypeKind.stUnknown) then
begin
if (baseType.Kind <> TStaticTypeKind.stSeries) and (baseType.Kind <> TStaticTypeKind.stRecordSeries) then
@@ -404,13 +419,12 @@ begin
elemType := TTypes.CreateRecord(baseType.Definition);
end;
- Result := SetType(TDataValue.FromIntf(Node), elemType);
+ Result := SetType(Node, elemType);
end;
-function TTypeChecker.VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue;
+function TTypeChecker.VisitRecordLiteral(const Node: IRecordLiteralNode): IAstNode;
var
i: Integer;
- boundFields: TArray;
scalarDefFields: TArray;
def: IScalarRecordDefinition;
staticType: IStaticType;
@@ -418,19 +432,22 @@ var
valType: IStaticType;
scalarKind: TScalar.TKind;
allScalar: Boolean;
+ N: TGenericRecordLiteralNode; // Parser creates this type
begin
- SetLength(boundFields, Length(Node.Fields));
- SetLength(scalarDefFields, Length(Node.Fields));
+ // 1. Visit all child nodes first to infer their types
+ inherited;
+
+ N := (Node as TGenericRecordLiteralNode);
+
+ SetLength(scalarDefFields, Length(N.Fields));
allScalar := True;
- // 1. Visit all child nodes first to infer their types
- for i := 0 to High(Node.Fields) do
+ // 2. Check if this record literal can be a TScalarRecord
+ for i := 0 to High(N.Fields) do
begin
- valNode := Accept(Node.Fields[i].Value).AsIntf;
+ valNode := N.Fields[i].Value;
valType := (valNode as TAstNode).StaticType;
- boundFields[i] := TRecordFieldLiteral.Create(Node.Fields[i].Key, valNode);
- // 2. Check if this field fits the scalar path
if (valType.Kind = stOrdinal) then
scalarKind := TScalar.TKind.Ordinal
else if (valType.Kind = stFloat) then
@@ -444,51 +461,51 @@ begin
end;
if allScalar then
- scalarDefFields[i] := TScalarRecordField.Create(Node.Fields[i].Key.Value, scalarKind);
+ scalarDefFields[i] := TScalarRecordField.Create(N.Fields[i].Key.Value, scalarKind);
end;
- // 3. Create the appropriate record type (Scalar or Generic)
+ // 3. Create the appropriate record type (Scalar or Generic) and mutate the node
if allScalar then
begin
def := TScalarRecordRegistry.Intern(scalarDefFields);
staticType := TTypes.CreateRecord(def);
- // We can re-use the TBoundRecordLiteralNode from the binder
- (Node as TBoundRecordLiteralNode).Definition := def;
+ N.Definition := def; // Mutate
+ N.GenericDefinition := nil; // Mutate
end
else
begin
var genDefFields: TArray>;
- SetLength(genDefFields, Length(boundFields));
- for i := 0 to High(boundFields) do
- genDefFields[i] := TPair.Create(boundFields[i].Key.Value, (boundFields[i].Value as TAstNode).StaticType);
+ SetLength(genDefFields, Length(N.Fields));
+ for i := 0 to High(N.Fields) do
+ genDefFields[i] := TPair.Create(N.Fields[i].Key.Value, (N.Fields[i].Value as TAstNode).StaticType);
var genDef := TGenericRecordRegistry.Intern(genDefFields);
staticType := TTypes.CreateGenericRecord(genDef);
- // Re-use the TBoundGenericRecordLiteralNode from the binder
- (Node as TBoundGenericRecordLiteralNode).Definition := genDef;
+ N.GenericDefinition := genDef; // Mutate
+ N.Definition := nil; // Mutate
end;
- Result := SetType(TDataValue.FromIntf(Node), staticType);
+ Result := SetType(N, staticType);
end;
-function TTypeChecker.VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
+function TTypeChecker.VisitCreateSeries(const Node: ICreateSeriesNode): IAstNode;
begin
// Type was set by Binder, just propagate it up.
- Result := TDataValue.FromIntf(Node);
+ Result := inherited VisitCreateSeries(Node);
end;
-function TTypeChecker.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
+function TTypeChecker.VisitAddSeriesItem(const Node: IAddSeriesItemNode): IAstNode;
var
- seriesNode, valueNode, lookbackNode: IAstNode;
seriesType, valueType: IStaticType;
begin
- seriesNode := Accept(Node.Series).AsIntf;
- valueNode := Accept(Node.Value).AsIntf;
- lookbackNode := Accept(Node.Lookback).AsIntf;
+ // 1. Visit children
+ inherited;
- seriesType := (seriesNode as TAstNode).StaticType;
- valueType := (valueNode as TAstNode).StaticType;
+ // 2. Get types
+ seriesType := (Node.Series as TAstNode).StaticType;
+ valueType := (Node.Value as TAstNode).StaticType;
+ // 3. Check types
if (seriesType.Kind <> stUnknown) then
begin
if (seriesType.Kind <> TStaticTypeKind.stSeries) then
@@ -499,30 +516,33 @@ begin
.CreateFmt('Cannot add item of type %s to series of type %s', [valueType.ToString, seriesType.ElementType.ToString]);
end;
- if (lookbackNode <> nil) then
+ if (Node.Lookback <> nil) then
begin
- var lookbackType := (lookbackNode as TAstNode).StaticType;
+ var lookbackType := (Node.Lookback as TAstNode).StaticType;
if (lookbackType.Kind <> stUnknown) and not (lookbackType.Kind = TStaticTypeKind.stOrdinal) then
raise ETypeException.Create('Lookback parameter for "add" must be an ordinal value.');
end;
- Result := SetType(TDataValue.FromIntf(Node), TTypes.Void);
+ Result := SetType(Node, TTypes.Void);
end;
-function TTypeChecker.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
+function TTypeChecker.VisitSeriesLength(const Node: ISeriesLengthNode): IAstNode;
var
- seriesNode: IAstNode;
seriesType: IStaticType;
begin
- seriesNode := Accept(Node.Series).AsIntf;
- seriesType := (seriesNode as TAstNode).StaticType;
+ // 1. Visit children
+ inherited;
+ // 2. Get type
+ seriesType := (Node.Series as TAstNode).StaticType;
+
+ // 3. Check type
if (seriesType.Kind <> stUnknown)
and (seriesType.Kind <> TStaticTypeKind.stSeries)
and (seriesType.Kind <> TStaticTypeKind.stRecordSeries) then
raise ETypeException.CreateFmt('"length" requires a series, but got %s', [seriesType.ToString]);
- Result := SetType(TDataValue.FromIntf(Node), TTypes.Ordinal);
+ Result := SetType(Node, TTypes.Ordinal);
end;
end.
diff --git a/Src/AST/Myc.Ast.Visitor.pas b/Src/AST/Myc.Ast.Visitor.pas
index d73c657..ac5ac52 100644
--- a/Src/AST/Myc.Ast.Visitor.pas
+++ b/Src/AST/Myc.Ast.Visitor.pas
@@ -10,434 +10,738 @@ uses
Myc.Ast.Nodes;
type
- // A fully abstract base class for any visitor of the AST.
+ TAstVisitor = class abstract(TInterfacedObject, IAstVisitor)
+ strict private
+ // IAstVisitor explicit implementation (bridge methods)
+ function IAstVisitor.VisitConstant = DoVisitConstant;
+ function IAstVisitor.VisitIdentifier = DoVisitIdentifier;
+ function IAstVisitor.VisitKeyword = DoVisitKeyword;
+ function IAstVisitor.VisitBinaryExpression = DoVisitBinaryExpression;
+ function IAstVisitor.VisitUnaryExpression = DoVisitUnaryExpression;
+ function IAstVisitor.VisitIfExpression = DoVisitIfExpression;
+ function IAstVisitor.VisitTernaryExpression = DoVisitTernaryExpression;
+ function IAstVisitor.VisitLambdaExpression = DoVisitLambdaExpression;
+ function IAstVisitor.VisitFunctionCall = DoVisitFunctionCall;
+ function IAstVisitor.VisitMacroExpansionNode = DoVisitMacroExpansionNode;
+ function IAstVisitor.VisitBlockExpression = DoVisitBlockExpression;
+ function IAstVisitor.VisitVariableDeclaration = DoVisitVariableDeclaration;
+ function IAstVisitor.VisitAssignment = DoVisitAssignment;
+ function IAstVisitor.VisitMacroDefinition = DoVisitMacroDefinition;
+ function IAstVisitor.VisitQuasiquote = DoVisitQuasiquote;
+ function IAstVisitor.VisitUnquote = DoVisitUnquote;
+ function IAstVisitor.VisitUnquoteSplicing = DoVisitUnquoteSplicing;
+ function IAstVisitor.VisitIndexer = DoVisitIndexer;
+ function IAstVisitor.VisitMemberAccess = DoVisitMemberAccess;
+ function IAstVisitor.VisitRecordLiteral = DoVisitRecordLiteral;
+ function IAstVisitor.VisitCreateSeries = DoVisitCreateSeries;
+ function IAstVisitor.VisitAddSeriesItem = DoVisitAddSeriesItem;
+ function IAstVisitor.VisitSeriesLength = DoVisitSeriesLength;
+ function IAstVisitor.VisitRecurNode = DoVisitRecurNode;
+
+ // Private bridge method implementations
+ function DoVisitConstant(const Node: IConstantNode): TDataValue;
+ function DoVisitIdentifier(const Node: IIdentifierNode): TDataValue;
+ function DoVisitKeyword(const Node: IKeywordNode): TDataValue;
+ function DoVisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
+ function DoVisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
+ function DoVisitIfExpression(const Node: IIfExpressionNode): TDataValue;
+ function DoVisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
+ function DoVisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
+ function DoVisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
+ function DoVisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
+ function DoVisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
+ function DoVisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
+ function DoVisitAssignment(const Node: IAssignmentNode): TDataValue;
+ function DoVisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
+ function DoVisitQuasiquote(const Node: IQuasiquoteNode): TDataValue;
+ function DoVisitUnquote(const Node: IUnquoteNode): TDataValue;
+ function DoVisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue;
+ function DoVisitIndexer(const Node: IIndexerNode): TDataValue;
+ function DoVisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
+ function DoVisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue;
+ function DoVisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
+ function DoVisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
+ function DoVisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
+ function DoVisitRecurNode(const Node: IRecurNode): TDataValue;
+
+ protected
+ // Visit a node.
+ function Accept(const Node: IAstNode): T; virtual;
+
+ function VisitConstant(const Node: IConstantNode): T; virtual; abstract;
+ function VisitIdentifier(const Node: IIdentifierNode): T; virtual; abstract;
+ function VisitKeyword(const Node: IKeywordNode): T; virtual; abstract;
+ function VisitBinaryExpression(const Node: IBinaryExpressionNode): T; virtual; abstract;
+ function VisitUnaryExpression(const Node: IUnaryExpressionNode): T; virtual; abstract;
+ function VisitIfExpression(const Node: IIfExpressionNode): T; virtual; abstract;
+ function VisitTernaryExpression(const Node: ITernaryExpressionNode): T; virtual; abstract;
+ function VisitLambdaExpression(const Node: ILambdaExpressionNode): T; virtual; abstract;
+ function VisitFunctionCall(const Node: IFunctionCallNode): T; virtual; abstract;
+ function VisitMacroExpansionNode(const Node: IMacroExpansionNode): T; virtual; abstract;
+ function VisitBlockExpression(const Node: IBlockExpressionNode): T; virtual; abstract;
+ function VisitVariableDeclaration(const Node: IVariableDeclarationNode): T; virtual; abstract;
+ function VisitAssignment(const Node: IAssignmentNode): T; virtual; abstract;
+ function VisitMacroDefinition(const Node: IMacroDefinitionNode): T; virtual; abstract;
+ function VisitQuasiquote(const Node: IQuasiquoteNode): T; virtual; abstract;
+ function VisitUnquote(const Node: IUnquoteNode): T; virtual; abstract;
+ function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): T; virtual; abstract;
+ function VisitIndexer(const Node: IIndexerNode): T; virtual; abstract;
+ function VisitMemberAccess(const Node: IMemberAccessNode): T; virtual; abstract;
+ function VisitRecordLiteral(const Node: IRecordLiteralNode): T; virtual; abstract;
+ function VisitCreateSeries(const Node: ICreateSeriesNode): T; virtual; abstract;
+ function VisitAddSeriesItem(const Node: IAddSeriesItemNode): T; virtual; abstract;
+ function VisitSeriesLength(const Node: ISeriesLengthNode): T; virtual; abstract;
+ function VisitRecurNode(const Node: IRecurNode): T; virtual; abstract;
+ end;
+
+ TAstTransformer = class abstract(TAstVisitor)
+ protected
+ function AcceptNodes(const Nodes: TArray; const Map: TFunc): TArray;
+
+ function VisitConstant(const Node: IConstantNode): IAstNode; override;
+ function VisitIdentifier(const Node: IIdentifierNode): IAstNode; override;
+ function VisitKeyword(const Node: IKeywordNode): IAstNode; override;
+ function VisitBinaryExpression(const Node: IBinaryExpressionNode): IAstNode; override;
+ function VisitUnaryExpression(const Node: IUnaryExpressionNode): IAstNode; override;
+ function VisitIfExpression(const Node: IIfExpressionNode): IAstNode; override;
+ function VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode; override;
+ function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override;
+ function VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; override;
+ function VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode; override;
+ function VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode; override;
+ function VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode; override;
+ function VisitAssignment(const Node: IAssignmentNode): IAstNode; override;
+ function VisitMacroDefinition(const Node: IMacroDefinitionNode): IAstNode; override;
+ function VisitQuasiquote(const Node: IQuasiquoteNode): IAstNode; override;
+ function VisitUnquote(const Node: IUnquoteNode): IAstNode; override;
+ function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): IAstNode; override;
+ function VisitIndexer(const Node: IIndexerNode): IAstNode; override;
+ function VisitMemberAccess(const Node: IMemberAccessNode): IAstNode; override;
+ function VisitRecordLiteral(const Node: IRecordLiteralNode): IAstNode; override;
+ function VisitCreateSeries(const Node: ICreateSeriesNode): IAstNode; override;
+ function VisitAddSeriesItem(const Node: IAddSeriesItemNode): IAstNode; override;
+ function VisitSeriesLength(const Node: ISeriesLengthNode): IAstNode; override;
+ function VisitRecurNode(const Node: IRecurNode): IAstNode; override;
+ end;
+
TAstVisitor = class abstract(TInterfacedObject, IAstVisitor)
- protected
- function VisitConstant(const Node: IConstantNode): TDataValue; virtual; abstract;
- function VisitIdentifier(const Node: IIdentifierNode): TDataValue; virtual; abstract;
- function VisitKeyword(const Node: IKeywordNode): TDataValue; virtual; abstract;
- function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue; virtual; abstract;
- function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue; virtual; abstract;
- function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; virtual; abstract;
- function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; virtual; abstract;
- function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; virtual; abstract;
- function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; virtual; abstract;
- function VisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue; virtual; abstract;
- function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue; virtual; abstract;
- function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue; virtual; abstract;
- function VisitAssignment(const Node: IAssignmentNode): TDataValue; virtual; abstract;
- function VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue; virtual; abstract;
- function VisitQuasiquote(const Node: IQuasiquoteNode): TDataValue; virtual; abstract;
- function VisitUnquote(const Node: IUnquoteNode): TDataValue; virtual; abstract;
- function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue; virtual; abstract;
- function VisitIndexer(const Node: IIndexerNode): TDataValue; virtual; abstract;
- function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue; virtual; abstract;
- function VisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue; virtual; abstract;
- function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue; virtual; abstract;
- function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; virtual; abstract;
- function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; virtual; abstract;
- function VisitRecurNode(const Node: IRecurNode): TDataValue; virtual; abstract;
- end;
+ strict private
+ // IAstVisitor explicit implementation (bridge methods)
+ function IAstVisitor.VisitConstant = DoVisitConstant;
+ function IAstVisitor.VisitIdentifier = DoVisitIdentifier;
+ function IAstVisitor.VisitKeyword = DoVisitKeyword;
+ function IAstVisitor.VisitBinaryExpression = DoVisitBinaryExpression;
+ function IAstVisitor.VisitUnaryExpression = DoVisitUnaryExpression;
+ function IAstVisitor.VisitIfExpression = DoVisitIfExpression;
+ function IAstVisitor.VisitTernaryExpression = DoVisitTernaryExpression;
+ function IAstVisitor.VisitLambdaExpression = DoVisitLambdaExpression;
+ function IAstVisitor.VisitFunctionCall = DoVisitFunctionCall;
+ function IAstVisitor.VisitMacroExpansionNode = DoVisitMacroExpansionNode;
+ function IAstVisitor.VisitBlockExpression = DoVisitBlockExpression;
+ function IAstVisitor.VisitVariableDeclaration = DoVisitVariableDeclaration;
+ function IAstVisitor.VisitAssignment = DoVisitAssignment;
+ function IAstVisitor.VisitMacroDefinition = DoVisitMacroDefinition;
+ function IAstVisitor.VisitQuasiquote = DoVisitQuasiquote;
+ function IAstVisitor.VisitUnquote = DoVisitUnquote;
+ function IAstVisitor.VisitUnquoteSplicing = DoVisitUnquoteSplicing;
+ function IAstVisitor.VisitIndexer = DoVisitIndexer;
+ function IAstVisitor.VisitMemberAccess = DoVisitMemberAccess;
+ function IAstVisitor.VisitRecordLiteral = DoVisitRecordLiteral;
+ function IAstVisitor.VisitCreateSeries = DoVisitCreateSeries;
+ function IAstVisitor.VisitAddSeriesItem = DoVisitAddSeriesItem;
+ function IAstVisitor.VisitSeriesLength = DoVisitSeriesLength;
+ function IAstVisitor.VisitRecurNode = DoVisitRecurNode;
- IAstTransformer = interface(IAstVisitor)
- function Execute(const RootNode: IAstNode): IAstNode;
- end;
-
- // A base visitor that walks the AST and rebuilds it node by node.
- // Derived classes can override the virtual Visit... methods to customize behavior.
- TAstTransformer = class abstract(TAstVisitor, IAstTransformer)
- private
- FDone: Boolean;
+ // Private bridge method implementations
+ function DoVisitConstant(const Node: IConstantNode): TDataValue;
+ function DoVisitIdentifier(const Node: IIdentifierNode): TDataValue;
+ function DoVisitKeyword(const Node: IKeywordNode): TDataValue;
+ function DoVisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
+ function DoVisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
+ function DoVisitIfExpression(const Node: IIfExpressionNode): TDataValue;
+ function DoVisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
+ function DoVisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
+ function DoVisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
+ function DoVisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
+ function DoVisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
+ function DoVisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
+ function DoVisitAssignment(const Node: IAssignmentNode): TDataValue;
+ function DoVisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
+ function DoVisitQuasiquote(const Node: IQuasiquoteNode): TDataValue;
+ function DoVisitUnquote(const Node: IUnquoteNode): TDataValue;
+ function DoVisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue;
+ function DoVisitIndexer(const Node: IIndexerNode): TDataValue;
+ function DoVisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
+ function DoVisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue;
+ function DoVisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
+ function DoVisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
+ function DoVisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
+ function DoVisitRecurNode(const Node: IRecurNode): TDataValue;
protected
- // These virtual methods implement the default identity-transformation (cloning) behavior.
- function VisitConstant(const Node: IConstantNode): TDataValue; override;
- function VisitIdentifier(const Node: IIdentifierNode): TDataValue; override;
- function VisitKeyword(const Node: IKeywordNode): 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 VisitRecordLiteral(const Node: IRecordLiteralNode): 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;
-
- function Accept(const Node: IAstNode): TDataValue; virtual;
- // Helper to transform an array of nodes.
- function AcceptNodes(const Nodes: TArray): TArray;
-
- property Done: Boolean read FDone write FDone;
- public
- // This is the main entry point for the transformer, returning a transformed node.
- function Execute(const RootNode: IAstNode): IAstNode;
- end;
-
- // Generic traverser for managing state during AST walks.
- TAstTraverser = class(TAstTransformer)
- private
- FData: TStack;
- protected
- function Accept(const Node: IAstNode): TDataValue; override;
- // Called before a node is visited. The returned value is pushed onto the state stack.
- function EnterNode(const Node: IAstNode): T; virtual; abstract;
- // Called after a node has been visited.
- procedure ExitNode(const Node: IAstNode; const Data: T); virtual;
- property Data: TStack read FData;
- public
- constructor Create;
- destructor Destroy; override;
+ // Virtual procedures for descendants (Interpreters/Side-effects) to override
+ procedure VisitConstant(const Node: IConstantNode); virtual; abstract;
+ procedure VisitIdentifier(const Node: IIdentifierNode); virtual; abstract;
+ procedure VisitKeyword(const Node: IKeywordNode); virtual; abstract;
+ procedure VisitBinaryExpression(const Node: IBinaryExpressionNode); virtual; abstract;
+ procedure VisitUnaryExpression(const Node: IUnaryExpressionNode); virtual; abstract;
+ procedure VisitIfExpression(const Node: IIfExpressionNode); virtual; abstract;
+ procedure VisitTernaryExpression(const Node: ITernaryExpressionNode); virtual; abstract;
+ procedure VisitLambdaExpression(const Node: ILambdaExpressionNode); virtual; abstract;
+ procedure VisitFunctionCall(const Node: IFunctionCallNode); virtual; abstract;
+ procedure VisitMacroExpansionNode(const Node: IMacroExpansionNode); virtual; abstract;
+ procedure VisitBlockExpression(const Node: IBlockExpressionNode); virtual; abstract;
+ procedure VisitVariableDeclaration(const Node: IVariableDeclarationNode); virtual; abstract;
+ procedure VisitAssignment(const Node: IAssignmentNode); virtual; abstract;
+ procedure VisitMacroDefinition(const Node: IMacroDefinitionNode); virtual; abstract;
+ procedure VisitQuasiquote(const Node: IQuasiquoteNode); virtual; abstract;
+ procedure VisitUnquote(const Node: IUnquoteNode); virtual; abstract;
+ procedure VisitUnquoteSplicing(const Node: IUnquoteSplicingNode); virtual; abstract;
+ procedure VisitIndexer(const Node: IIndexerNode); virtual; abstract;
+ procedure VisitMemberAccess(const Node: IMemberAccessNode); virtual; abstract;
+ procedure VisitRecordLiteral(const Node: IRecordLiteralNode); virtual; abstract;
+ procedure VisitCreateSeries(const Node: ICreateSeriesNode); virtual; abstract;
+ procedure VisitAddSeriesItem(const Node: IAddSeriesItemNode); virtual; abstract;
+ procedure VisitSeriesLength(const Node: ISeriesLengthNode); virtual; abstract;
+ procedure VisitRecurNode(const Node: IRecurNode); virtual; abstract;
end;
implementation
-{ TAstTransformer }
+{ TAstVisitor }
-function TAstTransformer.Accept(const Node: IAstNode): TDataValue;
+function TAstVisitor.Accept(const Node: IAstNode): T;
begin
- if (not Assigned(Node)) or FDone then
- exit;
- Result := Node.Accept(Self);
+ if Assigned(Node) then
+ Result := Node.Accept(Self).AsGeneric
+ else
+ Result := Default(T);
end;
-function TAstTransformer.AcceptNodes