xo-interpreter2 stack: apply user-defined lambda passes utest

This commit is contained in:
Roland Conybeare 2026-02-13 16:06:19 -05:00
commit 20cee5db7d
8 changed files with 49 additions and 22 deletions

View file

@ -30,11 +30,11 @@ namespace xo {
/** create instance, using memory from @p mm **/
static DVsmApplyClosureFrame * make(obj<AAllocator> mm,
obj<AGCObject> stack,
obj<AGCObject> parent,
VsmInstr cont,
DLocalEnv * env);
obj<AGCObject> stack() const { return stack_; }
obj<AGCObject> parent() const { return stack_; }
VsmInstr cont() const { return cont_; }
DLocalEnv * local_env() const { return local_env_; }

View file

@ -185,7 +185,7 @@ namespace xo {
* (specifically: local_env_, stack_, cont_)
* after invoking a schematika closure
**/
void _do_applycoda_op();
void _do_apply_cont_op();
/** loop continuation after evaluating element of a SequenceExpr **/
void _do_seq_cont_op();

View file

@ -18,8 +18,8 @@ namespace xo {
static VsmInstr c_apply;
static VsmInstr c_evalargs;
/** restore registers after calling a schematika closure **/
static VsmInstr c_applycoda;
/** proceed to continuation after an ApplyExpr **/
static VsmInstr c_apply_cont;
/** loop to evaluate members of a SequenceExpr **/
static VsmInstr c_seq_cont;

View file

@ -31,7 +31,7 @@ namespace xo {
/** Coda to restore vsm registers (local_env, stack, cont)
* after invoking a closure
**/
applycoda,
apply_cont,
/** Loop over elements of a SequenceExpr **/
seq_cont,

View file

@ -187,8 +187,8 @@ namespace xo {
case vsm_opcode::evalargs:
_do_evalargs_op();
break;
case vsm_opcode::applycoda:
_do_applycoda_op();
case vsm_opcode::apply_cont:
_do_apply_cont_op();
break;
case vsm_opcode::seq_cont:
_do_seq_cont_op();
@ -302,8 +302,37 @@ namespace xo {
void
VirtualSchematikaMachine::_do_eval_varref_op()
{
// not implemented
assert(false);
auto var = obj<AExpression,DVarRef>::from(expr_);
Binding b = var->path();
if (!local_env_) {
// need lookup on global_env_
assert(false);
}
auto value = local_env_->lookup_value(b);
if (value) {
this->value_ = VsmResult(value);
this->pc_ = this->cont_;
return;
}
// no binding
auto error = DRuntimeError::make(mm_.to_op(),
"_do_eval_varref_op",
"no binding for variable");
this->value_ = VsmResult(error);
// for now: halt VSM execution
// TODO: some combination of
// 1. emit stack trace
// 2. go to debugger
// 3. have every vsm instruction check inputs for errors
this->pc_ = VsmInstr::c_halt;
}
void
@ -439,7 +468,7 @@ namespace xo {
// DVsmApplyClosureFrame instance, in which case
// we can just refer to it instead of pushing a new one
if (cont_ == VsmInstr::c_applycoda) {
if (cont_ == VsmInstr::c_apply_cont) {
// we are making a tail call.
// No need to preserve (stack, cont, local_env),
// since continuation will restore on top of them
@ -454,7 +483,7 @@ namespace xo {
// push frame w/ saved vsm registers
this->stack_ = frame;
this->cont_ = VsmInstr::c_applycoda;
this->cont_ = VsmInstr::c_apply_cont;
}
auto lambda = closure->lambda();
@ -598,7 +627,7 @@ namespace xo {
}
void
VirtualSchematikaMachine::_do_applycoda_op()
VirtualSchematikaMachine::_do_apply_cont_op()
{
// see DVsmApplyClosureFrame
@ -606,12 +635,9 @@ namespace xo {
assert(frame);
this->stack_ = frame->stack();
this->stack_ = frame->parent();
this->local_env_ = frame->local_env();
this->pc_ = frame->cont();
// not implemented
assert(false);
}
void

View file

@ -15,7 +15,7 @@ namespace xo {
case vsm_opcode::eval: return "eval";
case vsm_opcode::apply: return "apply";
case vsm_opcode::evalargs: return "evalargs";
case vsm_opcode::applycoda: return "applycoda";
case vsm_opcode::apply_cont: return "apply_cont";
case vsm_opcode::seq_cont: return "seq_cont";
case vsm_opcode::N:
break;
@ -37,7 +37,7 @@ namespace xo {
VsmInstr::c_evalargs = VsmInstr(vsm_opcode::evalargs);
VsmInstr
VsmInstr::c_applycoda = VsmInstr(vsm_opcode::applycoda);
VsmInstr::c_apply_cont = VsmInstr(vsm_opcode::apply_cont);
VsmInstr
VsmInstr::c_seq_cont = VsmInstr(vsm_opcode::seq_cont);

View file

@ -246,11 +246,12 @@ namespace xo {
log && log(xtag("res.tseq", res.value()->_typeseq()));
// currently get not-implemented error
auto x = obj<AGCObject,DRuntimeError>::from(*res.value());
auto x = obj<AGCObject,DInteger>::from(*res.value());
REQUIRE(x);
REQUIRE(x->value() == 195);
log && log("runtime-error", xtag("ex.src", x->src_function()), xtag("ex.descr", x->error_descr()));
//log && log("runtime-error", xtag("ex.src", x->src_function()), xtag("ex.descr", x->error_descr()));
//REQUIRE(x.data()->value() == 1.570796325);

View file

@ -135,7 +135,7 @@ namespace xo {
for (size_type i = 0; i < size_; ++i) {
obj<AGCObject> & elt = elts_[i];
gc.forward_inplace(elt.iface(), (void **)&(elt.data_));
gc.forward_inplace(&elt);
}
return shallow_size();