From 240f794211aac904d21e48159bbdbab144c1f039 Mon Sep 17 00:00:00 2001 From: Michael Schimmel Date: Sat, 22 Nov 2025 14:49:24 +0100 Subject: [PATCH] AST function purity analysis --- ASTPlayground/ASTPlayground.delphilsp.json | 2 +- ASTPlayground/ASTPlayground.dpr | 3 +- ASTPlayground/ASTPlayground.dproj | 7 + ASTPlayground/MainForm.fmx | 2 +- ASTPlayground/MainForm.pas | 24 +- Src/AST/Myc.Ast.Analysis.Purity.pas | 250 +++++++++++++++++++++ Src/AST/Myc.Ast.Compiler.Binder.pas | 2 +- Src/AST/Myc.Ast.Compiler.Macros.pas | 2 +- Src/AST/Myc.Ast.Compiler.Specializer.pas | 33 ++- Src/AST/Myc.Ast.Compiler.TCO.pas | 16 +- Src/AST/Myc.Ast.Compiler.TypeChecker.pas | 3 +- Src/AST/Myc.Ast.Dumper.pas | 14 +- Src/AST/Myc.Ast.Environment.pas | 36 ++- Src/AST/Myc.Ast.Nodes.pas | 6 + Src/AST/Myc.Ast.RTL.pas | 31 +-- Src/AST/Myc.Ast.Visitor.pas | 12 +- Src/AST/Myc.Ast.pas | 54 +++-- 17 files changed, 429 insertions(+), 68 deletions(-) create mode 100644 Src/AST/Myc.Ast.Analysis.Purity.pas diff --git a/ASTPlayground/ASTPlayground.delphilsp.json b/ASTPlayground/ASTPlayground.delphilsp.json index b4e5cd8..e6957cc 100644 --- a/ASTPlayground/ASTPlayground.delphilsp.json +++ b/ASTPlayground/ASTPlayground.delphilsp.json @@ -1 +1 @@ -{ "settings": { "project": "file:///T%3A/Myc/ASTPlayground/ASTPlayground.dpr", "dllname": "dcc64370.dll", "dccOptions": "-$O- -$W+ --inline:off -$R+ -$Q+ --no-config -Q -TX.exe -AGenerics.Collections=System.Generics.Collections;Generics.Defaults=System.Generics.Defaults;WinTypes=Winapi.Windows;WinProcs=Winapi.Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE -DDEBUG;;FRAMEWORK_FMX -E.\\Win64\\Debug -I\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\\DE\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -LEC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Bpl\\Win64 -LNC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64 -NU.\\Win64\\Debug -NSWinapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;System;Xml;Data;Datasnap;Web;Soap; -OT:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -R\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -U\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\\DE\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -V -VN -VR -NBC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64 -NHC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\hpp\\Win64 -NO.\\Win64\\Debug -LU" , "projectFiles":[ { "name": "MainForm", "file": "file:///T%3A/Myc/ASTPlayground/MainForm.pas" }, { "name": "Myc.Ast.Nodes", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Nodes.pas" }, { "name": "Myc.Ast.Scope", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Scope.pas" }, { "name": "Myc.Data.Value", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Data.Value.pas" }, { "name": "Myc.Ast.Visitor", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Visitor.pas" }, { "name": "Myc.Ast.RTL", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.pas" }, { "name": "Myc.Ast.Dumper", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Dumper.pas" }, { "name": "Myc.Ast.RTL.Core", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.Core.pas" }, { "name": "Myc.Fmx.AstEditor.Node", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Fmx.AstEditor.Node.pas" }, { "name": "Myc.Fmx.AstEditor.Workspace", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Fmx.AstEditor.Workspace.pas" }, { "name": "Myc.Fmx.AstEditor.Text", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Fmx.AstEditor.Text.pas" }, { "name": "Myc.Utils", "file": "file:///T%3A/Myc/Src/Myc.Utils.pas" }, { "name": "Myc.Ast.Script", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Script.pas" }, { "name": "Myc.Ast.Types", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Types.pas" }, { "name": "Myc.Data.Keyword", "file": "file:///T%3A/Myc/Src/Data/Myc.Data.Keyword.pas" }, { "name": "Myc.Ast.Compiler.TCO", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.TCO.pas" }, { "name": "Myc.Ast.Compiler.Binder", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Binder.pas" }, { "name": "Myc.Ast.Compiler.Lowering", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Lowering.pas" }, { "name": "Myc.Ast.Compiler.TypeChecker", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.TypeChecker.pas" }, { "name": "Myc.Ast.Compiler.Macros", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Macros.pas" }, { "name": "Myc.Ast.Compiler.Specializer", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Specializer.pas" }, { "name": "Myc.Ast.Environment", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Environment.pas" }, { "name": "Myc.Ast.Debugger", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Debugger.pas" } ] , "includeDCUsInUsesCompletion": true, "enableKeyWordCompletion": false, "browsingPaths": [ "file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/OCX/Servers","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/VCL","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/RTL/SYS","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/win","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/win/winrt","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/ToolsAPI","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/IBX","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Internet","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/PROPERTY%20EDITORS","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/soap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/XML","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/Core","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/System","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/Protocols","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/fmx","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/components","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/engine","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/graph","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/ado","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/cloud","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/dbx","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/dsnap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/vclctrls","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap/connectors","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap/proxygen","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DataExplorer","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/Common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/Common/dunit","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/Common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/DUnitProject","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/DUnitProject/dunit","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/src","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/tests","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Experts","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indy/abstraction","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indy/implementation","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indyimpl","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Property%20Editors/Indy10","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/soap/wsdlimporter","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Visualizers","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/XMLReporting","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/XPGen","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/rest","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/firedac","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/tethering","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnitX","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/ems","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/net","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/FlatBox2D","file:///C%3A/Users/Public/Documents/Embarcadero/Studio/37.0/Dcp/%25PLATFORM%25","file:///%25TP%25/runtime/vcl","file:///S%3A/sc_famos_src/svn_vcl/cpxedits","file:///S%3A/sc_famos_src/svn_vcl/dzChart","file:///S%3A/sc_famos_src/svn_vcl/eaeditor","file:///S%3A/sc_famos_src/svn_vcl/FamosEvents","file:///S%3A/sc_famos_src/svn_vcl/HTML_Viewer/source","file:///S%3A/sc_famos_src/svn_vcl/Myc_ChartEdit","file:///S%3A/sc_famos_src/svn_vcl/Myc_HemiDrag","file:///S%3A/sc_famos_src/svn_vcl/Myc_SplitControl","file:///S%3A/sc_famos_src/svn_vcl/NiceChart","file:///S%3A/sc_famos_src/svn_vcl/plotter","file:///S%3A/sc_famos_src/svn_vcl/SimpleIPC","file:///S%3A/sc_famos_src/svn_vcl/SynEdit-master/Source","file:///S%3A/sc_famos_src/svn_vcl/ValEdits","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster/zlib","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster/zlib/win32","file:///S%3A/sc_famos_src/svn_vcl/Virtual-TreeView/Source","file:///S%3A/sc_famos_src/svn_common/caHelpSys","file:///S%3A/sc_famos_src/svn_common/Misc","file:///S%3A/sc_famos_src/svn_common/Myc_VecMath","file:///S%3A/sc_famos_src/svn_common/PascalScript/source","file:///S%3A/sc_famos_src/svn_common/TreeBase","file:///S%3A/sc_famos_src/svn_common/TreeBase/Medien","file:///S%3A/3rdParty/spring4d/Source","file:///S%3A/3rdParty/spring4d/Source/Base","file:///S%3A/3rdParty/spring4d/Source/Base/Collections","file:///S%3A/3rdParty/spring4d/Source/Base/Logging","file:///S%3A/3rdParty/spring4d/Source/Base/Patches","file:///S%3A/3rdParty/spring4d/Source/Core/Container","file:///S%3A/3rdParty/spring4d/Source/Core/Interception","file:///S%3A/3rdParty/spring4d/Source/Core/Logging","file:///S%3A/3rdParty/spring4d/Source/Core/Mocking","file:///S%3A/3rdParty/spring4d/Source/Core/Services","file:///S%3A/3rdParty/spring4d/Source/Extensions/Cryptography","file:///S%3A/3rdParty/spring4d/Source/Extensions/Utils","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressCore%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressCommon%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressGDI%2B%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressLibrary/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/XP%20Theme%20Manager/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressLayout%20Control/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressPageControl/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressEditors%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressDocking%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressBars/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressOfficeCore%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressMemData/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressDataController/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressNavBar/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressSkins%20Library/Sources","file:///T%3A/Myc/Src","file:///T%3A/Myc/Src/Data","file:///T%3A/Myc/Src/AST" ] , "CommonAppData": "file:///C%3A/Users/Brummel/AppData/Roaming/Embarcadero/BDS/37.0/" , "Templates": "file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/ObjRepos/" } } \ No newline at end of file +{ "settings": { "project": "file:///T%3A/Myc/ASTPlayground/ASTPlayground.dpr", "dllname": "dcc64370.dll", "dccOptions": "-$O- -$W+ --inline:off -$R+ -$Q+ --no-config -Q -TX.exe -AGenerics.Collections=System.Generics.Collections;Generics.Defaults=System.Generics.Defaults;WinTypes=Winapi.Windows;WinProcs=Winapi.Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE -DDEBUG;;FRAMEWORK_FMX -E.\\Win64\\Debug -I\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\\DE\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -LEC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Bpl\\Win64 -LNC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64 -NU.\\Win64\\Debug -NSWinapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;System;Xml;Data;Datasnap;Web;Soap; -OT:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -R\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -U\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\\DE\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -V -VN -VR -NBC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64 -NHC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\hpp\\Win64 -NO.\\Win64\\Debug -LU" , "projectFiles":[ { "name": "MainForm", "file": "file:///T%3A/Myc/ASTPlayground/MainForm.pas" }, { "name": "Myc.Ast.Nodes", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Nodes.pas" }, { "name": "Myc.Ast.Scope", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Scope.pas" }, { "name": "Myc.Data.Value", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Data.Value.pas" }, { "name": "Myc.Ast.Visitor", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Visitor.pas" }, { "name": "Myc.Ast.RTL", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.pas" }, { "name": "Myc.Ast.Dumper", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Dumper.pas" }, { "name": "Myc.Ast.RTL.Core", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.Core.pas" }, { "name": "Myc.Fmx.AstEditor.Node", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Fmx.AstEditor.Node.pas" }, { "name": "Myc.Fmx.AstEditor.Workspace", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Fmx.AstEditor.Workspace.pas" }, { "name": "Myc.Fmx.AstEditor.Text", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Fmx.AstEditor.Text.pas" }, { "name": "Myc.Utils", "file": "file:///T%3A/Myc/Src/Myc.Utils.pas" }, { "name": "Myc.Ast.Script", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Script.pas" }, { "name": "Myc.Ast.Types", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Types.pas" }, { "name": "Myc.Data.Keyword", "file": "file:///T%3A/Myc/Src/Data/Myc.Data.Keyword.pas" }, { "name": "Myc.Ast.Compiler.TCO", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.TCO.pas" }, { "name": "Myc.Ast.Compiler.Binder", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Binder.pas" }, { "name": "Myc.Ast.Compiler.Lowering", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Lowering.pas" }, { "name": "Myc.Ast.Compiler.TypeChecker", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.TypeChecker.pas" }, { "name": "Myc.Ast.Compiler.Macros", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Macros.pas" }, { "name": "Myc.Ast.Compiler.Specializer", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Specializer.pas" }, { "name": "Myc.Ast.Environment", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Environment.pas" }, { "name": "Myc.Ast.Debugger", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Debugger.pas" }, { "name": "Myc.Ast.Analysis.Purity", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Analysis.Purity.pas" } ] , "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 bc030d8..0e0365d 100644 --- a/ASTPlayground/ASTPlayground.dpr +++ b/ASTPlayground/ASTPlayground.dpr @@ -26,7 +26,8 @@ uses Myc.Ast.Compiler.Macros in '..\Src\AST\Myc.Ast.Compiler.Macros.pas', Myc.Ast.Compiler.Specializer in '..\Src\AST\Myc.Ast.Compiler.Specializer.pas', Myc.Ast.Environment in '..\Src\AST\Myc.Ast.Environment.pas', - Myc.Ast.Debugger in '..\Src\AST\Myc.Ast.Debugger.pas'; + Myc.Ast.Debugger in '..\Src\AST\Myc.Ast.Debugger.pas', + Myc.Ast.Analysis.Purity in '..\Src\AST\Myc.Ast.Analysis.Purity.pas'; {$R *.res} diff --git a/ASTPlayground/ASTPlayground.dproj b/ASTPlayground/ASTPlayground.dproj index 541fa8b..7c8d3b7 100644 --- a/ASTPlayground/ASTPlayground.dproj +++ b/ASTPlayground/ASTPlayground.dproj @@ -157,6 +157,7 @@ + Base @@ -212,6 +213,12 @@ true + + + ASTPlayground.rsm + true + + ASTPlayground.exe diff --git a/ASTPlayground/MainForm.fmx b/ASTPlayground/MainForm.fmx index b666098..ae7e376 100644 --- a/ASTPlayground/MainForm.fmx +++ b/ASTPlayground/MainForm.fmx @@ -197,7 +197,7 @@ object Form1: TForm1 'Expanded' 'Bound' 'Specialized') - ItemIndex = 0 + ItemIndex = 3 Position.X = 672.000000000000000000 Position.Y = 576.000000000000000000 Size.Width = 104.000000000000000000 diff --git a/ASTPlayground/MainForm.pas b/ASTPlayground/MainForm.pas index fdad466..cf1d221 100644 --- a/ASTPlayground/MainForm.pas +++ b/ASTPlayground/MainForm.pas @@ -110,7 +110,7 @@ type procedure RTLListViewChange(Sender: TObject); private FCurrUnboundAst: IAstNode; - FCurrExec: TDataValue.TFunc; + FCurrExec: TCompiledFunction; FEnvironment: TAstEnvironment; FWorkspace: TAuraWorkspace; FScriptUpdate: Boolean; @@ -262,7 +262,7 @@ end; function TForm1.ExecuteAst(const ANode: IAstNode): TDataValue; begin FCurrUnboundAst := ANode; - FCurrExec := nil; // Clear previous + FCurrExec := Default(TCompiledFunction); // 1. Set strategy based on UI if DebugBox.IsChecked then @@ -273,12 +273,21 @@ begin try // Wrap in Lambda to compile var funcDef := TAst.LambdaExpr([], ANode); - FCurrExec := FEnvironment.Compile(funcDef).Func; - Result := FCurrExec([]); + FCurrExec := FEnvironment.Compile(funcDef); + + if Assigned(FCurrExec.Func) then + begin + Memo1.Lines.Add( + Format('Compiled. Signature: %s, IsPure=%s', [FCurrExec.StaticType.ToString, BoolToStr(FCurrExec.IsPure, true)]) + ); + end; + + Result := FCurrExec.Func([]); except on E: Exception do begin + FCurrExec.Func := nil; Memo1.Lines.Add('--- ERROR ---'); Memo1.Lines.Add(E.ClassName + ': ' + E.Message); Result := TDataValue.Void; @@ -645,7 +654,7 @@ begin FCurrUnboundAst := converter.Deserialize(jsonObj); // Run the full pipeline via environment - FCurrExec := FEnvironment.Compile(FCurrUnboundAst).Func; + FCurrExec := FEnvironment.Compile(FCurrUnboundAst); Memo1.Lines.Add('AST deserialized and bound successfully from JSON.'); Memo1.Lines.Add('You can now visualize it (Middle Mouse Click) or pretty-print it.'); @@ -655,7 +664,6 @@ begin except on E: Exception do begin - FCurrExec := nil; Memo1.Lines.Add('Error deserializing AST from JSON:'); Memo1.Lines.Add(E.Message); Memo1.Lines.Add('--- Original JSON ---'); @@ -675,7 +683,7 @@ var begin Memo1.Lines.Clear; - if not Assigned(FCurrExec) then + if not Assigned(FCurrExec.Func) then begin Memo1.Lines.Add('No AST available to serialize. Please generate one first.'); exit; @@ -703,7 +711,7 @@ begin Memo1.Lines.Clear; Memo1.Lines.Add('--- AST Dump ---'); - if not Assigned(FCurrExec) then + if not Assigned(FCurrExec.Func) then begin Memo1.Lines.Add('No *compiled* AST has been generated yet. Click a test button first.'); exit; diff --git a/Src/AST/Myc.Ast.Analysis.Purity.pas b/Src/AST/Myc.Ast.Analysis.Purity.pas new file mode 100644 index 0000000..41b12fe --- /dev/null +++ b/Src/AST/Myc.Ast.Analysis.Purity.pas @@ -0,0 +1,250 @@ +unit Myc.Ast.Analysis.Purity; + +interface + +uses + System.SysUtils, + Myc.Data.Value, + Myc.Ast.Nodes, + Myc.Ast.Visitor, + Myc.Ast.Scope; + +type + /// + /// Analyzes an AST to determine if it is referentially transparent and free of side effects. + /// + TPurityAnalyzer = class(TAstVisitor) + protected + // Default behavior: Visit children. If all children return True, then True. + // However, we must explicitly define what is allowed. + function Accept(const Node: IAstNode): Boolean; override; + + // --- Safe Leaves / Constructs --- + function VisitConstant(const Node: IConstantNode): Boolean; override; + function VisitKeyword(const Node: IKeywordNode): Boolean; override; + function VisitIfExpression(const Node: IIfExpressionNode): Boolean; override; + function VisitTernaryExpression(const Node: ITernaryExpressionNode): Boolean; override; + function VisitBlockExpression(const Node: IBlockExpressionNode): Boolean; override; + function VisitRecordLiteral(const Node: IRecordLiteralNode): Boolean; override; + function VisitVariableDeclaration(const Node: IVariableDeclarationNode): Boolean; override; + function VisitSeriesLength(const Node: ISeriesLengthNode): Boolean; override; + + // --- Critical Checks --- + function VisitIdentifier(const Node: IIdentifierNode): Boolean; override; + function VisitFunctionCall(const Node: IFunctionCallNode): Boolean; override; + function VisitRecurNode(const Node: IRecurNode): Boolean; override; + + // --- Forbidden Constructs (Side Effects / Unsafe) --- + function VisitAssignment(const Node: IAssignmentNode): Boolean; override; + function VisitAddSeriesItem(const Node: IAddSeriesItemNode): Boolean; override; + + // Allocation is considered pure in this context (it creates a new value, doesn't mutate existing world) + function VisitCreateSeries(const Node: ICreateSeriesNode): Boolean; override; + + function VisitIndexer(const Node: IIndexerNode): Boolean; override; + function VisitMemberAccess(const Node: IMemberAccessNode): Boolean; override; + + // Ignored / Irrelevant for Runtime Purity (Compile-time constructs or Definitions) + function VisitLambdaExpression(const Node: ILambdaExpressionNode): Boolean; override; + function VisitMacroDefinition(const Node: IMacroDefinitionNode): Boolean; override; + function VisitQuasiquote(const Node: IQuasiquoteNode): Boolean; override; + function VisitUnquote(const Node: IUnquoteNode): Boolean; override; + function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): Boolean; override; + function VisitMacroExpansionNode(const Node: IMacroExpansionNode): Boolean; override; + function VisitNop(const Node: INopNode): Boolean; override; + + public + class function IsPure(const RootNode: IAstNode): Boolean; + end; + +implementation + +{ TPurityAnalyzer } + +class function TPurityAnalyzer.IsPure(const RootNode: IAstNode): Boolean; +begin + var analyzer := TPurityAnalyzer.Create; + try + Result := analyzer.Accept(RootNode); + finally + analyzer.Free; + end; +end; + +function TPurityAnalyzer.Accept(const Node: IAstNode): Boolean; +begin + // If a node is nil (e.g. optional else-branch), it's "nothing", which is pure. + if not Assigned(Node) then + exit(True); + + // Dispatch to specific Visit method via generic base + Result := Node.Accept(Self).AsGeneric; +end; + +// --- Safe Leaves --- + +function TPurityAnalyzer.VisitConstant(const Node: IConstantNode): Boolean; +begin + Result := True; +end; + +function TPurityAnalyzer.VisitKeyword(const Node: IKeywordNode): Boolean; +begin + Result := True; +end; + +function TPurityAnalyzer.VisitNop(const Node: INopNode): Boolean; +begin + Result := True; +end; + +// --- Identifier: Only local variables are safe --- + +function TPurityAnalyzer.VisitIdentifier(const Node: IIdentifierNode): Boolean; +begin + // We only allow access to local variables (ScopeDepth = 0). + // Accessing Parent/Upvalues (ScopeDepth > 0) makes the function state-dependent (closure state), + // effectively impure regarding referential transparency across different closure instances, + // unless we could prove the upvalue is constant (which we don't track yet). + + // Note: Parameters are also ScopeDepth=0 in the Binder logic. + Result := (Node.Address.Kind = akLocalOrParent) and (Node.Address.ScopeDepth = 0); +end; + +// --- Function Call: The Core Logic --- + +function TPurityAnalyzer.VisitFunctionCall(const Node: IFunctionCallNode): Boolean; +begin + // 1. The target function MUST be marked as Pure (from RTL or previous inference). + if not Node.IsTargetPure then + exit(False); + + // 2. All arguments must be pure expressions. + for var arg in Node.Arguments do + if not Accept(arg) then + exit(False); + + Result := True; +end; + +// --- Recursion --- + +function TPurityAnalyzer.VisitRecurNode(const Node: IRecurNode): Boolean; +begin + // 'recur' is just control flow. It is pure if its arguments are pure. + for var arg in Node.Arguments do + if not Accept(arg) then + exit(False); + Result := True; +end; + +// --- Structures: Recursive Checks --- + +function TPurityAnalyzer.VisitIfExpression(const Node: IIfExpressionNode): Boolean; +begin + Result := Accept(Node.Condition) and Accept(Node.ThenBranch) and Accept(Node.ElseBranch); +end; + +function TPurityAnalyzer.VisitTernaryExpression(const Node: ITernaryExpressionNode): Boolean; +begin + Result := Accept(Node.Condition) and Accept(Node.ThenBranch) and Accept(Node.ElseBranch); +end; + +function TPurityAnalyzer.VisitBlockExpression(const Node: IBlockExpressionNode): Boolean; +begin + for var expr in Node.Expressions do + if not Accept(expr) then + exit(False); + Result := True; +end; + +function TPurityAnalyzer.VisitVariableDeclaration(const Node: IVariableDeclarationNode): Boolean; +begin + // 'def x = ...' is locally pure if the initializer is pure. + // It mutates the local scope (stack), but that is contained within the function execution. + Result := Accept(Node.Initializer); +end; + +function TPurityAnalyzer.VisitRecordLiteral(const Node: IRecordLiteralNode): Boolean; +begin + for var field in Node.Fields do + if not Accept(field.Value) then + exit(False); + Result := True; +end; + +function TPurityAnalyzer.VisitIndexer(const Node: IIndexerNode): Boolean; +begin + // Reading from a structure is pure if the indices/base are pure. + Result := Accept(Node.Base) and Accept(Node.Index); +end; + +function TPurityAnalyzer.VisitMemberAccess(const Node: IMemberAccessNode): Boolean; +begin + Result := Accept(Node.Base); +end; + +function TPurityAnalyzer.VisitSeriesLength(const Node: ISeriesLengthNode): Boolean; +begin + // Querying length is pure. + // The series identifier check happens in VisitIdentifier. + Result := True; +end; + +// --- Forbidden (Impure) --- + +function TPurityAnalyzer.VisitAssignment(const Node: IAssignmentNode): Boolean; +begin + // Mutation of variables is defined as impure. + Result := False; +end; + +function TPurityAnalyzer.VisitAddSeriesItem(const Node: IAddSeriesItemNode): Boolean; +begin + // Mutation of a series (side effect). + Result := False; +end; + +function TPurityAnalyzer.VisitCreateSeries(const Node: ICreateSeriesNode): Boolean; +begin + // Creating a NEW object is considered pure in this context, + // as it does not mutate existing global state. + Result := True; +end; + +// --- Irrelevant / Nested (Definitions are pure, execution logic checked separately) --- + +function TPurityAnalyzer.VisitLambdaExpression(const Node: ILambdaExpressionNode): Boolean; +begin + // Defining a function is a pure operation. + // Whether the function itself is pure when executed is determined when *that* function is compiled. + Result := True; +end; + +function TPurityAnalyzer.VisitMacroDefinition(const Node: IMacroDefinitionNode): Boolean; +begin + Result := True; // Compile-time construct +end; + +function TPurityAnalyzer.VisitQuasiquote(const Node: IQuasiquoteNode): Boolean; +begin + Result := True; // Structural construction +end; + +function TPurityAnalyzer.VisitUnquote(const Node: IUnquoteNode): Boolean; +begin + Result := Accept(Node.Expression); +end; + +function TPurityAnalyzer.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): Boolean; +begin + Result := Accept(Node.Expression); +end; + +function TPurityAnalyzer.VisitMacroExpansionNode(const Node: IMacroExpansionNode): Boolean; +begin + // We analyze the already expanded body. + Result := Accept(Node.ExpandedBody); +end; + +end. diff --git a/Src/AST/Myc.Ast.Compiler.Binder.pas b/Src/AST/Myc.Ast.Compiler.Binder.pas index 0dd0748..a211e23 100644 --- a/Src/AST/Myc.Ast.Compiler.Binder.pas +++ b/Src/AST/Myc.Ast.Compiler.Binder.pas @@ -368,7 +368,7 @@ begin // If FLambdaCounter increased by more than just 1 (myself), children were visited. hasNested := FLambdaCounter > (startCount + 1); - Result := TAst.LambdaExpr(newParams, newBody, finalLayout, nil, upvaluesList, hasNested); + Result := TAst.LambdaExpr(newParams, newBody, finalLayout, nil, upvaluesList, hasNested, Node.IsPure); end; function TAstBinder.VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; diff --git a/Src/AST/Myc.Ast.Compiler.Macros.pas b/Src/AST/Myc.Ast.Compiler.Macros.pas index 6810b31..8bb62b6 100644 --- a/Src/AST/Myc.Ast.Compiler.Macros.pas +++ b/Src/AST/Myc.Ast.Compiler.Macros.pas @@ -219,7 +219,7 @@ begin newBody := Accept(Node.Body); - Result := TAst.LambdaExpr(newParams, newBody, nil, nil, nil, False, TTypes.Unknown); + Result := TAst.LambdaExpr(newParams, newBody, nil, nil, nil, False, Node.IsPure, TTypes.Unknown); end; function TExpansionVisitor.VisitUnquote(const Node: IUnquoteNode): IAstNode; diff --git a/Src/AST/Myc.Ast.Compiler.Specializer.pas b/Src/AST/Myc.Ast.Compiler.Specializer.pas index f75c3f5..4db470d 100644 --- a/Src/AST/Myc.Ast.Compiler.Specializer.pas +++ b/Src/AST/Myc.Ast.Compiler.Specializer.pas @@ -22,6 +22,7 @@ type // This transformer runs *after* TypeChecker. // It specializes all statically resolvable function calls (RTL and user-defined) // by replacing them with nodes that have a direct StaticTarget. + // It propagates Purity information but does NOT perform Constant Folding yet. TStaticSpecializer = class(TAstTransformer, IAstSpecializer) private FEnvironment: IEnvironment; @@ -35,7 +36,6 @@ type constructor Create(const AEnvironment: IEnvironment); function Execute(const RootNode: IAstNode): IAstNode; - // Descriptor removed from signature as it is not needed for specialization class function Specialize(const AEnvironment: IEnvironment; const RootNode: IAstNode): IAstNode; static; end; @@ -128,7 +128,16 @@ begin if FEnvironment.MonomorphCache.TryGetValue(key, specializedMethod) then begin // 4a. Cache Hit (Environment) - Result := TAst.FunctionCall(newCallee, newArgs, specializedMethod.ReturnType, Node.IsTailCall, specializedMethod.Target); + // Propagate IsPure flag from cache to AST node + Result := + TAst.FunctionCall( + newCallee, + newArgs, + specializedMethod.ReturnType, + Node.IsTailCall, + specializedMethod.Target, + specializedMethod.IsPure + ); exit; end; @@ -139,7 +148,16 @@ begin // 5a. Cache Hit (RTL) FEnvironment.MonomorphCache.Add(key, specializedMethod); - Result := TAst.FunctionCall(newCallee, newArgs, specializedMethod.ReturnType, Node.IsTailCall, specializedMethod.Target); + // Propagate IsPure flag from RTL definition to AST node + Result := + TAst.FunctionCall( + newCallee, + newArgs, + specializedMethod.ReturnType, + Node.IsTailCall, + specializedMethod.Target, + specializedMethod.IsPure + ); exit; end; @@ -148,7 +166,7 @@ begin if (funcDef <> nil) then begin - // Cannot specialize closures safely without more complex analysis + // Cannot specialize closures safely without more complex analysis if they have state if funcDef.Kind = akLambdaExpression then begin var lambdaDef := funcDef.AsLambdaExpression; @@ -160,17 +178,18 @@ begin end; // 6a. Compile func with KNOWN TYPES - // This recursively triggers Bind -> Check -> Specialize for the callee body! + // This recursively triggers Bind -> Check -> Specialize -> Purity Inference for the callee body! var compiled := FEnvironment.Compile(funcDef, argTypes); // 6b. Store in cache // Get the return type from the *full function type* returned by Compile var returnType := compiled.StaticType.Signatures[0].ReturnType; - specializedMethod := TSpecializedMethod.Create(compiled.Func, returnType); + specializedMethod := TSpecializedMethod.Create(compiled.Func, returnType, compiled.IsPure); FEnvironment.MonomorphCache.Add(key, specializedMethod); // 6c. Return the new node - Result := TAst.FunctionCall(newCallee, newArgs, returnType, Node.IsTailCall, compiled.Func); + // Propagate the inferred IsPure flag to the AST node + Result := TAst.FunctionCall(newCallee, newArgs, returnType, Node.IsTailCall, compiled.Func, compiled.IsPure); exit; end; diff --git a/Src/AST/Myc.Ast.Compiler.TCO.pas b/Src/AST/Myc.Ast.Compiler.TCO.pas index f0f8154..968f384 100644 --- a/Src/AST/Myc.Ast.Compiler.TCO.pas +++ b/Src/AST/Myc.Ast.Compiler.TCO.pas @@ -180,7 +180,18 @@ begin begin // Rebuild using factory. // IMPORTANT: Pass Layout AND Descriptor (TCO runs after TypeChecker). - Result := TAst.LambdaExpr(newParams, newBody, Node.Layout, Node.Descriptor, Node.Upvalues, Node.HasNestedLambdas, Node.StaticType); + // (* FIX: Pass Node.IsPure to preserve it *) + Result := + TAst.LambdaExpr( + newParams, + newBody, + Node.Layout, + Node.Descriptor, + Node.Upvalues, + Node.HasNestedLambdas, + Node.IsPure, + Node.StaticType + ); end; end; @@ -242,7 +253,8 @@ begin newArgs, Node.StaticType, isTailCall, - Node.StaticTarget // Preserve the static target from Specializer + Node.StaticTarget, // Preserve the static target from Specializer + Node.IsTargetPure // (* FIX: Preserve the purity flag from Specializer! *) ); end; diff --git a/Src/AST/Myc.Ast.Compiler.TypeChecker.pas b/Src/AST/Myc.Ast.Compiler.TypeChecker.pas index 479d9d7..e4784f6 100644 --- a/Src/AST/Myc.Ast.Compiler.TypeChecker.pas +++ b/Src/AST/Myc.Ast.Compiler.TypeChecker.pas @@ -400,7 +400,8 @@ begin end; // 9. Create new node with the Descriptor attached! - Result := TAst.LambdaExpr(newParams, newBody, Node.Layout, finalDescriptor, Node.Upvalues, Node.HasNestedLambdas, methodType); + Result := + TAst.LambdaExpr(newParams, newBody, Node.Layout, finalDescriptor, Node.Upvalues, Node.HasNestedLambdas, Node.IsPure, methodType); end; function TTypeChecker.VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; diff --git a/Src/AST/Myc.Ast.Dumper.pas b/Src/AST/Myc.Ast.Dumper.pas index 138125a..474e654 100644 --- a/Src/AST/Myc.Ast.Dumper.pas +++ b/Src/AST/Myc.Ast.Dumper.pas @@ -201,7 +201,12 @@ var slot: Integer; typ: IStaticType; begin - LogFmt('LambdaExpression (HasNested: %s)', [Node.HasNestedLambdas.ToString(TUseBoolStrs.True)], Node); + // (* UPDATED: Added IsPure output *) + LogFmt( + 'LambdaExpression (HasNested: %s, IsPure: %s)', + [Node.HasNestedLambdas.ToString(TUseBoolStrs.True), BoolToStr(Node.IsPure, True)], + Node + ); Indent; // 1. Layout & Symbols @@ -277,7 +282,12 @@ begin else staticStatus := 'nil'; - LogFmt('FunctionCall (IsTailCall: %s, StaticTarget: %s%s)', [Node.IsTailCall.ToString(TUseBoolStrs.True), staticStatus, sigStr], Node); + // (* UPDATED: Added IsTargetPure output *) + LogFmt( + 'FunctionCall (IsTailCall: %s, StaticTarget: %s%s, IsTargetPure: %s)', + [Node.IsTailCall.ToString(TUseBoolStrs.True), staticStatus, sigStr, BoolToStr(Node.IsTargetPure, True)], + Node + ); Indent; Log('Callee:'); diff --git a/Src/AST/Myc.Ast.Environment.pas b/Src/AST/Myc.Ast.Environment.pas index 15b4448..c9ebe85 100644 --- a/Src/AST/Myc.Ast.Environment.pas +++ b/Src/AST/Myc.Ast.Environment.pas @@ -41,7 +41,8 @@ type public Func: TDataValue.TFunc; StaticType: IStaticType; - constructor Create(const AFunc: TDataValue.TFunc; const AStaticType: IStaticType); + IsPure: Boolean; + constructor Create(const AFunc: TDataValue.TFunc; const AStaticType: IStaticType; AIsPure: Boolean); end; IExecutionStrategy = interface @@ -143,7 +144,8 @@ uses Myc.Ast.Compiler.Binder, Myc.Ast.Compiler.TypeChecker, Myc.Ast.Compiler.Specializer, - Myc.Ast.Compiler.TCO; + Myc.Ast.Compiler.TCO, + Myc.Ast.Analysis.Purity; { TMonoCacheKey } @@ -202,10 +204,11 @@ end; { TCompiledFunction } -constructor TCompiledFunction.Create(const AFunc: TDataValue.TFunc; const AStaticType: IStaticType); +constructor TCompiledFunction.Create(const AFunc: TDataValue.TFunc; const AStaticType: IStaticType; AIsPure: Boolean); begin Func := AFunc; StaticType := AStaticType; + IsPure := AIsPure; end; type @@ -344,6 +347,8 @@ end; procedure TAstEnvironment.Define(const Name: String; const AScript: IAstNode); begin var compiled := Compile(AScript); + // Note: Define now potentially handles Pure flags internally via the Node metadata, + // but the runtime value is just the TDataValue. RootScope.Define(Name, compiled.Func([]), compiled.StaticType); end; @@ -526,6 +531,7 @@ var typedNode: IAstNode; specialized: IAstNode; tcoOptimized: IAstNode; + isPure: Boolean; begin // 0. Wrap in Lambda to create an isolatable compilation unit (scope) var prg := TAst.LambdaExpr(Params, Node); @@ -549,25 +555,27 @@ begin // 4. Optimize (TCO) tcoOptimized := TAstTCO.Optimize(specialized); - // 5. Create Evaluator - // We create a scope based on the descriptor to run the lambda body. - // The lambda itself (as a node) is evaluated to produce a closure. - // Since we wrapped the user code in a LambdaExpr, evaluating 'tcoOptimized' - // returns the closure (TFunc). + // 5. Purity Inference + // Check the body of the optimized lambda for purity. + // Note: tcoOptimized is a LambdaExpressionNode. Its body is what we check. + isPure := TPurityAnalyzer.IsPure(tcoOptimized.AsLambdaExpression.Body); + + // 6. Create Evaluator var visitor := FExecutionStrategy.CreateVisitor(descriptor.CreateScope(FRootScope)); // Execute the AST to get the TFunc (Closure) - var closure := tcoOptimized.Accept(visitor); + var closure := tcoOptimized.Accept(visitor).AsMethod(); // Wrap TCO handling for the final result finalFunc := function(const Args: TArray): TDataValue begin - Result := closure.AsMethod()(Args); + Result := closure(Args); TEvaluatorVisitor.HandleTCO(Result); end; - Result := TCompiledFunction.Create(finalFunc, funcType); + // Pass IsPure flag to the compiled function record + Result := TCompiledFunction.Create(finalFunc, funcType, isPure); end; function TEnvironment.Compile(const Node: IFunctionDefinition; const ArgTypes: TArray): TCompiledFunction; @@ -578,6 +586,7 @@ var finalFunc: TDataValue.TFunc; typedNode, specialized, tcoOptimized: IAstNode; + isPure: Boolean; begin // Same steps as above, but Node is already a definition (Lambda) var expanded := ExpandMacros(Node); @@ -590,6 +599,9 @@ begin specialized := Specialize(typedNode); tcoOptimized := TAstTCO.Optimize(specialized); + // Purity Inference + isPure := TPurityAnalyzer.IsPure(tcoOptimized.AsLambdaExpression.Body); + var visitor := FExecutionStrategy.CreateVisitor(descriptor.CreateScope(FRootScope)); var closure := tcoOptimized.Accept(visitor); @@ -600,7 +612,7 @@ begin TEvaluatorVisitor.HandleTCO(Result); end; - Result := TCompiledFunction.Create(finalFunc, funcType); + Result := TCompiledFunction.Create(finalFunc, funcType, isPure); end; function TEnvironment.ExpandMacros(const Node: IAstNode): IAstNode; diff --git a/Src/AST/Myc.Ast.Nodes.pas b/Src/AST/Myc.Ast.Nodes.pas index fa19c5d..c37773c 100644 --- a/Src/AST/Myc.Ast.Nodes.pas +++ b/Src/AST/Myc.Ast.Nodes.pas @@ -158,9 +158,11 @@ type {$region 'private'} function GetBody: IAstNode; function GetParameters: TArray; + function GetIsPure: Boolean; // (* ADDED *) {$endregion} property Body: IAstNode read GetBody; property Parameters: TArray read GetParameters; + property IsPure: Boolean read GetIsPure; // (* ADDED *) end; INopNode = interface(IAstTypedNode) @@ -228,6 +230,7 @@ type function GetUpvalues: TArray; function GetHasNestedLambdas: Boolean; + // GetIsPure is inherited from IFunctionDefinition {$endregion} property Parameters: TArray read GetParameters; @@ -238,6 +241,7 @@ type property Upvalues: TArray read GetUpvalues; property HasNestedLambdas: Boolean read GetHasNestedLambdas; + // IsPure is inherited end; IFunctionCallNode = interface(IAstTypedNode) @@ -246,11 +250,13 @@ type function GetArguments: TArray; function GetIsTailCall: Boolean; function GetStaticTarget: TDataValue.TFunc; + function GetIsTargetPure: Boolean; // (* ADDED *) {$endregion} property Callee: IAstNode read GetCallee; property Arguments: TArray read GetArguments; property IsTailCall: Boolean read GetIsTailCall; property StaticTarget: TDataValue.TFunc read GetStaticTarget; + property IsTargetPure: Boolean read GetIsTargetPure; // (* ADDED *) end; // A node representing a macro call. diff --git a/Src/AST/Myc.Ast.RTL.pas b/Src/AST/Myc.Ast.RTL.pas index 68c4959..c6f7e67 100644 --- a/Src/AST/Myc.Ast.RTL.pas +++ b/Src/AST/Myc.Ast.RTL.pas @@ -47,11 +47,11 @@ type public Target: TDataValue.TFunc; ReturnType: IStaticType; - constructor Create(const ATarget: TDataValue.TFunc; const AReturnType: IStaticType); + IsPure: Boolean; // (* ADDED *) + constructor Create(const ATarget: TDataValue.TFunc; const AReturnType: IStaticType; AIsPure: Boolean); end; // The cache holding TDataValue.TFunc wrappers for static native functions. - // Verwendet den generischen TSpecializedMethod-Record aus Myc.Ast.Types TStaticBootstrapCache = TDictionary; TRtlFunctionInfo = class @@ -153,7 +153,7 @@ constructor TRtlExportAttribute.Create(const AName: string); begin inherited Create; Self.Name := AName; - Self.IsPure := False; // Default to impure + Self.IsPure := False; // Default to impure (safe) end; constructor TRtlExportAttribute.Create(const AName: string; AIsPure: Boolean); @@ -230,6 +230,15 @@ begin inherited Destroy; end; +{ TSpecializedMethod } + +constructor TSpecializedMethod.Create(const ATarget: TDataValue.TFunc; const AReturnType: IStaticType; AIsPure: Boolean); +begin + Target := ATarget; + ReturnType := AReturnType; + IsPure := AIsPure; +end; + { TRtlRegistry } class constructor TRtlRegistry.Create; @@ -252,7 +261,7 @@ begin FStaticBootstrap := TStaticBootstrapCache.Create(TStaticSignatureKeyComparer.Create); FStaticFuncMap := TRtlFunctionMap.Create; - // 2. Perform RTTI Scan (formerly Pass 1 of RegisterAll) + // 2. Perform RTTI Scan ctx := TRttiContext.Create; try rtlType := ctx.GetType(TypeInfo(TRtlFunctions)); @@ -292,7 +301,7 @@ begin if isDynamic then begin - if Assigned(funcInfo.DynamicWrapper) and Assigned(funcInfo.DynamicWrapper) then + if Assigned(funcInfo.DynamicWrapper) then raise EInvalidOpException.CreateFmt('Duplicate dynamic fallback defined for %s', [rtlName]); var wrapperFactory := @@ -323,8 +332,8 @@ begin var wrapper := CreateStaticWrapper(method, retType, argTypes, rttiParams); if Assigned(wrapper) then begin - methodRecord := TSpecializedMethod.Create(wrapper, retType); - // Use renamed static helper + // (* UPDATED: Capture IsPure from attribute *) + methodRecord := TSpecializedMethod.Create(wrapper, retType, exportAttr.IsPure); RegisterStaticSpecialization(rtlName, argTypes, methodRecord); end else @@ -366,8 +375,6 @@ var key: TStaticSignatureKey; begin key := TStaticSignatureKey.Create(AName, AArgTypes); - // This allows multiple RTTI scans (e.g. in tests) without crashing, - // though only the class constructor should call this now. FStaticBootstrap.AddOrSetValue(key, AMethod); end; @@ -724,12 +731,6 @@ begin TRtlRegistry.RegisterAll(AScope); end; -constructor TSpecializedMethod.Create(const ATarget: TDataValue.TFunc; const AReturnType: IStaticType); -begin - Target := ATarget; - ReturnType := AReturnType; -end; - initialization // Register this library's functions with the central AST factory. TAst.RegisterLibrary(RegisterRtlFunctions); diff --git a/Src/AST/Myc.Ast.Visitor.pas b/Src/AST/Myc.Ast.Visitor.pas index 2dd7fe5..d55b862 100644 --- a/Src/AST/Myc.Ast.Visitor.pas +++ b/Src/AST/Myc.Ast.Visitor.pas @@ -486,7 +486,17 @@ begin else begin // Use TAst factory and copy properties via interface getters - Result := TAst.LambdaExpr(newParams, newBody, Node.Layout, Node.Descriptor, Node.Upvalues, Node.HasNestedLambdas, Node.StaticType); + Result := + TAst.LambdaExpr( + newParams, + newBody, + Node.Layout, + Node.Descriptor, + Node.Upvalues, + Node.HasNestedLambdas, + Node.IsPure, + Node.StaticType + ); end; end; diff --git a/Src/AST/Myc.Ast.pas b/Src/AST/Myc.Ast.pas index 323fad3..b0935c2 100644 --- a/Src/AST/Myc.Ast.pas +++ b/Src/AST/Myc.Ast.pas @@ -56,14 +56,15 @@ type const AStaticType: IStaticType = nil ): ITernaryExpressionNode; static; - // Factory Updated: Includes Layout (mandatory) and Descriptor (optional) + // (* UPDATED Factory: Added AIsPure *) class function LambdaExpr( const AParameters: TArray; const ABody: IAstNode; - const ALayout: IScopeLayout = nil; // Nil allowed only for raw AST construction (before Binder) - const ADescriptor: IScopeDescriptor = nil; // Nil allowed before TypeChecker + const ALayout: IScopeLayout = nil; + const ADescriptor: IScopeDescriptor = nil; const AUpvalues: TArray = nil; const AHasNestedLambdas: Boolean = False; + const AIsPure: Boolean = False; // (* ADDED *) const AStaticType: IStaticType = nil ): ILambdaExpressionNode; static; @@ -76,12 +77,14 @@ type class function Unquote(const AExpression: IAstNode): IUnquoteNode; static; class function UnquoteSplicing(const AExpression: IQuasiquoteNode): IUnquoteSplicingNode; static; + // (* UPDATED Factory: Added AIsTargetPure *) class function FunctionCall( const ACallee: IAstNode; const AArguments: TArray; const AStaticType: IStaticType = nil; const AIsTailCall: Boolean = False; - const AStaticTarget: TDataValue.TFunc = nil + const AStaticTarget: TDataValue.TFunc = nil; + const AIsTargetPure: Boolean = False // (* ADDED *) ): IFunctionCallNode; static; class function MacroExpansionNode( @@ -194,6 +197,7 @@ type FDescriptor: IScopeDescriptor; FUpvalues: TArray; FHasNestedLambdas: Boolean; + FIsPure: Boolean; // (* ADDED *) function GetParameters: TArray; function GetBody: IAstNode; @@ -201,6 +205,7 @@ type function GetDescriptor: IScopeDescriptor; function GetUpvalues: TArray; function GetHasNestedLambdas: Boolean; + function GetIsPure: Boolean; // (* ADDED *) function GetKind: TAstNodeKind; override; public constructor Create( @@ -210,7 +215,8 @@ type const ALayout: IScopeLayout; const ADescriptor: IScopeDescriptor; const AUpvalues: TArray; - const AHasNestedLambdas: Boolean + const AHasNestedLambdas: Boolean; + const AIsPure: Boolean // (* ADDED *) ); destructor Destroy; override; function Accept(const Visitor: IAstVisitor): TDataValue; override; @@ -223,10 +229,12 @@ type FArguments: TArray; FIsTailCall: Boolean; FStaticTarget: TDataValue.TFunc; + FIsTargetPure: Boolean; // (* ADDED *) function GetCallee: IAstNode; function GetArguments: TArray; function GetIsTailCall: Boolean; function GetStaticTarget: TDataValue.TFunc; + function GetIsTargetPure: Boolean; // (* ADDED *) function GetKind: TAstNodeKind; override; public constructor Create( @@ -234,12 +242,14 @@ type const AArguments: TArray; const AStaticType: IStaticType; const AIsTailCall: Boolean; - const AStaticTarget: TDataValue.TFunc + const AStaticTarget: TDataValue.TFunc; + const AIsTargetPure: Boolean // (* ADDED *) ); function Accept(const Visitor: IAstVisitor): TDataValue; override; function AsFunctionCall: IFunctionCallNode; override; end; + // ... (Other node definitions unchanged) ... TVariableDeclarationNode = class(TAstTypedNode, IVariableDeclarationNode) private FIdentifier: IIdentifierNode; @@ -260,8 +270,6 @@ type function AsVariableDeclaration: IVariableDeclarationNode; override; end; - // --- Other internal node classes --- - TConstantNode = class(TAstTypedNode, IConstantNode) private FValue: TDataValue; @@ -644,7 +652,6 @@ end; class function TAst.Constant(const AValue: TDataValue; const AStaticType: IStaticType = nil): IConstantNode; begin var constType := AStaticType; - if constType = nil then begin case AValue.Kind of @@ -655,7 +662,6 @@ begin constType := TTypes.Unknown; end; end; - Result := TConstantNode.Create(AValue, constType); end; @@ -684,7 +690,8 @@ class function TAst.FunctionCall( const AArguments: TArray; const AStaticType: IStaticType = nil; const AIsTailCall: Boolean = False; - const AStaticTarget: TDataValue.TFunc = nil + const AStaticTarget: TDataValue.TFunc = nil; + const AIsTargetPure: Boolean = False // (* ADDED *) ): IFunctionCallNode; begin Result := @@ -694,7 +701,8 @@ begin if AStaticType <> nil then AStaticType else TTypes.Unknown, AIsTailCall, - AStaticTarget + AStaticTarget, + AIsTargetPure ); end; @@ -759,6 +767,7 @@ class function TAst.LambdaExpr( const ADescriptor: IScopeDescriptor = nil; const AUpvalues: TArray = nil; const AHasNestedLambdas: Boolean = False; + const AIsPure: Boolean = False; // (* ADDED *) const AStaticType: IStaticType = nil ): ILambdaExpressionNode; begin @@ -771,7 +780,8 @@ begin ALayout, ADescriptor, AUpvalues, - AHasNestedLambdas + AHasNestedLambdas, + AIsPure ); end; @@ -1247,7 +1257,8 @@ constructor TLambdaExpressionNode.Create( const ALayout: IScopeLayout; const ADescriptor: IScopeDescriptor; const AUpvalues: TArray; - const AHasNestedLambdas: Boolean + const AHasNestedLambdas: Boolean; + const AIsPure: Boolean // (* ADDED *) ); begin inherited Create(AStaticType); @@ -1257,6 +1268,7 @@ begin FDescriptor := ADescriptor; FUpvalues := AUpvalues; FHasNestedLambdas := AHasNestedLambdas; + FIsPure := AIsPure; // Consistency Check if Assigned(FDescriptor) and (FDescriptor.Layout <> FLayout) then @@ -1308,6 +1320,11 @@ begin Result := FHasNestedLambdas; end; +function TLambdaExpressionNode.GetIsPure: Boolean; // (* ADDED *) +begin + Result := FIsPure; +end; + function TLambdaExpressionNode.GetKind: TAstNodeKind; begin Result := akLambdaExpression; @@ -1444,7 +1461,8 @@ constructor TFunctionCallNode.Create( const AArguments: TArray; const AStaticType: IStaticType; const AIsTailCall: Boolean; - const AStaticTarget: TDataValue.TFunc + const AStaticTarget: TDataValue.TFunc; + const AIsTargetPure: Boolean // (* ADDED *) ); begin inherited Create(AStaticType); @@ -1452,6 +1470,7 @@ begin FArguments := AArguments; FIsTailCall := AIsTailCall; FStaticTarget := AStaticTarget; + FIsTargetPure := AIsTargetPure; end; function TFunctionCallNode.Accept(const Visitor: IAstVisitor): TDataValue; @@ -1489,6 +1508,11 @@ begin Result := FStaticTarget; end; +function TFunctionCallNode.GetIsTargetPure: Boolean; // (* ADDED *) +begin + Result := FIsTargetPure; +end; + { TMacroExpansionNode } constructor TMacroExpansionNode.Create(const ACallNode: IFunctionCallNode; const AExpandedBody: IAstNode);