xo-interpreter: prep for xo-symboltable

This commit is contained in:
Roland Conybeare 2025-11-17 22:31:10 -05:00
commit 6a0e4bfeaa
8 changed files with 62 additions and 19 deletions

View file

@ -116,6 +116,7 @@ add_subdirectory(xo-expression)
add_subdirectory(xo-pyexpression)
add_subdirectory(xo-tokenizer)
add_subdirectory(xo-reader)
add_subdirectory(xo-symboltable)
add_subdirectory(xo-interpreter)
add_subdirectory(xo-jit)
add_subdirectory(xo-pyjit)

View file

@ -1,3 +1,16 @@
# xo-alloc -- arena allocator with rudimentary GC support
# xo-alloc -- arena allocator and incremental garbage collector
Xo-alloc is a lightweight arena allocator
# Rules for writing garbage-collected classes.
Topics
* allocation - allocate Objects (inheriting xo::Object) before owned scratch space.
Can relax this if/when abandon the bad-for-locality use of two pointers
into to-space to keep track of grey objects. Want to use stack anyway
so we can do depth-first search.
* destructors - can omit except for finalization
* assignment - MUST USE Object::assign_member() to assign pointers to gc-owned memory.
Only necessary for old->new pointers, so don't need to worry about this
for initialization.
* finalization - not supported (yet)
- padding - use IAlloc::with_padding(z) for hand-allocated objects.

View file

@ -191,8 +191,6 @@ namespace xo {
**/
virtual std::size_t _shallow_size() const = 0;
// TODO: _shallow_move() also overwrite *this with gc-only forwarding object point to C
/** if subject is allocated by GC:
* - create copy C in to-space
* - destination C will be nursery|tenured depending on location of this.

View file

@ -0,0 +1,24 @@
/** @file Env.hpp
*
* @author Roland Conybeare, Nov 2025
**/
#pragma once
#include "xo/alloc/Object.hpp"
namespace xo {
namespace scm {
/** @class Env
* @brief runtime environment, holding variable bindings for schematika interpreter
*
* Garbage-collected
*
* TODO: rename xo-expression xo::scm::Environment -> xo::scm::SymbolTable
**/
class Env : public Object {
public:
//gp<Object> lookup_symbol(xxx);
};
} /*namespace scm*/
} /*namespace xo*/

View file

@ -1,7 +1,7 @@
/** @file StackFrame.hpp **/
#include "xo/alloc/IAlloc.hpp"
#include "xo/alloc/Object.hpp"
#include "Env.hpp"
#include <cstddef>
#include <cstdint>
@ -45,19 +45,21 @@ namespace xo {
* @ref StackFrame class
*
* memory layout:
*
* +-----------------------+
* | vtable |
* ^
* +-----------------------+ |
* | vtable | |
* +-----------------------+ |
* | .parent +------/
* +------------+----------+
* | .slot_v_ | .n_ |
* | +----------+
* | | .v_ +------\
* +------------+----------+ <--/
* | .v_[0] |
* | .v_[0] +---------> Object(1)
* +-----------------------+
* . .. .
* +-----------------------+
* | .v_[.n_-1] |
* | .v_[.n_-1] +---------> Object(n)
* +-----------------------+
**/
class StackFrame : public Object {
@ -65,16 +67,17 @@ namespace xo {
using TaggedPtr = xo::reflect::TaggedPtr;
public:
StackFrame(gc::IAlloc * mm, std::size_t n) : slot_v_{mm, n} {}
StackFrame(gc::IAlloc * mm, gp<StackFrame> p, std::size_t n) : parent_{p}, slot_v_{mm, n} {}
/** create frame using allocator @p mm,
* with exactly @p n_slot object pointers
* with parent @p p and exactly @p n_slot object pointers
**/
static gp<StackFrame> make(gc::IAlloc * mm, std::size_t n_slot);
static gp<StackFrame> make(gc::IAlloc * mm, gp<StackFrame> p, std::size_t n_slot);
/** reflect StackFrame object representation **/
static void reflect_self();
gp<StackFrame> parent() const { return parent_; }
std::size_t size() const { return slot_v_.size(); }
gp<Object> operator[](std::size_t i) const { return slot_v_[i]; }
@ -88,6 +91,8 @@ namespace xo {
virtual std::size_t _forward_children() final override;
private:
/** parent stack frame **/
gp<StackFrame> parent_;
/** stack frame contents **/
CVector<gp<Object>> slot_v_;
};

View file

@ -24,9 +24,9 @@ namespace xo {
}
gp<StackFrame>
StackFrame::make(gc::IAlloc * mm, std::size_t n)
StackFrame::make(gc::IAlloc * mm, gp<StackFrame> p, std::size_t n)
{
return new (MMPtr(mm)) StackFrame(mm, n);
return new (MMPtr(mm)) StackFrame(mm, p, n);
}
TaggedPtr
@ -70,7 +70,7 @@ namespace xo {
size_t z = size();
StackFrame * copy = new (cpof) StackFrame(cpof.mm_, z);
StackFrame * copy = new (cpof) StackFrame(cpof.mm_, parent_, z);
void * v_dest = copy->slot_v_.v_;
@ -90,6 +90,7 @@ namespace xo {
std::size_t
StackFrame::_forward_children()
{
Object::_forward_inplace(parent_);
for (std::size_t i = 0, n = slot_v_.size(); i < n; ++i) {
Object::_forward_inplace((*this)[i]);
}
@ -120,6 +121,7 @@ namespace xo {
td1->assign_tdextra(Reflect::get_final_invoker<VectorType>(),
std::move(tdx1));
REFLECT_MEMBER(sr, parent);
REFLECT_MEMBER(sr, slot_v);
}
}

View file

@ -53,7 +53,7 @@ namespace xo {
Object::mm = alloc.get();
std::size_t n = tc.contents_.size();
gp<StackFrame> frame = StackFrame::make(alloc.get(), n);
gp<StackFrame> frame = StackFrame::make(alloc.get(), nullptr /*parent*/, n);
TaggedPtr tp = frame->self_tp();
@ -94,7 +94,7 @@ namespace xo {
gc->add_gc_root(reinterpret_cast<Object **>(&x));
REQUIRE(gc->tospace_generation_of(x.ptr()) == generation_result::nursery);
gp<StackFrame> frame = StackFrame::make(gc.get(), n);
gp<StackFrame> frame = StackFrame::make(gc.get(), nullptr /*parent*/, n);
StackFrame ** frame_pp = frame.ptr_address();
gc->add_gc_root(reinterpret_cast<Object **>(frame_pp));

View file

@ -12,4 +12,4 @@ xo_headeronly_dependency(${SELF_LIB} xo_reflectutil)
xo_headeronly_dependency(${SELF_LIB} xo_unit)
xo_headeronly_dependency(${SELF_LIB} callback)
xo_dependency(${SELF_LIB} xo_alloc)
xo_dependency(${SELF_LIB} reflect)
#xo_dependency(${SELF_LIB} reflect) # should be able to get this indirectly via xo_alloc