diff --git a/xo-interpreter2/include/xo/interpreter2/vsm/DVirtualSchematikaMachine.hpp b/xo-interpreter2/include/xo/interpreter2/vsm/DVirtualSchematikaMachine.hpp index 84070673..e6badf83 100644 --- a/xo-interpreter2/include/xo/interpreter2/vsm/DVirtualSchematikaMachine.hpp +++ b/xo-interpreter2/include/xo/interpreter2/vsm/DVirtualSchematikaMachine.hpp @@ -32,18 +32,33 @@ namespace xo { bool is_error() const; const obj * value() const { return &result_; } - obj & value_ref() { return result_; } + const obj & value_ref() const { return result_; } /** result of evaluating first expression encountered in input **/ obj result_; }; - /** vsm result + reamining span **/ - struct VsmResultExt : public VsmResult { + /** vsm result + reamining span + * + * Preserves address of wrapped VsmResult + * (so it can continue to be owned by DVirtualSchematikaMachine, + * and to be known to gc without add'l effort) + **/ + struct VsmResultExt { + using AGCObject = xo::mm::AGCObject; using span_type = VsmResult::span_type; VsmResultExt() = default; - VsmResultExt(const VsmResult & result, span_type rem) : VsmResult{result}, remaining_{rem} {} + VsmResultExt(const VsmResult & result, span_type rem) : p_result_{&result}, remaining_{rem} {} + + bool is_empty() const { return !p_result_; } + bool is_value() const { return p_result_ ? p_result_->is_value() : false; } + bool is_error() const { return p_result_ ? p_result_->is_error() : false; } + + const obj * value() const { return p_result_ ? p_result_->value() : nullptr; } + //const obj & value_ref() { return result_.value_ref(); } + + const VsmResult * p_result_ = nullptr; /** unconsumed portion of input **/ VsmResult::span_type remaining_; diff --git a/xo-interpreter2/src/interpreter2/DVirtualSchematikaMachine.cpp b/xo-interpreter2/src/interpreter2/DVirtualSchematikaMachine.cpp index 9ceb8fac..f9977eb9 100644 --- a/xo-interpreter2/src/interpreter2/DVirtualSchematikaMachine.cpp +++ b/xo-interpreter2/src/interpreter2/DVirtualSchematikaMachine.cpp @@ -197,6 +197,8 @@ namespace xo { auto error = obj(DRuntimeError::_make(mm_.to_op(), src, msg)); + this->value_ = VsmResult(error); + { obj error_pr = FacetRegistry::instance().variant(error); @@ -206,7 +208,7 @@ namespace xo { pps.prettyn(error_pr); } - return VsmResultExt(VsmResult(error), remaining); + return VsmResultExt(value_, remaining); } else { // incomplete input return VsmResultExt(VsmResult(), remaining); @@ -215,7 +217,7 @@ namespace xo { // here: have obtained complete input expression - VsmResult evalresult = this->start_eval(expr); + const VsmResult & evalresult = this->start_eval(expr); if (evalresult.is_error()) { // TODO: print error here @@ -239,7 +241,7 @@ namespace xo { pps.prettyn(value_pr); } - return VsmResultExt(VsmResult(value), remaining); + return VsmResultExt(evalresult, remaining); } const VsmResult & @@ -975,7 +977,7 @@ namespace xo { gc.forward_inplace(&fn_); gc.forward_inplace(&args_); if (value_.is_value()) { - gc.forward_inplace(&value_.value_ref()); + gc.forward_inplace(const_cast *>(&value_.value_ref())); } return this->shallow_size(); diff --git a/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp b/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp index ac74bab3..aabda3a3 100644 --- a/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp +++ b/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp @@ -103,6 +103,8 @@ namespace xo { { scope log(XO_DEBUG(debug_flag)); + // WARNING: res.value() is unstable - gc may move it + VsmResultExt res = vsm_->read_eval_print(input_span, eof_flag); REQUIRE(res.is_value());