From 31c6697467bc201955212580a4a81ec13bea2bff Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sun, 15 Feb 2026 14:13:38 -0500 Subject: [PATCH] xo-interpreter2 stack: plumbing for aux_mm and use opportunistically --- .../interpreter2/VirtualSchematikaMachine.hpp | 22 +- .../include/xo/interpreter2/VsmConfig.hpp | 15 +- .../interpreter2/VirtualSchematikaMachine.cpp | 26 +-- .../utest/VirtualSchematikaMachine.test.cpp | 211 ++++++++---------- .../example/readerreplxx/readerreplxx.cpp | 22 +- .../include/xo/reader2/ParserStateMachine.hpp | 27 ++- .../include/xo/reader2/SchematikaParser.hpp | 10 +- .../include/xo/reader2/SchematikaReader.hpp | 9 +- xo-reader2/src/reader2/ParserStateMachine.cpp | 9 +- xo-reader2/src/reader2/SchematikaParser.cpp | 5 +- xo-reader2/src/reader2/SchematikaReader.cpp | 4 +- xo-reader2/utest/SchematikaParser.test.cpp | 66 +++--- 12 files changed, 243 insertions(+), 183 deletions(-) diff --git a/xo-interpreter2/include/xo/interpreter2/VirtualSchematikaMachine.hpp b/xo-interpreter2/include/xo/interpreter2/VirtualSchematikaMachine.hpp index b809a09d..2cbd08e4 100644 --- a/xo-interpreter2/include/xo/interpreter2/VirtualSchematikaMachine.hpp +++ b/xo-interpreter2/include/xo/interpreter2/VirtualSchematikaMachine.hpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include namespace xo { namespace scm { @@ -74,7 +74,12 @@ namespace xo { using span_type = xo::mm::span; public: - VirtualSchematikaMachine(const VsmConfig & config); + /** @p config. configuration + * @p aux_mm. Allocator for miscellaneous dataN + * owned by this VSM. + **/ + VirtualSchematikaMachine(const VsmConfig & config, + obj aux_mm); /** allocator for schematika data **/ obj allocator() const noexcept; @@ -213,10 +218,17 @@ namespace xo { /** configuration **/ VsmConfig config_; +#ifdef NOT_YET + /** allocator (likely DArena) for globals. + * For example DArenaHashMap in global symtab, + **/ + obj aux_mm_; +#endif + /** allocator (likely DX1Collector or similar) for * expressions and values **/ - box mm_; + abox mm_; /** Sidecar allocator for error reporting. * Separate to mitigate interference with @ref mm_ @@ -224,12 +236,12 @@ namespace xo { * an out-of-memory error). * Likely DArena or similar **/ - box error_mm_; + abox error_mm_; /** runtime context for this vsm. * For example, provides allocator to primitives **/ - box rcx_; + abox rcx_; // consider separate allocator (which _may_ turn out to be the same) // for VM stack. Only works for code that doesn't rely on fancy diff --git a/xo-interpreter2/include/xo/interpreter2/VsmConfig.hpp b/xo-interpreter2/include/xo/interpreter2/VsmConfig.hpp index f05ac449..bfbe152e 100644 --- a/xo-interpreter2/include/xo/interpreter2/VsmConfig.hpp +++ b/xo-interpreter2/include/xo/interpreter2/VsmConfig.hpp @@ -19,15 +19,28 @@ namespace xo { VsmConfig() = default; + VsmConfig with_debug_flag(bool x) const { + VsmConfig retval = *this; + retval.debug_flag_ = x; + return retval; + } + /** true for interactive parser session; false for batch session **/ bool interactive_flag_ = true; + /** true to enable logging **/ + bool debug_flag_ = false; + /** reader configuration **/ ReaderConfig rdr_config_; /** Configuration for allocator/collector. * TODO: may want to make CollectorConfig polymorphic **/ - X1CollectorConfig x1_config_ = X1CollectorConfig().with_size(4*1024*1024); + X1CollectorConfig x1_config_ = X1CollectorConfig().with_name("gc").with_size(4*1024*1024); + /** Configuration for handful of non-moveable high-level objects + * e.g. DArenaHashMap in global symtab + **/ + ArenaConfig fixed_config_ = ArenaConfig().with_name("fixed").with_size(4*1024); /** Configuration for error allocator * TODO: may want to make ArenaConfig polymorphic **/ diff --git a/xo-interpreter2/src/interpreter2/VirtualSchematikaMachine.cpp b/xo-interpreter2/src/interpreter2/VirtualSchematikaMachine.cpp index f3473681..5c2d2c57 100644 --- a/xo-interpreter2/src/interpreter2/VirtualSchematikaMachine.cpp +++ b/xo-interpreter2/src/interpreter2/VirtualSchematikaMachine.cpp @@ -54,16 +54,16 @@ namespace xo { // NOTE: using heap here for {DX1Collector, DArena, DVsmRcx} instances // (though DX1Collector allocations will be from explictly mmap'd memory) // - VirtualSchematikaMachine::VirtualSchematikaMachine(const VsmConfig & config) + VirtualSchematikaMachine::VirtualSchematikaMachine(const VsmConfig & config, + obj aux_mm) : config_{config}, - mm_(box(new DX1Collector(config.x1_config_))), - rcx_(box(new DVsmRcx(this))), - reader_{config.rdr_config_, mm_.to_op()} + mm_(abox::make(aux_mm, config.x1_config_)), + rcx_(abox::make(aux_mm, this)), + reader_{config.rdr_config_, mm_.to_op(), aux_mm} { { - DArena * arena = new DArena(); + DArena * arena = new DArena(config_.error_config_); assert(arena); - *arena = DArena::map(config_.error_config_); error_mm_.adopt(obj(arena)); } @@ -165,7 +165,7 @@ namespace xo { bool VirtualSchematikaMachine::execute_one() { - scope log(XO_DEBUG(true)); + scope log(XO_DEBUG(config_.debug_flag_)); log && log(xtag("pc", pc_), xtag("cont", cont_)); @@ -333,10 +333,10 @@ namespace xo { // for now: halt VSM execution // TODO: some combination of - // 1. emit stack trace + // 1. emit stack trace // 2. go to debugger // 3. have every vsm instruction check inputs for errors - + this->pc_ = VsmInstr::c_halt; } @@ -396,7 +396,7 @@ namespace xo { // control: // self -> eval(test) -> ifelse_cont -> eval(when_true) // -> eval(when_false) - + auto ifelse_expr = obj::from(expr_); obj ifelse_frame @@ -433,7 +433,7 @@ namespace xo { return; } - auto seqexpr_frame + auto seqexpr_frame = obj (DVsmSeqContFrame::make(mm_.to_op(), this->stack_ /*saved stack*/, @@ -693,10 +693,10 @@ namespace xo { // for now: halt VSM execution // TODO: some combination of - // 1. emit stack trace + // 1. emit stack trace // 2. go to debugger // 3. have every vsm instruction check inputs for errors - + this->pc_ = VsmInstr::c_halt; } } diff --git a/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp b/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp index eb62267e..1a50c555 100644 --- a/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp +++ b/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #ifdef NOT_YET #include @@ -37,61 +38,80 @@ namespace xo { using xo::scm::DRuntimeError; using xo::mm::AGCObject; using xo::mm::MemorySizeInfo; + using xo::mm::AAllocator; + using xo::mm::DArena; + using xo::mm::ArenaConfig; using xo::facet::FacetRegistry; using span_type = xo::scm::VirtualSchematikaMachine::span_type; using Catch::Matchers::WithinAbs; -#ifdef NOT_YET - using xo::scm::SchematikaParser; - using xo::scm::ASyntaxStateMachine; - using xo::scm::syntaxstatetype; -// using xo::scm::DDefineSsm; - using xo::scm::DExpectExprSsm; -// using xo::scm::defexprstatetype; - //using xo::scm::ParserResult; - //using xo::scm::parser_result_type; - using xo::scm::Token; - using xo::scm::DString; - using xo::mm::ArenaConfig; - using xo::mm::AAllocator; - using xo::mm::DArena; - using xo::facet::with_facet; -#endif using std::cout; using std::endl; static InitEvidence s_init = (InitSubsys::require()); namespace ut { + struct ArenaShim { + explicit ArenaShim(const std::string & name, std::size_t size = 16*1024) + : arena_(ArenaConfig().with_name(name).with_size(size)) + { + } + + obj to_op() { return obj(&arena_); } + + DArena arena_; + }; + + struct VsmFixture { + explicit VsmFixture(const std::string & testname, + bool debug_flag, + const VsmConfig & cfg = VsmConfig()) + : aux_mm_{testname}, + vsm_{cfg.with_debug_flag(debug_flag), aux_mm_.to_op()} + {} + + bool log_memory_layout(scope * p_log) { + auto visitor = [p_log](const MemorySizeInfo & info) { + *p_log && (*p_log)(xtag("resource", info.resource_name_), + xtag("used", info.used_), + xtag("alloc", info.allocated_), + xtag("commit", info.committed_), + xtag("resv", info.reserved_)); + }; + + aux_mm_.arena_.visit_pools(visitor); + FacetRegistry::instance().visit_pools(visitor); + vsm_.visit_pools(visitor); + + return true; + } + + ArenaShim aux_mm_; + VirtualSchematikaMachine vsm_; + }; + TEST_CASE("VirtualSchematikaMachine-ctor", "[interpreter2][VSM]") { const auto & testname = Catch::getResultCapture().getCurrentTestName(); - scope log(XO_DEBUG(true), xtag("test", testname)); + bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); - VsmConfig cfg; - VirtualSchematikaMachine vsm(cfg); + VsmFixture vsm_fixture(testname, c_debug_flag); - auto visitor = [&log](const MemorySizeInfo & info) { - log && log(xtag("resource", info.resource_name_), - xtag("used", info.used_), - xtag("alloc", info.allocated_), - xtag("commit", info.committed_), - xtag("resv", info.reserved_)); - }; - - FacetRegistry::instance().visit_pools(visitor); - vsm.visit_pools(visitor); + log && vsm_fixture.log_memory_layout(&log); } TEST_CASE("VirtualSchematikaMachine-const1", "[interpreter2][VSM]") { const auto & testname = Catch::getResultCapture().getCurrentTestName(); - scope log(XO_DEBUG(true), xtag("test", testname)); + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); - VsmConfig cfg; - VirtualSchematikaMachine vsm(cfg); + VsmFixture vsm_fixture(testname, c_debug_flag); + + auto & vsm = vsm_fixture.vsm_; bool eof_flag = false; @@ -109,26 +129,19 @@ namespace xo { REQUIRE(res.remaining_.size() == 1); REQUIRE(*res.remaining_.lo() == '\n'); - auto visitor = [&log](const MemorySizeInfo & info) { - log && log(xtag("resource", info.resource_name_), - xtag("used", info.used_), - xtag("alloc", info.allocated_), - xtag("commit", info.committed_), - xtag("resv", info.reserved_)); - }; - - FacetRegistry::instance().visit_pools(visitor); - vsm.visit_pools(visitor); + log && vsm_fixture.log_memory_layout(&log); } TEST_CASE("VirtualSchematikaMachine-const2", "[interpreter2][VSM]") { const auto & testname = Catch::getResultCapture().getCurrentTestName(); - scope log(XO_DEBUG(true), xtag("test", testname)); + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); - VsmConfig cfg; - VirtualSchematikaMachine vsm(cfg); + VsmFixture vsm_fixture(testname, c_debug_flag); + + auto & vsm = vsm_fixture.vsm_; bool eof_flag = false; @@ -148,26 +161,18 @@ namespace xo { REQUIRE(res.remaining_.size() == 1); REQUIRE(*res.remaining_.lo() == '\n'); - auto visitor = [&log](const MemorySizeInfo & info) { - log && log(xtag("resource", info.resource_name_), - xtag("used", info.used_), - xtag("alloc", info.allocated_), - xtag("commit", info.committed_), - xtag("resv", info.reserved_)); - }; - - FacetRegistry::instance().visit_pools(visitor); - vsm.visit_pools(visitor); + log && vsm_fixture.log_memory_layout(&log); } TEST_CASE("VirtualSchematikaMachine-arith1", "[interpreter2][VSM]") { const auto & testname = Catch::getResultCapture().getCurrentTestName(); - scope log(XO_DEBUG(true), xtag("test", testname)); + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); - VsmConfig cfg; - VirtualSchematikaMachine vsm(cfg); + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; bool eof_flag = false; @@ -187,16 +192,7 @@ namespace xo { REQUIRE(res.remaining_.size() == 1); REQUIRE(*res.remaining_.lo() == '\n'); - auto visitor = [&log](const MemorySizeInfo & info) { - log && log(xtag("resource", info.resource_name_), - xtag("used", info.used_), - xtag("alloc", info.allocated_), - xtag("commit", info.committed_), - xtag("resv", info.reserved_)); - }; - - FacetRegistry::instance().visit_pools(visitor); - vsm.visit_pools(visitor); + log && vsm_fixture.log_memory_layout(&log); } TEST_CASE("VirtualSchematikaMachine-cmp1", "[interpreter2][VSM]") @@ -206,13 +202,15 @@ namespace xo { constexpr bool c_debug_flag = false; scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); - VsmConfig cfg; - VirtualSchematikaMachine vsm(cfg); + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; bool eof_flag = false; vsm.begin_interactive_session(); - VsmResultExt res = vsm.read_eval_print(span_type::from_cstr("123 == 123;"), eof_flag); + VsmResultExt res + = vsm.read_eval_print(span_type::from_cstr("123 == 123;"), + eof_flag); REQUIRE(res.is_value()); REQUIRE(res.value()); @@ -227,32 +225,25 @@ namespace xo { REQUIRE(res.remaining_.size() == 1); REQUIRE(*res.remaining_.lo() == '\n'); - auto visitor = [&log](const MemorySizeInfo & info) { - log && log(xtag("resource", info.resource_name_), - xtag("used", info.used_), - xtag("alloc", info.allocated_), - xtag("commit", info.committed_), - xtag("resv", info.reserved_)); - }; - - FacetRegistry::instance().visit_pools(visitor); - vsm.visit_pools(visitor); + log && vsm_fixture.log_memory_layout(&log); } TEST_CASE("VirtualSchematikaMachine-if", "[interpreter2][VSM]") { const auto & testname = Catch::getResultCapture().getCurrentTestName(); - constexpr bool c_debug_flag = true; + constexpr bool c_debug_flag = false; scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); - VsmConfig cfg; - VirtualSchematikaMachine vsm(cfg); + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; bool eof_flag = false; vsm.begin_interactive_session(); - VsmResultExt res = vsm.read_eval_print(span_type::from_cstr("if 123 == 123 then \"equal\" else \"notequal\";"), eof_flag); + VsmResultExt res + = vsm.read_eval_print(span_type::from_cstr("if 123 == 123 then \"equal\" else \"notequal\";"), + eof_flag); REQUIRE(res.is_value()); REQUIRE(res.value()); @@ -267,16 +258,7 @@ namespace xo { REQUIRE(res.remaining_.size() == 1); REQUIRE(*res.remaining_.lo() == '\n'); - auto visitor = [&log](const MemorySizeInfo & info) { - log && log(xtag("resource", info.resource_name_), - xtag("used", info.used_), - xtag("alloc", info.allocated_), - xtag("commit", info.committed_), - xtag("resv", info.reserved_)); - }; - - FacetRegistry::instance().visit_pools(visitor); - vsm.visit_pools(visitor); + log && vsm_fixture.log_memory_layout(&log); } TEST_CASE("VirtualSchematikaMachine-lambda1", "[interpreter2][VSM]") @@ -286,13 +268,15 @@ namespace xo { constexpr bool c_debug_flag = false; scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); - VsmConfig cfg; - VirtualSchematikaMachine vsm(cfg); + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; bool eof_flag = false; vsm.begin_interactive_session(); - VsmResultExt res = vsm.read_eval_print(span_type::from_cstr("lambda (x : i64) -> i64 { x * x; }"), eof_flag); + VsmResultExt res + = vsm.read_eval_print(span_type::from_cstr("lambda (x : i64) -> i64 { x * x; }"), + eof_flag); REQUIRE(res.is_value()); REQUIRE(res.value()); @@ -307,26 +291,18 @@ namespace xo { REQUIRE(res.remaining_.size() == 1); REQUIRE(*res.remaining_.lo() == '\n'); - auto visitor = [&log](const MemorySizeInfo & info) { - log && log(xtag("resource", info.resource_name_), - xtag("used", info.used_), - xtag("alloc", info.allocated_), - xtag("commit", info.committed_), - xtag("resv", info.reserved_)); - }; - - FacetRegistry::instance().visit_pools(visitor); - vsm.visit_pools(visitor); + log && vsm_fixture.log_memory_layout(&log); } TEST_CASE("VirtualSchematikaMachine-apply2", "[interpreter2][VSM]") { const auto & testname = Catch::getResultCapture().getCurrentTestName(); - scope log(XO_DEBUG(false), xtag("test", testname)); + bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); - VsmConfig cfg; - VirtualSchematikaMachine vsm(cfg); + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; bool eof_flag = false; @@ -341,7 +317,7 @@ namespace xo { log && log(xtag("res.tseq", res.value()->_typeseq())); - // currently get not-implemented error + // currently get not-implemented error auto x = obj::from(*res.value()); REQUIRE(x); @@ -354,16 +330,7 @@ namespace xo { REQUIRE(res.remaining_.size() == 1); REQUIRE(*res.remaining_.lo() == '\n'); - auto visitor = [&log](const MemorySizeInfo & info) { - log && log(xtag("resource", info.resource_name_), - xtag("used", info.used_), - xtag("alloc", info.allocated_), - xtag("commit", info.committed_), - xtag("resv", info.reserved_)); - }; - - FacetRegistry::instance().visit_pools(visitor); - vsm.visit_pools(visitor); + log && vsm_fixture.log_memory_layout(&log); } } /*namespace ut*/ diff --git a/xo-reader2/example/readerreplxx/readerreplxx.cpp b/xo-reader2/example/readerreplxx/readerreplxx.cpp index c95dd101..292c3a43 100644 --- a/xo-reader2/example/readerreplxx/readerreplxx.cpp +++ b/xo-reader2/example/readerreplxx/readerreplxx.cpp @@ -2,8 +2,9 @@ #include #include -#include +#include #include +#include #include #include #include @@ -137,6 +138,7 @@ namespace { struct AppConfig { using ReaderConfig = xo::scm::ReaderConfig; using X1CollectorConfig = xo::mm::X1CollectorConfig; + using ArenaConfig = xo::mm::ArenaConfig; AppConfig() { rdr_config_.reader_debug_flag_ = true; @@ -147,17 +149,24 @@ struct AppConfig { std::size_t max_history_size_ = 1000; std::string repl_history_fname_ = "repl_history.txt";; ReaderConfig rdr_config_; - X1CollectorConfig x1_config_ = (X1CollectorConfig().with_size(4*1024*1024)); + X1CollectorConfig x1_config_ = (X1CollectorConfig().with_name("gc").with_size(4*1024*1024)); + ArenaConfig fixed_config_ = (ArenaConfig().with_name("fixed").with_size(4*1024)); }; struct AppContext { + using AAllocator = xo::mm::AAllocator; using DX1Collector = xo::mm::DX1Collector; using X1CollectorConfig = xo::mm::X1CollectorConfig; + using DArena = xo::mm::DArena; + using ArenaConfig = xo::mm::ArenaConfig; using Replxx = replxx::Replxx; AppContext(const AppConfig & cfg = AppConfig()) : config_{cfg}, - x1_{X1CollectorConfig().with_size(4*1024*1024)}, - rdr_{config_.rdr_config_, x1_.ref()} + x1_{cfg.x1_config_}, + fixed_{cfg.fixed_config_}, + rdr_{config_.rdr_config_, + x1_.ref(), + obj(&fixed_)} { rx_.set_max_history_size(config_.max_history_size_); rx_.history_load(config_.repl_history_fname_); @@ -167,9 +176,12 @@ struct AppContext { AppConfig config_; Replxx rx_; + /** collector/allocator for schematika expressions **/ DX1Collector x1_; + /** e.g. for DArenaHashMap within global symtab **/ + DArena fixed_; SchematikaReader rdr_; -}; +}; int main() diff --git a/xo-reader2/include/xo/reader2/ParserStateMachine.hpp b/xo-reader2/include/xo/reader2/ParserStateMachine.hpp index d8dc8da9..74a3e9bb 100644 --- a/xo-reader2/include/xo/reader2/ParserStateMachine.hpp +++ b/xo-reader2/include/xo/reader2/ParserStateMachine.hpp @@ -41,9 +41,21 @@ namespace xo { using size_type = std::size_t; public: + /** + * @p config arena configuration for parser state + * @p max_stringtable_capacity + * hard max size for unique stringtable + * @p expr_alloc allocator for schematika expressions. + * Probably shared with execution. + * @p aux_alloc auxiliary allocator for non-copyable memory + * (e.g. DArenaHashMap for global symtable). + * If not using X1Collector, this can be the + * same as @p expr_alloc. + **/ ParserStateMachine(const ArenaConfig & config, size_type max_stringtable_capacity, - obj expr_alloc); + obj expr_alloc, + obj aux_alloc); /** @defgroup scm-parserstatemachine-accessors accessor methods **/ ///@{ @@ -280,6 +292,19 @@ namespace xo { **/ obj expr_alloc_; + /** Allocator for data with lifetime bounded by this ParserStateMachine + * + * Cannot be DX1Collector; for example DArenaHashMap will + * for global symtab will be allocated from here, + * and does not support gc. + * + * If @ref expr_alloc_ is an ordinary arena (e.g. DArenaAlloc) + * can have aux_alloc_ = expr_alloc_. + * When expr_alloc_ is a garbage collector (e.g. DX1Collector) + * this needs to be distinct. + **/ + obj aux_alloc_; + /** symbol table with local bindings. * non-null during parsing of lambda expressions. * Always allocated from @p expr_alloc_. diff --git a/xo-reader2/include/xo/reader2/SchematikaParser.hpp b/xo-reader2/include/xo/reader2/SchematikaParser.hpp index 4be59f04..13cb18ee 100644 --- a/xo-reader2/include/xo/reader2/SchematikaParser.hpp +++ b/xo-reader2/include/xo/reader2/SchematikaParser.hpp @@ -164,14 +164,18 @@ namespace xo { /** create parser in initial state; * parser is ready to receive tokens via @ref include_token * - * @p config arena configuration for parser stack - * @p expr_alloc allocator for schematika expressions. - * Probably shared with execution. + * @p config arena configuration for parser stack + * @p expr_alloc allocator for schematika expressions. + * Probably shared with execution. + * @p aux_alloc aux allocator for non-copyable memory + * with lifetime bounded by this + * SchematikeParser itself * @p debug_flag true to enable debug logging **/ SchematikaParser(const ArenaConfig & config, size_t max_stringtable_capacity, obj expr_alloc, + obj aux_alloc, bool debug_flag); /** scm-schematikaparser-access-methods **/ diff --git a/xo-reader2/include/xo/reader2/SchematikaReader.hpp b/xo-reader2/include/xo/reader2/SchematikaReader.hpp index ee3de91f..6f2b325e 100644 --- a/xo-reader2/include/xo/reader2/SchematikaReader.hpp +++ b/xo-reader2/include/xo/reader2/SchematikaReader.hpp @@ -41,8 +41,15 @@ namespace xo { using size_type = std::size_t; public: + /** + * @p expr_alloc. allocator for Schematika expressions + * @p aux_alloc. allocator for miscellaneous objects + * (e.g. DArenaHashMap for global symtab) + * that have lifetime bounded by Schematika reader itself. + **/ SchematikaReader(const ReaderConfig & config, - obj expr_alloc); + obj expr_alloc, + obj fixed_alloc); /** visit reader-owned memory pools; call visitor(info) for each. * Specifically exclude expr_alloc, since we don't consider diff --git a/xo-reader2/src/reader2/ParserStateMachine.cpp b/xo-reader2/src/reader2/ParserStateMachine.cpp index 58119789..5541e8a0 100644 --- a/xo-reader2/src/reader2/ParserStateMachine.cpp +++ b/xo-reader2/src/reader2/ParserStateMachine.cpp @@ -24,13 +24,14 @@ namespace xo { namespace scm { ParserStateMachine::ParserStateMachine(const ArenaConfig & config, size_type max_stringtable_capacity, - obj expr_alloc) + obj expr_alloc, + obj aux_alloc) : stringtable_{max_stringtable_capacity}, parser_alloc_{DArena::map(config)}, expr_alloc_{expr_alloc}, + aux_alloc_{aux_alloc}, debug_flag_{config.debug_flag_} { - } bool @@ -60,8 +61,8 @@ namespace xo { stringtable_.visit_pools(visitor); parser_alloc_.visit_pools(visitor); - // not counting expr_alloc_. We don't consider - // that to be owned by ParserStateMachine + // not counting {expr_alloc_, fixed_alloc_}. We don't consider + // either to be owned by ParserStateMachine } void diff --git a/xo-reader2/src/reader2/SchematikaParser.cpp b/xo-reader2/src/reader2/SchematikaParser.cpp index 1973bbe7..1b8b1904 100644 --- a/xo-reader2/src/reader2/SchematikaParser.cpp +++ b/xo-reader2/src/reader2/SchematikaParser.cpp @@ -23,9 +23,10 @@ namespace xo { SchematikaParser::SchematikaParser(const ArenaConfig & config, size_t max_stringtable_capacity, obj expr_alloc, + obj fixed_alloc, bool debug_flag) - : psm_{config, max_stringtable_capacity, expr_alloc}, - debug_flag_{debug_flag} + : psm_{config, max_stringtable_capacity, expr_alloc, fixed_alloc}, + debug_flag_{debug_flag} { } diff --git a/xo-reader2/src/reader2/SchematikaReader.cpp b/xo-reader2/src/reader2/SchematikaReader.cpp index 47140d63..f2e70824 100644 --- a/xo-reader2/src/reader2/SchematikaReader.cpp +++ b/xo-reader2/src/reader2/SchematikaReader.cpp @@ -10,12 +10,14 @@ namespace xo { namespace scm { SchematikaReader::SchematikaReader(const ReaderConfig & config, - obj expr_alloc) + obj expr_alloc, + obj fixed_alloc) : tokenizer_{config.tk_buffer_config_, config.tk_debug_flag_}, parser_{config.parser_arena_config_, config.max_stringtable_cap_, expr_alloc, + fixed_alloc, config.parser_debug_flag_}, debug_flag_{config.reader_debug_flag_} { diff --git a/xo-reader2/utest/SchematikaParser.test.cpp b/xo-reader2/utest/SchematikaParser.test.cpp index d6f74edc..94e8218d 100644 --- a/xo-reader2/utest/SchematikaParser.test.cpp +++ b/xo-reader2/utest/SchematikaParser.test.cpp @@ -88,8 +88,9 @@ namespace xo { DArena expr_arena = DArena::map(config); obj expr_alloc = with_facet::mkobj(&expr_arena); + auto aux_alloc = expr_alloc; - SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + SchematikaParser parser(config, 4096, expr_alloc, aux_alloc, false /*debug_flag*/); REQUIRE(parser.debug_flag() == false); REQUIRE(parser.is_at_toplevel() == true); @@ -103,8 +104,9 @@ namespace xo { DArena expr_arena = DArena::map(config); obj expr_alloc = with_facet::mkobj(&expr_arena); + auto aux_alloc = expr_alloc; - SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + SchematikaParser parser(config, 4096, expr_alloc, aux_alloc, false /*debug_flag*/); parser.begin_interactive_session(); @@ -121,8 +123,9 @@ namespace xo { DArena expr_arena = DArena::map(config); obj expr_alloc = with_facet::mkobj(&expr_arena); + auto aux_alloc = expr_alloc; - SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + SchematikaParser parser(config, 4096, expr_alloc, aux_alloc, false /*debug_flag*/); parser.begin_batch_session(); @@ -133,17 +136,20 @@ namespace xo { TEST_CASE("SchematikaParser-batch-def", "[reader2][SchematikaParser]") { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + constexpr bool c_debug_flag = false; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); ArenaConfig config; - config.name_ = "test-arena"; + config.name_ = testname; config.size_ = 16 * 1024; DArena expr_arena = DArena::map(config); obj expr_alloc = with_facet::mkobj(&expr_arena); + auto aux_alloc = expr_alloc; - SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + SchematikaParser parser(config, 4096, expr_alloc, aux_alloc, false /*debug_flag*/); parser.begin_batch_session(); @@ -185,8 +191,9 @@ namespace xo { DArena expr_arena = DArena::map(config); obj expr_alloc = with_facet::mkobj(&expr_arena); + auto aux_alloc = expr_alloc; - SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + SchematikaParser parser(config, 4096, expr_alloc, aux_alloc, false /*debug_flag*/); parser.begin_interactive_session(); @@ -250,8 +257,9 @@ namespace xo { DArena expr_arena = DArena::map(config); obj expr_alloc = with_facet::mkobj(&expr_arena); + auto aux_alloc = expr_alloc; - SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + SchematikaParser parser(config, 4096, expr_alloc, aux_alloc, false /*debug_flag*/); parser.begin_interactive_session(); @@ -315,8 +323,9 @@ namespace xo { DArena expr_arena = DArena::map(config); obj expr_alloc = with_facet::mkobj(&expr_arena); + auto aux_alloc = expr_alloc; - SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + SchematikaParser parser(config, 4096, expr_alloc, aux_alloc, false /*debug_flag*/); parser.begin_interactive_session(); @@ -380,8 +389,9 @@ namespace xo { DArena expr_arena = DArena::map(config); obj expr_alloc = with_facet::mkobj(&expr_arena); + auto aux_alloc = expr_alloc; - SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + SchematikaParser parser(config, 4096, expr_alloc, aux_alloc, false /*debug_flag*/); parser.begin_interactive_session(); @@ -435,16 +445,17 @@ namespace xo { const auto & testname = Catch::getResultCapture().getCurrentTestName(); constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + scope log(XO_DEBUG(c_debug_flag), + xtag("test", testname)); - ArenaConfig config; - config.name_ = "test-arena"; - config.size_ = 16 * 1024; + ArenaConfig config + = (ArenaConfig().with_name(testname).with_size(16 * 1024)); DArena expr_arena = DArena::map(config); - obj expr_alloc = with_facet::mkobj(&expr_arena); + auto expr_alloc = obj(&expr_arena); + auto aux_alloc = expr_alloc; - SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + SchematikaParser parser(config, 4096, expr_alloc, aux_alloc, false /*debug_flag*/); parser.begin_interactive_session(); @@ -507,8 +518,9 @@ namespace xo { DArena expr_arena = DArena::map(config); obj expr_alloc = with_facet::mkobj(&expr_arena); + auto aux_alloc = expr_alloc; - SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + SchematikaParser parser(config, 4096, expr_alloc, aux_alloc, false /*debug_flag*/); parser.begin_interactive_session(); @@ -517,7 +529,7 @@ namespace xo { * lambda (n : i64, r : i64) -> i64 { 123 } * ^ ^^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ * 0 1| 3 4 5 6 7 8 9 a b c d e - * 2 + * 2 **/ std::vector tk_v{ @@ -549,13 +561,14 @@ namespace xo { scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); ArenaConfig config; - config.name_ = "test-arena"; + config.name_ = testname; config.size_ = 16 * 1024; DArena expr_arena = DArena::map(config); obj expr_alloc = with_facet::mkobj(&expr_arena); + auto aux_alloc = expr_alloc; - SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + SchematikaParser parser(config, 4096, expr_alloc, aux_alloc, false /*debug_flag*/); parser.begin_interactive_session(); @@ -592,8 +605,9 @@ namespace xo { DArena expr_arena = DArena::map(config); obj expr_alloc = with_facet::mkobj(&expr_arena); + auto aux_alloc = expr_alloc; - SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + SchematikaParser parser(config, 4096, expr_alloc, aux_alloc, false /*debug_flag*/); parser.begin_interactive_session(); @@ -632,13 +646,14 @@ namespace xo { scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); ArenaConfig config; - config.name_ = "test-arena"; + config.name_ = testname; config.size_ = 16 * 1024; DArena expr_arena = DArena::map(config); obj expr_alloc = with_facet::mkobj(&expr_arena); + auto aux_alloc = expr_alloc; - SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + SchematikaParser parser(config, 4096, expr_alloc, aux_alloc, false /*debug_flag*/); parser.begin_interactive_session(); @@ -689,8 +704,9 @@ namespace xo { DArena expr_arena = DArena::map(config); obj expr_alloc = with_facet::mkobj(&expr_arena); + auto aux_alloc = expr_alloc; - SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + SchematikaParser parser(config, 4096, expr_alloc, aux_alloc, false /*debug_flag*/); parser.begin_interactive_session(); @@ -699,7 +715,7 @@ namespace xo { * (lambda (x : i64, y : i64) { x * y })(13, 15) ; * ^^ ^^ ^ ^ ^ ^^ ^ ^ ^ ^ ^ ^ ^^^^ ^ ^ ^ ^ * 0| 2| 4 5 6 7| 9 a b c d e f|h| j k l m - * 1 3 8 g i + * 1 3 8 g i **/ std::vector tk_v{