diff --git a/CMakeLists.txt b/CMakeLists.txt index 62046f0d..592bf697 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,10 +102,12 @@ add_subdirectory(xo-alloc2) # experiment w/ facet object model add_subdirectory(xo-gc) add_subdirectory(xo-object) add_subdirectory(xo-object2) # experiment w/ facet object model +add_subdirectory(xo-procedure2) # schematika procedure abstraction + runtime context (fomo) add_subdirectory(xo-ordinaltree) # add_subdirectory(xo-tokenizer2) # schematika tokenizer (fomo) add_subdirectory(xo-expression2) # schematika expressions (fomo) +add_subdirectory(xo-reader2) # schematika expression parser (fomo) add_subdirectory(xo-interpreter2) # schematika interpreter (fomo) # add_subdirectory(xo-webutil) diff --git a/default.nix b/default.nix index 481dd59a..13c087a7 100644 --- a/default.nix +++ b/default.nix @@ -59,6 +59,20 @@ let }); }; + # ghostty tests require ptys + ghostty-overlay = self: super: { + ghostty = super.ghostty.overrideAttrs (old: { + doCheck = false; + }); + }; + + # fish tests require ptys + fish-overlay = self: super: { + fish = super.fish.overrideAttrs (old: { + doCheck = false; + }); + }; + # # nixGL not present in my nixpkgs snapshot # nixgl-overlay = self: super: { # nixGL = import (self.fetchFromGitHub { @@ -192,6 +206,8 @@ let swtpm-overlay mailutils-overlay notmuch-overlay + ghostty-overlay + fish-overlay # nixgl-overlay # llvm-overlay xo-overlay @@ -240,6 +256,10 @@ let pkgs.emacsPackages.notmuch pkgs.inconsolata-lgc pkgs.fontconfig + pkgs.ghostty + pkgs.timg + pkgs.fish + pkgs.nushell ]; # xo general-purpose devutils diff --git a/etc/hostubuntu/libEGL_mesa.so.0 b/etc/hostubuntu/libEGL_mesa.so.0 new file mode 120000 index 00000000..d53298a5 --- /dev/null +++ b/etc/hostubuntu/libEGL_mesa.so.0 @@ -0,0 +1 @@ +/usr/lib/x86_64-linux-gnu/libEGL_mesa.so.0 \ No newline at end of file diff --git a/etc/hostubuntu/libEGL_mesa.so.0.0.0 b/etc/hostubuntu/libEGL_mesa.so.0.0.0 new file mode 120000 index 00000000..bca1401a --- /dev/null +++ b/etc/hostubuntu/libEGL_mesa.so.0.0.0 @@ -0,0 +1 @@ +/usr/lib/x86_64-linux-gnu/libEGL_mesa.so.0.0.0 \ No newline at end of file diff --git a/etc/hostubuntu/libEGL_nvidia.so b/etc/hostubuntu/libEGL_nvidia.so deleted file mode 120000 index 543858c6..00000000 --- a/etc/hostubuntu/libEGL_nvidia.so +++ /dev/null @@ -1 +0,0 @@ -libEGL_nvidia.so.580.95.05 \ No newline at end of file diff --git a/etc/hostubuntu/libEGL_nvidia.so.0 b/etc/hostubuntu/libEGL_nvidia.so.0 new file mode 120000 index 00000000..26b761b3 --- /dev/null +++ b/etc/hostubuntu/libEGL_nvidia.so.0 @@ -0,0 +1 @@ +/usr/lib/x86_64-linux-gnu/libEGL_nvidia.so.0 \ No newline at end of file diff --git a/etc/hostubuntu/libEGL_nvidia.so.580.126.09 b/etc/hostubuntu/libEGL_nvidia.so.580.126.09 new file mode 120000 index 00000000..f9e88f8a --- /dev/null +++ b/etc/hostubuntu/libEGL_nvidia.so.580.126.09 @@ -0,0 +1 @@ +/usr/lib/x86_64-linux-gnu/libEGL_nvidia.so.580.126.09 \ No newline at end of file diff --git a/etc/hostubuntu/libEGL_nvidia.so.580.95.05 b/etc/hostubuntu/libEGL_nvidia.so.580.95.05 deleted file mode 120000 index 5c3d156a..00000000 --- a/etc/hostubuntu/libEGL_nvidia.so.580.95.05 +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/x86_64-linux-gnu/libEGL_nvidia.so.580.95.05 \ No newline at end of file diff --git a/etc/hostubuntu/libGLX_nvidia.so.580.126.09 b/etc/hostubuntu/libGLX_nvidia.so.580.126.09 new file mode 120000 index 00000000..c1a66d6d --- /dev/null +++ b/etc/hostubuntu/libGLX_nvidia.so.580.126.09 @@ -0,0 +1 @@ +/usr/lib/x86_64-linux-gnu/libGLX_nvidia.so.580.126.09 \ No newline at end of file diff --git a/etc/hostubuntu/libGLX_nvidia.so.580.95.05 b/etc/hostubuntu/libGLX_nvidia.so.580.95.05 deleted file mode 120000 index c5fd2bf6..00000000 --- a/etc/hostubuntu/libGLX_nvidia.so.580.95.05 +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/x86_64-linux-gnu/libGLX_nvidia.so.580.95.05 \ No newline at end of file diff --git a/etc/hostubuntu/libdrm.so b/etc/hostubuntu/libdrm.so new file mode 120000 index 00000000..4b830b64 --- /dev/null +++ b/etc/hostubuntu/libdrm.so @@ -0,0 +1 @@ +/usr/lib/x86_64-linux-gnu/libdrm.so \ No newline at end of file diff --git a/etc/hostubuntu/libdrm.so.2 b/etc/hostubuntu/libdrm.so.2 new file mode 120000 index 00000000..77111d6e --- /dev/null +++ b/etc/hostubuntu/libdrm.so.2 @@ -0,0 +1 @@ +/usr/lib/x86_64-linux-gnu/libdrm.so.2 \ No newline at end of file diff --git a/etc/hostubuntu/libdrm.so.2.4.0 b/etc/hostubuntu/libdrm.so.2.4.0 new file mode 120000 index 00000000..2b62d18e --- /dev/null +++ b/etc/hostubuntu/libdrm.so.2.4.0 @@ -0,0 +1 @@ +/usr/lib/x86_64-linux-gnu/libdrm.so.2.4.0 \ No newline at end of file diff --git a/etc/hostubuntu/libgbm.so b/etc/hostubuntu/libgbm.so new file mode 120000 index 00000000..c43545cf --- /dev/null +++ b/etc/hostubuntu/libgbm.so @@ -0,0 +1 @@ +/usr/lib/x86_64-linux-gnu/libgbm.so \ No newline at end of file diff --git a/etc/hostubuntu/libgbm.so.1 b/etc/hostubuntu/libgbm.so.1 new file mode 120000 index 00000000..54b72186 --- /dev/null +++ b/etc/hostubuntu/libgbm.so.1 @@ -0,0 +1 @@ +/usr/lib/x86_64-linux-gnu/libgbm.so.1 \ No newline at end of file diff --git a/etc/hostubuntu/libgbm.so.1.0.0 b/etc/hostubuntu/libgbm.so.1.0.0 new file mode 120000 index 00000000..e64ce8f3 --- /dev/null +++ b/etc/hostubuntu/libgbm.so.1.0.0 @@ -0,0 +1 @@ +/usr/lib/x86_64-linux-gnu/libgbm.so.1.0.0 \ No newline at end of file diff --git a/etc/hostubuntu/libnvidia-glcore.so.580.126.09 b/etc/hostubuntu/libnvidia-glcore.so.580.126.09 new file mode 120000 index 00000000..1b738450 --- /dev/null +++ b/etc/hostubuntu/libnvidia-glcore.so.580.126.09 @@ -0,0 +1 @@ +/usr/lib/x86_64-linux-gnu/libnvidia-glcore.so.580.126.09 \ No newline at end of file diff --git a/etc/hostubuntu/libnvidia-glcore.so.580.95.05 b/etc/hostubuntu/libnvidia-glcore.so.580.95.05 deleted file mode 120000 index f8475532..00000000 --- a/etc/hostubuntu/libnvidia-glcore.so.580.95.05 +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/x86_64-linux-gnu/libnvidia-glcore.so.580.95.05 \ No newline at end of file diff --git a/etc/hostubuntu/libnvidia-glsi.so.580.126.09 b/etc/hostubuntu/libnvidia-glsi.so.580.126.09 new file mode 120000 index 00000000..0324b15e --- /dev/null +++ b/etc/hostubuntu/libnvidia-glsi.so.580.126.09 @@ -0,0 +1 @@ +/usr/lib/x86_64-linux-gnu/libnvidia-glsi.so.580.126.09 \ No newline at end of file diff --git a/etc/hostubuntu/libnvidia-glsi.so.580.95.05 b/etc/hostubuntu/libnvidia-glsi.so.580.95.05 deleted file mode 120000 index 55dc4271..00000000 --- a/etc/hostubuntu/libnvidia-glsi.so.580.95.05 +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/x86_64-linux-gnu/libnvidia-glsi.so.580.95.05 \ No newline at end of file diff --git a/etc/hostubuntu/libnvidia-glvkspirv.so.580.126.09 b/etc/hostubuntu/libnvidia-glvkspirv.so.580.126.09 new file mode 120000 index 00000000..1e055f84 --- /dev/null +++ b/etc/hostubuntu/libnvidia-glvkspirv.so.580.126.09 @@ -0,0 +1 @@ +/usr/lib/x86_64-linux-gnu/libnvidia-glvkspirv.so.580.126.09 \ No newline at end of file diff --git a/etc/hostubuntu/libnvidia-glvkspirv.so.580.95.05 b/etc/hostubuntu/libnvidia-glvkspirv.so.580.95.05 deleted file mode 120000 index 58140c09..00000000 --- a/etc/hostubuntu/libnvidia-glvkspirv.so.580.95.05 +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/x86_64-linux-gnu/libnvidia-glvkspirv.so.580.95.05 \ No newline at end of file diff --git a/etc/hostubuntu/libnvidia-gpucomp.so.580.126.09 b/etc/hostubuntu/libnvidia-gpucomp.so.580.126.09 new file mode 120000 index 00000000..e97ad8cf --- /dev/null +++ b/etc/hostubuntu/libnvidia-gpucomp.so.580.126.09 @@ -0,0 +1 @@ +/usr/lib/x86_64-linux-gnu/libnvidia-gpucomp.so.580.126.09 \ No newline at end of file diff --git a/etc/hostubuntu/libnvidia-gpucomp.so.580.95.05 b/etc/hostubuntu/libnvidia-gpucomp.so.580.95.05 deleted file mode 120000 index a2021093..00000000 --- a/etc/hostubuntu/libnvidia-gpucomp.so.580.95.05 +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/x86_64-linux-gnu/libnvidia-gpucomp.so.580.95.05 \ No newline at end of file diff --git a/etc/hostubuntu/libnvidia-tls.so.580.126.09 b/etc/hostubuntu/libnvidia-tls.so.580.126.09 new file mode 120000 index 00000000..734a7a02 --- /dev/null +++ b/etc/hostubuntu/libnvidia-tls.so.580.126.09 @@ -0,0 +1 @@ +/usr/lib/x86_64-linux-gnu/libnvidia-tls.so.580.126.09 \ No newline at end of file diff --git a/etc/hostubuntu/libnvidia-tls.so.580.95.05 b/etc/hostubuntu/libnvidia-tls.so.580.95.05 deleted file mode 120000 index a5cf63b6..00000000 --- a/etc/hostubuntu/libnvidia-tls.so.580.95.05 +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/x86_64-linux-gnu/libnvidia-tls.so.580.95.05 \ No newline at end of file diff --git a/xo-alloc/include/xo/alloc/GcStatistics.hpp b/xo-alloc/include/xo/alloc/GcStatistics.hpp index b591bf22..69053457 100644 --- a/xo-alloc/include/xo/alloc/GcStatistics.hpp +++ b/xo-alloc/include/xo/alloc/GcStatistics.hpp @@ -1,16 +1,16 @@ -/* GcStatistics.hpp +/** @file GcStatistics.hpp * - * author: Roland Conybeare, Aug 2025 - */ + * @author Roland Conybeare, Aug 2025 + **/ #pragma once #include "generation.hpp" #include "CircularBuffer.hpp" -#include "xo/reflect/TypeDescr.hpp" -#include "xo/unit/quantity.hpp" -#include "xo/unit/quantity_iostream.hpp" -#include "xo/indentlog/print/pretty.hpp" +#include +#include +#include +#include #include #include diff --git a/xo-alloc2/CMakeLists.txt b/xo-alloc2/CMakeLists.txt index afe3d225..b4b03193 100644 --- a/xo-alloc2/CMakeLists.txt +++ b/xo-alloc2/CMakeLists.txt @@ -18,6 +18,22 @@ add_definitions(${PROJECT_CXX_FLAGS}) # ---------------------------------------------------------------- +# note: manual target; generated code committed to git +xo_add_genfacet( + TARGET xo-alloc2-facet-resourcevisitor + FACET ResourceVisitor + INPUT idl/ResourceVisitor.json5 + OUTPUT_HPP_DIR include/xo/alloc2 + OUTPUT_IMPL_SUBDIR visitor +) + +# ---------------------------------------------------------------- + +xo_add_genfacet_all(xo-alloc2-genfacet-all) + +# ---------------------------------------------------------------- + + # must complete definition of expression lib before configuring examples add_subdirectory(src/alloc2) add_subdirectory(utest) diff --git a/xo-alloc2/idl/ResourceVisitor.json5 b/xo-alloc2/idl/ResourceVisitor.json5 new file mode 100644 index 00000000..54effc41 --- /dev/null +++ b/xo-alloc2/idl/ResourceVisitor.json5 @@ -0,0 +1,52 @@ +{ + mode: "facet", + output_cpp_dir: "src/alloc2", + output_hpp_dir: "include/xo/alloc2", + output_impl_subdir: "visitor", + includes: [ + "\"Allocator.hpp\"" + ], + // extra includes in ResourceVisitor.hpp, if any + user_hpp_includes: [], + namespace1: "xo", + namespace2: "mm", + // text after includes, before AResourceVisitor + pretext: [ "// {pretext} here" ], + facet: "ResourceVisitor", + detail_subdir: "visitor", + brief: "visitor to inspect resource consumption", + using_doxygen: true, + doc: [ + "Visitor to receive measured resource consumption" + ], + types: [ + // using size_type = std::size_t + { + name: "size_type", + doc: ["type for length of a sequence"], + definition: "std::size_t", + }, +// // using AGCObject = xo::mm::AGCObject +// { +// name: "AGCObject", +// doc: ["facet for types with GC support"], +// definition: "xo::mm::AGCObject", +// } + ], + const_methods: [ + // bool on_memory(name, allocated, committed, reserved) const noexcept + { + name: "on_allocator", + doc: ["report memory consumption"], + return_type: "void", + args: [ + {type: "obj", name: "mm"}, + ], + const: true, + noexcept: true, + attributes: [], + }, + ], + nonconst_methods: [ + ], +} diff --git a/xo-alloc2/include/xo/alloc2/Arena.hpp b/xo-alloc2/include/xo/alloc2/Arena.hpp new file mode 100644 index 00000000..fac3f302 --- /dev/null +++ b/xo-alloc2/include/xo/alloc2/Arena.hpp @@ -0,0 +1,17 @@ +/** @file Arena.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +// reminder: we can't put this AAllocator +// (or APrintable for that matter) support in xo-arena, +// because xo-arena is a dependency of xo-facet, which is in turn +// a dependency of xo-alloc2 +// + +#include +#include "arena/IAllocator_DArena.hpp" + +/* end Arena.hpp */ diff --git a/xo-alloc2/include/xo/alloc2/ResourceVisitor.hpp b/xo-alloc2/include/xo/alloc2/ResourceVisitor.hpp new file mode 100644 index 00000000..b995e891 --- /dev/null +++ b/xo-alloc2/include/xo/alloc2/ResourceVisitor.hpp @@ -0,0 +1,22 @@ +/** @file ResourceVisitor.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ResourceVisitor.json5] + * 2. jinja2 template for facet .hpp file: + * [facet.hpp.j2] + * 3. idl for facet methods + * [idl/ResourceVisitor.json5] + **/ + +#pragma once + +#include "visitor/AResourceVisitor.hpp" +#include "visitor/IResourceVisitor_Any.hpp" +#include "visitor/IResourceVisitor_Xfer.hpp" +#include "visitor/RResourceVisitor.hpp" + + +/* end ResourceVisitor.hpp */ diff --git a/xo-alloc2/include/xo/alloc2/abox.hpp b/xo-alloc2/include/xo/alloc2/abox.hpp new file mode 100644 index 00000000..d34271ae --- /dev/null +++ b/xo-alloc2/include/xo/alloc2/abox.hpp @@ -0,0 +1,116 @@ +/** @file abox.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "Allocator.hpp" +#include +#include + +namespace xo { + namespace mm { + + /** object with owned state + * - with default DRepr argument: + * type-erased container (runtime polymorphism). + * - with sepcific DRepr argument: + * typed container (comptime polymorphism). + * + * Similar to box (see box.hpp in xo-facet/): + * 1. inherits fat object pointer with AFacet*, DRepr* pair + * 2. automatically calls polymorphic DRepr::~DRepr when + * abox goes out of scope. + * Unlike box: + * 3. gets memory from explicit arena-like allocator + * 4. calls dtor DRepr::~DRepr(), but not delete. + * Does not retain allocator. + **/ + template + struct abox : public xo::facet::RoutingType> { + using DVariantPlaceholder = xo::facet::DVariantPlaceholder; + using Super = xo::facet::RoutingType>; + + abox() : Super() {} + + /** abox takes ownership of data @p *d; + * will destroy when abox goes out of scope. + * + * Note this is not useful when DRepr=DVariablePlaceholder + **/ + explicit abox(Super::DataPtr d) : Super(d) {} + + /** Adopt instance that has interface @p iface and (type-erased here) + * representation @p data + **/ + abox(const AFacet * iface, void * data) + requires std::is_same_v + : Super(iface, data) + {} + + /** (copy ctor not supported -- ownership is unique) **/ + abox(const abox & other) = delete; + + /** Move constructor **/ + template + abox(abox && other) + requires (std::is_same_v + || std::is_same_v) + : xo::facet::RoutingType>() + { + /* replacing .iface_ along w/ .data_ */ + this->from_obj(other); + + other.reset_opaque(nullptr); + } + + /** allocates for sizeof(DRepr), so DRepr must not use flexible array **/ + template + static abox make(obj alloc, Args&&... args) { + void * mem = alloc.alloc_for(); + if (mem) { + DRepr * data = ::new (mem) DRepr(std::forward(args)...); + + assert(data); + + return abox(data); + } else { + assert(false); + + return abox(); + } + } + + // -------------------------------- + + /** explicit conversion to obj **/ + obj to_op() const noexcept { + return obj(this->iface(), this->data()); + } + + /** Take ownership from unowned object **/ + template + abox & adopt(const obj & other) + requires (std::is_same_v + || std::is_same_v) + { + /* replace .iface_ along w/ .data_ */ + this->from_obj(other); + + return *this; + } + + ~abox() { + auto p = this->data(); + if (p) { + this->_drop(); + } + } + }; + } /*namespace mm*/ + + using mm::abox; +} /*namespace xo*/ + +/* end abox.hpp */ diff --git a/xo-alloc2/include/xo/alloc2/alloc/AAllocator.hpp b/xo-alloc2/include/xo/alloc2/alloc/AAllocator.hpp index 588b439b..ecc52862 100644 --- a/xo-alloc2/include/xo/alloc2/alloc/AAllocator.hpp +++ b/xo-alloc2/include/xo/alloc2/alloc/AAllocator.hpp @@ -5,6 +5,7 @@ #pragma once +#include #include #include "AllocInfo.hpp" //#include "AllocIterator.hpp" @@ -33,9 +34,11 @@ namespace xo { struct AAllocator { /** @defgroup mm-allocator-type-traits allocator type traits **/ ///@{ - /** @brief type used for allocation amounts **/ + /** memory size report **/ + using MemorySizeInfo = xo::mm::MemorySizeInfo; + /** type used for allocation amounts **/ using size_type = std::size_t; - /** @brief type used for allocation responses **/ + /** type used for allocation responses **/ using value_type = std::byte *; /** object header, if configured **/ using header_type = std::uint64_t; @@ -62,6 +65,10 @@ namespace xo { /** RTTI: unique id# for actual runtime data representation **/ virtual typeseq _typeseq() const noexcept = 0; + /** destroy instance @p d. Calls c++ destructor for actual runtime type. + * does not recover memory. + **/ + virtual void _drop(Opaque d) const noexcept = 0; /** optional name for allocator @p d . * Allows labeling allocators, for diagnostics/instrumentation. **/ @@ -91,6 +98,12 @@ namespace xo { * Includes alloc headers and guard regions **/ virtual size_type allocated(Copaque d) const noexcept = 0; + /** call @p fn(i,n,info) for each memory pool owned by this allocator. + * Note: using std::function instead of obj<> to avoid leveling trouble + * with DArena + **/ + virtual void visit_pools(Copaque d, + const MemorySizeVisitor & fn) const = 0; /** true iff allocator @p d is responsible for memory at address @p p. **/ virtual bool contains(Copaque d, const void * p) const noexcept = 0; @@ -142,10 +155,6 @@ namespace xo { virtual value_type alloc_copy(Opaque d, value_type src) const = 0; /** reset allocator @p d to empty state. **/ virtual void clear(Opaque d) const = 0; - /** Destruct allocator @p d. - * Releases allocator memory to operating system. - **/ - virtual void destruct_data(Opaque d) const = 0; ///@} }; /*AAllocator*/ diff --git a/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Any.hpp b/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Any.hpp index b45e7651..fa8c14ab 100644 --- a/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Any.hpp +++ b/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Any.hpp @@ -32,7 +32,10 @@ namespace xo { const AAllocator * iface() const { return std::launder(this); } // from AAllocator + + // builtin methods typeseq _typeseq() const noexcept override { return s_typeseq; } + void _drop(Opaque) const noexcept override { _fatal(); } // const methods [[noreturn]] std::string_view name(Copaque) const noexcept override { _fatal(); } @@ -42,6 +45,8 @@ namespace xo { [[noreturn]] size_type available(Copaque) const noexcept override { _fatal(); } [[noreturn]] size_type allocated(Copaque) const noexcept override { _fatal(); } [[noreturn]] bool contains(Copaque, const void *) const noexcept override { _fatal(); } + [[noreturn]] void visit_pools(Copaque, + const MemorySizeVisitor &) const override { _fatal(); } [[noreturn]] AllocError last_error(Copaque) const noexcept override { _fatal(); } [[noreturn]] AllocInfo alloc_info(Copaque, value_type) const noexcept override { _fatal(); } // defn in .cpp - problematic to require compiler know vt defn here @@ -55,7 +60,6 @@ namespace xo { [[noreturn]] value_type sub_alloc(Opaque, std::size_t, bool) const override { _fatal(); } [[noreturn]] value_type alloc_copy(Opaque, value_type) const override { _fatal(); } [[noreturn]] void clear(Opaque) const override { _fatal(); } - [[noreturn]] void destruct_data(Opaque) const override { _fatal(); } private: [[noreturn]] static void _fatal(); diff --git a/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Xfer.hpp b/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Xfer.hpp index 790bcdc0..e5b539a1 100644 --- a/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Xfer.hpp +++ b/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Xfer.hpp @@ -36,10 +36,14 @@ namespace xo { // from AAllocator - // const methods - + // builtin methods /** return typeseq for @tparam DRepr **/ typeseq _typeseq() const noexcept override { return s_typeseq; } + /** invoke native c++ dtor **/ + void _drop(Opaque d) const noexcept override { _dcast(d).~DRepr(); } + + // const methods + std::string_view name(Copaque d) const noexcept override { return I::name(_dcast(d)); } size_type reserved(Copaque d) const noexcept override { return I::reserved(_dcast(d)); } size_type size(Copaque d) const noexcept override { return I::size(_dcast(d)); } @@ -49,6 +53,7 @@ namespace xo { bool contains(Copaque d, const void * p) const noexcept override { return I::contains(_dcast(d), p); } + void visit_pools(Copaque d, const MemorySizeVisitor & fn) const override { I::visit_pools(_dcast(d), fn); } AllocError last_error(Copaque d) const noexcept override { return I::last_error(_dcast(d)); } AllocInfo alloc_info(Copaque d, value_type mem) const noexcept override { return I::alloc_info(_dcast(d), mem); @@ -73,7 +78,6 @@ namespace xo { value_type alloc_copy(Opaque d, value_type src) const override { return I::alloc_copy(_dcast(d), src); } void clear(Opaque d) const override { return I::clear(_dcast(d)); } - void destruct_data(Opaque d) const override { return I::destruct_data(_dcast(d)); } ///@} private: diff --git a/xo-alloc2/include/xo/alloc2/alloc/RAllocator.hpp b/xo-alloc2/include/xo/alloc2/alloc/RAllocator.hpp index 2e9e7a80..b5252f49 100644 --- a/xo-alloc2/include/xo/alloc2/alloc/RAllocator.hpp +++ b/xo-alloc2/include/xo/alloc2/alloc/RAllocator.hpp @@ -27,14 +27,40 @@ namespace xo { RAllocator() {} RAllocator(Object::DataPtr data) : Object{std::move(data)} {} + RAllocator(const AAllocator * iface, void * data) + requires std::is_same_v + : Object(iface, data) {} + + template + void * alloc_for(size_type n = sizeof(T)) noexcept { + return O::iface()->alloc(O::data(), typeseq::id(), n); + } + + template + void * alloc_copy_for(const T * src) noexcept { + return O::iface()->alloc_copy(O::data(), (std::byte*)const_cast(src)); + } + + template + T * std_copy_for(const T * src) noexcept { + T * copy = (T *)(this->alloc_copy_for(src)); + + if (copy) { + *copy = *src; + } + + return copy; + } typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); } + void _drop() const noexcept { O::iface()->_drop(O::data()); } std::string_view name() const noexcept { return O::iface()->name(O::data()); } size_type reserved() const noexcept { return O::iface()->reserved(O::data()); } size_type size() const noexcept { return O::iface()->size(O::data()); } size_type committed() const noexcept { return O::iface()->committed(O::data()); } size_type available() const noexcept { return O::iface()->available(O::data()); } size_type allocated() const noexcept { return O::iface()->allocated(O::data()); } + void visit_pools(const MemorySizeVisitor & fn) const { O::iface()->visit_pools(O::data(), fn); } bool contains(const void * p) const noexcept { return O::iface()->contains(O::data(), p); } AllocError last_error() const noexcept { return O::iface()->last_error(O::data()); } AllocInfo alloc_info(value_type mem) const noexcept { return O::iface()->alloc_info(O::data(), mem); } diff --git a/xo-alloc2/include/xo/alloc2/alloc2_register_facets.hpp b/xo-alloc2/include/xo/alloc2/alloc2_register_facets.hpp new file mode 100644 index 00000000..a53248a2 --- /dev/null +++ b/xo-alloc2/include/xo/alloc2/alloc2_register_facets.hpp @@ -0,0 +1,15 @@ +/** @file alloc2_register_facets.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +namespace xo { + namespace mm { + /** Register alloc2 (facet,impl) combinations with Facet Registry **/ + bool alloc2_register_facets(); + } +} + +/* end alloc2_register_facets.hpp */ diff --git a/xo-alloc2/include/xo/alloc2/arena/IAllocator_DArena.hpp b/xo-alloc2/include/xo/alloc2/arena/IAllocator_DArena.hpp index 4a871822..81e92211 100644 --- a/xo-alloc2/include/xo/alloc2/arena/IAllocator_DArena.hpp +++ b/xo-alloc2/include/xo/alloc2/arena/IAllocator_DArena.hpp @@ -40,6 +40,8 @@ namespace xo { static size_type committed(const DArena &) noexcept; static size_type available(const DArena &) noexcept; static size_type allocated(const DArena &) noexcept; + static void visit_pools(const DArena &, + const MemorySizeVisitor & visitor); static bool contains(const DArena &, const void * p) noexcept; static AllocError last_error(const DArena &) noexcept; /** retrieve allocation bookkeeping info for @p mem from arena @p d **/ diff --git a/xo-alloc2/include/xo/alloc2/dp.hpp b/xo-alloc2/include/xo/alloc2/dp.hpp new file mode 100644 index 00000000..266f42dd --- /dev/null +++ b/xo-alloc2/include/xo/alloc2/dp.hpp @@ -0,0 +1,112 @@ +/** @file dp.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "Allocator.hpp" +#include +#include + +namespace xo { + namespace mm { + + /** unimorphic "data pointer" with known representation and owned memory. + * runs dtor *but not delete*. Does not store allocator! + * + * Compare with abox + **/ + template + struct dp { + dp() = default; + + /** dp takes ownership of data @p ptr; + * will run dtor when dp goes out of scope. + * + * Note this is not useful when DRepr=DVariablePlaceholder + **/ + explicit dp(DRepr * ptr) : ptr_{ptr} {} + + /** (copy ctor not supported -- ownership is unique) **/ + dp(const dp & other) = delete; + + /** Move constructor **/ + dp(dp && other) + { + ptr_ = other.ptr_; + other.ptr_ = nullptr; + } + + /** allocates for sizeof(DRepr), so DRepr must not use flexible array **/ + template + static dp make(obj alloc, Args&&... args) { + void * mem = alloc.alloc_for(); + + if (mem) { + DRepr * data = ::new (mem) DRepr(std::forward(args)...); + assert(data); + + return dp(data); + } else { + assert(false); + + return dp(); + } + } + + dp & operator=(const dp & x) = delete; + + /** move assignment **/ + dp & operator=(dp && x) { + ptr_ = x.ptr_; + x.ptr_ = nullptr; + + return *this; + } + + // -------------------------------- + + DRepr * data() const noexcept { return ptr_; } + + operator bool() const noexcept { return ptr_ != nullptr; } + + DRepr * operator->() const noexcept { return ptr_; } + DRepr & operator*() const noexcept { return *ptr_; } + +#ifdef NOT_YET + /** explicit conversion to obj **/ + obj to_op() const noexcept { + return obj(this->iface(), this->data()); + } +#endif + +#ifdef NOT_YET + /** Take ownership from unowned object **/ + template + dp & adopt(const obj & other) + requires (std::is_same_v + || std::is_same_v) + { + /* replace .iface_ along w/ .data_ */ + this->from_obj(other); + + return *this; + } +#endif + + ~dp() { + if (ptr_) { + ptr_->~DRepr(); + } + } + + private: + DRepr * ptr_ = nullptr; + }; + } /*namespace mm*/ + + using mm::dp; +} /*namespace xo*/ + +/* end dp.hpp */ diff --git a/xo-alloc2/include/xo/alloc2/init_alloc2.hpp b/xo-alloc2/include/xo/alloc2/init_alloc2.hpp new file mode 100644 index 00000000..c13160b8 --- /dev/null +++ b/xo-alloc2/include/xo/alloc2/init_alloc2.hpp @@ -0,0 +1,23 @@ +/** @file init_alloc2.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include + +namespace xo { + /* tag to represent the xo-alloc2/ subsystem within ordered initialization */ + enum S_alloc2_tag {}; + + template <> + struct InitSubsys { + static void init(); + static InitEvidence require(); + }; + + +} /*namespace xo*/ + +/* end init_alloc2.hpp */ diff --git a/xo-alloc2/include/xo/alloc2/visitor/AResourceVisitor.hpp b/xo-alloc2/include/xo/alloc2/visitor/AResourceVisitor.hpp new file mode 100644 index 00000000..c8ab3744 --- /dev/null +++ b/xo-alloc2/include/xo/alloc2/visitor/AResourceVisitor.hpp @@ -0,0 +1,76 @@ +/** @file AResourceVisitor.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ResourceVisitor.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [abstract_facet.hpp.j2] + * 3. idl for facet methods + * [idl/ResourceVisitor.json5] + **/ + +#pragma once + +// includes (via {facet_includes}) +#include "Allocator.hpp" +#include +#include +#include + +// {pretext} here + +namespace xo { +namespace mm { + +using Copaque = const void *; +using Opaque = void *; + +/** +Visitor to receive measured resource consumption +**/ +class AResourceVisitor { +public: + /** @defgroup mm-resourcevisitor-type-traits **/ + ///@{ + // types + /** integer identifying a type **/ + using typeseq = xo::facet::typeseq; + using Copaque = const void *; + using Opaque = void *; + /** type for length of a sequence **/ + using size_type = std::size_t; + ///@} + + /** @defgroup mm-resourcevisitor-methods **/ + ///@{ + // const methods + /** RTTI: unique id# for actual runtime data representation **/ + virtual typeseq _typeseq() const noexcept = 0; + /** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/ + virtual void _drop(Opaque d) const noexcept = 0; + /** report memory consumption **/ + virtual void on_allocator(Copaque data, obj mm) const noexcept = 0; + + // nonconst methods + ///@} +}; /*AResourceVisitor*/ + +/** Implementation IResourceVisitor_DRepr of AResourceVisitor for state DRepr + * should provide a specialization: + * + * template <> + * struct xo::facet::FacetImplementation { + * using Impltype = IResourceVisitor_DRepr; + * }; + * + * then IResourceVisitor_ImplType --> IResourceVisitor_DRepr + **/ +template +using IResourceVisitor_ImplType = xo::facet::FacetImplType; + +} /*namespace mm*/ +} /*namespace xo*/ + +/* AResourceVisitor.hpp */ diff --git a/xo-alloc2/include/xo/alloc2/visitor/IResourceVisitor_Any.hpp b/xo-alloc2/include/xo/alloc2/visitor/IResourceVisitor_Any.hpp new file mode 100644 index 00000000..18ae11a0 --- /dev/null +++ b/xo-alloc2/include/xo/alloc2/visitor/IResourceVisitor_Any.hpp @@ -0,0 +1,89 @@ +/** @file IResourceVisitor_Any.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ResourceVisitor.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ResourceVisitor.json5] + **/ + +#pragma once + +#include "AResourceVisitor.hpp" +#include + +namespace xo { namespace mm { class IResourceVisitor_Any; } } + +namespace xo { +namespace facet { + +template <> +struct FacetImplementation +{ + using ImplType = xo::mm::IResourceVisitor_Any; +}; + +} +} + +namespace xo { +namespace mm { + + /** @class IResourceVisitor_Any + * @brief AResourceVisitor implementation for empty variant instance + **/ + class IResourceVisitor_Any : public AResourceVisitor { + public: + /** @defgroup mm-resourcevisitor-any-type-traits **/ + ///@{ + + /** integer identifying a type **/ + using typeseq = xo::facet::typeseq; + using size_type = AResourceVisitor::size_type; + + ///@} + /** @defgroup mm-resourcevisitor-any-methods **/ + ///@{ + + const AResourceVisitor * iface() const { return std::launder(this); } + + // from AResourceVisitor + + // builtin methods + typeseq _typeseq() const noexcept override { return s_typeseq; } + [[noreturn]] void _drop(Opaque) const noexcept override { _fatal(); } + + // const methods + [[noreturn]] void on_allocator(Copaque, obj) const noexcept override { _fatal(); } + + // nonconst methods + + ///@} + + private: + /** @defgraoup mm-resourcevisitor-any-private-methods **/ + ///@{ + + [[noreturn]] static void _fatal(); + + ///@} + + public: + /** @defgroup mm-resourcevisitor-any-member-vars **/ + ///@{ + + static typeseq s_typeseq; + static bool _valid; + + ///@} + }; + +} /*namespace mm */ +} /*namespace xo */ + +/* IResourceVisitor_Any.hpp */ diff --git a/xo-alloc2/include/xo/alloc2/visitor/IResourceVisitor_Xfer.hpp b/xo-alloc2/include/xo/alloc2/visitor/IResourceVisitor_Xfer.hpp new file mode 100644 index 00000000..ded806e4 --- /dev/null +++ b/xo-alloc2/include/xo/alloc2/visitor/IResourceVisitor_Xfer.hpp @@ -0,0 +1,84 @@ +/** @file IResourceVisitor_Xfer.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ResourceVisitor.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ResourceVisitor.json5] + **/ + +#pragma once + +#include "Allocator.hpp" + +namespace xo { +namespace mm { + /** @class IResourceVisitor_Xfer + **/ + template + class IResourceVisitor_Xfer : public AResourceVisitor { + public: + /** @defgroup mm-resourcevisitor-xfer-type-traits **/ + ///@{ + /** actual implementation (not generated; often delegates to DRepr) **/ + using Impl = IResourceVisitor_DRepr; + /** integer identifying a type **/ + using typeseq = AResourceVisitor::typeseq; + using size_type = AResourceVisitor::size_type; + ///@} + + /** @defgroup mm-resourcevisitor-xfer-methods **/ + ///@{ + + static const DRepr & _dcast(Copaque d) { return *(const DRepr *)d; } + static DRepr & _dcast(Opaque d) { return *(DRepr *)d; } + + // from AResourceVisitor + + // builtin methods + typeseq _typeseq() const noexcept override { return s_typeseq; } + void _drop(Opaque d) const noexcept override { _dcast(d).~DRepr(); } + + // const methods + void on_allocator(Copaque data, obj mm) const noexcept override { + return I::on_allocator(_dcast(data), mm); + } + + // non-const methods + + ///@} + + private: + using I = Impl; + + public: + /** @defgroup mm-resourcevisitor-xfer-member-vars **/ + ///@{ + + /** typeseq for template parameter DRepr **/ + static typeseq s_typeseq; + /** true iff satisfies facet implementation **/ + static bool _valid; + + ///@} + }; + + template + xo::facet::typeseq + IResourceVisitor_Xfer::s_typeseq + = xo::facet::typeseq::id(); + + template + bool + IResourceVisitor_Xfer::_valid + = xo::facet::valid_facet_implementation(); + +} /*namespace mm */ +} /*namespace xo*/ + +/* end IResourceVisitor_Xfer.hpp */ diff --git a/xo-alloc2/include/xo/alloc2/visitor/RResourceVisitor.hpp b/xo-alloc2/include/xo/alloc2/visitor/RResourceVisitor.hpp new file mode 100644 index 00000000..6fa7a633 --- /dev/null +++ b/xo-alloc2/include/xo/alloc2/visitor/RResourceVisitor.hpp @@ -0,0 +1,85 @@ +/** @file RResourceVisitor.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ResourceVisitor.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ResourceVisitor.json5] + **/ + +#pragma once + +#include "AResourceVisitor.hpp" + +namespace xo { +namespace mm { + +/** @class RResourceVisitor + **/ +template +class RResourceVisitor : public Object { +private: + using O = Object; + +public: + /** @defgroup mm-resourcevisitor-router-type-traits **/ + ///@{ + using ObjectType = Object; + using DataPtr = Object::DataPtr; + using typeseq = xo::reflect::typeseq; + using size_type = AResourceVisitor::size_type; + ///@} + + /** @defgroup mm-resourcevisitor-router-ctors **/ + ///@{ + RResourceVisitor() {} + RResourceVisitor(Object::DataPtr data) : Object{std::move(data)} {} + RResourceVisitor(const AResourceVisitor * iface, void * data) + requires std::is_same_v + : Object(iface, data) {} + + ///@} + /** @defgroup mm-resourcevisitor-router-methods **/ + ///@{ + + // explicit injected content + + // builtin methods + typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); } + void _drop() const noexcept { O::iface()->_drop(O::data()); } + + // const methods + void on_allocator(obj mm) const noexcept { + return O::iface()->on_allocator(O::data(), mm); + } + + // non-const methods (still const in router!) + + ///@} + /** @defgroup mm-resourcevisitor-member-vars **/ + ///@{ + + static bool _valid; + + ///@} +}; + +template +bool +RResourceVisitor::_valid = xo::facet::valid_object_router(); + +} /*namespace mm*/ +} /*namespace xo*/ + +namespace xo { namespace facet { + template + struct RoutingFor { + using RoutingType = xo::mm::RResourceVisitor; + }; +} } + +/* end RResourceVisitor.hpp */ diff --git a/xo-alloc2/src/alloc2/CMakeLists.txt b/xo-alloc2/src/alloc2/CMakeLists.txt index 3a279746..29890c5f 100644 --- a/xo-alloc2/src/alloc2/CMakeLists.txt +++ b/xo-alloc2/src/alloc2/CMakeLists.txt @@ -3,24 +3,22 @@ set(SELF_LIB xo_alloc2) set(SELF_SRCS -# AllocError.cpp -# AllocInfo.cpp -# cmpresult.cpp + init_alloc2.cpp + alloc2_register_facets.cpp AAllocator.cpp -# ArenaConfig.cpp -# DArena.cpp IAllocator_Any.cpp IAllocator_DArena.cpp IAllocIterator_Any.cpp -# DArenaIterator.cpp IAllocIterator_DArenaIterator.cpp + IResourceVisitor_Any.cpp ) xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS}) # note: deps here must also appear in cmake/xo_alloc2Config.cmake.in xo_dependency(${SELF_LIB} xo_arena) xo_dependency(${SELF_LIB} xo_facet) +xo_dependency(${SELF_LIB} subsys) xo_dependency(${SELF_LIB} indentlog) diff --git a/xo-alloc2/src/alloc2/IAllocator_DArena.cpp b/xo-alloc2/src/alloc2/IAllocator_DArena.cpp index a3bd9613..2a3a2d58 100644 --- a/xo-alloc2/src/alloc2/IAllocator_DArena.cpp +++ b/xo-alloc2/src/alloc2/IAllocator_DArena.cpp @@ -52,6 +52,13 @@ namespace xo { return s.allocated(); } + void + IAllocator_DArena::visit_pools(const DArena & s, + const MemorySizeVisitor & visitor) + { + s.visit_pools(visitor); + } + bool IAllocator_DArena::contains(const DArena & s, const void * p) noexcept diff --git a/xo-alloc2/src/alloc2/IResourceVisitor_Any.cpp b/xo-alloc2/src/alloc2/IResourceVisitor_Any.cpp new file mode 100644 index 00000000..2d9fb12a --- /dev/null +++ b/xo-alloc2/src/alloc2/IResourceVisitor_Any.cpp @@ -0,0 +1,41 @@ +/** @file IResourceVisitor_Any.cpp + * + **/ + +#include "visitor/IResourceVisitor_Any.hpp" +#include + +namespace xo { +namespace mm { + +using xo::facet::DVariantPlaceholder; +using xo::facet::typeseq; +using xo::facet::valid_facet_implementation; + +void +IResourceVisitor_Any::_fatal() +{ + /* control here on uninitialized IAllocator_Any. + * Initialized instance will have specific implementation type + */ + std::cerr << "fatal" + << ": attempt to call uninitialized" + << " IResourceVisitor_Any method" + << std::endl; + std::terminate(); +} + +typeseq +IResourceVisitor_Any::s_typeseq = typeseq::id(); + +bool +IResourceVisitor_Any::_valid + = valid_facet_implementation(); + +// nonconst methods + + +} /*namespace mm*/ +} /*namespace xo*/ + +/* end IResourceVisitor_Any.cpp */ diff --git a/xo-alloc2/src/alloc2/alloc2_register_facets.cpp b/xo-alloc2/src/alloc2/alloc2_register_facets.cpp new file mode 100644 index 00000000..e03afde0 --- /dev/null +++ b/xo-alloc2/src/alloc2/alloc2_register_facets.cpp @@ -0,0 +1,33 @@ +/** @file alloc2_register_facets.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "alloc2_register_facets.hpp" +#include +#include +#include + +namespace xo { + using xo::facet::FacetRegistry; + //using xo::facet::TypeRegistry; + using xo::reflect::typeseq; + + namespace mm { + + bool + alloc2_register_facets() + { + scope log(XO_DEBUG(true)); + + FacetRegistry::register_impl(); + + log && log(xtag("DArena.tseq", typeseq::id())); + + return true; + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end alloc2_register_facets.cpp */ diff --git a/xo-alloc2/src/alloc2/init_alloc2.cpp b/xo-alloc2/src/alloc2/init_alloc2.cpp new file mode 100644 index 00000000..d3fb73fa --- /dev/null +++ b/xo-alloc2/src/alloc2/init_alloc2.cpp @@ -0,0 +1,36 @@ +/** @file init_alloc2.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "init_alloc2.hpp" +#include "alloc2_register_facets.hpp" + +namespace xo { + using xo::mm::alloc2_register_facets; + // using xo::mm::alloc2_register_types; + // using xo::mm::CollectorTypeRegistry; + + void + InitSubsys::init() + { + alloc2_register_facets(); + } + + InitEvidence + InitSubsys::require() + { + InitEvidence retval; + + /* direct subsystem deps for xo-alloc2/ (if/when) */ + //retval ^= InitSubsys>::require(); + + /* xo-alloc2/'s own initialization code */ + retval ^= Subsystem::provide("alloc2", &init); + + return retval; + } + +} /*namespace xo*/ + +/* end init_alloc2.cpp */ diff --git a/xo-alloc2/utest/DArenaIterator.test.cpp b/xo-alloc2/utest/DArenaIterator.test.cpp index 8eb1614a..7d26e623 100644 --- a/xo-alloc2/utest/DArenaIterator.test.cpp +++ b/xo-alloc2/utest/DArenaIterator.test.cpp @@ -169,7 +169,7 @@ namespace xo { /* arbitrary alloc size */ size_t req_z = 13; - byte * mem = a1o.alloc(typeseq::anon(), req_z); + byte * mem = a1o.alloc(typeseq::sentinel(), req_z); REQUIRE(arena.error_count_ == 0); REQUIRE(mem != nullptr); diff --git a/xo-alloc2/utest/arena.test.cpp b/xo-alloc2/utest/arena.test.cpp index 42ffa904..e9358a10 100644 --- a/xo-alloc2/utest/arena.test.cpp +++ b/xo-alloc2/utest/arena.test.cpp @@ -159,7 +159,7 @@ namespace xo { REQUIRE(a1o.allocated() == 0); size_t z0 = 1; - byte * m0 = a1o.alloc(typeseq::anon(), 1); + byte * m0 = a1o.alloc(typeseq::sentinel(), 1); REQUIRE(m0); REQUIRE(a1o.last_error().error_ == error::ok); @@ -171,7 +171,7 @@ namespace xo { REQUIRE(a1o.committed() <= a1o.reserved()); size_t z1 = 16; - byte * m1 = a1o.alloc(typeseq::anon(), z1); + byte * m1 = a1o.alloc(typeseq::sentinel(), z1); REQUIRE(m1); REQUIRE(a1o.last_error().error_ == error::ok); @@ -209,7 +209,7 @@ namespace xo { REQUIRE(a1o.allocated() == 0); size_t z0 = 1; - byte * m0 = a1o.alloc(typeseq::anon(), 1); + byte * m0 = a1o.alloc(typeseq::sentinel(), 1); REQUIRE(m0); @@ -253,7 +253,7 @@ namespace xo { REQUIRE(a1o.allocated() == 0); size_t z0 = 1; - byte * m0 = a1o.alloc(typeseq::anon(), 1); + byte * m0 = a1o.alloc(typeseq::sentinel(), 1); REQUIRE(m0); @@ -306,7 +306,7 @@ namespace xo { REQUIRE(a1o.allocated() == 0); size_t z0 = cfg.hugepage_z_ + 1; - byte * m0 = a1o.alloc(typeseq::anon(), z0); + byte * m0 = a1o.alloc(typeseq::sentinel(), z0); REQUIRE(!m0); diff --git a/xo-alloc2/utest/random_allocs.cpp b/xo-alloc2/utest/random_allocs.cpp index 1f7f833f..2325140d 100644 --- a/xo-alloc2/utest/random_allocs.cpp +++ b/xo-alloc2/utest/random_allocs.cpp @@ -67,7 +67,7 @@ namespace utest { bool ok_flag = true; - std::byte * mem = mm.alloc(typeseq::anon(), z); + std::byte * mem = mm.alloc(typeseq::sentinel(), z); log && log(xtag("i_alloc", i_alloc), xtag("si", si), diff --git a/xo-arena/include/xo/arena/AllocHeader.hpp b/xo-arena/include/xo/arena/AllocHeader.hpp index ec99f599..db8b6785 100644 --- a/xo-arena/include/xo/arena/AllocHeader.hpp +++ b/xo-arena/include/xo/arena/AllocHeader.hpp @@ -11,6 +11,13 @@ namespace xo { namespace mm { + /** @brief per-alloc header + * + * Appears immediately before each allocation when + * ArenaConfig.store_header_flag_ is set. + * + * See AllocInfo.hpp for encoding of @ref repr_ + **/ struct AllocHeader { using repr_type = std::uintptr_t; using size_type = std::size_t; diff --git a/xo-arena/include/xo/arena/ArenaConfig.hpp b/xo-arena/include/xo/arena/ArenaConfig.hpp index 4d79637b..05904f90 100644 --- a/xo-arena/include/xo/arena/ArenaConfig.hpp +++ b/xo-arena/include/xo/arena/ArenaConfig.hpp @@ -17,6 +17,30 @@ namespace xo { * @brief configuration for a @ref DArena instance **/ struct ArenaConfig { + /** @defgroup mm-arenaconfig-ctors **/ + ///@{ + + /** NOTE: not providing explicit ctors so we can use designated initializers **/ + + ArenaConfig with_name(std::string name) const { + ArenaConfig copy(*this); + copy.name_ = name; + return copy; + } + + ArenaConfig with_size(std::size_t z) const { + ArenaConfig copy(*this); + copy.size_ = z; + return copy; + } + + ArenaConfig with_store_header_flag(bool x) const { + ArenaConfig copy(*this); + copy.store_header_flag_ = x; + return copy; + } + + ///@} /** @defgroup mm-arenaconfig-instance-vars ArenaConfig members **/ ///@{ @@ -30,7 +54,7 @@ namespace xo { std::size_t hugepage_z_ = 2 * 1024 * 1024; /** true to store header (8 bytes) at the beginning of each allocation. * necessary and sufficient to allows iterating over allocs - * present in arena + * present in arena. **/ bool store_header_flag_ = false; /** configuration for per-alloc header **/ diff --git a/xo-arena/include/xo/arena/ArenaHashMapConfig.hpp b/xo-arena/include/xo/arena/ArenaHashMapConfig.hpp new file mode 100644 index 00000000..69174141 --- /dev/null +++ b/xo-arena/include/xo/arena/ArenaHashMapConfig.hpp @@ -0,0 +1,58 @@ +/** @file ArenaHashMapConfig.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include +#include + +namespace xo { + namespace map { + /** @class ArenaHashMapConfig + * + * @brief configuration for a @ref DArenaHashMap instance + **/ + struct ArenaHashMapConfig { + /** @defgroup map-arenahashmapconfig-ctors **/ + ///@{ + + ArenaHashMapConfig with_name(std::string name) const { + ArenaHashMapConfig copy(*this); + copy.name_ = name; + return copy; + } + + ArenaHashMapConfig with_hint_max_capacity(std::size_t z) const { + ArenaHashMapConfig copy(*this); + copy.hint_max_capacity_ = z; + return copy; + } + + ArenaHashMapConfig with_debug_flag(bool x) const { + ArenaHashMapConfig copy(*this); + copy.debug_flag_ = x; + return copy; + } + + ///@} + /** @defgroup mm-arenahashmapconfig-instance-vars ArenaHashMapConfig members **/ + ///@{ + + /** optional name, for diagnostics **/ + std::string name_; + /** desired hard max hashmap size -> reserved virtual memory + * hint: actual max may be larger, because of power-of-2 considerations. + **/ + std::size_t hint_max_capacity_ = 0; + /** true to enable debug logging **/ + bool debug_flag_ = false; + + ///@} + }; + + } /*namespace map*/ +} /*namespace xo*/ + +/* end ArenaHashMapConfig.hpp */ diff --git a/xo-arena/include/xo/arena/DArena.hpp b/xo-arena/include/xo/arena/DArena.hpp index 8eb6125c..24429188 100644 --- a/xo-arena/include/xo/arena/DArena.hpp +++ b/xo-arena/include/xo/arena/DArena.hpp @@ -7,6 +7,7 @@ #include "ArenaConfig.hpp" #include "AllocError.hpp" +#include "MemorySizeInfo.hpp" #include "AllocInfo.hpp" #include @@ -62,6 +63,13 @@ namespace xo { sub_complete, }; + /** @brief Checkpoint for unwinding arena state **/ + struct Checkpoint { + Checkpoint() = default; + explicit Checkpoint(std::byte * x) : free_{x} {} + std::byte * free_ = nullptr; + }; + ///@} /** @defgroup mm-arena-ctors arena constructors and destructors **/ @@ -72,7 +80,9 @@ namespace xo { /** null ctor **/ DArena() = default; - /** ctor from already-mapped (but not committed) address range **/ + /** create arena from @p cfg. Will reserve memory for allocation **/ + DArena(const ArenaConfig & cfg); + /** ctor from already-mapped (but not committed) address range [lo,hi] **/ DArena(const ArenaConfig & cfg, size_type page_z, size_type arena_align_z, @@ -115,34 +125,6 @@ namespace xo { **/ bool contains(const void * addr) const noexcept { return (lo_ <= addr) && (addr < hi_); } -#ifdef OBSOLETE - /** obtain uncommitted contiguous memory range comprising - * a whole multiple of @p align_z bytes, of at least size @p req_z, - * aligned on a @p align_z boundary. Uncommitted memory is not (yet) - * backed by physical memory. - * - * If @p enable_hugepage_flag is true and THP - * (transparent huge pages) are available, use THP for arena memory. - * This relieves TLB and page table memory when @p req_z is a lot larger than - * page size (likely 4KB). Cost is that arena will consum physical memory in unit - * of @p align_z. Arena may waste up to @p align_z bytes of memory as a result. - * - * If @p enable_hugepage_flag is true, @p align_z should be huge page size - * (probably 2MB) for optimal performance. - * - * At present the THP feature is not supported on OSX. - * May be supportable through mach_vm_allocate(). - * - * Note that we reject MAP_HUGETLB|MAP_HUGE_2MB flags to mmap here, - * since requires previously-reserved memory in /proc/sys/vm/nr_hugepages. - * - * @return pair giving reserved memory address range [lo,hi) - **/ - static range_type map_aligned_range(size_type req_z, - size_type align_z, - bool enable_hugepage_flag); -#endif - /** true if arena is mapped i.e. has a reserved address range **/ bool is_mapped() const noexcept { return (lo_ != nullptr) && (hi_ != nullptr); } @@ -158,6 +140,11 @@ namespace xo { **/ AllocHeader * end_header() const noexcept; + /** report memory use for this arena to @p fn. + * For DArena reporting just one pool = arena's memory range + **/ + void visit_pools(const MemorySizeVisitor & fn) const; + /** get header from allocated object address **/ header_type * obj2hdr(void * obj) noexcept; @@ -165,7 +152,8 @@ namespace xo { * * Require: * 1. @p mem is address returned by allocation on this arena - * i.e. by @ref IAllocator_DArena::alloc() or @ref IAllocator_DArena::alloc_super() + * i.e. by @ref IAllocator_DArena::alloc() or + * @ref IAllocator_DArena::alloc_super() * 2. @p mem has not been invalidated since it was allocated * i.e. by call to @ref DArena::clear * @@ -218,6 +206,15 @@ namespace xo { /** create initial guard **/ void establish_initial_guard() noexcept; + /** checkpoint arena state. Revert to the same state with + * @ref restore + **/ + Checkpoint checkpoint() noexcept { return Checkpoint(free_); } + + /** restore arena state to previously-established checkpoint **/ + void restore(Checkpoint ckp) noexcept { free_ = ckp.free_; } + + /** discard all allocated memory, return to empty state * Promise: * - committed memory unchanged diff --git a/xo-arena/include/xo/arena/DArenaHashMap.hpp b/xo-arena/include/xo/arena/DArenaHashMap.hpp index 50b7b4aa..50e66698 100644 --- a/xo-arena/include/xo/arena/DArenaHashMap.hpp +++ b/xo-arena/include/xo/arena/DArenaHashMap.hpp @@ -5,6 +5,7 @@ #pragma once +#include "ArenaHashMapConfig.hpp" #include "DArenaVector.hpp" #include "hashmap/verify_policy.hpp" #include "hashmap/HashMapStore.hpp" @@ -30,8 +31,10 @@ namespace xo { * * Replicates (to the extent feasible) std::unordered_map * - * @tparam K key type. - * @tparam V value type. + * @tparam Key key type. + * @tparam Value value type. + * @tparam Hash hash function for keys + * @tparam Equal equality function for keys **/ template ; using key_hash = Hash; using key_equal = Equal; + using MemorySizeVisitor = xo::mm::MemorySizeVisitor; using byte = std::byte; using group_type = detail::ControlGroup; using store_type = detail::HashMapStore; @@ -54,9 +58,12 @@ namespace xo { public: /** create hash map **/ - DArenaHashMap(size_type hint_max_capacity, + DArenaHashMap(const ArenaHashMapConfig & cfg); + DArenaHashMap(const std::string & name, + size_type hint_max_capacity, bool debug_flag = false); - DArenaHashMap(Hash && hash = Hash(), + DArenaHashMap(const std::string & name, + Hash && hash = Hash(), Equal && eq = Equal(), size_type hint_max_capacity = 0, bool debug_flag = false); @@ -76,6 +83,10 @@ namespace xo { iterator begin() { return _promote_iterator(_begin_aux()); } iterator end() { return _promote_iterator(_end_aux()); } + void visit_pools(const MemorySizeVisitor & visitor) const { + return store_.visit_pools(visitor); + } + /** insert @p kv_pair into hash map. * Replaces any previous value stored under the same key. * @@ -191,9 +202,16 @@ namespace xo { }; template - DArenaHashMap::DArenaHashMap(size_type hint_max_capacity, + DArenaHashMap::DArenaHashMap(const ArenaHashMapConfig & cfg) + : DArenaHashMap(cfg.name_, Hash(), Equal(), cfg.hint_max_capacity_, cfg.debug_flag_) + { + } + + template + DArenaHashMap::DArenaHashMap(const std::string & name, + size_type hint_max_capacity, bool debug_flag) - : DArenaHashMap(Hash(), Equal(), hint_max_capacity, debug_flag) + : DArenaHashMap(name, Hash(), Equal(), hint_max_capacity, debug_flag) { } @@ -202,13 +220,14 @@ namespace xo { * last 16 bytes will be copy of first 16 bytes */ template - DArenaHashMap::DArenaHashMap(Hash && hash, + DArenaHashMap::DArenaHashMap(const std::string & name, + Hash && hash, Equal && eq, size_type hint_max_capacity, bool debug_flag) : hash_{std::move(hash)}, equal_{std::move(eq)}, - store_{"arenahashmap", lub_exp2(lub_group_mult(hint_max_capacity))}, + store_{name, lub_exp2(lub_group_mult(hint_max_capacity))}, debug_flag_{debug_flag} { } diff --git a/xo-arena/include/xo/arena/DArenaVector.hpp b/xo-arena/include/xo/arena/DArenaVector.hpp index f8bd9820..79653fe0 100644 --- a/xo-arena/include/xo/arena/DArenaVector.hpp +++ b/xo-arena/include/xo/arena/DArenaVector.hpp @@ -79,6 +79,11 @@ namespace xo { constexpr T * data() { return reinterpret_cast(store_.lo_); } constexpr const T * data() const { return reinterpret_cast(store_.lo_); } + /** arena used for element storage + * (Might prefer obj here; refrain to avoid leveling violation) + **/ + void visit_pools(const MemorySizeVisitor & fn) const { store_.visit_pools(fn); } + /** reserve space, if possible, for at least @p z elements. * Always limited by ArenaConfig.size_ **/ @@ -109,6 +114,7 @@ namespace xo { private: size_type size_ = 0; DArena store_; + DArena::Checkpoint zero_ckp_; }; template @@ -117,14 +123,16 @@ namespace xo { size_type arena_align_z, DArena::value_type lo, DArena::value_type hi) - : store_{cfg, page_z, arena_align_z, lo, hi} + : store_{cfg, page_z, arena_align_z, lo, hi}, + zero_ckp_{store_.checkpoint()} {} template DArenaVector::DArenaVector(DArenaVector && other) - : size_{other.size_}, store_{std::move(other.store_)} + : size_{other.size_}, store_{std::move(other.store_)}, zero_ckp_{std::move(other.zero_ckp_)} { other.size_ = 0; + other.zero_ckp_ = DArena::Checkpoint(); } template @@ -148,8 +156,10 @@ namespace xo { { this->size_ = other.size_; this->store_ = std::move(other.store_); + this->zero_ckp_ = std::move(other.zero_ckp_); other.size_ = 0; + other.zero_ckp_ = DArena::Checkpoint(); return *this; } @@ -161,6 +171,7 @@ namespace xo { DArenaVector retval; retval.store_ = std::move(DArena::map(cfg)); + retval.zero_ckp_ = retval.store_.checkpoint(); return retval; } @@ -174,9 +185,11 @@ namespace xo { template void DArenaVector::resize(size_type z) { + // new arena size in bytes + size_t req_z = z * sizeof(T); + if (z > size_) { // expand arena to accomodate - size_t req_z = z * sizeof(T); store_.expand(req_z); @@ -203,6 +216,14 @@ namespace xo { } } + // rewind to checkpoint, then reallocate. + // This is for form's sake, so that DArena considers memory + // to be 'allocated'. DArenaVector doesn't care for itself, + // but this preserves expected behavior of visit_pools(). + // + store_.restore(zero_ckp_); + store_.alloc(xo::reflect::typeseq::id(), req_z); + this->size_ = z; } diff --git a/xo-arena/include/xo/arena/DCircularBuffer.hpp b/xo-arena/include/xo/arena/DCircularBuffer.hpp index 30a38960..ba744531 100644 --- a/xo-arena/include/xo/arena/DCircularBuffer.hpp +++ b/xo-arena/include/xo/arena/DCircularBuffer.hpp @@ -83,6 +83,9 @@ namespace xo { const_span_type occupied_range() const noexcept { return occupied_range_; } const_span_type input_range() const noexcept { return input_range_; } + /** report memory-size info for this buffer to @p fn **/ + void visit_pools(const MemorySizeVisitor & fn) const; + /** verify DCircularBuffer invariants. * Act on failure according to policy @p p * (combination of throw|log bits) diff --git a/xo-arena/include/xo/arena/ErrorArena.hpp b/xo-arena/include/xo/arena/ErrorArena.hpp new file mode 100644 index 00000000..0236c325 --- /dev/null +++ b/xo-arena/include/xo/arena/ErrorArena.hpp @@ -0,0 +1,54 @@ +/** @file ErrorArena.hpp +* + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DArena.hpp" + +namespace xo { + namespace mm { + + /** @brief Dedicated arena for error reporting + * + * Reserving memory for error messaages. + * Motivation + * 1. so we have room to report an out-of-memory condition + * 2. so we have place to allocate for an error that + * doesn't interfere with other allocator state + * + * Expect to reset arena between errors, so only need + * enough room to report one error. + * + * To initialize explicitly: + * @code + * // before any other ErrorArena method calls: + * ErrorArena::init_once(cfg...); + * + * // do stuff with ErrorArena.. + * ErrorArena::instance() + * @endcode + * + * Reminder: can't use obj here, + * would be leveling violation. + **/ + class ErrorArena { + public: + /** default configuration for error arena **/ + static ArenaConfig default_config(); + + /** idempotent initialization **/ + static void init_once(const ArenaConfig & cfg = default_config()); + + /** get initialized instnace **/ + static DArena * instance(); + + private: + static DArena s_instance; + }; + + } /*namespace mm*/ +} /*namespace xo*/ + +/* end ErrorArena.hpp */ diff --git a/xo-arena/include/xo/arena/MemorySizeInfo.hpp b/xo-arena/include/xo/arena/MemorySizeInfo.hpp new file mode 100644 index 00000000..a9649b3e --- /dev/null +++ b/xo-arena/include/xo/arena/MemorySizeInfo.hpp @@ -0,0 +1,66 @@ +/** @file MemorySizeInfo.hpp +* + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include +#include +#include +#include + +namespace xo { + namespace mm { + + struct MemorySizeDetail { + using typeseq = xo::reflect::typeseq; + + /** identifies a c++ type T. See xo/facet/TypeRegistry **/ + typeseq tseq_; + /** number of T-instances **/ + uint32_t n_alloc_ = 0; + /** bytes used by T-instances **/ + uint32_t z_alloc_ = 0; + }; + + struct MemorySizeInfo { + using size_type = std::size_t; + using DetailArrayType = std::array; + + MemorySizeInfo() = default; + MemorySizeInfo(std::string_view name, + std::size_t u, std::size_t a, std::size_t c, std::size_t r, + DetailArrayType * detail) + : resource_name_{name}, + used_{u}, allocated_{a}, committed_{c}, reserved_{r}, detail_{detail} + {} + + static MemorySizeInfo sentinel() { return MemorySizeInfo(); } + + /** resource name **/ + std::string_view resource_name_; + /** memory used (excluding wasted space) **/ + std::size_t used_ = 0; + /** memory allocated (including wasted space e.g. empty slots in hash tables **/ + std::size_t allocated_ = 0; + /** memory committed (backed by physical memory) **/ + std::size_t committed_ = 0; + /** memory reserved: + * virtual memory addresses range obtained, whether or not committed + **/ + std::size_t reserved_ = 0; + + /** optional histogram with per-data-type counts **/ + DetailArrayType * detail_ = nullptr; + }; + + /** function that visits MemorySizeInfo for a collection of @p n memory pools. + * Each pool reported with index @p i in [0, n), with associated + * size record @p info. + **/ + using MemorySizeVisitor = std::function; + } +} + +/* end MemorySizeInfo.hpp */ diff --git a/xo-arena/include/xo/arena/arena_streambuf.hpp b/xo-arena/include/xo/arena/arena_streambuf.hpp new file mode 100644 index 00000000..2b364622 --- /dev/null +++ b/xo-arena/include/xo/arena/arena_streambuf.hpp @@ -0,0 +1,236 @@ +/** @file arena_streambuf.hpp +* + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DArena.hpp" +//#include "print/quoted_char.hpp" +#include +#include +#include +#include // e.g. for std::memcpy() +#include +#include + +namespace xo { + namespace mm { + /** @brief Arena-based buffer for logging and pretty-printing + * + * Arena-based using mmap + * Write to self-extending storage array + * Track position relative to start of line + **/ + class arena_streambuf : public std::streambuf { + public: + struct rewind_state { + explicit rewind_state(std::size_t solpos, std::size_t color_esc, std::uint32_t p) + : solpos{solpos}, color_escape_chars{color_esc}, pos{p} {} + + std::size_t solpos = 0; + std::size_t color_escape_chars = 0; + std::uint32_t pos = 0; + }; + + public: + /** arena should be ready-to-allocate i.e. have committed > 0 **/ + arena_streambuf(DArena * arena, bool debug_flag = false) : arena_{arena}, debug_flag_{debug_flag} { + this->reset_stream(); + } /*ctor*/ + + std::streamsize capacity() const { return arena_->committed(); } + const char * lo() const { return this->pbase(); } + const char * hi() const { return this->lo() + this->capacity(); } + std::uint32_t pos() const { return this->pptr() - this->pbase(); } + + /** output position (relative to pbase) when local state last computed. Exposed here for unit tests **/ + std::size_t _local_ppos() const { return local_ppos_; } + /** position (relative to pbase) one character after last \n or \r. For unit tests **/ + std::uint32_t _solpos() const { return solpos_; } + /** start of incomplete color-escape sequence **/ + const char * _color_escape_start() const { return color_escape_start_; } + /** number of non-printing chars after @ref solpos_ from completed color-escape sequences **/ + std::uint32_t _color_escape_chars() const { return color_escape_chars_; } + + /** number of visible characters since start of line (last \n or \r) **/ + std::uint32_t lpos() const; + + rewind_state checkpoint() const; + + bool debug_flag() const { return debug_flag_; } + + operator std::string_view () const { return std::string_view(this->pbase(), this->pptr()); } + + void reset_stream(); + + void rewind_to(rewind_state s); + + protected: + /** expand buffer storage (by 2x), preserve current contents **/ + void expand_to(std::size_t new_z); + + virtual std::streamsize xsputn(const char * s, std::streamsize n) override; + + virtual int_type overflow(int_type new_ch) override; + + /* off. offset, relative to starting point dir. + * dir. + * which. in|out|both + * + * Note that off=0,dir=cur,which=out reads offset + */ + virtual pos_type seekoff(off_type off, + std::ios_base::seekdir dir, + std::ios_base::openmode which) override; + + private: + void _update_local_state_char(const char * p_lo, const char * p) + { + if ((*p == '\n') || (*p == '\r')) { + this->solpos_ = (p+1 - this->pbase()); + /* reset, since these chars relevant as correction to solpos */ + this->color_escape_chars_ = 0; + /* -> incomplete color escape, broken by newline */ + this->color_escape_start_ = nullptr; + } else if (*p == '\033') { + if (debug_flag_) [[unlikely]] { + std::cout << "xsputn: \\033 at p-p_lo=" << (p - p_lo) << std::endl; + } + this->color_escape_start_ = p; + } else if (this->color_escape_start_ != nullptr) { + if (*p == 'm') { + /* escape seq non-printing including both endpoints */ + std::int64_t esc_chars = (p+1 - color_escape_start_); + + this->color_escape_chars_ += esc_chars; + + if (debug_flag_) [[unlikely]] { + std::cout << "xsputn: m at p-p_lo" << (p - p_lo) << " +" << esc_chars + << " -> color_escape_chars=" << color_escape_chars_ << std::endl; + } + this->color_escape_start_ = nullptr; + } else if (!isdigit(*p) && (*p != '[') && (*p != ';')) { + /* not color escape after all */ + this->color_escape_start_ = nullptr; + } + } + } + + /** recognize stale local state vars: + * @ref solpos_, @ref color_escape_chars_, @ref color_escape_start_. + * + * Require: + * - {pbase, pptr} in consistent state + * Promise: + * - @c local_ppos_ + @c pbase = @c pptr + * - @c solpos_, @c color_escape_chars_, @c color_escape_start_ all up-to-date + **/ + void _check_update_local_state() { + const char * p0 = this->pbase(); + const char * pn = this->pptr(); + + if (debug_flag_) { + std::cerr << "_check_update_local_state:" << std::endl; + std::cerr << " buf: (p0=" << (void*)p0 << ", pn=" << (void*)pn << ")" << std::endl; + std::cerr << " solpos_=" << solpos_ << ", color_escape_chars_=" << color_escape_chars_ << std::endl; + } + + if (p0 + local_ppos_ == pn) [[likely]] { + // solpos_, color_escape_chars_, color_escape_start_ all up-to-date + } else { + // [pnew, pn): input that hasn't been incorporated into + // {solpos_, color_escape_chars_, color_escape_start_) + + const char * pnew = this->pbase() + this->local_ppos_; + + if (debug_flag_) { + std::cerr << "_check_update_local_state: range: (pnew=" << (void*)pnew << ", pn=" << (void*)pn << ")" << std::endl; + } + + for(const char * p = pnew; p < pn; ++p) { + this->_update_local_state_char(p0, p); + } + } + + // solpos_, color_escape_chars_, color_escape_start_ all up-to-date + // for current buffered contents + + this->local_ppos_ = pn - p0; + + if (debug_flag_) { + std::cerr << "_check_update_local_state: pos=" << pos(); + std::cerr << ", solpos=" << solpos_; + std::cerr << ", color_escape_chars=" << color_escape_chars_ << std::endl; + } + + assert(pos() >= solpos_ + color_escape_chars_); + } + + private: + /* + * pbase: start of buffered text. Thils will be arena_->lo_ + * + * + * pbase pptr epptr + * v >e1< >e2< v v + * |xx\xxEEExxx\xxxxxxxEExxxxEExxxxxxxEExxx\xEExxxxxx..................| + * ^ ^<------new-------> + * solpos local_ppos + * + * solpos : first character after newline (stale) + * color_escape_pos : e1+e2+.. (stale) + * new : new characters not reflected + * in local_ppos_, color_escape_chars_ etc. + * + * Legend: + * [\] newline + * [x] visible character + * [E] color escape chars + * + * + * after _check_update_local_state(): + * + * + * pbase pptr epptr + * v >e1< v v + * |xx\xxEEExxx\xxxxxxxEExxxxEExxxxxxxEExxx\xEExxxxxx..................| + * ^ ^ + * solpos local_ppos + * + */ + + /** @defgroup logstreambuf-instance-vars **/ + ///@{ + + /** value of pptr (relative to pbase) when _check_update_local_state() last ran **/ + std::size_t local_ppos_ = 0; + /** position (relative to pbase) one character after last \n or \r. + * Use to drive @ref lpos. This _has_ to be lazy, since + * xsputn() isn'g guaranteed to be called when there's room in + * in buffer. + **/ + std::size_t solpos_ = 0; + /** number of non-printing chars after @ref solpos_, from + * completed color escape sequences. + * (ansi color escapes = text between '\033' and 'm') + **/ + std::size_t color_escape_chars_ = 0; + /** non-null: start of incomplete color escape sequence **/ + const char * color_escape_start_ = nullptr; + + /** buffered output stored here. + * We don't use arena's allocation api, just treat as a block of available memory + **/ + DArena * arena_ = nullptr;; + /** true to debug log_streambuf itself **/ + bool debug_flag_ = false; + + ///@} + }; /*log_streambuf*/ + + } /*namespace mm*/ +} /*namespace xo*/ + +/* end arena_streambuf.hpp */ + diff --git a/xo-arena/include/xo/arena/hashmap/HashMapStore.hpp b/xo-arena/include/xo/arena/hashmap/HashMapStore.hpp index fd7c87f7..6393bb02 100644 --- a/xo-arena/include/xo/arena/hashmap/HashMapStore.hpp +++ b/xo-arena/include/xo/arena/hashmap/HashMapStore.hpp @@ -19,6 +19,8 @@ namespace xo { using group_type = detail::ControlGroup; using control_vector_type = xo::mm::DArenaVector; using slot_vector_type = xo::mm::DArenaVector; + using MemorySizeVisitor = xo::mm::MemorySizeVisitor; + using MemorySizeInfo = xo::mm::MemorySizeInfo; public: /** group_exp2: number of groups {x, 2^x} **/ @@ -31,12 +33,14 @@ namespace xo { n_slot_{group_exp2.second * c_group_size}, control_{control_vector_type::map (xo::mm::ArenaConfig{ - .name_ = name, - .size_ = control_size(n_slot_)})}, + .name_ = name + "-ctl", + .size_ = control_size(n_slot_), + .store_header_flag_ = false})}, slots_{slot_vector_type::map (xo::mm::ArenaConfig{ - .name_ = name, - .size_ = n_slot_ * sizeof(value_type)})} + .name_ = name + "-slots", + .size_ = n_slot_ * sizeof(value_type), + .store_header_flag_ = false})} { /* here: arenas have allocated address range, but no committed memory yet */ @@ -47,6 +51,23 @@ namespace xo { size_type capacity() const noexcept { return n_group_ * c_group_size; } float load_factor() const noexcept { return size_ / static_cast(n_slot_); } + void visit_pools(const MemorySizeVisitor & visitor) const { + // complexity here in service of HashMapStore-specific value for MemorySizeInfo.used + + MemorySizeInfo ctl_info; + MemorySizeInfo slot_info; + + control_.visit_pools([&ctl_info](const auto & x) { ctl_info = x; }); + slots_.visit_pools([&slot_info](const auto & x) { slot_info = x; }); + + // control: 1 byte per (key,value) pair + ctl_info.used_ = size_; + slot_info.used_ = size_ * sizeof(value_type); + + visitor(ctl_info); + visitor(slot_info); + } + void resize_from_empty(const std::pair & group_exp2) { diff --git a/xo-arena/src/arena/CMakeLists.txt b/xo-arena/src/arena/CMakeLists.txt index 5288c393..b3bb35a6 100644 --- a/xo-arena/src/arena/CMakeLists.txt +++ b/xo-arena/src/arena/CMakeLists.txt @@ -2,6 +2,8 @@ set(SELF_LIB xo_arena) set(SELF_SRCS + arena_streambuf.cpp + ErrorArena.cpp cmpresult.cpp mmap_util.cpp AllocError.cpp diff --git a/xo-arena/src/arena/DArena.cpp b/xo-arena/src/arena/DArena.cpp index 670666f5..2cd36dc1 100644 --- a/xo-arena/src/arena/DArena.cpp +++ b/xo-arena/src/arena/DArena.cpp @@ -65,6 +65,11 @@ namespace xo { return DArena(cfg, page_z, align_z, span.lo(), span.hi()); } /*map*/ + DArena::DArena(const ArenaConfig & cfg) + { + *this = map(cfg); + } + DArena::DArena(const ArenaConfig & cfg, size_type page_z, size_type arena_align_z, @@ -165,6 +170,51 @@ namespace xo { return (header_type *)((byte *)obj - sizeof(header_type)); } + void + DArena::visit_pools(const MemorySizeVisitor & fn) const { + /** arena can't tell purpose of allocated memory; + * must assume it's all used + **/ + + // assemble histogram + MemorySizeInfo::DetailArrayType detail_v; + MemorySizeInfo::DetailArrayType * p_detail = nullptr; + + if (config_.store_header_flag_) { + p_detail = &detail_v; + + for (const auto & ix : *this) { + typeseq ix_tseq(ix.tseq()); + + // totals in detail_v[0] + MemorySizeDetail & d = detail_v[0]; + ++d.n_alloc_; + d.z_alloc_ += ix.size(); + + // O(n) insertion here + for (size_t i = 1; i < detail_v.size(); ++i) { + if (detail_v[i].tseq_.is_sentinel() + || (detail_v[i].tseq_ == ix_tseq)) + { + MemorySizeDetail & d = detail_v[i]; + + d.tseq_ = ix_tseq; + ++d.n_alloc_; + d.z_alloc_ += ix.size(); + break; + } + } + } + } + + fn(MemorySizeInfo(config_.name_, + this->allocated() /*used*/, + this->allocated(), + this->committed(), + this->reserved(), + p_detail)); + } + AllocInfo DArena::alloc_info(value_type mem) const noexcept { @@ -272,7 +322,7 @@ namespace xo { (complete_flag ? alloc_mode::sub_complete : alloc_mode::sub_incomplete), - typeseq::anon() /*typeseq: ignored*/, + typeseq::sentinel() /*typeseq: ignored*/, 0 /*age - ignored */); } diff --git a/xo-arena/src/arena/DCircularBuffer.cpp b/xo-arena/src/arena/DCircularBuffer.cpp index 2a415c49..bd4dc0cd 100644 --- a/xo-arena/src/arena/DCircularBuffer.cpp +++ b/xo-arena/src/arena/DCircularBuffer.cpp @@ -75,10 +75,23 @@ namespace xo { mapped_range_{reserved_range_.prefix(0)}, occupied_range_{mapped_range_.prefix(0)}, input_range_{occupied_range_.prefix(0)}, - pinned_spans_{} + pinned_spans_{DArenaVector::map(ArenaConfig().with_name(config.name_ + "-pins"))} { } + void + DCircularBuffer::visit_pools(const MemorySizeVisitor & visitor) const + { + visitor(MemorySizeInfo(config_.name_, + occupied_range_.size() /*used*/, + occupied_range_.size(), + mapped_range_.size(), + reserved_range_.size(), + nullptr /*detail*/)); + + pinned_spans_.visit_pools(visitor); + } + bool DCircularBuffer::verify_ok(verify_policy policy) const { diff --git a/xo-arena/src/arena/ErrorArena.cpp b/xo-arena/src/arena/ErrorArena.cpp new file mode 100644 index 00000000..d1d3d62b --- /dev/null +++ b/xo-arena/src/arena/ErrorArena.cpp @@ -0,0 +1,43 @@ +/** @file ErrorArena.cpp +* + * @author Roland Conybeare, Feb 2026 + **/ + +#include "ErrorArena.hpp" + +namespace xo { + namespace mm { + DArena + ErrorArena::s_instance; + + ArenaConfig + ErrorArena::default_config() + { + return ArenaConfig().with_name("error-arena").with_size(16 * 1024); + } + + namespace { + bool s_init_done = false; + } + + void + ErrorArena::init_once(const ArenaConfig & cfg) + { + if (!s_init_done) { + s_init_done = true; + s_instance = DArena::map(cfg); + } + } + + DArena * + ErrorArena::instance() + { + init_once(default_config()); + + return &s_instance; + } + + } /*namespace mm*/ +} /*namespace xo*/ + +/* end ErrorArena.cpp */ diff --git a/xo-arena/src/arena/arena_streambuf.cpp b/xo-arena/src/arena/arena_streambuf.cpp new file mode 100644 index 00000000..18ea132e --- /dev/null +++ b/xo-arena/src/arena/arena_streambuf.cpp @@ -0,0 +1,214 @@ +/** @file arena_streambuf.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "arena_streambuf.hpp" + +namespace xo { + namespace mm { + + std::uint32_t + arena_streambuf::lpos() const + { + if (debug_flag_) { + std::cerr << "log_streambuf::lpos: enter" << std::endl; + } + + // logically-const. lazy implementation + arena_streambuf * self = const_cast(this); + + self->_check_update_local_state(); + + return pos() - solpos_ - color_escape_chars_; + } + + auto + arena_streambuf::checkpoint() const -> rewind_state + { + // logically-const. lazy implementation + arena_streambuf * self = const_cast(this); + + self->_check_update_local_state(); + + return rewind_state(solpos_, color_escape_chars_, pos()); + } + + void + arena_streambuf::reset_stream() + { + assert(arena_); + assert(arena_->committed() > 0); + + char * p_lo = (char *)(arena_->lo_); + char * p_hi = (char *)(arena_->limit_); + + /* tells parent our buffer extent */ + this->setp(p_lo, p_hi); + + this->local_ppos_ = 0; + this->solpos_ = 0; + this->color_escape_chars_ = 0; + this->color_escape_start_ = nullptr; + } + + void + arena_streambuf::rewind_to(rewind_state s) + { + if (debug_flag_) { + std::cout << "rewind_to: pos " << pos() << "->" << s.pos + << " solpos " << solpos_ << "->" << s.solpos + << " color_esc " << color_escape_chars_ << "->" << s.color_escape_chars + << std::endl; + } + + /* .setp(): using just for side effect: sets .pptr to .pbase */ + this->setp(this->pbase(), this->epptr()); + /* advance pptr to saved position */ + this->pbump(s.pos); + + this->local_ppos_ = this->pptr() - this->pbase(); + this->solpos_ = s.solpos; + this->color_escape_chars_ = s.color_escape_chars; + /* assuming we never try to capture rewind state with incomplete color escape */ + this->color_escape_start_ = nullptr; + } + + void + arena_streambuf::expand_to(std::size_t new_z) + { + char * old_pptr = pptr(); + std::streamsize old_n = old_pptr - pbase(); + + assert(old_n <= static_cast(arena_->allocated())); + assert(new_z > arena_->committed()); + + /* note: local_ppos_ invariant across expand_to() */ + + arena_->expand(new_z); + + char * p_base = (char *)(arena_->lo_); + char * p_hi = (char *)(arena_->limit_); + + this->setp(p_base, p_hi); + this->pbump(old_n); + } + + std::streamsize + arena_streambuf::xsputn(const char * s, std::streamsize n) + { + /* s must be an address in [this->lo() .. this->lo() + capacity()] */ + + assert(hi() >= pptr()); + + if (pptr() + n > hi()) { + std::size_t new_z = std::max(2 * arena_->committed(), std::size_t(this->pos() + n + 1)); + + if (new_z > arena_->reserved()) + new_z = arena_->reserved(); + + this->expand_to(new_z); + } + + if (debug_flag_) { + std::cout << "xsputn: pbase=" << (void *)(this->pbase()) + << ", pptr=" << (void*)(this->pptr()) + << "(+" << (this->pptr() - this->lo()) << ")" + << ", n=" << n << " -> (+" << (this->pptr() + n - this->lo()) << ")" + << ", arena.size=" << this->arena_->committed() + << std::endl; + } + + std::streamsize ncopied = 0; + + if (this->pptr() + n > this->hi()) { + ncopied = this->hi() - this->pptr(); + } else { + ncopied = n; + } + + if (false /*debug_flag_*/) { + std::cout << "xsputn: copying ncopied=" << ncopied << " (/n=" << n << ") bytes into range [lo,hi)" + << ", lo=" << (void*)this->pptr() + << ", hi=" << (void*)(this->pptr() + n) + << std::endl; + } + + std::memcpy(this->pptr(), s, ncopied); + + this->pbump(ncopied); + + /* now {pbase, pptr} consistent with new input */ + + this->_check_update_local_state(); + + return ncopied; + } + + auto + arena_streambuf::overflow(int_type new_ch) -> int_type + { + char * old_base = this->pbase(); + char * old_pptr = this->pptr(); + /* #of chars buffered */ + std::streamsize old_n = old_pptr - old_base; + + assert(old_n <= static_cast(arena_->committed())); + + // if (debug_flag_) { + // std::cout << "overflow: new_ch=" << quoted_char(new_ch) << std::endl; + // } + + /* increase buffer size */ + this->expand_to(2 * arena_->committed()); + + arena_->lo_[old_n] = static_cast(new_ch); + this->pbump(1); + + if ((new_ch == static_cast('\n')) || (new_ch == static_cast('\r'))) { + this->solpos_ = this->pos(); + + // what if new_ch starts color escape ? + } + + if (new_ch == std::char_traits::eof()) { + /* reminder: returning eof sets badbit on ostream */ + return std::char_traits::not_eof(new_ch); + } else { + return new_ch; + } + } + + auto + arena_streambuf::seekoff(off_type off, + std::ios_base::seekdir dir, + std::ios_base::openmode which) -> pos_type + { + //std::cout << "seekoff: off=" << off << ", dir=" << dir << ", which=" << which << std::endl; + if (debug_flag_) { + std::cout << "seekoff(off,dir,which)" << std::endl; + } + + // Only output stream is supported + if (which != std::ios_base::out) + throw std::runtime_error("log_streambuf: only output mode supported"); + + if (dir == std::ios_base::cur) { + this->pbump(off); + } else if (dir == std::ios_base::end) { + /* .setp(): using for side effect: sets .pptr to .pbase */ + this->setp(this->pbase(), this->epptr()); + this->pbump(off); + } else if (dir == std::ios_base::beg) { + /* .setp(): using for side effect: sets .pptr to .pbase */ + this->setp(this->pbase(), this->epptr()); + this->pbump(this->capacity() + off); + } + + return this->pptr() - this->pbase(); + } /*seekoff*/ + + } /*namespace mm*/ +} /*namespace xo*/ + +/* end arena_streambuf.cpp */ diff --git a/xo-arena/utest/DArena.test.cpp b/xo-arena/utest/DArena.test.cpp index e999c35f..03e1633f 100644 --- a/xo-arena/utest/DArena.test.cpp +++ b/xo-arena/utest/DArena.test.cpp @@ -147,7 +147,7 @@ namespace xo { REQUIRE(arena.allocated() == 0); size_t z0 = 1; - byte * m0 = arena.alloc(typeseq::anon(), 1); + byte * m0 = arena.alloc(typeseq::sentinel(), 1); REQUIRE(m0); REQUIRE(arena.last_error().error_ == error::ok); @@ -159,7 +159,7 @@ namespace xo { REQUIRE(arena.committed() <= arena.reserved()); size_t z1 = 16; - byte * m1 = arena.alloc(typeseq::anon(), z1); + byte * m1 = arena.alloc(typeseq::sentinel(), z1); REQUIRE(m1); REQUIRE(arena.last_error().error_ == error::ok); @@ -195,7 +195,7 @@ namespace xo { REQUIRE(arena.allocated() == 0); size_t z0 = 1; - byte * m0 = arena.alloc(typeseq::anon(), 1); + byte * m0 = arena.alloc(typeseq::sentinel(), 1); REQUIRE(m0); diff --git a/xo-arena/utest/DArenaHashMap.test.cpp b/xo-arena/utest/DArenaHashMap.test.cpp index bc672c8b..02ac3fc3 100644 --- a/xo-arena/utest/DArenaHashMap.test.cpp +++ b/xo-arena/utest/DArenaHashMap.test.cpp @@ -24,7 +24,7 @@ namespace xo { { using HashMap = DArenaHashMap; - HashMap map; + HashMap map("utest"); REQUIRE(map.empty()); REQUIRE(map.size() == 0); @@ -36,7 +36,7 @@ namespace xo { { using HashMap = DArenaHashMap; - HashMap map(257); + HashMap map("utest", 257); REQUIRE(map.empty()); REQUIRE(map.size() == 0); @@ -49,7 +49,7 @@ namespace xo { { using HashMap = DArenaHashMap; - HashMap map; + HashMap map("utest"); REQUIRE(map.empty()); REQUIRE(map.size() == 0); @@ -209,7 +209,7 @@ namespace xo { */ for (std::uint32_t n = 0; n <= 8; ) { - HashMap hash_map; + HashMap hash_map("utest"); auto test_fn = [&rgen, &hash_map](bool dbg_flag, std::uint32_t n) @@ -245,7 +245,7 @@ namespace xo { using HashMap = DArenaHashMap; - HashMap map; + HashMap map("utest"); // copy keys here so we can print stuff std::vector key_v; @@ -336,7 +336,7 @@ namespace xo { { using HashMap = DArenaHashMap; - HashMap map(1024); + HashMap map("utest", 1024); REQUIRE(map.verify_ok()); diff --git a/xo-cmake/cmake/xo_macros/xo_cxx.cmake b/xo-cmake/cmake/xo_macros/xo_cxx.cmake index c071f061..38d01df3 100644 --- a/xo-cmake/cmake/xo_macros/xo_cxx.cmake +++ b/xo-cmake/cmake/xo_macros/xo_cxx.cmake @@ -670,7 +670,7 @@ macro(xo_toplevel_compile_options) ) if(NOT DEFINED CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_STANDARD 23) endif() if(NOT DEFINED CMAKE_CXX_STANDARD_REQUIRED) set(CMAKE_CXX_STANDARD_REQUIRED True) @@ -1677,9 +1677,6 @@ function(xo_add_genfacet) TARGET # Name for this generation target FACET # facet name INPUT # Input .json5 file - OUTPUT_HPP_DIR # Directory for .hpp files - OUTPUT_IMPL_SUBDIR # Subdirectory name for impl headers - OUTPUT_CPP_DIR # Directory for .cpp files ) set(multiValueArgs "") @@ -1693,40 +1690,18 @@ function(xo_add_genfacet) if(NOT DEFINED GF_FACET) message(FATAL_ERROR "xo_add_genfacet: FACET is required") endif() - if(NOT DEFINED GF_OUTPUT_HPP_DIR) - message(FATAL_ERROR "xo_add_genfacet: OUTPUT_HPP_DIR is required") - endif() - if(NOT DEFINED GF_OUTPUT_IMPL_SUBDIR) - message(FATAL_ERROR "xo_add_genfacet: OUTPUT_IMPL_SUBDIR is required") - endif() - if(NOT DEFINED GF_OUTPUT_CPP_DIR) - message(FATAL_ERROR "xo_add_genfacet: OUTPUT_CPP_DIR is required") - endif() - find_program(GENFACET_EXECUTABLE NAMES genfacet HINTS ${CMAKE_SOURCE_DIR}/xo-facet/codegen DOC "path to xo genfacet code generator" REQUIRED) message(STATUS "GENFACET_EXECUTABLE=${GENFACET_EXECUTABLE}") - set(generatedFiles - ${GF_OUTPUT_HPP_DIR}/${GF_FACET}.hpp - ${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/A${GF_FACET}.hpp - ${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/I${GF_FACET}_Any.hpp - ${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/I${GF_FACET}_Xfer.hpp - ${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/R${GF_FACET}.hpp - ${GF_OUTPUT_CPP_DIR}/I${GF_FACET}_Any.cpp) - #message(STATUS "generatedFiles=${generatedFiles}") # Build the genfacet command add_custom_command( - OUTPUT ${generatedFiles} - COMMAND ${GENFACET_EXECUTABLE} - --input ${GF_INPUT} - --output-hpp ${GF_OUTPUT_HPP_DIR} - --output-impl-hpp ${GF_OUTPUT_IMPL_SUBDIR} - --output-cpp ${GF_OUTPUT_CPP_DIR} + OUTPUT ${GF_INPUT}.out + COMMAND ${GENFACET_EXECUTABLE} --input ${GF_INPUT} DEPENDS ${GF_INPUT} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating facet source files from ${GF_INPUT}" @@ -1734,7 +1709,9 @@ function(xo_add_genfacet) ) # Create a target for this generation - add_custom_target(${GF_TARGET} DEPENDS ${generatedFiles}) + add_custom_target(${GF_TARGET} DEPENDS ${GF_INPUT}.out) + + set_property(DIRECTORY APPEND PROPERTY XO_GENFACET_TARGETS ${GF_TARGET}) endfunction() function(xo_add_genfacetimpl) @@ -1767,16 +1744,6 @@ function(xo_add_genfacetimpl) if(NOT DEFINED GF_INPUT) message(FATAL_ERROR "xo_add_genfacetimpl: INPUT is required") endif() - if(NOT DEFINED GF_OUTPUT_HPP_DIR) - message(FATAL_ERROR "xo_add_genfacetimpl: OUTPUT_HPP_DIR is required") - endif() - if(NOT DEFINED GF_OUTPUT_IMPL_SUBDIR) - message(FATAL_ERROR "xo_add_genfacetimpl: OUTPUT_IMPL_SUBDIR is required") - endif() - if(NOT DEFINED GF_OUTPUT_CPP_DIR) - message(FATAL_ERROR "xo_add_genfacetimpl: OUTPUT_CPP_DIR is required") - endif() - if(NOT DEFINED GF_FACET_DIR) if (NOT DEFINED GF_FACET_PKG) message(FATAL_ERROR "xo_add_genfacetimpl: FACET_PKG or FACET_DIR required") @@ -1792,21 +1759,12 @@ function(xo_add_genfacetimpl) REQUIRED) message(STATUS "GENFACET_EXECUTABLE=${GENFACET_EXECUTABLE}") - set(generatedFiles - ${GF_OUTPUT_HPP_DIR}/${GF_OUTPUT_IMPL_SUBDIR}/I${GF_FACET}_D${GF_REPR}.hpp - ${GF_OUTPUT_CPP_DIR}/I${GF_FACET}_D${GF_REPR}.cpp) - # Build the genfacet command. # But careful: can't have the same generated files in two different rules, # so need to remove overlaps here add_custom_command( - OUTPUT ${generatedFiles} - COMMAND ${GENFACET_EXECUTABLE} - --input ${GF_INPUT} - --facet-dir ${GF_FACET_DIR} - --output-hpp ${GF_OUTPUT_HPP_DIR} - --output-impl-hpp ${GF_OUTPUT_IMPL_SUBDIR} - --output-cpp ${GF_OUTPUT_CPP_DIR} + OUTPUT ${GF_INPUT}.out + COMMAND ${GENFACET_EXECUTABLE} --input ${GF_INPUT} --facet-dir ${GF_FACET_DIR} DEPENDS ${GF_INPUT} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating facet source files from ${GF_INPUT}" @@ -1814,5 +1772,17 @@ function(xo_add_genfacetimpl) ) # Create a target for this generation - add_custom_target(${GF_TARGET} DEPENDS ${generatedFiles}) + add_custom_target(${GF_TARGET} DEPENDS ${GF_INPUT}.out) + + set_property(DIRECTORY APPEND PROPERTY XO_GENFACET_TARGETS ${GF_TARGET}) +endfunction() + +# create umbrella target for all genfacet targets in current directory +function(xo_add_genfacet_all target_name) + get_property(genfacet_targets DIRECTORY PROPERTY XO_GENFACET_TARGETS) + if(genfacet_targets) + add_custom_target(${target_name} DEPENDS ${genfacet_targets}) + else() + message(WARNING "xo_add_genfacet_all: no genfacet targets found") + endif() endfunction() diff --git a/xo-cmake/share/xo-macros/xo-reconfigure.in b/xo-cmake/share/xo-macros/xo-reconfigure.in index 3d8118bb..41d641c6 100644 --- a/xo-cmake/share/xo-macros/xo-reconfigure.in +++ b/xo-cmake/share/xo-macros/xo-reconfigure.in @@ -3,6 +3,7 @@ # Generated by cmake - rerun to reconfigure dry_run_flag=false +testing=@ENABLE_TESTING@ # Parse arguments while [[ $# -gt 0 ]]; do @@ -10,6 +11,12 @@ while [[ $# -gt 0 ]]; do -n|--dry-run) dry_run_flag=true ;; + --enable-testing) + testing=1 + ;; + --disable-testing) + testing=0 + ;; --) break; ;; @@ -35,7 +42,7 @@ CMAKE_CMD=( -DCMAKE_PREFIX_PATH=@CMAKE_PREFIX_PATH@ -DCMAKE_CXX_STANDARD=@CMAKE_CXX_STANDARD@ -DXO_CMAKE_CONFIG_EXECUTABLE=@XO_CMAKE_CONFIG_EXECUTABLE@ - -DENABLE_TESTING=@ENABLE_TESTING@ + -DENABLE_TESTING=$testing -DXO_ENABLE_DOCS=@XO_ENABLE_DOCS@ -DXO_ENABLE_ASM=@XO_ENABLE_ASM@ -DXO_ENABLE_EXAMPLES=@XO_ENABLE_EXAMPLES@ diff --git a/xo-expression2/CMakeLists.txt b/xo-expression2/CMakeLists.txt index 28982fba..c9180ad8 100644 --- a/xo-expression2/CMakeLists.txt +++ b/xo-expression2/CMakeLists.txt @@ -29,9 +29,80 @@ xo_add_genfacet( INPUT idl/SymbolTable.json5 OUTPUT_HPP_DIR include/xo/expression2 OUTPUT_IMPL_SUBDIR detail - OUTPUT_CPP_DIR src/expression2 ) +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-symboltable-localsymtab + FACET_PKG xo_expression2 + FACET SymbolTable + REPR LocalSymtab + INPUT idl/ISymbolTable_DLocalSymtab.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR symtab +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-gcobject-localsymtab + FACET_PKG xo_gc + FACET GCObject + REPR LocalSymtab + INPUT idl/IGCObject_DLocalSymtab.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR symtab +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-printable-localsymtab + FACET_PKG xo_printable2 + FACET Printable + REPR LocalSymtab + INPUT idl/IPrintable_DLocalSymtab.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR symtab +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-symboltable-globalsymtab + FACET_PKG xo_expression2 + FACET SymbolTable + REPR GlobalSymtab + INPUT idl/ISymbolTable_DGlobalSymtab.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR symtab +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-gcobject-globalsymtab + FACET_PKG xo_gc + FACET GCObject + REPR GlobalSymtab + INPUT idl/IGCObject_DGlobalSymtab.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR symtab +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-printable-globalsymtab + FACET_PKG xo_printable2 + FACET Printable + REPR GlobalSymtab + INPUT idl/IPrintable_DGlobalSymtab.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR symtab +) + +# ---------------------------------------------------------------- + # note: manual target; generated code committed to git xo_add_genfacet( TARGET xo-expression2-facet-expression @@ -39,9 +110,10 @@ xo_add_genfacet( INPUT idl/Expression.json5 OUTPUT_HPP_DIR include/xo/expression2 OUTPUT_IMPL_SUBDIR detail - OUTPUT_CPP_DIR src/expression2 ) +# ---------------------------------------------------------------- + # note: manual target; generated code committed to git xo_add_genfacetimpl( TARGET xo-expression2-facetimpl-expression-constant @@ -51,9 +123,32 @@ xo_add_genfacetimpl( INPUT idl/IExpression_DConstant.json5 OUTPUT_HPP_DIR include/xo/expression2 OUTPUT_IMPL_SUBDIR detail - OUTPUT_CPP_DIR src/expression2 ) +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-gcobject-constant + FACET_PKG xo_gc + FACET GCObject + REPR Constant + INPUT idl/IGCObject_DConstant.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-printable-constant + FACET_PKG xo_printable2 + FACET Printable + REPR Constant + INPUT idl/IPrintable_DConstant.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# ---------------------------------------------------------------- + # note: manual target; generated code committed to git xo_add_genfacetimpl( TARGET xo-expression2-facetimpl-expression-variable @@ -63,9 +158,242 @@ xo_add_genfacetimpl( INPUT idl/IExpression_DVariable.json5 OUTPUT_HPP_DIR include/xo/expression2 OUTPUT_IMPL_SUBDIR detail - OUTPUT_CPP_DIR src/expression2 ) +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-gcobject-variable + FACET_PKG xo_gc + FACET GCObject + REPR Variable + INPUT idl/IGCObject_DVariable.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-printable-variable + FACET_PKG xo_printable2 + FACET Printable + REPR Variable + INPUT idl/IPrintable_DVariable.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-expression-varref + FACET_PKG xo_expression2 + FACET Expression + REPR VarRef + INPUT idl/IExpression_DVarRef.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-gcobject-varref + FACET_PKG xo_gc + FACET GCObject + REPR VarRef + INPUT idl/IGCObject_DVarRef.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-printable-varref + FACET_PKG xo_printable2 + FACET Printable + REPR VarRef + INPUT idl/IPrintable_DVarRef.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-expression-defineexpr + FACET_PKG xo_expression2 + FACET Expression + REPR DefineExpr + INPUT idl/IExpression_DDefineExpr.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-gcobject-defineexpr + FACET_PKG xo_gc + FACET GCObject + REPR DefineExpr + INPUT idl/IGCObject_DDefineExpr.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR define +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-printable-defineexpr + FACET_PKG xo_printable2 + FACET Printable + REPR DefineExpr + INPUT idl/IPrintable_DDefineExpr.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-expression-applyexpr + FACET_PKG xo_expression2 + FACET Expression + REPR ApplyExpr + INPUT idl/IExpression_DApplyExpr.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-gcobject-applyexpr + FACET_PKG xo_gc + FACET GCObject + REPR ApplyExpr + INPUT idl/IGCObject_DApplyExpr.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-printable-applyexpr + FACET_PKG xo_printable2 + FACET Printable + REPR ApplyExpr + INPUT idl/IPrintable_DApplyExpr.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-expression-lambdaexpr + FACET_PKG xo_expression2 + FACET Expression + REPR LambdaExpr + INPUT idl/IExpression_DLambdaExpr.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-gcobject-lambdaexpr + FACET_PKG xo_gc + FACET GCObject + REPR LambdaExpr + INPUT idl/IGCObject_DLambdaExpr.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-printable-lambdaexpr + FACET_PKG xo_printable2 + FACET Printable + REPR LambdaExpr + INPUT idl/IPrintable_DLambdaExpr.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-expression-ifelseexpr + FACET_PKG xo_expression2 + FACET Expression + REPR IfElseExpr + INPUT idl/IExpression_DIfElseExpr.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-gcobject-ifelseexpr + FACET_PKG xo_gc + FACET GCObject + REPR IfElseExpr + INPUT idl/IGCObject_DIfElseExpr.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-printable-ifelseexpr + FACET_PKG xo_printable2 + FACET Printable + REPR IfElseExpr + INPUT idl/IPrintable_DIfElseExpr.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-expression-sequenceexpr + FACET_PKG xo_expression2 + FACET Expression + REPR SequenceExpr + INPUT idl/IExpression_DSequenceExpr.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-gcobject-sequenceexpr + FACET_PKG xo_gc + FACET GCObject + REPR SequenceExpr + INPUT idl/IGCObject_DSequenceExpr.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-expression2-facetimpl-printable-sequenceexpr + FACET_PKG xo_printable2 + FACET Printable + REPR SequenceExpr + INPUT idl/IPrintable_DSequenceExpr.json5 + OUTPUT_HPP_DIR include/xo/expression2 + OUTPUT_IMPL_SUBDIR detail +) + +# ---------------------------------------------------------------- + # note: manual target; generated code committed to git xo_add_genfacetimpl( TARGET xo-expression2-facetimpl-gcobject-uniquestring @@ -75,7 +403,6 @@ xo_add_genfacetimpl( INPUT idl/IGCObject_DUniqueString.json5 OUTPUT_HPP_DIR include/xo/expression2 OUTPUT_IMPL_SUBDIR detail - OUTPUT_CPP_DIR src/expression2 ) # note: manual target; generated code committed to git @@ -83,26 +410,24 @@ xo_add_genfacetimpl( TARGET xo-expression2-facetimpl-printable-uniquestring FACET_PKG xo_printable2 FACET Printable - REPR DUniqueString + REPR UniqueString INPUT idl/IPrintable_DUniqueString.json5 OUTPUT_HPP_DIR include/xo/expression2 OUTPUT_IMPL_SUBDIR detail - OUTPUT_CPP_DIR src/expression2 ) # ---------------------------------------------------------------- -# header-only library + +xo_add_genfacet_all(xo-expression2-genfacet-all) + +# ---------------------------------------------------------------- +# shared library add_subdirectory(src/expression2) +# ---------------------------------------------------------------- +# cmake helper (for external xo-expression2 users) + xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets) -# ---------------------------------------------------------------- -# input dependencies -# -# NOTE: dependency set here must be kept consistent with -# xo-expression2/cmake/xo_expression2Config.cmake.in - -#xo_headeronly_dependency(${SELF_LIB} xo_flatstring) - # end CMakeLists.txt diff --git a/xo-expression2/cmake/xo_expression2Config.cmake.in b/xo-expression2/cmake/xo_expression2Config.cmake.in index c8cfbcad..15ff18ff 100644 --- a/xo-expression2/cmake/xo_expression2Config.cmake.in +++ b/xo-expression2/cmake/xo_expression2Config.cmake.in @@ -8,7 +8,7 @@ include(CMakeFindDependencyMacro) # find_dependency(xo_gc) find_dependency(reflect) -find_dependency(xo_object2) +find_dependency(xo_procedure2) find_dependency(xo_printable2) find_dependency(xo_flatstring) find_dependency(cmake) diff --git a/xo-expression2/idl/Expression.json5 b/xo-expression2/idl/Expression.json5 index f2f7d44a..66c60def 100644 --- a/xo-expression2/idl/Expression.json5 +++ b/xo-expression2/idl/Expression.json5 @@ -1,5 +1,8 @@ { mode: "facet", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", includes: [ "\"TypeRef.hpp\"", "\"exprtype.hpp\"", ""], @@ -67,4 +70,5 @@ attributes: [], } ], + router_facet_explicit_content: [ ], } diff --git a/xo-expression2/idl/IExpression_DApplyExpr.json5 b/xo-expression2/idl/IExpression_DApplyExpr.json5 new file mode 100644 index 00000000..29762364 --- /dev/null +++ b/xo-expression2/idl/IExpression_DApplyExpr.json5 @@ -0,0 +1,15 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ "\"Expression.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Expression.json5", + brief: "provide AExpression interface for DApplyExpr state", + using_doxygen: true, + repr: "DApplyExpr", + doc: ["doc for IExpression+DApplyExpr" ], +} diff --git a/xo-expression2/idl/IExpression_DConstant.json5 b/xo-expression2/idl/IExpression_DConstant.json5 index d7628f81..bbbcc402 100644 --- a/xo-expression2/idl/IExpression_DConstant.json5 +++ b/xo-expression2/idl/IExpression_DConstant.json5 @@ -1,5 +1,8 @@ { mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", includes: [ "\"Expression.hpp\"" ], local_types: [ ], namespace1: "xo", diff --git a/xo-expression2/idl/IExpression_DDefineExpr.json5 b/xo-expression2/idl/IExpression_DDefineExpr.json5 new file mode 100644 index 00000000..8fd6149f --- /dev/null +++ b/xo-expression2/idl/IExpression_DDefineExpr.json5 @@ -0,0 +1,15 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ "\"Expression.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Expression.json5", + brief: "provide AExpression interface for DDefineExpr state", + using_doxygen: true, + repr: "DDefineExpr", + doc: ["doc for IExpression+DDefineExpr" ], +} diff --git a/xo-expression2/idl/IExpression_DIfElseExpr.json5 b/xo-expression2/idl/IExpression_DIfElseExpr.json5 new file mode 100644 index 00000000..431fd60a --- /dev/null +++ b/xo-expression2/idl/IExpression_DIfElseExpr.json5 @@ -0,0 +1,15 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ "\"Expression.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Expression.json5", + brief: "provide AExpression interface for DIfElseExpr state", + using_doxygen: true, + repr: "DIfElseExpr", + doc: ["doc for IExpression+DIfElseExpr" ], +} diff --git a/xo-expression2/idl/IExpression_DLambdaExpr.json5 b/xo-expression2/idl/IExpression_DLambdaExpr.json5 new file mode 100644 index 00000000..36aa9bb4 --- /dev/null +++ b/xo-expression2/idl/IExpression_DLambdaExpr.json5 @@ -0,0 +1,15 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ "\"Expression.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Expression.json5", + brief: "provide AExpression interface for DLambdaExpr state", + using_doxygen: true, + repr: "DLambdaExpr", + doc: ["doc for IExpression+DLambdaExpr" ], +} diff --git a/xo-expression2/idl/IExpression_DSequenceExpr.json5 b/xo-expression2/idl/IExpression_DSequenceExpr.json5 new file mode 100644 index 00000000..71b13aba --- /dev/null +++ b/xo-expression2/idl/IExpression_DSequenceExpr.json5 @@ -0,0 +1,15 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ "\"Expression.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Expression.json5", + brief: "provide AExpression interface for DSequenceExpr state", + using_doxygen: true, + repr: "DSequenceExpr", + doc: ["doc for something or other IExpression+DSequenceExpr" ], +} diff --git a/xo-expression2/idl/IExpression_DVarRef.json5 b/xo-expression2/idl/IExpression_DVarRef.json5 new file mode 100644 index 00000000..7b50c7fb --- /dev/null +++ b/xo-expression2/idl/IExpression_DVarRef.json5 @@ -0,0 +1,15 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ "\"Expression.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Expression.json5", + brief: "provide AExpression interface for DVarRef state", + using_doxygen: true, + repr: "DVarRef", + doc: ["doc for IExpression+DVarRef" ], +} diff --git a/xo-expression2/idl/IExpression_DVariable.json5 b/xo-expression2/idl/IExpression_DVariable.json5 index 6e7993d3..c68a9609 100644 --- a/xo-expression2/idl/IExpression_DVariable.json5 +++ b/xo-expression2/idl/IExpression_DVariable.json5 @@ -1,5 +1,8 @@ { mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", includes: [ "\"Expression.hpp\"" ], local_types: [ ], namespace1: "xo", diff --git a/xo-expression2/idl/IGCObject_DApplyExpr.json5 b/xo-expression2/idl/IGCObject_DApplyExpr.json5 new file mode 100644 index 00000000..60f997c8 --- /dev/null +++ b/xo-expression2/idl/IGCObject_DApplyExpr.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DApplyExpr", + using_doxygen: true, + repr: "DApplyExpr", + doc: [ "implement AGCObject for DApplyExpr" ], +} diff --git a/xo-expression2/idl/IGCObject_DConstant.json5 b/xo-expression2/idl/IGCObject_DConstant.json5 new file mode 100644 index 00000000..961f39bb --- /dev/null +++ b/xo-expression2/idl/IGCObject_DConstant.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DConstant", + using_doxygen: true, + repr: "DConstant", + doc: [ "implement AGCObject for DConstant" ], +} diff --git a/xo-expression2/idl/IGCObject_DDefineExpr.json5 b/xo-expression2/idl/IGCObject_DDefineExpr.json5 new file mode 100644 index 00000000..6b0eba68 --- /dev/null +++ b/xo-expression2/idl/IGCObject_DDefineExpr.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "define", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DDefineExpr", + using_doxygen: true, + repr: "DDefineExpr", + doc: [ "implement AGCObject for DDefineExpr" ], +} diff --git a/xo-expression2/idl/IGCObject_DGlobalSymtab.json5 b/xo-expression2/idl/IGCObject_DGlobalSymtab.json5 new file mode 100644 index 00000000..ac779ec2 --- /dev/null +++ b/xo-expression2/idl/IGCObject_DGlobalSymtab.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "symtab", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DGlobalSymtab", + using_doxygen: true, + repr: "DGlobalSymtab", + doc: [ "implement AGCObject for DGlobalSymtab" ], +} diff --git a/xo-expression2/idl/IGCObject_DIfElseExpr.json5 b/xo-expression2/idl/IGCObject_DIfElseExpr.json5 new file mode 100644 index 00000000..6fb8c07a --- /dev/null +++ b/xo-expression2/idl/IGCObject_DIfElseExpr.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DIfElseExpr", + using_doxygen: true, + repr: "DIfElseExpr", + doc: [ "implement AGCObject for DIfElseExpr" ], +} diff --git a/xo-expression2/idl/IGCObject_DLambdaExpr.json5 b/xo-expression2/idl/IGCObject_DLambdaExpr.json5 new file mode 100644 index 00000000..a0f494ff --- /dev/null +++ b/xo-expression2/idl/IGCObject_DLambdaExpr.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DLambdaExpr", + using_doxygen: true, + repr: "DLambdaExpr", + doc: [ "implement AGCObject for DLambdaExpr" ], +} diff --git a/xo-expression2/idl/IGCObject_DLocalSymtab.json5 b/xo-expression2/idl/IGCObject_DLocalSymtab.json5 new file mode 100644 index 00000000..ec8260a0 --- /dev/null +++ b/xo-expression2/idl/IGCObject_DLocalSymtab.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "symtab", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DLocalSymtab", + using_doxygen: true, + repr: "DLocalSymtab", + doc: [ "implement AGCObject for DLocalSymtab" ], +} diff --git a/xo-expression2/idl/IGCObject_DSequenceExpr.json5 b/xo-expression2/idl/IGCObject_DSequenceExpr.json5 new file mode 100644 index 00000000..1fc67e48 --- /dev/null +++ b/xo-expression2/idl/IGCObject_DSequenceExpr.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DSequenceExpr", + using_doxygen: true, + repr: "DSequenceExpr", + doc: [ "implement AGCObject for DSequenceExpr" ], +} diff --git a/xo-expression2/idl/IGCObject_DUniqueString.json5 b/xo-expression2/idl/IGCObject_DUniqueString.json5 index 8cf516b2..4f79e9de 100644 --- a/xo-expression2/idl/IGCObject_DUniqueString.json5 +++ b/xo-expression2/idl/IGCObject_DUniqueString.json5 @@ -1,5 +1,8 @@ { mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", includes: [ "", "" diff --git a/xo-expression2/idl/IGCObject_DVarRef.json5 b/xo-expression2/idl/IGCObject_DVarRef.json5 new file mode 100644 index 00000000..6c1bad33 --- /dev/null +++ b/xo-expression2/idl/IGCObject_DVarRef.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DVarRef", + using_doxygen: true, + repr: "DVarRef", + doc: [ "implement AGCObject for DVarRef" ], +} diff --git a/xo-expression2/idl/IGCObject_DVariable.json5 b/xo-expression2/idl/IGCObject_DVariable.json5 new file mode 100644 index 00000000..6bea1dc3 --- /dev/null +++ b/xo-expression2/idl/IGCObject_DVariable.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DVariable", + using_doxygen: true, + repr: "DVariable", + doc: [ "implement AGCObject for DVariable" ], +} diff --git a/xo-expression2/idl/IPrintable_DApplyExpr.json5 b/xo-expression2/idl/IPrintable_DApplyExpr.json5 new file mode 100644 index 00000000..f9d3f17d --- /dev/null +++ b/xo-expression2/idl/IPrintable_DApplyExpr.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DApplyExpr", + using_doxygen: true, + repr: "DApplyExpr", + doc: [ "implement APrintable for DApplyExpr" ], +} diff --git a/xo-expression2/idl/IPrintable_DConstant.json5 b/xo-expression2/idl/IPrintable_DConstant.json5 new file mode 100644 index 00000000..ca9d7948 --- /dev/null +++ b/xo-expression2/idl/IPrintable_DConstant.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DConstant", + using_doxygen: true, + repr: "DConstant", + doc: [ "implement APrintable for DConstant" ], +} diff --git a/xo-expression2/idl/IPrintable_DDefineExpr.json5 b/xo-expression2/idl/IPrintable_DDefineExpr.json5 new file mode 100644 index 00000000..c706817d --- /dev/null +++ b/xo-expression2/idl/IPrintable_DDefineExpr.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DDefineExpr", + using_doxygen: true, + repr: "DDefineExpr", + doc: [ "implement APrintable for DDefineExpr" ], +} diff --git a/xo-expression2/idl/IPrintable_DGlobalSymtab.json5 b/xo-expression2/idl/IPrintable_DGlobalSymtab.json5 new file mode 100644 index 00000000..d0242e8c --- /dev/null +++ b/xo-expression2/idl/IPrintable_DGlobalSymtab.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "symtab", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DGlobalSymtab", + using_doxygen: true, + repr: "DGlobalSymtab", + doc: [ "implement APrintable for DGlobalSymtab" ], +} diff --git a/xo-expression2/idl/IPrintable_DIfElseExpr.json5 b/xo-expression2/idl/IPrintable_DIfElseExpr.json5 new file mode 100644 index 00000000..208e7b06 --- /dev/null +++ b/xo-expression2/idl/IPrintable_DIfElseExpr.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DIfElseExpr", + using_doxygen: true, + repr: "DIfElseExpr", + doc: [ "implement APrintable for DIfElseExpr" ], +} diff --git a/xo-expression2/idl/IPrintable_DLambdaExpr.json5 b/xo-expression2/idl/IPrintable_DLambdaExpr.json5 new file mode 100644 index 00000000..89b07d1c --- /dev/null +++ b/xo-expression2/idl/IPrintable_DLambdaExpr.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DLambdaExpr", + using_doxygen: true, + repr: "DLambdaExpr", + doc: [ "implement APrintable for DLambdaExpr" ], +} diff --git a/xo-expression2/idl/IPrintable_DLocalSymtab.json5 b/xo-expression2/idl/IPrintable_DLocalSymtab.json5 new file mode 100644 index 00000000..15087c3d --- /dev/null +++ b/xo-expression2/idl/IPrintable_DLocalSymtab.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "symtab", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DLocalSymtab", + using_doxygen: true, + repr: "DLocalSymtab", + doc: [ "implement APrintable for DLocalSymtab" ], +} diff --git a/xo-expression2/idl/IPrintable_DSequenceExpr.json5 b/xo-expression2/idl/IPrintable_DSequenceExpr.json5 new file mode 100644 index 00000000..0cfe76c9 --- /dev/null +++ b/xo-expression2/idl/IPrintable_DSequenceExpr.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DSequenceExpr", + using_doxygen: true, + repr: "DSequenceExpr", + doc: [ "implement APrintable for DSequenceExpr" ], +} diff --git a/xo-expression2/idl/IPrintable_DUniqueString.json5 b/xo-expression2/idl/IPrintable_DUniqueString.json5 index 540f7b71..ba094879 100644 --- a/xo-expression2/idl/IPrintable_DUniqueString.json5 +++ b/xo-expression2/idl/IPrintable_DUniqueString.json5 @@ -1,5 +1,8 @@ { mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", includes: [ "", "" ], local_types: [ ], diff --git a/xo-expression2/idl/IPrintable_DVarRef.json5 b/xo-expression2/idl/IPrintable_DVarRef.json5 new file mode 100644 index 00000000..106b41d1 --- /dev/null +++ b/xo-expression2/idl/IPrintable_DVarRef.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DVarRef", + using_doxygen: true, + repr: "DVarRef", + doc: [ "implement APrintable for DVarRef" ], +} diff --git a/xo-expression2/idl/IPrintable_DVariable.json5 b/xo-expression2/idl/IPrintable_DVariable.json5 new file mode 100644 index 00000000..779afd25 --- /dev/null +++ b/xo-expression2/idl/IPrintable_DVariable.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "detail", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DVariable", + using_doxygen: true, + repr: "DVariable", + doc: [ "implement APrintable for DVariable" ], +} diff --git a/xo-expression2/idl/ISymbolTable_DGlobalSymtab.json5 b/xo-expression2/idl/ISymbolTable_DGlobalSymtab.json5 new file mode 100644 index 00000000..ff148a2f --- /dev/null +++ b/xo-expression2/idl/ISymbolTable_DGlobalSymtab.json5 @@ -0,0 +1,15 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "symtab", + includes: [ ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SymbolTable.json5", + brief: "provide ASymbolTable interface for DGlobalSymtab", + using_doxygen: true, + repr: "DGlobalSymtab", + doc: [ "implement ASymbolTable for DGlobalSymtab" ], +} diff --git a/xo-expression2/idl/ISymbolTable_DLocalSymtab.json5 b/xo-expression2/idl/ISymbolTable_DLocalSymtab.json5 new file mode 100644 index 00000000..7cfcd75f --- /dev/null +++ b/xo-expression2/idl/ISymbolTable_DLocalSymtab.json5 @@ -0,0 +1,15 @@ +{ + mode: "implementation", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "symtab", + includes: [ ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SymbolTable.json5", + brief: "provide ASymbolTable interface for DLocalSymtab", + using_doxygen: true, + repr: "DLocalSymtab", + doc: [ "implement ASymbolTable for DLocalSymtab" ], +} diff --git a/xo-expression2/idl/SymbolTable.json5 b/xo-expression2/idl/SymbolTable.json5 index 3d91a3d7..b299bfe7 100644 --- a/xo-expression2/idl/SymbolTable.json5 +++ b/xo-expression2/idl/SymbolTable.json5 @@ -1,5 +1,8 @@ { mode: "facet", + output_cpp_dir: "src/expression2", + output_hpp_dir: "include/xo/expression2", + output_impl_subdir: "symtab", includes: [ "\"Binding.hpp\"", "\"DUniqueString.hpp\"" @@ -56,4 +59,5 @@ // // Variable gives both {name, type} // void upsert_local(DVariable * target) = 0; ], + router_facet_explicit_content: [ ], } diff --git a/xo-expression2/include/xo/expression2/ApplyExpr.hpp b/xo-expression2/include/xo/expression2/ApplyExpr.hpp new file mode 100644 index 00000000..38625855 --- /dev/null +++ b/xo-expression2/include/xo/expression2/ApplyExpr.hpp @@ -0,0 +1,13 @@ +/** @file ApplyExpr.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DApplyExpr.hpp" +#include "detail/IExpression_DApplyExpr.hpp" +#include "detail/IGCObject_DApplyExpr.hpp" +#include "detail/IPrintable_DApplyExpr.hpp" + +/* end ApplyExpr.hpp */ diff --git a/xo-expression2/include/xo/expression2/Binding.hpp b/xo-expression2/include/xo/expression2/Binding.hpp index 455c1538..805ebeb9 100644 --- a/xo-expression2/include/xo/expression2/Binding.hpp +++ b/xo-expression2/include/xo/expression2/Binding.hpp @@ -5,41 +5,60 @@ #pragma once +#include #include namespace xo { namespace scm { class Binding { public: - static constexpr int32_t s_link_sentinel = -2; - static constexpr int32_t s_link_global = -1; + using slot_type = int32_t; + + static constexpr int32_t c_link_sentinel = -2; + static constexpr int32_t c_link_global = -1; public: + Binding() : i_link_{-2}, j_slot_{-1} {} Binding(int32_t i_link, int32_t j_slot) : i_link_{i_link}, j_slot_{j_slot} {} + static Binding null() { return Binding(); } /** global bindings are located by symbol name **/ - static Binding global() { return Binding(s_link_global, 0); } + static Binding global(int32_t j_slot) { return Binding(c_link_global, j_slot); } static Binding local(int32_t j_slot) { return Binding(0, j_slot); } + static Binding relative(int32_t i_link, Binding def); - bool is_global() const { return i_link_ == s_link_global; } + bool is_null() const { + return (i_link_ == c_link_sentinel) && (j_slot_ == -1); + } + bool is_global() const { return i_link_ == c_link_global; } + bool is_local() const { return (i_link_ == 0) && (j_slot_ >= 0); } int32_t i_link() const noexcept { return i_link_; } int32_t j_slot() const noexcept { return j_slot_; } + /** print human-readable repr to stream @p os **/ + void print(std::ostream & os) const; + private: /** * >= 0: number of parent links to traverse * to a fixed-size frame * -1: resolve globally + * -2: sentinel (binding info not computed) **/ - int32_t i_link_ = s_link_sentinel; + int32_t i_link_ = c_link_sentinel; /** if @ref i_link_ >= 0, frame offset * (in 'variables' not bytes). * ignored if @ref i_link_ is global **/ int32_t j_slot_ = -1; }; + + inline std::ostream & operator<< (std::ostream & os, Binding x) { + x.print(os); + return os; + } } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-expression2/include/xo/expression2/Constant.hpp b/xo-expression2/include/xo/expression2/Constant.hpp new file mode 100644 index 00000000..29e6694f --- /dev/null +++ b/xo-expression2/include/xo/expression2/Constant.hpp @@ -0,0 +1,13 @@ +/** @file Constant.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DConstant.hpp" +#include "detail/IExpression_DConstant.hpp" +#include "detail/IGCObject_DConstant.hpp" +#include "detail/IPrintable_DConstant.hpp" + +/* end Constant.hpp */ diff --git a/xo-expression2/include/xo/expression2/DApplyExpr.hpp b/xo-expression2/include/xo/expression2/DApplyExpr.hpp new file mode 100644 index 00000000..94bcea73 --- /dev/null +++ b/xo-expression2/include/xo/expression2/DApplyExpr.hpp @@ -0,0 +1,112 @@ +/** @file DApplyExpr.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "Expression.hpp" +#include "TypeRef.hpp" +#include "exprtype.hpp" +#include +#include +#include + +namespace xo { + namespace scm { + + /** @class DApplyExpr + * @brief syntax for a procedure/function call + **/ + class DApplyExpr { + public: + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using TypeDescr = xo::reflect::TypeDescr; + using ppindentinfo = xo::print::ppindentinfo; + using size_type = std::uint32_t; + + public: + /** @defgroup scm-applyexpr-constructors **/ + ///@{ + + /** construct empty instance, but with argument expressions empty **/ + DApplyExpr(TypeRef typeref, + obj fn_expr, + size_type n_args); + + /** create apply for function with 2 arguments **/ + static obj make2(obj mm, + TypeRef typeref, + obj fn_expr, + obj arg1, + obj arg2); + + /** create apply for function with 2 arguments **/ + static DApplyExpr * _make2(obj mm, + TypeRef typeref, + obj fn_expr, + obj arg1, + obj arg2); + + /** scaffold incomplete instance. + * apply-expr using memory from @p mm. + * will construct instance with space for @p n_args arguments + * but expressions left empty. + * use @ref assign_arg for all arguments to complete. + **/ + static DApplyExpr * scaffold(obj mm, + TypeRef typeref, + obj fn_expr, + size_type n_args); + void assign_arg(size_type i_arg, obj expr); + + ///@} + /** @defgroup scm-applyexpr-access-methods **/ + ///@{ + + obj fn() const noexcept { return fn_; } + size_type n_args() const noexcept { return n_args_; } + obj arg(size_type i) const; + + ///@} + /** @defgroup scm-applyexpr-expression-facet **/ + ///@{ + + exprtype extype() const noexcept { return exprtype::apply; } + TypeRef typeref() const noexcept { return typeref_; } + TypeDescr valuetype() const noexcept { return typeref_.td(); } + void assign_valuetype(TypeDescr td) noexcept; + + ///@} + /** @defgroup scm-applyexpr-gcobject-facet **/ + ///@{ + + std::size_t shallow_size() const noexcept; + DApplyExpr * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + ///@} + /** @defgroup scm-applyexpr-printable-facet **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + private: + /** expression value always has type consistent + * with this description + **/ + TypeRef typeref_; + /** expression for function/procedure to invoke **/ + obj fn_; + /** number of arguments (not counting @ref fn_ **/ + size_type n_args_ = 0; + /** args_[i] is expression for i'th argument to @ref fn_ **/ + obj args_[]; + }; + } +} + +/* end DApplyExpr.hpp */ diff --git a/xo-expression2/include/xo/expression2/DConstant.hpp b/xo-expression2/include/xo/expression2/DConstant.hpp index 9d2014b9..0c57f924 100644 --- a/xo-expression2/include/xo/expression2/DConstant.hpp +++ b/xo-expression2/include/xo/expression2/DConstant.hpp @@ -5,10 +5,12 @@ #pragma once +#include "Expression.hpp" #include "TypeRef.hpp" #include "exprtype.hpp" -#include +#include #include +#include namespace xo { namespace scm { @@ -19,24 +21,59 @@ namespace xo { public: using TaggedPtr = xo::reflect::TaggedPtr; using TypeDescr = xo::reflect::TypeDescr; + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; using AGCObject = xo::mm::AGCObject; using typeseq = xo::reflect::typeseq; + using ppindentinfo = xo::print::ppindentinfo; public: explicit DConstant(obj value) noexcept; + /** create isntance + * @p mm memory allocator + * @p value literal constant + **/ + static obj make(obj mm, + obj value); + + /** create instance + * @p mm memory allocator + * @p value literal constant + **/ + static DConstant * _make(obj mm, + obj value); + bool is_resolved() const noexcept { return typeref_.is_resolved(); } - exprtype extype() const noexcept { return exprtype::constant; } + obj value() const noexcept { return value_; } TypeDescr value_td() const noexcept { return typeref_.td(); } TaggedPtr value_tp() const noexcept { return TaggedPtr(typeref_.td(), value_.data()); } + /** @defgroup scm-constant-expression-facet **/ + ///@{ + + exprtype extype() const noexcept { return exprtype::constant; } TypeRef typeref() const noexcept { return typeref_; } TypeDescr valuetype() const noexcept { return typeref_.td(); } - obj value() const noexcept { return value_; } - void assign_valuetype(TypeDescr td) noexcept { typeref_.resolve(td); } + ///@} + /** @defgroup scm-constant-gcobject-facet **/ + ///@{ + + size_t shallow_size() const noexcept; + DConstant * shallow_copy(obj mm) const noexcept; + size_t forward_children(obj gc) noexcept; + + ///@} + /** @defgroup scm-constant-printable-facet **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + private: static TypeDescr _lookup_td(typeseq tseq); diff --git a/xo-expression2/include/xo/expression2/DDefineExpr.hpp b/xo-expression2/include/xo/expression2/DDefineExpr.hpp new file mode 100644 index 00000000..6ad8494f --- /dev/null +++ b/xo-expression2/include/xo/expression2/DDefineExpr.hpp @@ -0,0 +1,106 @@ +/** @file DDefineExpr.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "Expression.hpp" +#include "DVariable.hpp" +#include +#include + +namespace xo { + namespace scm { + class DUniqueString; // see DUniqueString.hpp + + /** @class DDefineExpr + * @brief an expression that introduces a variable. + * + * Variable may optionally be declared with a type, + * and may come with an expression specifying an initial value + **/ + class DDefineExpr { + public: + using ppindentinfo = xo::print::ppindentinfo; + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using TypeDescr = xo::reflect::TypeDescr; + + public: + /** @defgroup scm-defineexpr-constructors **/ + ///@{ + + /** create instance: define-expr using memory from @p mm + * with lhs name @p lhs_name and rhs expression @p rhs_expr + **/ + static DDefineExpr * make(obj mm, + const DUniqueString * lhs_name, + obj rhs_expr); + /** create empty skeleton. Rely on this for parsing + **/ + static DDefineExpr * make_empty(obj mm); + + DDefineExpr(DVariable * lhs_var, + obj rhs); + + ///@} + /** @defgroup scm-definexpr-access-methods **/ + ///@{ + + DVariable * lhs() const { return lhs_var_; } + obj rhs() const noexcept { return rhs_; } + const DUniqueString * name() const noexcept; + + ///@} + /** @defgroup scm-definexpr-bookkeeping-methods **/ + ///@{ + + void assign_lhs_name(const DUniqueString * name); + void assign_rhs(obj rhs); + + ///@} + /** @defgroup scm-defineexpr-expression-facet **/ + ///@{ + + exprtype extype() const noexcept { return exprtype::define; } + TypeRef typeref() const noexcept { return lhs_var_->typeref(); } + TypeDescr valuetype() const noexcept { return lhs_var_->typeref().td(); } + void assign_valuetype(TypeDescr td) noexcept; + + ///@} + /** @defgroup scm-defineexpr-gcobject-facet **/ + ///@{ + + std::size_t shallow_size() const noexcept; + DDefineExpr * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + ///@} + /** @defgroup scm-defineexpr-printable-facet **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + private: + /** @defgrouop scm-defineexpr-instance-vars **/ + ///@{ + + /** variable being defined by this expression. + **/ + DVariable * lhs_var_ = nullptr; + + /** expression for initial value of this expression + **/ + obj rhs_; + + // std::set free_var_set_; + + ///@} + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DDefineExpr.hpp */ diff --git a/xo-expression2/include/xo/expression2/DGlobalSymtab.hpp b/xo-expression2/include/xo/expression2/DGlobalSymtab.hpp new file mode 100644 index 00000000..5cd03fb2 --- /dev/null +++ b/xo-expression2/include/xo/expression2/DGlobalSymtab.hpp @@ -0,0 +1,126 @@ +/** @file DGlobalSymtab.hpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "Binding.hpp" +#include "DVariable.hpp" +#include +#include +#include + +namespace xo { + namespace scm { + class DUniqueString; + + /** @class DGlobalSymtab + * @brief symbol table for toplevel environment + * + * We're using DArenaHashMap to store pairs. + * Both of these are outside GC-space, so we don't need collector + * to traverse these. + **/ + class DGlobalSymtab { + public: + using key_type = const DUniqueString *; + using value_type = Binding; + using ArenaHashMapConfig = xo::map::ArenaHashMapConfig; + using repr_type = xo::map::DArenaHashMap; + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using MemorySizeVisitor = xo::mm::MemorySizeVisitor; + using ppindentinfo = xo::print::ppindentinfo; + using size_type = std::uint32_t; + + public: + /** @defgroup scm-globalsymtab-ctors constructors **/ + ///@{ + + DGlobalSymtab(dp map, DArray * vars); + + /** create instance. + * Use memory from @p fixed_mm for @ref map_. + * Use memory from @p mm for DGlobalSymtab instance. + * Hashmap configured per @p cfg. + **/ + static dp make(obj mm, + obj fixed_mm, + const ArenaHashMapConfig & cfg); + + /** non-trivial destructor for @ref map_ **/ + ~DGlobalSymtab() = default; + + ///@} + /** @defgroup scm-globalsymtab-access-methods access methods **/ + ///@{ + + size_type size() const noexcept { return map_->size(); } + size_type capacity() const noexcept { return map_->capacity(); } + + /** visit symtab-owned memory pools; call visitor(info) for each **/ + void visit_pools(const MemorySizeVisitor & visitor) const; + + /** lookup global symbol with name @p sym **/ + DVariable * lookup_variable(const DUniqueString * sym) const noexcept; + + ///@} + /** @defgroup scm-globalsymtab-general-methods general methods **/ + ///@{ + + /** update this symtab to associate @p var with @c var->name(). + * If there was a previous variable with the same name, + * replace it with @p var. + **/ + void upsert_variable(obj mm, + DVariable * var); + + ///@} + /** @defgroup scm-globalsymtab-symboltable-facet symboltable facet **/ + ///@{ + + /** true for global symbol table **/ + bool is_global_symtab() const noexcept { return true; } + + /** lookup binding for variable @p sym **/ + Binding lookup_binding(const DUniqueString * sym) const noexcept; + + ///@} + /** @defgroup scm-globalsymtab-gcobject-facet gcobject facet **/ + ///@{ + + std::size_t shallow_size() const noexcept; + DGlobalSymtab * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + ///@} + /** @defgroup scm-globalsymtab-printable-facet printable facet **/ + ///@{ + + /** pretty-printing support **/ + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + private: + /** map symbols -> bindings. + * Minor point: storing offsets instead of Variables allows us to omit + * iterating over map elements during GC. Possible savings if map_ slots + * sparsely populated. + **/ + dp map_; + + /** array of variables. + * When S is a unique-string for a global symbol, then: + * 1. map_[S] is unique global index i(S) for S. + * 2. vars_[i(S)] is variable-expr var(S) for S + * 3. var(S)->name == S + **/ + DArray * vars_ = nullptr; + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DGlobalSymtab.hpp */ diff --git a/xo-expression2/include/xo/expression2/DIfElseExpr.hpp b/xo-expression2/include/xo/expression2/DIfElseExpr.hpp new file mode 100644 index 00000000..3b7b07e2 --- /dev/null +++ b/xo-expression2/include/xo/expression2/DIfElseExpr.hpp @@ -0,0 +1,250 @@ +/** @file DIfElseExpr.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "Expression.hpp" +#include "TypeRef.hpp" +#include "exprtype.hpp" +#include +#include +//#include +#include +//#include + +namespace xo { + namespace scm { + + /** @class DIfExpr + * @brief abstract syntax tree for a function definition + **/ + class DIfElseExpr { + public: + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using TypeDescr = xo::reflect::TypeDescr; + using ppindentinfo = xo::print::ppindentinfo; + + public: + /** @defgroup scm-ifelseexpr-constructors **/ + ///@{ + + /** + * @p ifexpr_type type for value produced by if-expression. + * same as both when_true->valuetype() and + * when_false->valuetype(). + * @p test test-expression; always execute + * @p when_true then-branch; executes only when test succeeds + * @p when_false else-branch; executes only when test fails + **/ + DIfElseExpr(TypeRef ifexpr_type, + obj test_expr, + obj when_true, + obj when_false); + + /** create if-else expression using memory from @p mm. + * @p when_false can be null + **/ + static obj make(obj mm, + obj test, + obj when_true, + obj when_false); + + /** create expression for conditional execution of + * @p when_true or @p when_false, depending on result + * of evaluating expression @p test + **/ + static DIfElseExpr * _make(obj mm, + obj test, + obj when_true, + obj when_false); + + /** create empty if-else expression using memory from @p mm **/ + static obj make_empty(obj mm); + + /** create empty if-else expression using memory from @p mm **/ + static DIfElseExpr * _make_empty(obj mm); + + ///@} + /** @defgroup scm-ifelseexpr-access-methods **/ + ///@{ + + obj test() const noexcept { return test_; } + obj when_true() const noexcept { return when_true_; } + obj when_false() const noexcept { return when_false_; } + + void assign_test(obj x) { this->test_ = x; } + void assign_when_true(obj x) { this->when_true_ = x; } + void assign_when_false(obj x) { this->when_false_ = x; } + + ///@} + /** @defgroup scm-ifelseexpr-expression-facet **/ + ///@{ + + exprtype extype() const noexcept { return exprtype::ifexpr; } + TypeRef typeref() const noexcept { return typeref_; } + TypeDescr valuetype() const noexcept { return typeref_.td(); } + void assign_valuetype(TypeDescr td) noexcept; + + ///@} + /** @defgroup scm-ifelseexpr-printable-facet **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + /** @defgroup scm-ifelseexpr-gcobject-facet **/ + ///@{ + + std::size_t shallow_size() const noexcept; + DIfElseExpr * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + ///@} + +#ifdef NOT_YET + virtual std::set get_free_variables() const override { + std::set retval = test_->get_free_variables(); + + std::set free_vars; + free_vars = when_true_->get_free_variables(); + for (const auto & s : free_vars) + retval.insert(s); + + free_vars = when_false_->get_free_variables(); + for (const auto & s : free_vars) + retval.insert(s); + + return retval; + } + + virtual std::size_t visit_preorder(VisitFn visitor_fn) override { + std::size_t n = 1; + + visitor_fn(this); + + n += this->test_->visit_preorder(visitor_fn); + n += this->when_true_->visit_preorder(visitor_fn); + n += this->when_false_->visit_preorder(visitor_fn); + + return n; + } + + virtual std::size_t visit_layer(VisitFn visitor_fn) override { + std::size_t n = 1; + + visitor_fn(this); + + n += this->test_->visit_layer(visitor_fn); + n += this->when_true_->visit_layer(visitor_fn); + n += this->when_false_->visit_layer(visitor_fn); + + return n; + } + + virtual rp xform_layer(TransformFn xform_fn) override { + this->test_ = this->test_->xform_layer(xform_fn); + this->when_true_ = this->when_true_->xform_layer(xform_fn); + this->when_false_= this->when_false_->xform_layer(xform_fn); + + return xform_fn(this); + } + + virtual void attach_envs(bp p) override { + test_->attach_envs(p); + when_true_->attach_envs(p); + when_false_->attach_envs(p); + } +#endif + +#ifdef NOT_USING + virtual std::int32_t find_free_vars(std::set> * p_set) override { + return (test_->find_free_vars(p_set) + + when_true_->find_free_vars(p_set) + + when_false_->find_free_vars(p_set)); + } +#endif + +#ifdef NOPE + virtual void display(std::ostream & os) const override; + virtual std::uint32_t pretty_print(const ppindentinfo & ppi) const override; +#endif + + protected: +#ifdef NOT_YET + /** + * @p ifexpr_type type for value produced by if-expression. + * same as both when_true->valuetype() and + * when_false->valuetype(). + * @p test test-expression; always execute + * @p when_true then-branch; executes only when test succeeds + * @p when_false else-branch; executes only when test fails + **/ + IfExpr(TypeDescr ifexpr_type, + rp test, + rp when_true, + rp when_false) + : Expression(exprtype::ifexpr, ifexpr_type), + test_{std::move(test)}, + when_true_{std::move(when_true)}, + when_false_{std::move(when_false)} {} + + static TypeDescr check_consistent_valuetype(const rp & when_true, + const rp & when_false); + + /** determine if-expr valuetype **/ + void establish_valuetype(); +#endif + + private: + /** expression value always has type consistent + * with this description + **/ + TypeRef typeref_; + /** if: + * (if x y z) + * + * executes x; if true execute y; otherwise execute z + **/ + obj test_; + obj when_true_; + obj when_false_; + }; /*IfExpr*/ + +#ifdef NOPE + inline rp + make_ifexpr(const rp & test, + const rp & when_true, + const rp & when_false) + { + return IfExpr::make(test, when_true, when_false); + } + + class IfExprAccess : public IfExpr { + public: + static rp make(rp test, + rp when_true, + rp when_false); + static rp make_empty(); + + void assign_test(rp x) { test_ = std::move(x); } + void assign_when_true(rp x); + void assign_when_false(rp x); + + private: + IfExprAccess(TypeDescr ifexpr_type, + rp test, + rp when_true, + rp when_false) + : IfExpr(ifexpr_type, + std::move(test), + std::move(when_true), + std::move(when_false)) {} + }; +#endif + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DIfElseExpr.hpp */ diff --git a/xo-expression2/include/xo/expression2/DLambdaExpr.hpp b/xo-expression2/include/xo/expression2/DLambdaExpr.hpp new file mode 100644 index 00000000..30ed2b74 --- /dev/null +++ b/xo-expression2/include/xo/expression2/DLambdaExpr.hpp @@ -0,0 +1,131 @@ +/** @file DLambdaExpr.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "Expression.hpp" +#include "TypeRef.hpp" +#include "exprtype.hpp" +#include "DLocalSymtab.hpp" +#include "DString.hpp" +#include + +namespace xo { + namespace scm { + /** @class DLambdaExpr + * @brief syntax tree for a function/procedure definition + * + **/ + class DLambdaExpr { + public: + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using TypeDescr = xo::reflect::TypeDescr; + using ppindentinfo = xo::print::ppindentinfo; + using size_type = DLocalSymtab::size_type; + + public: + + /** @defgroup scm-lambdaexpr-ctors **/ + ///@{ + + DLambdaExpr(TypeRef typeref, + const DUniqueString * name, + DLocalSymtab * local_symtab, + obj body); + + /** create instance using memory from @p mm **/ + static obj make(obj mm, + TypeRef typeref, + const DUniqueString * name, + DLocalSymtab * local_symtab, + obj body); + + /** create instance, using memory from @p mm **/ + static DLambdaExpr * _make(obj mm, + TypeRef typeref, + const DUniqueString * name, + DLocalSymtab * local_symtab, + obj body); + + /** create type description for lambda with arguments described by @p symtab + * and return type @p return_td. + * Load-bearing for DLambdaSsm in xo-reader2/ + **/ + static TypeDescr assemble_lambda_td(DLocalSymtab * symtab, + TypeDescr return_td); + + ///@} + /** @defgroup scm-lambdaexpr-methods **/ + ///@{ + + DLocalSymtab * local_symtab() const noexcept { return local_symtab_; } + size_type n_args() const noexcept { return local_symtab_->size(); } + obj body_expr() const noexcept { return body_expr_; } + + // get_free_variables() + // visit_preorder() + // visit_layer() + // xform_layer() + // attach_envs(SymbolTable*) + + ///@} + /** @defgroup scm-lambdaexpr-expression-facet **/ + ///@{ + + exprtype extype() const noexcept; + TypeRef typeref() const noexcept; + TypeDescr valuetype() const noexcept; + void assign_valuetype(TypeDescr td) noexcept; + + ///@} + /** @defgroup scm-lambdaexpr-gcobject-facet **/ + ///@{ + + std::size_t shallow_size() const noexcept; + DLambdaExpr * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + ///@} + /** @defgroup scm-lambdaexpr-printable-facet **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + private: + /** expression value always has type consistent + * with description here + **/ + TypeRef typeref_; + + /** name for this lambda (generated if necessary) **/ + const DUniqueString * name_ = nullptr; + +#ifdef NOT_YET // when enabled, need to visit forward_children() + /** e.g. + * i64(f64,string) + * for function of two arguments with types (f64, string) respectively, + * that returns an i64. + **/ + const DUniqueString * type_name_str_ = nullptr; +#endif + + /** symbol table for lambda arguments **/ + DLocalSymtab * local_symtab_ = nullptr;; + + /** expression for function body **/ + obj body_expr_; + + // free_var_set + // captured_var_set + // layer_var_map + // nested_lambda_map + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DLambdaExpr.hpp */ diff --git a/xo-expression2/include/xo/expression2/DLocalSymtab.hpp b/xo-expression2/include/xo/expression2/DLocalSymtab.hpp index b60b6570..f4073226 100644 --- a/xo-expression2/include/xo/expression2/DLocalSymtab.hpp +++ b/xo-expression2/include/xo/expression2/DLocalSymtab.hpp @@ -6,6 +6,7 @@ #pragma once #include "Binding.hpp" +#include "DVariable.hpp" #include "DUniqueString.hpp" //#include "exprtype.hpp" //#include @@ -23,15 +24,65 @@ namespace xo { // using AGCObject = xo::mm::AGCObject; // using typeseq = xo::reflect::typeseq; + using ppindentinfo = xo::print::ppindentinfo; + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + /* note: uint16_t would be fine too */ + using size_type = std::uint32_t; + struct Slot { - // obj var_; - Binding binding_; + Slot() = default; + explicit Slot(DVariable * var) : var_{var} {} + + /** variable representing a formal argument. + * binding will be correct only within the same layer + * as top-level lambda body + * (i.e. up to the doorstep of each and every nested lambda) + **/ + DVariable * var_ = nullptr; }; public: -// explicit DLocalSymtab(obj value) noexcept; + /** @defgroup scm-lambdaexpr-constructors **/ + ///@{ - /** @defgroup xo-expression2-symboltable-facet symboltable facet**/ + /** empty instance with parent @p p and capacity for @p n slots. + * Caller must ensure that slots_[0..n) are actually addressable + **/ + DLocalSymtab(DLocalSymtab * p, size_type n); + + /** scaffold empty symtab instance, + * with capacity for @p n slots, using memory from allocator @p mm + **/ + static DLocalSymtab * _make_empty(obj mm, + DLocalSymtab * p, + size_type n); + + ///@} + /** @defgroup scm-lambdaexpr-methods **/ + ///@{ + + DLocalSymtab * parent() const noexcept { return parent_; } + size_type capacity() const noexcept { return capacity_; } + size_type size() const noexcept { return size_; } + + DVariable * lookup_var(Binding ix) noexcept { + assert(ix.i_link() == 0); + assert(ix.j_slot() < static_cast(size_)); + + return slots_[ix.j_slot()].var_; + } + + /** increase slot size (provided below capacity) to append + * binding for one local variable. Local variable will be allocated + * from @p mm, named @p name, with type described by @p typeref. + **/ + Binding append_var(obj mm, + const DUniqueString * name, + TypeRef typeref); + + ///@} + /** @defgroup xo-localsymtab-symboltable-facet symboltable facet**/ ///@{ /** true for global symbol table **/ @@ -41,9 +92,30 @@ namespace xo { Binding lookup_binding(const DUniqueString * sym) const noexcept; ///@} + /** @defgroup xo-localsymtab-gcobject-facet gcobject facet **/ + ///@{ + + std::size_t shallow_size() const noexcept; + DLocalSymtab * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + ///@} + /** @defgroup xo-localsymtab-printable-facet printable facet **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} private: - + /** parent symbol table from scoping surrounding this one **/ + DLocalSymtab * parent_ = nullptr; + /** actual range of slots_[] array. Can use indices in [0,..,n) **/ + size_type capacity_ = 0; + /** number of slots in use **/ + size_type size_ = 0; + /** memory for names and bindings **/ + Slot slots_[]; }; } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-expression2/include/xo/expression2/DSequenceExpr.hpp b/xo-expression2/include/xo/expression2/DSequenceExpr.hpp new file mode 100644 index 00000000..c5bb6f16 --- /dev/null +++ b/xo-expression2/include/xo/expression2/DSequenceExpr.hpp @@ -0,0 +1,92 @@ +/** @file DSequenceExpr.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "Expression.hpp" +#include "TypeRef.hpp" +#include + +namespace xo { + namespace scm { + + /** syntax for a sequence of expressions + * { + * expr(1); + * expr(2); + * ... + * expr(n); + * } + **/ + class DSequenceExpr { + public: + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using TypeDescr = xo::reflect::TypeDescr; + using size_type = DArray::size_type; + using ppindentinfo = xo::print::ppindentinfo; + + public: + DSequenceExpr() = default; + DSequenceExpr(DArray * xv) : expr_v_{xv} {} + + /** create empty sequence using memory from @p mm **/ + static obj make_empty(obj mm); + + /** create empty sequence expression using mmeory from @p mm **/ + static DSequenceExpr * _make_empty(obj mm); + + size_type size() const noexcept; + obj operator[](std::size_t i) const; + + /** append @p expr to the end of this sequence; + * use memory from @p mm if need to expand storage + **/ + void push_back(obj mm, + obj expr); + + // get_free_variables(); + // visit_preorder(); + // visit_layer(); + // xform_layer() + // attach_envs() + + /** @defgroup scm-ifelseexpr-expression-facets **/ + ///@{ + + exprtype extype() const noexcept { return exprtype::sequence; } + TypeRef typeref() const noexcept { return typeref_; } + TypeDescr valuetype() const noexcept { return typeref_.td(); } + void assign_valuetype(TypeDescr td) noexcept; + + ///@} + /** @defgroup scm-sequenceexpr-printable-facet printable facet methods **/ + ///@{ + + /** pretty-printing driver; combine layout+printing **/ + bool pretty(const ppindentinfo & ppii) const; + + ///@} + /** @defgroup scm-sequenceexpr-gcobject-facet gcobject facet methods **/ + ///@{ + + std::size_t shallow_size() const noexcept; + DSequenceExpr * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + ///@} + + private: + /** expression value always has type consistent with this description + **/ + TypeRef typeref_; + /** array of expressions **/ + DArray * expr_v_ = nullptr; + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DSequenceExpr.hpp */ diff --git a/xo-expression2/include/xo/expression2/DVarRef.hpp b/xo-expression2/include/xo/expression2/DVarRef.hpp new file mode 100644 index 00000000..d4a230b3 --- /dev/null +++ b/xo-expression2/include/xo/expression2/DVarRef.hpp @@ -0,0 +1,84 @@ +/** @file DVarRef.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "Variable.hpp" + +namespace xo { + namespace scm { + + /** @class DVarRef + * @brief syntax for a variable reference + * + * Reference to a known variable possibly + * defined in another scope. + * For non-local non-global variables, + **/ + class DVarRef { + public: + using ppindentinfo = xo::print::ppindentinfo; + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using TypeDescr = xo::reflect::TypeDescr; + + public: + DVarRef(DVariable * vardef, + Binding path); + + /** create instance + * @p mm memory allocator + * @p vardef variable definition (name, typeref, binding) + * @p link number of lexical scope boundaries we must cross + * to reach scope containing @p vardef. + * Only relevant for non-global vardef + **/ + static DVarRef * make(obj mm, + DVariable * vardef, + int32_t link); + + const DUniqueString * name() const; + Binding path() const { return path_; } + + /** @defgroup scm-variable-expression-facet **/ + ///@{ + + exprtype extype() const noexcept { return exprtype::varref; } + TypeRef typeref() const noexcept; + TypeDescr valuetype() const noexcept; + void assign_valuetype(TypeDescr td) noexcept; + + ///@} + /** @defgroup scm-variable-gcobject-facet **/ + ///@{ + + size_t shallow_size() const noexcept; + DVarRef * shallow_copy(obj mm) const noexcept; + size_t forward_children(obj gc) noexcept; + + ///@} + /** @defgroup scm-variable-printable-facet **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + private: + /** variable definition. Created in the sccope where variable introduced. + * Has an associated @ref Binding, but that binding is only correct + * around any nested scopes. + **/ + DVariable * vardef_ = nullptr; + + /** at runtime: navigate environemnt via this path to get + * runtime memory location for this variable + **/ + Binding path_; + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DVarRef.hpp */ diff --git a/xo-expression2/include/xo/expression2/DVariable.hpp b/xo-expression2/include/xo/expression2/DVariable.hpp index 036d88ce..29253097 100644 --- a/xo-expression2/include/xo/expression2/DVariable.hpp +++ b/xo-expression2/include/xo/expression2/DVariable.hpp @@ -10,25 +10,47 @@ #include "TypeRef.hpp" #include "exprtype.hpp" #include +#include namespace xo { namespace scm { - /** @class DVariable* + /** @class DVariable * @brief syntax for a variable reference **/ class DVariable { public: + using ppindentinfo = xo::print::ppindentinfo; + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; using TypeDescr = xo::reflect::TypeDescr; public: - DVariable(const DUniqueString & name, const TypeRef & typeref, Binding path) - : name_{name}, typeref_{typeref}, path_{path} {} + /** create instance + * @p mm memory allocator + * @p name variable name + * @p typeref type information for legal values + * (possibly just placeholder when relying on inference) + * @p path binding path to runtime value. + * This may be computed after parsing; + * mnust be resolved before execution. + **/ + static DVariable * make(obj mm, + const DUniqueString * name, + const TypeRef & typeref, + Binding path = Binding()); - const DUniqueString & name() const { return name_; } + DVariable(const DUniqueString * name, + const TypeRef & typeref, + Binding path); + + const DUniqueString * name() const { return name_; } Binding path() const { return path_; } - /** @defgroup scm-variable-expression-facet**/ + void assign_name(const DUniqueString * name) { this->name_ = name; } + void assign_path(Binding b) { this->path_ = b; } + + /** @defgroup scm-variable-expression-facet **/ ///@{ exprtype extype() const noexcept { return exprtype::variable; } @@ -37,10 +59,24 @@ namespace xo { void assign_valuetype(TypeDescr td) noexcept; ///@} + /** @defgroup scm-variable-gcobject-facet **/ + ///@{ + + size_t shallow_size() const noexcept; + DVariable * shallow_copy(obj mm) const noexcept; + size_t forward_children(obj gc) noexcept; + + ///@} + /** @defgroup scm-variable-printable-facet **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} private: /** symbol name **/ - const DUniqueString & name_; + const DUniqueString * name_; /** variable value always has type consistent * with this description **/ diff --git a/xo-expression2/include/xo/expression2/DefineExpr.hpp b/xo-expression2/include/xo/expression2/DefineExpr.hpp new file mode 100644 index 00000000..4a0c42c2 --- /dev/null +++ b/xo-expression2/include/xo/expression2/DefineExpr.hpp @@ -0,0 +1,13 @@ +/** @file DefineExpr.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DDefineExpr.hpp" +#include "detail/IExpression_DDefineExpr.hpp" +#include "define/IGCObject_DDefineExpr.hpp" +#include "detail/IPrintable_DDefineExpr.hpp" + +/* end DefineExpr.hpp */ diff --git a/xo-expression2/include/xo/expression2/Expression.hpp b/xo-expression2/include/xo/expression2/Expression.hpp index 60e8a402..6ed0e1f2 100644 --- a/xo-expression2/include/xo/expression2/Expression.hpp +++ b/xo-expression2/include/xo/expression2/Expression.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/Expression.json5] * 2. jinja2 template for facet .hpp file: @@ -19,4 +19,4 @@ #include "detail/RExpression.hpp" -/* end Expression.hpp */ \ No newline at end of file +/* end Expression.hpp */ diff --git a/xo-expression2/include/xo/expression2/GlobalSymtab.hpp b/xo-expression2/include/xo/expression2/GlobalSymtab.hpp new file mode 100644 index 00000000..05ad9f4b --- /dev/null +++ b/xo-expression2/include/xo/expression2/GlobalSymtab.hpp @@ -0,0 +1,13 @@ +/** @file GlobalSymtab.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DGlobalSymtab.hpp" +#include "symtab/ISymbolTable_DGlobalSymtab.hpp" +#include "symtab/IGCObject_DGlobalSymtab.hpp" +#include "symtab/IPrintable_DGlobalSymtab.hpp" + +/* end GlobalSymtab.hpp */ diff --git a/xo-expression2/include/xo/expression2/IfElseExpr.hpp b/xo-expression2/include/xo/expression2/IfElseExpr.hpp new file mode 100644 index 00000000..901062b2 --- /dev/null +++ b/xo-expression2/include/xo/expression2/IfElseExpr.hpp @@ -0,0 +1,13 @@ +/** @file IfElseExpr.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DIfElseExpr.hpp" +#include "detail/IExpression_DIfElseExpr.hpp" +#include "detail/IGCObject_DIfElseExpr.hpp" +#include "detail/IPrintable_DIfElseExpr.hpp" + +/* end IfElseExpr.hpp */ diff --git a/xo-expression2/include/xo/expression2/LambdaExpr.hpp b/xo-expression2/include/xo/expression2/LambdaExpr.hpp new file mode 100644 index 00000000..043ca319 --- /dev/null +++ b/xo-expression2/include/xo/expression2/LambdaExpr.hpp @@ -0,0 +1,13 @@ +/** @file LambdaExpr.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DLambdaExpr.hpp" +#include "detail/IExpression_DLambdaExpr.hpp" +#include "detail/IGCObject_DLambdaExpr.hpp" +#include "detail/IPrintable_DLambdaExpr.hpp" + +/* end LambdaExpr.hpp */ diff --git a/xo-expression2/include/xo/expression2/LocalSymtab.hpp b/xo-expression2/include/xo/expression2/LocalSymtab.hpp new file mode 100644 index 00000000..e594a08d --- /dev/null +++ b/xo-expression2/include/xo/expression2/LocalSymtab.hpp @@ -0,0 +1,13 @@ +/** @file LocalSymtab.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DLocalSymtab.hpp" +#include "symtab/ISymbolTable_DLocalSymtab.hpp" +#include "symtab/IGCObject_DLocalSymtab.hpp" +#include "symtab/IPrintable_DLocalSymtab.hpp" + +/* end LocalSymtab.hpp */ diff --git a/xo-expression2/include/xo/expression2/SequenceExpr.hpp b/xo-expression2/include/xo/expression2/SequenceExpr.hpp new file mode 100644 index 00000000..0cfe188c --- /dev/null +++ b/xo-expression2/include/xo/expression2/SequenceExpr.hpp @@ -0,0 +1,14 @@ +/** @file SequenceExpr.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DSequenceExpr.hpp" +#include "detail/IExpression_DSequenceExpr.hpp" +#include "detail/IGCObject_DSequenceExpr.hpp" +#include "detail/IPrintable_DSequenceExpr.hpp" + +/* end SequenceExpr.hpp */ + diff --git a/xo-expression2/include/xo/expression2/StringTable.hpp b/xo-expression2/include/xo/expression2/StringTable.hpp index 54b0a826..8d0354c8 100644 --- a/xo-expression2/include/xo/expression2/StringTable.hpp +++ b/xo-expression2/include/xo/expression2/StringTable.hpp @@ -21,6 +21,7 @@ namespace xo { class StringTable { public: using DArena = xo::mm::DArena; + using MemorySizeVisitor = xo::mm::MemorySizeVisitor; using StringMap = xo::map::DArenaHashMap; using size_type = StringMap::size_type; @@ -35,11 +36,19 @@ namespace xo { /** return unique string with contents @p key. Idempotent! **/ const DUniqueString * intern(std::string_view key); + /** generate unique symbol -- guaranteed not to collide + * with existing symbol in this table. + **/ + const DUniqueString * gensym(std::string_view prefix); + /** verify StringTable invariants. * Act on failure according to policy @p p **/ bool verify_ok(verify_policy p = verify_policy::throw_only()) const; + /** visit string-table memory pools, call visitor(info) for each **/ + void visit_pools(const MemorySizeVisitor & visitor) const; + private: /** allocate string storage in this arena; use DString to represent each string. * Can't use DArenaVector b/c DString has variable size diff --git a/xo-expression2/include/xo/expression2/SymbolTable.hpp b/xo-expression2/include/xo/expression2/SymbolTable.hpp index 09fc04a8..618cf2bf 100644 --- a/xo-expression2/include/xo/expression2/SymbolTable.hpp +++ b/xo-expression2/include/xo/expression2/SymbolTable.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/SymbolTable.json5] * 2. jinja2 template for facet .hpp file: @@ -19,4 +19,4 @@ #include "symtab/RSymbolTable.hpp" -/* end SymbolTable.hpp */ \ No newline at end of file +/* end SymbolTable.hpp */ diff --git a/xo-expression2/include/xo/expression2/TypeRef.hpp b/xo-expression2/include/xo/expression2/TypeRef.hpp index 01401d28..eecb438d 100644 --- a/xo-expression2/include/xo/expression2/TypeRef.hpp +++ b/xo-expression2/include/xo/expression2/TypeRef.hpp @@ -7,6 +7,7 @@ #include #include +#include namespace xo { namespace scm { @@ -22,6 +23,7 @@ namespace xo { using TypeDescr = xo::reflect::TypeDescr; using type_var = flatstring<20>; using prefix_type = flatstring<8>; + using ppindentinfo = xo::print::ppindentinfo; public: TypeRef() = default; @@ -54,6 +56,9 @@ namespace xo { /** resolve TypeRef by supplying final type-description **/ void resolve(TypeDescr td) noexcept { td_ = td; } + /** pretty-printer support **/ + bool pretty(const ppindentinfo & ppii) const; + private: /** unique (probably generated) name for type at this location **/ type_var id_; @@ -61,9 +66,21 @@ namespace xo { * May be null when this TypeRef created, * but expected to be immutable once established. **/ - TypeDescr td_; + TypeDescr td_ = nullptr; }; } /*namespace scm*/ + + namespace print { + /** pretty printer in relies on this specialization + * to handle TypeRef instances + **/ + template <> + struct ppdetail { + static inline bool print_pretty(const ppindentinfo & ppii, const xo::scm::TypeRef x) { + return x.pretty(ppii); + } + }; + } } /*namespace xo*/ /* end TypeRef.hpp */ diff --git a/xo-expression2/include/xo/expression2/UniqueString.hpp b/xo-expression2/include/xo/expression2/UniqueString.hpp new file mode 100644 index 00000000..90cd1cd2 --- /dev/null +++ b/xo-expression2/include/xo/expression2/UniqueString.hpp @@ -0,0 +1,12 @@ +/** @file UniqueString.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DUniqueString.hpp" +#include "detail/IGCObject_DUniqueString.hpp" +#include "detail/IPrintable_DUniqueString.hpp" + +/* end UniqueString.hpp */ diff --git a/xo-expression2/include/xo/expression2/VarRef.hpp b/xo-expression2/include/xo/expression2/VarRef.hpp new file mode 100644 index 00000000..19f2d1d0 --- /dev/null +++ b/xo-expression2/include/xo/expression2/VarRef.hpp @@ -0,0 +1,13 @@ +/** @file VarRef.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DVarRef.hpp" +#include "detail/IExpression_DVarRef.hpp" +#include "detail/IGCObject_DVarRef.hpp" +#include "detail/IPrintable_DVarRef.hpp" + +/* end VarRef.hpp */ diff --git a/xo-expression2/include/xo/expression2/Variable.hpp b/xo-expression2/include/xo/expression2/Variable.hpp new file mode 100644 index 00000000..26ef649b --- /dev/null +++ b/xo-expression2/include/xo/expression2/Variable.hpp @@ -0,0 +1,13 @@ +/** @file Variable.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DVariable.hpp" +#include "detail/IExpression_DVariable.hpp" +#include "detail/IGCObject_DVariable.hpp" +#include "detail/IPrintable_DVariable.hpp" + +/* end Variable.hpp */ diff --git a/xo-expression2/include/xo/expression2/define/IGCObject_DDefineExpr.hpp b/xo-expression2/include/xo/expression2/define/IGCObject_DDefineExpr.hpp new file mode 100644 index 00000000..216dd18b --- /dev/null +++ b/xo-expression2/include/xo/expression2/define/IGCObject_DDefineExpr.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DDefineExpr.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DDefineExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DDefineExpr.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DDefineExpr.hpp" + +namespace xo { namespace scm { class IGCObject_DDefineExpr; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DDefineExpr + **/ + class IGCObject_DDefineExpr { + public: + /** @defgroup scm-gcobject-ddefineexpr-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-ddefineexpr-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DDefineExpr & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DDefineExpr & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DDefineExpr & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/AExpression.hpp b/xo-expression2/include/xo/expression2/detail/AExpression.hpp index 10375114..96d68a65 100644 --- a/xo-expression2/include/xo/expression2/detail/AExpression.hpp +++ b/xo-expression2/include/xo/expression2/detail/AExpression.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/Expression.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -50,6 +50,8 @@ public: // const methods /** RTTI: unique id# for actual runtime data representation **/ virtual typeseq _typeseq() const noexcept = 0; + /** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/ + virtual void _drop(Opaque d) const noexcept = 0; /** expression type (constant | apply | ..) **/ virtual exprtype extype(Copaque data) const noexcept = 0; /** placeholder for type giving possible values for this expression **/ @@ -79,4 +81,4 @@ using IExpression_ImplType = xo::facet::FacetImplType; } /*namespace scm*/ } /*namespace xo*/ -/* AExpression.hpp */ \ No newline at end of file +/* AExpression.hpp */ diff --git a/xo-expression2/include/xo/expression2/detail/IExpression_Any.hpp b/xo-expression2/include/xo/expression2/detail/IExpression_Any.hpp index c92c2c4a..827f9d9b 100644 --- a/xo-expression2/include/xo/expression2/detail/IExpression_Any.hpp +++ b/xo-expression2/include/xo/expression2/detail/IExpression_Any.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/Expression.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -54,8 +54,11 @@ namespace scm { // from AExpression - // const methods + // builtin methods typeseq _typeseq() const noexcept override { return s_typeseq; } + [[noreturn]] void _drop(Opaque) const noexcept override { _fatal(); } + + // const methods [[noreturn]] exprtype extype(Copaque) const noexcept override { _fatal(); } [[noreturn]] TypeRef typeref(Copaque) const noexcept override { _fatal(); } [[noreturn]] TypeDescr valuetype(Copaque) const noexcept override { _fatal(); } @@ -86,4 +89,4 @@ namespace scm { } /*namespace scm */ } /*namespace xo */ -/* IExpression_Any.hpp */ \ No newline at end of file +/* IExpression_Any.hpp */ diff --git a/xo-expression2/include/xo/expression2/detail/IExpression_DApplyExpr.hpp b/xo-expression2/include/xo/expression2/detail/IExpression_DApplyExpr.hpp new file mode 100644 index 00000000..49cce701 --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IExpression_DApplyExpr.hpp @@ -0,0 +1,66 @@ +/** @file IExpression_DApplyExpr.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IExpression_DApplyExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IExpression_DApplyExpr.json5] + **/ + +#pragma once + +#include "Expression.hpp" +#include "Expression.hpp" +#include "DApplyExpr.hpp" + +namespace xo { namespace scm { class IExpression_DApplyExpr; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::IExpression_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IExpression_DApplyExpr + **/ + class IExpression_DApplyExpr { + public: + /** @defgroup scm-expression-dapplyexpr-type-traits **/ + ///@{ + using TypeDescr = xo::scm::AExpression::TypeDescr; + using Copaque = xo::scm::AExpression::Copaque; + using Opaque = xo::scm::AExpression::Opaque; + ///@} + /** @defgroup scm-expression-dapplyexpr-methods **/ + ///@{ + // const methods + /** expression type (constant | apply | ..) **/ + static exprtype extype(const DApplyExpr & self) noexcept; + /** placeholder for type giving possible values for this expression **/ + static TypeRef typeref(const DApplyExpr & self) noexcept; + /** type giving possible values for this expression. Maybe null before typecheck **/ + static TypeDescr valuetype(const DApplyExpr & self) noexcept; + + // non-const methods + /** assing to valuetype member. Useful when scaffolding expressions **/ + static void assign_valuetype(DApplyExpr & self, TypeDescr td) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/IExpression_DConstant.hpp b/xo-expression2/include/xo/expression2/detail/IExpression_DConstant.hpp similarity index 90% rename from xo-expression2/include/xo/expression2/IExpression_DConstant.hpp rename to xo-expression2/include/xo/expression2/detail/IExpression_DConstant.hpp index b08d8814..c6bbd819 100644 --- a/xo-expression2/include/xo/expression2/IExpression_DConstant.hpp +++ b/xo-expression2/include/xo/expression2/detail/IExpression_DConstant.hpp @@ -2,17 +2,18 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IExpression_DConstant.json5] * 2. jinja2 template for abstract facet .hpp file: - * [iface_facet_any.hpp.j2] + * [iface_facet_repr.hpp.j2] * 3. idl for facet methods * [idl/IExpression_DConstant.json5] **/ #pragma once +#include "Expression.hpp" #include "Expression.hpp" #include "DConstant.hpp" @@ -40,6 +41,8 @@ namespace xo { /** @defgroup scm-expression-dconstant-type-traits **/ ///@{ using TypeDescr = xo::scm::AExpression::TypeDescr; + using Copaque = xo::scm::AExpression::Copaque; + using Opaque = xo::scm::AExpression::Opaque; ///@} /** @defgroup scm-expression-dconstant-methods **/ ///@{ diff --git a/xo-expression2/include/xo/expression2/detail/IExpression_DDefineExpr.hpp b/xo-expression2/include/xo/expression2/detail/IExpression_DDefineExpr.hpp new file mode 100644 index 00000000..135c7bb4 --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IExpression_DDefineExpr.hpp @@ -0,0 +1,66 @@ +/** @file IExpression_DDefineExpr.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IExpression_DDefineExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IExpression_DDefineExpr.json5] + **/ + +#pragma once + +#include "Expression.hpp" +#include "Expression.hpp" +#include "DDefineExpr.hpp" + +namespace xo { namespace scm { class IExpression_DDefineExpr; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::IExpression_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IExpression_DDefineExpr + **/ + class IExpression_DDefineExpr { + public: + /** @defgroup scm-expression-ddefineexpr-type-traits **/ + ///@{ + using TypeDescr = xo::scm::AExpression::TypeDescr; + using Copaque = xo::scm::AExpression::Copaque; + using Opaque = xo::scm::AExpression::Opaque; + ///@} + /** @defgroup scm-expression-ddefineexpr-methods **/ + ///@{ + // const methods + /** expression type (constant | apply | ..) **/ + static exprtype extype(const DDefineExpr & self) noexcept; + /** placeholder for type giving possible values for this expression **/ + static TypeRef typeref(const DDefineExpr & self) noexcept; + /** type giving possible values for this expression. Maybe null before typecheck **/ + static TypeDescr valuetype(const DDefineExpr & self) noexcept; + + // non-const methods + /** assing to valuetype member. Useful when scaffolding expressions **/ + static void assign_valuetype(DDefineExpr & self, TypeDescr td) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IExpression_DIfElseExpr.hpp b/xo-expression2/include/xo/expression2/detail/IExpression_DIfElseExpr.hpp new file mode 100644 index 00000000..ca6e5705 --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IExpression_DIfElseExpr.hpp @@ -0,0 +1,66 @@ +/** @file IExpression_DIfElseExpr.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IExpression_DIfElseExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IExpression_DIfElseExpr.json5] + **/ + +#pragma once + +#include "Expression.hpp" +#include "Expression.hpp" +#include "DIfElseExpr.hpp" + +namespace xo { namespace scm { class IExpression_DIfElseExpr; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::IExpression_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IExpression_DIfElseExpr + **/ + class IExpression_DIfElseExpr { + public: + /** @defgroup scm-expression-difelseexpr-type-traits **/ + ///@{ + using TypeDescr = xo::scm::AExpression::TypeDescr; + using Copaque = xo::scm::AExpression::Copaque; + using Opaque = xo::scm::AExpression::Opaque; + ///@} + /** @defgroup scm-expression-difelseexpr-methods **/ + ///@{ + // const methods + /** expression type (constant | apply | ..) **/ + static exprtype extype(const DIfElseExpr & self) noexcept; + /** placeholder for type giving possible values for this expression **/ + static TypeRef typeref(const DIfElseExpr & self) noexcept; + /** type giving possible values for this expression. Maybe null before typecheck **/ + static TypeDescr valuetype(const DIfElseExpr & self) noexcept; + + // non-const methods + /** assing to valuetype member. Useful when scaffolding expressions **/ + static void assign_valuetype(DIfElseExpr & self, TypeDescr td) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IExpression_DLambdaExpr.hpp b/xo-expression2/include/xo/expression2/detail/IExpression_DLambdaExpr.hpp new file mode 100644 index 00000000..bdb074d9 --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IExpression_DLambdaExpr.hpp @@ -0,0 +1,66 @@ +/** @file IExpression_DLambdaExpr.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IExpression_DLambdaExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IExpression_DLambdaExpr.json5] + **/ + +#pragma once + +#include "Expression.hpp" +#include "Expression.hpp" +#include "DLambdaExpr.hpp" + +namespace xo { namespace scm { class IExpression_DLambdaExpr; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::IExpression_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IExpression_DLambdaExpr + **/ + class IExpression_DLambdaExpr { + public: + /** @defgroup scm-expression-dlambdaexpr-type-traits **/ + ///@{ + using TypeDescr = xo::scm::AExpression::TypeDescr; + using Copaque = xo::scm::AExpression::Copaque; + using Opaque = xo::scm::AExpression::Opaque; + ///@} + /** @defgroup scm-expression-dlambdaexpr-methods **/ + ///@{ + // const methods + /** expression type (constant | apply | ..) **/ + static exprtype extype(const DLambdaExpr & self) noexcept; + /** placeholder for type giving possible values for this expression **/ + static TypeRef typeref(const DLambdaExpr & self) noexcept; + /** type giving possible values for this expression. Maybe null before typecheck **/ + static TypeDescr valuetype(const DLambdaExpr & self) noexcept; + + // non-const methods + /** assing to valuetype member. Useful when scaffolding expressions **/ + static void assign_valuetype(DLambdaExpr & self, TypeDescr td) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IExpression_DSequenceExpr.hpp b/xo-expression2/include/xo/expression2/detail/IExpression_DSequenceExpr.hpp new file mode 100644 index 00000000..6e0107dd --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IExpression_DSequenceExpr.hpp @@ -0,0 +1,66 @@ +/** @file IExpression_DSequenceExpr.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IExpression_DSequenceExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IExpression_DSequenceExpr.json5] + **/ + +#pragma once + +#include "Expression.hpp" +#include "Expression.hpp" +#include "DSequenceExpr.hpp" + +namespace xo { namespace scm { class IExpression_DSequenceExpr; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::IExpression_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IExpression_DSequenceExpr + **/ + class IExpression_DSequenceExpr { + public: + /** @defgroup scm-expression-dsequenceexpr-type-traits **/ + ///@{ + using TypeDescr = xo::scm::AExpression::TypeDescr; + using Copaque = xo::scm::AExpression::Copaque; + using Opaque = xo::scm::AExpression::Opaque; + ///@} + /** @defgroup scm-expression-dsequenceexpr-methods **/ + ///@{ + // const methods + /** expression type (constant | apply | ..) **/ + static exprtype extype(const DSequenceExpr & self) noexcept; + /** placeholder for type giving possible values for this expression **/ + static TypeRef typeref(const DSequenceExpr & self) noexcept; + /** type giving possible values for this expression. Maybe null before typecheck **/ + static TypeDescr valuetype(const DSequenceExpr & self) noexcept; + + // non-const methods + /** assing to valuetype member. Useful when scaffolding expressions **/ + static void assign_valuetype(DSequenceExpr & self, TypeDescr td) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IExpression_DVarRef.hpp b/xo-expression2/include/xo/expression2/detail/IExpression_DVarRef.hpp new file mode 100644 index 00000000..332113c1 --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IExpression_DVarRef.hpp @@ -0,0 +1,66 @@ +/** @file IExpression_DVarRef.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IExpression_DVarRef.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IExpression_DVarRef.json5] + **/ + +#pragma once + +#include "Expression.hpp" +#include "Expression.hpp" +#include "DVarRef.hpp" + +namespace xo { namespace scm { class IExpression_DVarRef; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::IExpression_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IExpression_DVarRef + **/ + class IExpression_DVarRef { + public: + /** @defgroup scm-expression-dvarref-type-traits **/ + ///@{ + using TypeDescr = xo::scm::AExpression::TypeDescr; + using Copaque = xo::scm::AExpression::Copaque; + using Opaque = xo::scm::AExpression::Opaque; + ///@} + /** @defgroup scm-expression-dvarref-methods **/ + ///@{ + // const methods + /** expression type (constant | apply | ..) **/ + static exprtype extype(const DVarRef & self) noexcept; + /** placeholder for type giving possible values for this expression **/ + static TypeRef typeref(const DVarRef & self) noexcept; + /** type giving possible values for this expression. Maybe null before typecheck **/ + static TypeDescr valuetype(const DVarRef & self) noexcept; + + // non-const methods + /** assing to valuetype member. Useful when scaffolding expressions **/ + static void assign_valuetype(DVarRef & self, TypeDescr td) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IExpression_DVariable.hpp b/xo-expression2/include/xo/expression2/detail/IExpression_DVariable.hpp index 95b1becb..cacd4be2 100644 --- a/xo-expression2/include/xo/expression2/detail/IExpression_DVariable.hpp +++ b/xo-expression2/include/xo/expression2/detail/IExpression_DVariable.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IExpression_DVariable.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-expression2/include/xo/expression2/detail/IExpression_Xfer.hpp b/xo-expression2/include/xo/expression2/detail/IExpression_Xfer.hpp index 9f7356bc..095e21ed 100644 --- a/xo-expression2/include/xo/expression2/detail/IExpression_Xfer.hpp +++ b/xo-expression2/include/xo/expression2/detail/IExpression_Xfer.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/Expression.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -41,8 +41,11 @@ namespace scm { // from AExpression - // const methods + // builtin methods typeseq _typeseq() const noexcept override { return s_typeseq; } + void _drop(Opaque d) const noexcept override { _dcast(d).~DRepr(); } + + // const methods exprtype extype(Copaque data) const noexcept override { return I::extype(_dcast(data)); } @@ -89,4 +92,4 @@ namespace scm { } /*namespace scm */ } /*namespace xo*/ -/* end IExpression_Xfer.hpp */ \ No newline at end of file +/* end IExpression_Xfer.hpp */ diff --git a/xo-expression2/include/xo/expression2/detail/IGCObject_DApplyExpr.hpp b/xo-expression2/include/xo/expression2/detail/IGCObject_DApplyExpr.hpp new file mode 100644 index 00000000..10b08c10 --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IGCObject_DApplyExpr.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DApplyExpr.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DApplyExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DApplyExpr.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DApplyExpr.hpp" + +namespace xo { namespace scm { class IGCObject_DApplyExpr; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DApplyExpr + **/ + class IGCObject_DApplyExpr { + public: + /** @defgroup scm-gcobject-dapplyexpr-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dapplyexpr-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DApplyExpr & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DApplyExpr & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DApplyExpr & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IGCObject_DConstant.hpp b/xo-expression2/include/xo/expression2/detail/IGCObject_DConstant.hpp new file mode 100644 index 00000000..871f9c91 --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IGCObject_DConstant.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DConstant.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DConstant.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DConstant.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DConstant.hpp" + +namespace xo { namespace scm { class IGCObject_DConstant; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DConstant + **/ + class IGCObject_DConstant { + public: + /** @defgroup scm-gcobject-dconstant-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dconstant-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DConstant & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DConstant & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DConstant & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IGCObject_DIfElseExpr.hpp b/xo-expression2/include/xo/expression2/detail/IGCObject_DIfElseExpr.hpp new file mode 100644 index 00000000..6a47d9b8 --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IGCObject_DIfElseExpr.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DIfElseExpr.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DIfElseExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DIfElseExpr.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DIfElseExpr.hpp" + +namespace xo { namespace scm { class IGCObject_DIfElseExpr; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DIfElseExpr + **/ + class IGCObject_DIfElseExpr { + public: + /** @defgroup scm-gcobject-difelseexpr-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-difelseexpr-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DIfElseExpr & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DIfElseExpr & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DIfElseExpr & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IGCObject_DLambdaExpr.hpp b/xo-expression2/include/xo/expression2/detail/IGCObject_DLambdaExpr.hpp new file mode 100644 index 00000000..7d1ba5b0 --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IGCObject_DLambdaExpr.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DLambdaExpr.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DLambdaExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DLambdaExpr.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DLambdaExpr.hpp" + +namespace xo { namespace scm { class IGCObject_DLambdaExpr; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DLambdaExpr + **/ + class IGCObject_DLambdaExpr { + public: + /** @defgroup scm-gcobject-dlambdaexpr-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dlambdaexpr-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DLambdaExpr & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DLambdaExpr & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DLambdaExpr & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IGCObject_DSequenceExpr.hpp b/xo-expression2/include/xo/expression2/detail/IGCObject_DSequenceExpr.hpp new file mode 100644 index 00000000..1f6b8deb --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IGCObject_DSequenceExpr.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DSequenceExpr.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DSequenceExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DSequenceExpr.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DSequenceExpr.hpp" + +namespace xo { namespace scm { class IGCObject_DSequenceExpr; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DSequenceExpr + **/ + class IGCObject_DSequenceExpr { + public: + /** @defgroup scm-gcobject-dsequenceexpr-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dsequenceexpr-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DSequenceExpr & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DSequenceExpr & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DSequenceExpr & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IGCObject_DUniqueString.hpp b/xo-expression2/include/xo/expression2/detail/IGCObject_DUniqueString.hpp index b971daea..398e3eed 100644 --- a/xo-expression2/include/xo/expression2/detail/IGCObject_DUniqueString.hpp +++ b/xo-expression2/include/xo/expression2/detail/IGCObject_DUniqueString.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IGCObject_DUniqueString.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-expression2/include/xo/expression2/detail/IGCObject_DVarRef.hpp b/xo-expression2/include/xo/expression2/detail/IGCObject_DVarRef.hpp new file mode 100644 index 00000000..e991ebb8 --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IGCObject_DVarRef.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DVarRef.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DVarRef.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DVarRef.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DVarRef.hpp" + +namespace xo { namespace scm { class IGCObject_DVarRef; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DVarRef + **/ + class IGCObject_DVarRef { + public: + /** @defgroup scm-gcobject-dvarref-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dvarref-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DVarRef & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DVarRef & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DVarRef & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IGCObject_DVariable.hpp b/xo-expression2/include/xo/expression2/detail/IGCObject_DVariable.hpp new file mode 100644 index 00000000..242f335f --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IGCObject_DVariable.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DVariable.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DVariable.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DVariable.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DVariable.hpp" + +namespace xo { namespace scm { class IGCObject_DVariable; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DVariable + **/ + class IGCObject_DVariable { + public: + /** @defgroup scm-gcobject-dvariable-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dvariable-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DVariable & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DVariable & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DVariable & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IPrintable_DApplyExpr.hpp b/xo-expression2/include/xo/expression2/detail/IPrintable_DApplyExpr.hpp new file mode 100644 index 00000000..930846ce --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IPrintable_DApplyExpr.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DApplyExpr.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DApplyExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DApplyExpr.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DApplyExpr.hpp" + +namespace xo { namespace scm { class IPrintable_DApplyExpr; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DApplyExpr + **/ + class IPrintable_DApplyExpr { + public: + /** @defgroup scm-printable-dapplyexpr-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dapplyexpr-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DApplyExpr & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IPrintable_DConstant.hpp b/xo-expression2/include/xo/expression2/detail/IPrintable_DConstant.hpp new file mode 100644 index 00000000..dc907b89 --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IPrintable_DConstant.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DConstant.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DConstant.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DConstant.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DConstant.hpp" + +namespace xo { namespace scm { class IPrintable_DConstant; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DConstant + **/ + class IPrintable_DConstant { + public: + /** @defgroup scm-printable-dconstant-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dconstant-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DConstant & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IPrintable_DDefineExpr.hpp b/xo-expression2/include/xo/expression2/detail/IPrintable_DDefineExpr.hpp new file mode 100644 index 00000000..f399c743 --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IPrintable_DDefineExpr.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DDefineExpr.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DDefineExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DDefineExpr.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DDefineExpr.hpp" + +namespace xo { namespace scm { class IPrintable_DDefineExpr; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DDefineExpr + **/ + class IPrintable_DDefineExpr { + public: + /** @defgroup scm-printable-ddefineexpr-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-ddefineexpr-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DDefineExpr & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IPrintable_DIfElseExpr.hpp b/xo-expression2/include/xo/expression2/detail/IPrintable_DIfElseExpr.hpp new file mode 100644 index 00000000..f4045504 --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IPrintable_DIfElseExpr.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DIfElseExpr.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DIfElseExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DIfElseExpr.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DIfElseExpr.hpp" + +namespace xo { namespace scm { class IPrintable_DIfElseExpr; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DIfElseExpr + **/ + class IPrintable_DIfElseExpr { + public: + /** @defgroup scm-printable-difelseexpr-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-difelseexpr-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DIfElseExpr & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IPrintable_DLambdaExpr.hpp b/xo-expression2/include/xo/expression2/detail/IPrintable_DLambdaExpr.hpp new file mode 100644 index 00000000..c14cfefe --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IPrintable_DLambdaExpr.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DLambdaExpr.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DLambdaExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DLambdaExpr.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DLambdaExpr.hpp" + +namespace xo { namespace scm { class IPrintable_DLambdaExpr; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DLambdaExpr + **/ + class IPrintable_DLambdaExpr { + public: + /** @defgroup scm-printable-dlambdaexpr-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dlambdaexpr-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DLambdaExpr & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IPrintable_DSequenceExpr.hpp b/xo-expression2/include/xo/expression2/detail/IPrintable_DSequenceExpr.hpp new file mode 100644 index 00000000..a27ba9a4 --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IPrintable_DSequenceExpr.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DSequenceExpr.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DSequenceExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DSequenceExpr.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DSequenceExpr.hpp" + +namespace xo { namespace scm { class IPrintable_DSequenceExpr; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DSequenceExpr + **/ + class IPrintable_DSequenceExpr { + public: + /** @defgroup scm-printable-dsequenceexpr-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dsequenceexpr-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DSequenceExpr & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IPrintable_DUniqueString.hpp b/xo-expression2/include/xo/expression2/detail/IPrintable_DUniqueString.hpp index 34c9da79..a57039a8 100644 --- a/xo-expression2/include/xo/expression2/detail/IPrintable_DUniqueString.hpp +++ b/xo-expression2/include/xo/expression2/detail/IPrintable_DUniqueString.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IPrintable_DUniqueString.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-expression2/include/xo/expression2/detail/IPrintable_DVarRef.hpp b/xo-expression2/include/xo/expression2/detail/IPrintable_DVarRef.hpp new file mode 100644 index 00000000..50034312 --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IPrintable_DVarRef.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DVarRef.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DVarRef.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DVarRef.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DVarRef.hpp" + +namespace xo { namespace scm { class IPrintable_DVarRef; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DVarRef + **/ + class IPrintable_DVarRef { + public: + /** @defgroup scm-printable-dvarref-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dvarref-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DVarRef & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/IPrintable_DVariable.hpp b/xo-expression2/include/xo/expression2/detail/IPrintable_DVariable.hpp new file mode 100644 index 00000000..10bbecca --- /dev/null +++ b/xo-expression2/include/xo/expression2/detail/IPrintable_DVariable.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DVariable.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DVariable.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DVariable.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DVariable.hpp" + +namespace xo { namespace scm { class IPrintable_DVariable; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DVariable + **/ + class IPrintable_DVariable { + public: + /** @defgroup scm-printable-dvariable-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dvariable-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DVariable & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/detail/RExpression.hpp b/xo-expression2/include/xo/expression2/detail/RExpression.hpp index caf69fe0..89a8990f 100644 --- a/xo-expression2/include/xo/expression2/detail/RExpression.hpp +++ b/xo-expression2/include/xo/expression2/detail/RExpression.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/Expression.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -46,8 +46,13 @@ public: /** @defgroup scm-expression-router-methods **/ ///@{ - // const methods + // explicit injected content + + // builtin methods typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); } + void _drop() const noexcept { O::iface()->_drop(O::data()); } + + // const methods exprtype extype() const noexcept { return O::iface()->extype(O::data()); } @@ -86,4 +91,4 @@ namespace xo { namespace facet { }; } } -/* end RExpression.hpp */ \ No newline at end of file +/* end RExpression.hpp */ diff --git a/xo-expression2/include/xo/expression2/exprtype.hpp b/xo-expression2/include/xo/expression2/exprtype.hpp index 0d5e8299..8b1778fb 100644 --- a/xo-expression2/include/xo/expression2/exprtype.hpp +++ b/xo-expression2/include/xo/expression2/exprtype.hpp @@ -23,23 +23,29 @@ namespace xo { #ifdef NOT_YET /** a literal constant that refers to a linkable named function **/ primitive, +#endif /** variable/function definition **/ define, +#ifdef NOT_YET /** variable assignment **/ assign, +#endif /** function call **/ apply, + /** function definition **/ lambda, -#endif - /** variable reference **/ + + /** variable definition **/ variable, -#ifdef NOT_YET + /** variabele reference (possibly non-local) **/ + varref, /** if-then-else **/ ifexpr, /** sequence **/ sequence, - /** type conversion **/ +#ifdef NOT_YET + ) /** type conversion **/ convert, #endif @@ -55,16 +61,22 @@ namespace xo { case exprtype::constant: return "constant"; #ifdef NOT_YET case exprtype::primitive: return "primitive"; +#endif case exprtype::define: return "define"; +#ifdef NOT_YET case exprtype::assign: return "assign"; +#endif case exprtype::apply: return "apply"; case exprtype::lambda: return "lambda"; case exprtype::variable: return "variable"; + case exprtype::varref: return "varref"; case exprtype::ifexpr: return "if_expr"; case exprtype::sequence: return "sequence"; +#ifdef NOT_YET case exprtype::convert: return "convert"; #endif - default: break; + case exprtype::N: break; + //default: break; } return "???exprtype???"; diff --git a/xo-expression2/include/xo/expression2/symtab/ASymbolTable.hpp b/xo-expression2/include/xo/expression2/symtab/ASymbolTable.hpp index 36d4c812..59cf246f 100644 --- a/xo-expression2/include/xo/expression2/symtab/ASymbolTable.hpp +++ b/xo-expression2/include/xo/expression2/symtab/ASymbolTable.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/SymbolTable.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -47,6 +47,8 @@ public: // const methods /** RTTI: unique id# for actual runtime data representation **/ virtual typeseq _typeseq() const noexcept = 0; + /** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/ + virtual void _drop(Opaque d) const noexcept = 0; /** true iff this is toplevel (global) symbol table. **/ virtual bool is_global_symtab(Copaque data) const noexcept = 0; /** report ingredients needed to address variable at runtime. **/ @@ -72,4 +74,4 @@ using ISymbolTable_ImplType = xo::facet::FacetImplType; } /*namespace scm*/ } /*namespace xo*/ -/* ASymbolTable.hpp */ \ No newline at end of file +/* ASymbolTable.hpp */ diff --git a/xo-expression2/include/xo/expression2/symtab/IGCObject_DGlobalSymtab.hpp b/xo-expression2/include/xo/expression2/symtab/IGCObject_DGlobalSymtab.hpp new file mode 100644 index 00000000..92149015 --- /dev/null +++ b/xo-expression2/include/xo/expression2/symtab/IGCObject_DGlobalSymtab.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DGlobalSymtab.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DGlobalSymtab.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DGlobalSymtab.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DGlobalSymtab.hpp" + +namespace xo { namespace scm { class IGCObject_DGlobalSymtab; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DGlobalSymtab + **/ + class IGCObject_DGlobalSymtab { + public: + /** @defgroup scm-gcobject-dglobalsymtab-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dglobalsymtab-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DGlobalSymtab & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DGlobalSymtab & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DGlobalSymtab & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/symtab/IGCObject_DLocalSymtab.hpp b/xo-expression2/include/xo/expression2/symtab/IGCObject_DLocalSymtab.hpp new file mode 100644 index 00000000..94b9e279 --- /dev/null +++ b/xo-expression2/include/xo/expression2/symtab/IGCObject_DLocalSymtab.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DLocalSymtab.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DLocalSymtab.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DLocalSymtab.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DLocalSymtab.hpp" + +namespace xo { namespace scm { class IGCObject_DLocalSymtab; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DLocalSymtab + **/ + class IGCObject_DLocalSymtab { + public: + /** @defgroup scm-gcobject-dlocalsymtab-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dlocalsymtab-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DLocalSymtab & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DLocalSymtab & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DLocalSymtab & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/symtab/IPrintable_DGlobalSymtab.hpp b/xo-expression2/include/xo/expression2/symtab/IPrintable_DGlobalSymtab.hpp new file mode 100644 index 00000000..3e6d065c --- /dev/null +++ b/xo-expression2/include/xo/expression2/symtab/IPrintable_DGlobalSymtab.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DGlobalSymtab.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DGlobalSymtab.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DGlobalSymtab.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DGlobalSymtab.hpp" + +namespace xo { namespace scm { class IPrintable_DGlobalSymtab; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DGlobalSymtab + **/ + class IPrintable_DGlobalSymtab { + public: + /** @defgroup scm-printable-dglobalsymtab-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dglobalsymtab-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DGlobalSymtab & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/symtab/IPrintable_DLocalSymtab.hpp b/xo-expression2/include/xo/expression2/symtab/IPrintable_DLocalSymtab.hpp new file mode 100644 index 00000000..729534c0 --- /dev/null +++ b/xo-expression2/include/xo/expression2/symtab/IPrintable_DLocalSymtab.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DLocalSymtab.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DLocalSymtab.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DLocalSymtab.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DLocalSymtab.hpp" + +namespace xo { namespace scm { class IPrintable_DLocalSymtab; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DLocalSymtab + **/ + class IPrintable_DLocalSymtab { + public: + /** @defgroup scm-printable-dlocalsymtab-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dlocalsymtab-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DLocalSymtab & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/symtab/ISymbolTable_Any.hpp b/xo-expression2/include/xo/expression2/symtab/ISymbolTable_Any.hpp index 6a119832..2d873ea1 100644 --- a/xo-expression2/include/xo/expression2/symtab/ISymbolTable_Any.hpp +++ b/xo-expression2/include/xo/expression2/symtab/ISymbolTable_Any.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/SymbolTable.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -53,8 +53,11 @@ namespace scm { // from ASymbolTable - // const methods + // builtin methods typeseq _typeseq() const noexcept override { return s_typeseq; } + [[noreturn]] void _drop(Opaque) const noexcept override { _fatal(); } + + // const methods [[noreturn]] bool is_global_symtab(Copaque) const noexcept override { _fatal(); } [[noreturn]] Binding lookup_binding(Copaque, const DUniqueString *) const noexcept override { _fatal(); } @@ -83,4 +86,4 @@ namespace scm { } /*namespace scm */ } /*namespace xo */ -/* ISymbolTable_Any.hpp */ \ No newline at end of file +/* ISymbolTable_Any.hpp */ diff --git a/xo-expression2/include/xo/expression2/symtab/ISymbolTable_DGlobalSymtab.hpp b/xo-expression2/include/xo/expression2/symtab/ISymbolTable_DGlobalSymtab.hpp new file mode 100644 index 00000000..64f90528 --- /dev/null +++ b/xo-expression2/include/xo/expression2/symtab/ISymbolTable_DGlobalSymtab.hpp @@ -0,0 +1,60 @@ +/** @file ISymbolTable_DGlobalSymtab.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISymbolTable_DGlobalSymtab.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISymbolTable_DGlobalSymtab.json5] + **/ + +#pragma once + +#include "SymbolTable.hpp" +#include "DGlobalSymtab.hpp" + +namespace xo { namespace scm { class ISymbolTable_DGlobalSymtab; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISymbolTable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISymbolTable_DGlobalSymtab + **/ + class ISymbolTable_DGlobalSymtab { + public: + /** @defgroup scm-symboltable-dglobalsymtab-type-traits **/ + ///@{ + using Copaque = xo::scm::ASymbolTable::Copaque; + using Opaque = xo::scm::ASymbolTable::Opaque; + ///@} + /** @defgroup scm-symboltable-dglobalsymtab-methods **/ + ///@{ + // const methods + /** true iff this is toplevel (global) symbol table. **/ + static bool is_global_symtab(const DGlobalSymtab & self) noexcept; + /** report ingredients needed to address variable at runtime. **/ + static Binding lookup_binding(const DGlobalSymtab & self, const DUniqueString * sym) noexcept; + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/symtab/ISymbolTable_DLocalSymtab.hpp b/xo-expression2/include/xo/expression2/symtab/ISymbolTable_DLocalSymtab.hpp new file mode 100644 index 00000000..9c9a2f0d --- /dev/null +++ b/xo-expression2/include/xo/expression2/symtab/ISymbolTable_DLocalSymtab.hpp @@ -0,0 +1,60 @@ +/** @file ISymbolTable_DLocalSymtab.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISymbolTable_DLocalSymtab.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISymbolTable_DLocalSymtab.json5] + **/ + +#pragma once + +#include "SymbolTable.hpp" +#include "DLocalSymtab.hpp" + +namespace xo { namespace scm { class ISymbolTable_DLocalSymtab; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISymbolTable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISymbolTable_DLocalSymtab + **/ + class ISymbolTable_DLocalSymtab { + public: + /** @defgroup scm-symboltable-dlocalsymtab-type-traits **/ + ///@{ + using Copaque = xo::scm::ASymbolTable::Copaque; + using Opaque = xo::scm::ASymbolTable::Opaque; + ///@} + /** @defgroup scm-symboltable-dlocalsymtab-methods **/ + ///@{ + // const methods + /** true iff this is toplevel (global) symbol table. **/ + static bool is_global_symtab(const DLocalSymtab & self) noexcept; + /** report ingredients needed to address variable at runtime. **/ + static Binding lookup_binding(const DLocalSymtab & self, const DUniqueString * sym) noexcept; + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-expression2/include/xo/expression2/symtab/ISymbolTable_Xfer.hpp b/xo-expression2/include/xo/expression2/symtab/ISymbolTable_Xfer.hpp index 2333bb05..db81237f 100644 --- a/xo-expression2/include/xo/expression2/symtab/ISymbolTable_Xfer.hpp +++ b/xo-expression2/include/xo/expression2/symtab/ISymbolTable_Xfer.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/SymbolTable.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -39,8 +39,11 @@ namespace scm { // from ASymbolTable - // const methods + // builtin methods typeseq _typeseq() const noexcept override { return s_typeseq; } + void _drop(Opaque d) const noexcept override { _dcast(d).~DRepr(); } + + // const methods bool is_global_symtab(Copaque data) const noexcept override { return I::is_global_symtab(_dcast(data)); } @@ -81,4 +84,4 @@ namespace scm { } /*namespace scm */ } /*namespace xo*/ -/* end ISymbolTable_Xfer.hpp */ \ No newline at end of file +/* end ISymbolTable_Xfer.hpp */ diff --git a/xo-expression2/include/xo/expression2/symtab/RSymbolTable.hpp b/xo-expression2/include/xo/expression2/symtab/RSymbolTable.hpp index c72503cc..31405e89 100644 --- a/xo-expression2/include/xo/expression2/symtab/RSymbolTable.hpp +++ b/xo-expression2/include/xo/expression2/symtab/RSymbolTable.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/SymbolTable.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -45,8 +45,13 @@ public: /** @defgroup scm-symboltable-router-methods **/ ///@{ - // const methods + // explicit injected content + + // builtin methods typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); } + void _drop() const noexcept { O::iface()->_drop(O::data()); } + + // const methods bool is_global_symtab() const noexcept { return O::iface()->is_global_symtab(O::data()); } @@ -79,4 +84,4 @@ namespace xo { namespace facet { }; } } -/* end RSymbolTable.hpp */ \ No newline at end of file +/* end RSymbolTable.hpp */ diff --git a/xo-expression2/src/expression2/Binding.cpp b/xo-expression2/src/expression2/Binding.cpp new file mode 100644 index 00000000..94be9b6b --- /dev/null +++ b/xo-expression2/src/expression2/Binding.cpp @@ -0,0 +1,41 @@ +/** @file Binding.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "Binding.hpp" +#include + +namespace xo { + namespace scm { + + Binding + Binding::relative(int32_t i_link, Binding def) + { + if (def.i_link_ == Binding::c_link_global) { + // for globally defined vars, i_link always -1 + return def; + } else if (def.i_link_ >= 0) { + return Binding(i_link + def.i_link_, def.j_slot_); + } else { + assert(false); + return Binding(); + } + } + + void + Binding::print(std::ostream & os) const + { + if (i_link_ == c_link_global) { + os << "{path:global:" << j_slot_ << "}"; + } else if (i_link_ == c_link_sentinel) { + os << "{path}"; + } else { + os << "{path:" << i_link_ << ":" << j_slot_ << "}"; + } + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end Binding.cpp */ diff --git a/xo-expression2/src/expression2/CMakeLists.txt b/xo-expression2/src/expression2/CMakeLists.txt index 9194bfa5..f05cf2f1 100644 --- a/xo-expression2/src/expression2/CMakeLists.txt +++ b/xo-expression2/src/expression2/CMakeLists.txt @@ -3,33 +3,79 @@ set(SELF_LIB xo_expression2) set(SELF_SRCS init_expression2.cpp + expression2_register_facets.cpp + expression2_register_types.cpp DConstant.cpp DVariable.cpp + DVarRef.cpp + DApplyExpr.cpp TypeRef.cpp + Binding.cpp IExpression_Any.cpp - IExpression_DConstant.cpp - IExpression_DVariable.cpp - ISymbolTable_Any.cpp + IExpression_DConstant.cpp + IGCObject_DConstant.cpp + IPrintable_DConstant.cpp + + IExpression_DVariable.cpp + IGCObject_DVariable.cpp + IPrintable_DVariable.cpp + + IExpression_DVarRef.cpp + IGCObject_DVarRef.cpp + IPrintable_DVarRef.cpp + + DDefineExpr.cpp + IExpression_DDefineExpr.cpp + IGCObject_DDefineExpr.cpp + IPrintable_DDefineExpr.cpp + + IExpression_DApplyExpr.cpp + IGCObject_DApplyExpr.cpp + IPrintable_DApplyExpr.cpp + + DLambdaExpr.cpp + IExpression_DLambdaExpr.cpp + IGCObject_DLambdaExpr.cpp + IPrintable_DLambdaExpr.cpp + + DIfElseExpr.cpp + IExpression_DIfElseExpr.cpp + IGCObject_DIfElseExpr.cpp + IPrintable_DIfElseExpr.cpp + + DSequenceExpr.cpp + IExpression_DSequenceExpr.cpp + IGCObject_DSequenceExpr.cpp + IPrintable_DSequenceExpr.cpp + + DLocalSymtab.cpp + ISymbolTable_DLocalSymtab.cpp + IGCObject_DLocalSymtab.cpp + IPrintable_DLocalSymtab.cpp + + DGlobalSymtab.cpp + ISymbolTable_DGlobalSymtab.cpp + IGCObject_DGlobalSymtab.cpp + IPrintable_DGlobalSymtab.cpp + StringTable.cpp DUniqueString.cpp IGCObject_DUniqueString.cpp IPrintable_DUniqueString.cpp - expression2_register_facets.cpp - expression2_register_types.cpp ) xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS}) # note: deps here must also appear in cmake/xo_expression2Config.cmake.in xo_dependency(${SELF_LIB} xo_gc) xo_dependency(${SELF_LIB} reflect) -xo_dependency(${SELF_LIB} xo_object2) +xo_dependency(${SELF_LIB} xo_procedure2) xo_dependency(${SELF_LIB} xo_printable2) xo_dependency(${SELF_LIB} xo_flatstring) xo_dependency(${SELF_LIB} subsys) diff --git a/xo-expression2/src/expression2/DApplyExpr.cpp b/xo-expression2/src/expression2/DApplyExpr.cpp new file mode 100644 index 00000000..d4e1fa55 --- /dev/null +++ b/xo-expression2/src/expression2/DApplyExpr.cpp @@ -0,0 +1,202 @@ +/** @file DApplyExpr.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "Expression.hpp" +#include "DApplyExpr.hpp" +#include "detail/IExpression_DApplyExpr.hpp" +#include +#include + +namespace xo { + using xo::print::APrintable; + using xo::facet::FacetRegistry; + using xo::reflect::typeseq; + using xo::mm::AGCObject; + + namespace scm { + obj + DApplyExpr::make2(obj mm, + TypeRef typeref, + obj fn_expr, + obj arg1, + obj arg2) + { + return obj + (DApplyExpr::_make2(mm, typeref, fn_expr, arg1, arg2)); + } + + DApplyExpr * + DApplyExpr::_make2(obj mm, + TypeRef typeref, + obj fn_expr, + obj arg1, + obj arg2) + { + DApplyExpr * result + = DApplyExpr::scaffold(mm, typeref, fn_expr, 2 /*n_args*/); + + result->assign_arg(0, arg1); + result->assign_arg(1, arg2); + + return result; + } + + /* incomplete, in the sense that does not populate args_[] */ + DApplyExpr::DApplyExpr(TypeRef typeref, + obj fn_expr, + size_type n_args) : typeref_{typeref}, + fn_{fn_expr}, + n_args_{n_args} + {} + + DApplyExpr * + DApplyExpr::scaffold(obj mm, + TypeRef typeref, + obj fn_expr, + size_type n_args) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DApplyExpr) + (n_args * sizeof(obj))); + + DApplyExpr * result = new (mem) DApplyExpr(typeref, + fn_expr, + n_args); + + return result; + } + + void + DApplyExpr::assign_arg(size_type i_arg, + obj expr) + { + if (i_arg < n_args_) { + this->args_[i_arg] = expr; + } else { + assert(false); + + throw std::runtime_error(tostr("assign out-of-range argument i_arg where [0..n_args) expected", + xtag("i_arg", i_arg), + xtag("expr", expr), + xtag("n_args", n_args_))); + + } + } + + obj + DApplyExpr::arg(size_type i) const + { + if (i >= n_args_) [[unlikely]] { + throw std::runtime_error(tostr("attempt to fetch argument i where [0..n) expected", + xtag("i", i), + xtag("n", n_args_), + xtag("src", "DApplyExpr::arg"))); + } + + return args_[i]; + } + + void + DApplyExpr::assign_valuetype(TypeDescr td) noexcept { + typeref_.resolve(td); + } + + // ----- gcobject facet ----- + + std::size_t + DApplyExpr::shallow_size() const noexcept { + return sizeof(DApplyExpr) + (n_args_ * sizeof(obj)); + } + + DApplyExpr * + DApplyExpr::shallow_copy(obj mm) const noexcept { + DApplyExpr * copy = (DApplyExpr *)mm.alloc_copy((std::byte *)this); + + if (copy) { + copy->typeref_ = typeref_; + copy->fn_ = fn_; + copy->n_args_ = n_args_; + + constexpr auto c_obj_z = sizeof(obj); + + ::memcpy((void*)&(copy->args_[0]), (void*)&(args_[0]), n_args_ * c_obj_z); + } + + return copy; + } + + std::size_t + DApplyExpr::forward_children(obj gc) noexcept + { + for (size_type i = 0; i < n_args_; ++i) { + obj & arg = args_[i]; + + // runtime poly here + obj arg_gco = arg.to_facet(); + + // need the data address within *this + gc.forward_inplace(arg_gco.iface(), (void **)(&arg.data_)); + } + + return shallow_size(); + } + + // ----- printable facet ----- + + bool + DApplyExpr::pretty(const ppindentinfo & ppii) const { + using xo::print::ppstate; + + ppstate * pps = ppii.pps(); + + if (ppii.upto()) { + /* perhaps print on one line */ + if (!pps->print_upto(" fn + = FacetRegistry::instance().variant(fn_); + if (!pps->print_upto(refrtag("fn", fn))) + return false; + } + + for (size_t i_arg = 0; i_arg < n_args_; ++i_arg) { + obj arg_i + = FacetRegistry::instance().variant(args_[i_arg]); + + if (!pps->print_upto(refrtag(concat("arg", 1+i_arg), arg_i))) + return false; + } + + pps->write(">"); + + return true; + } else { + pps->write(" fn + = FacetRegistry::instance().variant(fn_); + + pps->newline_indent(ppii.ci1()); + pps->pretty(refrtag("fn", fn)); + + for (size_t i_arg = 0; i_arg < n_args_; ++i_arg) { + obj arg_i + = FacetRegistry::instance().variant(args_[i_arg]); + + pps->newline_indent(ppii.ci1()); + pps->pretty(refrtag(concat("arg", 1+i_arg), arg_i)); + } + + pps->write(">"); + + return false; + } + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DApplyExpr.cpp */ diff --git a/xo-expression2/src/expression2/DConstant.cpp b/xo-expression2/src/expression2/DConstant.cpp index fcb38f54..f1f560be 100644 --- a/xo-expression2/src/expression2/DConstant.cpp +++ b/xo-expression2/src/expression2/DConstant.cpp @@ -4,15 +4,21 @@ **/ #include "DConstant.hpp" +#include "detail/IExpression_DConstant.hpp" #include "TypeDescr.hpp" #include #include +#include +#include #include +#include #include namespace xo { using xo::scm::DFloat; using xo::scm::DInteger; + using xo::print::APrintable; + using xo::facet::FacetRegistry; using xo::reflect::Reflect; using xo::reflect::TypeDescr; using xo::reflect::typeseq; @@ -34,6 +40,23 @@ namespace xo { } } + obj + DConstant::make(obj mm, + obj value) + { + return obj(_make(mm, value)); + } + + DConstant * + DConstant::_make(obj mm, + obj value) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DConstant)); + + return new (mem) DConstant(value); + } + TypeDescr DConstant::_lookup_td(typeseq tseq) { @@ -47,6 +70,45 @@ namespace xo { return nullptr; } + + std::size_t + DConstant::shallow_size() const noexcept + { + return sizeof(DConstant); + } + + DConstant * + DConstant::shallow_copy(obj mm) const noexcept + { + DConstant * copy = (DConstant *)mm.alloc_copy((std::byte *)this); + + if (copy) + *copy = *this; + + return copy; + } + + std::size_t + DConstant::forward_children(obj gc) noexcept + { + gc.forward_inplace(value_.iface(), (void **)&(value_.data_)); + + return shallow_size(); + } + + bool + DConstant::pretty(const ppindentinfo & ppii) const + { + obj value_pr + = FacetRegistry::instance().variant(value_); + + return ppii.pps()->pretty_struct + (ppii, + "DConstant", + refrtag("value_.tseq", value_._typeseq()), + refrtag("value.tseq", value_pr._typeseq()), + refrtag("value", value_pr)); + } } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-expression2/src/expression2/DDefineExpr.cpp b/xo-expression2/src/expression2/DDefineExpr.cpp new file mode 100644 index 00000000..aee6ccf9 --- /dev/null +++ b/xo-expression2/src/expression2/DDefineExpr.cpp @@ -0,0 +1,143 @@ +/** @file DDefineExpr.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "DDefineExpr.hpp" +#include "Variable.hpp" +#include +#include +#include +#include +#include +#include + +namespace xo { + using xo::mm::poly_forward_inplace; + using xo::print::APrintable; + using xo::facet::FacetRegistry; + using xo::facet::typeseq; + + namespace scm { + + DDefineExpr::DDefineExpr(DVariable * lhs_var, + obj rhs) + : lhs_var_{lhs_var}, rhs_{rhs} + {} + + DDefineExpr * + DDefineExpr::make(obj mm, + const DUniqueString * lhs_name, + obj rhs_expr) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DDefineExpr)); + + TypeRef rhs_tref; + if (rhs_expr) + rhs_tref = rhs_expr.typeref(); + + auto lhs_var = DVariable::make(mm, + lhs_name, + rhs_tref); + + return new (mem) DDefineExpr(lhs_var, rhs_expr); + } + + DDefineExpr * + DDefineExpr::make_empty(obj mm) + { + return make(mm, + nullptr /*lhs_name*/, + obj() /*rhs_expr*/); + } + + const DUniqueString * + DDefineExpr::name() const noexcept + { + return lhs_var_->name(); + } + + void + DDefineExpr::assign_lhs_name(const DUniqueString * name) + { + lhs_var_->assign_name(name); + } + + void + DDefineExpr::assign_valuetype(TypeDescr td) noexcept + { + lhs_var_->assign_valuetype(td); + } + + void + DDefineExpr::assign_rhs(obj x) + { + this->rhs_ = x; + } + + // ----- GCObject facet ----- + + std::size_t + DDefineExpr::shallow_size() const noexcept + { + return sizeof(*this); + } + + DDefineExpr * + DDefineExpr::shallow_copy(obj mm) const noexcept + { + return mm.std_copy_for(this); + } + + std::size_t + DDefineExpr::forward_children(obj gc) noexcept + { + gc.forward_inplace(&lhs_var_); + //gc.forward_inplace(&rhs_); // complicated - need to access via GCObject facet + poly_forward_inplace(gc, &rhs_); + + return this->shallow_size(); + } + + bool + DDefineExpr::pretty(const ppindentinfo & ppii) const + { + assert(lhs_var_); + + auto lhs = obj(lhs_var_); + auto rhs = FacetRegistry::instance().try_variant(rhs_); + + if (lhs_var_) + assert(lhs.data()); + + (void)lhs; + (void)rhs; + + if (rhs_) + assert(rhs.data()); + + // note: xo::print::cond() doesn't resolve the way we want here + + if (rhs) { + return ppii.pps()->pretty_struct + (ppii, + "DDefineExpr" + , refrtag("lhs", lhs) + , refrtag("rhs", rhs) + ); + } else { + return ppii.pps()->pretty_struct + (ppii, + "DDefineExpr" + , refrtag("lhs", lhs) + ); + + } + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DDefineExpr.cpp */ diff --git a/xo-expression2/src/expression2/DGlobalSymtab.cpp b/xo-expression2/src/expression2/DGlobalSymtab.cpp new file mode 100644 index 00000000..38809a38 --- /dev/null +++ b/xo-expression2/src/expression2/DGlobalSymtab.cpp @@ -0,0 +1,219 @@ +/** @file DGlobalSymtab.cpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#include "DGlobalSymtab.hpp" +#include "DUniqueString.hpp" +#include +#include +#include +#include +#include +#include + +namespace xo { + using xo::map::DArenaHashMap; + using xo::mm::AGCObject; + + namespace scm { + + DGlobalSymtab::DGlobalSymtab(dp map, + DArray * vars) + : map_{std::move(map)}, vars_{vars} + { + } + + dp + DGlobalSymtab::make(obj mm, + obj aux_mm, + const ArenaHashMapConfig & cfg) + { + auto map = dp::make(aux_mm, cfg); + assert(map); + + /* choosing same capacity for hash, vars */ + DArray * vars = DArray::empty(mm, map->capacity()); + assert(vars); + + auto symtab = dp::make(mm, std::move(map), vars); + assert(symtab); + + return symtab; + } + + void + DGlobalSymtab::visit_pools(const MemorySizeVisitor & visitor) const + { + if (map_) + map_->visit_pools(visitor); + } + + DVariable * + DGlobalSymtab::lookup_variable(const DUniqueString * sym) const noexcept + { + Binding existing = this->lookup_binding(sym); + + if (existing.is_null()) + return nullptr; + + auto var_gco = obj::from((*vars_)[existing.j_slot()]); + auto var = var_gco.to_facet(); + + assert(var.data()); + + return var.data(); + } + + void + DGlobalSymtab::upsert_variable(obj mm, + DVariable * var) + { + scope log(XO_DEBUG(true), std::string_view(*var->name())); + + // It's possible there's already a global variable + // with the same name. + // + // For example redefining a variable in an interactive session. + // In this case use the established binding. + // + DVariable * existing = this->lookup_variable(var->name()); + + if (existing) { + log && log("variable with this symbol already exists"); + + if (existing == var) { + // impossible, but.. noop, right? + return; + } + + // adopt the existing binding + var->assign_path(existing->path()); + + // stash new definition (possibly has different type), + // replacing previous one + // + (*vars_)[existing->path().j_slot()] = obj(var); + } else { + log && log("variable is new"); + + DArray::size_type n = vars_->size(); + + // NOTE: expansion of var_ array here is moot at present (Feb 2026), + // since the feature isn't yet implemented in ArenaHashMap + + /** make sure vars_ has room **/ + if (n == vars_->capacity()) { + // DArray is out of room. Reallocate with more capacity + DArray * vars_2x = DArray::copy(mm, vars_, vars_->capacity() * 2); + + if (!vars_2x) { + assert(false); + + // in any case, we can't make progress + return; + } + + this->vars_ = vars_2x; + } + + /** now we know binding for var **/ + Binding binding = Binding::global(n); + + var->assign_path(binding); + + // need slot# in .map_ for this unique symbol + (*map_)[var->name()] = binding.j_slot(); + + vars_->push_back(obj(var)); + } + } + +#ifdef NOT_USING // don't know if we need this path + DVariable * + DGlobalSymtab::establish_variable(obj mm, + const DUniqueString * sym, + TypeRef typeref) + { + DVariable * var = this->lookup_variable(sym); + + if (!var) { + assert(vars_); + + xxx; + } + + return var; + } +#endif + + Binding + DGlobalSymtab::lookup_binding(const DUniqueString * sym) const noexcept + { + assert(sym); + + scope log(XO_DEBUG(true), std::string_view(*sym)); + + auto ix = map_->find(sym); + + if (ix == map_->end()) + return Binding::null(); + + return Binding::global(ix->second); + } + + // ----- gcobject facet ----- + + std::size_t + DGlobalSymtab::shallow_size() const noexcept + { + return sizeof(DGlobalSymtab); + } + + DGlobalSymtab * + DGlobalSymtab::shallow_copy(obj mm) const noexcept + { + /** can't use std_copy_for because of non-copyable dp + * + * TODO: rename to shallow_move() throughout, and have std_copy_for() + * -> std_move_for() + * + **/ + + void * copy_mem = mm.alloc_copy_for(this); + + if (copy_mem) { + DGlobalSymtab * self = const_cast(this); + + return new (copy_mem) DGlobalSymtab(std::move(self->map_), vars_); + } + + return nullptr; + } + + std::size_t + DGlobalSymtab::forward_children(obj gc) noexcept + { + // map_ doesn't contain any gc-owned data, can skip + + gc.forward_inplace(&vars_); + + return this->shallow_size(); + } + + // ----- printable facet ----- + + bool + DGlobalSymtab::pretty(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct + (ppii, + "DGlobalSymtab", + refrtag("nsym", vars_->size()), + refrtag("capacity", vars_->capacity())); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DGlobalSymtab.cpp */ diff --git a/xo-expression2/src/expression2/DIfElseExpr.cpp b/xo-expression2/src/expression2/DIfElseExpr.cpp new file mode 100644 index 00000000..6a0b053c --- /dev/null +++ b/xo-expression2/src/expression2/DIfElseExpr.cpp @@ -0,0 +1,248 @@ +/** @file DIfElseExpr.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "DIfElseExpr.hpp" +#include "detail/IExpression_DIfElseExpr.hpp" +#include +#include +#include +#include + +namespace xo { + using xo::mm::AGCObject; + using xo::print::APrintable; + using xo::reflect::typeseq; + using xo::facet::FacetRegistry; + + namespace scm { + DIfElseExpr::DIfElseExpr(TypeRef ifexpr_tref, + obj test_expr, + obj when_true, + obj when_false) + : typeref_{ifexpr_tref}, + test_{test_expr}, + when_true_{when_true}, + when_false_{when_false} + {} + + obj + DIfElseExpr::make(obj mm, + obj test, + obj when_true, + obj when_false) + { + return obj + (_make(mm, + test, when_true, when_false)); + } + + DIfElseExpr * + DIfElseExpr::_make(obj mm, + obj test, + obj when_true, + obj when_false) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DIfElseExpr)); + + // just crete typevar here, then rely on type checking + // later + + auto prefix = TypeRef::prefix_type::from_chars("if"); + TypeRef tref = TypeRef::dwim(prefix, nullptr); + + return new (mem) DIfElseExpr(tref, + test, + when_true, + when_false); + } + + obj + DIfElseExpr::make_empty(obj mm) + { + return obj(_make_empty(mm)); + } + + DIfElseExpr * + DIfElseExpr::_make_empty(obj mm) + { + return _make(mm, + obj() /*test*/, + obj() /*when_true*/, + obj() /*when_false*/); + } + + void + DIfElseExpr::assign_valuetype(TypeDescr td) noexcept + { + typeref_.resolve(td); + } + + // GCObject facet + + std::size_t + DIfElseExpr::shallow_size() const noexcept + { + return sizeof(DIfElseExpr); + } + + DIfElseExpr * + DIfElseExpr::shallow_copy(obj mm) const noexcept + { + DIfElseExpr * copy = (DIfElseExpr *)mm.alloc_copy((std::byte *)this); + + if (copy) + *copy = *this; + + return copy; + } + + std::size_t + DIfElseExpr::forward_children(obj gc) noexcept + { + // GC needs to locate AGCObject iface for each member. + { + auto gco = FacetRegistry::instance().variant(test_); + gc.forward_inplace(gco.iface(), (void **)&(test_.data_)); + } + { + auto gco = FacetRegistry::instance().variant(when_true_); + gc.forward_inplace(gco.iface(), (void **)&(when_true_.data_)); + } + { + auto gco = FacetRegistry::instance().variant(when_false_); + gc.forward_inplace(gco.iface(), (void **)&(when_false_.data_)); + } + + return shallow_size(); + } + + // ----- printable facet ----- + + bool + DIfElseExpr::pretty(const ppindentinfo & ppii) const + { + auto test + = FacetRegistry::instance().try_variant(test_); + auto when_true + = FacetRegistry::instance().try_variant(when_true_); + auto when_false + = FacetRegistry::instance().try_variant(when_false_); + + bool test_present = test; + bool when_true_present = when_true; + bool when_false_present = when_false; + + return ppii.pps()->pretty_struct + (ppii, + "DIfElseExpr", + refrtag("typeref", typeref_), + refrtag("test", test, test_present), + refrtag("when_true", when_true, when_true_present), + refrtag("when_false", when_false, when_false_present)); + } + + // ---------------------------------------------------------------- + +#ifdef NOPE + auto IfExpr::check_consistent_valuetype(const rp & when_true, + const rp & when_false) -> TypeDescr + { + if (when_true->valuetype() != when_false->valuetype()) + return nullptr; + + return when_true->valuetype(); + } + + void IfExpr::establish_valuetype() + { + if (this->when_true_.get() && this->when_false_.get()) + this->assign_valuetype(check_consistent_valuetype(this->when_true_, this->when_false_)); + } + + rp + IfExpr::make(const rp & test, + const rp & when_true, + const rp & when_false) + { + /** TODO: verify test returns _boolean_ type **/ + + if (when_true->valuetype() != when_false->valuetype()) { + throw std::runtime_error + (tostr("IfExpr::make:" + " types {T1,T2} found for branches of if-expr" + " where equal types expected", + xtag("T1", when_true->valuetype()->canonical_name()), + xtag("T2", when_false->valuetype()->canonical_name()))); + } + + /* arbitrary choice here */ + auto ifexpr_type = when_true->valuetype(); + + return new IfExpr(ifexpr_type, + test, + when_true, + when_false); + } /*make*/ + + void + IfExpr::display(std::ostream & os) const { + os << ""; + } /*display*/ + + std::uint32_t + IfExpr::pretty_print(const ppindentinfo & ppii) const { + return ppii.pps()->pretty_struct(ppii, "IfExpr"); +#ifdef NOT_YET + return ppii.pps()->pretty_struct(ppii, "IfExpr", + refrtag("test", test_), + refrtag("when_true", when_true_), + refrtag("when_false", when_false_)); +#endif + } + + rp + IfExprAccess::make(rp test, + rp when_true, + rp when_false) + { + auto ifexpr_type = check_consistent_valuetype(when_true, when_false); + + return new IfExprAccess(ifexpr_type, std::move(test), std::move(when_true), std::move(when_false)); + } + + rp + IfExprAccess::make_empty() + { + return new IfExprAccess(nullptr /*ifexpr_valuetype*/, + nullptr /*test*/, + nullptr /*when_true*/, + nullptr /*when_false*/); + } + + void + IfExprAccess::assign_when_true(rp x) + { + this->when_true_ = std::move(x); + } + + void + IfExprAccess::assign_when_false(rp x) + { + this->when_false_ = std::move(x); + } +#endif + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DIfElseExpr.cpp */ diff --git a/xo-expression2/src/expression2/DLambdaExpr.cpp b/xo-expression2/src/expression2/DLambdaExpr.cpp new file mode 100644 index 00000000..56d55c03 --- /dev/null +++ b/xo-expression2/src/expression2/DLambdaExpr.cpp @@ -0,0 +1,207 @@ +/** @file DLambdaExpr.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "LambdaExpr.hpp" +#include "LocalSymtab.hpp" +#include "UniqueString.hpp" +#include +#include +#include +#include + +namespace xo { + using xo::mm::AGCObject; + using xo::print::APrintable; + using xo::facet::FacetRegistry; + using xo::reflect::TypeDescr; + using xo::reflect::TypeDescrBase; + using xo::reflect::FunctionTdxInfo; + using xo::reflect::typeseq; + using xo::print::quot; + + namespace scm { + +#ifdef NOT_YET + TypeDescr + assemble_lambda_td() + { + std::vector arg_td_v; + { + arg_td_v.reserve(local_symtab->size()); + + for (DLocalSymtab::size_type i = 0, n = local_symtab->size(); i < n; ++i) { + const DVariable * var = local_symtab->lookup_var(i); + + if (!var) + break; + + TypeDescr arg_td = var->valuetype(); + + if (!arg_td) + break; + + arg_td_v.push_back(arg_td); + } + } + } +#endif + + DLambdaExpr::DLambdaExpr(TypeRef typeref, + const DUniqueString * name, + DLocalSymtab * local_symtab, + obj body) : typeref_{typeref}, + name_{name}, + local_symtab_{local_symtab}, + body_expr_{body} + { + } + + obj + DLambdaExpr::make(obj mm, + TypeRef typeref, + const DUniqueString * name, + DLocalSymtab * local_symtab, + obj body) + { + return obj(_make(mm, typeref, + name, local_symtab, body)); + } + + DLambdaExpr * + DLambdaExpr::_make(obj mm, + TypeRef typeref, + const DUniqueString * name, + DLocalSymtab * local_symtab, + obj body) + { + // in general we're not going to know argument types yet. + // perhaps want to delay this until after type resolution. + + void * mem = mm.alloc(typeseq::id(), sizeof(DLambdaExpr)); + + return new (mem) DLambdaExpr(typeref, + name, + local_symtab, + body); + } + + TypeDescr + DLambdaExpr::assemble_lambda_td(DLocalSymtab * symtab, + TypeDescr return_td) + { + assert(return_td); + + std::vector arg_td_v; + { + DLocalSymtab::size_type z = symtab->size(); + + arg_td_v.reserve(z); + + for (DLocalSymtab::size_type i = 0; i < z; ++i) { + auto param = symtab->lookup_var(Binding::local(i)); + + assert(param); + arg_td_v.push_back(param->valuetype()); + } + } + + auto function_tdx = FunctionTdxInfo(return_td, arg_td_v, false /*!is_noexcept*/); + + TypeDescr lambda_td = TypeDescrBase::require_by_fn_info(function_tdx); + + return lambda_td; + } + + exprtype + DLambdaExpr::extype() const noexcept { + return exprtype::lambda; + } + + TypeRef + DLambdaExpr::typeref() const noexcept { + return typeref_; + } + + TypeDescr + DLambdaExpr::valuetype() const noexcept { + return typeref_.td(); + } + + void + DLambdaExpr::assign_valuetype(TypeDescr td) noexcept { + typeref_.resolve(td); + } + + std::size_t + DLambdaExpr::shallow_size() const noexcept { + return sizeof(DLambdaExpr); + } + + DLambdaExpr * + DLambdaExpr::shallow_copy(obj mm) const noexcept { + DLambdaExpr * copy = (DLambdaExpr *)mm.alloc_copy((std::byte *)this); + + if (copy) { + *copy = *this; + } + + return copy; + } + + std::size_t + DLambdaExpr::forward_children(obj gc) noexcept { + { + auto iface = xo::facet::impl_for(); + gc.forward_inplace(&iface, (void **)(&name_)); + } + + // type_name_str_ + + { + auto iface = xo::facet::impl_for(); + gc.forward_inplace(&iface, (void **)(&local_symtab_)); + } + + { + auto iface = body_expr_.to_facet().iface(); + gc.forward_inplace(iface, (void **)(&body_expr_)); + } + + // xxx free_var_set + // xxx captured_var_set + // xxx layer_var_map + // xxx nested_lambda_map + + return shallow_size(); + } + + bool + DLambdaExpr::pretty(const ppindentinfo & ppii) const + { + auto body + = FacetRegistry::instance().try_variant(body_expr_); + + if (name_ && body) { + auto local_symtab_pr + = obj(local_symtab_); + + return ppii.pps()->pretty_struct(ppii, + "LambdaExpr", + refrtag("tref", typeref_), + refrtag("name", quot(std::string_view(*name_))), + refrtag("local_symtab", local_symtab_pr), + //refrtag("argv", local_env_->argv()), + refrtag("body", body)); + } else { + return ppii.pps()->pretty_struct(ppii, + "LambdaExpr"); + } + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DLambda.cpp */ diff --git a/xo-expression2/src/expression2/DLocalSymtab.cpp b/xo-expression2/src/expression2/DLocalSymtab.cpp new file mode 100644 index 00000000..cf9c8459 --- /dev/null +++ b/xo-expression2/src/expression2/DLocalSymtab.cpp @@ -0,0 +1,175 @@ +/** @file DLocalSymtab.cpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#include "LocalSymtab.hpp" +#include "Variable.hpp" +#include "DUniqueString.hpp" +#include +#include + +namespace xo { + using xo::mm::AGCObject; + using xo::print::APrintable; + using xo::facet::typeseq; + using xo::print::ppstate; + + namespace scm { + + DLocalSymtab::DLocalSymtab(DLocalSymtab * p, + size_type n) : parent_{p}, + capacity_{n}, + size_{0} + { + for (size_type i = 0; i < n; ++i) { + void * mem = &slots_[i]; + new (mem) Slot(); + } + } + + DLocalSymtab * + DLocalSymtab::_make_empty(obj mm, + DLocalSymtab * p, + size_type n) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DLocalSymtab) + (n * sizeof(Slot))); + + return new (mem) DLocalSymtab(p, n); + } + + Binding + DLocalSymtab::append_var(obj mm, + const DUniqueString * name, + TypeRef typeref) + { + assert(name); + + if (size_ >= capacity_ || !name) { + assert(false); + + return Binding::null(); + } else { + size_type i_slot = (this->size_)++; + Binding binding = Binding::local(i_slot); + DVariable * var = DVariable::make(mm, name, typeref, binding); + + this->slots_[i_slot] = Slot(var); + + return binding; + } + } + + Binding + DLocalSymtab::lookup_binding(const DUniqueString * sym) const noexcept + { + assert(sym); + + if (sym) { + for (size_type i = 0; i < size_; ++i) { + const Slot & slot = slots_[i]; + + if (*sym == *(slot.var_->name())) + return slot.var_->path(); + } + } + + return Binding(); + } + + // ----- gcobject facet ----- + + std::size_t + DLocalSymtab::shallow_size() const noexcept + { + return (sizeof(DLocalSymtab) + (capacity_ * sizeof(Slot))); + } + + DLocalSymtab * + DLocalSymtab::shallow_copy(obj mm) const noexcept + { + DLocalSymtab * copy = (DLocalSymtab *)mm.alloc_copy((std::byte *)this); + + if (copy) { + *copy = *this; + + ::memcpy((void*)&(copy->slots_[0]), + (void*)&(slots_[0]), + capacity_ * sizeof(Slot)); + } + + return copy; + } + + std::size_t + DLocalSymtab::forward_children(obj gc) noexcept + { + { + auto iface + = xo::facet::impl_for(); + gc.forward_inplace(&iface, (void **)(&parent_)); + } + + auto iface + = xo::facet::impl_for(); + for (size_type i = 0; i < size_; ++i) { + gc.forward_inplace(&iface, (void **)(&(slots_[i].var_))); + } + + return shallow_size(); + } + + // ----- printable facet ----- + + bool + DLocalSymtab::pretty(const ppindentinfo & ppii) const + { + ppstate * pps = ppii.pps(); + + if (ppii.upto()) { + /* perhaps print on one line */ + if (!pps->print_upto("print_upto(xrefrtag("size", size_))) + return false; + + for (size_type i = 0; i < size_; ++i) { + char buf[32]; + snprintf(buf, sizeof(buf), "[%u]", i); + + assert(slots_[i].var_); + + obj arg_pr(const_cast(slots_[i].var_)); + + if (!pps->print_upto(xrefrtag(buf, arg_pr))) + return false; + } + + pps->write(">"); + return true; + } else { + /* with line breaks */ + + pps->write("newline_pretty_tag(ppii.ci1(), "size", size_); + + for (size_type i = 0; i < size_; ++i) { + char buf[32]; + snprintf(buf, sizeof(buf), "[%u]", i); + + assert(slots_[i].var_); + + obj arg_pr(const_cast(slots_[i].var_)); + + pps->newline_pretty_tag(ppii.ci1(), buf, arg_pr); + } + + pps->write(">"); + return false; + } + } + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DLocalSymtab.cpp */ diff --git a/xo-expression2/src/expression2/DSequenceExpr.cpp b/xo-expression2/src/expression2/DSequenceExpr.cpp new file mode 100644 index 00000000..22b097fb --- /dev/null +++ b/xo-expression2/src/expression2/DSequenceExpr.cpp @@ -0,0 +1,144 @@ +/** @file DSequenceExpr.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "DSequenceExpr.hpp" +#include "detail/IExpression_DSequenceExpr.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace xo { + using xo::mm::AGCObject; + using xo::print::APrintable; + using xo::facet::FacetRegistry; + using xo::reflect::typeseq; + + namespace scm { + + obj + DSequenceExpr::make_empty(obj mm) + { + return obj(_make_empty(mm)); + } + + DSequenceExpr * + DSequenceExpr::_make_empty(obj mm) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DSequenceExpr)); + + DSequenceExpr * expr = new (mem) DSequenceExpr(); + + constexpr size_type c_hint_capacity = 8; + + /** allocate 2nd, so it comes after DSequenceExpr in + * memory. This may later allow realloc + **/ + DArray * expr_v = DArray::empty(mm, + c_hint_capacity); + + expr->expr_v_ = expr_v; + + return expr; + } + + auto + DSequenceExpr::size() const noexcept -> size_type + { + return expr_v_->size(); + } + + obj + DSequenceExpr::operator[](std::size_t i) const + { + obj gco = (*expr_v_)[i]; + + return FacetRegistry::instance().variant(gco); + } + + void + DSequenceExpr::push_back(obj mm, + obj expr) + { + if (expr_v_->size() == expr_v_->capacity()) { + /* reallocate+expand */ + + DArray * expr_2x_v + = DArray::empty(mm, 2 * expr_v_->capacity()); + + for (size_type i = 0, z = expr_v_->size(); i < z; ++i) { + expr_2x_v->push_back((*expr_2x_v)[i]); + } + + this->expr_v_ = expr_2x_v; + } + + obj expr_gco + = FacetRegistry::instance().variant(expr); + + this->expr_v_->push_back(expr_gco); + } + + void + DSequenceExpr::assign_valuetype(TypeDescr td) noexcept + { + typeref_.resolve(td); + } + + bool + DSequenceExpr::pretty(const ppindentinfo & ppii) const + { + using xo::print::ppstate; + + auto expr_v_pr = obj(expr_v_); + + return ppii.pps()->pretty_struct + (ppii, + "DSequenceExpr", + refrtag("expr_v", expr_v_pr)); + } + + // gc hooks for IGCObject_DSequenceExpr + + std::size_t + DSequenceExpr::shallow_size() const noexcept + { + return sizeof(DSequenceExpr); + } + + DSequenceExpr * + DSequenceExpr::shallow_copy(obj mm) const noexcept + { + DSequenceExpr * copy = (DSequenceExpr *)mm.alloc_copy((std::byte *)this); + + if (copy) + *copy = *this; + + return copy; + } + + std::size_t + DSequenceExpr::forward_children(obj gc) noexcept + { + // WARNING. + // if this proves problematic, + // may resort to obj for expr_v_ member + + auto iface = facet::impl_for(); + + gc.forward_inplace(&iface, (void**)&expr_v_); + + return this->shallow_size(); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DSequenceExpr.cpp */ diff --git a/xo-expression2/src/expression2/DVarRef.cpp b/xo-expression2/src/expression2/DVarRef.cpp new file mode 100644 index 00000000..afd9190e --- /dev/null +++ b/xo-expression2/src/expression2/DVarRef.cpp @@ -0,0 +1,105 @@ +/** @file DVarRef.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "DVarRef.hpp" + +namespace xo { + using xo::mm::AGCObject; + using xo::reflect::TypeDescr; + + namespace scm { + + DVarRef::DVarRef(DVariable * vardef, + Binding path) + : vardef_{vardef}, + path_{path} + {} + + DVarRef * + DVarRef::make(obj mm, + DVariable * vardef, + int32_t link) + { + assert(vardef); + + void * mem = mm.alloc_for(); + + return new (mem) DVarRef(vardef, + Binding::relative(link, + vardef->path())); + } + + const DUniqueString * + DVarRef::name() const { + return vardef_->name(); + } + + TypeRef + DVarRef::typeref() const noexcept { + assert(vardef_); + + return vardef_->typeref(); + } + + TypeDescr + DVarRef::valuetype() const noexcept + { + return this->typeref().td(); + } + + void + DVarRef::assign_valuetype(TypeDescr td) noexcept + { + assert(vardef_); + vardef_->assign_valuetype(td); + } + + // gcobject facet + + std::size_t + DVarRef::shallow_size() const noexcept + { + return sizeof(DVarRef); + } + + DVarRef * + DVarRef::shallow_copy(obj mm) const noexcept + { + DVarRef * copy = (DVarRef *)mm.alloc_copy((std::byte *)this); + + if (copy) + *copy = *this; + + return copy; + } + + std::size_t + DVarRef::forward_children(obj gc) noexcept + { + // TODO: this can be helper in RCollector interface + auto iface = xo::facet::impl_for(); + gc.forward_inplace(&iface, (void **)vardef_); + + // TODO: concept to indicate that no gc pointers in Binding + + return shallow_size(); + } + + // printable facet + + bool + DVarRef::pretty(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct + (ppii, + "DVarRef", + refrtag("name", std::string_view(*(this->name()))), + refrtag("path", this->path_)); + } + + } +} /*namespace xo*/ + +/* end DVarRef.cpp */ diff --git a/xo-expression2/src/expression2/DVariable.cpp b/xo-expression2/src/expression2/DVariable.cpp index f589da7b..ac051387 100644 --- a/xo-expression2/src/expression2/DVariable.cpp +++ b/xo-expression2/src/expression2/DVariable.cpp @@ -5,14 +5,85 @@ #include "DVariable.hpp" #include "exprtype.hpp" +#include +#include namespace xo { + using xo::mm::ACollector; + using xo::facet::typeseq; + namespace scm { + + DVariable * + DVariable::make(obj mm, + const DUniqueString * name, + const TypeRef & typeref, + Binding path) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DVariable)); + + return new (mem) DVariable(name, typeref, path); + } + + DVariable::DVariable(const DUniqueString * name, + const TypeRef & typeref, + Binding path) + : name_{name}, typeref_{typeref}, path_{path} + {} + void DVariable::assign_valuetype(TypeDescr td) noexcept { typeref_.resolve(td); } + + size_t + DVariable::shallow_size() const noexcept + { + return sizeof(DVariable); + } + + DVariable * + DVariable::shallow_copy(obj mm) const noexcept + { + DVariable * copy = (DVariable *)mm.alloc_copy((std::byte *)this); + + if (copy) { + *copy = *this; + } + + return copy; + } + + size_t + DVariable::forward_children(obj) noexcept + { + // nothing to collect. + // - DUniqueString never in GC space + // - TypeDescr not in GC space + // - path only integers + + return shallow_size(); + } + + bool + DVariable::pretty(const ppindentinfo & ppii) const + { + using xo::print::quot; + + auto name = (name_ + ? std::string_view(*name_) + : std::string_view("")); + + return ppii.pps()->pretty_struct + (ppii, + "DVariable" + , refrtag("name", quot(name)) + , refrtag("typeref", typeref_) + ); + } + } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-expression2/src/expression2/IExpression_Any.cpp b/xo-expression2/src/expression2/IExpression_Any.cpp index 7f60e5af..9557e7e7 100644 --- a/xo-expression2/src/expression2/IExpression_Any.cpp +++ b/xo-expression2/src/expression2/IExpression_Any.cpp @@ -44,4 +44,4 @@ IExpression_Any::assign_valuetype(Opaque, TypeDescr) noexcept -> void } /*namespace scm*/ } /*namespace xo*/ -/* end IExpression_Any.cpp */ \ No newline at end of file +/* end IExpression_Any.cpp */ diff --git a/xo-expression2/src/expression2/IExpression_DApplyExpr.cpp b/xo-expression2/src/expression2/IExpression_DApplyExpr.cpp new file mode 100644 index 00000000..4ee365e0 --- /dev/null +++ b/xo-expression2/src/expression2/IExpression_DApplyExpr.cpp @@ -0,0 +1,45 @@ +/** @file IExpression_DApplyExpr.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IExpression_DApplyExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IExpression_DApplyExpr.json5] +**/ + +#include "detail/IExpression_DApplyExpr.hpp" + +namespace xo { + namespace scm { + auto + IExpression_DApplyExpr::extype(const DApplyExpr & self) noexcept -> exprtype + { + return self.extype(); + } + + auto + IExpression_DApplyExpr::typeref(const DApplyExpr & self) noexcept -> TypeRef + { + return self.typeref(); + } + + auto + IExpression_DApplyExpr::valuetype(const DApplyExpr & self) noexcept -> TypeDescr + { + return self.valuetype(); + } + + auto + IExpression_DApplyExpr::assign_valuetype(DApplyExpr & self, TypeDescr td) noexcept -> void + { + self.assign_valuetype(td); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IExpression_DApplyExpr.cpp */ diff --git a/xo-expression2/src/expression2/IExpression_DConstant.cpp b/xo-expression2/src/expression2/IExpression_DConstant.cpp index 39f8135c..836a6aee 100644 --- a/xo-expression2/src/expression2/IExpression_DConstant.cpp +++ b/xo-expression2/src/expression2/IExpression_DConstant.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IExpression_DConstant.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -11,7 +11,7 @@ * [idl/IExpression_DConstant.json5] **/ -#include "IExpression_DConstant.hpp" +#include "detail/IExpression_DConstant.hpp" namespace xo { namespace scm { @@ -42,4 +42,4 @@ namespace xo { } /*namespace scm*/ } /*namespace xo*/ -/* end IExpression_DConstant.cpp */ \ No newline at end of file +/* end IExpression_DConstant.cpp */ diff --git a/xo-expression2/src/expression2/IExpression_DDefineExpr.cpp b/xo-expression2/src/expression2/IExpression_DDefineExpr.cpp new file mode 100644 index 00000000..f8f2429c --- /dev/null +++ b/xo-expression2/src/expression2/IExpression_DDefineExpr.cpp @@ -0,0 +1,45 @@ +/** @file IExpression_DDefineExpr.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IExpression_DDefineExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IExpression_DDefineExpr.json5] +**/ + +#include "detail/IExpression_DDefineExpr.hpp" + +namespace xo { + namespace scm { + auto + IExpression_DDefineExpr::extype(const DDefineExpr & self) noexcept -> exprtype + { + return self.extype(); + } + + auto + IExpression_DDefineExpr::typeref(const DDefineExpr & self) noexcept -> TypeRef + { + return self.typeref(); + } + + auto + IExpression_DDefineExpr::valuetype(const DDefineExpr & self) noexcept -> TypeDescr + { + return self.valuetype(); + } + + auto + IExpression_DDefineExpr::assign_valuetype(DDefineExpr & self, TypeDescr td) noexcept -> void + { + self.assign_valuetype(td); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IExpression_DDefineExpr.cpp */ diff --git a/xo-expression2/src/expression2/IExpression_DIfElseExpr.cpp b/xo-expression2/src/expression2/IExpression_DIfElseExpr.cpp new file mode 100644 index 00000000..947ca8de --- /dev/null +++ b/xo-expression2/src/expression2/IExpression_DIfElseExpr.cpp @@ -0,0 +1,45 @@ +/** @file IExpression_DIfElseExpr.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IExpression_DIfElseExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IExpression_DIfElseExpr.json5] +**/ + +#include "detail/IExpression_DIfElseExpr.hpp" + +namespace xo { + namespace scm { + auto + IExpression_DIfElseExpr::extype(const DIfElseExpr & self) noexcept -> exprtype + { + return self.extype(); + } + + auto + IExpression_DIfElseExpr::typeref(const DIfElseExpr & self) noexcept -> TypeRef + { + return self.typeref(); + } + + auto + IExpression_DIfElseExpr::valuetype(const DIfElseExpr & self) noexcept -> TypeDescr + { + return self.valuetype(); + } + + auto + IExpression_DIfElseExpr::assign_valuetype(DIfElseExpr & self, TypeDescr td) noexcept -> void + { + self.assign_valuetype(td); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IExpression_DIfElseExpr.cpp */ diff --git a/xo-expression2/src/expression2/IExpression_DLambdaExpr.cpp b/xo-expression2/src/expression2/IExpression_DLambdaExpr.cpp new file mode 100644 index 00000000..1b177c91 --- /dev/null +++ b/xo-expression2/src/expression2/IExpression_DLambdaExpr.cpp @@ -0,0 +1,45 @@ +/** @file IExpression_DLambdaExpr.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IExpression_DLambdaExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IExpression_DLambdaExpr.json5] +**/ + +#include "detail/IExpression_DLambdaExpr.hpp" + +namespace xo { + namespace scm { + auto + IExpression_DLambdaExpr::extype(const DLambdaExpr & self) noexcept -> exprtype + { + return self.extype(); + } + + auto + IExpression_DLambdaExpr::typeref(const DLambdaExpr & self) noexcept -> TypeRef + { + return self.typeref(); + } + + auto + IExpression_DLambdaExpr::valuetype(const DLambdaExpr & self) noexcept -> TypeDescr + { + return self.valuetype(); + } + + auto + IExpression_DLambdaExpr::assign_valuetype(DLambdaExpr & self, TypeDescr td) noexcept -> void + { + self.assign_valuetype(td); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IExpression_DLambdaExpr.cpp */ diff --git a/xo-expression2/src/expression2/IExpression_DSequenceExpr.cpp b/xo-expression2/src/expression2/IExpression_DSequenceExpr.cpp new file mode 100644 index 00000000..5ae4f3f7 --- /dev/null +++ b/xo-expression2/src/expression2/IExpression_DSequenceExpr.cpp @@ -0,0 +1,45 @@ +/** @file IExpression_DSequenceExpr.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IExpression_DSequenceExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IExpression_DSequenceExpr.json5] +**/ + +#include "detail/IExpression_DSequenceExpr.hpp" + +namespace xo { + namespace scm { + auto + IExpression_DSequenceExpr::extype(const DSequenceExpr & self) noexcept -> exprtype + { + return self.extype(); + } + + auto + IExpression_DSequenceExpr::typeref(const DSequenceExpr & self) noexcept -> TypeRef + { + return self.typeref(); + } + + auto + IExpression_DSequenceExpr::valuetype(const DSequenceExpr & self) noexcept -> TypeDescr + { + return self.valuetype(); + } + + auto + IExpression_DSequenceExpr::assign_valuetype(DSequenceExpr & self, TypeDescr td) noexcept -> void + { + self.assign_valuetype(td); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IExpression_DSequenceExpr.cpp */ diff --git a/xo-expression2/src/expression2/IExpression_DVarRef.cpp b/xo-expression2/src/expression2/IExpression_DVarRef.cpp new file mode 100644 index 00000000..843a0653 --- /dev/null +++ b/xo-expression2/src/expression2/IExpression_DVarRef.cpp @@ -0,0 +1,45 @@ +/** @file IExpression_DVarRef.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IExpression_DVarRef.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IExpression_DVarRef.json5] +**/ + +#include "detail/IExpression_DVarRef.hpp" + +namespace xo { + namespace scm { + auto + IExpression_DVarRef::extype(const DVarRef & self) noexcept -> exprtype + { + return self.extype(); + } + + auto + IExpression_DVarRef::typeref(const DVarRef & self) noexcept -> TypeRef + { + return self.typeref(); + } + + auto + IExpression_DVarRef::valuetype(const DVarRef & self) noexcept -> TypeDescr + { + return self.valuetype(); + } + + auto + IExpression_DVarRef::assign_valuetype(DVarRef & self, TypeDescr td) noexcept -> void + { + self.assign_valuetype(td); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IExpression_DVarRef.cpp */ diff --git a/xo-expression2/src/expression2/IExpression_DVariable.cpp b/xo-expression2/src/expression2/IExpression_DVariable.cpp index ca657c36..bea2a24e 100644 --- a/xo-expression2/src/expression2/IExpression_DVariable.cpp +++ b/xo-expression2/src/expression2/IExpression_DVariable.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IExpression_DVariable.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -42,4 +42,4 @@ namespace xo { } /*namespace scm*/ } /*namespace xo*/ -/* end IExpression_DVariable.cpp */ \ No newline at end of file +/* end IExpression_DVariable.cpp */ diff --git a/xo-expression2/src/expression2/IGCObject_DApplyExpr.cpp b/xo-expression2/src/expression2/IGCObject_DApplyExpr.cpp new file mode 100644 index 00000000..ad6571e0 --- /dev/null +++ b/xo-expression2/src/expression2/IGCObject_DApplyExpr.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DApplyExpr.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DApplyExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DApplyExpr.json5] +**/ + +#include "detail/IGCObject_DApplyExpr.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DApplyExpr::shallow_size(const DApplyExpr & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DApplyExpr::shallow_copy(const DApplyExpr & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DApplyExpr::forward_children(DApplyExpr & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DApplyExpr.cpp */ diff --git a/xo-expression2/src/expression2/IGCObject_DConstant.cpp b/xo-expression2/src/expression2/IGCObject_DConstant.cpp new file mode 100644 index 00000000..ea3be262 --- /dev/null +++ b/xo-expression2/src/expression2/IGCObject_DConstant.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DConstant.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DConstant.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DConstant.json5] +**/ + +#include "detail/IGCObject_DConstant.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DConstant::shallow_size(const DConstant & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DConstant::shallow_copy(const DConstant & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DConstant::forward_children(DConstant & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DConstant.cpp */ diff --git a/xo-expression2/src/expression2/IGCObject_DDefineExpr.cpp b/xo-expression2/src/expression2/IGCObject_DDefineExpr.cpp new file mode 100644 index 00000000..eb43932b --- /dev/null +++ b/xo-expression2/src/expression2/IGCObject_DDefineExpr.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DDefineExpr.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DDefineExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DDefineExpr.json5] +**/ + +#include "define/IGCObject_DDefineExpr.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DDefineExpr::shallow_size(const DDefineExpr & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DDefineExpr::shallow_copy(const DDefineExpr & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DDefineExpr::forward_children(DDefineExpr & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DDefineExpr.cpp */ diff --git a/xo-expression2/src/expression2/IGCObject_DGlobalSymtab.cpp b/xo-expression2/src/expression2/IGCObject_DGlobalSymtab.cpp new file mode 100644 index 00000000..d59e6bbf --- /dev/null +++ b/xo-expression2/src/expression2/IGCObject_DGlobalSymtab.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DGlobalSymtab.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DGlobalSymtab.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DGlobalSymtab.json5] +**/ + +#include "symtab/IGCObject_DGlobalSymtab.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DGlobalSymtab::shallow_size(const DGlobalSymtab & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DGlobalSymtab::shallow_copy(const DGlobalSymtab & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DGlobalSymtab::forward_children(DGlobalSymtab & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DGlobalSymtab.cpp */ diff --git a/xo-expression2/src/expression2/IGCObject_DIfElseExpr.cpp b/xo-expression2/src/expression2/IGCObject_DIfElseExpr.cpp new file mode 100644 index 00000000..8a0f03d5 --- /dev/null +++ b/xo-expression2/src/expression2/IGCObject_DIfElseExpr.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DIfElseExpr.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DIfElseExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DIfElseExpr.json5] +**/ + +#include "detail/IGCObject_DIfElseExpr.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DIfElseExpr::shallow_size(const DIfElseExpr & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DIfElseExpr::shallow_copy(const DIfElseExpr & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DIfElseExpr::forward_children(DIfElseExpr & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DIfElseExpr.cpp */ diff --git a/xo-expression2/src/expression2/IGCObject_DLambdaExpr.cpp b/xo-expression2/src/expression2/IGCObject_DLambdaExpr.cpp new file mode 100644 index 00000000..c7724cd5 --- /dev/null +++ b/xo-expression2/src/expression2/IGCObject_DLambdaExpr.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DLambdaExpr.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DLambdaExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DLambdaExpr.json5] +**/ + +#include "detail/IGCObject_DLambdaExpr.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DLambdaExpr::shallow_size(const DLambdaExpr & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DLambdaExpr::shallow_copy(const DLambdaExpr & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DLambdaExpr::forward_children(DLambdaExpr & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DLambdaExpr.cpp */ diff --git a/xo-expression2/src/expression2/IGCObject_DLocalSymtab.cpp b/xo-expression2/src/expression2/IGCObject_DLocalSymtab.cpp new file mode 100644 index 00000000..ca96d3b6 --- /dev/null +++ b/xo-expression2/src/expression2/IGCObject_DLocalSymtab.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DLocalSymtab.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DLocalSymtab.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DLocalSymtab.json5] +**/ + +#include "symtab/IGCObject_DLocalSymtab.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DLocalSymtab::shallow_size(const DLocalSymtab & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DLocalSymtab::shallow_copy(const DLocalSymtab & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DLocalSymtab::forward_children(DLocalSymtab & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DLocalSymtab.cpp */ diff --git a/xo-expression2/src/expression2/IGCObject_DSequenceExpr.cpp b/xo-expression2/src/expression2/IGCObject_DSequenceExpr.cpp new file mode 100644 index 00000000..54ad1bd5 --- /dev/null +++ b/xo-expression2/src/expression2/IGCObject_DSequenceExpr.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DSequenceExpr.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DSequenceExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DSequenceExpr.json5] +**/ + +#include "detail/IGCObject_DSequenceExpr.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DSequenceExpr::shallow_size(const DSequenceExpr & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DSequenceExpr::shallow_copy(const DSequenceExpr & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DSequenceExpr::forward_children(DSequenceExpr & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DSequenceExpr.cpp */ diff --git a/xo-expression2/src/expression2/IGCObject_DUniqueString.cpp b/xo-expression2/src/expression2/IGCObject_DUniqueString.cpp index b13b3f79..8238990f 100644 --- a/xo-expression2/src/expression2/IGCObject_DUniqueString.cpp +++ b/xo-expression2/src/expression2/IGCObject_DUniqueString.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IGCObject_DUniqueString.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -36,4 +36,4 @@ namespace xo { } /*namespace scm*/ } /*namespace xo*/ -/* end IGCObject_DUniqueString.cpp */ \ No newline at end of file +/* end IGCObject_DUniqueString.cpp */ diff --git a/xo-expression2/src/expression2/IGCObject_DVarRef.cpp b/xo-expression2/src/expression2/IGCObject_DVarRef.cpp new file mode 100644 index 00000000..61596baa --- /dev/null +++ b/xo-expression2/src/expression2/IGCObject_DVarRef.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DVarRef.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DVarRef.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DVarRef.json5] +**/ + +#include "detail/IGCObject_DVarRef.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DVarRef::shallow_size(const DVarRef & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DVarRef::shallow_copy(const DVarRef & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DVarRef::forward_children(DVarRef & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DVarRef.cpp */ diff --git a/xo-expression2/src/expression2/IGCObject_DVariable.cpp b/xo-expression2/src/expression2/IGCObject_DVariable.cpp new file mode 100644 index 00000000..ecc403ef --- /dev/null +++ b/xo-expression2/src/expression2/IGCObject_DVariable.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DVariable.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DVariable.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DVariable.json5] +**/ + +#include "detail/IGCObject_DVariable.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DVariable::shallow_size(const DVariable & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DVariable::shallow_copy(const DVariable & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DVariable::forward_children(DVariable & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DVariable.cpp */ diff --git a/xo-expression2/src/expression2/IPrintable_DApplyExpr.cpp b/xo-expression2/src/expression2/IPrintable_DApplyExpr.cpp new file mode 100644 index 00000000..06b7b752 --- /dev/null +++ b/xo-expression2/src/expression2/IPrintable_DApplyExpr.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DApplyExpr.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DApplyExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DApplyExpr.json5] +**/ + +#include "detail/IPrintable_DApplyExpr.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DApplyExpr::pretty(const DApplyExpr & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DApplyExpr.cpp */ diff --git a/xo-expression2/src/expression2/IPrintable_DConstant.cpp b/xo-expression2/src/expression2/IPrintable_DConstant.cpp new file mode 100644 index 00000000..57bd271f --- /dev/null +++ b/xo-expression2/src/expression2/IPrintable_DConstant.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DConstant.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DConstant.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DConstant.json5] +**/ + +#include "detail/IPrintable_DConstant.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DConstant::pretty(const DConstant & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DConstant.cpp */ diff --git a/xo-expression2/src/expression2/IPrintable_DDefineExpr.cpp b/xo-expression2/src/expression2/IPrintable_DDefineExpr.cpp new file mode 100644 index 00000000..2774e610 --- /dev/null +++ b/xo-expression2/src/expression2/IPrintable_DDefineExpr.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DDefineExpr.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DDefineExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DDefineExpr.json5] +**/ + +#include "detail/IPrintable_DDefineExpr.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DDefineExpr::pretty(const DDefineExpr & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DDefineExpr.cpp */ diff --git a/xo-expression2/src/expression2/IPrintable_DGlobalSymtab.cpp b/xo-expression2/src/expression2/IPrintable_DGlobalSymtab.cpp new file mode 100644 index 00000000..35ecf6e7 --- /dev/null +++ b/xo-expression2/src/expression2/IPrintable_DGlobalSymtab.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DGlobalSymtab.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DGlobalSymtab.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DGlobalSymtab.json5] +**/ + +#include "symtab/IPrintable_DGlobalSymtab.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DGlobalSymtab::pretty(const DGlobalSymtab & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DGlobalSymtab.cpp */ diff --git a/xo-expression2/src/expression2/IPrintable_DIfElseExpr.cpp b/xo-expression2/src/expression2/IPrintable_DIfElseExpr.cpp new file mode 100644 index 00000000..52694cb5 --- /dev/null +++ b/xo-expression2/src/expression2/IPrintable_DIfElseExpr.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DIfElseExpr.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DIfElseExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DIfElseExpr.json5] +**/ + +#include "detail/IPrintable_DIfElseExpr.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DIfElseExpr::pretty(const DIfElseExpr & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DIfElseExpr.cpp */ diff --git a/xo-expression2/src/expression2/IPrintable_DLambdaExpr.cpp b/xo-expression2/src/expression2/IPrintable_DLambdaExpr.cpp new file mode 100644 index 00000000..049a81c8 --- /dev/null +++ b/xo-expression2/src/expression2/IPrintable_DLambdaExpr.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DLambdaExpr.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DLambdaExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DLambdaExpr.json5] +**/ + +#include "detail/IPrintable_DLambdaExpr.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DLambdaExpr::pretty(const DLambdaExpr & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DLambdaExpr.cpp */ diff --git a/xo-expression2/src/expression2/IPrintable_DLocalSymtab.cpp b/xo-expression2/src/expression2/IPrintable_DLocalSymtab.cpp new file mode 100644 index 00000000..0e178e09 --- /dev/null +++ b/xo-expression2/src/expression2/IPrintable_DLocalSymtab.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DLocalSymtab.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DLocalSymtab.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DLocalSymtab.json5] +**/ + +#include "symtab/IPrintable_DLocalSymtab.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DLocalSymtab::pretty(const DLocalSymtab & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DLocalSymtab.cpp */ diff --git a/xo-expression2/src/expression2/IPrintable_DSequenceExpr.cpp b/xo-expression2/src/expression2/IPrintable_DSequenceExpr.cpp new file mode 100644 index 00000000..a3471232 --- /dev/null +++ b/xo-expression2/src/expression2/IPrintable_DSequenceExpr.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DSequenceExpr.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DSequenceExpr.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DSequenceExpr.json5] +**/ + +#include "detail/IPrintable_DSequenceExpr.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DSequenceExpr::pretty(const DSequenceExpr & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DSequenceExpr.cpp */ diff --git a/xo-expression2/src/expression2/IPrintable_DUniqueString.cpp b/xo-expression2/src/expression2/IPrintable_DUniqueString.cpp index a7b92af8..5f490bd9 100644 --- a/xo-expression2/src/expression2/IPrintable_DUniqueString.cpp +++ b/xo-expression2/src/expression2/IPrintable_DUniqueString.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IPrintable_DUniqueString.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -25,4 +25,4 @@ namespace xo { } /*namespace scm*/ } /*namespace xo*/ -/* end IPrintable_DUniqueString.cpp */ \ No newline at end of file +/* end IPrintable_DUniqueString.cpp */ diff --git a/xo-expression2/src/expression2/IPrintable_DVarRef.cpp b/xo-expression2/src/expression2/IPrintable_DVarRef.cpp new file mode 100644 index 00000000..a2027a2a --- /dev/null +++ b/xo-expression2/src/expression2/IPrintable_DVarRef.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DVarRef.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DVarRef.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DVarRef.json5] +**/ + +#include "detail/IPrintable_DVarRef.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DVarRef::pretty(const DVarRef & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DVarRef.cpp */ diff --git a/xo-expression2/src/expression2/IPrintable_DVariable.cpp b/xo-expression2/src/expression2/IPrintable_DVariable.cpp new file mode 100644 index 00000000..53364de5 --- /dev/null +++ b/xo-expression2/src/expression2/IPrintable_DVariable.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DVariable.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DVariable.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DVariable.json5] +**/ + +#include "detail/IPrintable_DVariable.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DVariable::pretty(const DVariable & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DVariable.cpp */ diff --git a/xo-expression2/src/expression2/ISymbolTable_Any.cpp b/xo-expression2/src/expression2/ISymbolTable_Any.cpp index 7c811253..95718429 100644 --- a/xo-expression2/src/expression2/ISymbolTable_Any.cpp +++ b/xo-expression2/src/expression2/ISymbolTable_Any.cpp @@ -38,4 +38,4 @@ ISymbolTable_Any::_valid } /*namespace scm*/ } /*namespace xo*/ -/* end ISymbolTable_Any.cpp */ \ No newline at end of file +/* end ISymbolTable_Any.cpp */ diff --git a/xo-expression2/src/expression2/ISymbolTable_DGlobalSymtab.cpp b/xo-expression2/src/expression2/ISymbolTable_DGlobalSymtab.cpp new file mode 100644 index 00000000..b735a6fb --- /dev/null +++ b/xo-expression2/src/expression2/ISymbolTable_DGlobalSymtab.cpp @@ -0,0 +1,34 @@ +/** @file ISymbolTable_DGlobalSymtab.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISymbolTable_DGlobalSymtab.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISymbolTable_DGlobalSymtab.json5] +**/ + +#include "symtab/ISymbolTable_DGlobalSymtab.hpp" + +namespace xo { + namespace scm { + auto + ISymbolTable_DGlobalSymtab::is_global_symtab(const DGlobalSymtab & self) noexcept -> bool + { + return self.is_global_symtab(); + } + + auto + ISymbolTable_DGlobalSymtab::lookup_binding(const DGlobalSymtab & self, const DUniqueString * sym) noexcept -> Binding + { + return self.lookup_binding(sym); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISymbolTable_DGlobalSymtab.cpp */ diff --git a/xo-expression2/src/expression2/ISymbolTable_DLocalSymtab.cpp b/xo-expression2/src/expression2/ISymbolTable_DLocalSymtab.cpp new file mode 100644 index 00000000..b67ada5c --- /dev/null +++ b/xo-expression2/src/expression2/ISymbolTable_DLocalSymtab.cpp @@ -0,0 +1,34 @@ +/** @file ISymbolTable_DLocalSymtab.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISymbolTable_DLocalSymtab.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISymbolTable_DLocalSymtab.json5] +**/ + +#include "symtab/ISymbolTable_DLocalSymtab.hpp" + +namespace xo { + namespace scm { + auto + ISymbolTable_DLocalSymtab::is_global_symtab(const DLocalSymtab & self) noexcept -> bool + { + return self.is_global_symtab(); + } + + auto + ISymbolTable_DLocalSymtab::lookup_binding(const DLocalSymtab & self, const DUniqueString * sym) noexcept -> Binding + { + return self.lookup_binding(sym); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISymbolTable_DLocalSymtab.cpp */ diff --git a/xo-expression2/src/expression2/StringTable.cpp b/xo-expression2/src/expression2/StringTable.cpp index ae48eea9..2d23d03e 100644 --- a/xo-expression2/src/expression2/StringTable.cpp +++ b/xo-expression2/src/expression2/StringTable.cpp @@ -10,6 +10,7 @@ namespace xo { using xo::mm::ArenaConfig; using xo::mm::AAllocator; + using xo::mm::MemorySizeInfo; using xo::facet::with_facet; using xo::facet::obj; @@ -18,7 +19,7 @@ namespace xo { bool debug_flag) : strings_{DArena::map(ArenaConfig{.name_ = "strings", .size_ = hint_max_capacity})}, - map_{hint_max_capacity} + map_{"stringkeys", hint_max_capacity} { (void)debug_flag; } @@ -72,6 +73,36 @@ namespace xo { return nullptr; } + const DUniqueString * + StringTable::gensym(std::string_view prefix) + { + static std::size_t s_counter = 0; + + while (true) { + ++s_counter; + + char buf[80]; + assert(prefix.size() + 20 < sizeof(buf)); + + int n = snprintf(buf, sizeof(buf), + "%s:%lu", + prefix.data(), s_counter); + + if ((0 < n) && (std::size_t(n) < sizeof(buf))) + buf[n] = '\0'; + else + buf[sizeof(buf)-1] = '\0'; + + std::string_view sv(buf); + const DUniqueString * retval = this->lookup(sv); + if (!retval) { + /* not already in string view -> we have viable candidate */ + retval = this->intern(sv); + return retval; + } + } + } + bool StringTable::verify_ok(verify_policy policy) const { @@ -129,6 +160,13 @@ namespace xo { return true; } + void + StringTable::visit_pools(const MemorySizeVisitor & visitor) const + { + strings_.visit_pools(visitor); + map_.visit_pools(visitor); + } + } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-expression2/src/expression2/TypeRef.cpp b/xo-expression2/src/expression2/TypeRef.cpp index 7b187ecd..5ff1d258 100644 --- a/xo-expression2/src/expression2/TypeRef.cpp +++ b/xo-expression2/src/expression2/TypeRef.cpp @@ -4,6 +4,9 @@ **/ #include "TypeRef.hpp" +#include +#include +#include namespace xo { namespace scm { @@ -62,6 +65,19 @@ namespace xo { return (td_ != nullptr); } + bool + TypeRef::pretty(const ppindentinfo & ppii) const + { + using xo::print::quot; + + return ppii.pps()->pretty_struct + (ppii, + "TypeRef" + , refrtag("id", quot(id_)) + , refrtag("td", cond(td_, td_, "null")) + ); + } + } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-expression2/src/expression2/expression2_register_facets.cpp b/xo-expression2/src/expression2/expression2_register_facets.cpp index 2d728bd3..82bff638 100644 --- a/xo-expression2/src/expression2/expression2_register_facets.cpp +++ b/xo-expression2/src/expression2/expression2_register_facets.cpp @@ -5,8 +5,25 @@ #include "expression2_register_facets.hpp" -#include -#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include #include #include @@ -17,6 +34,7 @@ namespace xo { using xo::mm::AGCObject; using xo::print::APrintable; using xo::facet::FacetRegistry; + using xo::facet::TypeRegistry; using xo::facet::typeseq; namespace scm { @@ -28,7 +46,80 @@ namespace xo { FacetRegistry::register_impl(); FacetRegistry::register_impl(); + // Expression + // +- Constant + // +- Variable + // +- VarRef + // +- DefineExpr + // +- ApplyExpr + // +- LambdaExpr + // +- IfElseExpr + // \- SequenceExpr + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + // SymbolTable + // +- LocalSymtab + // \- GlobalSymtab + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + // until we register facets + TypeRegistry::register_type(); + + TypeRegistry::register_type(); + log && log(xtag("DUniqueString.tseq", typeseq::id())); + log && log(xtag("DDefineExpr.tseq", typeseq::id())); + log && log(xtag("DVariable.tseq", typeseq::id())); + log && log(xtag("DVarRef.tseq", typeseq::id())); + log && log(xtag("DConstant.tseq", typeseq::id())); + log && log(xtag("DApplyExpr.tseq", typeseq::id())); + log && log(xtag("DLambdaExpr.tseq", typeseq::id())); + log && log(xtag("DIfElseExpr.tseq", typeseq::id())); + log && log(xtag("DSequenceExpr.tseq", typeseq::id())); + + log && log(xtag("DGlobalSymtab.tseq", typeseq::id())); + log && log(xtag("DLocalSymtab.tseq", typeseq::id())); + + log && log(xtag("AExpression.tseq", typeseq::id())); + log && log(xtag("ASymbolTable.tseq", typeseq::id())); return true; } diff --git a/xo-expression2/src/expression2/expression2_register_types.cpp b/xo-expression2/src/expression2/expression2_register_types.cpp index 2b8aadcf..b3dd21f8 100644 --- a/xo-expression2/src/expression2/expression2_register_types.cpp +++ b/xo-expression2/src/expression2/expression2_register_types.cpp @@ -5,11 +5,18 @@ #include "expression2_register_types.hpp" +#include "detail/IGCObject_DConstant.hpp" +#include "detail/IGCObject_DVariable.hpp" +//#include "detail/IGCObject_DDefineExpr.hpp" // when avail +//#include "detail/IGCObject_DApplyExpr.hpp" // when avail +//#include "detail/IGCObject_DLambdaExpr.hpp" // when avail +#include "detail/IGCObject_DIfElseExpr.hpp" +#include "detail/IGCObject_DSequenceExpr.hpp" +//#include "detail/IGCObject_DLocalSymtab.hpp" // when avail #include "detail/IGCObject_DUniqueString.hpp" -//#include "detail/IPrintable_DUniqueString.hpp" +//#include "detail/IPrintable_DUniqueString.hpp" // when avail -//#include #include namespace xo { @@ -27,6 +34,16 @@ namespace xo { bool ok = true; + ok &= gc.install_type(impl_for()); + ok &= gc.install_type(impl_for()); + //ok &= gc.install_type(impl_for()); // when avail + //ok &= gc.install_type(impl_for()); // when avail + //ok &= gc.install_type(impl_for()); // when avail + ok &= gc.install_type(impl_for()); + ok &= gc.install_type(impl_for()); + + //ok &= gc.install_type(impl_for()); // when avail + ok &= gc.install_type(impl_for()); return ok; diff --git a/xo-expression2/src/expression2/init_expression2.cpp b/xo-expression2/src/expression2/init_expression2.cpp index e975ef99..1ee5ec9e 100644 --- a/xo-expression2/src/expression2/init_expression2.cpp +++ b/xo-expression2/src/expression2/init_expression2.cpp @@ -7,7 +7,7 @@ #include "expression2_register_facets.hpp" #include "expression2_register_types.hpp" -#include +#include #include namespace xo { @@ -29,7 +29,7 @@ namespace xo { InitEvidence retval; /* direct subsystem deps for xo-object2/ */ - retval ^= InitSubsys::require(); + retval ^= InitSubsys::require(); /* xo-expression2/'s own initialization code */ retval ^= Subsystem::provide("expression2", &init); diff --git a/xo-expression2/utest/CMakeLists.txt b/xo-expression2/utest/CMakeLists.txt index 2b8bceec..deb1d25a 100644 --- a/xo-expression2/utest/CMakeLists.txt +++ b/xo-expression2/utest/CMakeLists.txt @@ -5,6 +5,11 @@ set(UTEST_SRCS expression2_utest_main.cpp StringTable.test.cpp X1Collector.test.cpp + DConstant.test.cpp + DVariable.test.cpp + DApplyExpr.test.cpp + DDefineExpr.test.cpp + DIfElseExpr.test.cpp ) xo_add_utest_executable(${UTEST_EXE} ${UTEST_SRCS}) diff --git a/xo-expression2/utest/DApplyExpr.test.cpp b/xo-expression2/utest/DApplyExpr.test.cpp new file mode 100644 index 00000000..f217d47e --- /dev/null +++ b/xo-expression2/utest/DApplyExpr.test.cpp @@ -0,0 +1,309 @@ +/** @file DApplyExpr.test.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "init_expression2.hpp" +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#include + +namespace ut { + using xo::S_expression2_tag; + using xo::scm::DApplyExpr; + using xo::scm::DConstant; + using xo::scm::DFloat; + using xo::scm::AExpression; + using xo::scm::TypeRef; + using xo::scm::Primitives; + using xo::scm::DPrimitive_gco_2_gco_gco; + using xo::mm::CollectorTypeRegistry; + using xo::mm::AAllocator; + using xo::mm::ACollector; + using xo::mm::AGCObject; + using xo::mm::DX1Collector; + using xo::mm::X1CollectorConfig; + using xo::mm::ArenaConfig; + using xo::print::APrintable; + using xo::print::ppstate_standalone; + using xo::print::ppconfig; + using xo::facet::FacetRegistry; + using xo::facet::with_facet; + using xo::facet::obj; + using xo::reflect::Reflect; + using xo::InitEvidence; + using xo::InitSubsys; + using xo::scope; + + static InitEvidence s_init = InitSubsys::require(); + + TEST_CASE("DApplyExpr-init", "[expression2][DApplyExpr]") + { + REQUIRE(s_init.evidence()); + } + + TEST_CASE("DApplyExpr-make2", "[expression2][DApplyExpr]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "dapplyexpr_make2_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + // wrap primitive as GCObject, then as expression + obj prim_gco = with_facet::mkobj(&Primitives::s_mul_gco_gco_pm); + obj fn_expr = DConstant::make(alloc, prim_gco); + REQUIRE(fn_expr.data() != nullptr); + + // create argument expressions + obj val1 = DFloat::box(alloc, 3.0); + obj val2 = DFloat::box(alloc, 7.0); + obj arg1 = DConstant::make(alloc, val1); + obj arg2 = DConstant::make(alloc, val2); + REQUIRE(arg1.data() != nullptr); + REQUIRE(arg2.data() != nullptr); + + // create apply expression: mul(3.0, 7.0) + TypeRef result_type = TypeRef::resolved(Reflect::require()); + auto apply_expr = DApplyExpr::make2(alloc, result_type, fn_expr, arg1, arg2); + REQUIRE(apply_expr.data() != nullptr); + } + + TEST_CASE("DApplyExpr-extype", "[expression2][DApplyExpr]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "dapplyexpr_extype_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + obj prim_gco = with_facet::mkobj(&Primitives::s_mul_gco_gco_pm); + obj fn_expr = DConstant::make(alloc, prim_gco); + + obj val1 = DFloat::box(alloc, 3.0); + obj val2 = DFloat::box(alloc, 7.0); + obj arg1 = DConstant::make(alloc, val1); + obj arg2 = DConstant::make(alloc, val2); + + TypeRef result_type = TypeRef::resolved(Reflect::require()); + auto apply_expr = DApplyExpr::make2(alloc, result_type, fn_expr, arg1, arg2); + + REQUIRE(apply_expr.data()->extype() == xo::scm::exprtype::apply); + } + + TEST_CASE("DApplyExpr-n_args", "[expression2][DApplyExpr]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "dapplyexpr_n_args_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + obj prim_gco = with_facet::mkobj(&Primitives::s_mul_gco_gco_pm); + obj fn_expr = DConstant::make(alloc, prim_gco); + + obj val1 = DFloat::box(alloc, 3.0); + obj val2 = DFloat::box(alloc, 7.0); + obj arg1 = DConstant::make(alloc, val1); + obj arg2 = DConstant::make(alloc, val2); + + TypeRef result_type = TypeRef::resolved(Reflect::require()); + auto apply_expr = DApplyExpr::make2(alloc, result_type, fn_expr, arg1, arg2); + + REQUIRE(apply_expr.data()->n_args() == 2); + } + + TEST_CASE("DApplyExpr-fn", "[expression2][DApplyExpr]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "dapplyexpr_fn_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + obj prim_gco = with_facet::mkobj(&Primitives::s_mul_gco_gco_pm); + obj fn_expr = DConstant::make(alloc, prim_gco); + + obj val1 = DFloat::box(alloc, 3.0); + obj val2 = DFloat::box(alloc, 7.0); + obj arg1 = DConstant::make(alloc, val1); + obj arg2 = DConstant::make(alloc, val2); + + TypeRef result_type = TypeRef::resolved(Reflect::require()); + auto apply_expr = DApplyExpr::make2(alloc, result_type, fn_expr, arg1, arg2); + + // verify fn() returns an expression + obj fn = apply_expr.data()->fn(); + REQUIRE(fn.data() != nullptr); + REQUIRE(fn.extype() == xo::scm::exprtype::constant); + } + + TEST_CASE("DApplyExpr-arg", "[expression2][DApplyExpr]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "dapplyexpr_arg_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + obj prim_gco = with_facet::mkobj(&Primitives::s_mul_gco_gco_pm); + obj fn_expr = DConstant::make(alloc, prim_gco); + + obj val1 = DFloat::box(alloc, 3.0); + obj val2 = DFloat::box(alloc, 7.0); + obj arg1 = DConstant::make(alloc, val1); + obj arg2 = DConstant::make(alloc, val2); + + TypeRef result_type = TypeRef::resolved(Reflect::require()); + auto apply_expr = DApplyExpr::make2(alloc, result_type, fn_expr, arg1, arg2); + + // verify arg(0) and arg(1) return expressions + obj a0 = apply_expr.data()->arg(0); + obj a1 = apply_expr.data()->arg(1); + + REQUIRE(a0.data() != nullptr); + REQUIRE(a1.data() != nullptr); + REQUIRE(a0.extype() == xo::scm::exprtype::constant); + REQUIRE(a1.extype() == xo::scm::exprtype::constant); + } + + TEST_CASE("DApplyExpr-pretty", "[expression2][DApplyExpr][pp]") + { + scope log(XO_DEBUG(false)); + + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "dapplyexpr_pretty_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + obj prim_gco = with_facet::mkobj(&Primitives::s_mul_gco_gco_pm); + obj fn_expr = DConstant::make(alloc, prim_gco); + + obj val1 = DFloat::box(alloc, 3.0); + obj val2 = DFloat::box(alloc, 7.0); + obj arg1 = DConstant::make(alloc, val1); + obj arg2 = DConstant::make(alloc, val2); + + TypeRef result_type = TypeRef::resolved(Reflect::require()); + auto apply_expr = DApplyExpr::make2(alloc, result_type, fn_expr, arg1, arg2); + + std::stringstream ss; + ppconfig ppc; + ppstate_standalone pps(&ss, 0, &ppc); + + obj expr_pr(apply_expr.data()); + pps.pretty(expr_pr); + + std::string output = ss.str(); + + log && log(output); + + CHECK(output.find("ApplyExpr") != std::string::npos); + } +} + +/* end DApplyExpr.test.cpp */ diff --git a/xo-expression2/utest/DConstant.test.cpp b/xo-expression2/utest/DConstant.test.cpp new file mode 100644 index 00000000..fd8e9b1b --- /dev/null +++ b/xo-expression2/utest/DConstant.test.cpp @@ -0,0 +1,232 @@ +/** @file DConstant.test.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "init_expression2.hpp" +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#include + +namespace ut { + using xo::S_expression2_tag; + using xo::scm::DConstant; + using xo::scm::DFloat; + using xo::scm::DInteger; + using xo::scm::AExpression; + using xo::mm::CollectorTypeRegistry; + using xo::mm::AAllocator; + using xo::mm::ACollector; + using xo::mm::AGCObject; + using xo::mm::DX1Collector; + using xo::mm::X1CollectorConfig; + using xo::mm::ArenaConfig; + using xo::print::APrintable; + using xo::print::ppstate_standalone; + using xo::print::ppconfig; + using xo::facet::FacetRegistry; + using xo::facet::with_facet; + using xo::facet::obj; + using xo::facet::typeseq; + using xo::reflect::Reflect; + using xo::InitEvidence; + using xo::InitSubsys; + using xo::scope; + + // Ensure subsystem initialized before tests + static InitEvidence s_init = InitSubsys::require(); + + TEST_CASE("DConstant-init", "[expression2][DConstant]") + { + // Verify subsystem initialization succeeded + REQUIRE(s_init.evidence()); + } + + TEST_CASE("DConstant-from-float", "[expression2][DConstant]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "dconstant_float_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + // Box a float value + obj fval = DFloat::box(alloc, 3.14); + REQUIRE(fval.data() != nullptr); + + // Create DConstant from the boxed float + auto expr = DConstant::make(alloc, fval); + REQUIRE(expr.data() != nullptr); + + // Verify expression type + REQUIRE(expr.data()->extype() == xo::scm::exprtype::constant); + + // Verify valuetype is double (DFloat::value_type) + REQUIRE(expr.data()->valuetype() == Reflect::require()); + + // Verify value is accessible + REQUIRE(expr.data()->value().data() != nullptr); + } + + TEST_CASE("DConstant-from-integer", "[expression2][DConstant]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "dconstant_int_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + // Box an integer value + obj ival = DInteger::box(alloc, 42); + REQUIRE(ival.data() != nullptr); + + // Create DConstant from the boxed integer + auto expr = DConstant::make(alloc, ival); + REQUIRE(expr.data() != nullptr); + + // Verify expression type + REQUIRE(expr.data()->extype() == xo::scm::exprtype::constant); + + // Verify valuetype is long (DInteger::value_type) + REQUIRE(expr.data()->valuetype() == Reflect::require()); + + // Verify value is accessible + REQUIRE(expr.data()->value().data() != nullptr); + } + + TEST_CASE("DConstant-pretty-float", "[expression2][DConstant][pp]") + { + scope log(XO_DEBUG(true)); + + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "dconstant_pp_float_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + // Box a float value + obj fval = DFloat::box(alloc, 2.718); + auto expr = DConstant::make(alloc, fval); + REQUIRE(expr.data() != nullptr); + + // Pretty print + std::stringstream ss; + ppconfig ppc; + ppstate_standalone pps(&ss, 0, &ppc); + + obj expr_pr(expr.data()); + pps.pretty(expr_pr); + + std::string output = ss.str(); + + log && log(output); + + // Output should contain "DConstant" struct name + CHECK(output.find("DConstant") != std::string::npos); + } + + TEST_CASE("DConstant-pretty-integer", "[expression2][DConstant][pp]") + { + scope log(XO_DEBUG(false)); + + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "dconstant_pp_int_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + // Box an integer value + obj ival = DInteger::box(alloc, 123); + auto expr = DConstant::make(alloc, ival); + REQUIRE(expr.data() != nullptr); + + // Pretty print + std::stringstream ss; + ppconfig ppc; + ppstate_standalone pps(&ss, 0, &ppc); + + obj expr_pr(expr.data()); + pps.pretty(expr_pr); + + std::string output = ss.str(); + + log && log(output); + + // Output should contain "DConstant" struct name + CHECK(output.find("DConstant") != std::string::npos); + } +} + +/* end DConstant.test.cpp */ diff --git a/xo-expression2/utest/DDefineExpr.test.cpp b/xo-expression2/utest/DDefineExpr.test.cpp new file mode 100644 index 00000000..5f78891d --- /dev/null +++ b/xo-expression2/utest/DDefineExpr.test.cpp @@ -0,0 +1,317 @@ +/** @file DDefineExpr.test.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "init_expression2.hpp" +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#include +#include + +namespace ut { + using xo::S_expression2_tag; + using xo::scm::DDefineExpr; + using xo::scm::DConstant; + using xo::scm::DFloat; + using xo::scm::DVariable; + using xo::scm::DUniqueString; + using xo::scm::StringTable; + using xo::scm::AExpression; + using xo::mm::CollectorTypeRegistry; + using xo::mm::AAllocator; + using xo::mm::ACollector; + using xo::mm::AGCObject; + using xo::mm::DX1Collector; + using xo::mm::X1CollectorConfig; + using xo::mm::ArenaConfig; + using xo::print::APrintable; + using xo::print::ppstate_standalone; + using xo::print::ppconfig; + using xo::facet::FacetRegistry; + using xo::facet::with_facet; + using xo::facet::obj; + using xo::reflect::Reflect; + using xo::InitEvidence; + using xo::InitSubsys; + using xo::scope; + + static InitEvidence s_init = InitSubsys::require(); + + TEST_CASE("DDefineExpr-init", "[expression2][DDefineExpr]") + { + REQUIRE(s_init.evidence()); + } + + TEST_CASE("DDefineExpr-make", "[expression2][DDefineExpr]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "ddefineexpr_make_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + StringTable table(1024); + const DUniqueString * name = table.intern("x"); + REQUIRE(name != nullptr); + + // Create rhs expression: constant 42.0 + obj fval = DFloat::box(alloc, 42.0); + auto rhs_expr = DConstant::make(alloc, fval); + REQUIRE(rhs_expr.data() != nullptr); + + // Create define expression: def x = 42.0 + DDefineExpr * def = DDefineExpr::make(alloc, name, rhs_expr); + REQUIRE(def != nullptr); + } + + TEST_CASE("DDefineExpr-lhs", "[expression2][DDefineExpr]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "ddefineexpr_lhs_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + StringTable table(1024); + const DUniqueString * name = table.intern("myvar"); + + obj fval = DFloat::box(alloc, 3.14); + auto rhs_expr = DConstant::make(alloc, fval); + + DDefineExpr * def = DDefineExpr::make(alloc, name, rhs_expr); + REQUIRE(def != nullptr); + + DVariable * lhs = def->lhs(); + REQUIRE(lhs != nullptr); + REQUIRE(lhs->name() == name); + } + + TEST_CASE("DDefineExpr-rhs", "[expression2][DDefineExpr]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "ddefineexpr_rhs_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + StringTable table(1024); + const DUniqueString * name = table.intern("y"); + + obj fval = DFloat::box(alloc, 2.718); + auto rhs_expr = DConstant::make(alloc, fval); + + DDefineExpr * def = DDefineExpr::make(alloc, name, rhs_expr); + REQUIRE(def != nullptr); + + obj rhs = def->rhs(); + REQUIRE(rhs.data() != nullptr); + // Verify rhs expression type is constant + REQUIRE(rhs.extype() == xo::scm::exprtype::constant); + } + + TEST_CASE("DDefineExpr-name", "[expression2][DDefineExpr]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "ddefineexpr_name_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + StringTable table(1024); + const DUniqueString * name = table.intern("foo"); + + obj fval = DFloat::box(alloc, 1.0); + auto rhs_expr = DConstant::make(alloc, fval); + + DDefineExpr * def = DDefineExpr::make(alloc, name, rhs_expr); + REQUIRE(def != nullptr); + REQUIRE(def->name() == name); + REQUIRE(std::strcmp(def->name()->chars(), "foo") == 0); + } + + TEST_CASE("DDefineExpr-extype", "[expression2][DDefineExpr]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "ddefineexpr_extype_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + StringTable table(1024); + const DUniqueString * name = table.intern("z"); + + obj fval = DFloat::box(alloc, 0.0); + auto rhs_expr = DConstant::make(alloc, fval); + + DDefineExpr * def = DDefineExpr::make(alloc, name, rhs_expr); + REQUIRE(def != nullptr); + REQUIRE(def->extype() == xo::scm::exprtype::define); + } + + TEST_CASE("DDefineExpr-valuetype", "[expression2][DDefineExpr]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "ddefineexpr_valuetype_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + StringTable table(1024); + const DUniqueString * name = table.intern("w"); + + obj fval = DFloat::box(alloc, 99.9); + auto rhs_expr = DConstant::make(alloc, fval); + + DDefineExpr * def = DDefineExpr::make(alloc, name, rhs_expr); + REQUIRE(def != nullptr); + REQUIRE(def->valuetype() == Reflect::require()); + } + + TEST_CASE("DDefineExpr-pretty", "[expression2][DDefineExpr][pp]") + { + scope log(XO_DEBUG(true)); + + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "ddefineexpr_pretty_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + StringTable table(1024); + const DUniqueString * name = table.intern("bar"); + + obj fval = DFloat::box(alloc, 123.456); + auto rhs_expr = DConstant::make(alloc, fval); + + DDefineExpr * def = DDefineExpr::make(alloc, name, rhs_expr); + REQUIRE(def != nullptr); + + std::stringstream ss; + ppconfig ppc; + ppstate_standalone pps(&ss, 0, &ppc); + + obj def_pr(def); + pps.pretty(def_pr); + + std::string output = ss.str(); + + log && log(output); + + CHECK(output.find("DDefineExpr") != std::string::npos); + } +} + +/* end DDefineExpr.test.cpp */ diff --git a/xo-expression2/utest/DIfElseExpr.test.cpp b/xo-expression2/utest/DIfElseExpr.test.cpp new file mode 100644 index 00000000..2dee2f26 --- /dev/null +++ b/xo-expression2/utest/DIfElseExpr.test.cpp @@ -0,0 +1,345 @@ +/** @file DIfElseExpr.test.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "init_expression2.hpp" +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#include + +namespace ut { + using xo::S_expression2_tag; + using xo::scm::DIfElseExpr; + using xo::scm::DConstant; + using xo::scm::DFloat; + using xo::scm::DBoolean; + using xo::scm::AExpression; + using xo::mm::CollectorTypeRegistry; + using xo::mm::AAllocator; + using xo::mm::ACollector; + using xo::mm::AGCObject; + using xo::mm::DX1Collector; + using xo::mm::X1CollectorConfig; + using xo::mm::ArenaConfig; + using xo::print::APrintable; + using xo::print::ppstate_standalone; + using xo::print::ppconfig; + //using xo::facet::FacetRegistry; + using xo::facet::with_facet; + using xo::facet::obj; + //using xo::reflect::Reflect; + using xo::InitEvidence; + using xo::InitSubsys; + using xo::scope; + + static InitEvidence s_init = InitSubsys::require(); + + TEST_CASE("DIfElseExpr-init", "[expression2][DIfElseExpr]") + { + REQUIRE(s_init.evidence()); + } + + TEST_CASE("DIfElseExpr-make", "[expression2][DIfElseExpr]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "difelseexpr_make_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + // Create test expression: constant true + obj bval = DBoolean::box(alloc, true); + auto test_expr = DConstant::make(alloc, bval); + REQUIRE(test_expr.data() != nullptr); + + // Create when_true expression: constant 1.0 + obj fval1 = DFloat::box(alloc, 1.0); + auto when_true_expr = DConstant::make(alloc, fval1); + REQUIRE(when_true_expr.data() != nullptr); + + // Create when_false expression: constant 2.0 + obj fval2 = DFloat::box(alloc, 2.0); + auto when_false_expr = DConstant::make(alloc, fval2); + REQUIRE(when_false_expr.data() != nullptr); + + // Create if-else expression: if true then 1.0 else 2.0 + auto ifexpr = DIfElseExpr::make(alloc, test_expr, when_true_expr, when_false_expr); + REQUIRE(ifexpr.data() != nullptr); + } + + TEST_CASE("DIfElseExpr-test", "[expression2][DIfElseExpr]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "difelseexpr_test_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + obj bval = DBoolean::box(alloc, true); + auto test_expr = DConstant::make(alloc, bval); + + obj fval1 = DFloat::box(alloc, 1.0); + auto when_true_expr = DConstant::make(alloc, fval1); + + obj fval2 = DFloat::box(alloc, 2.0); + auto when_false_expr = DConstant::make(alloc, fval2); + + auto ifexpr = DIfElseExpr::make(alloc, test_expr, when_true_expr, when_false_expr); + REQUIRE(ifexpr.data() != nullptr); + + obj test = ifexpr.data()->test(); + REQUIRE(test.data() != nullptr); + REQUIRE(test.extype() == xo::scm::exprtype::constant); + } + + TEST_CASE("DIfElseExpr-when-true", "[expression2][DIfElseExpr]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "difelseexpr_when_true_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + obj bval = DBoolean::box(alloc, true); + auto test_expr = DConstant::make(alloc, bval); + + obj fval1 = DFloat::box(alloc, 1.0); + auto when_true_expr = DConstant::make(alloc, fval1); + + obj fval2 = DFloat::box(alloc, 2.0); + auto when_false_expr = DConstant::make(alloc, fval2); + + auto ifexpr = DIfElseExpr::make(alloc, test_expr, when_true_expr, when_false_expr); + REQUIRE(ifexpr.data() != nullptr); + + obj wt = ifexpr.data()->when_true(); + REQUIRE(wt.data() != nullptr); + REQUIRE(wt.extype() == xo::scm::exprtype::constant); + } + + TEST_CASE("DIfElseExpr-when-false", "[expression2][DIfElseExpr]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "difelseexpr_when_false_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + obj bval = DBoolean::box(alloc, false); + auto test_expr = DConstant::make(alloc, bval); + + obj fval1 = DFloat::box(alloc, 1.0); + auto when_true_expr = DConstant::make(alloc, fval1); + + obj fval2 = DFloat::box(alloc, 2.0); + auto when_false_expr = DConstant::make(alloc, fval2); + + auto ifexpr = DIfElseExpr::make(alloc, test_expr, when_true_expr, when_false_expr); + REQUIRE(ifexpr.data() != nullptr); + + obj wf = ifexpr.data()->when_false(); + REQUIRE(wf.data() != nullptr); + REQUIRE(wf.extype() == xo::scm::exprtype::constant); + } + + TEST_CASE("DIfElseExpr-extype", "[expression2][DIfElseExpr]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "difelseexpr_extype_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + obj bval = DBoolean::box(alloc, true); + auto test_expr = DConstant::make(alloc, bval); + + obj fval1 = DFloat::box(alloc, 1.0); + auto when_true_expr = DConstant::make(alloc, fval1); + + obj fval2 = DFloat::box(alloc, 2.0); + auto when_false_expr = DConstant::make(alloc, fval2); + + auto ifexpr = DIfElseExpr::make(alloc, test_expr, when_true_expr, when_false_expr); + REQUIRE(ifexpr.data() != nullptr); + REQUIRE(ifexpr.data()->extype() == xo::scm::exprtype::ifexpr); + } + + TEST_CASE("DIfElseExpr-valuetype", "[expression2][DIfElseExpr]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "difelseexpr_valuetype_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + obj bval = DBoolean::box(alloc, true); + auto test_expr = DConstant::make(alloc, bval); + + obj fval1 = DFloat::box(alloc, 1.0); + auto when_true_expr = DConstant::make(alloc, fval1); + + obj fval2 = DFloat::box(alloc, 2.0); + auto when_false_expr = DConstant::make(alloc, fval2); + + auto ifexpr = DIfElseExpr::make(alloc, test_expr, when_true_expr, when_false_expr); + REQUIRE(ifexpr.data() != nullptr); + + // valuetype may be null before type resolution + // just verify we can call it + ifexpr.data()->valuetype(); + } + + TEST_CASE("DIfElseExpr-pretty", "[expression2][DIfElseExpr][pp]") + { + scope log(XO_DEBUG(true)); + + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "difelseexpr_pretty_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + obj bval = DBoolean::box(alloc, true); + auto test_expr = DConstant::make(alloc, bval); + + obj fval1 = DFloat::box(alloc, 1.0); + auto when_true_expr = DConstant::make(alloc, fval1); + + obj fval2 = DFloat::box(alloc, 2.0); + auto when_false_expr = DConstant::make(alloc, fval2); + + auto ifexpr = DIfElseExpr::make(alloc, + test_expr, + when_true_expr, when_false_expr); + REQUIRE(ifexpr.data() != nullptr); + + std::stringstream ss; + ppconfig ppc; + ppstate_standalone pps(&ss, 0, &ppc); + + obj ifexpr_pr(ifexpr.data()); + pps.pretty(ifexpr_pr); + + std::string output = ss.str(); + + log && log(output); + + CHECK(output.find("DIfElseExpr") != std::string::npos); + } +} + +/* end DIfElseExpr.test.cpp */ diff --git a/xo-expression2/utest/DVariable.test.cpp b/xo-expression2/utest/DVariable.test.cpp new file mode 100644 index 00000000..9c26a7c4 --- /dev/null +++ b/xo-expression2/utest/DVariable.test.cpp @@ -0,0 +1,227 @@ +/** @file DVariable.test.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "init_expression2.hpp" +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#include +#include + +namespace ut { + using xo::S_expression2_tag; + using xo::scm::DVariable; + using xo::scm::DUniqueString; + using xo::scm::StringTable; + using xo::scm::TypeRef; + using xo::scm::Binding; + using xo::scm::AExpression; + using xo::mm::CollectorTypeRegistry; + using xo::mm::AAllocator; + using xo::mm::ACollector; + using xo::mm::DX1Collector; + using xo::mm::X1CollectorConfig; + using xo::mm::ArenaConfig; + using xo::print::APrintable; + using xo::print::ppstate_standalone; + using xo::print::ppconfig; + using xo::facet::FacetRegistry; + using xo::facet::with_facet; + using xo::facet::obj; + using xo::reflect::Reflect; + using xo::InitEvidence; + using xo::InitSubsys; + using xo::scope; + + static InitEvidence s_init = InitSubsys::require(); + + TEST_CASE("DVariable-init", "[expression2][DVariable]") + { + REQUIRE(s_init.evidence()); + } + + TEST_CASE("DVariable-make", "[expression2][DVariable]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "dvariable_make_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + StringTable table(1024); + const DUniqueString * name = table.intern("x"); + REQUIRE(name != nullptr); + + TypeRef typeref = TypeRef::resolved(Reflect::require()); + + DVariable * var = DVariable::make(alloc, name, typeref); + REQUIRE(var != nullptr); + } + + TEST_CASE("DVariable-extype", "[expression2][DVariable]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "dvariable_extype_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + StringTable table(1024); + const DUniqueString * name = table.intern("y"); + TypeRef typeref = TypeRef::resolved(Reflect::require()); + + DVariable * var = DVariable::make(alloc, name, typeref); + REQUIRE(var != nullptr); + REQUIRE(var->extype() == xo::scm::exprtype::variable); + } + + TEST_CASE("DVariable-valuetype", "[expression2][DVariable]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "dvariable_valuetype_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + StringTable table(1024); + const DUniqueString * name = table.intern("z"); + TypeRef typeref = TypeRef::resolved(Reflect::require()); + + DVariable * var = DVariable::make(alloc, name, typeref); + REQUIRE(var != nullptr); + REQUIRE(var->valuetype() == Reflect::require()); + } + + TEST_CASE("DVariable-name", "[expression2][DVariable]") + { + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "dvariable_name_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + StringTable table(1024); + const DUniqueString * name = table.intern("myvar"); + TypeRef typeref = TypeRef::resolved(Reflect::require()); + + DVariable * var = DVariable::make(alloc, name, typeref); + REQUIRE(var != nullptr); + REQUIRE(var->name() == name); + REQUIRE(std::strcmp(var->name()->chars(), "myvar") == 0); + } + + TEST_CASE("DVariable-pretty", "[expression2][DVariable][pp]") + { + scope log(XO_DEBUG(false)); + + REQUIRE(s_init.evidence()); + + X1CollectorConfig cfg{ + .name_ = "dvariable_pretty_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{4096, 4096}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + auto alloc = with_facet::mkobj(&gc); + auto coll = with_facet::mkobj(&gc); + + bool ok = CollectorTypeRegistry::instance().install_types(coll); + REQUIRE(ok); + + StringTable table(1024); + const DUniqueString * name = table.intern("foo"); + TypeRef typeref = TypeRef::resolved(Reflect::require()); + + DVariable * var = DVariable::make(alloc, name, typeref); + REQUIRE(var != nullptr); + + std::stringstream ss; + ppconfig ppc; + ppstate_standalone pps(&ss, 0, &ppc); + + obj var_pr(var); + pps.pretty(var_pr); + + std::string output = ss.str(); + + log && log(output); + + CHECK(output.find("DVariable") != std::string::npos); + } +} + +/* end DVariable.test.cpp */ diff --git a/xo-expression2/utest/X1Collector.test.cpp b/xo-expression2/utest/X1Collector.test.cpp index a664f9a2..b872d877 100644 --- a/xo-expression2/utest/X1Collector.test.cpp +++ b/xo-expression2/utest/X1Collector.test.cpp @@ -39,7 +39,7 @@ namespace ut { using xo::mm::ACollector; using xo::mm::AGCObject; using xo::mm::DX1Collector; - using xo::mm::CollectorConfig; + using xo::mm::X1CollectorConfig; using xo::mm::ArenaConfig; using xo::facet::with_facet; using xo::facet::typeseq; @@ -54,14 +54,13 @@ namespace ut { REQUIRE(s_init.evidence()); // Create collector - CollectorConfig cfg{ - .name_ = "x1_duniquestring_test", - .arena_config_ = ArenaConfig{ - .size_ = 8192, - .store_header_flag_ = true}, - .object_types_z_ = 16384, - .gc_trigger_v_{{1024, 1024}}, - .debug_flag_ = false, + X1CollectorConfig cfg{ .name_ = "x1_duniquestring_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{1024, 1024}}, + .debug_flag_ = false, }; DX1Collector gc(cfg); diff --git a/xo-facet/CMakeLists.txt b/xo-facet/CMakeLists.txt index ad8a4cb4..d8ad41a4 100644 --- a/xo-facet/CMakeLists.txt +++ b/xo-facet/CMakeLists.txt @@ -27,6 +27,7 @@ set(SELF_LIB xo_facet) xo_add_headeronly_library(${SELF_LIB}) # note: dependencies here must coordinate with cmake/xo_facetConfig.cmake.in +xo_headeronly_dependency(${SELF_LIB} xo_arena) xo_headeronly_dependency(${SELF_LIB} xo_reflectutil) xo_install_library4(${SELF_LIB} ${PROJECT_NAME}Targets) diff --git a/xo-facet/cmake/xo_facetConfig.cmake.in b/xo-facet/cmake/xo_facetConfig.cmake.in index 88709824..23483949 100644 --- a/xo-facet/cmake/xo_facetConfig.cmake.in +++ b/xo-facet/cmake/xo_facetConfig.cmake.in @@ -2,6 +2,7 @@ include(CMakeFindDependencyMacro) # note: dependencies here must coordinate with xo-facet/CMakeLists.txt +find_dependency(xo_arena) find_dependency(xo_reflectutil) include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") check_required_components("@PROJECT_NAME@") diff --git a/xo-facet/codegen/abstract_facet.hpp.j2 b/xo-facet/codegen/abstract_facet.hpp.j2 index 76985b6a..b125bce4 100644 --- a/xo-facet/codegen/abstract_facet.hpp.j2 +++ b/xo-facet/codegen/abstract_facet.hpp.j2 @@ -60,6 +60,8 @@ public: // const methods /** RTTI: unique id# for actual runtime data representation **/ virtual typeseq _typeseq() const noexcept = 0; + /** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/ + virtual void _drop(Opaque d) const noexcept = 0; {% for md in const_methods %} /** {{md.doc}} **/ virtual {{md.return_type}} {{md.name}}({{md.args | args}}) {{md | qualifiers}} = 0; diff --git a/xo-facet/codegen/genfacet b/xo-facet/codegen/genfacet index ddea77e6..0d632ba0 100755 --- a/xo-facet/codegen/genfacet +++ b/xo-facet/codegen/genfacet @@ -153,7 +153,7 @@ def gen_facet(env, router_facet_hpp_fname = f'{router_facet}.hpp' context = { - 'genfacet': __file__, + 'genfacet': 'xo-facet/codegen/genfacet', 'genfacet_input': idl_fname, 'using_dox': using_dox, 'impl_hpp_subdir': facet_detail_subdir, @@ -314,6 +314,8 @@ def gen_facet_impl(env, router_facet = f'R{facet_name}' # RFoo.hpp router_facet_hpp_fname = f'{router_facet}.hpp' + # user defined content -- whatever you want + router_facet_explicit_content = facet_idl['router_facet_explicit_content'] # ================================================================ # vars for IFacet_DRepr @@ -345,7 +347,7 @@ def gen_facet_impl(env, # ================================================================ context = { - 'genfacet': __file__, + 'genfacet': 'xo-facet/codegen/genfacet', 'genfacet_input': idl_fname, 'using_dox': using_dox, 'impl_hpp_subdir': output_impl_hpp_subdir, @@ -384,6 +386,7 @@ def gen_facet_impl(env, 'router_facet': router_facet, 'router_facet_hpp_j2': 'router_facet.hpp.j2', 'router_facet_hpp_fname': router_facet_hpp_fname, + 'router_facet_explicit_content': router_facet_explicit_content, # 'types': facet_types, 'local_types': local_types, @@ -452,25 +455,21 @@ def main(): parser.add_argument('--input', required=True, help='input IDL JSON5 file') # --facet-dir: only with mode=implementation parser.add_argument('--facet-dir', required=False, help='base dir for facet json') - # --output-impl-hpp: putting this in .json5, will be able to drop this. - parser.add_argument('--output-impl-hpp', required=True, help='.hpp detail subdir') - parser.add_argument('--output-hpp', required=True, help='.hpp output directory') - parser.add_argument('--output-cpp', required=True, help='.cpp output directory') args = parser.parse_args() idl_fname = args.input idl = load_idl(idl_fname) - output_hpp_dir = Path(args.output_hpp) + output_hpp_dir = Path(idl['output_hpp_dir']) output_hpp_dir.mkdir(parents=False, exist_ok=True) - # TODO: output_impl_hpp_subdir: use idl['detail_subdir'] instead - output_impl_hpp_subdir = Path(args.output_impl_hpp) - output_impl_hpp_dir = Path(args.output_hpp) / output_impl_hpp_subdir + # output_impl_hpp_subdir: prefer IDL, fall back to CLI + output_impl_hpp_subdir = Path(idl['output_impl_subdir']) + output_impl_hpp_dir = output_hpp_dir / output_impl_hpp_subdir output_impl_hpp_dir.mkdir(parents=False, exist_ok=True) - output_cpp_dir = Path(args.output_cpp) + output_cpp_dir = Path(idl['output_cpp_dir']) output_cpp_dir.mkdir(parents=False, exist_ok=True) # setup jinja2 @@ -482,7 +481,8 @@ def main(): env = Environment(loader = FileSystemLoader(template_dir), trim_blocks = True, - lstrip_blocks = True) + lstrip_blocks = True, + keep_trailing_newline = True) # custom filters. # A filter 'foo' provides ability to write '{{var | foo}}' to expand diff --git a/xo-facet/codegen/iface_facet_any.hpp.j2 b/xo-facet/codegen/iface_facet_any.hpp.j2 index 87e9d74a..361bb2ef 100644 --- a/xo-facet/codegen/iface_facet_any.hpp.j2 +++ b/xo-facet/codegen/iface_facet_any.hpp.j2 @@ -62,8 +62,11 @@ namespace {{facet_ns2}} { // from {{abstract_facet}} - // const methods + // builtin methods typeseq _typeseq() const noexcept override { return s_typeseq; } + [[noreturn]] void _drop(Opaque) const noexcept override { _fatal(); } + + // const methods {% for md in const_methods %} [[noreturn]] {{md.return_type}} {{md.name}}({{md.args | argtypes}}) {{md | qualifiers}} override { _fatal(); } {% endfor %} diff --git a/xo-facet/codegen/iface_facet_xfer.hpp.j2 b/xo-facet/codegen/iface_facet_xfer.hpp.j2 index c0f02814..80bd79c1 100644 --- a/xo-facet/codegen/iface_facet_xfer.hpp.j2 +++ b/xo-facet/codegen/iface_facet_xfer.hpp.j2 @@ -49,8 +49,11 @@ namespace {{facet_ns2}} { // from {{abstract_facet}} - // const methods + // builtin methods typeseq _typeseq() const noexcept override { return s_typeseq; } + void _drop(Opaque d) const noexcept override { _dcast(d).~DRepr(); } + + // const methods {% for md in const_methods %} {{md.return_type}} {{md.name}}({{md.args | args}}) {{md | qualifiers}} override { return I::{{md.name}}({{md.args | argnames}}); diff --git a/xo-facet/codegen/router_facet.hpp.j2 b/xo-facet/codegen/router_facet.hpp.j2 index b8d70733..067a87c2 100644 --- a/xo-facet/codegen/router_facet.hpp.j2 +++ b/xo-facet/codegen/router_facet.hpp.j2 @@ -56,8 +56,16 @@ public: ///@{ {% endif %} - // const methods + // explicit injected content + {% for content in router_facet_explicit_content %} + {{content}} + {% endfor %} + + // builtin methods typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); } + void _drop() const noexcept { O::iface()->_drop(O::data()); } + + // const methods {% for md in const_methods %} {{md.return_type}} {{md.name}}({{md.args | argsnodata}}) {{md | qualifiers}} { return O::iface()->{{md.name}}({{md.args | argrouting}}); diff --git a/xo-facet/include/xo/facet/FacetRegistry.hpp b/xo-facet/include/xo/facet/FacetRegistry.hpp index 2a3aa48c..a69735a9 100644 --- a/xo-facet/include/xo/facet/FacetRegistry.hpp +++ b/xo-facet/include/xo/facet/FacetRegistry.hpp @@ -7,9 +7,11 @@ #pragma once +#include "TypeRegistry.hpp" #include "facet_implementation.hpp" -#include "typeseq.hpp" +//#include "typeseq.hpp" #include "obj.hpp" +#include #include #include #include @@ -38,6 +40,7 @@ namespace xo { **/ class FacetRegistry { public: + using MemorySizeVisitor = xo::mm::MemorySizeVisitor; using typeseq = xo::reflect::typeseq; using key_type = std::pair; @@ -51,9 +54,12 @@ namespace xo { } }; - /** singleton instance **/ - static FacetRegistry & instance() { - static FacetRegistry s_instance; + /** singleton instance. + * @p hint_max_capacity is a lower bound for swiss hash map implementation. + * Only honored the first time instance is called. + **/ + static FacetRegistry & instance(uint32_t hint_max_capacity = 1024) { + static FacetRegistry s_instance(hint_max_capacity); return s_instance; } @@ -69,6 +75,9 @@ namespace xo { static void register_impl() { static FacetImplType impl; + TypeRegistry::register_type(); + TypeRegistry::register_type(); + instance()._register_impl(typeseq::id(), typeseq::id(), &impl); @@ -88,6 +97,11 @@ namespace xo { /** Number of registered (facet, repr) pairs **/ std::size_t size() const { return registry_.size(); } + /** visit memory pools owned by facet registry **/ + void visit_pools(const MemorySizeVisitor & visitor) { + registry_.visit_pools(visitor); + } + /** Check if implementation is registered **/ bool contains(typeseq facet_id, typeseq repr_id) const @@ -115,7 +129,7 @@ namespace xo { * obj foo * = ...; // Foo instance with variant impl * obj bar - * = FacetRegistry::variant(foo); + * = FacetRegistry::instance().variant(foo); * * // exception thrown if bar has null data * @@ -128,7 +142,8 @@ namespace xo { if (!retval) throw std::runtime_error(tostr("FacetRegistry::try_variant failed", xtag("AFrom.tseq", typeseq::id()), - xtag("ATo.tseq", typeseq::id()))); + xtag("ATo.tseq", typeseq::id()), + xtag("DRepr", from._typeseq()))); return retval; } @@ -140,7 +155,7 @@ namespace xo { * obj foo * = ...; // Foo instance with variant impl * obj bar - * = FacetRegistry::try_variant(foo); + * = FacetRegistry::instance().try_variant(foo); * if (bar) { * // success * } else { @@ -148,7 +163,7 @@ namespace xo { * } **/ template - obj try_variant(obj from) { + obj try_variant(obj from) noexcept { return try_variant(from._typeseq(), from.data()); } @@ -162,7 +177,7 @@ namespace xo { * = FacetRegistry::variant(foo._typeseq(), foo.opaque_data()); **/ template - obj try_variant(typeseq repr_id, void * data) { + obj try_variant(typeseq repr_id, void * data) noexcept { const AFacet * iface = this->lookup(repr_id); if (iface) @@ -220,12 +235,55 @@ namespace xo { } private: - FacetRegistry() = default; + FacetRegistry(uint32_t hint_max_capacity) + : registry_("facets", hint_max_capacity, false /*!debug_flag*/) {} /** runtime lookup table (AFacet,DRepr) -> impl **/ - std::unordered_map registry_; + xo::map::DArenaHashMap registry_; }; + // Deferred definitioon of obj::to_facet(), + // since implementation requires FacetRegistry + // + template + template + obj + obj::to_facet() + { + if (this->data()) { + if constexpr (std::is_same_v) { + // return type has type-erased data + return FacetRegistry::instance().variant(*this); + } else { + // return type has known data + return obj(this->data()); + } + } else { + return obj(); + } + } + + // Deferred definitioon of obj::to_facet(), + // since implementation requires FacetRegistry + // + template + template + obj + obj::try_to_facet() noexcept + { + if (this->data()) { + if constexpr (std::is_same_v) { + // return type has type-erased data + return FacetRegistry::instance().try_variant(*this); + } else { + // return type has known data + return obj(this->data()); + } + } else { + return obj(); + } + } + } /*namespace facet*/ } /*namespace xo*/ diff --git a/xo-facet/include/xo/facet/OObject.hpp b/xo-facet/include/xo/facet/OObject.hpp index e4ed5b06..234a84df 100644 --- a/xo-facet/include/xo/facet/OObject.hpp +++ b/xo-facet/include/xo/facet/OObject.hpp @@ -59,6 +59,10 @@ namespace xo { **/ template struct OObject { + static_assert(has_facet_impl, + "Missing FacetImplementation specialization. " + "Did you include IFacet_DRepr.hpp (via the convenience header)?"); + using FacetType = AFacet; using ISpecific = FacetImplType; using DataType = DRepr; @@ -253,6 +257,15 @@ namespace xo { //iface_ = *std::launder(&iface_); } + /** use this to access non-facet methods, + * _when representation is known at compile time_. + * + * Deliberately disable this for variants + **/ + DRepr * operator->() + requires (!std::is_same_v) + { return data_; } + #ifdef NOPE DRepr & operator*() { return *data_; } #endif diff --git a/xo-facet/include/xo/facet/OUniqueBox.hpp b/xo-facet/include/xo/facet/OUniqueBox.hpp deleted file mode 100644 index d22ad70f..00000000 --- a/xo-facet/include/xo/facet/OUniqueBox.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/** @file OUniqueBox.hpp - * - * @author Roland Conybeare, Dec 2025 - **/ - -namespace xo { - namespace facet { - /** - * Uniquely-owned instance with runtime polymorphism. - * - * Reminder that in the facet object model we expect - * objects to be transient. - * - - * - * Unlike OUniqueBox can use for variant data - * without additional overhead. Tradeoff is that avoiding such - * overhead excludes std::unique_ptr. - * - * We're going to instead rely on AInterface providing a destruct_data() method, - * so in practice get the deleter from interface state. - * - * Possibly means we need all abstract interfaces to share a common base - * - * Remarks: - * - when @tparam Data is supplied - **/ - template - struct OUniqueBox { - using AbstractInterface = AInterface; - using ISpecific = ISpecificFor::ImplType; - /* note: Data can be void here */ - using DataType = Data; - using DataBox = Data*; - - explicit OUniqueBox() {} - /* unsatisfactory b/c doesn't enforce that @p d is heap-allocated */ - explicit OUniqueBox(DataBox d) : data_{std::move(d)} {} - - ~OUniqueBox() { - if (data_ != nullptr) { - this->iface()->destruct_data(data_); - delete data_; - this->data_ = nullptr; - } - } - - const AInterface * iface() const - requires std::is_same_v - { - return std::launder(&iface_); - } - - const AInterface * iface() const - requires (!std::is_same_v) - { - return &iface_; - } - - /** note: would prefer this to be constexpr, but not simple asof gcc 14.3 **/ - static bool _valid; - - /** note: load-bearing for routing classes such as RComplex **/ - Data * data() const { return data_; } - - ISpecific iface_; - DataBox data_ = nullptr; - }; - - - } -} /*namespace xo*/ - -/* end OUniqueBox.hpp */ diff --git a/xo-facet/include/xo/facet/TypeRegistry.hpp b/xo-facet/include/xo/facet/TypeRegistry.hpp new file mode 100644 index 00000000..1f3cb2be --- /dev/null +++ b/xo-facet/include/xo/facet/TypeRegistry.hpp @@ -0,0 +1,137 @@ +/** @file TypeRegistry.hpp + * + * @brief Runtime facet implementation lookup + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "typeseq.hpp" +#include +#include +#include + +namespace xo { + namespace facet { + + /** @class TypeRegistry + * + * @brief Runtime registry for types. + * + * Just assigns ids and remembers names. + * Not a full reflection implementation + **/ + class TypeRegistry { + public: + using ReprType = xo::mm::DArenaVector; + using ArenaConfig = xo::mm::ArenaConfig; + using MemorySizeVisitor = xo::mm::MemorySizeVisitor; + using typeseq = xo::reflect::typeseq; + + /** singleton instance. + * @p hint_max_capacity is a lower bound for registry capacity. + * Only honored the first time instance is called. + **/ + static TypeRegistry & instance(uint32_t hint_max_capacity = 1024) { + static TypeRegistry s_instance(hint_max_capacity); + return s_instance; + } + + /** Type-safe registration + * + * Registers the compile-time FacetImplementation + * for runtime lookup. + * + * @tparam AFacet abstract facet type + * @tparam DRepr data representation type + **/ + template + static void register_type() { + typerecd r = typerecd::recd(); + + instance()._register_type(r); + } + + static std::string_view id2name(typeseq id) noexcept { + return instance()._id2name(id); + } + + /** Number of registered (facet, repr) pairs **/ + std::size_t size() const { return registry_.size(); } + + /** visit memory pools owned by facet registry **/ + void visit_pools(const MemorySizeVisitor & visitor) { + registry_.visit_pools(visitor); + } + + /** Check if type is registered **/ + bool contains(typeseq id) const + { + if ((0 <= id.seqno()) + && (id.seqno() < static_cast(registry_.size()))) + { + return (registry_.at(id.seqno()).seqno() == id.seqno()); + } + + return false; + } + + void dump(std::ostream * p_out) const { + (*p_out) << std::endl; + (*p_out) << " " << item.name() << std::endl; + } + (*p_out) << ">" << std::endl; + } + + private: + /** Register a facet implementation (type-erased) + * + * @param facet_id typeseq for abstract facet (e.g., APrintable) + * @param repr_id typeseq for data representation (e.g., DFloat) + * @param impl pointer to stateless implementation instance + **/ + void _register_type(const typerecd & recd) + { + if ((recd.seqno() >= 0) + && (static_cast(registry_.size()) <= recd.seqno())) + { + registry_.resize(recd.seqno() + 1); + } + + registry_.at(recd.seqno()) = recd; + } + + /** Get typename from @p id. + **/ + std::string_view _id2name(typeseq id) const + { + if ((0 <= id.seqno()) + && (static_cast(id.seqno()) < registry_.size())) + { + return registry_.at(id.seqno()).name(); + } + + return typerecd::sentinel().name(); + } + + private: + TypeRegistry(uint32_t hint_max_capacity) + : registry_(ReprType::map(ArenaConfig() + .with_name("types") + .with_size(hint_max_capacity + * sizeof(typerecd)))) + {} + + /** runtime lookup table (AFacet,DRepr) -> impl **/ + ReprType registry_; + }; + + } /*namespace facet*/ +} /*namespace xo*/ + +/* end TypeRegistry.hpp */ diff --git a/xo-facet/include/xo/facet/box.hpp b/xo-facet/include/xo/facet/box.hpp new file mode 100644 index 00000000..62f797e3 --- /dev/null +++ b/xo-facet/include/xo/facet/box.hpp @@ -0,0 +1,88 @@ +/** @file box.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "obj.hpp" + +namespace xo { + namespace facet { + + /** object with owned state + * - with default DRepr argument: + * type-erased container (runtime polymorphism). + * - with sepcific DRepr argument: + * typed container (comptime polymorphism). + **/ + template + struct box : public RoutingType> { + using Super = RoutingType>; + + box() : Super() {} + + /** box takes ownership of data @p *d; + * will destroy when box goes out of scope. + * + * Note this is not useful when DRepr=DVariablePlaceholder + **/ + explicit box(Super::DataPtr d) : Super(d) {} + + /** Adopt instance that has interface @p iface and (type-erased here) + * representation @p data + **/ + box(const AFacet * iface, void * data) + requires std::is_same_v + : Super(iface, data) + {} + + /** (copy ctor not supported -- ownership is unique) **/ + box(const box & other) = delete; + + // -------------------------------- + + /** Move constructor **/ + template + box(box && other) + requires (std::is_same_v + || std::is_same_v) + : RoutingType>() + { + /* replacing .iface_ along w/ .data_ */ + this->from_obj(other); + + other.reset_opaque(nullptr); + } + + /** explicit conversion to obj **/ + obj to_op() const noexcept { + return obj(this->iface(), this->data()); + } + + /** Take ownership from unowned object **/ + template + box & adopt(const obj & other) + requires (std::is_same_v + || std::is_same_v) + { + /* replace .iface_ along w/ .data_ */ + this->from_obj(other); + + return *this; + } + + ~box() { + auto p = this->data(); + if (p) { + this->_drop(); + ::operator delete(p); + } + } + }; + } /*namespace facet*/ + + using facet::box; +} /*namespace xo*/ + +/* end box.hpp */ diff --git a/xo-facet/include/xo/facet/facet_implementation.hpp b/xo-facet/include/xo/facet/facet_implementation.hpp index 5669860a..7ce2ed5a 100644 --- a/xo-facet/include/xo/facet/facet_implementation.hpp +++ b/xo-facet/include/xo/facet/facet_implementation.hpp @@ -92,7 +92,15 @@ namespace xo { //static_assert(false && "expect specialization which should provide ImplType trait"); }; - /** Retrieve facet implementation for a (facet, datatype) pair **/ + /** true iff FacetImplementation has been specialized with ImplType. + * False when specialization header (IFacet_DRepr.hpp) not included. + **/ + template + concept has_facet_impl = requires { + typename FacetImplementation::ImplType; + }; + + /** Retrieve facet implementation for a (facet,datatype) pair **/ template using FacetImplType = FacetImplementation::ImplType; diff --git a/xo-facet/include/xo/facet/obj.hpp b/xo-facet/include/xo/facet/obj.hpp index b50bf65e..ada5c832 100644 --- a/xo-facet/include/xo/facet/obj.hpp +++ b/xo-facet/include/xo/facet/obj.hpp @@ -6,15 +6,16 @@ #pragma once #include "RRouter.hpp" +//#include "FacetRegistry.hpp" // nope, would create include cycle #include #include namespace xo { namespace facet { /** object with borrowed state pointer - * - With default Data argument: + * - With default DRepr argument: * type-erased polymorphic container - * - with specific Data argument: + * - with specific DRepr argument: * typed container. Trivially de-virtualizable * * Example: @@ -88,7 +89,7 @@ namespace xo { * - same strategy for holding state (naked / unique / refcounted ...) **/ template - obj(const obj && other) + obj(obj && other) requires (std::is_same_v || std::is_convertible_v) : Super() @@ -98,12 +99,17 @@ namespace xo { } obj & operator=(const obj & rhs) { - /* ensure we replace .iface_ along w/ .ata_ */ + /* ensure we replace .iface_ along w/ .data_ */ this->from_obj(rhs); return *this; } - /** safe downcast from variant. null if downcast fails **/ + /** safe downcast from variant. null if downcast fails + * + * Use: + * obj x = ...; + * obj quux = obj::from(x); + **/ static obj from(const OObject & other) { return obj(other.template downcast()); } @@ -122,6 +128,21 @@ namespace xo { return obj(iface, data); } + /** - runtime polymorphism (DRepr == DVariantPlaceholder) + * (requires FacetRegistry for lookup) + * - comptime polymorphism (DRepr != DVariantPlaceholder) + * + * Definition in FacetRegistry.hpp, to avoid #include dependency + **/ + template + obj to_facet(); + + /** like to_facet(), + * but on failure return empty obj instead of throwing exception + **/ + template + obj try_to_facet() noexcept; + /** enabled when RRouter provides _preincrement. * Note we don't need this trick for comparison operators, * since return type is fixed. diff --git a/xo-facet/include/xo/facet/typeseq.hpp b/xo-facet/include/xo/facet/typeseq.hpp index 23b84a92..d43d9e68 100644 --- a/xo-facet/include/xo/facet/typeseq.hpp +++ b/xo-facet/include/xo/facet/typeseq.hpp @@ -12,7 +12,7 @@ namespace xo { namespace facet { // Re-export from xo::arena namespace - using xo::reflect::typeseq_impl; + using xo::reflect::typerecd; using xo::reflect::typeseq; } } /*namespace xo*/ diff --git a/xo-gc/CMakeLists.txt b/xo-gc/CMakeLists.txt index 2ad70af5..df57b1e3 100644 --- a/xo-gc/CMakeLists.txt +++ b/xo-gc/CMakeLists.txt @@ -23,13 +23,14 @@ xo_add_genfacet( TARGET xo-gc-facet-gcobject FACET GCObject INPUT idl/GCObject.json5 - OUTPUT_HPP_DIR include/xo/gc - OUTPUT_IMPL_SUBDIR detail - OUTPUT_CPP_DIR src/gc ) # ---------------------------------------------------------------- +xo_add_genfacet_all(xo-gc-genfacet-all) + +# ---------------------------------------------------------------- + # must complete definition of expression lib before configuring examples add_subdirectory(src/gc) add_subdirectory(utest) diff --git a/xo-gc/cmake/xo_gcConfig.cmake.in b/xo-gc/cmake/xo_gcConfig.cmake.in index c32a8368..aebd133c 100644 --- a/xo-gc/cmake/xo_gcConfig.cmake.in +++ b/xo-gc/cmake/xo_gcConfig.cmake.in @@ -1,7 +1,9 @@ @PACKAGE_INIT@ include(CMakeFindDependencyMacro) -#find_dependency(indentlog) find_dependency(xo_alloc2) +find_dependency(xo_facet) +find_dependency(indentlog) + include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") check_required_components("@PROJECT_NAME@") diff --git a/xo-gc/idl/GCObject.json5 b/xo-gc/idl/GCObject.json5 index ef00b5d9..7056f0b8 100644 --- a/xo-gc/idl/GCObject.json5 +++ b/xo-gc/idl/GCObject.json5 @@ -1,16 +1,21 @@ { mode: "facet", + output_cpp_dir: "src/gc", + output_hpp_dir: "include/xo/gc", + output_impl_subdir: "detail", includes: [ "", "", "", "", ], + // extra includes in GCObject.hpp, if any + user_hpp_includes: [], + namespace1: "xo", + namespace2: "mm", pretext: [ "namespace xo { namespace mm { struct ACollector; }}", ], - namespace1: "xo", - namespace2: "mm", facet: "GCObject", detail_subdir: "detail", brief: "xxx", @@ -74,4 +79,5 @@ attributes: [], }, ], + router_facet_explicit_content: [] } diff --git a/xo-gc/include/xo/gc/DX1Collector.hpp b/xo-gc/include/xo/gc/DX1Collector.hpp index 33c9f56d..2ef7148a 100644 --- a/xo-gc/include/xo/gc/DX1Collector.hpp +++ b/xo-gc/include/xo/gc/DX1Collector.hpp @@ -5,6 +5,7 @@ #pragma once +#include "X1CollectorConfig.hpp" #include "GCObject.hpp" #include "generation.hpp" #include "object_age.hpp" @@ -40,98 +41,6 @@ namespace xo { }; #endif - struct CollectorConfig { - using size_type = std::size_t; - -#ifdef OBSOLETE // get from arena_config_.header_ - /* - * alloc header - * TTTTTTTTTTTTGGGGGZZZZZZZZZZZZ - * < tseq >< size > - * - * masking - * - * ..432107654321076543210 bit - * - * > < .gen_bits - * 0..............01111111 gen_mask_unshifted - * 0..011111110..........0 gen_mask_shifted - * > < gen_shift - */ - //constexpr std::uint64_t gen_mult() const; - constexpr std::uint64_t gen_shift() const; - constexpr std::uint64_t gen_mask_unshifted() const; - constexpr std::uint64_t gen_mask_shifted() const; - - //constexpr std::uint64_t tseq_mult() const; - constexpr std::uint64_t tseq_shift() const; - constexpr std::uint64_t tseq_mask_unshifted() const; - constexpr std::uint64_t tseq_mask_shifted() const; -#endif - - generation age2gen(object_age age) const noexcept { - return generation(age % n_survive_threshold_); - } - - public: - // ----- Instance Variables ----- - - /** optional name, for diagnostics **/ - std::string name_; - - /** Configuration for collector spaces. - * Will have at least {nursery,tenured} x {from,to} spaces. - * Not using name_ member. - * - * REQUIRE: - * - arena_config_.store_header_flag_ must be true - **/ - ArenaConfig arena_config_; - - /** storage for N object types requires 8*N bytes **/ - std::size_t object_types_z_ = 2*1024*1024; - - /** storage for N object roots requires 8*N bytes **/ - std::size_t object_roots_z_ = 16*1024; - - /** number of bits to represent generation **/ - std::uint64_t gen_bits_ = 8; - - /** number of bits to represent tseq **/ - std::uint64_t tseq_bits_ = 24; - - /** Number of generations. - * Must be at least 2. - **/ - uint32_t n_generation_ = 2; - - /** Number of promotion steps. - * An object that survives this number of collections - * advances to the next generation. - **/ - uint32_t n_survive_threshold_ = 2; - - /** Trigger garbage collection when to-space allocation for - * generation g reaches gc_trigger_v_[g] - **/ - std::array gc_trigger_v_; - - /** true -> enable incremental collection. - * false -> only do full collection. - * - * Incremental collection requires mutation logs. - **/ - bool allow_incremental_gc_ = true; - - /** If non-zero remember statistics for - * the last @p stats_history_z_ collections. - **/ - uint32_t stats_history_z_ = false; - - /** true to enable debug logging **/ - bool debug_flag_ = false; - }; - // ----- GCRunState ----- /** @class GCRunState @@ -167,7 +76,18 @@ namespace xo { static constexpr size_t c_max_typeseq = 4096; /** Create X1 collector instance. **/ - explicit DX1Collector(const CollectorConfig & cfg); + explicit DX1Collector(const X1CollectorConfig & cfg); + + /** faceted object pointer to this instance */ + template + obj ref() { return obj(this); } + +#ifdef NOT_YET + /** create instance with default configuration, + * generation size @p gen_z + **/ + static DX1Collector make_std(std::size_t gen_z); +#endif std::string_view name() const { return config_.name_; } @@ -190,6 +110,11 @@ namespace xo { /** total allocated memory in bytes, across all {role, generation} **/ size_type allocated_total() const noexcept; + /** introspection for memory use. + * Call @p visitor(info) for each pool owned by this allocator + **/ + void visit_pools(const MemorySizeVisitor & visitor) const; + /** true iff address @p addr allocated from this collector * in role @p r (according to current GC state) **/ @@ -327,7 +252,7 @@ namespace xo { public: /** garbage collector configuration **/ - CollectorConfig config_; + X1CollectorConfig config_; /** current gc state **/ GCRunState runstate_; diff --git a/xo-gc/include/xo/gc/GCObject.hpp b/xo-gc/include/xo/gc/GCObject.hpp index 25834817..c40ffb3a 100644 --- a/xo-gc/include/xo/gc/GCObject.hpp +++ b/xo-gc/include/xo/gc/GCObject.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/GCObject.json5] * 2. jinja2 template for facet .hpp file: @@ -18,4 +18,30 @@ #include "detail/IGCObject_Xfer.hpp" #include "detail/RGCObject.hpp" -/* end GCObject.hpp */ \ No newline at end of file +namespace xo { + namespace mm { + /** defined here to avoid #include cycle, since + * template obj awkward to make available there + **/ + template + template + void + RCollector::forward_inplace(xo::facet::obj * p_obj) + { + this->forward_inplace(p_obj->iface(), (void **)&(p_obj->data_)); + } + + template + template + void + RCollector::forward_inplace(DRepr ** p_repr) + { + // fetch static interface for DRepr + auto iface = xo::facet::impl_for(); + + this->forward_inplace(&iface, (void **)p_repr); + } + } +} + +/* end GCObject.hpp */ diff --git a/xo-gc/include/xo/gc/GCObjectConversion.hpp b/xo-gc/include/xo/gc/GCObjectConversion.hpp new file mode 100644 index 00000000..8a950c82 --- /dev/null +++ b/xo-gc/include/xo/gc/GCObjectConversion.hpp @@ -0,0 +1,92 @@ +/** @file GCObjectConversion.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include +#include +#include +#include + +namespace xo { + namespace scm { + /** @brief compile-time conversion obj <-> T + * + * Specialize for each T that participates in conversion. + * Methods here aren't implemented + **/ + template + struct GCObjectConversion { + using AGCObject = xo::mm::AGCObject; + using AAllocator = xo::mm::AAllocator; + + /** find gc-aware representation for @p x. + * If necessary allocate from @p mm, but may + * refer to @p x in-place + **/ + static obj to_gco(obj mm, const T & x); + /** convert to native representation @tparam T from gc-aware + * @p gco. If necessary allocate from @p mm, but + * may instead refer to @p x in-place + **/ + static T from_gco(obj mm, obj gco); + }; + + /** Motivating use-case for GCObjectConversion is to transform + * primitive function arguments and results to/from gc-aware + * representation. + * + * However: Schematika also supports runtime polymorphism + * which leads to primitives that expect obj arguments. + * + * Also, Schematika expression parser needs representation for + * expressions, before type unification. + * + * Consider a function like: + * def fact = lambda (n : i64) { if (n <= 0) then 1 else (n * fact(n - 1)); } + * During expression parsing the rhs argument to multiply has unknown type. + * To construct an expression for input to unification will use polymorphic + * binding for multiply primitive, relying on specialization here for + * its implementation. + **/ + template + struct GCObjectConversion> { + using AGCObject = xo::mm::AGCObject; + using AAllocator = xo::mm::AAllocator; + using FacetRegistry = xo::facet::FacetRegistry; + using DVariantPlaceholder = xo::facet::DVariantPlaceholder; + + static obj to_gco(obj, + obj gco) { + if constexpr (std::is_same_v) { + // trivial conversion! + return gco; + } else if constexpr (std::is_same_v) { + // runtime polymorphism + return FacetRegistry::instance().variant(gco); + } else /* DRepr != DVariantPlaceholder */ { + // known content w/ fat object pointer + return obj(gco.data()); + } + } + + static obj from_gco(obj, + obj gco) { + if constexpr (std::is_same_v) { + // trivial conversion + return gco; + } else { + // both runtime and comptime polymorphism + // use same path here, since representation of @p gco + // is type-erased here + + return FacetRegistry::instance().variant(gco); + } + } + }; + } /*namespace scm */ +} /*namespace xo*/ + +/* end GCObjectConversion.hpp */ diff --git a/xo-gc/include/xo/gc/PolyForwarderUtil.hpp b/xo-gc/include/xo/gc/PolyForwarderUtil.hpp new file mode 100644 index 00000000..19f99c9b --- /dev/null +++ b/xo-gc/include/xo/gc/PolyForwarderUtil.hpp @@ -0,0 +1,66 @@ +/** @file PolyForwarderUtil.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "Collector.hpp" +#include + +namespace xo { + namespace mm { + + /** Utility class for forwarding support on + * faceted object pointers that have some primary + * facet _other_ than AGCObject. + * + * For fop with AGCObject facet, with collector gc: + * + * obj gc = ..; + * obj ptr = ..; + * + * gc.forward_inplace(&ptr); + * + * for fop with some other facet: + * + * obj ptr = ..; + * PolyForwarderUtil::forward_inplace(gc, &ptr); + * + * or + * poly_forward_inplace(gc, &ptr); + **/ + class PolyForwarderUtil { + public: + template + static void forward_inplace(obj gc, obj * p_ptr) { + using xo::facet::FacetRegistry; + + /** + * p_ptr + * v FacetRegistry + * +--------+---------+ .variant() +-----------+---------+ + * | AFacet | DRepr x | -----------------> | AGCobject | DRepr x | + * +--------+-------|-+ +-----------+-------|-+ + * | | + * | /-------------------------------------------/ + * | | + * v v + * +-------+ + * | DRepr | + * +-------+ + **/ + + auto gco = FacetRegistry::instance().variant(*p_ptr); + gc.forward_inplace(gco.iface(), (void **)&(p_ptr->data_)); + } + }; + + template + void poly_forward_inplace(obj gc, obj * p_ptr) { + PolyForwarderUtil::forward_inplace(gc, p_ptr); + } + } /*namespace mm*/ +} /*namespace xo*/ + +/* end PolyForwarderUtil.hpp */ diff --git a/xo-gc/include/xo/gc/X1Collector.hpp b/xo-gc/include/xo/gc/X1Collector.hpp new file mode 100644 index 00000000..c9d00da3 --- /dev/null +++ b/xo-gc/include/xo/gc/X1Collector.hpp @@ -0,0 +1,11 @@ +/** @file X1Collector.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DX1Collector.hpp" +#include "detail/ICollector_DX1Collector.hpp" + +/* end X1Collector.hpp */ diff --git a/xo-gc/include/xo/gc/X1CollectorConfig.hpp b/xo-gc/include/xo/gc/X1CollectorConfig.hpp new file mode 100644 index 00000000..dec9545d --- /dev/null +++ b/xo-gc/include/xo/gc/X1CollectorConfig.hpp @@ -0,0 +1,97 @@ +/** @file X1CollectorConfig.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "object_age.hpp" +#include "generation.hpp" +#include +#include +#include + +namespace xo { + namespace mm { + struct X1CollectorConfig { + using size_type = std::size_t; + + /** copy of this config, + * but with @ref name_ set to @p name + **/ + X1CollectorConfig with_name(std::string name); + + /** copy of this config, + * but with @c arena_config_.size_ set to @p gen_z + **/ + X1CollectorConfig with_size(std::size_t gen_z); + + generation age2gen(object_age age) const noexcept { + return generation(age % n_survive_threshold_); + } + + public: + // ----- Instance Variables ----- + + /** optional name, for diagnostics **/ + std::string name_; + + /** Configuration for collector spaces. + * Will have at least {nursery,tenured} x {from,to} spaces. + * Not using name_ member. + * + * REQUIRE: + * - arena_config_.store_header_flag_ must be true + **/ + ArenaConfig arena_config_; + + /** storage for N object types requires 8*N bytes **/ + std::size_t object_types_z_ = 2*1024*1024; + + /** storage for N object roots requires 8*N bytes **/ + std::size_t object_roots_z_ = 16*1024; + + /** number of bits to represent generation **/ + std::uint64_t gen_bits_ = 8; + + /** number of bits to represent tseq **/ + std::uint64_t tseq_bits_ = 24; + + /** Number of generations. + * Must be at least 2. + **/ + uint32_t n_generation_ = 2; + + /** Number of promotion steps. + * An object that survives this number of collections + * advances to the next generation. + **/ + uint32_t n_survive_threshold_ = 2; + + /** Trigger garbage collection when to-space allocation for + * generation g reaches gc_trigger_v_[g] + **/ + std::array gc_trigger_v_; + + /** true -> enable incremental collection. + * false -> only do full collection. + * + * Incremental collection requires mutation logs. + **/ + bool allow_incremental_gc_ = true; + + /** If non-zero remember statistics for + * the last @p stats_history_z_ collections. + **/ + uint32_t stats_history_z_ = false; + + /** true to enable debug logging **/ + bool debug_flag_ = false; + }; + + + } /*namespace mm*/ +} /*namespace xo*/ + +/* end X1CollectorConfig.hpp */ + diff --git a/xo-gc/include/xo/gc/detail/AGCObject.hpp b/xo-gc/include/xo/gc/detail/AGCObject.hpp index b7a5ffa3..98f7e258 100644 --- a/xo-gc/include/xo/gc/detail/AGCObject.hpp +++ b/xo-gc/include/xo/gc/detail/AGCObject.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/GCObject.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -55,6 +55,8 @@ public: // const methods /** RTTI: unique id# for actual runtime data representation **/ virtual typeseq _typeseq() const noexcept = 0; + /** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/ + virtual void _drop(Opaque d) const noexcept = 0; /** memory consumption for this instance **/ virtual size_type shallow_size(Copaque data) const noexcept = 0; /** copy instance using allocator **/ @@ -82,4 +84,4 @@ using IGCObject_ImplType = xo::facet::FacetImplType; } /*namespace mm*/ } /*namespace xo*/ -/* AGCObject.hpp */ \ No newline at end of file +/* AGCObject.hpp */ diff --git a/xo-gc/include/xo/gc/detail/IAllocator_DX1Collector.hpp b/xo-gc/include/xo/gc/detail/IAllocator_DX1Collector.hpp index 424f24ff..ca529990 100644 --- a/xo-gc/include/xo/gc/detail/IAllocator_DX1Collector.hpp +++ b/xo-gc/include/xo/gc/detail/IAllocator_DX1Collector.hpp @@ -48,6 +48,8 @@ namespace xo { static size_type available(const DX1Collector &) noexcept; /** space used by @p d across all {roles, generations}. **/ static size_type allocated(const DX1Collector &) noexcept; + /** visit memory pools owned by this allocator; call fn(info) for each pool **/ + static void visit_pools(const DX1Collector & d, const MemorySizeVisitor & fn); /** true iff address @p p comes from collector @p d **/ static bool contains(const DX1Collector & d, const void * p) noexcept; /** report last error, if any, for collector @p d **/ diff --git a/xo-gc/include/xo/gc/detail/IGCObject_Any.hpp b/xo-gc/include/xo/gc/detail/IGCObject_Any.hpp index c930693f..9ff7bb2e 100644 --- a/xo-gc/include/xo/gc/detail/IGCObject_Any.hpp +++ b/xo-gc/include/xo/gc/detail/IGCObject_Any.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/GCObject.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -56,8 +56,11 @@ namespace mm { // from AGCObject - // const methods + // builtin methods typeseq _typeseq() const noexcept override { return s_typeseq; } + [[noreturn]] void _drop(Opaque) const noexcept override { _fatal(); } + + // const methods [[noreturn]] size_type shallow_size(Copaque) const noexcept override { _fatal(); } [[noreturn]] Opaque shallow_copy(Copaque, obj) const noexcept override { _fatal(); } @@ -87,4 +90,4 @@ namespace mm { } /*namespace mm */ } /*namespace xo */ -/* IGCObject_Any.hpp */ \ No newline at end of file +/* IGCObject_Any.hpp */ diff --git a/xo-gc/include/xo/gc/detail/IGCObject_Xfer.hpp b/xo-gc/include/xo/gc/detail/IGCObject_Xfer.hpp index 655263bf..7f094ab7 100644 --- a/xo-gc/include/xo/gc/detail/IGCObject_Xfer.hpp +++ b/xo-gc/include/xo/gc/detail/IGCObject_Xfer.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/GCObject.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -44,8 +44,11 @@ namespace mm { // from AGCObject - // const methods + // builtin methods typeseq _typeseq() const noexcept override { return s_typeseq; } + void _drop(Opaque d) const noexcept override { _dcast(d).~DRepr(); } + + // const methods size_type shallow_size(Copaque data) const noexcept override { return I::shallow_size(_dcast(data)); } @@ -89,4 +92,4 @@ namespace mm { } /*namespace mm */ } /*namespace xo*/ -/* end IGCObject_Xfer.hpp */ \ No newline at end of file +/* end IGCObject_Xfer.hpp */ diff --git a/xo-gc/include/xo/gc/detail/RCollector.hpp b/xo-gc/include/xo/gc/detail/RCollector.hpp index 5e3eddb3..9cce4844 100644 --- a/xo-gc/include/xo/gc/detail/RCollector.hpp +++ b/xo-gc/include/xo/gc/detail/RCollector.hpp @@ -23,6 +23,16 @@ namespace xo { RCollector() = default; RCollector(DataPtr data) : Object{std::move(data)} {} + /** forward op in place. Defined in GCObject.hpp to avoid #include cycle **/ + template + void forward_inplace(obj * p_obj); + + /** another convenience template for forwarding. + * Defined in RGCObject.hpp to avoid #include cycle. + **/ + template + void forward_inplace(DRepr ** pp_repr); + int32_t _typeseq() const noexcept { return O::iface()->_typeseq(); } size_type allocated(generation g, role r) const noexcept { return O::iface()->allocated(O::data(), g, r); } size_type reserved(generation g, role r) const noexcept { return O::iface()->reserved(O::data(), g, r); } diff --git a/xo-gc/include/xo/gc/detail/RGCObject.hpp b/xo-gc/include/xo/gc/detail/RGCObject.hpp index e54a2539..d24994a8 100644 --- a/xo-gc/include/xo/gc/detail/RGCObject.hpp +++ b/xo-gc/include/xo/gc/detail/RGCObject.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/GCObject.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -40,13 +40,21 @@ public: ///@{ RGCObject() {} RGCObject(Object::DataPtr data) : Object{std::move(data)} {} + RGCObject(const AGCObject * iface, void * data) + requires std::is_same_v + : Object(iface, data) {} ///@} /** @defgroup mm-gcobject-router-methods **/ ///@{ - // const methods + // explicit injected content + + // builtin methods typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); } + void _drop() const noexcept { O::iface()->_drop(O::data()); } + + // const methods size_type shallow_size() const noexcept { return O::iface()->shallow_size(O::data()); } @@ -54,7 +62,7 @@ public: return O::iface()->shallow_copy(O::data(), mm); } - // non-const methods + // non-const methods (still const in router!) size_type forward_children(obj gc) noexcept { return O::iface()->forward_children(O::data(), gc); } @@ -82,4 +90,4 @@ namespace xo { namespace facet { }; } } -/* end RGCObject.hpp */ \ No newline at end of file +/* end RGCObject.hpp */ diff --git a/xo-gc/src/gc/DX1Collector.cpp b/xo-gc/src/gc/DX1Collector.cpp index 263e5b8e..8cbd0bbd 100644 --- a/xo-gc/src/gc/DX1Collector.cpp +++ b/xo-gc/src/gc/DX1Collector.cpp @@ -24,19 +24,22 @@ namespace xo { using xo::facet::with_facet; namespace mm { -#ifdef NOT_USING - constexpr std::uint64_t - CollectorConfig::gen_mult() const { - return 1ul << arena_config_.header_size_bits_; - } -#endif -#ifdef NOT_USING - constexpr std::uint64_t - CollectorConfig::tseq_mult() const { - return 1ul << (gen_bits_ + arena_config_.header_size_bits_); + X1CollectorConfig + X1CollectorConfig::with_name(std::string name) + { + X1CollectorConfig copy = *this; + copy.name_ = std::move(name); + return copy; + } + + X1CollectorConfig + X1CollectorConfig::with_size(std::size_t gen_z) + { + X1CollectorConfig copy = *this; + copy.arena_config_ = arena_config_.with_size(gen_z); + return copy; } -#endif // ----- GCRunState ----- @@ -60,7 +63,7 @@ namespace xo { using size_type = xo::mm::DX1Collector::size_type; - DX1Collector::DX1Collector(const CollectorConfig & cfg) : config_{cfg} + DX1Collector::DX1Collector(const X1CollectorConfig & cfg) : config_{cfg} { assert(config_.arena_config_.header_.size_bits_ + config_.arena_config_.header_.age_bits_ + @@ -87,8 +90,18 @@ namespace xo { .store_header_flag_ = false}); for (uint32_t igen = 0, ngen = cfg.n_generation_; igen < ngen; ++igen) { - space_storage_[0][igen] = DArena::map(cfg.arena_config_); - space_storage_[1][igen] = DArena::map(cfg.arena_config_); + { + char buf[40]; + snprintf(buf, sizeof(buf), "x1-space-G%u-a", igen); + + space_storage_[0][igen] = DArena::map(cfg.arena_config_.with_name(std::string(buf))); + } + { + char buf[40]; + snprintf(buf, sizeof(buf), "x1-space-G%u-b", igen); + + space_storage_[1][igen] = DArena::map(cfg.arena_config_.with_name(std::string(buf))); + } space_[role::to_space()][igen] = &space_storage_[0][igen]; space_[role::from_space()][igen] = &space_storage_[1][igen]; @@ -100,6 +113,19 @@ namespace xo { } } + void + DX1Collector::visit_pools(const MemorySizeVisitor & visitor) const + { + object_types_.visit_pools(visitor); + roots_.visit_pools(visitor); + + for (uint32_t i = 0; i < c_n_role; ++i) { + for (uint32_t j = 0; j < config_.n_generation_; ++j) { + space_storage_[i][j].visit_pools(visitor); + } + } + } + bool DX1Collector::contains(role r, const void * addr) const noexcept { @@ -253,7 +279,7 @@ namespace xo { DX1Collector::add_gc_root_poly(obj * p_root) noexcept { std::byte * mem - = roots_.alloc(typeseq::anon(), + = roots_.alloc(typeseq::sentinel(), sizeof(obj*)); assert(mem); diff --git a/xo-gc/src/gc/IAllocator_DX1Collector.cpp b/xo-gc/src/gc/IAllocator_DX1Collector.cpp index 58e89941..039e84df 100644 --- a/xo-gc/src/gc/IAllocator_DX1Collector.cpp +++ b/xo-gc/src/gc/IAllocator_DX1Collector.cpp @@ -56,6 +56,12 @@ namespace xo { return d.allocated_total(); } + void + IAllocator_DX1Collector::visit_pools(const DX1Collector & d, const MemorySizeVisitor & visitor) + { + d.visit_pools(visitor); + } + bool IAllocator_DX1Collector::contains(const DX1Collector & d, const void * addr) noexcept { diff --git a/xo-gc/src/gc/IGCObject_Any.cpp b/xo-gc/src/gc/IGCObject_Any.cpp index ff6d395d..778760ad 100644 --- a/xo-gc/src/gc/IGCObject_Any.cpp +++ b/xo-gc/src/gc/IGCObject_Any.cpp @@ -44,4 +44,4 @@ IGCObject_Any::forward_children(Opaque, obj) const noexcept -> siz } /*namespace mm*/ } /*namespace xo*/ -/* end IGCObject_Any.cpp */ \ No newline at end of file +/* end IGCObject_Any.cpp */ diff --git a/xo-gc/utest/Collector.test.cpp b/xo-gc/utest/Collector.test.cpp index f322c286..318c9c21 100644 --- a/xo-gc/utest/Collector.test.cpp +++ b/xo-gc/utest/Collector.test.cpp @@ -23,7 +23,7 @@ namespace xo { using xo::mm::AAllocator; using xo::mm::ACollector; - using xo::mm::CollectorConfig; + using xo::mm::X1CollectorConfig; using xo::mm::DX1Collector; using xo::mm::ArenaConfig; using xo::mm::AllocHeaderConfig; @@ -61,12 +61,12 @@ namespace xo { 0 /*tseq_bits*/, 0 /*age_bits*/, 16 /*size_bits*/), }; - CollectorConfig cfg = { .arena_config_ = arena_cfg, - .n_generation_ = 2, - .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0}} }; + X1CollectorConfig cfg = { .arena_config_ = arena_cfg, + .n_generation_ = 2, + .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}} }; DX1Collector gc = DX1Collector{cfg}; @@ -109,12 +109,12 @@ namespace xo { 0 /*tseq_bits*/, 0 /*age_bits*/, 16 /*size_bits*/), }; - CollectorConfig cfg = { .arena_config_ = arena_cfg, - .n_generation_ = 2, - .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0}} }; + X1CollectorConfig cfg = { .arena_config_ = arena_cfg, + .n_generation_ = 2, + .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}} }; DX1Collector gc = DX1Collector{cfg}; @@ -135,12 +135,12 @@ namespace xo { 0 /*tseq-bits*/, 0 /*age-bits*/, 16 /*size-bits*/), }; - CollectorConfig cfg = { .arena_config_ = arena_cfg, - .n_generation_ = 2, - .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0}} }; + X1CollectorConfig cfg = { .arena_config_ = arena_cfg, + .n_generation_ = 2, + .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}} }; DX1Collector gc = DX1Collector{cfg}; @@ -165,12 +165,12 @@ namespace xo { 16 /*size-bits*/), }; /* collector with one generation collapses to a non-generational copying collector */ - CollectorConfig cfg = { .arena_config_ = arena_cfg, - .n_generation_ = 1, - .gc_trigger_v_ = {{64*1024, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0}} }; + X1CollectorConfig cfg = { .arena_config_ = arena_cfg, + .n_generation_ = 1, + .gc_trigger_v_ = {{64*1024, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}} }; DX1Collector x1state = DX1Collector{cfg}; @@ -209,12 +209,12 @@ namespace xo { }; /* collector with one generation collapses to a non-generational copying collector */ - CollectorConfig cfg = { .arena_config_ = arena_cfg, - .n_generation_ = 1, - .gc_trigger_v_ = {{64*1024, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0}} }; + X1CollectorConfig cfg = { .arena_config_ = arena_cfg, + .n_generation_ = 1, + .gc_trigger_v_ = {{64*1024, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}} }; /* X1 allocator+collector */ DX1Collector x1state = DX1Collector{cfg}; diff --git a/xo-gc/utest/DX1CollectorIterator.test.cpp b/xo-gc/utest/DX1CollectorIterator.test.cpp index 99347fad..137c07f3 100644 --- a/xo-gc/utest/DX1CollectorIterator.test.cpp +++ b/xo-gc/utest/DX1CollectorIterator.test.cpp @@ -24,7 +24,7 @@ namespace xo { using xo::mm::DX1CollectorIterator; using xo::mm::DArena; using xo::mm::DArenaIterator; - using xo::mm::CollectorConfig; + using xo::mm::X1CollectorConfig; using xo::mm::ArenaConfig; using xo::mm::AllocHeaderConfig; using xo::mm::cmpresult; @@ -51,12 +51,12 @@ namespace xo { 0 /*tseq_bits*/, 0 /*age_bits*/, 16 /*size_bits*/), }; - CollectorConfig cfg = { .arena_config_ = arena_cfg, - .n_generation_ = 2, - .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0}} }; + X1CollectorConfig cfg = { .arena_config_ = arena_cfg, + .n_generation_ = 2, + .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}} }; DX1Collector gc = DX1Collector{cfg}; @@ -94,12 +94,12 @@ namespace xo { 0 /*tseq_bits*/, 0 /*age_bits*/, 16 /*size_bits*/), }; - CollectorConfig cfg = { .arena_config_ = arena_cfg, - .n_generation_ = 2, - .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0}} }; + X1CollectorConfig cfg = { .arena_config_ = arena_cfg, + .n_generation_ = 2, + .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}} }; DX1Collector gc = DX1Collector{cfg}; obj a1o{&gc}; @@ -110,7 +110,7 @@ namespace xo { REQUIRE(a1o.allocated() == 0); size_t req_z = 13; - byte * mem = gc.alloc(typeseq::anon(), req_z); + byte * mem = gc.alloc(typeseq::sentinel(), req_z); REQUIRE(mem != nullptr); diff --git a/xo-gc/utest/random_allocs.cpp b/xo-gc/utest/random_allocs.cpp index 1f7f833f..2325140d 100644 --- a/xo-gc/utest/random_allocs.cpp +++ b/xo-gc/utest/random_allocs.cpp @@ -67,7 +67,7 @@ namespace utest { bool ok_flag = true; - std::byte * mem = mm.alloc(typeseq::anon(), z); + std::byte * mem = mm.alloc(typeseq::sentinel(), z); log && log(xtag("i_alloc", i_alloc), xtag("si", si), diff --git a/xo-indentlog/include/xo/indentlog/log_state.hpp b/xo-indentlog/include/xo/indentlog/log_state.hpp index e28fb2c4..461f2c7b 100644 --- a/xo-indentlog/include/xo/indentlog/log_state.hpp +++ b/xo-indentlog/include/xo/indentlog/log_state.hpp @@ -255,157 +255,6 @@ namespace xo { // instead of post-processing, rely on newline-aware log_streambuf // to indent in advance -#ifdef OBSOLETE - log_streambuf_type * sbuf2 = this->p_sbuf_phase2_.get(); - - /* often sbuf contains one line of output. - * if it contains multiple newlines, need to indent - * after each one. - * - * will scan output in *sbuf1, post-process to *sbuf2, - * then write *sbuf2 to output stream - * - * note: we inherit .lpos from prec call to .flush2sbuf(), - * in the unlikely event that it's non-zero - */ - char const * s = sbuf1->lo(); - - char const * e = s + sbuf1->pos(); - char const * p = s; - - /* point to first space following a non-space character. - * will indent to just after this space - */ - char const * space_after_nonspace = nullptr; - - /* true on VT100 color escape (\033); in which case false on terminating char (m) - * don't advance lpos during escape - */ - bool in_color_escape = false; - - while(true) { - bool have_nonspace = false; - - /* invariant: s<=p<=e */ - - /* for indenting, looking for first 'space following non-space, on first line', if any */ - -#ifdef OBSOLETE - // ..multiline input should have already been indented by custom log_streambuf. - // may need to extend to recognize terminal control sequences like below - - std::size_t lpos_on_newline = 0; -#endif - -#ifdef OBSOLETE - while(p < e) { - if(space_after_nonspace) { - ; - } else { - if(*p != ' ') - have_nonspace = true; - - if(have_nonspace && (*p == ' ')) { - space_after_nonspace = p; - } - } - - if (in_color_escape && (*p != '\n')) { - /* in color escape -> don't advance .lpos */ - if (*p == 'm') - in_color_escape = false; - ++p; - } else if (*p == '\033') { - /* begin color escape sequence */ - in_color_escape = true; - ++p; - } else if (*p == '\n') { - /* reset .pos on newline; also drop any (incomplete + ill-formed) color escape */ - - in_color_escape = false; - -#ifdef OBSOLETE - lpos_on_newline = this->lpos_; - this->lpos_ = 0; -#endif - - ++p; - break; - } else { - /* increment .lpos on non-newline */ - ++(this->lpos_); - ++p; - } - } -#endif - - /* p=e or *p=\n */ - - /* charseq [s,p) does not contain any newlines, print it */ - if (lpos_on_newline > 0) { - /* charseq [s,p) does not contain any newlines, print it */ - sbuf2->sputn(s, p - s - 1); - - if (this->location_flag_) { - /* 'tab' to position lpos for [file:line] */ - sbuf2->sputc(' '); - for (std::uint32_t i = lpos_on_newline + 1; i < log_config::location_tab; ++i) - sbuf2->sputc(' '); - - std::stringstream ss; - ss << code_location(this->file_, this->line_, - log_config::code_location_color); - - std::string ss_str = ss.str(); /*hoping for copy elision here*/ - sbuf2->sputn(ss_str.c_str(), ss_str.size()); - - this->location_flag_ = false; - this->file_ = ""; - this->line_ = 0; - } - - sbuf2->sputc('\n'); - } else { - /* control here if .flush2sbuf() called without trailing newline in .p_sbuf_phase1 */ - sbuf2->sputn(s, p - s); - } - - if (p == e) - break; - - // { - // char buf[80]; - // snprintf(buf, sizeof(buf), "*** indent=[%d] next=[%c]", this->nesting_level_, *(p+1)); - // - // std::clog.rdbuf()->sputn(buf, strlen(buf)); - //} - - /* control here only for continuation lines (application logging code embedding its own newlines) - * - minimum indent = nesting level; - * - however if space_after_nonspace defined, also indent for that - */ - std::uint32_t n_indent = 0; - - n_indent += this->calc_time_indent(); - - n_indent += std::min(this->nesting_level_ * log_config::indent_width, - log_config::max_indent_width); - -#ifdef OBSOLETE // nice try, broken for multiline input + written before log_streambuf calculated lpos - /* this is just to indent for per-line entry/exit label */ - if(space_after_nonspace) - n_indent += (space_after_nonspace - s); -#endif - - for(std::uint32_t i = 0; i < n_indent; ++i) - sbuf2->sputc(' '); - - s = p; - } - - /* now write entire contents of *sbuf2 to clog */ - p_sbuf->sputn(sbuf2->lo(), sbuf2->pos()); -#endif p_sbuf->sputn(sbuf1->lo(), sbuf1->pos()); /* reset streams for next message */ diff --git a/xo-indentlog/include/xo/indentlog/log_streambuf.hpp b/xo-indentlog/include/xo/indentlog/log_streambuf.hpp index b6e9305d..e9672f47 100644 --- a/xo-indentlog/include/xo/indentlog/log_streambuf.hpp +++ b/xo-indentlog/include/xo/indentlog/log_streambuf.hpp @@ -4,6 +4,7 @@ #include "print/quoted_char.hpp" #include +#include #include #include // e.g. for std::memcpy() #include @@ -19,7 +20,7 @@ namespace xo { public: struct rewind_state { explicit rewind_state(std::size_t solpos, std::size_t color_esc, std::uint32_t p) - : solpos{solpos}, color_escape_chars{color_esc}, pos{p} {} + : solpos{solpos}, color_escape_chars{color_esc}, pos{p} {} std::size_t solpos = 0; std::size_t color_escape_chars = 0; @@ -33,22 +34,46 @@ namespace xo { } /*ctor*/ std::streamsize capacity() const { return this->buf_v_.size(); } - char const * lo() const { return this->pbase(); } - char const * hi() const { return this->lo() + this->capacity(); } + const char * lo() const { return this->pbase(); } + const char * hi() const { return this->lo() + this->capacity(); } std::uint32_t pos() const { return this->pptr() - this->pbase(); } + /** output position (relative to pbase) when local state last computed. Exposed here for unit tests **/ + const char * _local_ppos() const { return local_ppos_; } + /** position (relative to pbase) one character after last \n or \r. For unit tests **/ + std::uint32_t _solpos() const { return solpos_; } + /** start of incomplete color-escape sequence **/ + const char * _color_escape_start() const { return color_escape_start_; } + /** number of non-printing chars after @ref solpos_ from completed color-escape sequences **/ + std::uint32_t _color_escape_chars() const { return color_escape_chars_; } + /** number of visible characters since start of line (last \n or \r) **/ std::uint32_t lpos() const { - assert(pos() >= solpos_ + color_escape_chars_); + if (debug_flag_) { + std::cerr << "log_streambuf::lpos: enter" << std::endl; + } + + // logically-const. lazy implementation + log_streambuf * self = const_cast(this); + + self->_check_update_local_state(); + return pos() - solpos_ - color_escape_chars_; } rewind_state checkpoint() const { + // logically-const. lazy implementation + log_streambuf * self = const_cast(this); + + self->_check_update_local_state(); + return rewind_state(solpos_, color_escape_chars_, pos()); } bool debug_flag() const { return debug_flag_; } + operator std::basic_string_view () const { return std::basic_string_view(this->pbase(), this->pptr()); } + void reset_stream() { char * p_lo = &(this->buf_v_[0]); char * p_hi = p_lo + this->capacity(); @@ -56,6 +81,7 @@ namespace xo { /* tells parent our buffer extent */ this->setp(p_lo, p_hi); + this->local_ppos_ = 0; this->solpos_ = 0; this->color_escape_chars_ = 0; this->color_escape_start_ = nullptr; @@ -69,12 +95,16 @@ namespace xo { << std::endl; } - /* .setp(): using for side effect: sets .pptr to .pbase */ + /* .setp(): using just for side effect: sets .pptr to .pbase */ this->setp(this->pbase(), this->epptr()); + /* advance pptr to saved position */ this->pbump(s.pos); + this->local_ppos_ = this->pptr() - this->pbase(); this->solpos_ = s.solpos; this->color_escape_chars_ = s.color_escape_chars; + /* assuming we never try to capture rewind state with incomplete color escape */ + this->color_escape_start_ = nullptr; } protected: @@ -87,6 +117,8 @@ namespace xo { assert(old_n <= static_cast(buf_v_.size())); assert(new_z > buf_v_.capacity()); + /* note: local_ppos_ invariant across expand_to() */ + this->buf_v_.resize(new_z); char * p_base = &(this->buf_v_[0]); @@ -132,51 +164,21 @@ namespace xo { std::memcpy(this->pptr(), s, ncopied); - /* scan range [pptr, pptr+n] for: - * 1. completed color escape sequences \033..m - * - account for chars in these sequences, since non-printing - * 2. newlines (and carriage returns) - * - remember position of last {newline or carriage return) - */ - for (char const * p_lo = this->pptr(), * p_hi = p_lo + n, * p = p_lo; p < p_hi; ++p) { - if (*p == '\n' || *p == '\r') { - this->solpos_ = (p+1 - this->pbase()); - /* reset, since these chars relevant as correction to solpos */ - this->color_escape_chars_ = 0; - /* -> incomplete color escape, broken by newline */ - this->color_escape_start_ = nullptr; - } else if (*p == '\033') { - if (debug_flag_) { - std::cout << "xsputn: \\033 at p-p_lo=" << (p - p_lo) << std::endl; - } - this->color_escape_start_ = p; - } else if (this->color_escape_start_ != nullptr) { - if (*p == 'm') { - /* escape seq non-printing including both endpoints */ - std::int64_t esc_chars = (p+1 - color_escape_start_); - this->color_escape_chars_ += esc_chars; - - if (debug_flag_) { - std::cout << "xsputn: m at p-p_lo" << (p - p_lo) << " +" << esc_chars - << " -> color_escape_chars=" << color_escape_chars_ << std::endl; - } - this->color_escape_start_ = nullptr; - } else if (!isdigit(*p) && (*p != '[') && (*p != ';')) { - /* not color escape after all */ - this->color_escape_start_ = nullptr; - } - } - } - this->pbump(ncopied); + /* now {pbase, pptr} consistent with new input */ + + this->_check_update_local_state(); + return ncopied; } /*xsputn*/ virtual int_type overflow(int_type new_ch) override { + char * old_base = this->pbase(); char * old_pptr = this->pptr(); - std::streamsize old_n = old_pptr - this->pbase(); + /* #of chars buffered */ + std::streamsize old_n = old_pptr - old_base; assert(old_n <= static_cast(this->buf_v_.size())); @@ -184,6 +186,7 @@ namespace xo { std::cout << "overflow: new_ch=" << quoted_char(new_ch) << std::endl; } + /* increase buffer size */ this->expand_to(2 * buf_v_.size()); this->buf_v_[old_n] = new_ch; @@ -191,6 +194,8 @@ namespace xo { if ((new_ch == static_cast('\n')) || (new_ch == static_cast('\r'))) { this->solpos_ = this->pos(); + + // what if new_ch starts color escape ? } if (new_ch == Traits::eof()) { @@ -235,8 +240,130 @@ namespace xo { } /*seekoff*/ private: + void _update_local_state_char(const char * p_lo, const char * p) + { + if ((*p == '\n') || (*p == '\r')) { + this->solpos_ = (p+1 - this->pbase()); + /* reset, since these chars relevant as correction to solpos */ + this->color_escape_chars_ = 0; + /* -> incomplete color escape, broken by newline */ + this->color_escape_start_ = nullptr; + } else if (*p == '\033') { + if (debug_flag_) [[unlikely]] { + std::cout << "xsputn: \\033 at p-p_lo=" << (p - p_lo) << std::endl; + } + this->color_escape_start_ = p; + } else if (this->color_escape_start_ != nullptr) { + if (*p == 'm') { + /* escape seq non-printing including both endpoints */ + std::int64_t esc_chars = (p+1 - color_escape_start_); + + this->color_escape_chars_ += esc_chars; + + if (debug_flag_) [[unlikely]] { + std::cout << "xsputn: m at p-p_lo" << (p - p_lo) << " +" << esc_chars + << " -> color_escape_chars=" << color_escape_chars_ << std::endl; + } + this->color_escape_start_ = nullptr; + } else if (!isdigit(*p) && (*p != '[') && (*p != ';')) { + /* not color escape after all */ + this->color_escape_start_ = nullptr; + } + } + } + + /** recognize stale local state vars: + * @ref solpos_, @ref color_escape_chars_, @ref color_escape_start_. + * + * Require: + * - {pbase, pptr} in consistent state + * Promise: + * - @c local_ppos_ + @c pbase = @c pptr + * - @c solpos_, @c color_escape_chars_, @c color_escape_start_ all up-to-date + **/ + void _check_update_local_state() { + const char * p0 = this->pbase(); + const char * pn = this->pptr(); + + if (debug_flag_) { + std::cerr << "_check_update_local_state:" << std::endl; + std::cerr << " buf: (p0=" << (void*)p0 << ", pn=" << (void*)pn << ")" << std::endl; + std::cerr << " solpos_=" << solpos_ << ", color_escape_chars_=" << color_escape_chars_ << std::endl; + } + + if (p0 + local_ppos_ == pn) [[likely]] { + // solpos_, color_escape_chars_, color_escape_start_ all up-to-date + } else { + // [pnew, pn): input that hasn't been incorporated into + // {solpos_, color_escape_chars_, color_escape_start_) + + const char * pnew = this->pbase() + this->local_ppos_; + + if (debug_flag_) { + std::cerr << "_check_update_local_state: range: (pnew=" << (void*)pnew << ", pn=" << (void*)pn << ")" << std::endl; + } + + for(const char * p = pnew; p < pn; ++p) { + this->_update_local_state_char(p0, p); + } + } + + // solpos_, color_escape_chars_, color_escape_start_ all up-to-date + // for current buffered contents + + this->local_ppos_ = pn - p0; + + if (debug_flag_) { + std::cerr << "_check_update_local_state: pos=" << pos(); + std::cerr << ", solpos=" << solpos_; + std::cerr << ", color_escape_chars=" << color_escape_chars_ << std::endl; + } + + assert(pos() >= solpos_ + color_escape_chars_); + } + + private: + /* + * pbase: start of buffered text. Thils will be address of buf_v_[0] + * + * + * pbase pptr epptr + * v >e1< >e2< v v + * |xx\xxEEExxx\xxxxxxxEExxxxEExxxxxxxEExxx\xEExxxxxx..................| + * ^ ^<------new-------> + * solpos local_ppos + * + * solpos : first character after newline (stale) + * color_escape_pos : e1+e2+.. (stale) + * new : new characters not reflected + * in local_ppos_, color_escape_chars_ etc. + * + * Legend: + * [\] newline + * [x] visible character + * [E] color escape chars + * + * + * after _check_update_local_state(): + * + * + * pbase pptr epptr + * v >e1< v v + * |xx\xxEEExxx\xxxxxxxEExxxxEExxxxxxxEExxx\xEExxxxxx..................| + * ^ ^ + * solpos local_ppos + * + */ + + /** @defgroup logstreambuf-instance-vars **/ + ///@{ + + /** value of pptr (relative to pbase) when _check_update_local_state() last ran **/ + std::size_t local_ppos_ = 0; /** position (relative to pbase) one character after last \n or \r. - * Use to drive @ref lpos + * Use to drive @ref lpos. This _has_ to be lazy, since + * xsputn() isn'g guaranteed to be called when there's room in + * in buffer. **/ std::size_t solpos_ = 0; /** number of non-printing chars after @ref solpos_, from @@ -245,11 +372,14 @@ namespace xo { **/ std::size_t color_escape_chars_ = 0; /** non-null: start of incomplete color escape sequence **/ - char const * color_escape_start_ = nullptr; + const char * color_escape_start_ = nullptr; + /** buffered output stored here **/ std::vector buf_v_; /** true to debug log_streambuf itself **/ bool debug_flag_ = false; + + ///@} }; /*log_streambuf*/ } /*namespace xo*/ diff --git a/xo-indentlog/include/xo/indentlog/print/cond.hpp b/xo-indentlog/include/xo/indentlog/print/cond.hpp new file mode 100644 index 00000000..47883bfa --- /dev/null +++ b/xo-indentlog/include/xo/indentlog/print/cond.hpp @@ -0,0 +1,92 @@ +/** @file cond.hpp + * + * author: Roland Conybeare + **/ + +#pragma once + +#include "ppdetail_atomic.hpp" +#include +#include + +namespace xo { + + /** @class cond_impl + * @brief conditional stream inserter implementation + * + * @tparam T type printed when condition is true + * @tparam U type printed when condition is false + **/ + template + struct cond_impl { + public: + cond_impl(bool condition, const T & if_true, const U & if_false) + : condition_{condition}, + if_true_{if_true}, + if_false_{if_false} {} + + bool condition() const { return condition_; } + const T & if_true() const { return if_true_; } + const U & if_false() const { return if_false_; } + + private: + bool condition_; + T if_true_; + U if_false_; + }; + + /** Create conditional stream inserter. + * + * @param condition when true, print @p if_true; otherwise print @p if_false + * @param if_true value to print when condition is true + * @param if_false value to print when condition is false + * + * Example: + * @code + * std::cout << cond(ptr, xtag("ptr", *ptr), "nullptr"); + * @endcode + **/ + template + auto + cond(bool condition, T && if_true, U && if_false) + { + return cond_impl, std::decay_t> + (condition, + std::forward(if_true), + std::forward(if_false)); + } + + /** Stream insertion operator for cond_impl **/ + template + inline std::ostream & + operator<<(std::ostream & os, const cond_impl & c) + { + if (c.condition()) + os << c.if_true(); + else + os << c.if_false(); + return os; + } + +#ifndef ppdetail_atomic + namespace print { + /** Pretty-printing support for cond_impl **/ + template + struct ppdetail> { + using target_type = cond_impl; + + static bool print_pretty(const ppindentinfo & ppii, + const target_type & c) + { + if (c.condition()) + return ppdetail::print_pretty(ppii, c.if_true()); + else + return ppdetail::print_pretty(ppii, c.if_false()); + } + }; + } +#endif + +} + +/* end cond.hpp */ diff --git a/xo-indentlog/include/xo/indentlog/print/ppconfig.hpp b/xo-indentlog/include/xo/indentlog/print/ppconfig.hpp index 67d1831a..10c89639 100644 --- a/xo-indentlog/include/xo/indentlog/print/ppconfig.hpp +++ b/xo-indentlog/include/xo/indentlog/print/ppconfig.hpp @@ -16,6 +16,21 @@ namespace xo { * Need one read-only instance of this to invoke pretty printer **/ struct ppconfig { + /** @defgroup ppconfig-ctors ppconfig constructors **/ + ///@{ + + /** config to use pretty printer in degenerate form: + * In this form right margin is absurdly far away, + * so should not be forced to use multiple lines. + * + * Note this won't prevent a printer from returning -1 + **/ + static inline ppconfig ugly() { + return ppconfig { .right_margin_ = 99999999, .indent_width_ = 0, .assert_indent_threshold = 10 }; + } + + ///@} + /** @defgroup ppconfig-instance-vars ppconfig instance variables **/ ///@{ diff --git a/xo-indentlog/include/xo/indentlog/print/pretty.hpp b/xo-indentlog/include/xo/indentlog/print/pretty.hpp index 3ae010eb..d215b8b3 100644 --- a/xo-indentlog/include/xo/indentlog/print/pretty.hpp +++ b/xo-indentlog/include/xo/indentlog/print/pretty.hpp @@ -256,6 +256,11 @@ namespace xo { Member && member, Rest&&... rest) { + if constexpr (has_present>) { + if (!member.present()) + return this->print_upto_struct_members(ppii, rest...); + } + if (this->print_upto(" ") && this->print_upto(member)) return this->print_upto_struct_members(ppii, rest...); @@ -268,6 +273,13 @@ namespace xo { Member && member, Rest&&... rest) { + if constexpr (has_present>) { + if (!member.present()) { + this->pretty_struct_members(ppii, rest...); + return; + } + } + newline_indent(ppii.ci1()); this->pretty(member); this->pretty_struct_members(ppii, rest...); @@ -381,6 +393,11 @@ namespace xo { static bool print_pretty(const ppindentinfo & ppii, const Tag & tag) { + if constexpr (has_present) { + if (!tag.present()) + return true; + } + if (ppii.upto()) { if (tag.prefix_space()) ppii.pps()->write(" "); diff --git a/xo-indentlog/include/xo/indentlog/print/tag.hpp b/xo-indentlog/include/xo/indentlog/print/tag.hpp index 026e8205..03a03223 100644 --- a/xo-indentlog/include/xo/indentlog/print/tag.hpp +++ b/xo-indentlog/include/xo/indentlog/print/tag.hpp @@ -6,6 +6,7 @@ #include "concat.hpp" #include "quoted.hpp" #include "color.hpp" +#include #include // STRINGIFY(xyz) -> "xyz" @@ -20,6 +21,12 @@ #define XTAG(x) xo::xtag(STRINGIFY(x), x) namespace xo { + /** concept: true if T has a .present() method returning something bool-like **/ + template + concept has_present = requires(const T& t) { + { t.present() } -> std::convertible_to; + }; + enum class tagstyle { /** print with automatic escapes for embedded special characters * (any of ' ','"','\','\n','\r','\t'). @@ -79,10 +86,13 @@ namespace xo { **/ template struct ref_tag_impl { - ref_tag_impl(Name const & n, Value const & v) : name_{n}, value_{v} {} - ref_tag_impl(Name && n, Value && v) : name_{std::forward(n)}, value_{std::forward(v)} {} + ref_tag_impl(Name const & n, Value const & v, bool present = true) + : name_{n}, value_{v}, present_{present} {} + ref_tag_impl(Name && n, Value && v, bool present = true) + : name_{std::forward(n)}, value_{std::forward(v)}, present_{present} {} constexpr bool prefix_space() const { return PrefixSpace; } + bool present() const { return present_; } Name const & name() const { return name_; } Value const & value() const { return value_; } @@ -90,6 +100,7 @@ namespace xo { private: Name name_; const Value& value_; + bool present_ = true; }; // ----- xtag ----- @@ -150,12 +161,14 @@ namespace xo { /** 'reference raw tag'. * 1. @p v must survive until refrtag is used (i.e. until tag inserted into some stream) * 2. don't escape whitespace when printing value (pretty-printing with parseable structure) + * + * Print nothing if @p present is false **/ template auto - refrtag(Name && n, Value && v) + refrtag(Name && n, Value && v, bool present = true) { - return ref_tag_impl, std::decay_t>(n, v); + return ref_tag_impl, std::decay_t>(n, v, present); } // ----- xrefrtag ----- @@ -164,9 +177,9 @@ namespace xo { **/ template auto - xrefrtag(Name && n, Value && v) + xrefrtag(Name && n, Value && v, bool present = true) { - return ref_tag_impl, std::decay_t>(n, v); + return ref_tag_impl, std::decay_t>(n, v, present); } // ----- operator<< on tag_impl ----- @@ -199,6 +212,9 @@ namespace xo { operator<<(std::ostream &s, ref_tag_impl const & tag) { + if (!tag.present()) + return s; + using xo::print::unq; if (PrefixSpace) diff --git a/xo-indentlog/utest/CMakeLists.txt b/xo-indentlog/utest/CMakeLists.txt index c8ea729c..5fa2bf1b 100644 --- a/xo-indentlog/utest/CMakeLists.txt +++ b/xo-indentlog/utest/CMakeLists.txt @@ -4,7 +4,7 @@ set(SELF_EXECUTABLE_NAME utest.indentlog) set(SELF_SOURCE_FILES fixed.test.cpp quoted.test.cpp vector.test.cpp array.test.cpp timeutil.test.cpp tag.test.cpp filename.test.cpp code_location.test.cpp function.test.cpp pretty_vector.test.cpp - indentlog_utest_main.cpp log_streambuf.test.cpp toppstr.test.cpp) + indentlog_utest_main.cpp log_streambuf.test.cpp toppstr.test.cpp cond.test.cpp) xo_add_utest_executable(${SELF_EXECUTABLE_NAME} ${SELF_SOURCE_FILES}) diff --git a/xo-indentlog/utest/cond.test.cpp b/xo-indentlog/utest/cond.test.cpp new file mode 100644 index 00000000..d360a449 --- /dev/null +++ b/xo-indentlog/utest/cond.test.cpp @@ -0,0 +1,60 @@ +/* @file cond.test.cpp */ + +#include "xo/indentlog/print/cond.hpp" +#include "xo/indentlog/print/tag.hpp" +#include +#include + +using namespace xo; + +namespace ut { + TEST_CASE("cond", "[cond]") { + tag_config::tag_color = color_spec_type::none(); + + { + std::stringstream ss; + ss << cond(true, "yes", "no"); + REQUIRE(ss.str() == "yes"); + } + + { + std::stringstream ss; + ss << cond(false, "yes", "no"); + REQUIRE(ss.str() == "no"); + } + + { + std::stringstream ss; + ss << cond(true, 42, "none"); + REQUIRE(ss.str() == "42"); + } + + { + std::stringstream ss; + ss << cond(false, 42, "none"); + REQUIRE(ss.str() == "none"); + } + + { + std::stringstream ss; + + int * ptr = nullptr; + + ss << cond(ptr, xtag("ptr", 123), xtag("ptr", "null")); + + REQUIRE(ss.str() == " :ptr null"); + } + + { + std::stringstream ss; + + int * ptr = nullptr; + + ss << xtag("ptr", cond(ptr, 123, "null")); + + REQUIRE(ss.str() == " :ptr null"); + } + } +} + +/* end cond.test.cpp */ diff --git a/xo-indentlog/utest/log_streambuf.test.cpp b/xo-indentlog/utest/log_streambuf.test.cpp index 8098d881..fc3968be 100644 --- a/xo-indentlog/utest/log_streambuf.test.cpp +++ b/xo-indentlog/utest/log_streambuf.test.cpp @@ -1,30 +1,103 @@ /* @file log_streambuf.test.cpp */ -#include "xo/indentlog/log_streambuf.hpp" -#include "xo/indentlog/print/tag.hpp" -#include "xo/indentlog/print/quoted.hpp" +#include "scope.hpp" +#include "log_streambuf.hpp" +#include "print/tag.hpp" +#include "print/quoted.hpp" #include +#include //#include namespace ut { + using xo::xtag; + using xo::scope; using xo::log_streambuf; + using std::string_view; + using std::cerr; + using std::endl; + + TEST_CASE("log_streamhuf", "[log_streambuf]") + { + constexpr bool c_debug_flag = false; + //scope log(XO_DEBUG(c_debug_flag), "log_streambuf test"); - TEST_CASE("log_streamhuf", "[log_streambuf]") { std::size_t z = 16; - log_streambuf> sbuf(z); + log_streambuf> sbuf(z, c_debug_flag); std::ostream ss(&sbuf); + REQUIRE(sbuf.debug_flag() == c_debug_flag); + + if (c_debug_flag) { + cerr << "empty log_streambuf" << endl; + cerr << "sbuf.lo=" << (void*)sbuf.lo() << endl; + cerr << "sbuf.hi=" << (void*)sbuf.hi() << endl; + cerr << "sbuf._color_escape_chars=" << sbuf._color_escape_chars() << endl; + } + + //REQUIRE(sbuf.lo() == sbuf.pbase()); + REQUIRE(sbuf.capacity() == z); REQUIRE(sbuf.pos() == 0); + REQUIRE(sbuf._solpos() == 0); REQUIRE(sbuf.lpos() == 0); + // note: log_streambuf doesn't get control on every character + ss << '\n'; + if (c_debug_flag) { + cerr << "after single newline" << endl; + cerr << "sbuf.lo=" << (void*)sbuf.lo() << endl; + cerr << "sbuf.hi=" << (void*)sbuf.hi() << endl; + cerr << "sbuf._color_escape_chars=" << sbuf._color_escape_chars() << endl; + } + REQUIRE(sbuf.capacity() == z); REQUIRE(sbuf.pos() == 1); + // we don't know what sbuf._solpos is. Could be 0 or 1 depending on + // ostream implementation + bool ok = (sbuf._solpos() == 0) || (sbuf._solpos() == 1); + REQUIRE(ok); REQUIRE(sbuf.lpos() == 0); // at least on OSX } + TEST_CASE("log_streambuf_xtag", "[log_streambuf][xtag]") + { + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), "log_streambuf_xtag test"); + + std::size_t z = 16; + log_streambuf> sbuf(z, false); + std::ostream ss(&sbuf); + + ss << "empty log_streambuf"; + ss << xtag("sbuf.lo", (void*)nullptr); + ss << xtag("sbuf.hi", (void*)nullptr); + ss << xtag("sbuf.color_escape_chars", sbuf._color_escape_chars()); + + //REQUIRE(sbuf.lo() == sbuf.pbase()); + + auto expected = string_view("empty log_streambuf :sbuf.lo 0 :sbuf.hi 0 :sbuf.color_escape_chars 0"); + + REQUIRE(string_view(sbuf) == expected); + + /* sbuf size will have been expanded */ + REQUIRE(sbuf.capacity() == 128); + REQUIRE(sbuf.pos() == expected.size()); + REQUIRE(sbuf._solpos() == 0); + REQUIRE(sbuf.lpos() == expected.size()); + + // note: log_streambuf doesn't get control on every character + + ss << '\n'; + + REQUIRE(sbuf.capacity() == 128); + REQUIRE(sbuf.pos() == expected.size() + 1); + REQUIRE(sbuf.lpos() == 0); + // note: solpos: updated b/c of call to lazy sbuf.lpos() + REQUIRE(sbuf._solpos() == expected.size() + 1); + } + // write test cases with some random strings. // for each string a list of tuples {ch,pos,lpos} diff --git a/xo-interpreter/src/interpreter/VirtualSchematikaMachine.cpp b/xo-interpreter/src/interpreter/VirtualSchematikaMachine.cpp index 9a9c7ddf..25f620b0 100644 --- a/xo-interpreter/src/interpreter/VirtualSchematikaMachine.cpp +++ b/xo-interpreter/src/interpreter/VirtualSchematikaMachine.cpp @@ -189,7 +189,8 @@ namespace xo { VirtualSchematikaMachine::execute_one() { scope log(XO_DEBUG(true)); - log && log("stack", stack_); + log && log(xtag("pc", pc_), xtag("cont", cont_)); + log && log(xtag("stack", stack_)); using Opcode = VsmInstr::Opcode; diff --git a/xo-interpreter2/CMakeLists.txt b/xo-interpreter2/CMakeLists.txt index ac944a36..426e4112 100644 --- a/xo-interpreter2/CMakeLists.txt +++ b/xo-interpreter2/CMakeLists.txt @@ -21,7 +21,215 @@ add_definitions(${PROJECT_CXX_FLAGS}) # output targets add_subdirectory(src/interpreter2) -#add_subdirectory(utest) +add_subdirectory(src/skrepl) +add_subdirectory(utest) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-gcobject-vsmdefcontframe + FACET_PKG xo_gc + FACET GCObject + REPR VsmDefContFrame + INPUT idl/IGCObject_DVsmDefContFrame.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-printable-vsmdefcontframe + FACET_PKG xo_printable2 + FACET Printable + REPR VsmDefContFrame + INPUT idl/IPrintable_DVsmDefContFrame.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-gcobject-vsmapplyframe + FACET_PKG xo_gc + FACET GCObject + REPR VsmApplyFrame + INPUT idl/IGCObject_DVsmApplyFrame.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-printable-vsmapplyframe + FACET_PKG xo_printable2 + FACET Printable + REPR VsmApplyFrame + INPUT idl/IPrintable_DVsmApplyFrame.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-gcobject-vsmevalargsframe + FACET_PKG xo_gc + FACET GCObject + REPR VsmEvalArgsFrame + INPUT idl/IGCObject_DVsmEvalArgsFrame.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-printable-vsmevalargsframe + FACET_PKG xo_printable2 + FACET Printable + REPR DVsmEvalArgsFrame + INPUT idl/IPrintable_DVsmEvalArgsFrame.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-gcobject-vsmapplyclosureframe + FACET_PKG xo_gc + FACET GCObject + REPR VsmApplyClosureFrame + INPUT idl/IGCObject_DVsmApplyClosureFrame.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-printable-vsmapplyclosureframe + FACET_PKG xo_printable2 + FACET Printable + REPR DVsmApplyClosureFrame + INPUT idl/IPrintable_DVsmApplyClosureFrame.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-gcobject-vsmifelsecontframe + FACET_PKG xo_gc + FACET GCObject + REPR VsmIfElseContFrame + INPUT idl/IGCObject_DVsmIfElseContFrame.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-printable-vsmifelsecontframe + FACET_PKG xo_printable2 + FACET Printable + REPR VsmIfElseContFrame + INPUT idl/IPrintable_DVsmIfElseContFrame.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-gcobject-vsmseqcontframe + FACET_PKG xo_gc + FACET GCObject + REPR VsmSeqContFrame + INPUT idl/IGCObject_DVsmSeqContFrame.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-printable-vsmseqcontframe + FACET_PKG xo_printable2 + FACET Printable + REPR DVsmSeqContFrame + INPUT idl/IPrintable_DVsmSeqContFrame.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +# +#xo_add_genfacetimpl( +# TARGET xo-interpreter2-facetimpl-procedure-closure +# FACET_PKG xo_procedure2 +# FACET Procedure +# REPR Closure +# INPUT idl/IProcedure_DClosure.json5 +#) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-gcobject-closure + FACET_PKG xo_gc + FACET GCObject + REPR Closure + INPUT idl/IGCObject_DClosure.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-printable-closure + FACET_PKG xo_printable2 + FACET Printable + REPR Closure + INPUT idl/IPrintable_DClosure.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-gcobject-globalenv + FACET_PKG xo_gc + FACET GCObject + REPR GlobalEnv + INPUT idl/IGCObject_DGlobalEnv.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-printable-globalenv + FACET_PKG xo_printable2 + FACET Printable + REPR GlobalEnv + INPUT idl/IPrintable_DGlobalEnv.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-gcobject-localenv + FACET_PKG xo_gc + FACET GCObject + REPR LocalEnv + INPUT idl/IGCObject_DLocalEnv.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-printable-localenv + FACET_PKG xo_printable2 + FACET Printable + REPR LocalEnv + INPUT idl/IPrintable_DLocalEnv.json5 +) + +# ---------------------------------------------------------------- + +xo_add_genfacetimpl( + TARGET xo-interpreter2-facetimpl-runtimecontext-vsmrcx + FACET_PKG xo_procedure2 + FACET RuntimeContext + REPR DVsmRcx + INPUT idl/IRuntimeContext_DVsmRcx.json5 + ) + +# ---------------------------------------------------------------- + +xo_add_genfacet_all(xo-interpreter2-genfacet-all) + +# ---------------------------------------------------------------- +# cmake helper (for external xo-interpreter2 users) xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets) diff --git a/xo-interpreter2/idl/IGCObject_DClosure.json5 b/xo-interpreter2/idl/IGCObject_DClosure.json5 new file mode 100644 index 00000000..a9b5616a --- /dev/null +++ b/xo-interpreter2/idl/IGCObject_DClosure.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "detail", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for Closure", + using_doxygen: true, + repr: "DClosure", + doc: [ "implement AGCObject for DClosure" ], +} diff --git a/xo-interpreter2/idl/IGCObject_DGlobalEnv.json5 b/xo-interpreter2/idl/IGCObject_DGlobalEnv.json5 new file mode 100644 index 00000000..ce0bc090 --- /dev/null +++ b/xo-interpreter2/idl/IGCObject_DGlobalEnv.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "env", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for GlobalEnv", + using_doxygen: true, + repr: "DGlobalEnv", + doc: [ "implement AGCObject for DGlobalEnv" ], +} diff --git a/xo-interpreter2/idl/IGCObject_DLocalEnv.json5 b/xo-interpreter2/idl/IGCObject_DLocalEnv.json5 new file mode 100644 index 00000000..252bfbd7 --- /dev/null +++ b/xo-interpreter2/idl/IGCObject_DLocalEnv.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "env", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for LocalEnv", + using_doxygen: true, + repr: "DLocalEnv", + doc: [ "implement AGCObject for DLocalEnv" ], +} diff --git a/xo-interpreter2/idl/IGCObject_DVsmApplyClosureFrame.json5 b/xo-interpreter2/idl/IGCObject_DVsmApplyClosureFrame.json5 new file mode 100644 index 00000000..2b68d579 --- /dev/null +++ b/xo-interpreter2/idl/IGCObject_DVsmApplyClosureFrame.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "detail", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DVsmApplyClosureFrame", + using_doxygen: true, + repr: "DVsmApplyClosureFrame", + doc: [ "implement AGCObject for DVsmApplyClosureFrame" ], +} diff --git a/xo-interpreter2/idl/IGCObject_DVsmApplyFrame.json5 b/xo-interpreter2/idl/IGCObject_DVsmApplyFrame.json5 new file mode 100644 index 00000000..ae284287 --- /dev/null +++ b/xo-interpreter2/idl/IGCObject_DVsmApplyFrame.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "detail", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DVsmApplyFrame", + using_doxygen: true, + repr: "DVsmApplyFrame", + doc: [ "implement AGCObject for DVsmApplyFrame" ], +} diff --git a/xo-interpreter2/idl/IGCObject_DVsmDefContFrame.json5 b/xo-interpreter2/idl/IGCObject_DVsmDefContFrame.json5 new file mode 100644 index 00000000..061fca5d --- /dev/null +++ b/xo-interpreter2/idl/IGCObject_DVsmDefContFrame.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "define", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DVsmDefContFrame", + using_doxygen: true, + repr: "DVsmDefContFrame", + doc: [ "implement AGCObject for DVsmDefContFrame" ], +} diff --git a/xo-interpreter2/idl/IGCObject_DVsmEvalArgsFrame.json5 b/xo-interpreter2/idl/IGCObject_DVsmEvalArgsFrame.json5 new file mode 100644 index 00000000..d36304b8 --- /dev/null +++ b/xo-interpreter2/idl/IGCObject_DVsmEvalArgsFrame.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "detail", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DVsmEvalArgsFrame", + using_doxygen: true, + repr: "DVsmEvalArgsFrame", + doc: [ "implement AGCObject for DVsmEvalArgsFrame" ], +} diff --git a/xo-interpreter2/idl/IGCObject_DVsmIfElseContFrame.json5 b/xo-interpreter2/idl/IGCObject_DVsmIfElseContFrame.json5 new file mode 100644 index 00000000..63617067 --- /dev/null +++ b/xo-interpreter2/idl/IGCObject_DVsmIfElseContFrame.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "ifelse", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DVsmIfElseContFrame", + using_doxygen: true, + repr: "DVsmIfElseContFrame", + doc: [ "implement AGCObject for DVsmIfElseContFrame" ], +} diff --git a/xo-interpreter2/idl/IGCObject_DVsmSeqContFrame.json5 b/xo-interpreter2/idl/IGCObject_DVsmSeqContFrame.json5 new file mode 100644 index 00000000..d2b68020 --- /dev/null +++ b/xo-interpreter2/idl/IGCObject_DVsmSeqContFrame.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "sequence", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DVsmSeqContFrame", + using_doxygen: true, + repr: "DVsmSeqContFrame", + doc: [ "implement AGCObject for DVsmSeqContFrame" ], +} diff --git a/xo-interpreter2/idl/IPrintable_DClosure.json5 b/xo-interpreter2/idl/IPrintable_DClosure.json5 new file mode 100644 index 00000000..2a1e2db9 --- /dev/null +++ b/xo-interpreter2/idl/IPrintable_DClosure.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "detail", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DClosure", + using_doxygen: true, + repr: "DClosure", + doc: [ "implement APrintable for DClosure" ], +} diff --git a/xo-interpreter2/idl/IPrintable_DGlobalEnv.json5 b/xo-interpreter2/idl/IPrintable_DGlobalEnv.json5 new file mode 100644 index 00000000..541146ae --- /dev/null +++ b/xo-interpreter2/idl/IPrintable_DGlobalEnv.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "env", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DGlobalEnv", + using_doxygen: true, + repr: "DGlobalEnv", + doc: [ "implement APrintable for DGlobalEnv" ], +} diff --git a/xo-interpreter2/idl/IPrintable_DLocalEnv.json5 b/xo-interpreter2/idl/IPrintable_DLocalEnv.json5 new file mode 100644 index 00000000..dfc6a644 --- /dev/null +++ b/xo-interpreter2/idl/IPrintable_DLocalEnv.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "env", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DLocalEnv", + using_doxygen: true, + repr: "DLocalEnv", + doc: [ "implement APrintable for DLocalEnv" ], +} diff --git a/xo-interpreter2/idl/IPrintable_DVsmApplyClosureFrame.json5 b/xo-interpreter2/idl/IPrintable_DVsmApplyClosureFrame.json5 new file mode 100644 index 00000000..45927399 --- /dev/null +++ b/xo-interpreter2/idl/IPrintable_DVsmApplyClosureFrame.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "detail", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DVsmApplyClosureFrame", + using_doxygen: true, + repr: "DVsmApplyClosureFrame", + doc: [ "implement APrintable for DVsmApplyClosureFrame" ], +} diff --git a/xo-interpreter2/idl/IPrintable_DVsmApplyFrame.json5 b/xo-interpreter2/idl/IPrintable_DVsmApplyFrame.json5 new file mode 100644 index 00000000..bef2fb62 --- /dev/null +++ b/xo-interpreter2/idl/IPrintable_DVsmApplyFrame.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "detail", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DVsmApplyFrame", + using_doxygen: true, + repr: "DVsmApplyFrame", + doc: [ "implement APrintable for DVsmApplyFrame" ], +} diff --git a/xo-interpreter2/idl/IPrintable_DVsmDefContFrame.json5 b/xo-interpreter2/idl/IPrintable_DVsmDefContFrame.json5 new file mode 100644 index 00000000..58410fd6 --- /dev/null +++ b/xo-interpreter2/idl/IPrintable_DVsmDefContFrame.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "define", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DVsmDefContFrame", + using_doxygen: true, + repr: "DVsmDefContFrame", + doc: [ "implement APrintable for DVsmDefContFrame" ], +} diff --git a/xo-interpreter2/idl/IPrintable_DVsmEvalArgsFrame.json5 b/xo-interpreter2/idl/IPrintable_DVsmEvalArgsFrame.json5 new file mode 100644 index 00000000..c43c5160 --- /dev/null +++ b/xo-interpreter2/idl/IPrintable_DVsmEvalArgsFrame.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "detail", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DVsmEvalArgsFrame", + using_doxygen: true, + repr: "DVsmEvalArgsFrame", + doc: [ "implement APrintable for DVsmEvalArgsFrame" ], +} diff --git a/xo-interpreter2/idl/IPrintable_DVsmIfElseContFrame.json5 b/xo-interpreter2/idl/IPrintable_DVsmIfElseContFrame.json5 new file mode 100644 index 00000000..6490d444 --- /dev/null +++ b/xo-interpreter2/idl/IPrintable_DVsmIfElseContFrame.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "ifelse", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DVsmIfElseContFrame", + using_doxygen: true, + repr: "DVsmIfElseContFrame", + doc: [ "implement APrintable for DVsmIfElseContFrame" ], +} diff --git a/xo-interpreter2/idl/IPrintable_DVsmSeqContFrame.json5 b/xo-interpreter2/idl/IPrintable_DVsmSeqContFrame.json5 new file mode 100644 index 00000000..7b8e7ddd --- /dev/null +++ b/xo-interpreter2/idl/IPrintable_DVsmSeqContFrame.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "sequence", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DVsmSeqContFrame", + using_doxygen: true, + repr: "DVsmSeqContFrame", + doc: [ "implement APrintable for DVsmSeqContFrame" ], +} diff --git a/xo-interpreter2/idl/IProcedure_DClosure.json5 b/xo-interpreter2/idl/IProcedure_DClosure.json5 new file mode 100644 index 00000000..eec40c0c --- /dev/null +++ b/xo-interpreter2/idl/IProcedure_DClosure.json5 @@ -0,0 +1,19 @@ +{ + mode: "implementation", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "detail", + includes: [ + "", + "", + "", + "", + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Procedure.json5", + brief: "provide AProcedure interface for DClosure", + using_doxygen: true, + repr: "DClosure", + doc: [ "implement AProcedure for DClosure" ], +} diff --git a/xo-interpreter2/idl/IRuntimeContext_DVsmRcx.json5 b/xo-interpreter2/idl/IRuntimeContext_DVsmRcx.json5 new file mode 100644 index 00000000..b52517ee --- /dev/null +++ b/xo-interpreter2/idl/IRuntimeContext_DVsmRcx.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2", + output_hpp_dir: "include/xo/interpreter2", + output_impl_subdir: "detail", + includes: [ + //"", + //"", + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/RuntimeContext.json5", + brief: "provide ARuntimeContext interface for DVsmRcx", + using_doxygen: true, + repr: "DVsmRcx", + doc: [ "implement ARuntimeContext for DVsmRcx" ], +} diff --git a/xo-interpreter2/include/xo/interpreter2/Closure.hpp b/xo-interpreter2/include/xo/interpreter2/Closure.hpp new file mode 100644 index 00000000..dc9272fe --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/Closure.hpp @@ -0,0 +1,13 @@ +/** @file Closure.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DClosure.hpp" +//#include "detail/IProcedure_DClosure.hpp" +#include "detail/IGCObject_DClosure.hpp" +#include "detail/IPrintable_DClosure.hpp" + +/* end Closure.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/DApplyFrame.hpp b/xo-interpreter2/include/xo/interpreter2/DApplyFrame.hpp new file mode 100644 index 00000000..d1c81c2b --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/DApplyFrame.hpp @@ -0,0 +1,20 @@ +/** @file DApplyFrame.hpp + * + * @author Roland Conyberae, Feb 2026 + **/ + +#pragma once + +namespace xo { + namespace scm { + /** In virtual schematika machine (VSM): + * stack frame for interpreted apply expression + * (@ref DApplyExpr) + **/ + class DApplyFrame { + obj + }; + } +} + +/* end DApplyFrame.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/DClosure.hpp b/xo-interpreter2/include/xo/interpreter2/DClosure.hpp new file mode 100644 index 00000000..26ff2703 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/DClosure.hpp @@ -0,0 +1,84 @@ +/** @file DClosure.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "LocalEnv.hpp" +#include +#include + +namespace xo { + namespace scm { + + /** @brief runtime representation for a procedure + * + * Maintains lambda + captured lexical context + **/ + class DClosure { + public: + using ARuntimeContext = xo::scm::ARuntimeContext; + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using AGCObject = xo::mm::AGCObject; + using ppindentinfo = xo::print::ppindentinfo; + using size_type = std::int32_t; + + public: + DClosure(const DLambdaExpr * lm, + const DLocalEnv * env); + + /** create instance using memory from @p mm + * for lambda @p lm with captured environment @p env. + **/ + static DClosure * make(obj mm, + const DLambdaExpr * lm, + const DLocalEnv * env); + + /** @defgroup scm-closure-general-methods **/ + ///@{ + + const DLambdaExpr * lambda() const noexcept { return lambda_; } + const DLocalEnv * env() const noexcept { return env_; } + + ///@} + /** @defgroup scm-closure-procedure-facet **/ + ///@{ + + /** for now, support just fixed-arity procedures **/ + bool is_nary() const noexcept { return false; } + /** number of arguments expected by this procedure (-1 if nary) **/ + size_type n_args() const noexcept { return lambda_->n_args(); } + + obj apply_nocheck(obj rcx, const DArray * args); + + ///@} + /** @defgroup scm-closure-gcobject-facet **/ + ///@{ + + std::size_t shallow_size() const noexcept; + DClosure * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + ///@} + /** @defgroup scm-closure-printable-facet **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + private: + /** lambda expression **/ + const DLambdaExpr * lambda_ = nullptr; + /** bindings for captured variables + * (from lexical context where lambda evaluated) + **/ + const DLocalEnv * env_ = nullptr; + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DClosure.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/DGlobalEnv.hpp b/xo-interpreter2/include/xo/interpreter2/DGlobalEnv.hpp new file mode 100644 index 00000000..e68ad55d --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/DGlobalEnv.hpp @@ -0,0 +1,85 @@ +/** @file DGlobalEnv.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include +#include + +namespace xo { + namespace scm { + + /** @brief runtime bindings for global variabels + * + * Implementation here uses a DArenaHashMap to hold pairs. + * The hash map has its own memory outside GC space. + * Keys are DUniqueStrings, also outside GC space. + * Values are regular gc-aware objects, generally will be in GC space. + * + * We need collector to traverse all the values in a global env + * on each cycle. Arrange that by having DGlobalEnv itself + * in GC space. + * + **/ + class DGlobalEnv { + public: + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using AGCObject = xo::mm::AGCObject; + using MemorySizeVisitor = xo::mm::MemorySizeVisitor; + using ppindentinfo = xo::print::ppindentinfo; + using size_type = std::uint32_t; + + public: + /** @defgroup scm-globalenv-ctors constructors **/ + ///@{ + + DGlobalEnv(DGlobalSymtab * symtab, DArray * values); + + static DGlobalEnv * _make(obj mm, + DGlobalSymtab * symtab); + + + ///@} + /** @defgroup scm-globalenv-methods methods **/ + ///@{ + + /** symbol-table size. Is the number of distinct global symbols **/ + size_type size() const noexcept { return symtab_->size(); } + + /** lookup current value associated with binding @p ix **/ + obj lookup_value(Binding ix) const noexcept; + + /** assign value associated with binding @p to @p x. + * If need to expand size of this env, use memory from @p mm + **/ + void assign_value(obj mm, Binding ix, obj x); + + ///@} + /** @defgroup scm-globalenv-gcobject-facet **/ + ///@{ + + std::size_t shallow_size() const noexcept; + DGlobalEnv * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + ///@} + /** @defgroup scm-globalenv-printable-facet **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + private: + + /** symbol table assigns a unique index for each symbol **/ + DGlobalSymtab * symtab_; + + /** value for a symbol S will be in values_[symtab->lookup_binding(S)] **/ + DArray * values_ = nullptr; + }; + } +} diff --git a/xo-interpreter2/include/xo/interpreter2/DLocalEnv.hpp b/xo-interpreter2/include/xo/interpreter2/DLocalEnv.hpp new file mode 100644 index 00000000..eaef71c2 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/DLocalEnv.hpp @@ -0,0 +1,82 @@ +/** @file DLocalEnv.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include +#include + +namespace xo { + namespace scm { + + /** @brief runtime bindings for arguments to a lambda + **/ + class DLocalEnv { + public: + using DArray = xo::scm::DArray; + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using AGCObject = xo::mm::AGCObject; + using ppindentinfo = xo::print::ppindentinfo; + using size_type = std::uint32_t; + + public: + /** @defgroup scm-localenv-constructors constructors **/ + ///@{ + + /** create instance with parent @p p for variables in @p symtab **/ + DLocalEnv(DLocalEnv * parent, + DLocalSymtab * symtab, + DArray * args); + + static DLocalEnv * _make(obj mm, + DLocalEnv * parent, + DLocalSymtab * symtab, + DArray * args); + + ///@} + /** @defgroup scm-localenv-methods methods **/ + ///@{ + + DLocalEnv * parent() const noexcept { return parent_; } + size_type size() const noexcept { return symtab_->size(); } + + /** lookup current value associated with binding @p ix **/ + obj lookup_value(Binding ix) const noexcept; + + /** assign value associated with binding @p ix to @p x **/ + void assign_value(Binding ix, obj x); + + ///@} + /** @defgroup scm-localenv-gcobject-facet **/ + ///@{ + + std::size_t shallow_size() const noexcept; + DLocalEnv * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + ///@} + /** @defgroup scm-localenv-printable-facet **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const noexcept; + + ///@} + + private: + /** parent environment (from closure) **/ + DLocalEnv * parent_ = nullptr; + /** bind values for variables in this symbol table **/ + DLocalSymtab * symtab_ = nullptr; + /** bindings. + * (*args)[i] associates a value with symtab->slots_[i] + **/ + DArray * args_ = nullptr; + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DLocalEnv.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/DVsmApplyClosureFrame.hpp b/xo-interpreter2/include/xo/interpreter2/DVsmApplyClosureFrame.hpp new file mode 100644 index 00000000..168fa1a3 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/DVsmApplyClosureFrame.hpp @@ -0,0 +1,62 @@ +/** @file DVsmApplyClosureFrame.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "VsmInstr.hpp" +#include "DLocalEnv.hpp" +#include + +namespace xo { + namespace scm { + + /** Frame to preserve VSM registers: + * (stack_, parent_, cont_) + * while applying a closure. + **/ + class DVsmApplyClosureFrame { + public: + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using AGCObject = xo::mm::AGCObject; + using ppindentinfo = xo::print::ppindentinfo; + + public: + DVsmApplyClosureFrame(obj stack, + VsmInstr cont, + DLocalEnv * env); + + /** create instance, using memory from @p mm **/ + static DVsmApplyClosureFrame * make(obj mm, + obj parent, + VsmInstr cont, + DLocalEnv * env); + + obj parent() const { return stack_; } + VsmInstr cont() const { return cont_; } + DLocalEnv * local_env() const { return local_env_; } + + /** gcobject facet **/ + std::size_t shallow_size() const noexcept; + DVsmApplyClosureFrame * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + /** pretty-printing support **/ + bool pretty(const ppindentinfo & ppii) const; + + protected: + /** saved VSM stack_ register **/ + obj stack_; + /** saved VSM cont_ register **/ + VsmInstr cont_; + /** saved VSM local_env_ register **/ + DLocalEnv * local_env_ = nullptr; + }; + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DVsmApplyClosureFrame.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/DVsmApplyFrame.hpp b/xo-interpreter2/include/xo/interpreter2/DVsmApplyFrame.hpp new file mode 100644 index 00000000..47735afe --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/DVsmApplyFrame.hpp @@ -0,0 +1,69 @@ +/** @file DVsmApplyFrame.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "VsmInstr.hpp" +#include +#include + +namespace xo { + namespace scm { + class DVsmApplyFrame { + public: + using AProcedure = xo::scm::AProcedure; + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using AGCObject = xo::mm::AGCObject; + using ppindentinfo = xo::print::ppindentinfo; + + public: + DVsmApplyFrame(obj old_parent, + VsmInstr old_cont, + DArray * args); + + /** create instance using memory from @p mm **/ + static DVsmApplyFrame * make(obj mm, + obj old_parent, + VsmInstr old_cont, + DArray * args); + + obj parent() const noexcept { return parent_; } + VsmInstr cont() const noexcept { return cont_; } + obj fn() const noexcept { return fn_; } + DArray * args() const noexcept { return args_; } + + void assign_fn(obj x) { this->fn_ = x; } + + std::size_t shallow_size() const noexcept; + DVsmApplyFrame * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + /** pretty-printing support **/ + bool pretty(const ppindentinfo & ppii) const; + + private: + /** saved VSM stack; restore when this frame consumed **/ + obj parent_; + /** saved continuation; restore when this frame consumed **/ + VsmInstr cont_; + /** evaluated target procedure. + * + * note: when initially created, this will be unpopulated; + * don't know correct value until we evaluate + * expression in head position. + * + * Must exhibit either: + * 1. AProcedure facet (runs natively) + * 2. AVsmProcedure facet (requires schematika runtime) + **/ + obj fn_; + /** evaluated arguments (to target procedure) **/ + DArray * args_; + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DVsmApplyFrame.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/DVsmDefContFrame.hpp b/xo-interpreter2/include/xo/interpreter2/DVsmDefContFrame.hpp new file mode 100644 index 00000000..68c2510a --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/DVsmDefContFrame.hpp @@ -0,0 +1,82 @@ +/** @file DVsmDefContFrame.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "VsmInstr.hpp" +#include +#include + +namespace xo { + namespace scm { + /** @brief saved VSM state during evaluation of a SequenceExpr + **/ + class DVsmDefContFrame { + public: + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using AGCObject = xo::mm::AGCObject; + using ppindentinfo = xo::print::ppindentinfo; + + public: + /** @defgroup scm-vsmdefcontframe-ctors constructors **/ + ///@{ + + DVsmDefContFrame(obj parent, + VsmInstr cont, + DDefineExpr * def_expr); + + /** create instance using memory from allocator @p mm **/ + static DVsmDefContFrame * make(obj mm, + obj parent_stack, + VsmInstr cont, + DDefineExpr * def_expr); + + ///@} + /** @defgroup scm-vsmdefcontframe-access-methods access methods **/ + ///@{ + + obj parent() const noexcept { return parent_; } + VsmInstr cont() const noexcept { return cont_; } + DDefineExpr * def_expr() const noexcept { return def_expr_; } + + ///@} + /** @defgroup scm-vsmdefcontframe-general-methods general methods **/ + ///@{ + + ///@} + /** @defgroup scm-vsmdefcontframe-gcobject-facet gcobject facet **/ + ///@{ + + std::size_t shallow_size() const noexcept; + DVsmDefContFrame * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + ///@} + /** @defgrouop scm-vsmseqcontframe-printable-facet printable facet **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const noexcept; + + ///@} + + private: + /** @defgroup scm-vsmdefcontframe-members member variables **/ + ///@{ + + /** saved VSM stack; restore when this frame consumed **/ + obj parent_; + /** saved continuation; restore when this frame consumed **/ + VsmInstr cont_; + /** saved expr. evaluate elements of this sequence in order **/ + DDefineExpr * def_expr_ = nullptr; + + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DVsmDefContFrame.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/DVsmEvalArgsFrame.hpp b/xo-interpreter2/include/xo/interpreter2/DVsmEvalArgsFrame.hpp new file mode 100644 index 00000000..e3b8b2b5 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/DVsmEvalArgsFrame.hpp @@ -0,0 +1,67 @@ +/** @file DVsmEvalArgsFrame.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "VsmApplyFrame.hpp" +#include + +namespace xo { + namespace scm { + + /** frame for executing an apply expression **/ + class DVsmEvalArgsFrame { + public: + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using AGCObject = xo::mm::AGCObject; + using ppindentinfo = xo::print::ppindentinfo; + + public: + /** see picture in VirtualSchematikaMachine._do_eval_apply_op() + * + * old_parent = [apply frame] + * old_cont = [xfer to called function] + * + **/ + DVsmEvalArgsFrame(DVsmApplyFrame * parent, + VsmInstr cont, + DApplyExpr * apply_expr); + + static DVsmEvalArgsFrame * make(obj mm, + DVsmApplyFrame * apply_frame, + VsmInstr old_cont, + DApplyExpr * apply_expr); + + DVsmApplyFrame * parent() const noexcept { return parent_; } + VsmInstr cont() const noexcept { return cont_; } + const DApplyExpr * apply_expr() const noexcept { return apply_expr_; } + int32_t i_arg() const noexcept { return i_arg_; } + + int32_t increment_arg() { return ++i_arg_; } + + std::size_t shallow_size() const noexcept; + DVsmEvalArgsFrame * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + bool pretty(const ppindentinfo & ppii) const; + + protected: + /** parent stack frame **/ + DVsmApplyFrame * parent_ = nullptr; + /** continuation after eval args completed (always VsmInstr::c_apply) **/ + VsmInstr cont_; + + /** expression being evaluated **/ + DApplyExpr * apply_expr_ = nullptr; + + /** next argument to be evaluated. -1 means function head **/ + int32_t i_arg_ = -1; + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DVsmEvalArgsFrame.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/DVsmIfElseContFrame.hpp b/xo-interpreter2/include/xo/interpreter2/DVsmIfElseContFrame.hpp new file mode 100644 index 00000000..3d4ace12 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/DVsmIfElseContFrame.hpp @@ -0,0 +1,82 @@ +/** @file DVsmIfElseContFrame.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "VsmInstr.hpp" +#include +#include + +namespace xo { + namespace scm { + /** @brief saved VSM state during evaluation of a SequenceExpr + **/ + class DVsmIfElseContFrame { + public: + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using AGCObject = xo::mm::AGCObject; + using ppindentinfo = xo::print::ppindentinfo; + + public: + /** @defgroup scm-vsmevalsequenceframe-ctors constructors **/ + ///@{ + + DVsmIfElseContFrame(obj parent, + VsmInstr cont, + DIfElseExpr * ifelse_expr); + + /** create instance using memory from allocator @p mm **/ + static DVsmIfElseContFrame * make(obj mm, + obj parent, + VsmInstr cont, + DIfElseExpr * ifelse_expr); + + ///@} + /** @defgroup scm-vsmevalsequenceframe-access-methods access methods **/ + ///@{ + + obj parent() const noexcept { return parent_; } + VsmInstr cont() const noexcept { return cont_; } + DIfElseExpr * ifelse_expr() const noexcept { return ifelse_expr_; } + + ///@} + /** @defgroup scm-vsmevalsequenceframe-general-methods general methods **/ + ///@{ + + ///@} + /** @defgroup scm-vsmevalsequenceframe-gcobject-facet gcobject facet **/ + ///@{ + + std::size_t shallow_size() const noexcept; + DVsmIfElseContFrame * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + ///@} + /** @defgrouop scm-vsmseqcontframe-printable-facet printable facet **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const noexcept; + + ///@} + + private: + /** @defgroup scm-vsmevalsequenceframe-members member variables **/ + ///@{ + + /** saved VSM stack; restore when this frame consumed **/ + obj parent_; + /** saved continuation; restore when this frame consumed **/ + VsmInstr cont_; + /** saved expr. evaluate elements of this sequence in order **/ + DIfElseExpr * ifelse_expr_ = nullptr; + + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DVsmIfElseContFrame.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/DVsmRcx.hpp b/xo-interpreter2/include/xo/interpreter2/DVsmRcx.hpp new file mode 100644 index 00000000..eeeb7289 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/DVsmRcx.hpp @@ -0,0 +1,37 @@ +/** @file DVsmRcx.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include + +namespace xo { + namespace scm { + // see xo-interpreter/ VirtualSchematikaMachine.hpp + class VirtualSchematikaMachine; + + /** @brief Runtime context for schematika interpreter + * + * Provides allocator + **/ + class DVsmRcx { + public: + using AAllocator = xo::mm::AAllocator; + + public: + DVsmRcx(VirtualSchematikaMachine * vsm); + + obj allocator() const noexcept; + obj error_allocator() const noexcept; + + private: + /** schematika interpreter **/ + VirtualSchematikaMachine * vsm_ = nullptr;; + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DVsmRcx.hpp */ + diff --git a/xo-interpreter2/include/xo/interpreter2/DVsmSeqContFrame.hpp b/xo-interpreter2/include/xo/interpreter2/DVsmSeqContFrame.hpp new file mode 100644 index 00000000..cb63f0d4 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/DVsmSeqContFrame.hpp @@ -0,0 +1,89 @@ +/** @file DVsmSeqContFrame.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "VsmInstr.hpp" +#include +#include + +namespace xo { + namespace scm { + /** @brief saved VSM state during evaluation of a SequenceExpr + **/ + class DVsmSeqContFrame { + public: + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using AGCObject = xo::mm::AGCObject; + using ppindentinfo = xo::print::ppindentinfo; + + public: + /** @defgroup scm-vsmevalsequenceframe-ctors constructors **/ + ///@{ + + DVsmSeqContFrame(obj parent, + VsmInstr cont, + DSequenceExpr * seq_expr, + uint32_t i_seq); + + /** create instance using memory from allocator @p mm **/ + static DVsmSeqContFrame * make(obj mm, + obj parent, + VsmInstr cont, + DSequenceExpr * seq_expr, + uint32_t i_seq); + + ///@} + /** @defgroup scm-vsmevalsequenceframe-access-methods access methods **/ + ///@{ + + obj parent() const noexcept { return parent_; } + VsmInstr cont() const noexcept { return cont_; } + DSequenceExpr * seq_expr() const noexcept { return seq_expr_; } + uint32_t i_seq() const noexcept { return i_seq_; } + + ///@} + /** @defgroup scm-vsmevalsequenceframe-general-methods general methods **/ + ///@{ + + uint32_t incr_i_seq() noexcept { return ++(this->i_seq_); } + + ///@} + /** @defgroup scm-vsmevalsequenceframe-gcobject-facet gcobject facet **/ + ///@{ + + std::size_t shallow_size() const noexcept; + DVsmSeqContFrame * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + ///@} + /** @defgrouop scm-vsmseqcontframe-printable-facet printable facet **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const noexcept; + + ///@} + + private: + /** @defgroup scm-vsmevalsequenceframe-members member variables **/ + ///@{ + + /** saved VSM stack; restore when this frame consumed **/ + obj parent_; + /** saved continuation; restore when this frame consumed **/ + VsmInstr cont_; + /** saved expr. evaluate elements of this sequence in order **/ + DSequenceExpr * seq_expr_ = nullptr; + /** current sequence element being evaluated **/ + uint32_t i_seq_ = 0; + + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DVsmSeqContFrame.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/GlobalEnv.hpp b/xo-interpreter2/include/xo/interpreter2/GlobalEnv.hpp new file mode 100644 index 00000000..94bafc42 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/GlobalEnv.hpp @@ -0,0 +1,12 @@ +/** @file GlobalEnv.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DGlobalEnv.hpp" +#include "env/IGCObject_DGlobalEnv.hpp" +#include "env/IPrintable_DGlobalEnv.hpp" + +/* end GlobalEnv.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/LocalEnv.hpp b/xo-interpreter2/include/xo/interpreter2/LocalEnv.hpp new file mode 100644 index 00000000..8955e35d --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/LocalEnv.hpp @@ -0,0 +1,12 @@ +/** @file LocalEnv.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DLocalEnv.hpp" +#include "detail/IGCObject_DLocalEnv.hpp" +#include "detail/IPrintable_DLocalEnv.hpp" + +/* end LocalEnv.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/VirtualSchematikaMachine.hpp b/xo-interpreter2/include/xo/interpreter2/VirtualSchematikaMachine.hpp index 8bbe6bb4..75fb968f 100644 --- a/xo-interpreter2/include/xo/interpreter2/VirtualSchematikaMachine.hpp +++ b/xo-interpreter2/include/xo/interpreter2/VirtualSchematikaMachine.hpp @@ -5,12 +5,62 @@ #pragma once +#include "VsmConfig.hpp" #include "VsmInstr.hpp" +#include "VsmFrame.hpp" +#include "DLocalEnv.hpp" +#include "DGlobalEnv.hpp" +#include +#include #include #include +#include namespace xo { namespace scm { +#ifdef OBSOLETE // see DVsmError + // TODO: move error to collected space? + // or special arena? + // + struct EvaluationError { + /** source location (in vsm implementation) at which error identified **/ + std::string_view src_function_; + /** error description (allocated from ErrorArena) **/ + std::string_view error_description_; + // TODO: info about location in schematika source + }; +#endif + + /** similar to @ref xo::scm::ReaderResult **/ + struct VsmResult { + using AGCObject = xo::mm::AGCObject; + using span_type = xo::mm::span; + + VsmResult() = default; + explicit VsmResult(obj value) : result_{value} {} + explicit VsmResult(TokenizerError err) : result_{err} {} + + bool is_value() const { return std::holds_alternative>(result_); } + bool is_tk_error() const { return std::holds_alternative(result_); } + bool is_eval_error() const; + + const obj * value() const { return std::get_if>(&result_); } + + /** result of evaluating first expression encountered in input **/ + std::variant, TokenizerError> result_; + }; + + /** vsm result + reamining span **/ + struct VsmResultExt : public VsmResult { + using span_type = VsmResult::span_type; + + VsmResultExt() = default; + VsmResultExt(const VsmResult & result, span_type rem) : VsmResult{result}, remaining_{rem} {} + + /** unconsumed portion of input **/ + VsmResult::span_type remaining_; + }; + /** @class VirtualSchematikaMachine * @brief virtual machine for schematika **/ @@ -18,10 +68,51 @@ namespace xo { public: // will be DArenaVector> probably using Stack = void *; + using AAllocator = xo::mm::AAllocator; using AGCObject = xo::mm::AGCObject; + using MemorySizeVisitor = xo::mm::MemorySizeVisitor; + using span_type = xo::mm::span; public: - VirtualSchematikaMachine(); + /** @p config. configuration + * @p aux_mm. Allocator for miscellaneous dataN + * owned by this VSM. + **/ + VirtualSchematikaMachine(const VsmConfig & config, + obj aux_mm); + + /** non-trivial dtor because of @ref reader_ + * indirect dependency on DGlobalSymtab + **/ + ~VirtualSchematikaMachine() = default; + + /** allocator for schematika data **/ + obj allocator() const noexcept; + /** allocator for runtime errors **/ + obj error_allocator() const noexcept; + + /** true iff parser is at top-level -> does not contain + * state for a incomplete/partial expression + **/ + bool is_at_toplevel() const noexcept; + + /** visit vsm-owned memory pools; call visitor(info) for each **/ + void visit_pools(const MemorySizeVisitor & visitor) const; + + /** begin interactive session. **/ + void begin_interactive_session(); + /** begin batch session **/ + void begin_batch_session(); + + /** consume input @p input_cstr. + * Require: must first start interactive/batch session + **/ + VsmResultExt read_eval_print(span_type input_span, bool eof); + + /** evaluate expression @p expr + * Require: must first start interactive/batch session + **/ + VsmResult start_eval(obj expr); /** borrow calling thread to run indefinitely, * until halt instruction @@ -45,40 +136,168 @@ namespace xo { **/ void _do_eval_constant_op(); - /** evaluate a variable expression + /** evaluate a define-expression + * Require: + * - expression in @ref expr_ + **/ + void _do_eval_define_op(); + + /** evaluate a lambda expression + * Require: + * - expression in @ref expr_ + **/ + void _do_eval_lambda_op(); + + /** evaluate variable expression (definition) * Require: * - expression in @ref expr_ **/ void _do_eval_variable_op(); + /** evaluate a variable reference (use after definition) + * Require: + * - expression in @ref expr_ + **/ + void _do_eval_varref_op(); + + /** evaluate an apply expression + * Require: + * - expression in @ref expr_ + **/ + void _do_eval_apply_op(); + + /** evaluate an if-else expression + * Require: + * - expression in @ref expr_ + **/ + void _do_eval_if_else_op(); + + /** evaluate a sequence expression + * Require: + * - expression in @ref expr_ + **/ + void _do_eval_sequence_op(); + + /** apply a function to evaluated arguments **/ + void _do_apply_op(); + + /** evaluate arguments on behalf of a function call + * Require: + * - expression value in @ref value_ + * - stack: + * [0] VsmEvalArgsFrame + * [1] VsmApplyFrame + * ... + **/ + void _do_evalargs_op(); + + /** call closure @ref fn_ with arguments @ref args_ **/ + void _do_call_closure_op(); + /** call primitive @ref fn_ with arguments @ref args_ **/ + void _do_call_primitive_op(); + + /** perform assignment after evaluating + * the rhs of a define-expr + **/ + void _do_def_cont_op(); + + /** restore registers from stack frame + * (specifically: local_env_, stack_, cont_) + * after invoking a schematika closure + **/ + void _do_apply_cont_op(); + + /** proceed with if- or else- branch of an if-else expression + * after evaluating test condition + **/ + void _do_ifelse_cont_op(); + + /** loop continuation after evaluating element of a SequenceExpr **/ + void _do_seq_cont_op(); + private: /* * Some registers are preserved by evaluation: * stack_ * cont_ + * local_env_ * - * Other registers are not preserved + * Other registers not preserved * pc_ * expr_ + * fn_ + * args_ * value_ */ - /** program counter **/ - VsmInstr pc_ = VsmInstr::halt(); + /** configuration **/ + VsmConfig config_; #ifdef NOT_YET - /** stack pointer **/ - Stack stack_; + /** allocator (likely DArena) for globals. + * For example DArenaHashMap in global symta. + **/ + obj aux_mm_; #endif + /** allocator (likely DX1Collector or similar) for + * expressions and values. Schemaatika reader will use this also + **/ + abox mm_; + + /** Sidecar allocator for error reporting. + * Separate to mitigate interference with @ref mm_ + * (separate memory so we can for example report + * an out-of-memory error). + * Likely DArena or similar + **/ + abox error_mm_; + + /** runtime context for this vsm. + * For example, provides allocator to primitives + **/ + abox rcx_; + + // consider separate allocator (which _may_ turn out to be the same) + // for VM stack. Only works for code that doesn't rely on fancy + // lexical scoping + + // consider separate allocator for reader (i.e. program code) + // and data (program execution) + + /** reader: text -> expression **/ + SchematikaReader reader_; + + /** program counter **/ + VsmInstr pc_ = VsmInstr::c_halt; + + /** stack pointer **/ + obj stack_; + /** expression register **/ obj expr_; + /** environment pointer. Maintains bindings + * for global variables. + **/ + DGlobalEnv * global_env_ = nullptr; + + /** environment pointer. Provides bindings + * for surrounding lexical scope at this point + * in execution + **/ + DLocalEnv * local_env_ = nullptr; + + /** evaluated function to call **/ + obj fn_; + /** evaluated argument list **/ + DArray * args_; + /** result register **/ - obj value_; + VsmResult value_; /** continuation register **/ - VsmInstr cont_ = VsmInstr::halt(); + VsmInstr cont_ = VsmInstr::c_halt; }; } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-interpreter2/include/xo/interpreter2/VsmApplyClosureFrame.hpp b/xo-interpreter2/include/xo/interpreter2/VsmApplyClosureFrame.hpp new file mode 100644 index 00000000..09b68d09 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/VsmApplyClosureFrame.hpp @@ -0,0 +1,12 @@ +/** @file VsmApplyClosureFrame.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DVsmApplyClosureFrame.hpp" +#include "detail/IGCObject_DVsmApplyClosureFrame.hpp" +#include "detail/IPrintable_DVsmApplyClosureFrame.hpp" + +/* end VsmApplyClosureFrame.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/VsmApplyFrame.hpp b/xo-interpreter2/include/xo/interpreter2/VsmApplyFrame.hpp new file mode 100644 index 00000000..5ed121ba --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/VsmApplyFrame.hpp @@ -0,0 +1,12 @@ +/** @file VsmApplyFrame.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DVsmApplyFrame.hpp" +#include "detail/IGCObject_DVsmApplyFrame.hpp" +#include "detail/IPrintable_DVsmApplyFrame.hpp" + +/* end VsmApplyFrame.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/VsmConfig.hpp b/xo-interpreter2/include/xo/interpreter2/VsmConfig.hpp new file mode 100644 index 00000000..bfbe152e --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/VsmConfig.hpp @@ -0,0 +1,52 @@ +/** @file VsmConfig.hpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include +#include +#include + +namespace xo { + namespace scm { + /** Configuration for virtual schematika machine + **/ + struct VsmConfig { + using X1CollectorConfig = xo::mm::X1CollectorConfig; + using ArenaConfig = xo::mm::ArenaConfig; + + VsmConfig() = default; + + VsmConfig with_debug_flag(bool x) const { + VsmConfig retval = *this; + retval.debug_flag_ = x; + return retval; + } + + /** true for interactive parser session; false for batch session **/ + bool interactive_flag_ = true; + + /** true to enable logging **/ + bool debug_flag_ = false; + + /** reader configuration **/ + ReaderConfig rdr_config_; + /** Configuration for allocator/collector. + * TODO: may want to make CollectorConfig polymorphic + **/ + X1CollectorConfig x1_config_ = X1CollectorConfig().with_name("gc").with_size(4*1024*1024); + /** Configuration for handful of non-moveable high-level objects + * e.g. DArenaHashMap in global symtab + **/ + ArenaConfig fixed_config_ = ArenaConfig().with_name("fixed").with_size(4*1024); + /** Configuration for error allocator + * TODO: may want to make ArenaConfig polymorphic + **/ + ArenaConfig error_config_ = ArenaConfig().with_name("error-reserve").with_size(64*1024); + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end VsmConfig.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/VsmDefContFrame.hpp b/xo-interpreter2/include/xo/interpreter2/VsmDefContFrame.hpp new file mode 100644 index 00000000..5ea2bad6 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/VsmDefContFrame.hpp @@ -0,0 +1,12 @@ +/** @file VsmDefContFrame.hpp +* + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DVsmDefContFrame.hpp" +#include "define/IGCObject_DVsmDefContFrame.hpp" +#include "define/IPrintable_DVsmDefContFrame.hpp" + +/* end VsmDefContFrame.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/VsmEvalArgsFrame.hpp b/xo-interpreter2/include/xo/interpreter2/VsmEvalArgsFrame.hpp new file mode 100644 index 00000000..8c45b25e --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/VsmEvalArgsFrame.hpp @@ -0,0 +1,12 @@ +/** @file VsmEvalArgsFrame.hpp +* +* @author Roland Conybeare, Feb 2026 +**/ + +#pragma once + +#include "DVsmEvalArgsFrame.hpp" +#include "detail/IGCObject_DVsmEvalArgsFrame.hpp" +#include "detail/IPrintable_DVsmEvalArgsFrame.hpp" + +/* end VsmEvalArgsFrame.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/VsmFrame.hpp b/xo-interpreter2/include/xo/interpreter2/VsmFrame.hpp new file mode 100644 index 00000000..52a30761 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/VsmFrame.hpp @@ -0,0 +1,36 @@ +/** @file VsmFrame.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "VsmInstr.hpp" +#include +#include + +namespace xo { + namespace scm { + class VsmFrame { + public: + using AGCObject = xo::mm::AGCObject; + + public: + VsmFrame(obj parent, + VsmInstr cont) : parent_{parent}, cont_{cont} {} + + //obj parent() const noexcept { return parent_; } + obj parent() const noexcept { return parent_; } + VsmInstr cont() const noexcept { return cont_; } + + protected: + /** saved VSM stack; restore when this frame consumed **/ + obj parent_; + /** saved continuation; restore when this frame consumed **/ + VsmInstr cont_; + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end VsmFrame.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/VsmIfElseContFrame.hpp b/xo-interpreter2/include/xo/interpreter2/VsmIfElseContFrame.hpp new file mode 100644 index 00000000..a0494ddf --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/VsmIfElseContFrame.hpp @@ -0,0 +1,12 @@ +/** @file VsmIfElseContFrame.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DVsmIfElseContFrame.hpp" +#include "ifelse/IGCObject_DVsmIfElseContFrame.hpp" +#include "ifelse/IPrintable_DVsmIfElseContFrame.hpp" + +/* end VsmIfElseContFrame.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/VsmInstr.hpp b/xo-interpreter2/include/xo/interpreter2/VsmInstr.hpp index ca74bc4c..2417757f 100644 --- a/xo-interpreter2/include/xo/interpreter2/VsmInstr.hpp +++ b/xo-interpreter2/include/xo/interpreter2/VsmInstr.hpp @@ -9,18 +9,54 @@ namespace xo { namespace scm { + /** + * Thin instruction wrapper for VSM (virtual schematika machine) instructions. + * For exeuction see VirtualSchematikaMachine.cpp + **/ class VsmInstr { public: explicit VsmInstr(vsm_opcode oc) : opcode_{oc} {} - static VsmInstr halt() { return VsmInstr{vsm_opcode::halt}; } - static VsmInstr eval() { return VsmInstr{vsm_opcode::eval}; } + // instructions + + static VsmInstr c_sentinel; + static VsmInstr c_halt; + static VsmInstr c_eval; + + /** proceed to assignment after evaluating rhs + * of define-expression + **/ + static VsmInstr c_def_cont; + + static VsmInstr c_apply; + static VsmInstr c_evalargs; + /** restore VSM state for continuation of an apply expression **/ + static VsmInstr c_apply_cont; + + /** proceed to branch of if-else expression after evaluating + * test condition + **/ + static VsmInstr c_ifelse_cont; + + /** loop to evaluate members of a SequenceExpr **/ + static VsmInstr c_seq_cont; vsm_opcode opcode() const noexcept { return opcode_; } private: vsm_opcode opcode_; }; + + inline bool + operator==(VsmInstr x, VsmInstr y) noexcept { + return x.opcode() == y.opcode(); + } + + inline std::ostream & + operator<<(std::ostream & os, VsmInstr x) { + os << x.opcode(); + return os; + } } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-interpreter2/include/xo/interpreter2/VsmOpcode.hpp b/xo-interpreter2/include/xo/interpreter2/VsmOpcode.hpp index 3638fa29..161b352e 100644 --- a/xo-interpreter2/include/xo/interpreter2/VsmOpcode.hpp +++ b/xo-interpreter2/include/xo/interpreter2/VsmOpcode.hpp @@ -5,6 +5,7 @@ #pragma once +#include #include namespace xo { @@ -13,16 +14,53 @@ namespace xo { * exeucted by VirtualSchematikaMachine **/ enum class vsm_opcode { + /** Flags bad state (defect in VSM itself) **/ + sentinel, /** Immediately halt virtual schematika machine. **/ halt, /** Evaluate expression in expr register **/ eval, + /** Apply function in stack frame + * See diagram in VirtualSchematikaMachine::_do_eval_apply_op + **/ + apply, + /** Eval arguments to function. + * See diagram in VirtualSchematikaMachine::_do_eval_apply_op + **/ + evalargs, + + /** continuation to complete execution of define-expression, + * after evaluting rhs expression + **/ + def_cont, + + /** continuation to restore vsm registers (local_env, stack, cont) + * after invoking a closure + **/ + apply_cont, + + /** continuation to act on a branch **/ + ifelse_cont, + + /** Loop over elements of a SequenceExpr **/ + seq_cont, + /** sentinel, counts number of opcodes **/ N, }; static constexpr uint32_t n_opcode = static_cast(vsm_opcode::N); + + /** stringified enum value **/ + const char * + vsm_opcode_descr(vsm_opcode x); + + inline std::ostream & + operator<<(std::ostream & os, vsm_opcode x) { + os << vsm_opcode_descr(x); + return os; + } } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-interpreter2/include/xo/interpreter2/VsmRcx.hpp b/xo-interpreter2/include/xo/interpreter2/VsmRcx.hpp new file mode 100644 index 00000000..c0f015eb --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/VsmRcx.hpp @@ -0,0 +1,11 @@ +/** @file VsmRcx.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DVsmRcx.hpp" +#include "detail/IRuntimeContext_DVsmRcx.hpp" + +/* end VsmRcx.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/VsmSeqContFrame.hpp b/xo-interpreter2/include/xo/interpreter2/VsmSeqContFrame.hpp new file mode 100644 index 00000000..96e8d053 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/VsmSeqContFrame.hpp @@ -0,0 +1,12 @@ +/** @file VsmSeqContFrame.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DVsmSeqContFrame.hpp" +#include "sequence/IGCObject_DVsmSeqContFrame.hpp" +#include "sequence/IPrintable_DVsmSeqContFrame.hpp" + +/* end VsmSeqContFrame.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/define/IGCObject_DVsmDefContFrame.hpp b/xo-interpreter2/include/xo/interpreter2/define/IGCObject_DVsmDefContFrame.hpp new file mode 100644 index 00000000..309a6ac7 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/define/IGCObject_DVsmDefContFrame.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DVsmDefContFrame.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DVsmDefContFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DVsmDefContFrame.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DVsmDefContFrame.hpp" + +namespace xo { namespace scm { class IGCObject_DVsmDefContFrame; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DVsmDefContFrame + **/ + class IGCObject_DVsmDefContFrame { + public: + /** @defgroup scm-gcobject-dvsmdefcontframe-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dvsmdefcontframe-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DVsmDefContFrame & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DVsmDefContFrame & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DVsmDefContFrame & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/define/IPrintable_DVsmDefContFrame.hpp b/xo-interpreter2/include/xo/interpreter2/define/IPrintable_DVsmDefContFrame.hpp new file mode 100644 index 00000000..46ab4ee7 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/define/IPrintable_DVsmDefContFrame.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DVsmDefContFrame.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DVsmDefContFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DVsmDefContFrame.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DVsmDefContFrame.hpp" + +namespace xo { namespace scm { class IPrintable_DVsmDefContFrame; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DVsmDefContFrame + **/ + class IPrintable_DVsmDefContFrame { + public: + /** @defgroup scm-printable-dvsmdefcontframe-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dvsmdefcontframe-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DVsmDefContFrame & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/detail/IGCObject_DClosure.hpp b/xo-interpreter2/include/xo/interpreter2/detail/IGCObject_DClosure.hpp new file mode 100644 index 00000000..fb863205 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/detail/IGCObject_DClosure.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DClosure.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DClosure.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DClosure.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DClosure.hpp" + +namespace xo { namespace scm { class IGCObject_DClosure; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DClosure + **/ + class IGCObject_DClosure { + public: + /** @defgroup scm-gcobject-dclosure-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dclosure-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DClosure & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DClosure & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DClosure & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/detail/IGCObject_DLocalEnv.hpp b/xo-interpreter2/include/xo/interpreter2/detail/IGCObject_DLocalEnv.hpp new file mode 100644 index 00000000..d318bb61 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/detail/IGCObject_DLocalEnv.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DLocalEnv.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DLocalEnv.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DLocalEnv.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DLocalEnv.hpp" + +namespace xo { namespace scm { class IGCObject_DLocalEnv; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DLocalEnv + **/ + class IGCObject_DLocalEnv { + public: + /** @defgroup scm-gcobject-dlocalenv-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dlocalenv-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DLocalEnv & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DLocalEnv & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DLocalEnv & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/detail/IGCObject_DVsmApplyClosureFrame.hpp b/xo-interpreter2/include/xo/interpreter2/detail/IGCObject_DVsmApplyClosureFrame.hpp new file mode 100644 index 00000000..2baacd05 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/detail/IGCObject_DVsmApplyClosureFrame.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DVsmApplyClosureFrame.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DVsmApplyClosureFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DVsmApplyClosureFrame.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DVsmApplyClosureFrame.hpp" + +namespace xo { namespace scm { class IGCObject_DVsmApplyClosureFrame; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DVsmApplyClosureFrame + **/ + class IGCObject_DVsmApplyClosureFrame { + public: + /** @defgroup scm-gcobject-dvsmapplyclosureframe-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dvsmapplyclosureframe-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DVsmApplyClosureFrame & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DVsmApplyClosureFrame & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DVsmApplyClosureFrame & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/detail/IGCObject_DVsmApplyFrame.hpp b/xo-interpreter2/include/xo/interpreter2/detail/IGCObject_DVsmApplyFrame.hpp new file mode 100644 index 00000000..ca6d3b10 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/detail/IGCObject_DVsmApplyFrame.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DVsmApplyFrame.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DVsmApplyFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DVsmApplyFrame.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DVsmApplyFrame.hpp" + +namespace xo { namespace scm { class IGCObject_DVsmApplyFrame; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DVsmApplyFrame + **/ + class IGCObject_DVsmApplyFrame { + public: + /** @defgroup scm-gcobject-dvsmapplyframe-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dvsmapplyframe-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DVsmApplyFrame & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DVsmApplyFrame & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DVsmApplyFrame & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/detail/IGCObject_DVsmEvalArgsFrame.hpp b/xo-interpreter2/include/xo/interpreter2/detail/IGCObject_DVsmEvalArgsFrame.hpp new file mode 100644 index 00000000..4a8ad18a --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/detail/IGCObject_DVsmEvalArgsFrame.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DVsmEvalArgsFrame.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DVsmEvalArgsFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DVsmEvalArgsFrame.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DVsmEvalArgsFrame.hpp" + +namespace xo { namespace scm { class IGCObject_DVsmEvalArgsFrame; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DVsmEvalArgsFrame + **/ + class IGCObject_DVsmEvalArgsFrame { + public: + /** @defgroup scm-gcobject-dvsmevalargsframe-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dvsmevalargsframe-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DVsmEvalArgsFrame & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DVsmEvalArgsFrame & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DVsmEvalArgsFrame & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/detail/IPrintable_DClosure.hpp b/xo-interpreter2/include/xo/interpreter2/detail/IPrintable_DClosure.hpp new file mode 100644 index 00000000..6cc91cf1 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/detail/IPrintable_DClosure.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DClosure.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DClosure.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DClosure.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DClosure.hpp" + +namespace xo { namespace scm { class IPrintable_DClosure; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DClosure + **/ + class IPrintable_DClosure { + public: + /** @defgroup scm-printable-dclosure-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dclosure-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DClosure & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/detail/IPrintable_DLocalEnv.hpp b/xo-interpreter2/include/xo/interpreter2/detail/IPrintable_DLocalEnv.hpp new file mode 100644 index 00000000..c0ddb7f8 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/detail/IPrintable_DLocalEnv.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DLocalEnv.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DLocalEnv.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DLocalEnv.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DLocalEnv.hpp" + +namespace xo { namespace scm { class IPrintable_DLocalEnv; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DLocalEnv + **/ + class IPrintable_DLocalEnv { + public: + /** @defgroup scm-printable-dlocalenv-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dlocalenv-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DLocalEnv & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/detail/IPrintable_DVsmApplyClosureFrame.hpp b/xo-interpreter2/include/xo/interpreter2/detail/IPrintable_DVsmApplyClosureFrame.hpp new file mode 100644 index 00000000..f2e5a072 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/detail/IPrintable_DVsmApplyClosureFrame.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DVsmApplyClosureFrame.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DVsmApplyClosureFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DVsmApplyClosureFrame.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DVsmApplyClosureFrame.hpp" + +namespace xo { namespace scm { class IPrintable_DVsmApplyClosureFrame; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DVsmApplyClosureFrame + **/ + class IPrintable_DVsmApplyClosureFrame { + public: + /** @defgroup scm-printable-dvsmapplyclosureframe-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dvsmapplyclosureframe-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DVsmApplyClosureFrame & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/detail/IPrintable_DVsmApplyFrame.hpp b/xo-interpreter2/include/xo/interpreter2/detail/IPrintable_DVsmApplyFrame.hpp new file mode 100644 index 00000000..af1a4e02 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/detail/IPrintable_DVsmApplyFrame.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DVsmApplyFrame.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DVsmApplyFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DVsmApplyFrame.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DVsmApplyFrame.hpp" + +namespace xo { namespace scm { class IPrintable_DVsmApplyFrame; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DVsmApplyFrame + **/ + class IPrintable_DVsmApplyFrame { + public: + /** @defgroup scm-printable-dvsmapplyframe-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dvsmapplyframe-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DVsmApplyFrame & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/detail/IPrintable_DVsmEvalArgsFrame.hpp b/xo-interpreter2/include/xo/interpreter2/detail/IPrintable_DVsmEvalArgsFrame.hpp new file mode 100644 index 00000000..1c06f71e --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/detail/IPrintable_DVsmEvalArgsFrame.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DVsmEvalArgsFrame.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DVsmEvalArgsFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DVsmEvalArgsFrame.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DVsmEvalArgsFrame.hpp" + +namespace xo { namespace scm { class IPrintable_DVsmEvalArgsFrame; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DVsmEvalArgsFrame + **/ + class IPrintable_DVsmEvalArgsFrame { + public: + /** @defgroup scm-printable-dvsmevalargsframe-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dvsmevalargsframe-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DVsmEvalArgsFrame & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/detail/IProcedure_DClosure.hpp b/xo-interpreter2/include/xo/interpreter2/detail/IProcedure_DClosure.hpp new file mode 100644 index 00000000..2c966a50 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/detail/IProcedure_DClosure.hpp @@ -0,0 +1,67 @@ +/** @file IProcedure_DClosure.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IProcedure_DClosure.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IProcedure_DClosure.json5] + **/ + +#pragma once + +#include "Procedure.hpp" +#include +#include +#include +#include +#include "DClosure.hpp" + +namespace xo { namespace scm { class IProcedure_DClosure; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::IProcedure_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IProcedure_DClosure + **/ + class IProcedure_DClosure { + public: + /** @defgroup scm-procedure-dclosure-type-traits **/ + ///@{ + using AGCObject = xo::scm::AProcedure::AGCObject; + using Copaque = xo::scm::AProcedure::Copaque; + using Opaque = xo::scm::AProcedure::Opaque; + ///@} + /** @defgroup scm-procedure-dclosure-methods **/ + ///@{ + // const methods + /** true iff procedure takes n arguments **/ + static bool is_nary(const DClosure & self) noexcept; + /** number of arguments. -1 for n-ary **/ + static std::int32_t n_args(const DClosure & self) noexcept; + + // non-const methods + /** invoke procedure; assume arguments satisfy type system **/ + static obj apply_nocheck(DClosure & self, obj rcx, const DArray * args); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/detail/IRuntimeContext_DVsmRcx.hpp b/xo-interpreter2/include/xo/interpreter2/detail/IRuntimeContext_DVsmRcx.hpp new file mode 100644 index 00000000..ecb81f1f --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/detail/IRuntimeContext_DVsmRcx.hpp @@ -0,0 +1,59 @@ +/** @file IRuntimeContext_DVsmRcx.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IRuntimeContext_DVsmRcx.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IRuntimeContext_DVsmRcx.json5] + **/ + +#pragma once + +#include "RuntimeContext.hpp" +#include "DVsmRcx.hpp" + +namespace xo { namespace scm { class IRuntimeContext_DVsmRcx; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::IRuntimeContext_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IRuntimeContext_DVsmRcx + **/ + class IRuntimeContext_DVsmRcx { + public: + /** @defgroup scm-runtimecontext-dvsmrcx-type-traits **/ + ///@{ + using AAllocator = xo::scm::ARuntimeContext::AAllocator; + using Copaque = xo::scm::ARuntimeContext::Copaque; + using Opaque = xo::scm::ARuntimeContext::Opaque; + ///@} + /** @defgroup scm-runtimecontext-dvsmrcx-methods **/ + ///@{ + // const methods + /** default allocator to use for objects **/ + static obj allocator(const DVsmRcx & self) noexcept; + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/env/IGCObject_DGlobalEnv.hpp b/xo-interpreter2/include/xo/interpreter2/env/IGCObject_DGlobalEnv.hpp new file mode 100644 index 00000000..1f0f9281 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/env/IGCObject_DGlobalEnv.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DGlobalEnv.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DGlobalEnv.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DGlobalEnv.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DGlobalEnv.hpp" + +namespace xo { namespace scm { class IGCObject_DGlobalEnv; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DGlobalEnv + **/ + class IGCObject_DGlobalEnv { + public: + /** @defgroup scm-gcobject-dglobalenv-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dglobalenv-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DGlobalEnv & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DGlobalEnv & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DGlobalEnv & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/env/IGCObject_DLocalEnv.hpp b/xo-interpreter2/include/xo/interpreter2/env/IGCObject_DLocalEnv.hpp new file mode 100644 index 00000000..d318bb61 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/env/IGCObject_DLocalEnv.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DLocalEnv.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DLocalEnv.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DLocalEnv.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DLocalEnv.hpp" + +namespace xo { namespace scm { class IGCObject_DLocalEnv; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DLocalEnv + **/ + class IGCObject_DLocalEnv { + public: + /** @defgroup scm-gcobject-dlocalenv-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dlocalenv-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DLocalEnv & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DLocalEnv & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DLocalEnv & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/env/IPrintable_DGlobalEnv.hpp b/xo-interpreter2/include/xo/interpreter2/env/IPrintable_DGlobalEnv.hpp new file mode 100644 index 00000000..6efcd963 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/env/IPrintable_DGlobalEnv.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DGlobalEnv.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DGlobalEnv.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DGlobalEnv.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DGlobalEnv.hpp" + +namespace xo { namespace scm { class IPrintable_DGlobalEnv; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DGlobalEnv + **/ + class IPrintable_DGlobalEnv { + public: + /** @defgroup scm-printable-dglobalenv-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dglobalenv-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DGlobalEnv & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/env/IPrintable_DLocalEnv.hpp b/xo-interpreter2/include/xo/interpreter2/env/IPrintable_DLocalEnv.hpp new file mode 100644 index 00000000..c0ddb7f8 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/env/IPrintable_DLocalEnv.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DLocalEnv.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DLocalEnv.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DLocalEnv.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DLocalEnv.hpp" + +namespace xo { namespace scm { class IPrintable_DLocalEnv; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DLocalEnv + **/ + class IPrintable_DLocalEnv { + public: + /** @defgroup scm-printable-dlocalenv-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dlocalenv-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DLocalEnv & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/ifelse/IGCObject_DVsmIfElseContFrame.hpp b/xo-interpreter2/include/xo/interpreter2/ifelse/IGCObject_DVsmIfElseContFrame.hpp new file mode 100644 index 00000000..293dd70d --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/ifelse/IGCObject_DVsmIfElseContFrame.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DVsmIfElseContFrame.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DVsmIfElseContFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DVsmIfElseContFrame.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DVsmIfElseContFrame.hpp" + +namespace xo { namespace scm { class IGCObject_DVsmIfElseContFrame; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DVsmIfElseContFrame + **/ + class IGCObject_DVsmIfElseContFrame { + public: + /** @defgroup scm-gcobject-dvsmifelsecontframe-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dvsmifelsecontframe-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DVsmIfElseContFrame & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DVsmIfElseContFrame & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DVsmIfElseContFrame & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/ifelse/IPrintable_DVsmIfElseContFrame.hpp b/xo-interpreter2/include/xo/interpreter2/ifelse/IPrintable_DVsmIfElseContFrame.hpp new file mode 100644 index 00000000..5f0e5a7b --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/ifelse/IPrintable_DVsmIfElseContFrame.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DVsmIfElseContFrame.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DVsmIfElseContFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DVsmIfElseContFrame.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DVsmIfElseContFrame.hpp" + +namespace xo { namespace scm { class IPrintable_DVsmIfElseContFrame; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DVsmIfElseContFrame + **/ + class IPrintable_DVsmIfElseContFrame { + public: + /** @defgroup scm-printable-dvsmifelsecontframe-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dvsmifelsecontframe-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DVsmIfElseContFrame & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/init_interpreter2.hpp b/xo-interpreter2/include/xo/interpreter2/init_interpreter2.hpp new file mode 100644 index 00000000..87e93438 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/init_interpreter2.hpp @@ -0,0 +1,21 @@ +/** @file init_interpreter2.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include + +namespace xo { + /* tag to represent the xo-interpreter2/ subsystem within ordered initialization */ + enum S_interpreter2_tag {}; + + template <> + struct InitSubsys { + static void init(); + static InitEvidence require(); + }; +} /*namespace xo*/ + +/* end init_interpreter2.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/interpreter2_register_facets.hpp b/xo-interpreter2/include/xo/interpreter2/interpreter2_register_facets.hpp new file mode 100644 index 00000000..587f882b --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/interpreter2_register_facets.hpp @@ -0,0 +1,15 @@ +/** @file interpreter2_register_facets.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +namespace xo { + namespace scm { + /** Register interpreter2 (facet,impl) combinations with FacetRegistry **/ + bool interpreter2_register_facets(); + } +} + +/* end interpreter2_register_facets.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/interpreter2_register_types.hpp b/xo-interpreter2/include/xo/interpreter2/interpreter2_register_types.hpp new file mode 100644 index 00000000..1409d13a --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/interpreter2_register_types.hpp @@ -0,0 +1,17 @@ +/** @file interpreter2_register_types.hpp + * + * @author Roland Conybeare, Dec 2025 + **/ + +#pragma once + +#include + +namespace xo { + namespace scm { + /** Register interpreter2 (facet,impl) combinations with FacetRegistry **/ + bool interpreter2_register_types(obj gc); + } +} + +/* end interpreter2_register_types.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/sequence/IGCObject_DVsmSeqContFrame.hpp b/xo-interpreter2/include/xo/interpreter2/sequence/IGCObject_DVsmSeqContFrame.hpp new file mode 100644 index 00000000..1bdbe2ab --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/sequence/IGCObject_DVsmSeqContFrame.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DVsmSeqContFrame.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DVsmSeqContFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DVsmSeqContFrame.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DVsmSeqContFrame.hpp" + +namespace xo { namespace scm { class IGCObject_DVsmSeqContFrame; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DVsmSeqContFrame + **/ + class IGCObject_DVsmSeqContFrame { + public: + /** @defgroup scm-gcobject-dvsmseqcontframe-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dvsmseqcontframe-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DVsmSeqContFrame & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DVsmSeqContFrame & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DVsmSeqContFrame & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/include/xo/interpreter2/sequence/IPrintable_DVsmSeqContFrame.hpp b/xo-interpreter2/include/xo/interpreter2/sequence/IPrintable_DVsmSeqContFrame.hpp new file mode 100644 index 00000000..0fb46c45 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/sequence/IPrintable_DVsmSeqContFrame.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DVsmSeqContFrame.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DVsmSeqContFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DVsmSeqContFrame.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DVsmSeqContFrame.hpp" + +namespace xo { namespace scm { class IPrintable_DVsmSeqContFrame; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DVsmSeqContFrame + **/ + class IPrintable_DVsmSeqContFrame { + public: + /** @defgroup scm-printable-dvsmseqcontframe-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dvsmseqcontframe-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DVsmSeqContFrame & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-interpreter2/src/interpreter2/CMakeLists.txt b/xo-interpreter2/src/interpreter2/CMakeLists.txt index 15d06fdf..c15ddef6 100644 --- a/xo-interpreter2/src/interpreter2/CMakeLists.txt +++ b/xo-interpreter2/src/interpreter2/CMakeLists.txt @@ -2,14 +2,57 @@ set(SELF_LIB xo_interpreter2) set(SELF_SRCS + init_interpreter2.cpp + interpreter2_register_facets.cpp + interpreter2_register_types.cpp + VirtualSchematikaMachine.cpp - #IExpression_Any.cpp - #interpreter2_register_facets.cpp + + DVsmDefContFrame.cpp + IGCObject_DVsmDefContFrame.cpp + IPrintable_DVsmDefContFrame.cpp + + DVsmEvalArgsFrame.cpp + IGCObject_DVsmEvalArgsFrame.cpp + IPrintable_DVsmEvalArgsFrame.cpp + + DVsmApplyFrame.cpp + IGCObject_DVsmApplyFrame.cpp + IPrintable_DVsmApplyFrame.cpp + + DVsmApplyClosureFrame.cpp + IGCObject_DVsmApplyClosureFrame.cpp + IPrintable_DVsmApplyClosureFrame.cpp + + DVsmIfElseContFrame.cpp + IGCObject_DVsmIfElseContFrame.cpp + IPrintable_DVsmIfElseContFrame.cpp + + DVsmSeqContFrame.cpp + IGCObject_DVsmSeqContFrame.cpp + IPrintable_DVsmSeqContFrame.cpp + + DClosure.cpp + IGCObject_DClosure.cpp + IPrintable_DClosure.cpp + + DGlobalEnv.cpp + IGCObject_DGlobalEnv.cpp + IPrintable_DGlobalEnv.cpp + + DLocalEnv.cpp + IGCObject_DLocalEnv.cpp + IPrintable_DLocalEnv.cpp + + DVsmRcx.cpp + IRuntimeContext_DVsmRcx.cpp + + VsmInstr.cpp ) xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS}) # note: deps here must also appear in cmake/xo_interpreter2Config.cmake.in -xo_dependency(${SELF_LIB} xo_expression2) +xo_dependency(${SELF_LIB} xo_reader2) xo_dependency(${SELF_LIB} xo_gc) #xo_dependency(${SELF_LIB} reflect) #xo_dependency(${SELF_LIB} xo_printable2) diff --git a/xo-interpreter2/src/interpreter2/DClosure.cpp b/xo-interpreter2/src/interpreter2/DClosure.cpp new file mode 100644 index 00000000..53015068 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/DClosure.cpp @@ -0,0 +1,118 @@ +/** @file DClosure.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "Closure.hpp" +#include "LambdaExpr.hpp" +#include "LocalEnv.hpp" +#include "VsmRcx.hpp" +#include +#include +#include + +namespace xo { + using xo::mm::AGCObject; + using xo::print::APrintable; + + namespace scm { + + DClosure::DClosure(const DLambdaExpr * lm, + const DLocalEnv * env) + : lambda_{lm}, env_{env} + {} + + DClosure * + DClosure::make(obj mm, + const DLambdaExpr * lm, + const DLocalEnv * env) + { + void * mem = mm.alloc_for(); + + return new (mem) DClosure(lm, env); + } + + obj + DClosure::apply_nocheck(obj rcx, + const DArray * args) + { + // control here only if you try to invoke a closure + // as a procedure. + // + // May support this later, but requires + // nesting VSM (because call consumes c++ stack) + // + // typically prefer trampoline built into VSM + + (void)args; + + scope log(XO_DEBUG(true)); + + auto vsm_rcx + = obj::from(rcx); + + log && log(xtag("vsm_rcx.data", (void*)vsm_rcx.data())); + + auto err_mm + = vsm_rcx->error_allocator(); + + auto err + = DRuntimeError::make(err_mm, + "DClosure::apply_nocheck", + "not implemented"); + return err; + } + + size_t + DClosure::shallow_size() const noexcept { + return sizeof(DClosure); + } + + DClosure * + DClosure::shallow_copy(obj mm) const noexcept { + DClosure * copy = (DClosure *)mm.alloc_copy((std::byte *)this); + + if (copy) + *copy = *this; + + return copy; + } + + std::size_t + DClosure::forward_children(obj gc) noexcept + { + { + auto iface = xo::facet::impl_for(); + gc.forward_inplace(&iface, (void **)(&lambda_)); + + } + { + auto iface = xo::facet::impl_for(); + gc.forward_inplace(&iface, (void **)(&env_)); + } + + return shallow_size(); + } + + // ----- printable facet ----- + + bool + DClosure::pretty(const ppindentinfo & ppii) const + { + obj lambda_pr(const_cast(lambda_)); + obj env_pr(const_cast(env_)); + + bool lambda_present = lambda_pr; + bool env_present = env_pr; + + return ppii.pps()->pretty_struct + (ppii, + "DClosure", + refrtag("lambda", lambda_pr, lambda_present), + refrtag("env", env_pr, env_present)); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DClosure.cpp */ diff --git a/xo-interpreter2/src/interpreter2/DGlobalEnv.cpp b/xo-interpreter2/src/interpreter2/DGlobalEnv.cpp new file mode 100644 index 00000000..a9285b73 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/DGlobalEnv.cpp @@ -0,0 +1,128 @@ +/** @file DGlobalEnv.cpp + * + * @author Roland Conybeare, Feb 2026 +**/ + +#include "GlobalEnv.hpp" +#include +#include + +namespace xo { + using xo::mm::AAllocator; + using xo::mm::AGCObject; + + namespace scm { + + DGlobalEnv::DGlobalEnv(DGlobalSymtab * symtab, DArray * values) + : symtab_{symtab}, values_{values} + {} + + DGlobalEnv * + DGlobalEnv::_make(obj mm, + DGlobalSymtab * symtab) + { + DArray * values = DArray::empty(mm, symtab->capacity()); + + void * mem = mm.alloc_for(); + + return new (mem) DGlobalEnv(symtab, values); + } + + obj + DGlobalEnv::lookup_value(Binding ix) const noexcept + { + if (!ix.is_global()) { + assert(false); + return obj(); + } + + if (ix.j_slot() >= static_cast(values_->size())) { + assert(false); + return obj(); + } + + return (*values_)[ix.j_slot()]; + } + + void + DGlobalEnv::assign_value(obj mm, Binding ix, obj x) + { + scope log(XO_DEBUG(true), + xtag("ix.j_slot", ix.j_slot()), + xtag("values.cap", values_->capacity())); + + assert(ix.is_global()); + + if (ix.j_slot() >= static_cast(values_->size())) { + // Control will come here in interpreter as new definitions are introduced. + // After seeing + // def foo = 1.2345; + // introducing new symbol foo: + // GlobalSymtab extends to include foo without this GlobalEnv + // knowing about it. + + if (ix.j_slot() + 1 > static_cast(values_->capacity())) { + // realloc global array for more size + + size_t cap_2x = 2 * values_->capacity(); + + while (cap_2x < static_cast(ix.j_slot() + 1)) + cap_2x = 2 * cap_2x; + + DArray * values_2x = DArray::copy(mm, values_, cap_2x); + assert(values_2x); + + if (values_2x) { + log && log("STUB: need write barrier for GC (also in GlobalSymtab!)"); + this->values_ = values_2x; + } else { + return; + } + } + + /** expand size sot that j_slot is valid **/ + values_->resize(ix.j_slot() + 1); + } + + log && log("STUB: need write barrier for GC here"); + (*values_)[ix.j_slot()] = x; + } + + // ----- AGCObject facet ----- + + std::size_t + DGlobalEnv::shallow_size() const noexcept + { + return sizeof(*this); + } + + DGlobalEnv * + DGlobalEnv::shallow_copy(obj mm) const noexcept + { + return mm.std_copy_for(this); + } + + std::size_t + DGlobalEnv::forward_children(obj gc) noexcept + { + gc.forward_inplace(&symtab_); + gc.forward_inplace(&values_); + + return this->shallow_size(); + } + + // ----- APrintable facet ----- + + bool + DGlobalEnv::pretty(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct + (ppii, + "DGlobalEnv", + refrtag("size", symtab_->size())); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DGlobalEnv.cpp */ diff --git a/xo-interpreter2/src/interpreter2/DLocalEnv.cpp b/xo-interpreter2/src/interpreter2/DLocalEnv.cpp new file mode 100644 index 00000000..8f45b38a --- /dev/null +++ b/xo-interpreter2/src/interpreter2/DLocalEnv.cpp @@ -0,0 +1,147 @@ +/** @file DLocalEnv.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "LocalEnv.hpp" +#include +#include +#include + +namespace xo { + using xo::mm::AGCObject; + using xo::reflect::typeseq; + + namespace scm { + + DLocalEnv::DLocalEnv(DLocalEnv * parent, + DLocalSymtab * symtab, + DArray * args) + : parent_{parent}, + symtab_{symtab}, + args_{args} + {} + + DLocalEnv * + DLocalEnv::_make(obj mm, + DLocalEnv * parent, + DLocalSymtab * symtab, + DArray * args) + { + assert(symtab); + + void * mem = mm.alloc_for(); + + return new (mem) DLocalEnv(parent, symtab, args); + } + + obj + DLocalEnv::lookup_value(Binding ix) const noexcept + { + assert(!ix.is_global()); + + const DLocalEnv * env = this; + + for (auto i = ix.i_link(); i > 0; --i) { + env = env->parent(); + } + + if (env) { + auto j = ix.j_slot(); + + if (j < static_cast(env->size())) { + return (*(env->args_))[j]; + } else { + assert(false); + } + } else { + assert(false); + } + + /* something terribly wrong if control here */ + return obj(); + } + + void + DLocalEnv::assign_value(Binding ix, obj x) + { + scope log(XO_DEBUG(true)); + + assert(!ix.is_global()); + + const DLocalEnv * env = this; + + for (auto i = ix.i_link(); i > 0; --i) { + env = env->parent(); + } + + if (env) { + auto j = ix.j_slot(); + + if (j < static_cast(env->size())) { + log && log("STUB: need write barrier for GC here"); + (*(env->args_))[j] = x; + } else { + assert(false); + } + } else { + assert(false); + } + + /* something terribly wrong if control here */ + } + + std::size_t + DLocalEnv::shallow_size() const noexcept { + return sizeof(DLocalEnv); + } + + DLocalEnv * + DLocalEnv::shallow_copy(obj mm) const noexcept { + DLocalEnv * copy = (DLocalEnv *)mm.alloc_copy((std::byte *)this); + + if (copy) + *copy = *this; + + return copy; + } + + std::size_t + DLocalEnv::forward_children(obj gc) noexcept + { + { + auto iface = xo::facet::impl_for(); + gc.forward_inplace(&iface, (void **)(&parent_)); + } + { + auto iface = xo::facet::impl_for(); + gc.forward_inplace(&iface, (void **)(&symtab_)); + } + { + auto iface = xo::facet::impl_for(); + gc.forward_inplace(&iface, (void **)(&args_)); + } + + return shallow_size(); + } + + // ----- printable facet ----- + + bool + DLocalEnv::pretty(const ppindentinfo & ppii) const noexcept + { + // print local bindings, perhaps + // symtab_ + // args_ + + return ppii.pps()->pretty_struct + (ppii, + "DLocalEnv", + refrtag("n_args", args_->size()) + ); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DLocalEnv.cpp */ diff --git a/xo-interpreter2/src/interpreter2/DVsmApplyClosureFrame.cpp b/xo-interpreter2/src/interpreter2/DVsmApplyClosureFrame.cpp new file mode 100644 index 00000000..26a215a4 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/DVsmApplyClosureFrame.cpp @@ -0,0 +1,74 @@ +/** @file DVsmApplyClosureFrame.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "DVsmApplyClosureFrame.hpp" +#include "LocalEnv.hpp" + +namespace xo { + using xo::mm::AGCObject; + using xo::reflect::typeseq; + + namespace scm { + + DVsmApplyClosureFrame::DVsmApplyClosureFrame(obj stack, + VsmInstr cont, + DLocalEnv * local_env) + : stack_{stack}, + cont_{cont}, + local_env_{local_env} + {} + + DVsmApplyClosureFrame * + DVsmApplyClosureFrame::make(obj mm, + obj stack, + VsmInstr cont, + DLocalEnv * local_env) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DVsmApplyClosureFrame)); + + return new (mem) DVsmApplyClosureFrame(stack, cont, local_env); + } + + std::size_t + DVsmApplyClosureFrame::shallow_size() const noexcept + { + return sizeof(DVsmApplyClosureFrame); + } + + DVsmApplyClosureFrame * + DVsmApplyClosureFrame::shallow_copy(obj mm) const noexcept + { + DVsmApplyClosureFrame * copy + = (DVsmApplyClosureFrame *)mm.alloc_copy((std::byte *)this); + + if (copy) + *copy = *this; + + return copy; + } + + std::size_t + DVsmApplyClosureFrame::forward_children(obj gc) noexcept + { + gc.forward_inplace(&stack_); + gc.forward_inplace(&local_env_); + + return this->shallow_size(); + } + + bool + DVsmApplyClosureFrame::pretty(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct + (ppii, + "DVsmApplyClosureFrame", + refrtag("cont", cont_), + refrtag("env", local_env_)); + } + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DVsmApplyClosureFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/DVsmApplyFrame.cpp b/xo-interpreter2/src/interpreter2/DVsmApplyFrame.cpp new file mode 100644 index 00000000..72b81405 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/DVsmApplyFrame.cpp @@ -0,0 +1,82 @@ +/** @file DVsmApplyFrame.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "DVsmApplyFrame.hpp" +#include +#include + +namespace xo { + using xo::facet::typeseq; + + namespace scm { + + DVsmApplyFrame::DVsmApplyFrame(obj old_parent, + VsmInstr old_cont, + DArray * args) + : parent_{old_parent}, + cont_{old_cont}, + args_{args} + {} + + DVsmApplyFrame * + DVsmApplyFrame::make(obj mm, + obj old_parent, + VsmInstr old_cont, + DArray * args) + { + DVsmApplyFrame * result = nullptr; + + void * mem = mm.alloc(typeseq::id(), + sizeof(DVsmApplyFrame)); + + result = new (mem) DVsmApplyFrame(old_parent, + old_cont, + args); + + assert(result); + + return result; + } + + std::size_t + DVsmApplyFrame::shallow_size() const noexcept + { + return sizeof(DVsmApplyFrame); + } + + DVsmApplyFrame * + DVsmApplyFrame::shallow_copy(obj mm) const noexcept + { + DVsmApplyFrame * copy = (DVsmApplyFrame *)mm.alloc_copy((std::byte *)this); + + if (copy) + *copy = *this; + + return copy; + } + + std::size_t + DVsmApplyFrame::forward_children(obj gc) noexcept + { + gc.forward_inplace(&parent_); + gc.forward_inplace(&fn_); + gc.forward_inplace(&args_); + + return this->shallow_size(); + } + + bool + DVsmApplyFrame::pretty(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct(ppii, + "DVsmApplyFrame", + refrtag("cont", cont_), + refrtag("n_args", args_->size())); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DVsmApplyFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/DVsmDefContFrame.cpp b/xo-interpreter2/src/interpreter2/DVsmDefContFrame.cpp new file mode 100644 index 00000000..7b3b9e7a --- /dev/null +++ b/xo-interpreter2/src/interpreter2/DVsmDefContFrame.cpp @@ -0,0 +1,68 @@ +/** @file DVsmDefContFrame.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "DVsmDefContFrame.hpp" +#include +#include + +namespace xo { + namespace scm { + + DVsmDefContFrame::DVsmDefContFrame(obj parent, + VsmInstr cont, + DDefineExpr * def_expr) + : parent_{parent}, + cont_{cont}, + def_expr_{def_expr} + {} + + DVsmDefContFrame * + DVsmDefContFrame::make(obj mm, + obj parent, + VsmInstr cont, + DDefineExpr * def_expr) + { + void * mem = mm.alloc_for(); + + return new (mem) DVsmDefContFrame(parent, cont, def_expr); + } + + // gcobject facet + + std::size_t + DVsmDefContFrame::shallow_size() const noexcept + { + return sizeof(*this); + } + + DVsmDefContFrame * + DVsmDefContFrame::shallow_copy(obj mm) const noexcept + { + return mm.std_copy_for(this); + } + + std::size_t + DVsmDefContFrame::forward_children(obj gc) noexcept + { + gc.forward_inplace(&parent_); + gc.forward_inplace(&def_expr_); + + return this->shallow_size(); + } + + // printable facet + + bool + DVsmDefContFrame::pretty(const ppindentinfo & ppii) const noexcept + { + return ppii.pps()->pretty_struct(ppii, + "DVsmDefContFrame", + refrtag("cont", cont_)); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DVsmDefContFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/DVsmEvalArgsFrame.cpp b/xo-interpreter2/src/interpreter2/DVsmEvalArgsFrame.cpp new file mode 100644 index 00000000..09439f2e --- /dev/null +++ b/xo-interpreter2/src/interpreter2/DVsmEvalArgsFrame.cpp @@ -0,0 +1,82 @@ +/** @file DVsmEvalArgsFrame.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "DVsmEvalArgsFrame.hpp" +#include +#include + +namespace xo { + using xo::facet::typeseq; + using xo::print::ppindentinfo; + + namespace scm { + + // ----- VsmEvalArgsFrame ----- + + DVsmEvalArgsFrame::DVsmEvalArgsFrame(DVsmApplyFrame * parent, + VsmInstr cont, + DApplyExpr * apply_expr) + : parent_{parent}, + cont_{cont}, + apply_expr_{apply_expr} + {} + + DVsmEvalArgsFrame * + DVsmEvalArgsFrame::make(obj mm, + DVsmApplyFrame * apply_frame, + VsmInstr cont, + DApplyExpr * apply_expr) + { + DVsmEvalArgsFrame * result = nullptr; + + void * mem = mm.alloc(typeseq::id(), + sizeof(DVsmEvalArgsFrame)); + + result = new (mem) DVsmEvalArgsFrame(apply_frame, cont, apply_expr); + + assert(result); + + return result; + } + + std::size_t + DVsmEvalArgsFrame::shallow_size() const noexcept + { + return sizeof(DVsmEvalArgsFrame); + } + + DVsmEvalArgsFrame * + DVsmEvalArgsFrame::shallow_copy(obj mm) const noexcept + { + DVsmEvalArgsFrame * copy + = (DVsmEvalArgsFrame *)mm.alloc_copy((std::byte *)this); + + if (copy) + *copy = *this; + + return copy; + } + + std::size_t + DVsmEvalArgsFrame::forward_children(obj gc) noexcept + { + gc.forward_inplace(&parent_); + gc.forward_inplace(&apply_expr_); + + return this->shallow_size(); + } + + bool + DVsmEvalArgsFrame::pretty(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct(ppii, + "DVsmEvalArgsFrame", + refrtag("cont", cont_), + refrtag("i_arg", i_arg_)); + } + } /*namespace scm*/ +} /*namespace xo*/ + +/* end VsmEvalArgsFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/DVsmIfElseContFrame.cpp b/xo-interpreter2/src/interpreter2/DVsmIfElseContFrame.cpp new file mode 100644 index 00000000..f47419e0 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/DVsmIfElseContFrame.cpp @@ -0,0 +1,66 @@ +/** @file DVsmIfElseContFrame.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "DVsmIfElseContFrame.hpp" + +namespace xo { + namespace scm { + + DVsmIfElseContFrame::DVsmIfElseContFrame(obj parent, + VsmInstr cont, + DIfElseExpr * ifelse_expr) + : parent_{parent}, + cont_{cont}, + ifelse_expr_{ifelse_expr} + {} + + DVsmIfElseContFrame * + DVsmIfElseContFrame::make(obj mm, + obj parent, + VsmInstr cont, + DIfElseExpr * seq_expr) + { + void * mem = mm.alloc_for(); + + return new (mem) DVsmIfElseContFrame(parent, cont, seq_expr); + } + + // gcobject facet + + std::size_t + DVsmIfElseContFrame::shallow_size() const noexcept + { + return sizeof(*this); + } + + DVsmIfElseContFrame * + DVsmIfElseContFrame::shallow_copy(obj mm) const noexcept + { + return mm.std_copy_for(this); + } + + std::size_t + DVsmIfElseContFrame::forward_children(obj gc) noexcept + { + gc.forward_inplace(&parent_); + gc.forward_inplace(&ifelse_expr_); + + return this->shallow_size(); + } + + // printable facet + + bool + DVsmIfElseContFrame::pretty(const ppindentinfo & ppii) const noexcept + { + return ppii.pps()->pretty_struct(ppii, + "DVsmIfElseContFrame", + refrtag("cont", cont_)); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DVsmIfElseContFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/DVsmRcx.cpp b/xo-interpreter2/src/interpreter2/DVsmRcx.cpp new file mode 100644 index 00000000..71916771 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/DVsmRcx.cpp @@ -0,0 +1,31 @@ +/** @file DVsmRcx.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "DVsmRcx.hpp" +#include "VirtualSchematikaMachine.hpp" + +namespace xo { + using xo::mm::AAllocator; + + namespace scm { + + DVsmRcx::DVsmRcx(VirtualSchematikaMachine * vsm) : vsm_{vsm} {} + + obj + DVsmRcx::allocator() const noexcept + { + return vsm_->allocator(); + } + + obj + DVsmRcx::error_allocator() const noexcept + { + return vsm_->error_allocator(); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DVsmRcx.cpp */ diff --git a/xo-interpreter2/src/interpreter2/DVsmSeqContFrame.cpp b/xo-interpreter2/src/interpreter2/DVsmSeqContFrame.cpp new file mode 100644 index 00000000..80c1665f --- /dev/null +++ b/xo-interpreter2/src/interpreter2/DVsmSeqContFrame.cpp @@ -0,0 +1,70 @@ +/** @file DVsmSeqContFrame.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "DVsmSeqContFrame.hpp" + +namespace xo { + namespace scm { + + DVsmSeqContFrame::DVsmSeqContFrame(obj parent, + VsmInstr cont, + DSequenceExpr * seq_expr, + uint32_t i_seq) + : parent_{parent}, + cont_{cont}, + seq_expr_{seq_expr}, + i_seq_{i_seq} + {} + + DVsmSeqContFrame * + DVsmSeqContFrame::make(obj mm, + obj parent, + VsmInstr cont, + DSequenceExpr * seq_expr, + uint32_t i_seq) + { + void * mem = mm.alloc_for(); + + return new (mem) DVsmSeqContFrame(parent, cont, seq_expr, i_seq); + } + + // gcobject facet + + std::size_t + DVsmSeqContFrame::shallow_size() const noexcept + { + return sizeof(*this); + } + + DVsmSeqContFrame * + DVsmSeqContFrame::shallow_copy(obj mm) const noexcept + { + return mm.std_copy_for(this); + } + + std::size_t + DVsmSeqContFrame::forward_children(obj gc) noexcept + { + gc.forward_inplace(&parent_); + gc.forward_inplace(&seq_expr_); + + return this->shallow_size(); + } + + // printable facet + + bool + DVsmSeqContFrame::pretty(const ppindentinfo & ppii) const noexcept + { + return ppii.pps()->pretty_struct(ppii, + "DVsmSeqContFrame", + refrtag("cont", cont_), + refrtag("i_seq", i_seq_)); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DVsmSeqContFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IGCObject_DClosure.cpp b/xo-interpreter2/src/interpreter2/IGCObject_DClosure.cpp new file mode 100644 index 00000000..28dd3277 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IGCObject_DClosure.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DClosure.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DClosure.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DClosure.json5] +**/ + +#include "detail/IGCObject_DClosure.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DClosure::shallow_size(const DClosure & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DClosure::shallow_copy(const DClosure & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DClosure::forward_children(DClosure & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DClosure.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IGCObject_DGlobalEnv.cpp b/xo-interpreter2/src/interpreter2/IGCObject_DGlobalEnv.cpp new file mode 100644 index 00000000..76606d6f --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IGCObject_DGlobalEnv.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DGlobalEnv.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DGlobalEnv.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DGlobalEnv.json5] +**/ + +#include "env/IGCObject_DGlobalEnv.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DGlobalEnv::shallow_size(const DGlobalEnv & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DGlobalEnv::shallow_copy(const DGlobalEnv & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DGlobalEnv::forward_children(DGlobalEnv & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DGlobalEnv.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IGCObject_DLocalEnv.cpp b/xo-interpreter2/src/interpreter2/IGCObject_DLocalEnv.cpp new file mode 100644 index 00000000..3b6cd5f7 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IGCObject_DLocalEnv.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DLocalEnv.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DLocalEnv.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DLocalEnv.json5] +**/ + +#include "env/IGCObject_DLocalEnv.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DLocalEnv::shallow_size(const DLocalEnv & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DLocalEnv::shallow_copy(const DLocalEnv & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DLocalEnv::forward_children(DLocalEnv & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DLocalEnv.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IGCObject_DVsmApplyClosureFrame.cpp b/xo-interpreter2/src/interpreter2/IGCObject_DVsmApplyClosureFrame.cpp new file mode 100644 index 00000000..7a05d47e --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IGCObject_DVsmApplyClosureFrame.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DVsmApplyClosureFrame.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DVsmApplyClosureFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DVsmApplyClosureFrame.json5] +**/ + +#include "detail/IGCObject_DVsmApplyClosureFrame.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DVsmApplyClosureFrame::shallow_size(const DVsmApplyClosureFrame & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DVsmApplyClosureFrame::shallow_copy(const DVsmApplyClosureFrame & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DVsmApplyClosureFrame::forward_children(DVsmApplyClosureFrame & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DVsmApplyClosureFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IGCObject_DVsmApplyFrame.cpp b/xo-interpreter2/src/interpreter2/IGCObject_DVsmApplyFrame.cpp new file mode 100644 index 00000000..1e794477 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IGCObject_DVsmApplyFrame.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DVsmApplyFrame.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DVsmApplyFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DVsmApplyFrame.json5] +**/ + +#include "detail/IGCObject_DVsmApplyFrame.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DVsmApplyFrame::shallow_size(const DVsmApplyFrame & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DVsmApplyFrame::shallow_copy(const DVsmApplyFrame & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DVsmApplyFrame::forward_children(DVsmApplyFrame & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DVsmApplyFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IGCObject_DVsmDefContFrame.cpp b/xo-interpreter2/src/interpreter2/IGCObject_DVsmDefContFrame.cpp new file mode 100644 index 00000000..26a23611 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IGCObject_DVsmDefContFrame.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DVsmDefContFrame.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DVsmDefContFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DVsmDefContFrame.json5] +**/ + +#include "define/IGCObject_DVsmDefContFrame.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DVsmDefContFrame::shallow_size(const DVsmDefContFrame & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DVsmDefContFrame::shallow_copy(const DVsmDefContFrame & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DVsmDefContFrame::forward_children(DVsmDefContFrame & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DVsmDefContFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IGCObject_DVsmEvalArgsFrame.cpp b/xo-interpreter2/src/interpreter2/IGCObject_DVsmEvalArgsFrame.cpp new file mode 100644 index 00000000..d64b47bd --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IGCObject_DVsmEvalArgsFrame.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DVsmEvalArgsFrame.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DVsmEvalArgsFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DVsmEvalArgsFrame.json5] +**/ + +#include "detail/IGCObject_DVsmEvalArgsFrame.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DVsmEvalArgsFrame::shallow_size(const DVsmEvalArgsFrame & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DVsmEvalArgsFrame::shallow_copy(const DVsmEvalArgsFrame & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DVsmEvalArgsFrame::forward_children(DVsmEvalArgsFrame & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DVsmEvalArgsFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IGCObject_DVsmIfElseContFrame.cpp b/xo-interpreter2/src/interpreter2/IGCObject_DVsmIfElseContFrame.cpp new file mode 100644 index 00000000..ba66cd8d --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IGCObject_DVsmIfElseContFrame.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DVsmIfElseContFrame.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DVsmIfElseContFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DVsmIfElseContFrame.json5] +**/ + +#include "ifelse/IGCObject_DVsmIfElseContFrame.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DVsmIfElseContFrame::shallow_size(const DVsmIfElseContFrame & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DVsmIfElseContFrame::shallow_copy(const DVsmIfElseContFrame & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DVsmIfElseContFrame::forward_children(DVsmIfElseContFrame & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DVsmIfElseContFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IGCObject_DVsmSeqContFrame.cpp b/xo-interpreter2/src/interpreter2/IGCObject_DVsmSeqContFrame.cpp new file mode 100644 index 00000000..eecdf291 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IGCObject_DVsmSeqContFrame.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DVsmSeqContFrame.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DVsmSeqContFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DVsmSeqContFrame.json5] +**/ + +#include "sequence/IGCObject_DVsmSeqContFrame.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DVsmSeqContFrame::shallow_size(const DVsmSeqContFrame & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DVsmSeqContFrame::shallow_copy(const DVsmSeqContFrame & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DVsmSeqContFrame::forward_children(DVsmSeqContFrame & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DVsmSeqContFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IPrintable_DClosure.cpp b/xo-interpreter2/src/interpreter2/IPrintable_DClosure.cpp new file mode 100644 index 00000000..e9c599fb --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IPrintable_DClosure.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DClosure.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DClosure.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DClosure.json5] +**/ + +#include "detail/IPrintable_DClosure.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DClosure::pretty(const DClosure & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DClosure.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IPrintable_DGlobalEnv.cpp b/xo-interpreter2/src/interpreter2/IPrintable_DGlobalEnv.cpp new file mode 100644 index 00000000..84fc561c --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IPrintable_DGlobalEnv.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DGlobalEnv.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DGlobalEnv.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DGlobalEnv.json5] +**/ + +#include "env/IPrintable_DGlobalEnv.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DGlobalEnv::pretty(const DGlobalEnv & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DGlobalEnv.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IPrintable_DLocalEnv.cpp b/xo-interpreter2/src/interpreter2/IPrintable_DLocalEnv.cpp new file mode 100644 index 00000000..6fe745b2 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IPrintable_DLocalEnv.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DLocalEnv.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DLocalEnv.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DLocalEnv.json5] +**/ + +#include "env/IPrintable_DLocalEnv.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DLocalEnv::pretty(const DLocalEnv & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DLocalEnv.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IPrintable_DVsmApplyClosureFrame.cpp b/xo-interpreter2/src/interpreter2/IPrintable_DVsmApplyClosureFrame.cpp new file mode 100644 index 00000000..36b89a10 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IPrintable_DVsmApplyClosureFrame.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DVsmApplyClosureFrame.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DVsmApplyClosureFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DVsmApplyClosureFrame.json5] +**/ + +#include "detail/IPrintable_DVsmApplyClosureFrame.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DVsmApplyClosureFrame::pretty(const DVsmApplyClosureFrame & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DVsmApplyClosureFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IPrintable_DVsmApplyFrame.cpp b/xo-interpreter2/src/interpreter2/IPrintable_DVsmApplyFrame.cpp new file mode 100644 index 00000000..5faa360f --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IPrintable_DVsmApplyFrame.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DVsmApplyFrame.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DVsmApplyFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DVsmApplyFrame.json5] +**/ + +#include "detail/IPrintable_DVsmApplyFrame.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DVsmApplyFrame::pretty(const DVsmApplyFrame & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DVsmApplyFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IPrintable_DVsmDefContFrame.cpp b/xo-interpreter2/src/interpreter2/IPrintable_DVsmDefContFrame.cpp new file mode 100644 index 00000000..f73b7dd6 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IPrintable_DVsmDefContFrame.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DVsmDefContFrame.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DVsmDefContFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DVsmDefContFrame.json5] +**/ + +#include "define/IPrintable_DVsmDefContFrame.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DVsmDefContFrame::pretty(const DVsmDefContFrame & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DVsmDefContFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IPrintable_DVsmEvalArgsFrame.cpp b/xo-interpreter2/src/interpreter2/IPrintable_DVsmEvalArgsFrame.cpp new file mode 100644 index 00000000..25d81800 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IPrintable_DVsmEvalArgsFrame.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DVsmEvalArgsFrame.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DVsmEvalArgsFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DVsmEvalArgsFrame.json5] +**/ + +#include "detail/IPrintable_DVsmEvalArgsFrame.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DVsmEvalArgsFrame::pretty(const DVsmEvalArgsFrame & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DVsmEvalArgsFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IPrintable_DVsmIfElseContFrame.cpp b/xo-interpreter2/src/interpreter2/IPrintable_DVsmIfElseContFrame.cpp new file mode 100644 index 00000000..e8afc908 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IPrintable_DVsmIfElseContFrame.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DVsmIfElseContFrame.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DVsmIfElseContFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DVsmIfElseContFrame.json5] +**/ + +#include "ifelse/IPrintable_DVsmIfElseContFrame.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DVsmIfElseContFrame::pretty(const DVsmIfElseContFrame & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DVsmIfElseContFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IPrintable_DVsmSeqContFrame.cpp b/xo-interpreter2/src/interpreter2/IPrintable_DVsmSeqContFrame.cpp new file mode 100644 index 00000000..74801873 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IPrintable_DVsmSeqContFrame.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DVsmSeqContFrame.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DVsmSeqContFrame.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DVsmSeqContFrame.json5] +**/ + +#include "sequence/IPrintable_DVsmSeqContFrame.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DVsmSeqContFrame::pretty(const DVsmSeqContFrame & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DVsmSeqContFrame.cpp */ diff --git a/xo-interpreter2/src/interpreter2/IRuntimeContext_DVsmRcx.cpp b/xo-interpreter2/src/interpreter2/IRuntimeContext_DVsmRcx.cpp new file mode 100644 index 00000000..3fd3730d --- /dev/null +++ b/xo-interpreter2/src/interpreter2/IRuntimeContext_DVsmRcx.cpp @@ -0,0 +1,28 @@ +/** @file IRuntimeContext_DVsmRcx.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IRuntimeContext_DVsmRcx.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IRuntimeContext_DVsmRcx.json5] +**/ + +#include "detail/IRuntimeContext_DVsmRcx.hpp" + +namespace xo { + namespace scm { + auto + IRuntimeContext_DVsmRcx::allocator(const DVsmRcx & self) noexcept -> obj + { + return self.allocator(); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IRuntimeContext_DVsmRcx.cpp */ diff --git a/xo-interpreter2/src/interpreter2/VirtualSchematikaMachine.cpp b/xo-interpreter2/src/interpreter2/VirtualSchematikaMachine.cpp index bd29e968..9104fa2f 100644 --- a/xo-interpreter2/src/interpreter2/VirtualSchematikaMachine.cpp +++ b/xo-interpreter2/src/interpreter2/VirtualSchematikaMachine.cpp @@ -4,15 +4,167 @@ **/ #include "VirtualSchematikaMachine.hpp" -#include -#include +#include "VsmDefContFrame.hpp" +#include "VsmApplyFrame.hpp" +#include "VsmEvalArgsFrame.hpp" +#include "VsmApplyClosureFrame.hpp" +#include "VsmIfElseContFrame.hpp" +#include "VsmSeqContFrame.hpp" +#include "VsmRcx.hpp" +#include "Closure.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include #include namespace xo { + using xo::print::APrintable; + using xo::print::ppconfig; + using xo::print::ppstate_standalone; + using xo::mm::AGCObject; + //using xo::mm::MemorySizeInfo; // not used yet + using xo::mm::AAllocator; + using xo::mm::DX1Collector; + using xo::mm::DArena; + using xo::facet::FacetRegistry; + using std::cout; + namespace scm { - VirtualSchematikaMachine::VirtualSchematikaMachine() - {} + bool + VsmResult::is_eval_error() const + { + if (std::holds_alternative>(result_)) { + auto err = obj::from(*(this->value())); + + return err; + } else { + return false; + } + } + + // NOTE: using heap here for {DX1Collector, DArena, DVsmRcx} instances + // (though DX1Collector allocations will be from explictly mmap'd memory) + // + VirtualSchematikaMachine::VirtualSchematikaMachine(const VsmConfig & config, + obj aux_mm) + : config_{config}, + mm_(abox::make(aux_mm, config.x1_config_)), + rcx_(abox::make(aux_mm, this)), + reader_{config.rdr_config_, mm_.to_op(), aux_mm} + { + { + DArena * arena = new DArena(config_.error_config_); + assert(arena); + + this->error_mm_.adopt(obj(arena)); + } + + this->global_env_ = DGlobalEnv::_make(mm_.to_op(), reader_.global_symtab()); + } + + obj + VirtualSchematikaMachine::allocator() const noexcept + { + return mm_.to_op(); + } + + obj + VirtualSchematikaMachine::error_allocator() const noexcept + { + return error_mm_.to_op(); + } + + bool + VirtualSchematikaMachine::is_at_toplevel() const noexcept + { + return reader_.is_at_toplevel(); + } + + void + VirtualSchematikaMachine::visit_pools(const MemorySizeVisitor & visitor) const + { + mm_.visit_pools(visitor); + error_mm_.visit_pools(visitor); + reader_.visit_pools(visitor); + } + + void + VirtualSchematikaMachine::begin_interactive_session() + { + reader_.begin_interactive_session(); + } + + void + VirtualSchematikaMachine::begin_batch_session() + { + reader_.begin_batch_session(); + } + + VsmResultExt + VirtualSchematikaMachine::read_eval_print(span_type input, bool eof) + { + if (input.empty()) { + return VsmResultExt(); + } + + reader_.reset_result(); + + auto [expr, remaining, error1] + = reader_.read_expr(input, eof); + + if (!expr) { + /* tokenizer error */ + + return VsmResultExt(VsmResult(error1), remaining); + } + + VsmResult evalresult = this->start_eval(expr); + + if (evalresult.is_eval_error() || evalresult.is_tk_error()) { + return VsmResultExt(evalresult, remaining); + } + + assert(evalresult.is_value()); + + obj * p_value = std::get_if>(&(evalresult.result_)); + + assert(p_value); + + obj value_pr + = FacetRegistry::instance().variant(*p_value); + + // pretty_toplevel(value_pr, &cout, ppconfig()); + ppconfig ppc; + ppstate_standalone pps(&cout, 0, &ppc); + pps.prettyn(value_pr); + + return VsmResultExt(VsmResult(*p_value), remaining); + } + + VsmResult + VirtualSchematikaMachine::start_eval(obj expr) + { + this->pc_ = VsmInstr::c_eval; + this->expr_ = expr; + this->value_ = VsmResult(obj()); + this->cont_ = VsmInstr::c_halt; + + this->run(); + + return value_; + } void VirtualSchematikaMachine::run() @@ -24,12 +176,45 @@ namespace xo { bool VirtualSchematikaMachine::execute_one() { + scope log(XO_DEBUG(config_.debug_flag_)); + + log && log(xtag("pc", pc_), + xtag("cont", cont_)); + + auto expr_pr = expr_.to_facet(); + if (expr_pr) + log && log(xtag("expr", expr_pr)); + + auto stack_pr = stack_.to_facet(); + if (stack_pr) + log && log(xtag("stack", stack_pr)); + switch (pc_.opcode()) { + case vsm_opcode::sentinel: case vsm_opcode::halt: case vsm_opcode::N: return false; case vsm_opcode::eval: _do_eval_op(); + break; + case vsm_opcode::apply: + _do_apply_op(); + break; + case vsm_opcode::evalargs: + _do_evalargs_op(); + break; + case vsm_opcode::def_cont: + _do_def_cont_op(); + break; + case vsm_opcode::apply_cont: + _do_apply_cont_op(); + break; + case vsm_opcode::ifelse_cont: + _do_ifelse_cont_op(); + break; + case vsm_opcode::seq_cont: + _do_seq_cont_op(); + break; } return true; @@ -45,9 +230,27 @@ namespace xo { case exprtype::constant: _do_eval_constant_op(); break; + case exprtype::define: + _do_eval_define_op(); + break; + case exprtype::lambda: + _do_eval_lambda_op(); + break; case exprtype::variable: _do_eval_variable_op(); break; + case exprtype::varref: + _do_eval_varref_op(); + break; + case exprtype::apply: + _do_eval_apply_op(); + break; + case exprtype::ifexpr: + _do_eval_if_else_op(); + break; + case exprtype::sequence: + _do_eval_sequence_op(); + break; } } @@ -57,8 +260,130 @@ namespace xo { auto expr = obj::from(expr_); - this->value_ = expr.data()->value(); + this->value_ = VsmResult(expr.data()->value()); + this->pc_ = this->cont_; + this->cont_ = VsmInstr::c_sentinel; + } + + void + VirtualSchematikaMachine::_do_eval_define_op() + { + scope log(XO_DEBUG(true)); + + auto def_expr + = obj::from(expr_); + + if (local_env_ == nullptr) { + // top-level define + + // .stack_ --+ + // | + // v + // +------DVsmDefContFrame------+ + // | .parent x | .cont | .def x | + // +---------|-+-------+------|-+ + // | | + // ParserStack* <-----/ | + // | + // v + // DDefineExpr + + /* stack frame for nested continuation + * (to perform assignment) + */ + auto defcont_frame + = obj + (DVsmDefContFrame::make(mm_.to_op(), + this->stack_ /*saved stack*/, + this->cont_ /*saved cont*/, + def_expr.data() /*saved expr*/)); + + this->stack_ = defcont_frame; + + // setup evaluation of rhs + + this->expr_ = def_expr->rhs(); + this->pc_ = VsmInstr::c_eval; + this->cont_ = VsmInstr::c_def_cont; + } else { + // nested defines implemented by rewriting, + // so this branch should be unreachable + + assert(false); + } + } + + void + VirtualSchematikaMachine::_do_def_cont_op() + { + // see DVsmDefContFrame + + auto frame = obj::from(stack_); + + assert(frame); + assert(value_.is_value()); + + // TODO: verify that value satisfies expected type ? + + DVariable * lhs = frame->def_expr()->lhs(); + obj rhs = *value_.value(); + + assert(lhs->path().is_global()); + + global_env_->assign_value(mm_.to_op(), lhs->path(), rhs); + + // TODO: unfortunate const_cast here, because obj<> doesn't support const DRepr yet + this->value_ = VsmResult(obj(const_cast(lhs->name()))); + + this->stack_ = frame->parent(); + this->pc_ = frame->cont(); + this->cont_ = VsmInstr::c_sentinel; + } + + void + VirtualSchematikaMachine::_do_eval_lambda_op() + { + // assuming bump allocator + // + // +----------- DArray---------+ +-------------DLocalEnv-----------+ +-----DClosure-------+ + // | .cap |.size | .elts_[]... |h| .parent x | .symtab x | .args x |h| .lambda x | .env x | + // +------+------+-------------+ +---------|-+---------|-+-------|-+ +---------|-+------|-+ + // ^ ^ | | | | | + // \-----------------------------|---------|-----------|---------/ | | + // | | | | | + // \---------|-----------|-----------------------|--------/ + // | | | + // <--------------------------------------/ | | + // | | + // v v + // DLocalSymtab DLambdaExpr + // + // DClosure runtime procedure (created below) + // DArray bound non-local variables (established by VSM) + // DLocalEnv local environment (copy ref from VSM state) + // h alloc header + // DLocalSymtab local symbol table (created by parser) + // DLambdaExpr lambda expression (created by parser) + // + + // will create DClosure with local_env_ + + // local_env_ + // global_env_ + + auto lambda + = obj::from(expr_); + + DClosure * closure = DClosure::make(mm_.to_op(), + lambda.data(), + local_env_); + + this->value_ + = VsmResult(obj(obj(closure))); + + this->pc_ = this->cont_; + this->cont_ = VsmInstr::c_sentinel; } void @@ -67,6 +392,448 @@ namespace xo { // not implemented assert(false); } + + void + VirtualSchematikaMachine::_do_eval_varref_op() + { + auto var = obj::from(expr_); + + Binding b = var->path(); + + obj value; + + if (b.is_local() && local_env_) { + value = local_env_->lookup_value(b); + } else if (b.is_global()) { + value = global_env_->lookup_value(b); + } + + if (value) { + this->value_ = VsmResult(value); + + this->pc_ = this->cont_; + this->cont_ = VsmInstr::c_sentinel; + return; + } + + // no local or global binding + + auto error = DRuntimeError::make(mm_.to_op(), + "_do_eval_varref_op", + "no binding for variable"); + this->value_ = VsmResult(error); + + // for now: halt VSM execution + // TODO: some combination of + // 1. emit stack trace + // 2. go to debugger + // 3. have every vsm instruction check inputs for errors + + this->pc_ = VsmInstr::c_halt; + this->cont_ = VsmInstr::c_sentinel; + } + + void + VirtualSchematikaMachine::_do_eval_apply_op() + { + // ApplyExpr in expr_ register + + // assuming bump allocator: + // + // DArray VsmApplyFrame VsmEvalArgsFrame + // v v v + // +----------------------+-------+-------+----+--------+-------+-------+-------+ + // | argument expressions | par x | cont1 | fn | args x | par x | cont2 | i_arg | + // +----------------------+-----|-+-------+----+------|-+-----|-+-------+-------+ + // ^ ^ | | | + // | \-----------------------------------/ + // \ | / + // \------------------------------------------------/ + // / + // <---------------------------/ + // + // - VsmEvalArgsFrame: owned by VSM, state for evalargs loop + // - VsmApplyFrame: owned by VSM, state for transferring control to called function + // - DArray: contains evaluated args; owned by called primitive + // - cont2: always c_apply + // + + auto apply = obj::from(expr_); + + // accumulate evaluated arguments here + DArray * args = DArray::empty(mm_.to_op(), + apply->n_args()); + + // TODO: check function signature + + DVsmApplyFrame * apply_frame + = DVsmApplyFrame::make(mm_.to_op(), stack_, cont_, args); + + auto evalargs_frame + = obj + (DVsmEvalArgsFrame::make(mm_.to_op(), + apply_frame, VsmInstr::c_apply, apply.data())); + + this->stack_ = evalargs_frame; + + // Setup evaluation of first argument. No new stack for this. + + this->expr_ = apply->fn(); + this->pc_ = VsmInstr::c_eval; + this->cont_ = VsmInstr::c_evalargs; + } + + void + VirtualSchematikaMachine::_do_eval_if_else_op() + { + // control: + // self -> eval(test) -> ifelse_cont -> eval(when_true) + // -> eval(when_false) + + auto ifelse_expr = obj::from(expr_); + + obj ifelse_frame + (DVsmIfElseContFrame::make(mm_.to_op(), + stack_, cont_, ifelse_expr.data())); + + this->stack_ = ifelse_frame; + this->expr_ = ifelse_expr->test(); + this->pc_ = VsmInstr::c_eval; + this->cont_ = VsmInstr::c_ifelse_cont; + } + + void + VirtualSchematikaMachine::_do_eval_sequence_op() + { + // stack: + // + // VsmEvalSequence + // v + // +-------+------+-------+-------+ + // | par x | cont | seq | i_elt | + // +-----|-+------+-------+-------+ + // | + // <-----/ + // + + auto seq_expr = obj::from(expr_); + + if (seq_expr->size() == 0) { + /* empty sequence expression does not produce a value */ + + this->value_ = VsmResult(obj()); + this->pc_ = this->cont_; + return; + } + + auto seqexpr_frame + = obj + (DVsmSeqContFrame::make(mm_.to_op(), + this->stack_ /*saved stack*/, + this->cont_ /*saved cont*/, + seq_expr.data() /*saved expr*/, + 0 /*index of seq element*/)); + + this->stack_ = seqexpr_frame; + + // Setup evaluation of first sequence element + + this->expr_ = (*seq_expr.data())[0]; + this->pc_ = VsmInstr::c_eval; + this->cont_ = VsmInstr::c_seq_cont; + } + + void + VirtualSchematikaMachine::_do_apply_op() + { + // rcx_ : runtime context + // fn_ : function to call + // args_ : array of arguments + + // TODO: check argument types + + auto closure = obj::from(fn_); + + if (closure) { + _do_call_closure_op(); + return; + } else { + _do_call_primitive_op(); + return; + } + } + + void + VirtualSchematikaMachine::_do_call_closure_op() + { + // We need to preserve registers while evaluating + // lambda body + + auto closure = obj::from(fn_); + + assert(closure); + + // TODO: for tail recursion: + // check whether stack_ already refers to a + // DVsmApplyClosureFrame instance, in which case + // we can just refer to it instead of pushing a new one + + if (cont_ == VsmInstr::c_apply_cont) { + // we are making a tail call. + // No need to preserve (stack, cont, local_env), + // since continuation will restore on top of them + // frame top stackframe anyway + } else { + obj frame( + DVsmApplyClosureFrame::make(mm_.to_op(), + stack_, + cont_, + local_env_)); + + // push frame w/ saved vsm registers + this->stack_ = frame; + this->cont_ = VsmInstr::c_apply_cont; + } + + auto lambda = closure->lambda(); + + auto local_env + = DLocalEnv::_make(mm_.to_op(), + local_env_, + lambda->local_symtab(), + args_); + + this->local_env_ = local_env; + this->expr_ = lambda->body_expr(); + this->pc_ = VsmInstr::c_eval; + // cont_ already established + } + + void + VirtualSchematikaMachine::_do_call_primitive_op() + { + auto fn = fn_.to_facet(); + + this->value_ = VsmResult(fn.apply_nocheck(rcx_.to_op(), args_)); + this->pc_ = cont_; + this->cont_ = VsmInstr::c_sentinel; + } + + void + VirtualSchematikaMachine::_do_evalargs_op() + { + scope log(XO_DEBUG(false)); + + if (!value_.is_value()) { + // error while evaluating function arg + + log.retroactively_enable(); + log && log("error in apply -> terminating app"); + + this->pc_ = VsmInstr::c_halt; + this->cont_ = VsmInstr::c_sentinel; + return; + } + + // here: nested evaluation succeeded + + // value of one of {fn, arg(i), ..} in fn(arg0 .. arg(n-1)) + // + obj value = *(value_.value()); + + // value_ in [i_arg] value_ + // . (if i_arg >= 0) . (if i_arg = -1) + // . . + // DArray . VsmApplyFrame . VsmEvalArgsFrame + // v v v v v + // +----------------------+-------+-------+----+--------+-------+-------+--------+-------+ + // | argument expressions | par o | cont1 | fn | args x | par o | cont2 | applyx | i_arg | + // +----------------------+-----|-+-------+----+------|-+-----|-+-------+--------+-------+ + // ^ ^ | | | + // | \-----------------------------------/ + // \ | / + // \------------------------------------------------/ + // / + // <---------------------------/ + // + // - VsmEvalArgsFrame: owned by VSM, state for evalargs loop + // - VsmApplyFrame: owned by VSM, state for transferring control to called function + // - DArray: contains evaluated args; owned by called primitive + + // - i_arg + // if -1: value_ register holds function + // if >=0: value_ register holds i'th function argument + // + + auto evalargs_frame + = obj::from(stack_); + + assert(evalargs_frame); + + int32_t i_arg = evalargs_frame->i_arg(); + + DVsmApplyFrame * apply_frame = evalargs_frame->parent(); + + const DApplyExpr * apply_expr + = evalargs_frame->apply_expr(); + + if (i_arg == -1) { + bool is_closure = obj::from(value); + bool is_native_fn = value.try_to_facet(); + + if (is_native_fn || is_closure) { + apply_frame->assign_fn(value); + + i_arg = evalargs_frame->increment_arg(); + + // now i_arg is 0 -> evaluate that argument + + this->expr_ = apply_expr->arg(i_arg); + this->pc_ = VsmInstr::c_eval; + this->cont_ = VsmInstr::c_evalargs; + + return; + } else { + // error - function position must deliver something with AProcedure? + // or DClosure, but we'll get to that. + + log.retroactively_enable(); + log("expected procedure in function position -> terminate"); + + assert(false); + } + } else { + DArray * args = apply_frame->args(); + + log && log(xtag("i_arg", i_arg), xtag("n_arg", args->size()), xtag("cap", args->capacity())); + + args->push_back(value); + + i_arg = evalargs_frame->increment_arg(); + + if (i_arg == static_cast(apply_expr->n_args())) { + // all apply-arguments have been evaluated + // -> done with VsmEvalArgsFrame + // + + this->fn_ = apply_frame->fn(); + this->args_ = apply_frame->args(); + + this->stack_ = apply_frame->parent(); + this->pc_ = VsmInstr::c_apply; + this->cont_ = apply_frame->cont(); + + return; + + } else { + this->expr_ = apply_expr->arg(i_arg); + this->pc_ = VsmInstr::c_eval; + this->cont_ = VsmInstr::c_evalargs; + + return; + } + } + + // not implemented + assert(false); + } + + void + VirtualSchematikaMachine::_do_apply_cont_op() + { + // see DVsmApplyClosureFrame + + auto frame = obj::from(stack_); + + assert(frame); + + this->stack_ = frame->parent(); + this->local_env_ = frame->local_env(); + this->pc_ = frame->cont(); + this->cont_ = VsmInstr::c_sentinel; + } + + void + VirtualSchematikaMachine::_do_ifelse_cont_op() + { + // pre: result of evaluating test condition in value_ register + + auto frame = obj::from(stack_); + + assert(frame); + assert(value_.is_value()); + + auto flag = obj::from(*value_.value()); + + if (flag.data()) { + obj next_expr; + { + if (flag->value()) { + // proceed with if-branch + next_expr = frame->ifelse_expr()->when_true(); + } else { + // proceed with else-branch + next_expr = frame->ifelse_expr()->when_false(); + } + } + + this->stack_ = frame->parent(); + this->expr_ = next_expr; + this->pc_ = VsmInstr::c_eval; + this->cont_ = frame->cont(); + } else { + auto error = DRuntimeError::make(mm_.to_op(), + "_do_ifelse_cont_op", + "expected boolean for test condition"); + this->value_ = VsmResult(error); + + // for now: halt VSM execution + // TODO: some combination of + // 1. emit stack trace + // 2. go to debugger + // 3. have every vsm instruction check inputs for errors + + this->pc_ = VsmInstr::c_halt; + this->cont_ = VsmInstr::c_sentinel; + } + } + + void + VirtualSchematikaMachine::_do_seq_cont_op() + { + auto frame = obj::from(stack_); + + assert(frame); + + uint32_t i_seq = 1 + frame->i_seq(); + + auto seq_expr = frame->seq_expr(); + + assert(seq_expr); + + if (i_seq == seq_expr->size()) { + /* done with sequence + * value of sequence-expr is the value of the last expression in that sequence, + * which is already in the value_ register + */ + + this->stack_ = frame->parent(); + this->pc_ = frame->cont(); + this->cont_ = VsmInstr::c_sentinel; + + return; + } else { + frame->incr_i_seq(); + + this->expr_ = (*seq_expr)[i_seq]; + this->pc_ = VsmInstr::c_eval; + this->cont_ = VsmInstr::c_seq_cont; + + return; + } + } + } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-reader2/include/xo/reader2/.gitkeep b/xo-interpreter2/src/interpreter2/VsmApplyFrame.cpp similarity index 100% rename from xo-reader2/include/xo/reader2/.gitkeep rename to xo-interpreter2/src/interpreter2/VsmApplyFrame.cpp diff --git a/xo-interpreter2/src/interpreter2/VsmInstr.cpp b/xo-interpreter2/src/interpreter2/VsmInstr.cpp new file mode 100644 index 00000000..852b6332 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/VsmInstr.cpp @@ -0,0 +1,59 @@ +/** @file VsmInstr.cpp +* + * @author Roland Conybeare, Feb 2026 + **/ + +#include "VsmInstr.hpp" + +namespace xo { + namespace scm { + const char * + vsm_opcode_descr(vsm_opcode x) + { + switch (x) { + case vsm_opcode::sentinel: return "sentinel"; + case vsm_opcode::halt: return "halt"; + case vsm_opcode::eval: return "eval"; + case vsm_opcode::apply: return "apply"; + case vsm_opcode::evalargs: return "evalargs"; + case vsm_opcode::def_cont: return "def_cont"; + case vsm_opcode::apply_cont: return "apply_cont"; + case vsm_opcode::ifelse_cont: return "ifelse_cont"; + case vsm_opcode::seq_cont: return "seq_cont"; + case vsm_opcode::N: + break; + } + + return "opcode?"; + } + + VsmInstr + VsmInstr::c_sentinel = VsmInstr(vsm_opcode::sentinel); + + VsmInstr + VsmInstr::c_halt = VsmInstr(vsm_opcode::halt); + + VsmInstr + VsmInstr::c_eval = VsmInstr(vsm_opcode::eval); + + VsmInstr + VsmInstr::c_apply = VsmInstr(vsm_opcode::apply); + + VsmInstr + VsmInstr::c_evalargs = VsmInstr(vsm_opcode::evalargs); + + VsmInstr + VsmInstr::c_def_cont = VsmInstr(vsm_opcode::def_cont); + + VsmInstr + VsmInstr::c_apply_cont = VsmInstr(vsm_opcode::apply_cont); + + VsmInstr + VsmInstr::c_ifelse_cont = VsmInstr(vsm_opcode::ifelse_cont); + + VsmInstr + VsmInstr::c_seq_cont = VsmInstr(vsm_opcode::seq_cont); + } /*namespace scm*/ +} /*namespace xo*/ + +/* end VsmInstr.cpp */ diff --git a/xo-interpreter2/src/interpreter2/init_interpreter2.cpp b/xo-interpreter2/src/interpreter2/init_interpreter2.cpp new file mode 100644 index 00000000..07308863 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/init_interpreter2.cpp @@ -0,0 +1,42 @@ +/** @file init_interpreter2.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "init_interpreter2.hpp" + +#include "interpreter2_register_facets.hpp" +#include "interpreter2_register_types.hpp" + +#include +#include + +namespace xo { + using xo::scm::interpreter2_register_facets; + using xo::scm::interpreter2_register_types; + using xo::mm::CollectorTypeRegistry; + + void + InitSubsys::init() + { + interpreter2_register_facets(); + + CollectorTypeRegistry::instance().register_types(&interpreter2_register_types); + } + + InitEvidence + InitSubsys::require() + { + InitEvidence retval; + + /* direct subsystem deps for xo-interpreter2/ */ + retval ^= InitSubsys::require(); + + /* xo-interpreter2/'s own initialization code */ + retval ^= Subsystem::provide("interpreter2", &init); + + return retval; + } +} /*namespace xo*/ + +/* end init_interpreter2.cpp */ diff --git a/xo-interpreter2/src/interpreter2/interpreter2_register_facets.cpp b/xo-interpreter2/src/interpreter2/interpreter2_register_facets.cpp new file mode 100644 index 00000000..22c9bfb9 --- /dev/null +++ b/xo-interpreter2/src/interpreter2/interpreter2_register_facets.cpp @@ -0,0 +1,112 @@ +/** @file interpreter2_register_facets.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "interpreter2_register_facets.hpp" + +#include "DPrimitive_gco_2_gco_gco.hpp" +#include "VsmDefContFrame.hpp" +#include "VsmApplyFrame.hpp" +#include "VsmEvalArgsFrame.hpp" +#include "VsmApplyClosureFrame.hpp" +#include "VsmIfElseContFrame.hpp" +#include "VsmSeqContFrame.hpp" +#include "Primitive_gco_2_gco_gco.hpp" +#include "Closure.hpp" +#include "GlobalEnv.hpp" +#include "LocalEnv.hpp" +#include "VsmRcx.hpp" + +#include +#include +#include +#include + +namespace xo { + using xo::mm::AGCObject; + using xo::print::APrintable; + using xo::facet::FacetRegistry; + using xo::reflect::typeseq; + using xo::xtag; + + namespace scm { + bool + interpreter2_register_facets() + { + scope log(XO_DEBUG(true)); + + + // VsmStqackFrame + // +- VsmApplyFrame + // +- VsmEvalArgsFrame + // +- VsmApplyClosureFrame + // +- VsmDefContFrame + // +- VsmIfElseContFrame + // \- VsmSeqContFrame + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + // GlobalEnv + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + // LocalEnv + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + // Procedure + // \- Primitive_gco_2_gco_gco + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + // Closure + +// FacetRegistry::register_impl(); // if/when provided + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + + // RuntimeContext + // \- VsmRcx + + FacetRegistry::register_impl(); + + log && log(xtag("DVsmApplyFrame.tseq", typeseq::id())); + log && log(xtag("DVsmEvalArgsFrame.tseq", typeseq::id())); + log && log(xtag("DVsmApplyClosureFrame.tseq", typeseq::id())); + log && log(xtag("DVsmDefContFrame.tseq", typeseq::id())); + log && log(xtag("DVsmDefContFrame.tseq", typeseq::id())); + log && log(xtag("DVsmIfElseContFrame.tseq", typeseq::id())); + log && log(xtag("DVsmSeqContFrame.tseq", typeseq::id())); + log && log(xtag("DClosure.tseq", typeseq::id())); + log && log(xtag("DGlobalEnv.tseq", typeseq::id())); + log && log(xtag("DLocalEnv.tseq", typeseq::id())); + log && log(xtag("DVsmRcx.tseq", typeseq::id())); + + return true; + } + } /*namespace scm*/ +} /*namespace xo*/ + +/* end interpreter2_register_facets.cpp */ diff --git a/xo-interpreter2/src/interpreter2/interpreter2_register_types.cpp b/xo-interpreter2/src/interpreter2/interpreter2_register_types.cpp new file mode 100644 index 00000000..54351beb --- /dev/null +++ b/xo-interpreter2/src/interpreter2/interpreter2_register_types.cpp @@ -0,0 +1,36 @@ +/** @file interpreter2_register_types.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "interpreter2_register_types.hpp" + +#include "VsmApplyFrame.hpp" +#include "VsmEvalArgsFrame.hpp" + +#include + +namespace xo { + using xo::mm::ACollector; + using xo::mm::AGCObject; + using xo::facet::impl_for; + //using xo::facet::typeseq; + using xo::scope; + + namespace scm { + bool + interpreter2_register_types(obj gc) + { + scope log(XO_DEBUG(true)); + + bool ok = true; + + ok &= gc.install_type(impl_for()); + ok &= gc.install_type(impl_for()); + + return ok; + } + } +} /*namespace xo*/ + +/* end interpreter2_register_types.cpp */ diff --git a/xo-interpreter2/src/skrepl/CMakeLists.txt b/xo-interpreter2/src/skrepl/CMakeLists.txt new file mode 100644 index 00000000..b5511114 --- /dev/null +++ b/xo-interpreter2/src/skrepl/CMakeLists.txt @@ -0,0 +1,13 @@ +# xo-interpreter2/src/repl/CMakeLists.txt + +set(SELF_EXE skrepl) +set(SELF_SRCS skreplxx.cpp) + +xo_add_executable(${SELF_EXE} ${SELF_SRCS}) +xo_self_dependency(${SELF_EXE} xo_interpreter2) +xo_external_target_dependency(${SELF_EXE} replxx replxx::replxx) + +# replxx requires this +find_package(Threads REQUIRED) +target_link_libraries(${SELF_EXE} PUBLIC Threads::Threads) + diff --git a/xo-interpreter2/src/skrepl/skreplxx.cpp b/xo-interpreter2/src/skrepl/skreplxx.cpp new file mode 100644 index 00000000..df6be29d --- /dev/null +++ b/xo-interpreter2/src/skrepl/skreplxx.cpp @@ -0,0 +1,242 @@ +/** @file skreplxx.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include +#include +#include +#include +#include +#include + +namespace xo { + using xo::scm::VirtualSchematikaMachine; + using xo::scm::VsmResultExt; + using xo::mm::AAllocator; + using xo::mm::ArenaConfig; + using xo::mm::DArena; + using span_type = xo::mm::span; + using xo::facet::FacetRegistry; + using xo::facet::TypeRegistry; + using std::cerr; + + // presumeably replxx assumes input is a tty anyway? + // + bool replxx_getline(bool interactive, + bool is_at_toplevel, + replxx::Replxx & rx, + span_type * p_input + //const char ** p_input + ) + { + using namespace std; + + char const * prompt = ""; + + if (interactive) { + prompt = ((is_at_toplevel) ? "> " : ". "); + } + + const char * input_cstr = rx.input(prompt); + + bool retval = (input_cstr != nullptr); + + if (retval) + *p_input = span_type::from_cstr(input_cstr); + + if (input_cstr) + rx.history_add(input_cstr); + + return retval; + } + + void + welcome(std::ostream & os) + { + using namespace std; + + os << "schematika repl" << endl; + os << " ctrl-a/ctrl-e beginning/end of line" << endl; + os << " ctrl-u delete entire line" << endl; + os << " ctrl-k delete to end of line" << endl; + os << " meta- backward delete word" << endl; + os << " |meta-p previous command from history" << endl; + os << " |meta-n next command from history" << endl; + os << " / page through history faster" << endl; + os << " ctrl-s/ctrl-r forward/backward history search" << endl; + os << endl; + } + + struct ReplConfig { + ReplConfig() = default; + + std::size_t max_history_size_ = 1000; + std::string repl_history_fname_ = "skrepl_history.txt"; + bool debug_flag_ = false; + }; + + struct AppConfig { + using VsmConfig = xo::scm::VsmConfig; + + //using ReaderConfig = xo::scm::ReaderConfig; + //using X1CollectorConfig = xo::mm::X1CollectorConfig; + //using ArenaConfig = xo::mm::ArenaConfig; + + AppConfig(const ReplConfig & repl_cfg = ReplConfig(), + const ArenaConfig & app_arena_cfg = ArenaConfig().with_name("skreplxx").with_size(16 * 1024), + const VsmConfig & vsm_cfg = VsmConfig()) + : repl_config_{repl_cfg}, app_arena_config_{app_arena_cfg}, vsm_config_{vsm_cfg} + { + //rdr_config_.reader_debug_flag_ = true; + //rdr_config.parser_debug_flag_ = true; + //rdr_config.tk_debug_flag_ = true; + } + + ReplConfig repl_config_; + ArenaConfig app_arena_config_; + VsmConfig vsm_config_; + //ReaderConfig rdr_config_; + //X1CollectorConfig x1_config_ = (X1CollectorConfig().with_name("gc").with_size(4*1024*1024)); + //ArenaConfig fixed_config_ = (ArenaConfig().with_name("fixed").with_size(4*1024)); + }; + + struct App { + //using AAllocator = xo::mm::AAllocator; + //using DX1Collector = xo::mm::DX1Collector; + //using X1CollectorConfig = xo::mm::X1CollectorConfig; + //using DArena = xo::mm::DArena; + //using ArenaConfig = xo::mm::ArenaConfig; + using Replxx = replxx::Replxx; + using span_type = VirtualSchematikaMachine::span_type; + + App(const AppConfig & cfg = AppConfig()) + : repl_config_{cfg.repl_config_}, + app_arena_{cfg.app_arena_config_}, + vsm_{cfg.vsm_config_, obj(&app_arena_)} + { + this->interactive_ = isatty(STDIN_FILENO); + + rx_.set_max_history_size(repl_config_.max_history_size_); + rx_.history_load(repl_config_.repl_history_fname_); + // rx.bind_key_internal(Replxx::KEY::control('p'), "history_previous"); + // rx.bind_key_internal(Replxx::KEY::control('n'), "history_next"); + } + + /** borrows calling thread to run application **/ + void run(); + + private: + void _init(); + void _start(); + void _repl(); + bool _read_eval_print(span_type * p_input, bool eof); + + private: + InitEvidence init_evidence_ = 0; + ReplConfig repl_config_; + bool interactive_ = false; + Replxx rx_; + ///** collector/allocator for schematika expressions **/ + //DX1Collector x1_; + ///** e.g. for DArenaHashMap within global symtab **/ + //DArena fixed_; + + /** arena with same lifetime as this application **/ + DArena app_arena_; + /** schematika virtual machine **/ + VirtualSchematikaMachine vsm_; + }; + + void + App::run() + { + this->_init(); + this->_start(); + this->_repl(); + } + + void + App::_init() + { + // window to contorl size of registries ends as soon as we init other subsystems + TypeRegistry::instance(1024); + FacetRegistry::instance(1024); + + InitEvidence init_evidence_ = (InitSubsys::require()); + + Subsystem::initialize_all(); + } + + void + App::_start() + { + welcome(cerr); + + vsm_.begin_interactive_session(); + } + + void + App::_repl() + { + bool eof = false; + span_type input; + + // outer loop: fetch one line of interactive input + while (replxx_getline(interactive_, vsm_.is_at_toplevel(), rx_, &input)) { + + // inner lo9op: consume up to one expression at a time. + while (!input.empty() && this->_read_eval_print(&input, false /*eof*/)) + { + ; + } + + /* here: either: + * 1. input.empty() or + * 2. error encountered + */ + } + + /* reminder: eof can complete at most one token */ + this->_read_eval_print(&input, true /*eof*/); + } + + /** body of read-parse-print loop + * + * true -> no errors; + * false -> reader encountered error + **/ + bool + App::_read_eval_print(span_type * p_input, + bool eof) + { + scope log(XO_DEBUG(repl_config_.debug_flag_)); + + if (!p_input || p_input->empty()) + return true; + + VsmResultExt res = vsm_.read_eval_print(*p_input, eof); + + *p_input = res.remaining_; + + return !res.is_tk_error() && !res.is_eval_error(); + } + +} /*namespace xo*/ + +int +main (int argc, char * argv[]) +{ + using xo::AppConfig; + using xo::App; + + AppConfig cfg; + // [cmdline options here] + + App app(cfg); + + app.run(); +} /*main*/ + +/* end skreplxx.cpp */ + diff --git a/xo-interpreter2/utest/CMakeLists.txt b/xo-interpreter2/utest/CMakeLists.txt new file mode 100644 index 00000000..e45cffaa --- /dev/null +++ b/xo-interpreter2/utest/CMakeLists.txt @@ -0,0 +1,11 @@ +# build unittest xo-interpreter2/utest + +set(UTEST_EXE utest.interpreter2) +set(UTEST_SRCS + interpreter2_utest_main.cpp + VirtualSchematikaMachine.test.cpp +) + +xo_add_utest_executable(${UTEST_EXE} ${UTEST_SRCS}) +xo_self_dependency(${UTEST_EXE} xo_interpreter2) +xo_external_target_dependency(${UTEST_EXE} Catch2 Catch2::Catch2) diff --git a/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp b/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp new file mode 100644 index 00000000..77b3a30b --- /dev/null +++ b/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp @@ -0,0 +1,512 @@ +/** @file VirtualSchematikaMachine.test.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace xo { + using xo::scm::VirtualSchematikaMachine; + using xo::scm::VsmConfig; + using xo::scm::VsmResultExt; + using xo::scm::DClosure; + using xo::scm::DString; + using xo::scm::DUniqueString; // aks Symbol in lisp + using xo::scm::DFloat; + using xo::scm::DBoolean; + using xo::scm::DInteger; + using xo::scm::DRuntimeError; + using xo::mm::AGCObject; + using xo::mm::MemorySizeInfo; + using xo::mm::AAllocator; + using xo::mm::DArena; + using xo::mm::ArenaConfig; + using xo::facet::FacetRegistry; + using xo::facet::TypeRegistry; + using span_type = xo::scm::VirtualSchematikaMachine::span_type; + using Catch::Matchers::WithinAbs; + + using std::cout; + using std::endl; + + static InitEvidence s_init = (InitSubsys::require()); + + namespace ut { + struct ArenaShim { + explicit ArenaShim(const std::string & name, std::size_t size = 16*1024) + : arena_(ArenaConfig().with_name(name).with_size(size)) + { + } + + obj to_op() { return obj(&arena_); } + + DArena arena_; + }; + + struct VsmFixture { + explicit VsmFixture(const std::string & testname, + bool debug_flag, + const VsmConfig & cfg = VsmConfig()) + : aux_mm_{testname}, + vsm_{cfg.with_debug_flag(debug_flag), aux_mm_.to_op()} + {} + + bool log_memory_layout(scope * p_log) { + auto visitor = [p_log](const MemorySizeInfo & info) { + *p_log && (*p_log)(xtag("resource", info.resource_name_), + xtag("used", info.used_), + xtag("alloc", info.allocated_), + xtag("commit", info.committed_), + xtag("resv", info.reserved_)); + }; + + aux_mm_.arena_.visit_pools(visitor); + FacetRegistry::instance().visit_pools(visitor); + TypeRegistry::instance().visit_pools(visitor); + vsm_.visit_pools(visitor); + + return true; + } + + ArenaShim aux_mm_; + VirtualSchematikaMachine vsm_; + }; + + TEST_CASE("VirtualSchematikaMachine-ctor", "[interpreter2][VSM]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + VsmFixture vsm_fixture(testname, c_debug_flag); + + log && vsm_fixture.log_memory_layout(&log); + } + + TEST_CASE("VirtualSchematikaMachine-const1", "[interpreter2][VSM]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + VsmFixture vsm_fixture(testname, c_debug_flag); + + auto & vsm = vsm_fixture.vsm_; + + bool eof_flag = false; + + vsm.begin_interactive_session(); + VsmResultExt res = vsm.read_eval_print(span_type::from_cstr("3.141592635;"), eof_flag); + + REQUIRE(res.is_value()); + REQUIRE(res.value()); + + auto x = obj::from(*res.value()); + + REQUIRE(x); + REQUIRE_THAT(x.data()->value(), WithinAbs(3.141592635, 1e-6)); + + REQUIRE(res.remaining_.size() == 1); + REQUIRE(*res.remaining_.lo() == '\n'); + + log && vsm_fixture.log_memory_layout(&log); + } + + TEST_CASE("VirtualSchematikaMachine-const2", "[interpreter2][VSM]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + VsmFixture vsm_fixture(testname, c_debug_flag); + + auto & vsm = vsm_fixture.vsm_; + + bool eof_flag = false; + + vsm.begin_interactive_session(); + VsmResultExt res = vsm.read_eval_print(span_type::from_cstr("1011;"), eof_flag); + + REQUIRE(res.is_value()); + REQUIRE(res.value()); + + log && log(xtag("res.tseq", res.value()->_typeseq())); + + auto x = obj::from(*res.value()); + + REQUIRE(x); + REQUIRE(x.data()->value() == 1011); + + REQUIRE(res.remaining_.size() == 1); + REQUIRE(*res.remaining_.lo() == '\n'); + + log && vsm_fixture.log_memory_layout(&log); + } + + TEST_CASE("VirtualSchematikaMachine-arith1", "[interpreter2][VSM]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; + + bool eof_flag = false; + + vsm.begin_interactive_session(); + VsmResultExt res = vsm.read_eval_print(span_type::from_cstr("3.14159265 * 0.5;"), eof_flag); + + REQUIRE(res.is_value()); + REQUIRE(res.value()); + + log && log(xtag("res.tseq", res.value()->_typeseq())); + + auto x = obj::from(*res.value()); + + REQUIRE(x); + REQUIRE(x.data()->value() == 1.570796325); + + REQUIRE(res.remaining_.size() == 1); + REQUIRE(*res.remaining_.lo() == '\n'); + + log && vsm_fixture.log_memory_layout(&log); + } + + TEST_CASE("VirtualSchematikaMachine-cmp1", "[interpreter2][VSM]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; + + bool eof_flag = false; + + vsm.begin_interactive_session(); + VsmResultExt res + = vsm.read_eval_print(span_type::from_cstr("123 == 123;"), + eof_flag); + + REQUIRE(res.is_value()); + REQUIRE(res.value()); + + log && log(xtag("res.tseq", res.value()->_typeseq())); + + auto x = obj::from(*res.value()); + + REQUIRE(x); + REQUIRE(x.data()->value() == true); + + REQUIRE(res.remaining_.size() == 1); + REQUIRE(*res.remaining_.lo() == '\n'); + + log && vsm_fixture.log_memory_layout(&log); + } + + TEST_CASE("VirtualSchematikaMachine-if", "[interpreter2][VSM]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; + + bool eof_flag = false; + + vsm.begin_interactive_session(); + VsmResultExt res + = vsm.read_eval_print(span_type::from_cstr("if 123 == 123 then \"equal\" else \"notequal\";"), + eof_flag); + + REQUIRE(res.is_value()); + REQUIRE(res.value()); + + log && log(xtag("res.tseq", res.value()->_typeseq())); + + auto x = obj::from(*res.value()); + + REQUIRE(x); + REQUIRE(strcmp(x.data()->chars(), "equal") == 0); + + REQUIRE(res.remaining_.size() == 1); + REQUIRE(*res.remaining_.lo() == '\n'); + + log && vsm_fixture.log_memory_layout(&log); + } + + TEST_CASE("VirtualSchematikaMachine-lambda1", "[interpreter2][VSM]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; + + bool eof_flag = false; + + vsm.begin_interactive_session(); + VsmResultExt res + = vsm.read_eval_print(span_type::from_cstr("lambda (x : i64) -> i64 { x * x; }"), + eof_flag); + + REQUIRE(res.is_value()); + REQUIRE(res.value()); + + log && log(xtag("res.tseq", res.value()->_typeseq())); + + auto x = obj::from(*res.value()); + + REQUIRE(x); + //REQUIRE(x.data()->value() == 1.570796325); + + REQUIRE(res.remaining_.size() == 1); + REQUIRE(*res.remaining_.lo() == '\n'); + + log && vsm_fixture.log_memory_layout(&log); + } + + TEST_CASE("VirtualSchematikaMachine-apply2", "[interpreter2][VSM]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; + + bool eof_flag = false; + + vsm.begin_interactive_session(); + VsmResultExt res + = vsm.read_eval_print(span_type::from_cstr + ("(lambda (x : i64, y : i64) { x * y; })(13, 15);"), + eof_flag); + + REQUIRE(res.is_value()); + REQUIRE(res.value()); + + log && log(xtag("res.tseq", res.value()->_typeseq())); + + // currently get not-implemented error + auto x = obj::from(*res.value()); + + REQUIRE(x); + REQUIRE(x->value() == 195); + + //log && log("runtime-error", xtag("ex.src", x->src_function()), xtag("ex.descr", x->error_descr())); + + //REQUIRE(x.data()->value() == 1.570796325); + + REQUIRE(res.remaining_.size() == 1); + REQUIRE(*res.remaining_.lo() == '\n'); + + log && vsm_fixture.log_memory_layout(&log); + } + + TEST_CASE("VirtualSchematikaMachine-def1", "[interpreter2][VSM]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; + + bool eof_flag = false; + + vsm.begin_interactive_session(); + VsmResultExt res + = vsm.read_eval_print(span_type::from_cstr("def foo = 3.14159;"), + eof_flag); + + REQUIRE(res.is_value()); + REQUIRE(res.value()); + + log && log(xtag("res.tseq", res.value()->_typeseq()), + xtag("res.type", TypeRegistry::id2name(res.value()->_typeseq()))); + + // currently get not-implemented error + auto x = obj::from(*res.value()); + + REQUIRE(x); + REQUIRE(strcmp(x->chars(), "foo") == 0); + + //log && log("runtime-error", xtag("ex.src", x->src_function()), xtag("ex.descr", x->error_descr())); + + //REQUIRE(x.data()->value() == 1.570796325); + + REQUIRE(res.remaining_.size() == 1); + REQUIRE(*res.remaining_.lo() == '\n'); + + log && vsm_fixture.log_memory_layout(&log); + } + + TEST_CASE("VirtualSchematikaMachine-def2", "[interpreter2][VSM]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; + + bool eof_flag = false; + + vsm.begin_interactive_session(); + + span_type input = span_type::from_cstr("def foo = 3.14159; foo;"); + + for (int i_expr = 0; i_expr < 2; ++i_expr) { + log && log(xtag("input", input)); + + VsmResultExt res + = vsm.read_eval_print(input, eof_flag); + + REQUIRE(res.is_value()); + REQUIRE(res.value()); + + log && log(xtag("res.tseq", res.value()->_typeseq()), + xtag("res.type", TypeRegistry::id2name(res.value()->_typeseq()))); + + if (i_expr == 0) { + auto x = obj::from(*res.value()); + REQUIRE(x); + REQUIRE(strcmp(x->chars(), "foo") == 0); + + REQUIRE(res.remaining_.size() > 1); + + input = res.remaining_; + } else if (i_expr == 1) { + auto x = obj::from(*res.value()); + REQUIRE(x); + REQUIRE_THAT(x->value(), WithinAbs(3.14159, 1e-6)); + + REQUIRE(res.remaining_.size() == 1); + REQUIRE(*res.remaining_.lo() == '\n'); + input = res.remaining_; + } + } + + log && vsm_fixture.log_memory_layout(&log); + + } + + TEST_CASE("VirtualSchematikaMachine-def3", "[interpreter2][VSM]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; + + bool eof_flag = true; + + vsm.begin_interactive_session(); + + span_type input = span_type::from_cstr("def fact = lambda (n) { if (n == 0) then 1 else n * fact(n - 1) };"); + + for (int i_expr = 0; i_expr < 1; ++i_expr) { + log && log(xtag("input", input)); + + VsmResultExt res + = vsm.read_eval_print(input, eof_flag); + + REQUIRE(res.is_value()); + REQUIRE(res.value()); + + log && log(xtag("res.tseq", res.value()->_typeseq()), + xtag("res.type", TypeRegistry::id2name(res.value()->_typeseq()))); + + if (i_expr == 0) { + auto x = obj::from(*res.value()); + REQUIRE(x); + REQUIRE(strcmp(x->chars(), "fact") == 0); + + REQUIRE(res.remaining_.size() == 1); + REQUIRE(*res.remaining_.lo() == '\n'); + input = res.remaining_; + } + } + + log && vsm_fixture.log_memory_layout(&log); + } + + TEST_CASE("VirtualSchematikaMachine-fact0", "[interpreter2][VSM]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; + + bool eof_flag = true; + + vsm.begin_interactive_session(); + + span_type input = span_type::from_cstr("def fact = lambda (n) { if (n == 0) then 1 else n * fact(n - 1) }; fact(4);"); + + for (int i_expr = 0; i_expr < 2; ++i_expr) { + log && log(xtag("input", input)); + + VsmResultExt res + = vsm.read_eval_print(input, eof_flag); + + REQUIRE(res.is_value()); + REQUIRE(res.value()); + + log && log(xtag("res.tseq", res.value()->_typeseq()), + xtag("res.type", TypeRegistry::id2name(res.value()->_typeseq()))); + + if (i_expr == 0) { + auto x = obj::from(*res.value()); + REQUIRE(x); + REQUIRE(strcmp(x->chars(), "fact") == 0); + input = res.remaining_; + } else if (i_expr == 1) { + auto x = obj::from(*res.value()); + REQUIRE(x); + REQUIRE(x->value() == 24); + + REQUIRE(res.remaining_.size() == 1); + REQUIRE(*res.remaining_.lo() == '\n'); + input = res.remaining_; + } + } + + log && vsm_fixture.log_memory_layout(&log); + } + + } /*namespace ut*/ +} /*namespace xo*/ + +/* end SchematikaParser.test.cpp */ diff --git a/xo-interpreter2/utest/interpreter2_utest_main.cpp b/xo-interpreter2/utest/interpreter2_utest_main.cpp new file mode 100644 index 00000000..ca898beb --- /dev/null +++ b/xo-interpreter2/utest/interpreter2_utest_main.cpp @@ -0,0 +1,32 @@ +/** @file interpreter2_utest_main.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include +#include + +#define CATCH_CONFIG_RUNNER +#include "catch2/catch.hpp" + +int +main(int argc, char* argv[]) +{ + using xo::facet::FacetRegistry; + using xo::Subsystem; + + // initialize facet registry + FacetRegistry::instance(1024); + + // initialize subsystems + Subsystem::initialize_all(); + + // Run Catch2's test session + int result = Catch::Session().run(argc, argv); + + // cleanup here, if any + + return result; +} + +/* end interpreter2_utest_main.cpp */ diff --git a/xo-object/include/xo/object/ObjectConversion.hpp b/xo-object/include/xo/object/ObjectConversion.hpp index def83545..38b11a7d 100644 --- a/xo-object/include/xo/object/ObjectConversion.hpp +++ b/xo-object/include/xo/object/ObjectConversion.hpp @@ -24,7 +24,7 @@ namespace xo { * ObjectConversion * in object/Integer.hpp **/ - } -} + } /*namespace obj*/ +} /*namespace xo*/ /* end ObjectConversion.hpp */ diff --git a/xo-object/include/xo/object/ObjectConverter.hpp b/xo-object/include/xo/object/ObjectConverter.hpp index a4b337fd..a7dd6a9b 100644 --- a/xo-object/include/xo/object/ObjectConverter.hpp +++ b/xo-object/include/xo/object/ObjectConverter.hpp @@ -13,7 +13,7 @@ namespace xo { namespace obj { /* Convert between xo::reflect::TaggedPtr and xo::Object for - * a particular wrapped c++ type + * a particular wrapped c++ type. */ struct Converter { using TaggedPtr = xo::reflect::TaggedPtr; @@ -22,7 +22,9 @@ namespace xo { public: Converter() = default; - explicit Converter(ConvertToObjectFn to, ConvertFromObjectFn from) : cvt_to_object_{to}, cvt_from_object_{from} {} + explicit Converter(ConvertToObjectFn to, + ConvertFromObjectFn from) + : cvt_to_object_{to}, cvt_from_object_{from} {} /** convert tagged pointer @p tp to new object, * allocated via @p mm. @@ -58,6 +60,9 @@ namespace xo { * // cvt is a converter for T instances * gp obj = (*(cvt->cvt_to_object_))(mm, * @endcode + * + * ObjectConverter converts at run-time + * @see ObjectConversion for compile-time conversion **/ class ObjectConverter { public: diff --git a/xo-object/src/object/ObjectConverter.cpp b/xo-object/src/object/ObjectConverter.cpp index 8ec4c620..a7d0ed4d 100644 --- a/xo-object/src/object/ObjectConverter.cpp +++ b/xo-object/src/object/ObjectConverter.cpp @@ -150,14 +150,19 @@ namespace xo { ObjectConverter::ObjectConverter() { - this->establish_conversion(&int_to_object, &object_to_int); - this->establish_conversion(&int_to_object, &object_to_int); + this->establish_conversion(&int_to_object, + &object_to_int); + this->establish_conversion(&int_to_object, + &object_to_int); - this->establish_conversion(&float_to_object, &object_to_float); + this->establish_conversion(&float_to_object, + &object_to_float); - this->establish_conversion(&bool_to_object, &object_to_bool); + this->establish_conversion(&bool_to_object, + &object_to_bool); - this->establish_conversion(&string_to_object, &object_to_string); + this->establish_conversion(&string_to_object, + &object_to_string); } gp @@ -172,9 +177,10 @@ namespace xo { return (cvt->cvt_to_object_)(mm, x_tp); } else { if (throw_flag) { - throw std::runtime_error(tostr("no to-object-converter available for instance of type", - xtag("id", x_tp.td()->id()), - xtag("name", x_tp.td()->short_name()))); + throw std::runtime_error + (tostr("no to-object-converter available for instance of type", + xtag("id", x_tp.td()->id()), + xtag("name", x_tp.td()->short_name()))); } return nullptr; diff --git a/xo-object2/CMakeLists.txt b/xo-object2/CMakeLists.txt index c7962ed7..4b0962de 100644 --- a/xo-object2/CMakeLists.txt +++ b/xo-object2/CMakeLists.txt @@ -23,11 +23,10 @@ xo_add_genfacet( TARGET xo-object2-facet-sequence FACET Sequence INPUT idl/Sequence.json5 - OUTPUT_HPP_DIR include/xo/object2 - OUTPUT_IMPL_SUBDIR sequence - OUTPUT_CPP_DIR src/object2 ) +# ---------------------------------------------------------------- + # note: manual target; generated code committed to git xo_add_genfacetimpl( TARGET xo-object2-facetimpl-sequence-list @@ -35,9 +34,6 @@ xo_add_genfacetimpl( FACET Sequence REPR List INPUT idl/ISequence_DList.json5 - OUTPUT_HPP_DIR include/xo/object2 - OUTPUT_IMPL_SUBDIR list - OUTPUT_CPP_DIR src/object2 ) # note: manual target; generated code committed to git @@ -47,9 +43,6 @@ xo_add_genfacetimpl( FACET Printable REPR List INPUT idl/IPrintable_DList.json5 - OUTPUT_HPP_DIR include/xo/object2 - OUTPUT_IMPL_SUBDIR list - OUTPUT_CPP_DIR src/object2 ) # note: manual target; generated code committed to git @@ -59,11 +52,30 @@ xo_add_genfacetimpl( FACET GCObject REPR List INPUT idl/IGCObject_DList.json5 - OUTPUT_HPP_DIR include/xo/object2 - OUTPUT_IMPL_SUBDIR list - OUTPUT_CPP_DIR src/object2 ) +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-object2-facetimpl-printable-boolean + FACET_PKG xo_printable2 + FACET Printable + REPR Boolean + INPUT idl/IPrintable_DBoolean.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-object2-facetimpl-gcobject-boolean + FACET_PKG xo_gc + FACET GCObject + REPR Boolean + INPUT idl/IGCObject_DBoolean.json5 +) + +# ---------------------------------------------------------------- + # note: manual target; generated code committed to git xo_add_genfacetimpl( TARGET xo-object2-facetimpl-printable-float @@ -71,9 +83,6 @@ xo_add_genfacetimpl( FACET Printable REPR Float INPUT idl/IPrintable_DFloat.json5 - OUTPUT_HPP_DIR include/xo/object2 - OUTPUT_IMPL_SUBDIR number - OUTPUT_CPP_DIR src/object2 ) # note: manual target; generated code committed to git @@ -83,11 +92,10 @@ xo_add_genfacetimpl( FACET GCObject REPR Float INPUT idl/IGCObject_DFloat.json5 - OUTPUT_HPP_DIR include/xo/object2 - OUTPUT_IMPL_SUBDIR number - OUTPUT_CPP_DIR src/object2 ) +# ---------------------------------------------------------------- + # note: manual target; generated code committed to git xo_add_genfacetimpl( TARGET xo-object2-facetimpl-printable-integer @@ -95,9 +103,6 @@ xo_add_genfacetimpl( FACET Printable REPR Integer INPUT idl/IPrintable_DInteger.json5 - OUTPUT_HPP_DIR include/xo/object2 - OUTPUT_IMPL_SUBDIR number - OUTPUT_CPP_DIR src/object2 ) # note: manual target; generated code committed to git @@ -107,11 +112,10 @@ xo_add_genfacetimpl( FACET GCObject REPR Integer INPUT idl/IGCObject_DInteger.json5 - OUTPUT_HPP_DIR include/xo/object2 - OUTPUT_IMPL_SUBDIR number - OUTPUT_CPP_DIR src/object2 ) +# ---------------------------------------------------------------- + # note: manual target; generated code committed to git xo_add_genfacetimpl( TARGET xo-object2-facetimpl-printable-string @@ -119,9 +123,6 @@ xo_add_genfacetimpl( FACET Printable REPR String INPUT idl/IPrintable_DString.json5 - OUTPUT_HPP_DIR include/xo/object2/string - OUTPUT_IMPL_SUBDIR . - OUTPUT_CPP_DIR src/object2 ) # note: manual target; generated code committed to git @@ -131,11 +132,10 @@ xo_add_genfacetimpl( FACET GCObject REPR String INPUT idl/IGCObject_DString.json5 - OUTPUT_HPP_DIR include/xo/object2/string - OUTPUT_IMPL_SUBDIR . - OUTPUT_CPP_DIR src/object2 ) +# ---------------------------------------------------------------- + # note: manual target; generated code committed to git xo_add_genfacetimpl( TARGET xo-object2-facetimpl-sequence-array @@ -143,9 +143,15 @@ xo_add_genfacetimpl( FACET Sequence REPR Array INPUT idl/ISequence_DArray.json5 - OUTPUT_HPP_DIR include/xo/object2 - OUTPUT_IMPL_SUBDIR array - OUTPUT_CPP_DIR src/object2 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-object2-facetimpl-printable-array + FACET_PKG xo_printable2 + FACET Printable + REPR Array + INPUT idl/IPrintable_DArray.json5 ) # note: manual target; generated code committed to git @@ -155,13 +161,34 @@ xo_add_genfacetimpl( FACET GCObject REPR Array INPUT idl/IGCObject_DArray.json5 - OUTPUT_HPP_DIR include/xo/object2 - OUTPUT_IMPL_SUBDIR array - OUTPUT_CPP_DIR src/object2 ) # ---------------------------------------------------------------- +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-object2-facetimpl-printable-runtimeerror + FACET_PKG xo_printable2 + FACET Printable + REPR RuntimeError + INPUT idl/IPrintable_DRuntimeError.json5 + ) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-object2-facetimpl-gcobject-runtimeerror + FACET_PKG xo_gc + FACET GCObject + REPR RuntimeError + INPUT idl/IGCObject_DRuntimeError.json5 +) + +# ---------------------------------------------------------------- + +xo_add_genfacet_all(xo-object2-genfacet-all) + +# ---------------------------------------------------------------- + # must complete definition of expression lib before configuring examples add_subdirectory(src/object2) add_subdirectory(utest) diff --git a/xo-object2/cmake/xo_object2Config.cmake.in b/xo-object2/cmake/xo_object2Config.cmake.in index 36d3bb62..6773adb7 100644 --- a/xo-object2/cmake/xo_object2Config.cmake.in +++ b/xo-object2/cmake/xo_object2Config.cmake.in @@ -1,6 +1,7 @@ @PACKAGE_INIT@ include(CMakeFindDependencyMacro) +find_dependency(reflect) find_dependency(xo_gc) find_dependency(xo_printable2) find_dependency(subsys) diff --git a/xo-object2/doc/glossary.rst b/xo-object2/doc/glossary.rst new file mode 100644 index 00000000..4cabbbd5 --- /dev/null +++ b/xo-object2/doc/glossary.rst @@ -0,0 +1 @@ +gco = gc-aware object diff --git a/xo-object2/idl/IGCObject_DArray.json5 b/xo-object2/idl/IGCObject_DArray.json5 index e8aeed3b..bef5bd62 100644 --- a/xo-object2/idl/IGCObject_DArray.json5 +++ b/xo-object2/idl/IGCObject_DArray.json5 @@ -1,5 +1,8 @@ { mode: "implementation", + output_cpp_dir: "src/object2", + output_hpp_dir: "include/xo/object2", + output_impl_subdir: "array", includes: [ "", "" diff --git a/xo-object2/idl/IGCObject_DBoolean.json5 b/xo-object2/idl/IGCObject_DBoolean.json5 new file mode 100644 index 00000000..c9aaf26b --- /dev/null +++ b/xo-object2/idl/IGCObject_DBoolean.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/object2", + output_hpp_dir: "include/xo/object2", + output_impl_subdir: "boolean", + includes: [ + "", + "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DBoolean", + using_doxygen: true, + repr: "DBoolean", + doc: [ "implement AGCObject for DBoolean" ], +} diff --git a/xo-object2/idl/IGCObject_DFloat.json5 b/xo-object2/idl/IGCObject_DFloat.json5 index 6120808b..eec1e3e3 100644 --- a/xo-object2/idl/IGCObject_DFloat.json5 +++ b/xo-object2/idl/IGCObject_DFloat.json5 @@ -1,6 +1,10 @@ { mode: "implementation", + output_cpp_dir: "src/object2", + output_hpp_dir: "include/xo/object2", + output_impl_subdir: "number", includes: [ + "", "", "" ], diff --git a/xo-object2/idl/IGCObject_DInteger.json5 b/xo-object2/idl/IGCObject_DInteger.json5 index 65f24371..37d603e5 100644 --- a/xo-object2/idl/IGCObject_DInteger.json5 +++ b/xo-object2/idl/IGCObject_DInteger.json5 @@ -1,5 +1,8 @@ { mode: "implementation", + output_cpp_dir: "src/object2", + output_hpp_dir: "include/xo/object2", + output_impl_subdir: "number", includes: [ "", "" diff --git a/xo-object2/idl/IGCObject_DList.json5 b/xo-object2/idl/IGCObject_DList.json5 index 342fc299..28fb3352 100644 --- a/xo-object2/idl/IGCObject_DList.json5 +++ b/xo-object2/idl/IGCObject_DList.json5 @@ -1,5 +1,8 @@ { mode: "implementation", + output_cpp_dir: "src/object2", + output_hpp_dir: "include/xo/object2", + output_impl_subdir: "list", includes: [ // "", // "" diff --git a/xo-object2/idl/IGCObject_DRuntimeError.json5 b/xo-object2/idl/IGCObject_DRuntimeError.json5 new file mode 100644 index 00000000..cfcbe9f6 --- /dev/null +++ b/xo-object2/idl/IGCObject_DRuntimeError.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/object2", + output_hpp_dir: "include/xo/object2", + output_impl_subdir: "error", + includes: [ +// "", +// "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCObject interface for DRuntimeError", + using_doxygen: true, + repr: "DRuntimeError", + doc: [ "implement AGCObject for DRuntimeError" ], +} diff --git a/xo-object2/idl/IGCObject_DString.json5 b/xo-object2/idl/IGCObject_DString.json5 index 8d0e14e0..caf33fae 100644 --- a/xo-object2/idl/IGCObject_DString.json5 +++ b/xo-object2/idl/IGCObject_DString.json5 @@ -1,5 +1,8 @@ { mode: "implementation", + output_cpp_dir: "src/object2", + output_hpp_dir: "include/xo/object2", + output_impl_subdir: "string", includes: [ "", "" diff --git a/xo-object2/idl/IPrintable_DArray.json5 b/xo-object2/idl/IPrintable_DArray.json5 new file mode 100644 index 00000000..b9bde4f4 --- /dev/null +++ b/xo-object2/idl/IPrintable_DArray.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/object2", + output_hpp_dir: "include/xo/object2", + output_impl_subdir: "array", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DArray", + using_doxygen: true, + repr: "DArray", + doc: [ "implement APrintable for DArray" ], +} diff --git a/xo-object2/idl/IPrintable_DBoolean.json5 b/xo-object2/idl/IPrintable_DBoolean.json5 new file mode 100644 index 00000000..db949258 --- /dev/null +++ b/xo-object2/idl/IPrintable_DBoolean.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/object2", + output_hpp_dir: "include/xo/object2", + output_impl_subdir: "boolean", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DBoolean", + using_doxygen: true, + repr: "DBoolean", + doc: [ "implement APrintable for DBoolean" ], +} diff --git a/xo-object2/idl/IPrintable_DFloat.json5 b/xo-object2/idl/IPrintable_DFloat.json5 index 7351c1b2..d28680f0 100644 --- a/xo-object2/idl/IPrintable_DFloat.json5 +++ b/xo-object2/idl/IPrintable_DFloat.json5 @@ -1,5 +1,8 @@ { mode: "implementation", + output_cpp_dir: "src/object2", + output_hpp_dir: "include/xo/object2", + output_impl_subdir: "number", includes: [ "", "" ], local_types: [ ], diff --git a/xo-object2/idl/IPrintable_DInteger.json5 b/xo-object2/idl/IPrintable_DInteger.json5 index 1a2e5490..478da579 100644 --- a/xo-object2/idl/IPrintable_DInteger.json5 +++ b/xo-object2/idl/IPrintable_DInteger.json5 @@ -1,5 +1,8 @@ { mode: "implementation", + output_cpp_dir: "src/object2", + output_hpp_dir: "include/xo/object2", + output_impl_subdir: "number", includes: [ "", "" ], local_types: [ ], diff --git a/xo-object2/idl/IPrintable_DList.json5 b/xo-object2/idl/IPrintable_DList.json5 index 640d7d1d..a7a6bfb6 100644 --- a/xo-object2/idl/IPrintable_DList.json5 +++ b/xo-object2/idl/IPrintable_DList.json5 @@ -1,5 +1,8 @@ { mode: "implementation", + output_cpp_dir: "src/object2", + output_hpp_dir: "include/xo/object2", + output_impl_subdir: "list", includes: [ "", "" ], local_types: [ ], diff --git a/xo-object2/idl/IPrintable_DRuntimeError.json5 b/xo-object2/idl/IPrintable_DRuntimeError.json5 new file mode 100644 index 00000000..a8404925 --- /dev/null +++ b/xo-object2/idl/IPrintable_DRuntimeError.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/object2", + output_hpp_dir: "include/xo/object2", + output_impl_subdir: "error", + includes: [ "", + "" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DRuntimeError", + using_doxygen: true, + repr: "DRuntimeError", + doc: [ "implement APrintable for DRuntimeError" ], +} diff --git a/xo-object2/idl/IPrintable_DString.json5 b/xo-object2/idl/IPrintable_DString.json5 index f032ca46..8510938b 100644 --- a/xo-object2/idl/IPrintable_DString.json5 +++ b/xo-object2/idl/IPrintable_DString.json5 @@ -1,5 +1,8 @@ { mode: "implementation", + output_cpp_dir: "src/object2", + output_hpp_dir: "include/xo/object2", + output_impl_subdir: "string", includes: [ "", "" ], local_types: [ ], diff --git a/xo-object2/idl/ISequence_DArray.json5 b/xo-object2/idl/ISequence_DArray.json5 index 198410da..265c3795 100644 --- a/xo-object2/idl/ISequence_DArray.json5 +++ b/xo-object2/idl/ISequence_DArray.json5 @@ -1,5 +1,8 @@ { mode: "implementation", + output_cpp_dir: "src/object2", + output_hpp_dir: "include/xo/object2", + output_impl_subdir: "array", includes: [ ], local_types: [ ], namespace1: "xo", diff --git a/xo-object2/idl/ISequence_DList.json5 b/xo-object2/idl/ISequence_DList.json5 index 677285da..2ff69f04 100644 --- a/xo-object2/idl/ISequence_DList.json5 +++ b/xo-object2/idl/ISequence_DList.json5 @@ -1,5 +1,8 @@ { mode: "implementation", + output_cpp_dir: "src/object2", + output_hpp_dir: "include/xo/object2", + output_impl_subdir: "list", includes: [ "" ], local_types: [ ], namespace1: "xo", diff --git a/xo-object2/idl/Sequence.json5 b/xo-object2/idl/Sequence.json5 index 9ceda9ea..20271697 100644 --- a/xo-object2/idl/Sequence.json5 +++ b/xo-object2/idl/Sequence.json5 @@ -1,5 +1,8 @@ { mode: "facet", + output_cpp_dir: "src/object2", + output_hpp_dir: "include/xo/object2", + output_impl_subdir: "sequence", includes: [""], // extra includes in Sequence.hpp, if any user_hpp_includes: [], @@ -67,4 +70,5 @@ ], nonconst_methods: [ ], + router_facet_explicit_content: [] } diff --git a/xo-object2/include/xo/object2/Array.hpp b/xo-object2/include/xo/object2/Array.hpp new file mode 100644 index 00000000..12c6eaa5 --- /dev/null +++ b/xo-object2/include/xo/object2/Array.hpp @@ -0,0 +1,14 @@ +/** @file Array.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DArray.hpp" +#include "array/ISequence_DArray.hpp" +#include "array/IGCObject_DArray.hpp" +#include "array/IPrintable_DArray.hpp" + + +/* end Array.hpp */ diff --git a/xo-object2/include/xo/object2/Boolean.hpp b/xo-object2/include/xo/object2/Boolean.hpp new file mode 100644 index 00000000..a246ffc0 --- /dev/null +++ b/xo-object2/include/xo/object2/Boolean.hpp @@ -0,0 +1,12 @@ +/** @file Boolean.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DBoolean.hpp" +#include "boolean/IGCObject_DBoolean.hpp" +#include "boolean/IPrintable_DBoolean.hpp" + +/* end Boolean.hpp */ diff --git a/xo-object2/include/xo/object2/DArray.hpp b/xo-object2/include/xo/object2/DArray.hpp index 0dc13cd1..8d7248e5 100644 --- a/xo-object2/include/xo/object2/DArray.hpp +++ b/xo-object2/include/xo/object2/DArray.hpp @@ -23,7 +23,7 @@ namespace xo { * fixed at construction time, but not part of type. * Can reallocate to change **/ - struct DArray { + class DArray { public: /** @defgroup darray-types type traits **/ ///@{ @@ -58,6 +58,13 @@ namespace xo { static DArray * empty(obj mm, size_type cap); + /** create copy of @p src using memory from @p mm + * with capacity for @p new_cap elements + **/ + static DArray * copy(obj mm, + DArray * src, + size_type new_cap); + /** create array containing elements @p args, using memory from @p mm. * Nullptr if space exhausted. * @@ -81,6 +88,10 @@ namespace xo { size_type size() const noexcept { return size_; } /** return element @p index of this array (0-based) **/ obj at(size_type index) const; + + const obj & operator[](size_type index) const noexcept { return elts_[index]; } + obj & operator[](size_type index) noexcept { return elts_[index]; } + ///@} /** @defgroup darray-iterators iterators **/ ///@{ @@ -96,6 +107,11 @@ namespace xo { /** @defgroup darray-general general methods **/ ///@{ + /** resize to @p new_size. @p new_size may not be larger than capacity + * Return true if resize was accomplished; false otherwise. + **/ + bool resize(size_type new_size) noexcept; + ///@} /** @defgroup darray-conversion-operators conversion operators **/ ///@{ @@ -108,6 +124,9 @@ namespace xo { /** @defgroup darray-printable-methods **/ ///@{ + /** pretty-printing support **/ + bool pretty(const ppindentinfo & ppii) const; + ///@} /** @defgroup darray-gcobject-methods **/ ///@{ diff --git a/xo-object2/include/xo/object2/DBoolean.hpp b/xo-object2/include/xo/object2/DBoolean.hpp new file mode 100644 index 00000000..69dd1c16 --- /dev/null +++ b/xo-object2/include/xo/object2/DBoolean.hpp @@ -0,0 +1,57 @@ +/** @file DBoolean.hpp + * + * @author Roland Conybeare, Dec 2025 + **/ + +#pragma once + +#include +#include +#include +#include +#include + +namespace xo { + namespace scm { + struct DBoolean { + using AAllocator = xo::mm::AAllocator; + using ACollector = xo::mm::ACollector; + using ppindentinfo = xo::print::ppindentinfo; + using value_type = long; + + explicit DBoolean(bool x) : value_{x} {} + + /** will likely want this to default to ANumeric, once we have it **/ + template + static obj box(obj mm, bool x); + + /** allocate boxed value @p x using memory from @p mm **/ + static DBoolean * _box(obj mm, bool x); + + bool value() const noexcept { return value_; } + + bool pretty(const ppindentinfo & ppii) const; + + operator bool() const noexcept { return value_; } + + // GCObject facet + + std::size_t shallow_size() const noexcept; + DBoolean * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + private: + /** boxed boolean value **/ + bool value_ = false; + }; + + template + obj + DBoolean::box(obj mm, bool x) { + return obj(_box(mm, x)); + } + + } /*nmaespace obj*/ +} /*namespace xo*/ + +/* end DBoolean.hpp */ diff --git a/xo-object2/include/xo/object2/DInteger.hpp b/xo-object2/include/xo/object2/DInteger.hpp index c56a4be1..b03693be 100644 --- a/xo-object2/include/xo/object2/DInteger.hpp +++ b/xo-object2/include/xo/object2/DInteger.hpp @@ -28,7 +28,7 @@ namespace xo { /** allocate boxed value @p x using memory from @p mm **/ static DInteger * _box(obj mm, long x); - double value() const noexcept { return value_; } + long value() const noexcept { return value_; } bool pretty(const ppindentinfo & ppii) const; diff --git a/xo-object2/include/xo/object2/DRuntimeError.hpp b/xo-object2/include/xo/object2/DRuntimeError.hpp new file mode 100644 index 00000000..c59de59d --- /dev/null +++ b/xo-object2/include/xo/object2/DRuntimeError.hpp @@ -0,0 +1,71 @@ +/** @file DRuntimeError.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "String.hpp" +#include +#include + +namespace xo { + namespace scm { + + /** @brief representation for runtime errors + **/ + class DRuntimeError { + public: + using AGCObject = xo::mm::AGCObject; + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using ppindentinfo = xo::print::ppindentinfo; + + public: + /** convenience shortcut.**/ + static obj make(obj mm, + const char * src_fn, + const char * error_descr); + + /** create instance using memory from allocator @p mm + * @p src_fn identifies the (c++) function/method in which + * error detercted. + * @p error_descr contains human-readable error message; + * will be copied by this function. + **/ + static DRuntimeError * _make(obj mm, + DString * src_fn, + DString * error_descr); + + DString * src_function() const noexcept { return src_function_; } + DString * error_descr() const noexcept { return error_descr_; } + + /** @defgroup scm-runtimeerror-printable-facet printable facet **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + /** @defgroup scm-runtimeerror-gcobject-facet gcobject facet **/ + ///@{ + + std::size_t shallow_size() const noexcept; + DRuntimeError * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + + ///@} + + private: + DRuntimeError(DString * src_fn, DString * error_descr); + + private: + /** source location at which error identified **/ + DString * src_function_ = nullptr; + /** error description (allocated from ErrorArena) **/ + DString * error_descr_ = nullptr; + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DRuntimeError.hpp */ diff --git a/xo-object2/include/xo/object2/DString.hpp b/xo-object2/include/xo/object2/DString.hpp index f35fe44f..a6cedb00 100644 --- a/xo-object2/include/xo/object2/DString.hpp +++ b/xo-object2/include/xo/object2/DString.hpp @@ -78,6 +78,12 @@ namespace xo { static DString * from_view(obj mm, std::string_view sv); + /** create string containing a copy @p str. + * Use memory from allocator @p mm. + **/ + static DString * from_str(obj mm, + const std::string & str); + /** create string containing a copy of @p sv. * Use memory from allocator @p mm via sub_alloc. * (load-bearing for StringTable) @@ -279,6 +285,15 @@ namespace xo { ///@} }; + inline std::ostream & operator<<(std::ostream & os, const DString * x) { + if (x) { + os << std::string_view(*x); + } else { + os << "nullptr"; + } + return os; + } + inline bool operator==(const DString & lhs, const DString & rhs) { return DString::compare(lhs, rhs) == 0; } diff --git a/xo-object2/include/xo/object2/Float.hpp b/xo-object2/include/xo/object2/Float.hpp new file mode 100644 index 00000000..94751ecf --- /dev/null +++ b/xo-object2/include/xo/object2/Float.hpp @@ -0,0 +1,12 @@ +/** @file Float.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DFloat.hpp" +#include "number/IGCObject_DFloat.hpp" +#include "number/IPrintable_DFloat.hpp" + +/* end Float.hpp */ diff --git a/xo-object2/include/xo/object2/GCObjectConverter.hpp b/xo-object2/include/xo/object2/GCObjectConverter.hpp new file mode 100644 index 00000000..bf244f48 --- /dev/null +++ b/xo-object2/include/xo/object2/GCObjectConverter.hpp @@ -0,0 +1,158 @@ +/** @file GCObjectConverter.hpp + * + * @author Roland Conybeare, Nov 2025 + **/ + +#pragma once + +#include +#include +#include +//#include "xo/reflect/TaggedPtr.hpp" +#include + +namespace xo { + namespace scm { + /* Convert between xo::reflect::TaggedPtr and xo::Object for + * a particular wrapped c++ type + */ + struct Converter { + using AAllocator = xo::mm::AAllocator; + using AGCObject = xo::mm::AGCObject; + using TaggedPtr = xo::reflect::TaggedPtr; + /** convert from some reflected T* @p src to + * obj dest + * using memory from allocator @p mm + **/ + using ConvertToObjectFn = obj (*)(obj mm, + TaggedPtr src); + /** convert from obj @p src to some refected T* @p dest + * using memory from allocator @p mm. + * + * NOTE: obj is gc-aware -> will likely reside in + * a collected memory region. + **/ + using ConvertFromObjectFn = TaggedPtr (*)(obj mm, + obj obj); + + public: + Converter() = default; + explicit Converter(ConvertToObjectFn to, + ConvertFromObjectFn from) + : cvt_to_object_{to}, + cvt_from_object_{from} + {} + + /** convert tagged pointer @p tp to new object, + * allocated via @p mm. + * + * Conversion will typically be for some specific type; + * see @ref ObjectConverter + **/ + ConvertToObjectFn cvt_to_object_ = nullptr; + + /** convert object to tagged pointer @p, + * allocated via @p mm. + * + * Conversion will typically be for some specific type; + * see @ref ObjectConverter + **/ + ConvertFromObjectFn cvt_from_object_ = nullptr; + }; + + /** @class ObjectConverter + * @brief Conversion to/from Object + * + * For some instance of type T: + * + * @code + * ObjectConverter & converters = ...; + * T x = ...; + * TaggedPtr tp = Reflect::make_tp(&x); + * TypeId tid = tp.td()->id(); + * + * const Converter * cvt = converters.cvt_.lookup(tid); + * + * if (cvt) { + * // cvt is a converter for T instances + * gp obj = (*(cvt->cvt_to_object_))(mm, + * @endcode + **/ + class ObjectConverter { + public: + using AAllocator = xo::mm::AAllocator; + using AGCObject = xo::mm::AGCObject; + using Reflect = xo::reflect::Reflect; + using TaggedPtr = xo::reflect::TaggedPtr; + using TypeId = xo::reflect::TypeId; + + /** sets up standard conversions **/ + ObjectConverter(); + + /** singleton instance **/ + static const ObjectConverter & instance(); + + /** establish conversion: use @p fn to convert values of type @tparam T. **/ + template + void establish_conversion(Converter::ConvertToObjectFn to, + Converter::ConvertFromObjectFn from); + + /** convert tagged poitner @p tp to object. allocates memory only from @p mm. + * return nullptr if no converter available and @p throw_flag not set. + * throw exception if no converter available and @p throw_flag set. + **/ + obj tp_to_gco(obj mm, + TaggedPtr tp, + bool throw_flag) const; + + /** convert @p x to object. + * return converted object; if allocated, using only memory from @p mm. + * return nullptr if no converter available, and @p throw_flag not set. + * throw exception if no converter available, and @p throw_flag set. + **/ + template + obj to_gco(obj mm, const T & x, bool throw_flag); + + /** convert object @p obj to tagged pointer, with typeid @p target_id. + * Allocates memory only from @p mm. + * return null TaggedPtr if no converter available and @p throw_flag not set. + * Throw exception if no converter available and @p throw_flag set. + **/ + TaggedPtr tp_from_gco(obj mm, + obj obj, + TypeId target_type_id, + bool throw_flag) const; + + private: + /** expandable type-driven conversion table. + **/ + xo::reflect::TypeDrivenMap cvt_; + }; + + template + void + ObjectConverter::establish_conversion(Converter::ConvertToObjectFn to, + Converter::ConvertFromObjectFn from) + { + using xo::reflect::TypeDescrW; + using xo::reflect::Reflect; + + TypeDescrW td = Reflect::require(); + Converter * cvt = cvt_.require(td); + + *cvt = Converter(to, from); + } + + template + auto + ObjectConverter::to_gco(obj mm, const T & x, bool throw_flag) + -> obj + { + TaggedPtr x_tp = Reflect::make_tp(&x); + + return tp_to_gco(mm, x_tp, throw_flag); + } + } /*namespace scm*/ +} /*namespace xo*/ + +/* end GCObjectConverter.hpp */ diff --git a/xo-object2/include/xo/object2/Integer.hpp b/xo-object2/include/xo/object2/Integer.hpp new file mode 100644 index 00000000..7279f97d --- /dev/null +++ b/xo-object2/include/xo/object2/Integer.hpp @@ -0,0 +1,12 @@ +/** @file Integer.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DInteger.hpp" +#include "number/IGCObject_DInteger.hpp" +#include "number/IPrintable_DInteger.hpp" + +/* end Integer.hpp */ diff --git a/xo-object2/include/xo/object2/RuntimeError.hpp b/xo-object2/include/xo/object2/RuntimeError.hpp new file mode 100644 index 00000000..c2a5f65d --- /dev/null +++ b/xo-object2/include/xo/object2/RuntimeError.hpp @@ -0,0 +1,12 @@ +/** @file RuntimeError.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DRuntimeError.hpp" +#include "error/IGCObject_DRuntimeError.hpp" +#include "error/IPrintable_DRuntimeError.hpp" + +/* end RuntimeError.hpp */ diff --git a/xo-object2/include/xo/object2/Sequence.hpp b/xo-object2/include/xo/object2/Sequence.hpp index fc934084..0478fa8b 100644 --- a/xo-object2/include/xo/object2/Sequence.hpp +++ b/xo-object2/include/xo/object2/Sequence.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/Sequence.json5] * 2. jinja2 template for facet .hpp file: @@ -19,4 +19,4 @@ #include "sequence/RSequence.hpp" -/* end Sequence.hpp */ \ No newline at end of file +/* end Sequence.hpp */ diff --git a/xo-object2/include/xo/object2/String.hpp b/xo-object2/include/xo/object2/String.hpp new file mode 100644 index 00000000..111b04fb --- /dev/null +++ b/xo-object2/include/xo/object2/String.hpp @@ -0,0 +1,12 @@ +/** @file String.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DString.hpp" +#include "string/IGCObject_DString.hpp" +#include "string/IPrintable_DString.hpp" + +/* end String.hpp */ diff --git a/xo-object2/include/xo/object2/array/IGCObject_DArray.hpp b/xo-object2/include/xo/object2/array/IGCObject_DArray.hpp index 0b2279f1..9af6d3c7 100644 --- a/xo-object2/include/xo/object2/array/IGCObject_DArray.hpp +++ b/xo-object2/include/xo/object2/array/IGCObject_DArray.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IGCObject_DArray.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-object2/include/xo/object2/array/IPrintable_DArray.hpp b/xo-object2/include/xo/object2/array/IPrintable_DArray.hpp new file mode 100644 index 00000000..890cbab5 --- /dev/null +++ b/xo-object2/include/xo/object2/array/IPrintable_DArray.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DArray.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DArray.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DArray.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DArray.hpp" + +namespace xo { namespace scm { class IPrintable_DArray; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DArray + **/ + class IPrintable_DArray { + public: + /** @defgroup scm-printable-darray-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-darray-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DArray & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-object2/include/xo/object2/array/ISequence_DArray.hpp b/xo-object2/include/xo/object2/array/ISequence_DArray.hpp index 27f47db3..3b756b94 100644 --- a/xo-object2/include/xo/object2/array/ISequence_DArray.hpp +++ b/xo-object2/include/xo/object2/array/ISequence_DArray.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/ISequence_DArray.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-object2/include/xo/object2/boolean/IGCObject_DBoolean.hpp b/xo-object2/include/xo/object2/boolean/IGCObject_DBoolean.hpp new file mode 100644 index 00000000..1d90b60e --- /dev/null +++ b/xo-object2/include/xo/object2/boolean/IGCObject_DBoolean.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DBoolean.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DBoolean.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DBoolean.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DBoolean.hpp" + +namespace xo { namespace scm { class IGCObject_DBoolean; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DBoolean + **/ + class IGCObject_DBoolean { + public: + /** @defgroup scm-gcobject-dboolean-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dboolean-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DBoolean & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DBoolean & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DBoolean & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-object2/include/xo/object2/boolean/IPrintable_DBoolean.hpp b/xo-object2/include/xo/object2/boolean/IPrintable_DBoolean.hpp new file mode 100644 index 00000000..b650c435 --- /dev/null +++ b/xo-object2/include/xo/object2/boolean/IPrintable_DBoolean.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DBoolean.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DBoolean.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DBoolean.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DBoolean.hpp" + +namespace xo { namespace scm { class IPrintable_DBoolean; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DBoolean + **/ + class IPrintable_DBoolean { + public: + /** @defgroup scm-printable-dboolean-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dboolean-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DBoolean & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-object2/include/xo/object2/error/IGCObject_DRuntimeError.hpp b/xo-object2/include/xo/object2/error/IGCObject_DRuntimeError.hpp new file mode 100644 index 00000000..3bb4d3d8 --- /dev/null +++ b/xo-object2/include/xo/object2/error/IGCObject_DRuntimeError.hpp @@ -0,0 +1,65 @@ +/** @file IGCObject_DRuntimeError.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DRuntimeError.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DRuntimeError.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include "DRuntimeError.hpp" + +namespace xo { namespace scm { class IGCObject_DRuntimeError; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DRuntimeError + **/ + class IGCObject_DRuntimeError { + public: + /** @defgroup scm-gcobject-druntimeerror-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-druntimeerror-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DRuntimeError & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DRuntimeError & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DRuntimeError & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-object2/include/xo/object2/error/IPrintable_DRuntimeError.hpp b/xo-object2/include/xo/object2/error/IPrintable_DRuntimeError.hpp new file mode 100644 index 00000000..8b5a4d17 --- /dev/null +++ b/xo-object2/include/xo/object2/error/IPrintable_DRuntimeError.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DRuntimeError.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DRuntimeError.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DRuntimeError.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DRuntimeError.hpp" + +namespace xo { namespace scm { class IPrintable_DRuntimeError; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DRuntimeError + **/ + class IPrintable_DRuntimeError { + public: + /** @defgroup scm-printable-druntimeerror-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-druntimeerror-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DRuntimeError & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-object2/include/xo/object2/init_object2.hpp b/xo-object2/include/xo/object2/init_object2.hpp index 5c26e76d..aa3dd510 100644 --- a/xo-object2/include/xo/object2/init_object2.hpp +++ b/xo-object2/include/xo/object2/init_object2.hpp @@ -1,5 +1,5 @@ /** @file init_object2.hpp -* + * * @author Roland Conybeare, Jan 2026 **/ diff --git a/xo-object2/include/xo/object2/list/IGCObject_DList.hpp b/xo-object2/include/xo/object2/list/IGCObject_DList.hpp index e87cdd96..7e1f1428 100644 --- a/xo-object2/include/xo/object2/list/IGCObject_DList.hpp +++ b/xo-object2/include/xo/object2/list/IGCObject_DList.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IGCObject_DList.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-object2/include/xo/object2/list/IPrintable_DList.hpp b/xo-object2/include/xo/object2/list/IPrintable_DList.hpp index 4371fdfb..77e7b1d3 100644 --- a/xo-object2/include/xo/object2/list/IPrintable_DList.hpp +++ b/xo-object2/include/xo/object2/list/IPrintable_DList.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IPrintable_DList.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-object2/include/xo/object2/list/ISequence_DList.hpp b/xo-object2/include/xo/object2/list/ISequence_DList.hpp index 81289db9..ac468764 100644 --- a/xo-object2/include/xo/object2/list/ISequence_DList.hpp +++ b/xo-object2/include/xo/object2/list/ISequence_DList.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/ISequence_DList.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-object2/include/xo/object2/number/GCObjectConversion_DFloat.hpp b/xo-object2/include/xo/object2/number/GCObjectConversion_DFloat.hpp new file mode 100644 index 00000000..959eeca0 --- /dev/null +++ b/xo-object2/include/xo/object2/number/GCObjectConversion_DFloat.hpp @@ -0,0 +1,29 @@ +/** @file GCObjectConversion_DFloat.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "DFloat.hpp" +#include "number/IGCObject_DFloat.hpp" +#include + +namespace xo { + namespace scm { + + template <> + struct GCObjectConversion { + static_assert(std::is_same_v); + + using AGCObject = xo::mm::AGCObject; + using AAllocator = xo::mm::AAllocator; + + static obj to_gco(obj mm, double x); + static double from_gco(obj mm, obj gco); + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end GCObjectConversion_DFloat.hpp */ diff --git a/xo-object2/include/xo/object2/number/GCObjectConversion_DInteger.hpp b/xo-object2/include/xo/object2/number/GCObjectConversion_DInteger.hpp new file mode 100644 index 00000000..458312c9 --- /dev/null +++ b/xo-object2/include/xo/object2/number/GCObjectConversion_DInteger.hpp @@ -0,0 +1,29 @@ +/** @file GCObjectConversion_DInteger.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "DInteger.hpp" +#include "number/IGCObject_DInteger.hpp" +#include + +namespace xo { + namespace scm { + + template <> + struct GCObjectConversion { + static_assert(std::is_same_v); + + using AGCObject = xo::mm::AGCObject; + using AAllocator = xo::mm::AAllocator; + + static obj to_gco(obj mm, long x); + static long from_gco(obj mm, obj gco); + }; + + } +} /*namespace xo*/ + +/* end GCObjectConversion_DInteger.hpp */ diff --git a/xo-object2/include/xo/object2/number/IGCObject_DFloat.hpp b/xo-object2/include/xo/object2/number/IGCObject_DFloat.hpp index c57c89ea..9a1dcbdc 100644 --- a/xo-object2/include/xo/object2/number/IGCObject_DFloat.hpp +++ b/xo-object2/include/xo/object2/number/IGCObject_DFloat.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IGCObject_DFloat.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -14,6 +14,7 @@ #pragma once #include "GCObject.hpp" +#include #include #include #include "DFloat.hpp" diff --git a/xo-object2/include/xo/object2/number/IGCObject_DInteger.hpp b/xo-object2/include/xo/object2/number/IGCObject_DInteger.hpp index 10a5c685..1136b577 100644 --- a/xo-object2/include/xo/object2/number/IGCObject_DInteger.hpp +++ b/xo-object2/include/xo/object2/number/IGCObject_DInteger.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IGCObject_DInteger.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-object2/include/xo/object2/number/IPrintable_DFloat.hpp b/xo-object2/include/xo/object2/number/IPrintable_DFloat.hpp index 17eab5d2..9506055a 100644 --- a/xo-object2/include/xo/object2/number/IPrintable_DFloat.hpp +++ b/xo-object2/include/xo/object2/number/IPrintable_DFloat.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IPrintable_DFloat.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-object2/include/xo/object2/number/IPrintable_DInteger.hpp b/xo-object2/include/xo/object2/number/IPrintable_DInteger.hpp index 95a9e108..1b5df6c4 100644 --- a/xo-object2/include/xo/object2/number/IPrintable_DInteger.hpp +++ b/xo-object2/include/xo/object2/number/IPrintable_DInteger.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IPrintable_DInteger.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-object2/include/xo/object2/sequence/ASequence.hpp b/xo-object2/include/xo/object2/sequence/ASequence.hpp index 99687473..53d112e7 100644 --- a/xo-object2/include/xo/object2/sequence/ASequence.hpp +++ b/xo-object2/include/xo/object2/sequence/ASequence.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/Sequence.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -51,6 +51,8 @@ public: // const methods /** RTTI: unique id# for actual runtime data representation **/ virtual typeseq _typeseq() const noexcept = 0; + /** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/ + virtual void _drop(Opaque d) const noexcept = 0; /** true iff sequence is empty **/ virtual bool is_empty(Copaque data) const noexcept = 0; /** true iff sequence is finite **/ @@ -78,4 +80,4 @@ using ISequence_ImplType = xo::facet::FacetImplType; } /*namespace scm*/ } /*namespace xo*/ -/* ASequence.hpp */ \ No newline at end of file +/* ASequence.hpp */ diff --git a/xo-object2/include/xo/object2/sequence/ISequence_Any.hpp b/xo-object2/include/xo/object2/sequence/ISequence_Any.hpp index 9f5901f2..e878f729 100644 --- a/xo-object2/include/xo/object2/sequence/ISequence_Any.hpp +++ b/xo-object2/include/xo/object2/sequence/ISequence_Any.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/Sequence.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -55,8 +55,11 @@ namespace scm { // from ASequence - // const methods + // builtin methods typeseq _typeseq() const noexcept override { return s_typeseq; } + [[noreturn]] void _drop(Opaque) const noexcept override { _fatal(); } + + // const methods [[noreturn]] bool is_empty(Copaque) const noexcept override { _fatal(); } [[noreturn]] bool is_finite(Copaque) const noexcept override { _fatal(); } [[noreturn]] obj at(Copaque, size_type) const override { _fatal(); } @@ -86,4 +89,4 @@ namespace scm { } /*namespace scm */ } /*namespace xo */ -/* ISequence_Any.hpp */ \ No newline at end of file +/* ISequence_Any.hpp */ diff --git a/xo-object2/include/xo/object2/sequence/ISequence_Xfer.hpp b/xo-object2/include/xo/object2/sequence/ISequence_Xfer.hpp index 60abc5aa..42d6cb1b 100644 --- a/xo-object2/include/xo/object2/sequence/ISequence_Xfer.hpp +++ b/xo-object2/include/xo/object2/sequence/ISequence_Xfer.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/Sequence.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -40,8 +40,11 @@ namespace scm { // from ASequence - // const methods + // builtin methods typeseq _typeseq() const noexcept override { return s_typeseq; } + void _drop(Opaque d) const noexcept override { _dcast(d).~DRepr(); } + + // const methods bool is_empty(Copaque data) const noexcept override { return I::is_empty(_dcast(data)); } @@ -85,4 +88,4 @@ namespace scm { } /*namespace scm */ } /*namespace xo*/ -/* end ISequence_Xfer.hpp */ \ No newline at end of file +/* end ISequence_Xfer.hpp */ diff --git a/xo-object2/include/xo/object2/sequence/RSequence.hpp b/xo-object2/include/xo/object2/sequence/RSequence.hpp index 26ec1735..76f60059 100644 --- a/xo-object2/include/xo/object2/sequence/RSequence.hpp +++ b/xo-object2/include/xo/object2/sequence/RSequence.hpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/Sequence.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -47,8 +47,13 @@ public: /** @defgroup scm-sequence-router-methods **/ ///@{ - // const methods + // explicit injected content + + // builtin methods typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); } + void _drop() const noexcept { O::iface()->_drop(O::data()); } + + // const methods bool is_empty() const noexcept { return O::iface()->is_empty(O::data()); } @@ -84,4 +89,4 @@ namespace xo { namespace facet { }; } } -/* end RSequence.hpp */ \ No newline at end of file +/* end RSequence.hpp */ diff --git a/xo-object2/include/xo/object2/string/IGCObject_DString.hpp b/xo-object2/include/xo/object2/string/IGCObject_DString.hpp index ad12cb80..159b9e49 100644 --- a/xo-object2/include/xo/object2/string/IGCObject_DString.hpp +++ b/xo-object2/include/xo/object2/string/IGCObject_DString.hpp @@ -2,17 +2,18 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IGCObject_DString.json5] * 2. jinja2 template for abstract facet .hpp file: - * [iface_facet_any.hpp.j2] + * [iface_facet_repr.hpp.j2] * 3. idl for facet methods * [idl/IGCObject_DString.json5] **/ #pragma once +#include "GCObject.hpp" #include #include #include "DString.hpp" diff --git a/xo-object2/include/xo/object2/string/IPrintable_DString.hpp b/xo-object2/include/xo/object2/string/IPrintable_DString.hpp index d1d3f22a..f898a17c 100644 --- a/xo-object2/include/xo/object2/string/IPrintable_DString.hpp +++ b/xo-object2/include/xo/object2/string/IPrintable_DString.hpp @@ -2,17 +2,18 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IPrintable_DString.json5] * 2. jinja2 template for abstract facet .hpp file: - * [iface_facet_any.hpp.j2] + * [iface_facet_repr.hpp.j2] * 3. idl for facet methods * [idl/IPrintable_DString.json5] **/ #pragma once +#include "Printable.hpp" #include #include #include "DString.hpp" diff --git a/xo-object2/src/object2/CMakeLists.txt b/xo-object2/src/object2/CMakeLists.txt index a87c349b..a5595246 100644 --- a/xo-object2/src/object2/CMakeLists.txt +++ b/xo-object2/src/object2/CMakeLists.txt @@ -2,30 +2,49 @@ set(SELF_LIB xo_object2) set(SELF_SRCS - IGCObject_DArray.cpp - IGCObject_DFloat.cpp - IGCObject_DInteger.cpp - IGCObject_DList.cpp - IGCObject_DString.cpp - ISequence_Any.cpp - ISequence_DArray.cpp - ISequence_DList.cpp - IPrintable_DList.cpp - IPrintable_DFloat.cpp - IPrintable_DInteger.cpp - IPrintable_DString.cpp - DArray.cpp - DList.cpp - DFloat.cpp - DInteger.cpp - DString.cpp init_object2.cpp object2_register_types.cpp object2_register_facets.cpp + + GCObjectConversion_DFloat.cpp + GCObjectConversion_DInteger.cpp + + ISequence_Any.cpp + + DArray.cpp + ISequence_DArray.cpp + IGCObject_DArray.cpp + IPrintable_DArray.cpp + + DList.cpp + ISequence_DList.cpp + IGCObject_DList.cpp + IPrintable_DList.cpp + + DFloat.cpp + IGCObject_DFloat.cpp + IPrintable_DFloat.cpp + + DInteger.cpp + IGCObject_DInteger.cpp + IPrintable_DInteger.cpp + + DBoolean.cpp + IGCObject_DBoolean.cpp + IPrintable_DBoolean.cpp + + DString.cpp + IGCObject_DString.cpp + IPrintable_DString.cpp + + DRuntimeError.cpp + IGCObject_DRuntimeError.cpp + IPrintable_DRuntimeError.cpp ) xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS}) # note: deps here must also appear in cmake/xo_object2Config.cmake.in +xo_dependency(${SELF_LIB} reflect) xo_dependency(${SELF_LIB} xo_gc) xo_dependency(${SELF_LIB} xo_printable2) xo_dependency(${SELF_LIB} subsys) diff --git a/xo-object2/src/object2/DArray.cpp b/xo-object2/src/object2/DArray.cpp index 1b4138c6..31ced92e 100644 --- a/xo-object2/src/object2/DArray.cpp +++ b/xo-object2/src/object2/DArray.cpp @@ -1,14 +1,19 @@ /** @file DArray.cpp -* + * * @author Roland Conybeare, Jan 2026 **/ #include "DArray.hpp" +#include +#include +#include #include #include #include namespace xo { + using xo::print::APrintable; + using xo::facet::FacetRegistry; using xo::mm::AGCObject; using xo::facet::typeseq; @@ -32,6 +37,23 @@ namespace xo { return result; } + DArray * + DArray::copy(obj mm, + DArray * src, + size_type new_cap) + { + DArray * dest = empty(mm, new_cap); + + /** could just memcpy here **/ + for (size_type i = 0, n = src->size(); i < n; ++i) { + dest->elts_[i] = src->elts_[i]; + } + + dest->size_ = src->size(); + + return dest; + } + obj DArray::at(size_type ix) const { @@ -62,12 +84,59 @@ namespace xo { } } + bool + DArray::resize(size_type new_z) noexcept { + if (new_z >= capacity_) { + return false; + } else if (new_z > size_) { + // ensure new size is zeroed (we/re not zeroing if/when we shrink) + ::memset((std::byte *)(&elts_[size_]), 0, (std::byte *)(&elts_[new_z]) - (std::byte *)(&elts_[size_])); + } + + this->size_ = new_z; + return true; + } + + // printing support + + bool + DArray::pretty(const ppindentinfo & ppii) const + { + using xo::print::ppstate; + + ppstate * pps = ppii.pps(); + + if (ppii.upto()) { + /* perhaps print on one line */ + pps->write("["); + + for (size_t i = 0, n = this->size(); i < n; ++i ) { + if (i > 0) + pps->write(" "); + + obj elt + = FacetRegistry::instance().variant(this->at(i)); + + assert(elt.data()); + + if (!pps->print_upto(elt)) + return false; + } + + pps->write("]"); + return true; + } else { + pps->write("[...]"); + return false; + } + } + // gc hooks for IGCObject_DArray std::size_t DArray::shallow_size() const noexcept { - return sizeof(DArray); + return sizeof(DArray) + (capacity_ * sizeof(obj)); } DArray * @@ -82,7 +151,9 @@ namespace xo { constexpr auto c_obj_z = sizeof(obj); /* memcpy sufficient for obj */ - ::memcpy((void*)&(copy->elts_[0]), (void*)&(elts_[0]), capacity_ * c_obj_z); + ::memcpy((void*)&(copy->elts_[0]), + (void*)&(elts_[0]), + capacity_ * c_obj_z); } return copy; @@ -94,7 +165,7 @@ namespace xo { for (size_type i = 0; i < size_; ++i) { obj & elt = elts_[i]; - gc.forward_inplace(elt.iface(), (void **)&(elt.data_)); + gc.forward_inplace(&elt); } return shallow_size(); diff --git a/xo-object2/src/object2/DBoolean.cpp b/xo-object2/src/object2/DBoolean.cpp new file mode 100644 index 00000000..a926b0ec --- /dev/null +++ b/xo-object2/src/object2/DBoolean.cpp @@ -0,0 +1,59 @@ +/** @file DBoolean.cpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#include "DBoolean.hpp" +#include +#include + +namespace xo { + using xo::facet::typeseq; + using xo::print::ppdetail_atomic; + + namespace scm { + DBoolean * + DBoolean::_box(obj mm, bool x) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DBoolean)); + + return new (mem) DBoolean(x); + } + + bool + DBoolean::pretty(const ppindentinfo & ppii) const + { + return ppdetail_atomic::print_pretty + (ppii, + (value_ ? "true" : "false")); + } + + size_t + DBoolean::shallow_size() const noexcept + { + return sizeof(DBoolean); + } + + DBoolean * + DBoolean::shallow_copy(obj mm) const noexcept + { + DBoolean * copy = (DBoolean *)mm.alloc_copy((std::byte *)this); + + if (copy) + *copy = *this; + + return copy; + } + + size_t + DBoolean::forward_children(obj) noexcept + { + return shallow_size(); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DBoolean.cpp */ diff --git a/xo-object2/src/object2/DList.cpp b/xo-object2/src/object2/DList.cpp index 81512218..35cb7223 100644 --- a/xo-object2/src/object2/DList.cpp +++ b/xo-object2/src/object2/DList.cpp @@ -33,7 +33,7 @@ namespace xo { obj car, DList * cdr) { - void * mem = mm.alloc(typeseq::id(), sizeof(DList)); + void * mem = mm.alloc_for(); return new (mem) DList(car, cdr); } @@ -148,6 +148,8 @@ namespace xo { } } + // ----- GCObject facet ------ + auto DList::shallow_size() const noexcept -> size_type { @@ -157,12 +159,7 @@ namespace xo { DList * DList::shallow_copy(obj mm) const noexcept { - DList * copy = (DList *)mm.alloc_copy((std::byte *)this); - - if (copy) - *copy = *this; - - return copy; + return mm.std_copy_for(this); } auto @@ -170,12 +167,14 @@ namespace xo { { //scope log(XO_DEBUG(true)); - gc.forward_inplace(head_.iface(), (void **)&(head_.data_)); + gc.forward_inplace(&head_); + //gc.forward_inplace(head_.iface(), (void **)&(head_.data_)); - auto iface = xo::facet::impl_for(); - gc.forward_inplace(&iface, (void **)(&rest_)); + gc.forward_inplace(&rest_); + //auto iface = xo::facet::impl_for(); + //gc.forward_inplace(&iface, (void **)(&rest_)); - return shallow_size(); + return this->shallow_size(); } } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-object2/src/object2/DRuntimeError.cpp b/xo-object2/src/object2/DRuntimeError.cpp new file mode 100644 index 00000000..2b9fa62f --- /dev/null +++ b/xo-object2/src/object2/DRuntimeError.cpp @@ -0,0 +1,100 @@ +/** @file DRuntimeError.cpp +* + * @author Roland Conybeare, Feb 2026 + **/ + +#include "RuntimeError.hpp" + +namespace xo { + using xo::mm::AGCObject; + using xo::facet::typeseq; + + namespace scm { + + obj + DRuntimeError::make(obj mm, + const char * src_fn, + const char * error_descr) + { + DRuntimeError * err = DRuntimeError::_make(mm, nullptr, nullptr); + + // pedantic: allocate strings after allocating DRuntimeError instance + + DString * src = DString::from_cstr(mm, src_fn); + DString * err_descr = DString::from_cstr(mm, error_descr); + + err->src_function_ = src; + err->error_descr_ = err_descr; + + return obj(err); + } + + DRuntimeError * + DRuntimeError::_make(obj mm, + DString * src_fn, + DString * error_descr) + { + void * mem + = mm.alloc(typeseq::id(), + sizeof(DRuntimeError)); + + DRuntimeError * err + = new (mem) DRuntimeError(src_fn, error_descr); + + return err; + } + + DRuntimeError::DRuntimeError(DString * src_fn, + DString * error_descr) : src_function_{src_fn}, + error_descr_{error_descr} + {} + + // ----- GCObject facet ----- + + std::size_t + DRuntimeError::shallow_size() const noexcept + { + return sizeof(DRuntimeError); + } + + DRuntimeError * + DRuntimeError::shallow_copy(obj mm) const noexcept + { + DRuntimeError * copy = (DRuntimeError *)mm.alloc_copy((std::byte *)this); + + if (copy) + *copy = *this; + + return copy; + } + + std::size_t + DRuntimeError::forward_children(obj gc) noexcept + { + { + auto iface = xo::facet::impl_for(); + gc.forward_inplace(&iface, (void **)(&src_function_)); + } + + { + auto iface = xo::facet::impl_for(); + gc.forward_inplace(&iface, (void **)(&error_descr_)); + } + + return this->shallow_size(); + } + + // ----- Printable facet ----- + + bool + DRuntimeError::pretty(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct(ppii, + "DRuntimeError"); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DRuntimeError.cpp */ + diff --git a/xo-object2/src/object2/DString.cpp b/xo-object2/src/object2/DString.cpp index ee9885b7..69baa5d6 100644 --- a/xo-object2/src/object2/DString.cpp +++ b/xo-object2/src/object2/DString.cpp @@ -91,6 +91,15 @@ namespace xo { return _from_view_aux(mm, sv, false /*!suballoc_flag*/); } + DString * + DString::from_str(obj mm, + const std::string & str) + { + return _from_view_aux(mm, + std::string_view(str), + false /*!suballoc_flag*/); + } + DString * DString::from_view_suballoc(obj mm, std::string_view sv) diff --git a/xo-object2/src/object2/GCObjectConversion_DFloat.cpp b/xo-object2/src/object2/GCObjectConversion_DFloat.cpp new file mode 100644 index 00000000..794431d2 --- /dev/null +++ b/xo-object2/src/object2/GCObjectConversion_DFloat.cpp @@ -0,0 +1,41 @@ +/** @file GCObjectConversion_DFloat.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "number/GCObjectConversion_DFloat.hpp" +#include + +namespace xo { + using xo::mm::AGCObject; + + namespace scm { + + obj + GCObjectConversion::to_gco(obj mm, + double x) + { + return DFloat::box(mm, x); + } + + double + GCObjectConversion::from_gco(obj mm, + obj gco) + { + (void)mm; + + auto float_obj = obj::from(gco); + + if (!float_obj) { + throw std::runtime_error + (tostr("Object obj found where Float expected", + xtag("obj", gco))); + } + + return float_obj.data()->value(); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end GCObjectConversion_DFloat.cpp */ diff --git a/xo-object2/src/object2/GCObjectConversion_DInteger.cpp b/xo-object2/src/object2/GCObjectConversion_DInteger.cpp new file mode 100644 index 00000000..bdaf8a18 --- /dev/null +++ b/xo-object2/src/object2/GCObjectConversion_DInteger.cpp @@ -0,0 +1,41 @@ +/** @file GCObjectConversion_DInteger.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "number/GCObjectConversion_DInteger.hpp" +#include + +namespace xo { + using xo::mm::AGCObject; + + namespace scm { + + obj + GCObjectConversion::to_gco(obj mm, + long x) + { + return DInteger::box(mm, x); + } + + long + GCObjectConversion::from_gco(obj mm, + obj gco) + { + (void)mm; + + auto int_obj = obj::from(gco); + + if (!int_obj) { + throw std::runtime_error + (tostr("Object obj found where Integer expected", + xtag("obj", gco))); + } + + return int_obj.data()->value(); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end GCObjectConversion_DFloat.cpp */ diff --git a/xo-object2/src/object2/GCObjectConverter.cpp b/xo-object2/src/object2/GCObjectConverter.cpp new file mode 100644 index 00000000..6f3f5b4a --- /dev/null +++ b/xo-object2/src/object2/GCObjectConverter.cpp @@ -0,0 +1,258 @@ +/** @file GCObjectConverter.cpp + * + * @author Roland Conybeare, Nov 2025 + **/ + +#include "GCObjectConverter.hpp" + +#include "DInteger.hpp" +#include "number/IGCObject_DInteger.hpp" + +#include "DFloat.hpp" +#include "number/IGCObject_DFloat.hpp" + +#include "DBoolean.hpp" +#include "boolean/IGCObject_DBoolean.hpp" + +#include "DString.hpp" +#include "string/IGCObject_DString.hpp" + +#include +#include +//#include "xo/alloc/Blob.hpp" + +namespace xo { + using xo::mm::AGCObject; + using xo::reflect::Reflect; + using xo::reflect::TaggedPtr; + using xo::reflect::TypeId; + using xo::facet::obj; + using xo::facet::typeseq; + using xo::mm::AAllocator; + + namespace scm { + namespace { + // DInteger <-> T + + template + obj + int_to_gco(obj mm, TaggedPtr src) + { + T * native = src.recover_native(); + + assert(native); + + return DInteger::box(mm, *native); + } + + template + TaggedPtr + gco_to_int(obj mm, + obj obj) + { + + /* mm cannot be GC allocator! + * That's Object-only + */ + + auto int_obj = xo::facet::obj::from(obj); //Integer::from(obj); + + if (!int_obj) { + throw std::runtime_error + (tostr("Object obj found where Integer expected", + xtag("obj", obj))); + } + + void * mem = mm.alloc(typeseq::id(), sizeof(T)); + + T * p = reinterpret_cast(mem); + + *p = int_obj.data()->value(); + + /* Note: + * retval invalidated when + * *mm cleared/recycled/collected + */ + + return Reflect::make_tp(p); + } + + // DFloat <-> T + + template + xo::facet::obj + float_to_gco(xo::facet::obj mm, + TaggedPtr src) + { + T * native = src.recover_native(); + + assert(native); + + return DFloat::box(mm, *native); + } + + template + TaggedPtr + gco_to_float(obj mm, obj obj) + { + auto float_obj = xo::facet::obj::from(obj); + + if (!float_obj) { + throw std::runtime_error + (tostr("Object obj found where Float expected", + xtag("obj", obj))); + } + + void * mem = mm.alloc(typeseq::id(), sizeof(T)); + + T * p = reinterpret_cast(mem); + + *p = float_obj.data()->value(); + + /* Note: + * retval invalidated when *mm cleared/recycled/collected + */ + + return Reflect::make_tp(p); + } + + // DBoolean <-> T + + obj + bool_to_gco(obj mm, TaggedPtr src) + { + bool * native = src.recover_native(); + + assert(native); + + return DBoolean::box(mm, *native); + } + + TaggedPtr + gco_to_bool(obj /*mm*/, + obj obj) + { + static bool s_true = true; + static bool s_false = false; + + auto bool_obj = xo::facet::obj::from(obj); + + if (!bool_obj) { + throw std::runtime_error + (tostr("Object obj found where Boolean expected", + xtag("obj", obj))); + } + + return Reflect::make_tp(bool_obj.data()->value() ? &s_true : &s_false); + } + + // DString <-> T + // w/ + // T = std::string + + obj + string_to_gco(obj mm, TaggedPtr src) + { + // try std::string.. + + std::string * native = src.recover_native(); + + assert(native); + + DString * dstr = DString::from_str(mm, *native); + + return xo::facet::obj(dstr); + } + + TaggedPtr + gco_to_string(obj mm, obj obj) + { + auto string_obj = xo::facet::obj::from(obj); + + if (!string_obj) { + throw std::runtime_error + (tostr("Object obj founcd where String expected", + xtag("obj", obj))); + } + + // still don't have impl for this + // Need regular std::allocator interface + // + + (void)mm; + assert(false); + } + } + + ObjectConverter::ObjectConverter() + { + this->establish_conversion(&int_to_gco, + &gco_to_int); + this->establish_conversion(&int_to_gco, + &gco_to_int); + + this->establish_conversion(&float_to_gco, + &gco_to_float); + + this->establish_conversion(&bool_to_gco, + &gco_to_bool); + + this->establish_conversion(&string_to_gco, + &gco_to_string); + } + + const ObjectConverter & + ObjectConverter::instance() { + static ObjectConverter s_instance; + + return s_instance; + } + + obj + ObjectConverter::tp_to_gco(obj mm, + TaggedPtr x_tp, + bool throw_flag) const + { + using xo::reflect::Reflect; + using xo::reflect::TaggedPtr; + + const Converter * cvt = cvt_.lookup(x_tp.td()); + + if (cvt) { + return (cvt->cvt_to_object_)(mm, x_tp); + } else { + if (throw_flag) { + throw std::runtime_error + (tostr("no to-object-converter available for instance of type", + xtag("id", x_tp.td()->id()), + xtag("name", x_tp.td()->short_name()))); + } + + return obj(); + } + } + + TaggedPtr + ObjectConverter::tp_from_gco(obj mm, + obj obj, + TypeId target_id, + bool throw_flag) const + { + const Converter * cvt = cvt_.lookup(target_id); + + if (cvt) { + return (cvt->cvt_from_object_)(mm, obj); + } else { + if (throw_flag) { + throw std::runtime_error + (tostr("no from-object-converter available for instance of type", + xtag("id", target_id))); + } + + return TaggedPtr::universal_null(); + } + } + } +} + +/* end GCObjectConverter.cpp */ diff --git a/xo-object2/src/object2/IGCObject_DArray.cpp b/xo-object2/src/object2/IGCObject_DArray.cpp index a2ee4bc1..1063bd45 100644 --- a/xo-object2/src/object2/IGCObject_DArray.cpp +++ b/xo-object2/src/object2/IGCObject_DArray.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IGCObject_DArray.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -36,4 +36,4 @@ namespace xo { } /*namespace scm*/ } /*namespace xo*/ -/* end IGCObject_DArray.cpp */ \ No newline at end of file +/* end IGCObject_DArray.cpp */ diff --git a/xo-object2/src/object2/IGCObject_DBoolean.cpp b/xo-object2/src/object2/IGCObject_DBoolean.cpp new file mode 100644 index 00000000..3ef60aea --- /dev/null +++ b/xo-object2/src/object2/IGCObject_DBoolean.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DBoolean.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DBoolean.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DBoolean.json5] +**/ + +#include "boolean/IGCObject_DBoolean.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DBoolean::shallow_size(const DBoolean & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DBoolean::shallow_copy(const DBoolean & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DBoolean::forward_children(DBoolean & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DBoolean.cpp */ diff --git a/xo-object2/src/object2/IGCObject_DFloat.cpp b/xo-object2/src/object2/IGCObject_DFloat.cpp index ef4214a7..9e31cf68 100644 --- a/xo-object2/src/object2/IGCObject_DFloat.cpp +++ b/xo-object2/src/object2/IGCObject_DFloat.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IGCObject_DFloat.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -36,4 +36,4 @@ namespace xo { } /*namespace scm*/ } /*namespace xo*/ -/* end IGCObject_DFloat.cpp */ \ No newline at end of file +/* end IGCObject_DFloat.cpp */ diff --git a/xo-object2/src/object2/IGCObject_DInteger.cpp b/xo-object2/src/object2/IGCObject_DInteger.cpp index 8b8a0112..55e1fae7 100644 --- a/xo-object2/src/object2/IGCObject_DInteger.cpp +++ b/xo-object2/src/object2/IGCObject_DInteger.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IGCObject_DInteger.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -36,4 +36,4 @@ namespace xo { } /*namespace scm*/ } /*namespace xo*/ -/* end IGCObject_DInteger.cpp */ \ No newline at end of file +/* end IGCObject_DInteger.cpp */ diff --git a/xo-object2/src/object2/IGCObject_DList.cpp b/xo-object2/src/object2/IGCObject_DList.cpp index 06584687..f4e9472b 100644 --- a/xo-object2/src/object2/IGCObject_DList.cpp +++ b/xo-object2/src/object2/IGCObject_DList.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IGCObject_DList.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -36,4 +36,4 @@ namespace xo { } /*namespace scm*/ } /*namespace xo*/ -/* end IGCObject_DList.cpp */ \ No newline at end of file +/* end IGCObject_DList.cpp */ diff --git a/xo-object2/src/object2/IGCObject_DRuntimeError.cpp b/xo-object2/src/object2/IGCObject_DRuntimeError.cpp new file mode 100644 index 00000000..d44c4359 --- /dev/null +++ b/xo-object2/src/object2/IGCObject_DRuntimeError.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DRuntimeError.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DRuntimeError.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DRuntimeError.json5] +**/ + +#include "error/IGCObject_DRuntimeError.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DRuntimeError::shallow_size(const DRuntimeError & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DRuntimeError::shallow_copy(const DRuntimeError & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DRuntimeError::forward_children(DRuntimeError & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DRuntimeError.cpp */ diff --git a/xo-object2/src/object2/IGCObject_DString.cpp b/xo-object2/src/object2/IGCObject_DString.cpp index d411686a..d34f0eaf 100644 --- a/xo-object2/src/object2/IGCObject_DString.cpp +++ b/xo-object2/src/object2/IGCObject_DString.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IGCObject_DString.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-object2/src/object2/IPrintable_DArray.cpp b/xo-object2/src/object2/IPrintable_DArray.cpp new file mode 100644 index 00000000..b9248516 --- /dev/null +++ b/xo-object2/src/object2/IPrintable_DArray.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DArray.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DArray.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DArray.json5] +**/ + +#include "array/IPrintable_DArray.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DArray::pretty(const DArray & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DArray.cpp */ diff --git a/xo-object2/src/object2/IPrintable_DBoolean.cpp b/xo-object2/src/object2/IPrintable_DBoolean.cpp new file mode 100644 index 00000000..3b85aa27 --- /dev/null +++ b/xo-object2/src/object2/IPrintable_DBoolean.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DBoolean.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DBoolean.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DBoolean.json5] +**/ + +#include "boolean/IPrintable_DBoolean.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DBoolean::pretty(const DBoolean & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DBoolean.cpp */ diff --git a/xo-object2/src/object2/IPrintable_DFloat.cpp b/xo-object2/src/object2/IPrintable_DFloat.cpp index b83613e5..f1e8be6d 100644 --- a/xo-object2/src/object2/IPrintable_DFloat.cpp +++ b/xo-object2/src/object2/IPrintable_DFloat.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IPrintable_DFloat.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -25,4 +25,4 @@ namespace xo { } /*namespace scm*/ } /*namespace xo*/ -/* end IPrintable_DFloat.cpp */ \ No newline at end of file +/* end IPrintable_DFloat.cpp */ diff --git a/xo-object2/src/object2/IPrintable_DInteger.cpp b/xo-object2/src/object2/IPrintable_DInteger.cpp index 889cfa8c..7a9bbdaa 100644 --- a/xo-object2/src/object2/IPrintable_DInteger.cpp +++ b/xo-object2/src/object2/IPrintable_DInteger.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IPrintable_DInteger.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -25,4 +25,4 @@ namespace xo { } /*namespace scm*/ } /*namespace xo*/ -/* end IPrintable_DInteger.cpp */ \ No newline at end of file +/* end IPrintable_DInteger.cpp */ diff --git a/xo-object2/src/object2/IPrintable_DList.cpp b/xo-object2/src/object2/IPrintable_DList.cpp index 384d8b60..a8f9b657 100644 --- a/xo-object2/src/object2/IPrintable_DList.cpp +++ b/xo-object2/src/object2/IPrintable_DList.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IPrintable_DList.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -25,4 +25,4 @@ namespace xo { } /*namespace scm*/ } /*namespace xo*/ -/* end IPrintable_DList.cpp */ \ No newline at end of file +/* end IPrintable_DList.cpp */ diff --git a/xo-object2/src/object2/IPrintable_DRuntimeError.cpp b/xo-object2/src/object2/IPrintable_DRuntimeError.cpp new file mode 100644 index 00000000..eaf084ca --- /dev/null +++ b/xo-object2/src/object2/IPrintable_DRuntimeError.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DRuntimeError.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DRuntimeError.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DRuntimeError.json5] +**/ + +#include "error/IPrintable_DRuntimeError.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DRuntimeError::pretty(const DRuntimeError & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DRuntimeError.cpp */ diff --git a/xo-object2/src/object2/IPrintable_DString.cpp b/xo-object2/src/object2/IPrintable_DString.cpp index f47aa3fa..f5ec4967 100644 --- a/xo-object2/src/object2/IPrintable_DString.cpp +++ b/xo-object2/src/object2/IPrintable_DString.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/IPrintable_DString.json5] * 2. jinja2 template for abstract facet .hpp file: diff --git a/xo-object2/src/object2/ISequence_Any.cpp b/xo-object2/src/object2/ISequence_Any.cpp index 8461d750..372571f7 100644 --- a/xo-object2/src/object2/ISequence_Any.cpp +++ b/xo-object2/src/object2/ISequence_Any.cpp @@ -38,4 +38,4 @@ ISequence_Any::_valid } /*namespace scm*/ } /*namespace xo*/ -/* end ISequence_Any.cpp */ \ No newline at end of file +/* end ISequence_Any.cpp */ diff --git a/xo-object2/src/object2/ISequence_DArray.cpp b/xo-object2/src/object2/ISequence_DArray.cpp index 40ffe36a..abeeaeee 100644 --- a/xo-object2/src/object2/ISequence_DArray.cpp +++ b/xo-object2/src/object2/ISequence_DArray.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/ISequence_DArray.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -37,4 +37,4 @@ namespace xo { } /*namespace scm*/ } /*namespace xo*/ -/* end ISequence_DArray.cpp */ \ No newline at end of file +/* end ISequence_DArray.cpp */ diff --git a/xo-object2/src/object2/ISequence_DList.cpp b/xo-object2/src/object2/ISequence_DList.cpp index b216b7e5..2bc21862 100644 --- a/xo-object2/src/object2/ISequence_DList.cpp +++ b/xo-object2/src/object2/ISequence_DList.cpp @@ -2,7 +2,7 @@ * * Generated automagically from ingredients: * 1. code generator: - * [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet] + * [xo-facet/codegen/genfacet] * arguments: * --input [idl/ISequence_DList.json5] * 2. jinja2 template for abstract facet .hpp file: @@ -37,4 +37,4 @@ namespace xo { } /*namespace scm*/ } /*namespace xo*/ -/* end ISequence_DList.cpp */ \ No newline at end of file +/* end ISequence_DList.cpp */ diff --git a/xo-object2/src/object2/init_object2.cpp b/xo-object2/src/object2/init_object2.cpp index b5e57aba..bcf7608c 100644 --- a/xo-object2/src/object2/init_object2.cpp +++ b/xo-object2/src/object2/init_object2.cpp @@ -1,5 +1,5 @@ /** @file init_object2.cpp -* + * * @author Roland Conybeare, Jan 2026 **/ @@ -7,6 +7,7 @@ #include "object2_register_facets.hpp" #include "object2_register_types.hpp" #include +#include namespace xo { using xo::scm::object2_register_facets; @@ -27,7 +28,7 @@ namespace xo { InitEvidence retval; /* direct subsystem deps for xo-object2/ */ - // retval ^= InitSubsys::require(); + retval ^= InitSubsys::require(); /* xo-expression2/'s own initialization code */ retval ^= Subsystem::provide("object2", &init); diff --git a/xo-object2/src/object2/object2_register_facets.cpp b/xo-object2/src/object2/object2_register_facets.cpp index 93438600..01d6ef04 100644 --- a/xo-object2/src/object2/object2_register_facets.cpp +++ b/xo-object2/src/object2/object2_register_facets.cpp @@ -4,20 +4,31 @@ **/ #include "object2_register_facets.hpp" +#include "RuntimeError.hpp" -#include +#include +//#include +#include +#include +#include +#include + +//#include #include -#include -#include -#include +//#include +//#include +//#include +//#include +//#include #include -#include -#include -#include +//#include +//#include +//#include +//#include #include -#include +//#include #include #include @@ -29,9 +40,11 @@ namespace xo { using xo::mm::AAllocator; using xo::mm::AGCObject; using xo::scm::DList; + using xo::scm::DBoolean; using xo::scm::DFloat; using xo::scm::DString; using xo::scm::DArray; + using xo::facet::DVariantPlaceholder; using xo::facet::FacetRegistry; using xo::facet::typeseq; @@ -45,6 +58,9 @@ namespace xo { FacetRegistry::register_impl(); FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); FacetRegistry::register_impl(); @@ -55,13 +71,21 @@ namespace xo { FacetRegistry::register_impl(); FacetRegistry::register_impl(); + FacetRegistry::register_impl(); FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + log && log(xtag("DVariantPlaceholder.tseq", typeseq::id())); + log && log(xtag("DList.tseq", typeseq::id())); + log && log(xtag("DBoolean.tseq", typeseq::id())); log && log(xtag("DFloat.tseq", typeseq::id())); log && log(xtag("DInteger.tseq", typeseq::id())); log && log(xtag("DString.tseq", typeseq::id())); log && log(xtag("DArray.tseq", typeseq::id())); + log && log(xtag("DRuntimeError.tseq", typeseq::id())); log && log(xtag("AAllocator.tseq", typeseq::id())); log && log(xtag("APrintable.tseq", typeseq::id())); diff --git a/xo-object2/src/object2/object2_register_types.cpp b/xo-object2/src/object2/object2_register_types.cpp index c2079a40..275995f8 100644 --- a/xo-object2/src/object2/object2_register_types.cpp +++ b/xo-object2/src/object2/object2_register_types.cpp @@ -5,6 +5,7 @@ #include "object2_register_types.hpp" +#include "boolean/IGCObject_DBoolean.hpp" #include "number/IGCObject_DFloat.hpp" #include "number/IGCObject_DInteger.hpp" #include "string/IGCObject_DString.hpp" @@ -33,6 +34,8 @@ namespace xo { bool ok = true; + ok &= gc.install_type(impl_for()); + ok &= gc.install_type(impl_for()); ok &= gc.install_type(impl_for()); diff --git a/xo-object2/utest/Printable.test.cpp b/xo-object2/utest/Printable.test.cpp index 6c09ca90..64736d22 100644 --- a/xo-object2/utest/Printable.test.cpp +++ b/xo-object2/utest/Printable.test.cpp @@ -44,7 +44,7 @@ namespace ut { using xo::mm::ACollector; using xo::mm::AGCObject; using xo::mm::DX1Collector; - using xo::mm::CollectorConfig; + using xo::mm::X1CollectorConfig; using xo::mm::ArenaConfig; using xo::print::APrintable; using xo::facet::FacetRegistry; @@ -99,15 +99,14 @@ namespace ut { try { const testcase_pp & tc = s_testcase_v[i_tc]; - CollectorConfig cfg{ - .name_ = "pp_test", - .arena_config_ = ArenaConfig{ - .size_ = tc.gc_gen_size_, - .store_header_flag_ = true}, - .object_types_z_ = 16384, - .gc_trigger_v_{{tc.gc_trigger_threshold_, - tc.gc_trigger_threshold_}}, - .debug_flag_ = c_debug_flag + X1CollectorConfig cfg{ .name_ = "pp_test", + .arena_config_ = ArenaConfig{ + .size_ = tc.gc_gen_size_, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{tc.gc_trigger_threshold_, + tc.gc_trigger_threshold_}}, + .debug_flag_ = c_debug_flag }; DX1Collector gc(cfg); diff --git a/xo-object2/utest/X1Collector.test.cpp b/xo-object2/utest/X1Collector.test.cpp index 0f20e68a..90122c25 100644 --- a/xo-object2/utest/X1Collector.test.cpp +++ b/xo-object2/utest/X1Collector.test.cpp @@ -48,7 +48,7 @@ namespace ut { using xo::mm::AGCObject; using xo::mm::DX1Collector; using xo::mm::DArena; - using xo::mm::CollectorConfig; + using xo::mm::X1CollectorConfig; using xo::mm::ArenaConfig; using xo::mm::generation; using xo::mm::role; @@ -108,16 +108,15 @@ namespace ut { try { const testcase_x1 & tc = s_testcase_v[i_tc]; - CollectorConfig cfg{ - .name_ = "x1_test", - .arena_config_ = ArenaConfig{ - .size_ = tc.tenured_z_, - .store_header_flag_ = true}, - .object_types_z_ = 16384, - .gc_trigger_v_{{ - tc.incr_gc_threshold_, - tc.full_gc_threshold_}}, - .debug_flag_ = c_debug_flag, + X1CollectorConfig cfg{ .name_ = "x1_test", + .arena_config_ = ArenaConfig{ + .size_ = tc.tenured_z_, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{ + tc.incr_gc_threshold_, + tc.full_gc_threshold_}}, + .debug_flag_ = c_debug_flag, }; DX1Collector gc(cfg); diff --git a/xo-printable2/CMakeLists.txt b/xo-printable2/CMakeLists.txt index 32034af1..7d3990be 100644 --- a/xo-printable2/CMakeLists.txt +++ b/xo-printable2/CMakeLists.txt @@ -24,7 +24,6 @@ xo_add_genfacet( INPUT idl/Printable.json5 OUTPUT_HPP_DIR include/xo/printable2 OUTPUT_IMPL_SUBDIR detail - OUTPUT_CPP_DIR src/printable2 ) # ---------------------------------------------------------------- diff --git a/xo-printable2/idl/Printable.json5 b/xo-printable2/idl/Printable.json5 index ada9d4ca..9926e73e 100644 --- a/xo-printable2/idl/Printable.json5 +++ b/xo-printable2/idl/Printable.json5 @@ -1,5 +1,8 @@ { mode: "facet", + output_cpp_dir: "src/printable2", + output_hpp_dir: "include/xo/printable2", + output_impl_subdir: "detail", includes: [""], // extra includes in Printable.hpp user_hpp_includes: ["\"detail/ppdetail_Printable.hpp\""], @@ -38,4 +41,5 @@ }, ], nonconst_methods: [], + router_facet_explicit_content: [], } diff --git a/xo-procedure2/CMakeLists.txt b/xo-procedure2/CMakeLists.txt new file mode 100644 index 00000000..a8b29a22 --- /dev/null +++ b/xo-procedure2/CMakeLists.txt @@ -0,0 +1,88 @@ +# xo-procedure2/CMakeLists.txt + +cmake_minimum_required(VERSION 3.10) + +project(xo_procedure2 VERSION 1.0) +enable_language(CXX) + +include(GNUInstallDirs) +include(cmake/xo-bootstrap-macros.cmake) + +xo_cxx_toplevel_options3() + +# ---------------------------------------------------------------- +# c++ settings + +# one-time project-specific c++ flags. usually empty +set(PROJECT_CXX_FLAGS "") +add_definitions(${PROJECT_CXX_FLAGS}) + +# ---------------------------------------------------------------- +# output targets + +# note: manual target; generated code committed to git +xo_add_genfacet( + TARGET xo-procedure2-facet-procedure + FACET Procedure + INPUT idl/Procedure.json5 + ) + +# note: manual target; generated code committed to git +xo_add_genfacet( + TARGET xo-procedure2-facet-runtimecontext + FACET RuntimeContext + INPUT idl/RuntimeContext.json5 + ) + +# ---------------------------------------------------------------- + +xo_add_genfacetimpl( + TARGET xo-procedure2-facetimpl-runtimecontext-simplercx + FACET_PKG xo_procedure2 + FACET RuntimeContext + REPR DSimpleRcx + INPUT idl/IRuntimeContext_DSimpleRcx.json5 + ) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-procedure2-facetimpl-procedure-primitive_gco_2_gco_gco + FACET_PKG xo_procedure2 + FACET Procedure + REPR DPrimitive_gco_2_gco_gco + INPUT idl/IProcedure_DPrimitive_gco_2_gco_gco.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-procedure2-facetimpl-gcobject-primitive_gco_2_gco_gco + FACET_PKG xo_gc + FACET GCObject + REPR Primitive_gco_2_gco_gco + INPUT idl/IGCObject_DPrimitive_gco_2_gco_gco.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-procedure2-facetimpl-printable-primitive_gco_2_gco_gco + FACET_PKG xo_printable2 + FACET Printable + REPR Primitive_gco_2_gco_gco + INPUT idl/IPrintable_DPrimitive_gco_2_gco_gco.json5 +) + +xo_add_genfacet_all(xo-procedure2-genfacet-all) + +# ---------------------------------------------------------------- + +add_subdirectory(src/procedure2) +add_subdirectory(utest) + +# ---------------------------------------------------------------- +# cmake export + +#xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets) + +# end CMakeLists.txt diff --git a/xo-procedure2/README.md b/xo-procedure2/README.md new file mode 100644 index 00000000..c47415a1 --- /dev/null +++ b/xo-procedure2/README.md @@ -0,0 +1,2 @@ +# xo-procedure2 +gc-aware function interface for Schematika diff --git a/xo-procedure2/cmake/xo-bootstrap-macros.cmake b/xo-procedure2/cmake/xo-bootstrap-macros.cmake new file mode 100644 index 00000000..592272c0 --- /dev/null +++ b/xo-procedure2/cmake/xo-bootstrap-macros.cmake @@ -0,0 +1,41 @@ +# ---------------------------------------------------------------- +# for example: +# $ PREFIX=/usr/local # for example +# $ cmake -DCMAKE_MODULE_PATH=prefix -DCMAKE_INSTALL_PREFIX=$PREFIX -B .build +# +# will get +# CMAKE_MODULE_PATH +# from xo-cmake-config --cmake-module-path +# +# and expect .cmake macros in +# CMAKE_MODULE_PATH/xo_macros/xo_cxx.cmake +# ---------------------------------------------------------------- + +find_program(XO_CMAKE_CONFIG_EXECUTABLE NAMES xo-cmake-config REQUIRED) + +if ("${XO_CMAKE_CONFIG_EXECUTABLE}" STREQUAL "XO_CMAKE_CONFIG_EXECUTABLE-NOT_FOUND") + message(FATAL "could not find xo-cmake-config executable") +endif() + +message(STATUS "XO_CMAKE_CONFIG_EXECUTABLE=${XO_CMAKE_CONFIG_EXECUTABLE}") + +if (XO_SUBMODULE_BUILD) + if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL prefix)) + # local version of xo-cmake macros + set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/xo-cmake/cmake") + message(STATUS "CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}") + endif() +else() + if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL prefix)) + # default to typical install location for xo-project-macros + execute_process(COMMAND ${XO_CMAKE_CONFIG_EXECUTABLE} --cmake-module-path OUTPUT_VARIABLE CMAKE_MODULE_PATH) + message(STATUS "CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}") + endif() +endif() + +# needs to have been installed somewhere on CMAKE_MODULE_PATH, +# (e.g. from xo-cmake with the same value for CMAKE_INSTALL_PREFIX) +# +include(xo_macros/xo_cxx) + +xo_cxx_bootstrap_message() diff --git a/xo-procedure2/cmake/xo_procedure2Config.cmake.in b/xo-procedure2/cmake/xo_procedure2Config.cmake.in new file mode 100644 index 00000000..867a3535 --- /dev/null +++ b/xo-procedure2/cmake/xo_procedure2Config.cmake.in @@ -0,0 +1,14 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) + +# note: changes to find_dependency() calls here +# must coordinate with xo_dependency() calls +# in CMakeLists.txt +# +find_dependency(xo_object2) +find_dependency(xo_gc) +find_dependency(subsys) + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") +check_required_components("@PROJECT_NAME@") diff --git a/xo-procedure2/doc/implementation.rst b/xo-procedure2/doc/implementation.rst new file mode 100644 index 00000000..418dc759 --- /dev/null +++ b/xo-procedure2/doc/implementation.rst @@ -0,0 +1,25 @@ +.. _implementation: + +.. toctree:: + :maxdepth: 2 + +Components +========== + +Library dependency tower for *xo-procedure2* + +.. ditaa:: + + +--------------------------------+ + | xo_gc | + +--------------------------------+ + | xo_alloc2 | + +--------------------------------+ + | xo_facet | + +----------------+---------------+ + | xo_reflectutil | xo_indentlog | + +----------------+---------------+ + | xo_cmake | + +--------------------------------+ + +Expect to have xo_facet depending on xo_arena instead of using std::unordered_map diff --git a/xo-procedure2/idl/IGCObject_DPrimitive_gco_2_gco_gco.json5 b/xo-procedure2/idl/IGCObject_DPrimitive_gco_2_gco_gco.json5 new file mode 100644 index 00000000..cd17ae4f --- /dev/null +++ b/xo-procedure2/idl/IGCObject_DPrimitive_gco_2_gco_gco.json5 @@ -0,0 +1,19 @@ +{ + mode: "implementation", + output_cpp_dir: "src/procedure2", + output_hpp_dir: "include/xo/procedure2", + output_impl_subdir: "detail", + includes: [ + // + "", + "", + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/GCObject.json5", + brief: "provide AGCobject interface for Primitive (gco x gco) -> gco", + using_doxygen: true, + repr: "DPrimitive_gco_2_gco_gco", + doc: [ "implement AGCObject for DPrimitive (gco x gco) -> gco" ], +} diff --git a/xo-procedure2/idl/IPrintable_DPrimitive_gco_2_gco_gco.json5 b/xo-procedure2/idl/IPrintable_DPrimitive_gco_2_gco_gco.json5 new file mode 100644 index 00000000..ee3a1951 --- /dev/null +++ b/xo-procedure2/idl/IPrintable_DPrimitive_gco_2_gco_gco.json5 @@ -0,0 +1,22 @@ +{ + mode: "implementation", + output_cpp_dir: "src/procedure2", + output_hpp_dir: "include/xo/procedure2", + output_impl_subdir: "detail", + includes: [ + "", + "", +// "", +// "", +// "", +// "", + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DPrimitive (gco x gco) -> gco", + using_doxygen: true, + repr: "DPrimitive_gco_2_gco_gco", + doc: [ "implement APrintable for DPrimitive (gco x gco) -> gco" ], +} diff --git a/xo-procedure2/idl/IProcedure_DPrimitive_gco_2_gco_gco.json5 b/xo-procedure2/idl/IProcedure_DPrimitive_gco_2_gco_gco.json5 new file mode 100644 index 00000000..b50a8634 --- /dev/null +++ b/xo-procedure2/idl/IProcedure_DPrimitive_gco_2_gco_gco.json5 @@ -0,0 +1,20 @@ +{ + mode: "implementation", + output_cpp_dir: "src/procedure2", + output_hpp_dir: "include/xo/procedure2", + output_impl_subdir: "detail", + includes: [ + "", + "", + "", + "", + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Procedure.json5", + brief: "provide AProcedure interface for Primitive (gco x gco) -> gco", + using_doxygen: true, + repr: "DPrimitive_gco_2_gco_gco", + doc: [ "implement AProcedure for DPrimitive (gco x gco) -> gco" ], +} diff --git a/xo-procedure2/idl/IRuntimeContext_DSimpleRcx.json5 b/xo-procedure2/idl/IRuntimeContext_DSimpleRcx.json5 new file mode 100644 index 00000000..324526f7 --- /dev/null +++ b/xo-procedure2/idl/IRuntimeContext_DSimpleRcx.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/procedure2", + output_hpp_dir: "include/xo/procedure2", + output_impl_subdir: "detail", + includes: [ + //"", + //"", + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/RuntimeContext.json5", + brief: "provide ARuntimeContext interface for DSimpleRcx", + using_doxygen: true, + repr: "DSimpleRcx", + doc: [ "implement ARuntimeContext for DSimpleRcx" ], +} diff --git a/xo-procedure2/idl/Procedure.json5 b/xo-procedure2/idl/Procedure.json5 new file mode 100644 index 00000000..b45227d0 --- /dev/null +++ b/xo-procedure2/idl/Procedure.json5 @@ -0,0 +1,72 @@ +// can regenerate downstream .*pp files with either: +// cmake --build -- xo-procedure2-facet-procedure +// cmake --build -- xo-procedure2-genfacet-all + +{ + mode: "facet", + output_cpp_dir: "src/procedure2", + output_hpp_dir: "include/xo/procedure2", + output_impl_subdir: "detail", + // includes in ASyntaxStateMachine.hpp + includes: [ + "\"RuntimeContext.hpp\"", + "", + ], + // extra includes in Procedure.hpp, if any + user_hpp_includes: [ + ], + namespace1: "xo", + namespace2: "scm", + // text after includes, before ASyntaxStateMachine + pretext: [ + //"namespace xo { namespace scm { class ARuntimeContext; } }", + "namespace xo { namespace scm { class DArray; } }", + ], + facet: "Procedure", + detail_subdir: "detail", + brief: "abstraction for a schematika procedure i.e. something callable", + using_doxygen: true, + doc: [ + "Abstraction for a schematika procedure" + ], + types: [ + { + name: "AGCObject", + definition: "xo::mm::AGCObject", + doc: [ "a gc-aware object" ], + }, + // { name: string, doc: [ string ], definition: string }, + ], + const_methods: [ + { + name: "is_nary", + doc: [ "true iff procedure takes n arguments" ], + return_type: "bool", + args: [], + const: true, + noexcept: true, + attributes: [] + }, + { + name: "n_args", + doc: ["number of arguments. -1 for n-ary" ], + return_type: "std::int32_t", + args: [], + const: true, + noexcept: true, + attributes: [] + } + ], + nonconst_methods: [ + { + name: "apply_nocheck", + doc: ["invoke procedure; assume arguments satisfy type system" ], + return_type: "obj", + args: [ + {type: "obj", name: "rcx"}, + {type: "const DArray *", name: "args"}, + ] + } + ], + router_facet_explicit_content: [ ], +} diff --git a/xo-procedure2/idl/RuntimeContext.json5 b/xo-procedure2/idl/RuntimeContext.json5 new file mode 100644 index 00000000..07ed5b00 --- /dev/null +++ b/xo-procedure2/idl/RuntimeContext.json5 @@ -0,0 +1,47 @@ +{ + mode: "facet", + output_cpp_dir: "src/procedure2", + output_hpp_dir: "include/xo/procedure2", + output_impl_subdir: "detail", + // includes in ARuntimeContext.hpp + includes: [ + "" + ], + // extra includes in RuntimeContext.hpp, if any + user_hpp_includes: [ + ], + namespace1: "xo", + namespace2: "scm", + // text after includes, before ARuntimeContext + pretext: [ + //"namespace xo { namespace mm { class AAllocator; } }", + ], + facet: "RuntimeContext", + detail_subdir: "detail", + brief: "runtime context for application code. At minimum provides allocator", + using_doxygen: true, + doc: [ + "Runtime application context" + ], + types: [ + { + name: "AAllocator", + definition: "xo::mm::AAllocator", + doc: [ "xo memory allocator" ], + }, + ], + const_methods: [ + { + name: "allocator", + doc: [ "default allocator to use for objects" ], + return_type: "obj", + args: [], + const: true, + noexcept: true, + attributes: [], + }, + ], + nonconst_methods: [ + ], + router_facet_explicit_content: [ ], +} diff --git a/xo-procedure2/include/xo/procedure2/.gitkeep b/xo-procedure2/include/xo/procedure2/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/xo-procedure2/include/xo/procedure2/DPrimitive.hpp b/xo-procedure2/include/xo/procedure2/DPrimitive.hpp new file mode 100644 index 00000000..abec46cc --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/DPrimitive.hpp @@ -0,0 +1,178 @@ +/** @file DPrimitive.hpp + * + * @author Roland Conybeare, Jan 2025 + **/ + +#pragma once + +#include "RuntimeContext.hpp" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace xo { + namespace scm { + namespace detail { + /** @brief Extract return type and argument types from a function type. + * + * Primary template (undefined) - specializations handle specific cases + **/ + template + struct PmFnTraits; + + /** specialization for function pointers **/ + template + struct PmFnTraits rcx, Args...)> { + /** function return type **/ + using return_type = R; + /** tuple type for function arguments (except for runtime context) **/ + using args_tuple = std::tuple; + /** number of arguments (except for runtime context) **/ + static constexpr std::size_t n_args = sizeof...(Args); + + /** arg_type is the type of the i'th argument to Fn. + * (starting from argument after runtime context) + **/ + template + using arg_type = std::tuple_element_t; + }; + + /** specialization for function references **/ + template + struct PmFnTraits, Args...)> : PmFnTraits, Args...)> {}; + + /** specialization for plain function types **/ + template + struct PmFnTraits, Args...)> : PmFnTraits, Args...)> {}; + } + + /** @brief Schematika primitive with fixed number of arguments + **/ + template + class Primitive { + public: + using Traits = detail::PmFnTraits; + + using ACollector = xo::mm::ACollector; + using AAllocator = xo::mm::AAllocator; + using AGCObject = xo::mm::AGCObject; + using DArray = xo::scm::DArray; + using Reflect = xo::reflect::Reflect; + using TypeDescr = xo::reflect::TypeDescr; + using ppindentinfo = xo::print::ppindentinfo; + + public: + Primitive(std::string_view name, Fn fn) : name_{name}, + fn_td_{Reflect::require()}, + fn_{fn} {} + + TypeDescr fn_td() const noexcept { return fn_td_; } + + std::string_view name() const noexcept { return name_; } + static constexpr std::int32_t n_args() noexcept { return Traits::n_args; } + + bool is_nary() const noexcept { return false; } + + obj apply_nocheck(obj rcx, const DArray * args) { + return _apply_nocheck(rcx, args, + std::make_index_sequence{}); + } + + /** @defgroup scm-primitive-printable-facet **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + /** @defgroup scm-primitive-gcobject-facet **/ + ///@{ + std::size_t shallow_size() const noexcept; + Primitive * shallow_copy(obj mm) const noexcept; + std::size_t forward_children(obj gc) noexcept; + ///@} + + private: + template + obj _apply_nocheck(obj rcx, + const DArray * args, + std::index_sequence) + { + using xo::facet::FacetRegistry; + + using R = typename Traits::return_type; + + assert(args); + assert(args->size() > 0); + + obj mm = rcx.allocator(); + + R result + = fn_(rcx, + GCObjectConversion>::from_gco(mm, args->at(Is))... ); + + return GCObjectConversion::to_gco(mm, result); + } + + private: + /** name of this primitive **/ + std::string_view name_; + + /** type description for function + * Note that this type description will have additional first argument + * for obj + **/ + TypeDescr fn_td_; + + /** function implementation **/ + Fn fn_; + }; /*Primitive*/ + + template + bool + Primitive::pretty(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct + (ppii, + "Primitive", + refrtag("name", name_), + refrtag("td", fn_td_), + refrtag("fn", fn_)); + } + + template + std::size_t + Primitive::shallow_size() const noexcept { + return sizeof(*this); + } + + template + Primitive * + Primitive::shallow_copy(obj mm) const noexcept { + void * mem = mm.alloc_copy((std::byte *)this); + + if (mem) { + return new (mem) Primitive(*this); + } + + return nullptr; + } + + template + std::size_t + Primitive::forward_children(obj) noexcept { + // Primitive holds no GC refs (just string_view + function pointer) + return this->shallow_size(); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DPrimitive.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/DPrimitive_gco_2_gco_gco.hpp b/xo-procedure2/include/xo/procedure2/DPrimitive_gco_2_gco_gco.hpp new file mode 100644 index 00000000..78dd26b9 --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/DPrimitive_gco_2_gco_gco.hpp @@ -0,0 +1,22 @@ +/** @file DPrimitive_gco_2_gco_gco.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include +#include "DPrimitive.hpp" + +namespace xo { + namespace scm { + using xo::mm::AGCObject; + using xo::facet::obj; + + using DPrimitive_gco_2_gco_gco = Primitive (*)(obj, + obj, + obj)>; + } +} + +/* end DPrimitive_gco_2_gco_gco.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/DSimpleRcx.hpp b/xo-procedure2/include/xo/procedure2/DSimpleRcx.hpp new file mode 100644 index 00000000..bd52dcc5 --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/DSimpleRcx.hpp @@ -0,0 +1,34 @@ +/** @file DSimpleRcx.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include + +namespace xo { + namespace scm { + + /** @brief Minimal runtime context. + * + * Minimal runtime context provides an allocator, + * and nothing more. + **/ + class DSimpleRcx { + public: + using AAllocator = xo::mm::AAllocator; + + public: + DSimpleRcx(obj mm) : allocator_{mm} {} + + obj allocator() const noexcept { return allocator_; } + + private: + obj allocator_; + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DSimpleRcx.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/Primitive_gco_2_gco_gco.hpp b/xo-procedure2/include/xo/procedure2/Primitive_gco_2_gco_gco.hpp new file mode 100644 index 00000000..9e6814f4 --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/Primitive_gco_2_gco_gco.hpp @@ -0,0 +1,11 @@ +/** @file Primitive_gco_2_gco_gco.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "DPrimitive_gco_2_gco_gco.hpp" +#include "detail/IProcedure_DPrimitive_gco_2_gco_gco.hpp" +#include "detail/IGCObject_DPrimitive_gco_2_gco_gco.hpp" +#include "detail/IPrintable_DPrimitive_gco_2_gco_gco.hpp" + +/* end Primitive_gco_2_gco_gco.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/Procedure.hpp b/xo-procedure2/include/xo/procedure2/Procedure.hpp new file mode 100644 index 00000000..05d1b661 --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/Procedure.hpp @@ -0,0 +1,22 @@ +/** @file Procedure.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/Procedure.json5] + * 2. jinja2 template for facet .hpp file: + * [facet.hpp.j2] + * 3. idl for facet methods + * [idl/Procedure.json5] + **/ + +#pragma once + +#include "detail/AProcedure.hpp" +#include "detail/IProcedure_Any.hpp" +#include "detail/IProcedure_Xfer.hpp" +#include "detail/RProcedure.hpp" + + +/* end Procedure.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/RuntimeContext.hpp b/xo-procedure2/include/xo/procedure2/RuntimeContext.hpp new file mode 100644 index 00000000..48891944 --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/RuntimeContext.hpp @@ -0,0 +1,22 @@ +/** @file RuntimeContext.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/RuntimeContext.json5] + * 2. jinja2 template for facet .hpp file: + * [facet.hpp.j2] + * 3. idl for facet methods + * [idl/RuntimeContext.json5] + **/ + +#pragma once + +#include "detail/ARuntimeContext.hpp" +#include "detail/IRuntimeContext_Any.hpp" +#include "detail/IRuntimeContext_Xfer.hpp" +#include "detail/RRuntimeContext.hpp" + + +/* end RuntimeContext.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/SimpleRcx.hpp b/xo-procedure2/include/xo/procedure2/SimpleRcx.hpp new file mode 100644 index 00000000..2fdc4929 --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/SimpleRcx.hpp @@ -0,0 +1,11 @@ +/** @file SimpleRcx.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DSimpleRcx.hpp" +#include "detail/IRuntimeContext_DSimpleRcx.hpp" + +/* end SimpleRcx.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/detail/AProcedure.hpp b/xo-procedure2/include/xo/procedure2/detail/AProcedure.hpp new file mode 100644 index 00000000..eb119fbd --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/detail/AProcedure.hpp @@ -0,0 +1,81 @@ +/** @file AProcedure.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/Procedure.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [abstract_facet.hpp.j2] + * 3. idl for facet methods + * [idl/Procedure.json5] + **/ + +#pragma once + +// includes (via {facet_includes}) +#include "RuntimeContext.hpp" +#include +#include +#include +#include + +namespace xo { namespace scm { class DArray; } } + +namespace xo { +namespace scm { + +using Copaque = const void *; +using Opaque = void *; + +/** +Abstraction for a schematika procedure +**/ +class AProcedure { +public: + /** @defgroup scm-procedure-type-traits **/ + ///@{ + // types + /** integer identifying a type **/ + using typeseq = xo::facet::typeseq; + using Copaque = const void *; + using Opaque = void *; + /** a gc-aware object **/ + using AGCObject = xo::mm::AGCObject; + ///@} + + /** @defgroup scm-procedure-methods **/ + ///@{ + // const methods + /** RTTI: unique id# for actual runtime data representation **/ + virtual typeseq _typeseq() const noexcept = 0; + /** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/ + virtual void _drop(Opaque d) const noexcept = 0; + /** true iff procedure takes n arguments **/ + virtual bool is_nary(Copaque data) const noexcept = 0; + /** number of arguments. -1 for n-ary **/ + virtual std::int32_t n_args(Copaque data) const noexcept = 0; + + // nonconst methods + /** invoke procedure; assume arguments satisfy type system **/ + virtual obj apply_nocheck(Opaque data, obj rcx, const DArray * args) = 0; + ///@} +}; /*AProcedure*/ + +/** Implementation IProcedure_DRepr of AProcedure for state DRepr + * should provide a specialization: + * + * template <> + * struct xo::facet::FacetImplementation { + * using Impltype = IProcedure_DRepr; + * }; + * + * then IProcedure_ImplType --> IProcedure_DRepr + **/ +template +using IProcedure_ImplType = xo::facet::FacetImplType; + +} /*namespace scm*/ +} /*namespace xo*/ + +/* AProcedure.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/detail/ARuntimeContext.hpp b/xo-procedure2/include/xo/procedure2/detail/ARuntimeContext.hpp new file mode 100644 index 00000000..09831870 --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/detail/ARuntimeContext.hpp @@ -0,0 +1,75 @@ +/** @file ARuntimeContext.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/RuntimeContext.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [abstract_facet.hpp.j2] + * 3. idl for facet methods + * [idl/RuntimeContext.json5] + **/ + +#pragma once + +// includes (via {facet_includes}) +#include +#include +#include +#include + + +namespace xo { +namespace scm { + +using Copaque = const void *; +using Opaque = void *; + +/** +Runtime application context +**/ +class ARuntimeContext { +public: + /** @defgroup scm-runtimecontext-type-traits **/ + ///@{ + // types + /** integer identifying a type **/ + using typeseq = xo::facet::typeseq; + using Copaque = const void *; + using Opaque = void *; + /** xo memory allocator **/ + using AAllocator = xo::mm::AAllocator; + ///@} + + /** @defgroup scm-runtimecontext-methods **/ + ///@{ + // const methods + /** RTTI: unique id# for actual runtime data representation **/ + virtual typeseq _typeseq() const noexcept = 0; + /** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/ + virtual void _drop(Opaque d) const noexcept = 0; + /** default allocator to use for objects **/ + virtual obj allocator(Copaque data) const noexcept = 0; + + // nonconst methods + ///@} +}; /*ARuntimeContext*/ + +/** Implementation IRuntimeContext_DRepr of ARuntimeContext for state DRepr + * should provide a specialization: + * + * template <> + * struct xo::facet::FacetImplementation { + * using Impltype = IRuntimeContext_DRepr; + * }; + * + * then IRuntimeContext_ImplType --> IRuntimeContext_DRepr + **/ +template +using IRuntimeContext_ImplType = xo::facet::FacetImplType; + +} /*namespace scm*/ +} /*namespace xo*/ + +/* ARuntimeContext.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/detail/IGCObject_DPrimitive_gco_2_gco_gco.hpp b/xo-procedure2/include/xo/procedure2/detail/IGCObject_DPrimitive_gco_2_gco_gco.hpp new file mode 100644 index 00000000..f6bfe6ed --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/detail/IGCObject_DPrimitive_gco_2_gco_gco.hpp @@ -0,0 +1,67 @@ +/** @file IGCObject_DPrimitive_gco_2_gco_gco.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DPrimitive_gco_2_gco_gco.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DPrimitive_gco_2_gco_gco.json5] + **/ + +#pragma once + +#include "GCObject.hpp" +#include +#include +#include "DPrimitive_gco_2_gco_gco.hpp" + +namespace xo { namespace scm { class IGCObject_DPrimitive_gco_2_gco_gco; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::mm::IGCObject_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IGCObject_DPrimitive_gco_2_gco_gco + **/ + class IGCObject_DPrimitive_gco_2_gco_gco { + public: + /** @defgroup scm-gcobject-dprimitive_gco_2_gco_gco-type-traits **/ + ///@{ + using size_type = xo::mm::AGCObject::size_type; + using AAllocator = xo::mm::AGCObject::AAllocator; + using ACollector = xo::mm::AGCObject::ACollector; + using Copaque = xo::mm::AGCObject::Copaque; + using Opaque = xo::mm::AGCObject::Opaque; + ///@} + /** @defgroup scm-gcobject-dprimitive_gco_2_gco_gco-methods **/ + ///@{ + // const methods + /** memory consumption for this instance **/ + static size_type shallow_size(const DPrimitive_gco_2_gco_gco & self) noexcept; + /** copy instance using allocator **/ + static Opaque shallow_copy(const DPrimitive_gco_2_gco_gco & self, obj mm) noexcept; + + // non-const methods + /** during GC: forward immdiate children **/ + static size_type forward_children(DPrimitive_gco_2_gco_gco & self, obj gc) noexcept; + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-procedure2/include/xo/procedure2/detail/IPrintable_DPrimitive_gco_2_gco_gco.hpp b/xo-procedure2/include/xo/procedure2/detail/IPrintable_DPrimitive_gco_2_gco_gco.hpp new file mode 100644 index 00000000..688ee6eb --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/detail/IPrintable_DPrimitive_gco_2_gco_gco.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DPrimitive_gco_2_gco_gco.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DPrimitive_gco_2_gco_gco.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DPrimitive_gco_2_gco_gco.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DPrimitive_gco_2_gco_gco.hpp" + +namespace xo { namespace scm { class IPrintable_DPrimitive_gco_2_gco_gco; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DPrimitive_gco_2_gco_gco + **/ + class IPrintable_DPrimitive_gco_2_gco_gco { + public: + /** @defgroup scm-printable-dprimitive_gco_2_gco_gco-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dprimitive_gco_2_gco_gco-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DPrimitive_gco_2_gco_gco & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-procedure2/include/xo/procedure2/detail/IProcedure_Any.hpp b/xo-procedure2/include/xo/procedure2/detail/IProcedure_Any.hpp new file mode 100644 index 00000000..10dccea5 --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/detail/IProcedure_Any.hpp @@ -0,0 +1,91 @@ +/** @file IProcedure_Any.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/Procedure.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/Procedure.json5] + **/ + +#pragma once + +#include "AProcedure.hpp" +#include + +namespace xo { namespace scm { class IProcedure_Any; } } + +namespace xo { +namespace facet { + +template <> +struct FacetImplementation +{ + using ImplType = xo::scm::IProcedure_Any; +}; + +} +} + +namespace xo { +namespace scm { + + /** @class IProcedure_Any + * @brief AProcedure implementation for empty variant instance + **/ + class IProcedure_Any : public AProcedure { + public: + /** @defgroup scm-procedure-any-type-traits **/ + ///@{ + + /** integer identifying a type **/ + using typeseq = xo::facet::typeseq; + using AGCObject = AProcedure::AGCObject; + + ///@} + /** @defgroup scm-procedure-any-methods **/ + ///@{ + + const AProcedure * iface() const { return std::launder(this); } + + // from AProcedure + + // builtin methods + typeseq _typeseq() const noexcept override { return s_typeseq; } + [[noreturn]] void _drop(Opaque) const noexcept override { _fatal(); } + + // const methods + [[noreturn]] bool is_nary(Copaque) const noexcept override { _fatal(); } + [[noreturn]] std::int32_t n_args(Copaque) const noexcept override { _fatal(); } + + // nonconst methods + [[noreturn]] obj apply_nocheck(Opaque, obj, const DArray *) override; + + ///@} + + private: + /** @defgraoup scm-procedure-any-private-methods **/ + ///@{ + + [[noreturn]] static void _fatal(); + + ///@} + + public: + /** @defgroup scm-procedure-any-member-vars **/ + ///@{ + + static typeseq s_typeseq; + static bool _valid; + + ///@} + }; + +} /*namespace scm */ +} /*namespace xo */ + +/* IProcedure_Any.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/detail/IProcedure_DPrimitive_gco_2_gco_gco.hpp b/xo-procedure2/include/xo/procedure2/detail/IProcedure_DPrimitive_gco_2_gco_gco.hpp new file mode 100644 index 00000000..858edfa5 --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/detail/IProcedure_DPrimitive_gco_2_gco_gco.hpp @@ -0,0 +1,67 @@ +/** @file IProcedure_DPrimitive_gco_2_gco_gco.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IProcedure_DPrimitive_gco_2_gco_gco.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IProcedure_DPrimitive_gco_2_gco_gco.json5] + **/ + +#pragma once + +#include "Procedure.hpp" +#include +#include +#include +#include +#include "DPrimitive_gco_2_gco_gco.hpp" + +namespace xo { namespace scm { class IProcedure_DPrimitive_gco_2_gco_gco; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::IProcedure_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IProcedure_DPrimitive_gco_2_gco_gco + **/ + class IProcedure_DPrimitive_gco_2_gco_gco { + public: + /** @defgroup scm-procedure-dprimitive_gco_2_gco_gco-type-traits **/ + ///@{ + using AGCObject = xo::scm::AProcedure::AGCObject; + using Copaque = xo::scm::AProcedure::Copaque; + using Opaque = xo::scm::AProcedure::Opaque; + ///@} + /** @defgroup scm-procedure-dprimitive_gco_2_gco_gco-methods **/ + ///@{ + // const methods + /** true iff procedure takes n arguments **/ + static bool is_nary(const DPrimitive_gco_2_gco_gco & self) noexcept; + /** number of arguments. -1 for n-ary **/ + static std::int32_t n_args(const DPrimitive_gco_2_gco_gco & self) noexcept; + + // non-const methods + /** invoke procedure; assume arguments satisfy type system **/ + static obj apply_nocheck(DPrimitive_gco_2_gco_gco & self, obj rcx, const DArray * args); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-procedure2/include/xo/procedure2/detail/IProcedure_Xfer.hpp b/xo-procedure2/include/xo/procedure2/detail/IProcedure_Xfer.hpp new file mode 100644 index 00000000..0be093fb --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/detail/IProcedure_Xfer.hpp @@ -0,0 +1,91 @@ +/** @file IProcedure_Xfer.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/Procedure.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/Procedure.json5] + **/ + +#pragma once + +#include "RuntimeContext.hpp" +#include + +namespace xo { +namespace scm { + /** @class IProcedure_Xfer + **/ + template + class IProcedure_Xfer : public AProcedure { + public: + /** @defgroup scm-procedure-xfer-type-traits **/ + ///@{ + /** actual implementation (not generated; often delegates to DRepr) **/ + using Impl = IProcedure_DRepr; + /** integer identifying a type **/ + using typeseq = AProcedure::typeseq; + using AGCObject = AProcedure::AGCObject; + ///@} + + /** @defgroup scm-procedure-xfer-methods **/ + ///@{ + + static const DRepr & _dcast(Copaque d) { return *(const DRepr *)d; } + static DRepr & _dcast(Opaque d) { return *(DRepr *)d; } + + // from AProcedure + + // builtin methods + typeseq _typeseq() const noexcept override { return s_typeseq; } + void _drop(Opaque d) const noexcept override { _dcast(d).~DRepr(); } + + // const methods + bool is_nary(Copaque data) const noexcept override { + return I::is_nary(_dcast(data)); + } + std::int32_t n_args(Copaque data) const noexcept override { + return I::n_args(_dcast(data)); + } + + // non-const methods + obj apply_nocheck(Opaque data, obj rcx, const DArray * args) override { + return I::apply_nocheck(_dcast(data), rcx, args); + } + + ///@} + + private: + using I = Impl; + + public: + /** @defgroup scm-procedure-xfer-member-vars **/ + ///@{ + + /** typeseq for template parameter DRepr **/ + static typeseq s_typeseq; + /** true iff satisfies facet implementation **/ + static bool _valid; + + ///@} + }; + + template + xo::facet::typeseq + IProcedure_Xfer::s_typeseq + = xo::facet::typeseq::id(); + + template + bool + IProcedure_Xfer::_valid + = xo::facet::valid_facet_implementation(); + +} /*namespace scm */ +} /*namespace xo*/ + +/* end IProcedure_Xfer.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/detail/IRuntimeContext_Any.hpp b/xo-procedure2/include/xo/procedure2/detail/IRuntimeContext_Any.hpp new file mode 100644 index 00000000..cb6dfa45 --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/detail/IRuntimeContext_Any.hpp @@ -0,0 +1,89 @@ +/** @file IRuntimeContext_Any.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/RuntimeContext.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/RuntimeContext.json5] + **/ + +#pragma once + +#include "ARuntimeContext.hpp" +#include + +namespace xo { namespace scm { class IRuntimeContext_Any; } } + +namespace xo { +namespace facet { + +template <> +struct FacetImplementation +{ + using ImplType = xo::scm::IRuntimeContext_Any; +}; + +} +} + +namespace xo { +namespace scm { + + /** @class IRuntimeContext_Any + * @brief ARuntimeContext implementation for empty variant instance + **/ + class IRuntimeContext_Any : public ARuntimeContext { + public: + /** @defgroup scm-runtimecontext-any-type-traits **/ + ///@{ + + /** integer identifying a type **/ + using typeseq = xo::facet::typeseq; + using AAllocator = ARuntimeContext::AAllocator; + + ///@} + /** @defgroup scm-runtimecontext-any-methods **/ + ///@{ + + const ARuntimeContext * iface() const { return std::launder(this); } + + // from ARuntimeContext + + // builtin methods + typeseq _typeseq() const noexcept override { return s_typeseq; } + [[noreturn]] void _drop(Opaque) const noexcept override { _fatal(); } + + // const methods + [[noreturn]] obj allocator(Copaque) const noexcept override { _fatal(); } + + // nonconst methods + + ///@} + + private: + /** @defgraoup scm-runtimecontext-any-private-methods **/ + ///@{ + + [[noreturn]] static void _fatal(); + + ///@} + + public: + /** @defgroup scm-runtimecontext-any-member-vars **/ + ///@{ + + static typeseq s_typeseq; + static bool _valid; + + ///@} + }; + +} /*namespace scm */ +} /*namespace xo */ + +/* IRuntimeContext_Any.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/detail/IRuntimeContext_DSimpleRcx.hpp b/xo-procedure2/include/xo/procedure2/detail/IRuntimeContext_DSimpleRcx.hpp new file mode 100644 index 00000000..247b6762 --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/detail/IRuntimeContext_DSimpleRcx.hpp @@ -0,0 +1,59 @@ +/** @file IRuntimeContext_DSimpleRcx.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IRuntimeContext_DSimpleRcx.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IRuntimeContext_DSimpleRcx.json5] + **/ + +#pragma once + +#include "RuntimeContext.hpp" +#include "DSimpleRcx.hpp" + +namespace xo { namespace scm { class IRuntimeContext_DSimpleRcx; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::IRuntimeContext_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IRuntimeContext_DSimpleRcx + **/ + class IRuntimeContext_DSimpleRcx { + public: + /** @defgroup scm-runtimecontext-dsimplercx-type-traits **/ + ///@{ + using AAllocator = xo::scm::ARuntimeContext::AAllocator; + using Copaque = xo::scm::ARuntimeContext::Copaque; + using Opaque = xo::scm::ARuntimeContext::Opaque; + ///@} + /** @defgroup scm-runtimecontext-dsimplercx-methods **/ + ///@{ + // const methods + /** default allocator to use for objects **/ + static obj allocator(const DSimpleRcx & self) noexcept; + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-procedure2/include/xo/procedure2/detail/IRuntimeContext_Xfer.hpp b/xo-procedure2/include/xo/procedure2/detail/IRuntimeContext_Xfer.hpp new file mode 100644 index 00000000..a4545b8f --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/detail/IRuntimeContext_Xfer.hpp @@ -0,0 +1,84 @@ +/** @file IRuntimeContext_Xfer.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/RuntimeContext.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/RuntimeContext.json5] + **/ + +#pragma once + +#include + +namespace xo { +namespace scm { + /** @class IRuntimeContext_Xfer + **/ + template + class IRuntimeContext_Xfer : public ARuntimeContext { + public: + /** @defgroup scm-runtimecontext-xfer-type-traits **/ + ///@{ + /** actual implementation (not generated; often delegates to DRepr) **/ + using Impl = IRuntimeContext_DRepr; + /** integer identifying a type **/ + using typeseq = ARuntimeContext::typeseq; + using AAllocator = ARuntimeContext::AAllocator; + ///@} + + /** @defgroup scm-runtimecontext-xfer-methods **/ + ///@{ + + static const DRepr & _dcast(Copaque d) { return *(const DRepr *)d; } + static DRepr & _dcast(Opaque d) { return *(DRepr *)d; } + + // from ARuntimeContext + + // builtin methods + typeseq _typeseq() const noexcept override { return s_typeseq; } + void _drop(Opaque d) const noexcept override { _dcast(d).~DRepr(); } + + // const methods + obj allocator(Copaque data) const noexcept override { + return I::allocator(_dcast(data)); + } + + // non-const methods + + ///@} + + private: + using I = Impl; + + public: + /** @defgroup scm-runtimecontext-xfer-member-vars **/ + ///@{ + + /** typeseq for template parameter DRepr **/ + static typeseq s_typeseq; + /** true iff satisfies facet implementation **/ + static bool _valid; + + ///@} + }; + + template + xo::facet::typeseq + IRuntimeContext_Xfer::s_typeseq + = xo::facet::typeseq::id(); + + template + bool + IRuntimeContext_Xfer::_valid + = xo::facet::valid_facet_implementation(); + +} /*namespace scm */ +} /*namespace xo*/ + +/* end IRuntimeContext_Xfer.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/detail/RProcedure.hpp b/xo-procedure2/include/xo/procedure2/detail/RProcedure.hpp new file mode 100644 index 00000000..191bd37e --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/detail/RProcedure.hpp @@ -0,0 +1,91 @@ +/** @file RProcedure.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/Procedure.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/Procedure.json5] + **/ + +#pragma once + +#include "AProcedure.hpp" + +namespace xo { +namespace scm { + +/** @class RProcedure + **/ +template +class RProcedure : public Object { +private: + using O = Object; + +public: + /** @defgroup scm-procedure-router-type-traits **/ + ///@{ + using ObjectType = Object; + using DataPtr = Object::DataPtr; + using typeseq = xo::reflect::typeseq; + using AGCObject = AProcedure::AGCObject; + ///@} + + /** @defgroup scm-procedure-router-ctors **/ + ///@{ + RProcedure() {} + RProcedure(Object::DataPtr data) : Object{std::move(data)} {} + RProcedure(const AProcedure * iface, void * data) + requires std::is_same_v + : Object(iface, data) {} + + ///@} + /** @defgroup scm-procedure-router-methods **/ + ///@{ + + // explicit injected content + + // builtin methods + typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); } + void _drop() const noexcept { O::iface()->_drop(O::data()); } + + // const methods + bool is_nary() const noexcept { + return O::iface()->is_nary(O::data()); + } + std::int32_t n_args() const noexcept { + return O::iface()->n_args(O::data()); + } + + // non-const methods (still const in router!) + obj apply_nocheck(obj rcx, const DArray * args) { + return O::iface()->apply_nocheck(O::data(), rcx, args); + } + + ///@} + /** @defgroup scm-procedure-member-vars **/ + ///@{ + + static bool _valid; + + ///@} +}; + +template +bool +RProcedure::_valid = xo::facet::valid_object_router(); + +} /*namespace scm*/ +} /*namespace xo*/ + +namespace xo { namespace facet { + template + struct RoutingFor { + using RoutingType = xo::scm::RProcedure; + }; +} } + +/* end RProcedure.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/detail/RRuntimeContext.hpp b/xo-procedure2/include/xo/procedure2/detail/RRuntimeContext.hpp new file mode 100644 index 00000000..a9e161ed --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/detail/RRuntimeContext.hpp @@ -0,0 +1,85 @@ +/** @file RRuntimeContext.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/RuntimeContext.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/RuntimeContext.json5] + **/ + +#pragma once + +#include "ARuntimeContext.hpp" + +namespace xo { +namespace scm { + +/** @class RRuntimeContext + **/ +template +class RRuntimeContext : public Object { +private: + using O = Object; + +public: + /** @defgroup scm-runtimecontext-router-type-traits **/ + ///@{ + using ObjectType = Object; + using DataPtr = Object::DataPtr; + using typeseq = xo::reflect::typeseq; + using AAllocator = ARuntimeContext::AAllocator; + ///@} + + /** @defgroup scm-runtimecontext-router-ctors **/ + ///@{ + RRuntimeContext() {} + RRuntimeContext(Object::DataPtr data) : Object{std::move(data)} {} + RRuntimeContext(const ARuntimeContext * iface, void * data) + requires std::is_same_v + : Object(iface, data) {} + + ///@} + /** @defgroup scm-runtimecontext-router-methods **/ + ///@{ + + // explicit injected content + + // builtin methods + typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); } + void _drop() const noexcept { O::iface()->_drop(O::data()); } + + // const methods + obj allocator() const noexcept { + return O::iface()->allocator(O::data()); + } + + // non-const methods (still const in router!) + + ///@} + /** @defgroup scm-runtimecontext-member-vars **/ + ///@{ + + static bool _valid; + + ///@} +}; + +template +bool +RRuntimeContext::_valid = xo::facet::valid_object_router(); + +} /*namespace scm*/ +} /*namespace xo*/ + +namespace xo { namespace facet { + template + struct RoutingFor { + using RoutingType = xo::scm::RRuntimeContext; + }; +} } + +/* end RRuntimeContext.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/init_primitives.hpp b/xo-procedure2/include/xo/procedure2/init_primitives.hpp new file mode 100644 index 00000000..6747fa6b --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/init_primitives.hpp @@ -0,0 +1,56 @@ +/** @file init_primitives.hpp **/ + +#pragma once + +#include "DPrimitive.hpp" +#include "DPrimitive_gco_2_gco_gco.hpp" + +namespace xo { + namespace scm { +/** TODO: move this into xo-reader2 ? **/ + +#ifdef NOT_YET + using Primitive_f64_1_f64 = Primitive; + using Primitive_f64_2_f64_f64 = Primitive; +#endif + + struct Primitives { + /** polymorphic multiply + * + * TODO: this will want to move to xo-numeric/ + * so we can dispatch on vector, matrix, function types + **/ + static DPrimitive_gco_2_gco_gco s_mul_gco_gco_pm; + + /** polymorphic subtract + * + * TODO: this will want to move to xo-numeric/ + * so we can dispatch on vector, matrix, function types + **/ + static DPrimitive_gco_2_gco_gco s_sub_gco_gco_pm; + + /** polymorphic equality comparison + * + * TODO: this will want to move to x-numeric/ + **/ + static DPrimitive_gco_2_gco_gco s_equal_gco_gco_pm; + +#ifdef NOT_YET + static Primitive_f64_1_f64 s_neg_f64_pm; + + static Primitive_f64_2_f64_f64 s_add_f64_f64_pm; + static Primitive_f64_2_f64_f64 s_sub_f64_f64_pm; + static Primitive_f64_2_f64_f64 s_mul_f64_f64_pm; + static Primitive_f64_2_f64_f64 s_div_f64_f64_pm; + static Primitive_f64_2_f64_f64 s_pow_f64_f64_pm; + + static Primitive_f64_1_f64 s_log_f64_pm; + static Primitive_f64_1_f64 s_sin_f64_pm; + static Primitive_f64_1_f64 s_cos_f64_pm; + static Primitive_f64_1_f64 s_tan_f64_pm; +#endif + }; + } +} + +/* end init_primitives.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/init_procedure2.hpp b/xo-procedure2/include/xo/procedure2/init_procedure2.hpp new file mode 100644 index 00000000..793cc061 --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/init_procedure2.hpp @@ -0,0 +1,21 @@ +/** @file init_procedure2.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include + +namespace xo { + /* tag to represent the xo-procedure2/ subsystem within ordered iniitalization */ + enum S_procedure2_tag {}; + + template <> + struct InitSubsys { + static void init(); + static InitEvidence require(); + }; +} /*namespace xo*/ + +/* end init_procedure2.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/primitives.hpp b/xo-procedure2/include/xo/procedure2/primitives.hpp new file mode 100644 index 00000000..e2e0d88a --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/primitives.hpp @@ -0,0 +1,13 @@ +/** @file primitives.hpp **/ + +#pragma once + +namespace xo { + namespace scm { + struct Primitives { + static void init_primitives(); + }; + } +} + +/* end primitives.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/procedure2_register_facets.hpp b/xo-procedure2/include/xo/procedure2/procedure2_register_facets.hpp new file mode 100644 index 00000000..219da3d4 --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/procedure2_register_facets.hpp @@ -0,0 +1,17 @@ +/** @file procedure2_register_facets.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include + +namespace xo { + namespace scm { + /** Register procedure2 (facet,impl) combinations with FacetRegistry **/ + bool procedure2_register_facets(); + } +} + +/* end procedure2_register_facets.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/procedure2_register_types.hpp b/xo-procedure2/include/xo/procedure2/procedure2_register_types.hpp new file mode 100644 index 00000000..be0170aa --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/procedure2_register_types.hpp @@ -0,0 +1,17 @@ +/** @file procedure2_register_types.hpp + * + * @author Roland Conybeare, Dec 2025 + **/ + +#pragma once + +#include + +namespace xo { + namespace scm { + /** Register gc-aware (AGCObject,DRepr) combinations with garbage collector @p gc **/ + bool procedure2_register_types(obj gc); + } +} + +/* end procedure2_register_types.hpp */ diff --git a/xo-procedure2/src/procedure2/CMakeLists.txt b/xo-procedure2/src/procedure2/CMakeLists.txt new file mode 100644 index 00000000..92685afb --- /dev/null +++ b/xo-procedure2/src/procedure2/CMakeLists.txt @@ -0,0 +1,42 @@ +# xo-procedure2/src/CMakeLists.txt + +set(SELF_LIB xo_procedure2) +set(SELF_SRCS + init_procedure2.cpp + init_primitives.cpp + procedure2_register_types.cpp + procedure2_register_facets.cpp + IRuntimeContext_Any.cpp + IRuntimeContext_DSimpleRcx.cpp + IProcedure_Any.cpp + DPrimitive.cpp + IGCObject_DPrimitive_gco_2_gco_gco.cpp + IProcedure_DPrimitive_gco_2_gco_gco.cpp + IPrintable_DPrimitive_gco_2_gco_gco.cpp + # Add source files here, e.g.: + # procedure2.cpp +) + +xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS}) +xo_install_include_tree3(include/xo/procedure2) + +# ---------------------------------------------------------------- +# input dependencies +# +# NOTE: dependency set here must be kept consistent with +# xo-procedure2/cmake/xo_procedure2Config.cmake.in + +xo_dependency(${SELF_LIB} xo_object2) +xo_dependency(${SELF_LIB} xo_gc) +xo_dependency(${SELF_LIB} subsys) +#xo_dependency(${SELF_LIB} xo_indentlog) + +xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets) + +# ---------------------------------------------------------------- +# docs targets depend on other library/utest/exec targets above, +# --> must come after them. +# +#add_subdirectory(docs) + +# end src/CMakeLists.txt diff --git a/xo-procedure2/src/procedure2/DPrimitive.cpp b/xo-procedure2/src/procedure2/DPrimitive.cpp new file mode 100644 index 00000000..ab335d8d --- /dev/null +++ b/xo-procedure2/src/procedure2/DPrimitive.cpp @@ -0,0 +1,16 @@ +/** @file DPrimitive.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "DPrimitive.hpp" +#include + +namespace xo { + namespace scm { + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DPrimitive.cpp */ diff --git a/xo-procedure2/src/procedure2/IGCObject_DPrimitive_gco_2_gco_gco.cpp b/xo-procedure2/src/procedure2/IGCObject_DPrimitive_gco_2_gco_gco.cpp new file mode 100644 index 00000000..b889d0d0 --- /dev/null +++ b/xo-procedure2/src/procedure2/IGCObject_DPrimitive_gco_2_gco_gco.cpp @@ -0,0 +1,39 @@ +/** @file IGCObject_DPrimitive_gco_2_gco_gco.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IGCObject_DPrimitive_gco_2_gco_gco.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IGCObject_DPrimitive_gco_2_gco_gco.json5] +**/ + +#include "detail/IGCObject_DPrimitive_gco_2_gco_gco.hpp" + +namespace xo { + namespace scm { + auto + IGCObject_DPrimitive_gco_2_gco_gco::shallow_size(const DPrimitive_gco_2_gco_gco & self) noexcept -> size_type + { + return self.shallow_size(); + } + + auto + IGCObject_DPrimitive_gco_2_gco_gco::shallow_copy(const DPrimitive_gco_2_gco_gco & self, obj mm) noexcept -> Opaque + { + return self.shallow_copy(mm); + } + + auto + IGCObject_DPrimitive_gco_2_gco_gco::forward_children(DPrimitive_gco_2_gco_gco & self, obj gc) noexcept -> size_type + { + return self.forward_children(gc); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DPrimitive_gco_2_gco_gco.cpp */ diff --git a/xo-procedure2/src/procedure2/IPrintable_DPrimitive_gco_2_gco_gco.cpp b/xo-procedure2/src/procedure2/IPrintable_DPrimitive_gco_2_gco_gco.cpp new file mode 100644 index 00000000..c8b7c2d8 --- /dev/null +++ b/xo-procedure2/src/procedure2/IPrintable_DPrimitive_gco_2_gco_gco.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DPrimitive_gco_2_gco_gco.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DPrimitive_gco_2_gco_gco.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DPrimitive_gco_2_gco_gco.json5] +**/ + +#include "detail/IPrintable_DPrimitive_gco_2_gco_gco.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DPrimitive_gco_2_gco_gco::pretty(const DPrimitive_gco_2_gco_gco & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DPrimitive_gco_2_gco_gco.cpp */ diff --git a/xo-procedure2/src/procedure2/IProcedure_Any.cpp b/xo-procedure2/src/procedure2/IProcedure_Any.cpp new file mode 100644 index 00000000..dcdf9eeb --- /dev/null +++ b/xo-procedure2/src/procedure2/IProcedure_Any.cpp @@ -0,0 +1,47 @@ +/** @file IProcedure_Any.cpp + * + **/ + +#include "detail/IProcedure_Any.hpp" +#include + +namespace xo { +namespace scm { + +using xo::facet::DVariantPlaceholder; +using xo::facet::typeseq; +using xo::facet::valid_facet_implementation; + +void +IProcedure_Any::_fatal() +{ + /* control here on uninitialized IAllocator_Any. + * Initialized instance will have specific implementation type + */ + std::cerr << "fatal" + << ": attempt to call uninitialized" + << " IProcedure_Any method" + << std::endl; + std::terminate(); +} + +typeseq +IProcedure_Any::s_typeseq = typeseq::id(); + +bool +IProcedure_Any::_valid + = valid_facet_implementation(); + +// nonconst methods + +auto +IProcedure_Any::apply_nocheck(Opaque, obj, const DArray *) -> obj +{ + _fatal(); +} + + +} /*namespace scm*/ +} /*namespace xo*/ + +/* end IProcedure_Any.cpp */ diff --git a/xo-procedure2/src/procedure2/IProcedure_DPrimitive_gco_2_gco_gco.cpp b/xo-procedure2/src/procedure2/IProcedure_DPrimitive_gco_2_gco_gco.cpp new file mode 100644 index 00000000..1207429f --- /dev/null +++ b/xo-procedure2/src/procedure2/IProcedure_DPrimitive_gco_2_gco_gco.cpp @@ -0,0 +1,39 @@ +/** @file IProcedure_DPrimitive_gco_2_gco_gco.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IProcedure_DPrimitive_gco_2_gco_gco.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IProcedure_DPrimitive_gco_2_gco_gco.json5] +**/ + +#include "detail/IProcedure_DPrimitive_gco_2_gco_gco.hpp" + +namespace xo { + namespace scm { + auto + IProcedure_DPrimitive_gco_2_gco_gco::is_nary(const DPrimitive_gco_2_gco_gco & self) noexcept -> bool + { + return self.is_nary(); + } + + auto + IProcedure_DPrimitive_gco_2_gco_gco::n_args(const DPrimitive_gco_2_gco_gco & self) noexcept -> std::int32_t + { + return self.n_args(); + } + + auto + IProcedure_DPrimitive_gco_2_gco_gco::apply_nocheck(DPrimitive_gco_2_gco_gco & self, obj rcx, const DArray * args) -> obj + { + return self.apply_nocheck(rcx, args); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IProcedure_DPrimitive_gco_2_gco_gco.cpp */ diff --git a/xo-procedure2/src/procedure2/IRuntimeContext_Any.cpp b/xo-procedure2/src/procedure2/IRuntimeContext_Any.cpp new file mode 100644 index 00000000..1ea5859a --- /dev/null +++ b/xo-procedure2/src/procedure2/IRuntimeContext_Any.cpp @@ -0,0 +1,41 @@ +/** @file IRuntimeContext_Any.cpp + * + **/ + +#include "detail/IRuntimeContext_Any.hpp" +#include + +namespace xo { +namespace scm { + +using xo::facet::DVariantPlaceholder; +using xo::facet::typeseq; +using xo::facet::valid_facet_implementation; + +void +IRuntimeContext_Any::_fatal() +{ + /* control here on uninitialized IAllocator_Any. + * Initialized instance will have specific implementation type + */ + std::cerr << "fatal" + << ": attempt to call uninitialized" + << " IRuntimeContext_Any method" + << std::endl; + std::terminate(); +} + +typeseq +IRuntimeContext_Any::s_typeseq = typeseq::id(); + +bool +IRuntimeContext_Any::_valid + = valid_facet_implementation(); + +// nonconst methods + + +} /*namespace scm*/ +} /*namespace xo*/ + +/* end IRuntimeContext_Any.cpp */ diff --git a/xo-procedure2/src/procedure2/IRuntimeContext_DSimpleRcx.cpp b/xo-procedure2/src/procedure2/IRuntimeContext_DSimpleRcx.cpp new file mode 100644 index 00000000..f057220d --- /dev/null +++ b/xo-procedure2/src/procedure2/IRuntimeContext_DSimpleRcx.cpp @@ -0,0 +1,28 @@ +/** @file IRuntimeContext_DSimpleRcx.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IRuntimeContext_DSimpleRcx.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IRuntimeContext_DSimpleRcx.json5] +**/ + +#include "detail/IRuntimeContext_DSimpleRcx.hpp" + +namespace xo { + namespace scm { + auto + IRuntimeContext_DSimpleRcx::allocator(const DSimpleRcx & self) noexcept -> obj + { + return self.allocator(); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IRuntimeContext_DSimpleRcx.cpp */ diff --git a/xo-procedure2/src/procedure2/init_primitives.cpp b/xo-procedure2/src/procedure2/init_primitives.cpp new file mode 100644 index 00000000..f3759f4b --- /dev/null +++ b/xo-procedure2/src/procedure2/init_primitives.cpp @@ -0,0 +1,303 @@ +/** @file init_primitives.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "init_primitives.hpp" +#include "DPrimitive.hpp" +#include +//#include +#include +//#include +#include +#include +#include +#include +#include +#include + +namespace xo { + using xo::mm::AAllocator; + using xo::scm::DFloat; + using xo::facet::with_facet; + + namespace scm { +#ifdef NOT_YET + double + neg_f64(double x) { + return -x; + } + + double + add_f64_f64(double x, double y) { + return x + y; + } + + double + sub_f64_f64(double x, double y) { + return x - y; + } +#endif + + obj + mul_gco_gco(obj rcx, + obj x_gco, + obj y_gco) + { + using xo::reflect::typeseq; + + obj mm = rcx.allocator(); + + // PLACEHOLDER + + // TODO: + // 1. move this to xo-numeric2/ when available + // 2. at that point will require polymorphic dispatch + // on argument representations, analogous to dispatch + // in FacetRegistry + + typeseq x_tseq = x_gco._typeseq(); + typeseq y_tseq = y_gco._typeseq(); + + // FOR NOW: just test runtime values + // + if (x_tseq == typeseq::id()) { + // i64 * .. + long x = GCObjectConversion::from_gco(mm, x_gco); + + if (y_tseq == typeseq::id()) { + // i64 * i64 + long y = GCObjectConversion::from_gco(mm, y_gco); + + return DInteger::box(mm, x * y); + } else if (y_tseq == typeseq::id()) { + // i64 * f64 + double y = GCObjectConversion::from_gco(mm, y_gco); + + return DFloat::box(mm, x * y); + } + } else if (x_tseq == typeseq::id()) { + if (y_tseq == typeseq::id()) { + // f64 * i64. + double x = GCObjectConversion::from_gco(mm, x_gco); + long y = GCObjectConversion::from_gco(mm, y_gco); + + return DFloat::box(mm, x * y); + } else if (y_tseq == typeseq::id()) { + // f64 * f64. + double x = GCObjectConversion::from_gco(mm, x_gco); + double y = GCObjectConversion::from_gco(mm, y_gco); + + return DFloat::box(mm, x * y); + } + } + + // here: error + throw std::runtime_error(tostr("mul_gco_gco: unexpected argument types xt,yt", + xtag("x.tseq", x_tseq), + xtag("y.tseq", y_tseq))); + return obj(); + } + + obj + sub_gco_gco(obj rcx, + obj x_gco, + obj y_gco) + { + using xo::reflect::typeseq; + + obj mm = rcx.allocator(); + + // PLACEHOLDER + + // TODO: + // 1. move this to xo-numeric2/ when available + // 2. at that point will require polymorphic dispatch + // on argument representations, analogous to dispatch + // in FacetRegistry + + typeseq x_tseq = x_gco._typeseq(); + typeseq y_tseq = y_gco._typeseq(); + + // FOR NOW: just test runtime values + // + if (x_tseq == typeseq::id()) { + // i64 * .. + long x = GCObjectConversion::from_gco(mm, x_gco); + + if (y_tseq == typeseq::id()) { + // i64 * i64 + long y = GCObjectConversion::from_gco(mm, y_gco); + + return DInteger::box(mm, x - y); + } else if (y_tseq == typeseq::id()) { + // i64 * f64 + double y = GCObjectConversion::from_gco(mm, y_gco); + + return DFloat::box(mm, x - y); + } + } else if (x_tseq == typeseq::id()) { + if (y_tseq == typeseq::id()) { + // f64 * i64. + double x = GCObjectConversion::from_gco(mm, x_gco); + long y = GCObjectConversion::from_gco(mm, y_gco); + + return DFloat::box(mm, x - y); + } else if (y_tseq == typeseq::id()) { + // f64 * f64. + double x = GCObjectConversion::from_gco(mm, x_gco); + double y = GCObjectConversion::from_gco(mm, y_gco); + + return DFloat::box(mm, x - y); + } + } + + // here: error + throw std::runtime_error(tostr("sub_gco_gco: unexpected argument types xt,yt", + xtag("x.tseq", x_tseq), + xtag("y.tseq", y_tseq))); + return obj(); + } + + obj + equal_gco_gco(obj rcx, + obj x_gco, + obj y_gco) + { + using xo::reflect::typeseq; + + obj mm = rcx.allocator(); + + // PLACEHOLDER + + // TODO + // 1. move this to xo-numeric2/ when available + // 2. at that point will require polymorphic dispatch on argument representations. + // + + typeseq x_tseq = x_gco._typeseq(); + typeseq y_tseq = y_gco._typeseq(); + + // FOR NOW: just test runtime values + // + if (x_tseq == typeseq::id()) { + // i64 * .. + long x = GCObjectConversion::from_gco(mm, x_gco); + + if (y_tseq == typeseq::id()) { + // i64 == i64 + long y = GCObjectConversion::from_gco(mm, y_gco); + + return DBoolean::box(mm, x == y); + } else if (y_tseq == typeseq::id()) { + // i64 == f64 + double y = GCObjectConversion::from_gco(mm, y_gco); + + return DFloat::box(mm, static_cast(x) == y); + } + } else if (x_tseq == typeseq::id()) { + if (y_tseq == typeseq::id()) { + // f64 == i64. + double x = GCObjectConversion::from_gco(mm, x_gco); + long y = GCObjectConversion::from_gco(mm, y_gco); + + return DFloat::box(mm, x == static_cast(y)); + } else if (y_tseq == typeseq::id()) { + // f64 * f64. + double x = GCObjectConversion::from_gco(mm, x_gco); + double y = GCObjectConversion::from_gco(mm, y_gco); + + return DFloat::box(mm, x == y); + } + } + + // here: error + throw std::runtime_error(tostr("mul_gco_gco: unexpected argument types xt,yt", + xtag("x.tseq", x_tseq), + xtag("y.tseq", y_tseq))); + return obj(); + } + +#ifdef NOT_YET + double + mul_f64_f64(double x, double y) { + return x * y; + } + + double + div_f64_f64(double x, double y) { + return x / y; + } + + double + pow_f64_f64(double x, double y) { + return ::pow(x, y); + } + + double + log_f64(double x) { + return ::log(x); + } + + double + sin_f64(double x) { + return ::sin(x); + } + + double + cos_f64(double x) { + return ::cos(x); + } + + double + tan_f64(double x) { + return ::tan(x); + } +#endif + + DPrimitive_gco_2_gco_gco + Primitives::s_mul_gco_gco_pm("_mul", &mul_gco_gco); + + DPrimitive_gco_2_gco_gco + Primitives::s_sub_gco_gco_pm("_sub", &sub_gco_gco); + + DPrimitive_gco_2_gco_gco + Primitives::s_equal_gco_gco_pm("_equal", &equal_gco_gco); + +#ifdef NOT_YET + Primitive_f64_1_f64 + Primitives::s_neg_f64_pm("_neg_d", + &neg_f64); + + Primitive_f64_2_f64_f64 + Primitives::s_add_f64_f64_pm("_add_d_d", &add_f64_f64); + + Primitive_f64_2_f64_f64 + Primitives::s_sub_f64_f64_pm("_sub_d_d", &sub_f64_f64); + + Primitive_f64_2_f64_f64 + Primitives::s_mul_f64_f64_pm("_mul_d_d", &mul_f64_f64); + + Primitive_f64_2_f64_f64 + Primitives::s_div_f64_f64_pm("_div_d_d", &div_f64_f64); + + Primitive_f64_2_f64_f64 + Primitives::s_pow_f64_f64_pm("_pow_d_d", &pow_f64_f64); + + Primitive_f64_1_f64 + Primitives::s_log_f64_pm("_log_d", &log_f64); + + Primitive_f64_1_f64 + Primitives::s_sin_f64_pm("_sin_d", &sin_f64); + + Primitive_f64_1_f64 + Primitives::s_cos_f64_pm("_cos_d", &cos_f64); + + Primitive_f64_1_f64 + Primitives::s_tan_f64_pm("_tan_d", &tan_f64); +#endif + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end init_primitives.cpp */ diff --git a/xo-procedure2/src/procedure2/init_procedure2.cpp b/xo-procedure2/src/procedure2/init_procedure2.cpp new file mode 100644 index 00000000..aaa6a021 --- /dev/null +++ b/xo-procedure2/src/procedure2/init_procedure2.cpp @@ -0,0 +1,42 @@ +/** @file init_procedure2.cpp + * + * @author Roland Conybeare, Jan 2026 +**/ + +#include "init_procedure2.hpp" +#include "init_primitives.hpp" +#include "procedure2_register_facets.hpp" +#include "procedure2_register_types.hpp" + +#include +#include + +namespace xo { + using xo::scm::procedure2_register_facets; + using xo::scm::procedure2_register_types; + using xo::mm::CollectorTypeRegistry; + + void + InitSubsys::init() + { + procedure2_register_facets(); + + CollectorTypeRegistry::instance().register_types(&procedure2_register_types); + } + + InitEvidence + InitSubsys::require() + { + InitEvidence retval; + + /* recursive subsystem deps for xo-object2/ */ + retval ^= InitSubsys::require(); + + /* xo-procedure2/'s own initialization code */ + retval ^= Subsystem::provide("procedure2", &init); + + return retval; + } +} /*namespace xo*/ + +/* end init_procedure2.cpp */ diff --git a/xo-procedure2/src/procedure2/procedure2_register_facets.cpp b/xo-procedure2/src/procedure2/procedure2_register_facets.cpp new file mode 100644 index 00000000..6905e0ba --- /dev/null +++ b/xo-procedure2/src/procedure2/procedure2_register_facets.cpp @@ -0,0 +1,44 @@ +/** @file procedure2_register_facets.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "Procedure.hpp" +#include "SimpleRcx.hpp" +#include "Primitive_gco_2_gco_gco.hpp" + +#include +#include +#include +#include + +namespace xo { + using xo::facet::FacetRegistry; + using xo::facet::typeseq; + using xo::print::APrintable; + + namespace scm { + bool + procedure2_register_facets() + { + scope log(XO_DEBUG(true)); + + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + log && log(xtag("DSimpleRcx.tseq", typeseq::id())); + log && log(xtag("DPrimitive_gco_2_gco_gco.tseq", typeseq::id())); + + log && log(xtag("ARuntimeContext.tseq", typeseq::id())); + log && log(xtag("AProcedure.tseq", typeseq::id())); + + return true; + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end procedure2_register_facets.cpp */ diff --git a/xo-procedure2/src/procedure2/procedure2_register_types.cpp b/xo-procedure2/src/procedure2/procedure2_register_types.cpp new file mode 100644 index 00000000..497773d2 --- /dev/null +++ b/xo-procedure2/src/procedure2/procedure2_register_types.cpp @@ -0,0 +1,35 @@ +/** @file procedure2_register_types.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "procedure2_register_types.hpp" + +#include "detail/IGCObject_DPrimitive_gco_2_gco_gco.hpp" +#include + +namespace xo { + using xo::mm::ACollector; + using xo::mm::AGCObject; + using xo::facet::impl_for; + using xo::facet::typeseq; + using xo::scope; + + namespace scm { + bool + procedure2_register_types(obj gc) + { + scope log(XO_DEBUG(true)); + + bool ok = true; + + // (note: don't currently intend to support AGCObject for DSimpleRcx) + + ok &= gc.install_type(impl_for()); + + return ok; + } + } +} /*namespace xo*/ + +/* end procedure2_register_types.cpp */ diff --git a/xo-procedure2/utest/CMakeLists.txt b/xo-procedure2/utest/CMakeLists.txt new file mode 100644 index 00000000..e758d282 --- /dev/null +++ b/xo-procedure2/utest/CMakeLists.txt @@ -0,0 +1,12 @@ +# built unittest xo-procedure2/utest + +set(UTEST_EXE utest.procedure2) +set(UTEST_SRCS + procedure2_utest_main.cpp + DPrimitive.test.cpp + DSimpleRcx.test.cpp +) + +xo_add_utest_executable(${UTEST_EXE} ${UTEST_SRCS}) +xo_self_dependency(${UTEST_EXE} xo_procedure2) +xo_external_target_dependency(${UTEST_EXE} Catch2 Catch2::Catch2) diff --git a/xo-procedure2/utest/DPrimitive.test.cpp b/xo-procedure2/utest/DPrimitive.test.cpp new file mode 100644 index 00000000..73e807fd --- /dev/null +++ b/xo-procedure2/utest/DPrimitive.test.cpp @@ -0,0 +1,144 @@ +/** @file DPrimitive.test.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace xo { + using xo::scm::Primitives; + using xo::scm::DSimpleRcx; + using xo::scm::ARuntimeContext; + using xo::scm::DFloat; + using xo::scm::DInteger; + using xo::scm::DArray; + using xo::scm::DPrimitive_gco_2_gco_gco; + using xo::mm::AAllocator; + using xo::mm::AGCObject; + using xo::mm::DArena; + using xo::mm::ArenaConfig; + using xo::print::APrintable; + using xo::print::ppstate_standalone; + using xo::print::ppconfig; + using xo::facet::with_facet; + using xo::facet::obj; + using xo::scope; + + namespace ut { + static InitEvidence s_init = InitSubsys::require(); + + TEST_CASE("DPrimitive-init", "[procedure2][DPrimitive]") + { + REQUIRE(s_init.evidence()); + } + + TEST_CASE("DPrimitive-n_args", "[procedure2][DPrimitive]") + { + // s_mul_gco_gco_pm takes 2 AGCObject args + REQUIRE(Primitives::s_mul_gco_gco_pm.n_args() == 2); + } + + TEST_CASE("DPrimitive-is_nary", "[procedure2][DPrimitive]") + { + REQUIRE(Primitives::s_mul_gco_gco_pm.is_nary() == false); + } + + TEST_CASE("DPrimitive-apply_nocheck-float-float", "[procedure2][DPrimitive]") + { + ArenaConfig cfg { .name_ = "testarena", .size_ = 4*1024 }; + DArena arena = DArena::map(cfg); + auto alloc = with_facet::mkobj(&arena); + + DSimpleRcx rcx_data(alloc); + obj rcx = with_facet::mkobj(&rcx_data); + + // 3.0 * 7.0 = 21.0 + obj x = DFloat::box(alloc, 3.0); + obj y = DFloat::box(alloc, 7.0); + DArray * args = DArray::array(alloc, x, y); + + obj result = Primitives::s_mul_gco_gco_pm.apply_nocheck(rcx, args); + + auto result_float = obj::from(result); + REQUIRE(result_float); + REQUIRE(result_float.data()->value() == 21.0); + } + + TEST_CASE("DPrimitive-apply_nocheck-int-int", "[procedure2][DPrimitive]") + { + ArenaConfig cfg { .name_ = "testarena", .size_ = 4*1024 }; + DArena arena = DArena::map(cfg); + auto alloc = with_facet::mkobj(&arena); + + DSimpleRcx rcx_data(alloc); + obj rcx = with_facet::mkobj(&rcx_data); + + // 3 * 7 = 21 + obj x = DInteger::box(alloc, 3L); + obj y = DInteger::box(alloc, 7L); + DArray * args = DArray::array(alloc, x, y); + + obj result = Primitives::s_mul_gco_gco_pm.apply_nocheck(rcx, args); + + auto result_int = obj::from(result); + REQUIRE(result_int); + REQUIRE(result_int.data()->value() == 21L); + } + + TEST_CASE("DPrimitive-apply_nocheck-int-float", "[procedure2][DPrimitive]") + { + ArenaConfig cfg { .name_ = "testarena", .size_ = 4*1024 }; + DArena arena = DArena::map(cfg); + auto alloc = with_facet::mkobj(&arena); + + DSimpleRcx rcx_data(alloc); + obj rcx = with_facet::mkobj(&rcx_data); + + // 3 * 7.0 = 21.0 (mixed: result is float) + obj x = DInteger::box(alloc, 3L); + obj y = DFloat::box(alloc, 7.0); + DArray * args = DArray::array(alloc, x, y); + + obj result = Primitives::s_mul_gco_gco_pm.apply_nocheck(rcx, args); + + auto result_float = obj::from(result); + REQUIRE(result_float); + REQUIRE(result_float.data()->value() == 21.0); + } + + TEST_CASE("DPrimitive-pretty", "[procedure2][DPrimitive][pp]") + { + scope log(XO_DEBUG(false)); + + std::stringstream ss; + ppconfig ppc; + ppstate_standalone pps(&ss, 0, &ppc); + + obj prim_pr(&Primitives::s_mul_gco_gco_pm); + pps.pretty(prim_pr); + + std::string output = ss.str(); + + log && log(output); + + CHECK(output.find("_mul") != std::string::npos); + } + + } /*namespace ut*/ +} /*namespace xo*/ + +/* end DPrimitive.test.cpp */ diff --git a/xo-procedure2/utest/DSimpleRcx.test.cpp b/xo-procedure2/utest/DSimpleRcx.test.cpp new file mode 100644 index 00000000..cab1362d --- /dev/null +++ b/xo-procedure2/utest/DSimpleRcx.test.cpp @@ -0,0 +1,60 @@ +/** @file DSimpleRcx.test.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include +#include +#include +#include +#include + +namespace xo { + using xo::scm::DSimpleRcx; + using xo::scm::ARuntimeContext; + using xo::mm::AAllocator; + using xo::mm::DArena; + using xo::mm::ArenaConfig; + using xo::facet::with_facet; + using xo::facet::obj; + + namespace ut { + static InitEvidence s_init = InitSubsys::require(); + + TEST_CASE("DSimpleRcx-init", "[procedure2][DSimpleRcx]") + { + REQUIRE(s_init.evidence()); + } + + TEST_CASE("DSimpleRcx-construct", "[procedure2][DSimpleRcx]") + { + ArenaConfig cfg { .name_ = "testarena", + .size_ = 4*1024 }; + DArena arena = DArena::map(cfg); + auto alloc = with_facet::mkobj(&arena); + + DSimpleRcx rcx(alloc); + + REQUIRE((void*)rcx.allocator().data() == (void*)alloc.data()); + } + + TEST_CASE("DSimpleRcx-as-ARuntimeContext", "[procedure2][DSimpleRcx]") + { + ArenaConfig cfg { .name_ = "testarena", + .size_ = 4*1024 }; + DArena arena = DArena::map(cfg); + auto alloc = with_facet::mkobj(&arena); + + DSimpleRcx rcx(alloc); + obj rcx_obj = with_facet::mkobj(&rcx); + + // verify we can recover allocator from obj + obj recovered_alloc = rcx_obj.allocator(); + + REQUIRE((void*)recovered_alloc.data() == (void*)alloc.data()); + } + + } /*namespace ut*/ +} /*namespace xo*/ + +/* end DSimpleRcx.test.cpp */ diff --git a/xo-procedure2/utest/procedure2_utest_main.cpp b/xo-procedure2/utest/procedure2_utest_main.cpp new file mode 100644 index 00000000..477099bc --- /dev/null +++ b/xo-procedure2/utest/procedure2_utest_main.cpp @@ -0,0 +1,20 @@ +/* file procedure2_utest_main.cpp */ + +#include + +#define CATCH_CONFIG_RUNNER +#include "catch2/catch.hpp" + +int +main(int argc, char* argv[]) +{ + using xo::Subsystem; + + Subsystem::initialize_all(); + + int result = Catch::Session().run(argc, argv); + + return result; +} + +/* end procedure2_utest_main.cpp */ diff --git a/xo-reader2/CMakeLists.txt b/xo-reader2/CMakeLists.txt index a8508472..9f05802f 100644 --- a/xo-reader2/CMakeLists.txt +++ b/xo-reader2/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.10) +#set(CMAKE_CXX_STANDARD 23) + project(xo_reader2 VERSION 1.0) enable_language(CXX) @@ -20,22 +22,292 @@ add_definitions(${PROJECT_CXX_FLAGS}) # ---------------------------------------------------------------- # output targets -#add_subdirectory(utest) +add_subdirectory(utest) + +# note: manual target; generated code committed to git +xo_add_genfacet( + TARGET xo-reader2-facet-syntaxstatemachine + FACET SyntaxStateMachine + INPUT idl/SyntaxStateMachine.json5 + ) # ---------------------------------------------------------------- -# header-only library -set(SELF_LIB xo_reader2) -xo_add_headeronly_library(${SELF_LIB}) -xo_install_library4(${SELF_LIB} ${PROJECT_NAME}Targets) +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-syntaxstatemachine-toplevelseqssm + FACET_PKG xo_reader2 + FACET SyntaxStateMachine + REPR ToplevelSeqSsm + INPUT idl/ISyntaxStateMachine_DToplevelSeqSsm.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-printable-toplevelseqssm + FACET_PKG xo_printable2 + FACET Printable + REPR ToplevelSeqSsm + INPUT idl/IPrintable_DToplevelSeqSsm.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-syntaxstatemachine-definessm + FACET_PKG xo_reader2 + FACET SyntaxStateMachine + REPR DefineSsm + INPUT idl/ISyntaxStateMachine_DDefineSsm.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-printable-definessm + FACET_PKG xo_printable2 + FACET Printable + REPR DefineSsm + INPUT idl/IPrintable_DDefineSsm.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-syntaxstatemachine-lambdassm + FACET_PKG xo_reader2 + FACET SyntaxStateMachine + REPR LambdaSsm + INPUT idl/ISyntaxStateMachine_DLambdaSsm.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-printable-lambdassm + FACET_PKG xo_printable2 + FACET Printable + REPR LambdaSsm + INPUT idl/IPrintable_DLambdaSsm.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-syntaxstatemachine-parenssm + FACET_PKG xo_reader2 + FACET SyntaxStateMachine + REPR ParenSsm + INPUT idl/ISyntaxStateMachine_DParenSsm.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-printable-parenssm + FACET_PKG xo_printable2 + FACET Printable + REPR ParenSsm + INPUT idl/IPrintable_DParenSsm.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-syntaxstatemachine-expectformalarglistssm + FACET_PKG xo_reader2 + FACET SyntaxStateMachine + REPR ExpectFormalArglistSsm + INPUT idl/ISyntaxStateMachine_DExpectFormalArglistSsm.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-printable-expectformalarglistssm + FACET_PKG xo_printable2 + FACET Printable + REPR ExpectFormalArglistSsm + INPUT idl/IPrintable_DExpectFormalArglistSsm.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-syntaxstatemachine-expectformalargssm + FACET_PKG xo_reader2 + FACET SyntaxStateMachine + REPR ExpectFormalArgSsm + INPUT idl/ISyntaxStateMachine_DExpectFormalArgSsm.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-printable-expectformalargssm + FACET_PKG xo_printable2 + FACET Printable + REPR ExpectFormalArgSsm + INPUT idl/IPrintable_DExpectFormalArgSsm.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-syntaxstatemachine-ifelsessm + FACET_PKG xo_reader2 + FACET SyntaxStateMachine + REPR IfElseSsm + INPUT idl/ISyntaxStateMachine_DIfElseSsm.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-printable-ifelsessm + FACET_PKG xo_printable2 + FACET Printable + REPR IfElseSsm + INPUT idl/IPrintable_DIfElseSsm.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-syntaxstatemachine-sequencessm + FACET_PKG xo_reader2 + FACET SyntaxStateMachine + REPR SequenceSsm + INPUT idl/ISyntaxStateMachine_DSequenceSsm.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-printable-sequencessm + FACET_PKG xo_printable2 + FACET Printable + REPR SequenceSsm + INPUT idl/IPrintable_DSequenceSsm.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-syntaxstatemachine-applyssm + FACET_PKG xo_reader2 + FACET SyntaxStateMachine + REPR ApplySsm + INPUT idl/ISyntaxStateMachine_DApplySsm.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-printable-applyssm + FACET_PKG xo_printable2 + FACET Printable + REPR ApplySsm + INPUT idl/IPrintable_DApplySsm.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-syntaxstatemachine-expectsymbolssm + FACET_PKG xo_reader2 + FACET SyntaxStateMachine + REPR ExpectSymbolSsm + INPUT idl/ISyntaxStateMachine_DExpectSymbolSsm.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-printable-expectsymbolssm + FACET_PKG xo_printable2 + FACET Printable + REPR ExpectSymbolSsm + INPUT idl/IPrintable_DExpectSymbolSsm.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-syntaxstatemachine-expecttypessm + FACET_PKG xo_reader2 + FACET SyntaxStateMachine + REPR ExpectTypeSsm + INPUT idl/ISyntaxStateMachine_DExpectTypeSsm.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-printable-expecttypessm + FACET_PKG xo_printable2 + FACET Printable + REPR ExpectTypeSsm + INPUT idl/IPrintable_DExpectTypeSsm.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-syntaxstatemachine-expectexprssm + FACET_PKG xo_reader2 + FACET SyntaxStateMachine + REPR ExpectExprSsm + INPUT idl/ISyntaxStateMachine_DExpectExprSsm.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-printable-expectexprssm + FACET_PKG xo_printable2 + FACET Printable + REPR ExpectExprSsm + INPUT idl/IPrintable_DExpectExprSsm.json5 +) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-syntaxstatemachine-progressssm + FACET_PKG xo_reader2 + FACET SyntaxStateMachine + REPR ProgressSsm + INPUT idl/ISyntaxStateMachine_DProgressSsm.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-printable-progressssm + FACET_PKG xo_printable2 + FACET Printable + REPR ProgressSsm + INPUT idl/IPrintable_DProgressSsm.json5 +) + +# ---------------------------------------------------------------- + +xo_add_genfacet_all(xo-reader2-genfacet-all) + +# ---------------------------------------------------------------- +# shared library + +add_subdirectory(src/reader2) + +# ---------------------------------------------------------------- +# example programs + +add_subdirectory(example) + +# ---------------------------------------------------------------- +# cmake helper (for external xo-reader2 users) + xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets) -# ---------------------------------------------------------------- -# input dependencies -# -# NOTE: dependency set here must be kept consistent with -# xo-reader2/cmake/xo_reader2Config.cmake.in - -#xo_headeronly_dependency(${SELF_LIB} xo_flatstring) - # end CMakeLists.txt diff --git a/xo-reader2/DESIGN.md b/xo-reader2/DESIGN.md new file mode 100644 index 00000000..73e863e3 --- /dev/null +++ b/xo-reader2/DESIGN.md @@ -0,0 +1,12 @@ +Uses arena allocators for fast+efficient parsing. + +Composition of nested state machines. + +## SyntaxStateMachine + +a state machine dedicated to some particular Schematika syntax. +Examples: if-expression, type declaration, function call + +## DToplevelSeqSsm + +top-level expression sequence diff --git a/xo-reader2/cmake/xo_reader2Config.cmake.in b/xo-reader2/cmake/xo_reader2Config.cmake.in index b5c3cd5c..ed161c20 100644 --- a/xo-reader2/cmake/xo_reader2Config.cmake.in +++ b/xo-reader2/cmake/xo_reader2Config.cmake.in @@ -6,7 +6,11 @@ include(CMakeFindDependencyMacro) # must coordinate with xo_dependency() calls # in CMakeLists.txt # -#find_dependency(xo_flatstring) +find_dependency(xo_procedure2) +find_dependency(xo_gc) +find_dependency(xo_tokenizer2) +find_dependency(xo_expression2) +find_dependency(subsys) include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") check_required_components("@PROJECT_NAME@") diff --git a/xo-reader2/doc/README.md b/xo-reader2/doc/README.md new file mode 100644 index 00000000..01b5c555 --- /dev/null +++ b/xo-reader2/doc/README.md @@ -0,0 +1,6 @@ +diagram for parsing stack. +stack growing down for nested ssm's + +`on_if_token` etc going to same state + +`on_parsed_xxx` going back up the stack diff --git a/xo-reader2/doc/glossary.rst b/xo-reader2/doc/glossary.rst new file mode 100644 index 00000000..67b04538 --- /dev/null +++ b/xo-reader2/doc/glossary.rst @@ -0,0 +1,3 @@ +ssm = syntax state machine +psm = parser state machine +ckp = checkpoint diff --git a/xo-reader2/example/CMakeLists.txt b/xo-reader2/example/CMakeLists.txt new file mode 100644 index 00000000..fbb01ff0 --- /dev/null +++ b/xo-reader2/example/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(readerreplxx) diff --git a/xo-reader2/example/readerreplxx/CMakeLists.txt b/xo-reader2/example/readerreplxx/CMakeLists.txt new file mode 100644 index 00000000..37ecd45e --- /dev/null +++ b/xo-reader2/example/readerreplxx/CMakeLists.txt @@ -0,0 +1,14 @@ +# xo-reader2/example/readerreplxx/CMakeLists.txt + +set(SELF_EXE xo_reader2_readereplxx) +set(SELF_SRCS readerreplxx.cpp) + +if (XO_ENABLE_EXAMPLES) + xo_add_executable(${SELF_EXE} ${SELF_SRCS}) + xo_self_dependency(${SELF_EXE} xo_reader2) + xo_external_target_dependency(${SELF_EXE} replxx replxx::replxx) + + # replxx requires this + find_package(Threads REQUIRED) + target_link_libraries(${SELF_EXE} PUBLIC Threads::Threads) +endif() diff --git a/xo-reader2/example/readerreplxx/readerreplxx.cpp b/xo-reader2/example/readerreplxx/readerreplxx.cpp new file mode 100644 index 00000000..292c3a43 --- /dev/null +++ b/xo-reader2/example/readerreplxx/readerreplxx.cpp @@ -0,0 +1,248 @@ +/** @file readerreplxx.cpp **/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for isatty + +// presumeably replxx assumes input is a tty +// +bool replxx_getline(bool interactive, + bool is_at_toplevel, + replxx::Replxx & rx, + const char ** p_input) +{ + using namespace std; + + char const * prompt = ""; + + if (interactive) { + prompt = ((is_at_toplevel) ? "> " : ". "); + } + + const char * input_cstr = rx.input(prompt); + + bool retval = (input_cstr != nullptr); + + if (retval) + *p_input = input_cstr; + + if (input_cstr) + rx.history_add(input_cstr); + + return retval; +} + +void +welcome(std::ostream & os) +{ + using namespace std; + + os << "read-eval-print loop for schematika expressions" << endl; + os << " ctrl-a/ctrl-e beginning/end of line" << endl; + os << " ctrl-u delete entire line" << endl; + os << " ctrl-k delete to end of line" << endl; + os << " meta- backward delete word" << endl; + os << " |meta-p previous command from history" << endl; + os << " |meta-n next command from history" << endl; + os << " / page through history faster" << endl; + os << " ctrl-s/ctrl-r forward/backward history search" << endl; + os << endl; +} + +namespace { + using xo::scm::SchematikaReader; + using xo::scm::AExpression; + using xo::print::APrintable; + using xo::print::ppstate_standalone; + using xo::print::ppconfig; + using xo::facet::FacetRegistry; + using xo::facet::obj; + using xo::xtag; + using xo::scope; + using std::cout; + using std::endl; + + /** body of read-parse-print loop + * + * true -> no errors; + * false -> reader encountered error + **/ + bool + reader_seq(SchematikaReader * p_reader, + SchematikaReader::span_type * p_input, + bool eof, + bool debug_flag) + { + scope log(XO_DEBUG(debug_flag)); + + if (!p_input || p_input->empty()) + return true; + + auto [expr, remaining, error] = p_reader->read_expr(*p_input, eof); + + obj expr_pr; + + if (expr) { + expr_pr = FacetRegistry::instance().variant(expr); + assert(expr_pr); + } + + if (log) { + if (expr_pr) { + log(xtag("expr", expr_pr)); + } + log(xtag("remaining", remaining)); + log(xtag("error", error)); + } + + if (expr) { + ppconfig ppc; + ppstate_standalone pps(&cout, 0, &ppc); + + pps.prettyn(expr_pr); + + p_reader->reset_result(); + + *p_input = remaining; + + return true; + } else if (error.is_error()) { + cout << "parsing error (detected in " << error.src_function() << "): " << endl; + error.report(cout); + + /* discard stashed remainder of input line + * (for nicely-formatted errors) + */ + p_reader->reset_to_idle_toplevel(); + + return false; + } else { + *p_input = remaining; + + /* partial expression or whitespace input, no error */ + return true; + } + } +} + +struct AppConfig { + using ReaderConfig = xo::scm::ReaderConfig; + using X1CollectorConfig = xo::mm::X1CollectorConfig; + using ArenaConfig = xo::mm::ArenaConfig; + + AppConfig() { + rdr_config_.reader_debug_flag_ = true; + //rdr_config.parser_debug_flag_ = true; + //rdr_config.tk_debug_flag_ = true; + } + + std::size_t max_history_size_ = 1000; + std::string repl_history_fname_ = "repl_history.txt";; + ReaderConfig rdr_config_; + X1CollectorConfig x1_config_ = (X1CollectorConfig().with_name("gc").with_size(4*1024*1024)); + ArenaConfig fixed_config_ = (ArenaConfig().with_name("fixed").with_size(4*1024)); +}; + +struct AppContext { + using AAllocator = xo::mm::AAllocator; + using DX1Collector = xo::mm::DX1Collector; + using X1CollectorConfig = xo::mm::X1CollectorConfig; + using DArena = xo::mm::DArena; + using ArenaConfig = xo::mm::ArenaConfig; + using Replxx = replxx::Replxx; + + AppContext(const AppConfig & cfg = AppConfig()) : config_{cfg}, + x1_{cfg.x1_config_}, + fixed_{cfg.fixed_config_}, + rdr_{config_.rdr_config_, + x1_.ref(), + obj(&fixed_)} + { + rx_.set_max_history_size(config_.max_history_size_); + rx_.history_load(config_.repl_history_fname_); + // rx.bind_key_internal(Replxx::KEY::control('p'), "history_previous"); + // rx.bind_key_internal(Replxx::KEY::control('n'), "history_next"); + } + + AppConfig config_; + Replxx rx_; + /** collector/allocator for schematika expressions **/ + DX1Collector x1_; + /** e.g. for DArenaHashMap within global symtab **/ + DArena fixed_; + SchematikaReader rdr_; +}; + +int +main() +{ + using namespace replxx; + + using xo::scm::SchematikaReader; + using xo::scm::ReaderConfig; + using xo::mm::AAllocator; + using xo::mm::DX1Collector; + using xo::mm::DArena; + using xo::facet::with_facet; + using xo::facet::obj; + using xo::S_reader2_tag; + using xo::InitSubsys; + using xo::Subsystem; + using xo::scope; + using namespace std; + + bool interactive = isatty(STDIN_FILENO); + + InitSubsys::require(); + Subsystem::initialize_all(); + + AppConfig cfg; + AppContext cx(cfg); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag)); + + using span_type = SchematikaReader::span_type; + + welcome(cerr); + + cx.rdr_.begin_interactive_session(); + + bool eof = false; + const char * input_str = nullptr; + span_type input; + + while (replxx_getline(interactive, cx.rdr_.is_at_toplevel(), cx.rx_, &input_str)) { + if (input_str && *input_str) { + input = span_type::from_cstr(input_str); + + while (!input.empty() + && reader_seq(&cx.rdr_, &input, false /*eof*/, c_debug_flag)) + { + ; + } + + /* here: either: + * 1. input.empty() or + * 2. error encountered + */ + } + } + + /* reminder: eof can complete at most one token */ + reader_seq(&cx.rdr_, &input, true /*eof*/, c_debug_flag); + + cx.rx_.history_save(cx.config_.repl_history_fname_); +} + +/* end readerreplxx.cpp */ diff --git a/xo-reader2/idl/IPrintable_DApplySsm.json5 b/xo-reader2/idl/IPrintable_DApplySsm.json5 new file mode 100644 index 00000000..6f2a531d --- /dev/null +++ b/xo-reader2/idl/IPrintable_DApplySsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "", + "" ], + local_types: [], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DApplySsm", + using_doxygen: true, + repr: "DApplySsm", + doc: [ "implement APrintable for DApplySsm" ], +} diff --git a/xo-reader2/idl/IPrintable_DDefineSsm.json5 b/xo-reader2/idl/IPrintable_DDefineSsm.json5 new file mode 100644 index 00000000..28463e92 --- /dev/null +++ b/xo-reader2/idl/IPrintable_DDefineSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "", + "" ], + local_types: [], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DDefineSsm", + using_doxygen: true, + repr: "DDefineSsm", + doc: [ "implement APrintable for DDefineSsm" ], +} diff --git a/xo-reader2/idl/IPrintable_DExpectExprSsm.json5 b/xo-reader2/idl/IPrintable_DExpectExprSsm.json5 new file mode 100644 index 00000000..f5465709 --- /dev/null +++ b/xo-reader2/idl/IPrintable_DExpectExprSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "", + "" ], + local_types: [], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DExpectExprSsm", + using_doxygen: true, + repr: "DExpectExprSsm", + doc: [ "implement APrintable for DExpectExprSsm" ], +} diff --git a/xo-reader2/idl/IPrintable_DExpectFormalArgSsm.json5 b/xo-reader2/idl/IPrintable_DExpectFormalArgSsm.json5 new file mode 100644 index 00000000..73389166 --- /dev/null +++ b/xo-reader2/idl/IPrintable_DExpectFormalArgSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "", + "" ], + local_types: [], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DExpectFormalArgSsm", + using_doxygen: true, + repr: "DExpectFormalArgSsm", + doc: [ "implement APrintable for DExpectFormalArgSsm" ], +} diff --git a/xo-reader2/idl/IPrintable_DExpectFormalArglistSsm.json5 b/xo-reader2/idl/IPrintable_DExpectFormalArglistSsm.json5 new file mode 100644 index 00000000..1aa3c951 --- /dev/null +++ b/xo-reader2/idl/IPrintable_DExpectFormalArglistSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "", + "" ], + local_types: [], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DExpectFormalArglistSsm", + using_doxygen: true, + repr: "DExpectFormalArglistSsm", + doc: [ "implement APrintable for DExpectFormalArglistSsm" ], +} diff --git a/xo-reader2/idl/IPrintable_DExpectSymbolSsm.json5 b/xo-reader2/idl/IPrintable_DExpectSymbolSsm.json5 new file mode 100644 index 00000000..fee89873 --- /dev/null +++ b/xo-reader2/idl/IPrintable_DExpectSymbolSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "", + "" ], + local_types: [], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DExpectSymbolSsm", + using_doxygen: true, + repr: "DExpectSymbolSsm", + doc: [ "implement APrintable for DExpectSymbolSsm" ], +} diff --git a/xo-reader2/idl/IPrintable_DExpectTypeSsm.json5 b/xo-reader2/idl/IPrintable_DExpectTypeSsm.json5 new file mode 100644 index 00000000..463cb399 --- /dev/null +++ b/xo-reader2/idl/IPrintable_DExpectTypeSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "", + "" ], + local_types: [], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DExpectTypeSsm", + using_doxygen: true, + repr: "DExpectTypeSsm", + doc: [ "implement APrintable for DExpectTypeSsm" ], +} diff --git a/xo-reader2/idl/IPrintable_DIfElseSsm.json5 b/xo-reader2/idl/IPrintable_DIfElseSsm.json5 new file mode 100644 index 00000000..dbcdbb0a --- /dev/null +++ b/xo-reader2/idl/IPrintable_DIfElseSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "", + "" ], + local_types: [], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DIfElseSsm", + using_doxygen: true, + repr: "DIfElseSsm", + doc: [ "implement APrintable for DIfElseSsm" ], +} diff --git a/xo-reader2/idl/IPrintable_DLambdaSsm.json5 b/xo-reader2/idl/IPrintable_DLambdaSsm.json5 new file mode 100644 index 00000000..035f71f1 --- /dev/null +++ b/xo-reader2/idl/IPrintable_DLambdaSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "", + "" ], + local_types: [], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DLambdaSsm", + using_doxygen: true, + repr: "DLambdaSsm", + doc: [ "implement APrintable for DLambdaSsm" ], +} diff --git a/xo-reader2/idl/IPrintable_DParenSsm.json5 b/xo-reader2/idl/IPrintable_DParenSsm.json5 new file mode 100644 index 00000000..9750cb31 --- /dev/null +++ b/xo-reader2/idl/IPrintable_DParenSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "", + "" ], + local_types: [], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DParenSsm", + using_doxygen: true, + repr: "DParenSsm", + doc: [ "implement APrintable for DParenSsm" ], +} diff --git a/xo-reader2/idl/IPrintable_DProgressSsm.json5 b/xo-reader2/idl/IPrintable_DProgressSsm.json5 new file mode 100644 index 00000000..d3d298b1 --- /dev/null +++ b/xo-reader2/idl/IPrintable_DProgressSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "", + "" ], + local_types: [], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DProgressSsm", + using_doxygen: true, + repr: "DProgressSsm", + doc: [ "implement APrintable for DProgressSsm" ], +} diff --git a/xo-reader2/idl/IPrintable_DSequenceSsm.json5 b/xo-reader2/idl/IPrintable_DSequenceSsm.json5 new file mode 100644 index 00000000..f5c89aca --- /dev/null +++ b/xo-reader2/idl/IPrintable_DSequenceSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "", + "" ], + local_types: [], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DSequenceSsm", + using_doxygen: true, + repr: "DSequenceSsm", + doc: [ "implement APrintable for DSequenceSsm" ], +} diff --git a/xo-reader2/idl/IPrintable_DToplevelSeqSsm.json5 b/xo-reader2/idl/IPrintable_DToplevelSeqSsm.json5 new file mode 100644 index 00000000..d3c78474 --- /dev/null +++ b/xo-reader2/idl/IPrintable_DToplevelSeqSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "", + "" ], + local_types: [], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DToplevelSeqSsm", + using_doxygen: true, + repr: "DToplevelSeqSsm", + doc: [ "implement APrintable for DToplevelSeqSsm" ], +} diff --git a/xo-reader2/idl/ISyntaxStateMachine_DApplySsm.json5 b/xo-reader2/idl/ISyntaxStateMachine_DApplySsm.json5 new file mode 100644 index 00000000..bc433fdf --- /dev/null +++ b/xo-reader2/idl/ISyntaxStateMachine_DApplySsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "\"SyntaxStateMachine.hpp\"", + "\"ssm/ISyntaxStateMachine_Xfer.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SyntaxStateMachine.json5", + brief: "provide ASyntaxStateMachine interface for DApplySsm", + using_doxygen: true, + repr: "DApplySsm", + doc: [ "implement ASyntaxStateMachine for DApplySsm" ], +} diff --git a/xo-reader2/idl/ISyntaxStateMachine_DDefineSsm.json5 b/xo-reader2/idl/ISyntaxStateMachine_DDefineSsm.json5 new file mode 100644 index 00000000..8b3fff2a --- /dev/null +++ b/xo-reader2/idl/ISyntaxStateMachine_DDefineSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "\"SyntaxStateMachine.hpp\"", + "\"ssm/ISyntaxStateMachine_Xfer.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SyntaxStateMachine.json5", + brief: "provide ASyntaxStateMachine interface for DDefineSsm", + using_doxygen: true, + repr: "DDefineSsm", + doc: [ "implement ASyntaxStateMachine for DDefineSsm" ], +} diff --git a/xo-reader2/idl/ISyntaxStateMachine_DExpectExprSsm.json5 b/xo-reader2/idl/ISyntaxStateMachine_DExpectExprSsm.json5 new file mode 100644 index 00000000..d1c78ad2 --- /dev/null +++ b/xo-reader2/idl/ISyntaxStateMachine_DExpectExprSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "\"SyntaxStateMachine.hpp\"", + "\"ssm/ISyntaxStateMachine_Xfer.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SyntaxStateMachine.json5", + brief: "provide ASyntaxStateMachine interface for DExpectExprSsm", + using_doxygen: true, + repr: "DExpectExprSsm", + doc: [ "implement ASyntaxStateMachine for DExpectExprSsm" ], +} \ No newline at end of file diff --git a/xo-reader2/idl/ISyntaxStateMachine_DExpectFormalArgSsm.json5 b/xo-reader2/idl/ISyntaxStateMachine_DExpectFormalArgSsm.json5 new file mode 100644 index 00000000..e3486759 --- /dev/null +++ b/xo-reader2/idl/ISyntaxStateMachine_DExpectFormalArgSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "\"SyntaxStateMachine.hpp\"", + "\"ssm/ISyntaxStateMachine_Xfer.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SyntaxStateMachine.json5", + brief: "provide ASyntaxStateMachine interface for DExpectFormalArgSsm", + using_doxygen: true, + repr: "DExpectFormalArgSsm", + doc: [ "implement ASyntaxStateMachine for DExpectFormalArgSsm" ], +} diff --git a/xo-reader2/idl/ISyntaxStateMachine_DExpectFormalArglistSsm.json5 b/xo-reader2/idl/ISyntaxStateMachine_DExpectFormalArglistSsm.json5 new file mode 100644 index 00000000..019573d0 --- /dev/null +++ b/xo-reader2/idl/ISyntaxStateMachine_DExpectFormalArglistSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "\"SyntaxStateMachine.hpp\"", + "\"ssm/ISyntaxStateMachine_Xfer.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SyntaxStateMachine.json5", + brief: "provide ASyntaxStateMachine interface for DExpectFormalArglistSsm", + using_doxygen: true, + repr: "DExpectFormalArglistSsm", + doc: [ "implement ASyntaxStateMachine for DExpectFormalArglistSsm" ], +} diff --git a/xo-reader2/idl/ISyntaxStateMachine_DExpectSymbolSsm.json5 b/xo-reader2/idl/ISyntaxStateMachine_DExpectSymbolSsm.json5 new file mode 100644 index 00000000..49248b62 --- /dev/null +++ b/xo-reader2/idl/ISyntaxStateMachine_DExpectSymbolSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "\"SyntaxStateMachine.hpp\"", + "\"ssm/ISyntaxStateMachine_Xfer.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SyntaxStateMachine.json5", + brief: "provide ASyntaxStateMachine interface for DExpectSymbolSsm", + using_doxygen: true, + repr: "DExpectSymbolSsm", + doc: [ "implement ASyntaxStateMachine for DExpectSymbolSsm" ], +} diff --git a/xo-reader2/idl/ISyntaxStateMachine_DExpectTypeSsm.json5 b/xo-reader2/idl/ISyntaxStateMachine_DExpectTypeSsm.json5 new file mode 100644 index 00000000..68883ef0 --- /dev/null +++ b/xo-reader2/idl/ISyntaxStateMachine_DExpectTypeSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "\"SyntaxStateMachine.hpp\"", + "\"ssm/ISyntaxStateMachine_Xfer.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SyntaxStateMachine.json5", + brief: "provide ASyntaxStateMachine interface for DExpectTypeSsm", + using_doxygen: true, + repr: "DExpectTypeSsm", + doc: [ "implement ASyntaxStateMachine for DExpectTypeSsm" ], +} \ No newline at end of file diff --git a/xo-reader2/idl/ISyntaxStateMachine_DIfElseSsm.json5 b/xo-reader2/idl/ISyntaxStateMachine_DIfElseSsm.json5 new file mode 100644 index 00000000..25feadde --- /dev/null +++ b/xo-reader2/idl/ISyntaxStateMachine_DIfElseSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "\"SyntaxStateMachine.hpp\"", + "\"ssm/ISyntaxStateMachine_Xfer.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SyntaxStateMachine.json5", + brief: "provide ASyntaxStateMachine interface for DIfElseSsm", + using_doxygen: true, + repr: "DIfElseSsm", + doc: [ "implement ASyntaxStateMachine for DIfElseSsm" ], +} diff --git a/xo-reader2/idl/ISyntaxStateMachine_DLambdaSsm.json5 b/xo-reader2/idl/ISyntaxStateMachine_DLambdaSsm.json5 new file mode 100644 index 00000000..413c64c8 --- /dev/null +++ b/xo-reader2/idl/ISyntaxStateMachine_DLambdaSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "\"SyntaxStateMachine.hpp\"", + "\"ssm/ISyntaxStateMachine_Xfer.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SyntaxStateMachine.json5", + brief: "provide ASyntaxStateMachine interface for DLambdaSsm", + using_doxygen: true, + repr: "DLambdaSsm", + doc: [ "implement ASyntaxStateMachine for DLambdaSsm" ], +} diff --git a/xo-reader2/idl/ISyntaxStateMachine_DParenSsm.json5 b/xo-reader2/idl/ISyntaxStateMachine_DParenSsm.json5 new file mode 100644 index 00000000..7ea19fc0 --- /dev/null +++ b/xo-reader2/idl/ISyntaxStateMachine_DParenSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "\"SyntaxStateMachine.hpp\"", + "\"ssm/ISyntaxStateMachine_Xfer.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SyntaxStateMachine.json5", + brief: "provide ASyntaxStateMachine interface for DParenSsm", + using_doxygen: true, + repr: "DParenSsm", + doc: [ "implement ASyntaxStateMachine for DParenSsm" ], +} diff --git a/xo-reader2/idl/ISyntaxStateMachine_DProgressSsm.json5 b/xo-reader2/idl/ISyntaxStateMachine_DProgressSsm.json5 new file mode 100644 index 00000000..83c10717 --- /dev/null +++ b/xo-reader2/idl/ISyntaxStateMachine_DProgressSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "\"SyntaxStateMachine.hpp\"", + "\"ssm/ISyntaxStateMachine_Xfer.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SyntaxStateMachine.json5", + brief: "provide ASyntaxStateMachine interface for DProgressSsm", + using_doxygen: true, + repr: "DProgressSsm", + doc: [ "implement ASyntaxStateMachine for DProgressSsm" ], +} diff --git a/xo-reader2/idl/ISyntaxStateMachine_DSequenceSsm.json5 b/xo-reader2/idl/ISyntaxStateMachine_DSequenceSsm.json5 new file mode 100644 index 00000000..e497ef7f --- /dev/null +++ b/xo-reader2/idl/ISyntaxStateMachine_DSequenceSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "\"SyntaxStateMachine.hpp\"", + "\"ssm/ISyntaxStateMachine_Xfer.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SyntaxStateMachine.json5", + brief: "provide ASyntaxStateMachine interface for DSequenceSsm", + using_doxygen: true, + repr: "DSequenceSsm", + doc: [ "implement ASyntaxStateMachine for DSequenceSsm" ], +} diff --git a/xo-reader2/idl/ISyntaxStateMachine_DToplevelSeqSsm.json5 b/xo-reader2/idl/ISyntaxStateMachine_DToplevelSeqSsm.json5 new file mode 100644 index 00000000..7a91622f --- /dev/null +++ b/xo-reader2/idl/ISyntaxStateMachine_DToplevelSeqSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "\"SyntaxStateMachine.hpp\"", + "\"ssm/ISyntaxStateMachine_Xfer.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SyntaxStateMachine.json5", + brief: "provide ASyntaxStateMachine interface for DToplevelSeqSsm", + using_doxygen: true, + repr: "DToplevelSeqSsm", + doc: [ "implement ASyntaxStateMachine for DToplevelSeqSsm" ], +} diff --git a/xo-reader2/idl/SyntaxStateMachine.json5 b/xo-reader2/idl/SyntaxStateMachine.json5 new file mode 100644 index 00000000..4cafd9c3 --- /dev/null +++ b/xo-reader2/idl/SyntaxStateMachine.json5 @@ -0,0 +1,129 @@ +{ + mode: "facet", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + // includes in ASyntaxStateMachine.hpp + includes: [ + "\"ParserStateMachine.hpp\"", + "\"syntaxstatetype.hpp\"", + "", + "", + ], + // extra includes in SyntaxStateMachine.hpp, if any + user_hpp_includes: [], + namespace1: "xo", + namespace2: "scm", + // text after includes, before ASyntaxStateMachine + pretext: ["// {pretex} here"], + facet: "SyntaxStateMachine", + detail_subdir: "ssm", + brief: "specialized state machine for parsing some particular schematika syntax", + using_doxygen: true, + doc: [ + "Assistant to schematika parser dedicated to particular syntax" + ], + types: [ + { name: "TypeDescr", doc: [ "reflected c++ type" ], definition: "xo::reflect::TypeDescr" }, + // { name: string, doc: [ string ], definition: string }, + ], + const_methods: [ + { + name: "ssm_type", + doc: ["identify a type of syntax state machine"], + return_type: "syntaxstatetype", + args: [], + const: true, + noexcept: true, + attributes: [], + }, + { + name: "get_expect_str", + doc: ["text describing expected/allowed input to this ssm in current state"], + return_type: "std::string_view", + args: [], + const: true, + noexcept: true, + attributes: [], + }, + ], + nonconst_methods: [ + { + name: "on_token", + doc: ["operate state machine for incoming token @p tk"], + return_type: "void", + args: [ + {type: "const Token &", name: "tk"}, + {type: "ParserStateMachine *", name: "p_psm"}, + ], + }, + { + name: "on_parsed_symbol", + doc: ["update stat machine for incoming parsed symbol @p sym"], + return_type: "void", + args: [ + {type: "std::string_view", name: "sym"}, + {type: "ParserStateMachine *", name: "p_psm"}, + ], + }, + { + name: "on_parsed_typedescr", + doc: ["operate state machine for incoming type description @p td"], + return_type: "void", + args: [ + {type: "TypeDescr", name: "td"}, + {type: "ParserStateMachine *", name: "p_psm"}, + ], + }, + { + name: "on_parsed_formal", + doc: ["operate state machine for formal emitted by nested ssm"], + return_type: "void", + args: [ + {type: "const DUniqueString *", name: "param_name"}, + {type: "TypeDescr", name: "param_type"}, + {type: "ParserStateMachine *", name: "p_psm"}, + ], + }, + { + name: "on_parsed_formal_with_token", + doc: ["operate state machine for formal emitted by nested ssm"], + return_type: "void", + args: [ + {type: "const DUniqueString *", name: "param_name"}, + {type: "TypeDescr", name: "param_type"}, + {type: "const Token &", name: "tk"}, + {type: "ParserStateMachine *", name: "p_psm"}, + ], + }, + { + name: "on_parsed_formal_arglist", + doc: ["consume formal arglist emitted by nested ssm"], + return_type: "void", + args: [ + {type: "DArray *", name: "arglist"}, + {type: "ParserStateMachine *", name: "p_psm"}, + ], + }, + { + name: "on_parsed_expression", + doc: ["update state machine for incoming parsed expression @p expr"], + return_type: "void", + args: [ + {type: "obj", name: "expr"}, + {type: "ParserStateMachine *", name: "p_psm"}, + ], + }, + { + name: "on_parsed_expression_with_token", + doc: ["update state machine @p p_psm for incoming parsed expression @p expr followed by token @p tk"], + return_type: "void", + args: [ + {type: "obj", name: "expr"}, + {type: "const Token &", name: "tk"}, + {type: "ParserStateMachine *", name: "p_psm"}, + ], + }, + ], + router_facet_explicit_content: [ ], +} diff --git a/xo-reader2/include/xo/reader2/ApplySsm.hpp b/xo-reader2/include/xo/reader2/ApplySsm.hpp new file mode 100644 index 00000000..6e9f9a9d --- /dev/null +++ b/xo-reader2/include/xo/reader2/ApplySsm.hpp @@ -0,0 +1,12 @@ +/** @file ApplySsm.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DApplySsm.hpp" +#include "ssm/ISyntaxStateMachine_DApplySsm.hpp" +#include "ssm/IPrintable_DApplySsm.hpp" + +/* end ApplySsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/DApplySsm.hpp b/xo-reader2/include/xo/reader2/DApplySsm.hpp new file mode 100644 index 00000000..d53b3c5c --- /dev/null +++ b/xo-reader2/include/xo/reader2/DApplySsm.hpp @@ -0,0 +1,213 @@ +/** @file DApplySsm.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DSyntaxStateMachine.hpp" +#include "syntaxstatetype.hpp" +#include +//#include +#include + + +namespace xo { + namespace scm { + /** + * fn ( arg1 , arg2 , .. , argn ) + * ^ ^ ^ ^ ^ ^ ^ ^ ^ + * | | | | | | | | (done) + * | | | | | | | apply_3 + * | | | | | | apply_2:expect_rhs_expression + * | | | | | apply_3 + * | | | | apply_2:expect_rhs_expression + * | | | apply_3 + * | | apply_2:expect_rhs_expression + * | apply_1 + * apply_0:expect_rhs_expression + * + * apply_0 --on_expr()--> apply_1 + * apply_1 --on_leftparen()--> apply_2 + * apply_2 --on_expr()--> apply_3 + * apply_3 --on_comma()--> apply_2 + * --on_rightparen()-> (done) + * + * apply_0: start + * apply_1: leftparen following expr allows parser to recognize apply + * apply_2: expect next argument + * apply_3: got argument, expect comma or rightparen to continue + * (done): apply complete, pop exprstate from stack + * + * In practice will start in state apply_1 + **/ + enum class applyexprstatetype { + invalid = -1, + + apply_0, + apply_1, + apply_2, // rename -> apply_2a + apply_3, // rename -> apply_2b + + N + }; + + extern const char * applyexprstatetype_descr(applyexprstatetype x); + + std::ostream & + operator<<(std::ostream & os, applyexprstatetype x); + + /** @class DApplySsm + * @brief state machine for parsing a schematika function-call-expression + **/ + class DApplySsm : public DSyntaxStateMachine { + public: + using Super = DSyntaxStateMachine; + using TypeDescr = xo::reflect::TypeDescr; + using AAllocator = xo::mm::AAllocator; + using DArena = xo::mm::DArena; + using ppindentinfo = xo::print::ppindentinfo; + + //using Apply = xo::scm::Apply; + + public: + /** @defgroup scm-applyssm-ctors constructors **/ + ///@{ + + /** construct apply ssm with @p fn_expr + * supplying function to be invoked. + * + * Expect during parsing of input like f(...) + * that we parse f before parser knows that it will be + * followed by leftparen + **/ + explicit DApplySsm(applyexprstatetype applystate, + obj fn_expr, + DArray * args); + + /** create instance using memory from @p parser_mm. + * with function to be called supplied by @p fn_expr. + **/ + static DApplySsm * _make(DArena & parser_mm, + obj fn_expr); + + /** create fop referring to new DApplySsm **/ + static obj make(DArena & parser_mm, + obj fn_expr); + + /** + * Start apply. Will trigger this after input like + * "fn(" + * or + * "makefn()()" + * + * apply_xs remains on expr stack until closing right paren + * fn(arg1-expr, arg2-expr, ...) + * + * @p fnex expression in function position + * @p p_psm parser state machine + **/ + static void start(obj fnex, + ParserStateMachine * p_psm); + ///@} + /** @defgroup scm-applyssm-access-methods access methods **/ + ///@{ + + /** identify this nested state machine **/ + static const char * ssm_classname() { return "DApplySsm"; } + + /** current internal state **/ + applyexprstatetype applystate() const noexcept { return applystate_; } + + ///@} + /** @defgroup scm-applyssm-methods general methods **/ + ///@{ + + /** handle leftparen token @p tk for this ssm, + * with overall parser state in @p p_psm + **/ + void on_leftparen_token(const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup ssm-applyssm-facet syntaxstatemachine facet methods **/ + ///@{ + + /** identifies the ssm implemented here **/ + syntaxstatetype ssm_type() const noexcept; + + /** mnemonic for expected remaining syntax for current parsing state **/ + std::string_view get_expect_str() const noexcept; + + /** update this apply-ssm for incoming token @p tk, + * with overall parsing state in @p p_psm + **/ + void on_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update this apply-ssm with data from nested ssm: + * expression @p expr, followed by token @p tk. + **/ + void on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm); + + ///@} + +#ifdef NOT_YET + + virtual void on_expr(bp expr, + parserstatemachine * p_psm) override; + + virtual void on_comma_token(const token_type & tk, + parserstatemachine * p_psm) override; + virtual void on_rightparen_token(const token_type & tk, + parserstatemachine * p_psm) override; + + private: + static std::unique_ptr make(); +#endif + + /** @defgroup ssm-applyssm-printable-facet printable facet **/ + ///@{ + + /** pretty-printing support **/ + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + private: + /** @defgroup ssm-applyssm-mpl-methods **/ + ///@{ + + ///@} + + private: + /** @defgroup ssm-applyssm-member-variables **/ + ///@{ + + /** current state of parser for this apply expression **/ + applyexprstatetype applystate_ = applyexprstatetype::apply_0; + /** evaluates to function to be invoked **/ + obj fn_expr_; + /** args_expr_v_[i] evaluates to the i'th argument to call. + * Not using flexible array here since we don't know size at + * construction time + * + * (though could revisit + realloc this DApplySsm instance in + * place to optimize) + **/ + DArray * args_expr_v_ = nullptr; + + ///@} + }; + } /*namespace scm */ + + namespace print { +#ifndef ppdetail_atomic + PPDETAIL_ATOMIC(xo::scm::applyexprstatetype); +#endif + } +} /*namespace xo*/ + +/* end DApplySsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/DDefineSsm.hpp b/xo-reader2/include/xo/reader2/DDefineSsm.hpp new file mode 100644 index 00000000..6380a233 --- /dev/null +++ b/xo-reader2/include/xo/reader2/DDefineSsm.hpp @@ -0,0 +1,216 @@ +/** @file DDefineSsm.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "DSyntaxStateMachine.hpp" +#include "syntaxstatetype.hpp" +#include +#include +#include +#include + +namespace xo { + namespace scm { + /** + * @pre + * + * def foo : f64 = 1 ; + * ^ ^ ^ ^ ^ ^ ^ ^ + * | | | | | | | (done) + * | | | | | | def_6:expect_rhs_expression:expr_progress + * | | | | | def_5:expect_rhs_expression + * | | | | def_4 + * | | | def_3:expect_type + * | | def_2 + * | def_1:expect_symbol + * def_0 + * expect_toplevel_expression_sequence + * + * def_0 --on_def_token()--> def_1 + * def_1 --on_symbol()--> def_2 + * def_2 --on_colon_token()--> def_3 + * --on_singleassign_token()--> def_5 + * def_3 --on_typedescr()--> def_4 + * def_4 --on_singleassign_token()--> def_5 + * def_5 --on_parsed_expression()--> def_6 + * def_6 --on_semicolon_token()--> (done) + * + * def_1:expect_symbol: got 'def' keyword, symbol to follow + * def_1: got symbol name + * def_3:expect_symbol got (optional) colon, type name to follow + * def_4: got symbol type + * def_6:expect_rhs_expression got (optional) equal sign, value to follow + * (done): definition complete, pop exprstate from stack + * + * @endpre + **/ + enum class defexprstatetype { + invalid = -1, + + def_0, + def_1, + def_2, + def_3, + def_4, + def_5, + def_6, + + n_defexprstatetype, + }; + + extern const char * defexprstatetype_descr(defexprstatetype x); + + std::ostream & + operator<<(std::ostream & os, defexprstatetype x); + + /** @class DDefineSsm + * @brief state machine for parsing a define expression + **/ + class DDefineSsm : public DSyntaxStateMachine { + public: + using Super = DSyntaxStateMachine; + using TypeDescr = xo::reflect::TypeDescr; + using AAllocator = xo::mm::AAllocator; + using DArena = xo::mm::DArena; + using ppindentinfo = xo::print::ppindentinfo; + + public: + /** @defgroup scm-definessm-ctors constructors **/ + ///@{ + + /** constructor; using @p def_expr for initial expression scaffold **/ + explicit DDefineSsm(DDefineExpr * def_expr); + + /** create instance using memory from @p parser_mm. + * Initial expression scaffold @p def_expr + **/ + static DDefineSsm * _make(DArena & parser_mm, + DDefineExpr * def_expr); + + /** create fop referring to new DDefineSsm **/ + static obj make(DArena & parser_mm, + DDefineExpr * def_expr); + + /** start nested parser for a define-expression, + * on top of parser state machine @p p_psm + * Use @p parser_mm to allocate syntax state machines, + * and @p expr_mm to allocate expressions + **/ + static void start(DArena & parser_mm, + obj expr_mm, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-definessm-access-methods **/ + ///@{ + + /** identify this nested state machine **/ + static const char * ssm_classname() { return "DDefineSsm"; } + + /** internal state **/ + defexprstatetype defstate() const noexcept { return defstate_; } + + ///@} + /** @defgroup scm-definessm-facet syntaxstatemachine facet methods **/ + ///@{ + + /** identifies the ssm implemented here **/ + syntaxstatetype ssm_type() const noexcept; + + /** text describing expected/allowed input to this ssm in current state. + * Intended to drive error messages + **/ + std::string_view get_expect_str() const noexcept; + + /** operate state machine for this syntax on incoming token @p tk + * with overall parser state in @p p_psm + **/ + void on_token(const Token & tk, + ParserStateMachine * p_psm); + + /** operate state machine for this syntax on incoming symbol-token @p tk + * with overall parser state in @p p_psm + **/ + void on_symbol_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming token @p tk, + * overall parser state in @p p_psm + **/ + void on_def_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming colon token @p tk, + * overall parser state in @p p_psm + **/ + void on_colon_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming singleassign token @p tk, + * overall parser state in @p p_psm + **/ + void on_singleassign_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming semicolon token @p tk, + * overall parser state in @p p_psm + **/ + void on_semicolon_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax after parsing a symbol @p sym; + * overall parser state in @p p_psm + **/ + void on_parsed_symbol(std::string_view sym, + ParserStateMachine * p_psm); + + /** update state for this syntax after parsing a type-description @p td, + * overall parser state in @p p_psm + **/ + void on_parsed_typedescr(TypeDescr td, + ParserStateMachine * p_psm); + + /** update state for this syntax after parsing an expression @p expr, + * overall parser state in @p p_psm + **/ + void on_parsed_expression(obj expr, + ParserStateMachine * p_psm); + + /** update state for this syntax after parsing an expression @p expr + * followed by token @p tk, + * with overall parser state in @p p_psm + **/ + void on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-define-printable-facet printable facet methods **/ + ///@{ + + /** pretty-printer support **/ + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + private: + /** @defgroup scm-definessm-member-vars **/ + ///@{ + + /** identify define-expression state **/ + defexprstatetype defstate_; + + /** scaffolded define-expression. + * This will eventually be the output of this ssm + **/ + obj def_expr_; + + ///@} + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DDefineSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp b/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp new file mode 100644 index 00000000..7600948c --- /dev/null +++ b/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp @@ -0,0 +1,174 @@ +/** @file DExpectExprSsm.hpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "DSyntaxStateMachine.hpp" +//#include "ParserStateMachine.hpp" +#include "syntaxstatetype.hpp" +#include +#include + +namespace xo { + namespace scm { + + class DExpectExprSsm : public DSyntaxStateMachine { + public: + using Super = DSyntaxStateMachine; + using TypeDescr = xo::reflect::TypeDescr; + using DArena = xo::mm::DArena; + using ppindentinfo = xo::print::ppindentinfo; + + public: + explicit DExpectExprSsm(bool allow_defs, + bool cxl_on_rightparen); + + static DExpectExprSsm * _make(DArena & parser_mm, + bool allow_defs, + bool cxl_on_rightbrace); + + /** create fop referring to new DExpectExprSsm **/ + static obj make(DArena & parser_mm, + bool allow_defs, + bool cxl_on_rightbrace); + + static void start(DArena & parser_mm, + bool allow_defs, + bool cxl_on_rightbrace, + ParserStateMachine * p_psm); + static void start(ParserStateMachine * p_psm); + + /** @defgroup scm-expectexpr-access-methods access methods **/ + ///@{ + + static const char * ssm_classname() { return "DExpectExprSsm"; } + bool allow_defs() const noexcept { return allow_defs_; } + bool cxl_on_rightbrace() const noexcept { return cxl_on_rightbrace_; } + + ///@} + /** @defgroup scm-expectexpr-methods general methods **/ + ///@{ + + /** update state for this syntax on incoming leftparen token @p tk, + * with overall parser state in @p p_psm + **/ + void on_leftparen_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming leftbrace token @p tk, + * with overall parser state in @p p_psm + **/ + void on_leftbrace_token(const Token & tk, + ParserStateMachine * p_psm); + + /** step state machine for this syntax on incoming boolean literal token @p tkk + * with overall parser state in @p p_psm + **/ + void on_bool_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming f64 token @p tk, + * overall parser state in @p p_psm + **/ + void on_f64_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming i64 token @p tk, + * overall parser state in @p p_psm + **/ + void on_i64_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming string token @p tk, + * overall parser state in @p p_psm + **/ + void on_string_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming if-token @p tk, + * overall parser state in @p p_psm. + * + * action: start nested if-else ssm + **/ + void on_if_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming lambda token @p tk, + * overall parser state in @p p_psm + * + * action: start nested lambda ssm + **/ + void on_lambda_token(const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-expectexpr-ssm-facet syntaxstatemachine facet methods **/ + ///@{ + + /** identifies the ssm implemented here **/ + syntaxstatetype ssm_type() const noexcept; + + /** text describing expected/allowed input to this ssm in current state. + * Intended to drive error mesages + **/ + std::string_view get_expect_str() const noexcept; + + /** operate state machine for this syntax on incoming token @p tk + * with overall parser state in @p p_psm + **/ + void on_token(const Token & tk, + ParserStateMachine * p_psm); + + /** operate state machine for this syntax on incoming symbol-token @p tk + * with overall parser state in @p p_psm + **/ + void on_symbol_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming token @p tk, + * overall parser state in @p p_psm + **/ + void on_def_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax after parsing an expression @p expr, + * overall parser state in @p p_psm + **/ + void on_parsed_expression(obj expr, + ParserStateMachine * p_psm); + + /** update state for this syntax after parsing an expression @p expr + * followed by token @p tk + * overall parser state in @p p_psm + **/ + void on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-define-printable-facet printable facet methods **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + private: + /** if true: allow a define-expression here; otherwise reject **/ + bool allow_defs_ = false; + /** if true: expecting either: + * 1a. expression + * 1b. right brace '}', in which case no expression + * if false: expecting only: + * 2a. expression + **/ + bool cxl_on_rightbrace_ = false; + + + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DExpectExprSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/DExpectFormalArgSsm.hpp b/xo-reader2/include/xo/reader2/DExpectFormalArgSsm.hpp new file mode 100644 index 00000000..f1bd7867 --- /dev/null +++ b/xo-reader2/include/xo/reader2/DExpectFormalArgSsm.hpp @@ -0,0 +1,141 @@ +/** @file DExpectFormalSsm.hpp + * + * @author Roland Conybeare, Aug 2024 + **/ + +#pragma once + +#include "DSyntaxStateMachine.hpp" +//#include +//#include "exprstate.hpp" + +namespace xo { + namespace scm { + /** + * name : type + * ^ ^ ^ + * | | formal_2 + * | formal_1 + * formal_0 + * + * formal_0 --on_symbol()--> formal_1 + * formal_1 --on_colon_token()--> formal_2 + * formal_2 --on_typedescr()--> (done) + **/ + enum class formalstatetype { + invalid = -1, + + formal_0, + formal_1, + formal_2, + + n_formalstatetype, + }; + + extern const char * + formalstatetype_descr(formalstatetype x); + + inline std::ostream & + operator<< (std::ostream & os, formalstatetype x) { + os << formalstatetype_descr(x); + return os; + } + + /** @class expect_formal_xs + * @brief parser state-machine for a typed formal parameter + **/ + class DExpectFormalArgSsm : public DSyntaxStateMachine { + public: + using Super = DSyntaxStateMachine; + using TypeDescr = xo::reflect::TypeDescr; + using DArena = xo::mm::DArena; + using ppindentinfo = xo::print::ppindentinfo; + + public: + /** @defgroupo scm-expectfromalargssm-ctors constructors **/ + ///@{ + + DExpectFormalArgSsm(); + + /** create empty instance using memory from @p mm **/ + static obj make(DArena & mm); + + /** create empty instance using memory from @p mm **/ + static DExpectFormalArgSsm * _make(DArena & mm); + + /** puah instance of this ssm onto @p p_psm **/ + static void start(ParserStateMachine * p_psm); + + ///@} + + /** @defgroup scm-expectformalargssm-methods general methods **/ + ///@{ + + static const char * ssm_classname() { return "DExpectFormalArgSsm"; } + + /** update state on incoming colon token @p tk; + * with overall parser state in @p p_psm + **/ + void on_colon_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state on incoming rightparen token @p tk; + * with overall parser state in @p p_psm + **/ + void on_rightparen_token(const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-expectformalargssm-ssm-facet syntaxstatemachine facet methods **/ + ///@{ + + /** identifies the ssm implemented here **/ + syntaxstatetype ssm_type() const noexcept; + + /** mnemonic for expected input (for this ssm) in current state **/ + std::string_view get_expect_str() const noexcept; + + /** update state on incoming token @p tk, + * with overall parser state in @p p_psm + **/ + void on_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state on parsed symbol @p sym emitted by nested ssm, + * with overall parser state in @p p_psm + **/ + void on_parsed_symbol(std::string_view sym, + ParserStateMachine * p_psm); + + /** update state on parsed typedescr @p td emitted by nested ssm, + * with overall parser state in @p p_psm + **/ + void on_parsed_typedescr(TypeDescr td, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-expectformalargssm-printable-facet printable facet methods **/ + ///@{ + + /** pretty-printing support **/ + bool pretty(const ppindentinfo & ppii) const; + + ///@} + +#ifdef PROBABLY_NOT + virtual void on_rightparen_token(const token_type & tk, + exprstatestack * p_stack, + rp * p_emit_expr) override; +#endif + + private: + /** parsing state-machine state **/ + formalstatetype fstate_ = formalstatetype::formal_0; + + /** formal parameter name **/ + const DUniqueString * name_ = nullptr; + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DExpectFormalArgSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/DExpectFormalArglistSsm.hpp b/xo-reader2/include/xo/reader2/DExpectFormalArglistSsm.hpp new file mode 100644 index 00000000..3129f0dc --- /dev/null +++ b/xo-reader2/include/xo/reader2/DExpectFormalArglistSsm.hpp @@ -0,0 +1,157 @@ +/** @file DExpectFormalArglistSsm.hpp + * + * @author Roland Conybeare, Aug 2024 + **/ + +#pragma once + +#include "DSyntaxStateMachine.hpp" +#include +#include + +#ifdef NOT_YET +#include "exprstate.hpp" +#include "formal_arg.hpp" +#include +#endif + +namespace xo { + namespace scm { + /** + * ( name(1) : type(1) , ..., ) + * ^ ^ ^ ^ ^ + * | | | | | + * | | | | argl_1b + * | argl_1a | argl_1a + * argl_0 argl_1b + * + * argl_0 --on_leftparen_token()--> argl_1a + * argl_1a --on_formal()--> argl_1b + * argl_1b -+-on_comma_token()--> argl_1a + * \-on_rightparen_token()--> (done) + **/ + enum class formalarglstatetype { + invalid = -1, + + argl_0, + argl_1a, + argl_1b, + + n_formalarglstatetype, + }; + + extern const char * + formalarglstatetype_descr(formalarglstatetype x); + + inline std::ostream & + operator<< (std::ostream & os, formalarglstatetype x) { + os << formalarglstatetype_descr(x); + return os; + } + + /** @class expect_formal_arglist + * @brief parser state-machine for a formal parameter list + **/ + class DExpectFormalArglistSsm : public DSyntaxStateMachine { + public: + using Super = DSyntaxStateMachine; + using AAllocator = xo::mm::AAllocator; + using DArena = xo::mm::DArena; + using TypeDescr = xo::reflect::TypeDescr; + using ppindentinfo = xo::print::ppindentinfo; + using size_type = std::uint32_t; + + public: + DExpectFormalArglistSsm(DArray * argl); + + /** create instance, using memory from @parser_mm **/ + static obj make(DArena & parser_mm); + static DExpectFormalArglistSsm * _make(DArena & parser_mm); + + static void start(ParserStateMachine * p_psm); + + /** @defgroup scm-expectformalarglistssm-methods general methods **/ + ///@{ + + static const char * ssm_classname() { return "DExpectFormalArglistSsm"; } + + /** update state on incoming token @p tk, with overall parser state in @p p_psm **/ + void on_leftparen_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state on incoming token @p tk, with overall parser state in @p p_psm **/ + void on_comma_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state on incoming rightparen token @p tk, with overall parser state in @p p_psm **/ + void on_rightparen_token(const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-expectformalarglistssm-ssm-facet syntaxstatemachine facet methods **/ + ///@{ + + /** identifies the ssm implemented here **/ + syntaxstatetype ssm_type() const noexcept; + + /** mnemonic for expected input (for this ssm) in current state **/ + std::string_view get_expect_str() const; + + /** update state on incoming token @p tk, + * with overall parser state in @p p_psm + **/ + void on_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state to consume parsed param (name,type) emitted by + * nested ssm, with overall parser state in @p p_psm + **/ + void on_parsed_formal(const DUniqueString * param_name, + TypeDescr param_type, + ParserStateMachine * p_psm); + /** update state to consume parsed formal (name,type) emitted + * by nested ssm, that's followed immediately by token @p tk. + * overall parser state in @p *p_psm + **/ + void on_parsed_formal_with_token(const DUniqueString * param_name, + TypeDescr param_type, + const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-expectformalarglistssm-printable-facet printable facet methods **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + private: + /** @defgroup scm-expectformalarglistssm-impl-methods **/ + ///@{ + + /** update local state to include parsed formal (param_name, param_type). + * If stack memory needed, get from @p parser_alloc. + * Lifetime until formal arglist completely parsed + **/ + void _accept_formal(obj expr_alloc, + DArena & parser_alloc, + const DUniqueString * param_name, + TypeDescr param_type); + + ///@} + + private: + /** parsing state-machine state **/ + formalarglstatetype fastate_ = formalarglstatetype::argl_0; + /** populate with (parameter-name, parameter-type) list + * as they're encountered. + * + * Not using flexible array here since we don't know size at construction time + **/ + DArray * argl_ = nullptr; + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DExpectFormalArglistSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/DExpectSymbolSsm.hpp b/xo-reader2/include/xo/reader2/DExpectSymbolSsm.hpp new file mode 100644 index 00000000..b621985b --- /dev/null +++ b/xo-reader2/include/xo/reader2/DExpectSymbolSsm.hpp @@ -0,0 +1,82 @@ +/* file DExpectSymbolSsm.hpp + * + * author: Roland Conybeare, Aug 2024 + */ + +#pragma once + +#include "DSyntaxStateMachine.hpp" +#include "syntaxstatetype.hpp" +#include +#include + +namespace xo { + namespace scm { + /** @class DExpectSymbolSsm + * @brief state machine to expect + capture a symbol + * + * For example: + * - lhs in a define-expression + **/ + class DExpectSymbolSsm : public DSyntaxStateMachine { + public: + using Super = DSyntaxStateMachine; + using DArena = xo::mm::DArena; + using TypeDescr = xo::reflect::TypeDescr; + using ppindentinfo = xo::print::ppindentinfo; + + public: + DExpectSymbolSsm(); + + /** create instance using memory from @p parser_mm **/ + static DExpectSymbolSsm * _make(DArena & parser_mm); + + /** create fop referring to new DExpectSymbolSsm **/ + static obj make(DArena & parser_mm); + + /** start nested parser expecting a symbol, + * on top of parser state machine @p p_psm. + * On success will deliver symbol by invoking + * .on_symbol(sym, p_psm) + * to the state machine on top of the stack + * as of when this start() method invoked + **/ + static void start(ParserStateMachine * p_psm); + + /** update state for this syntax on incoming token @p tk, + * with overall parser state in @p p_psm + **/ + static void on_symbol_token(const Token & tk, + ParserStateMachine * p_psm); + + static const char * ssm_classname() { return "DExpectSymbolSsm"; } + + /** @defgroup scm-expectsymbol-ssm-facet syntaxstatemachine facet methods **/ + ///@{ + + /** identifies the ssm implemented here **/ + syntaxstatetype ssm_type() const noexcept; + + /** text describing expected/allowed input to this ssm in current state. + * Intended to drive error mesages + **/ + std::string_view get_expect_str() const noexcept; + + /** operate state machine for this syntax on incoming token @p tk + * with overall parser state in @p p_psm + **/ + void on_token(const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-expectsymbol-printable-facet printable facet methods **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DExpectSymbolSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/DExpectTypeSsm.hpp b/xo-reader2/include/xo/reader2/DExpectTypeSsm.hpp new file mode 100644 index 00000000..8d67b448 --- /dev/null +++ b/xo-reader2/include/xo/reader2/DExpectTypeSsm.hpp @@ -0,0 +1,80 @@ +/** @file expect_type_xs.hpp + * + * @author Roland Conybeare, Aug 2024 + **/ + +#pragma once + +#include "DSyntaxStateMachine.hpp" +#include +#include + +namespace xo { + namespace scm { + /** @class DExpectTypeSsm + * @brief syntax state-machine for accepting a Schemtika typename-expression + * + * Jan 2026 + * Placeholder implementation at present. + * Only types are a handful of baked-in values + * + * @pre + * + * @endpre + **/ + class DExpectTypeSsm : public DSyntaxStateMachine { + public: + using Super = DSyntaxStateMachine; + using TypeDescr = xo::reflect::TypeDescr; + using DArena = xo::mm::DArena; + using ppindentinfo = xo::print::ppindentinfo; + + public: + DExpectTypeSsm(); + + static DExpectTypeSsm * _make(DArena & parser_mm); + + /** create fop referring to new DExpectTypeSsm **/ + static obj make(DArena & parser_mm); + + static void start(ParserStateMachine * p_psm); + + static const char * ssm_classname() { return "DExpectTypeSsm"; } + + /** @defgroup scm-expecttype-ssm-facet syntaxstatemachine facet methods **/ + ///@{ + + /** identifies the ssm implemented here **/ + syntaxstatetype ssm_type() const noexcept; + + /** text describing expected/allowed input to this ssm in current state. + * Intended to drive error messages. + **/ + std::string_view get_expect_str() const noexcept; + + /** operate state machine for this syntax on incoming token @p tk + * with overall parser state in @p p_psm + **/ + void on_token(const Token & tk, + ParserStateMachine * p_psm); + + /** operate state machien for this syntax on incoming symbol-token @p tk + * with overall parser state in @p p_psm + **/ + void on_symbol_token(const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-expecttype-printable-facet printable facet methods **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + }; + } /*namespace scm*/ +} /*namespace xo*/ + + +/* end DExpectTypeSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/DIfElseSsm.hpp b/xo-reader2/include/xo/reader2/DIfElseSsm.hpp new file mode 100644 index 00000000..345f3fa5 --- /dev/null +++ b/xo-reader2/include/xo/reader2/DIfElseSsm.hpp @@ -0,0 +1,193 @@ +/** @file DIfElseSsm.hpp + * + * @author Roland Conybeare, Jul 2025 + **/ + +#pragma once + +#include "DSyntaxStateMachine.hpp" +#include +#include "syntaxstatetype.hpp" +#include +#include +#include + +namespace xo { + namespace scm { + /** + * if test-expr then then-expr else else-expr ; + * ^ ^ ^ ^ ^ ^ ^ + * | | | | | | | + * | if_1 if_2 if_3 if_4 if_5 if_6 + * if_0 + * + * if_0 --on_if_token()--> if_1 + * if_1 --on_expr()--> if_2 + * if_2 --on_then_token()--> if_3 + * if_3 --on_expr()--> if_4 + * if_4 --on_else_token()--> if_5 + * --on_semicolon_token()--> (done) + * if_5 --on_expr()-->if_6 + * if_6 --on_semicolon_token()--> (done) + **/ + enum class ifexprstatetype { + invalid = -1, + + if_0, + if_1, + if_2, + if_3, + if_4, + if_5, + if_6, + + N, + }; + + extern const char * ifexprstatetype_descr(ifexprstatetype x); + + std::ostream & + operator<<(std::ostream & os, ifexprstatetype x); + + /** @class DIfElseSsm + * @brief syntax state machine for parsing a conditional expression + **/ + class DIfElseSsm : public DSyntaxStateMachine { + public: + using Super = DSyntaxStateMachine; + using AAllocator = xo::mm::AAllocator; + using DArena = xo::mm::DArena; + using TypeDescr = xo::reflect::TypeDescr; + using ppindentinfo = xo::print::ppindentinfo; + + public: + /** @defgroup scm-ifelsessm-expression-ctors constructors **/ + ///@{ + explicit DIfElseSsm(DIfElseExpr * ifelse_expr); + + /** create instance using memory from @p parser_mm + * with initial scaffold @p ifelse_expr. + **/ + static DIfElseSsm * _make(DArena & parser_mm, + DIfElseExpr * ifelse_expr); + + /** create fop referring to new DIfElseSsm **/ + static obj make(DArena & parser_mm, + DIfElseExpr * ifelse_expr); + + /** start nested parser for an if-else expression + * on top of parser state machine @p p_psm. + * Use @p parser_mm to allocate syntax state machines + * (i.e. temporary memory needed only during parsing) + * Use @p expr_mm to allocate expressions. + **/ + static void start(DArena & parser_mm, + obj expr_mm, + ParserStateMachine * p_psm); + + static const char * ssm_classname() { return "DIfElseSsm"; } + + DSyntaxStateMachine * super() { return this; } + + ///@} + /** @defgroup scm-ifelsessm-expression-methods general methods **/ + ///@{ + + /** operate state machine on if-token input @p tk, + * with overall parser state in @p p_psm + **/ + void on_if_token(const Token & tk, + ParserStateMachine * p_psm); + + /** operate state machine on then-token input @p tk, + * with overall parser state in @p p_psm + **/ + void on_then_token(const Token & tk, + ParserStateMachine * p_psm); + + /** operate state machine on else-token input @p tk, + * with overall parser state in @p p_psm + **/ + void on_else_token(const Token & tk, + ParserStateMachine * p_psm); + + /** victory: report completed @ref if_expr_ to parent ssm, + * after removing this ssm from parser stack + **/ + void finish_and_continue(ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-ifelsessm-expression-facet expression facet methods **/ + ///@{ + + /** identifies this state machine **/ + syntaxstatetype ssm_type() const noexcept; + + /** text describing expected/allowed input to this ssm in current state. + * Intended to drive error messages + **/ + std::string_view get_expect_str() const noexcept; + + /** operate state machine for this syntax on incoming token @p tk + * with overall parser state in @p p_psm + **/ + void on_token(const Token & tk, + ParserStateMachine * p_psm); + + /** operate state machine for this syntax on incoming semicolon token @p tk + * with overall parser state in @p p_psm + **/ + void on_semicolon_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax after parsing an expression @p expr, + * overall parser state in @p p_psm. + **/ + void on_parsed_expression(obj expr, + ParserStateMachine * p_psm); + + /** update state for this syntax after parsing an expression @p expr, + * followed by semicolon, + * with overall parser state in @p p_psm. + **/ + void on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-ifelsessm-printable-facet printable facet methods **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + +#ifdef NOT_YET + virtual void on_rightbrace_token(const token_type & tk, + parserstatemachine * p_psm) override; +#endif + + private: +#ifdef NOT_YET + static std::unique_ptr make(); + + /** exit this exprstate, + * and deliver @ref if_expr_ to parent exprstate + **/ + void finish_and_continue(parserstatemachine * p_psm); +#endif + + private: + ifexprstatetype ifstate_ = ifexprstatetype::invalid; + /** scaffold ifelse-expression here. + * This will eventually be the output of this ssm + * + * TODO: can use DIfElseExpr* here. See xo-object2//DList + **/ + obj if_expr_; + + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DIfElseSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/DLambdaSsm.hpp b/xo-reader2/include/xo/reader2/DLambdaSsm.hpp new file mode 100644 index 00000000..5ecbecd2 --- /dev/null +++ b/xo-reader2/include/xo/reader2/DLambdaSsm.hpp @@ -0,0 +1,213 @@ +/** @file DLambdaSsm.hpp + * + * Author: Roland Conybeare + **/ + +#pragma once + +#include "DSyntaxStateMachine.hpp" +#include +#include +//#include + +namespace xo { + namespace scm { + class ParserStateMachine; + + /** + * @text + * + * lambda ( name(1) : type(1), ..., ) : type body-expr ; + * ^ ^ ^ ^ ^ ^ + * | | | | lm_4 lm_5 + * | | | lm_3 + * lm_0 lm_1 lm_2 + * + * lm_0 --on_lambda_token()--> lm_1 + * lm_1 --on_formal_arglist()--> lm_2 + * lm_2 --on_expr()--> lm_3 + * lm_5 --on_semicolon_token()--> (done) + * + * @endtext + **/ + enum class lambdastatetype { + invalid = -1, + + lm_0, + lm_1, + lm_2, + lm_3, + lm_4, + lm_5, + + n_lambdastatetype + }; + + extern const char * + lambdastatetype_descr(lambdastatetype x); + + inline std::ostream & + operator<< (std::ostream & os, lambdastatetype x) { + os << lambdastatetype_descr(x); + return os; + } + + /** @class DLambdaSsm + * @brief parsing state-machine for a lambda-expression + **/ + class DLambdaSsm : public DSyntaxStateMachine { + public: + using Super = DSyntaxStateMachine; + using DLocalSymtab = xo::scm::DLocalSymtab; + using AAllocator = xo::mm::AAllocator; + using DArena = xo::mm::DArena; + using TypeDescr = xo::reflect::TypeDescr; + using ppindentinfo = xo::print::ppindentinfo; + + public: + /** @defgroup scm-lambdassm-ctors **/ + ///@{ + + DLambdaSsm(); + + /** create instance using memory from @p parser_mm **/ + static obj make(DArena & parser_mm); + + /** create instance using memory from @p parser_mm **/ + static DLambdaSsm * _make(DArena & parser_mm); + + ///@} + /** @defgroup scm-lambdassm-methods **/ + ///@{ + + static const char * ssm_classname() { return "DLambdaSsm"; } + + static void start(ParserStateMachine * p_psm); + + /** update ssm on lambda keyword token @p tk, + * with overall parser state in @p p_psm + **/ + void on_lambda_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update ssm on yield token @p tk, + * with overall parser state in @p p_psm + **/ + void on_yields_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update ssm on leftbrace token @p tk, + * with overall parser state in @p p_psm + **/ + void on_leftbrace_token(const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-lambdassm-syntaxstatemachine-facet **/ + ///@{ + + /** identify this nested state machine **/ + syntaxstatetype ssm_type() const noexcept; + + /** text describing expected/allowed input to this ssm in current state. + * Intended to drive error messages + **/ + std::string_view get_expect_str() const noexcept; + + /** update this ssm for incoming token @p tk **/ + void on_token(const Token & tk, + ParserStateMachine * p_psm); + +#ifdef OBSOLETE + /** update this ssm when nested parser + * emits @p td. + **/ + void on_parsed_symbol(std::string_view sym, + ParserStateMachine * p_psm); +#endif + + /** update this ssm when nested parser + * emits @p td. + **/ + void on_parsed_typedescr(TypeDescr td, + ParserStateMachine * p_psm); + +#ifdef OBSOLETE + /** update this ssm to consume parsed formal (name,value) + * from nested (and now expired) ssm + **/ + void on_parsed_formal(const DUniqueString * sym, + TypeDescr td, + ParserStateMachine * p_psm); +#endif + + /** consume formal params @p arglist from completed nested ssm, + * with overall parser state in @p p_psm. + **/ + void on_parsed_formal_arglist(DArray * arglist, + ParserStateMachine * p_psm); + + /** update this ssm when nested parser + * emits expression @p expr + **/ + void on_parsed_expression(obj expr, + ParserStateMachine * p_psm); + + /** update this ssm when nested parser + * emits expression @p expr + **/ + void on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm); + +#ifdef NOT_YET + virtual const char * get_expect_str() const override; + + virtual void on_leftbrace_token(const token_type & tk, + parserstatemachine * p_psm) override; + virtual void on_colon_token(const token_type & tk, + parserstatemachine * p_psm) override; + virtual void on_semicolon_token(const token_type & tk, + parserstatemachine * p_psm) override; + virtual void on_f64_token(const token_type & tk, + parserstatemachine * p_psm) final override; + + virtual void print(std::ostream & os) const override; + virtual bool pretty_print(const print::ppindentinfo & ppii) const override; +#endif + + ///@} + /** @defgroup scm-lambdassm-printable-facet **/ + ///@{ + + /** pretty-printing support **/ + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + + private: + /** parsing state-machine state **/ + lambdastatetype lmstate_ = lambdastatetype::lm_0; + + /** lambda environment (for formal parameters) **/ + DLocalSymtab * local_symtab_ = nullptr; + + /** explicit return type (if supplied) **/ + TypeDescr explicit_return_td_ = nullptr; + + /** lambda signature (when known) **/ + TypeDescr lambda_td_ = nullptr; + + /** body expression **/ + obj body_; + + /** parent environment **/ + obj parent_symtab_; + + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DLambdaSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/DParenSsm.hpp b/xo-reader2/include/xo/reader2/DParenSsm.hpp new file mode 100644 index 00000000..05c3926b --- /dev/null +++ b/xo-reader2/include/xo/reader2/DParenSsm.hpp @@ -0,0 +1,150 @@ +/** @file DParenSsm.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DSyntaxStateMachine.hpp" +#include "syntaxstatetype.hpp" +#include +#include + +namespace xo { + namespace scm { + + /** + * @pre + * + * ( x * x ) + * ^ ^ ^ ^ + * | | | (done) + * | | | + * | | lparen_2 + * | lparen_1:expect expr + * lparen_0 + * + * lparen_0 --on_leftparen_token()--> lparen_1 + * lparen_1 --on_parsed_expression()--> lparen_2 + * lparen_2 --on_rightparen_token()--> (done) + * + * @endpre + **/ + + enum class parenexprstatetype { + invalid = -1, + + lparen_0, + lparen_1, + lparen_2, + + N, + }; + + extern const char * parenexprstatetype_descr(parenexprstatetype x); + + std::ostream & + operator<<(std::ostream & os, parenexprstatetype x); + + class DParenSsm : public DSyntaxStateMachine { + public: + using Super = DSyntaxStateMachine; + using TypeDescr = xo::reflect::TypeDescr; + using AAllocator = xo::mm::AAllocator; + using DArena = xo::mm::DArena; + using ppindentinfo = xo::print::ppindentinfo; + + public: + /** @defgroup scm-parenssm-ctors **/ + ///@{ + + DParenSsm(); + + /** create instance using memory from @p parser_mm + **/ + static DParenSsm * _make(DArena & parser_mm); + + /** create fop pointing with new DParenSsm using memory from @p parser_mm **/ + static obj make(DArena & parser_mm); + + /** push DParenSsm instance onto @p p_psm stack **/ + static void start(ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-parenssm-access-methods **/ + ///@{ + + /** identify this nested state machine **/ + static const char * ssm_classname() { return "DParenSsm"; } + + /** internal state **/ + parenexprstatetype parenstate() const noexcept { return parenstate_; } + + ///@} + /** @defgroup scm-parenssm-admin-methods admin methods **/ + ///@{ + + /** update ssm state for incoming leftparen token @p tk, + * with overall parser state in @p p_psm + **/ + void on_leftparen_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update ssm state for incoming rightparen token @p tk + * with overall parser state in @p p_psm + **/ + void on_rightparen_token(const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-parenssm-ssm-facet syntaxstatemachine facet methods **/ + ///@{ + + /** identifies this ssm **/ + syntaxstatetype ssm_type() const noexcept; + + /** text describing expected/allowed input to this ssm in current state. **/ + std::string_view get_expect_str() const noexcept; + + /** update ssm for token @p tk, with overall state in @p p_psm **/ + void on_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update ssm for expression @p expr (emitted by nested ssm), + * with overall parser state in @p p_psm + **/ + void on_parsed_expression(obj expr, + ParserStateMachine * p_psm); + + /** update ssm for expression @p expr (emitted by nested ssm) + * that's immediately followed by token @p tk + * with overall parser state in @p p_psm + **/ + void on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psmn); + + ///@} + /** @defgroup scm-parenssm-printable-facet printable facet methods **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + private: + /** @defgroup scm-parenssm-member-vars **/ + ///@{ + + /** identify paren-expression state **/ + parenexprstatetype parenstate_; + /** scaffold expression (representing parenthesized value) here **/ + obj expr_; + + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DParenSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/DProgressSsm.hpp b/xo-reader2/include/xo/reader2/DProgressSsm.hpp new file mode 100644 index 00000000..cc0eb0c5 --- /dev/null +++ b/xo-reader2/include/xo/reader2/DProgressSsm.hpp @@ -0,0 +1,244 @@ +/** @file DProgressSsm.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "DSyntaxStateMachine.hpp" +#include "syntaxstatetype.hpp" +//#include +#include + +#ifdef NOT_YET +#include "exprstate.hpp" +#include "xo/reflect/TypeDescr.hpp" +#include +//#include +#endif + +namespace xo { + namespace scm { + /** represent an infix operator. + * + * See @ref progress_xs::assemble_expr() for translation + * to Expression + **/ + enum class optype { + invalid = -1, + + /** op:= **/ + op_assign, + + /** op< **/ + op_less, + /** op<= **/ + op_less_equal, + /** op== **/ + op_equal, + /** op!= **/ + op_not_equal, + /** op> **/ + op_great, + /** op>= **/ + op_great_equal, + + /** op+ **/ + op_add, + /** op- **/ + op_subtract, + + /** op* **/ + op_multiply, + /** op/ **/ + op_divide, + + n_optype + }; + + extern const char * + optype_descr(optype x); + + /** report operator precedence. + * lowest operator precedence is 1 + **/ + extern int + precedence(optype x); + + inline std::ostream & + operator<< (std::ostream & os, optype x) { + os << optype_descr(x); + return os; + } + + /** @class DProgressSsm + * @brief syntax state machine for parsing a schematica rhs-value-expression + * + * Handles an expression that produces a value, for example appearing on the + * right-hand side of a definition. + * + * Deals with: + * 1. infix operators including operator precedence. + * 2. generates argument-type-specific arithmetic expressions, + * for example using ``Apply::make_add2_f64()`` when adding floating-point numbers + * + * One reason for this to exist is to simulate one-token lookahead. + * To look at but not consume a token T, can push a progress_xs instance P, + * then send T to P. + **/ + class DProgressSsm : public DSyntaxStateMachine { + public: + using Super = DSyntaxStateMachine; + using TypeDescr = xo::reflect::TypeDescr; + using DArena = xo::mm::DArena; + using ppindentinfo = xo::print::ppindentinfo; + + public: + DProgressSsm(obj lhs, optype op); + + static DProgressSsm * _make(DArena & parser_mm, + obj lhs, + optype op); + + /** create fop referring to new DProgressSsm **/ + static obj make(DArena & parser_mm, + obj lhs, + optype op); + + static void start(DArena & parser_mm, + ParserStateMachine * p_psm); + static void start(DArena & parser_mm, + obj lhs, + ParserStateMachine * p_psm); + static void start(DArena & parsermm, + obj lhs, + optype optype, + ParserStateMachine * p_psm); + + syntaxstatetype ssm_type() const noexcept; + +#ifdef NOT_YET + bool admits_f64() const; + + void apply_type_error(const char * self_name, + optype op, + bp expr1, + bp expr2, + parserstatemachine * p_psm) const; +#endif + + static const char * ssm_classname() { return "DProgressSsm"; } + + std::string_view get_expect_str() const noexcept; + + /** assemble expression from collected inputs. + * Usually triggered by syntax like ';' or ')' + **/ + obj assemble_expr(ParserStateMachine * p_psm); + + /** @defgroup scm-progressssm-methods general methods **/ + ///@{ + + /** handle leftparen token @p tk. Overall parser state in @p p_psm **/ + void on_leftparen_token(const Token & tk, + ParserStateMachine * p_psm); + void on_rightparen_token(const Token & tk, + ParserStateMachine * p_psm); + + void on_symbol_token(const Token & tk, + ParserStateMachine * p_psm); + void on_comma_token(const Token & tk, + ParserStateMachine * p_psm); + void on_colon_token(const Token & tk, + ParserStateMachine * p_psm); + void on_singleassign_token(const Token & tk, + ParserStateMachine * p_psm); + void on_operator_token(const Token & tk, + ParserStateMachine * p_psm); + void on_string_token(const Token & tk, + ParserStateMachine * p_psm); + void on_f64_token(const Token & tk, + ParserStateMachine * p_psm); + void on_i64_token(const Token & tk, + ParserStateMachine * p_psm); + void on_bool_token(const Token & tk, + ParserStateMachine * p_psm); + void on_semicolon_token(const Token & tk, + ParserStateMachine * p_psm); + void on_rightbrace_token(const Token & tk, + ParserStateMachine * p_psm); + + /** token belongs to surrounding syntax, + * -> lock in current progress + **/ + void on_completing_token(const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-progressssm-ssm-facet syntaxstatemachine facet methods **/ + /// @{ + + /** operate state machine for this syntax on incoming token @p tk + * with overall parser state in @p p_psm + **/ + void on_token(const Token & tk, + ParserStateMachine * p_psm); + + void on_parsed_expression(obj expr, + ParserStateMachine * p_psm); + void on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-progressssm-printable-facet printable facet methods **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + +#ifdef NOT_YET + void on_comma_token(const token_type & tk, + parserstatemachine * p_psm) final override; + void on_typedescr(TypeDescr td, + parserstatemachine * p_psm) override; + + void on_assign_token(const token_type & tk, + parserstatemachine * p_psm) final override; + void on_leftparen_token(const token_type & tk, + parserstatemachine * p_psm) override; + void on_rightparen_token(const token_type & tk, + parserstatemachine * p_psm) override; + + void print(std::ostream & os) const override; +#endif + + private: + /** populate an expression here, may be followed by an operator **/ + obj lhs_; + + /** infix operator, if supplied **/ + optype op_type_ = optype::invalid; + + /** populate an expression here, that follows an infix operator. + * + * Note this may not resolve immediately. + * Consider input + * 5 + 6 + * Need to know if following token is * + * before deciding if 6 belongs to addition 5 + 6 + **/ + obj rhs_; + }; + } /*namespace scm*/ + +#ifndef ppdetail_atomic + namespace print { + PPDETAIL_ATOMIC(xo::scm::optype); + } +#endif +} /*namespace xo*/ + + +/* end DProgressSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/DSequenceSsm.hpp b/xo-reader2/include/xo/reader2/DSequenceSsm.hpp new file mode 100644 index 00000000..486187fc --- /dev/null +++ b/xo-reader2/include/xo/reader2/DSequenceSsm.hpp @@ -0,0 +1,111 @@ +/** @file DSequenceSsm.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "DSyntaxStateMachine.hpp" +#include +#include "syntaxstatetype.hpp" +#include +#include +#include + +namespace xo { + namespace scm { class Sequence; } + namespace scm { class Lambda; } + + namespace scm { + // TODO: need switching between 1a,1b states. + // Allow + // { } + // { 1 } + // { 1; } + // Reject + // { 1 2 } + // + + class DSequenceSsm : public DSyntaxStateMachine { + public: + using Super = DSyntaxStateMachine; + //using Sequence = xo::scm::Sequence; + //using Lambda = xo::scm::Lambda; + using AAllocator = xo::mm::AAllocator; + using DArena = xo::mm::DArena; + using ppindentinfo = xo::print::ppindentinfo; + + public: + static const char * ssm_classname() { return "DSequenceSsm"; } + + /** start parsing a sequence-expr. + * input begins with first expression in the sequence. + **/ + static void start(ParserStateMachine * p_psm); + + /** create instance using memory from @p parser_mm **/ + static obj make(DArena & parser_mm, + obj expr_mm); + + /** create instance using memory from @p parser_mm **/ + static DSequenceSsm * _make(DArena & parser_mm, + obj expr_mm); + +#ifdef NOT_YET + virtual void on_expr_with_semicolon(bp expr, + parserstatemachine * p_psm) override; +#endif + + /** update ssm for incoming rightbrace token '}' **/ + void on_rightbrace_token(const Token & tk, + ParserStateMachine * p_psm); + + /** @defgroup scm-sequencessm-syntaxstatemachine-facet ssm facet **/ + ///@{ + + /** indentifies this state machine **/ + syntaxstatetype ssm_type() const noexcept; + + /** mnemonic for syntax sequence ssm expects given current state **/ + std::string_view get_expect_str() const noexcept; + + /** operate state machine for this syntax on incoming token @p tk + * with overall parser state in @p p_psm + **/ + void on_token(const Token & tk, + ParserStateMachine * p_psm); + + /** consume expression @p expr produced by nested ssm; overall parser state in @p p_psm **/ + void on_parsed_expression(obj expr, + ParserStateMachine * p_psm); + + /** consume expression @p expr produced by nested ssm followed by token @p tk; + * overall parser state in @p p_psm + **/ + void on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-sequencessm-printable-facet printable facet **/ + ///@{ + + /** pretty printing support **/ + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + private: + explicit DSequenceSsm(DSequenceExpr * seq_expr); + + private: + /** scaffold sequence-expression here. + * This will eventually be the output of this ssm + **/ + DSequenceExpr * seq_expr_ = nullptr; + }; + } /*namespace scm*/ +} /*namespace xo*/ + + +/* end DSequenceSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/DSyntaxStateMachine.hpp b/xo-reader2/include/xo/reader2/DSyntaxStateMachine.hpp new file mode 100644 index 00000000..5851390b --- /dev/null +++ b/xo-reader2/include/xo/reader2/DSyntaxStateMachine.hpp @@ -0,0 +1,156 @@ +/** @file DSyntaxStateMachine.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include "ParserStateMachine.hpp" +#include + +namespace xo { + namespace scm { + + /** @class DSyntaxStateMachine + * @brief static helper interface for ASyntaxStateMachine implementations + * + * Using CRTP. + * + * Deliberately unusable through base class pointer. + * For runtime polymorphism use something like: + * @code + * Derived * d = ...; + * auto obj = with_facet::mkobj(d); + * // or + * obj(d) + * @endcode + **/ + template + class DSyntaxStateMachine { + public: + using TypeDescr = xo::reflect::TypeDescr; + + /** Default implementation for required SyntaxStateMachine facet method + **/ + void on_token(const Token & tk, + ParserStateMachine * p_psm) + { + // starting with c++23 can use "this auto&& self" instead + Derived & self = reinterpret_cast(*this); + + p_psm->illegal_input_on_token(Derived::ssm_classname(), + tk, + self.get_expect_str()); + } + + void on_parsed_symbol(std::string_view sym, + ParserStateMachine * p_psm) + { + // starting with c++23 can use "this auto&& self" instead + Derived & self = reinterpret_cast(*this); + + p_psm->illegal_input_on_symbol(Derived::ssm_classname(), + sym, + self.get_expect_str()); + } + + /** Default implementation for required SyntaxStateMachine facet method + **/ + void on_parsed_typedescr(TypeDescr td, + ParserStateMachine * p_psm) + { + // starting with c++23 can use "this auto&& self" instead + Derived & self = reinterpret_cast(*this); + + p_psm->illegal_input_on_typedescr(Derived::ssm_classname(), + td, + self.get_expect_str()); + } + + /** Default implementation for required SyntaxStateMachine facet method + **/ + void on_parsed_formal(const DUniqueString * param_name, + TypeDescr param_type, + ParserStateMachine * p_psm) + { + // starting with c++23 can use "this auto&& self" instead + Derived & self = reinterpret_cast(*this); + + p_psm->illegal_parsed_formal(Derived::ssm_classname(), + param_name, + param_type, + self.get_expect_str()); + } + + /** Default implementation for required SyntaxStateMachine facet method + **/ + void on_parsed_formal_with_token(const DUniqueString * param_name, + TypeDescr param_type, + const Token & tk, + ParserStateMachine * p_psm) + { + // starting with c++23 can use "this auto&& self" instead + Derived & self = reinterpret_cast(*this); + + p_psm->illegal_parsed_formal_with_token(Derived::ssm_classname(), + param_name, + param_type, + tk, + self.get_expect_str()); + } + + /** Default implementation for required SyntaxStateMachine facet method + * + * arglist is DArray of obj + **/ + void on_parsed_formal_arglist(DArray * arglist, + ParserStateMachine * p_psm) + { + // starting with c++23 can use "this auto&& self" instead + Derived & self = static_cast(*this); + + p_psm->illegal_parsed_formal_arglist(Derived::ssm_classname(), + arglist, + self.get_expect_str()); + } + + /** Default implementation for required SyntaxStateMachine facet method + **/ + void on_parsed_expression(obj expr, + ParserStateMachine * p_psm) + { + // starting with c++23 can use "this auto&& self" instead + Derived & self = static_cast(*this); + + p_psm->illegal_parsed_expression(Derived::ssm_classname(), + expr, + self.get_expect_str()); + + } + + /** Default implementation for required SyntaxStateMachine facet method + **/ + void on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm) + { + // starting with c++23 can use "this auto&& self" instead + Derived & self = static_cast(*this); + + // We don't need a separate entry point, + // since the semicolon isn't relevant to problem with syntax + // + + p_psm->illegal_parsed_expression_with_token(Derived::ssm_classname(), + expr, + tk, + self.get_expect_str()); + + } + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DSyntaxStateMachine.hpp */ diff --git a/xo-reader2/include/xo/reader2/DToplevelSeqSsm.hpp b/xo-reader2/include/xo/reader2/DToplevelSeqSsm.hpp new file mode 100644 index 00000000..743d2133 --- /dev/null +++ b/xo-reader2/include/xo/reader2/DToplevelSeqSsm.hpp @@ -0,0 +1,155 @@ +/** @file DToplevelSeqSsm.hpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "DSyntaxStateMachine.hpp" +#include "syntaxstatetype.hpp" +#include + +namespace xo { + namespace scm { + enum class exprseqtype { + /** toplevel interactive sequence. + * allows: rvalue expressions + **/ + toplevel_interactive, + /** toplevel non-interactive sequence. + * allows: + **/ + toplevel_batch, + /** counts number of valid enums **/ + N + }; + + const char * exprseqtype_descr(exprseqtype x); + + inline std::ostream & operator<<(std::ostream & os, exprseqtype x) { + os << exprseqtype_descr(x); + return os; + } + + /** @class DToplevelSeqSsm + * @brief state machine for parsing a sequence of expression + * + * Similar to exprseq_xs in xo-expresion + **/ + class DToplevelSeqSsm : public DSyntaxStateMachine { + public: + using Super = DSyntaxStateMachine; + using TypeDescr = xo::reflect::TypeDescr; + using AAllocator = xo::mm::AAllocator; + using DArena = xo::mm::DArena; + using ppindentinfo = xo::print::ppindentinfo; + + public: + explicit DToplevelSeqSsm(exprseqtype ty); + + /** start interactive top-level session **/ + static void establish_interactive(DArena & mm, + ParserStateMachine * p_psm); + /** start non-interactive top-level session **/ + static void establish_batch(DArena & mm, + ParserStateMachine * p_psm); + + public: + static const char * ssm_classname() { return "DToplevelSeqSsm"; } + + /** @defgroup scm-exprseq-ssm-facet syntaxstatemachine facet methods **/ + ///@{ + + /** identifies the ssm implemented here **/ + syntaxstatetype ssm_type() const noexcept; + + /** text describing expected/allowed input to this ssm in current state. + * Intended to drive error mesages + **/ + std::string_view get_expect_str() const noexcept; + + /** operate state machine for this syntax on incoming token @p tk + * with overall parser state in @p p_psm + **/ + void on_token(const Token & tk, + ParserStateMachine * p_psm); + + /** operate state machine for this syntax on incoming symbol token @p tk + * with overall parser state in @p p_psm + **/ + void on_symbol_token(const Token & tk, ParserStateMachine * p_psm); + + /** update state for this syntax on incoming token @p tk, + * overall parser state in @p p_psm + **/ + void on_def_token(const Token & tk, ParserStateMachine * p_psm); + + /** update state for this syntax on incoming lamdba token @p tk, + * overall parser state in @p p_psm + **/ + void on_lambda_token(const Token & tk, ParserStateMachine * p_psm); + + /** update state for this syntax on incoming token @p tk, + * overall parser state in @p p_psm + **/ + void on_if_token(const Token & tk, ParserStateMachine * p_psm); + + /** update state for this syntax on incoming string token @p tk, + * overall parser state in @p p_psm + **/ + void on_string_token(const Token & tk, ParserStateMachine * p_psm); + + /** update state for this syntax on incoming f64 token @p tk, + * overall parser state in @p p_psm + **/ + void on_f64_token(const Token & tk, ParserStateMachine * p_psm); + + /** update state for this syntax on incoming i64 token @p tk, + * overall parser state in @p p_psm + **/ + void on_i64_token(const Token & tk, ParserStateMachine * p_psm); + + /** update state for this syntax on incoming bool token @p tk, + * overall parser state in @p p_psm + **/ + void on_bool_token(const Token & tk, ParserStateMachine * p_psm); + + /** update state for this syntax on incoming leftparen token @p tk, + * overall parser state in @p p_psm + **/ + void on_leftparen_token(const Token & tk, ParserStateMachine * p_psm); + + /** update state for this syntax on parsed expression @p expr + * from nested ssm. + * overall parser state in @p p_psm + **/ + void on_parsed_expression(obj expr, ParserStateMachine * p_psm); + + /** update state for this syntax on parsed expression @p expr + * followed by token @p tk from nested ssm. + * overall parser state in @p p_psm + **/ + void on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-exprseq-printable-facet printable facet methods **/ + ///@{ + + /** pretty-printing driver; combine layout+printing **/ + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + private: + /** sequence type. accept rvalue expressions when + * this is toplevel_interactive. + * Always accept definitions and declarations. + **/ + exprseqtype seqtype_; + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DToplevelSeqSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/DefineSsm.hpp b/xo-reader2/include/xo/reader2/DefineSsm.hpp new file mode 100644 index 00000000..4a4489a0 --- /dev/null +++ b/xo-reader2/include/xo/reader2/DefineSsm.hpp @@ -0,0 +1,12 @@ +/** @file DefineSsm.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DDefineSsm.hpp" +#include "ssm/ISyntaxStateMachine_DDefineSsm.hpp" +#include "ssm/IPrintable_DDefineSsm.hpp" + +/* end DefineSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/ExpectExprSsm.hpp b/xo-reader2/include/xo/reader2/ExpectExprSsm.hpp new file mode 100644 index 00000000..d46ef489 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ExpectExprSsm.hpp @@ -0,0 +1,12 @@ +/** @file ExpectExprSsm.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DExpectExprSsm.hpp" +#include "ssm/ISyntaxStateMachine_DExpectExprSsm.hpp" +#include "ssm/IPrintable_DExpectExprSsm.hpp" + +/* end ExpectExprSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/ExpectFormalArgSsm.hpp b/xo-reader2/include/xo/reader2/ExpectFormalArgSsm.hpp new file mode 100644 index 00000000..f0aaa9ed --- /dev/null +++ b/xo-reader2/include/xo/reader2/ExpectFormalArgSsm.hpp @@ -0,0 +1,12 @@ +/** @file ExpectFormalArgSsm.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DExpectFormalArgSsm.hpp" +#include "ssm/ISyntaxStateMachine_DExpectFormalArgSsm.hpp" +#include "ssm/IPrintable_DExpectFormalArgSsm.hpp" + +/* end ExpectFormalArgSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/ExpectFormalArglistSsm.hpp b/xo-reader2/include/xo/reader2/ExpectFormalArglistSsm.hpp new file mode 100644 index 00000000..35ffcf04 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ExpectFormalArglistSsm.hpp @@ -0,0 +1,12 @@ +/** @file ExpectFormalArglistSsm.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DExpectFormalArglistSsm.hpp" +#include "ssm/ISyntaxStateMachine_DExpectFormalArglistSsm.hpp" +#include "ssm/IPrintable_DExpectFormalArglistSsm.hpp" + +/* end ExpectFormalArglistSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/ExpectSymbolSsm.hpp b/xo-reader2/include/xo/reader2/ExpectSymbolSsm.hpp new file mode 100644 index 00000000..66e44aef --- /dev/null +++ b/xo-reader2/include/xo/reader2/ExpectSymbolSsm.hpp @@ -0,0 +1,12 @@ +/** @file ExpectSymbolSsm.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DExpectSymbolSsm.hpp" +#include "ssm/ISyntaxStateMachine_DExpectSymbolSsm.hpp" +#include "ssm/IPrintable_DExpectSymbolSsm.hpp" + +/* end ExpectSymbolSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/ExpectTypeSsm.hpp b/xo-reader2/include/xo/reader2/ExpectTypeSsm.hpp new file mode 100644 index 00000000..2c189551 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ExpectTypeSsm.hpp @@ -0,0 +1,12 @@ +/** @file ExpectTypeSsm.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DExpectTypeSsm.hpp" +#include "ssm/ISyntaxStateMachine_DExpectTypeSsm.hpp" +#include "ssm/IPrintable_DExpectTypeSsm.hpp" + +/* end ExpectTypeSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/ExpressionParser.hpp b/xo-reader2/include/xo/reader2/ExpressionParser.hpp new file mode 100644 index 00000000..e59464b5 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ExpressionParser.hpp @@ -0,0 +1,80 @@ +/** @file ExpressionParser.hpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#include "ExprState.hpp" +#include +#include +#include + +namespace xo { + namespace scm { + /** @class ExpressionParser + * @brief Assemble Schematika expressions from token sequences + * + * Parser represents Each partially assembled expression by + * an ExprState object. + * Expreesions form a tree: + * each expression belongs to at most one parent. + * + **/ + class ExpressionParser { + public: + void push_exprstate(obj xstate); + + private: + /* TODO: + * ASymbolTable + * DLocalSymtab + * DGlobalSymtab + * + * Will also need + * DVariable + * DLambda + * + * For DGlobalSymtab perhaps use DArenaHashMap. + * May also want to use DArenaHashMap+DArena to intern strings + * + * Also: + * TypeUnifier + */ + + /** Arena for internal parsing stack. + * Must be owned exclusively because destructively + * modified as parser completes parsing of each sub-expression + * + * Contents will be a stack of ExprState instances + **/ + DArena parser_alloc_; + +#ifdef NOT_YET + /** Arena for internal environment stack. + * This represents just nesting for environments. + * Details for each frame survive parsing and are + * stored in @ref expr_alloc_. + * Maybe that means we don't need env_alloc_ + **/ + DArena env_alloc_; +#endif + + /** Allocator for parsed expressions. + * Information available during subsequent execution + * (whether compiling or interpreting) must be stored here. + * + * Also use this allocator for error messages arising + * during parsing + * + * Memory use patterns for executions are not predictable, + * and require garbage collection, e.g. DX1Collector. + * + * May alternatively be able to use DArena in a compile-only + * scenario, where top-level Expressions can be discarded + * once compiled. + **/ + obj expr_alloc_; + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ExpressionParser.hpp */ diff --git a/xo-reader2/include/xo/reader2/IfElseSsm.hpp b/xo-reader2/include/xo/reader2/IfElseSsm.hpp new file mode 100644 index 00000000..eaa6948d --- /dev/null +++ b/xo-reader2/include/xo/reader2/IfElseSsm.hpp @@ -0,0 +1,12 @@ +/** @file IfElseSsm.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DIfElseSsm.hpp" +#include "ssm/ISyntaxStateMachine_DIfElseSsm.hpp" +#include "ssm/IPrintable_DIfElseSsm.hpp" + +/* end IfElseSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/LambdaSsm.hpp b/xo-reader2/include/xo/reader2/LambdaSsm.hpp new file mode 100644 index 00000000..49ac731b --- /dev/null +++ b/xo-reader2/include/xo/reader2/LambdaSsm.hpp @@ -0,0 +1,10 @@ +/** @file LambdaSsm.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "DLambdaSsm.hpp" +#include "ssm/ISyntaxStateMachine_DLambdaSsm.hpp" +#include "ssm/IPrintable_DLambdaSsm.hpp" + +/* end LambdaSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/ParenSsm.hpp b/xo-reader2/include/xo/reader2/ParenSsm.hpp new file mode 100644 index 00000000..a9a786fd --- /dev/null +++ b/xo-reader2/include/xo/reader2/ParenSsm.hpp @@ -0,0 +1,12 @@ +/** @file ParenSsm.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DParenSsm.hpp" +#include "ssm/ISyntaxStateMachine_DParenSsm.hpp" +#include "ssm/IPrintable_DParenSsm.hpp" + +/* end ParenSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/ParserConfig.hpp b/xo-reader2/include/xo/reader2/ParserConfig.hpp new file mode 100644 index 00000000..080238c7 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ParserConfig.hpp @@ -0,0 +1,49 @@ +/** @file SchematikaParserConfig.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include +#include + +namespace xo { + namespace scm { + + /** @brief Configuration for SchematikaParser **/ + struct ParserConfig { + using ArenaHashMapConfig = xo::map::ArenaHashMapConfig; + using ArenaConfig = xo::mm::ArenaConfig; + + /** arena configuration for parser stack **/ + ArenaConfig parser_arena_config_ { .name_ = "parser-arena", + .size_ = 2*1024*1024, + .hugepage_z_ = 2*1024*1024, + .store_header_flag_ = true, + .header_{}, + .debug_flag_ = false }; + + /** configuration for hash map for global symbol table + * + * reminder: ownership chain + * SchematikaReader + * ->SchematikaParser + * ->ParserStateMachine + * ->DGlobalSymtab + **/ + ArenaHashMapConfig symtab_config_ { .name_ = "global-symtab", + .hint_max_capacity_ = 64*1024, + .debug_flag_ = false }; + + /** max capacity for unique string table **/ + size_t max_stringtable_capacity_ = 4096; + + /** control SchematikaParser debug logging **/ + bool debug_flag_ = false; + }; + + } +} + +/* end SchematikaParserConfig.hpp */ diff --git a/xo-reader2/include/xo/reader2/ParserResult.hpp b/xo-reader2/include/xo/reader2/ParserResult.hpp new file mode 100644 index 00000000..492b78b0 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ParserResult.hpp @@ -0,0 +1,114 @@ +/** @file ParserResult.hpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include +#include +#include +#include + +namespace xo { + namespace scm { + enum class parser_result_type { + /** no result yet (no input or incomplete expression) **/ + none, + /** emit expression **/ + expression, + /** emit parsing error **/ + error, + N + }; + + /** @return string representation for enum @p x **/ + const char * parser_result_type_descr(parser_result_type x); + + inline std::ostream & operator<<(std::ostream & os, parser_result_type x) { + os << parser_result_type_descr(x); + return os; + } + + class ParserResult { + public: + using ppindentinfo = xo::print::ppindentinfo; + + public: + ParserResult() = default; + ParserResult(parser_result_type type, + obj expr, + std::string_view error_src_fn, + const DString * error_description); + + /** create ParserResult for parsing success; + * parsing yields expression @p expr + **/ + static ParserResult expression(std::string_view ssm, + obj expr); + + /** create ParserResult for a parsing error. + * Reporting detailed message @p errmsg + * from syntax state machine @p ssm + **/ + static ParserResult error(std::string_view ssm, + const DString * errmsg); + + parser_result_type result_type() const { return result_type_; } + obj result_expr() const { return result_expr_; } + const DString * error_description() const { return error_description_; } + + bool is_incomplete() const { return result_type_ == parser_result_type::none; } + bool is_expression() const { return result_type_ == parser_result_type::expression; } + bool is_error() const { return result_type_ == parser_result_type::error; } + + /** ordinary not-pretty printer **/ + void print(std::ostream & os) const; + /** pretty-printing support **/ + bool pretty(const ppindentinfo & ppii) const; + + public: + /** none|expression|error_description + * + * @text + * result_type | error_src_function | error_description + * -------------+--------------------+------------------- + * none | nullptr | empty + * expression | nullptr | empty + * error | non-null | non-empty + * @endtext + **/ + parser_result_type result_type_ = parser_result_type::none; + /** non-null iff @ref result_type_ is expression **/ + obj result_expr_; + /** non-null iff @ref result_type_ is error. + * In which case gives parsing function detecting this error + **/ + std::string_view error_src_fn_; + /** non-null iff @ref result_type_ is error + * Human-targeted error description. + **/ + const DString * error_description_ = nullptr; + }; + + inline std::ostream & operator<<(std::ostream & os, const ParserResult & x) { + x.print(os); + return os; + } + + } /*namespace scm*/ + + namespace print { + /** pretty printer in relies on this specialization + * to handle ParserResult instances + **/ + template <> + struct ppdetail { + static inline bool print_pretty(const ppindentinfo & ppii, const xo::scm::ParserResult & x) { + return x.pretty(ppii); + } + }; + } +} /*namespace xo*/ + +/* end ParserResult.hpp */ diff --git a/xo-reader2/include/xo/reader2/ParserStack.hpp b/xo-reader2/include/xo/reader2/ParserStack.hpp new file mode 100644 index 00000000..ef5705e9 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ParserStack.hpp @@ -0,0 +1,91 @@ +/** @file ParserStack.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include +#include +#include + +namespace xo { + namespace scm { + + /** @brief A stack of expression state machines + * + * Each state machine is dedicated to a particular syntax instance. + * The innermost machine is in xsm; machines for surrounding expressions + * are in progressively removed frames reached via parent links. + **/ + class ParserStack { + public: + using DArena = xo::mm::DArena; + using ppindentinfo = xo::print::ppindentinfo; + + public: + ParserStack(DArena::Checkpoint ckp, + obj ssm, + ParserStack * parent); + + /** create new top of stack for syntax @p ssm, using memory from @p mm. + * previous stack given by @p parent. + * Checkpoint @p ckp will refer to stack _before_ allocating @p ssm + **/ + static ParserStack * push(ParserStack * stack, + DArena::Checkpoint ckp, + DArena & mm, + obj ssm); + + /** unwind effect of last call to @ref push **/ + static ParserStack * pop(ParserStack * stack, + DArena & mm); + + DArena::Checkpoint ckp() const noexcept { return ckp_; } + obj top() const noexcept { return ssm_; } + ParserStack * parent() const noexcept { return parent_; } + + /** regular printing **/ + void print(std::ostream & os) const; + /** pretty-printer support **/ + bool pretty(const ppindentinfo & ppii) const; + + private: + /** stack pointer: top of stack just before this instance created **/ + DArena::Checkpoint ckp_; + /** top of parsing stack: always non-null **/ + obj ssm_; + /** remainder of parsing stack excluding top **/ + ParserStack * parent_ = nullptr; + }; + + inline std::ostream & operator<< (std::ostream & os, const ParserStack * x) { + if (x) { + x->print(os); + } else { + os << "nullptr"; + } + return os; + } + + } /*namespace scm*/ + + namespace print { + /** pretty printer in relies on this specialization + * to handle ParserResult instances + **/ + template <> + struct ppdetail { + static inline bool print_pretty(const ppindentinfo & ppii, const xo::scm::ParserStack * p) { + if (p) + return p->pretty(ppii); + else + return ppii.pps()->print_upto("nullptr"); + } + }; + } + +} /*namespace xo*/ + +/* end ParserStack.hpp */ diff --git a/xo-reader2/include/xo/reader2/ParserStateMachine.hpp b/xo-reader2/include/xo/reader2/ParserStateMachine.hpp new file mode 100644 index 00000000..bec90ae8 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ParserStateMachine.hpp @@ -0,0 +1,364 @@ +/** @file ParserStateMachine.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "ParserResult.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace xo { + namespace scm { + // defined in ssm/ASyntaxStateMachine.hpp, but + // including here would create include cycle + // + class ASyntaxStateMachine; + + // note: it's load-bearing here to forward-declare ParserStack, + // see ParserStack.hpp for impl + // because ASyntaxStateMachine.hpp includes ParserStateMachine.hpp; + // before obj is defined. + class ParserStack; + + /** @brief State machine embodying Schematika parser + **/ + class ParserStateMachine { + public: + using TypeDescr = xo::reflect::TypeDescr; + using AAllocator = xo::mm::AAllocator; + using ArenaConfig = xo::mm::ArenaConfig; + using DArena = xo::mm::DArena; + using MemorySizeVisitor = xo::mm::MemorySizeVisitor; + using ArenaHashMapConfig = xo::map::ArenaHashMapConfig; + using size_type = std::size_t; + + public: + /** + * @p config arena configuration for parser state + * @p symtab_config configuration for global symtab + * (maps separate dedicated memory) + * @p max_stringtable_capacity + * hard max size for unique stringtable + * @p expr_alloc allocator for schematika expressions. + * Probably shared with execution. + * @p aux_alloc auxiliary allocator for non-copyable memory + * (e.g. DArenaHashMap for global symtable). + * If not using X1Collector, this can be the + * same as @p expr_alloc. + **/ + ParserStateMachine(const ArenaConfig & config, + const ArenaHashMapConfig & symtab_config, + size_type max_stringtable_capacity, + obj expr_alloc, + obj aux_alloc); + + /** non-trivial dtor for @ref global_symtab_ **/ + ~ParserStateMachine() = default; + + /** @defgroup scm-parserstatemachine-accessors accessor methods **/ + ///@{ + + bool debug_flag() const noexcept { return debug_flag_; } + ParserStack * stack() const noexcept { return stack_; } + obj expr_alloc() const noexcept { return expr_alloc_; } + DGlobalSymtab * global_symtab() const noexcept { return global_symtab_.data(); } + DLocalSymtab * local_symtab() const noexcept { return local_symtab_; } + const ParserResult & result() const noexcept { return result_; } + + /** true iff state machine is currently idle (at top-level) **/ + bool is_at_toplevel() const noexcept; + + /** true iff state machine currently has incomplete expression **/ + bool has_incomplete_expr() const noexcept; + + /** top of parser stack **/ + obj top_ssm() const; + + /** visit psm-owned memory pools; call visitor(info) for each **/ + void visit_pools(const MemorySizeVisitor & visitor) const; + + ///@} + + /** @defgroup scm-parserstatemachine-bookkeeping bookkeeping methods **/ + ///@{ + + /** allocator for parsing stack and ssm's **/ + DArena & parser_alloc() noexcept { return parser_alloc_; } + + /** establish toplevel @p ssm. Must have empty stack **/ + void establish_toplevel_ssm(obj ssm); + + /** push syntax @p ssm onto @ref stack_, restore parser stack to @p ckp + * when popped + **/ + void push_ssm(DArena::Checkpoint ckp, obj ssm); + + /** pop syntax state machine from top of @ref stack_ **/ + void pop_ssm(); + + /** get unique string copy of @p str. Idempotent for each @p str. + **/ + const DUniqueString * intern_string(std::string_view str); + + /** get unique (within stringtable) string, beginning with @p prefix **/ + const DUniqueString * gensym(std::string_view prefix); + + /** get variable reference for @p symbolname in current context, or else nullptr **/ + DVarRef * lookup_varref(std::string_view symbolname); + + /** push nested local symtab while parsing the body of a lambda expression; + * restore previous symtab at the end of lambda-expression definition. + * See @ref pop_local_symtab + **/ + void push_local_symtab(DLocalSymtab * symtab); + + /** pop nested symbol table from symbol-table stack **/ + void pop_local_symtab(); + + /** add variable to current local environment (innermost lexical scope) **/ + void upsert_var(DVariable * var); + + /** reset result to none **/ + void reset_result(); + + /** reset after reporting error **/ + void clear_error_reset(); + + ///@} + + /** @defgroup scm-parserstatemachine-inputmethods input methods **/ + ///@{ + + /** update state to respond to parsed symbol @p sym + * (from nested parsing state) + **/ + void on_parsed_symbol(std::string_view sym); + + /** update state to respond to parsed type-description @p td + * (from nested parsing state) + **/ + void on_parsed_typedescr(TypeDescr td); + + /** update state to consume param (name, type) emitted by + * nested (expired) parsing state + **/ + void on_parsed_formal(const DUniqueString * param_name, + TypeDescr param_type); + + /** update state to consume formal parameter (name, type) + * emitted by nested (now expired) parsing state, + * with trailing token @p tk + **/ + void on_parsed_formal_with_token(const DUniqueString * param_name, + TypeDescr param_type, + const Token & tk); + + /** update state to consume formal arugment list + * emitted by nested (expired) parsing state + **/ + void on_parsed_formal_arglist(DArray * arglist); + + /** update state to respond to parsed expression @p expr + * (from nested parsing state) + **/ + void on_parsed_expression(obj expr); + + /** update state to respond to parsed expression @p expr + * (from nested parsing state), with trailing token @p tk. + * + * Need to distinguish cases like: + * 6 // ) ? ; allowed } ? + * f(6 // ) allowed ; forbidden } forbidden + * 6 + // ) forbidden ; forbidden } forbidden + * + **/ + void on_parsed_expression_with_token(obj expr, + const Token & tk); + + /** update state to respond to input token @p tk. + * record output (if any) in @ref result_ + **/ + void on_token(const Token & tk); + + ///@} + /** @defgroup scm-parserstatemachine-error-entrypoints error entry points **/ + ///@{ + + /** capture result expression @p expr **/ + void capture_result(std::string_view ssm_anme, + obj expr); + + /** capture error message @p errmsg from @p ssm_name, + * as current state machine output. + * + * @p errmsg will have been allocated from the @p expr_alloc_ allocator + **/ + void capture_error(std::string_view ssm_name, + const DString * errmsg); + + /** report illegal input from syntax state machine @p ssm_name + * recognized on input token @p tk. @p expect_str describes + * expected input in current ssm state + **/ + void illegal_input_on_token(std::string_view ssm_name, + const Token & tk, + std::string_view expect_str); + + /** report illegal input from syntax state machine @p ssm_name + * receiving parsed symbol @p sym. @p expect_str describes + * expected input in current ssm state + **/ + void illegal_input_on_symbol(std::string_view ssm_name, + std::string_view sym, + std::string_view expect_str); + + /** report illegal input arriving in syntax state machine (ssm) @p ssm_name + * receiving assembled type-description @p td. + * @p expect_str sketches expected input in current ssm state + **/ + void illegal_input_on_typedescr(std::string_view ssm_name, + TypeDescr td, + std::string_view expect_str); + + /** report illegal parsed formal (param_name, param_type) from nested ssm. + * Introducing as placeholder; not expected to be reachable in + * full parser + **/ + void illegal_parsed_formal(std::string_view ssm_name, + const DUniqueString * param_name, + TypeDescr param_type, + std::string_view expect_str); + + /** report illegal parsed formal (param_name, param_type) from nested ssm; + * presented with immediately-following input token @p tk. + **/ + void illegal_parsed_formal_with_token(std::string_view ssm_name, + const DUniqueString * param_name, + TypeDescr param_type, + const Token & tk, + std::string_view expect_str); + + /** @p arglist stores obj pointers. + **/ + void illegal_parsed_formal_arglist(std::string_view ssm_name, + DArray * arglist, + std::string_view expect_str); + + /** report illegal parsed expression from nested ssm. + * Introducing as placeholder; not clear if this will be reachable + * in full parser + **/ + void illegal_parsed_expression(std::string_view ssm_name, + obj, + std::string_view expect_str); + + /** report illegal parsed expression @p expr from nested ssm @p ssm_name, + * presented with immediately-following input token @p tk + * Introducing as placeholder; not clear if this will be reachable + * in full parser + **/ + void illegal_parsed_expression_with_token(std::string_view ssm_name, + obj expr, + const Token & tk, + std::string_view expect_str); + + /** report error - no binding for variable @p sym + **/ + void error_unbound_variable(std::string_view ssm_name, + std::string_view sym); + + ///@} + + private: + + /** Table containing interned strings + symbols. + **/ + StringTable stringtable_; + + /** Arena for internal parsing stack. + * Must be owned exclusively because destructively + * modified as parser completes parsing of each sub-expression + * + * Contents will be a stack of ExprState instances + **/ + DArena parser_alloc_; + + /** Checkpoint of toplevel parser allocator. + * Retore parser_alloc to this checkpoint to proceed + * after encountering a parsing error. + **/ + DArena::Checkpoint parser_alloc_ckp_; + /** parser stack. Memory always from @ref parser_alloc_; + * elements that should survive parsing allocate from + * @ref expr_alloc_, see below. + **/ + ParserStack * stack_ = nullptr; + + /** Allocator for parsed expressions. + * Information available during subsequent execution + * (whether compiling or interpreting) must be stored here. + * + * Also use this allocator for error messages arising + * during parsing + * + * Memory use patterns for executions are not predictable, + * and benefit from garbage collection, e.g. DX1Collector. + * + * May alternatively be able to use DArena in a compile-only + * scenario, where top-level Expressions can be discarded + * once compiled. + **/ + obj expr_alloc_; + + /** Allocator for data with lifetime bounded by this ParserStateMachine + * + * Cannot be DX1Collector; for example DArenaHashMap will + * for global symtab will be allocated from here, + * and does not support gc. + * + * If @ref expr_alloc_ is an ordinary arena (e.g. DArenaAlloc) + * can have aux_alloc_ = expr_alloc_. + * When expr_alloc_ is a garbage collector (e.g. DX1Collector) + * this needs to be distinct. + **/ + obj aux_alloc_; + + /** global symbol table. + * Toplevel definitions go here. + * + * Uses mmap -> non-trivial destructor. + * + * TODO: may want to move ownership upstairs. + * if so, along with stringtable_. + * maybe new struct ParserState? + **/ + dp global_symtab_; + + /** symbol table with local bindings. + * non-null during parsing of lambda expressions. + * Always allocated from @p expr_alloc_. + * Push local symbol table here to remember local params + * during the body of a lambda expression. + **/ + DLocalSymtab * local_symtab_ = nullptr; + + /** current output from parser **/ + ParserResult result_; + + /** true to enable debug output **/ + bool debug_flag_ = false; + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ParserStateMachine.hpp */ diff --git a/xo-reader2/include/xo/reader2/ProgressSsm.hpp b/xo-reader2/include/xo/reader2/ProgressSsm.hpp new file mode 100644 index 00000000..150c60d9 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ProgressSsm.hpp @@ -0,0 +1,12 @@ +/** @file ProgressSsm.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DProgressSsm.hpp" +#include "ssm/ISyntaxStateMachine_DProgressSsm.hpp" +#include "ssm/IPrintable_DProgressSsm.hpp" + +/* end ProgressSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/Reader.hpp b/xo-reader2/include/xo/reader2/Reader.hpp new file mode 100644 index 00000000..9ae65d61 --- /dev/null +++ b/xo-reader2/include/xo/reader2/Reader.hpp @@ -0,0 +1,25 @@ +/** @file Reader.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include + +namespace xo { + namespace scm { + /** @class Reader + * @brief Assemble Schematika expressions from lexical tokens + **/ + class Reader { + public: + private: + /** tokenizer: assembles Schematika tokens from text **/ + Tokenizer tokenizer_; + + /** parser: assemble Schematika expressions from token sequences **/ + ExpressionParser parser_; + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end Reader.hpp */ diff --git a/xo-reader2/include/xo/reader2/ReaderConfig.hpp b/xo-reader2/include/xo/reader2/ReaderConfig.hpp new file mode 100644 index 00000000..e139e9eb --- /dev/null +++ b/xo-reader2/include/xo/reader2/ReaderConfig.hpp @@ -0,0 +1,65 @@ +/** @file ReaderConfig.hpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include +#include +#include + +namespace xo { + namespace scm { + + /** @brief Configuration for SchematikaReader + **/ + struct ReaderConfig { + using ArenaHashMapConfig = xo::map::ArenaHashMapConfig; + using CircularBufferConfig = xo::mm::CircularBufferConfig; + using ArenaConfig = xo::mm::ArenaConfig; + using size_t = std::size_t; + + /** tokenizer circular buffer config **/ + CircularBufferConfig tk_buffer_config_ {.name_ = "tk-buffer", + .max_capacity_ = 2*1024*1024, + .hugepage_z_ = 2*1024*1024, + .threshold_move_efficiency_ = 50.0, + .max_captured_span_ = 128 }; + /** debug flag for schematika tokenizer **/ + bool tk_debug_flag_ = false; + + /** arena configuration for parser stack **/ + ArenaConfig parser_arena_config_ { .name_ = "parser-arena", + .size_ = 2*1024*1024, + .hugepage_z_ = 2*1024*1024, + .store_header_flag_ = false, + .header_{}, + .debug_flag_ = false }; + + /** configuration for hash map for global symbol table + * + * reminder: ownership chain + * SchematikaReader + * ->SchematikaParser + * ->ParserStateMachine + * ->DGlobalSymtab + **/ + ArenaHashMapConfig symtab_config_ { .name_ = "global-symtab", + .hint_max_capacity_ = 64*1024, + .debug_flag_ = false }; + + /** debug flag for schematika parser **/ + bool parser_debug_flag_ = false; + + /** max size (in bytes) of stringtable **/ + size_t max_stringtable_cap_ = 64*1024; + + /** debug flag for schematika_reader **/ + bool reader_debug_flag_ = false; + }; + + } /*namespace scm*/ +} /*namepspace xo*/ + +/* end ReaderConfig.hpp */ diff --git a/xo-reader2/include/xo/reader2/SchematikaParser.hpp b/xo-reader2/include/xo/reader2/SchematikaParser.hpp new file mode 100644 index 00000000..96de8628 --- /dev/null +++ b/xo-reader2/include/xo/reader2/SchematikaParser.hpp @@ -0,0 +1,292 @@ +/** @file SchematikaParser.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "ParserConfig.hpp" +#include "ParserStateMachine.hpp" +#include "ParserResult.hpp" +#include +#include + +namespace xo { + namespace scm { + /** schematica parser + * + * Examples: + * + * decltype point + * + * // forward declarations + * decl pi : f64; + * decl fib(n : i32) -> i32; + * + * def pi = 3.14159265; // constant. = is single assignment + * + * def fib(n : i32) -> i32 { + * // nested defs ok + * def aux(n : i32, s1 : i32, s2 : i32) -> i32 { + * // or: + * // (n == 0) ? s1 : aux(n - 1, s1 + s2, s1) + * // + * if (n == 0) { + * s1; + * } else { + * aux(n - 1, s1 + s2, s1); + * } + * + * // or: + * // if (n == 0) ? s1 : aux(n - 1, s1 + s2, s1) + * } + * + * aux(n=n, s1=1, s2=0); + * } + * + * def x := "fu"; // non-constant + * x += "bar"; + * + * def anotherfib = lambda(n : i32) { fib(n) }; + * + * def any : object; + * def l : list = '(); + * + * deftype point :: {x : f64, y : f64}; + * deftype polar :: {arg : f64, mag : f64}; + * deftype converter :: (point -> polar); + * + * def polar2rect(pt : polar) -> point { + * point(x = pt.mag * cos(arg), + * y = pt.mag * sin(arg)); + * } + * + * Grammar: + * toplevel-program = $toplevel-expression(1); ..; $toplevel-expression(n) + * + * if interactive: + * toplevel-expression = expression + * else + * toplevel-expression = type-decl | define-expr + * + * type-decl = decltype $typename [<$tp1 .. $tpn>] + * expression = type-decl + * | define-expr + * | literal-expr + * | variable-expr + * | apply-expr + * | if-expr + * | lambda-expr + * | arithmetic-expr + * | block + * + * define-expr = type-decl + * | type-def + * | variable-def + * | function-decl + * | function-def + * + * type-def = deftype $typename [<$tp1 .. $tpn>] :: type-def-rhs + * type-def-rhs = object + * | bool + * | i128 | i64 | i32 | i16 | i8 + * | f128 | f64 | f32 | f16 + * | struct $typename { ($membername(i) : $typename(i))* } + * [end $typename] + * | tuple $typename { $typename(1), .., $typename(n) } + * [end $typename] + * | copytype $typename + * | subtype $typename { ($member(i) : $typename(i))* } + * + * variable-def = decl $varname [: $typename] [= expression] + * function-decl = decl $functionname($varname(1) : $typename(1), + * .., + * $varname(n) : $typename(n)) -> $typename[ret] + * function-def = def $functionname($varname(1) : $typename(1), + * .., + * $varname(n) : $typename(n)) [-> $typename[ret]] + * body-expr + * [ end $functionname ] + * literal-expr = boolean-literal + * | integer-literal + * | fp-literal + * | string-literal + * | symbol-literal + * | struct-literal + * + * + * boolean-literal = true | false + * + * variable-expr = $varname + * apply-expr = fn-expr(arg-expr(1), .., arg-expr(n)) + * fn-expr = expression + * arg-expr(i) = expression + * + * if-expr = if (test-expr) then-block else else-block + * | ((test-expr) ? then-expr : else-expr) + * test-expr = expression + * then-block = block + * else-block = block + * + * block = { (definition | expression)* } + * + * lambda-expr = lambda ($paramname(1) : $type(1), + * .., + * $paramname(n) : $type(n)) body-expr + * body-expr = expression + * + * arithmetic-expr = expression binop expression + * + * binop = + + * | - + * | * + * | / + * | | + * | & + * | ^ + * | == + * | != + * | < + * | <= + * | => + * | > + * + **/ + class SchematikaParser { + public: + using token_type = Token; + using ArenaHashMapConfig = xo::map::ArenaHashMapConfig; + using ArenaConfig = xo::mm::ArenaConfig; + using AAllocator = xo::mm::AAllocator; + using MemorySizeVisitor = xo::mm::MemorySizeVisitor; + using ppindentinfo = xo::print::ppindentinfo; + using size_type = std::size_t; + + public: + /** create parser in initial state; + * parser is ready to receive tokens via @ref include_token + * + * @p config parser configuration + * @p expr_alloc allocator for schematika expressions. + * Probably shared with execution. + * @p aux_alloc aux allocator for non-copyable memory + * with lifetime bounded by this + * SchematikeParser itself + **/ + SchematikaParser(const ParserConfig & config, + obj expr_alloc, + obj aux_alloc); + + /** non-trivial dtor because of @ref psm_ **/ + ~SchematikaParser() = default; + + /** scm-schematikaparser-access-methods **/ + ///@{ + + DGlobalSymtab * global_symtab() const noexcept; + + bool debug_flag() const { return debug_flag_; } + + /** true if parser is at top-level, + * i.e. ready for next top-level expression + **/ + bool is_at_toplevel() const; + + /** true iff parser contains state for an incomplete expression. + * For this to be true, parser must have consumed at least one token + * since end of last toplevel expression + **/ + bool has_incomplete_expr() const; + + /** top of parser stack **/ + obj top_ssm() const; + + /** current parser result. Value of last return from @ref on_token **/ + const ParserResult & result() const; + + /** visit parser-owned memory pools; invoke visitor(info) for each **/ + void visit_pools(const MemorySizeVisitor & visitor) const; + + ///@} + /** scm-schematikaparser-general-methods **/ + ///@{ + + /** put parser into state for beginning an interactive session. + **/ + void begin_interactive_session(); + + /** put parser into state for beginning of a translation unit + * (i.e. input stream) + **/ + void begin_batch_session(); + + /** include next token @p tk and increment parser state. + * + * @param tk next input token + * @return parsed expression, if @p tk completes an expression. + * otherwise nullptr + **/ + const ParserResult & on_token(const token_type & tk); + + /** reset parsed result expression; use using return value from + * @ref include_token. Complicating api here to avoid copying ParserResult + * on each token + **/ + void reset_result(); + + /** reset to starting parsing state. + * use this after encountering an error, to avoid cascade of + * spurious secondary errors. particularly important when + * invoked as part of a REPL. + **/ + void reset_to_idle_toplevel(); + + ///@} + /** scm-schematikaparser-pretty-methods **/ + ///@{ + + /** print human-readable representation on stream @p os **/ + void print(std::ostream & os) const; + /** pretty-printer support **/ + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + private: + /** state machine **/ + ParserStateMachine psm_; + + /** debug flag (also stored in psm_) **/ + bool debug_flag_ = false; + }; /*SchematikaParser*/ + + inline std::ostream & + operator<< (std::ostream & os, + const SchematikaParser * x) { + if (x) { + x->print(os); + } else { + os << "nullptr"; + } + return os; + } + + } /*namespace scm*/ + + namespace print { + /** pretty printer in relies on this specialization + * to handle ParserResult instances + **/ + template <> + struct ppdetail { + static inline bool print_pretty(const ppindentinfo & ppii, const xo::scm::SchematikaParser* p) { + if (p) + return p->pretty(ppii); + else + return ppii.pps()->print_upto("nullptr"); + } + }; + } +} /*namespace xo*/ + +/* end SchematikaParser.hpp */ diff --git a/xo-reader2/include/xo/reader2/SchematikaReader.hpp b/xo-reader2/include/xo/reader2/SchematikaReader.hpp new file mode 100644 index 00000000..efd031ca --- /dev/null +++ b/xo-reader2/include/xo/reader2/SchematikaReader.hpp @@ -0,0 +1,114 @@ +/** @file SchematikaReader.hpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "ReaderConfig.hpp" +#include "SchematikaParser.hpp" +#include + +namespace xo { + namespace scm { + struct ReaderResult { + using span_type = xo::mm::span; + + bool is_tk_error() const { return tk_error_.is_error(); } + + /** schematika expression parsed from input **/ + obj expr_; + /** unconsumed portion of input span + * only relevant when result type is expression. + * (otherwise input consumed) + **/ + span_type remaining_input_; + + /** {src_function, error_description, input_state, error_pos} **/ + TokenizerError tk_error_; + }; + + /** @class SchematikaReader + * @brief Pipeline comprising Schematika tokenizer and parser + * + * Consumes text; produces expressions + **/ + class SchematikaReader { + public: + using AAllocator = xo::mm::AAllocator; + using MemorySizeVisitor = xo::mm::MemorySizeVisitor; + using span_type = xo::mm::span; + using size_type = std::size_t; + + public: + /** + * @p expr_alloc. allocator for Schematika expressions + * @p aux_alloc. allocator for miscellaneous objects + * (e.g. DArenaHashMap for global symtab) + * that have lifetime bounded by Schematika reader itself. + **/ + SchematikaReader(const ReaderConfig & config, + obj expr_alloc, + obj aux_alloc); + + /** non-trivial dtor because of @p parser **/ + ~SchematikaReader() = default; + + /** top-level symbol table **/ + DGlobalSymtab * global_symtab() const noexcept; + + /** visit reader-owned memory pools; call visitor(info) for each. + * Specifically exclude expr_alloc, since we don't consider + * that reader-owned + **/ + void visit_pools(const MemorySizeVisitor & visitor) const; + + /** true iff parser is at top-level. + * false iff parser is working on incomplete expression + **/ + bool is_at_toplevel() const noexcept; + + /** prepare interactive session + * (allows rvalue expressions at toplevel) + **/ + void begin_interactive_session(); + + /** prepare batch session + * (limits expression types at toplevel) + **/ + void begin_batch_session(); + + /** consume input @p input_cstr **/ + const ReaderResult & read_expr(span_type input_span, bool eof); + + /** reset @ref result_ to nominal value **/ + void reset_result(); + + /** reset to known starting point after encountering an error. + * - remainder of stashed current line. + * Necesary for well-formatted error reporting. + * - current parsing state + **/ + void reset_to_idle_toplevel(); + + private: + /** tokenizer converts a stream of chars + * to a stream of lexical tokens + **/ + Tokenizer tokenizer_; + + /** parser converts a stream of tokens + * to a stream of expressions + **/ + SchematikaParser parser_; + + /** current output from reader **/ + ReaderResult result_; + + /** true to enable reader debug logging **/ + bool debug_flag_ = false; + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end SchematikaReader.hpp */ diff --git a/xo-reader2/include/xo/reader2/SequenceSsm.hpp b/xo-reader2/include/xo/reader2/SequenceSsm.hpp new file mode 100644 index 00000000..0e82e081 --- /dev/null +++ b/xo-reader2/include/xo/reader2/SequenceSsm.hpp @@ -0,0 +1,13 @@ +/** @file SequenceSsm.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DSequenceSsm.hpp" +#include "ssm/ISyntaxStateMachine_DSequenceSsm.hpp" +#include "ssm/IPrintable_DSequenceSsm.hpp" + +/* end SequenceSsm.hpp */ + diff --git a/xo-reader2/include/xo/reader2/SyntaxStateMachine.hpp b/xo-reader2/include/xo/reader2/SyntaxStateMachine.hpp new file mode 100644 index 00000000..c9c37ee1 --- /dev/null +++ b/xo-reader2/include/xo/reader2/SyntaxStateMachine.hpp @@ -0,0 +1,22 @@ +/** @file SyntaxStateMachine.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/SyntaxStateMachine.json5] + * 2. jinja2 template for facet .hpp file: + * [facet.hpp.j2] + * 3. idl for facet methods + * [idl/SyntaxStateMachine.json5] + **/ + +#pragma once + +#include "ssm/ASyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_Any.hpp" +#include "ssm/ISyntaxStateMachine_Xfer.hpp" +#include "ssm/RSyntaxStateMachine.hpp" + + +/* end SyntaxStateMachine.hpp */ diff --git a/xo-reader2/include/xo/reader2/ToplevelSeqSsm.hpp b/xo-reader2/include/xo/reader2/ToplevelSeqSsm.hpp new file mode 100644 index 00000000..35cd8362 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ToplevelSeqSsm.hpp @@ -0,0 +1,12 @@ +/** @file ToplevelSeqSsm.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DToplevelSeqSsm.hpp" +#include "ssm/ISyntaxStateMachine_DToplevelSeqSsm.hpp" +#include "ssm/IPrintable_DToplevelSeqSsm.hpp" + +/* end ToplevelSeqSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/init_reader2.hpp b/xo-reader2/include/xo/reader2/init_reader2.hpp new file mode 100644 index 00000000..e0bf18b4 --- /dev/null +++ b/xo-reader2/include/xo/reader2/init_reader2.hpp @@ -0,0 +1,21 @@ +/** @file init_reader2.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include + +namespace xo { + /* tag to represent the xo-reader2/ subsystem within ordered initialization */ + enum S_reader2_tag {}; + + template <> + struct InitSubsys { + static void init(); + static InitEvidence require(); + }; +} /*namespace xo*/ + +/* end init_reader2.hpp */ diff --git a/xo-reader2/include/xo/reader2/reader2_register_facets.hpp b/xo-reader2/include/xo/reader2/reader2_register_facets.hpp new file mode 100644 index 00000000..6e606e40 --- /dev/null +++ b/xo-reader2/include/xo/reader2/reader2_register_facets.hpp @@ -0,0 +1,15 @@ +/** @file reader2_register_facets.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +namespace xo { + namespace scm { + /** Register reader2 (facet,impl) combinations with FacetRegistry **/ + bool reader2_register_facets(); + } +} + +/* end reader2_register_facets.hpp */ diff --git a/xo-reader2/include/xo/reader2/reader2_register_types.hpp b/xo-reader2/include/xo/reader2/reader2_register_types.hpp new file mode 100644 index 00000000..a7e6c0e1 --- /dev/null +++ b/xo-reader2/include/xo/reader2/reader2_register_types.hpp @@ -0,0 +1,17 @@ +/** @file reader2_register_types.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include + +namespace xo { + namespace scm { + /** Register reader2 gc-aware types with collector **/ + bool reader2_register_types(obj gc); + } +} + +/* end reader2_register_types.hpp */ diff --git a/xo-reader2/include/xo/reader2/ssm/ASyntaxStateMachine.hpp b/xo-reader2/include/xo/reader2/ssm/ASyntaxStateMachine.hpp new file mode 100644 index 00000000..6b2976e1 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ASyntaxStateMachine.hpp @@ -0,0 +1,97 @@ +/** @file ASyntaxStateMachine.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/SyntaxStateMachine.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [abstract_facet.hpp.j2] + * 3. idl for facet methods + * [idl/SyntaxStateMachine.json5] + **/ + +#pragma once + +// includes (via {facet_includes}) +#include "ParserStateMachine.hpp" +#include "syntaxstatetype.hpp" +#include +#include +#include +#include +#include + +// {pretex} here + +namespace xo { +namespace scm { + +using Copaque = const void *; +using Opaque = void *; + +/** +Assistant to schematika parser dedicated to particular syntax +**/ +class ASyntaxStateMachine { +public: + /** @defgroup scm-syntaxstatemachine-type-traits **/ + ///@{ + // types + /** integer identifying a type **/ + using typeseq = xo::facet::typeseq; + using Copaque = const void *; + using Opaque = void *; + /** reflected c++ type **/ + using TypeDescr = xo::reflect::TypeDescr; + ///@} + + /** @defgroup scm-syntaxstatemachine-methods **/ + ///@{ + // const methods + /** RTTI: unique id# for actual runtime data representation **/ + virtual typeseq _typeseq() const noexcept = 0; + /** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/ + virtual void _drop(Opaque d) const noexcept = 0; + /** identify a type of syntax state machine **/ + virtual syntaxstatetype ssm_type(Copaque data) const noexcept = 0; + /** text describing expected/allowed input to this ssm in current state **/ + virtual std::string_view get_expect_str(Copaque data) const noexcept = 0; + + // nonconst methods + /** operate state machine for incoming token @p tk **/ + virtual void on_token(Opaque data, const Token & tk, ParserStateMachine * p_psm) = 0; + /** update stat machine for incoming parsed symbol @p sym **/ + virtual void on_parsed_symbol(Opaque data, std::string_view sym, ParserStateMachine * p_psm) = 0; + /** operate state machine for incoming type description @p td **/ + virtual void on_parsed_typedescr(Opaque data, TypeDescr td, ParserStateMachine * p_psm) = 0; + /** operate state machine for formal emitted by nested ssm **/ + virtual void on_parsed_formal(Opaque data, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) = 0; + /** operate state machine for formal emitted by nested ssm **/ + virtual void on_parsed_formal_with_token(Opaque data, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) = 0; + /** consume formal arglist emitted by nested ssm **/ + virtual void on_parsed_formal_arglist(Opaque data, DArray * arglist, ParserStateMachine * p_psm) = 0; + /** update state machine for incoming parsed expression @p expr **/ + virtual void on_parsed_expression(Opaque data, obj expr, ParserStateMachine * p_psm) = 0; + /** update state machine @p p_psm for incoming parsed expression @p expr followed by token @p tk **/ + virtual void on_parsed_expression_with_token(Opaque data, obj expr, const Token & tk, ParserStateMachine * p_psm) = 0; + ///@} +}; /*ASyntaxStateMachine*/ + +/** Implementation ISyntaxStateMachine_DRepr of ASyntaxStateMachine for state DRepr + * should provide a specialization: + * + * template <> + * struct xo::facet::FacetImplementation { + * using Impltype = ISyntaxStateMachine_DRepr; + * }; + * + * then ISyntaxStateMachine_ImplType --> ISyntaxStateMachine_DRepr + **/ +template +using ISyntaxStateMachine_ImplType = xo::facet::FacetImplType; + +} /*namespace scm*/ +} /*namespace xo*/ + +/* ASyntaxStateMachine.hpp */ diff --git a/xo-reader2/include/xo/reader2/ssm/IPrintable_DApplySsm.hpp b/xo-reader2/include/xo/reader2/ssm/IPrintable_DApplySsm.hpp new file mode 100644 index 00000000..3bae71f2 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/IPrintable_DApplySsm.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DApplySsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DApplySsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DApplySsm.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DApplySsm.hpp" + +namespace xo { namespace scm { class IPrintable_DApplySsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DApplySsm + **/ + class IPrintable_DApplySsm { + public: + /** @defgroup scm-printable-dapplyssm-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dapplyssm-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DApplySsm & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/IPrintable_DDefineSsm.hpp b/xo-reader2/include/xo/reader2/ssm/IPrintable_DDefineSsm.hpp new file mode 100644 index 00000000..d50b0394 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/IPrintable_DDefineSsm.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DDefineSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DDefineSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DDefineSsm.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DDefineSsm.hpp" + +namespace xo { namespace scm { class IPrintable_DDefineSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DDefineSsm + **/ + class IPrintable_DDefineSsm { + public: + /** @defgroup scm-printable-ddefinessm-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-ddefinessm-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DDefineSsm & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectExprSsm.hpp b/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectExprSsm.hpp new file mode 100644 index 00000000..c61011ed --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectExprSsm.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DExpectExprSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DExpectExprSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DExpectExprSsm.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DExpectExprSsm.hpp" + +namespace xo { namespace scm { class IPrintable_DExpectExprSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DExpectExprSsm + **/ + class IPrintable_DExpectExprSsm { + public: + /** @defgroup scm-printable-dexpectexprssm-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dexpectexprssm-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DExpectExprSsm & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectFormalArgSsm.hpp b/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectFormalArgSsm.hpp new file mode 100644 index 00000000..6467a0d4 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectFormalArgSsm.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DExpectFormalArgSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DExpectFormalArgSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DExpectFormalArgSsm.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DExpectFormalArgSsm.hpp" + +namespace xo { namespace scm { class IPrintable_DExpectFormalArgSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DExpectFormalArgSsm + **/ + class IPrintable_DExpectFormalArgSsm { + public: + /** @defgroup scm-printable-dexpectformalargssm-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dexpectformalargssm-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DExpectFormalArgSsm & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectFormalArglistSsm.hpp b/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectFormalArglistSsm.hpp new file mode 100644 index 00000000..0e7802ca --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectFormalArglistSsm.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DExpectFormalArglistSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DExpectFormalArglistSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DExpectFormalArglistSsm.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DExpectFormalArglistSsm.hpp" + +namespace xo { namespace scm { class IPrintable_DExpectFormalArglistSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DExpectFormalArglistSsm + **/ + class IPrintable_DExpectFormalArglistSsm { + public: + /** @defgroup scm-printable-dexpectformalarglistssm-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dexpectformalarglistssm-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DExpectFormalArglistSsm & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectSymbolSsm.hpp b/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectSymbolSsm.hpp new file mode 100644 index 00000000..45d90eeb --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectSymbolSsm.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DExpectSymbolSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DExpectSymbolSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DExpectSymbolSsm.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DExpectSymbolSsm.hpp" + +namespace xo { namespace scm { class IPrintable_DExpectSymbolSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DExpectSymbolSsm + **/ + class IPrintable_DExpectSymbolSsm { + public: + /** @defgroup scm-printable-dexpectsymbolssm-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dexpectsymbolssm-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DExpectSymbolSsm & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectTypeSsm.hpp b/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectTypeSsm.hpp new file mode 100644 index 00000000..d0fa9c34 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectTypeSsm.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DExpectTypeSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DExpectTypeSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DExpectTypeSsm.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DExpectTypeSsm.hpp" + +namespace xo { namespace scm { class IPrintable_DExpectTypeSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DExpectTypeSsm + **/ + class IPrintable_DExpectTypeSsm { + public: + /** @defgroup scm-printable-dexpecttypessm-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dexpecttypessm-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DExpectTypeSsm & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/IPrintable_DIfElseSsm.hpp b/xo-reader2/include/xo/reader2/ssm/IPrintable_DIfElseSsm.hpp new file mode 100644 index 00000000..39f009ef --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/IPrintable_DIfElseSsm.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DIfElseSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DIfElseSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DIfElseSsm.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DIfElseSsm.hpp" + +namespace xo { namespace scm { class IPrintable_DIfElseSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DIfElseSsm + **/ + class IPrintable_DIfElseSsm { + public: + /** @defgroup scm-printable-difelsessm-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-difelsessm-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DIfElseSsm & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/IPrintable_DLambdaSsm.hpp b/xo-reader2/include/xo/reader2/ssm/IPrintable_DLambdaSsm.hpp new file mode 100644 index 00000000..9385be7c --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/IPrintable_DLambdaSsm.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DLambdaSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DLambdaSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DLambdaSsm.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DLambdaSsm.hpp" + +namespace xo { namespace scm { class IPrintable_DLambdaSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DLambdaSsm + **/ + class IPrintable_DLambdaSsm { + public: + /** @defgroup scm-printable-dlambdassm-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dlambdassm-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DLambdaSsm & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/IPrintable_DParenSsm.hpp b/xo-reader2/include/xo/reader2/ssm/IPrintable_DParenSsm.hpp new file mode 100644 index 00000000..2b4b49c2 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/IPrintable_DParenSsm.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DParenSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DParenSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DParenSsm.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DParenSsm.hpp" + +namespace xo { namespace scm { class IPrintable_DParenSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DParenSsm + **/ + class IPrintable_DParenSsm { + public: + /** @defgroup scm-printable-dparenssm-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dparenssm-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DParenSsm & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/IPrintable_DProgressSsm.hpp b/xo-reader2/include/xo/reader2/ssm/IPrintable_DProgressSsm.hpp new file mode 100644 index 00000000..85779cb6 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/IPrintable_DProgressSsm.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DProgressSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DProgressSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DProgressSsm.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DProgressSsm.hpp" + +namespace xo { namespace scm { class IPrintable_DProgressSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DProgressSsm + **/ + class IPrintable_DProgressSsm { + public: + /** @defgroup scm-printable-dprogressssm-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dprogressssm-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DProgressSsm & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/IPrintable_DSequenceSsm.hpp b/xo-reader2/include/xo/reader2/ssm/IPrintable_DSequenceSsm.hpp new file mode 100644 index 00000000..e5555c7f --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/IPrintable_DSequenceSsm.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DSequenceSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DSequenceSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DSequenceSsm.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DSequenceSsm.hpp" + +namespace xo { namespace scm { class IPrintable_DSequenceSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DSequenceSsm + **/ + class IPrintable_DSequenceSsm { + public: + /** @defgroup scm-printable-dsequencessm-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dsequencessm-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DSequenceSsm & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/IPrintable_DToplevelSeqSsm.hpp b/xo-reader2/include/xo/reader2/ssm/IPrintable_DToplevelSeqSsm.hpp new file mode 100644 index 00000000..b219b589 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/IPrintable_DToplevelSeqSsm.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DToplevelSeqSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DToplevelSeqSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DToplevelSeqSsm.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DToplevelSeqSsm.hpp" + +namespace xo { namespace scm { class IPrintable_DToplevelSeqSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DToplevelSeqSsm + **/ + class IPrintable_DToplevelSeqSsm { + public: + /** @defgroup scm-printable-dtoplevelseqssm-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dtoplevelseqssm-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DToplevelSeqSsm & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_Any.hpp b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_Any.hpp new file mode 100644 index 00000000..8eb513c9 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_Any.hpp @@ -0,0 +1,98 @@ +/** @file ISyntaxStateMachine_Any.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/SyntaxStateMachine.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/SyntaxStateMachine.json5] + **/ + +#pragma once + +#include "ASyntaxStateMachine.hpp" +#include + +namespace xo { namespace scm { class ISyntaxStateMachine_Any; } } + +namespace xo { +namespace facet { + +template <> +struct FacetImplementation +{ + using ImplType = xo::scm::ISyntaxStateMachine_Any; +}; + +} +} + +namespace xo { +namespace scm { + + /** @class ISyntaxStateMachine_Any + * @brief ASyntaxStateMachine implementation for empty variant instance + **/ + class ISyntaxStateMachine_Any : public ASyntaxStateMachine { + public: + /** @defgroup scm-syntaxstatemachine-any-type-traits **/ + ///@{ + + /** integer identifying a type **/ + using typeseq = xo::facet::typeseq; + using TypeDescr = ASyntaxStateMachine::TypeDescr; + + ///@} + /** @defgroup scm-syntaxstatemachine-any-methods **/ + ///@{ + + const ASyntaxStateMachine * iface() const { return std::launder(this); } + + // from ASyntaxStateMachine + + // builtin methods + typeseq _typeseq() const noexcept override { return s_typeseq; } + [[noreturn]] void _drop(Opaque) const noexcept override { _fatal(); } + + // const methods + [[noreturn]] syntaxstatetype ssm_type(Copaque) const noexcept override { _fatal(); } + [[noreturn]] std::string_view get_expect_str(Copaque) const noexcept override { _fatal(); } + + // nonconst methods + [[noreturn]] void on_token(Opaque, const Token &, ParserStateMachine *) override; + [[noreturn]] void on_parsed_symbol(Opaque, std::string_view, ParserStateMachine *) override; + [[noreturn]] void on_parsed_typedescr(Opaque, TypeDescr, ParserStateMachine *) override; + [[noreturn]] void on_parsed_formal(Opaque, const DUniqueString *, TypeDescr, ParserStateMachine *) override; + [[noreturn]] void on_parsed_formal_with_token(Opaque, const DUniqueString *, TypeDescr, const Token &, ParserStateMachine *) override; + [[noreturn]] void on_parsed_formal_arglist(Opaque, DArray *, ParserStateMachine *) override; + [[noreturn]] void on_parsed_expression(Opaque, obj, ParserStateMachine *) override; + [[noreturn]] void on_parsed_expression_with_token(Opaque, obj, const Token &, ParserStateMachine *) override; + + ///@} + + private: + /** @defgraoup scm-syntaxstatemachine-any-private-methods **/ + ///@{ + + [[noreturn]] static void _fatal(); + + ///@} + + public: + /** @defgroup scm-syntaxstatemachine-any-member-vars **/ + ///@{ + + static typeseq s_typeseq; + static bool _valid; + + ///@} + }; + +} /*namespace scm */ +} /*namespace xo */ + +/* ISyntaxStateMachine_Any.hpp */ diff --git a/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DApplySsm.hpp b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DApplySsm.hpp new file mode 100644 index 00000000..eb9b10fa --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DApplySsm.hpp @@ -0,0 +1,79 @@ +/** @file ISyntaxStateMachine_DApplySsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DApplySsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DApplySsm.json5] + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include "SyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_Xfer.hpp" +#include "DApplySsm.hpp" + +namespace xo { namespace scm { class ISyntaxStateMachine_DApplySsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISyntaxStateMachine_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISyntaxStateMachine_DApplySsm + **/ + class ISyntaxStateMachine_DApplySsm { + public: + /** @defgroup scm-syntaxstatemachine-dapplyssm-type-traits **/ + ///@{ + using TypeDescr = xo::scm::ASyntaxStateMachine::TypeDescr; + using Copaque = xo::scm::ASyntaxStateMachine::Copaque; + using Opaque = xo::scm::ASyntaxStateMachine::Opaque; + ///@} + /** @defgroup scm-syntaxstatemachine-dapplyssm-methods **/ + ///@{ + // const methods + /** identify a type of syntax state machine **/ + static syntaxstatetype ssm_type(const DApplySsm & self) noexcept; + /** text describing expected/allowed input to this ssm in current state **/ + static std::string_view get_expect_str(const DApplySsm & self) noexcept; + + // non-const methods + /** operate state machine for incoming token @p tk **/ + static void on_token(DApplySsm & self, const Token & tk, ParserStateMachine * p_psm); + /** update stat machine for incoming parsed symbol @p sym **/ + static void on_parsed_symbol(DApplySsm & self, std::string_view sym, ParserStateMachine * p_psm); + /** operate state machine for incoming type description @p td **/ + static void on_parsed_typedescr(DApplySsm & self, TypeDescr td, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal(DApplySsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal_with_token(DApplySsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm); + /** consume formal arglist emitted by nested ssm **/ + static void on_parsed_formal_arglist(DApplySsm & self, DArray * arglist, ParserStateMachine * p_psm); + /** update state machine for incoming parsed expression @p expr **/ + static void on_parsed_expression(DApplySsm & self, obj expr, ParserStateMachine * p_psm); + /** update state machine @p p_psm for incoming parsed expression @p expr followed by token @p tk **/ + static void on_parsed_expression_with_token(DApplySsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DDefineSsm.hpp b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DDefineSsm.hpp new file mode 100644 index 00000000..8fee27fd --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DDefineSsm.hpp @@ -0,0 +1,79 @@ +/** @file ISyntaxStateMachine_DDefineSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DDefineSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DDefineSsm.json5] + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include "SyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_Xfer.hpp" +#include "DDefineSsm.hpp" + +namespace xo { namespace scm { class ISyntaxStateMachine_DDefineSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISyntaxStateMachine_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISyntaxStateMachine_DDefineSsm + **/ + class ISyntaxStateMachine_DDefineSsm { + public: + /** @defgroup scm-syntaxstatemachine-ddefinessm-type-traits **/ + ///@{ + using TypeDescr = xo::scm::ASyntaxStateMachine::TypeDescr; + using Copaque = xo::scm::ASyntaxStateMachine::Copaque; + using Opaque = xo::scm::ASyntaxStateMachine::Opaque; + ///@} + /** @defgroup scm-syntaxstatemachine-ddefinessm-methods **/ + ///@{ + // const methods + /** identify a type of syntax state machine **/ + static syntaxstatetype ssm_type(const DDefineSsm & self) noexcept; + /** text describing expected/allowed input to this ssm in current state **/ + static std::string_view get_expect_str(const DDefineSsm & self) noexcept; + + // non-const methods + /** operate state machine for incoming token @p tk **/ + static void on_token(DDefineSsm & self, const Token & tk, ParserStateMachine * p_psm); + /** update stat machine for incoming parsed symbol @p sym **/ + static void on_parsed_symbol(DDefineSsm & self, std::string_view sym, ParserStateMachine * p_psm); + /** operate state machine for incoming type description @p td **/ + static void on_parsed_typedescr(DDefineSsm & self, TypeDescr td, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal(DDefineSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal_with_token(DDefineSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm); + /** consume formal arglist emitted by nested ssm **/ + static void on_parsed_formal_arglist(DDefineSsm & self, DArray * arglist, ParserStateMachine * p_psm); + /** update state machine for incoming parsed expression @p expr **/ + static void on_parsed_expression(DDefineSsm & self, obj expr, ParserStateMachine * p_psm); + /** update state machine @p p_psm for incoming parsed expression @p expr followed by token @p tk **/ + static void on_parsed_expression_with_token(DDefineSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectExprSsm.hpp b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectExprSsm.hpp new file mode 100644 index 00000000..b452860f --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectExprSsm.hpp @@ -0,0 +1,79 @@ +/** @file ISyntaxStateMachine_DExpectExprSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DExpectExprSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DExpectExprSsm.json5] + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include "SyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_Xfer.hpp" +#include "DExpectExprSsm.hpp" + +namespace xo { namespace scm { class ISyntaxStateMachine_DExpectExprSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISyntaxStateMachine_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISyntaxStateMachine_DExpectExprSsm + **/ + class ISyntaxStateMachine_DExpectExprSsm { + public: + /** @defgroup scm-syntaxstatemachine-dexpectexprssm-type-traits **/ + ///@{ + using TypeDescr = xo::scm::ASyntaxStateMachine::TypeDescr; + using Copaque = xo::scm::ASyntaxStateMachine::Copaque; + using Opaque = xo::scm::ASyntaxStateMachine::Opaque; + ///@} + /** @defgroup scm-syntaxstatemachine-dexpectexprssm-methods **/ + ///@{ + // const methods + /** identify a type of syntax state machine **/ + static syntaxstatetype ssm_type(const DExpectExprSsm & self) noexcept; + /** text describing expected/allowed input to this ssm in current state **/ + static std::string_view get_expect_str(const DExpectExprSsm & self) noexcept; + + // non-const methods + /** operate state machine for incoming token @p tk **/ + static void on_token(DExpectExprSsm & self, const Token & tk, ParserStateMachine * p_psm); + /** update stat machine for incoming parsed symbol @p sym **/ + static void on_parsed_symbol(DExpectExprSsm & self, std::string_view sym, ParserStateMachine * p_psm); + /** operate state machine for incoming type description @p td **/ + static void on_parsed_typedescr(DExpectExprSsm & self, TypeDescr td, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal(DExpectExprSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal_with_token(DExpectExprSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm); + /** consume formal arglist emitted by nested ssm **/ + static void on_parsed_formal_arglist(DExpectExprSsm & self, DArray * arglist, ParserStateMachine * p_psm); + /** update state machine for incoming parsed expression @p expr **/ + static void on_parsed_expression(DExpectExprSsm & self, obj expr, ParserStateMachine * p_psm); + /** update state machine @p p_psm for incoming parsed expression @p expr followed by token @p tk **/ + static void on_parsed_expression_with_token(DExpectExprSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectFormalArgSsm.hpp b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectFormalArgSsm.hpp new file mode 100644 index 00000000..466dce8b --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectFormalArgSsm.hpp @@ -0,0 +1,79 @@ +/** @file ISyntaxStateMachine_DExpectFormalArgSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DExpectFormalArgSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DExpectFormalArgSsm.json5] + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include "SyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_Xfer.hpp" +#include "DExpectFormalArgSsm.hpp" + +namespace xo { namespace scm { class ISyntaxStateMachine_DExpectFormalArgSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISyntaxStateMachine_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISyntaxStateMachine_DExpectFormalArgSsm + **/ + class ISyntaxStateMachine_DExpectFormalArgSsm { + public: + /** @defgroup scm-syntaxstatemachine-dexpectformalargssm-type-traits **/ + ///@{ + using TypeDescr = xo::scm::ASyntaxStateMachine::TypeDescr; + using Copaque = xo::scm::ASyntaxStateMachine::Copaque; + using Opaque = xo::scm::ASyntaxStateMachine::Opaque; + ///@} + /** @defgroup scm-syntaxstatemachine-dexpectformalargssm-methods **/ + ///@{ + // const methods + /** identify a type of syntax state machine **/ + static syntaxstatetype ssm_type(const DExpectFormalArgSsm & self) noexcept; + /** text describing expected/allowed input to this ssm in current state **/ + static std::string_view get_expect_str(const DExpectFormalArgSsm & self) noexcept; + + // non-const methods + /** operate state machine for incoming token @p tk **/ + static void on_token(DExpectFormalArgSsm & self, const Token & tk, ParserStateMachine * p_psm); + /** update stat machine for incoming parsed symbol @p sym **/ + static void on_parsed_symbol(DExpectFormalArgSsm & self, std::string_view sym, ParserStateMachine * p_psm); + /** operate state machine for incoming type description @p td **/ + static void on_parsed_typedescr(DExpectFormalArgSsm & self, TypeDescr td, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal(DExpectFormalArgSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal_with_token(DExpectFormalArgSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm); + /** consume formal arglist emitted by nested ssm **/ + static void on_parsed_formal_arglist(DExpectFormalArgSsm & self, DArray * arglist, ParserStateMachine * p_psm); + /** update state machine for incoming parsed expression @p expr **/ + static void on_parsed_expression(DExpectFormalArgSsm & self, obj expr, ParserStateMachine * p_psm); + /** update state machine @p p_psm for incoming parsed expression @p expr followed by token @p tk **/ + static void on_parsed_expression_with_token(DExpectFormalArgSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectFormalArglistSsm.hpp b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectFormalArglistSsm.hpp new file mode 100644 index 00000000..571255f9 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectFormalArglistSsm.hpp @@ -0,0 +1,79 @@ +/** @file ISyntaxStateMachine_DExpectFormalArglistSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DExpectFormalArglistSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DExpectFormalArglistSsm.json5] + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include "SyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_Xfer.hpp" +#include "DExpectFormalArglistSsm.hpp" + +namespace xo { namespace scm { class ISyntaxStateMachine_DExpectFormalArglistSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISyntaxStateMachine_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISyntaxStateMachine_DExpectFormalArglistSsm + **/ + class ISyntaxStateMachine_DExpectFormalArglistSsm { + public: + /** @defgroup scm-syntaxstatemachine-dexpectformalarglistssm-type-traits **/ + ///@{ + using TypeDescr = xo::scm::ASyntaxStateMachine::TypeDescr; + using Copaque = xo::scm::ASyntaxStateMachine::Copaque; + using Opaque = xo::scm::ASyntaxStateMachine::Opaque; + ///@} + /** @defgroup scm-syntaxstatemachine-dexpectformalarglistssm-methods **/ + ///@{ + // const methods + /** identify a type of syntax state machine **/ + static syntaxstatetype ssm_type(const DExpectFormalArglistSsm & self) noexcept; + /** text describing expected/allowed input to this ssm in current state **/ + static std::string_view get_expect_str(const DExpectFormalArglistSsm & self) noexcept; + + // non-const methods + /** operate state machine for incoming token @p tk **/ + static void on_token(DExpectFormalArglistSsm & self, const Token & tk, ParserStateMachine * p_psm); + /** update stat machine for incoming parsed symbol @p sym **/ + static void on_parsed_symbol(DExpectFormalArglistSsm & self, std::string_view sym, ParserStateMachine * p_psm); + /** operate state machine for incoming type description @p td **/ + static void on_parsed_typedescr(DExpectFormalArglistSsm & self, TypeDescr td, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal(DExpectFormalArglistSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal_with_token(DExpectFormalArglistSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm); + /** consume formal arglist emitted by nested ssm **/ + static void on_parsed_formal_arglist(DExpectFormalArglistSsm & self, DArray * arglist, ParserStateMachine * p_psm); + /** update state machine for incoming parsed expression @p expr **/ + static void on_parsed_expression(DExpectFormalArglistSsm & self, obj expr, ParserStateMachine * p_psm); + /** update state machine @p p_psm for incoming parsed expression @p expr followed by token @p tk **/ + static void on_parsed_expression_with_token(DExpectFormalArglistSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectSymbolSsm.hpp b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectSymbolSsm.hpp new file mode 100644 index 00000000..d8367631 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectSymbolSsm.hpp @@ -0,0 +1,79 @@ +/** @file ISyntaxStateMachine_DExpectSymbolSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DExpectSymbolSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DExpectSymbolSsm.json5] + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include "SyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_Xfer.hpp" +#include "DExpectSymbolSsm.hpp" + +namespace xo { namespace scm { class ISyntaxStateMachine_DExpectSymbolSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISyntaxStateMachine_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISyntaxStateMachine_DExpectSymbolSsm + **/ + class ISyntaxStateMachine_DExpectSymbolSsm { + public: + /** @defgroup scm-syntaxstatemachine-dexpectsymbolssm-type-traits **/ + ///@{ + using TypeDescr = xo::scm::ASyntaxStateMachine::TypeDescr; + using Copaque = xo::scm::ASyntaxStateMachine::Copaque; + using Opaque = xo::scm::ASyntaxStateMachine::Opaque; + ///@} + /** @defgroup scm-syntaxstatemachine-dexpectsymbolssm-methods **/ + ///@{ + // const methods + /** identify a type of syntax state machine **/ + static syntaxstatetype ssm_type(const DExpectSymbolSsm & self) noexcept; + /** text describing expected/allowed input to this ssm in current state **/ + static std::string_view get_expect_str(const DExpectSymbolSsm & self) noexcept; + + // non-const methods + /** operate state machine for incoming token @p tk **/ + static void on_token(DExpectSymbolSsm & self, const Token & tk, ParserStateMachine * p_psm); + /** update stat machine for incoming parsed symbol @p sym **/ + static void on_parsed_symbol(DExpectSymbolSsm & self, std::string_view sym, ParserStateMachine * p_psm); + /** operate state machine for incoming type description @p td **/ + static void on_parsed_typedescr(DExpectSymbolSsm & self, TypeDescr td, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal(DExpectSymbolSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal_with_token(DExpectSymbolSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm); + /** consume formal arglist emitted by nested ssm **/ + static void on_parsed_formal_arglist(DExpectSymbolSsm & self, DArray * arglist, ParserStateMachine * p_psm); + /** update state machine for incoming parsed expression @p expr **/ + static void on_parsed_expression(DExpectSymbolSsm & self, obj expr, ParserStateMachine * p_psm); + /** update state machine @p p_psm for incoming parsed expression @p expr followed by token @p tk **/ + static void on_parsed_expression_with_token(DExpectSymbolSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectTypeSsm.hpp b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectTypeSsm.hpp new file mode 100644 index 00000000..87b5db71 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectTypeSsm.hpp @@ -0,0 +1,79 @@ +/** @file ISyntaxStateMachine_DExpectTypeSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DExpectTypeSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DExpectTypeSsm.json5] + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include "SyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_Xfer.hpp" +#include "DExpectTypeSsm.hpp" + +namespace xo { namespace scm { class ISyntaxStateMachine_DExpectTypeSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISyntaxStateMachine_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISyntaxStateMachine_DExpectTypeSsm + **/ + class ISyntaxStateMachine_DExpectTypeSsm { + public: + /** @defgroup scm-syntaxstatemachine-dexpecttypessm-type-traits **/ + ///@{ + using TypeDescr = xo::scm::ASyntaxStateMachine::TypeDescr; + using Copaque = xo::scm::ASyntaxStateMachine::Copaque; + using Opaque = xo::scm::ASyntaxStateMachine::Opaque; + ///@} + /** @defgroup scm-syntaxstatemachine-dexpecttypessm-methods **/ + ///@{ + // const methods + /** identify a type of syntax state machine **/ + static syntaxstatetype ssm_type(const DExpectTypeSsm & self) noexcept; + /** text describing expected/allowed input to this ssm in current state **/ + static std::string_view get_expect_str(const DExpectTypeSsm & self) noexcept; + + // non-const methods + /** operate state machine for incoming token @p tk **/ + static void on_token(DExpectTypeSsm & self, const Token & tk, ParserStateMachine * p_psm); + /** update stat machine for incoming parsed symbol @p sym **/ + static void on_parsed_symbol(DExpectTypeSsm & self, std::string_view sym, ParserStateMachine * p_psm); + /** operate state machine for incoming type description @p td **/ + static void on_parsed_typedescr(DExpectTypeSsm & self, TypeDescr td, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal(DExpectTypeSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal_with_token(DExpectTypeSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm); + /** consume formal arglist emitted by nested ssm **/ + static void on_parsed_formal_arglist(DExpectTypeSsm & self, DArray * arglist, ParserStateMachine * p_psm); + /** update state machine for incoming parsed expression @p expr **/ + static void on_parsed_expression(DExpectTypeSsm & self, obj expr, ParserStateMachine * p_psm); + /** update state machine @p p_psm for incoming parsed expression @p expr followed by token @p tk **/ + static void on_parsed_expression_with_token(DExpectTypeSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DIfElseSsm.hpp b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DIfElseSsm.hpp new file mode 100644 index 00000000..d1373a1a --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DIfElseSsm.hpp @@ -0,0 +1,79 @@ +/** @file ISyntaxStateMachine_DIfElseSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DIfElseSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DIfElseSsm.json5] + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include "SyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_Xfer.hpp" +#include "DIfElseSsm.hpp" + +namespace xo { namespace scm { class ISyntaxStateMachine_DIfElseSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISyntaxStateMachine_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISyntaxStateMachine_DIfElseSsm + **/ + class ISyntaxStateMachine_DIfElseSsm { + public: + /** @defgroup scm-syntaxstatemachine-difelsessm-type-traits **/ + ///@{ + using TypeDescr = xo::scm::ASyntaxStateMachine::TypeDescr; + using Copaque = xo::scm::ASyntaxStateMachine::Copaque; + using Opaque = xo::scm::ASyntaxStateMachine::Opaque; + ///@} + /** @defgroup scm-syntaxstatemachine-difelsessm-methods **/ + ///@{ + // const methods + /** identify a type of syntax state machine **/ + static syntaxstatetype ssm_type(const DIfElseSsm & self) noexcept; + /** text describing expected/allowed input to this ssm in current state **/ + static std::string_view get_expect_str(const DIfElseSsm & self) noexcept; + + // non-const methods + /** operate state machine for incoming token @p tk **/ + static void on_token(DIfElseSsm & self, const Token & tk, ParserStateMachine * p_psm); + /** update stat machine for incoming parsed symbol @p sym **/ + static void on_parsed_symbol(DIfElseSsm & self, std::string_view sym, ParserStateMachine * p_psm); + /** operate state machine for incoming type description @p td **/ + static void on_parsed_typedescr(DIfElseSsm & self, TypeDescr td, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal(DIfElseSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal_with_token(DIfElseSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm); + /** consume formal arglist emitted by nested ssm **/ + static void on_parsed_formal_arglist(DIfElseSsm & self, DArray * arglist, ParserStateMachine * p_psm); + /** update state machine for incoming parsed expression @p expr **/ + static void on_parsed_expression(DIfElseSsm & self, obj expr, ParserStateMachine * p_psm); + /** update state machine @p p_psm for incoming parsed expression @p expr followed by token @p tk **/ + static void on_parsed_expression_with_token(DIfElseSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DLambdaSsm.hpp b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DLambdaSsm.hpp new file mode 100644 index 00000000..3c945b94 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DLambdaSsm.hpp @@ -0,0 +1,79 @@ +/** @file ISyntaxStateMachine_DLambdaSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DLambdaSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DLambdaSsm.json5] + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include "SyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_Xfer.hpp" +#include "DLambdaSsm.hpp" + +namespace xo { namespace scm { class ISyntaxStateMachine_DLambdaSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISyntaxStateMachine_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISyntaxStateMachine_DLambdaSsm + **/ + class ISyntaxStateMachine_DLambdaSsm { + public: + /** @defgroup scm-syntaxstatemachine-dlambdassm-type-traits **/ + ///@{ + using TypeDescr = xo::scm::ASyntaxStateMachine::TypeDescr; + using Copaque = xo::scm::ASyntaxStateMachine::Copaque; + using Opaque = xo::scm::ASyntaxStateMachine::Opaque; + ///@} + /** @defgroup scm-syntaxstatemachine-dlambdassm-methods **/ + ///@{ + // const methods + /** identify a type of syntax state machine **/ + static syntaxstatetype ssm_type(const DLambdaSsm & self) noexcept; + /** text describing expected/allowed input to this ssm in current state **/ + static std::string_view get_expect_str(const DLambdaSsm & self) noexcept; + + // non-const methods + /** operate state machine for incoming token @p tk **/ + static void on_token(DLambdaSsm & self, const Token & tk, ParserStateMachine * p_psm); + /** update stat machine for incoming parsed symbol @p sym **/ + static void on_parsed_symbol(DLambdaSsm & self, std::string_view sym, ParserStateMachine * p_psm); + /** operate state machine for incoming type description @p td **/ + static void on_parsed_typedescr(DLambdaSsm & self, TypeDescr td, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal(DLambdaSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal_with_token(DLambdaSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm); + /** consume formal arglist emitted by nested ssm **/ + static void on_parsed_formal_arglist(DLambdaSsm & self, DArray * arglist, ParserStateMachine * p_psm); + /** update state machine for incoming parsed expression @p expr **/ + static void on_parsed_expression(DLambdaSsm & self, obj expr, ParserStateMachine * p_psm); + /** update state machine @p p_psm for incoming parsed expression @p expr followed by token @p tk **/ + static void on_parsed_expression_with_token(DLambdaSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DParenSsm.hpp b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DParenSsm.hpp new file mode 100644 index 00000000..19e4a89b --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DParenSsm.hpp @@ -0,0 +1,79 @@ +/** @file ISyntaxStateMachine_DParenSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DParenSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DParenSsm.json5] + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include "SyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_Xfer.hpp" +#include "DParenSsm.hpp" + +namespace xo { namespace scm { class ISyntaxStateMachine_DParenSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISyntaxStateMachine_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISyntaxStateMachine_DParenSsm + **/ + class ISyntaxStateMachine_DParenSsm { + public: + /** @defgroup scm-syntaxstatemachine-dparenssm-type-traits **/ + ///@{ + using TypeDescr = xo::scm::ASyntaxStateMachine::TypeDescr; + using Copaque = xo::scm::ASyntaxStateMachine::Copaque; + using Opaque = xo::scm::ASyntaxStateMachine::Opaque; + ///@} + /** @defgroup scm-syntaxstatemachine-dparenssm-methods **/ + ///@{ + // const methods + /** identify a type of syntax state machine **/ + static syntaxstatetype ssm_type(const DParenSsm & self) noexcept; + /** text describing expected/allowed input to this ssm in current state **/ + static std::string_view get_expect_str(const DParenSsm & self) noexcept; + + // non-const methods + /** operate state machine for incoming token @p tk **/ + static void on_token(DParenSsm & self, const Token & tk, ParserStateMachine * p_psm); + /** update stat machine for incoming parsed symbol @p sym **/ + static void on_parsed_symbol(DParenSsm & self, std::string_view sym, ParserStateMachine * p_psm); + /** operate state machine for incoming type description @p td **/ + static void on_parsed_typedescr(DParenSsm & self, TypeDescr td, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal(DParenSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal_with_token(DParenSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm); + /** consume formal arglist emitted by nested ssm **/ + static void on_parsed_formal_arglist(DParenSsm & self, DArray * arglist, ParserStateMachine * p_psm); + /** update state machine for incoming parsed expression @p expr **/ + static void on_parsed_expression(DParenSsm & self, obj expr, ParserStateMachine * p_psm); + /** update state machine @p p_psm for incoming parsed expression @p expr followed by token @p tk **/ + static void on_parsed_expression_with_token(DParenSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DProgressSsm.hpp b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DProgressSsm.hpp new file mode 100644 index 00000000..13a2d461 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DProgressSsm.hpp @@ -0,0 +1,79 @@ +/** @file ISyntaxStateMachine_DProgressSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DProgressSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DProgressSsm.json5] + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include "SyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_Xfer.hpp" +#include "DProgressSsm.hpp" + +namespace xo { namespace scm { class ISyntaxStateMachine_DProgressSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISyntaxStateMachine_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISyntaxStateMachine_DProgressSsm + **/ + class ISyntaxStateMachine_DProgressSsm { + public: + /** @defgroup scm-syntaxstatemachine-dprogressssm-type-traits **/ + ///@{ + using TypeDescr = xo::scm::ASyntaxStateMachine::TypeDescr; + using Copaque = xo::scm::ASyntaxStateMachine::Copaque; + using Opaque = xo::scm::ASyntaxStateMachine::Opaque; + ///@} + /** @defgroup scm-syntaxstatemachine-dprogressssm-methods **/ + ///@{ + // const methods + /** identify a type of syntax state machine **/ + static syntaxstatetype ssm_type(const DProgressSsm & self) noexcept; + /** text describing expected/allowed input to this ssm in current state **/ + static std::string_view get_expect_str(const DProgressSsm & self) noexcept; + + // non-const methods + /** operate state machine for incoming token @p tk **/ + static void on_token(DProgressSsm & self, const Token & tk, ParserStateMachine * p_psm); + /** update stat machine for incoming parsed symbol @p sym **/ + static void on_parsed_symbol(DProgressSsm & self, std::string_view sym, ParserStateMachine * p_psm); + /** operate state machine for incoming type description @p td **/ + static void on_parsed_typedescr(DProgressSsm & self, TypeDescr td, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal(DProgressSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal_with_token(DProgressSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm); + /** consume formal arglist emitted by nested ssm **/ + static void on_parsed_formal_arglist(DProgressSsm & self, DArray * arglist, ParserStateMachine * p_psm); + /** update state machine for incoming parsed expression @p expr **/ + static void on_parsed_expression(DProgressSsm & self, obj expr, ParserStateMachine * p_psm); + /** update state machine @p p_psm for incoming parsed expression @p expr followed by token @p tk **/ + static void on_parsed_expression_with_token(DProgressSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DSequenceSsm.hpp b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DSequenceSsm.hpp new file mode 100644 index 00000000..7e0cfb42 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DSequenceSsm.hpp @@ -0,0 +1,79 @@ +/** @file ISyntaxStateMachine_DSequenceSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DSequenceSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DSequenceSsm.json5] + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include "SyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_Xfer.hpp" +#include "DSequenceSsm.hpp" + +namespace xo { namespace scm { class ISyntaxStateMachine_DSequenceSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISyntaxStateMachine_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISyntaxStateMachine_DSequenceSsm + **/ + class ISyntaxStateMachine_DSequenceSsm { + public: + /** @defgroup scm-syntaxstatemachine-dsequencessm-type-traits **/ + ///@{ + using TypeDescr = xo::scm::ASyntaxStateMachine::TypeDescr; + using Copaque = xo::scm::ASyntaxStateMachine::Copaque; + using Opaque = xo::scm::ASyntaxStateMachine::Opaque; + ///@} + /** @defgroup scm-syntaxstatemachine-dsequencessm-methods **/ + ///@{ + // const methods + /** identify a type of syntax state machine **/ + static syntaxstatetype ssm_type(const DSequenceSsm & self) noexcept; + /** text describing expected/allowed input to this ssm in current state **/ + static std::string_view get_expect_str(const DSequenceSsm & self) noexcept; + + // non-const methods + /** operate state machine for incoming token @p tk **/ + static void on_token(DSequenceSsm & self, const Token & tk, ParserStateMachine * p_psm); + /** update stat machine for incoming parsed symbol @p sym **/ + static void on_parsed_symbol(DSequenceSsm & self, std::string_view sym, ParserStateMachine * p_psm); + /** operate state machine for incoming type description @p td **/ + static void on_parsed_typedescr(DSequenceSsm & self, TypeDescr td, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal(DSequenceSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal_with_token(DSequenceSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm); + /** consume formal arglist emitted by nested ssm **/ + static void on_parsed_formal_arglist(DSequenceSsm & self, DArray * arglist, ParserStateMachine * p_psm); + /** update state machine for incoming parsed expression @p expr **/ + static void on_parsed_expression(DSequenceSsm & self, obj expr, ParserStateMachine * p_psm); + /** update state machine @p p_psm for incoming parsed expression @p expr followed by token @p tk **/ + static void on_parsed_expression_with_token(DSequenceSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DToplevelSeqSsm.hpp b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DToplevelSeqSsm.hpp new file mode 100644 index 00000000..69a3c71f --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DToplevelSeqSsm.hpp @@ -0,0 +1,79 @@ +/** @file ISyntaxStateMachine_DToplevelSeqSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DToplevelSeqSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DToplevelSeqSsm.json5] + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include "SyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_Xfer.hpp" +#include "DToplevelSeqSsm.hpp" + +namespace xo { namespace scm { class ISyntaxStateMachine_DToplevelSeqSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISyntaxStateMachine_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISyntaxStateMachine_DToplevelSeqSsm + **/ + class ISyntaxStateMachine_DToplevelSeqSsm { + public: + /** @defgroup scm-syntaxstatemachine-dtoplevelseqssm-type-traits **/ + ///@{ + using TypeDescr = xo::scm::ASyntaxStateMachine::TypeDescr; + using Copaque = xo::scm::ASyntaxStateMachine::Copaque; + using Opaque = xo::scm::ASyntaxStateMachine::Opaque; + ///@} + /** @defgroup scm-syntaxstatemachine-dtoplevelseqssm-methods **/ + ///@{ + // const methods + /** identify a type of syntax state machine **/ + static syntaxstatetype ssm_type(const DToplevelSeqSsm & self) noexcept; + /** text describing expected/allowed input to this ssm in current state **/ + static std::string_view get_expect_str(const DToplevelSeqSsm & self) noexcept; + + // non-const methods + /** operate state machine for incoming token @p tk **/ + static void on_token(DToplevelSeqSsm & self, const Token & tk, ParserStateMachine * p_psm); + /** update stat machine for incoming parsed symbol @p sym **/ + static void on_parsed_symbol(DToplevelSeqSsm & self, std::string_view sym, ParserStateMachine * p_psm); + /** operate state machine for incoming type description @p td **/ + static void on_parsed_typedescr(DToplevelSeqSsm & self, TypeDescr td, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal(DToplevelSeqSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal_with_token(DToplevelSeqSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm); + /** consume formal arglist emitted by nested ssm **/ + static void on_parsed_formal_arglist(DToplevelSeqSsm & self, DArray * arglist, ParserStateMachine * p_psm); + /** update state machine for incoming parsed expression @p expr **/ + static void on_parsed_expression(DToplevelSeqSsm & self, obj expr, ParserStateMachine * p_psm); + /** update state machine @p p_psm for incoming parsed expression @p expr followed by token @p tk **/ + static void on_parsed_expression_with_token(DToplevelSeqSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_Xfer.hpp b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_Xfer.hpp new file mode 100644 index 00000000..30c87269 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_Xfer.hpp @@ -0,0 +1,114 @@ +/** @file ISyntaxStateMachine_Xfer.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/SyntaxStateMachine.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/SyntaxStateMachine.json5] + **/ + +#pragma once + +#include "ParserStateMachine.hpp" +#include "syntaxstatetype.hpp" +#include +#include + +namespace xo { +namespace scm { + /** @class ISyntaxStateMachine_Xfer + **/ + template + class ISyntaxStateMachine_Xfer : public ASyntaxStateMachine { + public: + /** @defgroup scm-syntaxstatemachine-xfer-type-traits **/ + ///@{ + /** actual implementation (not generated; often delegates to DRepr) **/ + using Impl = ISyntaxStateMachine_DRepr; + /** integer identifying a type **/ + using typeseq = ASyntaxStateMachine::typeseq; + using TypeDescr = ASyntaxStateMachine::TypeDescr; + ///@} + + /** @defgroup scm-syntaxstatemachine-xfer-methods **/ + ///@{ + + static const DRepr & _dcast(Copaque d) { return *(const DRepr *)d; } + static DRepr & _dcast(Opaque d) { return *(DRepr *)d; } + + // from ASyntaxStateMachine + + // builtin methods + typeseq _typeseq() const noexcept override { return s_typeseq; } + void _drop(Opaque d) const noexcept override { _dcast(d).~DRepr(); } + + // const methods + syntaxstatetype ssm_type(Copaque data) const noexcept override { + return I::ssm_type(_dcast(data)); + } + std::string_view get_expect_str(Copaque data) const noexcept override { + return I::get_expect_str(_dcast(data)); + } + + // non-const methods + void on_token(Opaque data, const Token & tk, ParserStateMachine * p_psm) override { + return I::on_token(_dcast(data), tk, p_psm); + } + void on_parsed_symbol(Opaque data, std::string_view sym, ParserStateMachine * p_psm) override { + return I::on_parsed_symbol(_dcast(data), sym, p_psm); + } + void on_parsed_typedescr(Opaque data, TypeDescr td, ParserStateMachine * p_psm) override { + return I::on_parsed_typedescr(_dcast(data), td, p_psm); + } + void on_parsed_formal(Opaque data, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) override { + return I::on_parsed_formal(_dcast(data), param_name, param_type, p_psm); + } + void on_parsed_formal_with_token(Opaque data, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) override { + return I::on_parsed_formal_with_token(_dcast(data), param_name, param_type, tk, p_psm); + } + void on_parsed_formal_arglist(Opaque data, DArray * arglist, ParserStateMachine * p_psm) override { + return I::on_parsed_formal_arglist(_dcast(data), arglist, p_psm); + } + void on_parsed_expression(Opaque data, obj expr, ParserStateMachine * p_psm) override { + return I::on_parsed_expression(_dcast(data), expr, p_psm); + } + void on_parsed_expression_with_token(Opaque data, obj expr, const Token & tk, ParserStateMachine * p_psm) override { + return I::on_parsed_expression_with_token(_dcast(data), expr, tk, p_psm); + } + + ///@} + + private: + using I = Impl; + + public: + /** @defgroup scm-syntaxstatemachine-xfer-member-vars **/ + ///@{ + + /** typeseq for template parameter DRepr **/ + static typeseq s_typeseq; + /** true iff satisfies facet implementation **/ + static bool _valid; + + ///@} + }; + + template + xo::facet::typeseq + ISyntaxStateMachine_Xfer::s_typeseq + = xo::facet::typeseq::id(); + + template + bool + ISyntaxStateMachine_Xfer::_valid + = xo::facet::valid_facet_implementation(); + +} /*namespace scm */ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_Xfer.hpp */ diff --git a/xo-reader2/include/xo/reader2/ssm/RSyntaxStateMachine.hpp b/xo-reader2/include/xo/reader2/ssm/RSyntaxStateMachine.hpp new file mode 100644 index 00000000..8012b657 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/RSyntaxStateMachine.hpp @@ -0,0 +1,112 @@ +/** @file RSyntaxStateMachine.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/SyntaxStateMachine.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/SyntaxStateMachine.json5] + **/ + +#pragma once + +#include "ASyntaxStateMachine.hpp" + +namespace xo { +namespace scm { + +/** @class RSyntaxStateMachine + **/ +template +class RSyntaxStateMachine : public Object { +private: + using O = Object; + +public: + /** @defgroup scm-syntaxstatemachine-router-type-traits **/ + ///@{ + using ObjectType = Object; + using DataPtr = Object::DataPtr; + using typeseq = xo::reflect::typeseq; + using TypeDescr = ASyntaxStateMachine::TypeDescr; + ///@} + + /** @defgroup scm-syntaxstatemachine-router-ctors **/ + ///@{ + RSyntaxStateMachine() {} + RSyntaxStateMachine(Object::DataPtr data) : Object{std::move(data)} {} + RSyntaxStateMachine(const ASyntaxStateMachine * iface, void * data) + requires std::is_same_v + : Object(iface, data) {} + + ///@} + /** @defgroup scm-syntaxstatemachine-router-methods **/ + ///@{ + + // explicit injected content + + // builtin methods + typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); } + void _drop() const noexcept { O::iface()->_drop(O::data()); } + + // const methods + syntaxstatetype ssm_type() const noexcept { + return O::iface()->ssm_type(O::data()); + } + std::string_view get_expect_str() const noexcept { + return O::iface()->get_expect_str(O::data()); + } + + // non-const methods (still const in router!) + void on_token(const Token & tk, ParserStateMachine * p_psm) { + return O::iface()->on_token(O::data(), tk, p_psm); + } + void on_parsed_symbol(std::string_view sym, ParserStateMachine * p_psm) { + return O::iface()->on_parsed_symbol(O::data(), sym, p_psm); + } + void on_parsed_typedescr(TypeDescr td, ParserStateMachine * p_psm) { + return O::iface()->on_parsed_typedescr(O::data(), td, p_psm); + } + void on_parsed_formal(const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) { + return O::iface()->on_parsed_formal(O::data(), param_name, param_type, p_psm); + } + void on_parsed_formal_with_token(const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) { + return O::iface()->on_parsed_formal_with_token(O::data(), param_name, param_type, tk, p_psm); + } + void on_parsed_formal_arglist(DArray * arglist, ParserStateMachine * p_psm) { + return O::iface()->on_parsed_formal_arglist(O::data(), arglist, p_psm); + } + void on_parsed_expression(obj expr, ParserStateMachine * p_psm) { + return O::iface()->on_parsed_expression(O::data(), expr, p_psm); + } + void on_parsed_expression_with_token(obj expr, const Token & tk, ParserStateMachine * p_psm) { + return O::iface()->on_parsed_expression_with_token(O::data(), expr, tk, p_psm); + } + + ///@} + /** @defgroup scm-syntaxstatemachine-member-vars **/ + ///@{ + + static bool _valid; + + ///@} +}; + +template +bool +RSyntaxStateMachine::_valid = xo::facet::valid_object_router(); + +} /*namespace scm*/ +} /*namespace xo*/ + +namespace xo { namespace facet { + template + struct RoutingFor { + using RoutingType = xo::scm::RSyntaxStateMachine; + }; +} } + +/* end RSyntaxStateMachine.hpp */ diff --git a/xo-reader2/include/xo/reader2/syntaxstatetype.hpp b/xo-reader2/include/xo/reader2/syntaxstatetype.hpp new file mode 100644 index 00000000..957272e8 --- /dev/null +++ b/xo-reader2/include/xo/reader2/syntaxstatetype.hpp @@ -0,0 +1,74 @@ +/** @file syntaxstatetype.hpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include + +namespace xo { + namespace scm { + /** @enum syntaxstatemachine + * @brief Label a specialized parsing state machine + * + * Label for a schematika syntax state machine + * dedicated to some particular piece of syntax + **/ + enum class syntaxstatetype { + invalid = -1, + + /** handle define-expression. See @ref DDefineSsm **/ + defexpr, + + /** handle lambda-expression. See @ref DLambdaSsm **/ + lambdaexpr, + + /** handle ifelse-expression. See @ref DIfElseSsm **/ + ifelseexpr, + + /** handle sequence-expression syntax. See @ref DSequenceSsm **/ + sequence, + + /** handle apply-expression syntax. See @ref DApplySsm **/ + apply, + + /** rhs expression. state exists to achieve 1-token lookahead **/ + progress, + + /** expression enclosed in parentheses. See @ref DParenSsm **/ + paren, + + /** toplevel of some translation unit. See @ref DToplevelSeqSsm **/ + expect_toplevel_expression_sequence, + + /** expecting a formal argument list (sub-syntax within lambda-expression) **/ + expect_formal_arglist, + + /** expecting a formal argument (sub-syntax within formal-arglist) **/ + expect_formal_arg, + + /** expecting a s symbol. See @ref DExpectSymbolSsm **/ + expect_symbol, + + /** expecting a type. See @ref DExpectTypeSsm **/ + expect_type, + + /** expecting a rhs expression. See @ref DExpectExprSsm **/ + expect_rhs_expression, + + /** comes lasts, counts number of valid enums **/ + N + }; + + const char * syntaxstatetype_descr(syntaxstatetype x); + + inline std::ostream & + operator<< (std::ostream & os, syntaxstatetype x) { + os << syntaxstatetype_descr(x); + return os; + } + } +} /*namespace xo*/ + +/* end syntaxstatetype.hpp */ diff --git a/xo-reader2/src/reader2/CMakeLists.txt b/xo-reader2/src/reader2/CMakeLists.txt new file mode 100644 index 00000000..6ad71cdf --- /dev/null +++ b/xo-reader2/src/reader2/CMakeLists.txt @@ -0,0 +1,85 @@ +# reader2/CMakeLists.txt + +set(SELF_LIB xo_reader2) +set(SELF_SRCS + init_reader2.cpp + reader2_register_facets.cpp + reader2_register_types.cpp + + SchematikaReader.cpp + ReaderConfig.cpp + + SchematikaParser.cpp + ParserStateMachine.cpp + ParserStack.cpp + ParserResult.cpp + + syntaxstatetype.cpp + ISyntaxStateMachine_Any.cpp + + DToplevelSeqSsm.cpp + ISyntaxStateMachine_DToplevelSeqSsm.cpp + IPrintable_DToplevelSeqSsm.cpp + + DDefineSsm.cpp + ISyntaxStateMachine_DDefineSsm.cpp + IPrintable_DDefineSsm.cpp + + DIfElseSsm.cpp + ISyntaxStateMachine_DIfElseSsm.cpp + IPrintable_DIfElseSsm.cpp + + DSequenceSsm.cpp + ISyntaxStateMachine_DSequenceSsm.cpp + IPrintable_DSequenceSsm.cpp + + DLambdaSsm.cpp + ISyntaxStateMachine_DLambdaSsm.cpp + IPrintable_DLambdaSsm.cpp + + DApplySsm.cpp + ISyntaxStateMachine_DApplySsm.cpp + IPrintable_DApplySsm.cpp + + DParenSsm.cpp + ISyntaxStateMachine_DParenSsm.cpp + IPrintable_DParenSsm.cpp + + DExpectFormalArglistSsm.cpp + ISyntaxStateMachine_DExpectFormalArglistSsm.cpp + IPrintable_DExpectFormalArglistSsm.cpp + + DExpectFormalArgSsm.cpp + ISyntaxStateMachine_DExpectFormalArgSsm.cpp + IPrintable_DExpectFormalArgSsm.cpp + + DExpectSymbolSsm.cpp + ISyntaxStateMachine_DExpectSymbolSsm.cpp + IPrintable_DExpectSymbolSsm.cpp + + DExpectTypeSsm.cpp + ISyntaxStateMachine_DExpectTypeSsm.cpp + IPrintable_DExpectTypeSsm.cpp + + DExpectExprSsm.cpp + ISyntaxStateMachine_DExpectExprSsm.cpp + IPrintable_DExpectExprSsm.cpp + + DProgressSsm.cpp + ISyntaxStateMachine_DProgressSsm.cpp + IPrintable_DProgressSsm.cpp + + ) + +xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS}) +# note: deps here must also appear in cmake/xo_expression2Config.cmake.in +xo_dependency(${SELF_LIB} xo_procedure2) +xo_dependency(${SELF_LIB} xo_gc) +xo_dependency(${SELF_LIB} xo_tokenizer2) +xo_dependency(${SELF_LIB} xo_expression2) +#xo_dependency(${SELF_LIB} reflect) +#xo_dependency(${SELF_LIB} xo_object2) +#xo_dependency(${SELF_LIB} xo_printable2) +#xo_dependency(${SELF_LIB} xo_flatstring) +xo_dependency(${SELF_LIB} subsys) +#xo_dependency(${SELF_LIB} indentlog) diff --git a/xo-reader2/src/reader2/DApplySsm.cpp b/xo-reader2/src/reader2/DApplySsm.cpp new file mode 100644 index 00000000..d6f5e151 --- /dev/null +++ b/xo-reader2/src/reader2/DApplySsm.cpp @@ -0,0 +1,370 @@ +/** @file DApplySsm.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "ApplySsm.hpp" +#include "ExpectExprSsm.hpp" +#include +#include +#include + +//#include "parserstatemachine.hpp" +//#include "expect_expr_xs.hpp" + +namespace xo { + using xo::mm::AGCObject; + using xo::print::APrintable; + using xo::reflect::typeseq; + + namespace scm { + + // ----- applyexprstatetype ----- + + const char * + applyexprstatetype_descr(applyexprstatetype x) { + switch (x) { + case applyexprstatetype::invalid: return "invalid"; + case applyexprstatetype::apply_0: return "apply_0"; + case applyexprstatetype::apply_1: return "apply_1"; + case applyexprstatetype::apply_2: return "apply_2"; + case applyexprstatetype::apply_3: return "apply_3"; + case applyexprstatetype::N: break; + } + + return "???applyexprstatetype"; + } + + std::ostream & + operator<<(std::ostream & os, applyexprstatetype x) { + os << applyexprstatetype_descr(x); + return os; + } + + // ----- DApplySsm ----- + + DApplySsm::DApplySsm(applyexprstatetype applystate, + obj fn_expr, + DArray * args) + : applystate_{applystate}, + fn_expr_{fn_expr}, + args_expr_v_{args} + { + if (fn_expr) { + this->applystate_ = applyexprstatetype::apply_1; + } + + assert(args->is_empty()); + } + + DApplySsm * + DApplySsm::_make(DArena & arena, + obj fn_expr) + { + obj mm(&arena); + + void * mem = arena.alloc(typeseq::id(), + sizeof(DApplySsm)); + + /* allocate room for 8 arguments (during parsing) + * will reallocate to expand if needed. + * + * See similar code in DExpectFormalArglistSsm::_make + */ + DArray * args = DArray::empty(mm, 8); + + applyexprstatetype applystate + = (fn_expr + ? applyexprstatetype::apply_1 + : applyexprstatetype::apply_0); + + // TODO: revisit if we decide to use flexible array for arguments + + return new (mem) DApplySsm(applystate, fn_expr, args); + } + + obj + DApplySsm::make(DArena & arena, + obj fn_expr) + { + return obj(_make(arena, fn_expr)); + } + + void + DApplySsm::start(obj fn_expr, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + + auto ssm = DApplySsm::make(p_psm->parser_alloc(), fn_expr); + + p_psm->push_ssm(ckp, ssm); + } + + syntaxstatetype + DApplySsm::ssm_type() const noexcept { + return syntaxstatetype::apply; + } + + + std::string_view + DApplySsm::get_expect_str() const noexcept + { + switch(applystate_) { + case applyexprstatetype::invalid: return "invalid"; + case applyexprstatetype::apply_0: return "expr"; + case applyexprstatetype::apply_1: return "lparen"; + case applyexprstatetype::apply_2: return "expr"; + case applyexprstatetype::apply_3: return "comma|rparen"; + case applyexprstatetype::N: break; + } + + return "?expect"; + } + + void + DApplySsm::on_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag()), xtag("tk", tk)); + + switch (tk.tk_type()) { + case tokentype::tk_leftparen: + this->on_leftparen_token(tk, p_psm); + return; + case tokentype::tk_symbol: + case tokentype::tk_def: + case tokentype::tk_if: + case tokentype::tk_then: + case tokentype::tk_else: + case tokentype::tk_semicolon: + case tokentype::tk_colon: + case tokentype::tk_singleassign: + case tokentype::tk_string: + case tokentype::tk_f64: + case tokentype::tk_i64: + case tokentype::tk_bool: + case tokentype::tk_invalid: + case tokentype::tk_rightparen: + case tokentype::tk_leftbracket: + case tokentype::tk_rightbracket: + case tokentype::tk_leftbrace: + case tokentype::tk_rightbrace: + case tokentype::tk_leftangle: + case tokentype::tk_rightangle: + case tokentype::tk_lessequal: + case tokentype::tk_greatequal: + case tokentype::tk_dot: + case tokentype::tk_comma: + case tokentype::tk_doublecolon: + case tokentype::tk_assign: + case tokentype::tk_yields: + case tokentype::tk_plus: + case tokentype::tk_minus: + case tokentype::tk_star: + case tokentype::tk_slash: + case tokentype::tk_cmpeq: + case tokentype::tk_cmpne: + case tokentype::tk_type: + case tokentype::tk_lambda: + case tokentype::tk_let: + case tokentype::tk_in: + case tokentype::tk_end: + case tokentype::N: + break; + } + + Super::on_token(tk, p_psm); + } + + void + DApplySsm::on_leftparen_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (applystate_ == applyexprstatetype::apply_1) { + this->applystate_ = applyexprstatetype::apply_2; + + DExpectExprSsm::start(p_psm); + return; + } + + Super::on_token(tk, p_psm); + } + + void + DApplySsm::on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm) + { + /* maybe we'll find control comes here also on function position? + * hasn't come up when applyssm recognized via leftparen + */ + + if (applystate_ == applyexprstatetype::apply_2) { + obj expr_gco = expr.to_facet(); + assert(expr_gco); + + obj mm(&(p_psm->parser_alloc())); + + if (args_expr_v_->size() == args_expr_v_->capacity()) { + // need to expand .args_expr_v_ capacity. + // Could use DArena checkpoint to redo this in place, + // since argument array must be on the top of the stack. + + DArray * argv_2x = DArray::empty(mm, 2 * args_expr_v_->capacity()); + + for (DArray::size_type i = 0, n = args_expr_v_->size(); i < n; ++i) { + argv_2x->push_back((*args_expr_v_)[i]); + } + + this->args_expr_v_ = argv_2x; + } + + if (args_expr_v_->size() < args_expr_v_->capacity()) + args_expr_v_->push_back(expr_gco); + + if (tk.tk_type() == tokentype::tk_rightparen) { + // begin assemble_expr().. + + std::uint32_t n_args = args_expr_v_->size(); + + DApplyExpr * apply + = (DApplyExpr::scaffold + (mm, + TypeRef::dwim(TypeRef::prefix_type::from_chars("apply"), + nullptr), + fn_expr_, + n_args)); + + for (std::uint32_t i_arg = 0; i_arg < n_args; ++i_arg) { + auto arg_expr + = args_expr_v_->at(i_arg).to_facet(); + + apply->assign_arg(i_arg, arg_expr); + } + + // ..end assemble_expr() + + obj apply_ex(apply); + + p_psm->pop_ssm(); + p_psm->on_parsed_expression(apply_ex); + + return; + } else if (tk.tk_type() == tokentype::tk_comma) { + // 1. want to remain in state apply_2 + // 2. expr from nested ssm already incorporated + // into .args_expr_v_ + + DExpectExprSsm::start(p_psm); + return; + } + } + + Super::on_parsed_expression_with_token(expr, tk, p_psm); + } + +#ifdef NOT_YET + void + apply_xs::on_expr(bp expr, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + switch (applyxs_type_) { + case applyexprstatetype::invalid: + case applyexprstatetype::n_applyexprstatetype: + // unreachable + break; + case applyexprstatetype::apply_0: + log && log("stash fn -> new state apply_1"); + this->fn_expr_ = expr.promote(); + this->applyxs_type_ = applyexprstatetype::apply_1; + return; + case applyexprstatetype::apply_1: + log && log("error: was expecting lparen"); + // error, expecting lparen + break; + case applyexprstatetype::apply_2: + log && log(xtag("expr", expr), xtag("do", "stash expr -> new state apply_3")); + this->args_expr_v_.push_back(expr.promote()); + this->applyxs_type_ = applyexprstatetype::apply_3; + return; + case applyexprstatetype::apply_3: + // error, expecting comma|rparen + break; + } + + /* control here --implies-> error state */ + + constexpr const char * c_self_name = "apply_xs::on_expr"; + const char * exp = this->get_expect_str(); + + this->illegal_input_on_expr(c_self_name, expr, exp, p_psm); + } + + void + apply_xs::on_comma_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + if (this->applyxs_type_ == applyexprstatetype::apply_3) { + this->applyxs_type_ = applyexprstatetype::apply_2; + expect_expr_xs::start(p_psm); + } else { + constexpr const char * c_self_name = "apply_xs::on_comma_token"; + const char * exp = this->get_expect_str(); + + this->illegal_input_on_token(c_self_name, tk, exp, p_psm); + } + } + + void + apply_xs::on_rightparen_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log("applyxs_type", applyxs_type_); + + if (this->applyxs_type_ == applyexprstatetype::apply_3) { + /* (done) state */ + log("apply complete -> pop + send expr"); + + rp apply_expr = Apply::make(this->fn_expr_, this->args_expr_v_); + + std::unique_ptr self = p_psm->pop_exprstate(); + + p_psm->top_exprstate().on_expr(apply_expr, p_psm); + return; + } + + constexpr const char * c_self_name = "apply_xs::on_rightparen_token"; + const char * exp = this->get_expect_str(); + + this->illegal_input_on_token(c_self_name, tk, exp, p_psm); + } +#endif + + bool + DApplySsm::pretty(const ppindentinfo & ppii) const + { + // TODO: const-correct version of obj<> template + auto fn_expr = const_cast(this)->fn_expr_.to_facet(); + bool fn_expr_present(fn_expr); + + return ppii.pps()->pretty_struct(ppii, + "DApplySsm", + refrtag("applystate", applystate_), + refrtag("expect", this->get_expect_str()), + refrtag("fn_expr", fn_expr, fn_expr_present)); + } + + } /*namespace scm*/ +} /*namespace xo*/ + + +/* end DApplySsm.cpp */ diff --git a/xo-reader2/src/reader2/DDefineSsm.cpp b/xo-reader2/src/reader2/DDefineSsm.cpp new file mode 100644 index 00000000..aae07b90 --- /dev/null +++ b/xo-reader2/src/reader2/DDefineSsm.cpp @@ -0,0 +1,701 @@ + /** @file DDefineSsm.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "DDefineSsm.hpp" +#include "DExpectSymbolSsm.hpp" +#include "DExpectTypeSsm.hpp" +#include "DExpectExprSsm.hpp" +#include "ssm/ISyntaxStateMachine_DDefineSsm.hpp" +#include "ssm/IPrintable_DDefineSsm.hpp" +#include +#include +#include + +#ifdef NOT_YET +#include "parserstatemachine.hpp" +#include "expect_symbol_xs.hpp" +#include "expect_expr_xs.hpp" +#include "expect_type_xs.hpp" +#include "pretty_expression.hpp" +#endif + +namespace xo { + using xo::print::APrintable; + using xo::facet::FacetRegistry; + using xo::facet::with_facet; + using xo::facet::typeseq; + + namespace scm { + // ----- defexprstatetype ----- + + const char * + defexprstatetype_descr(defexprstatetype x) { + switch (x) { + case defexprstatetype::invalid: return "invalid"; + case defexprstatetype::def_0: return "def_0"; + case defexprstatetype::def_1: return "def_1"; + case defexprstatetype::def_2: return "def_2"; + case defexprstatetype::def_3: return "def_3"; + case defexprstatetype::def_4: return "def_4"; + case defexprstatetype::def_5: return "def_5"; + case defexprstatetype::def_6: return "def_6"; + case defexprstatetype::n_defexprstatetype: break; + } + + return "???defexprstatetype"; + } + + std::ostream & + operator<<(std::ostream & os, defexprstatetype x) { + os << defexprstatetype_descr(x); + return os; + } + + // ----- define_xs ----- + + // DDefineSsm::make + + // DDefineSsm::start + +#ifdef NOT_YET + define_xs::define_xs(rp def_expr) + : exprstate(exprstatetype::defexpr), + defxs_type_{defexprstatetype::def_0}, + def_expr_{std::move(def_expr)} + {} + + // const char * + // define_xs::get_expect_str() const { ... } + + void + define_xs::on_expr(bp expr, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log(xtag("defxs_type", defxs_type_)); + + if (this->defxs_type_ == defexprstatetype::def_5) { + /* have all the ingredients to create an expression + * representing a definition + * + * 1. if ir_type is a symbol, interpret as variable name. + * Need to be able to locate variable by type + * 2. if ir_type is an expression, adopt as rhs + */ + rp rhs_value = expr.promote(); + + if (this->cvt_expr_) { + this->cvt_expr_->assign_arg(rhs_value); + } else { + /* note: establishes .def_expr_ valuetype */ + this->def_expr_->assign_rhs(rhs_value); + } + + rp def_expr = this->def_expr_; + + this->defxs_type_ = defexprstatetype::def_6; + return; + } + + constexpr const char * c_self_name = "define_xs::on_expr"; + const char * exp = get_expect_str(); + + this->illegal_input_on_expr(c_self_name, expr, exp, p_psm); + } + + void + define_xs::on_expr_with_semicolon(bp expr, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log(xtag("defxs_type", defxs_type_)); + + this->on_expr(expr, p_psm); + /* semicolon is allowed to terminate def expr */ + this->on_semicolon_token(token_type::semicolon(), p_psm); + } + + void + define_xs::on_symbol(const std::string & symbol_name, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log(xtag("defxs_type", defxs_type_), xtag("env_stack_size", p_psm->env_stack_size())); + + if (this->defxs_type_ == defexprstatetype::def_1) { + this->defxs_type_ = defexprstatetype::def_2; + this->def_expr_->assign_lhs_name(symbol_name); + + // if this is a genuine top-level define (i.e. nesting level = 0), + // then we need to upsert so we can refer to rhs later. + // + // In other contexts (e.g. body-of-lambda) will be rewriting + // { + // def y = foo(x,x); + // bar(y,y); + // } + // into something like + // { + // (lambda (y123) bar(y123,y123))(foo(x,x)); + // } + // + // This works in the body of lambda, because we don't evaluate anything + // until lambda definition is complete. + // + // For interactive top-level defs we want to evaluate as we go, + // so need incremental bindings. + + if (p_psm->env_stack_size() == 1) { + /* remember variable binding in lexical context, + * so we can refer to it later + */ + p_psm->upsert_var(this->def_expr_->lhs_variable()); + } + + return; + } + + constexpr const char * c_self_name = "define_xs::on_symbol"; + const char * exp = this->get_expect_str(); + + this->illegal_input_on_symbol(c_self_name, symbol_name, exp, p_psm); + } + + void + define_xs::on_typedescr(TypeDescr td, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log("defxs_type", defxs_type_); + + if (this->defxs_type_ == defexprstatetype::def_3) { + this->defxs_type_ = defexprstatetype::def_4; + this->cvt_expr_ = ConvertExprAccess::make(td /*dest_type*/, + nullptr /*source_expr*/); + /* note: establishes .def_expr_ valuetype */ + this->def_expr_->assign_rhs(this->cvt_expr_); + return; + } + + constexpr const char * c_self_name = "define_xs::on_symbol"; + const char * exp = this->get_expect_str(); + + this->illegal_input_on_type(c_self_name, td, exp, p_psm); + } + + void + define_xs::on_def_token(const token_type & tk, + parserstatemachine * p_psm) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + log && log("defxs_type", defxs_type_); + + if (this->defxs_type_ == defexprstatetype::def_0) { + this->defxs_type_ = defexprstatetype::def_1; + + expect_symbol_xs::start(p_psm); + return; + } + + constexpr const char * c_self_name = "define_xs::on_def_token"; + const char * exp = this->get_expect_str(); + + this->illegal_input_on_token(c_self_name, tk, exp, p_psm); + } + + void + define_xs::on_colon_token(const token_type & tk, + parserstatemachine * p_psm) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + log && log("defxs_type", defxs_type_); + + if (this->defxs_type_ == defexprstatetype::def_2) { + this->defxs_type_ = defexprstatetype::def_3; + + expect_type_xs::start(p_psm); + return; + } + + constexpr const char * c_self_name = "define_xs::on_symbol"; + const char * exp = this->get_expect_str(); + + this->illegal_input_on_token(c_self_name, tk, exp, p_psm); + } + + void + define_xs::on_semicolon_token(const token_type & tk, + parserstatemachine * p_psm) + { + /* def expr consumes semicolon */ + + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log("defxs_type", defxs_type_); + + if (this->defxs_type_ == defexprstatetype::def_6) { + rp def_expr = this->def_expr_; + + std::unique_ptr self = p_psm->pop_exprstate(); + + p_psm->top_exprstate().on_expr(def_expr, p_psm); + return; + } + + constexpr const char * c_self_name = "define_xs::on_symbol"; + const char * exp = this->get_expect_str(); + + this->illegal_input_on_token(c_self_name, tk, exp, p_psm); + } + + void + define_xs::on_singleassign_token(const token_type & tk, + parserstatemachine * p_psm) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + log && log("defxs_type", defxs_type_); + + if ((this->defxs_type_ == defexprstatetype::def_2) + || (this->defxs_type_ == defexprstatetype::def_4)) + { + this->defxs_type_ = defexprstatetype::def_5; + expect_expr_xs::start(p_psm); + return; + } + + constexpr const char * c_self_name = "define_xs::on_singleassign_token"; + const char * exp = get_expect_str(); + + this->illegal_input_on_token(c_self_name, tk, exp, p_psm); + } + + void + define_xs::on_rightparen_token(const token_type & tk, + parserstatemachine * p_psm) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + constexpr const char * c_self_name = "define_xs::on_rightparen"; + const char * exp = get_expect_str(); + + this->illegal_input_on_token(c_self_name, tk, exp, p_psm); + } + + void + define_xs::on_i64_token(const token_type & tk, + parserstatemachine * p_psm) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + constexpr const char * c_self_name = "define_xs::on_i64"; + const char * exp = get_expect_str(); + + this->illegal_input_on_token(c_self_name, tk, exp, p_psm); + } + + void + define_xs::on_f64_token(const token_type & tk, + parserstatemachine * p_psm) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + constexpr const char * c_self_name = "define_xs::on_f64"; + const char * exp = get_expect_str(); + + this->illegal_input_on_token(c_self_name, tk, exp, p_psm); + } + + void + define_xs::print(std::ostream & os) const { + os << ""; + } + + bool + define_xs::pretty_print(const xo::print::ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct(ppii, "define_xs", + refrtag("defxs_type", defxs_type_)); + } +#endif + + //////////////////////////////////////////////////////////////// + + DDefineSsm::DDefineSsm(DDefineExpr * def_expr) + : defstate_{defexprstatetype::def_0}, + def_expr_{def_expr} + {} + + DDefineSsm * + DDefineSsm::_make(DArena & mm, + DDefineExpr * def_expr) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DDefineSsm)); + + return new (mem) DDefineSsm(def_expr); + } + + obj + DDefineSsm::make(DArena & mm, + DDefineExpr * def_expr) + { + return obj(_make(mm, def_expr)); + } + + void + DDefineSsm::start(DArena & mm, + obj expr_mm, + ParserStateMachine * p_psm) + { + //scope log(XO_DEBUG(p_psm->debug_flag())); + + assert(p_psm->stack()); + + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + + DDefineExpr * def_expr = DDefineExpr::make_empty(expr_mm); + + auto define_ssm = DDefineSsm::make(mm, def_expr); + + p_psm->push_ssm(ckp, define_ssm); + + // note: triggers poly dispatch + p_psm->on_token(Token::def_token()); + } + + syntaxstatetype + DDefineSsm::ssm_type() const noexcept + { + return syntaxstatetype::defexpr; + } + + std::string_view + DDefineSsm::get_expect_str() const noexcept + { + /* + * def foo = 1 ; + * def foo : f64 = 1 ; + * ^ ^ ^ ^ ^ ^ ^ ^ + * | | | | | | | (done) + * | | | | | | def_6 + * | | | | | def_5:expect_rhs_expression + * | | | | def_4 + * | | | def_3:expect_type + * | | def_2 + * | def_1:expect_symbol + * expect_toplevel_expression_sequence + * + * note that we skip from def_2 -> def_5 if '=' instead of ':' + */ + switch (this->defstate_) { + case defexprstatetype::invalid: + case defexprstatetype::def_0: + case defexprstatetype::n_defexprstatetype: + assert(false); // impossible + return "impossible!?"; + case defexprstatetype::def_1: + return "symbol"; + case defexprstatetype::def_2: + return "singleassign|colon"; + case defexprstatetype::def_4: + return "singleassign"; + case defexprstatetype::def_3: + return "type"; + case defexprstatetype::def_5: + return "expression"; + case defexprstatetype::def_6: + return "semicolon"; + } + + return "?expect"; + } + + void + DDefineSsm::on_parsed_symbol(std::string_view sym_name, + ParserStateMachine * p_psm) + { + if (defstate_ == defexprstatetype::def_1) { + this->defstate_ = defexprstatetype::def_2; + + const DUniqueString * sym + = p_psm->intern_string(sym_name); + + def_expr_.data()->assign_lhs_name(sym); + + // if this is a genuine top-level define (i.e. nesting level = 0), + // then we need to upsert so we can refer to rhs later. + // + // In other contexts (e.g. body-of-lambda) will be rewriting + // { + // def y = foo(x,x); + // bar(y,y); + // } + // into something like + // { + // (lambda (y123) bar(y123,y123))(foo(x,x)); + // } + // + // This works in the body of lambda, because we don't evaluate anything + // until lambda definition is complete. + // + // For interactive top-level defs we want to evaluate as we go, + // so need incremental bindings. + + if (p_psm->is_at_toplevel()) { + /** remember variable binding in current lexical context **/ + p_psm->upsert_var(def_expr_.data()->lhs()); + } + + return; + } + + p_psm->illegal_input_on_symbol("DDefineSsm::on_parsed_symbol", + sym_name, + this->get_expect_str()); + } + + void + DDefineSsm::on_parsed_typedescr(TypeDescr td, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(true), xtag("td", td)); + + if (defstate_ == defexprstatetype::def_3) { + this->defstate_ = defexprstatetype::def_4; + + // note: not present in x0-reader/ version + def_expr_.assign_valuetype(td); + +#ifdef NOT_YET + this->cvt_expr_ = ConvertExpr::make(td, nullptr); + def_expr_->assign_rhs(cvt_expr_); +#endif + log && log("STUB: ConvertExpr not implemented, TypeDescr not captured"); + + return; + } + + p_psm->illegal_input_on_typedescr("DDefineSsm::on_parsed_typedescr", + td, + this->get_expect_str()); + } + + void + DDefineSsm::on_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag()), xtag("tk", tk)); + + switch (tk.tk_type()) { + case tokentype::tk_symbol: + this->on_symbol_token(tk, p_psm); + return; + + case tokentype::tk_def: + this->on_def_token(tk, p_psm); + return; + + case tokentype::tk_colon: + this->on_colon_token(tk, p_psm); + return; + + case tokentype::tk_singleassign: + this->on_singleassign_token(tk, p_psm); + return; + + case tokentype::tk_semicolon: + this->on_semicolon_token(tk, p_psm); + return; + + // all the not-yet handled cases + case tokentype::tk_invalid: + case tokentype::tk_string: + case tokentype::tk_f64: + case tokentype::tk_i64: + case tokentype::tk_bool: + case tokentype::tk_if: + case tokentype::tk_leftparen: + case tokentype::tk_rightparen: + case tokentype::tk_leftbracket: + case tokentype::tk_rightbracket: + case tokentype::tk_leftbrace: + case tokentype::tk_rightbrace: + case tokentype::tk_leftangle: + case tokentype::tk_rightangle: + case tokentype::tk_lessequal: + case tokentype::tk_greatequal: + case tokentype::tk_dot: + case tokentype::tk_comma: + case tokentype::tk_doublecolon: + case tokentype::tk_assign: + case tokentype::tk_yields: + case tokentype::tk_plus: + case tokentype::tk_minus: + case tokentype::tk_star: + case tokentype::tk_slash: + case tokentype::tk_cmpeq: + case tokentype::tk_cmpne: + case tokentype::tk_type: + case tokentype::tk_lambda: + case tokentype::tk_then: + case tokentype::tk_else: + case tokentype::tk_let: + case tokentype::tk_in: + case tokentype::tk_end: + case tokentype::N: + break; + } + + Super::on_token(tk, p_psm); + } + + void + DDefineSsm::on_symbol_token(const Token & tk, + ParserStateMachine * p_psm) + { + // note: + // in state def_1, DDefineSsm learns symbol via .on_parsed_symbol(). + // symbol token arriving here means encountered symbol while + // in some other, which can't happen for valid Schematika input + + Super::on_token(tk, p_psm); + } + + void + DDefineSsm::on_def_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (defstate_ == defexprstatetype::def_0) { + this->defstate_ = defexprstatetype::def_1; + + DExpectSymbolSsm::start(p_psm); + return; + } + + Super::on_token(tk, p_psm); + } + + void + DDefineSsm::on_colon_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (defstate_ == defexprstatetype::def_2) { + this->defstate_ = defexprstatetype::def_3; + + DExpectTypeSsm::start(p_psm); + + return; + } + + Super::on_token(tk, p_psm); + } + + void + DDefineSsm::on_singleassign_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag()), xtag("defstate", defstate_)); + + if ((defstate_ == defexprstatetype::def_2) + || (defstate_ == defexprstatetype::def_4)) + { + this->defstate_ = defexprstatetype::def_5; + + DExpectExprSsm::start(p_psm); + return; + } + + Super::on_token(tk, p_psm); + } + + void + DDefineSsm::on_semicolon_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (defstate_ == defexprstatetype::def_6) { + p_psm->pop_ssm(); + p_psm->on_parsed_expression_with_token(def_expr_, tk); + return; + } + + Super::on_token(tk, p_psm); + } + + void + DDefineSsm::on_parsed_expression(obj expr, + ParserStateMachine * p_psm) + { + if (defstate_ == defexprstatetype::def_5) + { + this->defstate_ = defexprstatetype::def_6; + + def_expr_.data()->assign_rhs(expr); + return; + } + + Super::on_parsed_expression(expr, p_psm); + } + + void + DDefineSsm::on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm) + { + /* must end with semicolon */ + + if (tk.tk_type() == tokentype::tk_semicolon) { + if (defstate_ == defexprstatetype::def_5) + { + this->defstate_ = defexprstatetype::def_6; + + def_expr_.data()->assign_rhs(expr); + + // completes this definition syntax + this->on_semicolon_token(tk, p_psm); + + return; + } + } + + // error in all other cases + Super::on_parsed_expression_with_token(expr, tk, p_psm); + } + + // ----- printable facet ----- + + bool + DDefineSsm::pretty(const ppindentinfo & ppii) const + { + auto expr + = FacetRegistry::instance().variant(def_expr_); + assert(expr.data()); + (void)expr; + + return ppii.pps()->pretty_struct(ppii, + "DDefineSsm", + refrtag("defstate", defstate_), + refrtag("expect", this->get_expect_str()), + refrtag("def_expr", expr)); + } + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DDefineSsm.cpp */ diff --git a/xo-reader2/src/reader2/DExpectExprSsm.cpp b/xo-reader2/src/reader2/DExpectExprSsm.cpp new file mode 100644 index 00000000..445ee76d --- /dev/null +++ b/xo-reader2/src/reader2/DExpectExprSsm.cpp @@ -0,0 +1,555 @@ +/** @file DExpectExprSsm.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "ExpectExprSsm.hpp" +#include "ParserStateMachine.hpp" +#include "SyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_DProgressSsm.hpp" +#include "DSequenceSsm.hpp" +#include "IfElseSsm.hpp" +#include "LambdaSsm.hpp" +#include "syntaxstatetype.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef NOT_YET +#include "exprstatestack.hpp" +#include "define_xs.hpp" +#include "lambda_xs.hpp" +#include "if_else_xs.hpp" +#include "paren_xs.hpp" +#include "sequence_xs.hpp" +#include "progress_xs.hpp" +#include "xo/expression/Lambda.hpp" +#include "xo/expression/Constant.hpp" +#include "xo/expression/pretty_expression.hpp" +#endif + +namespace xo { +#ifdef NOT_YET + using xo::scm::Constant; +#endif + using xo::scm::DFloat; + using xo::mm::AGCObject; + + using xo::reflect::typeseq; + using xo::facet::with_facet; + + namespace scm { + + DExpectExprSsm::DExpectExprSsm(bool allow_defs, + bool cxl_on_rightbrace) + : allow_defs_{allow_defs}, + cxl_on_rightbrace_{cxl_on_rightbrace} + { + } + + DExpectExprSsm * + DExpectExprSsm::_make(DArena & mm, + bool allow_defs, + bool cxl_on_rightbrace) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DExpectExprSsm)); + + return new (mem) DExpectExprSsm(allow_defs, + cxl_on_rightbrace); + } + + obj + DExpectExprSsm::make(DArena & mm, + bool allow_defs, + bool cxl_on_rightbrace) + { + return obj(_make(mm, allow_defs, cxl_on_rightbrace)); + } + + void + DExpectExprSsm::start(DArena & mm, + bool allow_defs, + bool cxl_on_rightbrace, + ParserStateMachine * p_psm) + { + DArena::Checkpoint ckp = mm.checkpoint(); + + auto ssm = DExpectExprSsm::make(mm, allow_defs, cxl_on_rightbrace); + + p_psm->push_ssm(ckp, ssm); + } + + void + DExpectExprSsm::start(ParserStateMachine * p_psm) + { + start(p_psm->parser_alloc(), + false /*!allow_defs*/, + false /*!cxl_on_rightbrace*/, + p_psm); + } + + syntaxstatetype + DExpectExprSsm::ssm_type() const noexcept + { + return syntaxstatetype::expect_rhs_expression; + } + + std::string_view + DExpectExprSsm::get_expect_str() const noexcept + { + if (allow_defs_) { + return "def|if|lambda|lparen|lbrace|literal|var"; + } else { + return "if|lambda|lparen|lbrace|literal|var"; + } + } + + void + DExpectExprSsm::on_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag()), xtag("tk", tk)); + + switch (tk.tk_type()) { + case tokentype::tk_leftparen: + this->on_leftparen_token(tk, p_psm); + return; + + case tokentype::tk_leftbrace: + this->on_leftbrace_token(tk, p_psm); + return; + + case tokentype::tk_symbol: + this->on_symbol_token(tk, p_psm); + return; + + case tokentype::tk_def: + this->on_def_token(tk, p_psm); + return; + + case tokentype::tk_string: + this->on_string_token(tk, p_psm); + return; + + case tokentype::tk_f64: + this->on_f64_token(tk, p_psm); + return; + + case tokentype::tk_i64: + this->on_i64_token(tk, p_psm); + return; + + case tokentype::tk_bool: + this->on_bool_token(tk, p_psm); + return; + + case tokentype::tk_if: + this->on_if_token(tk, p_psm); + return; + + case tokentype::tk_lambda: + this->on_lambda_token(tk, p_psm); + return; + + // all the not-yet handled cases + case tokentype::tk_invalid: + case tokentype::tk_singleassign: + case tokentype::tk_colon: + case tokentype::tk_semicolon: + case tokentype::tk_rightparen: + case tokentype::tk_leftbracket: + case tokentype::tk_rightbracket: + case tokentype::tk_rightbrace: + case tokentype::tk_leftangle: + case tokentype::tk_rightangle: + case tokentype::tk_lessequal: + case tokentype::tk_greatequal: + case tokentype::tk_dot: + case tokentype::tk_comma: + case tokentype::tk_doublecolon: + case tokentype::tk_assign: + case tokentype::tk_yields: + case tokentype::tk_plus: + case tokentype::tk_minus: + case tokentype::tk_star: + case tokentype::tk_slash: + case tokentype::tk_cmpeq: + case tokentype::tk_cmpne: + case tokentype::tk_type: + case tokentype::tk_then: + case tokentype::tk_else: + case tokentype::tk_let: + case tokentype::tk_in: + case tokentype::tk_end: + case tokentype::N: + break; + } + + Super::on_token(tk, p_psm); + } + + void + DExpectExprSsm::on_leftparen_token(const Token & tk, + ParserStateMachine * p_psm) + { + // need progress ssm here because this is allowed: + // + // if (foo) > 5 then ... + // + // Start progress ssm, delegate incoming token thereto + // + + DProgressSsm::start(p_psm->parser_alloc(), + p_psm); + p_psm->on_token(tk); + } + + void + DExpectExprSsm::on_leftbrace_token(const Token & tk, + ParserStateMachine * p_psm) + { + (void)tk; + + DSequenceSsm::start(p_psm); + } + + void + DExpectExprSsm::on_symbol_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log(xtag("tk", tk)); + + DVarRef * var = p_psm->lookup_varref(tk.text()); + + if (!var) { + p_psm->error_unbound_variable(ssm_classname(), + tk.text()); + } + + // examples of possible continuations from symbol foo + // foo ; // (1) foo is entire rvalue expression + // foo + ... // (2) foo begin operator expression + // foo(..); // (3) foo begin apply function + // + // + + DProgressSsm::start(p_psm->parser_alloc(), + obj(var), + p_psm); + } + +#ifdef NOT_YET + void + expect_expr_xs::on_symbol_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log(xtag("tk", tk)); + + constexpr const char * c_self_name = "expect_expr_xs::on_symbol_token"; + + /* various possibilities when looking for rhs expression: + * + * x := y // (1) + * x := f(a) // (2) + * x := f(a,b) // (3) + * + * need lookahead token following symbol to distinguish + * between (1) (symbol completes rhs expression) + * and {(2), (3)} (symbol is function call) + */ + + bp var = p_psm->lookup_var(tk.text()); + + if (!var) { + this->unknown_variable_error(c_self_name, tk, p_psm); + return; + } + + /* e.g. + * def pi = 3.14159265; + * def mypi = pi; + * ^ + * def pi2 = pi * 2; + * ^ + * def y = foo(pi2); + * ^ + */ + progress_xs::start(var.promote(), p_psm); + + #ifdef NOT_YET + p_stack->push_exprstate(exprstate(exprstatetype::expr_progress, + Variable::make(name, type))); +#endif + +#ifdef LATER + p_psm->pop_exprstate(); + p_psm->top_exprstate().on_symbol(tk.text(), + p_stack, p_emit_expr); +#endif + return; + } +#endif + +#ifdef NOT_YET + void + expect_expr_xs::on_def_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + if (allow_defs_) { + define_xs::start(p_psm); + } else { + exprstate::on_def_token(tk, p_psm); + } + } +#endif + + void + DExpectExprSsm::on_def_token(const Token & tk, + ParserStateMachine * p_psm) + { + Super::on_token(tk, p_psm); + } + + void + DExpectExprSsm::on_bool_token(const Token & tk, + ParserStateMachine * p_psm) + { + auto flag = DBoolean::box(p_psm->expr_alloc(), + tk.bool_value()); + + auto expr = DConstant::make(p_psm->expr_alloc(), flag); + + // DProgressSsm responsible for resolving cases like + // true; + // true && false; + + DProgressSsm::start(p_psm->parser_alloc(), + expr, + p_psm); + } + + void + DExpectExprSsm::on_f64_token(const Token & tk, + ParserStateMachine * p_psm) + { + auto f64o = DFloat::box(p_psm->expr_alloc(), + tk.f64_value()); + + auto expr = DConstant::make(p_psm->expr_alloc(), f64o); + + // DProgressSsm responsible for resolving cases like + // 1.9, + // 1.9; + // 1.9 + 2; + // 1.9 + 2 .. // could be followed by infix + // 1.9 + 2 * 3; + // 1.9 + 2 * 3 .. // could be followed by infix + // 1.9 * (2 + 3) + + DProgressSsm::start(p_psm->parser_alloc(), + expr, + p_psm); + } + + void + DExpectExprSsm::on_i64_token(const Token & tk, + ParserStateMachine * p_psm) + { + auto i64o = DInteger::box(p_psm->expr_alloc(), + tk.i64_value()); + + auto expr = DConstant::make(p_psm->expr_alloc(), i64o); + + // DProgressSsm responsible for resolving cases like + // 1, + // 1; + // 1 + 2; + // 1 + 2 .. // could be followed by infix + // 1 + 2 * 3; + // 1 + 2 * 3 .. // could be followed by infix + // 1 * (2 + 3) + + DProgressSsm::start(p_psm->parser_alloc(), + expr, + p_psm); + } + + void + DExpectExprSsm::on_string_token(const Token & tk, + ParserStateMachine * p_psm) + { + auto str = DString::from_str(p_psm->expr_alloc(), + tk.text()); + auto str_o = obj(str); + + auto expr = DConstant::make(p_psm->expr_alloc(), str_o); + + /* e.g. + * def msg = "hello, world"; + * \----tk----/ + * + * DProgressSsm responsible for operators that apply to string + * "foo"; + * "foo" <= "bar" + * "foo" + ", she said"; + */ + + DProgressSsm::start(p_psm->parser_alloc(), + expr, + p_psm); + } + + void + DExpectExprSsm::on_if_token(const Token & tk, + ParserStateMachine * p_psm) + { + (void)tk; + + DIfElseSsm::start(p_psm->parser_alloc(), + p_psm->expr_alloc(), + p_psm); + // TODO: should send if-token here + } + + void + DExpectExprSsm::on_lambda_token(const Token & tk, + ParserStateMachine * p_psm) + { + (void)tk; + + DLambdaSsm::start(p_psm); + } + + void + DExpectExprSsm::on_parsed_expression(obj expr, + ParserStateMachine * p_psm) + { + p_psm->pop_ssm(); + p_psm->on_parsed_expression(expr); + } + + void + DExpectExprSsm::on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm) + { + // expression (reported by nested ProgressSsm) + // completes this DExpectExprSsm's assignment + + p_psm->pop_ssm(); + p_psm->on_parsed_expression_with_token(expr, tk); + } + + bool + DExpectExprSsm::pretty(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct + (ppii, + "DExpectExprSsm", + refrtag("allow_defs", allow_defs_), + refrtag("cxl_on_rightbrace", cxl_on_rightbrace_), + refrtag("expect", this->get_expect_str()) + ); + } + +#ifdef NOT_YET + void + expect_expr_xs::on_if_token(const token_type & /*tk*/, + parserstatemachine * p_psm) + { + if_else_xs::start(p_psm); + } + + void + expect_expr_xs::on_leftparen_token(const token_type & /*tk*/, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + //constexpr const char * self_name = "exprstate::on_leftparen"; + + /* push lparen_0 to remember to look for subsequent rightparen. */ + paren_xs::start(p_psm); + } + + void + expect_expr_xs::on_rightbrace_token(const token_type & tk, + parserstatemachine * p_psm) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + if (cxl_on_rightbrace_) { + auto self = p_psm->pop_exprstate(); + + /* do not call .on_expr(), since '}' cancelled */ + + p_psm->on_rightbrace_token(tk); + } else { + exprstate::on_rightbrace_token(tk, p_psm); + } + } + + void + expect_expr_xs::on_expr(bp expr, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log(xtag("exstype", this->exs_type_), + xtag("expr", expr.promote())); + log && log("pop expect_expr_xs, forward to parent"); + + std::unique_ptr self = p_psm->pop_exprstate(); + + p_psm->on_expr(expr); + } /*on_expr*/ + + void + expect_expr_xs::on_expr_with_semicolon(bp expr, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log(xtag("exstype", this->exs_type_), + xtag("expr", expr.promote())); + log && log("pop expect_expr_xs, forward to parent"); + + std::unique_ptr self = p_psm->pop_exprstate(); + + p_psm->on_expr_with_semicolon(expr); + } /*on_expr_with_semicolon*/ + + void + expect_expr_xs::print(std::ostream & os) const { + os << ""; + } + + bool + expect_expr_xs::pretty_print(const xo::print::ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct(ppii, "expect_expr_xs", + refrtag("allow_defs", allow_defs_), + refrtag("cxl_on_rightbrace", cxl_on_rightbrace_)); + } +#endif + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DExpectExprSsm.cpp */ diff --git a/xo-reader2/src/reader2/DExpectFormalArgSsm.cpp b/xo-reader2/src/reader2/DExpectFormalArgSsm.cpp new file mode 100644 index 00000000..bbb9048e --- /dev/null +++ b/xo-reader2/src/reader2/DExpectFormalArgSsm.cpp @@ -0,0 +1,275 @@ +/** @file DExpectFormalArgSsm.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "DExpectFormalArgSsm.hpp" +#include "ssm/ISyntaxStateMachine_DExpectFormalArgSsm.hpp" +#include "DExpectSymbolSsm.hpp" +#include "ssm/ISyntaxStateMachine_DExpectSymbolSsm.hpp" +#include "DExpectTypeSsm.hpp" +#include "ssm/ISyntaxStateMachine_DExpectTypeSsm.hpp" + +#ifdef NOT_YET +#include "xo/expression/Variable.hpp" +#endif + +namespace xo { + using xo::scm::DVariable; + using xo::reflect::TypeDescr; + using xo::facet::typeseq; + + namespace scm { + const char * + formalstatetype_descr(formalstatetype x) { + switch (x) { + case formalstatetype::invalid: + case formalstatetype::n_formalstatetype: + return "?formalstatetype"; + case formalstatetype::formal_0: + return "formal_0"; + case formalstatetype::formal_1: + return "formal_1"; + case formalstatetype::formal_2: + return "formal_2"; + } + + return "???formalstatetype"; + } + + DExpectFormalArgSsm::DExpectFormalArgSsm() = default; + + obj + DExpectFormalArgSsm::make(DArena & mm) + { + return obj(_make(mm)); + } + + DExpectFormalArgSsm * + DExpectFormalArgSsm::_make(DArena & mm) + { + void * mem = mm.alloc(typeseq::id(), sizeof(DExpectFormalArgSsm)); + + return new (mem) DExpectFormalArgSsm(); + } + + void + DExpectFormalArgSsm::start(ParserStateMachine * p_psm) + { + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + + p_psm->push_ssm(ckp, DExpectFormalArgSsm::make(p_psm->parser_alloc())); + + DExpectSymbolSsm::start(p_psm); + } + + syntaxstatetype + DExpectFormalArgSsm::ssm_type() const noexcept { + return syntaxstatetype::expect_formal_arg; + } + + std::string_view + DExpectFormalArgSsm::get_expect_str() const noexcept + { + switch(fstate_) { + case formalstatetype::invalid: + case formalstatetype::n_formalstatetype: + break; + case formalstatetype::formal_0: + return "formal-name"; + case formalstatetype::formal_1: + return "colon|typename"; + case formalstatetype::formal_2: + return "typename"; + } + + return "?expect"; + } + + /** update state on incoming token @p tk, + * with overall parser state in @p p_psm + **/ + void + DExpectFormalArgSsm::on_token(const Token & tk, + ParserStateMachine * p_psm) + { + switch (tk.tk_type()) { + case tokentype::tk_colon: + this->on_colon_token(tk, p_psm); + return; + case tokentype::tk_rightparen: + this->on_rightparen_token(tk, p_psm); + return; + + // all the not-yet-handled cases + case tokentype::tk_leftparen: + case tokentype::tk_lambda: + case tokentype::tk_def: + case tokentype::tk_if: + case tokentype::tk_symbol: + case tokentype::tk_singleassign: + case tokentype::tk_string: + case tokentype::tk_f64: + case tokentype::tk_i64: + case tokentype::tk_bool: + case tokentype::tk_semicolon: + case tokentype::tk_invalid: + case tokentype::tk_leftbracket: + case tokentype::tk_rightbracket: + case tokentype::tk_leftbrace: + case tokentype::tk_rightbrace: + case tokentype::tk_leftangle: + case tokentype::tk_rightangle: + case tokentype::tk_lessequal: + case tokentype::tk_greatequal: + case tokentype::tk_dot: + case tokentype::tk_comma: + case tokentype::tk_doublecolon: + case tokentype::tk_assign: + case tokentype::tk_yields: + case tokentype::tk_plus: + case tokentype::tk_minus: + case tokentype::tk_star: + case tokentype::tk_slash: + case tokentype::tk_cmpeq: + case tokentype::tk_cmpne: + case tokentype::tk_type: + case tokentype::tk_then: + case tokentype::tk_else: + case tokentype::tk_let: + case tokentype::tk_in: + case tokentype::tk_end: + case tokentype::N: + break; + } + + Super::on_token(tk, p_psm); + } + + void + DExpectFormalArgSsm::on_colon_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (fstate_ == formalstatetype::formal_1) { + this->fstate_ = formalstatetype::formal_2; + + DExpectTypeSsm::start(p_psm); + + /* control reenters via DExpectFormalArgSsm::on_parsed_typedescr() */ + return; + } + + Super::on_token(tk, p_psm); + } + + void + DExpectFormalArgSsm::on_rightparen_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (fstate_ == formalstatetype::formal_1) { + // formal with no type annotation + + assert(name_); + + p_psm->pop_ssm(); + p_psm->on_parsed_formal_with_token(name_, nullptr, tk); + + return; + } + + Super::on_token(tk, p_psm); + } + + void + DExpectFormalArgSsm::on_parsed_symbol(std::string_view sym, + ParserStateMachine * p_psm) + { + if (fstate_ == formalstatetype::formal_0) { + // parsed symbol @c sym is stored in tokenizer memory; + // must be copied to storage with expression lifetime, + // hence call to intern_string() + + this->fstate_ = formalstatetype::formal_1; + this->name_ = p_psm->intern_string(sym); + return; + } + + Super::on_parsed_symbol(sym, p_psm); + } + + void + DExpectFormalArgSsm::on_parsed_typedescr(TypeDescr td, + ParserStateMachine * p_psm) + { + if (fstate_ == formalstatetype::formal_2) { + assert(name_); + + p_psm->pop_ssm(); + p_psm->on_parsed_formal(name_, td); + + return; + } + + Super::on_parsed_typedescr(td, p_psm); + } + +#ifdef NOT_YET + expect_formal_xs::expect_formal_xs() + : exprstate(exprstatetype::expect_formal) + {} + + void + expect_formal_xs::on_symbol(const std::string & symbol_name, + parserstatemachine * p_psm) + { + if (this->formalxs_type_ == formalstatetype::formal_0) { + this->formalxs_type_ = formalstatetype::formal_1; + this->result_.assign_name(symbol_name); + } else { + exprstate::on_symbol(symbol_name, p_psm); + } + } + + void + expect_formal_xs::on_typedescr(TypeDescr td, + parserstatemachine * p_psm) + { + if (this->formalxs_type_ == formalstatetype::formal_2) { + this->result_.assign_td(td); + + std::unique_ptr self = p_psm->pop_exprstate(); + + rp var = Variable::make(result_.name(), + result_.td()); + + p_psm->top_exprstate().on_formal(var, p_psm); + } else { + exprstate::on_typedescr(td, p_psm); + } + } +#endif + + bool + DExpectFormalArgSsm::pretty(const ppindentinfo & ppii) const { + if (name_) { + return ppii.pps()->pretty_struct + (ppii, + "DExpectFormalArgSsm", + refrtag("fstate", fstate_), + refrtag("expect", this->get_expect_str()), + refrtag("name", std::string_view(*name_))); + } else { + return ppii.pps()->pretty_struct + (ppii, + "DExpectFormalArgSsm", + refrtag("fstate", fstate_), + refrtag("expect", this->get_expect_str()) + ); + } + } + + } /*namespace scm*/ +} /*namespace xo*/ + + +/* end DExpectFormalArgSsm.cpp */ diff --git a/xo-reader2/src/reader2/DExpectFormalArglistSsm.cpp b/xo-reader2/src/reader2/DExpectFormalArglistSsm.cpp new file mode 100644 index 00000000..53dcf30c --- /dev/null +++ b/xo-reader2/src/reader2/DExpectFormalArglistSsm.cpp @@ -0,0 +1,371 @@ +/* @file DExpectFormalArglistSsm.cpp + * + * @author Roland Conybeare, Jan 2026 + */ + +#include "DExpectFormalArglistSsm.hpp" +#include "ssm/ISyntaxStateMachine_DExpectFormalArglistSsm.hpp" +#include "DExpectFormalArgSsm.hpp" +#include "ssm/ISyntaxStateMachine_DExpectFormalArgSsm.hpp" +#include +#include +#include +#include +#include +#include + +#ifdef NOT_YET +#include "parserstatemachine.hpp" +#include "exprstatestack.hpp" +#include "expect_formal_xs.hpp" +#include "expect_symbol_xs.hpp" +#include "xo/expression/Variable.hpp" +#include "xo/indentlog/print/vector.hpp" +#endif + +namespace xo { + using xo::print::APrintable; + using xo::print::ppstate; + using xo::print::ppindentinfo; + using xo::mm::AGCObject; + using xo::mm::AAllocator; + using xo::facet::FacetRegistry; + using xo::reflect::typeseq; + + namespace scm { + const char * + formalarglstatetype_descr(formalarglstatetype x) { + switch (x) { + case formalarglstatetype::invalid: + return "invalid"; + case formalarglstatetype::argl_0: + return "argl_0"; + case formalarglstatetype::argl_1a: + return "argl_1a"; + case formalarglstatetype::argl_1b: + return "argl_1b"; + case formalarglstatetype::n_formalarglstatetype: + break; + } + + return "?formalarglstatetype"; + } + + DExpectFormalArglistSsm::DExpectFormalArglistSsm(DArray * argl) : argl_{argl} + {} + + DExpectFormalArglistSsm * + DExpectFormalArglistSsm::_make(DArena & arena) + { + obj mm(&arena); + + /* out-of-order so argl follows ssm in arena, + * consistent with any subsequent arglist realloc. + * Not a load-bearing choice however + */ + + void * mem = arena.alloc(typeseq::id(), + sizeof(DExpectFormalArglistSsm)); + + + /* allocate room for 8 arguments (during parsing) + * will re-alloc to expand as needed + */ + DArray * argl = DArray::empty(mm, 8); + + return new (mem) DExpectFormalArglistSsm(argl); + } + + obj + DExpectFormalArglistSsm::make(DArena & arena) + { + obj retval(_make(arena)); + + return retval; + } + + void + DExpectFormalArglistSsm::start(ParserStateMachine * p_psm) + { + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + + p_psm->push_ssm(ckp, DExpectFormalArglistSsm::make(p_psm->parser_alloc())); + } + + syntaxstatetype + DExpectFormalArglistSsm::ssm_type() const noexcept { + return syntaxstatetype::expect_formal_arglist; + } + + std::string_view + DExpectFormalArglistSsm::get_expect_str() const { + switch (fastate_) { + case formalarglstatetype::invalid: + case formalarglstatetype::n_formalarglstatetype: + assert(false); // impossible + break; + case formalarglstatetype::argl_0: + return "leftparen"; + case formalarglstatetype::argl_1a: + return "formal-name"; + case formalarglstatetype::argl_1b: + return "comma|rightparen"; + } + + return "?expect"; + } + + void + DExpectFormalArglistSsm::on_token(const Token & tk, + ParserStateMachine * p_psm) + { + switch (tk.tk_type()) { + case tokentype::tk_leftparen: + this->on_leftparen_token(tk, p_psm); + return; + + case tokentype::tk_comma: + this->on_comma_token(tk, p_psm); + return; + + case tokentype::tk_rightparen: + this->on_rightparen_token(tk, p_psm); + return; + + // all the not-yet-handled cases + case tokentype::tk_lambda: + case tokentype::tk_def: + case tokentype::tk_if: + case tokentype::tk_symbol: + case tokentype::tk_colon: + case tokentype::tk_singleassign: + case tokentype::tk_string: + case tokentype::tk_f64: + case tokentype::tk_i64: + case tokentype::tk_bool: + case tokentype::tk_semicolon: + case tokentype::tk_invalid: + case tokentype::tk_leftbracket: + case tokentype::tk_rightbracket: + case tokentype::tk_leftbrace: + case tokentype::tk_rightbrace: + case tokentype::tk_leftangle: + case tokentype::tk_rightangle: + case tokentype::tk_lessequal: + case tokentype::tk_greatequal: + case tokentype::tk_dot: + case tokentype::tk_doublecolon: + case tokentype::tk_assign: + case tokentype::tk_yields: + case tokentype::tk_plus: + case tokentype::tk_minus: + case tokentype::tk_star: + case tokentype::tk_slash: + case tokentype::tk_cmpeq: + case tokentype::tk_cmpne: + case tokentype::tk_type: + case tokentype::tk_then: + case tokentype::tk_else: + case tokentype::tk_let: + case tokentype::tk_in: + case tokentype::tk_end: + case tokentype::N: + break; + } + + Super::on_token(tk, p_psm); + } + + + void + DExpectFormalArglistSsm::_accept_formal(obj expr_alloc, + DArena & parser_alloc, + const DUniqueString * param_name, + TypeDescr param_type) + { + /* note: param_type can be nullptr */ + TypeRef typeref + = TypeRef::dwim(TypeRef::prefix_type::from_chars("formal"), param_type); + + DVariable * var = DVariable::make(expr_alloc, + param_name, + typeref); + + // need AGCObject facet to use DArray here. + // May want to have gc feature that allows it to use + // FacetRegistry on memory that stores obj + // + // In this case doesn't matter since DExpectFormalArglistSsm not actually collected! + + obj var_o(var); + + if (argl_->size() == argl_->capacity()) { + // need to expand argl_ capacity. + // If DArena were to allow it (i.e. offer a realloc() feature, + // could do this in place since this SSM is at the top of the parser stack. + + obj mm(&parser_alloc); + DArray * argl_2x = DArray::empty(mm, 2 * argl_->capacity()); + + for (DArray::size_type i = 0, n = argl_->size(); i < n; ++i) { + // TODO: prefer non-bounds-checked access here + argl_2x->push_back(argl_->at(i)); + } + + // update in place + this->argl_ = argl_2x; + } + + this->argl_->push_back(var_o); + } + + void + DExpectFormalArglistSsm::on_parsed_formal(const DUniqueString * param_name, + TypeDescr param_type, + ParserStateMachine * p_psm) + { + if (fastate_ == formalarglstatetype::argl_1a) { + this->fastate_ = formalarglstatetype::argl_1b; + + this->_accept_formal(p_psm->expr_alloc(), + p_psm->parser_alloc(), + param_name, + param_type); + return; + } + + Super::on_parsed_formal(param_name, param_type, p_psm); + } + + void + DExpectFormalArglistSsm::on_parsed_formal_with_token(const DUniqueString * param_name, + TypeDescr param_type, + const Token & tk, + ParserStateMachine * p_psm) + { + if (fastate_ == formalarglstatetype::argl_1a) { + this->fastate_ = formalarglstatetype::argl_1b; + + this->_accept_formal(p_psm->expr_alloc(), + p_psm->parser_alloc(), + param_name, + param_type); + + this->on_token(tk, p_psm); + return; + } + + Super::on_parsed_formal_with_token(param_name, param_type, tk, p_psm); + } + + void + DExpectFormalArglistSsm::on_leftparen_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (fastate_ == formalarglstatetype::argl_0) { + this->fastate_ = formalarglstatetype::argl_1a; + + DExpectFormalArgSsm::start(p_psm); + return; + } + + Super::on_token(tk, p_psm); + } + + void + DExpectFormalArglistSsm::on_comma_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (fastate_ == formalarglstatetype::argl_1b) { + this->fastate_ = formalarglstatetype::argl_1a; + + DExpectFormalArgSsm::start(p_psm); + return; + } + + Super::on_token(tk, p_psm); + } + + void + DExpectFormalArglistSsm::on_rightparen_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (fastate_ == formalarglstatetype::argl_1b) { + DArray * args = argl_; + + p_psm->pop_ssm(); + p_psm->on_parsed_formal_arglist(args); + return; + } + + Super::on_token(tk, p_psm); + } + + bool + DExpectFormalArglistSsm::pretty(const ppindentinfo & ppii) const + { + ppstate * pps = ppii.pps(); + + if (ppii.upto()) { + if (!pps->print_upto("print_upto(xrefrtag("fastate", fastate_))) + return false; + + if (!pps->print_upto(xrefrtag("expect", this->get_expect_str()))) + return false; + + if (!pps->print_upto(xrefrtag("n_args", argl_->size()))) + return false; + + for (size_type i_arg = 0; i_arg < argl_->size(); ++i_arg) { + char buf[80]; + snprintf(buf, sizeof(buf), "arg[%u]", i_arg); + + auto arg_gco = argl_->at(i_arg); + obj arg_pr + = FacetRegistry::instance().try_variant(arg_gco); + + if (!pps->print_upto(xrefrtag(buf, arg_pr))) + return false; + } + + pps->write(">"); + + return true; + } else { + pps->write("newline_indent(ppii.ci1()); + pps->pretty(refrtag("fastate", fastate_)); + + pps->newline_indent(ppii.ci1()); + pps->pretty(refrtag("expect", this->get_expect_str())); + + pps->newline_indent(ppii.ci1()); + pps->pretty(refrtag("n_args", argl_->size())); + + for (size_type i_arg = 0, n_arg = argl_->size(); i_arg < n_arg; ++i_arg) { + char buf[80]; + snprintf(buf, sizeof(buf), "arg[%u]", i_arg); + + auto arg_gco = argl_->at(i_arg); + obj arg_pr + = FacetRegistry::instance().try_variant(arg_gco); + + pps->newline_indent(ppii.ci1()); + pps->pretty(refrtag(buf, arg_pr)); + } + + pps->write(">"); + + return false; + } + } + + } /*namespace scm*/ +} /*namespace xo*/ + + +/* end DExpectFormalArglistSsm.cpp */ diff --git a/xo-reader2/src/reader2/DExpectSymbolSsm.cpp b/xo-reader2/src/reader2/DExpectSymbolSsm.cpp new file mode 100644 index 00000000..8a750751 --- /dev/null +++ b/xo-reader2/src/reader2/DExpectSymbolSsm.cpp @@ -0,0 +1,148 @@ +/** @file DExpectSymbolSsm.cpp + * + * @author Roland Conybeare, Aug 2024 + **/ + +#include "DExpectSymbolSsm.hpp" +#include "ssm/ISyntaxStateMachine_DExpectSymbolSsm.hpp" +#include "SyntaxStateMachine.hpp" +#include "ParserStateMachine.hpp" +#include "syntaxstatetype.hpp" +#include +//#include + +namespace xo { + using xo::facet::with_facet; + using xo::facet::typeseq; + + namespace scm { + DExpectSymbolSsm::DExpectSymbolSsm() + {} + + DExpectSymbolSsm * + DExpectSymbolSsm::_make(DArena & mm) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DExpectSymbolSsm)); + + return new (mem) DExpectSymbolSsm(); + } + + obj + DExpectSymbolSsm::make(DArena & mm) + { + return obj(_make(mm)); + } + + void + DExpectSymbolSsm::start(ParserStateMachine * p_psm) + { + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + + auto ssm = DExpectSymbolSsm::make(p_psm->parser_alloc()); + + p_psm->push_ssm(ckp, ssm); + } + + syntaxstatetype + DExpectSymbolSsm::ssm_type() const noexcept + { + return syntaxstatetype::expect_symbol; + } + + std::string_view + DExpectSymbolSsm::get_expect_str() const noexcept + { + return "symbol"; + } + + void + DExpectSymbolSsm::on_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag()), xtag("tk", tk)); + + switch (tk.tk_type()) { + case tokentype::tk_symbol: + this->on_symbol_token(tk, p_psm); + return; + + // all the not-yet handled cases + case tokentype::tk_invalid: + case tokentype::tk_string: + case tokentype::tk_f64: + case tokentype::tk_i64: + case tokentype::tk_bool: + case tokentype::tk_def: + case tokentype::tk_if: + case tokentype::tk_singleassign: + case tokentype::tk_colon: + case tokentype::tk_semicolon: + case tokentype::tk_leftparen: + case tokentype::tk_rightparen: + case tokentype::tk_leftbracket: + case tokentype::tk_rightbracket: + case tokentype::tk_leftbrace: + case tokentype::tk_rightbrace: + case tokentype::tk_leftangle: + case tokentype::tk_rightangle: + case tokentype::tk_lessequal: + case tokentype::tk_greatequal: + case tokentype::tk_dot: + case tokentype::tk_comma: + case tokentype::tk_doublecolon: + case tokentype::tk_assign: + case tokentype::tk_yields: + case tokentype::tk_plus: + case tokentype::tk_minus: + case tokentype::tk_star: + case tokentype::tk_slash: + case tokentype::tk_cmpeq: + case tokentype::tk_cmpne: + case tokentype::tk_type: + case tokentype::tk_lambda: + case tokentype::tk_then: + case tokentype::tk_else: + case tokentype::tk_let: + case tokentype::tk_in: + case tokentype::tk_end: + case tokentype::N: + break; + } + + Super::on_token(tk, p_psm); + } + + void + DExpectSymbolSsm::on_symbol_token(const Token & tk, + ParserStateMachine * p_psm) + { +#ifdef NOT_YET + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag)); + + log && log(xtag("tk", tk)); + + assert(&p_psm->top_exprstate() == this); +#endif + + /* have to do pop first, before sending symbol to + * the o.g. symbol-requester + */ + p_psm->pop_ssm(); + p_psm->on_parsed_symbol(std::string_view(tk.text())); + } + + bool + DExpectSymbolSsm::pretty(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct + (ppii, + "DExpectSymbolSsm" + //refrtag("member", member_) + ); + } + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DExpectSymbolSsm.cpp */ diff --git a/xo-reader2/src/reader2/DExpectTypeSsm.cpp b/xo-reader2/src/reader2/DExpectTypeSsm.cpp new file mode 100644 index 00000000..b4fa8819 --- /dev/null +++ b/xo-reader2/src/reader2/DExpectTypeSsm.cpp @@ -0,0 +1,165 @@ +/** @file DExpectTypeSsm.cpp + * + * @author Roland Conybeare, Aug 2024 + **/ + +#include "DExpectTypeSsm.hpp" +#include "ssm/ISyntaxStateMachine_DExpectTypeSsm.hpp" +#include "SyntaxStateMachine.hpp" +#include +#include +#include +#include +#include + +namespace xo { + using xo::facet::with_facet; + using xo::reflect::Reflect; + using xo::reflect::TypeDescr; + using xo::reflect::typeseq; + + namespace scm { + DExpectTypeSsm::DExpectTypeSsm() + {} + + DExpectTypeSsm * + DExpectTypeSsm::_make(DArena & mm) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DArena)); + + return new (mem) DExpectTypeSsm(); + } + + obj + DExpectTypeSsm::make(DArena & mm) + { + return obj(_make(mm)); + } + + void + DExpectTypeSsm::start(ParserStateMachine * p_psm) + { + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + + auto ssm = DExpectTypeSsm::make(p_psm->parser_alloc()); + + p_psm->push_ssm(ckp, ssm); + } + + syntaxstatetype + DExpectTypeSsm::ssm_type() const noexcept + { + return syntaxstatetype::expect_type; + } + + std::string_view + DExpectTypeSsm::get_expect_str() const noexcept + { + return "typename"; + } + + void + DExpectTypeSsm::on_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag()), xtag("tk", tk)); + + switch (tk.tk_type()) { + case tokentype::tk_symbol: + this->on_symbol_token(tk, p_psm); + break; + + // all the not-yet handled cases + case tokentype::tk_invalid: + case tokentype::tk_def: + case tokentype::tk_if: + case tokentype::tk_f64: + case tokentype::tk_i64: + case tokentype::tk_bool: + case tokentype::tk_string: + case tokentype::tk_leftparen: + case tokentype::tk_rightparen: + case tokentype::tk_leftbracket: + case tokentype::tk_rightbracket: + case tokentype::tk_leftbrace: + case tokentype::tk_rightbrace: + case tokentype::tk_leftangle: + case tokentype::tk_rightangle: + case tokentype::tk_lessequal: + case tokentype::tk_greatequal: + case tokentype::tk_dot: + case tokentype::tk_comma: + case tokentype::tk_colon: + case tokentype::tk_semicolon: + case tokentype::tk_doublecolon: + case tokentype::tk_assign: + case tokentype::tk_singleassign: + case tokentype::tk_yields: + case tokentype::tk_plus: + case tokentype::tk_minus: + case tokentype::tk_star: + case tokentype::tk_slash: + case tokentype::tk_cmpeq: + case tokentype::tk_cmpne: + case tokentype::tk_type: + case tokentype::tk_lambda: + case tokentype::tk_then: + case tokentype::tk_else: + case tokentype::tk_let: + case tokentype::tk_in: + case tokentype::tk_end: + case tokentype::N: + p_psm->illegal_input_on_token("DExpectTypeSsm::on_token", + tk, + this->get_expect_str()); + break; + } + } + + void + DExpectTypeSsm::on_symbol_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + TypeDescr td = nullptr; + + /* TODO: replace with typetable lookup */ + + if (tk.text() == "bool") + td = Reflect::require(); + else if (tk.text() == "str") + td = Reflect::require(); + else if (tk.text() == "f64") + td = Reflect::require(); + else if(tk.text() == "f32") + td = Reflect::require(); + else if(tk.text() == "i16") + td = Reflect::require(); + else if(tk.text() == "i32") + td = Reflect::require(); + else if(tk.text() == "i64") + td = Reflect::require(); + + if (!td) { + Super::on_token(tk, p_psm); + return; + } + + p_psm->pop_ssm(); + p_psm->on_parsed_typedescr(td); + } + + bool + DExpectTypeSsm::pretty(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct + (ppii, + "DExpectTypeSsm"); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DExpectTypeSsm.cpp */ diff --git a/xo-reader2/src/reader2/DIfElseSsm.cpp b/xo-reader2/src/reader2/DIfElseSsm.cpp new file mode 100644 index 00000000..b7d150af --- /dev/null +++ b/xo-reader2/src/reader2/DIfElseSsm.cpp @@ -0,0 +1,512 @@ +/** @file DIfElseSsm.cpp + * + * @author Roland Conybeare, Jul 2025 + **/ + +#include "DIfElseSsm.hpp" +#include "ssm/ISyntaxStateMachine_DIfElseSsm.hpp" +#include "ssm/IPrintable_DDefineSsm.hpp" +#include "DExpectExprSsm.hpp" +#include +#include +#include +//#include "exprstatestack.hpp" +//#include "parserstatemachine.hpp" +//#include "expect_expr_xs.hpp" +//#include "xo/indentlog/print/ppdetail_atomic.hpp" + +namespace xo { + using xo::print::APrintable; + using xo::facet::FacetRegistry; + using xo::facet::with_facet; + using xo::reflect::typeseq; + + namespace scm { + // ----- ifexprstatetype ----- + + const char * + ifexprstatetype_descr(ifexprstatetype x) { + switch (x) { + case ifexprstatetype::invalid: return "invalid"; + case ifexprstatetype::if_0: return "if_0"; + case ifexprstatetype::if_1: return "if_1"; + case ifexprstatetype::if_2: return "if_2"; + case ifexprstatetype::if_3: return "if_3"; + case ifexprstatetype::if_4: return "if_4"; + case ifexprstatetype::if_5: return "if_5"; + case ifexprstatetype::if_6: return "if_6"; + case ifexprstatetype::N: break; + } + + return "ifexprstatetype?"; + } + + std::ostream & + operator<<(std::ostream & os, ifexprstatetype x) { + os << ifexprstatetype_descr(x); + return os; + } + + // ----- DIfElseSsm ----- + + DIfElseSsm::DIfElseSsm(DIfElseExpr * ifelse_expr) : ifstate_{ifexprstatetype::if_0}, + if_expr_{ifelse_expr} + {} + + DIfElseSsm * + DIfElseSsm::_make(DArena & mm, + DIfElseExpr * ifelse_expr) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DIfElseSsm)); + + return new (mem) DIfElseSsm(ifelse_expr); + } + + obj + DIfElseSsm::make(DArena & mm, + DIfElseExpr * ifelse_expr) + { + return obj(_make(mm, ifelse_expr)); + } + + void + DIfElseSsm::start(DArena & parser_mm, + obj expr_mm, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + DArena::Checkpoint ckp = parser_mm.checkpoint(); + + DIfElseExpr * if_expr = DIfElseExpr::_make_empty(expr_mm); + + auto ssm = DIfElseSsm::make(parser_mm, if_expr); + + p_psm->push_ssm(ckp, ssm); + + // note: triggers poly dispatch + p_psm->on_token(Token::if_token()); + } + + syntaxstatetype + DIfElseSsm::ssm_type() const noexcept + { + return syntaxstatetype::ifelseexpr; + } + + std::string_view + DIfElseSsm::get_expect_str() const noexcept + { + /** + * if test-expr then then-expr else else-expr ; + * ^ ^ ^ ^ ^ ^ ^ + * | | | | | | | + * | if_1 if_2 if_3 if_4 if_5 if_6 + * if_0 + * + * if_0 --on_if_token()--> if_1 + * if_1 --on_expr()--> if_2 + * if_2 --on_then_token()--> if_3 + * if_3 --on_expr()--> if_4 + * if_4 --on_else_token()--> if_5 + * --on_semicolon_token()--> (done) + * if_5 --on_expr()-->if_6 + * if_6 --on_semicolon_token()--> (done) + **/ + switch (this->ifstate_) { + case ifexprstatetype::invalid: + case ifexprstatetype::N: + assert(false); // unreachable + break; + case ifexprstatetype::if_0: + return "if"; + case ifexprstatetype::if_1: + return "expression"; + case ifexprstatetype::if_2: + return "then"; + case ifexprstatetype::if_3: + return "expression"; + case ifexprstatetype::if_4: + return "else|semicolon"; + case ifexprstatetype::if_5: + return "expression"; + case ifexprstatetype::if_6: + return "semicolon"; + } + + return "?expect"; + } + + void + DIfElseSsm::on_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag()), xtag("tk", tk)); + + switch (tk.tk_type()) { + case tokentype::tk_symbol: + case tokentype::tk_def: + break; + case tokentype::tk_if: + this->on_if_token(tk, p_psm); + return; + case tokentype::tk_then: + this->on_then_token(tk, p_psm); + return; + case tokentype::tk_else: + this->on_else_token(tk, p_psm); + return; + case tokentype::tk_semicolon: + this->on_semicolon_token(tk, p_psm); + return; + case tokentype::tk_colon: + case tokentype::tk_singleassign: + case tokentype::tk_string: + case tokentype::tk_f64: + case tokentype::tk_i64: + case tokentype::tk_bool: + case tokentype::tk_invalid: + case tokentype::tk_leftparen: + case tokentype::tk_rightparen: + case tokentype::tk_leftbracket: + case tokentype::tk_rightbracket: + case tokentype::tk_leftbrace: + case tokentype::tk_rightbrace: + case tokentype::tk_leftangle: + case tokentype::tk_rightangle: + case tokentype::tk_lessequal: + case tokentype::tk_greatequal: + case tokentype::tk_dot: + case tokentype::tk_comma: + case tokentype::tk_doublecolon: + case tokentype::tk_assign: + case tokentype::tk_yields: + case tokentype::tk_plus: + case tokentype::tk_minus: + case tokentype::tk_star: + case tokentype::tk_slash: + case tokentype::tk_cmpeq: + case tokentype::tk_cmpne: + case tokentype::tk_type: + case tokentype::tk_lambda: + case tokentype::tk_let: + case tokentype::tk_in: + case tokentype::tk_end: + case tokentype::N: + break; + } + + DSyntaxStateMachine::on_token(tk, p_psm); + } + + void + DIfElseSsm::on_if_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log("ifstate", ifstate_); + + if (ifstate_ == ifexprstatetype::if_0) { + this->ifstate_ = ifexprstatetype::if_1; + + DExpectExprSsm::start(p_psm); + return; + } + + DSyntaxStateMachine::on_token(tk, p_psm); + } + + void + DIfElseSsm::on_then_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log("ifstate", ifstate_); + + if (ifstate_ == ifexprstatetype::if_2) { + this->ifstate_ = ifexprstatetype::if_3; + + DExpectExprSsm::start(p_psm); + return; + } + + DSyntaxStateMachine::on_token(tk, p_psm); + } + + void + DIfElseSsm::on_else_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log("ifstate", ifstate_); + + if (ifstate_ == ifexprstatetype::if_4) { + this->ifstate_ = ifexprstatetype::if_5; + + DExpectExprSsm::start(p_psm); + return; + } + + DSyntaxStateMachine::on_token(tk, p_psm); + } + +#ifdef NOT_YET + void + if_else_xs::finish_and_continue(parserstatemachine * p_psm) + { + rp if_expr = this->if_expr_; + std::unique_ptr self = p_psm->pop_exprstate(); + + if (this->ifxs_type_ == ifexprstatetype::if_4) { + /* if no else-branch, then if-expr can't have valuetype */ + if_expr->assign_valuetype(nullptr); + } + + p_psm->top_exprstate().on_expr(if_expr, p_psm); + } +#endif + + void + DIfElseSsm::finish_and_continue(ParserStateMachine * p_psm) + { + p_psm->pop_ssm(); + + // rp if_expr = this->if_expr_; + // std::unique_ptr self = p_psm->pop_exprstate(); + + p_psm->on_parsed_expression(if_expr_); + } + +#ifdef NOT_YET + void + if_else_xs::on_rightbrace_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + this->finish_and_continue(p_psm); + p_psm->on_rightbrace_token(tk); + } + +#endif + + void + DIfElseSsm::on_semicolon_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log("ifstate", ifstate_); + + switch (ifstate_) { + case ifexprstatetype::invalid: + case ifexprstatetype::N: + // unreachable + assert(false); + break; + + case ifexprstatetype::if_0: + case ifexprstatetype::if_1: + case ifexprstatetype::if_2: + case ifexprstatetype::if_3: + case ifexprstatetype::if_5: + break; + case ifexprstatetype::if_4: + case ifexprstatetype::if_6: + this->finish_and_continue(p_psm); + return; + } + + DSyntaxStateMachine::on_token(tk, p_psm); + } + +#ifdef NOT_YET + void + if_else_xs::on_expr(bp expr, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log(xtag("ifxs_type", ifxs_type_)); + + switch (this->ifxs_type_) { + case ifexprstatetype::invalid: + case ifexprstatetype::if_0: + case ifexprstatetype::n_ifexprstatetype: + assert(false); // unreachable + return; + case ifexprstatetype::if_1: + if_expr_->assign_test(expr.promote()); + ifxs_type_ = ifexprstatetype::if_2; + return; + case ifexprstatetype::if_2: + /** error: expecting 'then' **/ + break; + case ifexprstatetype::if_3: + if_expr_->assign_when_true(expr.promote()); + ifxs_type_ = ifexprstatetype::if_4; + return; + case ifexprstatetype::if_4: + /** error: expecting 'else' or ';' **/ + break; + case ifexprstatetype::if_5: + if_expr_->assign_when_false(expr.promote()); + ifxs_type_ = ifexprstatetype::if_6; + return; + case ifexprstatetype::if_6: + /** error: expecting ';' **/ + break; + } + + constexpr const char* c_self_name = "if_else_xs::on_expr"; + const char * exp = get_expect_str(); + + this->illegal_input_on_expr(c_self_name, expr, exp, p_psm); + } + +#endif + + void + DIfElseSsm::on_parsed_expression(obj expr, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + log && log(xtag("ifstate", ifstate_)); + + // if (ifstate_ == ...) { .... return; } + + switch (ifstate_) { + case ifexprstatetype::invalid: + case ifexprstatetype::N: + assert(false); + break; + case ifexprstatetype::if_0: + // should be unreachable + break; + case ifexprstatetype::if_1: + if_expr_.data()->assign_test(expr); + this->ifstate_ = ifexprstatetype::if_2; + return; + case ifexprstatetype::if_2: + // error: expecting "then" token here + break; + case ifexprstatetype::if_3: + if_expr_.data()->assign_when_true(expr); + this->ifstate_ = ifexprstatetype::if_4; + return; + case ifexprstatetype::if_4: + // error: expecting "else" or ";" + break; + case ifexprstatetype::if_5: + if_expr_.data()->assign_when_false(expr); + this->ifstate_ = ifexprstatetype::if_6; + return; + case ifexprstatetype::if_6: + // error: expecting ";" + break; + } + + DSyntaxStateMachine::on_parsed_expression(expr, p_psm); + } + + void + DIfElseSsm::on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + // TODO: may consider allowing if-else to terminate on other particular tokens + // e.g. ')' + + switch (ifstate_) { + case ifexprstatetype::invalid: + case ifexprstatetype::N: + // impossible + assert(false); + break; + case ifexprstatetype::if_0: + // also unreachable + break; + case ifexprstatetype::if_1: + // only ok if tk-type is tk_then. + if (tk.tk_type() == tokentype::tk_then) { + // advance to if_2 -then-> if_3 + this->on_parsed_expression(expr, p_psm); + this->on_token(tk, p_psm); + return; + } + break; + case ifexprstatetype::if_2: + // illegal, not expecting expression + break; + case ifexprstatetype::if_3: + // incoming expr argument is sufficient to complete this if-else + // but may continue on else-token + if (tk.tk_type() == tokentype::tk_else) { + // advance to if_4 -else-> if_5 + this->on_parsed_expression(expr, p_psm); + this->on_token(tk, p_psm); + return; + } else if ((tk.tk_type() == tokentype::tk_semicolon) + || (tk.tk_type() == tokentype::tk_rightparen) + || (tk.tk_type() == tokentype::tk_rightbrace)) { + + this->on_parsed_expression(expr, p_psm); + p_psm->pop_ssm(); + p_psm->on_parsed_expression_with_token(if_expr_, tk); + return; + } + + break; + case ifexprstatetype::if_4: + // illegal, not expecting expression + break; + + case ifexprstatetype::if_5: + // incoming expr argument completes this if-else + // advance to if_6 + if ((tk.tk_type() == tokentype::tk_semicolon) + || (tk.tk_type() == tokentype::tk_rightparen) + || (tk.tk_type() == tokentype::tk_rightbrace)) + { + // attaches expr as else- branch + this->on_parsed_expression(expr, p_psm); + + p_psm->pop_ssm(); + p_psm->on_parsed_expression_with_token(if_expr_, tk); + return; + } + break; + + case ifexprstatetype::if_6: + // illegal, not expecting expression + break; + + } + + Super::on_parsed_expression_with_token(expr, tk, p_psm); + } + + bool + DIfElseSsm::pretty(const ppindentinfo & ppii) const + { + auto expr + = FacetRegistry::instance().variant(if_expr_); + assert(expr.data()); + (void)expr; + + return ppii.pps()->pretty_struct + (ppii, + "DIfElseSsm", + refrtag("ifstate", ifstate_), + refrtag("if_expr", expr)); + } + + } /*namespace scm*/ +} /*namespace xo*/ diff --git a/xo-reader2/src/reader2/DLambdaSsm.cpp b/xo-reader2/src/reader2/DLambdaSsm.cpp new file mode 100644 index 00000000..6308ae08 --- /dev/null +++ b/xo-reader2/src/reader2/DLambdaSsm.cpp @@ -0,0 +1,486 @@ +/** @file DLambdaSsm.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "DLambdaSsm.hpp" +#include "ssm/ISyntaxStateMachine_DLambdaSsm.hpp" +#include "DExpectFormalArglistSsm.hpp" +#include "ssm/ISyntaxStateMachine_DExpectFormalArglistSsm.hpp" +#include "DExpectTypeSsm.hpp" +#include "DExpectExprSsm.hpp" +#include "ParserStateMachine.hpp" +#include "syntaxstatetype.hpp" +#include +#include +#include +//#include +#include +#include +#include + +#ifdef NOT_YET +#include "define_xs.hpp" +#include "parserstatemachine.hpp" +#include "exprstatestack.hpp" +#include "expect_formal_arglist_xs.hpp" +#include "expect_expr_xs.hpp" +#include "expect_type_xs.hpp" +#include "pretty_expression.hpp" +#include "pretty_variable.hpp" +#include "xo/expression/Lambda.hpp" +#endif + +namespace xo { + using xo::print::APrintable; + using xo::mm::AAllocator; + using xo::mm::AGCObject; + using xo::facet::FacetRegistry; + using xo::reflect::typeseq; + + namespace scm { + const char * + lambdastatetype_descr(lambdastatetype x) { + switch(x) { + case lambdastatetype::invalid: return "invalid"; + case lambdastatetype::lm_0: return "lm_0"; + case lambdastatetype::lm_1: return "lm_1"; + case lambdastatetype::lm_2: return "lm_2"; + case lambdastatetype::lm_3: return "lm_3"; + case lambdastatetype::lm_4: return "lm_4"; + case lambdastatetype::lm_5: return "lm_5"; + default: break; + } + + return "???lambdastatetype"; + } + + // ----- lambda_xs - ---- + + DLambdaSsm::DLambdaSsm() + {} + + obj + DLambdaSsm::make(DArena & parser_mm) + { + return obj(_make(parser_mm)); + } + + DLambdaSsm * + DLambdaSsm::_make(DArena & parser_mm) + { + void * mem = parser_mm.alloc(typeseq::id(), + sizeof(DLambdaSsm)); + + return new (mem) DLambdaSsm(); + } + + void + DLambdaSsm::start(ParserStateMachine * p_psm) + { + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + + p_psm->push_ssm(ckp, DLambdaSsm::make(p_psm->parser_alloc())); + p_psm->on_token(Token::lambda_token()); + } + + syntaxstatetype + DLambdaSsm::ssm_type() const noexcept + { + return syntaxstatetype::lambdaexpr; + } + + std::string_view + DLambdaSsm::get_expect_str() const noexcept + { + /* + * lambda (x : f64) -> f64 { ... } ; + * ^ ^ ^ ^ ^ ^ + * | | | | | lm_5 + * | | | | lm_4:expect_expression + * | | | lm_3 + * | | lm_2 + * | lm_1: + * expect_expression + */ + switch (this->lmstate_) { + case lambdastatetype::invalid: + case lambdastatetype::n_lambdastatetype: + assert(false); // impossible + break; + case lambdastatetype::lm_0: + return "lambda"; + case lambdastatetype::lm_1: + return "lambda-params"; + case lambdastatetype::lm_2: + return "yields|lambda-body"; + case lambdastatetype::lm_3: + return "type"; + case lambdastatetype::lm_4: + return "lambda-body"; + case lambdastatetype::lm_5: + return "semicolon"; + } + + return "?expect"; + } + + void + DLambdaSsm::on_token(const Token & tk, + ParserStateMachine * p_psm) + { + switch (tk.tk_type()) { + case tokentype::tk_lambda: + this->on_lambda_token(tk, p_psm); + return; + + case tokentype::tk_yields: + this->on_yields_token(tk, p_psm); + return; + + case tokentype::tk_leftbrace: + this->on_leftbrace_token(tk, p_psm); + return; + + // all the not-yet-handled cases + case tokentype::tk_def: + case tokentype::tk_if: + case tokentype::tk_symbol: + case tokentype::tk_colon: + case tokentype::tk_singleassign: + case tokentype::tk_string: + case tokentype::tk_f64: + case tokentype::tk_i64: + case tokentype::tk_bool: + case tokentype::tk_semicolon: + case tokentype::tk_invalid: + case tokentype::tk_leftparen: + case tokentype::tk_rightparen: + case tokentype::tk_leftbracket: + case tokentype::tk_rightbracket: + case tokentype::tk_rightbrace: + case tokentype::tk_leftangle: + case tokentype::tk_rightangle: + case tokentype::tk_lessequal: + case tokentype::tk_greatequal: + case tokentype::tk_dot: + case tokentype::tk_comma: + case tokentype::tk_doublecolon: + case tokentype::tk_assign: + case tokentype::tk_plus: + case tokentype::tk_minus: + case tokentype::tk_star: + case tokentype::tk_slash: + case tokentype::tk_cmpeq: + case tokentype::tk_cmpne: + case tokentype::tk_type: + case tokentype::tk_then: + case tokentype::tk_else: + case tokentype::tk_let: + case tokentype::tk_in: + case tokentype::tk_end: + case tokentype::N: + break; + } + + Super::on_token(tk, p_psm); + } + + void + DLambdaSsm::on_lambda_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (lmstate_ == lambdastatetype::lm_0) { + this->lmstate_ = lambdastatetype::lm_1; + + DExpectFormalArglistSsm::start(p_psm); + + return; + } + + Super::on_token(tk, p_psm); + } + + void + DLambdaSsm::on_yields_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (lmstate_ == lambdastatetype::lm_2) { + this->lmstate_ = lambdastatetype::lm_3; + + DExpectTypeSsm::start(p_psm); + + /* control reenters via .on_parsed_typedescr() */ + return; + } + + Super::on_token(tk, p_psm); + } + + void + DLambdaSsm::on_leftbrace_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (lmstate_ == lambdastatetype::lm_2) { + // control here when leftbrace immediately follows + // formal param list. + // Otherwise leftbrace arrives in DExpectExprSsm + // pushed via on_parsed_typedescr() + + this->lmstate_ = lambdastatetype::lm_4; + + DExpectExprSsm::start(p_psm); + // precharge ssm for body with leftbrace + p_psm->on_token(Token::leftbrace_token()); + return; + } + + Super::on_token(tk, p_psm); + } + + void + DLambdaSsm::on_parsed_typedescr(TypeDescr td, + ParserStateMachine * p_psm) + { + if (lmstate_ == lambdastatetype::lm_3) { + this->lmstate_ = lambdastatetype::lm_4; + this->explicit_return_td_ = td; + this->lambda_td_ = DLambdaExpr::assemble_lambda_td(local_symtab_, td); + + DExpectExprSsm::start(p_psm); + return; + } + + Super::on_parsed_typedescr(td, p_psm); + } + +#ifdef NOT_YET + void + lambda_xs::on_expr_with_semicolon(bp expr, + parserstatemachine * p_psm) + { + this->on_expr(expr, p_psm); + this->on_semicolon_token(token_type::semicolon(), p_psm); + } + + void + lambda_xs::on_leftbrace_token(const token_type & tk, + parserstatemachine * p_psm) + { + constexpr const char * c_self_name = "lambda_xs::on_leftbrace_token"; + + if (lmxs_type_ == lambdastatetype::lm_2) + this->lmxs_type_ = lambdastatetype::lm_4; + + if (lmxs_type_ == lambdastatetype::lm_4) { + expect_expr_xs::start(p_psm); + /* want { to start expr sequence, that finishes on matching } */ + p_psm->on_leftbrace_token(token_type::leftbrace()); + } else { + this->illegal_input_on_token(c_self_name, tk, this->get_expect_str(), p_psm); + } + } +#endif + + void + DLambdaSsm::on_parsed_formal_arglist(DArray * arglist, + ParserStateMachine * p_psm) + { + if (lmstate_ == lambdastatetype::lm_1) { + this->lmstate_ = lambdastatetype::lm_2; + /// something with top env frame ? + + /// TODO: arena-friendly non-gc-aware vector; + // use instead of DArray for arglist. + // something like DTypedArray + + /// create LocalSymtab from arglist + + DLocalSymtab * symtab + = DLocalSymtab::_make_empty(p_psm->expr_alloc(), + p_psm->local_symtab(), + arglist->size()); + assert(symtab); + + for (DArray::size_type i = 0, n = arglist->size(); i < n; ++i) { + obj param = arglist->at(i); + + // TODO: + // sad! runtime poly conversion from obj + // We need this because of (suboptimally) using DArray to store arglist + + obj param_expr + = FacetRegistry::instance().variant(param); + obj param_var + = obj::from(param_expr); + + assert(param_expr.data()); + assert(param_var.data()); + + Binding b = symtab->append_var(p_psm->expr_alloc(), + param_var.data()->name(), + param_var.data()->typeref()); + + assert(b.is_local()); + + this->local_symtab_ = symtab; + } + + // stash env frame: records local variables while we handle lambda body + + p_psm->push_local_symtab(symtab); + + // control reenters via .on_colon_token() / .on_leftbrace_token() + + return; + } + + Super::on_parsed_formal_arglist(arglist, p_psm); +#ifdef OBSOLETE + p_psm->illegal_parsed_formal_arglist("DLambdaSsm::on_parsed_formal_arglist", + arglist, + this->get_expect_str()); +#endif + } + + void + DLambdaSsm::on_parsed_expression(obj expr, + ParserStateMachine * p_psm) + { + if (lmstate_ == lambdastatetype::lm_4) { + this->lmstate_ = lambdastatetype::lm_5; + this->body_ = expr; + + // assemble lambda + + auto prefix = TypeRef::prefix_type::from_chars("lm"); + TypeRef tref = TypeRef::dwim(prefix, nullptr); + + const DUniqueString * name = p_psm->gensym("lambda"); + + auto lm_expr = obj + (DLambdaExpr::make(p_psm->expr_alloc(), + tref, + name, + local_symtab_, + body_)); + + p_psm->pop_ssm(); // this lambda + p_psm->on_parsed_expression(lm_expr); + return; + } + + Super::on_parsed_expression(expr, p_psm); + } + + void + DLambdaSsm::on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm) + { + Super::on_parsed_expression_with_token(expr, tk, p_psm); + } + +#ifdef NOT_YET + void + lambda_xs::on_expr(bp expr, + parserstatemachine * p_psm) + { + constexpr const char * c_self_name = "lambda_xs::on_expr"; + + if (lmxs_type_ == lambdastatetype::lm_4) { + this->lmxs_type_ = lambdastatetype::lm_5; + this->body_ = expr.promote(); + } else { + this->illegal_input_on_expr(c_self_name, expr, this->get_expect_str(), p_psm); + } + } + + void + lambda_xs::on_semicolon_token(const token_type & tk, + parserstatemachine * p_psm) + { + if (lmxs_type_ == lambdastatetype::lm_5) { + /* done! */ + + std::unique_ptr self = p_psm->pop_exprstate(); + + std::string name = Variable::gensym("lambda"); + + /* top env frame recorded arguments to this lambda */ + p_psm->pop_envframe(); + + rp lm; + + /* TODO: unify explicit_return_td_ with body_ */ + + if (lambda_td_) { + lm = Lambda::make(name, lambda_td_, local_env_, body_); + } else { + lm = Lambda::make_from_env(name, local_env_, + explicit_return_td_, body_); + } + + p_psm->top_exprstate().on_expr(lm, p_psm); + p_psm->top_exprstate().on_semicolon_token(tk, p_psm); + + return; + } + + exprstate::on_semicolon_token(tk, p_psm); + } + + void + lambda_xs::on_f64_token(const token_type & tk, + parserstatemachine * p_psm) + { + constexpr const char * c_self_name = "lambda_xs::on_f64_token"; + + /* f64 literal can begin lambda body, otherwise illegal. + * for example: + * def foo = lambda (x: bool) 3.14; + */ + if (lmxs_type_ == lambdastatetype::lm_2) { + /* omitting return type. + * omitting left brace. + */ + this->lmxs_type_ = lambdastatetype::lm_4; + + expect_expr_xs::start(p_psm); + p_psm->on_f64_token(tk); + } else { + this->illegal_input_on_token(c_self_name, tk, this->get_expect_str(), p_psm); + } + } + + // TODO: on_i64_token, on_bool token + +#endif + + bool + DLambdaSsm::pretty(const ppindentinfo & ppii) const + { + obj body + = FacetRegistry::instance().try_variant(body_); + + if (body) { + return ppii.pps()->pretty_struct + (ppii, + "DLambdaSsm", + refrtag("lmstate", lmstate_), + refrtag("expect", this->get_expect_str()), + refrtag("body", body)); + } else { + return ppii.pps()->pretty_struct + (ppii, + "DLambdaSsm", + refrtag("lmstate", lmstate_), + refrtag("expect", this->get_expect_str())); + } + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DLambdaSsm.cpp */ diff --git a/xo-reader2/src/reader2/DParenSsm.cpp b/xo-reader2/src/reader2/DParenSsm.cpp new file mode 100644 index 00000000..b89dec52 --- /dev/null +++ b/xo-reader2/src/reader2/DParenSsm.cpp @@ -0,0 +1,463 @@ +/** @file DParenSsm.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "ParenSsm.hpp" +#include "ExpectExprSsm.hpp" +#include "syntaxstatetype.hpp" +#include + +namespace xo { + using xo::facet::with_facet; + using xo::facet::typeseq; + + namespace scm { + + extern const char * + parenexprstatetype_descr(parenexprstatetype x) + { + switch(x) { + case parenexprstatetype::invalid: return "invalid"; + case parenexprstatetype::lparen_0: return "lparen_0"; + case parenexprstatetype::lparen_1: return "lparen_1"; + case parenexprstatetype::lparen_2: return "lparen_2"; + case parenexprstatetype::N: break; + } + + return "???parenexprstatetype"; + } + + std::ostream & + operator<<(std::ostream & os, parenexprstatetype x) { + os << parenexprstatetype_descr(x); + return os; + } + + DParenSsm::DParenSsm() + : parenstate_(parenexprstatetype::lparen_0), + expr_{} + {} + + DParenSsm * + DParenSsm::_make(DArena & mm) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DParenSsm)); + + return new (mem) DParenSsm(); + } + + obj + DParenSsm::make(DArena & mm) + { + return obj(_make(mm)); + } + + void + DParenSsm::start(ParserStateMachine * p_psm) + { + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + + auto paren_ssm = DParenSsm::make(p_psm->parser_alloc()); + + p_psm->push_ssm(ckp, paren_ssm); + } + + syntaxstatetype + DParenSsm::ssm_type() const noexcept + { + return syntaxstatetype::paren; + } + + std::string_view + DParenSsm::get_expect_str() const noexcept + { + switch (this->parenstate_) { + case parenexprstatetype::invalid: + case parenexprstatetype::N: + break; + case parenexprstatetype::lparen_0: return "leftparen"; + case parenexprstatetype::lparen_1: return "expression"; + case parenexprstatetype::lparen_2: return "rightparen"; + } + + return "???parenexprstatetype"; + } + + void + DParenSsm::on_token(const Token & tk, + ParserStateMachine * p_psm) + { + switch (tk.tk_type()) { + + case tokentype::tk_leftparen: + this->on_leftparen_token(tk, p_psm); + return; + + case tokentype::tk_rightparen: + this->on_rightparen_token(tk, p_psm); + return; + + // all the not-yet handled cases + case tokentype::tk_symbol: + case tokentype::tk_def: + case tokentype::tk_colon: + case tokentype::tk_singleassign: + case tokentype::tk_semicolon: + case tokentype::tk_invalid: + case tokentype::tk_string: + case tokentype::tk_f64: + case tokentype::tk_i64: + case tokentype::tk_bool: + case tokentype::tk_if: + case tokentype::tk_leftbracket: + case tokentype::tk_rightbracket: + case tokentype::tk_leftbrace: + case tokentype::tk_rightbrace: + case tokentype::tk_leftangle: + case tokentype::tk_rightangle: + case tokentype::tk_lessequal: + case tokentype::tk_greatequal: + case tokentype::tk_dot: + case tokentype::tk_comma: + case tokentype::tk_doublecolon: + case tokentype::tk_assign: + case tokentype::tk_yields: + case tokentype::tk_plus: + case tokentype::tk_minus: + case tokentype::tk_star: + case tokentype::tk_slash: + case tokentype::tk_cmpeq: + case tokentype::tk_cmpne: + case tokentype::tk_type: + case tokentype::tk_lambda: + case tokentype::tk_then: + case tokentype::tk_else: + case tokentype::tk_let: + case tokentype::tk_in: + case tokentype::tk_end: + case tokentype::N: + break; + } + + Super::on_token(tk, p_psm); + } + + void + DParenSsm::on_leftparen_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (parenstate_ == parenexprstatetype::lparen_0) { + this->parenstate_ = parenexprstatetype::lparen_1; + + /** 1. allow_defs=false not allowing definitions immediately + * within a parenthesized expression. + * e.g. + * (def y : i64 = 4; x + y) // nope + * 2. cxl_on_rightparen=false expression _must_ be followed + * by rightparen. empty parentheses '()' + * do not denote anything, in expression context + **/ + DExpectExprSsm::start(p_psm->parser_alloc(), + false /*!allow_defs*/, + false /*cx_on_rightbrace*/, + p_psm); + + return; + } + + Super::on_token(tk, p_psm); + } + +#ifdef OBSOLETE + void + paren_xs::start(parserstatemachine * p_psm) + { + p_psm->push_exprstate(paren_xs::make()); + expect_expr_xs::start(p_psm); + } + + bool + paren_xs::admits_rightparen() const { + switch (parenxs_type_) { + case parenexprstatetype::lparen_0: + /* unreachable */ + assert(false); + return false; + + case parenexprstatetype::lparen_1: + return true; + + case parenexprstatetype::invalid: + case parenexprstatetype::n_parenexprstatetype: + /* unreachable */ + assert(false); + return false; + } + + return false; + } + + bool + paren_xs::admits_f64() const { + switch (parenxs_type_) { + case parenexprstatetype::lparen_0: + return true; + + case parenexprstatetype::lparen_1: + return false; + + case parenexprstatetype::invalid: + case parenexprstatetype::n_parenexprstatetype: + /* unreachable */ + assert(false); + return false; + } + + return false; + } + + void + paren_xs::on_def_token(const token_type & tk, + parserstatemachine * /*p_psm*/) + { + constexpr const char * c_self_name = "paren_xs::on_def"; + + this->illegal_input_error(c_self_name, tk); + } + + void + paren_xs::on_symbol_token(const token_type & /*tk*/, + parserstatemachine * p_psm) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + log && log(xtag("exstype", p_psm->top_exprstate().exs_type())); + + //constexpr const char * self_name = "paren_xs::on_symbol"; + + /* TODO: lparen_0: treat as variable reference */ + + assert(false); + } + + void + paren_xs::on_typedescr(TypeDescr /*td*/, + parserstatemachine * /*p_psm*/) + { + assert(false); + return; + } + + void + paren_xs::on_colon_token(const token_type & tk, + parserstatemachine * /*p_psm*/) + { + constexpr const char * c_self_name = "paren_xs::on_colon"; + + this->illegal_input_error(c_self_name, tk); + } + + void + paren_xs::on_semicolon_token(const token_type & tk, + parserstatemachine * /*p_psm*/) + { + constexpr const char * c_self_name = "paren_xs::on_semicolon"; + + this->illegal_input_error(c_self_name, tk); + } + + void + paren_xs::on_singleassign_token(const token_type & tk, + parserstatemachine * /*p_psm*/) + { + constexpr const char * c_self_name = "paren_xs::on_singleassign"; + + this->illegal_input_error(c_self_name, tk); + } + + void + paren_xs::on_leftparen_token(const token_type & tk, + parserstatemachine * /*p_psm*/) + { + constexpr const char * c_self_name = "paren_xs::on_leftparen"; + + this->illegal_input_error(c_self_name, tk); + } +#endif + + void + DParenSsm::on_rightparen_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (this->parenstate_ == parenexprstatetype::lparen_2) { + // parenthesized expression successfully parsed + + p_psm->pop_ssm(); + p_psm->on_parsed_expression(this->expr_); + return; + } + + Super::on_token(tk, p_psm); + } + +#ifdef NOT_YET + void + paren_xs::on_rightparen_token(const token_type & tk, + parserstatemachine * p_psm) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + constexpr const char * c_self_name = "paren_xs::on_rightparen"; + + if (!this->admits_rightparen()) + { + this->illegal_input_error(c_self_name, tk); + } + + if (this->parenxs_type_ == parenexprstatetype::lparen_1) { + rp expr = this->gen_expr_; + + std::unique_ptr self = p_psm->pop_exprstate(); + + p_psm->top_exprstate().on_expr(expr, p_psm); + } + } + + void + paren_xs::on_i64_token(const token_type & tk, + parserstatemachine * /*p_psm*/) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + constexpr const char * c_self_name = "paren_xs::on_i64"; + + this->illegal_input_error(c_self_name, tk); + } + + void + paren_xs::on_f64_token(const token_type & tk, + parserstatemachine * /*p_psm*/) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + constexpr const char * c_self_name = "paren_xs::on_f64"; + + this->illegal_input_error(c_self_name, tk); + } +#endif + + void + DParenSsm::on_parsed_expression(obj expr, + ParserStateMachine * p_psm) + { + if (parenstate_ == parenexprstatetype::lparen_1) { + this->parenstate_ = parenexprstatetype::lparen_2; + this->expr_ = expr; + + return; + } + + Super::on_parsed_expression(expr, p_psm); + } + + void + DParenSsm::on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm) + { + if (parenstate_ == parenexprstatetype::lparen_1) { + this->parenstate_ = parenexprstatetype::lparen_2; + this->expr_ = expr; + + this->on_token(tk, p_psm); + + return; + } + + Super::on_parsed_expression(expr, p_psm); + } + +#ifdef NOT_YET + void + paren_xs::on_expr(bp expr, + parserstatemachine * p_psm) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + log && log(xtag("exstype", this->exs_type_), + xtag("expr", expr)); + + switch (this->parenxs_type_) { + case parenexprstatetype::lparen_0: { + this->parenxs_type_ = parenexprstatetype::lparen_1; /* wants on_rightparen */ + progress_xs::start(expr.promote(), p_psm); + + return; + } + + case parenexprstatetype::lparen_1: { + this->gen_expr_ = expr.promote(); + + /* expect immediate incoming call, this time to on_rightparen() */ + return; + } + + default: + /* unreachable */ + assert(false); + return; + } + } /*on_expr*/ + + void + paren_xs::on_symbol(const std::string & /*symbol_name*/, + parserstatemachine * /*p_psm*/) + { + switch(this->parenxs_type_) { + case parenexprstatetype::lparen_0: + case parenexprstatetype::lparen_1: + /* NOT IMPLEMENTED */ + assert(false); + return; + + default: + /* unreachable */ + assert(false); + return; + } + } + + void + paren_xs::print(std::ostream & os) const { + os << ""; + } +#endif + + bool + DParenSsm::pretty(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct(ppii, + "DParenSsm", + refrtag("parenstate", parenstate_), + refrtag("expect", this->get_expect_str())); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DParenSsm.cpp */ diff --git a/xo-reader2/src/reader2/DProgressSsm.cpp b/xo-reader2/src/reader2/DProgressSsm.cpp new file mode 100644 index 00000000..72ec3e93 --- /dev/null +++ b/xo-reader2/src/reader2/DProgressSsm.cpp @@ -0,0 +1,1455 @@ +/** @file DProgressSsm.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "DProgressSsm.hpp" +#include "ssm/ISyntaxStateMachine_DProgressSsm.hpp" + +#include "DExpectExprSsm.hpp" +#include "ssm/ISyntaxStateMachine_DExpectExprSsm.hpp" + +#include "ApplySsm.hpp" +#include "ParenSsm.hpp" + +#include +#include + +#include +#include + +#include // for xo::scm::Primitives +#include + +#include +#include +#include +#include + +#ifdef NOT_YET +#include "expect_expr_xs.hpp" +#include "pretty_exprstatestack.hpp" +#include "xo/expression/AssignExpr.hpp" +#include "xo/expression/Apply.hpp" +#include "xo/expression/pretty_expression.hpp" +#endif + +namespace xo { +#ifdef NOT_YET + using xo::scm::Expression; + using xo::scm::AssignExpr; + using xo::scm::Variable; + using xo::scm::Apply; +#endif + using xo::mm::AGCObject; + using xo::print::APrintable; + using xo::facet::FacetRegistry; + using xo::facet::with_facet; + using xo::reflect::typeseq; + + namespace scm { + const char * + optype_descr(optype x) { + switch (x) { + case optype::invalid: + return "?optype"; + case optype::op_assign: + return "op:="; + case optype::op_less: + return "op<"; + case optype::op_less_equal: + return "op<="; + case optype::op_equal: + return "op=="; + case optype::op_not_equal: + return "op!="; + case optype::op_great: + return "op>"; + case optype::op_great_equal: + return "op>="; + case optype::op_add: + return "op+"; + case optype::op_subtract: + return "op-"; + case optype::op_multiply: + return "op*"; + case optype::op_divide: + return "op/"; + case optype::n_optype: + break; + } + return "???"; + } + + /** higher-precedence operators bind before lower-preference operators **/ + int + precedence(optype x) { + switch (x) { + case optype::invalid: + case optype::n_optype: + return 0; + + case optype::op_assign: + return 1; + + case optype::op_less: + case optype::op_less_equal: + case optype::op_equal: + case optype::op_not_equal: + case optype::op_great: + case optype::op_great_equal: + return 2; + + case optype::op_add: + case optype::op_subtract: + return 3; + + case optype::op_multiply: + case optype::op_divide: + return 4; + } + + return 0; + } + + namespace { + optype + tk2op(const tokentype & tktype) { + switch (tktype) { + case tokentype::tk_assign: + return optype::op_assign; + case tokentype::tk_plus: + return optype::op_add; + case tokentype::tk_minus: + return optype::op_subtract; + case tokentype::tk_star: + return optype::op_multiply; + case tokentype::tk_slash: + return optype::op_divide; + case tokentype::tk_cmpeq: + return optype::op_equal; + case tokentype::tk_cmpne: + return optype::op_not_equal; + case tokentype::tk_leftangle: + return optype::op_less; + case tokentype::tk_lessequal: + return optype::op_less_equal; + case tokentype::tk_rightangle: + return optype::op_great; + case tokentype::tk_greatequal: + return optype::op_great_equal; + default: + assert(false); + return optype::invalid; + } + return optype::invalid; + } + } + + DProgressSsm * + DProgressSsm::_make(DArena & mm, + obj lhs, + optype op) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DProgressSsm)); + + return new (mem) DProgressSsm(lhs, op); + } + + obj + DProgressSsm::make(DArena & mm, + obj lhs, + optype op) + { + return obj(_make(mm, lhs, op)); + } + + void + DProgressSsm::start(DArena & parser_mm, + obj lhs, + optype op, + ParserStateMachine * p_psm) + { + DArena::Checkpoint ckp = parser_mm.checkpoint(); + + auto ssm = DProgressSsm::make(parser_mm, lhs, op); + + p_psm->push_ssm(ckp, ssm); + } + + void + DProgressSsm::start(DArena & parser_mm, + obj lhs, + ParserStateMachine * p_psm) + { + start(parser_mm, lhs, optype::invalid, p_psm); + } + + void + DProgressSsm::start(DArena & parser_mm, + ParserStateMachine * p_psm) + { + start(parser_mm, obj(), p_psm); + } + + DProgressSsm::DProgressSsm(obj valex, + optype op) + : lhs_{valex}, + op_type_{op} + {} + + syntaxstatetype + DProgressSsm::ssm_type() const noexcept + { + return syntaxstatetype::progress; + } + +#ifdef NOT_YET + bool + progress_xs::admits_f64() const { return false; } +#endif + + std::string_view + DProgressSsm::get_expect_str() const noexcept { + if (!lhs_) { + return "expr1|leftparen"; + } else if (op_type_ == optype::invalid) { + return "oper|semicolon|rightparen|rightbrace"; + } else { + return "expr2|leftparen"; + } + } + + void + DProgressSsm::on_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag()), xtag("tk", tk)); + + switch (tk.tk_type()) { + case tokentype::tk_then: + case tokentype::tk_else: + case tokentype::tk_comma: + this->on_completing_token(tk, p_psm); + return; + + case tokentype::tk_symbol: + this->on_symbol_token(tk, p_psm); + return; + + case tokentype::tk_colon: + this->on_colon_token(tk, p_psm); + return; + + case tokentype::tk_singleassign: + this->on_singleassign_token(tk, p_psm); + return; + + case tokentype::tk_string: + this->on_string_token(tk, p_psm); + return; + + case tokentype::tk_f64: + this->on_f64_token(tk, p_psm); + return; + + case tokentype::tk_i64: + this->on_i64_token(tk, p_psm); + return; + + case tokentype::tk_bool: + this->on_bool_token(tk, p_psm); + return; + + case tokentype::tk_semicolon: + this->on_semicolon_token(tk, p_psm); + return; + + case tokentype::tk_rightbrace: + this->on_rightbrace_token(tk, p_psm); + return; + + case tokentype::tk_leftparen: + this->on_leftparen_token(tk, p_psm); + return; + + case tokentype::tk_rightparen: + this->on_rightparen_token(tk, p_psm); + return; + + // all the not-yet handled cases + case tokentype::tk_invalid: + case tokentype::tk_def: + case tokentype::tk_if: + case tokentype::tk_leftbracket: + case tokentype::tk_rightbracket: + case tokentype::tk_leftbrace: + case tokentype::tk_leftangle: + case tokentype::tk_rightangle: + case tokentype::tk_lessequal: + case tokentype::tk_greatequal: + case tokentype::tk_dot: + case tokentype::tk_doublecolon: + case tokentype::tk_assign: + case tokentype::tk_yields: + case tokentype::tk_plus: + break; + + case tokentype::tk_star: + case tokentype::tk_minus: + case tokentype::tk_cmpeq: + this->on_operator_token(tk, p_psm); + return; + + case tokentype::tk_slash: + case tokentype::tk_cmpne: + case tokentype::tk_type: + case tokentype::tk_lambda: + break; + case tokentype::tk_let: + case tokentype::tk_in: + case tokentype::tk_end: + case tokentype::N: + break; + } + + Super::on_token(tk, p_psm); + } + + void + DProgressSsm::on_symbol_token(const Token & tk, + ParserStateMachine * p_psm) + { + Super::on_token(tk, p_psm); + } + + void + DProgressSsm::on_completing_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + obj expr = this->assemble_expr(p_psm); + + p_psm->pop_ssm(); // completes self + p_psm->on_parsed_expression_with_token(expr, tk); + } + + void + DProgressSsm::on_colon_token(const Token & tk, + ParserStateMachine * p_psm) + { + p_psm->illegal_input_on_token("DProgressSsm::on_colon_token", + tk, + this->get_expect_str()); + } + + void + DProgressSsm::on_singleassign_token(const Token & tk, + ParserStateMachine * p_psm) + { + p_psm->illegal_input_on_token("DProgressSsm::on_singleassign_token", + tk, + this->get_expect_str()); + } + + void + DProgressSsm::on_operator_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (op_type_ == optype::invalid) { + // tk is the operator this instance was waiting for + this->op_type_ = tk2op(tk.tk_type()); + + DExpectExprSsm::start(p_psm); + return; + } else if (rhs_) { + optype op_type2 = tk2op(tk.tk_type()); + + /* already have {lhs_, op_type_, rhs_}, + * with incoming op_type2 operator decides whether to parse like + * (lhs_, op_type_, rhs_) op_type2 ... + * or + * (lhs_, op_type_, (rhs_ op_type2 ...)) + */ + + if (precedence(op_type_) >= precedence(op_type2)) { + /* associate to the left + * + * parse like + * a + b - ... (a + b) - ... + * a * b - ... (a * b) - ... + */ + + auto lhs2 = this->assemble_expr(p_psm); + + p_psm->pop_ssm(); + + DProgressSsm::start(p_psm->parser_alloc(), + lhs2, + op_type2, + p_psm); + return; + } else { + /* associate to the right + * + * parse like + * a + b * ... (a + (b * ...)) + */ + + p_psm->pop_ssm(); + + /* (a + ..) */ + DProgressSsm::start(p_psm->parser_alloc(), + lhs_, + op_type_, + p_psm); + DExpectExprSsm::start(p_psm); + /* (b * ..) */ + DProgressSsm::start(p_psm->parser_alloc(), + rhs_, + op_type2, + p_psm); + DExpectExprSsm::start(p_psm); + return; + } + } + + p_psm->illegal_input_on_token("DProgressSsm::on_operator_token", + tk, + this->get_expect_str()); + } + + void + DProgressSsm::on_string_token(const Token & tk, + ParserStateMachine * p_psm) + { + Super::on_token(tk, p_psm); + } + + void + DProgressSsm::on_f64_token(const Token & tk, + ParserStateMachine * p_psm) + { + Super::on_token(tk, p_psm); + } + + void + DProgressSsm::on_i64_token(const Token & tk, + ParserStateMachine * p_psm) + { + Super::on_token(tk, p_psm); + } + + void + DProgressSsm::on_bool_token(const Token & tk, + ParserStateMachine * p_psm) + { + Super::on_token(tk, p_psm); + } + + void + DProgressSsm::on_semicolon_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + /* note: implementation should parallel .on_rightparen_token() */ + + (void)tk; + + obj expr = this->assemble_expr(p_psm); + + { + obj expr_pr + = FacetRegistry::instance().variant(expr); + assert(expr_pr); + log && log(xtag("expr", expr_pr)); + } + + p_psm->pop_ssm(); + p_psm->on_parsed_expression_with_token(expr, tk); + } + + void + DProgressSsm::on_rightbrace_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + (void)tk; + + obj expr = this->assemble_expr(p_psm); + + if (expr) { + obj expr_pr + = FacetRegistry::instance().try_variant(expr); + assert(expr_pr); + log && log(xtag("expr", expr_pr)); + } else { + // illegal token if assemble failed + Super::on_token(tk, p_psm); + return; + } + + p_psm->pop_ssm(); + p_psm->on_parsed_expression_with_token(expr, tk); + } + + void + DProgressSsm::on_parsed_expression(obj expr, + ParserStateMachine * p_psm) + { + const bool c_debug_flag = p_psm->debug_flag(); + + scope log(XO_DEBUG(c_debug_flag)); + + if (!lhs_) { + log && log("accepting expr1"); + + this->lhs_ = expr; + return; + } + + Super::on_parsed_expression(expr, p_psm); + } + + void + DProgressSsm::on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm) + { + const bool c_debug_flag = p_psm->debug_flag(); + + scope log(XO_DEBUG(c_debug_flag), + xtag("expr", expr), + xtag("tk", tk)); + +#ifdef NOT_YET + if (!lhs_) { + log && log("DProgressSsm: accepting expr1"); + + this->lhs_ = expr; + + // now we have to handle tk! + + return; + } +#endif + + // here: have lhs_ expression + + if (op_type_ == optype::invalid) { + // e.g. control here on input like + // x : = 4 4 + + p_psm->illegal_parsed_expression + ("DProgressSsm::on_parsed_expression_with_token", + expr, + this->get_expect_str()); + + return; + } + + this->rhs_ = expr; + + obj expr2 = this->assemble_expr(p_psm); + + if (expr2) { + p_psm->pop_ssm(); + p_psm->on_parsed_expression_with_token(expr2, tk); + } + } + +#ifdef NOT_YET + void + progress_xs::apply_type_error(const char * self_name, + optype op, + bp expr1, + bp expr2, + parserstatemachine * p_psm) const + { + std::string errmsg = tostr("incompatible argument types T1,T2 to op", + xtag("op", op), + xtag("T1", expr1->valuetype()), + xtag("T2", expr2->valuetype())); + + p_psm->on_error(self_name, std::move(errmsg)); + } + + rp + progress_xs::assemble_expr(parserstatemachine * p_psm) { + /* need to defer building Apply incase expr followed by higher-precedence operator: + * consider input like + * 3.14 + 2.0 * ... + */ + + constexpr const char * c_self_name = "progress_xs::assemble_expr"; + + if ((op_type_ != optype::invalid) && (rhs_.get() == nullptr)) { + std::string errmsg = tostr("expected expression on rhs of operator op", + xtag("lhs", lhs_), + xtag("op", op_type_)); + + p_psm->on_error(c_self_name, errmsg); + } + + /* consecutive expressions not legal, e.g: + * 3.14 6.28 + * but expressions surrounding an infix operators is: + * 3.14 / 6.28 + */ + switch (op_type_) { + case optype::invalid: + return this->lhs_; + + case optype::op_assign: + { + bp lhs = Variable::from(this->lhs_); + + if (!lhs) { + throw std::runtime_error + (tostr("progress_xs::assemble_expr", + " expect variable on lhs of assignment operator :=", + xtag("lhs", lhs_), + xtag("rhs", rhs_))); + } + + return AssignExpr::make(lhs.promote(), + this->rhs_); + } + + case optype::op_equal: + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_cmp_eq_i64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + break; + + case optype::op_not_equal: + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_cmp_ne_i64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + break; + + case optype::op_less: + // TODO: floating-point less-than + + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_cmp_lt_i64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + break; + + case optype::op_less_equal: + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_cmp_le_i64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + break; + + case optype::op_great: + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_cmp_gt_i64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + break; + + case optype::op_great_equal: + // TODO: upconvert integer->double + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_cmp_ge_i64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + + assert(false); + + case optype::op_add: + // TODO: upconvert integer->double + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_add2_i64(lhs_, rhs_); + } else if (lhs_->valuetype()->is_f64() && rhs_->valuetype()->is_f64()) { + return Apply::make_add2_f64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + break; + case optype::op_subtract: + // TODO: upconvert integer->double + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_sub2_i64(lhs_, rhs_); + } else if (lhs_->valuetype()->is_f64() && rhs_->valuetype()->is_f64()) { + return Apply::make_sub2_f64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + break; + + case optype::op_multiply: + // TODO: upconvert integer->double + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_mul2_i64(lhs_, rhs_); + } else if (lhs_->valuetype()->is_f64() && rhs_->valuetype()->is_f64()) { + return Apply::make_mul2_f64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + + break; + + case optype::op_divide: + // TODO: upconvert integer->double + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_div2_i64(lhs_, rhs_); + } else if (lhs_->valuetype()->is_f64() && rhs_->valuetype()->is_f64()) { + return Apply::make_div2_f64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + break; + + case optype::n_optype: + /* unreachable */ + assert(false); + return nullptr; + } + + return nullptr; + } + + void + progress_xs::on_expr(bp expr, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag()), xtag("expr", expr)); + + /* note: previous token probably an operator, + * handled from progress_xs::on_operator_token(), + * which pushes expect_expr_xs::expect_rhs_expression() + */ + + constexpr const char * c_self_name = "progress_xs::on_expr"; + const char * exp = get_expect_str(); + + if (lhs_) { + if (op_type_ == optype::invalid) { + /* two consecutive expression without an operator */ + this->illegal_input_on_expr(c_self_name, expr, exp, p_psm); + } + +#ifdef NOT_QUITE + assert(result.get()); + + /* this expression complete.. */ + std::unique_ptr self = p_psm->pop_exprstate(); + + /* ..but more operators could follow, so don't commit yet */ + p_stack->push_exprstate(progress_xs::make(result)); +#endif + + this->rhs_ = expr.promote(); + } else { + /* control here on input like + * add(1,2)... + * + * add(1,2) needs to be handled inside a progress_xs + * instance because may be followed by an operator: + * add(1,2) + ... + */ + this->lhs_ = expr.promote(); + } + } + + void + progress_xs::on_expr_with_semicolon(bp expr, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log(xtag("lhs", lhs_), xtag("op", op_type_), xtag("expr", expr)); + + constexpr const char * c_self_name = "progress_xs::on_expr_with_semicolon"; + const char * exp = get_expect_str(); + + if (op_type_ == optype::invalid) { + this->illegal_input_on_expr(c_self_name, expr, exp, p_psm); + } + + this->rhs_ = expr.promote(); + + // FORBIDDEN, because .on_semicolon_token() destroys *this before returning + // this->on_semicolon_token(token_type::semicolon(), p_psm); + // INSTEAD, spell out the body + + rp expr2 = this->assemble_expr(p_psm); + + if (expr2) { + std::unique_ptr self = p_psm->pop_exprstate(); + + p_psm->on_expr_with_semicolon(expr2); + } + } +#endif + +#ifdef NOT_YET + void + progress_xs::on_comma_token(const token_type & tk, + parserstatemachine * p_psm) + { + /* note: implementation parllels .on_semicolon_token(), .on_rightparen_token() */ + + scope log(XO_DEBUG(p_psm->debug_flag())); + + constexpr const char * self_name = "progress::xs::on_comma_token"; + + auto & xs_stack = p_psm->xs_stack_; + + /* stack may be something like + * + * applyexpr + * expect_expr_xs + * progress_xs + * <-- comma + * + * 1. comma completes expression-in-progress + */ + + /* comma confirms stack expression */ + rp expr = this->assemble_expr(p_psm); + + std::unique_ptr self = p_psm->pop_exprstate(); + + if (xs_stack.empty()) { + throw std::runtime_error(tostr(self_name, + ": expected non-empty parsing state")); + } + + log && log(xtag("stack", &xs_stack)); + + p_psm->top_exprstate().on_expr(expr, p_psm); + + /* now deliver comma */ + p_psm->top_exprstate().on_comma_token(tk, p_psm); + } + + void + progress_xs::on_semicolon_token(const token_type & /*tk*/, + parserstatemachine * p_psm) + { + /* note: implementation parallels .on_rightparen_token() */ + + scope log(XO_DEBUG(p_psm->debug_flag())); + + rp expr = this->assemble_expr(p_psm); + + log && log(xtag("assembled-expr", expr)); + + std::unique_ptr self = p_psm->pop_exprstate(); + + p_psm->on_expr_with_semicolon(expr); + + /* control here on input like: + * (1.234; + * + * a. '(' sets up stack [lparen_0:expect_rhs_expression] + * (see exprstate::on_leftparen()) + * b. 1.234 pushes (in case operators) [lparen_0:expect_rhs_expression:expr_progress] + * (see exprstate::on_f64()) + * c. semicolon completes expr_progress [lparen_0:expect_rhs_expression] + * deliver expresssion to expect_rhs_expression.on_expr_with_semicolon() + * (see exprstate::on_expr_with_semicolon()) + * d. expr_rhs_expression forwards expression to [lparen_0] + * e. lparen_0 would advance to [lparen_1], but rejects semicolon + */ + } + + void + progress_xs::on_assign_token(const token_type & tk, + parserstatemachine * p_psm) + { + this->on_operator_token(tk, p_psm); + } +#endif + + void + DProgressSsm::on_leftparen_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (!lhs_) { + // leftparen begins possible lhs expression + DParenSsm::start(p_psm); + + p_psm->on_token(Token::leftparen_token()); + return; + } + + if (op_type_ == optype::invalid) { + // input: + /// <--- F1 ---> + // (..........)(.. ).. + // <------ A1 -----> + // <------- X1 ------> + // + // F1: expression evaluating to a function, + // parsed as fn_expr + // A1: expression parsed as a function call (i.e. apply-expression) + // X1: operator expression starting with A1 + // + // before: + // [0] ProgressSsm responsible for input beginning with F1 + // .lhs = fn_expr, .op_type empty, .rhs empty + // + // after: + // [0] ApplySsm responsible for function call A1 + // .fn_expr = fn_expr + // [1] ProgressSsm responsible for operator expression X1 + // .lhs empty, .op_type empty, .rhs empty + // + // Remarks: + // 1. keep ProgressSsm on the stack in case input continues like: + // fn_expr(args..) + .. + // i.e. to allow for infix operator following apply + // + + obj fn_expr(this->lhs_); + + this->lhs_ = obj(); + + DApplySsm::start(fn_expr, p_psm); + // + send leftparen to just-pushed apply + p_psm->on_token(tk); + + return; + } + + Super::on_token(tk, p_psm); + } + +#ifdef NOT_YET + /* editor bait: on_lparen */ + void + progress_xs::on_leftparen_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + /* input like: + * 'foo(' -> expect function call. might continue 'foo(a,b,c)' + * 'foo+(' -> expect parenthesized expression. might continue 'foo+(bar/2)' + */ + + if (op_type_ == optype::invalid) { + /* start function call */ + assert(rhs_.get() == nullptr); + + rp fn_expr = lhs_; + + /* reset this progress_xs back to empty state; + * apply_xs will be responsible for lhs_. + */ + lhs_ = nullptr; + +#ifdef OBSOLETE + /* don't unwind! want to handle input like + * f(x,y)+g(z) + */ + /* unwind this progress_xs + replace with function call */ + std::unique_ptr self = p_psm->pop_exprstate(); +#endif + + apply_xs::start(fn_expr, p_psm); + + /* control will reenter progress_xs via .on_expr() */ + return; + } + + const char * exp = get_expect_str(); + constexpr const char * c_self_name = "exprstate::on_leftparen"; + + this->illegal_input_on_token(c_self_name, tk, exp, p_psm); + } +#endif + + void + DProgressSsm::on_rightparen_token(const Token & tk, + ParserStateMachine * p_psm) + { + /* note: implementation parallels .on_semicolon_token() */ + + scope log(XO_DEBUG(p_psm->debug_flag())); + + /* stack may be something like: + * + * [0] DProgressSsm + * [1] DExpectExprSsm + * [2] DApplySsm + * + * where we want rightparen to resolve in [2] DApplySsm, + * after triggering completion of [0] and [1] + */ + auto expr = this->assemble_expr(p_psm); + + if (expr) { + /* 1. popping self from parser stack.. */ + p_psm->pop_ssm(); + /* 2. report parsed subexpr to parent ssm, along with the triggering rightparen **/ + p_psm->on_parsed_expression_with_token(expr, tk); + + return; + } + + Super::on_token(tk, p_psm); + } + +#ifdef NOT_YET + void + progress_xs::on_rightparen_token(const token_type & tk, + parserstatemachine * p_psm) + { + /* note: implementation parallels .on_semicolon_token() */ + + scope log(XO_DEBUG(p_psm->debug_flag())); + + constexpr const char * self_name = "progress_xs::on_rightparen"; + + auto & xs_stack = p_psm->xs_stack_; + + /* stack may be something like: + * + * lparen_0 + * expect_expr_xs + * expr_progress + * <-- rightparen + * + * 1. rightparen completes expression-in-progress + * 2. rightparen must then match innermost waiting lparen_0 + */ + + /* right paren confirms stack expression */ + rp expr = this->assemble_expr(p_psm); + + log && log(xtag("expr", expr), + xtag("do", "pop self + send {expr, rparen} -> parent")); + + std::unique_ptr self = p_psm->pop_exprstate(); + + if (xs_stack.empty()) { + throw std::runtime_error(tostr(self_name, + ": expected non-empty parsing stack")); + } + + log && log(xtag("stack", &xs_stack)); + + p_psm->top_exprstate().on_expr(expr, p_psm); + + /* now deliver rightparen */ + p_psm->top_exprstate().on_rightparen_token(tk, p_psm); + } + + void + progress_xs::on_else_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + rp expr = this->assemble_expr(p_psm); + + log && log(xtag("assembled-expr", expr)); + + std::unique_ptr self = p_psm->pop_exprstate(); + + p_psm->on_expr(expr); + p_psm->on_else_token(tk); + + /* control here on input like: + * + * if a > b then c else.. + */ + } + + void + progress_xs::on_rightbrace_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + rp expr = this->assemble_expr(p_psm); + + log && log(xtag("assembled-expr", expr)); + + std::unique_ptr self = p_psm->pop_exprstate(); + + p_psm->on_expr(expr); + p_psm->on_rightbrace_token(tk); + + /* control here on input like: + * + * { n * n } + */ + } +#endif + +#ifdef OBSOLETE + //void progress_xs::on_operator_token(const token_type & tk, parserstatemachine * p_psm) + + void + progress_xs::on_bool_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + constexpr const char * c_self_name = "progress_xs::on_bool_token"; + const char * exp = get_expect_str(); + + if (this->op_type_ == optype::invalid) { + this->illegal_input_on_token(c_self_name, tk, exp, p_psm); + } else { + exprstate::on_bool_token(tk, p_psm); + } + } + + void + progress_xs::on_i64_token(const token_type & tk, + parserstatemachine * p_psm) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + constexpr const char * c_self_name = "progress_xs::on_i64_token"; + const char * exp = get_expect_str(); + + if (this->op_type_ == optype::invalid) { + this->illegal_input_on_token(c_self_name, tk, exp, p_psm); + } else { + exprstate::on_i64_token(tk, p_psm); + } + } +#endif + + bool + DProgressSsm::pretty(const xo::print::ppindentinfo & ppii) const + { + scope log(XO_DEBUG(false)); + log && log(xtag("lhs_.tseq", lhs_._typeseq())); + log && log(xtag("rhs_.tseq", rhs_._typeseq())); + + obj lhs + = FacetRegistry::instance().try_variant(lhs_); + + obj rhs + = FacetRegistry::instance().try_variant(rhs_); + + bool lhs_present = lhs; + bool rhs_present = rhs; + bool op_present = (op_type_ != optype::invalid); + + return ppii.pps()->pretty_struct + (ppii, + "DProgressSsm", + refrtag("lhs", lhs, lhs_present), + refrtag("op", op_type_, op_present), + refrtag("rhs", rhs, rhs_present), + refrtag("expect", this->get_expect_str()) + ); + } + + namespace { + // make_builtin_apply_pm2 + } + + obj + DProgressSsm::assemble_expr(ParserStateMachine * p_psm) + { + /* need to defer building Apply incase expr followed by higher-precedence operator: + * consider input like + * 3.14 + 2.0 * ... + */ + + constexpr const char * c_self_name = "DProgressSsm::assemble_expr"; + + if ((op_type_ != optype::invalid) && !rhs_) { + std::string errmsg_string = tostr("expected expression on rhs of operator op", + xtag("lhs", lhs_), + xtag("op", op_type_)); + + auto errmsg = DString::from_view(p_psm->expr_alloc(), + std::string_view(errmsg_string)); + + p_psm->capture_error(c_self_name, errmsg); + return obj(); + } + + /* consecutive expressions not legal, e.g: + * 3.14 6.28 + * but expressions surrounding an infix operators is: + * 3.14 / 6.28 + */ + switch (op_type_) { + case optype::invalid: + return this->lhs_; + + case optype::op_assign: + assert(false); + break; + + case optype::op_equal: + { + auto pm_obj = (with_facet::mkobj + (&Primitives::s_equal_gco_gco_pm)); + auto fn_expr = (DConstant::make + (p_psm->expr_alloc(), pm_obj)); + + // see note on op_multiply + + TypeRef tref = TypeRef::dwim + (TypeRef::prefix_type::from_chars("_equal_gco"), + nullptr); + + return DApplyExpr::make2(p_psm->expr_alloc(), + tref, + fn_expr, lhs_, rhs_); + } + break; + + case optype::op_not_equal: + case optype::op_less: + case optype::op_less_equal: + case optype::op_great: + case optype::op_great_equal: + case optype::op_add: + assert(false); + break; + + case optype::op_multiply: + { + auto pm_obj = (with_facet::mkobj + (&Primitives::s_mul_gco_gco_pm)); + auto fn_expr = (DConstant::make + (p_psm->expr_alloc(), pm_obj)); + + /* note: + * 1. don't assume we know lhs_ / rhs_ value types yet. + * perhaps have expression like + * f(..) * g(..) + * where f is the function that contains current ssm. + * + * 2. consequence: we need representation for + * polymorphic multiply on unknown numeric arguments. + * + * 3. TypeRef::dwim(..) is a placeholder. + * Plan to later provide abstract interpreter + * (ie compiler pass :) to drive type inference/unification + * + * 4. Alternatively could supply type-annotation syntax + * so human can assist inference; context here is we want + * to automate the boring stuff + */ + + TypeRef tref = TypeRef::dwim + (TypeRef::prefix_type::from_chars("_mul_gco"), + nullptr); + + return DApplyExpr::make2(p_psm->expr_alloc(), + tref, fn_expr, lhs_, rhs_); + } + + break; + case optype::op_divide: + // TODO: implement binary operator expression assembly + assert(false); + break; + case optype::op_subtract: /* editor bait: op_minus */ + { + auto pm_obj = (with_facet::mkobj + (&Primitives::s_sub_gco_gco_pm)); + auto fn_expr = (DConstant::make + (p_psm->expr_alloc(), pm_obj)); + + // see comment on op_multiply re need for poly impl + + TypeRef tref = TypeRef::dwim + (TypeRef::prefix_type::from_chars("_sub_gco"), + nullptr); + + return DApplyExpr::make2(p_psm->expr_alloc(), + tref, fn_expr, lhs_, rhs_); + } + + break; + +#ifdef NOT_YET +case optype::op_assign: + { + bp lhs = Variable::from(this->lhs_); + + if (!lhs) { + throw std::runtime_error + (tostr("progress_xs::assemble_expr", + " expect variable on lhs of assignment operator :=", + xtag("lhs", lhs_), + xtag("rhs", rhs_))); + } + + return AssignExpr::make(lhs.promote(), + this->rhs_); + } + +case optype::op_equal: + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_cmp_eq_i64(lhs_, rhs_); + } else { + + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + break; + +case optype::op_not_equal: + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_cmp_ne_i64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + break; + +case optype::op_less: + // TODO: floating-point less-than + + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_cmp_lt_i64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + break; + +case optype::op_less_equal: + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_cmp_le_i64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + break; + +case optype::op_great: + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_cmp_gt_i64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + break; + +case optype::op_great_equal: + // TODO: upconvert integer->double + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_cmp_ge_i64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + + assert(false); + +case optype::op_add: + // TODO: upconvert integer->double + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_add2_i64(lhs_, rhs_); + } else if (lhs_->valuetype()->is_f64() && rhs_->valuetype()->is_f64()) { + return Apply::make_add2_f64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + break; +case optype::op_subtract: + // TODO: upconvert integer->double + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_sub2_i64(lhs_, rhs_); + } else if (lhs_->valuetype()->is_f64() && rhs_->valuetype()->is_f64()) { + return Apply::make_sub2_f64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + break; + +case optype::op_multiply: + // TODO: upconvert integer->double + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_mul2_i64(lhs_, rhs_); + } else if (lhs_->valuetype()->is_f64() && rhs_->valuetype()->is_f64()) { + return Apply::make_mul2_f64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + + break; + +case optype::op_divide: + // TODO: upconvert integer->double + if (lhs_->valuetype()->is_i64() && rhs_->valuetype()->is_i64()) { + return Apply::make_div2_i64(lhs_, rhs_); + } else if (lhs_->valuetype()->is_f64() && rhs_->valuetype()->is_f64()) { + return Apply::make_div2_f64(lhs_, rhs_); + } else { + this->apply_type_error(c_self_name, + op_type_, lhs_, rhs_, p_psm); + return nullptr; + } + break; +#endif + + case optype::n_optype: + /* unreachable */ + assert(false); + break; + } + + return obj(); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DProgressSsm.cpp */ diff --git a/xo-reader2/src/reader2/DSequenceSsm.cpp b/xo-reader2/src/reader2/DSequenceSsm.cpp new file mode 100644 index 00000000..87460804 --- /dev/null +++ b/xo-reader2/src/reader2/DSequenceSsm.cpp @@ -0,0 +1,260 @@ +/* @file DSequenceSsm.cpp */ + +#include "DSequenceSsm.hpp" +#include "ssm/ISyntaxStateMachine_DSequenceSsm.hpp" +#include "DExpectExprSsm.hpp" + +#ifdef NOT_YET +#include "expect_expr_xs.hpp" +#include "let1_xs.hpp" +#include "xo/expression/DefineExpr.hpp" +#include "xo/expression/Sequence.hpp" +#include "xo/expression/pretty_expression.hpp" +#endif + +namespace xo { +#ifdef NOT_YET + using xo::scm::DDefineExpr; +#endif + using xo::facet::typeseq; + + namespace scm { + void + DSequenceSsm::start(ParserStateMachine * p_psm) + { + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + + p_psm->push_ssm(ckp, DSequenceSsm::make(p_psm->parser_alloc(), + p_psm->expr_alloc())); + /* want to accept anything that starts an expression, + * except that rightbrace '}' ends it + */ + DExpectExprSsm::start(p_psm->parser_alloc(), + true /*allow_defs*/, + true /*cxl_on_rightbrace*/, + p_psm); + } + + obj + DSequenceSsm::make(DArena & mm, + obj expr_mm) + { + return obj(_make(mm, expr_mm)); + } + + DSequenceSsm * + DSequenceSsm::_make(DArena & mm, + obj expr_mm) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DSequenceSsm)); + + DSequenceExpr * seq_expr = DSequenceExpr::_make_empty(expr_mm); + + return new (mem) DSequenceSsm(seq_expr); + } + + DSequenceSsm::DSequenceSsm(DSequenceExpr * seq_expr) : seq_expr_{seq_expr} + {} + + syntaxstatetype + DSequenceSsm::ssm_type() const noexcept + { + return syntaxstatetype::sequence; + } + + std::string_view + DSequenceSsm::get_expect_str() const noexcept + { + return "expr|semicolon|rightbrace"; + } + + void + DSequenceSsm::on_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag()), xtag("tk", tk)); + + switch (tk.tk_type()) { + case tokentype::tk_rightbrace: + this->on_rightbrace_token(tk, p_psm); + return; + case tokentype::tk_symbol: + case tokentype::tk_def: + case tokentype::tk_if: + case tokentype::tk_then: + case tokentype::tk_else: + case tokentype::tk_colon: + case tokentype::tk_singleassign: + case tokentype::tk_string: + case tokentype::tk_f64: + case tokentype::tk_i64: + case tokentype::tk_bool: + case tokentype::tk_semicolon: + case tokentype::tk_invalid: + case tokentype::tk_leftparen: + case tokentype::tk_rightparen: + case tokentype::tk_leftbracket: + case tokentype::tk_rightbracket: + case tokentype::tk_leftbrace: + case tokentype::tk_leftangle: + case tokentype::tk_rightangle: + case tokentype::tk_lessequal: + case tokentype::tk_greatequal: + case tokentype::tk_dot: + case tokentype::tk_comma: + case tokentype::tk_doublecolon: + case tokentype::tk_assign: + case tokentype::tk_yields: + case tokentype::tk_plus: + case tokentype::tk_minus: + case tokentype::tk_star: + case tokentype::tk_slash: + case tokentype::tk_cmpeq: + case tokentype::tk_cmpne: + case tokentype::tk_type: + case tokentype::tk_lambda: + case tokentype::tk_let: + case tokentype::tk_in: + case tokentype::tk_end: + case tokentype::N: + break; + } + + // default = illegal token error + DSyntaxStateMachine::on_token(tk, p_psm); + } + + void + DSequenceSsm::on_rightbrace_token(const Token & tk, + ParserStateMachine * p_psm) + { + (void)tk; + + /** rightbrace ends DSequenceSsm **/ + + obj expr(seq_expr_); + + p_psm->pop_ssm(); + + /* make sequence from expressions seen at this level, + * and report it to parent + */ + p_psm->top_ssm().on_parsed_expression(expr, p_psm); + } + + void + DSequenceSsm::on_parsed_expression(obj expr, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + // TODO: switch to printable facet + + log && log(xtag("expr", expr)); + +#ifdef NOT_YET + /* TODO: if expr is a DefineExpr, + * then need to rewrite... + * + * ...prefix + * DefineExpr(lhs_name, rhs) + * rest... + * + * becomes: + * + * /-- .outer_seq_expr_ + * v + * Sequence( + * ...prefix, + * + * /-- .inner_lm_expr_ + * v + * Apply(Lambda(gen999, + * [Variable(lhs_name, type(rhs))], + * /-- .expr_v_ + * v + * sequencify(rest...)), + * rhs)) + * + * so amongst other things, + * helpful to have nested seequence_xs that propagates '}' + * instead of swallowing it. + */ + bp def_expr = DefineExpr::from(expr); + + if (def_expr) { + /** nested_start: control returns via + * .on_expr(x) + * with x something like: + * Apply(Lambda(gensym(), + * [Variable(def_expr->lhs_name(), + * def_expr->valuetype())], + * body...)) + * followed immediately by + * .on_rightbrace_token() + **/ + let1_xs::start(def_expr->lhs_name(), + def_expr->rhs(), + p_psm); + } else { + this->expr_v_.push_back(expr.promote()); + + expect_expr_xs::start(true /*allow_defs*/, + true /*cxl_on_rightbrace*/, + p_psm); + } +#endif + + this->seq_expr_->push_back(p_psm->expr_alloc(), expr); + } + + void + DSequenceSsm::on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + if (tk.tk_type() == tokentype::tk_semicolon) { + // keep sequence on stack, consuming semicolon + + this->seq_expr_->push_back(p_psm->expr_alloc(), + expr); + return; + } else if (tk.tk_type() == tokentype::tk_rightbrace) { + // rightbrace ends sequence + + this->seq_expr_->push_back(p_psm->expr_alloc(), expr); + this->on_rightbrace_token(tk, p_psm); + return; + } + + Super::on_parsed_expression_with_token(expr, tk, p_psm); + } + +#ifdef NOT_YET + void + sequence_xs::on_expr_with_semicolon(bp expr, + parserstatemachine * p_psm) + { + /* sequence continues until right brace */ + this->on_expr(expr, p_psm); + } +#endif + + bool + DSequenceSsm::pretty(const xo::print::ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct + (ppii, + "DSequenceSsm", + refrtag("seq_expr.size", seq_expr_->size()), + refrtag("expect", this->get_expect_str())); + } + + } /*namespace scm*/ +} /*namespace xo*/ + + +/* end DSequenceSsm.cpp */ diff --git a/xo-reader2/src/reader2/DToplevelSeqSsm.cpp b/xo-reader2/src/reader2/DToplevelSeqSsm.cpp new file mode 100644 index 00000000..42c870b6 --- /dev/null +++ b/xo-reader2/src/reader2/DToplevelSeqSsm.cpp @@ -0,0 +1,459 @@ +/** @file DToplevelSeqSsm.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "DToplevelSeqSsm.hpp" +#include "ssm/ISyntaxStateMachine_DToplevelSeqSsm.hpp" +#include "DDefineSsm.hpp" +#include "DLambdaSsm.hpp" +#include "ProgressSsm.hpp" +#include "DIfElseSsm.hpp" +#include "ParenSsm.hpp" +#include "ExpectExprSsm.hpp" +#include "VarRef.hpp" + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include + +namespace xo { + using xo::scm::DProgressSsm; + using xo::scm::DConstant; + using xo::scm::DFloat; + using xo::mm::AGCObject; + using xo::mm::AAllocator; + using xo::mm::DArena; + using xo::facet::with_facet; + using xo::reflect::typeseq; + + namespace scm { + const char * + exprseqtype_descr(exprseqtype x) + { + switch (x) { + case exprseqtype::toplevel_interactive: + return "toplevel-interactive"; + case exprseqtype::toplevel_batch: + return "toplevel-batch"; + case exprseqtype::N: + break; + } + + return "exprseqtype?"; + } + + DToplevelSeqSsm::DToplevelSeqSsm(exprseqtype ty) : seqtype_{ty} + {} + + namespace { + obj + make_exprseq_ssm(DArena & mm, + exprseqtype seqtype) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DToplevelSeqSsm)); + + DToplevelSeqSsm * ssm = new (mem) DToplevelSeqSsm(seqtype); + + return obj(ssm); + } + } + + void + DToplevelSeqSsm::establish_interactive(DArena & mm, + ParserStateMachine * p_psm) + { + p_psm->establish_toplevel_ssm(make_exprseq_ssm + (mm, + exprseqtype::toplevel_interactive)); + } + + void + DToplevelSeqSsm::establish_batch(DArena & mm, + ParserStateMachine * p_psm) + { + p_psm->establish_toplevel_ssm(make_exprseq_ssm + (mm, + exprseqtype::toplevel_batch)); + } + + // SyntaxStateMachine facet methods + + syntaxstatetype + DToplevelSeqSsm::ssm_type() const noexcept + { + return syntaxstatetype::expect_toplevel_expression_sequence; + } + + std::string_view + DToplevelSeqSsm::get_expect_str() const noexcept + { + // TODO: provisional. Will expand as more syntax implemented + + switch (seqtype_) { + case exprseqtype::toplevel_interactive: + return "def|expression|..."; + case exprseqtype::toplevel_batch: + return "def|..."; + case exprseqtype::N: + break; + } + + assert(false); + return "impossible-DToplevelSeqSsm::get_expr_str"; + } + + void + DToplevelSeqSsm::on_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag()), xtag("tk", tk)); + + switch (tk.tk_type()) { + case tokentype::tk_symbol: + this->on_symbol_token(tk, p_psm); + return; + + case tokentype::tk_def: + this->on_def_token(tk, p_psm); + return; + + case tokentype::tk_lambda: + this->on_lambda_token(tk, p_psm); + return; + + case tokentype::tk_if: + this->on_if_token(tk, p_psm); + return; + + case tokentype::tk_string: + this->on_string_token(tk, p_psm); + return; + + case tokentype::tk_f64: + this->on_f64_token(tk, p_psm); + return; + + case tokentype::tk_i64: + this->on_i64_token(tk, p_psm); + return; + + case tokentype::tk_bool: + this->on_bool_token(tk, p_psm); + return; + + case tokentype::tk_leftparen: + this->on_leftparen_token(tk, p_psm); + return; + + // all the not-yet handled cases + case tokentype::tk_invalid: + case tokentype::tk_rightparen: + case tokentype::tk_leftbracket: + case tokentype::tk_rightbracket: + case tokentype::tk_leftbrace: + case tokentype::tk_rightbrace: + case tokentype::tk_leftangle: + case tokentype::tk_rightangle: + case tokentype::tk_lessequal: + case tokentype::tk_greatequal: + case tokentype::tk_dot: + case tokentype::tk_comma: + case tokentype::tk_colon: + break; + case tokentype::tk_semicolon: + assert(false); + break; + case tokentype::tk_doublecolon: + case tokentype::tk_singleassign: + case tokentype::tk_assign: + case tokentype::tk_yields: + case tokentype::tk_plus: + case tokentype::tk_minus: + case tokentype::tk_star: + case tokentype::tk_slash: + case tokentype::tk_cmpeq: + case tokentype::tk_cmpne: + case tokentype::tk_type: + case tokentype::tk_then: + case tokentype::tk_else: + case tokentype::tk_let: + case tokentype::tk_in: + case tokentype::tk_end: + case tokentype::N: + break; + } + + p_psm->illegal_input_on_token("DToplevelSeqSsm::on_token", + tk, + this->get_expect_str()); + } + + void + DToplevelSeqSsm::on_symbol_token(const Token & tk, + ParserStateMachine * p_psm) + { + switch (seqtype_) { + case exprseqtype::toplevel_interactive: + { + auto varref = obj(p_psm->lookup_varref(tk.text())); + + if (varref) { + DProgressSsm::start(p_psm->parser_alloc(), + varref, + p_psm); + return; + } else { + p_psm->error_unbound_variable("DToplevelSeqSsm", + tk.text()); + return; + } + } + break; + case exprseqtype::toplevel_batch: + break; + case exprseqtype::N: + assert(false); // unreachable + break; + } + + Super::on_token(tk, p_psm); + } + + void + DToplevelSeqSsm::on_def_token(const Token & tk, + ParserStateMachine * p_psm) + { + (void)tk; + + DDefineSsm::start(p_psm->parser_alloc(), + p_psm->expr_alloc(), + p_psm); + + /* keyword 'def' introduces a definition: + * def pi : f64 = 3.14159265 + * def sq(x : f64) -> f64 { (x * x) } + */ + } + + void + DToplevelSeqSsm::on_lambda_token(const Token & tk, + ParserStateMachine * p_psm) + { + (void)tk; + + switch (seqtype_) { + case exprseqtype::toplevel_interactive: + DLambdaSsm::start(p_psm); + return; + case exprseqtype::toplevel_batch: + /* lambda not allowed at top-level in batch mode */ + break; + case exprseqtype::N: + assert(false); // unreachable + break; + } + + Super::on_token(tk, p_psm); + } + + void + DToplevelSeqSsm::on_if_token(const Token & tk, + ParserStateMachine * p_psm) + { + switch (seqtype_) { + case exprseqtype::toplevel_interactive: + DIfElseSsm::start(p_psm->parser_alloc(), + p_psm->expr_alloc(), + p_psm); + return; + case exprseqtype::toplevel_batch: + break; + case exprseqtype::N: + assert(false); // unreachable + break; + } + + Super::on_token(tk, p_psm); + } + + void + DToplevelSeqSsm::on_string_token(const Token & tk, + ParserStateMachine * p_psm) + { + switch (seqtype_) { + case exprseqtype::toplevel_interactive: + { + DString * dstr = DString::from_cstr(p_psm->expr_alloc(), + tk.text().c_str()); + obj str(dstr); + obj expr = DConstant::make(p_psm->expr_alloc(), str); + + DProgressSsm::start(p_psm->parser_alloc(), + expr, + p_psm); + return; + } + case exprseqtype::toplevel_batch: + break; + case exprseqtype::N: + assert(false); // unreachable + break; + } + + Super::on_token(tk, p_psm); + } + + void + DToplevelSeqSsm::on_f64_token(const Token & tk, + ParserStateMachine * p_psm) + { + switch (seqtype_) { + case exprseqtype::toplevel_interactive: + { + auto f64o = DFloat::box(p_psm->expr_alloc(), + tk.f64_value()); + auto expr = DConstant::make(p_psm->expr_alloc(), f64o); + + DProgressSsm::start(p_psm->parser_alloc(), + expr, + p_psm); + return; + } + case exprseqtype::toplevel_batch: + break; + case exprseqtype::N: + assert(false); // unreachable + break; + } + + Super::on_token(tk, p_psm); + } + + void + DToplevelSeqSsm::on_i64_token(const Token & tk, + ParserStateMachine * p_psm) + { + switch (seqtype_) { + case exprseqtype::toplevel_interactive: + { + auto i64o = DInteger::box(p_psm->expr_alloc(), + tk.i64_value()); + auto expr = DConstant::make(p_psm->expr_alloc(), i64o); + + DProgressSsm::start(p_psm->parser_alloc(), + expr, + p_psm); + return; + } + case exprseqtype::toplevel_batch: + break; + case exprseqtype::N: + assert(false); // unreachable + break; + } + + Super::on_token(tk, p_psm); + } + + void + DToplevelSeqSsm::on_bool_token(const Token & tk, + ParserStateMachine * p_psm) + { + switch (seqtype_) { + case exprseqtype::toplevel_interactive: + { + auto dvalue = DBoolean::box(p_psm->expr_alloc(), + tk.bool_value()); + auto expr = DConstant::make(p_psm->expr_alloc(), dvalue); + + DProgressSsm::start(p_psm->parser_alloc(), + expr, + p_psm); + return; + } + case exprseqtype::toplevel_batch: + break; + case exprseqtype::N: + assert(false); // unreachable + break; + } + + Super::on_token(tk, p_psm); + } + + void + DToplevelSeqSsm::on_leftparen_token(const Token & tk, + ParserStateMachine * p_psm) + { + switch (seqtype_) { + case exprseqtype::toplevel_interactive: { + // not sufficient to just start a paren-ssm here. + // we want to parse toplevel input like + // (getfunction())(); + // just as C would. + // To wait for token following right paren, use a progress-ssm + + DProgressSsm::start(p_psm->parser_alloc(), p_psm); + p_psm->on_token(Token::leftparen_token()); + + return; + } + case exprseqtype::toplevel_batch: + break; + case exprseqtype::N: + assert(false); // unreachable + break; + } + + Super::on_token(tk, p_psm); + } + + void + DToplevelSeqSsm::on_parsed_expression(obj expr, + ParserStateMachine * p_psm) + { + // toplevel expr sequence accepts an arbitrary number of expressions. + + p_psm->capture_result("DToplevelSeqSsm::on_parsed_expression", expr); + } + + void + DToplevelSeqSsm::on_parsed_expression_with_token(obj expr, + const Token & tk, + ParserStateMachine * p_psm) + { + if (tk.tk_type() == tokentype::tk_semicolon) { + p_psm->capture_result("DToplevelSeqSsm::on_parsed_expression_with_token", expr); + return; + } + + Super::on_parsed_expression_with_token(expr, tk, p_psm); + } + + bool + DToplevelSeqSsm::pretty(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct + (ppii, + "DToplevelSeqSsm", + refrtag("seqtype", seqtype_)); + } + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DToplevelSeqSsm.cpp */ diff --git a/xo-reader2/src/reader2/IPrintable_DApplySsm.cpp b/xo-reader2/src/reader2/IPrintable_DApplySsm.cpp new file mode 100644 index 00000000..5066b082 --- /dev/null +++ b/xo-reader2/src/reader2/IPrintable_DApplySsm.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DApplySsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DApplySsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DApplySsm.json5] +**/ + +#include "ssm/IPrintable_DApplySsm.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DApplySsm::pretty(const DApplySsm & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DApplySsm.cpp */ diff --git a/xo-reader2/src/reader2/IPrintable_DDefineSsm.cpp b/xo-reader2/src/reader2/IPrintable_DDefineSsm.cpp new file mode 100644 index 00000000..dbd0bfc9 --- /dev/null +++ b/xo-reader2/src/reader2/IPrintable_DDefineSsm.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DDefineSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DDefineSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DDefineSsm.json5] +**/ + +#include "ssm/IPrintable_DDefineSsm.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DDefineSsm::pretty(const DDefineSsm & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DDefineSsm.cpp */ diff --git a/xo-reader2/src/reader2/IPrintable_DExpectExprSsm.cpp b/xo-reader2/src/reader2/IPrintable_DExpectExprSsm.cpp new file mode 100644 index 00000000..7febe575 --- /dev/null +++ b/xo-reader2/src/reader2/IPrintable_DExpectExprSsm.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DExpectExprSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DExpectExprSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DExpectExprSsm.json5] +**/ + +#include "ssm/IPrintable_DExpectExprSsm.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DExpectExprSsm::pretty(const DExpectExprSsm & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DExpectExprSsm.cpp */ diff --git a/xo-reader2/src/reader2/IPrintable_DExpectFormalArgSsm.cpp b/xo-reader2/src/reader2/IPrintable_DExpectFormalArgSsm.cpp new file mode 100644 index 00000000..13164b15 --- /dev/null +++ b/xo-reader2/src/reader2/IPrintable_DExpectFormalArgSsm.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DExpectFormalArgSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DExpectFormalArgSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DExpectFormalArgSsm.json5] +**/ + +#include "ssm/IPrintable_DExpectFormalArgSsm.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DExpectFormalArgSsm::pretty(const DExpectFormalArgSsm & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DExpectFormalArgSsm.cpp */ diff --git a/xo-reader2/src/reader2/IPrintable_DExpectFormalArglistSsm.cpp b/xo-reader2/src/reader2/IPrintable_DExpectFormalArglistSsm.cpp new file mode 100644 index 00000000..262cb91e --- /dev/null +++ b/xo-reader2/src/reader2/IPrintable_DExpectFormalArglistSsm.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DExpectFormalArglistSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DExpectFormalArglistSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DExpectFormalArglistSsm.json5] +**/ + +#include "ssm/IPrintable_DExpectFormalArglistSsm.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DExpectFormalArglistSsm::pretty(const DExpectFormalArglistSsm & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DExpectFormalArglistSsm.cpp */ diff --git a/xo-reader2/src/reader2/IPrintable_DExpectSymbolSsm.cpp b/xo-reader2/src/reader2/IPrintable_DExpectSymbolSsm.cpp new file mode 100644 index 00000000..f03af120 --- /dev/null +++ b/xo-reader2/src/reader2/IPrintable_DExpectSymbolSsm.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DExpectSymbolSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DExpectSymbolSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DExpectSymbolSsm.json5] +**/ + +#include "ssm/IPrintable_DExpectSymbolSsm.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DExpectSymbolSsm::pretty(const DExpectSymbolSsm & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DExpectSymbolSsm.cpp */ diff --git a/xo-reader2/src/reader2/IPrintable_DExpectTypeSsm.cpp b/xo-reader2/src/reader2/IPrintable_DExpectTypeSsm.cpp new file mode 100644 index 00000000..14c20d53 --- /dev/null +++ b/xo-reader2/src/reader2/IPrintable_DExpectTypeSsm.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DExpectTypeSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DExpectTypeSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DExpectTypeSsm.json5] +**/ + +#include "ssm/IPrintable_DExpectTypeSsm.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DExpectTypeSsm::pretty(const DExpectTypeSsm & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DExpectTypeSsm.cpp */ diff --git a/xo-reader2/src/reader2/IPrintable_DIfElseSsm.cpp b/xo-reader2/src/reader2/IPrintable_DIfElseSsm.cpp new file mode 100644 index 00000000..d0ef4bb3 --- /dev/null +++ b/xo-reader2/src/reader2/IPrintable_DIfElseSsm.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DIfElseSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DIfElseSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DIfElseSsm.json5] +**/ + +#include "ssm/IPrintable_DIfElseSsm.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DIfElseSsm::pretty(const DIfElseSsm & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DIfElseSsm.cpp */ diff --git a/xo-reader2/src/reader2/IPrintable_DLambdaSsm.cpp b/xo-reader2/src/reader2/IPrintable_DLambdaSsm.cpp new file mode 100644 index 00000000..4e7a09d8 --- /dev/null +++ b/xo-reader2/src/reader2/IPrintable_DLambdaSsm.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DLambdaSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DLambdaSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DLambdaSsm.json5] +**/ + +#include "ssm/IPrintable_DLambdaSsm.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DLambdaSsm::pretty(const DLambdaSsm & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DLambdaSsm.cpp */ diff --git a/xo-reader2/src/reader2/IPrintable_DParenSsm.cpp b/xo-reader2/src/reader2/IPrintable_DParenSsm.cpp new file mode 100644 index 00000000..b2228f7f --- /dev/null +++ b/xo-reader2/src/reader2/IPrintable_DParenSsm.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DParenSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DParenSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DParenSsm.json5] +**/ + +#include "ssm/IPrintable_DParenSsm.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DParenSsm::pretty(const DParenSsm & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DParenSsm.cpp */ diff --git a/xo-reader2/src/reader2/IPrintable_DProgressSsm.cpp b/xo-reader2/src/reader2/IPrintable_DProgressSsm.cpp new file mode 100644 index 00000000..bd9dd7e8 --- /dev/null +++ b/xo-reader2/src/reader2/IPrintable_DProgressSsm.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DProgressSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DProgressSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DProgressSsm.json5] +**/ + +#include "ssm/IPrintable_DProgressSsm.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DProgressSsm::pretty(const DProgressSsm & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DProgressSsm.cpp */ diff --git a/xo-reader2/src/reader2/IPrintable_DSequenceSsm.cpp b/xo-reader2/src/reader2/IPrintable_DSequenceSsm.cpp new file mode 100644 index 00000000..8c525ba8 --- /dev/null +++ b/xo-reader2/src/reader2/IPrintable_DSequenceSsm.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DSequenceSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DSequenceSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DSequenceSsm.json5] +**/ + +#include "ssm/IPrintable_DSequenceSsm.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DSequenceSsm::pretty(const DSequenceSsm & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DSequenceSsm.cpp */ diff --git a/xo-reader2/src/reader2/IPrintable_DToplevelSeqSsm.cpp b/xo-reader2/src/reader2/IPrintable_DToplevelSeqSsm.cpp new file mode 100644 index 00000000..7a958fa8 --- /dev/null +++ b/xo-reader2/src/reader2/IPrintable_DToplevelSeqSsm.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DToplevelSeqSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DToplevelSeqSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DToplevelSeqSsm.json5] +**/ + +#include "ssm/IPrintable_DToplevelSeqSsm.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DToplevelSeqSsm::pretty(const DToplevelSeqSsm & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DToplevelSeqSsm.cpp */ diff --git a/xo-reader2/src/reader2/ISyntaxStateMachine_Any.cpp b/xo-reader2/src/reader2/ISyntaxStateMachine_Any.cpp new file mode 100644 index 00000000..393fea04 --- /dev/null +++ b/xo-reader2/src/reader2/ISyntaxStateMachine_Any.cpp @@ -0,0 +1,89 @@ +/** @file ISyntaxStateMachine_Any.cpp + * + **/ + +#include "ssm/ISyntaxStateMachine_Any.hpp" +#include + +namespace xo { +namespace scm { + +using xo::facet::DVariantPlaceholder; +using xo::facet::typeseq; +using xo::facet::valid_facet_implementation; + +void +ISyntaxStateMachine_Any::_fatal() +{ + /* control here on uninitialized IAllocator_Any. + * Initialized instance will have specific implementation type + */ + std::cerr << "fatal" + << ": attempt to call uninitialized" + << " ISyntaxStateMachine_Any method" + << std::endl; + std::terminate(); +} + +typeseq +ISyntaxStateMachine_Any::s_typeseq = typeseq::id(); + +bool +ISyntaxStateMachine_Any::_valid + = valid_facet_implementation(); + +// nonconst methods + +auto +ISyntaxStateMachine_Any::on_token(Opaque, const Token &, ParserStateMachine *) -> void +{ + _fatal(); +} + +auto +ISyntaxStateMachine_Any::on_parsed_symbol(Opaque, std::string_view, ParserStateMachine *) -> void +{ + _fatal(); +} + +auto +ISyntaxStateMachine_Any::on_parsed_typedescr(Opaque, TypeDescr, ParserStateMachine *) -> void +{ + _fatal(); +} + +auto +ISyntaxStateMachine_Any::on_parsed_formal(Opaque, const DUniqueString *, TypeDescr, ParserStateMachine *) -> void +{ + _fatal(); +} + +auto +ISyntaxStateMachine_Any::on_parsed_formal_with_token(Opaque, const DUniqueString *, TypeDescr, const Token &, ParserStateMachine *) -> void +{ + _fatal(); +} + +auto +ISyntaxStateMachine_Any::on_parsed_formal_arglist(Opaque, DArray *, ParserStateMachine *) -> void +{ + _fatal(); +} + +auto +ISyntaxStateMachine_Any::on_parsed_expression(Opaque, obj, ParserStateMachine *) -> void +{ + _fatal(); +} + +auto +ISyntaxStateMachine_Any::on_parsed_expression_with_token(Opaque, obj, const Token &, ParserStateMachine *) -> void +{ + _fatal(); +} + + +} /*namespace scm*/ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_Any.cpp */ diff --git a/xo-reader2/src/reader2/ISyntaxStateMachine_DApplySsm.cpp b/xo-reader2/src/reader2/ISyntaxStateMachine_DApplySsm.cpp new file mode 100644 index 00000000..bcc672a4 --- /dev/null +++ b/xo-reader2/src/reader2/ISyntaxStateMachine_DApplySsm.cpp @@ -0,0 +1,74 @@ +/** @file ISyntaxStateMachine_DApplySsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DApplySsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DApplySsm.json5] +**/ + +#include "ssm/ISyntaxStateMachine_DApplySsm.hpp" + +namespace xo { + namespace scm { + auto + ISyntaxStateMachine_DApplySsm::ssm_type(const DApplySsm & self) noexcept -> syntaxstatetype + { + return self.ssm_type(); + } + + auto + ISyntaxStateMachine_DApplySsm::get_expect_str(const DApplySsm & self) noexcept -> std::string_view + { + return self.get_expect_str(); + } + + auto + ISyntaxStateMachine_DApplySsm::on_token(DApplySsm & self, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_token(tk, p_psm); + } + auto + ISyntaxStateMachine_DApplySsm::on_parsed_symbol(DApplySsm & self, std::string_view sym, ParserStateMachine * p_psm) -> void + { + self.on_parsed_symbol(sym, p_psm); + } + auto + ISyntaxStateMachine_DApplySsm::on_parsed_typedescr(DApplySsm & self, TypeDescr td, ParserStateMachine * p_psm) -> void + { + self.on_parsed_typedescr(td, p_psm); + } + auto + ISyntaxStateMachine_DApplySsm::on_parsed_formal(DApplySsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal(param_name, param_type, p_psm); + } + auto + ISyntaxStateMachine_DApplySsm::on_parsed_formal_with_token(DApplySsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm); + } + auto + ISyntaxStateMachine_DApplySsm::on_parsed_formal_arglist(DApplySsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_arglist(arglist, p_psm); + } + auto + ISyntaxStateMachine_DApplySsm::on_parsed_expression(DApplySsm & self, obj expr, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression(expr, p_psm); + } + auto + ISyntaxStateMachine_DApplySsm::on_parsed_expression_with_token(DApplySsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression_with_token(expr, tk, p_psm); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_DApplySsm.cpp */ diff --git a/xo-reader2/src/reader2/ISyntaxStateMachine_DDefineSsm.cpp b/xo-reader2/src/reader2/ISyntaxStateMachine_DDefineSsm.cpp new file mode 100644 index 00000000..dad9d0e8 --- /dev/null +++ b/xo-reader2/src/reader2/ISyntaxStateMachine_DDefineSsm.cpp @@ -0,0 +1,74 @@ +/** @file ISyntaxStateMachine_DDefineSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DDefineSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DDefineSsm.json5] +**/ + +#include "ssm/ISyntaxStateMachine_DDefineSsm.hpp" + +namespace xo { + namespace scm { + auto + ISyntaxStateMachine_DDefineSsm::ssm_type(const DDefineSsm & self) noexcept -> syntaxstatetype + { + return self.ssm_type(); + } + + auto + ISyntaxStateMachine_DDefineSsm::get_expect_str(const DDefineSsm & self) noexcept -> std::string_view + { + return self.get_expect_str(); + } + + auto + ISyntaxStateMachine_DDefineSsm::on_token(DDefineSsm & self, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_token(tk, p_psm); + } + auto + ISyntaxStateMachine_DDefineSsm::on_parsed_symbol(DDefineSsm & self, std::string_view sym, ParserStateMachine * p_psm) -> void + { + self.on_parsed_symbol(sym, p_psm); + } + auto + ISyntaxStateMachine_DDefineSsm::on_parsed_typedescr(DDefineSsm & self, TypeDescr td, ParserStateMachine * p_psm) -> void + { + self.on_parsed_typedescr(td, p_psm); + } + auto + ISyntaxStateMachine_DDefineSsm::on_parsed_formal(DDefineSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal(param_name, param_type, p_psm); + } + auto + ISyntaxStateMachine_DDefineSsm::on_parsed_formal_with_token(DDefineSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm); + } + auto + ISyntaxStateMachine_DDefineSsm::on_parsed_formal_arglist(DDefineSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_arglist(arglist, p_psm); + } + auto + ISyntaxStateMachine_DDefineSsm::on_parsed_expression(DDefineSsm & self, obj expr, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression(expr, p_psm); + } + auto + ISyntaxStateMachine_DDefineSsm::on_parsed_expression_with_token(DDefineSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression_with_token(expr, tk, p_psm); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_DDefineSsm.cpp */ diff --git a/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectExprSsm.cpp b/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectExprSsm.cpp new file mode 100644 index 00000000..855135e6 --- /dev/null +++ b/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectExprSsm.cpp @@ -0,0 +1,74 @@ +/** @file ISyntaxStateMachine_DExpectExprSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DExpectExprSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DExpectExprSsm.json5] +**/ + +#include "ssm/ISyntaxStateMachine_DExpectExprSsm.hpp" + +namespace xo { + namespace scm { + auto + ISyntaxStateMachine_DExpectExprSsm::ssm_type(const DExpectExprSsm & self) noexcept -> syntaxstatetype + { + return self.ssm_type(); + } + + auto + ISyntaxStateMachine_DExpectExprSsm::get_expect_str(const DExpectExprSsm & self) noexcept -> std::string_view + { + return self.get_expect_str(); + } + + auto + ISyntaxStateMachine_DExpectExprSsm::on_token(DExpectExprSsm & self, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_token(tk, p_psm); + } + auto + ISyntaxStateMachine_DExpectExprSsm::on_parsed_symbol(DExpectExprSsm & self, std::string_view sym, ParserStateMachine * p_psm) -> void + { + self.on_parsed_symbol(sym, p_psm); + } + auto + ISyntaxStateMachine_DExpectExprSsm::on_parsed_typedescr(DExpectExprSsm & self, TypeDescr td, ParserStateMachine * p_psm) -> void + { + self.on_parsed_typedescr(td, p_psm); + } + auto + ISyntaxStateMachine_DExpectExprSsm::on_parsed_formal(DExpectExprSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal(param_name, param_type, p_psm); + } + auto + ISyntaxStateMachine_DExpectExprSsm::on_parsed_formal_with_token(DExpectExprSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm); + } + auto + ISyntaxStateMachine_DExpectExprSsm::on_parsed_formal_arglist(DExpectExprSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_arglist(arglist, p_psm); + } + auto + ISyntaxStateMachine_DExpectExprSsm::on_parsed_expression(DExpectExprSsm & self, obj expr, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression(expr, p_psm); + } + auto + ISyntaxStateMachine_DExpectExprSsm::on_parsed_expression_with_token(DExpectExprSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression_with_token(expr, tk, p_psm); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_DExpectExprSsm.cpp */ diff --git a/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectFormalArgSsm.cpp b/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectFormalArgSsm.cpp new file mode 100644 index 00000000..948a4fe2 --- /dev/null +++ b/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectFormalArgSsm.cpp @@ -0,0 +1,74 @@ +/** @file ISyntaxStateMachine_DExpectFormalArgSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DExpectFormalArgSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DExpectFormalArgSsm.json5] +**/ + +#include "ssm/ISyntaxStateMachine_DExpectFormalArgSsm.hpp" + +namespace xo { + namespace scm { + auto + ISyntaxStateMachine_DExpectFormalArgSsm::ssm_type(const DExpectFormalArgSsm & self) noexcept -> syntaxstatetype + { + return self.ssm_type(); + } + + auto + ISyntaxStateMachine_DExpectFormalArgSsm::get_expect_str(const DExpectFormalArgSsm & self) noexcept -> std::string_view + { + return self.get_expect_str(); + } + + auto + ISyntaxStateMachine_DExpectFormalArgSsm::on_token(DExpectFormalArgSsm & self, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_token(tk, p_psm); + } + auto + ISyntaxStateMachine_DExpectFormalArgSsm::on_parsed_symbol(DExpectFormalArgSsm & self, std::string_view sym, ParserStateMachine * p_psm) -> void + { + self.on_parsed_symbol(sym, p_psm); + } + auto + ISyntaxStateMachine_DExpectFormalArgSsm::on_parsed_typedescr(DExpectFormalArgSsm & self, TypeDescr td, ParserStateMachine * p_psm) -> void + { + self.on_parsed_typedescr(td, p_psm); + } + auto + ISyntaxStateMachine_DExpectFormalArgSsm::on_parsed_formal(DExpectFormalArgSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal(param_name, param_type, p_psm); + } + auto + ISyntaxStateMachine_DExpectFormalArgSsm::on_parsed_formal_with_token(DExpectFormalArgSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm); + } + auto + ISyntaxStateMachine_DExpectFormalArgSsm::on_parsed_formal_arglist(DExpectFormalArgSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_arglist(arglist, p_psm); + } + auto + ISyntaxStateMachine_DExpectFormalArgSsm::on_parsed_expression(DExpectFormalArgSsm & self, obj expr, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression(expr, p_psm); + } + auto + ISyntaxStateMachine_DExpectFormalArgSsm::on_parsed_expression_with_token(DExpectFormalArgSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression_with_token(expr, tk, p_psm); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_DExpectFormalArgSsm.cpp */ diff --git a/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectFormalArglistSsm.cpp b/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectFormalArglistSsm.cpp new file mode 100644 index 00000000..f56a90d2 --- /dev/null +++ b/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectFormalArglistSsm.cpp @@ -0,0 +1,74 @@ +/** @file ISyntaxStateMachine_DExpectFormalArglistSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DExpectFormalArglistSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DExpectFormalArglistSsm.json5] +**/ + +#include "ssm/ISyntaxStateMachine_DExpectFormalArglistSsm.hpp" + +namespace xo { + namespace scm { + auto + ISyntaxStateMachine_DExpectFormalArglistSsm::ssm_type(const DExpectFormalArglistSsm & self) noexcept -> syntaxstatetype + { + return self.ssm_type(); + } + + auto + ISyntaxStateMachine_DExpectFormalArglistSsm::get_expect_str(const DExpectFormalArglistSsm & self) noexcept -> std::string_view + { + return self.get_expect_str(); + } + + auto + ISyntaxStateMachine_DExpectFormalArglistSsm::on_token(DExpectFormalArglistSsm & self, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_token(tk, p_psm); + } + auto + ISyntaxStateMachine_DExpectFormalArglistSsm::on_parsed_symbol(DExpectFormalArglistSsm & self, std::string_view sym, ParserStateMachine * p_psm) -> void + { + self.on_parsed_symbol(sym, p_psm); + } + auto + ISyntaxStateMachine_DExpectFormalArglistSsm::on_parsed_typedescr(DExpectFormalArglistSsm & self, TypeDescr td, ParserStateMachine * p_psm) -> void + { + self.on_parsed_typedescr(td, p_psm); + } + auto + ISyntaxStateMachine_DExpectFormalArglistSsm::on_parsed_formal(DExpectFormalArglistSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal(param_name, param_type, p_psm); + } + auto + ISyntaxStateMachine_DExpectFormalArglistSsm::on_parsed_formal_with_token(DExpectFormalArglistSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm); + } + auto + ISyntaxStateMachine_DExpectFormalArglistSsm::on_parsed_formal_arglist(DExpectFormalArglistSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_arglist(arglist, p_psm); + } + auto + ISyntaxStateMachine_DExpectFormalArglistSsm::on_parsed_expression(DExpectFormalArglistSsm & self, obj expr, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression(expr, p_psm); + } + auto + ISyntaxStateMachine_DExpectFormalArglistSsm::on_parsed_expression_with_token(DExpectFormalArglistSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression_with_token(expr, tk, p_psm); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_DExpectFormalArglistSsm.cpp */ diff --git a/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectSymbolSsm.cpp b/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectSymbolSsm.cpp new file mode 100644 index 00000000..77f0fd10 --- /dev/null +++ b/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectSymbolSsm.cpp @@ -0,0 +1,74 @@ +/** @file ISyntaxStateMachine_DExpectSymbolSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DExpectSymbolSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DExpectSymbolSsm.json5] +**/ + +#include "ssm/ISyntaxStateMachine_DExpectSymbolSsm.hpp" + +namespace xo { + namespace scm { + auto + ISyntaxStateMachine_DExpectSymbolSsm::ssm_type(const DExpectSymbolSsm & self) noexcept -> syntaxstatetype + { + return self.ssm_type(); + } + + auto + ISyntaxStateMachine_DExpectSymbolSsm::get_expect_str(const DExpectSymbolSsm & self) noexcept -> std::string_view + { + return self.get_expect_str(); + } + + auto + ISyntaxStateMachine_DExpectSymbolSsm::on_token(DExpectSymbolSsm & self, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_token(tk, p_psm); + } + auto + ISyntaxStateMachine_DExpectSymbolSsm::on_parsed_symbol(DExpectSymbolSsm & self, std::string_view sym, ParserStateMachine * p_psm) -> void + { + self.on_parsed_symbol(sym, p_psm); + } + auto + ISyntaxStateMachine_DExpectSymbolSsm::on_parsed_typedescr(DExpectSymbolSsm & self, TypeDescr td, ParserStateMachine * p_psm) -> void + { + self.on_parsed_typedescr(td, p_psm); + } + auto + ISyntaxStateMachine_DExpectSymbolSsm::on_parsed_formal(DExpectSymbolSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal(param_name, param_type, p_psm); + } + auto + ISyntaxStateMachine_DExpectSymbolSsm::on_parsed_formal_with_token(DExpectSymbolSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm); + } + auto + ISyntaxStateMachine_DExpectSymbolSsm::on_parsed_formal_arglist(DExpectSymbolSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_arglist(arglist, p_psm); + } + auto + ISyntaxStateMachine_DExpectSymbolSsm::on_parsed_expression(DExpectSymbolSsm & self, obj expr, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression(expr, p_psm); + } + auto + ISyntaxStateMachine_DExpectSymbolSsm::on_parsed_expression_with_token(DExpectSymbolSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression_with_token(expr, tk, p_psm); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_DExpectSymbolSsm.cpp */ diff --git a/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectTypeSsm.cpp b/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectTypeSsm.cpp new file mode 100644 index 00000000..f5f650ae --- /dev/null +++ b/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectTypeSsm.cpp @@ -0,0 +1,74 @@ +/** @file ISyntaxStateMachine_DExpectTypeSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DExpectTypeSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DExpectTypeSsm.json5] +**/ + +#include "ssm/ISyntaxStateMachine_DExpectTypeSsm.hpp" + +namespace xo { + namespace scm { + auto + ISyntaxStateMachine_DExpectTypeSsm::ssm_type(const DExpectTypeSsm & self) noexcept -> syntaxstatetype + { + return self.ssm_type(); + } + + auto + ISyntaxStateMachine_DExpectTypeSsm::get_expect_str(const DExpectTypeSsm & self) noexcept -> std::string_view + { + return self.get_expect_str(); + } + + auto + ISyntaxStateMachine_DExpectTypeSsm::on_token(DExpectTypeSsm & self, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_token(tk, p_psm); + } + auto + ISyntaxStateMachine_DExpectTypeSsm::on_parsed_symbol(DExpectTypeSsm & self, std::string_view sym, ParserStateMachine * p_psm) -> void + { + self.on_parsed_symbol(sym, p_psm); + } + auto + ISyntaxStateMachine_DExpectTypeSsm::on_parsed_typedescr(DExpectTypeSsm & self, TypeDescr td, ParserStateMachine * p_psm) -> void + { + self.on_parsed_typedescr(td, p_psm); + } + auto + ISyntaxStateMachine_DExpectTypeSsm::on_parsed_formal(DExpectTypeSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal(param_name, param_type, p_psm); + } + auto + ISyntaxStateMachine_DExpectTypeSsm::on_parsed_formal_with_token(DExpectTypeSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm); + } + auto + ISyntaxStateMachine_DExpectTypeSsm::on_parsed_formal_arglist(DExpectTypeSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_arglist(arglist, p_psm); + } + auto + ISyntaxStateMachine_DExpectTypeSsm::on_parsed_expression(DExpectTypeSsm & self, obj expr, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression(expr, p_psm); + } + auto + ISyntaxStateMachine_DExpectTypeSsm::on_parsed_expression_with_token(DExpectTypeSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression_with_token(expr, tk, p_psm); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_DExpectTypeSsm.cpp */ diff --git a/xo-reader2/src/reader2/ISyntaxStateMachine_DIfElseSsm.cpp b/xo-reader2/src/reader2/ISyntaxStateMachine_DIfElseSsm.cpp new file mode 100644 index 00000000..d5a78844 --- /dev/null +++ b/xo-reader2/src/reader2/ISyntaxStateMachine_DIfElseSsm.cpp @@ -0,0 +1,74 @@ +/** @file ISyntaxStateMachine_DIfElseSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DIfElseSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DIfElseSsm.json5] +**/ + +#include "ssm/ISyntaxStateMachine_DIfElseSsm.hpp" + +namespace xo { + namespace scm { + auto + ISyntaxStateMachine_DIfElseSsm::ssm_type(const DIfElseSsm & self) noexcept -> syntaxstatetype + { + return self.ssm_type(); + } + + auto + ISyntaxStateMachine_DIfElseSsm::get_expect_str(const DIfElseSsm & self) noexcept -> std::string_view + { + return self.get_expect_str(); + } + + auto + ISyntaxStateMachine_DIfElseSsm::on_token(DIfElseSsm & self, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_token(tk, p_psm); + } + auto + ISyntaxStateMachine_DIfElseSsm::on_parsed_symbol(DIfElseSsm & self, std::string_view sym, ParserStateMachine * p_psm) -> void + { + self.on_parsed_symbol(sym, p_psm); + } + auto + ISyntaxStateMachine_DIfElseSsm::on_parsed_typedescr(DIfElseSsm & self, TypeDescr td, ParserStateMachine * p_psm) -> void + { + self.on_parsed_typedescr(td, p_psm); + } + auto + ISyntaxStateMachine_DIfElseSsm::on_parsed_formal(DIfElseSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal(param_name, param_type, p_psm); + } + auto + ISyntaxStateMachine_DIfElseSsm::on_parsed_formal_with_token(DIfElseSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm); + } + auto + ISyntaxStateMachine_DIfElseSsm::on_parsed_formal_arglist(DIfElseSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_arglist(arglist, p_psm); + } + auto + ISyntaxStateMachine_DIfElseSsm::on_parsed_expression(DIfElseSsm & self, obj expr, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression(expr, p_psm); + } + auto + ISyntaxStateMachine_DIfElseSsm::on_parsed_expression_with_token(DIfElseSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression_with_token(expr, tk, p_psm); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_DIfElseSsm.cpp */ diff --git a/xo-reader2/src/reader2/ISyntaxStateMachine_DLambdaSsm.cpp b/xo-reader2/src/reader2/ISyntaxStateMachine_DLambdaSsm.cpp new file mode 100644 index 00000000..f99ab05d --- /dev/null +++ b/xo-reader2/src/reader2/ISyntaxStateMachine_DLambdaSsm.cpp @@ -0,0 +1,74 @@ +/** @file ISyntaxStateMachine_DLambdaSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DLambdaSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DLambdaSsm.json5] +**/ + +#include "ssm/ISyntaxStateMachine_DLambdaSsm.hpp" + +namespace xo { + namespace scm { + auto + ISyntaxStateMachine_DLambdaSsm::ssm_type(const DLambdaSsm & self) noexcept -> syntaxstatetype + { + return self.ssm_type(); + } + + auto + ISyntaxStateMachine_DLambdaSsm::get_expect_str(const DLambdaSsm & self) noexcept -> std::string_view + { + return self.get_expect_str(); + } + + auto + ISyntaxStateMachine_DLambdaSsm::on_token(DLambdaSsm & self, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_token(tk, p_psm); + } + auto + ISyntaxStateMachine_DLambdaSsm::on_parsed_symbol(DLambdaSsm & self, std::string_view sym, ParserStateMachine * p_psm) -> void + { + self.on_parsed_symbol(sym, p_psm); + } + auto + ISyntaxStateMachine_DLambdaSsm::on_parsed_typedescr(DLambdaSsm & self, TypeDescr td, ParserStateMachine * p_psm) -> void + { + self.on_parsed_typedescr(td, p_psm); + } + auto + ISyntaxStateMachine_DLambdaSsm::on_parsed_formal(DLambdaSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal(param_name, param_type, p_psm); + } + auto + ISyntaxStateMachine_DLambdaSsm::on_parsed_formal_with_token(DLambdaSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm); + } + auto + ISyntaxStateMachine_DLambdaSsm::on_parsed_formal_arglist(DLambdaSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_arglist(arglist, p_psm); + } + auto + ISyntaxStateMachine_DLambdaSsm::on_parsed_expression(DLambdaSsm & self, obj expr, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression(expr, p_psm); + } + auto + ISyntaxStateMachine_DLambdaSsm::on_parsed_expression_with_token(DLambdaSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression_with_token(expr, tk, p_psm); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_DLambdaSsm.cpp */ diff --git a/xo-reader2/src/reader2/ISyntaxStateMachine_DParenSsm.cpp b/xo-reader2/src/reader2/ISyntaxStateMachine_DParenSsm.cpp new file mode 100644 index 00000000..0773ff3f --- /dev/null +++ b/xo-reader2/src/reader2/ISyntaxStateMachine_DParenSsm.cpp @@ -0,0 +1,74 @@ +/** @file ISyntaxStateMachine_DParenSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DParenSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DParenSsm.json5] +**/ + +#include "ssm/ISyntaxStateMachine_DParenSsm.hpp" + +namespace xo { + namespace scm { + auto + ISyntaxStateMachine_DParenSsm::ssm_type(const DParenSsm & self) noexcept -> syntaxstatetype + { + return self.ssm_type(); + } + + auto + ISyntaxStateMachine_DParenSsm::get_expect_str(const DParenSsm & self) noexcept -> std::string_view + { + return self.get_expect_str(); + } + + auto + ISyntaxStateMachine_DParenSsm::on_token(DParenSsm & self, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_token(tk, p_psm); + } + auto + ISyntaxStateMachine_DParenSsm::on_parsed_symbol(DParenSsm & self, std::string_view sym, ParserStateMachine * p_psm) -> void + { + self.on_parsed_symbol(sym, p_psm); + } + auto + ISyntaxStateMachine_DParenSsm::on_parsed_typedescr(DParenSsm & self, TypeDescr td, ParserStateMachine * p_psm) -> void + { + self.on_parsed_typedescr(td, p_psm); + } + auto + ISyntaxStateMachine_DParenSsm::on_parsed_formal(DParenSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal(param_name, param_type, p_psm); + } + auto + ISyntaxStateMachine_DParenSsm::on_parsed_formal_with_token(DParenSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm); + } + auto + ISyntaxStateMachine_DParenSsm::on_parsed_formal_arglist(DParenSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_arglist(arglist, p_psm); + } + auto + ISyntaxStateMachine_DParenSsm::on_parsed_expression(DParenSsm & self, obj expr, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression(expr, p_psm); + } + auto + ISyntaxStateMachine_DParenSsm::on_parsed_expression_with_token(DParenSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression_with_token(expr, tk, p_psm); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_DParenSsm.cpp */ diff --git a/xo-reader2/src/reader2/ISyntaxStateMachine_DProgressSsm.cpp b/xo-reader2/src/reader2/ISyntaxStateMachine_DProgressSsm.cpp new file mode 100644 index 00000000..0e1e4a4c --- /dev/null +++ b/xo-reader2/src/reader2/ISyntaxStateMachine_DProgressSsm.cpp @@ -0,0 +1,74 @@ +/** @file ISyntaxStateMachine_DProgressSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DProgressSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DProgressSsm.json5] +**/ + +#include "ssm/ISyntaxStateMachine_DProgressSsm.hpp" + +namespace xo { + namespace scm { + auto + ISyntaxStateMachine_DProgressSsm::ssm_type(const DProgressSsm & self) noexcept -> syntaxstatetype + { + return self.ssm_type(); + } + + auto + ISyntaxStateMachine_DProgressSsm::get_expect_str(const DProgressSsm & self) noexcept -> std::string_view + { + return self.get_expect_str(); + } + + auto + ISyntaxStateMachine_DProgressSsm::on_token(DProgressSsm & self, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_token(tk, p_psm); + } + auto + ISyntaxStateMachine_DProgressSsm::on_parsed_symbol(DProgressSsm & self, std::string_view sym, ParserStateMachine * p_psm) -> void + { + self.on_parsed_symbol(sym, p_psm); + } + auto + ISyntaxStateMachine_DProgressSsm::on_parsed_typedescr(DProgressSsm & self, TypeDescr td, ParserStateMachine * p_psm) -> void + { + self.on_parsed_typedescr(td, p_psm); + } + auto + ISyntaxStateMachine_DProgressSsm::on_parsed_formal(DProgressSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal(param_name, param_type, p_psm); + } + auto + ISyntaxStateMachine_DProgressSsm::on_parsed_formal_with_token(DProgressSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm); + } + auto + ISyntaxStateMachine_DProgressSsm::on_parsed_formal_arglist(DProgressSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_arglist(arglist, p_psm); + } + auto + ISyntaxStateMachine_DProgressSsm::on_parsed_expression(DProgressSsm & self, obj expr, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression(expr, p_psm); + } + auto + ISyntaxStateMachine_DProgressSsm::on_parsed_expression_with_token(DProgressSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression_with_token(expr, tk, p_psm); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_DProgressSsm.cpp */ diff --git a/xo-reader2/src/reader2/ISyntaxStateMachine_DSequenceSsm.cpp b/xo-reader2/src/reader2/ISyntaxStateMachine_DSequenceSsm.cpp new file mode 100644 index 00000000..bc6ab823 --- /dev/null +++ b/xo-reader2/src/reader2/ISyntaxStateMachine_DSequenceSsm.cpp @@ -0,0 +1,74 @@ +/** @file ISyntaxStateMachine_DSequenceSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DSequenceSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DSequenceSsm.json5] +**/ + +#include "ssm/ISyntaxStateMachine_DSequenceSsm.hpp" + +namespace xo { + namespace scm { + auto + ISyntaxStateMachine_DSequenceSsm::ssm_type(const DSequenceSsm & self) noexcept -> syntaxstatetype + { + return self.ssm_type(); + } + + auto + ISyntaxStateMachine_DSequenceSsm::get_expect_str(const DSequenceSsm & self) noexcept -> std::string_view + { + return self.get_expect_str(); + } + + auto + ISyntaxStateMachine_DSequenceSsm::on_token(DSequenceSsm & self, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_token(tk, p_psm); + } + auto + ISyntaxStateMachine_DSequenceSsm::on_parsed_symbol(DSequenceSsm & self, std::string_view sym, ParserStateMachine * p_psm) -> void + { + self.on_parsed_symbol(sym, p_psm); + } + auto + ISyntaxStateMachine_DSequenceSsm::on_parsed_typedescr(DSequenceSsm & self, TypeDescr td, ParserStateMachine * p_psm) -> void + { + self.on_parsed_typedescr(td, p_psm); + } + auto + ISyntaxStateMachine_DSequenceSsm::on_parsed_formal(DSequenceSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal(param_name, param_type, p_psm); + } + auto + ISyntaxStateMachine_DSequenceSsm::on_parsed_formal_with_token(DSequenceSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm); + } + auto + ISyntaxStateMachine_DSequenceSsm::on_parsed_formal_arglist(DSequenceSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_arglist(arglist, p_psm); + } + auto + ISyntaxStateMachine_DSequenceSsm::on_parsed_expression(DSequenceSsm & self, obj expr, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression(expr, p_psm); + } + auto + ISyntaxStateMachine_DSequenceSsm::on_parsed_expression_with_token(DSequenceSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression_with_token(expr, tk, p_psm); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_DSequenceSsm.cpp */ diff --git a/xo-reader2/src/reader2/ISyntaxStateMachine_DToplevelSeqSsm.cpp b/xo-reader2/src/reader2/ISyntaxStateMachine_DToplevelSeqSsm.cpp new file mode 100644 index 00000000..6850aee1 --- /dev/null +++ b/xo-reader2/src/reader2/ISyntaxStateMachine_DToplevelSeqSsm.cpp @@ -0,0 +1,74 @@ +/** @file ISyntaxStateMachine_DToplevelSeqSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DToplevelSeqSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DToplevelSeqSsm.json5] +**/ + +#include "ssm/ISyntaxStateMachine_DToplevelSeqSsm.hpp" + +namespace xo { + namespace scm { + auto + ISyntaxStateMachine_DToplevelSeqSsm::ssm_type(const DToplevelSeqSsm & self) noexcept -> syntaxstatetype + { + return self.ssm_type(); + } + + auto + ISyntaxStateMachine_DToplevelSeqSsm::get_expect_str(const DToplevelSeqSsm & self) noexcept -> std::string_view + { + return self.get_expect_str(); + } + + auto + ISyntaxStateMachine_DToplevelSeqSsm::on_token(DToplevelSeqSsm & self, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_token(tk, p_psm); + } + auto + ISyntaxStateMachine_DToplevelSeqSsm::on_parsed_symbol(DToplevelSeqSsm & self, std::string_view sym, ParserStateMachine * p_psm) -> void + { + self.on_parsed_symbol(sym, p_psm); + } + auto + ISyntaxStateMachine_DToplevelSeqSsm::on_parsed_typedescr(DToplevelSeqSsm & self, TypeDescr td, ParserStateMachine * p_psm) -> void + { + self.on_parsed_typedescr(td, p_psm); + } + auto + ISyntaxStateMachine_DToplevelSeqSsm::on_parsed_formal(DToplevelSeqSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal(param_name, param_type, p_psm); + } + auto + ISyntaxStateMachine_DToplevelSeqSsm::on_parsed_formal_with_token(DToplevelSeqSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm); + } + auto + ISyntaxStateMachine_DToplevelSeqSsm::on_parsed_formal_arglist(DToplevelSeqSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_arglist(arglist, p_psm); + } + auto + ISyntaxStateMachine_DToplevelSeqSsm::on_parsed_expression(DToplevelSeqSsm & self, obj expr, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression(expr, p_psm); + } + auto + ISyntaxStateMachine_DToplevelSeqSsm::on_parsed_expression_with_token(DToplevelSeqSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression_with_token(expr, tk, p_psm); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_DToplevelSeqSsm.cpp */ diff --git a/xo-reader2/src/reader2/ParserResult.cpp b/xo-reader2/src/reader2/ParserResult.cpp new file mode 100644 index 00000000..974724d9 --- /dev/null +++ b/xo-reader2/src/reader2/ParserResult.cpp @@ -0,0 +1,108 @@ +/** @file ParserResult.cpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#include "ParserResult.hpp" +#include +#include + +namespace xo { + using xo::print::APrintable; + using xo::facet::FacetRegistry; + + namespace scm { + + const char * + parser_result_type_descr(parser_result_type x) + { + switch (x) { + case parser_result_type::none: return "none"; + case parser_result_type::expression: return "expression"; + case parser_result_type::error: return "error"; + case parser_result_type::N: break; + } + + return "parser_result_type?"; + } + + ParserResult::ParserResult(parser_result_type type, + obj expr, + std::string_view error_src_fn, + const DString * error_description) + : result_type_{type}, + result_expr_{expr}, + error_src_fn_{error_src_fn}, + error_description_{error_description} + {} + + ParserResult + ParserResult::expression(std::string_view ssm_name, + obj expr) + { + return ParserResult(parser_result_type::expression, + expr, + ssm_name, + nullptr); + } + + ParserResult + ParserResult::error(std::string_view ssm_name, + const DString * errmsg) + { + return ParserResult(parser_result_type::error, + obj(), + ssm_name, + errmsg); + } + + void + ParserResult::print(std::ostream & os) const + { + os << ""; + } + + bool + ParserResult::pretty(const ppindentinfo & ppii) const + { + switch (result_type_) { + case parser_result_type::none: + return ppii.pps()->pretty_struct + (ppii, + "ParserResult", + refrtag("type", result_type_)); + case parser_result_type::expression: + { + auto expr = FacetRegistry::instance().variant(result_expr_); + + return ppii.pps()->pretty_struct + (ppii, + "ParserResult", + refrtag("type", result_type_), + refrtag("expr", expr)); + } + break; + case parser_result_type::error: + return ppii.pps()->pretty_struct + (ppii, + "ParserResult", + refrtag("type", result_type_), + refrtag("src_fn", error_src_fn_), + refrtag("error", error_description_)); + case parser_result_type::N: + assert(false); + break; + } + + return false; + } + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ParserResult.cpp */ diff --git a/xo-reader2/src/reader2/ParserStack.cpp b/xo-reader2/src/reader2/ParserStack.cpp new file mode 100644 index 00000000..9ab919b2 --- /dev/null +++ b/xo-reader2/src/reader2/ParserStack.cpp @@ -0,0 +1,95 @@ +/** @file ParserStack.cpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#include "ParserStack.hpp" +#include "SyntaxStateMachine.hpp" +#include +#include + +namespace xo { + using xo::print::APrintable; + using xo::facet::FacetRegistry; + using xo::facet::typeseq; + + namespace scm { + ParserStack::ParserStack(DArena::Checkpoint ckp, + obj ssm, + ParserStack * parent) + : ckp_{ckp}, ssm_{ssm}, parent_{parent} + {} + + ParserStack * + ParserStack::push(ParserStack * stack, + DArena::Checkpoint ckp, + DArena & mm, + obj ssm) + + { + //DArena::Checkpoint ckp = mm.checkpoint(); // wrong, must precede allocation of ssm + + void * mem = mm.alloc(typeseq::id(), + sizeof(ParserStack)); + + return new (mem) ParserStack(ckp, ssm, stack); + } + + ParserStack * + ParserStack::pop(ParserStack * stack, + DArena & mm) + { + assert(stack); + + mm.restore(stack->ckp()); + + return stack->parent(); + } + + void + ParserStack::print(std::ostream & os) const + { + os << ""; + os << xtag("ssm", "*placeholder*"); + os << xtag("parent", "*placeholder*"); + os << ">"; + } + + bool + ParserStack::pretty(const ppindentinfo & ppii) const + { + auto * pps = ppii.pps(); + + /* always use multiple lines */ + + if (ppii.upto()) + return false; + + pps->write(" (frame->top())); + assert(ssm.data()); + + pps->newline_pretty_tag(ppii.ci1(), buf, ssm); + + ++i_frame; + frame = frame->parent_; + } + + pps->write(">"); + + return false; + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ParserStack.cpp */ diff --git a/xo-reader2/src/reader2/ParserStateMachine.cpp b/xo-reader2/src/reader2/ParserStateMachine.cpp new file mode 100644 index 00000000..dee9e4b2 --- /dev/null +++ b/xo-reader2/src/reader2/ParserStateMachine.cpp @@ -0,0 +1,589 @@ +/** @file ParserStateMachine.cpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#include "ParserStateMachine.hpp" +#include "ParserStack.hpp" +#include "SyntaxStateMachine.hpp" +#include "ToplevelSeqSsm.hpp" +#include "DefineSsm.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace xo { + using xo::mm::MemorySizeInfo; + using xo::print::APrintable; + using xo::facet::FacetRegistry; + using xo::facet::with_facet; + + namespace scm { + ParserStateMachine::ParserStateMachine(const ArenaConfig & config, + const ArenaHashMapConfig & symtab_config, + size_type max_stringtable_capacity, + obj expr_alloc, + obj aux_alloc) + : stringtable_{max_stringtable_capacity}, + parser_alloc_{DArena::map(config)}, + expr_alloc_{expr_alloc}, + aux_alloc_{aux_alloc}, + global_symtab_{DGlobalSymtab::make(expr_alloc, aux_alloc, symtab_config)}, + debug_flag_{config.debug_flag_} + { + } + + bool + ParserStateMachine::is_at_toplevel() const noexcept + { + /* top-level alwyas has DToplevelSeqSsm */ + + ParserStack * s = stack_; + + if (s) { + auto def = obj::from(s->top()); + + if (def) { + /* carve-out for top-level DefineSsm: report 'at top-level' when + * that top-level DefineSsm is on the stack, so we detect + * this condition inside DefineSsm's event handling + */ + s = stack_->parent(); + } + + if (s && s->parent() == nullptr) { + auto top = obj::from(s->top()); + + return top; + } + } else { + /** this isn't a normal operating state, still need a batch/interactive toplevel seq. + * just the same seems better to call it top-level + **/ + return true; + } + + return false; + } + + bool + ParserStateMachine::has_incomplete_expr() const noexcept + { + scope log(XO_DEBUG(debug_flag_)); + + // don't count toplevel expression + + ParserStack * s = stack_; + + if (s) { + auto top = obj::from(s->top()); + + return !top; + } else { + return false; + } + } + + obj + ParserStateMachine::top_ssm() const + { + return this->stack_->top(); + } + + void + ParserStateMachine::visit_pools(const MemorySizeVisitor & visitor) const + { + stringtable_.visit_pools(visitor); + parser_alloc_.visit_pools(visitor); + global_symtab_->visit_pools(visitor); + + // not counting {expr_alloc_, fixed_alloc_}. We don't consider + // either to be owned by ParserStateMachine + } + + void + ParserStateMachine::establish_toplevel_ssm(obj ssm) + { + scope log(XO_DEBUG(debug_flag_)); + + assert(stack_ == nullptr); + + DArena::Checkpoint ckp = parser_alloc_.checkpoint(); + + this->stack_ = ParserStack::push(nullptr /*stack*/, ckp, parser_alloc_, ssm); + this->parser_alloc_ckp_ = parser_alloc_.checkpoint(); + } + + void + ParserStateMachine::push_ssm(DArena::Checkpoint ckp, obj ssm) + { + scope log(XO_DEBUG(debug_flag_)); + + // note: using parser_alloc_ for parser stack, since stacklike behavior + + this->stack_ = ParserStack::push(stack_, ckp, parser_alloc_, ssm); + } + + void + ParserStateMachine::pop_ssm() + { + scope log(XO_DEBUG(debug_flag_)); + + assert(this->stack_); + + this->stack_ = ParserStack::pop(stack_, parser_alloc_); + } + + const DUniqueString * + ParserStateMachine::intern_string(std::string_view str) + { + return stringtable_.intern(str); + } + + const DUniqueString * + ParserStateMachine::gensym(std::string_view str) + { + return stringtable_.gensym(str); + } + + DVarRef * + ParserStateMachine::lookup_varref(std::string_view symbolname) + { + scope log(XO_DEBUG(debug_flag_)); + + const DUniqueString * ustr = stringtable_.lookup(symbolname); + + if (!ustr) { + // if we don't already know the symbol, + // -> can't be a valid variable reference + // (whether global or local) + + return nullptr; + } + + // TODO: + // 1. check global symtab + // 2. combine local+global symtab into indept struct + // 3. move lookup_varref implementation there. + // + + if (local_symtab_) { + DLocalSymtab * symtab = local_symtab_; + + // count #of nested scopes to cross, to reach symbol + // + int32_t link_count = 0; + + while (symtab) { + Binding b = symtab->lookup_binding(ustr); + + if (b.is_local()) { + assert(b.i_link() == 0); + + DVariable * vardef = symtab->lookup_var(b); + assert(vardef); + + /** ascii diagram here + **/ + + return DVarRef::make(expr_alloc_, + vardef, + link_count); + } else { + assert(b.is_null()); + } + + ++link_count; + symtab = symtab->parent(); + } + } + + DVariable * vardef = global_symtab_->lookup_variable(ustr); + + if (vardef) { + return DVarRef::make(expr_alloc_, + vardef, + 0 /*link_count -- n/a for globals*/); + + } + + // symbol not found + return nullptr; + } + + void + ParserStateMachine::push_local_symtab(DLocalSymtab * symtab) + { + this->local_symtab_ = symtab; + } + + void + ParserStateMachine::pop_local_symtab() + { + assert(local_symtab_); + + this->local_symtab_ = local_symtab_->parent(); + } + + void + ParserStateMachine::upsert_var(DVariable * var) + { + assert(global_symtab_); + + global_symtab_->upsert_variable(this->expr_alloc(), var); + } + + void + ParserStateMachine::reset_result() + { + this->result_ = ParserResult(); + } + + void + ParserStateMachine::clear_error_reset() + { + this->reset_result(); + + while (stack_ && stack_->parent()) + stack_ = stack_->parent(); + + this->parser_alloc_.restore(parser_alloc_ckp_); + } + + void + ParserStateMachine::on_parsed_symbol(std::string_view sym) + { + scope log(XO_DEBUG(debug_flag_), xtag("sym", sym)); + + assert(stack_); + + this->stack_->top().on_parsed_symbol(sym, this); + } + + void + ParserStateMachine::on_parsed_typedescr(TypeDescr td) + { + scope log(XO_DEBUG(debug_flag_), xtag("td", td)); + + assert(stack_); + + this->stack_->top().on_parsed_typedescr(td, this); + } + + void + ParserStateMachine::on_parsed_formal(const DUniqueString * sym, + TypeDescr td) + { + scope log(XO_DEBUG(debug_flag_), xtag("sym", std::string_view(*sym)), xtag("td", td)); + + assert(stack_); + + this->stack_->top().on_parsed_formal(sym, td, this); + } + + void + ParserStateMachine::on_parsed_formal_with_token(const DUniqueString * sym, + TypeDescr td, + const Token & tk) + { + scope log(XO_DEBUG(debug_flag_), xtag("sym", std::string_view(*sym)), xtag("td", td), xtag("tk", tk)); + + assert(stack_); + + this->stack_->top().on_parsed_formal_with_token(sym, td, tk, this); + } + + void + ParserStateMachine::on_parsed_formal_arglist(DArray * arglist) + { + scope log(XO_DEBUG(debug_flag_), + xtag("arglist", obj(arglist))); + + assert(stack_); + + this->stack_->top().on_parsed_formal_arglist(arglist, this); + } + + void + ParserStateMachine::on_parsed_expression(obj expr) + { + scope log(XO_DEBUG(debug_flag_), xtag("expr", expr)); + + assert(stack_); + + this->top_ssm().on_parsed_expression(expr, this); + } + + void + ParserStateMachine::on_parsed_expression_with_token(obj expr, + const Token & tk) + { + scope log(XO_DEBUG(debug_flag_), xtag("expr", expr), xtag("tk", tk)); + + assert(stack_); + + this->top_ssm().on_parsed_expression_with_token(expr, tk, this); + } + + void + ParserStateMachine::on_token(const Token & tk) + { + scope log(XO_DEBUG(debug_flag_), xtag("tk", tk)); + + if (!stack_) { + // parsing stack should always have toplevel expression sequence + throw std::runtime_error(tostr("unexpected empty parsing stack", + xtag("token", tk), + xtag("help", "do it the same. but better!") + )); + } + + stack_->top().on_token(tk, this); + } + + void + ParserStateMachine::capture_result(std::string_view ssm_name, + obj expr) + { + this->result_ = ParserResult::expression(ssm_name, expr); + } + + void + ParserStateMachine::capture_error(std::string_view ssm_name, + const DString * errmsg) + { + if (result_.is_error()) { + /* in case one error triggers another, remmber just the first one */ + } else { + this->result_ = ParserResult::error(ssm_name, errmsg); + } + } + + void + ParserStateMachine::illegal_input_on_token(std::string_view ssm_name, + const Token & tk, + std::string_view expect_str) + { + // TODO: + // - want to write error message using DArena + // - need something like log_streambuf and/or tostr() that's arena-aware + + auto errmsg_string = tostr("Unexpected token for parsing state", + xtag("token", tk), + xtag("expecting", expect_str), + xtag("ssm", ssm_name), + xtag("via", "ParserStateMachine::illegal_input_on_token")); + + assert(expr_alloc_); + + auto errmsg = DString::from_view(expr_alloc_, + std::string_view(errmsg_string)); + + this->capture_error(ssm_name, errmsg); + } + + void + ParserStateMachine::illegal_input_on_symbol(std::string_view ssm_name, + std::string_view sym, + std::string_view expect_str) + { + // TODO: + // - want to write error message using DArena + // - need something like log_streambuf and/or tostr() that's arena-aware + + auto errmsg_string = tostr("Unexpected symbol for parsing state", + xtag("symbol", sym), + xtag("expecting", expect_str), + xtag("ssm", ssm_name), + xtag("via", "ParserStateMachine::illegal_input_on_symbol")); + + assert(expr_alloc_); + + auto errmsg = DString::from_view(expr_alloc_, + std::string_view(errmsg_string)); + + this->capture_error(ssm_name, errmsg); + } + + void + ParserStateMachine::illegal_input_on_typedescr(std::string_view ssm_name, + TypeDescr td, + std::string_view expect_str) + { + // TODO: + // - want to write error message using DArena + // - need something like log_streambuf and/or tostr() that's arena-aware + + auto errmsg_string = tostr("Unexpected type-description for parsing state", + xtag("td", td), + xtag("expecting", expect_str), + xtag("ssm", ssm_name), + xtag("via", "ParserStateMachine::illegal_input_on_typedescr")); + + assert(expr_alloc_); + + auto errmsg = DString::from_view(expr_alloc_, + std::string_view(errmsg_string)); + + this->capture_error(ssm_name, errmsg); + } + + void + ParserStateMachine::illegal_parsed_formal(std::string_view ssm_name, + const DUniqueString * param_name, + TypeDescr param_type, + std::string_view expect_str) + { + // TODO: + // - want to write error message using DArena + // - need something like log_streambuf and/or tostr() that's arena-aware + + auto errmsg_string = tostr("Unexpected formal", + xtag("param_name", std::string_view(*param_name)), + xtag("param_type", param_type), + xtag("expecting", expect_str), + xtag("ssm", ssm_name), + xtag("via", "ParserStateMachine::illegal_parsed_formal")); + + assert(expr_alloc_); + + auto errmsg = DString::from_view(expr_alloc_, + std::string_view(errmsg_string)); + + this->capture_error(ssm_name, errmsg); + } + + void + ParserStateMachine::illegal_parsed_formal_with_token(std::string_view ssm_name, + const DUniqueString * param_name, + TypeDescr param_type, + const Token & tk, + std::string_view expect_str) + { + // TODO: + // - want to write error message using DArena + // - need something like log_streambuf and/or tostr() that's arena-aware + + auto errmsg_string = tostr("Unexpected formal", + xtag("param_name", std::string_view(*param_name)), + xtag("param_type", param_type), + xtag("tk", tk), + xtag("expecting", expect_str), + xtag("ssm", ssm_name), + xtag("via", "ParserStateMachine::illegal_parsed_formal")); + + assert(expr_alloc_); + + auto errmsg = DString::from_view(expr_alloc_, + std::string_view(errmsg_string)); + + this->capture_error(ssm_name, errmsg); + } + + void + ParserStateMachine::illegal_parsed_formal_arglist(std::string_view ssm_name, + DArray * arglist, + std::string_view expect_str) + { + obj arglist_pr(arglist); + + auto errmsg_string = tostr("Unexpected formal arglist", + xtag("arglist", arglist_pr), + xtag("expecting", expect_str), + xtag("ssm", ssm_name), + xtag("via", "ParserStateMachine::illegal_parsed_formal_arglist")); + + assert(expr_alloc_); + + auto errmsg = DString::from_str(expr_alloc_, errmsg_string); + + this->capture_error(ssm_name, errmsg); + } + + void + ParserStateMachine::illegal_parsed_expression(std::string_view ssm_name, + obj expr, + std::string_view expect_str) + { + // TODO: + // - want to write error message using DArena + // - need something like log_streambuf and/or tostr() that's arena-aware + + auto expr_pr = expr.to_facet(); + //= FacetRegistry::instance().variant(expr); + assert(expr_pr); + + /** TODO + * problem here: we have pretty() support for obj, + * but not "ordinary printing" support. So expression doesn't get printed + **/ + auto errmsg_string = tostr("Unexpected expression", + xtag("expr", expr_pr), + xtag("expecting", expect_str), + xtag("ssm", ssm_name), + xtag("via", "ParserStateMachine::illegal_parsed_expression")); + + assert(expr_alloc_); + + auto errmsg = DString::from_view(expr_alloc_, + std::string_view(errmsg_string)); + + this->capture_error(ssm_name, errmsg); + } + + void + ParserStateMachine::illegal_parsed_expression_with_token(std::string_view ssm_name, + obj expr, + const Token & tk, + std::string_view expect_str) + { + // TODO: + // - want to write error message using DArena + // - need something like log_streambuf and/or tostr() that's arena-aware + + obj expr_pr + = FacetRegistry::instance().variant(expr); + assert(expr_pr); + + /** TODO + * problem here: we have pretty() support for obj, + * but not "ordinary printing" support. So expression doesn't get printed + **/ + auto errmsg_string = tostr("Unexpected expression", + xtag("expr", expr_pr), + xtag("tk", tk), + xtag("expecting", expect_str), + xtag("ssm", ssm_name), + xtag("via", "ParserStateMachine::illegal_parsed_expression")); + + assert(expr_alloc_); + + auto errmsg = DString::from_view(expr_alloc_, + std::string_view(errmsg_string)); + + this->capture_error(ssm_name, errmsg); + } + + void + ParserStateMachine::error_unbound_variable(std::string_view ssm_name, + std::string_view sym) + { + auto errmsg_string = tostr("No binding for symbol", + xtag("symbol", sym), + xtag("ssm", ssm_name)); + + auto errmsg = DString::from_view(expr_alloc_, + std::string_view(errmsg_string)); + + this->capture_error(ssm_name, errmsg); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ParserStateMachine.cpp */ diff --git a/xo-reader2/src/reader2/ReaderConfig.cpp b/xo-reader2/src/reader2/ReaderConfig.cpp new file mode 100644 index 00000000..7db5fe59 --- /dev/null +++ b/xo-reader2/src/reader2/ReaderConfig.cpp @@ -0,0 +1,13 @@ +/** @file ReaderConfig.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "ReaderConfig.hpp" + +namespace xo { + namespace scm { + } +} /*namespace xo*/ + +/* end ReaderConfig.cpp */ diff --git a/xo-reader2/src/reader2/SchematikaParser.cpp b/xo-reader2/src/reader2/SchematikaParser.cpp new file mode 100644 index 00000000..25b3bc7f --- /dev/null +++ b/xo-reader2/src/reader2/SchematikaParser.cpp @@ -0,0 +1,148 @@ +/** @file SchematikaParser.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "SchematikaParser.hpp" +#include "ParserStateMachine.hpp" +#include "ParserStack.hpp" +#include "DToplevelSeqSsm.hpp" +#include +#include +#include + +namespace xo { + using xo::mm::AAllocator; + using xo::mm::MemorySizeInfo; + using xo::tostr; + using xo::xtag; + + namespace scm { + // ----- SchematikaParser ----- + + SchematikaParser::SchematikaParser(const ParserConfig & cfg, + obj expr_alloc, + obj aux_alloc) + : psm_{cfg.parser_arena_config_, + cfg.symtab_config_, + cfg.max_stringtable_capacity_, + expr_alloc, + aux_alloc}, + debug_flag_{cfg.debug_flag_} + { + } + + DGlobalSymtab * + SchematikaParser::global_symtab() const noexcept + { + return psm_.global_symtab(); + } + + bool + SchematikaParser::is_at_toplevel() const + { + return psm_.is_at_toplevel(); + } + + bool + SchematikaParser::has_incomplete_expr() const + { + return psm_.has_incomplete_expr(); + } + + obj + SchematikaParser::top_ssm() const + { + return psm_.top_ssm(); + } + + const ParserResult & + SchematikaParser::result() const + { + return psm_.result(); + } + + void + SchematikaParser::visit_pools(const MemorySizeVisitor & visitor) const + { + return psm_.visit_pools(visitor); + } + + void + SchematikaParser::begin_interactive_session() + { + DToplevelSeqSsm::establish_interactive(psm_.parser_alloc(), &psm_); + + } + + void + SchematikaParser::begin_batch_session() + { + DToplevelSeqSsm::establish_batch(psm_.parser_alloc(), &psm_); + } + + const ParserResult & + SchematikaParser::on_token(const token_type & tk) + { + scope log(XO_DEBUG(debug_flag_), xtag("tk", tk)); + + if (psm_.stack() == nullptr) { + throw std::runtime_error(tostr("SchematikaParser::include_token", + ": parser not expecting input" + "(call parser.begin_translation_unit()..?)", + xtag("token", tk))); + } + + /* stack is non-empty */ + + psm_.on_token(tk); + + return psm_.result(); + } /*include_token*/ + + void + SchematikaParser::reset_result() + { + psm_.reset_result(); + } + + void + SchematikaParser::reset_to_idle_toplevel() + { + psm_.clear_error_reset(); + } /*reset_to_idle_toplevel*/ + + void + SchematikaParser::print(std::ostream & os) const { + os << "" << std::endl; + } + + bool + SchematikaParser::pretty(const ppindentinfo & ppii) const { + auto * pps = ppii.pps(); + + if (ppii.upto()) + return false; + + // TODO: consider printing: + // psm.stringtable_ + // psm.parser_alloc_ + // psm.parser_alloc_ckp_ + // psm.expr_alloc_ + // psm.result_ + // psm.debug_flag_ + // + + return pps->pretty_struct + (ppii, + "SchematikaParser", + refrtag("stack", psm_.stack()) + ); + } + } /*namespace scm*/ +} /*namespace xo*/ + +/* end SchematikaParser.cpp */ diff --git a/xo-reader2/src/reader2/SchematikaReader.cpp b/xo-reader2/src/reader2/SchematikaReader.cpp new file mode 100644 index 00000000..c3e13254 --- /dev/null +++ b/xo-reader2/src/reader2/SchematikaReader.cpp @@ -0,0 +1,184 @@ +/** @file SchematikaReader.cpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#include "SchematikaReader.hpp" + +namespace xo { + using xo::mm::MemorySizeInfo; + + namespace scm { + SchematikaReader::SchematikaReader(const ReaderConfig & config, + obj expr_alloc, + obj aux_alloc) + : tokenizer_{config.tk_buffer_config_, + config.tk_debug_flag_}, + parser_{ParserConfig(config.parser_arena_config_, + config.symtab_config_, + config.max_stringtable_cap_, + config.parser_debug_flag_), + expr_alloc, + aux_alloc}, + debug_flag_{config.reader_debug_flag_} + { + } + + DGlobalSymtab * + SchematikaReader::global_symtab() const noexcept + { + return parser_.global_symtab(); + } + + void + SchematikaReader::visit_pools(const MemorySizeVisitor & visitor) const + { + tokenizer_.visit_pools(visitor); + parser_.visit_pools(visitor); + } + + bool + SchematikaReader::is_at_toplevel() const noexcept + { + return parser_.is_at_toplevel(); + } + + void + SchematikaReader::begin_interactive_session() + { + parser_.begin_interactive_session(); + } + + void + SchematikaReader::begin_batch_session() + { + parser_.begin_batch_session(); + } + + // TODO: + // Schematika::end_interactive_session() + + const ReaderResult & + SchematikaReader::read_expr(span_type input_ext, bool eof) + { + scope log(XO_DEBUG(debug_flag_)); + + if (log) { + log(xtag("input_ext", input_ext)); + log(xtag("eof", eof)); + } + + if (!input_ext.empty()) { + auto [error, input] + = tokenizer_.buffer_input_line(input_ext, eof); + + if (log) { + log(xtag("msg", "before loop: buffered input line")); + log(xtag("input", input)); + } + + while (!input.empty()) { + log && log(xtag("msg", "loop"), + xtag("input", input)); + + auto [tk, consumed, error] = tokenizer_.scan(input); + + log && log(xtag("tk", tk), xtag("consumed", consumed)); + + auto rem_input = input.after_prefix(consumed); + + log && log(xtag("rem_input", rem_input)); + + if (!tk.is_valid() && error.is_error()) { + this->result_ + = ReaderResult + { .expr_ = obj(), + .remaining_input_ = rem_input, + .tk_error_ = std::move(error) + }; + + return result_; + } + + // log && log(xtag("consumed", consumed), xtag("tk", tk)); + + if (tk.is_valid()) { + // presult { + // result_type :: parser_result_type = none|expression|error + // result_expr :: obj + // error_src_function :: string_view + // error_description :: const DString * + // } + // + const ParserResult & presult = parser_.on_token(tk); + + if (presult.is_error()) { + // tk_error { + // src_function :: const char * + // error_description :: string + // input_state { + // current_line :: span + // tk_start :: size_t + // current_pos :: size_t + // whitespace :: size_t + // debug_flag :: bool + // } + // error_pos :: size_t + // } + // + // tk_error.report(cout); + + this->result_ + = ReaderResult + { .expr_ = obj(), + .remaining_input_ = rem_input, + .tk_error_ = std::move(error) }; + + assert(presult.error_description()); + + // carefully created error description, maybe + this->result_.tk_error_ + = result_.tk_error_.with_error + (presult.error_src_fn_, + std::string + (std::string_view(*(presult.error_description())))); + + return result_; + } else if (presult.is_expression()) { + this->result_ + = ReaderResult + { + .expr_ = presult.result_expr(), + .remaining_input_ = rem_input, + .tk_error_ = TokenizerError() + }; + + return result_; + } + } + + input = rem_input; + } + } + + this->result_ = ReaderResult(); + + return this->result_; + } + + void + SchematikaReader::reset_result() + { + this->parser_.reset_result(); + } + + void + SchematikaReader::reset_to_idle_toplevel() + { + this->tokenizer_.discard_current_line(); + this->parser_.reset_to_idle_toplevel(); + } + } /*namespace scm*/ +} /*namespace xo*/ + +/* end SchematikaReader.cpp */ diff --git a/xo-reader2/src/reader2/init_reader2.cpp b/xo-reader2/src/reader2/init_reader2.cpp new file mode 100644 index 00000000..aa7e291c --- /dev/null +++ b/xo-reader2/src/reader2/init_reader2.cpp @@ -0,0 +1,41 @@ +/** @file init_reader2.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "init_reader2.hpp" +#include "reader2_register_facets.hpp" +#include "reader2_register_types.hpp" + +#include +#include + +namespace xo { + using xo::scm::reader2_register_facets; + using xo::scm::reader2_register_types; + using xo::mm::CollectorTypeRegistry; + + void + InitSubsys::init() + { + reader2_register_facets(); + + CollectorTypeRegistry::instance().register_types(&reader2_register_types); + } + + InitEvidence + InitSubsys::require() + { + InitEvidence retval; + + /* direct subsystem deps for xo-reader2/ */ + retval ^= InitSubsys::require(); + + /* xo-reader2/'s own initialization code */ + retval ^= Subsystem::provide("reader2", &init); + + return retval; + } +} /*namespace xo*/ + +/* end init_reader2.cpp */ diff --git a/xo-reader2/src/reader2/reader2_register_facets.cpp b/xo-reader2/src/reader2/reader2_register_facets.cpp new file mode 100644 index 00000000..59d91907 --- /dev/null +++ b/xo-reader2/src/reader2/reader2_register_facets.cpp @@ -0,0 +1,101 @@ +/** @file reader2_register_facets.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "reader2_register_facets.hpp" + +#include "SchematikaParser.hpp" +#include "ToplevelSeqSsm.hpp" +#include "DefineSsm.hpp" +#include "LambdaSsm.hpp" +#include "IfElseSsm.hpp" +#include "ApplySsm.hpp" +#include "SequenceSsm.hpp" +#include "ParenSsm.hpp" +#include "ExpectFormalArglistSsm.hpp" +#include "ExpectFormalArgSsm.hpp" +#include "ExpectSymbolSsm.hpp" +#include "ExpectTypeSsm.hpp" +#include "ExpectExprSsm.hpp" +#include "ProgressSsm.hpp" +#include "SyntaxStateMachine.hpp" + +#include +#include +#include + +namespace xo { + using xo::print::APrintable; + using xo::facet::FacetRegistry; + using xo::facet::TypeRegistry; + using xo::facet::typeseq; + + namespace scm { + bool + reader2_register_facets() + { + scope log(XO_DEBUG(true)); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + // misc types showing up in aux arena + TypeRegistry::register_type(); + // misc types showing up in parser stack arena + TypeRegistry::register_type(); + + log && log(xtag("DToplevelSeqSsm.tseq", typeseq::id())); + log && log(xtag("DDefineSsm.tseq", typeseq::id())); + log && log(xtag("DLambdaSsm.tseq", typeseq::id())); + log && log(xtag("DIfElseSsm.tseq", typeseq::id())); + log && log(xtag("DExpectFormalArglistSsm.tseq", typeseq::id())); + log && log(xtag("DExpectFormalArgSsm.tseq", typeseq::id())); + log && log(xtag("DExpectSymbolSsm.tseq", typeseq::id())); + log && log(xtag("DExpectTypeSsm.tseq", typeseq::id())); + log && log(xtag("DExpectExprSsm.tseq", typeseq::id())); + log && log(xtag("DProgressSsm.tseq", typeseq::id())); + log && log(xtag("DParenSsm.tseq", typeseq::id())); + log && log(xtag("ASyntaxStateMachine.tseq", typeseq::id())); + + return true; + } + } /*namespace scm*/ +} /*namespace xo*/ + +/* end reader2_register_facets.cpp */ diff --git a/xo-reader2/src/reader2/reader2_register_types.cpp b/xo-reader2/src/reader2/reader2_register_types.cpp new file mode 100644 index 00000000..3720752d --- /dev/null +++ b/xo-reader2/src/reader2/reader2_register_types.cpp @@ -0,0 +1,29 @@ +/** @file reader2_register_types.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "reader2_register_types.hpp" + +#include + +namespace xo { + using xo::mm::ACollector; + using xo::scope; + + namespace scm { + bool + reader2_register_types(obj /*gc*/) + { + scope log(XO_DEBUG(true)); + + bool ok = true; + + /* no gc-aware types yet; scaffold for future use */ + + return ok; + } + } +} /*namespace xo*/ + +/* end reader2_register_types.cpp */ diff --git a/xo-reader2/src/reader2/syntaxstatetype.cpp b/xo-reader2/src/reader2/syntaxstatetype.cpp new file mode 100644 index 00000000..01ab1005 --- /dev/null +++ b/xo-reader2/src/reader2/syntaxstatetype.cpp @@ -0,0 +1,52 @@ +/** @file syntaxstatetype.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "syntaxstatetype.hpp" + +namespace xo { + namespace scm { + + const char * + syntaxstatetype_descr(syntaxstatetype x) { + switch (x) { + case syntaxstatetype::invalid: + break; + case syntaxstatetype::defexpr: + return "defexpr"; + case syntaxstatetype::lambdaexpr: + return "lambdaexpr"; + case syntaxstatetype::ifelseexpr: + return "ifelseexpr"; + case syntaxstatetype::sequence: + return "sequence"; + case syntaxstatetype::apply: + return "apply"; + case syntaxstatetype::progress: + return "progress"; + case syntaxstatetype::paren: + return "paren"; + case syntaxstatetype::expect_toplevel_expression_sequence: + return "expect-toplevel-expression-sequence"; + case syntaxstatetype::expect_formal_arglist: + return "expect-formal-arglist"; + case syntaxstatetype::expect_formal_arg: + return "expect-formal-arg"; + case syntaxstatetype::expect_symbol: + return "expect-symbol"; + case syntaxstatetype::expect_type: + return "expect-type"; + case syntaxstatetype::expect_rhs_expression: + return "expect-rhs-expression"; + case syntaxstatetype::N: + break; + } + + return "syntaxstatetype?"; + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end syntaxstatetype.cpp */ diff --git a/xo-reader2/utest/CMakeLists.txt b/xo-reader2/utest/CMakeLists.txt new file mode 100644 index 00000000..f6de05ed --- /dev/null +++ b/xo-reader2/utest/CMakeLists.txt @@ -0,0 +1,11 @@ +# build unittest xo-reader2/utest + +set(UTEST_EXE utest.reader2) +set(UTEST_SRCS + reader2_utest_main.cpp + SchematikaParser.test.cpp +) + +xo_add_utest_executable(${UTEST_EXE} ${UTEST_SRCS}) +xo_self_dependency(${UTEST_EXE} xo_reader2) +xo_external_target_dependency(${UTEST_EXE} Catch2 Catch2::Catch2) diff --git a/xo-reader2/utest/SchematikaParser.test.cpp b/xo-reader2/utest/SchematikaParser.test.cpp new file mode 100644 index 00000000..2b92161a --- /dev/null +++ b/xo-reader2/utest/SchematikaParser.test.cpp @@ -0,0 +1,925 @@ +/** @file SchematikaParser.test.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace xo { + using xo::scm::ParserConfig; + using xo::scm::SchematikaParser; + using xo::scm::ASyntaxStateMachine; + using xo::scm::syntaxstatetype; +// using xo::scm::DDefineSsm; + using xo::scm::DExpectExprSsm; + + using xo::scm::AExpression; + using xo::scm::DDefineExpr; + using xo::scm::DApplyExpr; + using xo::scm::DVarRef; + using xo::scm::DConstant; + + //using xo::scm::ParserResult; + using xo::scm::Token; + using xo::mm::AGCObject; + using xo::scm::DPrimitive_gco_2_gco_gco; + using xo::scm::DString; + using xo::scm::DFloat; + using xo::scm::DInteger; + + using xo::facet::FacetRegistry; + + using xo::mm::ArenaConfig; + using xo::mm::AAllocator; + using xo::mm::DArena; + using xo::mm::MemorySizeInfo; + using xo::facet::with_facet; + + static InitEvidence s_init = (InitSubsys::require()); + + namespace ut { + struct ParserFixture { + ParserFixture(const std::string & testname, bool debug_flag) + { + this->aux_arena_ + = std::move(DArena(ArenaConfig() + .with_name(testname) + .with_size(4 * 1024) + .with_store_header_flag(true))); + obj aux_mm(&aux_arena_); + + this->expr_arena_ + = dp::make(aux_mm, + (ArenaConfig() + .with_name("expr") + .with_size(16 * 1024) + .with_store_header_flag(true))); + obj expr_mm(expr_arena_.data()); + + ParserConfig cfg; + cfg.parser_arena_config_.size_ = 16 * 1024; + /* editor bait: symbol table */ + cfg.symtab_config_.hint_max_capacity_ = 128; + cfg.max_stringtable_capacity_ = 512; + cfg.debug_flag_ = false; + + this->parser_ + = dp::make(aux_mm, cfg, expr_mm, aux_mm); + } + + ParserFixture(const ParserFixture & other) = delete; + ParserFixture(const ParserFixture && other) = delete; + + bool log_memory_layout(scope * p_log) { + using xo::facet::TypeRegistry; + using xo::mm::MemorySizeDetail; + + auto visitor = [p_log](const MemorySizeInfo & info) { + *p_log && (*p_log)(xtag("name", info.resource_name_), + xtag("used", info.used_), + xtag("alloc", info.allocated_), + xtag("commit", info.committed_), + xtag("resv", info.reserved_)); + if (*p_log && info.detail_) { + (*p_log)("detail", + xtag("n", (*info.detail_)[0].n_alloc_), + xtag("z", (*info.detail_)[0].z_alloc_)); + for (size_t i = 1; i < info.detail_->size(); ++i) { + const MemorySizeDetail & d = (*info.detail_)[i]; + + if (d.tseq_.is_sentinel()) + break; + + (*p_log)("[",i,"]", + xtag("tseq",d.tseq_), + xtag("type", TypeRegistry::id2name(d.tseq_)), + xtag("n", d.n_alloc_), + xtag("z", d.z_alloc_)); + } + } + }; + + aux_arena_.visit_pools(visitor); + FacetRegistry::instance().visit_pools(visitor); + TypeRegistry::instance().visit_pools(visitor); + expr_arena_->visit_pools(visitor); + parser_->visit_pools(visitor); + + return true; + } + + DArena aux_arena_; + dp expr_arena_; + dp parser_; + }; + + void + utest_tokenizer_loop(SchematikaParser * parser, std::vector & tk_v, bool debug_flag) + { + scope log(XO_DEBUG(debug_flag)); + + size_t i_tk = 0; + size_t n_tk = tk_v.size(); + for (const auto & tk : tk_v) { + INFO(tostr(xtag("i_tk", i_tk), xtag("tk", tk))); + + auto & result = parser->on_token(tk); + + log && log("after token", xtag("i_tk", i_tk), xtag("tk", tk)); + log && log(xtag("parser", parser)); + log && log(xtag("result", result)); + + if (i_tk + 1 < n_tk) { + REQUIRE(parser->has_incomplete_expr() == true); + REQUIRE(!result.is_error()); + REQUIRE(result.is_incomplete()); + } else { + /* last token in tk_v[] */ + + REQUIRE(parser->has_incomplete_expr() == false); + REQUIRE(!result.is_error()); + REQUIRE(result.is_expression()); + REQUIRE(result.result_expr()); + } + + ++i_tk; + } + } + + TEST_CASE("SchematikaParser-ctor", "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + REQUIRE(parser.debug_flag() == false); + REQUIRE(parser.is_at_toplevel() == true); + + // baseline: + // SchematikaParser-ctor :used 1408 + // facets-ctl :used 73 // facet hashtable + // facets-slots :used 1168 // facet hashtable + // expr :used 2056 + // [1] :type xo::scm::DArray :n 1 :z 2056 // DArray of DUniqueString* + // [2] :type ? :n 1 : z 16 + // strings :used 0 + // stringkeys-ctl :used 0 + // strinkeys-slots :used 0 + // parser-arena :used 0 + // global-symtab-ctl :used 0 + // global-symtab-slots :used 0 + + log && fixture.log_memory_layout(&log); + } + + TEST_CASE("SchematikaParser-begin-interactive", + "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + parser.begin_interactive_session(); + + // after begin_interactive_session, parser has toplevel exprseq + // but is still "at toplevel" in the sense of ready for input + REQUIRE(parser.has_incomplete_expr() == false); + + log && fixture.log_memory_layout(&log); + } + + TEST_CASE("SchematikaParser-begin-batch", "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + parser.begin_batch_session(); + + // after begin_translation_unit, parser has toplevel exprseq + // but is still "at toplevel" in the sense of ready for input + REQUIRE(parser.has_incomplete_expr() == false); + + log && fixture.log_memory_layout(&log); + } + + TEST_CASE("SchematikaParser-batch-def", "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + parser.begin_batch_session(); + + /** Walkthrough parsing input equivalent to: + * + * def foo : f64 = 3.141593 ; + * + **/ + + std::vector tk_v{ + Token::def_token(), + Token::symbol_token("foo"), + Token::colon_token(), + Token::symbol_token("f64"), + Token::singleassign_token(), + Token::f64_token("3.141593"), + Token::semicolon_token(), + }; + + utest_tokenizer_loop(&parser, tk_v, c_debug_flag); + + const auto & result = parser.result(); + { + auto expr = obj::from(result.result_expr()); + REQUIRE(expr); + } + + log && fixture.log_memory_layout(&log); + } + + TEST_CASE("SchematikaParser-interactive-def2", "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + parser.begin_interactive_session(); + + { + /** Walkthrough parsing input equivalent to: + * + * def foo : f64 = 3.141593 ; + * + **/ + + std::vector tk_v{ + Token::def_token(), + Token::symbol_token("foo"), + Token::colon_token(), + Token::symbol_token("f64"), + Token::singleassign_token(), + Token::f64_token("3.141593"), + Token::semicolon_token(), + }; + + utest_tokenizer_loop(&parser, tk_v, c_debug_flag); + + const auto & result = parser.result(); + { + auto expr = obj::from(result.result_expr()); + REQUIRE(expr); + } + + parser.reset_result(); + } + + { + /** Walkthrough parsing input equivalent to: + * + * foo ; + * + **/ + + std::vector tk_v{ +// Token::f64_token("2.0"), +// Token::star_token(), + Token::symbol_token("foo"), + Token::semicolon_token(), + }; + + utest_tokenizer_loop(&parser, tk_v, c_debug_flag); + + const auto & result = parser.result(); + { + auto expr = obj::from(result.result_expr()); + REQUIRE(expr); + } + } + + log && fixture.log_memory_layout(&log); + } + + TEST_CASE("SchematikaParser-interactive-integer", "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + parser.begin_interactive_session(); + + /** Walkthrough parsing input equivalent to: + * + * 1011 ; + * + **/ + + { + auto & result = parser.on_token(Token::i64_token("1011")); + + log && log("after integer token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == true); + REQUIRE(!result.is_error()); + REQUIRE(result.is_incomplete()); + } + + { + auto & result = parser.on_token(Token::semicolon_token()); + + log && log("after semicolon token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == false); + REQUIRE(!result.is_error()); + REQUIRE(result.is_expression()); + REQUIRE(result.result_expr()); + + auto expr = obj::from(result.result_expr()); + REQUIRE(expr); + + REQUIRE(expr->value()); + + auto value_i64 = obj::from(expr->value()); + + REQUIRE(value_i64); + + REQUIRE(value_i64->value() == 1011); + } + + //REQUIRE(result.is_error()); + //// illegal input on token + //REQUIRE(result.error_description()); + + log && fixture.log_memory_layout(&log); + } + + TEST_CASE("SchematikaParser-interactive-float", "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + parser.begin_interactive_session(); + + /** Walkthrough parsing input equivalent to: + * + * 3.14159265 ; + * + **/ + + { + auto & result = parser.on_token(Token::f64_token("3.14159265")); + + log && log("after float token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == true); + REQUIRE(!result.is_error()); + REQUIRE(result.is_incomplete()); + } + + { + auto & result = parser.on_token(Token::semicolon_token()); + + log && log("after semicolon token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == false); + REQUIRE(!result.is_error()); + REQUIRE(result.is_expression()); + REQUIRE(result.result_expr()); + + auto expr = obj::from(result.result_expr()); + REQUIRE(expr); + + REQUIRE(expr->value()); + + auto value_f64 = obj::from(expr->value()); + + REQUIRE(value_f64); + + REQUIRE(value_f64->value() == 3.14159265); + } + + //REQUIRE(result.is_error()); + //// illegal input on token + //REQUIRE(result.error_description()); + + log && fixture.log_memory_layout(&log); + } + + TEST_CASE("SchematikaParser-interactive-string", "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + parser.begin_interactive_session(); + + /** Walkthrough parsing input equivalent to: + * + * "hello world" ; + * + **/ + + { + auto & result = parser.on_token(Token::string_token("hello world")); + + log && log("after string token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == true); + REQUIRE(!result.is_error()); + REQUIRE(result.is_incomplete()); + } + + { + auto & result = parser.on_token(Token::semicolon_token()); + + log && log("after semicolon token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == false); + REQUIRE(!result.is_error()); + REQUIRE(result.is_expression()); + REQUIRE(result.result_expr()); + + auto expr = obj::from(result.result_expr()); + REQUIRE(expr); + + REQUIRE(expr->value()); + + auto value_str = obj::from(expr->value()); + + REQUIRE(value_str); + + REQUIRE(strcmp(value_str->chars(), "hello world") == 0); + } + + //REQUIRE(result.is_error()); + //// illegal input on token + //REQUIRE(result.error_description()); + + log && fixture.log_memory_layout(&log); + } + + TEST_CASE("SchematikaParser-interactive-arith", "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + parser.begin_interactive_session(); + + /** Walkthrough parsing input equivalent to: + * + * 3.14159265 * 0.5 ; + * + **/ + + std::vector tk_v{ + Token::f64_token("3.14159265"), + Token::star_token(), + Token::f64_token("0.5"), + Token::semicolon_token(), + }; + + utest_tokenizer_loop(&parser, tk_v, c_debug_flag); + + const auto & result = parser.result(); + { + auto expr = obj::from(result.result_expr()); + REQUIRE(expr); + + REQUIRE(expr->n_args() == 2); + + auto fn = obj::from(expr->fn()); + REQUIRE(fn); + + auto pm = obj::from(fn->value()); + REQUIRE(pm); + REQUIRE(pm->name() == "_mul"); + + auto lhs = obj::from(expr->arg(0)); + REQUIRE(lhs); + + auto lhs_f64 = obj::from(lhs->value()); + REQUIRE(lhs_f64); + REQUIRE(lhs_f64->value() == 3.14159265); + + auto rhs = obj::from(expr->arg(1)); + REQUIRE(rhs); + + auto rhs_f64 = obj::from(rhs->value()); + REQUIRE(rhs_f64); + REQUIRE(rhs_f64->value() == 0.5); + } + + log && fixture.log_memory_layout(&log); + } + + TEST_CASE("SchematikaParser-interactive-cmp", "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), + xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + parser.begin_interactive_session(); + + /** Walkthrough parsing input equivalent to: + * + * 312 == 312 ; + * ^ ^ ^ ^ + * 0 1 2 3 + **/ + + std::vector tk_v{ + /* [0] */ Token::i64_token("312"), + /* [1] */ Token::cmpeq_token(), + /* [2] */ Token::i64_token("312"), + /* [3] */ Token::semicolon_token(), + }; + + utest_tokenizer_loop(&parser, tk_v, c_debug_flag); + + const auto & result = parser.result(); + { + auto expr = obj::from(result.result_expr()); + REQUIRE(expr); + + REQUIRE(expr->n_args() == 2); + + auto fn = obj::from(expr->fn()); + REQUIRE(fn); + + auto pm = obj::from(fn->value()); + REQUIRE(pm); + REQUIRE(pm->name() == "_equal"); + + auto lhs = obj::from(expr->arg(0)); + REQUIRE(lhs); + + auto lhs_i64 = obj::from(lhs->value()); + REQUIRE(lhs_i64); + REQUIRE(lhs_i64->value() == 312); + + auto rhs = obj::from(expr->arg(1)); + REQUIRE(rhs); + + auto rhs_i64 = obj::from(rhs->value()); + REQUIRE(rhs_i64); + REQUIRE(rhs_i64->value() == 312); + } + + log && fixture.log_memory_layout(&log); + } + + TEST_CASE("SchematikaParser-interactive-lambda", "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + parser.begin_interactive_session(); + + /** Walkthrough parsing input equivalent to: + * + * lambda (n : i64, r : i64) -> i64 { 123 } + * ^ ^^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ + * 0 1| 3 4 5 6 7 8 9 a b c d e + * 2 + **/ + + std::vector tk_v{ + /* [ 0] */ Token::lambda_token(), + /* [ 1] */ Token::leftparen_token(), + /* [ 2] */ Token::symbol_token("n"), + /* [ 3] */ Token::colon_token(), + /* [ 4] */ Token::symbol_token("i64"), + /* [ 5] */ Token::comma_token(), + /* [ 6] */ Token::symbol_token("r"), + /* [ 7] */ Token::colon_token(), + /* [ 8] */ Token::symbol_token("i64"), + /* [ 9] */ Token::rightparen_token(), + /* [ a] */ Token::yields_token(), + /* [ b] */ Token::symbol_token("i64"), + /* [ c] */ Token::leftbrace_token(), + /* [ d] */ Token::i64_token("123"), + /* [ e] */ Token::rightbrace_token(), + }; + + utest_tokenizer_loop(&parser, tk_v, c_debug_flag); + + log && fixture.log_memory_layout(&log); + } + + TEST_CASE("SchematikaParser-interactive-if", "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + parser.begin_interactive_session(); + + /** Walkthrough parsing input equivalent to: + * + * if true then 777 else "fooey" ; + * ^ ^ ^ ^ ^ ^ ^ + * 0 1 2 3 4 5 6 + **/ + + std::vector tk_v{ + /* [0] */ Token::if_token(), + /* [1] */ Token::bool_token("true"), + /* [2] */ Token::then_token(), + /* [3] */ Token::i64_token("777"), + /* [4] */ Token::else_token(), + /* [5] */ Token::string_token("fooey"), + /* [6] */ Token::semicolon_token(), + }; + + utest_tokenizer_loop(&parser, tk_v, c_debug_flag); + + log && fixture.log_memory_layout(&log); + } + + TEST_CASE("SchematikaParser-interactive-lambda2", "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + parser.begin_interactive_session(); + + /** Walkthrough parsing input equivalent to: + * + * lambda (x : i64) -> i64 { x * x } + * ^ ^^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ + * 0 1| 3 4 5 6 7 8 9 a b c + * 2 + **/ + + std::vector tk_v{ + /* [ 0] */ Token::lambda_token(), + /* [ 1] */ Token::leftparen_token(), + /* [ 2] */ Token::symbol_token("x"), + /* [ 3] */ Token::colon_token(), + /* [ 4] */ Token::symbol_token("i64"), + /* [ 5] */ Token::rightparen_token(), + /* [ 6] */ Token::yields_token(), + /* [ 7] */ Token::symbol_token("i64"), + /* [ 8] */ Token::leftbrace_token(), + /* [ 9] */ Token::symbol_token("x"), + /* [ a] */ Token::star_token(), + /* [ b] */ Token::symbol_token("x"), + /* [ c] */ Token::rightbrace_token(), + }; + + utest_tokenizer_loop(&parser, tk_v, c_debug_flag); + + log && fixture.log_memory_layout(&log); + } + + TEST_CASE("SchematikaParser-interactive-apply", "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + parser.begin_interactive_session(); + + /** Walkthrough parsing input equivalent to: + * + * (lambda (x : i64) { x * x })(13) ; + * ^^ ^^ ^ ^ ^ ^ ^ ^ ^ ^^^^ ^ ^ + * 0| 2| 4 5 6 7 8 9 a b|d| f g + * 1 3 c e + **/ + + std::vector tk_v{ + /* [ 0] */ Token::leftparen_token(), + + /* [ 1] */ Token::lambda_token(), + /* [ 2] */ Token::leftparen_token(), + /* [ 3] */ Token::symbol_token("x"), + /* [ 4] */ Token::colon_token(), + /* [ 5] */ Token::symbol_token("i64"), + /* [ 6] */ Token::rightparen_token(), + /* [ 7] */ Token::leftbrace_token(), + /* [ 8] */ Token::symbol_token("x"), + /* [ 9] */ Token::star_token(), + /* [ a] */ Token::symbol_token("x"), + /* [ b] */ Token::rightbrace_token(), + /* [ c] */ Token::rightparen_token(), + /* [ d] */ Token::leftparen_token(), + /* [ e] */ Token::i64_token("13"), + /* [ f] */ Token::rightparen_token(), + /* [ g] */ Token::semicolon_token(), + }; + + utest_tokenizer_loop(&parser, tk_v, c_debug_flag); + + log && fixture.log_memory_layout(&log); + } + + TEST_CASE("SchematikaParser-interactive-apply2", "[reader2][SchematikaParser]") + { + // top-level apply, with multiple arguments + + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + parser.begin_interactive_session(); + + /** Walkthrough parsing input equivalent to: + * + * (lambda (x : i64, y : i64) { x * y })(13, 15) ; + * ^^ ^^ ^ ^ ^ ^^ ^ ^ ^ ^ ^ ^ ^^^^ ^ ^ ^ ^ + * 0| 2| 4 5 6 7| 9 a b c d e f|h| j k l m + * 1 3 8 g i + **/ + + std::vector tk_v{ + /* [ 0] */ Token::leftparen_token(), + + /* [ 1] */ Token::lambda_token(), + /* [ 2] */ Token::leftparen_token(), + /* [ 3] */ Token::symbol_token("x"), + /* [ 4] */ Token::colon_token(), + /* [ 5] */ Token::symbol_token("i64"), + /* [ 6] */ Token::comma_token(), + /* [ 7] */ Token::symbol_token("y"), + /* [ 8] */ Token::colon_token(), + /* [ 9] */ Token::symbol_token("i64"), + /* [ a] */ Token::rightparen_token(), + + /* [ b] */ Token::leftbrace_token(), + /* [ c] */ Token::symbol_token("x"), + /* [ d] */ Token::star_token(), + /* [ e] */ Token::symbol_token("y"), + /* [ f] */ Token::rightbrace_token(), + + /* [ g] */ Token::rightparen_token(), + + /* [ h] */ Token::leftparen_token(), + /* [ i] */ Token::i64_token("13"), + /* [ j] */ Token::comma_token(), + /* [ k] */ Token::i64_token("15"), + /* [ l] */ Token::rightparen_token(), + + /* [ m] */ Token::semicolon_token(), + }; + + utest_tokenizer_loop(&parser, tk_v, c_debug_flag); + + log && fixture.log_memory_layout(&log); + } + + TEST_CASE("SchematikaParser-batch-def2", "[reader2][SchematikaParser]") + { + // top-level recursive function definition + + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + parser.begin_interactive_session(); + + /** Walkthrough parsing input equivalent to: + * + * def fact = lambda (n) { if (n == 0) then 1 else n * fact(n - 1) }; + * ^ ^ ^ ^ ^^^ ^ ^ ^^ ^ ^^ ^ ^ ^ ^ ^ ^ ^^ ^ ^^ ^^ + * 0 1 2 3 4|6 7 8 9| b c| e f g h i j k| m n| p| + * 5 a d l o q + **/ + + std::vector tk_v{ + /* [ 0] */ Token::def_token(), + + /* [ 1] */ Token::symbol_token("fact"), + /* [ 2] */ Token::singleassign_token(), + /* [ 3] */ Token::lambda_token(), + /* [ 4] */ Token::leftparen_token(), + /* [ 5] */ Token::symbol_token("n"), + /* [ 6] */ Token::rightparen_token(), + /* [ 7] */ Token::leftbrace_token(), + /* [ 8] */ Token::if_token(), + /* [ 9] */ Token::leftparen_token(), + /* [ a] */ Token::symbol_token("n"), + /* [ b] */ Token::cmpeq_token(), + /* [ c] */ Token::i64_token("0"), + /* [ d] */ Token::rightparen_token(), + /* [ e] */ Token::then_token(), + /* [ f] */ Token::i64_token("1"), + /* [ g] */ Token::else_token(), + /* [ h] */ Token::symbol_token("n"), + /* [ i] */ Token::star_token(), + /* [ j] */ Token::symbol_token("fact"), + /* [ k] */ Token::leftparen_token(), + /* [ l] */ Token::symbol_token("n"), + /* [ m] */ Token::minus_token(), + /* [ n] */ Token::i64_token("1"), + /* [ o] */ Token::rightparen_token(), + /* [ p] */ Token::rightbrace_token(), + /* [ q] */ Token::semicolon_token(), + }; + + utest_tokenizer_loop(&parser, tk_v, c_debug_flag); + + log && fixture.log_memory_layout(&log); + } + + } /*namespace ut*/ +} /*namespace xo*/ + +/* end SchematikaParser.test.cpp */ diff --git a/xo-reader2/utest/reader2_utest_main.cpp b/xo-reader2/utest/reader2_utest_main.cpp new file mode 100644 index 00000000..cccb0e64 --- /dev/null +++ b/xo-reader2/utest/reader2_utest_main.cpp @@ -0,0 +1,27 @@ +/** @file reader2_utest_main.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include + +#define CATCH_CONFIG_RUNNER +#include "catch2/catch.hpp" + +int +main(int argc, char* argv[]) +{ + using xo::Subsystem; + + // initialize subsystems + Subsystem::initialize_all(); + + // Run Catch2's test session + int result = Catch::Session().run(argc, argv); + + // cleanup here, if any + + return result; +} + +/* end reader2_utest_main.cpp */ diff --git a/xo-refcnt/include/xo/cxxutil/demangle.hpp b/xo-refcnt/include/xo/cxxutil/demangle.hpp index e2184f5d..fd7425ba 100644 --- a/xo-refcnt/include/xo/cxxutil/demangle.hpp +++ b/xo-refcnt/include/xo/cxxutil/demangle.hpp @@ -2,91 +2,6 @@ #pragma once -#include -#include -#include // std::array -#include // std::index_sequence - -namespace xo { - namespace reflect { - - template - constexpr auto - substring_as_array(std::string_view str, - std::index_sequence indexes) - { - //return std::array{str[Idxs]..., '\n'}; - return std::array{str[Idxs]...}; - } /*substring_as_array*/ - - template constexpr auto type_name_array() { -#if defined(__clang__) - constexpr auto prefix = std::string_view{"[T = "}; - constexpr auto suffix = std::string_view{"]"}; - constexpr auto function = std::string_view{__PRETTY_FUNCTION__}; -#elif defined(__GNUC__) - constexpr auto prefix = std::string_view{"with T = "}; - constexpr auto suffix = std::string_view{"]"}; - constexpr auto function = std::string_view{__PRETTY_FUNCTION__}; -#elif defined(_MSC_VER) - constexpr auto prefix = std::string_view{"type_name_array<"}; - constexpr auto suffix = std::string_view{">(void)"}; - constexpr auto function = std::string_view{__FUNCSIG__}; -#else -# error type_name_array: Unsupported compiler -#endif - - constexpr auto start = function.find(prefix) + prefix.size(); - constexpr auto end = function.rfind(suffix); - - //static_assert(start < end); - - constexpr auto name = function.substr(start, (end - start)); - - constexpr auto ixseq = std::make_index_sequence{}; - - return substring_as_array(name, ixseq); - } /*type_name_array*/ - - template - struct type_name_holder { - static inline constexpr auto value = type_name_array(); - }; - - template - constexpr auto type_name() -> std::string_view - { - constexpr auto& value = type_name_holder::value; - return std::string_view{value.data(), value.size()}; - } - -#ifdef NOT_IN_USE - template - struct join - { - // Join all strings into a single std::array of chars - static constexpr auto impl() noexcept - { - constexpr std::size_t len = (Strs.size() + ... + 0); - std::array arr{}; - auto append = [i = 0, &arr](auto const& s) mutable { - for (auto c : s) arr[i++] = c; - }; - (append(Strs), ...); - arr[len] = 0; - return arr; - } - // Give the joined string static storage - static constexpr auto arr = impl(); - // View as a std::string_view - static constexpr std::string_view value {arr.data(), arr.size() - 1}; - }; - - // Helper to get the value out - template - static constexpr auto join_v = join::value; -#endif - } /*namespace reflect*/ -} /*namespace xo*/ +#include /* end demangle.hpp */ diff --git a/xo-refcnt/src/CMakeLists.txt b/xo-refcnt/src/CMakeLists.txt index 9cbc92ff..e8b5288f 100644 --- a/xo-refcnt/src/CMakeLists.txt +++ b/xo-refcnt/src/CMakeLists.txt @@ -7,4 +7,5 @@ xo_install_include_tree3(include/xo/cxxutil) # NOTE: # dependency set here must be kept consistent with refcnt/cmake/refcntConfig.cmake.in # +xo_dependency(${SELF_LIB} xo_reflectutil) xo_dependency(${SELF_LIB} indentlog) diff --git a/xo-reflect/include/xo/reflect/TypeDescr.hpp b/xo-reflect/include/xo/reflect/TypeDescr.hpp index d39d64e8..f22f96bd 100644 --- a/xo-reflect/include/xo/reflect/TypeDescr.hpp +++ b/xo-reflect/include/xo/reflect/TypeDescr.hpp @@ -3,7 +3,8 @@ #pragma once #include "TypeDescrExtra.hpp" -#include "xo/cxxutil/demangle.hpp" +#include +#include #include #include #include @@ -202,6 +203,9 @@ namespace xo { /* run-time description for a native c++ type */ class TypeDescrBase { + public: + using ppindentinfo = xo::print::ppindentinfo; + public: /* type-description objects for a type T is unique, * --> can always use its address @@ -391,6 +395,9 @@ namespace xo { TypeDescr fn_arg(uint32_t i) const { return this->tdextra_->fn_arg(i); } bool fn_is_noexcept() const { return this->tdextra_->fn_is_noexcept(); } + /** pretty-printer support, using @p ppii **/ + bool pretty(const ppindentinfo & ppii) const; + void display(std::ostream & os) const; std::string display_string() const; @@ -543,7 +550,6 @@ namespace xo { return os; } - /* tag to drive overload resolution */ struct reflected_types_printer {}; @@ -567,6 +573,24 @@ namespace xo { static TypeDescrTable s_instance; }; } /*namespace reflect*/ + + namespace print { + template <> + struct ppdetail { + static bool print_pretty(const ppindentinfo & ppii, + const xo::reflect::TypeDescrBase & td) { + return td.pretty(ppii); + } + }; + + template <> + struct ppdetail { + static bool print_pretty(const ppindentinfo & ppii, + xo::reflect::TypeDescr td) { + return td ? td->pretty(ppii) : true; + } + }; + } /*namespace print*/ } /*namespace xo*/ namespace std { diff --git a/xo-reflect/include/xo/reflect/TypeDrivenMap.hpp b/xo-reflect/include/xo/reflect/TypeDrivenMap.hpp index d972780f..2568887d 100644 --- a/xo-reflect/include/xo/reflect/TypeDrivenMap.hpp +++ b/xo-reflect/include/xo/reflect/TypeDrivenMap.hpp @@ -17,7 +17,7 @@ namespace xo { TypeDrivenMap() = default; const Value * lookup(TypeId id) const { return this->lookup_slot(id); } - const Value * lookup(TypeDescr td) { return this->lookup_slot(td->id()); } + const Value * lookup(TypeDescr td) const { return this->lookup_slot(td->id()); } Value * require(TypeId id) { return this->require_slot(id); } Value * require(TypeDescr td) { return this->require_slot(td->id()); } diff --git a/xo-reflect/src/reflect/TypeDescr.cpp b/xo-reflect/src/reflect/TypeDescr.cpp index de5f4ada..c6cb1664 100644 --- a/xo-reflect/src/reflect/TypeDescr.cpp +++ b/xo-reflect/src/reflect/TypeDescr.cpp @@ -301,6 +301,19 @@ namespace xo { return this->tdextra_->child_tp(i, object); } /*child_tp*/ + bool + TypeDescrBase::pretty(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct + (ppii, + "TypeDescr", + refrtag("id", id_), + refrtag("canonical_name", canonical_name_), + refrtag("complete", complete_flag_), + refrtag("metatype", this->metatype())); + + } + void TypeDescrBase::display(std::ostream & os) const { diff --git a/xo-reflectutil/include/xo/reflectutil/type_name.hpp b/xo-reflectutil/include/xo/reflectutil/type_name.hpp new file mode 100644 index 00000000..bdce1b0a --- /dev/null +++ b/xo-reflectutil/include/xo/reflectutil/type_name.hpp @@ -0,0 +1,94 @@ +/* @file type_name.hpp */ + +#pragma once + +//#include +#include +#include // std::array +#include // std::index_sequence + +namespace xo { + namespace reflect { + + template + constexpr auto + substring_as_array(std::string_view str, + std::index_sequence indexes) + { + //return std::array{str[Idxs]..., '\n'}; + return std::array{str[Idxs]...}; + } /*substring_as_array*/ + + template constexpr auto type_name_array() { +#if defined(__clang__) + constexpr auto prefix = std::string_view{"[T = "}; + constexpr auto suffix = std::string_view{"]"}; + constexpr auto function = std::string_view{__PRETTY_FUNCTION__}; +#elif defined(__GNUC__) + constexpr auto prefix = std::string_view{"with T = "}; + constexpr auto suffix = std::string_view{"]"}; + constexpr auto function = std::string_view{__PRETTY_FUNCTION__}; +#elif defined(_MSC_VER) + constexpr auto prefix = std::string_view{"type_name_array<"}; + constexpr auto suffix = std::string_view{">(void)"}; + constexpr auto function = std::string_view{__FUNCSIG__}; +#else +# error type_name_array: Unsupported compiler +#endif + + constexpr auto start = function.find(prefix) + prefix.size(); + constexpr auto end = function.rfind(suffix); + + //static_assert(start < end); + + constexpr auto name = function.substr(start, (end - start)); + + constexpr auto ixseq = std::make_index_sequence{}; + + return substring_as_array(name, ixseq); + } /*type_name_array*/ + + template + struct type_name_holder { + static inline constexpr auto value = type_name_array(); + }; + + /** report name of type T as a string_view; + * using constexpr deps so runs at **/ + template + constexpr auto type_name() -> std::string_view + { + constexpr auto& value = type_name_holder::value; + return std::string_view{value.data(), value.size()}; + } + +#ifdef NOT_IN_USE + template + struct join + { + // Join all strings into a single std::array of chars + static constexpr auto impl() noexcept + { + constexpr std::size_t len = (Strs.size() + ... + 0); + std::array arr{}; + auto append = [i = 0, &arr](auto const& s) mutable { + for (auto c : s) arr[i++] = c; + }; + (append(Strs), ...); + arr[len] = 0; + return arr; + } + // Give the joined string static storage + static constexpr auto arr = impl(); + // View as a std::string_view + static constexpr std::string_view value {arr.data(), arr.size() - 1}; + }; + + // Helper to get the value out + template + static constexpr auto join_v = join::value; +#endif + } /*namespace reflect*/ +} /*namespace xo*/ + +/* end type_name.hpp */ diff --git a/xo-reflectutil/include/xo/reflectutil/typeseq.hpp b/xo-reflectutil/include/xo/reflectutil/typeseq.hpp index dd0b869a..d337cd5b 100644 --- a/xo-reflectutil/include/xo/reflectutil/typeseq.hpp +++ b/xo-reflectutil/include/xo/reflectutil/typeseq.hpp @@ -5,18 +5,20 @@ #pragma once +#include "type_name.hpp" #include #include namespace xo { namespace reflect { - /** - * Tag here so we can preserve header-only implementation - * and still have static variable - */ - template - struct typeseq_impl { - explicit typeseq_impl(int32_t s) : seqno_{s} {} +// template + struct typerecd { + /** sentinel value **/ + typerecd() = default; + + /** type-record with specific, unique id **/ + explicit typerecd(int32_t s, + std::string_view n) : seqno_{s}, name_{n} {} /** Can't have this be constexpr. * We need ids in shared libraries to be generated @@ -31,57 +33,89 @@ namespace xo { * when using clang. **/ template - static typeseq_impl id() { - static bool armed = true; + static typerecd recd() { + // reminder: {armed, id} are distint for each T + static bool s_armed = true; static int32_t id = 0; - if (armed) { - armed = false; - id = ++s_next_id; + if (s_armed) { + s_armed = false; + id = require_next_id(); } - return typeseq_impl(id); + return typerecd(id, xo::reflect::type_name()); } + static int32_t require_next_id() { + static int32_t s_next_id = 0; + return s_next_id++; + } + + int32_t seqno() const { return seqno_; } + std::string_view name() const { return name_; } + + /** sentinel typerecd instance **/ + static typerecd sentinel() { + return typerecd(-1, "_%sentinel%_"); + } + + private: + int32_t seqno_ = -1; + std::string_view name_; + }; + + //template + //int32_t typerecd_impl::s_next_id = 0; + + /** + * Tag here so we can preserve header-only implementation + * and still have static variable + */ + struct typeseq { + /** create sentinel value **/ + typeseq() = default; + + /** typeseq with specific unique id **/ + explicit typeseq(int32_t s) : seqno_{s} {} + /** 'anonymous' sentinel type. * Niche uses for this, e.g. untyped allocator **/ - static typeseq_impl anon() { - return typeseq_impl(-1); + static typeseq sentinel() { + return typeseq(typerecd::sentinel().seqno()); } + template + static typeseq id() { + return typeseq(xo::reflect::typerecd::recd().seqno()); + } + + bool is_sentinel() const { return seqno_ == -1; } int32_t seqno() const { return seqno_; } private: - static int32_t s_next_id; - - int32_t seqno_; + int32_t seqno_ = -1; }; - template - int32_t typeseq_impl::s_next_id = 0; + //template + //int32_t typeseq_impl::s_next_id = 0; - template inline bool - operator==(const typeseq_impl & lhs, const typeseq_impl & rhs) { + operator==(const typeseq & lhs, const typeseq & rhs) { return lhs.seqno() == rhs.seqno(); } - template inline bool - operator!=(const typeseq_impl & lhs, const typeseq_impl & rhs) { + operator!=(const typeseq & lhs, const typeseq & rhs) { return lhs.seqno() != rhs.seqno(); } - template inline std::ostream & - operator<<(std::ostream & s, const typeseq_impl & x) { + operator<<(std::ostream & s, const typeseq & x) { s << x.seqno(); return s; } - - using typeseq = typeseq_impl<>; } /*namespace reflect*/ } /*namespace xo*/ diff --git a/xo-tokenizer2/example/tokenrepl/tokenrepl.cpp b/xo-tokenizer2/example/tokenrepl/tokenrepl.cpp index 1cf02244..d8ddbd7f 100644 --- a/xo-tokenizer2/example/tokenrepl/tokenrepl.cpp +++ b/xo-tokenizer2/example/tokenrepl/tokenrepl.cpp @@ -85,32 +85,33 @@ main() { { //cout << "input: " << input << endl; + auto input_ext = Tokenizer::span_type::from_cstr(input_cstr); + // reminder: input may contain multiple tokens - if (input_cstr && *input_cstr) { - auto [error, input] = tkz.buffer_input_line(input_cstr, false /*!eof*/); + auto [error, input] = tkz.buffer_input_line(input_ext, false /*!eof*/); - if (log) { - log(xtag("msg", "buffered input line")); - log(xtag("input", input)); + if (log) { + log(xtag("msg", "buffered input line")); + log(xtag("input", input)); + } + + while (!input.empty()) + { + auto [tk, consumed, error] = tkz.scan(input); + + log && log(xtag("consumed", consumed), xtag("tk", tk)); + + if (tk.is_valid()) { + cout << tk << endl; + } else if (error.is_error()) { + cout << "tokenizer error: " << endl; + + error.report(cout); + + break; } - while (!input.empty()) - { - auto [tk, consumed, error] = tkz.scan(input); - - log && log(xtag("consumed", consumed), xtag("tk", tk)); - - if (tk.is_valid()) { - cout << tk << endl; - } else if (error.is_error()) { - cout << "tokenizer error: " << endl; - error.report(cout); - - break; - } - - input = input.after_prefix(consumed); - } + input = input.after_prefix(consumed); } /* here: input.empty() or error encountered */ diff --git a/xo-tokenizer2/include/xo/tokenizer2/Token.hpp b/xo-tokenizer2/include/xo/tokenizer2/Token.hpp index 0994e3b8..b211f967 100644 --- a/xo-tokenizer2/include/xo/tokenizer2/Token.hpp +++ b/xo-tokenizer2/include/xo/tokenizer2/Token.hpp @@ -92,33 +92,33 @@ namespace xo { /** token representing right angle bracket @c ">" **/ static Token rightangle() { return Token(tokentype::tk_rightangle); } /** token representing left parenthesis @c "(" **/ - static Token leftparen() { return Token(tokentype::tk_leftparen); } + static Token leftparen_token() { return Token(tokentype::tk_leftparen); } /** Token representing right parenthesis @c ")" **/ - static Token rightparen() { return Token(tokentype::tk_rightparen); } + static Token rightparen_token() { return Token(tokentype::tk_rightparen); } /** token representing left bracket @c "[" **/ static Token leftbracket() { return Token(tokentype::tk_leftbracket); } /** token representing right bracket @c "]" **/ static Token rightbracket() { return Token(tokentype::tk_rightbracket); } /** token representing left brace @c "{" **/ - static Token leftbrace() { return Token(tokentype::tk_leftbrace); } - /** token representing right brace @c "}' **/ - static Token rightbrace() { return Token(tokentype::tk_rightbrace); } + static Token leftbrace_token() { return Token(tokentype::tk_leftbrace); } + /** token representing right brace @c "}" **/ + static Token rightbrace_token() { return Token(tokentype::tk_rightbrace); } /** token representing period @c "." **/ static Token dot() { return Token(tokentype::tk_dot); } /** token representing comma @c "," **/ - static Token comma() { return Token(tokentype::tk_comma); } + static Token comma_token() { return Token(tokentype::tk_comma); } /** token representing colon @c ":" **/ - static Token colon() { return Token(tokentype::tk_colon); } + static Token colon_token() { return Token(tokentype::tk_colon); } /** token representing double-colo @c "::" **/ static Token doublecolon() { return Token(tokentype::tk_doublecolon); } /** token representing semicolon @c ";" **/ - static Token semicolon() { return Token(tokentype::tk_semicolon); } - /** token representing single-assignment @c "=" **/ - static Token singleassign() { return Token(tokentype::tk_singleassign); } + static Token semicolon_token() { return Token(tokentype::tk_semicolon); } + /** token representing single-assignment @c "=" (editor bait: equal_token) **/ + static Token singleassign_token() { return Token(tokentype::tk_singleassign); } /** token representing unrestricted assignment @c ":=" **/ static Token assign_token() { return Token(tokentype::tk_assign); } - /** token representing indirection @c "->" **/ - static Token yields() { return Token(tokentype::tk_yields); } + /** token representing indirection @c "->" / function return type **/ + static Token yields_token() { return Token(tokentype::tk_yields); } /** token for @c "+" **/ static Token plus_token() { return Token(tokentype::tk_plus); } @@ -129,14 +129,19 @@ namespace xo { /** token for @c "/" **/ static Token slash_token() { return Token(tokentype::tk_slash); } + /** token for @c "==" **/ + static Token cmpeq_token() { return Token(tokentype::tk_cmpeq); } + /** token representing keyword @c type **/ static Token type() { return Token(tokentype::tk_type); } /** token representing keyword @c def **/ - static Token def() { return Token(tokentype::tk_def); } + static Token def_token() { return Token(tokentype::tk_def); } /** token representing keyword @c lambda **/ - static Token lambda() { return Token(tokentype::tk_lambda); } + static Token lambda_token() { return Token(tokentype::tk_lambda); } /** token representing keyword @c if **/ static Token if_token() { return Token(tokentype::tk_if); } + /** token representing keyword @c then **/ + static Token then_token() { return Token(tokentype::tk_then); } /** token representing keyword @c else **/ static Token else_token() { return Token(tokentype::tk_else); } /** token representing keyword @c let **/ diff --git a/xo-tokenizer2/include/xo/tokenizer2/Tokenizer.hpp b/xo-tokenizer2/include/xo/tokenizer2/Tokenizer.hpp index 40a98cd9..0a212a8f 100644 --- a/xo-tokenizer2/include/xo/tokenizer2/Tokenizer.hpp +++ b/xo-tokenizer2/include/xo/tokenizer2/Tokenizer.hpp @@ -61,6 +61,7 @@ namespace xo { using error_type = TokenizerError; using DCircularBuffer = xo::mm::DCircularBuffer; using CircularBufferConfig = xo::mm::CircularBufferConfig; + using MemorySizeVisitor = xo::mm::MemorySizeVisitor; using span_type = xo::mm::span; //using input_state_type = TkInputState; using result_type = scan_result; @@ -90,6 +91,9 @@ namespace xo { const TkInputState & input_state() const { return input_state_; } #pragma GCC diagnostic pop + /** visit tokenizer-owned memory pools; invoke visitor(info) for each one **/ + void visit_pools(const MemorySizeVisitor & visitor) const; + ///@} /** @defgroup tokenizer-general-methods tokenizer methods **/ @@ -109,19 +113,19 @@ namespace xo { static bool is_2char_punctuation(CharT ch); /** assemble token from text @p token_text. - * @p initial_whitespace Amount of whitespace input being consumed from input. + * @p ws_span whitespace preceding token * @p token_text subset of input_line representing a single token. * @p p_input_state input state containing input_line. On exit current line cleared * if error * * retval.consumed will represent some possibly-empty prefix of @p input **/ - static scan_result assemble_token(std::size_t initial_whitespace, - const span_type & token_text, + static scan_result assemble_token( span_type ws_span, + span_type token_text, TkInputState * p_input_state); /** degenerate version of assemble_token() on reaching end-of-file **/ - static scan_result assemble_final_token(const span_type & token_text, + static scan_result assemble_final_token(span_type token_text, TkInputState * p_input_state); /** true if tokenizer contains stored prefix of @@ -129,10 +133,11 @@ namespace xo { **/ bool has_prefix() const { return !prefix_.empty(); } - /** buffer contents of input_cstr. + /** copy into buffer the contents of @p input. * May throw if buffer space exhausted **/ - std::pair buffer_input_line(const char * input_cstr, bool eof_flag); + std::pair buffer_input_line(span_type input, + bool eof_flag); /** scan for next input token, given @p input. * Note: diff --git a/xo-tokenizer2/include/xo/tokenizer2/TokenizerError.hpp b/xo-tokenizer2/include/xo/tokenizer2/TokenizerError.hpp index a1cb99ee..bf7702b1 100644 --- a/xo-tokenizer2/include/xo/tokenizer2/TokenizerError.hpp +++ b/xo-tokenizer2/include/xo/tokenizer2/TokenizerError.hpp @@ -32,7 +32,7 @@ namespace xo { * @p tk_start current position on entry to scanner * @p error_pos error location relative to token start **/ - TokenizerError(const char * src_function, + TokenizerError(std::string_view src_function, std::string error_description, const TkInputState & input_state, size_t error_pos) @@ -46,12 +46,20 @@ namespace xo { log && log(xtag("input_state.current_pos", input_state.current_pos()), xtag("error_pos", error_pos)); } + + TokenizerError with_error(std::string_view error_src_fn, + std::string error_msg) { + return TokenizerError(error_src_fn, + std::string(error_msg), + this->input_state_, + 0 /*error_pos*/); + } ///@} /** @defgroup tokenizer-error-access-methods **/ ///@{ - const char * src_function() const { return src_function_; } + std::string_view src_function() const { return src_function_; } const std::string & error_description() const { return error_description_; } #pragma GCC diagnostic push #ifndef __APPLE__ @@ -88,8 +96,8 @@ namespace xo { ///@{ /** source location (in tokenizer) at which error identified **/ - char const * src_function_ = nullptr; - /** static error description **/ + std::string_view src_function_; + /** error description **/ std::string error_description_; /** input state associated with this error. * Sufficient to precisely locate it with context. @@ -99,7 +107,7 @@ namespace xo { size_t error_pos_ = 0; ///@} - }; /*error_token*/ + }; inline std::ostream & operator<< (std::ostream & os, diff --git a/xo-tokenizer2/include/xo/tokenizer2/scan_result.hpp b/xo-tokenizer2/include/xo/tokenizer2/scan_result.hpp index 249154f1..45718c5c 100644 --- a/xo-tokenizer2/include/xo/tokenizer2/scan_result.hpp +++ b/xo-tokenizer2/include/xo/tokenizer2/scan_result.hpp @@ -28,9 +28,9 @@ namespace xo { **/ class scan_result { public: - using CharT = char; + //using CharT = char; using token_type = Token; - using span_type = xo::mm::span; + using span_type = xo::mm::span; using error_type = TokenizerError; using input_state_type = TkInputState; diff --git a/xo-tokenizer2/include/xo/tokenizer2/tokentype.hpp b/xo-tokenizer2/include/xo/tokenizer2/tokentype.hpp index eeeb7dd0..91cb3622 100644 --- a/xo-tokenizer2/include/xo/tokenizer2/tokentype.hpp +++ b/xo-tokenizer2/include/xo/tokenizer2/tokentype.hpp @@ -164,8 +164,8 @@ namespace xo { /** keyword @c 'end' **/ tk_end, - /** counts number of entries **/ - n_tokentype + /** comes last, counts number of entries **/ + N }; /*tokentype*/ /** String representation for enum value. diff --git a/xo-tokenizer2/src/tokenizer2/Tokenizer.cpp b/xo-tokenizer2/src/tokenizer2/Tokenizer.cpp index 4fa98a97..f176a88f 100644 --- a/xo-tokenizer2/src/tokenizer2/Tokenizer.cpp +++ b/xo-tokenizer2/src/tokenizer2/Tokenizer.cpp @@ -6,6 +6,7 @@ #include "Tokenizer.hpp" namespace xo { + using xo::mm::MemorySizeInfo; using std::byte; namespace scm { @@ -21,6 +22,12 @@ namespace xo { this->input_state_.discard_current_line(); } + void + Tokenizer::visit_pools(const MemorySizeVisitor & visitor) const + { + input_buffer_.visit_pools(visitor); + } + bool Tokenizer::is_1char_punctuation(CharT ch) { @@ -110,8 +117,8 @@ namespace xo { } auto - Tokenizer::assemble_token(std::size_t initial_whitespace, - const span_type & token_text, + Tokenizer::assemble_token(span_type ws_span, + span_type token_text, TkInputState * p_input_state) -> result_type { /* literal|pretty|streamlined */ @@ -119,7 +126,7 @@ namespace xo { scope log(XO_DEBUG(p_input_state->debug_flag())); log && log(xtag("token_text", token_text), - xtag("initial_whitespace", initial_whitespace), + xtag("initial_whitespace", ws_span.size()), xtag("input_state", *p_input_state)); tokentype tk_type = tokentype::tk_invalid; @@ -595,36 +602,36 @@ namespace xo { tk_text.clear(); } - /* input.prefix(0): - * require caller preserves current input line until it's entirely exhausted - */ - return result_type(token_type(tk_type, std::move(tk_text)), - p_input_state->current_line().prefix(0)); + // TOOD: report tk_text as span, + // but must pin / unpin + + return result_type(Token(tk_type, std::move(tk_text)), + span_type::concat(ws_span, + span_type(tk_start, tk_end))); } /*assemble_token*/ auto - Tokenizer::assemble_final_token(const span_type & token_text, + Tokenizer::assemble_final_token(span_type token_text, TkInputState * p_input_state) -> result_type { - return assemble_token(0 /*initial_whitespace*/, + return assemble_token(token_text.prefix(0) /*ws_span*/, token_text, p_input_state); } auto - Tokenizer::buffer_input_line(const char * input_cstr, + Tokenizer::buffer_input_line(span_type input_ext, bool eof_flag) -> std::pair { scope log(XO_DEBUG(input_state_.debug_flag())); - log && log(xtag("input", input_cstr)); + log && log(xtag("input_ext", input_ext)); auto buf_input_0 = input_buffer_.input_range().hi(); - auto remainder = input_buffer_.append - (DCircularBuffer::const_span_type::from_cstr(input_cstr)); - auto remainder2 = input_buffer_.append - (DCircularBuffer::const_span_type::from_cstr("\n")); + auto remainder = input_buffer_.append(input_ext); + auto remainder2 = input_buffer_.append(span_type::from_cstr("\n")); + //(DCircularBuffer::const_span_type::from_cstr("\n")); if (!remainder.empty() || !remainder2.empty()) { throw std::runtime_error(tostr("Tokenizer::buffer_line: line too long!", @@ -633,16 +640,17 @@ namespace xo { auto buf_input_1 = input_buffer_.input_range().hi(); - span_type input = span_type(buf_input_0, - buf_input_1); + span_type input_ours = span_type(buf_input_0, + buf_input_1); - return this->input_state_.capture_current_line(input, eof_flag); + return this->input_state_.capture_current_line(input_ours, eof_flag); } auto Tokenizer::scan(const span_type & input) -> result_type { scope log(XO_DEBUG(input_state_.debug_flag())); + log && log(xtag("input", input)); /* - Always at beginning of token when scan() invoked * - scan will not report any portion of line as consumed until it has @@ -657,12 +665,14 @@ namespace xo { const CharT * ix = this->input_state_.skip_leading_whitespace(); if(ix == input.hi()) { - log && log("end input -> consume current line"); + log && log("end buffered input -> consume current line"); /* entirety of current line has been tokenized * -> caller may consume it */ - return result_type::make_whitespace(this->input_state_.consume_current_line()); + this->input_state_.consume_current_line(); + + return result_type::make_whitespace(input); } /* ix: if ix < input.hi: first non-whitespace character after input_state_.current_pos_ */ @@ -695,27 +705,17 @@ namespace xo { ++ix; -#ifdef OBSOLETE // no longer a thing. either input ends in whitespace, or ends translation unit - if (ix == input.hi()) { - /* need more input to know if/when token complete */ - this->prefix_ += std::string(tk_start, input.hi()); + CharT ch2 = *ix; - log && log(xtag("captured-prefix1", this->prefix_)); - } else -#endif - { - CharT ch2 = *ix; - - if (((ch2 >= '0') && (ch2 <= '9')) - || ((ch2 >= 'A') && (ch2 <= 'Z')) - || ((ch2 >= 'a') && (ch2 <= 'z'))) + if (((ch2 >= '0') && (ch2 <= '9')) + || ((ch2 >= 'A') && (ch2 <= 'Z')) + || ((ch2 >= 'a') && (ch2 <= 'z'))) { /* treat as 1 char punctuation */ ; } else { - /* include next char */ - ++ix; - } + /* include next char */ + ++ix; } } else if (*ix == '"') { bool complete_flag = false; @@ -777,7 +777,7 @@ namespace xo { this->input_state_.advance_until(ix); - return assemble_token(whitespace_z, + return assemble_token(span_type(input.lo(), tk_start), span_type(tk_start, ix) /*token*/, &(this->input_state_)); } @@ -801,7 +801,7 @@ namespace xo { this->input_state_.advance_until(ix); /* ignore next char and complete token */ - return assemble_token(whitespace_z, + return assemble_token(span_type(input.lo(), tk_start), span_type(tk_start, ix) /*token*/, &(this->input_state_)); } @@ -852,7 +852,7 @@ namespace xo { this->input_state_.advance_until(ix); - return assemble_token(whitespace_z, + return assemble_token(span_type(input.lo(), tk_start), span_type(tk_start, ix) /*token*/, &(this->input_state_)); } /*_scan_aux*/ diff --git a/xo-tokenizer2/src/tokenizer2/tokentype.cpp b/xo-tokenizer2/src/tokenizer2/tokentype.cpp index 33d683de..40c2dbfb 100644 --- a/xo-tokenizer2/src/tokenizer2/tokentype.cpp +++ b/xo-tokenizer2/src/tokenizer2/tokentype.cpp @@ -60,7 +60,7 @@ namespace xo { CASE(tk_end); case tokentype::tk_invalid: - case tokentype::n_tokentype: + case tokentype::N: return "?tokentype"; }