diff --git a/include/xo/interpreter2/VirtualSchematikaMachine.hpp b/include/xo/interpreter2/VirtualSchematikaMachine.hpp index af551d04..39421981 100644 --- a/include/xo/interpreter2/VirtualSchematikaMachine.hpp +++ b/include/xo/interpreter2/VirtualSchematikaMachine.hpp @@ -10,6 +10,7 @@ #include "VsmFrame.hpp" #include "DLocalEnv.hpp" #include "DGlobalEnv.hpp" +#include #include #include #include @@ -17,6 +18,10 @@ namespace xo { namespace scm { +#ifdef OBSOLETE // see DVsmError + // TODO: move error to collected space? + // or special arena? + // struct EvaluationError { /** source location (in vsm implementation) at which error identified **/ std::string_view src_function_; @@ -24,6 +29,7 @@ namespace xo { std::string_view error_description_; // TODO: info about location in schematika source }; +#endif /** similar to @ref xo::scm::ReaderResult **/ struct VsmResult { @@ -31,17 +37,17 @@ namespace xo { using span_type = xo::mm::span; VsmResult() = default; - VsmResult(obj value) : result_{value} {} - VsmResult(TokenizerError err) : result_{err} {} + explicit VsmResult(obj value) : result_{value} {} + explicit VsmResult(TokenizerError err) : result_{err} {} bool is_value() const { return std::holds_alternative>(result_); } bool is_tk_error() const { return std::holds_alternative(result_); } - bool is_eval_error() const { return std::holds_alternative(result_); } + bool is_eval_error() const; const obj * value() const { return std::get_if>(&result_); } /** result of evaluating first expression encountered in input **/ - std::variant, TokenizerError, EvaluationError> result_; + std::variant, TokenizerError> result_; }; /** vsm result + reamining span **/ @@ -72,6 +78,8 @@ namespace xo { /** allocator for schematika data **/ obj allocator() const noexcept; + /** allocator for runtime errors **/ + obj error_allocator() const noexcept; /** visit vsm-owned memory pools; call visitor(info) for each **/ void visit_pools(const MemorySizeVisitor & visitor) const; @@ -185,11 +193,19 @@ namespace xo { /** configuration **/ VsmConfig config_; - /** allocator (likely collector) for + /** allocator (likely DX1Collector or similar) for * expressions and values **/ box mm_; + /** Sidecar allocator for error reporting. + * Separate to mitigate interference with @ref mm_ + * (separate memory so we can for example report + * an out-of-memory error). + * Likely DArena or similar + **/ + box error_mm_; + /** runtime context for this vsm. * For example, provides allocator to primitives **/ diff --git a/include/xo/interpreter2/VsmConfig.hpp b/include/xo/interpreter2/VsmConfig.hpp index 9d13ab8e..63c4b365 100644 --- a/include/xo/interpreter2/VsmConfig.hpp +++ b/include/xo/interpreter2/VsmConfig.hpp @@ -7,6 +7,7 @@ #include #include +#include namespace xo { namespace scm { @@ -14,6 +15,7 @@ namespace xo { **/ struct VsmConfig { using X1CollectorConfig = xo::mm::X1CollectorConfig; + using ArenaConfig = xo::mm::ArenaConfig; VsmConfig() = default; @@ -26,6 +28,10 @@ namespace xo { * TODO: may want to make CollectorConfig polymorphic **/ X1CollectorConfig x1_config_ = X1CollectorConfig().with_size(4*1024*1024); + /** Configuration for error allocator + * TODO: may want to make ArenaConfig polymorphic + **/ + ArenaConfig error_config_ = ArenaConfig().with_size(64*1024); }; } /*namespace scm*/ } /*namespace xo*/ diff --git a/src/interpreter2/DClosure.cpp b/src/interpreter2/DClosure.cpp index d1baa172..7fa3698c 100644 --- a/src/interpreter2/DClosure.cpp +++ b/src/interpreter2/DClosure.cpp @@ -6,6 +6,8 @@ #include "Closure.hpp" #include "LambdaExpr.hpp" #include "LocalEnv.hpp" +#include "VsmRcx.hpp" +#include #include namespace xo { @@ -33,7 +35,30 @@ namespace xo { DClosure::apply_nocheck(obj rcx, const DArray * args) { - (void)rcx; + scope log(XO_DEBUG(true)); + + auto vsm_rcx + = obj::from(rcx); + + log && log(xtag("vsm_rcx.data", (void*)vsm_rcx.data())); + + // let's try a not-implemented error + + // don't want to clutter Procedure facet, since it's + // lower-level than xo-interpreter2 + +#ifdef NOT_YET + // TODO: verify arguments against type signature. + // unless we have evidence that program is type correct + + int32_t n_args = this->n_args(); + + if (n_args != args->size()) { + // + } +#endif + + (void)args; assert(false); diff --git a/src/interpreter2/VirtualSchematikaMachine.cpp b/src/interpreter2/VirtualSchematikaMachine.cpp index 1569ccc0..abdfb168 100644 --- a/src/interpreter2/VirtualSchematikaMachine.cpp +++ b/src/interpreter2/VirtualSchematikaMachine.cpp @@ -15,6 +15,7 @@ //#include #include #include +#include #include #include #include @@ -27,12 +28,25 @@ namespace xo { //using xo::mm::MemorySizeInfo; // not used yet using xo::mm::AAllocator; using xo::mm::DX1Collector; + using xo::mm::DArena; using xo::facet::FacetRegistry; using std::cout; namespace scm { - // NOTE: using heap here for {DX1Collector, DVsmRcx} instances + bool + VsmResult::is_eval_error() const + { + if (std::holds_alternative>(result_)) { + auto err = obj::from(*(this->value())); + + return err; + } else { + return false; + } + } + + // NOTE: using heap here for {DX1Collector, DArena, DVsmRcx} instances // (though DX1Collector allocations will be from explictly mmap'd memory) // VirtualSchematikaMachine::VirtualSchematikaMachine(const VsmConfig & config) @@ -41,6 +55,14 @@ namespace xo { rcx_(box(new DVsmRcx(this))), reader_{config.rdr_config_, mm_.to_op()} { + { + DArena * arena = new DArena(); + assert(arena); + *arena = DArena::map(config_.error_config_); + + error_mm_.adopt(obj(arena)); + } + // TODO: allocate global_env } @@ -50,6 +72,12 @@ namespace xo { return mm_.to_op(); } + obj + VirtualSchematikaMachine::error_allocator() const noexcept + { + return error_mm_.to_op(); + } + void VirtualSchematikaMachine::visit_pools(const MemorySizeVisitor & visitor) const { @@ -113,7 +141,7 @@ namespace xo { { this->pc_ = VsmInstr::c_eval; this->expr_ = expr; - this->value_ = obj(); + this->value_ = VsmResult(obj()); this->cont_ = VsmInstr::c_halt; this->run(); @@ -200,7 +228,7 @@ namespace xo { auto expr = obj::from(expr_); - this->value_ = expr.data()->value(); + this->value_ = VsmResult(expr.data()->value()); this->pc_ = this->cont_; } @@ -250,7 +278,7 @@ namespace xo { local_env_); this->value_ - = obj(obj(closure)); + = VsmResult(obj(obj(closure))); this->pc_ = this->cont_; } @@ -341,7 +369,7 @@ namespace xo { // TODO: check argument types - this->value_ = fn_.apply_nocheck(rcx_.to_op(), args_); + this->value_ = VsmResult(fn_.apply_nocheck(rcx_.to_op(), args_)); this->pc_ = cont_; return; diff --git a/utest/VirtualSchematikaMachine.test.cpp b/utest/VirtualSchematikaMachine.test.cpp index 4213764b..5ccef226 100644 --- a/utest/VirtualSchematikaMachine.test.cpp +++ b/utest/VirtualSchematikaMachine.test.cpp @@ -225,7 +225,6 @@ namespace xo { vsm.visit_pools(visitor); } -#ifdef NOT_YET TEST_CASE("VirtualSchematikaMachine-apply2", "[interpreter2][VSM]") { scope log(XO_DEBUG(true)); @@ -265,7 +264,6 @@ namespace xo { FacetRegistry::instance().visit_pools(visitor); vsm.visit_pools(visitor); } -#endif } /*namespace ut*/ } /*namespace xo*/