From 7b49d3da887235fd999269794608a9513693f363 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Tue, 25 Nov 2025 14:31:05 -0500 Subject: [PATCH] xo-interpreter: handle assignment expressions --- .../interpreter/VirtualSchematikaMachine.hpp | 6 +- .../include/xo/interpreter/VsmInstr.hpp | 2 +- .../interpreter/VirtualSchematikaMachine.cpp | 75 ++++++++++++++++--- xo-reader/include/xo/reader/exprstate.hpp | 3 + xo-reader/include/xo/reader/progress_xs.hpp | 6 +- xo-reader/src/reader/exprstate.cpp | 17 +++++ xo-reader/src/reader/progress_xs.cpp | 9 +++ 7 files changed, 103 insertions(+), 15 deletions(-) diff --git a/xo-interpreter/include/xo/interpreter/VirtualSchematikaMachine.hpp b/xo-interpreter/include/xo/interpreter/VirtualSchematikaMachine.hpp index 31a7082b..ea3b9d7b 100644 --- a/xo-interpreter/include/xo/interpreter/VirtualSchematikaMachine.hpp +++ b/xo-interpreter/include/xo/interpreter/VirtualSchematikaMachine.hpp @@ -81,10 +81,12 @@ namespace xo { /** interpret literal constant expression **/ void eval_constant_op(); - /** interpret define expression **/ + /** execute define expression (finished in do_complete_assign_op()) **/ void eval_define_op(); + /** execute assign expression (finishes in do_complete_assign_op()) **/ + void eval_assign_op(); /** continue after establishing value fo rhs of define exprsssion **/ - void do_defexpr_assign_op(); + void do_complete_assign_op(); /** interpret variable expression **/ void eval_variable_op(); diff --git a/xo-interpreter/include/xo/interpreter/VsmInstr.hpp b/xo-interpreter/include/xo/interpreter/VsmInstr.hpp index 2eab625b..9044cd6a 100644 --- a/xo-interpreter/include/xo/interpreter/VsmInstr.hpp +++ b/xo-interpreter/include/xo/interpreter/VsmInstr.hpp @@ -32,7 +32,7 @@ namespace xo { * [1] cont : continuation after assignment * ... maybe other vsm state that must be saved **/ - defexpr_assign, + complete_assign, N_Opcode }; diff --git a/xo-interpreter/src/interpreter/VirtualSchematikaMachine.cpp b/xo-interpreter/src/interpreter/VirtualSchematikaMachine.cpp index b005bf12..6cfd2a4c 100644 --- a/xo-interpreter/src/interpreter/VirtualSchematikaMachine.cpp +++ b/xo-interpreter/src/interpreter/VirtualSchematikaMachine.cpp @@ -5,6 +5,7 @@ #include "ExpressionBoxed.hpp" #include "xo/expression/ConstantInterface.hpp" #include "xo/expression/DefineExpr.hpp" +#include "xo/expression/AssignExpr.hpp" #include "xo/expression/Variable.hpp" #include "xo/alloc/GC.hpp" @@ -35,11 +36,11 @@ namespace xo { **/ static VsmInstr eval_op; - /** assign variable after evaluating rhs of a define-expression + /** assign variable after evaluating rhs of a define-expression or assign-expression * - opcode is Opcode::defexpr_assign * - top stack frame contains {lhs, cont} */ - static VsmInstr defexpr_assign_op; + static VsmInstr complete_assign_op; }; VsmInstr @@ -49,7 +50,7 @@ namespace xo { VsmOps::eval_op{VsmInstr::Opcode::eval, "eval"}; VsmInstr - VsmOps::defexpr_assign_op{VsmInstr::Opcode::defexpr_assign, "defexpr-assign"}; + VsmOps::complete_assign_op{VsmInstr::Opcode::complete_assign, "complete-assign"}; // ----- VirtualSchematikaMachineFlyweight ----- @@ -164,6 +165,11 @@ namespace xo { this->eval_define_op(); break; + case exprtype::assign: + log && log("eval -> assign"); + this->eval_assign_op(); + break; + case exprtype::variable: log && log("eval -> variable"); this->eval_variable_op(); @@ -172,7 +178,6 @@ namespace xo { case exprtype::invalid: case exprtype::primitive: - case exprtype::assign: case exprtype::apply: case exprtype::lambda: case exprtype::ifexpr: @@ -189,8 +194,8 @@ namespace xo { } break; - case Opcode::defexpr_assign: - this->do_defexpr_assign_op(); + case Opcode::complete_assign: + this->do_complete_assign_op(); break; case Opcode::N_Opcode: @@ -276,13 +281,65 @@ namespace xo { /* .stack_: * frame * [0] = lhs_0 (boxed lhs Variable) + * .. */ - this->cont_ = &VsmOps::defexpr_assign_op; + this->cont_ = &VsmOps::complete_assign_op; } void - VirtualSchematikaMachine::do_defexpr_assign_op() + VirtualSchematikaMachine::eval_assign_op() + { + using xo::scm::AssignExpr; + + scope log(XO_DEBUG(true)); + + auto mm = flyweight_.object_mm_; + + bp assign = AssignExpr::from(expr_); + + assert(assign.get()); + assert(env_.get()); + + assert(assign->lhs().get()); + assert(assign->rhs().get()); + + /* verify slot exists, before we evaluate rhs */ + gp * slot = env_->lookup_slot(assign->lhs()->name()); + + if (slot) { + /** must promote rp -> gp **/ + gp lhs = ExpressionBoxed::make(mm, assign->lhs()); + + this->pc_ = &VsmOps::eval_op; + this->expr_ = assign->rhs(); + + /* when control arrives at .cont_, will have: + * .value_ -> result of evaluating assign->rhs() + */ + this->stack_ = VsmStackFrame::push1(mm, this->stack_, lhs, cont_); + + /* .stack_: + * frame + * [0] = lhs (boxed lhs Variable) + * .. + */ + + this->cont_ = &VsmOps::complete_assign_op; + } else { + std::string err = tostr("no binding for lhs of assignment", xtag("name", assign->lhs()->name())); + + this->value_ = nullptr; + this->error_ = SchematikaError(err); + + /* note: poor man's exception */ + this->pc_ = nullptr; + this->cont_ = nullptr; + } + } + + void + VirtualSchematikaMachine::do_complete_assign_op() { scope log(XO_DEBUG(true)); @@ -348,8 +405,6 @@ namespace xo { /* note: poor man's exception */ this->pc_ = nullptr; this->cont_ = nullptr; - - this->pc_ = cont_; } } diff --git a/xo-reader/include/xo/reader/exprstate.hpp b/xo-reader/include/xo/reader/exprstate.hpp index f3b00d51..c21f453f 100644 --- a/xo-reader/include/xo/reader/exprstate.hpp +++ b/xo-reader/include/xo/reader/exprstate.hpp @@ -172,6 +172,9 @@ namespace xo { /** handle incoming '=' token **/ virtual void on_singleassign_token(const token_type & tk, parserstatemachine * p_psm); + /** handle incoming ':=' token **/ + virtual void on_assign_token(const token_type & tk, + parserstatemachine * p_psm); /** handle incoming '(' token **/ virtual void on_leftparen_token(const token_type & tk, parserstatemachine * p_psm); diff --git a/xo-reader/include/xo/reader/progress_xs.hpp b/xo-reader/include/xo/reader/progress_xs.hpp index ce77966d..780f5232 100644 --- a/xo-reader/include/xo/reader/progress_xs.hpp +++ b/xo-reader/include/xo/reader/progress_xs.hpp @@ -97,7 +97,7 @@ namespace xo { bp expr2, parserstatemachine * p_psm) const; - virtual const char * get_expect_str() const override; + virtual const char * get_expect_str() const final override; virtual void on_expr(bp expr, parserstatemachine * p_psm) override; @@ -116,6 +116,8 @@ namespace xo { parserstatemachine * p_psm) override; virtual void on_singleassign_token(const token_type & tk, parserstatemachine * p_psm) override; + virtual void on_assign_token(const token_type & tk, + parserstatemachine * p_psm) final override; virtual void on_leftparen_token(const token_type & tk, parserstatemachine * p_psm) override; virtual void on_rightparen_token(const token_type & tk, @@ -129,7 +131,7 @@ namespace xo { /* entry point for an infix operator token */ virtual void on_operator_token(const token_type & tk, - parserstatemachine * p_psm) override; + parserstatemachine * p_psm) final override; virtual void on_bool_token(const token_type & tk, parserstatemachine * p_psm) override; diff --git a/xo-reader/src/reader/exprstate.cpp b/xo-reader/src/reader/exprstate.cpp index 0a8b0d32..47e368d4 100644 --- a/xo-reader/src/reader/exprstate.cpp +++ b/xo-reader/src/reader/exprstate.cpp @@ -216,6 +216,20 @@ namespace xo { this->illegal_input_on_token(c_self_name, tk, exp, p_psm); } + void + exprstate::on_assign_token(const token_type & tk, + parserstatemachine * p_psm) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + constexpr const char * c_self_name = "exprstate::on_assign_token"; + const char * exp = get_expect_str(); + + this->illegal_input_on_token(c_self_name, tk, exp, p_psm); + } + + void exprstate::on_leftparen_token(const token_type & tk, parserstatemachine * p_psm) @@ -445,6 +459,9 @@ namespace xo { return; case tokentype::tk_assign: + this->on_assign_token(tk, p_psm); + return; + case tokentype::tk_yields: assert(false); break; diff --git a/xo-reader/src/reader/progress_xs.cpp b/xo-reader/src/reader/progress_xs.cpp index c99aaaa6..d47c8cf9 100644 --- a/xo-reader/src/reader/progress_xs.cpp +++ b/xo-reader/src/reader/progress_xs.cpp @@ -434,6 +434,13 @@ namespace xo { this->illegal_input_on_token(c_self_name, tk, exp, p_psm); } + void + progress_xs::on_assign_token(const token_type & tk, + parserstatemachine * p_psm) + { + this->on_operator_token(tk, p_psm); + } + void progress_xs::on_leftparen_token(const token_type & tk, parserstatemachine * p_psm) @@ -573,6 +580,8 @@ namespace xo { optype tk2op(const tokentype & tktype) { switch (tktype) { + case tokentype::tk_assign: + return optype::op_assign; case tokentype::tk_plus: return optype::op_add; case tokentype::tk_minus: