diff --git a/ASTPlayground/ASTPlayground.delphilsp.json b/ASTPlayground/ASTPlayground.delphilsp.json
index 4cf9498..7d77b89 100644
--- a/ASTPlayground/ASTPlayground.delphilsp.json
+++ b/ASTPlayground/ASTPlayground.delphilsp.json
@@ -1 +1 @@
-{ "settings": { "project": "file:///T%3A/Myc/ASTPlayground/ASTPlayground.dpr", "dllname": "dcc64370.dll", "dccOptions": "-$O- -$W+ --inline:off -$R+ -$Q+ --no-config -Q -TX.exe -AGenerics.Collections=System.Generics.Collections;Generics.Defaults=System.Generics.Defaults;WinTypes=Winapi.Windows;WinProcs=Winapi.Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE -DDEBUG;;FRAMEWORK_FMX -E.\\Win64\\Debug -I\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\\DE\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -LEC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Bpl\\Win64 -LNC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64 -NU.\\Win64\\Debug -NSWinapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;System;Xml;Data;Datasnap;Web;Soap; -OT:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -R\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -U\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\\DE\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -V -VN -VR -NBC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64 -NHC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\hpp\\Win64 -NO.\\Win64\\Debug -LU" , "projectFiles":[ { "name": "MainForm", "file": "file:///T%3A/Myc/ASTPlayground/MainForm.pas" }, { "name": "Myc.Ast.Nodes", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Nodes.pas" }, { "name": "Myc.Ast.Scope", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Scope.pas" }, { "name": "Myc.Data.Value", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Data.Value.pas" }, { "name": "Myc.Ast.Visitor", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Visitor.pas" }, { "name": "Myc.Ast.RTL", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.pas" }, { "name": "Myc.Ast.Dumper", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Dumper.pas" }, { "name": "Myc.Ast.RTL.Core", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.Core.pas" }, { "name": "Myc.Utils", "file": "file:///T%3A/Myc/Src/Myc.Utils.pas" }, { "name": "Myc.Ast.Script", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Script.pas" }, { "name": "Myc.Ast.Types", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Types.pas" }, { "name": "Myc.Data.Keyword", "file": "file:///T%3A/Myc/Src/Data/Myc.Data.Keyword.pas" }, { "name": "Myc.Ast.Compiler.TCO", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.TCO.pas" }, { "name": "Myc.Ast.Compiler.Binder", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Binder.pas" }, { "name": "Myc.Ast.Compiler.Lowering", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Lowering.pas" }, { "name": "Myc.Ast.Compiler.TypeChecker", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.TypeChecker.pas" }, { "name": "Myc.Ast.Compiler.Macros", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Macros.pas" }, { "name": "Myc.Ast.Compiler.Specializer", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Specializer.pas" }, { "name": "Myc.Ast.Environment", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Environment.pas" }, { "name": "Myc.Ast.Debugger", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Debugger.pas" }, { "name": "Myc.Ast.Analysis.Purity", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Analysis.Purity.pas" }, { "name": "Myc.Ast.Identities", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Identities.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.pas" }, { "name": "Myc.Fmx.AstEditor.Visualizer", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Visualizer.pas" }, { "name": "Myc.Fmx.AstEditor.Workspace", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Workspace.pas" }, { "name": "Myc.Fmx.AstEditor.Layout", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Layout.pas" }, { "name": "Myc.Fmx.AstEditor.Node", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Node.pas" }, { "name": "Myc.Ast.Refactoring.Remove", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Refactoring.Remove.pas" }, { "name": "Myc.Fmx.AstEditor.Render", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Render.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Lists", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Lists.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Primitives", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Primitives.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Control", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Control.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Data", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Data.pas" }, { "name": "Myc.Ast.RTL.TypeRegistry", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.TypeRegistry.pas" }, { "name": "Myc.Trade.Broker", "file": "file:///T%3A/Myc/Src/Myc.Trade.Broker.pas" } ] , "includeDCUsInUsesCompletion": true, "enableKeyWordCompletion": false, "browsingPaths": [ "file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/OCX/Servers","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/VCL","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/RTL/SYS","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/win","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/win/winrt","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/ToolsAPI","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/IBX","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Internet","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/PROPERTY%20EDITORS","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/soap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/XML","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/Core","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/System","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/Protocols","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/fmx","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/components","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/engine","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/graph","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/ado","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/cloud","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/dbx","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/dsnap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/vclctrls","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap/connectors","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap/proxygen","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DataExplorer","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/Common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/Common/dunit","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/Common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/DUnitProject","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/DUnitProject/dunit","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/src","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/tests","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Experts","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indy/abstraction","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indy/implementation","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indyimpl","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Property%20Editors/Indy10","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/soap/wsdlimporter","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Visualizers","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/XMLReporting","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/XPGen","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/rest","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/firedac","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/tethering","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnitX","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/ems","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/net","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/FlatBox2D","file:///C%3A/Users/Public/Documents/Embarcadero/Studio/37.0/Dcp/%25PLATFORM%25","file:///%25TP%25/runtime/vcl","file:///S%3A/sc_famos_src/svn_vcl/cpxedits","file:///S%3A/sc_famos_src/svn_vcl/dzChart","file:///S%3A/sc_famos_src/svn_vcl/eaeditor","file:///S%3A/sc_famos_src/svn_vcl/FamosEvents","file:///S%3A/sc_famos_src/svn_vcl/HTML_Viewer/source","file:///S%3A/sc_famos_src/svn_vcl/Myc_ChartEdit","file:///S%3A/sc_famos_src/svn_vcl/Myc_HemiDrag","file:///S%3A/sc_famos_src/svn_vcl/Myc_SplitControl","file:///S%3A/sc_famos_src/svn_vcl/NiceChart","file:///S%3A/sc_famos_src/svn_vcl/plotter","file:///S%3A/sc_famos_src/svn_vcl/SimpleIPC","file:///S%3A/sc_famos_src/svn_vcl/SynEdit-master/Source","file:///S%3A/sc_famos_src/svn_vcl/ValEdits","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster/zlib","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster/zlib/win32","file:///S%3A/sc_famos_src/svn_vcl/Virtual-TreeView/Source","file:///S%3A/sc_famos_src/svn_common/caHelpSys","file:///S%3A/sc_famos_src/svn_common/Misc","file:///S%3A/sc_famos_src/svn_common/Myc_VecMath","file:///S%3A/sc_famos_src/svn_common/PascalScript/source","file:///S%3A/sc_famos_src/svn_common/TreeBase","file:///S%3A/sc_famos_src/svn_common/TreeBase/Medien","file:///S%3A/3rdParty/spring4d/Source","file:///S%3A/3rdParty/spring4d/Source/Base","file:///S%3A/3rdParty/spring4d/Source/Base/Collections","file:///S%3A/3rdParty/spring4d/Source/Base/Logging","file:///S%3A/3rdParty/spring4d/Source/Base/Patches","file:///S%3A/3rdParty/spring4d/Source/Core/Container","file:///S%3A/3rdParty/spring4d/Source/Core/Interception","file:///S%3A/3rdParty/spring4d/Source/Core/Logging","file:///S%3A/3rdParty/spring4d/Source/Core/Mocking","file:///S%3A/3rdParty/spring4d/Source/Core/Services","file:///S%3A/3rdParty/spring4d/Source/Extensions/Cryptography","file:///S%3A/3rdParty/spring4d/Source/Extensions/Utils","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressCore%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressCommon%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressGDI%2B%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressLibrary/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/XP%20Theme%20Manager/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressLayout%20Control/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressPageControl/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressEditors%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressDocking%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressBars/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressOfficeCore%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressMemData/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressDataController/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressNavBar/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressSkins%20Library/Sources","file:///T%3A/Myc/Src","file:///T%3A/Myc/Src/Data","file:///T%3A/Myc/Src/AST" ] , "CommonAppData": "file:///C%3A/Users/Brummel/AppData/Roaming/Embarcadero/BDS/37.0/" , "Templates": "file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/ObjRepos/" } }
\ No newline at end of file
+{ "settings": { "project": "file:///T%3A/Myc/ASTPlayground/ASTPlayground.dpr", "dllname": "dcc64370.dll", "dccOptions": "-$O- -$W+ --inline:off -$R+ -$Q+ --no-config -Q -TX.exe -AGenerics.Collections=System.Generics.Collections;Generics.Defaults=System.Generics.Defaults;WinTypes=Winapi.Windows;WinProcs=Winapi.Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE -DDEBUG;;FRAMEWORK_FMX -E.\\Win64\\Debug -I\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\\DE\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -LEC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Bpl\\Win64 -LNC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64 -NU.\\Win64\\Debug -NSWinapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;System;Xml;Data;Datasnap;Web;Soap; -OT:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -R\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -U\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\\DE\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -V -VN -VR -NBC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64 -NHC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\hpp\\Win64 -NO.\\Win64\\Debug -LU" , "projectFiles":[ { "name": "MainForm", "file": "file:///T%3A/Myc/ASTPlayground/MainForm.pas" }, { "name": "Myc.Ast.Nodes", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Nodes.pas" }, { "name": "Myc.Ast.Scope", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Scope.pas" }, { "name": "Myc.Data.Value", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Data.Value.pas" }, { "name": "Myc.Ast.Visitor", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Visitor.pas" }, { "name": "Myc.Ast.RTL", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.pas" }, { "name": "Myc.Ast.Dumper", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Dumper.pas" }, { "name": "Myc.Ast.RTL.Core", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.Core.pas" }, { "name": "Myc.Utils", "file": "file:///T%3A/Myc/Src/Myc.Utils.pas" }, { "name": "Myc.Ast.Script", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Script.pas" }, { "name": "Myc.Ast.Types", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Types.pas" }, { "name": "Myc.Data.Keyword", "file": "file:///T%3A/Myc/Src/Data/Myc.Data.Keyword.pas" }, { "name": "Myc.Ast.Compiler.TCO", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.TCO.pas" }, { "name": "Myc.Ast.Compiler.Binder", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Binder.pas" }, { "name": "Myc.Ast.Compiler.Lowering", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Lowering.pas" }, { "name": "Myc.Ast.Compiler.TypeChecker", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.TypeChecker.pas" }, { "name": "Myc.Ast.Compiler.Macros", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Macros.pas" }, { "name": "Myc.Ast.Compiler.Specializer", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Specializer.pas" }, { "name": "Myc.Ast.Environment", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Environment.pas" }, { "name": "Myc.Ast.Debugger", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Debugger.pas" }, { "name": "Myc.Ast.Analysis.Purity", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Analysis.Purity.pas" }, { "name": "Myc.Ast.Identities", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Identities.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.pas" }, { "name": "Myc.Fmx.AstEditor.Visualizer", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Visualizer.pas" }, { "name": "Myc.Fmx.AstEditor.Workspace", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Workspace.pas" }, { "name": "Myc.Fmx.AstEditor.Layout", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Layout.pas" }, { "name": "Myc.Fmx.AstEditor.Node", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Node.pas" }, { "name": "Myc.Ast.Refactoring.Remove", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Refactoring.Remove.pas" }, { "name": "Myc.Fmx.AstEditor.Render", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Render.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Lists", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Lists.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Primitives", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Primitives.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Control", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Control.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Data", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Data.pas" }, { "name": "Myc.Ast.RTL.TypeRegistry", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.TypeRegistry.pas" }, { "name": "Myc.Trade.Broker", "file": "file:///T%3A/Myc/Src/Myc.Trade.Broker.pas" }, { "name": "Myc.Ast.Pipes", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Pipes.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 2db9b4c..f9468b3 100644
--- a/ASTPlayground/ASTPlayground.dpr
+++ b/ASTPlayground/ASTPlayground.dpr
@@ -38,7 +38,8 @@ uses
Myc.Fmx.AstEditor.Handlers.Control in '..\Src\AST\Myc.Fmx.AstEditor.Handlers.Control.pas',
Myc.Fmx.AstEditor.Handlers.Data in '..\Src\AST\Myc.Fmx.AstEditor.Handlers.Data.pas',
Myc.Ast.RTL.TypeRegistry in '..\Src\AST\Myc.Ast.RTL.TypeRegistry.pas',
- Myc.Trade.Broker in '..\Src\Myc.Trade.Broker.pas';
+ Myc.Trade.Broker in '..\Src\Myc.Trade.Broker.pas',
+ Myc.Ast.Pipes in '..\Src\AST\Myc.Ast.Pipes.pas';
{$R *.res}
diff --git a/ASTPlayground/ASTPlayground.dproj b/ASTPlayground/ASTPlayground.dproj
index 3177e75..30b15c0 100644
--- a/ASTPlayground/ASTPlayground.dproj
+++ b/ASTPlayground/ASTPlayground.dproj
@@ -169,6 +169,7 @@
+
Base
diff --git a/Src/AST/Myc.Ast.Evaluator.pas b/Src/AST/Myc.Ast.Evaluator.pas
index 661a6eb..29cab95 100644
--- a/Src/AST/Myc.Ast.Evaluator.pas
+++ b/Src/AST/Myc.Ast.Evaluator.pas
@@ -431,9 +431,6 @@ begin
vkRecordSeries:
begin
recSeries := baseValue.AsRecordSeries;
- if (index < 0) or (index >= recSeries.TotalCount) then
- raise EEvaluatorException
- .CreateFmt('Index %d is out of bounds for series with %d elements.', [index, recSeries.TotalCount]);
fieldCount := recSeries.Def.Count;
SetLength(values, fieldCount);
@@ -441,7 +438,12 @@ begin
for i := 0 to fieldCount - 1 do
begin
key := recSeries.Def.Items[i].Key;
- memberSeries := recSeries[key];
+ memberSeries := recSeries.Fields[key];
+
+ if (index < 0) or (index >= memberSeries.TotalCount) then
+ raise EEvaluatorException
+ .CreateFmt('Index %d is out of bounds for series with %d elements.', [index, memberSeries.TotalCount]);
+
scalarValue := memberSeries[index];
values[i] := scalarValue.Value;
end;
@@ -460,7 +462,7 @@ begin
baseValue := Node.Base.Accept(Self);
case baseValue.Kind of
- vkRecordSeries: Result := TDataValue.FromSeries(baseValue.AsRecordSeries[Node.Member.Value]);
+ vkRecordSeries: Result := TDataValue.FromSeries(baseValue.AsRecordSeries.Fields[Node.Member.Value]);
vkScalarRecord: Result := TDataValue(baseValue.AsScalarRecord.Fields[Node.Member.Value]);
vkGenericRecord: Result := TDataValue(baseValue.AsGenericRecord.Fields[Node.Member.Value]);
else
@@ -583,7 +585,7 @@ begin
case seriesValue.Kind of
vkSeries: len := seriesValue.AsSeries.Count;
- vkRecordSeries: len := seriesValue.AsRecordSeries.Count;
+ vkRecordSeries: len := seriesValue.AsRecordSeries.RecordCount;
else
raise EEvaluatorException
.CreateFmt('Cannot get length of type %s.', [GetEnumName(TypeInfo(TDataValueKind), Ord(seriesValue.Kind))]);
diff --git a/Src/AST/Myc.Ast.Nodes.pas b/Src/AST/Myc.Ast.Nodes.pas
index 2e294ba..a8fdaf6 100644
--- a/Src/AST/Myc.Ast.Nodes.pas
+++ b/Src/AST/Myc.Ast.Nodes.pas
@@ -141,7 +141,11 @@ type
akAddSeriesItem,
akSeriesLength,
akRecur,
- akNop
+ akNop,
+ // Pipes
+ akPipe,
+ akPipeInput,
+ akPipeInputList
);
TAstNodeKindHelper = record helper for TAstNodeKind
@@ -452,10 +456,38 @@ type
property Series: IIdentifierNode read GetSeries;
end;
+ // Represents a single input definition within a pipe: "btc [:Close]"
+ // - StreamSource: The identifier of the stream (e.g., "btc")
+ // - Selector: Optional keyword path to select a field (e.g., :Close)
+ IPipeInputNode = interface(IAstTypedNode)
+ {$region 'private'}
+ function GetStreamSource: IIdentifierNode;
+ function GetSelector: IKeywordNode; // Can be nil if the whole record is used
+ {$endregion}
+ property StreamSource: IIdentifierNode read GetStreamSource;
+ property Selector: IKeywordNode read GetSelector;
+ end;
+
+ // A list of pipe inputs
+ IPipeInputList = interface(INodeList)
+ end;
+
+ // The main pipe definition: (pipe [inputs...] (fn ...))
+ IPipeNode = interface(IAstTypedNode)
+ {$region 'private'}
+ function GetInputs: IPipeInputList;
+ function GetTransformation: ILambdaExpressionNode;
+ {$endregion}
+ property Inputs: IPipeInputList read GetInputs;
+ property Transformation: ILambdaExpressionNode read GetTransformation;
+ end;
+
IParameterList = interface(INodeList)
end;
+
IArgumentList = interface(INodeList)
end;
+
IExpressionList = interface(INodeList)
end;
@@ -491,6 +523,12 @@ type
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
function VisitRecurNode(const Node: IRecurNode): TDataValue;
function VisitNop(const Node: INopNode): TDataValue;
+
+ // Pipes
+ // Not implemented yet. that's ok, it just needs to compile
+ // function VisitPipeInput(const Node: IPipeInputNode): TDataValue;
+ // function VisitPipeInputList(const Node: IPipeInputList): TDataValue;
+ // function VisitPipe(const Node: IPipeNode): TDataValue;
end;
IEvaluatorVisitor = interface(IAstVisitor)
@@ -502,9 +540,10 @@ type
TAstNode = class(TInterfacedObject, IAstNode)
private
FIdentity: IAstIdentity;
+ function GetIdentity: IAstIdentity;
+ protected
function GetKind: TAstNodeKind; virtual; abstract;
function GetIsTyped: Boolean; virtual;
- function GetIdentity: IAstIdentity;
public
constructor Create(const AIdentity: IAstIdentity);
function Accept(const Visitor: IAstVisitor): TDataValue; virtual; abstract;
@@ -551,6 +590,7 @@ type
private
FStaticType: IStaticType;
function GetStaticType: IStaticType;
+ protected
function GetIsTyped: Boolean; override;
public
constructor Create(const AStaticType: IStaticType; const AIdentity: IAstIdentity);
@@ -617,6 +657,7 @@ type
FValue: IAstNode;
function GetKey: IKeywordNode;
function GetValue: IAstNode;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(const AKey: IKeywordNode; const AValue: IAstNode; const AIdentity: IAstIdentity);
@@ -638,6 +679,7 @@ type
private
FConstIdentity: IConstantIdentity; // Typed reference for fast access
function GetValue: TDataValue;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(const AIdentity: IConstantIdentity; const AStaticType: IStaticType);
@@ -651,6 +693,7 @@ type
FAddress: TResolvedAddress;
function GetAddress: TResolvedAddress;
function GetName: string;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(const AIdentity: INamedIdentity; const AAddress: TResolvedAddress; const AStaticType: IStaticType);
@@ -662,6 +705,7 @@ type
private
FKeywordIdentity: IKeywordIdentity;
function GetValue: IKeyword;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(const AIdentity: IKeywordIdentity);
@@ -673,6 +717,7 @@ type
private
FDefIdentity: IDefinitionIdentity;
function GetDefinition: String;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(const AIdentity: IDefinitionIdentity; const AStaticType: IStaticType);
@@ -688,6 +733,7 @@ type
function GetCondition: IAstNode;
function GetThenBranch: IAstNode;
function GetElseBranch: IAstNode;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(
@@ -705,6 +751,7 @@ type
FElseBranch: IAstNode;
function GetPairs: TArray;
function GetElseBranch: IAstNode;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(
@@ -732,6 +779,7 @@ type
function GetUpvalues: TArray;
function GetHasNestedLambdas: Boolean;
function GetIsPure: Boolean;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(
@@ -760,6 +808,7 @@ type
function GetIsTailCall: Boolean;
function GetStaticTarget: TDataValue.TFunc;
function GetIsTargetPure: Boolean;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(
@@ -783,6 +832,7 @@ type
function GetName: IIdentifierNode;
function GetParameters: IParameterList;
function GetBody: IAstNode;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(
@@ -801,6 +851,7 @@ type
FExpandedBody: IAstNode;
function GetCallNode: IFunctionCallNode;
function GetExpandedBody: IAstNode;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(const ACallNode: IFunctionCallNode; const AExpandedBody: IAstNode; const AIdentity: IAstIdentity);
@@ -812,6 +863,7 @@ type
private
FExpression: IAstNode;
function GetExpression: IAstNode;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(const AExpression: IAstNode; const AIdentity: IAstIdentity);
@@ -823,6 +875,7 @@ type
private
FExpression: IAstNode;
function GetExpression: IAstNode;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(const AExpression: IAstNode; const AIdentity: IAstIdentity);
@@ -834,6 +887,7 @@ type
private
FExpression: IQuasiquoteNode;
function GetExpression: IQuasiquoteNode;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(const AExpression: IQuasiquoteNode; const AIdentity: IAstIdentity);
@@ -845,6 +899,7 @@ type
private
FArguments: IArgumentList;
function GetArguments: IArgumentList;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(const AArguments: IArgumentList; const AStaticType: IStaticType; const AIdentity: IAstIdentity);
@@ -856,6 +911,7 @@ type
private
FExpressions: IExpressionList;
function GetExpressions: IExpressionList;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(const AExpressions: IExpressionList; const AStaticType: IStaticType; const AIdentity: IAstIdentity);
@@ -870,6 +926,7 @@ type
function GetTarget: IAstNode;
function GetInitializer: IAstNode;
function GetIsBoxed: Boolean;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(
@@ -888,6 +945,7 @@ type
FTarget, FValue: IAstNode;
function GetTarget: IAstNode;
function GetValue: IAstNode;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(const ATarget, AValue: IAstNode; const AStaticType: IStaticType; const AIdentity: IAstIdentity);
@@ -900,6 +958,7 @@ type
FBase, FIndex: IAstNode;
function GetBase: IAstNode;
function GetIndex: IAstNode;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(const ABase, AIndex: IAstNode; const AStaticType: IStaticType; const AIdentity: IAstIdentity);
@@ -913,6 +972,7 @@ type
FMember: IKeywordNode;
function GetBase: IAstNode;
function GetMember: IKeywordNode;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(
@@ -933,6 +993,7 @@ type
function GetFields: IRecordFieldList;
function GetGenericDefinition: IGenericRecordDefinition;
function GetScalarDefinition: IScalarRecordDefinition;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(
@@ -953,6 +1014,7 @@ type
function GetSeries: IIdentifierNode;
function GetValue: IAstNode;
function GetLookback: IAstNode;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(
@@ -969,6 +1031,7 @@ type
private
FSeries: IIdentifierNode;
function GetSeries: IIdentifierNode;
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(const ASeries: IIdentifierNode; const AStaticType: IStaticType; const AIdentity: IAstIdentity);
@@ -977,7 +1040,7 @@ type
end;
TNopNode = class(TAstTypedNode, INopNode)
- private
+ protected
function GetKind: TAstNodeKind; override;
public
constructor Create(const AStaticType: IStaticType; const AIdentity: IAstIdentity);
@@ -985,6 +1048,49 @@ type
function AsNop: INopNode; override;
end;
+ TPipeInputNode = class(TAstTypedNode, IPipeInputNode)
+ private
+ FStreamSource: IIdentifierNode;
+ FSelector: IKeywordNode;
+ function GetStreamSource: IIdentifierNode;
+ function GetSelector: IKeywordNode;
+ protected
+ function GetKind: TAstNodeKind; override;
+ public
+ constructor Create(
+ const AStreamSource: IIdentifierNode;
+ const ASelector: IKeywordNode;
+ const AIdentity: IAstIdentity;
+ const AStaticType: IStaticType
+ );
+ function Accept(const Visitor: IAstVisitor): TDataValue; override;
+ end;
+
+ TPipeInputList = class(TAstNodeList, IPipeInputList)
+ protected
+ function GetKind: TAstNodeKind; override;
+ public
+ function Accept(const Visitor: IAstVisitor): TDataValue; override;
+ end;
+
+ TPipeNode = class(TAstTypedNode, IPipeNode)
+ private
+ FInputs: IPipeInputList;
+ FTransformation: ILambdaExpressionNode;
+ function GetInputs: IPipeInputList;
+ function GetTransformation: ILambdaExpressionNode;
+ protected
+ function GetKind: TAstNodeKind; override;
+ public
+ constructor Create(
+ const AInputs: IPipeInputList;
+ const ATransformation: ILambdaExpressionNode;
+ const AIdentity: IAstIdentity;
+ const AStaticType: IStaticType
+ );
+ function Accept(const Visitor: IAstVisitor): TDataValue; override;
+ end;
+
implementation
uses
@@ -2260,4 +2366,84 @@ begin
Inc(FIndex);
end;
+{ TPipeInputNode }
+
+constructor TPipeInputNode.Create(
+ const AStreamSource: IIdentifierNode;
+ const ASelector: IKeywordNode;
+ const AIdentity: IAstIdentity;
+ const AStaticType: IStaticType
+);
+begin
+ inherited Create(AStaticType, AIdentity);
+ FStreamSource := AStreamSource;
+ FSelector := ASelector;
+end;
+
+function TPipeInputNode.Accept(const Visitor: IAstVisitor): TDataValue;
+begin
+ // Result := Visitor.VisitPipeInput(Self);
+end;
+
+function TPipeInputNode.GetKind: TAstNodeKind;
+begin
+ Result := akPipeInput;
+end;
+
+function TPipeInputNode.GetSelector: IKeywordNode;
+begin
+ Result := FSelector;
+end;
+
+function TPipeInputNode.GetStreamSource: IIdentifierNode;
+begin
+ Result := FStreamSource;
+end;
+
+{ TPipeInputList }
+
+function TPipeInputList.Accept(const Visitor: IAstVisitor): TDataValue;
+begin
+ // Result := Visitor.VisitPipeInputList(Self);
+end;
+
+function TPipeInputList.GetKind: TAstNodeKind;
+begin
+ Result := akPipeInputList;
+end;
+
+{ TPipeNode }
+
+constructor TPipeNode.Create(
+ const AInputs: IPipeInputList;
+ const ATransformation: ILambdaExpressionNode;
+ const AIdentity: IAstIdentity;
+ const AStaticType: IStaticType
+);
+begin
+ inherited Create(AStaticType, AIdentity);
+ FInputs := AInputs;
+ FTransformation := ATransformation;
+end;
+
+function TPipeNode.Accept(const Visitor: IAstVisitor): TDataValue;
+begin
+ // Result := Visitor.VisitPipe(Self);
+end;
+
+function TPipeNode.GetInputs: IPipeInputList;
+begin
+ Result := FInputs;
+end;
+
+function TPipeNode.GetKind: TAstNodeKind;
+begin
+ Result := akPipe;
+end;
+
+function TPipeNode.GetTransformation: ILambdaExpressionNode;
+begin
+ Result := FTransformation;
+end;
+
end.
diff --git a/Src/AST/Myc.Ast.Pipes.pas b/Src/AST/Myc.Ast.Pipes.pas
new file mode 100644
index 0000000..fc644ba
--- /dev/null
+++ b/Src/AST/Myc.Ast.Pipes.pas
@@ -0,0 +1,272 @@
+(*TODO
+Ich möchte ein neues Sprachkonzept einbauen. Folgendes Skript skizziert, was möglich sein soll:
+
+; Record-Streams sind Record-Series, an die "Pipes" andocken können (Observer) um neue Daten zu bekommen
+; Es handelt sich um reaktives Producer-Consumer-Pattern
+
+;; Beispiel: SMA auf Close
+(def btc (create-ticker "BTCUSD")) ; ein Open-High-Low-Close-Record-Stream
+(def sma (create-sma 20)) ; erzeugt eine Lambda (sma(price)), die den sma20 berechnet
+
+
+; Das Ergebnis eines pipe-Befehls ist wieder ein Record-Stream.
+; btc-sma ist also ein Record-Stream, der {:ma ..} records enthält:
+(def btc-sma
+ (pipe [btc [:Close]]
+ (fn [price]
+ ; pipe mappt die Elemente des Record-Streams (hier :Close) auf die Parameter der fn. Price ist als eine ScalarSeries.
+ ; (Index=0 ist das neueste Element)
+ ; emit ist eine von pipe in den lambda-scope injizierte Funktion, die das neue Element in den Ergebnis-Stream
+ ; pusht (und damit die Observer des Ergebnis-Streams benachrichtigt).
+ (emit {:ma (sma (get price 0))})
+ )
+ )
+)
+
+; Diese pipe hat zwei Streams als Input: den Closing-Price und den SMA. Jede pipe kann also N Input Stream haben
+(def btc-signal
+ (pipe [btc [:Close] btc-sma [:ma]]
+ (fn [price ma]
+ (emit {:signal (? (> (get price 0) (get ma 0)) :buy : sell)})
+ )
+ )
+)
+*)
+
+unit Myc.Ast.Pipes;
+
+interface
+
+uses
+ System.SysUtils,
+ System.Classes,
+ System.Generics.Collections,
+ System.SyncObjs,
+ Myc.Data.Value,
+ Myc.Data.Scalar,
+ Myc.Data.Keyword,
+ Myc.Data.Stream,
+ Myc.Core.Notifier;
+
+type
+ // Forward declaration
+ TPipeStream = class;
+
+ // mapped fields per input stream
+ TPipeConfig = TArray>;
+
+ TPipeSource = class(TInterfacedObject, IStreamObserver)
+ private
+ [Weak]
+ FOwner: TPipeStream;
+ FSource: IStream;
+ FTag: TSubscriptionTag;
+
+ // State for barrier synchronization
+ FLastSeenCycle: Int64;
+
+ procedure OnSignal(const Signal: TStreamSignal);
+ procedure Destroying;
+
+ public
+ constructor Create(AOwner: TPipeStream; ASource: IStream; const AInputs: TArray);
+ property LastSeenCycle: Int64 read FLastSeenCycle;
+ end;
+
+ // --- Runtime: The Pipe ---
+ // The executable instance of a pipe.
+ // Acts as IStream (Producer) for downstream consumers and manages internal inputs.
+ TPipeStream = class(TInterfacedObject, IStream)
+ private
+ FConfig: TPipeConfig;
+ FSources: TArray;
+ FObservers: TMycNotifyList;
+ FSeries: IWriteableScalarRecordSeries;
+
+ // Barrier State
+ FLastFiredCycleID: Int64;
+
+ // Execution Logic
+ // The compiled lambda function representing (fn [inputs...] ...)
+ FLambda: TDataValue.TFunc;
+ FLambdaArgs: TArray;
+
+ procedure CheckBarrierAndFire(CurrentCycle: Int64);
+ function GetSeries: IScalarRecordSeries;
+
+ public
+ constructor Create(const AConfig: TPipeConfig; const ASources: TArray);
+ destructor Destroy; override;
+
+ procedure SetTransformation(const Lambda: TDataValue.TFunc);
+
+ // Injected into lambda scope as "emit"
+ procedure Emit(const Value: IScalarRecord);
+
+ // IStream Implementation
+ function Subscribe(const Observer: IStreamObserver): TSubscriptionTag;
+ procedure Unsubscribe(Tag: TSubscriptionTag);
+ end;
+
+implementation
+
+uses
+ Myc.Ast.Visitor;
+
+{ TPipeSource }
+
+constructor TPipeSource.Create(AOwner: TPipeStream; ASource: IStream; const AInputs: TArray);
+begin
+ inherited Create;
+
+ FOwner := AOwner;
+ FSource := ASource;
+ FLastSeenCycle := -1;
+
+ FTag := FSource.Subscribe(Self);
+end;
+
+procedure TPipeSource.Destroying;
+begin
+ FSource.Unsubscribe(FTag);
+ FOwner := nil;
+end;
+
+procedure TPipeSource.OnSignal(const Signal: TStreamSignal);
+begin
+ FLastSeenCycle := Signal.CycleID;
+
+ if Assigned(FOwner) then
+ FOwner.CheckBarrierAndFire(FLastSeenCycle);
+end;
+
+{ TPipeStream }
+
+constructor TPipeStream.Create(const AConfig: TPipeConfig; const ASources: TArray);
+var
+ fields: TArray;
+begin
+ inherited Create;
+ FConfig := AConfig;
+ FLastFiredCycleID := -1;
+
+ Assert(Length(AConfig) = Length(ASources));
+
+ SetLength(FSources, Length(ASources));
+
+ // Construct record series definition from source config
+ var n := 0;
+ for var i := 0 to High(AConfig) do
+ begin
+ FSources[i] := TPipeSource.Create(Self, ASources[i], AConfig[i]);
+ FSources[i]._AddRef;
+ inc(n, Length(AConfig[i]));
+ end;
+
+ SetLength(FLambdaArgs, n);
+
+ n := 0;
+ for var i := 0 to High(AConfig) do
+ begin
+ for var j := 0 to High(AConfig[i]) do
+ begin
+ fields[n] := AConfig[i][j];
+
+ FLambdaArgs[n] := TDataValue.FromSeries(ASources[i].Series[j].Value);
+
+ inc(n);
+ end;
+ end;
+
+ FSeries := TScalarRecordSeries.Create(TScalarRecord.TRegistry.Intern(fields));
+end;
+
+destructor TPipeStream.Destroy;
+begin
+ for var src in FSources do
+ begin
+ src.Destroying;
+ src._Release;
+ end;
+ FObservers.Finalize;
+ inherited;
+end;
+
+procedure TPipeStream.SetTransformation(const Lambda: TDataValue.TFunc);
+begin
+ FLambda := Lambda;
+end;
+
+function TPipeStream.Subscribe(const Observer: IStreamObserver): TSubscriptionTag;
+begin
+ FObservers.Lock;
+ try
+ Result := FObservers.Advise(Observer);
+ finally
+ FObservers.Release;
+ end;
+end;
+
+procedure TPipeStream.Unsubscribe(Tag: TSubscriptionTag);
+begin
+ FObservers.Lock;
+ try
+ FObservers.Unadvise(Tag);
+ finally
+ FObservers.Release;
+ end;
+end;
+
+procedure TPipeStream.CheckBarrierAndFire(CurrentCycle: Int64);
+begin
+ // Barrier Check
+ for var src in FSources do
+ begin
+ if src.LastSeenCycle < CurrentCycle then
+ exit;
+ end;
+
+ // --- Barrier Open ---
+
+ if FLastFiredCycleID >= CurrentCycle then
+ exit;
+
+ FLastFiredCycleID := CurrentCycle;
+
+ // Execute Lambda
+ if Assigned(FLambda) then
+ begin
+ try
+ FLambda(FLambdaArgs);
+ except
+ // Error handling strategy: Propagate/Crash for now.
+ raise;
+ end;
+ end;
+end;
+
+procedure TPipeStream.Emit(const Value: IScalarRecord);
+begin
+ FObservers.Lock;
+ try
+ FSeries.Add(Value);
+ var signal := TStreamSignal.Create(skData, FLastFiredCycleID);
+
+ FObservers.Notify(
+ function(const Obs: IStreamObserver): Boolean
+ begin
+ Obs.OnSignal(signal);
+ Result := True;
+ end
+ );
+ finally
+ FObservers.Release;
+ end;
+end;
+
+function TPipeStream.GetSeries: IScalarRecordSeries;
+begin
+ Result := FSeries;
+end;
+
+end.
diff --git a/Src/AST/Myc.Ast.pas b/Src/AST/Myc.Ast.pas
index 445d928..5fa8c7a 100644
--- a/Src/AST/Myc.Ast.pas
+++ b/Src/AST/Myc.Ast.pas
@@ -1,3 +1,6 @@
+//==================================================================================================
+//== FULL UNIT START: Myc.Ast (from Myc.Ast.pas)
+//==================================================================================================
unit Myc.Ast;
interface
@@ -327,6 +330,27 @@ type
const AStaticType: IStaticType = nil
): ISeriesLengthNode; overload; static;
+ // --- PIPES ---
+
+ class function PipeInput(
+ const AStream: IIdentifierNode;
+ const ASelector: IKeywordNode = nil;
+ const Loc: ISourceLocation = nil
+ ): IPipeInputNode; static;
+
+ class function Pipe(
+ const AInputs: TArray;
+ const ATransformation: ILambdaExpressionNode;
+ const Loc: ISourceLocation = nil
+ ): IPipeNode; overload; static;
+
+ class function Pipe(
+ const Identity: IAstIdentity;
+ const AInputs: IPipeInputList;
+ const ATransformation: ILambdaExpressionNode;
+ const AStaticType: IStaticType = nil
+ ): IPipeNode; overload; static;
+
end;
implementation
@@ -909,4 +933,47 @@ begin
);
end;
+// --- PIPES ---
+
+class function TAst.PipeInput(const AStream: IIdentifierNode; const ASelector: IKeywordNode; const Loc: ISourceLocation): IPipeInputNode;
+begin
+ var id := TIdentities.Structural(Loc);
+ // Erzeugt Node aus Myc.Ast.Nodes
+ Result := TPipeInputNode.Create(AStream, ASelector, id, TTypes.Unknown);
+end;
+
+class function TAst.Pipe(
+ const AInputs: TArray;
+ const ATransformation: ILambdaExpressionNode;
+ const Loc: ISourceLocation
+): IPipeNode;
+begin
+ var listId := TIdentities.List('[', ']', ' ', Loc);
+ var inputList := TPipeInputList.Create(AInputs, listId);
+
+ var id := TIdentities.Structural(Loc);
+ // Erzeugt Node aus Myc.Ast.Nodes
+ Result := TPipeNode.Create(inputList, ATransformation, id, TTypes.Unknown);
+end;
+
+class function TAst.Pipe(
+ const Identity: IAstIdentity;
+ const AInputs: IPipeInputList;
+ const ATransformation: ILambdaExpressionNode;
+ const AStaticType: IStaticType
+): IPipeNode;
+begin
+ Result :=
+ TPipeNode.Create(
+ AInputs,
+ ATransformation,
+ Identity,
+ if AStaticType <> nil then AStaticType
+ else TTypes.Unknown
+ );
+end;
+
end.
+ //==================================================================================================
+//== FULL UNIT END: Myc.Ast
+//==================================================================================================
diff --git a/Src/Data/Myc.Data.Scalar.pas b/Src/Data/Myc.Data.Scalar.pas
index d34d9f4..509d626 100644
--- a/Src/Data/Myc.Data.Scalar.pas
+++ b/Src/Data/Myc.Data.Scalar.pas
@@ -133,21 +133,29 @@ type
// A field definition for a scalar record.
TScalarRecordField = TPair;
IScalarRecordDefinition = IKeywordMapping;
- IScalarRecord = IKeywordMapping;
- TScalarRecord = class(TInterfacedObject, IScalarRecord)
+ IScalarRecord = interface(IKeywordMapping)
+ {$region 'private'}
+ function GetDef: IScalarRecordDefinition;
+ {$endregion}
+ property Def: IScalarRecordDefinition read GetDef;
+ end;
+
+ TScalarRecord = class(TInterfacedObject, IKeywordMapping, IScalarRecord)
type
TRegistry = TKeywordMappingRegistry;
private
- FDef: IScalarRecordDefinition;
FData: TArray;
+ FDef: IScalarRecordDefinition;
function IndexOf(const Key: IKeyword): Integer;
function GetCount: Integer;
+ function GetDef: IScalarRecordDefinition;
function GetItems(Idx: Integer): TPair;
function GetFields(const Key: IKeyword): TScalar;
public
constructor Create(const ADef: IScalarRecordDefinition; const AData: TArray);
+ property Def: IScalarRecordDefinition read GetDef;
end;
ISeries = interface
@@ -179,27 +187,25 @@ type
procedure Add(const Item: TScalar.TValue; Lookback: Int64 = -1);
end;
- IScalarRecordSeries = interface
+ IScalarRecordSeries = interface(IKeywordMapping)
{$region 'private'}
- function GetCount: Int64;
function GetDef: IScalarRecordDefinition;
- function GetFields(const Key: IKeyword): ISeries;
- function GetTotalCount: Int64;
{$endregion}
- property Count: Int64 read GetCount;
property Def: IScalarRecordDefinition read GetDef;
- property Fields[const Key: IKeyword]: ISeries read GetFields; default;
- property TotalCount: Int64 read GetTotalCount;
end;
IWriteableScalarRecordSeries = interface(IScalarRecordSeries)
{$region 'private'}
+ function GetRecordCount: Int64;
+ function GetTotalCount: Int64;
{$endregion}
- procedure Add(const Item: IScalarRecord; Lookback: Int64 = -1);
+ procedure Add(const Item: IKeywordMapping; Lookback: Int64 = -1);
+ property RecordCount: Int64 read GetRecordCount;
+ property TotalCount: Int64 read GetTotalCount;
end;
// A series of scalar records, optimized for memory and access speed.
- TScalarRecordSeries = class(TInterfacedObject, IWriteableScalarRecordSeries)
+ TScalarRecordSeries = class(TInterfacedObject, IWriteableScalarRecordSeries, IKeywordMapping)
type
TMemberSeries = class(TGenericContainedObject, ISeries)
private
@@ -218,19 +224,24 @@ type
FArray: TChunkArray;
FFields: TArray;
FTotalCount: Int64;
- function GetCount: Int64; inline;
+
+ function GetItems(Idx: Integer): TPair;
+ function GetCount: Integer;
+ function IndexOf(const Key: IKeyword): Integer;
+
+ function GetRecordCount: Int64; inline;
function GetFields(const Key: IKeyword): ISeries;
function GetDef: IScalarRecordDefinition; inline;
function GetTotalCount: Int64; inline;
function GetItemRef(Idx: Integer): TChunkArray.PT; inline;
+ function GetMapping: IKeywordMapping;
public
constructor Create(const ADef: IScalarRecordDefinition);
destructor Destroy; override;
- procedure Add(const Item: IScalarRecord; Lookback: Int64 = -1);
+ procedure Add(const Item: IKeywordMapping; Lookback: Int64 = -1);
- property Count: Int64 read GetCount;
- property Fields[const Key: IKeyword]: ISeries read GetFields; default;
+ property RecordCount: Int64 read GetRecordCount;
property Def: IScalarRecordDefinition read GetDef;
property TotalCount: Int64 read GetTotalCount;
end;
@@ -803,7 +814,7 @@ begin
inherited;
end;
-procedure TScalarRecordSeries.Add(const Item: IScalarRecord; Lookback: Int64 = -1);
+procedure TScalarRecordSeries.Add(const Item: IKeywordMapping; Lookback: Int64 = -1);
begin
var lb := FDef.Count * Integer(Lookback);
for var i := 0 to FDef.Count - 1 do
@@ -820,7 +831,7 @@ begin
Result := FFields[elem];
end;
-function TScalarRecordSeries.GetCount: Int64;
+function TScalarRecordSeries.GetRecordCount: Int64;
begin
Result := FArray.Count div FDef.Count;
end;
@@ -836,11 +847,32 @@ begin
Result := FArray.ItemRef[(FArray.Count - len) - (Idx * len)];
end;
+function TScalarRecordSeries.GetMapping: IKeywordMapping;
+begin
+ Result := Self;
+end;
+
function TScalarRecordSeries.GetTotalCount: Int64;
begin
Result := FTotalCount;
end;
+function TScalarRecordSeries.GetCount: Integer;
+begin
+ Result := Length(FFields);
+end;
+
+function TScalarRecordSeries.GetItems(Idx: Integer): TPair;
+begin
+ Result.Key := FDef.Items[Idx].Key;
+ Result.Value := FFields[Idx];
+end;
+
+function TScalarRecordSeries.IndexOf(const Key: IKeyword): Integer;
+begin
+ Result := FDef.IndexOf(Key);
+end;
+
{ TScalar.TKindHelper }
function TScalar.TKindHelper.ToString: string;
@@ -907,7 +939,7 @@ end;
function TScalarRecordSeries.TMemberSeries.GetCount: Int64;
begin
- Result := RecordSeries.Count;
+ Result := RecordSeries.RecordCount;
end;
function TScalarRecordSeries.TMemberSeries.GetItems(Idx: Integer): TScalar;
@@ -998,6 +1030,11 @@ begin
Result := FDef.Count;
end;
+function TScalarRecord.GetDef: IScalarRecordDefinition;
+begin
+ Result := FDef;
+end;
+
function TScalarRecord.GetFields(const Key: IKeyword): TScalar;
var
idx: Integer;
diff --git a/Src/Data/Myc.Data.Stream.pas b/Src/Data/Myc.Data.Stream.pas
new file mode 100644
index 0000000..c4e7a08
--- /dev/null
+++ b/Src/Data/Myc.Data.Stream.pas
@@ -0,0 +1,268 @@
+unit Myc.Data.Stream;
+
+interface
+
+uses
+ System.SysUtils,
+ System.Classes,
+ System.Generics.Collections,
+ System.SyncObjs,
+ Myc.Data.Scalar,
+ Myc.Data.Value,
+ Myc.Core.Notifier;
+
+type
+ TSignalKind = (skData, skHeartbeat);
+
+ TStreamSignal = record
+ private
+ FCycleID: Int64;
+ FKind: TSignalKind;
+ public
+ constructor Create(AKind: TSignalKind; ACycleID: Int64);
+ function ToString: string;
+ property CycleID: Int64 read FCycleID;
+ property Kind: TSignalKind read FKind;
+ end;
+
+ IStreamObserver = interface
+ procedure OnSignal(const Signal: TStreamSignal);
+ end;
+
+ TSubscriptionTag = Pointer;
+
+ IStream = interface
+ {$region 'private'}
+ function GetSeries: IScalarRecordSeries;
+ {$endregion}
+
+ function Subscribe(const Observer: IStreamObserver): TSubscriptionTag;
+ procedure Unsubscribe(Tag: TSubscriptionTag);
+
+ // Returns the Series of the records this stream produces. Streams are scalar record series. Always!
+ property Series: IScalarRecordSeries read GetSeries;
+ end;
+
+ IInputChannel = interface
+ {$region 'private'}
+ function GetStream: IStream;
+ {$endregion}
+
+ procedure Push(const Value: IScalarRecord);
+ property Stream: IStream read GetStream;
+ end;
+
+ IGraphExecutor = interface
+ {$region 'private'}
+ function GetCycleID: Int64;
+ {$endregion}
+
+ // Now requires a Definition when creating a channel
+ function GetInputChannel(const Name: string; const Def: IScalarRecordDefinition): IInputChannel;
+ procedure Step;
+ property CycleID: Int64 read GetCycleID;
+ end;
+
+ TGraphExecutor = class(TInterfacedObject, IGraphExecutor)
+ private
+ type
+ TChannel = class(TInterfacedObject, IInputChannel, IStream)
+ private
+ type
+ TStreamNotifier = TMycNotifyList;
+ private
+ FName: string;
+ FSeries: IWriteableScalarRecordSeries;
+ FQueue: TQueue;
+ FQueueLock: TSpinLock;
+ FObservers: TStreamNotifier;
+
+ procedure Push(const Value: IScalarRecord);
+ function GetStream: IStream;
+ function Subscribe(const Observer: IStreamObserver): TSubscriptionTag;
+ procedure Unsubscribe(Tag: TSubscriptionTag);
+ procedure Emit(ACycle: Int64);
+
+ function GetSeries: IScalarRecordSeries;
+
+ public
+ constructor Create(const AName: string; const ASeries: IWriteableScalarRecordSeries);
+ destructor Destroy; override;
+ end;
+
+ private
+ FCycleID: Int64;
+ FChannels: TDictionary;
+ FLock: TSpinLock;
+ function GetInputChannel(const Name: string; const Def: IScalarRecordDefinition): IInputChannel;
+ function GetCycleID: Int64;
+ public
+ constructor Create;
+ destructor Destroy; override;
+ procedure Step;
+ end;
+
+implementation
+
+constructor TStreamSignal.Create(AKind: TSignalKind; ACycleID: Int64);
+begin
+ FKind := AKind;
+ FCycleID := ACycleID;
+end;
+
+function TStreamSignal.ToString: string;
+begin
+ if Kind = skData then
+ Result := Format('Signal(Data, #%d)', [CycleID])
+ else
+ Result := Format('Signal(Heartbeat, #%d)', [CycleID]);
+end;
+
+{ TGraphExecutor.TChannel }
+
+constructor TGraphExecutor.TChannel.Create(const AName: string; const ASeries: IWriteableScalarRecordSeries);
+begin
+ inherited Create;
+ FName := AName;
+ FSeries := ASeries;
+ FQueue := TQueue.Create;
+end;
+
+destructor TGraphExecutor.TChannel.Destroy;
+begin
+ FObservers.Finalize;
+ FQueue.Free;
+ inherited;
+end;
+
+procedure TGraphExecutor.TChannel.Push(const Value: IScalarRecord);
+begin
+ Assert(Value.Def = FSeries.Def);
+
+ FQueueLock.Enter;
+ try
+ FQueue.Enqueue(Value);
+ finally
+ FQueueLock.Exit;
+ end;
+end;
+
+function TGraphExecutor.TChannel.GetStream: IStream;
+begin
+ Result := Self;
+end;
+
+function TGraphExecutor.TChannel.Subscribe(const Observer: IStreamObserver): TSubscriptionTag;
+begin
+ FObservers.Lock;
+ try
+ Result := FObservers.Advise(Observer);
+ finally
+ FObservers.Release;
+ end;
+end;
+
+procedure TGraphExecutor.TChannel.Unsubscribe(Tag: TSubscriptionTag);
+begin
+ FObservers.Lock;
+ try
+ FObservers.Unadvise(Tag);
+ finally
+ FObservers.Release;
+ end;
+end;
+
+procedure TGraphExecutor.TChannel.Emit(ACycle: Int64);
+var
+ signal: TStreamSignal;
+begin
+ FQueueLock.Enter;
+ try
+ FSeries.Add(FQueue.Dequeue);
+ signal :=
+ TStreamSignal.Create(
+ if FQueue.Count > 0 then skData
+ else skHeartbeat,
+ ACycle
+ )
+ finally
+ FQueueLock.Exit;
+ end;
+
+ FObservers.Lock;
+ try
+ FObservers.Notify(
+ function(const Obs: IStreamObserver): Boolean
+ begin
+ Obs.OnSignal(signal);
+ Result := True;
+ end
+ );
+ finally
+ FObservers.Release;
+ end;
+end;
+
+function TGraphExecutor.TChannel.GetSeries: IScalarRecordSeries;
+begin
+ Result := FSeries;
+end;
+
+{ TGraphExecutor }
+
+constructor TGraphExecutor.Create;
+begin
+ inherited Create;
+ FChannels := TDictionary.Create;
+ FCycleID := 0;
+end;
+
+destructor TGraphExecutor.Destroy;
+begin
+ FChannels.Free;
+ inherited;
+end;
+
+function TGraphExecutor.GetInputChannel(const Name: string; const Def: IScalarRecordDefinition): IInputChannel;
+var
+ impl: TChannel;
+begin
+ FLock.Enter;
+ try
+ if not FChannels.TryGetValue(Name, Result) then
+ begin
+ impl := TChannel.Create(Name, TScalarRecordSeries.Create(Def));
+ Result := impl;
+ FChannels.Add(Name, Result);
+ end;
+ finally
+ FLock.Exit;
+ end;
+end;
+
+function TGraphExecutor.GetCycleID: Int64;
+begin
+ Result := FCycleID;
+end;
+
+procedure TGraphExecutor.Step;
+var
+ channelsArr: TArray;
+ channel: IInputChannel;
+begin
+ FLock.Enter;
+ try
+ Inc(FCycleID);
+ channelsArr := FChannels.Values.ToArray;
+ finally
+ FLock.Exit;
+ end;
+
+ for channel in channelsArr do
+ (channel as TChannel).Emit(FCycleID);
+end;
+
+initialization
+ TMycNotifyList.ReverseOnNotify := False;
+
+end.
diff --git a/Src/Data/Myc.Data.Value.pas b/Src/Data/Myc.Data.Value.pas
index 93b4c17..c52e4a3 100644
--- a/Src/Data/Myc.Data.Value.pas
+++ b/Src/Data/Myc.Data.Value.pas
@@ -397,7 +397,7 @@ begin
first := False;
end;
sb.Append('}');
- Result := Format('', [sb.ToString, series.Count]);
+ Result := Format('', [sb.ToString, series.RecordCount]);
finally
sb.Free;
end;