git subrepo clone (merge) git@github.com:Rconybea/xo-interpreter2.git xo-interpreter2

subrepo:
  subdir:   "xo-interpreter2"
  merged:   "e4c6ff57"
upstream:
  origin:   "git@github.com:Rconybea/xo-interpreter2.git"
  branch:   "main"
  commit:   "e4c6ff57"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
This commit is contained in:
Roland Conybeare 2026-06-06 22:13:05 -04:00
commit 7f4b4e7cbd
112 changed files with 6831 additions and 0 deletions

12
xo-interpreter2/.gitrepo Normal file
View file

@ -0,0 +1,12 @@
; DO NOT EDIT (unless you know what you are doing)
;
; This subdirectory is a git "subrepo", and this file is maintained by the
; git-subrepo command. See https://github.com/ingydotnet/git-subrepo#readme
;
[subrepo]
remote = git@github.com:Rconybea/xo-interpreter2.git
branch = main
commit = e4c6ff5739a2a97d2c470630da63541196a1cc08
parent = d11f6ca5977b1f6b79b201652ce37e631f6d48ba
method = merge
cmdver = 0.4.9

View file

@ -0,0 +1,198 @@
# xo-interpreter2/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(xo_interpreter2 VERSION 1.0)
enable_language(CXX)
include(GNUInstallDirs)
include(cmake/xo-bootstrap-macros.cmake)
xo_cxx_toplevel_options3()
# ----------------------------------------------------------------
# c++ settings
# one-time project-specific c++ flags. usually empty
set(PROJECT_CXX_FLAGS "")
add_definitions(${PROJECT_CXX_FLAGS})
# ----------------------------------------------------------------
# output targets
add_subdirectory(src/interpreter2)
add_subdirectory(src/skrepl)
add_subdirectory(utest)
# ----------------------------------------------------------------
# only supporting forward_children(), for virtual root.
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-gcobject-virtualschematikamachine
FACET_PKG xo_alloc2
INPUT idl/IGCObject_DVirtualSchematikaMachine.json5
)
# ----------------------------------------------------------------
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-gcobject-vsmdefcontframe
FACET_PKG xo_alloc2
INPUT idl/IGCObject_DVsmDefContFrame.json5
)
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-printable-vsmdefcontframe
FACET_PKG xo_printable2
INPUT idl/IPrintable_DVsmDefContFrame.json5
)
# ----------------------------------------------------------------
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-gcobject-vsmapplyframe
FACET_PKG xo_alloc2
INPUT idl/IGCObject_DVsmApplyFrame.json5
)
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-printable-vsmapplyframe
FACET_PKG xo_printable2
INPUT idl/IPrintable_DVsmApplyFrame.json5
)
# ----------------------------------------------------------------
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-gcobject-vsmevalargsframe
FACET_PKG xo_alloc2
INPUT idl/IGCObject_DVsmEvalArgsFrame.json5
)
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-printable-vsmevalargsframe
FACET_PKG xo_printable2
INPUT idl/IPrintable_DVsmEvalArgsFrame.json5
)
# ----------------------------------------------------------------
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-gcobject-vsmapplyclosureframe
FACET_PKG xo_alloc2
INPUT idl/IGCObject_DVsmApplyClosureFrame.json5
)
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-printable-vsmapplyclosureframe
FACET_PKG xo_printable2
INPUT idl/IPrintable_DVsmApplyClosureFrame.json5
)
# ----------------------------------------------------------------
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-gcobject-vsmifelsecontframe
FACET_PKG xo_alloc2
INPUT idl/IGCObject_DVsmIfElseContFrame.json5
)
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-printable-vsmifelsecontframe
FACET_PKG xo_printable2
INPUT idl/IPrintable_DVsmIfElseContFrame.json5
)
# ----------------------------------------------------------------
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-gcobject-vsmseqcontframe
FACET_PKG xo_alloc2
INPUT idl/IGCObject_DVsmSeqContFrame.json5
)
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-printable-vsmseqcontframe
FACET_PKG xo_printable2
INPUT idl/IPrintable_DVsmSeqContFrame.json5
)
# ----------------------------------------------------------------
# note: manual target; generated code committed to git
#
#xo_add_genfacetimpl(
# TARGET xo-interpreter2-facetimpl-procedure-closure
# FACET_PKG xo_procedure2
# REPR Closure
# INPUT idl/IProcedure_DClosure.json5
#)
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-gcobject-closure
FACET_PKG xo_alloc2
INPUT idl/IGCObject_DClosure.json5
)
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-printable-closure
FACET_PKG xo_printable2
INPUT idl/IPrintable_DClosure.json5
)
# ----------------------------------------------------------------
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-gcobject-localenv
FACET_PKG xo_alloc2
INPUT idl/IGCObject_DLocalEnv.json5
)
# note: manual target; generated code committed to git
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-printable-localenv
FACET_PKG xo_printable2
INPUT idl/IPrintable_DLocalEnv.json5
)
# ----------------------------------------------------------------
xo_add_genfacetimpl(
TARGET xo-interpreter2-facetimpl-runtimecontext-vsmrcx
FACET_PKG xo_procedure2
INPUT idl/IRuntimeContext_DVsmRcx.json5
)
# ----------------------------------------------------------------
xo_add_genfacet_all(xo-interpreter2-genfacet-all)
# ----------------------------------------------------------------
# cmake helper (for external xo-interpreter2 users)
xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets)
# ----------------------------------------------------------------
# input dependencies
#
# NOTE: dependency set here must be kept consistent with
# xo-interpreter2/cmake/xo_interpreter2Config.cmake.in
#xo_headeronly_dependency(${SELF_LIB} xo_flatstring)
# end CMakeLists.txt

View file

@ -0,0 +1 @@
# xo-interpreter2

View file

@ -0,0 +1,33 @@
# ----------------------------------------------------------------
# for example:
# $ PREFIX=/usr/local # for example
# $ cmake -DCMAKE_MODULE_PATH=prefix -DCMAKE_INSTALL_PREFIX=$PREFIX -B .build
#
# will get
# CMAKE_MODULE_PATH
# from xo-cmake-config --cmake-module-path
#
# and expect .cmake macros in
# CMAKE_MODULE_PATH/xo_macros/xo_cxx.cmake
# ----------------------------------------------------------------
find_program(XO_CMAKE_CONFIG_EXECUTABLE NAMES xo-cmake-config REQUIRED)
if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL "prefix"))
message(FATAL "could not find xo-cmake-config executable")
endif()
if (NOT XO_SUBMODULE_BUILD)
if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL prefix))
# default to typical install location for xo-project-macros
execute_process(COMMAND ${XO_CMAKE_CONFIG_EXECUTABLE} --cmake-module-path OUTPUT_VARIABLE CMAKE_MODULE_PATH)
message(STATUS "CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}")
endif()
endif()
# needs to have been installed somewhere on CMAKE_MODULE_PATH,
# (e.g. from xo-cmake with the same value for CMAKE_INSTALL_PREFIX)
#
include(xo_macros/xo_cxx)
xo_cxx_bootstrap_message()

View file

@ -0,0 +1,14 @@
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
# note: changes to find_dependency() calls here
# must coordinate with xo_dependency() calls
# in CMakeLists.txt
#
find_dependency(xo_reader2)
find_dependency(xo_gc)
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Share.cmake")
check_required_components("@PROJECT_NAME@")

View file

@ -0,0 +1,18 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "detail",
includes: [
"<xo/alloc2/GCObject.hpp>",
"<xo/alloc2/Allocator.hpp>"
],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/GCObject.json5",
brief: "provide AGCObject interface for Closure",
using_doxygen: true,
repr: "DClosure",
doc: [ "implement AGCObject for DClosure" ],
}

View file

@ -0,0 +1,18 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2/facet",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "env",
includes: [
"<xo/alloc2/GCObject.hpp>",
"<xo/alloc2/Allocator.hpp>"
],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/GCObject.json5",
brief: "provide AGCObject interface for LocalEnv",
using_doxygen: true,
repr: "DLocalEnv",
doc: [ "implement AGCObject for DLocalEnv" ],
}

View file

@ -0,0 +1,18 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2/facet",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "vsm",
includes: [
"<xo/alloc2/GCObject.hpp>",
"<xo/alloc2/Allocator.hpp>"
],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/GCObject.json5",
brief: "provide AGCObject interface for DVirtualSchematikaMachine",
using_doxygen: true,
repr: "DVirtualSchematikaMachine",
doc: [ "implement AGCObject for DVirtualSchematikaMachine" ],
}

View file

@ -0,0 +1,18 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "detail",
includes: [
"<xo/alloc2/GCObject.hpp>",
"<xo/alloc2/Allocator.hpp>"
],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/GCObject.json5",
brief: "provide AGCObject interface for DVsmApplyClosureFrame",
using_doxygen: true,
repr: "DVsmApplyClosureFrame",
doc: [ "implement AGCObject for DVsmApplyClosureFrame" ],
}

View file

@ -0,0 +1,18 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "detail",
includes: [
"<xo/alloc2/GCObject.hpp>",
"<xo/alloc2/Allocator.hpp>"
],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/GCObject.json5",
brief: "provide AGCObject interface for DVsmApplyFrame",
using_doxygen: true,
repr: "DVsmApplyFrame",
doc: [ "implement AGCObject for DVsmApplyFrame" ],
}

View file

@ -0,0 +1,18 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "define",
includes: [
"<xo/alloc2/GCObject.hpp>",
"<xo/alloc2/Allocator.hpp>"
],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/GCObject.json5",
brief: "provide AGCObject interface for DVsmDefContFrame",
using_doxygen: true,
repr: "DVsmDefContFrame",
doc: [ "implement AGCObject for DVsmDefContFrame" ],
}

View file

@ -0,0 +1,18 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "detail",
includes: [
"<xo/alloc2/GCObject.hpp>",
"<xo/alloc2/Allocator.hpp>"
],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/GCObject.json5",
brief: "provide AGCObject interface for DVsmEvalArgsFrame",
using_doxygen: true,
repr: "DVsmEvalArgsFrame",
doc: [ "implement AGCObject for DVsmEvalArgsFrame" ],
}

View file

@ -0,0 +1,18 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "ifelse",
includes: [
"<xo/alloc2/GCObject.hpp>",
"<xo/alloc2/Allocator.hpp>"
],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/GCObject.json5",
brief: "provide AGCObject interface for DVsmIfElseContFrame",
using_doxygen: true,
repr: "DVsmIfElseContFrame",
doc: [ "implement AGCObject for DVsmIfElseContFrame" ],
}

View file

@ -0,0 +1,18 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "sequence",
includes: [
"<xo/alloc2/GCObject.hpp>",
"<xo/alloc2/Allocator.hpp>"
],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/GCObject.json5",
brief: "provide AGCObject interface for DVsmSeqContFrame",
using_doxygen: true,
repr: "DVsmSeqContFrame",
doc: [ "implement AGCObject for DVsmSeqContFrame" ],
}

View file

@ -0,0 +1,16 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "detail",
includes: [ "<xo/printable2/Printable.hpp>",
"<xo/printable2/detail/IPrintable_Xfer.hpp>" ],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/Printable.json5",
brief: "provide APrintable interface for DClosure",
using_doxygen: true,
repr: "DClosure",
doc: [ "implement APrintable for DClosure" ],
}

View file

@ -0,0 +1,16 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "env",
includes: [ "<xo/printable2/Printable.hpp>",
"<xo/printable2/detail/IPrintable_Xfer.hpp>" ],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/Printable.json5",
brief: "provide APrintable interface for DLocalEnv",
using_doxygen: true,
repr: "DLocalEnv",
doc: [ "implement APrintable for DLocalEnv" ],
}

View file

@ -0,0 +1,16 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "detail",
includes: [ "<xo/printable2/Printable.hpp>",
"<xo/printable2/detail/IPrintable_Xfer.hpp>" ],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/Printable.json5",
brief: "provide APrintable interface for DVsmApplyClosureFrame",
using_doxygen: true,
repr: "DVsmApplyClosureFrame",
doc: [ "implement APrintable for DVsmApplyClosureFrame" ],
}

View file

@ -0,0 +1,16 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "detail",
includes: [ "<xo/printable2/Printable.hpp>",
"<xo/printable2/detail/IPrintable_Xfer.hpp>" ],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/Printable.json5",
brief: "provide APrintable interface for DVsmApplyFrame",
using_doxygen: true,
repr: "DVsmApplyFrame",
doc: [ "implement APrintable for DVsmApplyFrame" ],
}

View file

@ -0,0 +1,16 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "define",
includes: [ "<xo/printable2/Printable.hpp>",
"<xo/printable2/detail/IPrintable_Xfer.hpp>" ],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/Printable.json5",
brief: "provide APrintable interface for DVsmDefContFrame",
using_doxygen: true,
repr: "DVsmDefContFrame",
doc: [ "implement APrintable for DVsmDefContFrame" ],
}

View file

@ -0,0 +1,16 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "detail",
includes: [ "<xo/printable2/Printable.hpp>",
"<xo/printable2/detail/IPrintable_Xfer.hpp>" ],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/Printable.json5",
brief: "provide APrintable interface for DVsmEvalArgsFrame",
using_doxygen: true,
repr: "DVsmEvalArgsFrame",
doc: [ "implement APrintable for DVsmEvalArgsFrame" ],
}

View file

@ -0,0 +1,16 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "ifelse",
includes: [ "<xo/printable2/Printable.hpp>",
"<xo/printable2/detail/IPrintable_Xfer.hpp>" ],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/Printable.json5",
brief: "provide APrintable interface for DVsmIfElseContFrame",
using_doxygen: true,
repr: "DVsmIfElseContFrame",
doc: [ "implement APrintable for DVsmIfElseContFrame" ],
}

View file

@ -0,0 +1,16 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "sequence",
includes: [ "<xo/printable2/Printable.hpp>",
"<xo/printable2/detail/IPrintable_Xfer.hpp>" ],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/Printable.json5",
brief: "provide APrintable interface for DVsmSeqContFrame",
using_doxygen: true,
repr: "DVsmSeqContFrame",
doc: [ "implement APrintable for DVsmSeqContFrame" ],
}

View file

@ -0,0 +1,19 @@
{
mode: "implementation",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "detail",
includes: [
"<xo/procedure2/RuntimeContext.hpp>",
"<xo/procedure2/detail/IRuntimeContext_Xfer.hpp>",
"<xo/procedure2/Procedure.hpp>",
"<xo/procedure2/detail/IProcedure_Xfer.hpp>",
],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/Procedure.json5",
brief: "provide AProcedure interface for DClosure",
using_doxygen: true,
repr: "DClosure",
doc: [ "implement AProcedure for DClosure" ],
}

View file

@ -0,0 +1,18 @@
{
mode: "implementation",
output_cpp_dir: "src/interpreter2",
output_hpp_dir: "include/xo/interpreter2",
output_impl_subdir: "detail",
includes: [
//"<xo/procedure2/RuntimeContext.hpp>",
//"<xo/procedure2/detail/IRuntimeContext_Xfer.hpp>",
],
local_types: [ ],
namespace1: "xo",
namespace2: "scm",
facet_idl: "idl/RuntimeContext.json5",
brief: "provide ARuntimeContext interface for DVsmRcx",
using_doxygen: true,
repr: "DVsmRcx",
doc: [ "implement ARuntimeContext for DVsmRcx" ],
}

View file

@ -0,0 +1,13 @@
/** @file Closure.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include "DClosure.hpp"
//#include "detail/IProcedure_DClosure.hpp"
#include "detail/IGCObject_DClosure.hpp"
#include "detail/IPrintable_DClosure.hpp"
/* end Closure.hpp */

View file

@ -0,0 +1,20 @@
/** @file DApplyFrame.hpp
*
* @author Roland Conyberae, Feb 2026
**/
#pragma once
namespace xo {
namespace scm {
/** In virtual schematika machine (VSM):
* stack frame for interpreted apply expression
* (@ref DApplyExpr)
**/
class DApplyFrame {
obj<AGCObject>
};
}
}
/* end DApplyFrame.hpp */

View file

@ -0,0 +1,84 @@
/** @file DClosure.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include "LocalEnv.hpp"
#include <xo/expression2/LambdaExpr.hpp>
#include <xo/procedure2/RuntimeContext.hpp>
namespace xo {
namespace scm {
/** @brief runtime representation for a procedure
*
* Maintains lambda + captured lexical context
**/
class DClosure {
public:
using ARuntimeContext = xo::scm::ARuntimeContext;
using AGCObject = xo::mm::AGCObject;
using AGCObjectVisitor = xo::mm::AGCObjectVisitor;
using VisitReason = xo::mm::VisitReason;
using AAllocator = xo::mm::AAllocator;
using ppindentinfo = xo::print::ppindentinfo;
using size_type = std::int32_t;
public:
DClosure(const DLambdaExpr * lm,
const DLocalEnv * env);
/** create instance using memory from @p mm
* for lambda @p lm with captured environment @p env.
**/
static DClosure * make(obj<AAllocator> mm,
const DLambdaExpr * lm,
const DLocalEnv * env);
/** @defgroup scm-closure-general-methods **/
///@{
const DLambdaExpr * lambda() const noexcept { return lambda_; }
const DLocalEnv * env() const noexcept { return env_; }
///@}
/** @defgroup scm-closure-procedure-facet **/
///@{
/** for now, support just fixed-arity procedures **/
bool is_nary() const noexcept { return false; }
/** number of arguments expected by this procedure (-1 if nary) **/
size_type n_args() const noexcept { return lambda_->n_args(); }
obj<AGCObject> apply_nocheck(obj<ARuntimeContext> rcx, const DArray * args);
///@}
/** @defgroup scm-closure-gcobject-facet **/
///@{
DClosure * gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept;
void visit_gco_children(VisitReason reason, obj<AGCObjectVisitor> gc) noexcept;
///@}
/** @defgroup scm-closure-printable-facet **/
///@{
bool pretty(const ppindentinfo & ppii) const;
///@}
private:
/** lambda expression **/
const DLambdaExpr * lambda_ = nullptr;
/** bindings for captured variables
* (from lexical context where lambda evaluated)
**/
const DLocalEnv * env_ = nullptr;
};
} /*namespace scm*/
} /*namespace xo*/
/* end DClosure.hpp */

View file

@ -0,0 +1,84 @@
/** @file DLocalEnv.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include <xo/expression2/LocalSymtab.hpp>
#include <xo/object2/DArray.hpp>
namespace xo {
namespace scm {
/** @brief runtime bindings for arguments to a lambda
**/
class DLocalEnv {
public:
using DArray = xo::scm::DArray;
using ACollector = xo::mm::ACollector;
using AGCObject = xo::mm::AGCObject;
using AGCObjectVisitor = xo::mm::AGCObjectVisitor;
using VisitReason = xo::mm::VisitReason;
using AAllocator = xo::mm::AAllocator;
using ppindentinfo = xo::print::ppindentinfo;
using size_type = std::uint32_t;
public:
/** @defgroup scm-localenv-constructors constructors **/
///@{
/** create instance with parent @p p for variables in @p symtab **/
DLocalEnv(DLocalEnv * parent,
DLocalSymtab * symtab,
DArray * args);
static DLocalEnv * _make(obj<AAllocator> mm,
DLocalEnv * parent,
DLocalSymtab * symtab,
DArray * args);
///@}
/** @defgroup scm-localenv-methods methods **/
///@{
DLocalEnv * parent() const noexcept { return parent_; }
size_type n_vars() const noexcept { return symtab_->n_vars(); }
size_type n_types() const noexcept { return symtab_->n_types(); }
/** lookup current value associated with binding @p ix **/
obj<AGCObject> lookup_value(Binding ix) const noexcept;
/** assign value associated with binding @p ix to @p x **/
void assign_value(obj<AAllocator> mm, Binding ix, obj<AGCObject> x);
///@}
/** @defgroup scm-localenv-gcobject-facet **/
///@{
DLocalEnv * gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept;
void visit_gco_children(VisitReason reason, obj<AGCObjectVisitor> gc) noexcept;
///@}
/** @defgroup scm-localenv-printable-facet **/
///@{
bool pretty(const ppindentinfo & ppii) const noexcept;
///@}
private:
/** parent environment (from closure) **/
DLocalEnv * parent_ = nullptr;
/** bind values for variables in this symbol table **/
DLocalSymtab * symtab_ = nullptr;
/** bindings.
* (*args)[i] associates a value with symtab->slots_[i]
**/
DArray * args_ = nullptr;
};
} /*namespace scm*/
} /*namespace xo*/
/* end DLocalEnv.hpp */

View file

@ -0,0 +1,64 @@
/** @file DVsmApplyClosureFrame.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include "VsmInstr.hpp"
#include "DLocalEnv.hpp"
#include <xo/expression2/DApplyExpr.hpp>
namespace xo {
namespace scm {
/** Frame to preserve VSM registers:
* (stack_, parent_, cont_)
* while applying a closure.
**/
class DVsmApplyClosureFrame {
public:
using ACollector = xo::mm::ACollector;
using AGCObject = xo::mm::AGCObject;
using AGCObjectVisitor = xo::mm::AGCObjectVisitor;
using VisitReason = xo::mm::VisitReason;
using AAllocator = xo::mm::AAllocator;
using ppindentinfo = xo::print::ppindentinfo;
public:
DVsmApplyClosureFrame(obj<AGCObject> stack,
VsmInstr cont,
DLocalEnv * env);
/** create instance, using memory from @p mm **/
static DVsmApplyClosureFrame * make(obj<AAllocator> mm,
obj<AGCObject> parent,
VsmInstr cont,
DLocalEnv * env);
obj<AGCObject> parent() 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 * gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept;
void visit_gco_children(VisitReason reason, obj<AGCObjectVisitor> gc) noexcept;
/** pretty-printing support **/
bool pretty(const ppindentinfo & ppii) const;
protected:
/** saved VSM stack_ register **/
obj<AGCObject> stack_;
/** saved VSM cont_ register **/
VsmInstr cont_;
/** saved VSM local_env_ register **/
DLocalEnv * local_env_ = nullptr;
};
} /*namespace scm*/
} /*namespace xo*/
/* end DVsmApplyClosureFrame.hpp */

View file

@ -0,0 +1,69 @@
/** @file DVsmApplyFrame.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include "VsmInstr.hpp"
#include <xo/procedure2/Procedure.hpp>
#include <xo/object2/DArray.hpp>
namespace xo {
namespace scm {
class DVsmApplyFrame {
public:
using AProcedure = xo::scm::AProcedure;
using AGCObject = xo::mm::AGCObject;
using AGCObjectVisitor = xo::mm::AGCObjectVisitor;
using VisitReason = xo::mm::VisitReason;
using AAllocator = xo::mm::AAllocator;
using ppindentinfo = xo::print::ppindentinfo;
public:
DVsmApplyFrame(obj<AGCObject> old_parent,
VsmInstr old_cont,
DArray * args);
/** create instance using memory from @p mm **/
static DVsmApplyFrame * make(obj<AAllocator> mm,
obj<AGCObject> old_parent,
VsmInstr old_cont,
DArray * args);
obj<AGCObject> parent() const noexcept { return parent_; }
VsmInstr cont() const noexcept { return cont_; }
obj<AGCObject> fn() const noexcept { return fn_; }
DArray * args() const noexcept { return args_; }
void assign_fn(obj<AGCObject> x) { this->fn_ = x; }
DVsmApplyFrame * gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept;
void visit_gco_children(VisitReason reason, obj<AGCObjectVisitor> gc) noexcept;
/** pretty-printing support **/
bool pretty(const ppindentinfo & ppii) const;
private:
/** saved VSM stack; restore when this frame consumed **/
obj<AGCObject> parent_;
/** saved continuation; restore when this frame consumed **/
VsmInstr cont_;
/** evaluated target procedure.
*
* note: when initially created, this will be unpopulated;
* don't know correct value until we evaluate
* expression in head position.
*
* Must exhibit either:
* 1. AProcedure facet (runs natively)
* 2. AVsmProcedure facet (requires schematika runtime)
**/
obj<AGCObject> fn_;
/** evaluated arguments (to target procedure) **/
DArray * args_;
};
} /*namespace scm*/
} /*namespace xo*/
/* end DVsmApplyFrame.hpp */

View file

@ -0,0 +1,82 @@
/** @file DVsmDefContFrame.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include "VsmInstr.hpp"
#include <xo/expression2/DefineExpr.hpp>
#include <xo/alloc2/GCObject.hpp>
namespace xo {
namespace scm {
/** @brief saved VSM state during evaluation of a SequenceExpr
**/
class DVsmDefContFrame {
public:
using AGCObjectVisitor = xo::mm::AGCObjectVisitor;
using VisitReason = xo::mm::VisitReason;
using AAllocator = xo::mm::AAllocator;
using AGCObject = xo::mm::AGCObject;
using ppindentinfo = xo::print::ppindentinfo;
public:
/** @defgroup scm-vsmdefcontframe-ctors constructors **/
///@{
DVsmDefContFrame(obj<AGCObject> parent,
VsmInstr cont,
DDefineExpr * def_expr);
/** create instance using memory from allocator @p mm **/
static DVsmDefContFrame * make(obj<AAllocator> mm,
obj<AGCObject> parent_stack,
VsmInstr cont,
DDefineExpr * def_expr);
///@}
/** @defgroup scm-vsmdefcontframe-access-methods access methods **/
///@{
obj<AGCObject> parent() const noexcept { return parent_; }
VsmInstr cont() const noexcept { return cont_; }
DDefineExpr * def_expr() const noexcept { return def_expr_; }
///@}
/** @defgroup scm-vsmdefcontframe-general-methods general methods **/
///@{
///@}
/** @defgroup scm-vsmdefcontframe-gcobject-facet gcobject facet **/
///@{
DVsmDefContFrame * gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept;
void visit_gco_children(VisitReason reason, obj<AGCObjectVisitor> gc) noexcept;
///@}
/** @defgrouop scm-vsmseqcontframe-printable-facet printable facet **/
///@{
bool pretty(const ppindentinfo & ppii) const noexcept;
///@}
private:
/** @defgroup scm-vsmdefcontframe-members member variables **/
///@{
/** saved VSM stack; restore when this frame consumed **/
obj<AGCObject> parent_;
/** saved continuation; restore when this frame consumed **/
VsmInstr cont_;
/** saved expr. evaluate elements of this sequence in order **/
DDefineExpr * def_expr_ = nullptr;
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end DVsmDefContFrame.hpp */

View file

@ -0,0 +1,67 @@
/** @file DVsmEvalArgsFrame.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include "VsmApplyFrame.hpp"
#include <xo/expression2/DApplyExpr.hpp>
namespace xo {
namespace scm {
/** frame for executing an apply expression **/
class DVsmEvalArgsFrame {
public:
using AGCObject = xo::mm::AGCObject;
using AGCObjectVisitor = xo::mm::AGCObjectVisitor;
using VisitReason = xo::mm::VisitReason;
using AAllocator = xo::mm::AAllocator;
using ppindentinfo = xo::print::ppindentinfo;
public:
/** see picture in VirtualSchematikaMachine._do_eval_apply_op()
*
* old_parent = [apply frame]
* old_cont = [xfer to called function]
*
**/
DVsmEvalArgsFrame(DVsmApplyFrame * parent,
VsmInstr cont,
DApplyExpr * apply_expr);
static DVsmEvalArgsFrame * make(obj<AAllocator> mm,
DVsmApplyFrame * apply_frame,
VsmInstr old_cont,
DApplyExpr * apply_expr);
DVsmApplyFrame * parent() const noexcept { return parent_; }
VsmInstr cont() const noexcept { return cont_; }
const DApplyExpr * apply_expr() const noexcept { return apply_expr_; }
int32_t i_arg() const noexcept { return i_arg_; }
int32_t increment_arg() { return ++i_arg_; }
DVsmEvalArgsFrame * gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept;
void visit_gco_children(VisitReason reason, obj<AGCObjectVisitor> gc) noexcept;
bool pretty(const ppindentinfo & ppii) const;
protected:
/** parent stack frame **/
DVsmApplyFrame * parent_ = nullptr;
/** continuation after eval args completed (always VsmInstr::c_apply) **/
VsmInstr cont_;
/** expression being evaluated **/
DApplyExpr * apply_expr_ = nullptr;
/** next argument to be evaluated. -1 means function head **/
int32_t i_arg_ = -1;
};
} /*namespace scm*/
} /*namespace xo*/
/* end DVsmEvalArgsFrame.hpp */

View file

@ -0,0 +1,82 @@
/** @file DVsmIfElseContFrame.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include "VsmInstr.hpp"
#include <xo/expression2/IfElseExpr.hpp>
#include <xo/alloc2/GCObject.hpp>
namespace xo {
namespace scm {
/** @brief saved VSM state during evaluation of a SequenceExpr
**/
class DVsmIfElseContFrame {
public:
using AGCObjectVisitor = xo::mm::AGCObjectVisitor;
using AGCObject = xo::mm::AGCObject;
using VisitReason = xo::mm::VisitReason;
using AAllocator = xo::mm::AAllocator;
using ppindentinfo = xo::print::ppindentinfo;
public:
/** @defgroup scm-vsmevalsequenceframe-ctors constructors **/
///@{
DVsmIfElseContFrame(obj<AGCObject> parent,
VsmInstr cont,
DIfElseExpr * ifelse_expr);
/** create instance using memory from allocator @p mm **/
static DVsmIfElseContFrame * make(obj<AAllocator> mm,
obj<AGCObject> parent,
VsmInstr cont,
DIfElseExpr * ifelse_expr);
///@}
/** @defgroup scm-vsmevalsequenceframe-access-methods access methods **/
///@{
obj<AGCObject> parent() const noexcept { return parent_; }
VsmInstr cont() const noexcept { return cont_; }
DIfElseExpr * ifelse_expr() const noexcept { return ifelse_expr_; }
///@}
/** @defgroup scm-vsmevalsequenceframe-general-methods general methods **/
///@{
///@}
/** @defgroup scm-vsmevalsequenceframe-gcobject-facet gcobject facet **/
///@{
DVsmIfElseContFrame * gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept;
void visit_gco_children(VisitReason reason, obj<AGCObjectVisitor> gc) noexcept;
///@}
/** @defgrouop scm-vsmseqcontframe-printable-facet printable facet **/
///@{
bool pretty(const ppindentinfo & ppii) const noexcept;
///@}
private:
/** @defgroup scm-vsmevalsequenceframe-members member variables **/
///@{
/** saved VSM stack; restore when this frame consumed **/
obj<AGCObject> parent_;
/** saved continuation; restore when this frame consumed **/
VsmInstr cont_;
/** saved expr. evaluate elements of this sequence in order **/
DIfElseExpr * ifelse_expr_ = nullptr;
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end DVsmIfElseContFrame.hpp */

View file

@ -0,0 +1,44 @@
/** @file DVsmRcx.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include <xo/stringtable2/StringTable.hpp>
#include <xo/alloc2/Allocator.hpp>
#include <xo/arena/MemorySizeInfo.hpp>
namespace xo {
namespace scm {
// see xo-interpreter/ VirtualSchematikaMachine.hpp
class DVirtualSchematikaMachine;
/** @brief Runtime context for schematika interpreter
*
* Provides allocator
**/
class DVsmRcx {
public:
using StringTable = xo::scm::StringTable;
using AAllocator = xo::mm::AAllocator;
using ACollector = xo::mm::ACollector;
using MemorySizeVisitor = xo::mm::MemorySizeVisitor;
public:
DVsmRcx(DVirtualSchematikaMachine * vsm);
obj<AAllocator> allocator() const noexcept;
obj<ACollector> collector() const noexcept;
StringTable * stringtable() const noexcept;
obj<AAllocator> error_allocator() const noexcept;
void visit_pools(const MemorySizeVisitor & visitor) const;
private:
/** schematika interpreter **/
DVirtualSchematikaMachine * vsm_ = nullptr;;
};
} /*namespace scm*/
} /*namespace xo*/
/* end DVsmRcx.hpp */

View file

@ -0,0 +1,89 @@
/** @file DVsmSeqContFrame.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include "VsmInstr.hpp"
#include <xo/expression2/SequenceExpr.hpp>
#include <xo/alloc2/GCObject.hpp>
namespace xo {
namespace scm {
/** @brief saved VSM state during evaluation of a SequenceExpr
**/
class DVsmSeqContFrame {
public:
using AGCObject = xo::mm::AGCObject;
using AGCObjectVisitor = xo::mm::AGCObjectVisitor;
using VisitReason = xo::mm::VisitReason;
using AAllocator = xo::mm::AAllocator;
using ppindentinfo = xo::print::ppindentinfo;
public:
/** @defgroup scm-vsmevalsequenceframe-ctors constructors **/
///@{
DVsmSeqContFrame(obj<AGCObject> parent,
VsmInstr cont,
DSequenceExpr * seq_expr,
uint32_t i_seq);
/** create instance using memory from allocator @p mm **/
static DVsmSeqContFrame * make(obj<AAllocator> mm,
obj<AGCObject> parent,
VsmInstr cont,
DSequenceExpr * seq_expr,
uint32_t i_seq);
///@}
/** @defgroup scm-vsmevalsequenceframe-access-methods access methods **/
///@{
obj<AGCObject> parent() const noexcept { return parent_; }
VsmInstr cont() const noexcept { return cont_; }
DSequenceExpr * seq_expr() const noexcept { return seq_expr_; }
uint32_t i_seq() const noexcept { return i_seq_; }
///@}
/** @defgroup scm-vsmevalsequenceframe-general-methods general methods **/
///@{
uint32_t incr_i_seq() noexcept { return ++(this->i_seq_); }
///@}
/** @defgroup scm-vsmevalsequenceframe-gcobject-facet gcobject facet **/
///@{
DVsmSeqContFrame * gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept;
void visit_gco_children(VisitReason reason, obj<AGCObjectVisitor> gc) noexcept;
///@}
/** @defgrouop scm-vsmseqcontframe-printable-facet printable facet **/
///@{
bool pretty(const ppindentinfo & ppii) const noexcept;
///@}
private:
/** @defgroup scm-vsmevalsequenceframe-members member variables **/
///@{
/** saved VSM stack; restore when this frame consumed **/
obj<AGCObject> parent_;
/** saved continuation; restore when this frame consumed **/
VsmInstr cont_;
/** saved expr. evaluate elements of this sequence in order **/
DSequenceExpr * seq_expr_ = nullptr;
/** current sequence element being evaluated **/
uint32_t i_seq_ = 0;
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end DVsmSeqContFrame.hpp */

View file

@ -0,0 +1,12 @@
/** @file LocalEnv.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include "DLocalEnv.hpp"
#include "env/IGCObject_DLocalEnv.hpp"
#include "detail/IPrintable_DLocalEnv.hpp"
/* end LocalEnv.hpp */

View file

@ -0,0 +1,27 @@
/** @file SetupInterpreter2.hpp
*
* @author Roland Conybeare, Mar 2026
**/
#pragma once
#include "PrimitiveRegistry.hpp"
#include <xo/alloc2/Collector.hpp>
namespace xo {
namespace scm {
struct SetupInterpreter2 {
public:
using ACollector = xo::mm::ACollector;
public:
static bool register_facets();
static bool register_types(obj<ACollector> gc);
static bool register_primitives(obj<ARuntimeContext> rcx,
InstallSink sink,
InstallFlags flags);
};
}
}
/* end SetupInterpreter2.hpp */

View file

@ -0,0 +1,11 @@
/** @file VirtualSchematikaMachine.hpp
*
* @author Roland Conybeare, Mar 2026
**/
#pragma once
#include "vsm/DVirtualSchematikaMachine.hpp"
#include "vsm/IGCObject_DVirtualSchematikaMachine.hpp"
/* end VirtualSchematikaMachine.hpp */

View file

@ -0,0 +1,12 @@
/** @file VsmApplyClosureFrame.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include "DVsmApplyClosureFrame.hpp"
#include "detail/IGCObject_DVsmApplyClosureFrame.hpp"
#include "detail/IPrintable_DVsmApplyClosureFrame.hpp"
/* end VsmApplyClosureFrame.hpp */

View file

@ -0,0 +1,12 @@
/** @file VsmApplyFrame.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include "DVsmApplyFrame.hpp"
#include "detail/IGCObject_DVsmApplyFrame.hpp"
#include "detail/IPrintable_DVsmApplyFrame.hpp"
/* end VsmApplyFrame.hpp */

View file

@ -0,0 +1,74 @@
/** @file VsmConfig.hpp
*
* @author Roland Conybeare, Jan 2026
**/
#pragma once
#include <xo/reader2/ReaderConfig.hpp>
#include <xo/gc/X1CollectorConfig.hpp>
#include <xo/arena/ArenaConfig.hpp>
namespace xo {
namespace scm {
/** Configuration for virtual schematika machine
**/
struct VsmConfig {
using X1CollectorConfig = xo::mm::X1CollectorConfig;
using ArenaConfig = xo::mm::ArenaConfig;
VsmConfig() = default;
VsmConfig with_debug_flag(bool x) const {
VsmConfig retval = *this;
retval.debug_flag_ = x;
return retval;
}
VsmConfig with_parser_debug_flag(bool x) const {
VsmConfig retval = *this;
retval.rdr_config_.parser_debug_flag_ = x;
return retval;
}
VsmConfig with_x1_config(const X1CollectorConfig & x) const {
VsmConfig retval = *this;
retval.x1_config_ = x;
return retval;
}
VsmConfig with_x1_debug_flag(bool x) const {
VsmConfig retval = *this;
retval.x1_config_.debug_flag_ = x;
return retval;
}
static X1CollectorConfig std_x1_config() {
return X1CollectorConfig().with_name("gc").with_size(4*1024*1024);
}
/** true for interactive parser session; false for batch session **/
bool interactive_flag_ = true;
/** true to enable logging **/
bool debug_flag_ = false;
/** reader configuration **/
ReaderConfig rdr_config_;
/** Configuration for allocator/collector.
* TODO: may want to make CollectorConfig polymorphic
**/
X1CollectorConfig x1_config_ = std_x1_config();
/** Configuration for handful of non-moveable high-level objects
* e.g. DArenaHashMap in global symtab
**/
ArenaConfig fixed_config_ = ArenaConfig().with_name("fixed").with_size(4*1024);
/** Configuration for error allocator
* TODO: may want to make ArenaConfig polymorphic
**/
ArenaConfig error_config_ = ArenaConfig().with_name("error-reserve").with_size(64*1024);
};
} /*namespace scm*/
} /*namespace xo*/
/* end VsmConfig.hpp */

View file

@ -0,0 +1,12 @@
/** @file VsmDefContFrame.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include "DVsmDefContFrame.hpp"
#include "define/IGCObject_DVsmDefContFrame.hpp"
#include "define/IPrintable_DVsmDefContFrame.hpp"
/* end VsmDefContFrame.hpp */

View file

@ -0,0 +1,12 @@
/** @file VsmEvalArgsFrame.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include "DVsmEvalArgsFrame.hpp"
#include "detail/IGCObject_DVsmEvalArgsFrame.hpp"
#include "detail/IPrintable_DVsmEvalArgsFrame.hpp"
/* end VsmEvalArgsFrame.hpp */

View file

@ -0,0 +1,36 @@
/** @file VsmFrame.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include "VsmInstr.hpp"
#include <xo/procedure2/Procedure.hpp>
#include <xo/object2/DArray.hpp>
namespace xo {
namespace scm {
class VsmFrame {
public:
using AGCObject = xo::mm::AGCObject;
public:
VsmFrame(obj<AGCObject> parent,
VsmInstr cont) : parent_{parent}, cont_{cont} {}
//obj<AGCObject> parent() const noexcept { return parent_; }
obj<AGCObject> parent() const noexcept { return parent_; }
VsmInstr cont() const noexcept { return cont_; }
protected:
/** saved VSM stack; restore when this frame consumed **/
obj<AGCObject> parent_;
/** saved continuation; restore when this frame consumed **/
VsmInstr cont_;
};
} /*namespace scm*/
} /*namespace xo*/
/* end VsmFrame.hpp */

View file

@ -0,0 +1,12 @@
/** @file VsmIfElseContFrame.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include "DVsmIfElseContFrame.hpp"
#include "ifelse/IGCObject_DVsmIfElseContFrame.hpp"
#include "ifelse/IPrintable_DVsmIfElseContFrame.hpp"
/* end VsmIfElseContFrame.hpp */

View file

@ -0,0 +1,63 @@
/** @file VsmInstr.hpp
*
* @author Roland Conybeare, Jan 2026
**/
#pragma once
#include "VsmOpcode.hpp"
namespace xo {
namespace scm {
/**
* Thin instruction wrapper for VSM (virtual schematika machine) instructions.
* For exeuction see VirtualSchematikaMachine.cpp
**/
class VsmInstr {
public:
explicit VsmInstr(vsm_opcode oc) : opcode_{oc} {}
// instructions
static VsmInstr c_sentinel;
static VsmInstr c_halt;
static VsmInstr c_eval;
/** proceed to assignment after evaluating rhs
* of define-expression
**/
static VsmInstr c_def_cont;
static VsmInstr c_apply;
static VsmInstr c_evalargs;
/** restore VSM state for continuation of an apply expression **/
static VsmInstr c_apply_cont;
/** proceed to branch of if-else expression after evaluating
* test condition
**/
static VsmInstr c_ifelse_cont;
/** loop to evaluate members of a SequenceExpr **/
static VsmInstr c_seq_cont;
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();
return os;
}
} /*namespace scm*/
} /*namespace xo*/
/* end VsmInstr.hpp */

View file

@ -0,0 +1,67 @@
/** @file VsmOpcode.hpp
*
* @author Roland Conybeare, Jan 2026
**/
#pragma once
#include <ostream>
#include <cstdint>
namespace xo {
namespace scm {
/** Opcode for a virtual schematika expression;
* exeucted by VirtualSchematikaMachine
**/
enum class vsm_opcode {
/** Flags bad state (defect in VSM itself) **/
sentinel,
/** Immediately halt virtual schematika machine. **/
halt,
/** Evaluate expression in expr register **/
eval,
/** Apply function in stack frame
* See diagram in VirtualSchematikaMachine::_do_eval_apply_op
**/
apply,
/** Eval arguments to function.
* See diagram in VirtualSchematikaMachine::_do_eval_apply_op
**/
evalargs,
/** continuation to complete execution of define-expression,
* after evaluting rhs expression
**/
def_cont,
/** continuation to restore vsm registers (local_env, stack, cont)
* after invoking a closure
**/
apply_cont,
/** continuation to act on a branch **/
ifelse_cont,
/** Loop over elements of a SequenceExpr **/
seq_cont,
/** sentinel, counts number of opcodes **/
N,
};
static constexpr uint32_t n_opcode = static_cast<uint32_t>(vsm_opcode::N);
/** stringified enum value **/
const char *
vsm_opcode_descr(vsm_opcode x);
inline std::ostream &
operator<<(std::ostream & os, vsm_opcode x) {
os << vsm_opcode_descr(x);
return os;
}
} /*namespace scm*/
} /*namespace xo*/
/* end VsmOpcode.hpp */

View file

@ -0,0 +1,28 @@
/** @file VsmPrimitives.hpp
*
* @author Roland Conybeare, Mar 2026
**/
#pragma once
#include <xo/procedure2/Primitive_gco_0.hpp>
namespace xo {
namespace scm {
/** @brief primitives centered on interpreter2/ data
*
**/
class VsmPrimitives {
public:
using AAllocator = xo::mm::AAllocator;
public:
/** create primitive: report memory use to console **/
static DPrimitive_gco_0 * make_report_memory_use_pm(obj<AAllocator> mm,
StringTable * stbl);
};
} /*namespace scm*/
} /*namespace xo*/
/* end VsmPrimitives.hpp */

View file

@ -0,0 +1,11 @@
/** @file VsmRcx.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include "DVsmRcx.hpp"
#include "detail/IRuntimeContext_DVsmRcx.hpp"
/* end VsmRcx.hpp */

View file

@ -0,0 +1,12 @@
/** @file VsmSeqContFrame.hpp
*
* @author Roland Conybeare, Feb 2026
**/
#pragma once
#include "DVsmSeqContFrame.hpp"
#include "sequence/IGCObject_DVsmSeqContFrame.hpp"
#include "sequence/IPrintable_DVsmSeqContFrame.hpp"
/* end VsmSeqContFrame.hpp */

View file

@ -0,0 +1,69 @@
/** @file IGCObject_DVsmDefContFrame.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IGCObject_DVsmDefContFrame.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IGCObject_DVsmDefContFrame.json5]
**/
#pragma once
#include "GCObject.hpp"
#include <xo/alloc2/GCObject.hpp>
#include <xo/alloc2/Allocator.hpp>
#include "DVsmDefContFrame.hpp"
namespace xo { namespace scm { class IGCObject_DVsmDefContFrame; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::mm::AGCObject,
xo::scm::DVsmDefContFrame>
{
using ImplType = xo::mm::IGCObject_Xfer
<xo::scm::DVsmDefContFrame,
xo::scm::IGCObject_DVsmDefContFrame>;
};
}
}
namespace xo {
namespace scm {
/** @class IGCObject_DVsmDefContFrame
**/
class IGCObject_DVsmDefContFrame {
public:
/** @defgroup scm-gcobject-dvsmdefcontframe-type-traits **/
///@{
using size_type = xo::mm::AGCObject::size_type;
using AAllocator = xo::mm::AGCObject::AAllocator;
using AGCObjectVisitor = xo::mm::AGCObject::AGCObjectVisitor;
using VisitReason = xo::mm::AGCObject::VisitReason;
using Copaque = xo::mm::AGCObject::Copaque;
using Opaque = xo::mm::AGCObject::Opaque;
///@}
/** @defgroup scm-gcobject-dvsmdefcontframe-methods **/
///@{
// const methods
// non-const methods
/** move instance using object visitor.
Arguably abusing the word 'visitor' here **/
static Opaque gco_shallow_move(DVsmDefContFrame & self, obj<AGCObjectVisitor> gc) noexcept;
/** Invoke fn.visit_child(iface,data) for each child GCObject pointer.
Context: provides address of data pointer so it can be updated in place
when @p fn invokes garbage collector reentry point **/
static void visit_gco_children(DVsmDefContFrame & self, VisitReason reason, obj<AGCObjectVisitor> fn) noexcept;
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,62 @@
/** @file IPrintable_DVsmDefContFrame.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IPrintable_DVsmDefContFrame.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IPrintable_DVsmDefContFrame.json5]
**/
#pragma once
#include "Printable.hpp"
#include <xo/printable2/Printable.hpp>
#include <xo/printable2/detail/IPrintable_Xfer.hpp>
#include "DVsmDefContFrame.hpp"
namespace xo { namespace scm { class IPrintable_DVsmDefContFrame; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::print::APrintable,
xo::scm::DVsmDefContFrame>
{
using ImplType = xo::print::IPrintable_Xfer
<xo::scm::DVsmDefContFrame,
xo::scm::IPrintable_DVsmDefContFrame>;
};
}
}
namespace xo {
namespace scm {
/** @class IPrintable_DVsmDefContFrame
**/
class IPrintable_DVsmDefContFrame {
public:
/** @defgroup scm-printable-dvsmdefcontframe-type-traits **/
///@{
using ppindentinfo = xo::print::APrintable::ppindentinfo;
using Copaque = xo::print::APrintable::Copaque;
using Opaque = xo::print::APrintable::Opaque;
///@}
/** @defgroup scm-printable-dvsmdefcontframe-methods **/
///@{
// const methods
/** Pretty-printing support for this object.
See [xo-indentlog/xo/indentlog/pretty.hpp] **/
static bool pretty(const DVsmDefContFrame & self, const ppindentinfo & ppii);
// non-const methods
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,69 @@
/** @file IGCObject_DClosure.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IGCObject_DClosure.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IGCObject_DClosure.json5]
**/
#pragma once
#include "GCObject.hpp"
#include <xo/alloc2/GCObject.hpp>
#include <xo/alloc2/Allocator.hpp>
#include "DClosure.hpp"
namespace xo { namespace scm { class IGCObject_DClosure; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::mm::AGCObject,
xo::scm::DClosure>
{
using ImplType = xo::mm::IGCObject_Xfer
<xo::scm::DClosure,
xo::scm::IGCObject_DClosure>;
};
}
}
namespace xo {
namespace scm {
/** @class IGCObject_DClosure
**/
class IGCObject_DClosure {
public:
/** @defgroup scm-gcobject-dclosure-type-traits **/
///@{
using size_type = xo::mm::AGCObject::size_type;
using AAllocator = xo::mm::AGCObject::AAllocator;
using AGCObjectVisitor = xo::mm::AGCObject::AGCObjectVisitor;
using VisitReason = xo::mm::AGCObject::VisitReason;
using Copaque = xo::mm::AGCObject::Copaque;
using Opaque = xo::mm::AGCObject::Opaque;
///@}
/** @defgroup scm-gcobject-dclosure-methods **/
///@{
// const methods
// non-const methods
/** move instance using object visitor.
Arguably abusing the word 'visitor' here **/
static Opaque gco_shallow_move(DClosure & self, obj<AGCObjectVisitor> gc) noexcept;
/** Invoke fn.visit_child(iface,data) for each child GCObject pointer.
Context: provides address of data pointer so it can be updated in place
when @p fn invokes garbage collector reentry point **/
static void visit_gco_children(DClosure & self, VisitReason reason, obj<AGCObjectVisitor> fn) noexcept;
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,69 @@
/** @file IGCObject_DVsmApplyClosureFrame.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IGCObject_DVsmApplyClosureFrame.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IGCObject_DVsmApplyClosureFrame.json5]
**/
#pragma once
#include "GCObject.hpp"
#include <xo/alloc2/GCObject.hpp>
#include <xo/alloc2/Allocator.hpp>
#include "DVsmApplyClosureFrame.hpp"
namespace xo { namespace scm { class IGCObject_DVsmApplyClosureFrame; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::mm::AGCObject,
xo::scm::DVsmApplyClosureFrame>
{
using ImplType = xo::mm::IGCObject_Xfer
<xo::scm::DVsmApplyClosureFrame,
xo::scm::IGCObject_DVsmApplyClosureFrame>;
};
}
}
namespace xo {
namespace scm {
/** @class IGCObject_DVsmApplyClosureFrame
**/
class IGCObject_DVsmApplyClosureFrame {
public:
/** @defgroup scm-gcobject-dvsmapplyclosureframe-type-traits **/
///@{
using size_type = xo::mm::AGCObject::size_type;
using AAllocator = xo::mm::AGCObject::AAllocator;
using AGCObjectVisitor = xo::mm::AGCObject::AGCObjectVisitor;
using VisitReason = xo::mm::AGCObject::VisitReason;
using Copaque = xo::mm::AGCObject::Copaque;
using Opaque = xo::mm::AGCObject::Opaque;
///@}
/** @defgroup scm-gcobject-dvsmapplyclosureframe-methods **/
///@{
// const methods
// non-const methods
/** move instance using object visitor.
Arguably abusing the word 'visitor' here **/
static Opaque gco_shallow_move(DVsmApplyClosureFrame & self, obj<AGCObjectVisitor> gc) noexcept;
/** Invoke fn.visit_child(iface,data) for each child GCObject pointer.
Context: provides address of data pointer so it can be updated in place
when @p fn invokes garbage collector reentry point **/
static void visit_gco_children(DVsmApplyClosureFrame & self, VisitReason reason, obj<AGCObjectVisitor> fn) noexcept;
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,69 @@
/** @file IGCObject_DVsmApplyFrame.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IGCObject_DVsmApplyFrame.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IGCObject_DVsmApplyFrame.json5]
**/
#pragma once
#include "GCObject.hpp"
#include <xo/alloc2/GCObject.hpp>
#include <xo/alloc2/Allocator.hpp>
#include "DVsmApplyFrame.hpp"
namespace xo { namespace scm { class IGCObject_DVsmApplyFrame; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::mm::AGCObject,
xo::scm::DVsmApplyFrame>
{
using ImplType = xo::mm::IGCObject_Xfer
<xo::scm::DVsmApplyFrame,
xo::scm::IGCObject_DVsmApplyFrame>;
};
}
}
namespace xo {
namespace scm {
/** @class IGCObject_DVsmApplyFrame
**/
class IGCObject_DVsmApplyFrame {
public:
/** @defgroup scm-gcobject-dvsmapplyframe-type-traits **/
///@{
using size_type = xo::mm::AGCObject::size_type;
using AAllocator = xo::mm::AGCObject::AAllocator;
using AGCObjectVisitor = xo::mm::AGCObject::AGCObjectVisitor;
using VisitReason = xo::mm::AGCObject::VisitReason;
using Copaque = xo::mm::AGCObject::Copaque;
using Opaque = xo::mm::AGCObject::Opaque;
///@}
/** @defgroup scm-gcobject-dvsmapplyframe-methods **/
///@{
// const methods
// non-const methods
/** move instance using object visitor.
Arguably abusing the word 'visitor' here **/
static Opaque gco_shallow_move(DVsmApplyFrame & self, obj<AGCObjectVisitor> gc) noexcept;
/** Invoke fn.visit_child(iface,data) for each child GCObject pointer.
Context: provides address of data pointer so it can be updated in place
when @p fn invokes garbage collector reentry point **/
static void visit_gco_children(DVsmApplyFrame & self, VisitReason reason, obj<AGCObjectVisitor> fn) noexcept;
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,69 @@
/** @file IGCObject_DVsmEvalArgsFrame.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IGCObject_DVsmEvalArgsFrame.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IGCObject_DVsmEvalArgsFrame.json5]
**/
#pragma once
#include "GCObject.hpp"
#include <xo/alloc2/GCObject.hpp>
#include <xo/alloc2/Allocator.hpp>
#include "DVsmEvalArgsFrame.hpp"
namespace xo { namespace scm { class IGCObject_DVsmEvalArgsFrame; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::mm::AGCObject,
xo::scm::DVsmEvalArgsFrame>
{
using ImplType = xo::mm::IGCObject_Xfer
<xo::scm::DVsmEvalArgsFrame,
xo::scm::IGCObject_DVsmEvalArgsFrame>;
};
}
}
namespace xo {
namespace scm {
/** @class IGCObject_DVsmEvalArgsFrame
**/
class IGCObject_DVsmEvalArgsFrame {
public:
/** @defgroup scm-gcobject-dvsmevalargsframe-type-traits **/
///@{
using size_type = xo::mm::AGCObject::size_type;
using AAllocator = xo::mm::AGCObject::AAllocator;
using AGCObjectVisitor = xo::mm::AGCObject::AGCObjectVisitor;
using VisitReason = xo::mm::AGCObject::VisitReason;
using Copaque = xo::mm::AGCObject::Copaque;
using Opaque = xo::mm::AGCObject::Opaque;
///@}
/** @defgroup scm-gcobject-dvsmevalargsframe-methods **/
///@{
// const methods
// non-const methods
/** move instance using object visitor.
Arguably abusing the word 'visitor' here **/
static Opaque gco_shallow_move(DVsmEvalArgsFrame & self, obj<AGCObjectVisitor> gc) noexcept;
/** Invoke fn.visit_child(iface,data) for each child GCObject pointer.
Context: provides address of data pointer so it can be updated in place
when @p fn invokes garbage collector reentry point **/
static void visit_gco_children(DVsmEvalArgsFrame & self, VisitReason reason, obj<AGCObjectVisitor> fn) noexcept;
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,62 @@
/** @file IPrintable_DClosure.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IPrintable_DClosure.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IPrintable_DClosure.json5]
**/
#pragma once
#include "Printable.hpp"
#include <xo/printable2/Printable.hpp>
#include <xo/printable2/detail/IPrintable_Xfer.hpp>
#include "DClosure.hpp"
namespace xo { namespace scm { class IPrintable_DClosure; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::print::APrintable,
xo::scm::DClosure>
{
using ImplType = xo::print::IPrintable_Xfer
<xo::scm::DClosure,
xo::scm::IPrintable_DClosure>;
};
}
}
namespace xo {
namespace scm {
/** @class IPrintable_DClosure
**/
class IPrintable_DClosure {
public:
/** @defgroup scm-printable-dclosure-type-traits **/
///@{
using ppindentinfo = xo::print::APrintable::ppindentinfo;
using Copaque = xo::print::APrintable::Copaque;
using Opaque = xo::print::APrintable::Opaque;
///@}
/** @defgroup scm-printable-dclosure-methods **/
///@{
// const methods
/** Pretty-printing support for this object.
See [xo-indentlog/xo/indentlog/pretty.hpp] **/
static bool pretty(const DClosure & self, const ppindentinfo & ppii);
// non-const methods
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,62 @@
/** @file IPrintable_DLocalEnv.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IPrintable_DLocalEnv.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IPrintable_DLocalEnv.json5]
**/
#pragma once
#include "Printable.hpp"
#include <xo/printable2/Printable.hpp>
#include <xo/printable2/detail/IPrintable_Xfer.hpp>
#include "DLocalEnv.hpp"
namespace xo { namespace scm { class IPrintable_DLocalEnv; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::print::APrintable,
xo::scm::DLocalEnv>
{
using ImplType = xo::print::IPrintable_Xfer
<xo::scm::DLocalEnv,
xo::scm::IPrintable_DLocalEnv>;
};
}
}
namespace xo {
namespace scm {
/** @class IPrintable_DLocalEnv
**/
class IPrintable_DLocalEnv {
public:
/** @defgroup scm-printable-dlocalenv-type-traits **/
///@{
using ppindentinfo = xo::print::APrintable::ppindentinfo;
using Copaque = xo::print::APrintable::Copaque;
using Opaque = xo::print::APrintable::Opaque;
///@}
/** @defgroup scm-printable-dlocalenv-methods **/
///@{
// const methods
/** Pretty-printing support for this object.
See [xo-indentlog/xo/indentlog/pretty.hpp] **/
static bool pretty(const DLocalEnv & self, const ppindentinfo & ppii);
// non-const methods
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,62 @@
/** @file IPrintable_DVsmApplyClosureFrame.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IPrintable_DVsmApplyClosureFrame.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IPrintable_DVsmApplyClosureFrame.json5]
**/
#pragma once
#include "Printable.hpp"
#include <xo/printable2/Printable.hpp>
#include <xo/printable2/detail/IPrintable_Xfer.hpp>
#include "DVsmApplyClosureFrame.hpp"
namespace xo { namespace scm { class IPrintable_DVsmApplyClosureFrame; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::print::APrintable,
xo::scm::DVsmApplyClosureFrame>
{
using ImplType = xo::print::IPrintable_Xfer
<xo::scm::DVsmApplyClosureFrame,
xo::scm::IPrintable_DVsmApplyClosureFrame>;
};
}
}
namespace xo {
namespace scm {
/** @class IPrintable_DVsmApplyClosureFrame
**/
class IPrintable_DVsmApplyClosureFrame {
public:
/** @defgroup scm-printable-dvsmapplyclosureframe-type-traits **/
///@{
using ppindentinfo = xo::print::APrintable::ppindentinfo;
using Copaque = xo::print::APrintable::Copaque;
using Opaque = xo::print::APrintable::Opaque;
///@}
/** @defgroup scm-printable-dvsmapplyclosureframe-methods **/
///@{
// const methods
/** Pretty-printing support for this object.
See [xo-indentlog/xo/indentlog/pretty.hpp] **/
static bool pretty(const DVsmApplyClosureFrame & self, const ppindentinfo & ppii);
// non-const methods
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,62 @@
/** @file IPrintable_DVsmApplyFrame.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IPrintable_DVsmApplyFrame.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IPrintable_DVsmApplyFrame.json5]
**/
#pragma once
#include "Printable.hpp"
#include <xo/printable2/Printable.hpp>
#include <xo/printable2/detail/IPrintable_Xfer.hpp>
#include "DVsmApplyFrame.hpp"
namespace xo { namespace scm { class IPrintable_DVsmApplyFrame; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::print::APrintable,
xo::scm::DVsmApplyFrame>
{
using ImplType = xo::print::IPrintable_Xfer
<xo::scm::DVsmApplyFrame,
xo::scm::IPrintable_DVsmApplyFrame>;
};
}
}
namespace xo {
namespace scm {
/** @class IPrintable_DVsmApplyFrame
**/
class IPrintable_DVsmApplyFrame {
public:
/** @defgroup scm-printable-dvsmapplyframe-type-traits **/
///@{
using ppindentinfo = xo::print::APrintable::ppindentinfo;
using Copaque = xo::print::APrintable::Copaque;
using Opaque = xo::print::APrintable::Opaque;
///@}
/** @defgroup scm-printable-dvsmapplyframe-methods **/
///@{
// const methods
/** Pretty-printing support for this object.
See [xo-indentlog/xo/indentlog/pretty.hpp] **/
static bool pretty(const DVsmApplyFrame & self, const ppindentinfo & ppii);
// non-const methods
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,62 @@
/** @file IPrintable_DVsmEvalArgsFrame.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IPrintable_DVsmEvalArgsFrame.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IPrintable_DVsmEvalArgsFrame.json5]
**/
#pragma once
#include "Printable.hpp"
#include <xo/printable2/Printable.hpp>
#include <xo/printable2/detail/IPrintable_Xfer.hpp>
#include "DVsmEvalArgsFrame.hpp"
namespace xo { namespace scm { class IPrintable_DVsmEvalArgsFrame; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::print::APrintable,
xo::scm::DVsmEvalArgsFrame>
{
using ImplType = xo::print::IPrintable_Xfer
<xo::scm::DVsmEvalArgsFrame,
xo::scm::IPrintable_DVsmEvalArgsFrame>;
};
}
}
namespace xo {
namespace scm {
/** @class IPrintable_DVsmEvalArgsFrame
**/
class IPrintable_DVsmEvalArgsFrame {
public:
/** @defgroup scm-printable-dvsmevalargsframe-type-traits **/
///@{
using ppindentinfo = xo::print::APrintable::ppindentinfo;
using Copaque = xo::print::APrintable::Copaque;
using Opaque = xo::print::APrintable::Opaque;
///@}
/** @defgroup scm-printable-dvsmevalargsframe-methods **/
///@{
// const methods
/** Pretty-printing support for this object.
See [xo-indentlog/xo/indentlog/pretty.hpp] **/
static bool pretty(const DVsmEvalArgsFrame & self, const ppindentinfo & ppii);
// non-const methods
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,67 @@
/** @file IProcedure_DClosure.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IProcedure_DClosure.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IProcedure_DClosure.json5]
**/
#pragma once
#include "Procedure.hpp"
#include <xo/procedure2/RuntimeContext.hpp>
#include <xo/procedure2/detail/IRuntimeContext_Xfer.hpp>
#include <xo/procedure2/Procedure.hpp>
#include <xo/procedure2/detail/IProcedure_Xfer.hpp>
#include "DClosure.hpp"
namespace xo { namespace scm { class IProcedure_DClosure; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::scm::AProcedure,
xo::scm::DClosure>
{
using ImplType = xo::scm::IProcedure_Xfer
<xo::scm::DClosure,
xo::scm::IProcedure_DClosure>;
};
}
}
namespace xo {
namespace scm {
/** @class IProcedure_DClosure
**/
class IProcedure_DClosure {
public:
/** @defgroup scm-procedure-dclosure-type-traits **/
///@{
using AGCObject = xo::scm::AProcedure::AGCObject;
using Copaque = xo::scm::AProcedure::Copaque;
using Opaque = xo::scm::AProcedure::Opaque;
///@}
/** @defgroup scm-procedure-dclosure-methods **/
///@{
// const methods
/** true iff procedure takes n arguments **/
static bool is_nary(const DClosure & self) noexcept;
/** number of arguments. -1 for n-ary **/
static std::int32_t n_args(const DClosure & self) noexcept;
// non-const methods
/** invoke procedure; assume arguments satisfy type system **/
static obj<AGCObject> apply_nocheck(DClosure & self, obj<ARuntimeContext> rcx, const DArray * args);
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,69 @@
/** @file IRuntimeContext_DVsmRcx.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IRuntimeContext_DVsmRcx.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IRuntimeContext_DVsmRcx.json5]
**/
#pragma once
#include "RuntimeContext.hpp"
#include "DVsmRcx.hpp"
namespace xo { namespace scm { class IRuntimeContext_DVsmRcx; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::scm::ARuntimeContext,
xo::scm::DVsmRcx>
{
using ImplType = xo::scm::IRuntimeContext_Xfer
<xo::scm::DVsmRcx,
xo::scm::IRuntimeContext_DVsmRcx>;
};
}
}
namespace xo {
namespace scm {
/** @class IRuntimeContext_DVsmRcx
**/
class IRuntimeContext_DVsmRcx {
public:
/** @defgroup scm-runtimecontext-dvsmrcx-type-traits **/
///@{
using AAllocator = xo::scm::ARuntimeContext::AAllocator;
using ACollector = xo::scm::ARuntimeContext::ACollector;
using MemorySizeVisitor = xo::scm::ARuntimeContext::MemorySizeVisitor;
using Copaque = xo::scm::ARuntimeContext::Copaque;
using Opaque = xo::scm::ARuntimeContext::Opaque;
///@}
/** @defgroup scm-runtimecontext-dvsmrcx-methods **/
///@{
// const methods
/** default allocator to use for objects **/
static obj<AAllocator> allocator(const DVsmRcx & self) noexcept;
/** collector facet for allocator. If non-null, same data pointer as allocator **/
static obj<ACollector> collector(const DVsmRcx & self) noexcept;
/** last-resort allocator for erros. e.g. regular allocator exhausted **/
static obj<AAllocator> error_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);
// non-const methods
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,69 @@
/** @file IGCObject_DLocalEnv.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IGCObject_DLocalEnv.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IGCObject_DLocalEnv.json5]
**/
#pragma once
#include "GCObject.hpp"
#include <xo/alloc2/GCObject.hpp>
#include <xo/alloc2/Allocator.hpp>
#include "DLocalEnv.hpp"
namespace xo { namespace scm { class IGCObject_DLocalEnv; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::mm::AGCObject,
xo::scm::DLocalEnv>
{
using ImplType = xo::mm::IGCObject_Xfer
<xo::scm::DLocalEnv,
xo::scm::IGCObject_DLocalEnv>;
};
}
}
namespace xo {
namespace scm {
/** @class IGCObject_DLocalEnv
**/
class IGCObject_DLocalEnv {
public:
/** @defgroup scm-gcobject-dlocalenv-type-traits **/
///@{
using size_type = xo::mm::AGCObject::size_type;
using AAllocator = xo::mm::AGCObject::AAllocator;
using AGCObjectVisitor = xo::mm::AGCObject::AGCObjectVisitor;
using VisitReason = xo::mm::AGCObject::VisitReason;
using Copaque = xo::mm::AGCObject::Copaque;
using Opaque = xo::mm::AGCObject::Opaque;
///@}
/** @defgroup scm-gcobject-dlocalenv-methods **/
///@{
// const methods
// non-const methods
/** move instance using object visitor.
Arguably abusing the word 'visitor' here **/
static Opaque gco_shallow_move(DLocalEnv & self, obj<AGCObjectVisitor> gc) noexcept;
/** Invoke fn.visit_child(iface,data) for each child GCObject pointer.
Context: provides address of data pointer so it can be updated in place
when @p fn invokes garbage collector reentry point **/
static void visit_gco_children(DLocalEnv & self, VisitReason reason, obj<AGCObjectVisitor> fn) noexcept;
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,62 @@
/** @file IPrintable_DLocalEnv.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IPrintable_DLocalEnv.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IPrintable_DLocalEnv.json5]
**/
#pragma once
#include "Printable.hpp"
#include <xo/printable2/Printable.hpp>
#include <xo/printable2/detail/IPrintable_Xfer.hpp>
#include "DLocalEnv.hpp"
namespace xo { namespace scm { class IPrintable_DLocalEnv; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::print::APrintable,
xo::scm::DLocalEnv>
{
using ImplType = xo::print::IPrintable_Xfer
<xo::scm::DLocalEnv,
xo::scm::IPrintable_DLocalEnv>;
};
}
}
namespace xo {
namespace scm {
/** @class IPrintable_DLocalEnv
**/
class IPrintable_DLocalEnv {
public:
/** @defgroup scm-printable-dlocalenv-type-traits **/
///@{
using ppindentinfo = xo::print::APrintable::ppindentinfo;
using Copaque = xo::print::APrintable::Copaque;
using Opaque = xo::print::APrintable::Opaque;
///@}
/** @defgroup scm-printable-dlocalenv-methods **/
///@{
// const methods
/** Pretty-printing support for this object.
See [xo-indentlog/xo/indentlog/pretty.hpp] **/
static bool pretty(const DLocalEnv & self, const ppindentinfo & ppii);
// non-const methods
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,69 @@
/** @file IGCObject_DVsmIfElseContFrame.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IGCObject_DVsmIfElseContFrame.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IGCObject_DVsmIfElseContFrame.json5]
**/
#pragma once
#include "GCObject.hpp"
#include <xo/alloc2/GCObject.hpp>
#include <xo/alloc2/Allocator.hpp>
#include "DVsmIfElseContFrame.hpp"
namespace xo { namespace scm { class IGCObject_DVsmIfElseContFrame; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::mm::AGCObject,
xo::scm::DVsmIfElseContFrame>
{
using ImplType = xo::mm::IGCObject_Xfer
<xo::scm::DVsmIfElseContFrame,
xo::scm::IGCObject_DVsmIfElseContFrame>;
};
}
}
namespace xo {
namespace scm {
/** @class IGCObject_DVsmIfElseContFrame
**/
class IGCObject_DVsmIfElseContFrame {
public:
/** @defgroup scm-gcobject-dvsmifelsecontframe-type-traits **/
///@{
using size_type = xo::mm::AGCObject::size_type;
using AAllocator = xo::mm::AGCObject::AAllocator;
using AGCObjectVisitor = xo::mm::AGCObject::AGCObjectVisitor;
using VisitReason = xo::mm::AGCObject::VisitReason;
using Copaque = xo::mm::AGCObject::Copaque;
using Opaque = xo::mm::AGCObject::Opaque;
///@}
/** @defgroup scm-gcobject-dvsmifelsecontframe-methods **/
///@{
// const methods
// non-const methods
/** move instance using object visitor.
Arguably abusing the word 'visitor' here **/
static Opaque gco_shallow_move(DVsmIfElseContFrame & self, obj<AGCObjectVisitor> gc) noexcept;
/** Invoke fn.visit_child(iface,data) for each child GCObject pointer.
Context: provides address of data pointer so it can be updated in place
when @p fn invokes garbage collector reentry point **/
static void visit_gco_children(DVsmIfElseContFrame & self, VisitReason reason, obj<AGCObjectVisitor> fn) noexcept;
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,62 @@
/** @file IPrintable_DVsmIfElseContFrame.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IPrintable_DVsmIfElseContFrame.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IPrintable_DVsmIfElseContFrame.json5]
**/
#pragma once
#include "Printable.hpp"
#include <xo/printable2/Printable.hpp>
#include <xo/printable2/detail/IPrintable_Xfer.hpp>
#include "DVsmIfElseContFrame.hpp"
namespace xo { namespace scm { class IPrintable_DVsmIfElseContFrame; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::print::APrintable,
xo::scm::DVsmIfElseContFrame>
{
using ImplType = xo::print::IPrintable_Xfer
<xo::scm::DVsmIfElseContFrame,
xo::scm::IPrintable_DVsmIfElseContFrame>;
};
}
}
namespace xo {
namespace scm {
/** @class IPrintable_DVsmIfElseContFrame
**/
class IPrintable_DVsmIfElseContFrame {
public:
/** @defgroup scm-printable-dvsmifelsecontframe-type-traits **/
///@{
using ppindentinfo = xo::print::APrintable::ppindentinfo;
using Copaque = xo::print::APrintable::Copaque;
using Opaque = xo::print::APrintable::Opaque;
///@}
/** @defgroup scm-printable-dvsmifelsecontframe-methods **/
///@{
// const methods
/** Pretty-printing support for this object.
See [xo-indentlog/xo/indentlog/pretty.hpp] **/
static bool pretty(const DVsmIfElseContFrame & self, const ppindentinfo & ppii);
// non-const methods
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,21 @@
/** @file init_interpreter2.hpp
*
* @author Roland Conybeare, Jan 2026
**/
#pragma once
#include <xo/subsys/Subsystem.hpp>
namespace xo {
/* tag to represent the xo-interpreter2/ subsystem within ordered initialization */
enum S_interpreter2_tag {};
template <>
struct InitSubsys<S_interpreter2_tag> {
static void init();
static InitEvidence require();
};
} /*namespace xo*/
/* end init_interpreter2.hpp */

View file

@ -0,0 +1,69 @@
/** @file IGCObject_DVsmSeqContFrame.hpp
*
* 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_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IGCObject_DVsmSeqContFrame.json5]
**/
#pragma once
#include "GCObject.hpp"
#include <xo/alloc2/GCObject.hpp>
#include <xo/alloc2/Allocator.hpp>
#include "DVsmSeqContFrame.hpp"
namespace xo { namespace scm { class IGCObject_DVsmSeqContFrame; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::mm::AGCObject,
xo::scm::DVsmSeqContFrame>
{
using ImplType = xo::mm::IGCObject_Xfer
<xo::scm::DVsmSeqContFrame,
xo::scm::IGCObject_DVsmSeqContFrame>;
};
}
}
namespace xo {
namespace scm {
/** @class IGCObject_DVsmSeqContFrame
**/
class IGCObject_DVsmSeqContFrame {
public:
/** @defgroup scm-gcobject-dvsmseqcontframe-type-traits **/
///@{
using size_type = xo::mm::AGCObject::size_type;
using AAllocator = xo::mm::AGCObject::AAllocator;
using AGCObjectVisitor = xo::mm::AGCObject::AGCObjectVisitor;
using VisitReason = xo::mm::AGCObject::VisitReason;
using Copaque = xo::mm::AGCObject::Copaque;
using Opaque = xo::mm::AGCObject::Opaque;
///@}
/** @defgroup scm-gcobject-dvsmseqcontframe-methods **/
///@{
// const methods
// non-const methods
/** move instance using object visitor.
Arguably abusing the word 'visitor' here **/
static Opaque gco_shallow_move(DVsmSeqContFrame & self, obj<AGCObjectVisitor> gc) noexcept;
/** Invoke fn.visit_child(iface,data) for each child GCObject pointer.
Context: provides address of data pointer so it can be updated in place
when @p fn invokes garbage collector reentry point **/
static void visit_gco_children(DVsmSeqContFrame & self, VisitReason reason, obj<AGCObjectVisitor> fn) noexcept;
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,62 @@
/** @file IPrintable_DVsmSeqContFrame.hpp
*
* 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_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IPrintable_DVsmSeqContFrame.json5]
**/
#pragma once
#include "Printable.hpp"
#include <xo/printable2/Printable.hpp>
#include <xo/printable2/detail/IPrintable_Xfer.hpp>
#include "DVsmSeqContFrame.hpp"
namespace xo { namespace scm { class IPrintable_DVsmSeqContFrame; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::print::APrintable,
xo::scm::DVsmSeqContFrame>
{
using ImplType = xo::print::IPrintable_Xfer
<xo::scm::DVsmSeqContFrame,
xo::scm::IPrintable_DVsmSeqContFrame>;
};
}
}
namespace xo {
namespace scm {
/** @class IPrintable_DVsmSeqContFrame
**/
class IPrintable_DVsmSeqContFrame {
public:
/** @defgroup scm-printable-dvsmseqcontframe-type-traits **/
///@{
using ppindentinfo = xo::print::APrintable::ppindentinfo;
using Copaque = xo::print::APrintable::Copaque;
using Opaque = xo::print::APrintable::Opaque;
///@}
/** @defgroup scm-printable-dvsmseqcontframe-methods **/
///@{
// const methods
/** Pretty-printing support for this object.
See [xo-indentlog/xo/indentlog/pretty.hpp] **/
static bool pretty(const DVsmSeqContFrame & self, const ppindentinfo & ppii);
// non-const methods
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,350 @@
/** @file VirtualSchematikaMachine.hpp
*
* @author Roland Conybare, Jan 2026
**/
#pragma once
#include "VsmConfig.hpp"
#include "VsmInstr.hpp"
#include "VsmFrame.hpp"
#include "LocalEnv.hpp"
#include "GlobalEnv.hpp"
#include <xo/object2/RuntimeError.hpp>
#include <xo/object2/Array.hpp>
#include <xo/reader2/SchematikaReader.hpp>
#include <xo/expression2/Expression.hpp>
#include <xo/alloc2/GCObject.hpp>
#include <xo/alloc2/abox.hpp>
#include <variant>
namespace xo {
namespace scm {
/** similar to @ref xo::scm::ReaderResult **/
struct VsmResult {
using AGCObject = xo::mm::AGCObject;
using span_type = xo::mm::span<const char>;
VsmResult() = default;
explicit VsmResult(obj<AGCObject> value) : result_{value} {}
bool is_value() const { return result_; }
bool is_error() const;
const obj<AGCObject> * value() const { return &result_; }
const obj<AGCObject> & value_ref() const { return result_; }
/** result of evaluating first expression encountered in input **/
obj<AGCObject> result_;
};
/** vsm result + reamining span
*
* Preserves address of wrapped VsmResult
* (so it can continue to be owned by DVirtualSchematikaMachine,
* and to be known to gc without add'l effort)
**/
struct VsmResultExt {
using AGCObject = xo::mm::AGCObject;
using span_type = VsmResult::span_type;
VsmResultExt() = default;
VsmResultExt(const VsmResult & result, span_type rem) : p_result_{&result}, remaining_{rem} {}
bool is_empty() const { return !p_result_; }
bool is_value() const { return p_result_ ? p_result_->is_value() : false; }
bool is_error() const { return p_result_ ? p_result_->is_error() : false; }
const obj<AGCObject> * value() const { return p_result_ ? p_result_->value() : nullptr; }
//const obj<AGCObject> & value_ref() { return result_.value_ref(); }
const VsmResult * p_result_ = nullptr;
/** unconsumed portion of input **/
VsmResult::span_type remaining_;
};
/** @class VirtualSchematikaMachine
* @brief virtual machine for schematika
**/
class DVirtualSchematikaMachine {
public:
// will be DArenaVector<obj<StackFrame>> probably
using Stack = void *;
using AGCObject = xo::mm::AGCObject;
using AGCObjectVisitor = xo::mm::AGCObjectVisitor;
using VisitReason = xo::mm::VisitReason;
using AAllocator = xo::mm::AAllocator;
using MemorySizeVisitor = xo::mm::MemorySizeVisitor;
using span_type = xo::mm::span<const char>;
public:
/** @p config. configuration
* @p aux_mm. Allocator for miscellaneous dataN
* owned by this VSM.
**/
DVirtualSchematikaMachine(const VsmConfig & config,
obj<AAllocator> aux_mm);
/** non-trivial dtor because of @ref reader_
* indirect dependency on DGlobalSymtab
**/
~DVirtualSchematikaMachine() = default;
/** create instance using memory from @p mm.
* with configuration @p config.
* Machine will use @p aux_mm for auxiliary (non-GC, non-arena)
* memory.
**/
static DVirtualSchematikaMachine * _make(obj<AAllocator> mm,
const VsmConfig & config,
obj<AAllocator> aux_mm);
/** like _make(), but create fop **/
static obj<AGCObject,DVirtualSchematikaMachine> make(obj<AAllocator> mm,
const VsmConfig & config,
obj<AAllocator> aux_mm);
/** allocator for schematika data **/
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
**/
bool is_at_toplevel() const noexcept;
/** visit vsm-owned memory pools; call visitor(info) for each **/
void visit_pools(const MemorySizeVisitor & visitor) const;
/** begin interactive session. **/
void begin_interactive_session();
/** begin batch session **/
void begin_batch_session();
/** consume input @p input_cstr.
* Require: must first start interactive/batch session
**/
VsmResultExt read_eval_print(span_type input_span, bool eof);
/** evaluate expression @p expr
* Require: must first start interactive/batch session
**/
const VsmResult & start_eval(obj<AExpression> expr);
/** borrow calling thread to run indefinitely,
* until halt instruction
**/
void run();
/** execute vsm instruction in @ref pc_.
* @retval instruction count. 1 unless pc_ is halt.
**/
bool execute_one();
/** @defgroup scm-virtualschematikamachine-gcobject-facet gcobject facet **/
///@{
/** object size. Not implemented. Only intending to support VSM as virtual root **/
std::size_t shallow_size() const noexcept;
/** shallow copy during gc cycle. Not implemented! Only intending to support
* VSM as virtual root
**/
DVirtualSchematikaMachine * gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept;
/** forward gc-aware child pointers
**/
void visit_gco_children(VisitReason reason, obj<AGCObjectVisitor> gc) noexcept;
///@}
private:
/** Require:
* - expression in @ref expr_
**/
void _do_eval_op();
/** evaluate a constant expression
* Require:
* - expression in @ref expr_
**/
void _do_eval_constant_op();
/** evaluate a define-expression
* Require:
* - expression in @ref expr_
**/
void _do_eval_define_op();
/** evaluate a lambda expression
* Require:
* - expression in @ref expr_
**/
void _do_eval_lambda_op();
/** evaluate variable expression (definition)
* Require:
* - expression in @ref expr_
**/
void _do_eval_variable_op();
/** evaluate a variable reference (use after definition)
* Require:
* - expression in @ref expr_
**/
void _do_eval_varref_op();
/** evaluate an apply expression
* Require:
* - expression in @ref expr_
**/
void _do_eval_apply_op();
/** evaluate an if-else expression
* Require:
* - expression in @ref expr_
**/
void _do_eval_if_else_op();
/** evaluate a sequence expression
* Require:
* - expression in @ref expr_
**/
void _do_eval_sequence_op();
/** apply a function to evaluated arguments **/
void _do_apply_op();
/** evaluate arguments on behalf of a function call
* Require:
* - expression value in @ref value_
* - stack:
* [0] VsmEvalArgsFrame
* [1] VsmApplyFrame
* ...
**/
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();
/** perform assignment after evaluating
* the rhs of a define-expr
**/
void _do_def_cont_op();
/** restore registers from stack frame
* (specifically: local_env_, stack_, cont_)
* after invoking a schematika closure
**/
void _do_apply_cont_op();
/** proceed with if- or else- branch of an if-else expression
* after evaluating test condition
**/
void _do_ifelse_cont_op();
/** loop continuation after evaluating element of a SequenceExpr **/
void _do_seq_cont_op();
private:
/*
* Some registers are preserved by evaluation:
* stack_
* cont_
* local_env_
*
* Other registers not preserved
* pc_
* expr_
* fn_
* args_
* value_
*/
/** configuration **/
VsmConfig config_;
/** virtual gc root.
* Arranges for gc to traverse+forward pointers exiting VSM.
* It won't (and can't) copy/move the VSM itself, since alloc'd
* outside gc.
**/
obj<AGCObject> self_vroot_;
/** allocator (likely DArena) for globals.
* For example DArenaHashMap in global symta.
**/
obj<AAllocator> aux_mm_;
/** allocator (likely DX1Collector or similar) for
* expressions and values. Schemaatika reader will use this also.
*
* Allocations must represent a type that supports GCObject.
**/
abox<AAllocator> mm_;
/** Sidecar allocator for error reporting.
* Separate to mitigate interference with @ref mm_
* (separate memory so we can for example report
* an out-of-memory error).
* Likely DArena or similar
**/
abox<AAllocator> error_mm_;
/** runtime context for this vsm.
* For example, provides allocator to primitives
**/
abox<ARuntimeContext> rcx_;
// consider separate allocator (which _may_ turn out to be the same)
// for VM stack. Only works for code that doesn't rely on fancy
// lexical scoping
// consider separate allocator for reader (i.e. program code)
// and data (program execution)
/** reader: text -> expression **/
SchematikaReader reader_;
/** program counter **/
VsmInstr pc_ = VsmInstr::c_halt;
/** stack pointer **/
obj<AGCObject> stack_;
/** expression register **/
obj<AExpression> expr_;
/** environment pointer. Maintains bindings
* for global variables. Obtained from reader
**/
obj<AGCObject,DGlobalEnv> global_env_;
/** environment pointer. Provides bindings
* for surrounding lexical scope at this point
* in execution
**/
obj<AGCObject,DLocalEnv> local_env_;
/** evaluated function to call **/
obj<AGCObject> fn_;
/** evaluated argument list **/
obj<AGCObject,DArray> args_;
/** result register **/
VsmResult value_;
/** continuation register **/
VsmInstr cont_ = VsmInstr::c_halt;
};
} /*namespace scm*/
} /*namespace xo*/
/* end DVirtualSchematikaMachine.hpp */

View file

@ -0,0 +1,69 @@
/** @file IGCObject_DVirtualSchematikaMachine.hpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IGCObject_DVirtualSchematikaMachine.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_repr.hpp.j2]
* 3. idl for facet methods
* [idl/IGCObject_DVirtualSchematikaMachine.json5]
**/
#pragma once
#include "GCObject.hpp"
#include <xo/alloc2/GCObject.hpp>
#include <xo/alloc2/Allocator.hpp>
#include "DVirtualSchematikaMachine.hpp"
namespace xo { namespace scm { class IGCObject_DVirtualSchematikaMachine; } }
namespace xo {
namespace facet {
template <>
struct FacetImplementation<xo::mm::AGCObject,
xo::scm::DVirtualSchematikaMachine>
{
using ImplType = xo::mm::IGCObject_Xfer
<xo::scm::DVirtualSchematikaMachine,
xo::scm::IGCObject_DVirtualSchematikaMachine>;
};
}
}
namespace xo {
namespace scm {
/** @class IGCObject_DVirtualSchematikaMachine
**/
class IGCObject_DVirtualSchematikaMachine {
public:
/** @defgroup scm-gcobject-dvirtualschematikamachine-type-traits **/
///@{
using size_type = xo::mm::AGCObject::size_type;
using AAllocator = xo::mm::AGCObject::AAllocator;
using AGCObjectVisitor = xo::mm::AGCObject::AGCObjectVisitor;
using VisitReason = xo::mm::AGCObject::VisitReason;
using Copaque = xo::mm::AGCObject::Copaque;
using Opaque = xo::mm::AGCObject::Opaque;
///@}
/** @defgroup scm-gcobject-dvirtualschematikamachine-methods **/
///@{
// const methods
// non-const methods
/** move instance using object visitor.
Arguably abusing the word 'visitor' here **/
static Opaque gco_shallow_move(DVirtualSchematikaMachine & self, obj<AGCObjectVisitor> gc) noexcept;
/** Invoke fn.visit_child(iface,data) for each child GCObject pointer.
Context: provides address of data pointer so it can be updated in place
when @p fn invokes garbage collector reentry point **/
static void visit_gco_children(DVirtualSchematikaMachine & self, VisitReason reason, obj<AGCObjectVisitor> fn) noexcept;
///@}
};
} /*namespace scm*/
} /*namespace xo*/
/* end */

View file

@ -0,0 +1,55 @@
# interpreter2/CMakeLists.txt
set(SELF_LIB xo_interpreter2)
set(SELF_SRCS
init_interpreter2.cpp
SetupInterpreter2.cpp
VsmPrimitives.cpp
DVirtualSchematikaMachine.cpp
facet/IGCObject_DVirtualSchematikaMachine.cpp
DVsmDefContFrame.cpp
IGCObject_DVsmDefContFrame.cpp
IPrintable_DVsmDefContFrame.cpp
DVsmEvalArgsFrame.cpp
IGCObject_DVsmEvalArgsFrame.cpp
IPrintable_DVsmEvalArgsFrame.cpp
DVsmApplyFrame.cpp
IGCObject_DVsmApplyFrame.cpp
IPrintable_DVsmApplyFrame.cpp
DVsmApplyClosureFrame.cpp
IGCObject_DVsmApplyClosureFrame.cpp
IPrintable_DVsmApplyClosureFrame.cpp
DVsmIfElseContFrame.cpp
IGCObject_DVsmIfElseContFrame.cpp
IPrintable_DVsmIfElseContFrame.cpp
DVsmSeqContFrame.cpp
IGCObject_DVsmSeqContFrame.cpp
IPrintable_DVsmSeqContFrame.cpp
DClosure.cpp
IGCObject_DClosure.cpp
IPrintable_DClosure.cpp
DLocalEnv.cpp
facet/IGCObject_DLocalEnv.cpp
IPrintable_DLocalEnv.cpp
DVsmRcx.cpp
IRuntimeContext_DVsmRcx.cpp
VsmInstr.cpp
)
xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS})
# note: deps here must also appear in cmake/xo_interpreter2Config.cmake.in
xo_dependency(${SELF_LIB} xo_reader2)
xo_dependency(${SELF_LIB} xo_gc)

View file

@ -0,0 +1,101 @@
/** @file DClosure.cpp
*
* @author Roland Conybeare, Feb 2026
**/
#include "Closure.hpp"
#include "LambdaExpr.hpp"
#include "LocalEnv.hpp"
#include "VsmRcx.hpp"
#include <xo/object2/RuntimeError.hpp>
#include <xo/facet/FacetRegistry.hpp>
#include <xo/indentlog/scope.hpp>
#include <cstddef>
namespace xo {
using xo::mm::AGCObject;
using xo::print::APrintable;
namespace scm {
DClosure::DClosure(const DLambdaExpr * lm,
const DLocalEnv * env)
: lambda_{lm}, env_{env}
{}
DClosure *
DClosure::make(obj<AAllocator> mm,
const DLambdaExpr * lm,
const DLocalEnv * env)
{
void * mem = mm.alloc_for<DClosure>();
return new (mem) DClosure(lm, env);
}
obj<AGCObject>
DClosure::apply_nocheck(obj<ARuntimeContext> rcx,
const DArray * args)
{
// control here only if you try to invoke a closure
// as a procedure.
//
// May support this later, but requires
// nesting VSM (because call consumes c++ stack)
//
// typically prefer trampoline built into VSM
(void)args;
scope log(XO_DEBUG(true));
auto vsm_rcx
= obj<ARuntimeContext,DVsmRcx>::from(rcx);
log && log(xtag("vsm_rcx.data", (void*)vsm_rcx.data()));
auto err_mm
= vsm_rcx->error_allocator();
auto err
= DRuntimeError::make(err_mm,
"DClosure::apply_nocheck",
"not implemented");
return err;
}
DClosure *
DClosure::gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept {
return gc.std_move_for(this);
}
void
DClosure::visit_gco_children(VisitReason reason,
obj<AGCObjectVisitor> gc) noexcept
{
gc.visit_child(reason, &lambda_);
gc.visit_child(reason, &env_);
}
// ----- printable facet -----
bool
DClosure::pretty(const ppindentinfo & ppii) const
{
obj<APrintable,DLambdaExpr> lambda_pr(const_cast<DLambdaExpr *>(lambda_));
obj<APrintable,DLocalEnv> env_pr(const_cast<DLocalEnv *>(env_));
bool lambda_present = lambda_pr;
bool env_present = env_pr;
return ppii.pps()->pretty_struct
(ppii,
"DClosure",
refrtag("lambda", lambda_pr, lambda_present),
refrtag("env", env_pr, env_present));
}
} /*namespace scm*/
} /*namespace xo*/
/* end DClosure.cpp */

View file

@ -0,0 +1,128 @@
/** @file DLocalEnv.cpp
*
* @author Roland Conybeare, Feb 2026
**/
#include "LocalEnv.hpp"
#include <xo/object2/Array.hpp>
#include <xo/reflectutil/typeseq.hpp>
#include <xo/indentlog/scope.hpp>
namespace xo {
using xo::mm::AGCObject;
using xo::reflect::typeseq;
namespace scm {
DLocalEnv::DLocalEnv(DLocalEnv * parent,
DLocalSymtab * symtab,
DArray * args)
: parent_{parent},
symtab_{symtab},
args_{args}
{}
DLocalEnv *
DLocalEnv::_make(obj<AAllocator> mm,
DLocalEnv * parent,
DLocalSymtab * symtab,
DArray * args)
{
assert(symtab);
void * mem = mm.alloc_for<DLocalEnv>();
return new (mem) DLocalEnv(parent, symtab, args);
}
obj<AGCObject>
DLocalEnv::lookup_value(Binding ix) const noexcept
{
assert(!ix.is_global());
const DLocalEnv * env = this;
for (auto i = ix.i_link(); i > 0; --i) {
env = env->parent();
}
if (env) {
auto j = ix.j_slot();
if (j < static_cast<decltype(j)>(env->n_vars())) {
return (*(env->args_))[j];
} else {
assert(false);
}
} else {
assert(false);
}
/* something terribly wrong if control here */
return obj<AGCObject>();
}
void
DLocalEnv::assign_value(obj<AAllocator> mm,
Binding ix,
obj<AGCObject> x)
{
scope log(XO_DEBUG(true));
assert(!ix.is_global());
const DLocalEnv * env = this;
for (auto i = ix.i_link(); i > 0; --i) {
env = env->parent();
}
if (env) {
auto j = ix.j_slot();
if (j < static_cast<decltype(j)>(env->n_vars())) {
env->args_->assign_at(mm, j, x);
} else {
assert(false);
}
} else {
assert(false);
}
/* something terribly wrong if control here */
}
DLocalEnv *
DLocalEnv::gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept {
return gc.std_move_for(this);
}
void
DLocalEnv::visit_gco_children(VisitReason reason,
obj<AGCObjectVisitor> gc) noexcept
{
gc.visit_child(reason, &parent_);
gc.visit_child(reason, &symtab_);
gc.visit_child(reason, &args_);
}
// ----- printable facet -----
bool
DLocalEnv::pretty(const ppindentinfo & ppii) const noexcept
{
// print local bindings, perhaps
// symtab_
// args_
return ppii.pps()->pretty_struct
(ppii,
"DLocalEnv",
refrtag("n_args", args_->size())
);
}
} /*namespace scm*/
} /*namespace xo*/
/* end DLocalEnv.cpp */

View file

@ -0,0 +1,995 @@
/** @file VirtualSchematikaMachine.cpp
*
* @author Roland Conybeare, Jan 2026
**/
#include "VirtualSchematikaMachine.hpp"
#include "DPrimitive_gco_3_dict_string_gco.hpp"
#include "DPrimitive_gco_2_gco_gco.hpp"
#include "VsmDefContFrame.hpp"
#include "VsmApplyFrame.hpp"
#include "VsmEvalArgsFrame.hpp"
#include "VsmApplyClosureFrame.hpp"
#include "VsmIfElseContFrame.hpp"
#include "VsmSeqContFrame.hpp"
#include "VsmRcx.hpp"
#include "Closure.hpp"
#include <xo/object2/Sequence.hpp>
#include <xo/object2/List.hpp>
#include <xo/numeric/NumericDispatch.hpp>
#include <xo/expression2/DefineExpr.hpp>
#include <xo/expression2/ApplyExpr.hpp>
#include <xo/expression2/LambdaExpr.hpp>
#include <xo/expression2/Constant.hpp>
#include <xo/expression2/SequenceExpr.hpp>
#include <xo/object2/Dictionary.hpp>
#include <xo/object2/Integer.hpp>
#include <xo/object2/Boolean.hpp>
#include <xo/procedure2/RuntimeContext.hpp>
#include <xo/procedure2/Primitive_gco_0.hpp>
#include <xo/procedure2/Primitive_gco_1_gco.hpp>
#include <xo/procedure2/Primitive_gco_2_gco_gco.hpp>
#include <xo/procedure2/Primitive_gco_3_dict_string_gco.hpp>
#include <xo/gc/X1Collector.hpp>
#include <xo/reflect/Reflect.hpp>
#include <xo/stringtable2/UniqueString.hpp>
#include <xo/alloc2/CollectorTypeRegistry.hpp>
#include <xo/alloc2/Arena.hpp>
#include <xo/printable2/Printable.hpp>
#include <xo/facet/FacetRegistry.hpp>
#include <cassert>
namespace xo {
using xo::scm::DDictionary;
using xo::print::APrintable;
using xo::print::ppconfig;
using xo::print::ppstate_standalone;
using xo::reflect::Reflect;
using xo::mm::AGCObject;
using xo::mm::MemorySizeInfo;
using xo::mm::CollectorTypeRegistry;
using xo::mm::AAllocator;
using xo::mm::ACollector;
using xo::mm::DX1Collector;
using xo::mm::X1CollectorConfig;
using xo::mm::DArena;
using xo::facet::FacetRegistry;
using xo::facet::TypeRegistry;
using std::cout;
namespace scm {
bool
VsmResult::is_error() const
{
return (*this->value() && obj<AGCObject,DRuntimeError>::from(*(this->value())));
}
namespace {
/** helper function to create X1 collector instance **/
abox<AAllocator,DX1Collector>
vsm_make_gc(obj<AAllocator> aux_mm,
const X1CollectorConfig & config)
{
auto retval = abox<AAllocator,DX1Collector>::make(aux_mm, config);
// establish the set of types that mm_ will be able to collect
CollectorTypeRegistry::instance().install_types
(retval.to_op().to_facet<ACollector>());
return retval;
}
}
// NOTE: using heap here for {DX1Collector, DArena, DVsmRcx} instances
// (though DX1Collector allocations will be from explictly mmap'd memory)
//
DVirtualSchematikaMachine::DVirtualSchematikaMachine(const VsmConfig & config,
obj<AAllocator> aux_mm)
: config_{config},
self_vroot_{obj<AGCObject,DVirtualSchematikaMachine>(this)},
aux_mm_{aux_mm},
mm_(vsm_make_gc(aux_mm_, config.x1_config_)),
rcx_(abox<ARuntimeContext,DVsmRcx>::make(aux_mm_, this)),
reader_{config.rdr_config_, mm_.to_op(), aux_mm_}
{
{
DArena * arena = new DArena(config_.error_config_);
assert(arena);
this->error_mm_.adopt(obj<AAllocator,DArena>(arena));
}
this->global_env_
= obj<AGCObject,DGlobalEnv>(reader_.global_env());
// TODO:
// annoying to have to create self_vroot_ to appease
// add_gc_root_poly() signature.
// In practice gc won't modify the pointer
// (instead traverses it to find +update children)
//
mm_.to_op().to_facet<ACollector>().add_gc_root_poly(&self_vroot_);
}
DVirtualSchematikaMachine *
DVirtualSchematikaMachine::_make(obj<AAllocator> mm,
const VsmConfig & config,
obj<AAllocator> aux_mm)
{
void * mem = mm.alloc_for<DVirtualSchematikaMachine>();
return new (mem) DVirtualSchematikaMachine(config, aux_mm);
}
obj<AGCObject,DVirtualSchematikaMachine>
DVirtualSchematikaMachine::make(obj<AAllocator> mm,
const VsmConfig & config,
obj<AAllocator> aux_mm)
{
return obj<AGCObject,DVirtualSchematikaMachine>(
_make(mm, config, aux_mm));
}
obj<AAllocator>
DVirtualSchematikaMachine::allocator() const noexcept
{
return mm_.to_op();
}
obj<AAllocator>
DVirtualSchematikaMachine::error_allocator() const noexcept
{
return error_mm_.to_op();
}
StringTable *
DVirtualSchematikaMachine::stringtable() noexcept
{
return reader_.stringtable();
}
bool
DVirtualSchematikaMachine::is_at_toplevel() const noexcept
{
return reader_.is_at_toplevel();
}
void
DVirtualSchematikaMachine::visit_pools(const MemorySizeVisitor & visitor) const
{
aux_mm_.visit_pools(visitor);
mm_.visit_pools(visitor);
error_mm_.visit_pools(visitor);
reader_.visit_pools(visitor);
}
void
DVirtualSchematikaMachine::begin_interactive_session()
{
reader_.begin_interactive_session();
}
void
DVirtualSchematikaMachine::begin_batch_session()
{
reader_.begin_batch_session();
}
VsmResultExt
DVirtualSchematikaMachine::read_eval_print(span_type input, bool eof)
{
if (input.empty()) {
return VsmResultExt();
}
reader_.reset_result();
auto [expr, remaining, tk_error]
= reader_.read_expr(input, eof);
if (!expr) {
if (tk_error.is_error()) {
// tokenizer error -> convert to runtime error
DString * src = DString::from_view(mm_.to_op(), tk_error.src_function());
DString * msg = tk_error.report_to_string(mm_.to_op());
auto error = obj<AGCObject,DRuntimeError>(DRuntimeError::_make(mm_.to_op(), src, msg));
this->value_ = VsmResult(error);
{
obj<APrintable> error_pr
= FacetRegistry::instance().variant<APrintable,AGCObject>(error);
ppconfig ppc;
ppstate_standalone pps(&cout, 0, &ppc);
pps.prettyn(error_pr);
}
return VsmResultExt(value_, remaining);
} else {
// incomplete input
return VsmResultExt(VsmResult(), remaining);
}
}
// here: have obtained complete input expression
const VsmResult & evalresult = this->start_eval(expr);
if (evalresult.is_error()) {
// TODO: print error here
return VsmResultExt(evalresult, remaining);
}
assert(evalresult.is_value());
obj<AGCObject> value = evalresult.result_;
assert(value);
{
obj<APrintable> value_pr
= FacetRegistry::instance().variant<APrintable,AGCObject>(value);
// pretty_toplevel(value_pr, &cout, ppconfig());
ppconfig ppc;
ppstate_standalone pps(&cout, 0, &ppc);
pps.prettyn(value_pr);
}
return VsmResultExt(evalresult, remaining);
}
const VsmResult &
DVirtualSchematikaMachine::start_eval(obj<AExpression> expr)
{
this->pc_ = VsmInstr::c_eval;
this->expr_ = expr;
this->value_ = VsmResult(obj<AGCObject>());
this->cont_ = VsmInstr::c_halt;
this->run();
return value_;
}
void
DVirtualSchematikaMachine::run()
{
while (this->execute_one())
;
}
bool
DVirtualSchematikaMachine::execute_one()
{
scope log(XO_DEBUG(config_.debug_flag_));
log && log(xtag("pc", pc_),
xtag("cont", cont_));
auto expr_pr = expr_.to_facet<APrintable>();
if (expr_pr)
log && log(xtag("expr", expr_pr));
if (value_.value()) {
auto value_pr
= const_cast<obj<AGCObject> *>(value_.value())->to_facet<APrintable>();
if (value_pr)
log && log(xtag("value", value_pr));
} else {
log && log("value not present or tk error");
}
auto stack_pr = stack_.to_facet<APrintable>();
if (stack_pr)
log && log(xtag("stack", stack_pr));
switch (pc_.opcode()) {
case vsm_opcode::sentinel:
case vsm_opcode::halt:
case vsm_opcode::N:
return false;
case vsm_opcode::eval:
_do_eval_op();
break;
case vsm_opcode::apply:
_do_apply_op();
break;
case vsm_opcode::evalargs:
_do_evalargs_op();
break;
case vsm_opcode::def_cont:
_do_def_cont_op();
break;
case vsm_opcode::apply_cont:
_do_apply_cont_op();
break;
case vsm_opcode::ifelse_cont:
_do_ifelse_cont_op();
break;
case vsm_opcode::seq_cont:
_do_seq_cont_op();
break;
}
return true;
}
void
DVirtualSchematikaMachine::_do_eval_op()
{
switch(expr_.extype()) {
case exprtype::invalid:
case exprtype::N:
break;
case exprtype::constant:
_do_eval_constant_op();
break;
case exprtype::define:
_do_eval_define_op();
break;
case exprtype::lambda:
_do_eval_lambda_op();
break;
case exprtype::variable:
_do_eval_variable_op();
break;
case exprtype::varref:
_do_eval_varref_op();
break;
case exprtype::apply:
_do_eval_apply_op();
break;
case exprtype::ifexpr:
_do_eval_if_else_op();
break;
case exprtype::sequence:
_do_eval_sequence_op();
break;
}
}
void
DVirtualSchematikaMachine::_do_eval_constant_op()
{
auto expr
= obj<AExpression,DConstant>::from(expr_);
this->value_ = VsmResult(expr.data()->value());
this->pc_ = this->cont_;
this->cont_ = VsmInstr::c_sentinel;
}
void
DVirtualSchematikaMachine::_do_eval_define_op()
{
scope log(XO_DEBUG(true));
auto def_expr
= obj<AExpression,DDefineExpr>::from(expr_);
if (local_env_) {
// nested defines implemented by rewriting,
// so this branch should be unreachable
assert(false);
} else {
// top-level define
// .stack_ --+
// |
// v
// +------DVsmDefContFrame------+
// | .parent x | .cont | .def x |
// +---------|-+-------+------|-+
// | |
// ParserStack* <-----/ |
// |
// v
// DDefineExpr
/* stack frame for nested continuation
* (to perform assignment)
*/
auto defcont_frame
= obj<AGCObject,DVsmDefContFrame>
(DVsmDefContFrame::make(mm_.to_op(),
this->stack_ /*saved stack*/,
this->cont_ /*saved cont*/,
def_expr.data() /*saved expr*/));
this->stack_ = defcont_frame;
// setup evaluation of rhs
this->expr_ = def_expr->rhs();
this->pc_ = VsmInstr::c_eval;
this->cont_ = VsmInstr::c_def_cont;
}
}
void
DVirtualSchematikaMachine::_do_def_cont_op()
{
// see DVsmDefContFrame
auto frame = obj<AGCObject,DVsmDefContFrame>::from(stack_);
assert(frame);
assert(value_.is_value());
// TODO: verify that value satisfies expected type ?
DVariable * lhs = frame->def_expr()->lhs();
obj<AGCObject> rhs = *value_.value();
assert(lhs->path().is_global());
global_env_->assign_value(mm_.to_op(), lhs->path(), rhs);
// TODO: unfortunate const_cast here, because obj<> doesn't support const DRepr yet
this->value_ = VsmResult(obj<AGCObject,DUniqueString>(const_cast<DUniqueString*>(lhs->name())));
this->stack_ = frame->parent();
this->pc_ = frame->cont();
this->cont_ = VsmInstr::c_sentinel;
}
void
DVirtualSchematikaMachine::_do_eval_lambda_op()
{
// assuming bump allocator
//
// +----------- DArray---------+ +-------------DLocalEnv-----------+ +-----DClosure-------+
// | .cap |.size | .elts_[]... |h| .parent x | .symtab x | .args x |h| .lambda x | .env x |
// +------+------+-------------+ +---------|-+---------|-+-------|-+ +---------|-+------|-+
// ^ ^ | | | | |
// \-----------------------------|---------|-----------|---------/ | |
// | | | | |
// \---------|-----------|-----------------------|--------/
// | | |
// <--------------------------------------/ | |
// | |
// v v
// DLocalSymtab DLambdaExpr
//
// DClosure runtime procedure (created below)
// DArray bound non-local variables (established by VSM)
// DLocalEnv local environment (copy ref from VSM state)
// h alloc header
// DLocalSymtab local symbol table (created by parser)
// DLambdaExpr lambda expression (created by parser)
//
// will create DClosure with local_env_
// local_env_
// global_env_
auto lambda
= obj<AExpression,DLambdaExpr>::from(expr_);
DClosure * closure = DClosure::make(mm_.to_op(),
lambda.data(),
local_env_.data());
this->value_
= VsmResult(obj<AGCObject>(obj<AGCObject,DClosure>(closure)));
this->pc_ = this->cont_;
this->cont_ = VsmInstr::c_sentinel;
}
void
DVirtualSchematikaMachine::_do_eval_variable_op()
{
// not implemented
assert(false);
}
void
DVirtualSchematikaMachine::_do_eval_varref_op()
{
auto var = obj<AExpression,DVarRef>::from(expr_);
Binding b = var->path();
obj<AGCObject> value;
if (b.is_local() && local_env_) {
value = local_env_->lookup_value(b);
} else if (b.is_global()) {
value = global_env_->lookup_value(b);
}
if (value) {
this->value_ = VsmResult(value);
this->pc_ = this->cont_;
this->cont_ = VsmInstr::c_sentinel;
return;
}
// no local or global binding
auto error = DRuntimeError::make(mm_.to_op(),
"_do_eval_varref_op",
"no binding for variable");
this->value_ = VsmResult(error);
// for now: halt VSM execution
// TODO: some combination of
// 1. emit stack trace
// 2. go to debugger
// 3. have every vsm instruction check inputs for errors
this->pc_ = VsmInstr::c_halt;
this->cont_ = VsmInstr::c_sentinel;
}
void
DVirtualSchematikaMachine::_do_eval_apply_op()
{
// ApplyExpr in expr_ register
// assuming bump allocator:
//
// DArray VsmApplyFrame VsmEvalArgsFrame
// v v v
// +----------------------+-------+-------+----+--------+-------+-------+-------+
// | argument expressions | par x | cont1 | fn | args x | par x | cont2 | i_arg |
// +----------------------+-----|-+-------+----+------|-+-----|-+-------+-------+
// ^ ^ | | |
// | \-----------------------------------/
// \ | /
// \------------------------------------------------/
// /
// <---------------------------/
//
// - VsmEvalArgsFrame: owned by VSM, state for evalargs loop
// - VsmApplyFrame: owned by VSM, state for transferring control to called function
// - DArray: contains evaluated args; owned by called primitive
// - cont2: always c_apply
//
auto apply = obj<AExpression,DApplyExpr>::from(expr_);
// accumulate evaluated arguments here
DArray * args = DArray::_empty(mm_.to_op(),
apply->n_args());
// TODO: check function signature
DVsmApplyFrame * apply_frame
= DVsmApplyFrame::make(mm_.to_op(), stack_, cont_, args);
auto evalargs_frame
= obj<AGCObject,DVsmEvalArgsFrame>
(DVsmEvalArgsFrame::make(mm_.to_op(),
apply_frame, VsmInstr::c_apply, apply.data()));
this->stack_ = evalargs_frame;
// Setup evaluation of first argument. No new stack for this.
this->expr_ = apply->fn();
this->pc_ = VsmInstr::c_eval;
this->cont_ = VsmInstr::c_evalargs;
}
void
DVirtualSchematikaMachine::_do_eval_if_else_op()
{
// control:
// self -> eval(test) -> ifelse_cont -> eval(when_true)
// -> eval(when_false)
auto ifelse_expr = obj<AExpression,DIfElseExpr>::from(expr_);
obj<AGCObject,DVsmIfElseContFrame> ifelse_frame
(DVsmIfElseContFrame::make(mm_.to_op(),
stack_, cont_, ifelse_expr.data()));
this->stack_ = ifelse_frame;
this->expr_ = ifelse_expr->test();
this->pc_ = VsmInstr::c_eval;
this->cont_ = VsmInstr::c_ifelse_cont;
}
void
DVirtualSchematikaMachine::_do_eval_sequence_op()
{
// stack:
//
// 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->expr_ = (*seq_expr.data())[0];
this->pc_ = VsmInstr::c_eval;
this->cont_ = VsmInstr::c_seq_cont;
}
void
DVirtualSchematikaMachine::_do_apply_op()
{
// rcx_ : runtime context
// fn_ : function to call
// args_ : array of arguments
// TODO: check argument types
auto closure = obj<AGCObject,DClosure>::from(fn_);
if (closure) {
_do_call_closure_op();
return;
} else {
_do_call_primitive_op();
return;
}
}
void
DVirtualSchematikaMachine::_do_call_closure_op()
{
// We need to preserve registers while evaluating
// lambda body
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
// we can just refer to it instead of pushing a new one
if (cont_ == VsmInstr::c_apply_cont) {
// we are making a tail call.
// No need to preserve (stack, cont, local_env),
// since continuation will restore on top of them
// frame top stackframe anyway
} else {
obj<AGCObject,
DVsmApplyClosureFrame> frame(
DVsmApplyClosureFrame::make(mm_.to_op(),
stack_,
cont_,
local_env_.data()));
// push frame w/ saved vsm registers
this->stack_ = frame;
this->cont_ = VsmInstr::c_apply_cont;
}
auto lambda = closure->lambda();
auto local_env
= DLocalEnv::_make(mm_.to_op(),
local_env_.data(),
lambda->local_symtab(),
args_.data());
this->local_env_ = obj<AGCObject,DLocalEnv>(local_env);
this->expr_ = lambda->body_expr();
this->pc_ = VsmInstr::c_eval;
// cont_ already established
}
void
DVirtualSchematikaMachine::_do_call_primitive_op()
{
auto fn = fn_.to_facet<AProcedure>();
this->value_ = VsmResult(fn.apply_nocheck(rcx_.to_op(), args_.data()));
this->pc_ = cont_;
this->cont_ = VsmInstr::c_sentinel;
}
void
DVirtualSchematikaMachine::_do_evalargs_op()
{
scope log(XO_DEBUG(false));
if (!value_.is_value()) {
// error while evaluating function arg
log.retroactively_enable();
log && log("error in apply -> terminating app");
this->pc_ = VsmInstr::c_halt;
this->cont_ = VsmInstr::c_sentinel;
return;
}
// here: nested evaluation succeeded
// value of one of {fn, arg(i), ..} in fn(arg0 .. arg(n-1))
//
obj<AGCObject> value = *(value_.value());
// value_ in [i_arg] value_
// . (if i_arg >= 0) . (if i_arg = -1)
// . .
// DArray . VsmApplyFrame . VsmEvalArgsFrame
// v v v v v
// +----------------------+-------+-------+----+--------+-------+-------+--------+-------+
// | argument expressions | par o | cont1 | fn | args x | par o | cont2 | applyx | i_arg |
// +----------------------+-----|-+-------+----+------|-+-----|-+-------+--------+-------+
// ^ ^ | | |
// | \-----------------------------------/
// \ | /
// \------------------------------------------------/
// /
// <---------------------------/
//
// - VsmEvalArgsFrame: owned by VSM, state for evalargs loop
// - VsmApplyFrame: owned by VSM, state for transferring control to called function
// - DArray: contains evaluated args; owned by called primitive
// - i_arg
// if -1: value_ register holds function
// if >=0: value_ register holds i'th function argument
//
auto evalargs_frame
= obj<AGCObject,DVsmEvalArgsFrame>::from(stack_);
assert(evalargs_frame);
int32_t i_arg = evalargs_frame->i_arg();
DVsmApplyFrame * apply_frame = evalargs_frame->parent();
const DApplyExpr * apply_expr
= evalargs_frame->apply_expr();
if (i_arg == -1) {
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);
i_arg = evalargs_frame->increment_arg();
// now i_arg is 0 -> evaluate that argument
if (i_arg >= static_cast<int32_t>(apply_expr->n_args())) {
// corner case: function with 0 arguments
this->fn_ = apply_frame->fn(); // = value;
this->args_ = obj<AGCObject,DArray>(apply_frame->args()); // empty
this->stack_ = apply_frame->parent();
this->pc_ = VsmInstr::c_apply;
this->cont_ = apply_frame->cont();
return;
} else {
this->expr_ = apply_expr->arg(i_arg);
this->pc_ = VsmInstr::c_eval;
this->cont_ = VsmInstr::c_evalargs;
return;
}
} else {
// error - function position must deliver something with AProcedure?
// or DClosure, but we'll get to that.
log.retroactively_enable();
log("expected procedure in function position -> terminate");
assert(false);
}
} else {
DArray * args = apply_frame->args();
log && log(xtag("i_arg", i_arg), xtag("n_arg", args->size()), xtag("cap", args->capacity()));
args->push_back(mm_.to_op(), value);
i_arg = evalargs_frame->increment_arg();
if (i_arg == static_cast<int32_t>(apply_expr->n_args())) {
// all apply-arguments have been evaluated
// -> done with VsmEvalArgsFrame
//
this->fn_ = apply_frame->fn();
this->args_ = obj<AGCObject,DArray>(apply_frame->args());
this->stack_ = apply_frame->parent();
this->pc_ = VsmInstr::c_apply;
this->cont_ = apply_frame->cont();
return;
} else {
this->expr_ = apply_expr->arg(i_arg);
this->pc_ = VsmInstr::c_eval;
this->cont_ = VsmInstr::c_evalargs;
return;
}
}
// not implemented
assert(false);
}
void
DVirtualSchematikaMachine::_do_apply_cont_op()
{
// see DVsmApplyClosureFrame
auto frame = obj<AGCObject,DVsmApplyClosureFrame>::from(stack_);
assert(frame);
this->stack_ = frame->parent();
this->local_env_ = obj<AGCObject,DLocalEnv>(frame->local_env());
this->pc_ = frame->cont();
this->cont_ = VsmInstr::c_sentinel;
}
void
DVirtualSchematikaMachine::_do_ifelse_cont_op()
{
// pre: result of evaluating test condition in value_ register
auto frame = obj<AGCObject,DVsmIfElseContFrame>::from(stack_);
assert(frame);
assert(value_.is_value());
auto flag = obj<AGCObject,DBoolean>::from(*value_.value());
if (flag.data()) {
obj<AExpression> next_expr;
{
if (flag->value()) {
// proceed with if-branch
next_expr = frame->ifelse_expr()->when_true();
} else {
// proceed with else-branch
next_expr = frame->ifelse_expr()->when_false();
}
}
this->stack_ = frame->parent();
this->expr_ = next_expr;
this->pc_ = VsmInstr::c_eval;
this->cont_ = frame->cont();
} else {
auto error = DRuntimeError::make(mm_.to_op(),
"_do_ifelse_cont_op",
"expected boolean for test condition");
this->value_ = VsmResult(error);
// for now: halt VSM execution
// TODO: some combination of
// 1. emit stack trace
// 2. go to debugger
// 3. have every vsm instruction check inputs for errors
this->pc_ = VsmInstr::c_halt;
this->cont_ = VsmInstr::c_sentinel;
}
}
void
DVirtualSchematikaMachine::_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();
this->cont_ = VsmInstr::c_sentinel;
return;
} else {
frame->incr_i_seq();
this->expr_ = (*seq_expr)[i_seq];
this->pc_ = VsmInstr::c_eval;
this->cont_ = VsmInstr::c_seq_cont;
return;
}
}
std::size_t
DVirtualSchematikaMachine::shallow_size() const noexcept
{
return sizeof(DVirtualSchematikaMachine);
}
DVirtualSchematikaMachine *
DVirtualSchematikaMachine::gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept
{
// need move-ctor on abox<..>
//return gc.std_move_for(this);
(void)gc;
/** TODO: should be able to use gc.std_move_for(this) now
* that shallow_move uses move construction.
* DVirtualSchematikaMachine is (or can be made) moveable.
**/
assert(false);
return nullptr;
}
void
DVirtualSchematikaMachine::visit_gco_children(VisitReason reason,
obj<AGCObjectVisitor> gc) noexcept
{
reader_.visit_gco_children(reason, gc);
gc.visit_child(reason, &stack_);
gc.visit_poly_child(reason, &expr_);
gc.visit_child(reason, &global_env_);
gc.visit_child(reason, &local_env_);
gc.visit_child(reason, &fn_);
gc.visit_child(reason, &args_);
if (value_.is_value()) {
gc.visit_child(reason, const_cast<obj<AGCObject> *>(&value_.value_ref()));
}
}
} /*namespace scm*/
} /*namespace xo*/
/* end DVirtualSchematikaMachine.cpp */

View file

@ -0,0 +1,61 @@
/** @file DVsmApplyClosureFrame.cpp
*
* @author Roland Conybeare, Feb 2026
**/
#include "DVsmApplyClosureFrame.hpp"
#include "LocalEnv.hpp"
namespace xo {
using xo::mm::AGCObject;
using xo::reflect::typeseq;
namespace scm {
DVsmApplyClosureFrame::DVsmApplyClosureFrame(obj<AGCObject> stack,
VsmInstr cont,
DLocalEnv * local_env)
: stack_{stack},
cont_{cont},
local_env_{local_env}
{}
DVsmApplyClosureFrame *
DVsmApplyClosureFrame::make(obj<AAllocator> mm,
obj<AGCObject> stack,
VsmInstr cont,
DLocalEnv * local_env)
{
void * mem = mm.alloc(typeseq::id<DVsmApplyClosureFrame>(),
sizeof(DVsmApplyClosureFrame));
return new (mem) DVsmApplyClosureFrame(stack, cont, local_env);
}
DVsmApplyClosureFrame *
DVsmApplyClosureFrame::gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept
{
return gc.std_move_for(this);
}
void
DVsmApplyClosureFrame::visit_gco_children(VisitReason reason,
obj<AGCObjectVisitor> gc) noexcept
{
gc.visit_child(reason, &stack_);
gc.visit_child(reason, &local_env_);
}
bool
DVsmApplyClosureFrame::pretty(const ppindentinfo & ppii) const
{
return ppii.pps()->pretty_struct
(ppii,
"DVsmApplyClosureFrame",
refrtag("cont", cont_),
refrtag("env", local_env_));
}
} /*namespace scm*/
} /*namespace xo*/
/* end DVsmApplyClosureFrame.cpp */

View file

@ -0,0 +1,70 @@
/** @file DVsmApplyFrame.cpp
*
* @author Roland Conybeare, Feb 2026
**/
#include "DVsmApplyFrame.hpp"
#include <xo/object2/Array.hpp>
#include <xo/indentlog/print/pretty.hpp>
namespace xo {
using xo::facet::typeseq;
namespace scm {
DVsmApplyFrame::DVsmApplyFrame(obj<AGCObject> old_parent,
VsmInstr old_cont,
DArray * args)
: parent_{old_parent},
cont_{old_cont},
args_{args}
{}
DVsmApplyFrame *
DVsmApplyFrame::make(obj<AAllocator> mm,
obj<AGCObject> old_parent,
VsmInstr old_cont,
DArray * args)
{
DVsmApplyFrame * result = nullptr;
void * mem = mm.alloc(typeseq::id<DVsmApplyFrame>(),
sizeof(DVsmApplyFrame));
result = new (mem) DVsmApplyFrame(old_parent,
old_cont,
args);
assert(result);
return result;
}
DVsmApplyFrame *
DVsmApplyFrame::gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept
{
return gc.std_move_for(this);
}
void
DVsmApplyFrame::visit_gco_children(VisitReason reason,
obj<AGCObjectVisitor> gc) noexcept
{
gc.visit_child(reason, &parent_);
gc.visit_child(reason, &fn_);
gc.visit_child(reason, &args_);
}
bool
DVsmApplyFrame::pretty(const ppindentinfo & ppii) const
{
return ppii.pps()->pretty_struct(ppii,
"DVsmApplyFrame",
refrtag("cont", cont_),
refrtag("n_args", args_->size()));
}
} /*namespace scm*/
} /*namespace xo*/
/* end DVsmApplyFrame.cpp */

View file

@ -0,0 +1,61 @@
/** @file DVsmDefContFrame.cpp
*
* @author Roland Conybeare, Feb 2026
**/
#include "DVsmDefContFrame.hpp"
#include <xo/expression2/DefineExpr.hpp>
#include <xo/alloc2/Collector.hpp>
namespace xo {
namespace scm {
DVsmDefContFrame::DVsmDefContFrame(obj<AGCObject> parent,
VsmInstr cont,
DDefineExpr * def_expr)
: parent_{parent},
cont_{cont},
def_expr_{def_expr}
{}
DVsmDefContFrame *
DVsmDefContFrame::make(obj<AAllocator> mm,
obj<AGCObject> parent,
VsmInstr cont,
DDefineExpr * def_expr)
{
void * mem = mm.alloc_for<DVsmDefContFrame>();
return new (mem) DVsmDefContFrame(parent, cont, def_expr);
}
// gcobject facet
DVsmDefContFrame *
DVsmDefContFrame::gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept
{
return gc.std_move_for<DVsmDefContFrame>(this);
}
void
DVsmDefContFrame::visit_gco_children(VisitReason reason,
obj<AGCObjectVisitor> gc) noexcept
{
gc.visit_child(reason, &parent_);
gc.visit_child(reason, &def_expr_);
}
// printable facet
bool
DVsmDefContFrame::pretty(const ppindentinfo & ppii) const noexcept
{
return ppii.pps()->pretty_struct(ppii,
"DVsmDefContFrame",
refrtag("cont", cont_));
}
} /*namespace scm*/
} /*namespace xo*/
/* end DVsmDefContFrame.cpp */

View file

@ -0,0 +1,69 @@
/** @file DVsmEvalArgsFrame.cpp
*
* @author Roland Conybeare, Feb 2026
**/
#include "DVsmEvalArgsFrame.hpp"
#include <xo/expression2/ApplyExpr.hpp>
#include <xo/indentlog/print/pretty.hpp>
namespace xo {
using xo::facet::typeseq;
using xo::print::ppindentinfo;
namespace scm {
// ----- VsmEvalArgsFrame -----
DVsmEvalArgsFrame::DVsmEvalArgsFrame(DVsmApplyFrame * parent,
VsmInstr cont,
DApplyExpr * apply_expr)
: parent_{parent},
cont_{cont},
apply_expr_{apply_expr}
{}
DVsmEvalArgsFrame *
DVsmEvalArgsFrame::make(obj<AAllocator> mm,
DVsmApplyFrame * apply_frame,
VsmInstr cont,
DApplyExpr * apply_expr)
{
DVsmEvalArgsFrame * result = nullptr;
void * mem = mm.alloc(typeseq::id<DVsmEvalArgsFrame>(),
sizeof(DVsmEvalArgsFrame));
result = new (mem) DVsmEvalArgsFrame(apply_frame, cont, apply_expr);
assert(result);
return result;
}
DVsmEvalArgsFrame *
DVsmEvalArgsFrame::gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept
{
return gc.std_move_for(this);
}
void
DVsmEvalArgsFrame::visit_gco_children(VisitReason reason,
obj<AGCObjectVisitor> gc) noexcept
{
gc.visit_child(reason, &parent_);
gc.visit_child(reason, &apply_expr_);
}
bool
DVsmEvalArgsFrame::pretty(const ppindentinfo & ppii) const
{
return ppii.pps()->pretty_struct(ppii,
"DVsmEvalArgsFrame",
refrtag("cont", cont_),
refrtag("i_arg", i_arg_));
}
} /*namespace scm*/
} /*namespace xo*/
/* end VsmEvalArgsFrame.cpp */

View file

@ -0,0 +1,59 @@
/** @file DVsmIfElseContFrame.cpp
*
* @author Roland Conybeare, Feb 2026
**/
#include "DVsmIfElseContFrame.hpp"
namespace xo {
namespace scm {
DVsmIfElseContFrame::DVsmIfElseContFrame(obj<AGCObject> parent,
VsmInstr cont,
DIfElseExpr * ifelse_expr)
: parent_{parent},
cont_{cont},
ifelse_expr_{ifelse_expr}
{}
DVsmIfElseContFrame *
DVsmIfElseContFrame::make(obj<AAllocator> mm,
obj<AGCObject> parent,
VsmInstr cont,
DIfElseExpr * seq_expr)
{
void * mem = mm.alloc_for<DVsmIfElseContFrame>();
return new (mem) DVsmIfElseContFrame(parent, cont, seq_expr);
}
// gcobject facet
DVsmIfElseContFrame *
DVsmIfElseContFrame::gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept
{
return gc.std_move_for<DVsmIfElseContFrame>(this);
}
void
DVsmIfElseContFrame::visit_gco_children(VisitReason reason,
obj<AGCObjectVisitor> gc) noexcept
{
gc.visit_child(reason, &parent_);
gc.visit_child(reason, &ifelse_expr_);
}
// printable facet
bool
DVsmIfElseContFrame::pretty(const ppindentinfo & ppii) const noexcept
{
return ppii.pps()->pretty_struct(ppii,
"DVsmIfElseContFrame",
refrtag("cont", cont_));
}
} /*namespace scm*/
} /*namespace xo*/
/* end DVsmIfElseContFrame.cpp */

View file

@ -0,0 +1,51 @@
/** @file DVsmRcx.cpp
*
* @author Roland Conybeare, Feb 2026
**/
#include "DVsmRcx.hpp"
#include "VirtualSchematikaMachine.hpp"
#include <xo/facet/FacetRegistry.hpp>
namespace xo {
using xo::mm::AAllocator;
using xo::mm::ACollector;
namespace scm {
DVsmRcx::DVsmRcx(DVirtualSchematikaMachine * vsm) : vsm_{vsm} {}
obj<AAllocator>
DVsmRcx::allocator() const noexcept
{
return vsm_->allocator();
}
obj<ACollector>
DVsmRcx::collector() const noexcept
{
return vsm_->allocator().try_to_facet<ACollector>();
}
obj<AAllocator>
DVsmRcx::error_allocator() const noexcept
{
return vsm_->error_allocator();
}
StringTable *
DVsmRcx::stringtable() const noexcept
{
return vsm_->stringtable();
}
void
DVsmRcx::visit_pools(const MemorySizeVisitor & visitor) const
{
vsm_->visit_pools(visitor);
}
} /*namespace scm*/
} /*namespace xo*/
/* end DVsmRcx.cpp */

View file

@ -0,0 +1,63 @@
/** @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
DVsmSeqContFrame *
DVsmSeqContFrame::gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept
{
return gc.std_move_for(this);
}
void
DVsmSeqContFrame::visit_gco_children(VisitReason reason,
obj<AGCObjectVisitor> gc) noexcept
{
gc.visit_child(reason, &parent_);
gc.visit_child(reason, &seq_expr_);
}
// 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,32 @@
/** @file IGCObject_DClosure.cpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IGCObject_DClosure.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_any.hpp.j2]
* 3. idl for facet methods
* [idl/IGCObject_DClosure.json5]
**/
#include "detail/IGCObject_DClosure.hpp"
namespace xo {
namespace scm {
auto
IGCObject_DClosure::gco_shallow_move(DClosure & self, obj<AGCObjectVisitor> gc) noexcept -> Opaque
{
return self.gco_shallow_move(gc);
}
auto
IGCObject_DClosure::visit_gco_children(DClosure & self, VisitReason reason, obj<AGCObjectVisitor> fn) noexcept -> void
{
self.visit_gco_children(reason, fn);
}
} /*namespace scm*/
} /*namespace xo*/
/* end IGCObject_DClosure.cpp */

View file

@ -0,0 +1,32 @@
/** @file IGCObject_DVsmApplyClosureFrame.cpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IGCObject_DVsmApplyClosureFrame.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_any.hpp.j2]
* 3. idl for facet methods
* [idl/IGCObject_DVsmApplyClosureFrame.json5]
**/
#include "detail/IGCObject_DVsmApplyClosureFrame.hpp"
namespace xo {
namespace scm {
auto
IGCObject_DVsmApplyClosureFrame::gco_shallow_move(DVsmApplyClosureFrame & self, obj<AGCObjectVisitor> gc) noexcept -> Opaque
{
return self.gco_shallow_move(gc);
}
auto
IGCObject_DVsmApplyClosureFrame::visit_gco_children(DVsmApplyClosureFrame & self, VisitReason reason, obj<AGCObjectVisitor> fn) noexcept -> void
{
self.visit_gco_children(reason, fn);
}
} /*namespace scm*/
} /*namespace xo*/
/* end IGCObject_DVsmApplyClosureFrame.cpp */

View file

@ -0,0 +1,32 @@
/** @file IGCObject_DVsmApplyFrame.cpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IGCObject_DVsmApplyFrame.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_any.hpp.j2]
* 3. idl for facet methods
* [idl/IGCObject_DVsmApplyFrame.json5]
**/
#include "detail/IGCObject_DVsmApplyFrame.hpp"
namespace xo {
namespace scm {
auto
IGCObject_DVsmApplyFrame::gco_shallow_move(DVsmApplyFrame & self, obj<AGCObjectVisitor> gc) noexcept -> Opaque
{
return self.gco_shallow_move(gc);
}
auto
IGCObject_DVsmApplyFrame::visit_gco_children(DVsmApplyFrame & self, VisitReason reason, obj<AGCObjectVisitor> fn) noexcept -> void
{
self.visit_gco_children(reason, fn);
}
} /*namespace scm*/
} /*namespace xo*/
/* end IGCObject_DVsmApplyFrame.cpp */

View file

@ -0,0 +1,32 @@
/** @file IGCObject_DVsmDefContFrame.cpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IGCObject_DVsmDefContFrame.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_any.hpp.j2]
* 3. idl for facet methods
* [idl/IGCObject_DVsmDefContFrame.json5]
**/
#include "define/IGCObject_DVsmDefContFrame.hpp"
namespace xo {
namespace scm {
auto
IGCObject_DVsmDefContFrame::gco_shallow_move(DVsmDefContFrame & self, obj<AGCObjectVisitor> gc) noexcept -> Opaque
{
return self.gco_shallow_move(gc);
}
auto
IGCObject_DVsmDefContFrame::visit_gco_children(DVsmDefContFrame & self, VisitReason reason, obj<AGCObjectVisitor> fn) noexcept -> void
{
self.visit_gco_children(reason, fn);
}
} /*namespace scm*/
} /*namespace xo*/
/* end IGCObject_DVsmDefContFrame.cpp */

View file

@ -0,0 +1,32 @@
/** @file IGCObject_DVsmEvalArgsFrame.cpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IGCObject_DVsmEvalArgsFrame.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_any.hpp.j2]
* 3. idl for facet methods
* [idl/IGCObject_DVsmEvalArgsFrame.json5]
**/
#include "detail/IGCObject_DVsmEvalArgsFrame.hpp"
namespace xo {
namespace scm {
auto
IGCObject_DVsmEvalArgsFrame::gco_shallow_move(DVsmEvalArgsFrame & self, obj<AGCObjectVisitor> gc) noexcept -> Opaque
{
return self.gco_shallow_move(gc);
}
auto
IGCObject_DVsmEvalArgsFrame::visit_gco_children(DVsmEvalArgsFrame & self, VisitReason reason, obj<AGCObjectVisitor> fn) noexcept -> void
{
self.visit_gco_children(reason, fn);
}
} /*namespace scm*/
} /*namespace xo*/
/* end IGCObject_DVsmEvalArgsFrame.cpp */

View file

@ -0,0 +1,32 @@
/** @file IGCObject_DVsmIfElseContFrame.cpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IGCObject_DVsmIfElseContFrame.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_any.hpp.j2]
* 3. idl for facet methods
* [idl/IGCObject_DVsmIfElseContFrame.json5]
**/
#include "ifelse/IGCObject_DVsmIfElseContFrame.hpp"
namespace xo {
namespace scm {
auto
IGCObject_DVsmIfElseContFrame::gco_shallow_move(DVsmIfElseContFrame & self, obj<AGCObjectVisitor> gc) noexcept -> Opaque
{
return self.gco_shallow_move(gc);
}
auto
IGCObject_DVsmIfElseContFrame::visit_gco_children(DVsmIfElseContFrame & self, VisitReason reason, obj<AGCObjectVisitor> fn) noexcept -> void
{
self.visit_gco_children(reason, fn);
}
} /*namespace scm*/
} /*namespace xo*/
/* end IGCObject_DVsmIfElseContFrame.cpp */

View file

@ -0,0 +1,32 @@
/** @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::gco_shallow_move(DVsmSeqContFrame & self, obj<AGCObjectVisitor> gc) noexcept -> Opaque
{
return self.gco_shallow_move(gc);
}
auto
IGCObject_DVsmSeqContFrame::visit_gco_children(DVsmSeqContFrame & self, VisitReason reason, obj<AGCObjectVisitor> fn) noexcept -> void
{
self.visit_gco_children(reason, fn);
}
} /*namespace scm*/
} /*namespace xo*/
/* end IGCObject_DVsmSeqContFrame.cpp */

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

@ -0,0 +1,52 @@
/** @file IRuntimeContext_DVsmRcx.cpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [xo-facet/codegen/genfacet]
* arguments:
* --input [idl/IRuntimeContext_DVsmRcx.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_any.hpp.j2]
* 3. idl for facet methods
* [idl/IRuntimeContext_DVsmRcx.json5]
**/
#include "detail/IRuntimeContext_DVsmRcx.hpp"
namespace xo {
namespace scm {
auto
IRuntimeContext_DVsmRcx::allocator(const DVsmRcx & self) noexcept -> obj<AAllocator>
{
return self.allocator();
}
auto
IRuntimeContext_DVsmRcx::collector(const DVsmRcx & self) noexcept -> obj<ACollector>
{
return self.collector();
}
auto
IRuntimeContext_DVsmRcx::error_allocator(const DVsmRcx & self) noexcept -> obj<AAllocator>
{
return self.error_allocator();
}
auto
IRuntimeContext_DVsmRcx::stringtable(const DVsmRcx & self) noexcept -> StringTable *
{
return self.stringtable();
}
auto
IRuntimeContext_DVsmRcx::visit_pools(const DVsmRcx & self, MemorySizeVisitor visitor) -> void
{
self.visit_pools(visitor);
}
} /*namespace scm*/
} /*namespace xo*/
/* end IRuntimeContext_DVsmRcx.cpp */

Some files were not shown because too many files have changed in this diff Show more