xo-interpreter2 stack: refactor + bugfix operator expr

This commit is contained in:
Roland Conybeare 2026-03-12 20:26:08 -05:00
commit 6c7216ed7d
7 changed files with 195 additions and 200 deletions

View file

@ -55,6 +55,18 @@ namespace xo {
}
/** @brief Schematika primitive with fixed number of arguments
*
* Distinction between type-constructor (@ref type_) and
* type-description (@ref fn_td_): type-constructor is narrower;
* it may lift into schematika type system some information about function
* behavior. For example
* @pre
* cons :: (T x list<T>) -> list<T>
* @endpre
* but implementation has signature:
* @pre
* (obj<AGCobject> x obj<AGCObject,DList>) -> obj<AGCObject,DList>
* @endpre
**/
template <typename Fn>
class Primitive {
@ -70,13 +82,28 @@ namespace xo {
using ppindentinfo = xo::print::ppindentinfo;
public:
Primitive(std::string_view name, Fn fn) : name_{name},
fn_td_{Reflect::require<Fn>()},
fn_{fn} {}
/** @defgroup scm-primitive-ctors constructors **/
///@{
Primitive(std::string_view name, Fn fn)
: name_{name},
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);
}
///@}
/** @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; }
bool is_nary() const noexcept { return false; }
@ -86,6 +113,7 @@ namespace xo {
std::make_index_sequence<Traits::n_args>{});
}
///@}
/** @defgroup scm-primitive-printable-facet **/
///@{
@ -166,8 +194,12 @@ namespace xo {
template <typename Fn>
std::size_t
Primitive<Fn>::forward_children(obj<ACollector>) noexcept {
// Primitive holds no GC refs (just string_view + function pointer)
Primitive<Fn>::forward_children(obj<ACollector> gc) noexcept {
{
auto e = type_.to_facet<AGCObject>(); // FacetRegistry dep
gc.forward_inplace(e.iface(), (void **)&(type_.data_));
}
return this->shallow_size();
}

View file

@ -0,0 +1,89 @@
/** @file PrimitiveRegistry.hpp
*
* @author Roland Conybeare, Mar 2026
**/
#pragma once
#include "Procedure.hpp"
#include <xo/alloc2/Allocator.hpp>
#include <xo/reflect/TypeDescr.hpp>
#include <functional>
namespace xo {
namespace scm {
/** partition primitives based on scope.
* Each primitive associates with exactly one flag value.
* Flags also operate as bitmasks when calling
* @ref PrimitiveRegistry::install_primitives()
**/
enum class InstallFlags {
f_none = 0x0,
/** mandatory primitives, necessary for operator support,
* e.g. _add needed to implement infix +
**/
f_essential = 0x1,
f_generalpurpose = 0x2,
/** all primitives **/
f_all = f_essential | f_generalpurpose,
};
inline InstallFlags operator&(InstallFlags x, InstallFlags y) {
return InstallFlags(static_cast<uint64_t>(x) & static_cast<uint64_t>(y));
}
/** provided by VSM to receive created primitives.
* InstallSink(pm) adopts a primitive
**/
using InstallSink = std::function<bool (std::string_view name,
xo::reflect::TypeDescr fn_td,
obj<AProcedure> pm,
InstallFlags flags)>;
/** @class PrimitiveRegistry
*
* @brief Runtime registry for primitives
*
* Singleton to remember setup code for known primitives.
* Use to gather primitives for installation in global
* environment for a virtual schematika machine (VSM)
**/
class PrimitiveRegistry {
public:
using AAllocator = xo::mm::AAllocator;
/** provided by a subsystem that provides primitives.
* Allocates primitives using memory from mm, delivering them
* to InstallSink sink.
**/
using InstallSource = std::function<bool (obj<AAllocator> mm,
InstallSink sink,
InstallFlags flags)>;
public:
/** singleton instance **/
static PrimitiveRegistry & instance();
/** remember primitive-factory @p source_fn **/
void register_primitives(InstallSource source_fn);
/** create primitives using memory from @p mm,
* delivering each primitive to @p sink.
**/
bool install_primitives(obj<AAllocator> mm,
InstallSink sink,
InstallFlags flags);
private:
/** a set of factories that create primitives **/
std::vector<InstallSource> init_seq_v_;
};
} /*namespace scm*/
} /*namespace xo*/
/* end PrimitiveRegistry.hpp */

View file

@ -0,0 +1,18 @@
/** @file procedure2_register_primitives.hpp
*
* @author Roland Conybeare, Mar 2026
**/
#pragma once
#include "PrimitiveRegistry.hpp"
#include <xo/alloc2/Collector.hpp>
namespace xo {
namespace scm {
/** Register gc-aware (AGCObject,DRepr) combinations with garbage collector @p gc **/
bool procedure2_register_primitives(obj<xo::mm::AAllocator> gc, InstallSink sink);
}
}
/* end procedure2_register_primitives.hpp */