xo-interpreter2 stack: invoke closures w/ tail-call opt [WIP]

This commit is contained in:
Roland Conybeare 2026-02-13 02:05:47 -05:00
commit cfa5692804
14 changed files with 174 additions and 87 deletions

View file

@ -6,7 +6,7 @@
#pragma once
#include "DClosure.hpp"
#include "detail/IProcedure_DClosure.hpp"
//#include "detail/IProcedure_DClosure.hpp"
#include "detail/IGCObject_DClosure.hpp"
#include "detail/IPrintable_DClosure.hpp"

View file

@ -28,6 +28,16 @@ namespace xo {
VsmInstr cont,
DLocalEnv * env);
/** create instance, using memory from @p mm **/
static DVsmApplyClosureFrame * make(obj<AAllocator> mm,
obj<AGCObject> stack,
VsmInstr cont,
DLocalEnv * env);
obj<AGCObject> stack() const { return stack_; }
VsmInstr cont() const { return cont_; }
DLocalEnv * local_env() const { return local_env_; }
/** gcobject facet **/
std::size_t shallow_size() const noexcept;
DVsmApplyClosureFrame * shallow_copy(obj<AAllocator> mm) const noexcept;

View file

@ -30,10 +30,10 @@ namespace xo {
obj<AGCObject> parent() const noexcept { return parent_; }
VsmInstr cont() const noexcept { return cont_; }
obj<AProcedure> fn() const noexcept { return fn_; }
obj<AGCObject> fn() const noexcept { return fn_; }
DArray * args() const noexcept { return args_; }
void assign_fn(obj<AProcedure> x) { this->fn_ = x; }
void assign_fn(obj<AGCObject> x) { this->fn_ = x; }
std::size_t shallow_size() const noexcept;
DVsmApplyFrame * shallow_copy(obj<AAllocator> mm) const noexcept;
@ -51,9 +51,13 @@ namespace xo {
*
* note: when initially created, this will be unpopulated;
* don't know correct value until we evaluate
* expression in head position
* expression in head position.
*
* Must exhibit either:
* 1. AProcedure facet (runs natively)
* 2. AVsmProcedure facet (requires schematika runtime)
**/
obj<AProcedure> fn_;
obj<AGCObject> fn_;
/** evaluated arguments (to target procedure) **/
DArray * args_;
};

View file

@ -176,16 +176,28 @@ namespace xo {
**/
void _do_evalargs_op();
/** call closure @ref fn_ with arguments @ref args_ **/
void _do_call_closure_op();
/** call primitive @ref fn_ with arguments @ref args_ **/
void _do_call_primitive_op();
/** restore registers from stack frame
* (specifically: local_env_, stack_, cont_)
* after invoking a schematika closure
**/
void _do_applycoda_op();
private:
/*
* Some registers are preserved by evaluation:
* stack_
* cont_
* local_env_
*
* Other registers not preserved
* pc_
* expr_
* local_env_
* fn_
* args_
* value_
@ -244,8 +256,8 @@ namespace xo {
DGlobalEnv * global_env_ = nullptr;
private:
/** function to call **/
obj<AProcedure> fn_;
/** evaluated function to call **/
obj<AGCObject> fn_;
/** evaluated argument list **/
DArray * args_;

View file

@ -19,12 +19,20 @@ namespace xo {
static VsmInstr c_apply;
static VsmInstr c_evalargs;
/** restore registers after calling a schematika closure **/
static VsmInstr c_applycoda;
vsm_opcode opcode() const noexcept { return opcode_; }
private:
vsm_opcode opcode_;
};
inline bool
operator==(VsmInstr x, VsmInstr y) noexcept {
return x.opcode() == y.opcode();
}
inline std::ostream &
operator<<(std::ostream & os, VsmInstr x) {
os << x.opcode();

View file

@ -28,6 +28,11 @@ namespace xo {
**/
evalargs,
/** Coda to restore vsm registers (local_env, stack, cont)
* after invoking a closure
**/
applycoda,
/** sentinel, counts number of opcodes **/
N,
};