xo-interpreter: handle define-expressions.
This commit is contained in:
parent
f98d1345d3
commit
fb5c43dc85
16 changed files with 523 additions and 53 deletions
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
#include "VirtualSchematikaMachine.hpp"
|
||||
#include "VsmInstr.hpp"
|
||||
#include "ExpressionBoxed.hpp"
|
||||
#include "xo/expression/ConstantInterface.hpp"
|
||||
#include "xo/expression/DefineExpr.hpp"
|
||||
#include "xo/expression/Variable.hpp"
|
||||
#include "xo/alloc/GC.hpp"
|
||||
|
||||
/** continue after completing a VSM instruction;
|
||||
|
|
@ -14,6 +17,8 @@
|
|||
**/
|
||||
#define VSM_ERROR(msg) report_error(msg); return;
|
||||
|
||||
|
||||
|
||||
namespace xo {
|
||||
using xo::gc::GC;
|
||||
|
||||
|
|
@ -29,6 +34,12 @@ namespace xo {
|
|||
* - expression in register @ref expr_
|
||||
**/
|
||||
static VsmInstr eval_op;
|
||||
|
||||
/** assign variable after evaluating rhs of a define-expression
|
||||
* - opcode is Opcode::defexpr_assign
|
||||
* - top stack frame contains {lhs, cont}
|
||||
*/
|
||||
static VsmInstr defexpr_assign_op;
|
||||
};
|
||||
|
||||
VsmInstr
|
||||
|
|
@ -37,18 +48,27 @@ namespace xo {
|
|||
VsmInstr
|
||||
VsmOps::eval_op{VsmInstr::Opcode::eval, "eval"};
|
||||
|
||||
VsmInstr
|
||||
VsmOps::defexpr_assign_op{VsmInstr::Opcode::defexpr_assign, "defexpr-assign"};
|
||||
|
||||
// ----- VirtualSchematikaMachineFlyweight -----
|
||||
|
||||
VirtualSchematikaMachineFlyweight::VirtualSchematikaMachineFlyweight(gc::IAlloc * mm,
|
||||
gp<Env> env) :
|
||||
gp<Env> env,
|
||||
log_level ll) :
|
||||
object_mm_{mm},
|
||||
toplevel_env_{env}
|
||||
toplevel_env_{env},
|
||||
log_level_{ll}
|
||||
{}
|
||||
|
||||
// ----- VirtualSchematikaMachine -----
|
||||
|
||||
VirtualSchematikaMachine::VirtualSchematikaMachine(gc::IAlloc * mm, gp<Env> env) : flyweight_{mm, env}
|
||||
VirtualSchematikaMachine::VirtualSchematikaMachine(gc::IAlloc * mm,
|
||||
gp<Env> env,
|
||||
log_level ll) : flyweight_{mm, env, ll}
|
||||
{
|
||||
this->env_ = env;
|
||||
|
||||
// gc roots
|
||||
gc::GC * gc = GC::from(mm);
|
||||
|
||||
|
|
@ -90,10 +110,13 @@ namespace xo {
|
|||
SchematikaError>
|
||||
VirtualSchematikaMachine::eval(bp<Expression> expr, gp<Env> env)
|
||||
{
|
||||
this->pc_ = &VsmOps::eval_op;
|
||||
this->expr_ = expr.promote();
|
||||
this->env_ = env;
|
||||
this->cont_ = &VsmOps::halt_op;
|
||||
this->pc_ = &VsmOps::eval_op;
|
||||
this->expr_ = expr.promote();
|
||||
this->env_ = env;
|
||||
this->stack_ = nullptr;
|
||||
this->value_ = nullptr;
|
||||
this->error_ = SchematikaError();
|
||||
this->cont_ = &VsmOps::halt_op;
|
||||
|
||||
this->run();
|
||||
|
||||
|
|
@ -110,6 +133,9 @@ namespace xo {
|
|||
void
|
||||
VirtualSchematikaMachine::execute_one()
|
||||
{
|
||||
scope log(XO_DEBUG(true));
|
||||
log && log("stack", stack_);
|
||||
|
||||
using Opcode = VsmInstr::Opcode;
|
||||
|
||||
switch (pc_->opcode()) {
|
||||
|
|
@ -123,6 +149,8 @@ namespace xo {
|
|||
|
||||
case Opcode::eval:
|
||||
{
|
||||
log && log("eval");
|
||||
|
||||
/* generally speaking: opcode will be 1:1 with extypes */
|
||||
|
||||
switch (expr_->extype()) {
|
||||
|
|
@ -130,9 +158,14 @@ namespace xo {
|
|||
this->eval_constant_op();
|
||||
break;
|
||||
|
||||
|
||||
case exprtype::define:
|
||||
this->eval_define_op();
|
||||
break;
|
||||
|
||||
case exprtype::invalid:
|
||||
case exprtype::primitive:
|
||||
case exprtype::define:
|
||||
|
||||
case exprtype::assign:
|
||||
case exprtype::apply:
|
||||
case exprtype::lambda:
|
||||
|
|
@ -151,6 +184,10 @@ namespace xo {
|
|||
}
|
||||
break;
|
||||
|
||||
case Opcode::defexpr_assign:
|
||||
this->do_defexpr_assign_op();
|
||||
break;
|
||||
|
||||
case Opcode::N_Opcode:
|
||||
assert(false);
|
||||
break;
|
||||
|
|
@ -197,29 +234,60 @@ namespace xo {
|
|||
|
||||
// placeholder: primitive_op
|
||||
|
||||
#ifdef NOT_YET
|
||||
void
|
||||
VirtualSchematikaMachine::define_op()
|
||||
VirtualSchematikaMachine::eval_define_op()
|
||||
{
|
||||
using xo::scm::DefineExpr;
|
||||
|
||||
scope log(XO_DEBUG(true));
|
||||
|
||||
auto mm = flyweight_.object_mm_;
|
||||
|
||||
bp<DefineExpr> expr = DefineExpr::from(expr_);
|
||||
|
||||
assert(expr);
|
||||
assert(env_.get());
|
||||
|
||||
// note: expecting nested define to have expanded iteself into
|
||||
// applying a lambda
|
||||
|
||||
// note: establish lhs_var first, to allow for recursion, for example:
|
||||
// def fact(n: i64) { if (n == 0) then 1; else n * fact(n-1); }
|
||||
|
||||
/** remembers promised variable type **/
|
||||
env_->establish_var(expr->lhs_variable());
|
||||
this->env_->establish_var(expr->lhs_variable());
|
||||
|
||||
/** must promote rp<Expression> -> gp<ExpressionBoxed> **/
|
||||
gp<ExpressionBoxed> lhs_0 = ExpressionBoxed::make(mm, expr->lhs_variable());
|
||||
|
||||
this->pc_ = &VsmOps::eval_op;
|
||||
this->expr_ = expr->rhs();
|
||||
|
||||
/* lhs_var
|
||||
* rhs
|
||||
/* when control arrives at .cont_, will have:
|
||||
* .value_ -> result of evaluating expr->rhs()
|
||||
*/
|
||||
|
||||
this->stack_ = VsmStackFrame::push1(mm, this->stack_, lhs_0, cont_);
|
||||
this->cont_ = &VsmOps::defexpr_assign_op;
|
||||
}
|
||||
|
||||
void
|
||||
VirtualSchematikaMachine::do_defexpr_assign_op()
|
||||
{
|
||||
/*
|
||||
* - value: contains result of evaluating rhs of define
|
||||
* - stack: top frame has 1 slot, holds variable to receive assignment
|
||||
*/
|
||||
assert(value_.get());
|
||||
assert(stack_.get());
|
||||
|
||||
gp<VsmStackFrame> sp0 = this->stack_;
|
||||
|
||||
//this->value_ = this->value_; // preserve value from rhs of defexpr
|
||||
|
||||
this->stack_ = sp0->parent();
|
||||
this->pc_ = this->cont_ = sp0->continuation();
|
||||
}
|
||||
#endif
|
||||
|
||||
} /*namespace scm*/
|
||||
} /*namespace xo*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue