From 3dc6268dfe91a0ccab60120d94fa014ade03ab08 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 12 Mar 2026 20:26:08 -0500 Subject: [PATCH] xo-interpreter2 stack: refactor + bugfix operator expr --- CMakeLists.txt | 16 ++ idl/IGCObject_DGlobalEnv.json5 | 18 ++ idl/IPrintable_DGlobalEnv.json5 | 16 ++ include/xo/reader2/DGlobalEnv.hpp | 94 ++++++ include/xo/reader2/GlobalEnv.hpp | 12 + include/xo/reader2/ParserConfig.hpp | 4 + include/xo/reader2/ParserStateMachine.hpp | 45 ++- include/xo/reader2/ReaderConfig.hpp | 4 + .../xo/reader2/env/IGCObject_DGlobalEnv.hpp | 67 +++++ .../xo/reader2/env/IPrintable_DGlobalEnv.hpp | 62 ++++ src/reader2/CMakeLists.txt | 4 + src/reader2/DGlobalEnv.cpp | 145 ++++++++++ src/reader2/DProgressSsm.cpp | 272 +++--------------- src/reader2/ParserStateMachine.cpp | 2 + src/reader2/SchematikaParser.cpp | 1 + src/reader2/SchematikaReader.cpp | 1 + src/reader2/facet/IGCObject_DGlobalEnv.cpp | 39 +++ src/reader2/facet/IPrintable_DGlobalEnv.cpp | 28 ++ src/reader2/reader2_register_facets.cpp | 9 + src/reader2/reader2_register_types.cpp | 7 +- 20 files changed, 615 insertions(+), 231 deletions(-) create mode 100644 idl/IGCObject_DGlobalEnv.json5 create mode 100644 idl/IPrintable_DGlobalEnv.json5 create mode 100644 include/xo/reader2/DGlobalEnv.hpp create mode 100644 include/xo/reader2/GlobalEnv.hpp create mode 100644 include/xo/reader2/env/IGCObject_DGlobalEnv.hpp create mode 100644 include/xo/reader2/env/IPrintable_DGlobalEnv.hpp create mode 100644 src/reader2/DGlobalEnv.cpp create mode 100644 src/reader2/facet/IGCObject_DGlobalEnv.cpp create mode 100644 src/reader2/facet/IPrintable_DGlobalEnv.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index faf792a9..a88c83e0 100644 --- a/CMakeLists.txt +++ b/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/idl/IGCObject_DGlobalEnv.json5 b/idl/IGCObject_DGlobalEnv.json5 new file mode 100644 index 00000000..1a590527 --- /dev/null +++ b/idl/IGCObject_DGlobalEnv.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2/facet", + 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/idl/IPrintable_DGlobalEnv.json5 b/idl/IPrintable_DGlobalEnv.json5 new file mode 100644 index 00000000..0a05eb62 --- /dev/null +++ b/idl/IPrintable_DGlobalEnv.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/interpreter2/facet", + 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/include/xo/reader2/DGlobalEnv.hpp b/include/xo/reader2/DGlobalEnv.hpp new file mode 100644 index 00000000..da7f8536 --- /dev/null +++ b/include/xo/reader2/DGlobalEnv.hpp @@ -0,0 +1,94 @@ +/** @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 TypeDescr = xo::reflect::TypeDescr; + 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 variables **/ + size_type n_vars() const noexcept { return symtab_->n_vars(); } + + /** 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); + + /** create/establish global for symbol @p sym with resolved type @p td + * and associate with @p value. + **/ + DVariable * _upsert_value(obj mm, + const DUniqueString * sym, + TypeDescr td, + obj value); + + ///@} + /** @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/include/xo/reader2/GlobalEnv.hpp b/include/xo/reader2/GlobalEnv.hpp new file mode 100644 index 00000000..94bafc42 --- /dev/null +++ b/include/xo/reader2/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/include/xo/reader2/ParserConfig.hpp b/include/xo/reader2/ParserConfig.hpp index 07dcb37b..2804be7b 100644 --- a/include/xo/reader2/ParserConfig.hpp +++ b/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/include/xo/reader2/ParserStateMachine.hpp b/include/xo/reader2/ParserStateMachine.hpp index f24c6bed..aa2797d0 100644 --- a/include/xo/reader2/ParserStateMachine.hpp +++ b/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/include/xo/reader2/ReaderConfig.hpp b/include/xo/reader2/ReaderConfig.hpp index 513f515e..9af06879 100644 --- a/include/xo/reader2/ReaderConfig.hpp +++ b/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/include/xo/reader2/env/IGCObject_DGlobalEnv.hpp b/include/xo/reader2/env/IGCObject_DGlobalEnv.hpp new file mode 100644 index 00000000..a2fcb5f6 --- /dev/null +++ b/include/xo/reader2/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/include/xo/reader2/env/IPrintable_DGlobalEnv.hpp b/include/xo/reader2/env/IPrintable_DGlobalEnv.hpp new file mode 100644 index 00000000..6efcd963 --- /dev/null +++ b/include/xo/reader2/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/src/reader2/CMakeLists.txt b/src/reader2/CMakeLists.txt index af8bf4af..bb49efb8 100644 --- a/src/reader2/CMakeLists.txt +++ b/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/src/reader2/DGlobalEnv.cpp b/src/reader2/DGlobalEnv.cpp new file mode 100644 index 00000000..fcc92efa --- /dev/null +++ b/src/reader2/DGlobalEnv.cpp @@ -0,0 +1,145 @@ +/** @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->var_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; + } + + DVariable * + DGlobalEnv::_upsert_value(obj mm, + const DUniqueString * sym, + TypeDescr td, + obj value) + { + DVariable * var + = DVariable::make(mm, sym, TypeRef::resolved(td)); + + assert(var); + + symtab_->upsert_variable(mm, var); + this->assign_value(mm, var->path(), value); + + return var; + } + + // ----- 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("n_vars", symtab_->n_vars())); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DGlobalEnv.cpp */ diff --git a/src/reader2/DProgressSsm.cpp b/src/reader2/DProgressSsm.cpp index be927bef..e2b0d1a1 100644 --- a/src/reader2/DProgressSsm.cpp +++ b/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/src/reader2/ParserStateMachine.cpp b/src/reader2/ParserStateMachine.cpp index 360ae43e..55845f3b 100644 --- a/src/reader2/ParserStateMachine.cpp +++ b/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/src/reader2/SchematikaParser.cpp b/src/reader2/SchematikaParser.cpp index d6ab1a0a..acfbeaa1 100644 --- a/src/reader2/SchematikaParser.cpp +++ b/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/src/reader2/SchematikaReader.cpp b/src/reader2/SchematikaReader.cpp index 0725a18c..98ef2292 100644 --- a/src/reader2/SchematikaReader.cpp +++ b/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/src/reader2/facet/IGCObject_DGlobalEnv.cpp b/src/reader2/facet/IGCObject_DGlobalEnv.cpp new file mode 100644 index 00000000..76606d6f --- /dev/null +++ b/src/reader2/facet/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/src/reader2/facet/IPrintable_DGlobalEnv.cpp b/src/reader2/facet/IPrintable_DGlobalEnv.cpp new file mode 100644 index 00000000..84fc561c --- /dev/null +++ b/src/reader2/facet/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/src/reader2/reader2_register_facets.cpp b/src/reader2/reader2_register_facets.cpp index dc9915ef..ccabe3a9 100644 --- a/src/reader2/reader2_register_facets.cpp +++ b/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/src/reader2/reader2_register_types.cpp b/src/reader2/reader2_register_types.cpp index 3720752d..3d6a0fe0 100644 --- a/src/reader2/reader2_register_types.cpp +++ b/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; }