diff --git a/CMakeLists.txt b/CMakeLists.txt index 3aa3d849..38bc2ade 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,11 +103,11 @@ add_subdirectory(xo-stringtable2) # experiment w/ facet object model add_subdirectory(xo-gc) # experiment w/ facet object model add_subdirectory(xo-object) add_subdirectory(xo-object2) # experiment w/ facet object model +add_subdirectory(xo-type) # experiment w/ fomo add_subdirectory(xo-procedure2) # schematika procedure abstraction + runtime context (fomo) add_subdirectory(xo-numeric) # experiment w/ facet object model add_subdirectory(xo-ordinaltree) # -add_subdirectory(xo-type) # experiment w/ (fomo) add_subdirectory(xo-tokenizer2) # schematika tokenizer (fomo) add_subdirectory(xo-expression2) # schematika expressions (fomo) add_subdirectory(xo-reader2) # schematika expression parser (fomo) diff --git a/xo-alloc2/include/xo/alloc2/gc/ACollector.hpp b/xo-alloc2/include/xo/alloc2/gc/ACollector.hpp index 1dfca96a..72d3802e 100644 --- a/xo-alloc2/include/xo/alloc2/gc/ACollector.hpp +++ b/xo-alloc2/include/xo/alloc2/gc/ACollector.hpp @@ -58,9 +58,14 @@ namespace xo { * Return false if installation fails (e.g. memory exhausted) **/ virtual bool install_type(Opaque d, const AGCObject & iface) = 0; + + /** add gc root with address @p p_root **/ virtual void add_gc_root_poly(Opaque d, obj * p_root) = 0; //virtual void add_gc_root_typed(Opaque d, typeseq tseq, Opaque * root) = 0; + /** remove gc root with address @p p_root **/ + virtual void remove_gc_root_poly(Opaque d, obj * p_root) = 0; + /** Request immediate collection. * 1. if collection is enabled, immediately collect all generations * up to (but not including) g diff --git a/xo-alloc2/include/xo/alloc2/gc/ICollector_Any.hpp b/xo-alloc2/include/xo/alloc2/gc/ICollector_Any.hpp index 6ed758c2..555adc6e 100644 --- a/xo-alloc2/include/xo/alloc2/gc/ICollector_Any.hpp +++ b/xo-alloc2/include/xo/alloc2/gc/ICollector_Any.hpp @@ -39,6 +39,7 @@ namespace xo { // non-const methods [[noreturn]] bool install_type(Opaque, const AGCObject &) noexcept override { _fatal(); } [[noreturn]] void add_gc_root_poly(Opaque, obj *) override { _fatal(); } + [[noreturn]] void remove_gc_root_poly(Opaque, obj *) override { _fatal(); } [[noreturn]] void request_gc(Opaque, generation) override { _fatal(); } [[noreturn]] void forward_inplace(Opaque, AGCObject *, void **) override { _fatal(); } diff --git a/xo-alloc2/include/xo/alloc2/gc/ICollector_Xfer.hpp b/xo-alloc2/include/xo/alloc2/gc/ICollector_Xfer.hpp index d7d43ef4..4100c8c5 100644 --- a/xo-alloc2/include/xo/alloc2/gc/ICollector_Xfer.hpp +++ b/xo-alloc2/include/xo/alloc2/gc/ICollector_Xfer.hpp @@ -53,6 +53,9 @@ namespace xo { void add_gc_root_poly(Opaque d, obj * p_root) override { I::add_gc_root_poly(_dcast(d), p_root); } + void remove_gc_root_poly(Opaque d, obj * p_root) override { + I::remove_gc_root_poly(_dcast(d), p_root); + } void request_gc(Opaque d, generation upto) override { I::request_gc(_dcast(d), upto); } diff --git a/xo-alloc2/include/xo/alloc2/gc/RCollector.hpp b/xo-alloc2/include/xo/alloc2/gc/RCollector.hpp index 9cce4844..b9d3e3ed 100644 --- a/xo-alloc2/include/xo/alloc2/gc/RCollector.hpp +++ b/xo-alloc2/include/xo/alloc2/gc/RCollector.hpp @@ -22,6 +22,9 @@ namespace xo { RCollector() = default; RCollector(DataPtr data) : Object{std::move(data)} {} + RCollector(const ACollector * iface, void * data) + requires std::is_same_v + : Object(iface, data) {} /** forward op in place. Defined in GCObject.hpp to avoid #include cycle **/ template @@ -33,6 +36,11 @@ namespace xo { template void forward_inplace(DRepr ** pp_repr); + /** convenience template where pointer requires pivot **/ + template + requires (!std::is_same_v) + void forward_pivot_inplace(obj * p_obj); + 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); } @@ -41,6 +49,7 @@ namespace xo { bool install_type(const AGCObject & iface) { return O::iface()->install_type(O::data(), iface); } void add_gc_root_poly(obj * p_root) { O::iface()->add_gc_root_poly(O::data(), p_root); } + void remove_gc_root_poly(obj * p_root) { O::iface()->remove_gc_root_poly(O::data(), p_root); } void request_gc(generation g) { O::iface()->request_gc(O::data(), g); } void forward_inplace(AGCObject * lhs_iface, void ** lhs_data) { O::iface()->forward_inplace(O::data(), lhs_iface, lhs_data); } @@ -50,6 +59,12 @@ namespace xo { O::iface()->add_gc_root_poly(O::data(), (obj *)p_root); } + /** remove root @p p_root **/ + template + void remove_gc_root(obj * p_root) { + O::iface()->remove_gc_root_poly(O::data(), (obj *)p_root); + } + static bool _valid; }; diff --git a/xo-alloc2/include/xo/alloc2/gc/RCollector_aux.hpp b/xo-alloc2/include/xo/alloc2/gc/RCollector_aux.hpp index b85c73b5..5e560358 100644 --- a/xo-alloc2/include/xo/alloc2/gc/RCollector_aux.hpp +++ b/xo-alloc2/include/xo/alloc2/gc/RCollector_aux.hpp @@ -10,6 +10,8 @@ #pragma once +#include + namespace xo { namespace mm { /** defined here to avoid #include cycle, since @@ -34,6 +36,16 @@ namespace xo { this->forward_inplace(&iface, (void **)p_repr); } + + template + template + requires (!std::is_same_v) + void + RCollector::forward_pivot_inplace(obj * p_objs) + { + auto e = xo::facet::FacetRegistry::instance().variant(*p_objs); + this->forward_inplace(e.iface(), (void **)&(p_objs->data_)); + } } } diff --git a/xo-alloc2/src/alloc2/CollectorTypeRegistry.cpp b/xo-alloc2/src/alloc2/CollectorTypeRegistry.cpp index 98d45a86..33f307c1 100644 --- a/xo-alloc2/src/alloc2/CollectorTypeRegistry.cpp +++ b/xo-alloc2/src/alloc2/CollectorTypeRegistry.cpp @@ -1,4 +1,6 @@ /** @file CollectorTypeRegistry.cpp + * + * @author Roland Conybeare, Mar 2026 **/ #include "CollectorTypeRegistry.hpp" diff --git a/xo-expression2/utest/DApplyExpr.test.cpp b/xo-expression2/utest/DApplyExpr.test.cpp index 17b3dca6..7854397d 100644 --- a/xo-expression2/utest/DApplyExpr.test.cpp +++ b/xo-expression2/utest/DApplyExpr.test.cpp @@ -92,7 +92,7 @@ namespace ut { REQUIRE(ok); // wrap primitive as GCObject, then as expression - obj prim_gco = with_facet::mkobj(&NumericPrimitives::s_mul_gco_gco_pm); + obj prim_gco = with_facet::mkobj(NumericPrimitives::make_multiply_pm(alloc)); obj fn_expr = DConstant::make(alloc, prim_gco); REQUIRE(fn_expr.data() != nullptr); @@ -131,7 +131,8 @@ namespace ut { bool ok = CollectorTypeRegistry::instance().install_types(coll); REQUIRE(ok); - obj prim_gco = with_facet::mkobj(&NumericPrimitives::s_mul_gco_gco_pm); + obj prim_gco + = with_facet::mkobj(NumericPrimitives::make_multiply_pm(alloc)); obj fn_expr = DConstant::make(alloc, prim_gco); obj val1 = DFloat::box(alloc, 3.0); @@ -166,7 +167,7 @@ namespace ut { bool ok = CollectorTypeRegistry::instance().install_types(coll); REQUIRE(ok); - obj prim_gco = with_facet::mkobj(&NumericPrimitives::s_mul_gco_gco_pm); + obj prim_gco = with_facet::mkobj(NumericPrimitives::make_multiply_pm(alloc)); obj fn_expr = DConstant::make(alloc, prim_gco); obj val1 = DFloat::box(alloc, 3.0); @@ -201,7 +202,7 @@ namespace ut { bool ok = CollectorTypeRegistry::instance().install_types(coll); REQUIRE(ok); - obj prim_gco = with_facet::mkobj(&NumericPrimitives::s_mul_gco_gco_pm); + obj prim_gco = with_facet::mkobj(NumericPrimitives::make_multiply_pm(alloc)); obj fn_expr = DConstant::make(alloc, prim_gco); obj val1 = DFloat::box(alloc, 3.0); @@ -283,7 +284,8 @@ namespace ut { bool ok = CollectorTypeRegistry::instance().install_types(coll); REQUIRE(ok); - obj prim_gco = with_facet::mkobj(&NumericPrimitives::s_mul_gco_gco_pm); + obj prim_gco + = with_facet::mkobj(NumericPrimitives::make_multiply_pm(alloc)); obj fn_expr = DConstant::make(alloc, prim_gco); obj val1 = DFloat::box(alloc, 3.0); diff --git a/xo-facet/include/xo/facet/FacetRegistry.hpp b/xo-facet/include/xo/facet/FacetRegistry.hpp index 69bfbee8..cbcf4979 100644 --- a/xo-facet/include/xo/facet/FacetRegistry.hpp +++ b/xo-facet/include/xo/facet/FacetRegistry.hpp @@ -9,7 +9,6 @@ #include "TypeRegistry.hpp" #include "facet_implementation.hpp" -//#include "typeseq.hpp" #include "obj.hpp" #include #include diff --git a/xo-facet/include/xo/facet/OObject.hpp b/xo-facet/include/xo/facet/OObject.hpp index c121e5ee..24397e58 100644 --- a/xo-facet/include/xo/facet/OObject.hpp +++ b/xo-facet/include/xo/facet/OObject.hpp @@ -273,7 +273,7 @@ namespace xo { * * Deliberately disable this for variants **/ - DRepr * operator->() + DRepr * operator->() const noexcept requires (!std::is_same_v) { return data_; } diff --git a/xo-gc/include/xo/gc/detail/ICollector_DX1Collector.hpp b/xo-gc/include/xo/gc/detail/ICollector_DX1Collector.hpp index 1db50e23..9e4c56a7 100644 --- a/xo-gc/include/xo/gc/detail/ICollector_DX1Collector.hpp +++ b/xo-gc/include/xo/gc/detail/ICollector_DX1Collector.hpp @@ -47,6 +47,7 @@ namespace xo { static bool install_type(DX1Collector & d, const AGCObject & iface); static void add_gc_root_poly(DX1Collector & d, obj * p_root); + static void remove_gc_root_poly(DX1Collector & d, obj * p_root); static void request_gc(DX1Collector & d, generation upto); static void forward_inplace(DX1Collector & d, AGCObject * lhs_iface, void ** lhs_data); diff --git a/xo-gc/src/gc/DX1Collector.cpp b/xo-gc/src/gc/DX1Collector.cpp index 78d27340..25665d73 100644 --- a/xo-gc/src/gc/DX1Collector.cpp +++ b/xo-gc/src/gc/DX1Collector.cpp @@ -287,6 +287,14 @@ namespace xo { *(obj **)mem = p_root; } + void + DX1Collector::remove_gc_root_poly(obj * p_root) noexcept + { + // iterate over roots_, find p_root and drop it + + (void)p_root; + } + void DX1Collector::request_gc(generation upto) noexcept { diff --git a/xo-gc/src/gc/ICollector_DX1Collector.cpp b/xo-gc/src/gc/ICollector_DX1Collector.cpp index e30182de..781fcfea 100644 --- a/xo-gc/src/gc/ICollector_DX1Collector.cpp +++ b/xo-gc/src/gc/ICollector_DX1Collector.cpp @@ -67,6 +67,13 @@ namespace xo { d.add_gc_root_poly(p_root); } + void + ICollector_DX1Collector::remove_gc_root_poly(DX1Collector & d, + obj * p_root) + { + d.remove_gc_root_poly(p_root); + } + void ICollector_DX1Collector::request_gc(DX1Collector & d, generation upto) diff --git a/xo-interpreter2/CMakeLists.txt b/xo-interpreter2/CMakeLists.txt index 229bf176..f325441b 100644 --- a/xo-interpreter2/CMakeLists.txt +++ b/xo-interpreter2/CMakeLists.txt @@ -161,24 +161,6 @@ xo_add_genfacetimpl( # ---------------------------------------------------------------- -# note: manual target; generated code committed to git -xo_add_genfacetimpl( - TARGET xo-interpreter2-facetimpl-gcobject-globalenv - FACET_PKG xo_alloc2 -# 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 -# REPR GlobalEnv - INPUT idl/IPrintable_DGlobalEnv.json5 -) - -# ---------------------------------------------------------------- - # note: manual target; generated code committed to git xo_add_genfacetimpl( TARGET xo-interpreter2-facetimpl-gcobject-localenv diff --git a/xo-interpreter2/src/interpreter2/CMakeLists.txt b/xo-interpreter2/src/interpreter2/CMakeLists.txt index c15ddef6..27927606 100644 --- a/xo-interpreter2/src/interpreter2/CMakeLists.txt +++ b/xo-interpreter2/src/interpreter2/CMakeLists.txt @@ -36,10 +36,6 @@ set(SELF_SRCS IGCObject_DClosure.cpp IPrintable_DClosure.cpp - DGlobalEnv.cpp - IGCObject_DGlobalEnv.cpp - IPrintable_DGlobalEnv.cpp - DLocalEnv.cpp IGCObject_DLocalEnv.cpp IPrintable_DLocalEnv.cpp diff --git a/xo-interpreter2/src/interpreter2/init_interpreter2.cpp b/xo-interpreter2/src/interpreter2/init_interpreter2.cpp index 73a6a5c2..6302be0c 100644 --- a/xo-interpreter2/src/interpreter2/init_interpreter2.cpp +++ b/xo-interpreter2/src/interpreter2/init_interpreter2.cpp @@ -27,6 +27,8 @@ namespace xo { InitEvidence InitSubsys::require() { + scope log(XO_DEBUG(true)); + InitEvidence retval; /* direct subsystem deps for xo-interpreter2/ */ diff --git a/xo-interpreter2/src/interpreter2/interpreter2_register_facets.cpp b/xo-interpreter2/src/interpreter2/interpreter2_register_facets.cpp index 22c9bfb9..24801f66 100644 --- a/xo-interpreter2/src/interpreter2/interpreter2_register_facets.cpp +++ b/xo-interpreter2/src/interpreter2/interpreter2_register_facets.cpp @@ -63,12 +63,7 @@ namespace xo { FacetRegistry::register_impl(); FacetRegistry::register_impl(); - // GlobalEnv - - FacetRegistry::register_impl(); - FacetRegistry::register_impl(); - - // LocalEnv + // LocalEnv (see xo-reader2/ for GlobalEnv) FacetRegistry::register_impl(); FacetRegistry::register_impl(); diff --git a/xo-interpreter2/src/skrepl/skreplxx.cpp b/xo-interpreter2/src/skrepl/skreplxx.cpp index 3362b823..e3d5564e 100644 --- a/xo-interpreter2/src/skrepl/skreplxx.cpp +++ b/xo-interpreter2/src/skrepl/skreplxx.cpp @@ -110,13 +110,15 @@ namespace xo { //using X1CollectorConfig = xo::mm::X1CollectorConfig; //using DArena = xo::mm::DArena; //using ArenaConfig = xo::mm::ArenaConfig; + using VsmConfig = xo::scm::VsmConfig; 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_)} + vsm_config_{cfg.vsm_config_} + //vsm_{cfg.vsm_config_, obj(&app_arena_)} { this->interactive_ = isatty(STDIN_FILENO); @@ -148,7 +150,8 @@ namespace xo { /** arena with same lifetime as this application **/ DArena app_arena_; /** schematika virtual machine **/ - VirtualSchematikaMachine vsm_; + VsmConfig vsm_config_; + std::unique_ptr vsm_; }; void @@ -162,13 +165,16 @@ namespace xo { void App::_init() { - // window to contorl size of registries ends as soon as we init other subsystems + // window to control 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(); + + vsm_.reset(new VirtualSchematikaMachine(vsm_config_, + obj(&app_arena_))); } void @@ -176,7 +182,7 @@ namespace xo { { welcome(cerr); - vsm_.begin_interactive_session(); + vsm_->begin_interactive_session(); } void @@ -186,7 +192,7 @@ namespace xo { span_type input; // outer loop: fetch one line of interactive input - while (replxx_getline(interactive_, vsm_.is_at_toplevel(), rx_, &input)) { + while (replxx_getline(interactive_, vsm_->is_at_toplevel(), rx_, &input)) { // inner loop: consume up to one expression at a time. while (!input.empty() && this->_read_eval_print(&input, false /*eof*/)) @@ -218,7 +224,7 @@ namespace xo { if (!p_input || p_input->empty()) return true; - VsmResultExt res = vsm_.read_eval_print(*p_input, eof); + VsmResultExt res = vsm_->read_eval_print(*p_input, eof); *p_input = res.remaining_; diff --git a/xo-numeric/include/xo/numeric/NumericPrimitives.hpp b/xo-numeric/include/xo/numeric/NumericPrimitives.hpp index b67ec911..feacb480 100644 --- a/xo-numeric/include/xo/numeric/NumericPrimitives.hpp +++ b/xo-numeric/include/xo/numeric/NumericPrimitives.hpp @@ -14,21 +14,25 @@ namespace xo { **/ class NumericPrimitives { public: - /** polymorphic (in both arguments) multiply **/ - static DPrimitive_gco_2_gco_gco s_mul_gco_gco_pm; + using AAllocator = xo::mm::AAllocator; + + public: + /** polymorphic (in both arguments1) multiply **/ + static DPrimitive_gco_2_gco_gco * make_multiply_pm(obj mm); + /** polymorphic (in both arguments) divide **/ - static DPrimitive_gco_2_gco_gco s_div_gco_gco_pm; + static DPrimitive_gco_2_gco_gco * make_divide_pm(obj mm); /** polymorphic (in both arguments) add **/ - static DPrimitive_gco_2_gco_gco s_add_gco_gco_pm; + static DPrimitive_gco_2_gco_gco * make_add_pm(obj mm); /** polymorphic (in both arguments) subtract **/ - static DPrimitive_gco_2_gco_gco s_sub_gco_gco_pm; + static DPrimitive_gco_2_gco_gco * make_subtract_pm(obj mm); /** polymorphic (in both arguments) compare (==) **/ - static DPrimitive_gco_2_gco_gco s_cmpeq_gco_gco_pm; + static DPrimitive_gco_2_gco_gco * make_cmpeq_pm(obj mm); /** polymorphic (in both arguments) compare (!=) **/ - static DPrimitive_gco_2_gco_gco s_cmpne_gco_gco_pm; + static DPrimitive_gco_2_gco_gco * make_cmpne_pm(obj mm); /** polymorphic (in both arguments) compare (<) **/ - static DPrimitive_gco_2_gco_gco s_cmplt_gco_gco_pm; + static DPrimitive_gco_2_gco_gco * make_cmplt_pm(obj mm); }; } } diff --git a/xo-numeric/include/xo/numeric/numeric_register_primitives.hpp b/xo-numeric/include/xo/numeric/numeric_register_primitives.hpp new file mode 100644 index 00000000..455d8b44 --- /dev/null +++ b/xo-numeric/include/xo/numeric/numeric_register_primitives.hpp @@ -0,0 +1,20 @@ +/** @file numeric_register_primitives.hpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#pragma once + +#include "PrimitiveRegistry.hpp" +#include + +namespace xo { + namespace scm { + /** Register gc-aware (AGCObject,DRepr) combinations with garbage collector @p gc **/ + bool numeric_register_primitives(obj gc, + InstallSink sink, + InstallFlags flags); + } +} + +/* end numeric_register_primitives.hpp */ diff --git a/xo-numeric/src/numeric/CMakeLists.txt b/xo-numeric/src/numeric/CMakeLists.txt index 4d2b4345..ca7dd6d5 100644 --- a/xo-numeric/src/numeric/CMakeLists.txt +++ b/xo-numeric/src/numeric/CMakeLists.txt @@ -4,6 +4,7 @@ set(SELF_LIB xo_numeric) set(SELF_SRCS init_numeric.cpp numeric_register_facets.cpp + numeric_register_primitives.cpp NumericPrimitives.cpp NumericDispatch.cpp INumeric_Any.cpp diff --git a/xo-numeric/src/numeric/NumericPrimitives.cpp b/xo-numeric/src/numeric/NumericPrimitives.cpp index f9cdf4d2..fabc3648 100644 --- a/xo-numeric/src/numeric/NumericPrimitives.cpp +++ b/xo-numeric/src/numeric/NumericPrimitives.cpp @@ -7,38 +7,59 @@ #include "NumericDispatch.hpp" namespace xo { - using xo::mm::AGCObject; + using xo::mm::AAllocator; + //using xo::mm::AGCObject; namespace scm { - DPrimitive_gco_2_gco_gco - NumericPrimitives::s_mul_gco_gco_pm("_mul", - &NumericDispatch::multiply); + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_multiply_pm(obj mm) + { + return DPrimitive_gco_2_gco_gco::_make(mm, "_mul", + &NumericDispatch::multiply); + } - DPrimitive_gco_2_gco_gco - NumericPrimitives::s_div_gco_gco_pm("_div", - &NumericDispatch::divide); + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_divide_pm(obj mm) + { + return DPrimitive_gco_2_gco_gco::_make(mm, "_div", + &NumericDispatch::divide); + } - DPrimitive_gco_2_gco_gco - NumericPrimitives::s_add_gco_gco_pm("_add", - &NumericDispatch::add); + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_add_pm(obj mm) + { + return DPrimitive_gco_2_gco_gco::_make(mm, "_add", + &NumericDispatch::add); + } - DPrimitive_gco_2_gco_gco - NumericPrimitives::s_sub_gco_gco_pm("_sub", - &NumericDispatch::subtract); + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_subtract_pm(obj mm) + { + return DPrimitive_gco_2_gco_gco::_make(mm, "_sub", + &NumericDispatch::subtract); + } - DPrimitive_gco_2_gco_gco - NumericPrimitives::s_cmpeq_gco_gco_pm("_cmpeq", - &NumericDispatch::cmp_equal); + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_cmpeq_pm(obj mm) + { + return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpeq", + &NumericDispatch::cmp_equal); + } - DPrimitive_gco_2_gco_gco - NumericPrimitives::s_cmpne_gco_gco_pm("_cmpne", - &NumericDispatch::cmp_notequal); - - DPrimitive_gco_2_gco_gco - NumericPrimitives::s_cmplt_gco_gco_pm("_cmplt", - &NumericDispatch::cmp_less); + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_cmpne_pm(obj mm) + { + return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpne", + &NumericDispatch::cmp_notequal); + } + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_cmplt_pm(obj mm) + { + return DPrimitive_gco_2_gco_gco::_make(mm, "_cmplt", + &NumericDispatch::cmp_less); + } } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-numeric/src/numeric/init_numeric.cpp b/xo-numeric/src/numeric/init_numeric.cpp index 1b205585..faa678a0 100644 --- a/xo-numeric/src/numeric/init_numeric.cpp +++ b/xo-numeric/src/numeric/init_numeric.cpp @@ -7,14 +7,20 @@ #include #include "Subsystem.hpp" #include "numeric_register_facets.hpp" +#include "numeric_register_primitives.hpp" namespace xo { using xo::scm::numeric_register_facets; + using xo::scm::numeric_register_primitives; + using xo::scm::PrimitiveRegistry; void InitSubsys::init() { numeric_register_facets(); + + PrimitiveRegistry::instance().register_primitives(&numeric_register_primitives); + } InitEvidence diff --git a/xo-numeric/src/numeric/numeric_register_primitives.cpp b/xo-numeric/src/numeric/numeric_register_primitives.cpp new file mode 100644 index 00000000..e407eca8 --- /dev/null +++ b/xo-numeric/src/numeric/numeric_register_primitives.cpp @@ -0,0 +1,81 @@ +/** @file numeric_register_primitives.cpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#include "numeric_register_primitives.hpp" +#include "NumericPrimitives.hpp" +#include "NumericDispatch.hpp" +#include +#include + +namespace xo { + using xo::mm::AAllocator; + using xo::scope; + + namespace scm { + namespace { + bool install_aux(InstallSink sink, + DPrimitive_gco_2_gco_gco * pm, + InstallFlags flags) + { + if (flags != InstallFlags::f_none) { + return sink(pm->name(), + pm->fn_td(), + obj(pm), + flags); + } else { + return true; + } + } + + bool install_aux(InstallSink sink, + obj mm, + std::string_view name, + obj (*impl)(obj rcx, + obj x, + obj y), + InstallFlags flags) + { + if (flags != InstallFlags::f_none) { + auto pm + = DPrimitive_gco_2_gco_gco::_make(mm, name, impl); + + return install_aux(sink, pm, flags); + } else { + return true; + } + } + } + + bool + numeric_register_primitives(obj mm, InstallSink sink, InstallFlags flags) + { + scope log(XO_DEBUG(true)); + + bool ok = true; + + ok = ok & install_aux(sink, + NumericPrimitives::make_multiply_pm(mm), + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, + NumericPrimitives::make_divide_pm(mm), + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, mm, "_add", &NumericDispatch::add, + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, mm, "_sub", &NumericDispatch::subtract, + flags & InstallFlags::f_essential); + + ok = ok & install_aux(sink, mm, "_cmpeq", &NumericDispatch::cmp_equal, + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, mm, "_cmpne", &NumericDispatch::cmp_notequal, + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, mm, "_cmplt", &NumericDispatch::cmp_less, + flags & InstallFlags::f_essential); + + return ok; + } + } +} /*namespace xo*/ + +/* end numeric_register_primitives.cpp */ diff --git a/xo-procedure2/cmake/xo_procedure2Config.cmake.in b/xo-procedure2/cmake/xo_procedure2Config.cmake.in index 96f11c99..250797df 100644 --- a/xo-procedure2/cmake/xo_procedure2Config.cmake.in +++ b/xo-procedure2/cmake/xo_procedure2Config.cmake.in @@ -6,8 +6,8 @@ include(CMakeFindDependencyMacro) # must coordinate with xo_dependency() calls # in CMakeLists.txt # +find_dependency(xo_type) find_dependency(xo_object2) -#find_dependency(xo_gc) find_dependency(subsys) include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") diff --git a/xo-procedure2/include/xo/procedure2/DPrimitive.hpp b/xo-procedure2/include/xo/procedure2/DPrimitive.hpp index 17c19435..7735bf0b 100644 --- a/xo-procedure2/include/xo/procedure2/DPrimitive.hpp +++ b/xo-procedure2/include/xo/procedure2/DPrimitive.hpp @@ -55,6 +55,18 @@ namespace xo { } /** @brief Schematika primitive with fixed number of arguments + * + * Distinction between type-constructor (@ref type_) and + * type-description (@ref fn_td_): type-constructor is narrower; + * it may lift into schematika type system some information about function + * behavior. For example + * @pre + * cons :: (T x list) -> list + * @endpre + * but implementation has signature: + * @pre + * (obj x obj) -> obj + * @endpre **/ template class Primitive { @@ -70,13 +82,28 @@ namespace xo { using ppindentinfo = xo::print::ppindentinfo; public: - Primitive(std::string_view name, Fn fn) : name_{name}, - fn_td_{Reflect::require()}, - fn_{fn} {} + /** @defgroup scm-primitive-ctors constructors **/ + ///@{ + + Primitive(std::string_view name, Fn fn) + : name_{name}, + fn_td_{Reflect::require()}, + fn_{fn} {} + + static Primitive * _make(obj mm, std::string_view name, Fn fn) { + void * mem = mm.alloc_for(); + + return new (mem) Primitive(name, fn); + } + + ///@} + /** @defgroup scm-primitive-methods general methods **/ + ///@{ 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; } @@ -86,6 +113,7 @@ namespace xo { std::make_index_sequence{}); } + ///@} /** @defgroup scm-primitive-printable-facet **/ ///@{ @@ -166,8 +194,12 @@ namespace xo { template std::size_t - Primitive::forward_children(obj) noexcept { - // Primitive holds no GC refs (just string_view + function pointer) + Primitive::forward_children(obj gc) noexcept { + { + auto e = type_.to_facet(); // FacetRegistry dep + gc.forward_inplace(e.iface(), (void **)&(type_.data_)); + } + return this->shallow_size(); } diff --git a/xo-procedure2/include/xo/procedure2/PrimitiveRegistry.hpp b/xo-procedure2/include/xo/procedure2/PrimitiveRegistry.hpp new file mode 100644 index 00000000..6f1f67ea --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/PrimitiveRegistry.hpp @@ -0,0 +1,89 @@ +/** @file PrimitiveRegistry.hpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#pragma once + +#include "Procedure.hpp" +#include +#include +#include + +namespace xo { + namespace scm { + /** partition primitives based on scope. + * Each primitive associates with exactly one flag value. + * Flags also operate as bitmasks when calling + * @ref PrimitiveRegistry::install_primitives() + **/ + enum class InstallFlags { + f_none = 0x0, + + /** mandatory primitives, necessary for operator support, + * e.g. _add needed to implement infix + + **/ + f_essential = 0x1, + f_generalpurpose = 0x2, + + /** all primitives **/ + f_all = f_essential | f_generalpurpose, + }; + + inline InstallFlags operator&(InstallFlags x, InstallFlags y) { + return InstallFlags(static_cast(x) & static_cast(y)); + } + + + + /** provided by VSM to receive created primitives. + * InstallSink(pm) adopts a primitive + **/ + using InstallSink = std::function pm, + InstallFlags flags)>; + + /** @class PrimitiveRegistry + * + * @brief Runtime registry for primitives + * + * Singleton to remember setup code for known primitives. + * Use to gather primitives for installation in global + * environment for a virtual schematika machine (VSM) + **/ + class PrimitiveRegistry { + public: + using AAllocator = xo::mm::AAllocator; + + /** provided by a subsystem that provides primitives. + * Allocates primitives using memory from mm, delivering them + * to InstallSink sink. + **/ + using InstallSource = std::function mm, + InstallSink sink, + InstallFlags flags)>; + + public: + /** singleton instance **/ + static PrimitiveRegistry & instance(); + + /** remember primitive-factory @p source_fn **/ + void register_primitives(InstallSource source_fn); + + /** create primitives using memory from @p mm, + * delivering each primitive to @p sink. + **/ + bool install_primitives(obj mm, + InstallSink sink, + InstallFlags flags); + + private: + /** a set of factories that create primitives **/ + std::vector init_seq_v_; + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end PrimitiveRegistry.hpp */ diff --git a/xo-procedure2/include/xo/procedure2/procedure2_register_primitives.hpp b/xo-procedure2/include/xo/procedure2/procedure2_register_primitives.hpp new file mode 100644 index 00000000..12e1db94 --- /dev/null +++ b/xo-procedure2/include/xo/procedure2/procedure2_register_primitives.hpp @@ -0,0 +1,18 @@ +/** @file procedure2_register_primitives.hpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#pragma once + +#include "PrimitiveRegistry.hpp" +#include + +namespace xo { + namespace scm { + /** Register gc-aware (AGCObject,DRepr) combinations with garbage collector @p gc **/ + bool procedure2_register_primitives(obj gc, InstallSink sink); + } +} + +/* end procedure2_register_primitives.hpp */ diff --git a/xo-procedure2/src/procedure2/CMakeLists.txt b/xo-procedure2/src/procedure2/CMakeLists.txt index b74b3e62..1a65a629 100644 --- a/xo-procedure2/src/procedure2/CMakeLists.txt +++ b/xo-procedure2/src/procedure2/CMakeLists.txt @@ -34,10 +34,9 @@ xo_install_include_tree3(include/xo/procedure2) # NOTE: dependency set here must be kept consistent with # xo-procedure2/cmake/xo_procedure2Config.cmake.in +xo_dependency(${SELF_LIB} xo_type) 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) diff --git a/xo-procedure2/src/procedure2/PrimitiveRegistry.cpp b/xo-procedure2/src/procedure2/PrimitiveRegistry.cpp new file mode 100644 index 00000000..0ce7aa68 --- /dev/null +++ b/xo-procedure2/src/procedure2/PrimitiveRegistry.cpp @@ -0,0 +1,49 @@ +/** @file PrimitiveRegistry.cpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#include "PrimitiveRegistry.hpp" +#include + +namespace xo { + namespace scm { + PrimitiveRegistry & + PrimitiveRegistry::instance() + { + static PrimitiveRegistry s_instance; + + return s_instance; + } + + void + PrimitiveRegistry::register_primitives(InstallSource factory) + { + scope log(XO_DEBUG(true)); + + init_seq_v_.push_back(factory); + } + + bool + PrimitiveRegistry::install_primitives(obj mm, + InstallSink sink, + InstallFlags flags) + { + scope log(XO_DEBUG(true)); + + bool ok = true; + + size_t i = 0; + size_t n = init_seq_v_.size(); + log && log("run n init steps", xtag("n", n)); + + for (const auto & fn : init_seq_v_) { + log && log("do install fn (", i+1, "/", n, ")"); + + ok = ok & fn(mm, sink, flags); + } + + return ok; + } + } +} /*namespace xo*/ diff --git a/xo-procedure2/src/procedure2/init_primitives.cpp b/xo-procedure2/src/procedure2/init_primitives.cpp index 142ad868..58b9d7aa 100644 --- a/xo-procedure2/src/procedure2/init_primitives.cpp +++ b/xo-procedure2/src/procedure2/init_primitives.cpp @@ -37,187 +37,6 @@ namespace xo { } #endif -#ifdef OBSOLETE // see xo-numeric/xo/numeric/NumericPrimitives.cpp - 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(); - } -#endif - #ifdef NOT_YET double mul_f64_f64(double x, double y) { @@ -255,17 +74,6 @@ namespace xo { } #endif -#ifdef OSOLETE - 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); -#endif - #ifdef NOT_YET Primitive_f64_1_f64 Primitives::s_neg_f64_pm("_neg_d", diff --git a/xo-reader2/CMakeLists.txt b/xo-reader2/CMakeLists.txt index faf792a9..a88c83e0 100644 --- a/xo-reader2/CMakeLists.txt +++ b/xo-reader2/CMakeLists.txt @@ -337,6 +337,22 @@ xo_add_genfacetimpl( # ---------------------------------------------------------------- +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-gcobject-globalenv + FACET_PKG xo_alloc2 + INPUT idl/IGCObject_DGlobalEnv.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-printable-globalenv + FACET_PKG xo_printable2 + INPUT idl/IPrintable_DGlobalEnv.json5 +) + +# ---------------------------------------------------------------- + xo_add_genfacet_all(xo-reader2-genfacet-all) # ---------------------------------------------------------------- diff --git a/xo-interpreter2/idl/IGCObject_DGlobalEnv.json5 b/xo-reader2/idl/IGCObject_DGlobalEnv.json5 similarity index 91% rename from xo-interpreter2/idl/IGCObject_DGlobalEnv.json5 rename to xo-reader2/idl/IGCObject_DGlobalEnv.json5 index 9ce50388..1a590527 100644 --- a/xo-interpreter2/idl/IGCObject_DGlobalEnv.json5 +++ b/xo-reader2/idl/IGCObject_DGlobalEnv.json5 @@ -1,6 +1,6 @@ { mode: "implementation", - output_cpp_dir: "src/interpreter2", + output_cpp_dir: "src/reader2/facet", output_hpp_dir: "include/xo/interpreter2", output_impl_subdir: "env", includes: [ diff --git a/xo-interpreter2/idl/IPrintable_DGlobalEnv.json5 b/xo-reader2/idl/IPrintable_DGlobalEnv.json5 similarity index 91% rename from xo-interpreter2/idl/IPrintable_DGlobalEnv.json5 rename to xo-reader2/idl/IPrintable_DGlobalEnv.json5 index 541146ae..0a05eb62 100644 --- a/xo-interpreter2/idl/IPrintable_DGlobalEnv.json5 +++ b/xo-reader2/idl/IPrintable_DGlobalEnv.json5 @@ -1,6 +1,6 @@ { mode: "implementation", - output_cpp_dir: "src/interpreter2", + output_cpp_dir: "src/interpreter2/facet", output_hpp_dir: "include/xo/interpreter2", output_impl_subdir: "env", includes: [ "", diff --git a/xo-interpreter2/include/xo/interpreter2/DGlobalEnv.hpp b/xo-reader2/include/xo/reader2/DGlobalEnv.hpp similarity index 100% rename from xo-interpreter2/include/xo/interpreter2/DGlobalEnv.hpp rename to xo-reader2/include/xo/reader2/DGlobalEnv.hpp diff --git a/xo-interpreter2/include/xo/interpreter2/GlobalEnv.hpp b/xo-reader2/include/xo/reader2/GlobalEnv.hpp similarity index 100% rename from xo-interpreter2/include/xo/interpreter2/GlobalEnv.hpp rename to xo-reader2/include/xo/reader2/GlobalEnv.hpp diff --git a/xo-reader2/include/xo/reader2/ParserConfig.hpp b/xo-reader2/include/xo/reader2/ParserConfig.hpp index 07dcb37b..2804be7b 100644 --- a/xo-reader2/include/xo/reader2/ParserConfig.hpp +++ b/xo-reader2/include/xo/reader2/ParserConfig.hpp @@ -5,6 +5,7 @@ #pragma once +#include #include #include @@ -55,6 +56,9 @@ namespace xo { /** max capacity for unique string table **/ size_t max_stringtable_capacity_ = 4096; + /** flags controlling which primitives to install **/ + InstallFlags pm_install_flags_ = InstallFlags::f_all; + /** control SchematikaParser debug logging **/ bool debug_flag_ = false; }; diff --git a/xo-reader2/include/xo/reader2/ParserStateMachine.hpp b/xo-reader2/include/xo/reader2/ParserStateMachine.hpp index f24c6bed..aa2797d0 100644 --- a/xo-reader2/include/xo/reader2/ParserStateMachine.hpp +++ b/xo-reader2/include/xo/reader2/ParserStateMachine.hpp @@ -6,11 +6,13 @@ #pragma once #include "ParserResult.hpp" +#include "GlobalEnv.hpp" #include #include #include #include #include +#include #include #include #include @@ -45,6 +47,9 @@ namespace xo { using size_type = std::size_t; public: + /** @defgroup scm-parserstatemachine-ctors constructors **/ + ///@{ + /** * @p config arena configuration for parser state * @p symtab_var_config configuration for global symtab variables @@ -53,6 +58,8 @@ namespace xo { * (maps to separate dedicated memory) * @p max_stringtable_capacity * hard max size for unique stringtable + * @p pm_install_flags + * flags controlling primitives to install * @p expr_alloc allocator for schematika expressions. * Probably shared with execution. * @p aux_alloc auxiliary allocator for non-copyable memory @@ -64,12 +71,17 @@ namespace xo { const ArenaHashMapConfig & symtab_var_config, const ArenaHashMapConfig & symtab_type_config, size_type max_stringtable_capacity, + InstallFlags pm_install_flags, obj expr_alloc, obj aux_alloc); - /** non-trivial dtor for @ref global_symtab_ **/ - ~ParserStateMachine() = default; + /** not copyable (need to put global_env into gc **/ + ParserStateMachine(const ParserStateMachine & other) = delete; + /** non-trivial dtor for @ref global_symtab_ **/ + ~ParserStateMachine(); + + ///@} /** @defgroup scm-parserstatemachine-accessors accessor methods **/ ///@{ @@ -80,6 +92,21 @@ namespace xo { DLocalSymtab * local_symtab() const noexcept { return local_symtab_; } const ParserResult & result() const noexcept { return result_; } + /** polymoprhihc multiply primitive. Use to implement infix op* **/ + obj multiply_pm() const; + /** polymorphic divide primitive. Use to implement infix op/ **/ + obj divide_pm() const; + /** polymorphic add primitive. Use to implement infix op+ **/ + obj add_pm() const; + /** polymorphic subtract primitive. Use to implement infix op- **/ + obj subtract_pm() const; + /** polymorphic equality comparison. Use to implement infix op== **/ + obj cmpeq_pm() const; + /** polymorphic inequality comparison. Use to implement infix op!= **/ + obj cmpne_pm() const; + /** polymorphich less-than comparison. Use to implement infix op< **/ + obj cmplt_pm() const; + /** true iff state machine is currently idle (at top-level) **/ bool is_at_toplevel() const noexcept; @@ -378,6 +405,20 @@ namespace xo { **/ DLocalSymtab * local_symtab_ = nullptr; + /** global variable bindings (builtin primitives) **/ + obj global_env_; + + /** bindings for special builtin primitives + * (asociated with hardwired operator syntax) + **/ + Binding multiply_binding_; + Binding divide_binding_; + Binding add_binding_; + Binding subtract_binding_; + Binding cmpeq_binding_; + Binding cmpne_binding_; + Binding cmplt_binding_; + /** current output from parser **/ ParserResult result_; diff --git a/xo-reader2/include/xo/reader2/ReaderConfig.hpp b/xo-reader2/include/xo/reader2/ReaderConfig.hpp index 513f515e..9af06879 100644 --- a/xo-reader2/include/xo/reader2/ReaderConfig.hpp +++ b/xo-reader2/include/xo/reader2/ReaderConfig.hpp @@ -5,6 +5,7 @@ #pragma once +#include #include #include #include @@ -71,6 +72,9 @@ namespace xo { /** max size (in bytes) of stringtable **/ size_t max_stringtable_cap_ = 64*1024; + /** flags controlling which primitives to install **/ + InstallFlags pm_install_flags_ = InstallFlags::f_all; + /** debug flag for schematika_reader **/ bool reader_debug_flag_ = false; }; diff --git a/xo-interpreter2/include/xo/interpreter2/env/IGCObject_DGlobalEnv.hpp b/xo-reader2/include/xo/reader2/env/IGCObject_DGlobalEnv.hpp similarity index 100% rename from xo-interpreter2/include/xo/interpreter2/env/IGCObject_DGlobalEnv.hpp rename to xo-reader2/include/xo/reader2/env/IGCObject_DGlobalEnv.hpp diff --git a/xo-interpreter2/include/xo/interpreter2/env/IPrintable_DGlobalEnv.hpp b/xo-reader2/include/xo/reader2/env/IPrintable_DGlobalEnv.hpp similarity index 100% rename from xo-interpreter2/include/xo/interpreter2/env/IPrintable_DGlobalEnv.hpp rename to xo-reader2/include/xo/reader2/env/IPrintable_DGlobalEnv.hpp diff --git a/xo-reader2/src/reader2/CMakeLists.txt b/xo-reader2/src/reader2/CMakeLists.txt index af8bf4af..bb49efb8 100644 --- a/xo-reader2/src/reader2/CMakeLists.txt +++ b/xo-reader2/src/reader2/CMakeLists.txt @@ -14,6 +14,10 @@ set(SELF_SRCS ParserStack.cpp ParserResult.cpp + DGlobalEnv.cpp + facet/IGCObject_DGlobalEnv.cpp + facet/IPrintable_DGlobalEnv.cpp + syntaxstatetype.cpp ISyntaxStateMachine_Any.cpp diff --git a/xo-interpreter2/src/interpreter2/DGlobalEnv.cpp b/xo-reader2/src/reader2/DGlobalEnv.cpp similarity index 100% rename from xo-interpreter2/src/interpreter2/DGlobalEnv.cpp rename to xo-reader2/src/reader2/DGlobalEnv.cpp diff --git a/xo-reader2/src/reader2/DProgressSsm.cpp b/xo-reader2/src/reader2/DProgressSsm.cpp index be927bef..e2b0d1a1 100644 --- a/xo-reader2/src/reader2/DProgressSsm.cpp +++ b/xo-reader2/src/reader2/DProgressSsm.cpp @@ -603,173 +603,6 @@ namespace xo { 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) @@ -1216,11 +1049,10 @@ namespace xo { obj assemble_numeric_expr_aux(obj expr_alloc, const TypeRef::prefix_type & prefix, - DPrimitive_gco_2_gco_gco * p_gco_pm, + obj pm_obj, obj lhs, obj rhs) { - auto pm_obj = with_facet::mkobj(p_gco_pm); auto fn_expr = DConstant::make(expr_alloc, pm_obj); /* note: @@ -1247,6 +1079,23 @@ namespace xo { tref, fn_expr, lhs, rhs); } + +#ifdef OBSOLETE + obj + assemble_numeric_expr_aux(obj expr_alloc, + const TypeRef::prefix_type & prefix, + DPrimitive_gco_2_gco_gco * p_gco_pm, + obj lhs, + obj rhs) + { + auto pm_obj = with_facet::mkobj(p_gco_pm); + + return assemble_numeric_expr_aux(expr_alloc, + prefix, + pm_obj, + lhs, rhs); + } +#endif } obj @@ -1288,41 +1137,21 @@ namespace xo { return assemble_numeric_expr_aux (p_psm->expr_alloc(), TypeRef::prefix_type::from_chars("_cmpeq_gco"), - &NumericPrimitives::s_cmpeq_gco_gco_pm, + p_psm->cmpeq_pm(), lhs_, rhs_); -#ifdef OBSOLETE - { - auto pm_obj = (with_facet::mkobj - (&NumericPrimitives::s_cmpeq_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; -#endif - case optype::op_not_equal: return assemble_numeric_expr_aux (p_psm->expr_alloc(), TypeRef::prefix_type::from_chars("_cmpne_gco"), - &NumericPrimitives::s_cmpne_gco_gco_pm, + p_psm->cmpne_pm(), lhs_, rhs_); case optype::op_less: return assemble_numeric_expr_aux (p_psm->expr_alloc(), TypeRef::prefix_type::from_chars("_cmplt_gco"), - &NumericPrimitives::s_cmplt_gco_gco_pm, + p_psm->cmplt_pm(), lhs_, rhs_); case optype::op_less_equal: @@ -1335,45 +1164,18 @@ namespace xo { return assemble_numeric_expr_aux (p_psm->expr_alloc(), TypeRef::prefix_type::from_chars("_mul_gco"), - &NumericPrimitives::s_mul_gco_gco_pm, + p_psm->multiply_pm(), //&NumericPrimitives::s_mul_gco_gco_pm lhs_, rhs_); -#ifdef OBSOLETE - { - auto pm_obj = (with_facet::mkobj - (&NumericPrimitives::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_); - } -#endif - break; case optype::op_divide: + return assemble_numeric_expr_aux + (p_psm->expr_alloc(), + TypeRef::prefix_type::from_chars("_div_gco"), + p_psm->divide_pm(), // &NumericPrimitives::s_div_gco_gco_pm + lhs_, rhs_); + +#ifdef OBSOLETE { auto pm_obj = (with_facet::mkobj (&NumericPrimitives::s_div_gco_gco_pm)); @@ -1405,10 +1207,17 @@ namespace xo { return DApplyExpr::make2(p_psm->expr_alloc(), tref, fn_expr, lhs_, rhs_); } +#endif break; case optype::op_add: + return assemble_numeric_expr_aux + (p_psm->expr_alloc(), + TypeRef::prefix_type::from_chars("_add_gco"), + p_psm->add_pm(), + lhs_, rhs_); +#ifdef OBSOLETE { auto pm_obj = (with_facet::mkobj (&NumericPrimitives::s_add_gco_gco_pm)); @@ -1440,10 +1249,18 @@ namespace xo { return DApplyExpr::make2(p_psm->expr_alloc(), tref, fn_expr, lhs_, rhs_); } +#endif break; case optype::op_subtract: /* editor bait: op_minus */ + return assemble_numeric_expr_aux + (p_psm->expr_alloc(), + TypeRef::prefix_type::from_chars("_sub_gco"), + p_psm->subtract_pm(), + lhs_, rhs_); + +#ifdef OBSOLETE { auto pm_obj = (with_facet::mkobj (&NumericPrimitives::s_sub_gco_gco_pm)); @@ -1459,6 +1276,7 @@ namespace xo { return DApplyExpr::make2(p_psm->expr_alloc(), tref, fn_expr, lhs_, rhs_); } +#endif break; diff --git a/xo-reader2/src/reader2/ParserStateMachine.cpp b/xo-reader2/src/reader2/ParserStateMachine.cpp index 360ae43e..55845f3b 100644 --- a/xo-reader2/src/reader2/ParserStateMachine.cpp +++ b/xo-reader2/src/reader2/ParserStateMachine.cpp @@ -8,8 +8,10 @@ #include "SyntaxStateMachine.hpp" #include "ToplevelSeqSsm.hpp" #include "DefineSsm.hpp" +#include #include #include +#include #include #include #include diff --git a/xo-reader2/src/reader2/SchematikaParser.cpp b/xo-reader2/src/reader2/SchematikaParser.cpp index d6ab1a0a..acfbeaa1 100644 --- a/xo-reader2/src/reader2/SchematikaParser.cpp +++ b/xo-reader2/src/reader2/SchematikaParser.cpp @@ -28,6 +28,7 @@ namespace xo { cfg.symtab_var_config_, cfg.symtab_types_config_, cfg.max_stringtable_capacity_, + cfg.pm_install_flags_, expr_alloc, aux_alloc }, diff --git a/xo-reader2/src/reader2/SchematikaReader.cpp b/xo-reader2/src/reader2/SchematikaReader.cpp index 0725a18c..98ef2292 100644 --- a/xo-reader2/src/reader2/SchematikaReader.cpp +++ b/xo-reader2/src/reader2/SchematikaReader.cpp @@ -18,6 +18,7 @@ namespace xo { config.symtab_var_config_, config.symtab_types_config_, config.max_stringtable_cap_, + config.pm_install_flags_, config.parser_debug_flag_), expr_alloc, aux_alloc}, diff --git a/xo-interpreter2/src/interpreter2/IGCObject_DGlobalEnv.cpp b/xo-reader2/src/reader2/facet/IGCObject_DGlobalEnv.cpp similarity index 100% rename from xo-interpreter2/src/interpreter2/IGCObject_DGlobalEnv.cpp rename to xo-reader2/src/reader2/facet/IGCObject_DGlobalEnv.cpp diff --git a/xo-interpreter2/src/interpreter2/IPrintable_DGlobalEnv.cpp b/xo-reader2/src/reader2/facet/IPrintable_DGlobalEnv.cpp similarity index 100% rename from xo-interpreter2/src/interpreter2/IPrintable_DGlobalEnv.cpp rename to xo-reader2/src/reader2/facet/IPrintable_DGlobalEnv.cpp diff --git a/xo-reader2/src/reader2/reader2_register_facets.cpp b/xo-reader2/src/reader2/reader2_register_facets.cpp index dc9915ef..ccabe3a9 100644 --- a/xo-reader2/src/reader2/reader2_register_facets.cpp +++ b/xo-reader2/src/reader2/reader2_register_facets.cpp @@ -33,6 +33,7 @@ namespace xo { using xo::print::APrintable; + using xo::mm::AGCObject; using xo::facet::FacetRegistry; using xo::facet::TypeRegistry; using xo::facet::typeseq; @@ -43,6 +44,13 @@ namespace xo { { scope log(XO_DEBUG(true)); + // GlobalEnv + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + // SyntaxStateMachine + FacetRegistry::register_impl(); FacetRegistry::register_impl(); @@ -105,6 +113,7 @@ namespace xo { // misc types showing up in parser stack arena TypeRegistry::register_type(); + log && log(xtag("DGlobalEnv.tseq", typeseq::id())); log && log(xtag("DToplevelSeqSsm.tseq", typeseq::id())); log && log(xtag("DDefineSsm.tseq", typeseq::id())); log && log(xtag("DDeftypeSsm.tseq", typeseq::id())); diff --git a/xo-reader2/src/reader2/reader2_register_types.cpp b/xo-reader2/src/reader2/reader2_register_types.cpp index 3720752d..3d6a0fe0 100644 --- a/xo-reader2/src/reader2/reader2_register_types.cpp +++ b/xo-reader2/src/reader2/reader2_register_types.cpp @@ -4,22 +4,25 @@ **/ #include "reader2_register_types.hpp" +#include "GlobalEnv.hpp" #include namespace xo { using xo::mm::ACollector; + using xo::mm::AGCObject; + using xo::facet::impl_for; using xo::scope; namespace scm { bool - reader2_register_types(obj /*gc*/) + reader2_register_types(obj gc) { scope log(XO_DEBUG(true)); bool ok = true; - /* no gc-aware types yet; scaffold for future use */ + ok &= gc.install_type(impl_for()); return ok; }