xo-interpreter2 stack: handle SequenceExpr + gc for frames

This commit is contained in:
Roland Conybeare 2026-02-13 15:16:05 -05:00
commit caed95c54d
22 changed files with 559 additions and 36 deletions

View file

@ -20,6 +20,10 @@ set(SELF_SRCS
IGCObject_DVsmApplyClosureFrame.cpp
IPrintable_DVsmApplyClosureFrame.cpp
DVsmSeqContFrame.cpp
IGCObject_DVsmSeqContFrame.cpp
IPrintable_DVsmSeqContFrame.cpp
DClosure.cpp
IGCObject_DClosure.cpp
IPrintable_DClosure.cpp

View file

@ -4,6 +4,7 @@
**/
#include "DVsmApplyClosureFrame.hpp"
#include "LocalEnv.hpp"
namespace xo {
using xo::mm::AGCObject;
@ -52,7 +53,8 @@ namespace xo {
std::size_t
DVsmApplyClosureFrame::forward_children(obj<ACollector> gc) noexcept
{
(void)gc;
gc.forward_inplace(&stack_);
gc.forward_inplace(&local_env_);
return this->shallow_size();
}

View file

@ -4,6 +4,7 @@
**/
#include "DVsmApplyFrame.hpp"
#include <xo/object2/Array.hpp>
#include <xo/indentlog/print/pretty.hpp>
namespace xo {
@ -59,9 +60,9 @@ namespace xo {
std::size_t
DVsmApplyFrame::forward_children(obj<ACollector> gc) noexcept
{
// GC needs to locate AGCObject iface for each member
(void)gc;
gc.forward_inplace(&parent_);
gc.forward_inplace(&fn_);
gc.forward_inplace(&args_);
return this->shallow_size();
}
@ -69,12 +70,10 @@ namespace xo {
bool
DVsmApplyFrame::pretty(const ppindentinfo & ppii) const
{
return ppii.pps()->pretty_struct
(ppii,
"DVsmApplyFrame",
refrtag("cont", cont_),
refrtag("n_args", args_->size())
);
return ppii.pps()->pretty_struct(ppii,
"DVsmApplyFrame",
refrtag("cont", cont_),
refrtag("n_args", args_->size()));
}
} /*namespace scm*/

View file

@ -4,6 +4,7 @@
**/
#include "DVsmEvalArgsFrame.hpp"
#include <xo/expression2/ApplyExpr.hpp>
#include <xo/indentlog/print/pretty.hpp>
namespace xo {
@ -16,7 +17,7 @@ namespace xo {
DVsmEvalArgsFrame::DVsmEvalArgsFrame(DVsmApplyFrame * parent,
VsmInstr cont,
const DApplyExpr * apply_expr)
DApplyExpr * apply_expr)
: parent_{parent},
cont_{cont},
apply_expr_{apply_expr}
@ -26,7 +27,7 @@ namespace xo {
DVsmEvalArgsFrame::make(obj<AAllocator> mm,
DVsmApplyFrame * apply_frame,
VsmInstr cont,
const DApplyExpr * apply_expr)
DApplyExpr * apply_expr)
{
DVsmEvalArgsFrame * result = nullptr;
@ -61,7 +62,8 @@ namespace xo {
std::size_t
DVsmEvalArgsFrame::forward_children(obj<ACollector> gc) noexcept
{
(void)gc;
gc.forward_inplace(&parent_);
gc.forward_inplace(&apply_expr_);
return this->shallow_size();
}
@ -69,12 +71,10 @@ namespace xo {
bool
DVsmEvalArgsFrame::pretty(const ppindentinfo & ppii) const
{
return ppii.pps()->pretty_struct
(ppii,
"DVsmEvalArgsFrame",
refrtag("cont", cont_),
refrtag("i_arg", i_arg_)
);
return ppii.pps()->pretty_struct(ppii,
"DVsmEvalArgsFrame",
refrtag("cont", cont_),
refrtag("i_arg", i_arg_));
}
} /*namespace scm*/
} /*namespace xo*/

View file

@ -0,0 +1,70 @@
/** @file DVsmSeqContFrame.cpp
*
* @author Roland Conybeare, Feb 2026
**/
#include "DVsmSeqContFrame.hpp"
namespace xo {
namespace scm {
DVsmSeqContFrame::DVsmSeqContFrame(obj<AGCObject> parent,
VsmInstr cont,
DSequenceExpr * seq_expr,
uint32_t i_seq)
: parent_{parent},
cont_{cont},
seq_expr_{seq_expr},
i_seq_{i_seq}
{}
DVsmSeqContFrame *
DVsmSeqContFrame::make(obj<AAllocator> mm,
obj<AGCObject> parent,
VsmInstr cont,
DSequenceExpr * seq_expr,
uint32_t i_seq)
{
void * mem = mm.alloc_for<DVsmSeqContFrame>();
return new (mem) DVsmSeqContFrame(parent, cont, seq_expr, i_seq);
}
// gcobject facet
std::size_t
DVsmSeqContFrame::shallow_size() const noexcept
{
return sizeof(*this);
}
DVsmSeqContFrame *
DVsmSeqContFrame::shallow_copy(obj<AAllocator> mm) const noexcept
{
return mm.std_copy_for<DVsmSeqContFrame>(this);
}
std::size_t
DVsmSeqContFrame::forward_children(obj<ACollector> gc) noexcept
{
gc.forward_inplace(&parent_);
gc.forward_inplace(&seq_expr_);
return this->shallow_size();
}
// printable facet
bool
DVsmSeqContFrame::pretty(const ppindentinfo & ppii) const noexcept
{
return ppii.pps()->pretty_struct(ppii,
"DVsmSeqContFrame",
refrtag("cont", cont_),
refrtag("i_seq", i_seq_));
}
} /*namespace scm*/
} /*namespace xo*/
/* end DVsmSeqContFrame.cpp */

View file

@ -0,0 +1,39 @@
/** @file IGCObject_DVsmSeqContFrame.cpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IGCObject_DVsmSeqContFrame.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_any.hpp.j2]
* 3. idl for facet methods
* [idl/IGCObject_DVsmSeqContFrame.json5]
**/
#include "sequence/IGCObject_DVsmSeqContFrame.hpp"
namespace xo {
namespace scm {
auto
IGCObject_DVsmSeqContFrame::shallow_size(const DVsmSeqContFrame & self) noexcept -> size_type
{
return self.shallow_size();
}
auto
IGCObject_DVsmSeqContFrame::shallow_copy(const DVsmSeqContFrame & self, obj<AAllocator> mm) noexcept -> Opaque
{
return self.shallow_copy(mm);
}
auto
IGCObject_DVsmSeqContFrame::forward_children(DVsmSeqContFrame & self, obj<ACollector> gc) noexcept -> size_type
{
return self.forward_children(gc);
}
} /*namespace scm*/
} /*namespace xo*/
/* end IGCObject_DVsmSeqContFrame.cpp */

View file

@ -0,0 +1,28 @@
/** @file IPrintable_DVsmSeqContFrame.cpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IPrintable_DVsmSeqContFrame.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_any.hpp.j2]
* 3. idl for facet methods
* [idl/IPrintable_DVsmSeqContFrame.json5]
**/
#include "sequence/IPrintable_DVsmSeqContFrame.hpp"
namespace xo {
namespace scm {
auto
IPrintable_DVsmSeqContFrame::pretty(const DVsmSeqContFrame & self, const ppindentinfo & ppii) -> bool
{
return self.pretty(ppii);
}
} /*namespace scm*/
} /*namespace xo*/
/* end IPrintable_DVsmSeqContFrame.cpp */

View file

@ -7,11 +7,13 @@
#include "VsmApplyFrame.hpp"
#include "VsmEvalArgsFrame.hpp"
#include "VsmApplyClosureFrame.hpp"
#include "VsmSeqContFrame.hpp"
#include "VsmRcx.hpp"
#include "Closure.hpp"
#include <xo/expression2/ApplyExpr.hpp>
#include <xo/expression2/LambdaExpr.hpp>
#include <xo/expression2/Constant.hpp>
#include <xo/expression2/SequenceExpr.hpp>
#include <xo/procedure2/RuntimeContext.hpp>
//#include <xo/procedure2/SimpleRcx.hpp>
#include <xo/gc/DX1Collector.hpp>
@ -188,6 +190,9 @@ namespace xo {
case vsm_opcode::applycoda:
_do_applycoda_op();
break;
case vsm_opcode::seq_cont:
_do_seq_cont_op();
break;
}
return true;
@ -328,7 +333,7 @@ namespace xo {
auto apply = obj<AExpression,DApplyExpr>::from(expr_);
// evaluated arguments
// accumulate evaluated arguments here
DArray * args = DArray::empty(mm_.to_op(),
apply->n_args());
@ -361,8 +366,42 @@ namespace xo {
void
VirtualSchematikaMachine::_do_eval_sequence_op()
{
// not implemented
assert(false);
// assuming bump allocator:
//
// VsmEvalSequence
// v
// +-------+------+-------+-------+
// | par x | cont | seq | i_elt |
// +-----|-+------+-------+-------+
// |
// <-----/
//
auto seq_expr = obj<AExpression,DSequenceExpr>::from(expr_);
if (seq_expr->size() == 0) {
/* empty sequence expression does not produce a value */
this->value_ = VsmResult(obj<AGCObject>());
this->pc_ = this->cont_;
return;
}
auto seqexpr_frame
= obj<AGCObject,DVsmSeqContFrame>
(DVsmSeqContFrame::make(mm_.to_op(),
this->stack_ /*saved stack*/,
this->cont_ /*saved cont*/,
seq_expr.data() /*saved expr*/,
0 /*index of seq element*/));
this->stack_ = seqexpr_frame;
// Setup evaluation of first sequence element
this->cont_ = VsmInstr::c_seq_cont;
this->expr_ = (*seq_expr.data())[0];
this->pc_ = VsmInstr::c_eval;
}
void
@ -380,7 +419,7 @@ namespace xo {
_do_call_closure_op();
return;
} else {
_do_call_closure_op();
_do_call_primitive_op();
return;
}
}
@ -393,6 +432,8 @@ namespace xo {
auto closure = obj<AGCObject,DClosure>::from(fn_);
assert(closure);
// TODO: for tail recursion:
// check whether stack_ already refers to a
// DVsmApplyClosureFrame instance, in which case
@ -496,8 +537,8 @@ namespace xo {
= evalargs_frame->apply_expr();
if (i_arg == -1) {
bool is_native_fn = value.to_facet<AProcedure>();
bool is_closure = obj<AGCObject,DClosure>::from(value);
bool is_native_fn = value.try_to_facet<AProcedure>();
if (is_native_fn || is_closure) {
apply_frame->assign_fn(value);
@ -572,6 +613,39 @@ namespace xo {
// not implemented
assert(false);
}
void
VirtualSchematikaMachine::_do_seq_cont_op()
{
auto frame = obj<AGCObject,DVsmSeqContFrame>::from(stack_);
assert(frame);
uint32_t i_seq = 1 + frame->i_seq();
auto seq_expr = frame->seq_expr();
assert(seq_expr);
if (i_seq == seq_expr->size()) {
/* done with sequence
* value of sequence-expr is the value of the last expression in that sequence,
* which is already in the value_ register
*/
this->stack_ = frame->parent();
this->pc_ = frame->cont();
return;
} else {
frame->incr_i_seq();
this->cont_ = VsmInstr::c_seq_cont;
this->expr_ = (*seq_expr)[i_seq];
this->pc_ = VsmInstr::c_eval;
return;
}
}
} /*namespace scm*/
} /*namespace xo*/

View file

@ -16,6 +16,7 @@ namespace xo {
case vsm_opcode::apply: return "apply";
case vsm_opcode::evalargs: return "evalargs";
case vsm_opcode::applycoda: return "applycoda";
case vsm_opcode::seq_cont: return "seq_cont";
case vsm_opcode::N:
break;
}
@ -37,6 +38,9 @@ namespace xo {
VsmInstr
VsmInstr::c_applycoda = VsmInstr(vsm_opcode::applycoda);
VsmInstr
VsmInstr::c_seq_cont = VsmInstr(vsm_opcode::seq_cont);
} /*namespace scm*/
} /*namespace xo*/

View file

@ -9,6 +9,7 @@
#include "VsmApplyFrame.hpp"
#include "VsmEvalArgsFrame.hpp"
#include "VsmApplyClosureFrame.hpp"
#include "VsmSeqContFrame.hpp"
#include "Primitive_gco_2_gco_gco.hpp"
#include "Closure.hpp"
#include "LocalEnv.hpp"
@ -32,10 +33,12 @@ namespace xo {
{
scope log(XO_DEBUG(true));
// VsmStackFrame
// VsmStqackFrame
// +- VsmApplyFrame
// +- VsmEvalArgsFrame
// \- VsmApplyClosureFrame
// +- VsmApplyClosureFrame
// \- VsmSeqContFrame
FacetRegistry::register_impl<AGCObject, DVsmApplyFrame>();
FacetRegistry::register_impl<APrintable, DVsmApplyFrame>();
@ -46,22 +49,27 @@ namespace xo {
FacetRegistry::register_impl<AGCObject, DVsmApplyClosureFrame>();
FacetRegistry::register_impl<APrintable, DVsmApplyClosureFrame>();
FacetRegistry::register_impl<AGCObject, DVsmSeqContFrame>();
FacetRegistry::register_impl<APrintable, DVsmSeqContFrame>();
// LocalEnv
FacetRegistry::register_impl<AGCObject, DLocalEnv>();
FacetRegistry::register_impl<APrintable, DLocalEnv>();
// Procedure
// +- Primitive_gco_2_gco_gco
// \- Closure
// \- Primitive_gco_2_gco_gco
FacetRegistry::register_impl<AProcedure, DPrimitive_gco_2_gco_gco>();
FacetRegistry::register_impl<AGCObject, DPrimitive_gco_2_gco_gco>();
FacetRegistry::register_impl<APrintable, DPrimitive_gco_2_gco_gco>();
// FacetRegistry::register_impl<AProcedure, DClosure>();
// FacetRegistry::register_impl<AGCObject, DClosure>();
// FacetRegistry::register_impl<APrintable, DClosure>();
// Closure
// FacetRegistry::register_impl<AProcedure, DClosure>(); // if/when provided
FacetRegistry::register_impl<AGCObject, DClosure>();
FacetRegistry::register_impl<APrintable, DClosure>();
// RuntimeContext
// \- VsmRcx
@ -70,6 +78,8 @@ namespace xo {
log && log(xtag("DVsmApplyFrame.tseq", typeseq::id<DVsmApplyFrame>()));
log && log(xtag("DVsmEvalArgsFrame.tseq", typeseq::id<DVsmEvalArgsFrame>()));
log && log(xtag("DVsmApplyClosureFrame.tseq", typeseq::id<DVsmApplyClosureFrame>()));
log && log(xtag("DVsmSeqContFrame.tseq", typeseq::id<DVsmSeqContFrame>()));
log && log(xtag("DClosure.tseq", typeseq::id<DClosure>()));
log && log(xtag("DLocalEnv.tseq", typeseq::id<DLocalEnv>()));
log && log(xtag("DVsmRcx.tseq", typeseq::id<DVsmRcx>()));