xo-interpreter2 stack: + stringtable() in RuntimeContext api

This commit is contained in:
Roland Conybeare 2026-03-16 01:27:25 -05:00
commit edd6c50e10
22 changed files with 99 additions and 9 deletions

View file

@ -5,6 +5,7 @@
#pragma once
#include <xo/stringtable2/StringTable.hpp>
#include <xo/alloc2/Allocator.hpp>
#include <xo/arena/MemorySizeInfo.hpp>
@ -19,6 +20,7 @@ namespace xo {
**/
class DVsmRcx {
public:
using StringTable = xo::scm::StringTable;
using AAllocator = xo::mm::AAllocator;
using MemorySizeVisitor = xo::mm::MemorySizeVisitor;
@ -26,6 +28,7 @@ namespace xo {
DVsmRcx(VirtualSchematikaMachine * vsm);
obj<AAllocator> allocator() const noexcept;
StringTable * stringtable() const noexcept;
obj<AAllocator> error_allocator() const noexcept;
void visit_pools(const MemorySizeVisitor & visitor) const;

View file

@ -91,6 +91,8 @@ namespace xo {
obj<AAllocator> allocator() const noexcept;
/** allocator for runtime errors **/
obj<AAllocator> error_allocator() const noexcept;
/** global unique-string table **/
StringTable * stringtable() noexcept;
/** true iff parser is at top-level -> does not contain
* state for a incomplete/partial expression

View file

@ -49,6 +49,8 @@ namespace xo {
// const methods
/** default allocator to use for objects **/
static obj<AAllocator> allocator(const DVsmRcx & self) noexcept;
/** stringtable for unique symbols **/
static StringTable * stringtable(const DVsmRcx & self) noexcept;
/** invoke visitor for each distinct memory pool **/
static void visit_pools(const DVsmRcx & self, MemorySizeVisitor visitor);

View file

@ -25,6 +25,12 @@ namespace xo {
return vsm_->error_allocator();
}
StringTable *
DVsmRcx::stringtable() const noexcept
{
return vsm_->stringtable();
}
void
DVsmRcx::visit_pools(const MemorySizeVisitor & visitor) const
{

View file

@ -21,6 +21,12 @@ namespace xo {
return self.allocator();
}
auto
IRuntimeContext_DVsmRcx::stringtable(const DVsmRcx & self) noexcept -> StringTable *
{
return self.stringtable();
}
auto
IRuntimeContext_DVsmRcx::visit_pools(const DVsmRcx & self, MemorySizeVisitor visitor) -> void
{

View file

@ -100,6 +100,12 @@ namespace xo {
return error_mm_.to_op();
}
StringTable *
VirtualSchematikaMachine::stringtable() noexcept
{
return reader_.stringtable();
}
bool
VirtualSchematikaMachine::is_at_toplevel() const noexcept
{

View file

@ -5,6 +5,7 @@
output_impl_subdir: "detail",
// includes in ARuntimeContext.hpp
includes: [
"<xo/stringtable2/StringTable.hpp>",
"<xo/alloc2/Allocator.hpp>",
"<xo/arena/MemorySizeInfo.hpp>"
],
@ -46,6 +47,15 @@
noexcept: true,
attributes: [],
},
{
name: "stringtable",
doc: [ "stringtable for unique symbols" ],
return_type: "StringTable *",
args: [],
const: true,
noexcept: true,
attributes: [],
},
{
name: "visit_pools",
doc: [ "invoke visitor for each distinct memory pool" ],

View file

@ -87,27 +87,36 @@ namespace xo {
/** @defgroup scm-primitive-ctors constructors **/
///@{
Primitive(std::string_view name, Fn fn)
Primitive(std::string_view name, obj<AType> type, Fn fn)
: name_{name},
type_{type},
fn_td_{Reflect::require<Fn>()},
fn_{fn} {}
static Primitive * _make(obj<AAllocator> mm, std::string_view name, Fn fn) {
void * mem = mm.alloc_for<Primitive>();
return new (mem) Primitive(name, fn);
return new (mem) Primitive(name, obj<AType>(), fn);
}
static Primitive * _make(obj<AAllocator> mm,
std::string_view name,
obj<AType> type,
Fn fn)
{
void * mem = mm.alloc_for<Primitive>();
return new (mem) Primitive(name, type, fn);
}
///@}
/** @defgroup scm-primitive-methods general methods **/
///@{
TypeDescr fn_td() const noexcept { return fn_td_; }
std::string_view name() const noexcept { return name_; }
static constexpr std::int32_t n_args() noexcept { return Traits::n_args; }
TypeDescr fn_td() const noexcept { return fn_td_; }
std::string_view name() const noexcept { return name_; }
bool is_nary() const noexcept { return false; }
obj<AGCObject> apply_nocheck(obj<ARuntimeContext> rcx, const DArray * args) {

View file

@ -5,6 +5,7 @@
#pragma once
#include <xo/stringtable2/StringTable.hpp>
#include <xo/alloc2/Allocator.hpp>
namespace xo {
@ -21,13 +22,16 @@ namespace xo {
using MemorySizeVisitor = xo::mm::MemorySizeVisitor;
public:
DSimpleRcx(obj<AAllocator> mm) : allocator_{mm} {}
DSimpleRcx(obj<AAllocator> mm, StringTable * st)
: allocator_{mm}, stringtable_{st} {}
obj<AAllocator> allocator() const noexcept { return allocator_; }
StringTable * stringtable() const noexcept { return stringtable_; }
void visit_pools(const MemorySizeVisitor & visitor) const;
private:
obj<AAllocator> allocator_;
StringTable * stringtable_ = nullptr;
};
} /*namespace scm*/

View file

@ -14,6 +14,7 @@
#pragma once
// includes (via {facet_includes})
#include <xo/stringtable2/StringTable.hpp>
#include <xo/alloc2/Allocator.hpp>
#include <xo/arena/MemorySizeInfo.hpp>
#include <xo/facet/obj.hpp>
@ -54,6 +55,8 @@ public:
virtual void _drop(Opaque d) const noexcept = 0;
/** default allocator to use for objects **/
virtual obj<AAllocator> allocator(Copaque data) const noexcept = 0;
/** stringtable for unique symbols **/
virtual StringTable * stringtable(Copaque data) const noexcept = 0;
/** invoke visitor for each distinct memory pool **/
virtual void visit_pools(Copaque data, MemorySizeVisitor visitor) const = 0;

View file

@ -61,6 +61,7 @@ namespace scm {
// const methods
[[noreturn]] obj<AAllocator> allocator(Copaque) const noexcept override { _fatal(); }
[[noreturn]] StringTable * stringtable(Copaque) const noexcept override { _fatal(); }
[[noreturn]] void visit_pools(Copaque, MemorySizeVisitor) const override { _fatal(); }
// nonconst methods

View file

@ -49,6 +49,8 @@ namespace xo {
// const methods
/** default allocator to use for objects **/
static obj<AAllocator> allocator(const DSimpleRcx & self) noexcept;
/** stringtable for unique symbols **/
static StringTable * stringtable(const DSimpleRcx & self) noexcept;
/** invoke visitor for each distinct memory pool **/
static void visit_pools(const DSimpleRcx & self, MemorySizeVisitor visitor);

View file

@ -13,6 +13,7 @@
#pragma once
#include <xo/stringtable2/StringTable.hpp>
#include <xo/alloc2/Allocator.hpp>
#include <xo/arena/MemorySizeInfo.hpp>
@ -49,6 +50,9 @@ namespace scm {
obj<AAllocator> allocator(Copaque data) const noexcept override {
return I::allocator(_dcast(data));
}
StringTable * stringtable(Copaque data) const noexcept override {
return I::stringtable(_dcast(data));
}
void visit_pools(Copaque data, MemorySizeVisitor visitor) const override {
return I::visit_pools(_dcast(data), visitor);
}

View file

@ -57,6 +57,9 @@ public:
obj<AAllocator> allocator() const noexcept {
return O::iface()->allocator(O::data());
}
StringTable * stringtable() const noexcept {
return O::iface()->stringtable(O::data());
}
void visit_pools(MemorySizeVisitor visitor) const {
return O::iface()->visit_pools(O::data(), visitor);
}

View file

@ -75,6 +75,8 @@ namespace xo {
auto cdr_list = obj<AGCObject,DList>::from(cdr);
//auto T = DTypeVarRef::_make(rcx.allocator(), "T");
return DList::cons(rcx.allocator(),
car,
cdr_list.data());

View file

@ -21,6 +21,12 @@ namespace xo {
return self.allocator();
}
auto
IRuntimeContext_DSimpleRcx::stringtable(const DSimpleRcx & self) noexcept -> StringTable *
{
return self.stringtable();
}
auto
IRuntimeContext_DSimpleRcx::visit_pools(const DSimpleRcx & self, MemorySizeVisitor visitor) -> void
{

View file

@ -6,12 +6,14 @@
#include <xo/procedure2/init_procedure2.hpp>
#include <xo/procedure2/DSimpleRcx.hpp>
#include <xo/procedure2/detail/IRuntimeContext_DSimpleRcx.hpp>
#include <xo/stringtable2/StringTable.hpp>
#include <xo/alloc2/arena/IAllocator_DArena.hpp>
#include <catch2/catch.hpp>
namespace xo {
using xo::scm::DSimpleRcx;
using xo::scm::ARuntimeContext;
using xo::scm::StringTable;
using xo::mm::AAllocator;
using xo::mm::DArena;
using xo::mm::ArenaConfig;
@ -30,12 +32,17 @@ namespace xo {
{
ArenaConfig cfg { .name_ = "testarena",
.size_ = 4*1024 };
DArena arena = DArena::map(cfg);
auto alloc = with_facet<AAllocator>::mkobj(&arena);
DSimpleRcx rcx(alloc);
auto stbl = StringTable(1024 /*hint_max_capacity*/,
false /*!debug_flag*/);
DSimpleRcx rcx(alloc, &stbl);
REQUIRE((void*)rcx.allocator().data() == (void*)alloc.data());
REQUIRE(rcx.stringtable() == &stbl);
}
TEST_CASE("DSimpleRcx-as-ARuntimeContext", "[procedure2][DSimpleRcx]")
@ -44,8 +51,10 @@ namespace xo {
.size_ = 4*1024 };
DArena arena = DArena::map(cfg);
auto alloc = with_facet<AAllocator>::mkobj(&arena);
auto stbl = StringTable(1024 /*hint_max_capacity*/,
false /*!debug_flag*/);
DSimpleRcx rcx(alloc);
DSimpleRcx rcx(alloc, &stbl);
obj<ARuntimeContext> rcx_obj = with_facet<ARuntimeContext>::mkobj(&rcx);
// verify we can recover allocator from obj<ARuntimeContext>

View file

@ -88,6 +88,7 @@ namespace xo {
bool debug_flag() const noexcept { return debug_flag_; }
ParserStack * stack() const noexcept { return stack_; }
obj<AAllocator> expr_alloc() const noexcept { return expr_alloc_; }
StringTable * stringtable() noexcept { return &stringtable_; }
DGlobalSymtab * global_symtab() const noexcept { return global_symtab_.data(); }
DLocalSymtab * local_symtab() const noexcept { return local_symtab_; }
DGlobalEnv * global_env() const noexcept { return global_env_.data(); }

View file

@ -185,6 +185,7 @@ namespace xo {
DGlobalSymtab * global_symtab() const noexcept;
DGlobalEnv * global_env() const noexcept;
StringTable * stringtable() noexcept { return psm_.stringtable(); }
bool debug_flag() const { return debug_flag_; }

View file

@ -60,6 +60,9 @@ namespace xo {
/** top-level global environment (e.g. contains built-in primitives) **/
DGlobalEnv * global_env() const noexcept;
/** global unique-string table **/
StringTable * stringtable() noexcept;
/** visit reader-owned memory pools; call visitor(info) for each.
* Specifically exclude expr_alloc, since we don't consider
* that reader-owned

View file

@ -38,6 +38,12 @@ namespace xo {
return parser_.global_env();
}
StringTable *
SchematikaReader::stringtable() noexcept
{
return parser_.stringtable();
}
void
SchematikaReader::visit_pools(const MemorySizeVisitor & visitor) const
{

View file

@ -27,6 +27,7 @@ namespace xo {
using size_type = StringMap::size_type;
public:
/** hint_max_capacity in bytes = capacity for strings **/
StringTable(size_type hint_max_capacity,
bool debug_flag = false);