xo-interpreter2 stack: VSM as AGCObject for virtual root
This commit is contained in:
parent
364f34cc8a
commit
92bea14aa0
15 changed files with 679 additions and 412 deletions
|
|
@ -1,321 +1,11 @@
|
|||
/** @file VirtualSchematikaMachine.hpp
|
||||
*
|
||||
* @author Roland Conybare, Jan 2026
|
||||
* @author Roland Conybeare, Mar 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 {
|
||||
#ifdef OBSOLETE // see DVsmError
|
||||
// TODO: move error to collected space?
|
||||
// or special arena?
|
||||
//
|
||||
struct EvaluationError {
|
||||
/** source location (in vsm implementation) at which error identified **/
|
||||
std::string_view src_function_;
|
||||
/** error description (allocated from ErrorArena) **/
|
||||
std::string_view error_description_;
|
||||
// TODO: info about location in schematika source
|
||||
};
|
||||
#endif
|
||||
|
||||
/** 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} {}
|
||||
explicit VsmResult(TokenizerError err) : result_{err} {}
|
||||
|
||||
bool is_value() const { return std::holds_alternative<obj<AGCObject>>(result_); }
|
||||
bool is_tk_error() const { return std::holds_alternative<TokenizerError>(result_); }
|
||||
bool is_eval_error() const;
|
||||
|
||||
const obj<AGCObject> * value() const { return std::get_if<obj<AGCObject>>(&result_); }
|
||||
obj<AGCObject> & value_ref() { return std::get<obj<AGCObject>>(result_); }
|
||||
|
||||
/** result of evaluating first expression encountered in input **/
|
||||
std::variant<obj<AGCObject>, TokenizerError> result_;
|
||||
};
|
||||
|
||||
/** vsm result + reamining span **/
|
||||
struct VsmResultExt : public VsmResult {
|
||||
using span_type = VsmResult::span_type;
|
||||
|
||||
VsmResultExt() = default;
|
||||
VsmResultExt(const VsmResult & result, span_type rem) : VsmResult{result}, remaining_{rem} {}
|
||||
|
||||
/** unconsumed portion of input **/
|
||||
VsmResult::span_type remaining_;
|
||||
};
|
||||
|
||||
/** @class VirtualSchematikaMachine
|
||||
* @brief virtual machine for schematika
|
||||
**/
|
||||
class VirtualSchematikaMachine {
|
||||
public:
|
||||
// will be DArenaVector<obj<StackFrame>> probably
|
||||
using Stack = void *;
|
||||
using ACollector = xo::mm::ACollector;
|
||||
using AAllocator = xo::mm::AAllocator;
|
||||
using AGCObject = xo::mm::AGCObject;
|
||||
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.
|
||||
**/
|
||||
VirtualSchematikaMachine(const VsmConfig & config,
|
||||
obj<AAllocator> aux_mm);
|
||||
|
||||
/** non-trivial dtor because of @ref reader_
|
||||
* indirect dependency on DGlobalSymtab
|
||||
**/
|
||||
~VirtualSchematikaMachine() = default;
|
||||
|
||||
/** 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
|
||||
**/
|
||||
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 **/
|
||||
std::size_t shallow_size() const noexcept;
|
||||
|
||||
/** forward gc-aware child pointers
|
||||
**/
|
||||
std::size_t forward_children(obj<ACollector> 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_;
|
||||
|
||||
/** 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
|
||||
**/
|
||||
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*/
|
||||
#include "vsm/DVirtualSchematikaMachine.hpp"
|
||||
#include "vsm/IGCObject_DVirtualSchematikaMachine.hpp"
|
||||
|
||||
/* end VirtualSchematikaMachine.hpp */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue