xo-interpreter: interpret if-expressions. not tested
This commit is contained in:
parent
7b49d3da88
commit
705406e039
4 changed files with 118 additions and 5 deletions
|
|
@ -91,6 +91,11 @@ namespace xo {
|
||||||
/** interpret variable expression **/
|
/** interpret variable expression **/
|
||||||
void eval_variable_op();
|
void eval_variable_op();
|
||||||
|
|
||||||
|
/** interpret if-expression **/
|
||||||
|
void eval_ifexpr_op();
|
||||||
|
/** continue after establish value of test expression **/
|
||||||
|
void do_complete_ifexpr_op();
|
||||||
|
|
||||||
/** goto error state with message @p err **/
|
/** goto error state with message @p err **/
|
||||||
void report_error(const std::string & err);
|
void report_error(const std::string & err);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,19 @@ namespace xo {
|
||||||
*
|
*
|
||||||
* stack: frame with:
|
* stack: frame with:
|
||||||
* [0] lhs : variable to assign
|
* [0] lhs : variable to assign
|
||||||
* [1] cont : continuation after assignment
|
|
||||||
* ... maybe other vsm state that must be saved
|
|
||||||
**/
|
**/
|
||||||
complete_assign,
|
complete_assign,
|
||||||
|
|
||||||
|
/** execute ifexpr branch, given
|
||||||
|
* result of test expression has been established
|
||||||
|
**/
|
||||||
|
complete_ifexpr,
|
||||||
|
|
||||||
|
/** choose branch of if-expression + continue
|
||||||
|
*
|
||||||
|
* stack: frame with
|
||||||
|
* [0] ifexpr : original if-expression
|
||||||
|
**/
|
||||||
N_Opcode
|
N_Opcode
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
#include "xo/expression/DefineExpr.hpp"
|
#include "xo/expression/DefineExpr.hpp"
|
||||||
#include "xo/expression/AssignExpr.hpp"
|
#include "xo/expression/AssignExpr.hpp"
|
||||||
#include "xo/expression/Variable.hpp"
|
#include "xo/expression/Variable.hpp"
|
||||||
|
#include "xo/expression/IfExpr.hpp"
|
||||||
|
#include "xo/object/Boolean.hpp"
|
||||||
#include "xo/alloc/GC.hpp"
|
#include "xo/alloc/GC.hpp"
|
||||||
|
|
||||||
/** continue after completing a VSM instruction;
|
/** continue after completing a VSM instruction;
|
||||||
|
|
@ -22,6 +24,7 @@
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
using xo::gc::GC;
|
using xo::gc::GC;
|
||||||
|
using xo::obj::Boolean;
|
||||||
|
|
||||||
namespace scm {
|
namespace scm {
|
||||||
struct VsmOps {
|
struct VsmOps {
|
||||||
|
|
@ -37,10 +40,16 @@ namespace xo {
|
||||||
static VsmInstr eval_op;
|
static VsmInstr eval_op;
|
||||||
|
|
||||||
/** assign variable after evaluating rhs of a define-expression or assign-expression
|
/** assign variable after evaluating rhs of a define-expression or assign-expression
|
||||||
* - opcode is Opcode::defexpr_assign
|
* - opcode is Opcode::complete_assign
|
||||||
* - top stack frame contains {lhs, cont}
|
* - top stack frame contains {lhs, cont}
|
||||||
*/
|
**/
|
||||||
static VsmInstr complete_assign_op;
|
static VsmInstr complete_assign_op;
|
||||||
|
|
||||||
|
/** choose branch of if-expr after evaluating test condition.
|
||||||
|
* - opcode is Opcode::complete_ifexpr
|
||||||
|
* - top stack frame contains {ifexpr, cont}
|
||||||
|
**/
|
||||||
|
static VsmInstr complete_ifexpr_op;
|
||||||
};
|
};
|
||||||
|
|
||||||
VsmInstr
|
VsmInstr
|
||||||
|
|
@ -52,6 +61,9 @@ namespace xo {
|
||||||
VsmInstr
|
VsmInstr
|
||||||
VsmOps::complete_assign_op{VsmInstr::Opcode::complete_assign, "complete-assign"};
|
VsmOps::complete_assign_op{VsmInstr::Opcode::complete_assign, "complete-assign"};
|
||||||
|
|
||||||
|
VsmInstr
|
||||||
|
VsmOps::complete_ifexpr_op{VsmInstr::Opcode::complete_ifexpr, "complete-ifexpr"};
|
||||||
|
|
||||||
// ----- VirtualSchematikaMachineFlyweight -----
|
// ----- VirtualSchematikaMachineFlyweight -----
|
||||||
|
|
||||||
VirtualSchematikaMachineFlyweight::VirtualSchematikaMachineFlyweight(gc::IAlloc * mm,
|
VirtualSchematikaMachineFlyweight::VirtualSchematikaMachineFlyweight(gc::IAlloc * mm,
|
||||||
|
|
@ -175,12 +187,16 @@ namespace xo {
|
||||||
this->eval_variable_op();
|
this->eval_variable_op();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case exprtype::ifexpr:
|
||||||
|
log && log("eval -> ifexpr");
|
||||||
|
this->eval_ifexpr_op();
|
||||||
|
break;
|
||||||
|
|
||||||
case exprtype::invalid:
|
case exprtype::invalid:
|
||||||
case exprtype::primitive:
|
case exprtype::primitive:
|
||||||
|
|
||||||
case exprtype::apply:
|
case exprtype::apply:
|
||||||
case exprtype::lambda:
|
case exprtype::lambda:
|
||||||
case exprtype::ifexpr:
|
|
||||||
case exprtype::sequence:
|
case exprtype::sequence:
|
||||||
case exprtype::convert:
|
case exprtype::convert:
|
||||||
case exprtype::n_expr:
|
case exprtype::n_expr:
|
||||||
|
|
@ -198,6 +214,10 @@ namespace xo {
|
||||||
this->do_complete_assign_op();
|
this->do_complete_assign_op();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Opcode::complete_ifexpr:
|
||||||
|
this->do_complete_ifexpr_op();
|
||||||
|
break;
|
||||||
|
|
||||||
case Opcode::N_Opcode:
|
case Opcode::N_Opcode:
|
||||||
assert(false);
|
assert(false);
|
||||||
break;
|
break;
|
||||||
|
|
@ -408,6 +428,85 @@ namespace xo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VirtualSchematikaMachine::eval_ifexpr_op()
|
||||||
|
{
|
||||||
|
using xo::scm::IfExpr;
|
||||||
|
|
||||||
|
scope log(XO_DEBUG(true));
|
||||||
|
|
||||||
|
gc::IAlloc * mm = flyweight_.object_mm_;
|
||||||
|
|
||||||
|
/** must promote bp<IfExpr> -> gp<ExpressionBoxed> **/
|
||||||
|
gp<ExpressionBoxed> ifexpr_boxed = ExpressionBoxed::make(mm, expr_);
|
||||||
|
bp<IfExpr> ifexpr = IfExpr::from(expr_);
|
||||||
|
|
||||||
|
assert(ifexpr.get());
|
||||||
|
assert(env_.get());
|
||||||
|
|
||||||
|
this->pc_ = &VsmOps::eval_op;
|
||||||
|
this->expr_ = ifexpr->test();
|
||||||
|
|
||||||
|
|
||||||
|
/* when control arrives at .cont_ will have:
|
||||||
|
* .value_ -> result of evaluating ifexpr->test()
|
||||||
|
*/
|
||||||
|
this->stack_ = VsmStackFrame::push1(mm, this->stack_, ifexpr_boxed, cont_);
|
||||||
|
|
||||||
|
/* .stack_:
|
||||||
|
* frame
|
||||||
|
* [0] = ifexpr (boxed expression)
|
||||||
|
*/
|
||||||
|
|
||||||
|
this->cont_ = &VsmOps::complete_ifexpr_op;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VirtualSchematikaMachine::do_complete_ifexpr_op()
|
||||||
|
{
|
||||||
|
using xo::scm::IfExpr;
|
||||||
|
|
||||||
|
scope log(XO_DEBUG(true));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* - value: contains result of evaluating test condition of if-expr
|
||||||
|
* - stack: top frame has 1 slot, holds (boxed) if-expr itself
|
||||||
|
*/
|
||||||
|
assert(value_.get());
|
||||||
|
assert(stack_.get());
|
||||||
|
assert(env_.get());
|
||||||
|
|
||||||
|
gp<Boolean> test_value = gp<Boolean>::from(value_);
|
||||||
|
|
||||||
|
if (test_value.get()) {
|
||||||
|
gp<VsmStackFrame> sp0 = this->stack_;
|
||||||
|
|
||||||
|
bp<IfExpr> ifexpr = IfExpr::from(ExpressionBoxed::from((*sp0)[0])->contents());
|
||||||
|
|
||||||
|
assert(ifexpr.get());
|
||||||
|
|
||||||
|
this->pc_ = &VsmOps::eval_op;
|
||||||
|
|
||||||
|
if (test_value->value()) {
|
||||||
|
this->expr_ = ifexpr->when_true();
|
||||||
|
} else {
|
||||||
|
this->expr_ = ifexpr->when_false();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->stack_ = sp0->parent();
|
||||||
|
this->cont_ = sp0->continuation();
|
||||||
|
} else {
|
||||||
|
std::string err = tostr("expect boolean value for result of if-expr test", xtag("value", test_value));
|
||||||
|
|
||||||
|
this->value_ = nullptr;
|
||||||
|
this->error_ = SchematikaError(err);
|
||||||
|
|
||||||
|
/* note: poor man's exception */
|
||||||
|
this->pc_ = nullptr;
|
||||||
|
this->cont_ = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} /*namespace scm*/
|
} /*namespace scm*/
|
||||||
} /*namespace xo*/
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ namespace xo {
|
||||||
static gp<Boolean> boolean_obj(bool x);
|
static gp<Boolean> boolean_obj(bool x);
|
||||||
static gp<Boolean> true_obj();
|
static gp<Boolean> true_obj();
|
||||||
static gp<Boolean> false_obj();
|
static gp<Boolean> false_obj();
|
||||||
|
static gp<Boolean> from(gp<Object> x) { return gp<Boolean>::from(x); }
|
||||||
|
|
||||||
bool value() const { return value_; }
|
bool value() const { return value_; }
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue