xo-interpreter: handle assignment expressions
This commit is contained in:
parent
2bffef29d5
commit
7b49d3da88
7 changed files with 103 additions and 15 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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<AssignExpr> 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<Object> * slot = env_->lookup_slot(assign->lhs()->name());
|
||||
|
||||
if (slot) {
|
||||
/** must promote rp<Expression> -> gp<ExpressionBoxed> **/
|
||||
gp<ExpressionBoxed> 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_;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ namespace xo {
|
|||
bp<Expression> 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<Expression> 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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue