From 6db1ddc802984ca336e2ea0b33009ba7f2921aa7 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 2 Feb 2026 21:55:34 -0500 Subject: [PATCH] xo-interpreter2: scaffold repl + alloc measurement frameowkr --- .../interpreter2/VirtualSchematikaMachine.hpp | 63 ++++++++++++---- include/xo/interpreter2/VsmConfig.hpp | 3 + include/xo/interpreter2/VsmInstr.hpp | 4 +- src/interpreter2/CMakeLists.txt | 1 + src/interpreter2/VirtualSchematikaMachine.cpp | 73 ++++++++++++++----- src/interpreter2/VsmInstr.cpp | 18 +++++ utest/VirtualSchematikaMachine.test.cpp | 35 ++++++--- 7 files changed, 152 insertions(+), 45 deletions(-) create mode 100644 src/interpreter2/VsmInstr.cpp diff --git a/include/xo/interpreter2/VirtualSchematikaMachine.hpp b/include/xo/interpreter2/VirtualSchematikaMachine.hpp index c9dc0749..5165c9a8 100644 --- a/include/xo/interpreter2/VirtualSchematikaMachine.hpp +++ b/include/xo/interpreter2/VirtualSchematikaMachine.hpp @@ -14,21 +14,42 @@ namespace xo { namespace scm { + 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 + }; + /** similar to @ref xo::scm::ReaderResult **/ struct VsmResult { using AGCObject = xo::mm::AGCObject; using span_type = xo::mm::span; - bool is_tk_error() const { return tk_error_.is_error(); } + VsmResult() = default; + VsmResult(obj value) : result_{value} {} + 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 { return std::holds_alternative(result_); } + + const obj * value() const { return std::get_if>(&result_); } /** result of evaluating first expression encountered in input **/ - obj value_; + std::variant, TokenizerError, EvaluationError> result_; + }; - /** unconsumed portion of input span **/ - span_type remaining_input_; + /** vsm result + reamining span **/ + struct VsmResultExt : public VsmResult { + using span_type = VsmResult::span_type; - /** {src_function, error_description, input_state, error_pos} **/ - TokenizerError tk_error_; + VsmResultExt() = default; + VsmResultExt(const VsmResult & result, span_type rem) : VsmResult{result}, remaining_{rem} {} + + /** unconsumed portion of input **/ + VsmResult::span_type remaining_; }; /** @class VirtualSchematikaMachine @@ -40,16 +61,29 @@ namespace xo { using Stack = void *; using AAllocator = xo::mm::AAllocator; using AGCObject = xo::mm::AGCObject; + using MemorySizeInfo = xo::mm::MemorySizeInfo; using span_type = xo::mm::span; public: VirtualSchematikaMachine(const VsmConfig & config); - /** consume input @p input_cstr **/ - VsmResult read_eval_print(span_type input_span, bool eof); + size_t _n_store() const noexcept; + MemorySizeInfo _store_info(std::size_t i) const noexcept; - /** evaluate expression @p expr **/ - std::pair, TokenizerError> eval(obj expr); + /** 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 @@ -124,13 +158,16 @@ namespace xo { /** configuration **/ VsmConfig config_; + /** allocator (likely collector) for + * expressions and values + **/ box mm_; /** reader: text -> expression **/ SchematikaReader reader_; /** program counter **/ - VsmInstr pc_ = VsmInstr::halt(); + VsmInstr pc_ = VsmInstr::c_halt; #ifdef NOT_YET /** stack pointer **/ @@ -141,10 +178,10 @@ namespace xo { obj expr_; /** result register **/ - obj value_; + VsmResult value_; /** continuation register **/ - VsmInstr cont_ = VsmInstr::halt(); + VsmInstr cont_ = VsmInstr::c_halt; }; } /*namespace scm*/ } /*namespace xo*/ diff --git a/include/xo/interpreter2/VsmConfig.hpp b/include/xo/interpreter2/VsmConfig.hpp index 2957b297..9d13ab8e 100644 --- a/include/xo/interpreter2/VsmConfig.hpp +++ b/include/xo/interpreter2/VsmConfig.hpp @@ -17,6 +17,9 @@ namespace xo { VsmConfig() = default; + /** true for interactive parser session; false for batch session **/ + bool interactive_flag_ = true; + /** reader configuration **/ ReaderConfig rdr_config_; /** Configuration for allocator/collector. diff --git a/include/xo/interpreter2/VsmInstr.hpp b/include/xo/interpreter2/VsmInstr.hpp index ca74bc4c..c956c607 100644 --- a/include/xo/interpreter2/VsmInstr.hpp +++ b/include/xo/interpreter2/VsmInstr.hpp @@ -13,8 +13,8 @@ namespace xo { public: explicit VsmInstr(vsm_opcode oc) : opcode_{oc} {} - static VsmInstr halt() { return VsmInstr{vsm_opcode::halt}; } - static VsmInstr eval() { return VsmInstr{vsm_opcode::eval}; } + static VsmInstr c_halt; + static VsmInstr c_eval; vsm_opcode opcode() const noexcept { return opcode_; } diff --git a/src/interpreter2/CMakeLists.txt b/src/interpreter2/CMakeLists.txt index 7d9cd250..93ecd47e 100644 --- a/src/interpreter2/CMakeLists.txt +++ b/src/interpreter2/CMakeLists.txt @@ -4,6 +4,7 @@ set(SELF_LIB xo_interpreter2) set(SELF_SRCS init_interpreter2.cpp VirtualSchematikaMachine.cpp + VsmInstr.cpp #IExpression_Any.cpp #interpreter2_register_facets.cpp ) diff --git a/src/interpreter2/VirtualSchematikaMachine.cpp b/src/interpreter2/VirtualSchematikaMachine.cpp index fabc5441..d40b85c6 100644 --- a/src/interpreter2/VirtualSchematikaMachine.cpp +++ b/src/interpreter2/VirtualSchematikaMachine.cpp @@ -17,6 +17,7 @@ namespace xo { using xo::print::ppconfig; using xo::print::ppstate_standalone; using xo::mm::AGCObject; + using xo::mm::MemorySizeInfo; using xo::mm::DX1Collector; using xo::facet::FacetRegistry; using std::cout; @@ -29,50 +30,84 @@ namespace xo { reader_{config.rdr_config_, mm_.to_op()} {} - VsmResult + std::size_t + VirtualSchematikaMachine::_n_store() const noexcept + { + // oops. need something that goes through AAllocator api + + return reader_._n_store(); + } + + MemorySizeInfo + VirtualSchematikaMachine::_store_info(std::size_t i) const noexcept + { + // oops. need something poly that goes through AAllocator api + + return reader_._store_info(i); + } + + 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 VsmResult(); + return VsmResultExt(); } auto [expr, remaining, error1] = reader_.read_expr(input, eof); if (!expr) { - return { - .remaining_input_ = remaining, - .tk_error_ = error1 - }; + /* tokenizer error */ + + return VsmResultExt(VsmResult(error1), remaining); } - auto [value, error2] = this->eval(expr); + VsmResult evalresult = this->start_eval(expr); - if (!value) { - return { - .remaining_input_ = remaining, - .tk_error_ = error2 - }; + 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(value); + = FacetRegistry::instance().variant(*p_value); // pretty_toplevel(value_pr, &cout, ppconfig()); ppconfig ppc; ppstate_standalone pps(&cout, 0, &ppc); pps.prettyn(value_pr); - return { .remaining_input_ = remaining }; + return VsmResultExt(VsmResult(*p_value), remaining); } - std::pair, TokenizerError> - VirtualSchematikaMachine::eval(obj expr) + VsmResult + VirtualSchematikaMachine::start_eval(obj expr) { - (void)expr; + this->pc_ = VsmInstr::c_eval; + this->expr_ = expr; + this->value_ = obj(); + this->cont_ = VsmInstr::c_halt; - assert(false); - return std::make_pair(obj(), TokenizerError()); + this->run(); + + return value_; } void diff --git a/src/interpreter2/VsmInstr.cpp b/src/interpreter2/VsmInstr.cpp new file mode 100644 index 00000000..95a0ef74 --- /dev/null +++ b/src/interpreter2/VsmInstr.cpp @@ -0,0 +1,18 @@ +/** @file VsmInstr.cpp +* + * @author Roland Conybeare, Feb 2026 + **/ + +#include "VsmInstr.hpp" + +namespace xo { + namespace scm { + VsmInstr + VsmInstr::c_halt = VsmInstr(vsm_opcode::halt); + + VsmInstr + VsmInstr::c_eval = VsmInstr(vsm_opcode::eval); + } /*namespace scm*/ +} /*namespace xo*/ + +/* end VsmInstr.cpp */ diff --git a/utest/VirtualSchematikaMachine.test.cpp b/utest/VirtualSchematikaMachine.test.cpp index 8dacb437..a0554f87 100644 --- a/utest/VirtualSchematikaMachine.test.cpp +++ b/utest/VirtualSchematikaMachine.test.cpp @@ -4,6 +4,8 @@ **/ #include +#include +#include #ifdef NOT_YET #include @@ -16,12 +18,18 @@ #ifdef NOT_YET #include #endif +#include #include namespace xo { using xo::scm::VirtualSchematikaMachine; using xo::scm::VsmConfig; + using xo::scm::VsmResultExt; + using xo::scm::DFloat; + using xo::mm::AGCObject; + using span_type = xo::scm::VirtualSchematikaMachine::span_type; + using Catch::Matchers::WithinAbs; #ifdef NOT_YET using xo::scm::SchematikaParser; @@ -39,27 +47,32 @@ namespace xo { using xo::mm::DArena; using xo::facet::with_facet; #endif + using std::cout; + using std::endl; static InitEvidence s_init = (InitSubsys::require()); namespace ut { TEST_CASE("VirtualSchematikaMachine-ctor", "[interpreter2][VSM]") { - VirtualSchematikaMachine vsm(VsmConfig); + VsmConfig cfg; + VirtualSchematikaMachine vsm(cfg); -#ifdef NOT_YET - ArenaConfig config; - config.name_ = "test-arena"; - config.size_ = 16 * 1024; + bool eof_flag = false; - DArena expr_arena = DArena::map(config); - obj expr_alloc = with_facet::mkobj(&expr_arena); + vsm.begin_interactive_session(); + VsmResultExt res = vsm.read_eval_print(span_type::from_cstr("3.141592635;"), eof_flag); - SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + REQUIRE(res.is_value()); + REQUIRE(res.value()); - REQUIRE(parser.debug_flag() == false); - REQUIRE(parser.is_at_toplevel() == true); -#endif + 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'); } } /*namespace ut*/