xo-interpreter2: apply sequence now working in interpreter
This commit is contained in:
parent
e71954697c
commit
61d41a2298
8 changed files with 203 additions and 34 deletions
|
|
@ -29,6 +29,8 @@ namespace xo {
|
||||||
obj<AProcedure> fn() const noexcept { return fn_; }
|
obj<AProcedure> fn() const noexcept { return fn_; }
|
||||||
DArray * args() const noexcept { return args_; }
|
DArray * args() const noexcept { return args_; }
|
||||||
|
|
||||||
|
void assign_fn(obj<AProcedure> x) { this->fn_ = x; }
|
||||||
|
|
||||||
std::size_t shallow_size() const noexcept;
|
std::size_t shallow_size() const noexcept;
|
||||||
DVsmApplyFrame * shallow_copy(obj<AAllocator> mm) const noexcept;
|
DVsmApplyFrame * shallow_copy(obj<AAllocator> mm) const noexcept;
|
||||||
std::size_t forward_children(obj<ACollector> gc) noexcept;
|
std::size_t forward_children(obj<ACollector> gc) noexcept;
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,18 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "DVsmApplyFrame.hpp"
|
#include "VsmApplyFrame.hpp"
|
||||||
|
#include <xo/expression2/DApplyExpr.hpp>
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
namespace scm {
|
namespace scm {
|
||||||
|
|
||||||
/** frame for executing an apply expression **/
|
/** frame for executing an apply expression **/
|
||||||
class DVsmEvalArgsFrame : public VsmFrame {
|
class DVsmEvalArgsFrame {
|
||||||
public:
|
public:
|
||||||
using ACollector = xo::mm::ACollector;
|
using ACollector = xo::mm::ACollector;
|
||||||
using AAllocator = xo::mm::AAllocator;
|
using AAllocator = xo::mm::AAllocator;
|
||||||
|
using AGCObject = xo::mm::AGCObject;
|
||||||
using ppindentinfo = xo::print::ppindentinfo;
|
using ppindentinfo = xo::print::ppindentinfo;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -24,12 +26,21 @@ namespace xo {
|
||||||
* old_cont = [xfer to called function]
|
* old_cont = [xfer to called function]
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
DVsmEvalArgsFrame(obj<AGCObject> old_parent,
|
DVsmEvalArgsFrame(DVsmApplyFrame * parent,
|
||||||
VsmInstr old_cont);
|
VsmInstr cont,
|
||||||
|
const DApplyExpr * apply_expr);
|
||||||
|
|
||||||
static DVsmEvalArgsFrame * make(obj<AAllocator> mm,
|
static DVsmEvalArgsFrame * make(obj<AAllocator> mm,
|
||||||
obj<AGCObject> apply_frame,
|
DVsmApplyFrame * apply_frame,
|
||||||
VsmInstr old_cont);
|
VsmInstr old_cont,
|
||||||
|
const DApplyExpr * apply_expr);
|
||||||
|
|
||||||
|
DVsmApplyFrame * parent() const noexcept { return parent_; }
|
||||||
|
VsmInstr cont() const noexcept { return cont_; }
|
||||||
|
const DApplyExpr * apply_expr() const noexcept { return apply_expr_; }
|
||||||
|
int32_t i_arg() const noexcept { return i_arg_; }
|
||||||
|
|
||||||
|
int32_t increment_arg() { return ++i_arg_; }
|
||||||
|
|
||||||
std::size_t shallow_size() const noexcept;
|
std::size_t shallow_size() const noexcept;
|
||||||
DVsmEvalArgsFrame * shallow_copy(obj<AAllocator> mm) const noexcept;
|
DVsmEvalArgsFrame * shallow_copy(obj<AAllocator> mm) const noexcept;
|
||||||
|
|
@ -38,6 +49,14 @@ namespace xo {
|
||||||
bool pretty(const ppindentinfo & ppii) const;
|
bool pretty(const ppindentinfo & ppii) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/** parent stack frame **/
|
||||||
|
DVsmApplyFrame * parent_ = nullptr;
|
||||||
|
/** continuation after eval args completed (always VsmInstr::c_apply) **/
|
||||||
|
VsmInstr cont_;
|
||||||
|
|
||||||
|
/** expression being evaluated **/
|
||||||
|
const DApplyExpr * apply_expr_ = nullptr;
|
||||||
|
|
||||||
/** next argument to be evaluated. -1 means function head **/
|
/** next argument to be evaluated. -1 means function head **/
|
||||||
int32_t i_arg_ = -1;
|
int32_t i_arg_ = -1;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,14 @@ namespace xo {
|
||||||
/** apply a function to evaluated arguments **/
|
/** apply a function to evaluated arguments **/
|
||||||
void _do_apply_op();
|
void _do_apply_op();
|
||||||
|
|
||||||
/** evaluate arguments on behalf of a function call **/
|
/** evaluate arguments on behalf of a function call
|
||||||
|
* Require:
|
||||||
|
* - expression value in @ref value_
|
||||||
|
* - stack:
|
||||||
|
* [0] VsmEvalArgsFrame
|
||||||
|
* [1] VsmApplyFrame
|
||||||
|
* ...
|
||||||
|
**/
|
||||||
void _do_evalargs_op();
|
void _do_evalargs_op();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -159,6 +166,8 @@ namespace xo {
|
||||||
* Other registers are not preserved
|
* Other registers are not preserved
|
||||||
* pc_
|
* pc_
|
||||||
* expr_
|
* expr_
|
||||||
|
* fn_
|
||||||
|
* args_
|
||||||
* value_
|
* value_
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -170,6 +179,11 @@ namespace xo {
|
||||||
**/
|
**/
|
||||||
box<AAllocator> mm_;
|
box<AAllocator> mm_;
|
||||||
|
|
||||||
|
/** runtime context for this vsm.
|
||||||
|
* For example, provides allocator to primitives
|
||||||
|
**/
|
||||||
|
box<ARuntimeContext> rcx_;
|
||||||
|
|
||||||
// consider separate allocator (which _may_ turn out to be the same)
|
// consider separate allocator (which _may_ turn out to be the same)
|
||||||
// for VM stack. Only works for code that doesn't rely on fancy
|
// for VM stack. Only works for code that doesn't rely on fancy
|
||||||
// lexical scoping
|
// lexical scoping
|
||||||
|
|
@ -186,6 +200,11 @@ namespace xo {
|
||||||
/** expression register **/
|
/** expression register **/
|
||||||
obj<AExpression> expr_;
|
obj<AExpression> expr_;
|
||||||
|
|
||||||
|
/** function to call **/
|
||||||
|
obj<AProcedure> fn_;
|
||||||
|
/** evaluated argument list **/
|
||||||
|
DArray * args_;
|
||||||
|
|
||||||
/** result register **/
|
/** result register **/
|
||||||
VsmResult value_;
|
VsmResult value_;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,7 @@ namespace xo {
|
||||||
VsmInstr cont) : parent_{parent}, cont_{cont} {}
|
VsmInstr cont) : parent_{parent}, cont_{cont} {}
|
||||||
|
|
||||||
//obj<AGCObject> parent() const noexcept { return parent_; }
|
//obj<AGCObject> parent() const noexcept { return parent_; }
|
||||||
VsmFrame * parent() const noexcept {
|
obj<AGCObject> parent() const noexcept { return parent_; }
|
||||||
return reinterpret_cast<VsmFrame *>(parent_.data());
|
|
||||||
}
|
|
||||||
VsmInstr cont() const noexcept { return cont_; }
|
VsmInstr cont() const noexcept { return cont_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -14,22 +14,26 @@ namespace xo {
|
||||||
|
|
||||||
// ----- VsmEvalArgsFrame -----
|
// ----- VsmEvalArgsFrame -----
|
||||||
|
|
||||||
DVsmEvalArgsFrame::DVsmEvalArgsFrame(obj<AGCObject> old_parent,
|
DVsmEvalArgsFrame::DVsmEvalArgsFrame(DVsmApplyFrame * parent,
|
||||||
VsmInstr old_cont)
|
VsmInstr cont,
|
||||||
: VsmFrame(old_parent, old_cont)
|
const DApplyExpr * apply_expr)
|
||||||
|
: parent_{parent},
|
||||||
|
cont_{cont},
|
||||||
|
apply_expr_{apply_expr}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
DVsmEvalArgsFrame *
|
DVsmEvalArgsFrame *
|
||||||
DVsmEvalArgsFrame::make(obj<AAllocator> mm,
|
DVsmEvalArgsFrame::make(obj<AAllocator> mm,
|
||||||
obj<AGCObject> apply_frame,
|
DVsmApplyFrame * apply_frame,
|
||||||
VsmInstr cont)
|
VsmInstr cont,
|
||||||
|
const DApplyExpr * apply_expr)
|
||||||
{
|
{
|
||||||
DVsmEvalArgsFrame * result = nullptr;
|
DVsmEvalArgsFrame * result = nullptr;
|
||||||
|
|
||||||
void * mem = mm.alloc(typeseq::id<DVsmEvalArgsFrame>(),
|
void * mem = mm.alloc(typeseq::id<DVsmEvalArgsFrame>(),
|
||||||
sizeof(DVsmEvalArgsFrame));
|
sizeof(DVsmEvalArgsFrame));
|
||||||
|
|
||||||
result = new (mem) DVsmEvalArgsFrame(apply_frame, cont);
|
result = new (mem) DVsmEvalArgsFrame(apply_frame, cont, apply_expr);
|
||||||
|
|
||||||
assert(result);
|
assert(result);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@
|
||||||
#include "VsmEvalArgsFrame.hpp"
|
#include "VsmEvalArgsFrame.hpp"
|
||||||
#include <xo/expression2/ApplyExpr.hpp>
|
#include <xo/expression2/ApplyExpr.hpp>
|
||||||
#include <xo/expression2/Constant.hpp>
|
#include <xo/expression2/Constant.hpp>
|
||||||
|
#include <xo/procedure2/RuntimeContext.hpp>
|
||||||
|
#include <xo/procedure2/SimpleRcx.hpp>
|
||||||
#include <xo/gc/DX1Collector.hpp>
|
#include <xo/gc/DX1Collector.hpp>
|
||||||
#include <xo/gc/detail/IAllocator_DX1Collector.hpp>
|
#include <xo/gc/detail/IAllocator_DX1Collector.hpp>
|
||||||
#include <xo/printable2/Printable.hpp>
|
#include <xo/printable2/Printable.hpp>
|
||||||
|
|
@ -26,9 +28,13 @@ namespace xo {
|
||||||
|
|
||||||
namespace scm {
|
namespace scm {
|
||||||
|
|
||||||
|
// NOTE: using heap for {DX1Collector, DSimpleRcx} instances
|
||||||
|
// (though allocation from explictly mmap'd memory)
|
||||||
|
//
|
||||||
VirtualSchematikaMachine::VirtualSchematikaMachine(const VsmConfig & config)
|
VirtualSchematikaMachine::VirtualSchematikaMachine(const VsmConfig & config)
|
||||||
: config_{config},
|
: config_{config},
|
||||||
mm_(box<AAllocator,DX1Collector>(new DX1Collector(config.x1_config_))),
|
mm_(box<AAllocator,DX1Collector>(new DX1Collector(config.x1_config_))),
|
||||||
|
rcx_(box<ARuntimeContext,DSimpleRcx>(new DSimpleRcx(mm_.to_op()))),
|
||||||
reader_{config.rdr_config_, mm_.to_op()}
|
reader_{config.rdr_config_, mm_.to_op()}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
@ -211,21 +217,23 @@ namespace xo {
|
||||||
|
|
||||||
// assuming bump allocator:
|
// assuming bump allocator:
|
||||||
//
|
//
|
||||||
// DArray VsmApplyFrame VsmEvalArgsFrame
|
// DArray VsmApplyFrame VsmEvalArgsFrame
|
||||||
// v v v
|
// v v v
|
||||||
// +----------------------+-------+------+----+--------+-------+------+-------+
|
// +----------------------+-------+-------+----+--------+-------+-------+-------+
|
||||||
// | argument expressions | par x | cont | fn | args x | par x | cont | i_arg |
|
// | argument expressions | par x | cont1 | fn | args x | par x | cont2 | i_arg |
|
||||||
// +----------------------+-----|-+------+----+------|-+-----|-+------+-------+
|
// +----------------------+-----|-+-------+----+------|-+-----|-+-------+-------+
|
||||||
// ^ ^ | | |
|
// ^ ^ | | |
|
||||||
// | \----------------------------------/
|
// | \-----------------------------------/
|
||||||
// \ | /
|
// \ | /
|
||||||
// \-----------------------------------------------/
|
// \------------------------------------------------/
|
||||||
// /
|
// /
|
||||||
// <---------------------------/
|
// <---------------------------/
|
||||||
//
|
//
|
||||||
// - VsmEvalArgsFrame: owned by VSM, state for evalargs loop
|
// - VsmEvalArgsFrame: owned by VSM, state for evalargs loop
|
||||||
// - VsmApplyFrame: owned by VSM, state for transferring control to called function
|
// - VsmApplyFrame: owned by VSM, state for transferring control to called function
|
||||||
// - DArray: contains evaluated args; owned by called primitive
|
// - DArray: contains evaluated args; owned by called primitive
|
||||||
|
// - cont2: always c_apply
|
||||||
|
//
|
||||||
|
|
||||||
auto apply = obj<AExpression,DApplyExpr>::from(expr_);
|
auto apply = obj<AExpression,DApplyExpr>::from(expr_);
|
||||||
|
|
||||||
|
|
@ -235,13 +243,13 @@ namespace xo {
|
||||||
|
|
||||||
// TODO: check function signature
|
// TODO: check function signature
|
||||||
|
|
||||||
auto apply_frame
|
DVsmApplyFrame * apply_frame
|
||||||
= obj<AGCObject,DVsmApplyFrame>
|
= DVsmApplyFrame::make(mm_.to_op(), stack_, cont_, args);
|
||||||
(DVsmApplyFrame::make(mm_.to_op(), stack_, cont_, args));
|
|
||||||
|
|
||||||
auto evalargs_frame
|
auto evalargs_frame
|
||||||
= obj<AGCObject,DVsmEvalArgsFrame>
|
= obj<AGCObject,DVsmEvalArgsFrame>
|
||||||
(DVsmEvalArgsFrame::make(mm_.to_op(), apply_frame, VsmInstr::c_apply));
|
(DVsmEvalArgsFrame::make(mm_.to_op(),
|
||||||
|
apply_frame, VsmInstr::c_apply, apply.data()));
|
||||||
|
|
||||||
this->stack_ = evalargs_frame;
|
this->stack_ = evalargs_frame;
|
||||||
|
|
||||||
|
|
@ -269,13 +277,131 @@ namespace xo {
|
||||||
void
|
void
|
||||||
VirtualSchematikaMachine::_do_apply_op()
|
VirtualSchematikaMachine::_do_apply_op()
|
||||||
{
|
{
|
||||||
// not implemented
|
// rcx_ : runtime context
|
||||||
assert(false);
|
// fn_ : function to call
|
||||||
|
// args_ : array of arguments
|
||||||
|
|
||||||
|
// TODO: check argument types
|
||||||
|
|
||||||
|
this->value_ = fn_.apply_nocheck(rcx_.to_op(), args_);
|
||||||
|
this->pc_ = cont_;
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
VirtualSchematikaMachine::_do_evalargs_op()
|
VirtualSchematikaMachine::_do_evalargs_op()
|
||||||
{
|
{
|
||||||
|
scope log(XO_DEBUG(false));
|
||||||
|
|
||||||
|
if (!value_.is_value()) {
|
||||||
|
// error while evaluating function arg
|
||||||
|
|
||||||
|
log.retroactively_enable();
|
||||||
|
log && log("error in apply -> terminating app");
|
||||||
|
|
||||||
|
this->pc_ = VsmInstr::c_halt;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// here: nested evaluation succeeded
|
||||||
|
|
||||||
|
// value of one of {fn, arg(i), ..} in fn(arg0 .. arg(n-1))
|
||||||
|
//
|
||||||
|
obj<AGCObject> value = *(value_.value());
|
||||||
|
|
||||||
|
// value_ in [i_arg] value_
|
||||||
|
// . (if i_arg >= 0) . (if i_arg = -1)
|
||||||
|
// . .
|
||||||
|
// DArray . VsmApplyFrame . VsmEvalArgsFrame
|
||||||
|
// v v v v v
|
||||||
|
// +----------------------+-------+-------+----+--------+-------+-------+--------+-------+
|
||||||
|
// | argument expressions | par o | cont1 | fn | args x | par o | cont2 | applyx | i_arg |
|
||||||
|
// +----------------------+-----|-+-------+----+------|-+-----|-+-------+--------+-------+
|
||||||
|
// ^ ^ | | |
|
||||||
|
// | \-----------------------------------/
|
||||||
|
// \ | /
|
||||||
|
// \------------------------------------------------/
|
||||||
|
// /
|
||||||
|
// <---------------------------/
|
||||||
|
//
|
||||||
|
// - VsmEvalArgsFrame: owned by VSM, state for evalargs loop
|
||||||
|
// - VsmApplyFrame: owned by VSM, state for transferring control to called function
|
||||||
|
// - DArray: contains evaluated args; owned by called primitive
|
||||||
|
|
||||||
|
// - i_arg
|
||||||
|
// if -1: value_ register holds function
|
||||||
|
// if >=0: value_ register holds i'th function argument
|
||||||
|
//
|
||||||
|
|
||||||
|
auto evalargs_frame
|
||||||
|
= obj<AGCObject,DVsmEvalArgsFrame>::from(stack_);
|
||||||
|
|
||||||
|
assert(evalargs_frame);
|
||||||
|
|
||||||
|
int32_t i_arg = evalargs_frame->i_arg();
|
||||||
|
|
||||||
|
DVsmApplyFrame * apply_frame = evalargs_frame->parent();
|
||||||
|
|
||||||
|
const DApplyExpr * apply_expr
|
||||||
|
= evalargs_frame->apply_expr();
|
||||||
|
|
||||||
|
if (i_arg == -1) {
|
||||||
|
auto fn = value.to_facet<AProcedure>();
|
||||||
|
|
||||||
|
if (fn) {
|
||||||
|
apply_frame->assign_fn(fn);
|
||||||
|
|
||||||
|
i_arg = evalargs_frame->increment_arg();
|
||||||
|
|
||||||
|
// now i_arg is 0 -> evaluate that argument
|
||||||
|
|
||||||
|
this->expr_ = apply_expr->arg(i_arg);
|
||||||
|
this->pc_ = VsmInstr::c_eval;
|
||||||
|
//this->cont_ = VsmInstra::c_evalargs; // redundant, since preserved
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// error - function position must deliver something with AProcedure?
|
||||||
|
// or DClosure, but we'll get to that.
|
||||||
|
|
||||||
|
log.retroactively_enable();
|
||||||
|
log("expected procedure in function position -> terminate");
|
||||||
|
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DArray * args = apply_frame->args();
|
||||||
|
|
||||||
|
log && log(xtag("i_arg", i_arg), xtag("n_arg", args->size()), xtag("cap", args->capacity()));
|
||||||
|
|
||||||
|
args->push_back(value);
|
||||||
|
|
||||||
|
i_arg = evalargs_frame->increment_arg();
|
||||||
|
|
||||||
|
if (i_arg == static_cast<int32_t>(apply_expr->n_args())) {
|
||||||
|
// all apply-arguments have been evaluated
|
||||||
|
// -> done with VsmEvalArgsFrame
|
||||||
|
//
|
||||||
|
|
||||||
|
this->fn_ = apply_frame->fn();
|
||||||
|
this->args_ = apply_frame->args();
|
||||||
|
|
||||||
|
this->stack_ = apply_frame->parent();
|
||||||
|
this->pc_ = VsmInstr::c_apply;
|
||||||
|
this->cont_ = apply_frame->cont();
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this->expr_ = apply_expr->arg(i_arg);
|
||||||
|
this->pc_ = VsmInstr::c_eval;
|
||||||
|
//this->cont_ = VsmInstra::c_evalargs; // redundant, since preserved
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,10 +166,10 @@ namespace xo {
|
||||||
|
|
||||||
log && log(xtag("res.tseq", res.value()->_typeseq()));
|
log && log(xtag("res.tseq", res.value()->_typeseq()));
|
||||||
|
|
||||||
auto x = obj<AGCObject,DInteger>::from(*res.value());
|
auto x = obj<AGCObject,DFloat>::from(*res.value());
|
||||||
|
|
||||||
REQUIRE(x);
|
REQUIRE(x);
|
||||||
REQUIRE(x.data()->value() == 1011);
|
REQUIRE(x.data()->value() == 1.570796325);
|
||||||
|
|
||||||
REQUIRE(res.remaining_.size() == 1);
|
REQUIRE(res.remaining_.size() == 1);
|
||||||
REQUIRE(*res.remaining_.lo() == '\n');
|
REQUIRE(*res.remaining_.lo() == '\n');
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,8 @@ namespace xo {
|
||||||
requires (std::same_as<Args, obj<AGCObject>> && ...)
|
requires (std::same_as<Args, obj<AGCObject>> && ...)
|
||||||
static DArray * array(obj<AAllocator> mm, Args... args);
|
static DArray * array(obj<AAllocator> mm, Args... args);
|
||||||
|
|
||||||
obj<AGCObject> operator[](size_type index) const noexcept { return elts_[index]; }
|
const obj<AGCObject> & operator[](size_type index) const noexcept { return elts_[index]; }
|
||||||
|
obj<AGCObject> & operator[](size_type index) noexcept { return elts_[index]; }
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
/** @defgroup darray-access acecss methods **/
|
/** @defgroup darray-access acecss methods **/
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue