xo-interpreter: plumb initial global symtab so builtins reach parser

This commit is contained in:
Roland Conybeare 2025-11-27 11:50:34 -05:00
commit 79d32b61c6
14 changed files with 57 additions and 23 deletions

View file

@ -26,6 +26,8 @@ namespace xo {
gc::IAlloc * get_mm() const { return mm_; } gc::IAlloc * get_mm() const { return mm_; }
#endif #endif
const rp<GlobalSymtab> & symtab() const { return symtab_; }
// inherited from Env.. // inherited from Env..
virtual bool local_contains_var(const std::string & vname) const final override; virtual bool local_contains_var(const std::string & vname) const final override;
virtual gp<Object> * lookup_slot(const std::string & vname) final override; virtual gp<Object> * lookup_slot(const std::string & vname) final override;

View file

@ -5,7 +5,7 @@
#include "VsmInstr.hpp" #include "VsmInstr.hpp"
#include "VsmStackFrame.hpp" #include "VsmStackFrame.hpp"
#include "SchematikaError.hpp" #include "SchematikaError.hpp"
#include "Env.hpp" #include "GlobalEnv.hpp"
#include "xo/expression/Expression.hpp" #include "xo/expression/Expression.hpp"
#include "xo/object/ObjectConverter.hpp" #include "xo/object/ObjectConverter.hpp"
#include "xo/alloc/Object.hpp" #include "xo/alloc/Object.hpp"
@ -15,13 +15,13 @@ namespace xo {
/** @brief state that may be shared across VirtualSchematikaMachine instances **/ /** @brief state that may be shared across VirtualSchematikaMachine instances **/
struct VirtualSchematikaMachineFlyweight { struct VirtualSchematikaMachineFlyweight {
explicit VirtualSchematikaMachineFlyweight(gc::IAlloc * mm, explicit VirtualSchematikaMachineFlyweight(gc::IAlloc * mm,
gp<Env> env, gp<GlobalEnv> env,
log_level log_level); log_level log_level);
/** memory allocator for interpreter operation. **/ /** memory allocator for interpreter operation. **/
gc::IAlloc * object_mm_ = nullptr; gc::IAlloc * object_mm_ = nullptr;
/** global environment **/ /** global environment **/
gp<Env> toplevel_env_; gp<GlobalEnv> toplevel_env_;
/** convert TaggedPtr->Object **/ /** convert TaggedPtr->Object **/
xo::obj::ObjectConverter object_converter_; xo::obj::ObjectConverter object_converter_;
/** control logging level. higher values -> more logging **/ /** control logging level. higher values -> more logging **/
@ -37,9 +37,11 @@ namespace xo {
using IAlloc = xo::gc::IAlloc; using IAlloc = xo::gc::IAlloc;
public: public:
VirtualSchematikaMachine(IAlloc * mm, gp<Env> toplevel_env, log_level log_level); VirtualSchematikaMachine(IAlloc * mm, gp<GlobalEnv> toplevel_env, log_level log_level);
~VirtualSchematikaMachine(); ~VirtualSchematikaMachine();
gp<GlobalEnv> toplevel_env() const { return flyweight_.toplevel_env_; }
/** evaluate expression @p expr. /** evaluate expression @p expr.
* borrows calling thread until completion * borrows calling thread until completion
* return [value, error]. error ignored unless value is nullptr. * return [value, error]. error ignored unless value is nullptr.
@ -48,7 +50,7 @@ namespace xo {
* *
* Evaluate schematika expression @p expr in environment @p env * Evaluate schematika expression @p expr in environment @p env
**/ **/
std::pair<gp<Object>, SchematikaError> eval(bp<Expression> expr, gp<Env> env); std::pair<gp<Object>, SchematikaError> eval(bp<Expression> expr, gp<GlobalEnv> env);
/** evaluate expression @p expr in toplevel environment **/ /** evaluate expression @p expr in toplevel environment **/
std::pair<gp<Object>, SchematikaError> toplevel_eval(bp<Expression> expr); std::pair<gp<Object>, SchematikaError> toplevel_eval(bp<Expression> expr);
@ -123,7 +125,7 @@ namespace xo {
* *
* caller saves! * caller saves!
**/ **/
gp<Env> env_; gp<GlobalEnv> env_;
/** vsm stack. callee saves! /** vsm stack. callee saves!
**/ **/

View file

@ -24,6 +24,9 @@ namespace xo {
void void
BuiltinPrimitives::install(gc::IAlloc * mm, gp<GlobalEnv> env) BuiltinPrimitives::install(gc::IAlloc * mm, gp<GlobalEnv> env)
{ {
scope log(XO_DEBUG(true));
// add(x,y)
{ {
gp<Object> rhs = xo::obj::make_primitive(mm, add64); gp<Object> rhs = xo::obj::make_primitive(mm, add64);
TypeDescr td = Reflect::require<decltype(add64)>(); TypeDescr td = Reflect::require<decltype(add64)>();

View file

@ -28,7 +28,7 @@ namespace xo {
* rather than VirtualSchematikaMachine to own allocator * rather than VirtualSchematikaMachine to own allocator
* to preserve option to share it * to preserve option to share it
**/ **/
Impl(const Config & config, up<IAlloc> mm, gp<Env> toplevel_env) : Impl(const Config & config, up<IAlloc> mm, gp<GlobalEnv> toplevel_env) :
config_{config}, config_{config},
mm_{std::move(mm)}, mm_{std::move(mm)},
vsm_{mm_.get(), toplevel_env, config.vsm_log_level_} {} vsm_{mm_.get(), toplevel_env, config.vsm_log_level_} {}
@ -44,6 +44,11 @@ namespace xo {
void welcome(std::ostream & os); void welcome(std::ostream & os);
/** get one line of input. prompt if @p interactive,
* with prompt depending on @p parser_stack_size.
* Use @p rx to perform line editing (when @p interactive).
* Store completed line in @p input.
**/
bool replxx_getline(bool interactive, bool replxx_getline(bool interactive,
std::size_t parser_stack_size, std::size_t parser_stack_size,
replxx::Replxx & rx, replxx::Replxx & rx,
@ -133,6 +138,8 @@ namespace xo {
void void
Schematika::Impl::interactive_repl() Schematika::Impl::interactive_repl()
{ {
scope log(XO_DEBUG(true));
using span_type = xo::scm::span<const char>; using span_type = xo::scm::span<const char>;
bool interactive = isatty(STDIN_FILENO); bool interactive = isatty(STDIN_FILENO);
@ -143,7 +150,7 @@ namespace xo {
// rx.bind_key_internal(Replxx::KEY::control('p'), "history_previous"); // rx.bind_key_internal(Replxx::KEY::control('p'), "history_previous");
// rx.bind_key_internal(Replxx::KEY::control('n'), "history_next"); // rx.bind_key_internal(Replxx::KEY::control('n'), "history_next");
reader rdr(config_.debug_flag); reader rdr(vsm_.toplevel_env()->symtab(), config_.debug_flag);
rdr.begin_interactive_session(); rdr.begin_interactive_session();
string input_str; string input_str;

View file

@ -79,7 +79,7 @@ namespace xo {
// ----- VirtualSchematikaMachineFlyweight ----- // ----- VirtualSchematikaMachineFlyweight -----
VirtualSchematikaMachineFlyweight::VirtualSchematikaMachineFlyweight(gc::IAlloc * mm, VirtualSchematikaMachineFlyweight::VirtualSchematikaMachineFlyweight(gc::IAlloc * mm,
gp<Env> env, gp<GlobalEnv> env,
log_level ll) : log_level ll) :
object_mm_{mm}, object_mm_{mm},
toplevel_env_{env}, toplevel_env_{env},
@ -89,9 +89,11 @@ namespace xo {
// ----- VirtualSchematikaMachine ----- // ----- VirtualSchematikaMachine -----
VirtualSchematikaMachine::VirtualSchematikaMachine(gc::IAlloc * mm, VirtualSchematikaMachine::VirtualSchematikaMachine(gc::IAlloc * mm,
gp<Env> env, gp<GlobalEnv> env,
log_level ll) : flyweight_{mm, env, ll} log_level ll) : flyweight_{mm, env, ll}
{ {
scope log(XO_DEBUG(true), xtag("env", env), xtag("symtab", env->symtab()));
this->env_ = env; this->env_ = env;
// gc roots // gc roots
@ -133,8 +135,10 @@ namespace xo {
std::pair<gp<Object>, std::pair<gp<Object>,
SchematikaError> SchematikaError>
VirtualSchematikaMachine::eval(bp<Expression> expr, gp<Env> env) VirtualSchematikaMachine::eval(bp<Expression> expr, gp<GlobalEnv> env)
{ {
scope log(XO_DEBUG(true), xtag("env", env), xtag("symtab", env->symtab()));
this->pc_ = &VsmOps::eval_op; this->pc_ = &VsmOps::eval_op;
this->expr_ = expr.promote(); this->expr_ = expr.promote();
this->env_ = env; this->env_ = env;

View file

@ -1,7 +1,7 @@
/* @file MachPipeline.test.cpp */ /* @file MachPipeline.test.cpp */
#include "xo/jit/MachPipeline.hpp" #include "xo/jit/MachPipeline.hpp"
#include "xo/expression/Primitive.hpp" #include "xo/expression/PrimitiveExpr.hpp"
#include "xo/ratio/ratio.hpp" #include "xo/ratio/ratio.hpp"
#include "xo/ratio/ratio_reflect.hpp" #include "xo/ratio/ratio_reflect.hpp"
#include "xo/reflect/reflect_struct.hpp" #include "xo/reflect/reflect_struct.hpp"

View file

@ -46,10 +46,11 @@ main() {
using span_type = xo::scm::span<const char>; using span_type = xo::scm::span<const char>;
bool interactive = isatty(STDIN_FILENO); bool interactive = isatty(STDIN_FILENO);
bool c_debug_flag = false; bool c_debug_flag = false;
reader rdr(c_debug_flag); auto toplevel_symtab = GlobalSymtab::make_empty();
reader rdr(toplevel_symtab, c_debug_flag);
rdr.begin_interactive_session(); rdr.begin_interactive_session();
string input_str; string input_str;

View file

@ -83,7 +83,9 @@ main()
constexpr bool c_debug_flag = false; constexpr bool c_debug_flag = false;
reader rdr(c_debug_flag); rp<GlobalSymtab> toplevel_symtab = GlobalSymtab::make_empty();
reader rdr(toplevel_symtab, c_debug_flag);
rdr.begin_interactive_session(); rdr.begin_interactive_session();
string input_str; string input_str;

View file

@ -9,6 +9,7 @@
#include "envframestack.hpp" #include "envframestack.hpp"
#include "parser_result.hpp" #include "parser_result.hpp"
#include "parserstatemachine.hpp" #include "parserstatemachine.hpp"
#include "xo/expression/GlobalSymtab.hpp"
#include <stdexcept> #include <stdexcept>
namespace xo { namespace xo {
@ -161,9 +162,12 @@ namespace xo {
/** create parser in initial state; /** create parser in initial state;
* parser is ready to receive tokens via @ref include_token * parser is ready to receive tokens via @ref include_token
* *
* At least for xo-interpreter will have non-empty symbol table.
*
* @p toplevel_symtab symbol table.
* @p debug_flag true to enable debug logging * @p debug_flag true to enable debug logging
**/ **/
explicit parser(bool debug_flag); parser(const rp<GlobalSymtab> & toplevel_symtab, bool debug_flag);
bool debug_flag() const { return psm_.debug_flag(); } bool debug_flag() const { return psm_.debug_flag(); }

View file

@ -8,6 +8,7 @@
#include "parser.hpp" #include "parser.hpp"
#include "reader_error.hpp" #include "reader_error.hpp"
#include "xo/expression/Expression.hpp" #include "xo/expression/Expression.hpp"
#include "xo/expression/GlobalSymtab.hpp"
#include "xo/expression/pretty_expression.hpp" #include "xo/expression/pretty_expression.hpp"
#include "xo/tokenizer/tokenizer.hpp" #include "xo/tokenizer/tokenizer.hpp"
@ -78,7 +79,7 @@ namespace xo {
using span_type = tokenizer_type::span_type; using span_type = tokenizer_type::span_type;
public: public:
explicit reader(bool debug_flag); reader(const rp<GlobalSymtab> & toplevel_symtab, bool debug_flag);
bool debug_flag() const { return parser_.debug_flag(); } bool debug_flag() const { return parser_.debug_flag(); }

View file

@ -24,13 +24,15 @@ namespace xo {
namespace scm { namespace scm {
// ----- parser ----- // ----- parser -----
parser::parser(bool debug_flag) parser::parser(const rp<GlobalSymtab> & toplevel_symtab, bool debug_flag)
: psm_{debug_flag} : psm_{debug_flag}
{ {
#ifdef OBSOLETE
/* top-level environment. initially empty */ /* top-level environment. initially empty */
rp<SymbolTable> toplevel_env = GlobalSymtab::make_empty(); rp<SymbolTable> toplevel_env = GlobalSymtab::make_empty();
#endif
this->psm_.env_stack_.push_envframe(toplevel_env); this->psm_.env_stack_.push_envframe(toplevel_symtab);
} }
bool bool

View file

@ -4,9 +4,9 @@
namespace xo { namespace xo {
namespace scm { namespace scm {
reader::reader(bool debug_flag) : reader::reader(const rp<GlobalSymtab> & toplevel_symtab, bool debug_flag) :
tokenizer_{debug_flag}, tokenizer_{debug_flag},
parser_{debug_flag} parser_{toplevel_symtab, debug_flag}
{} {}
void void

View file

@ -10,6 +10,7 @@
namespace xo { namespace xo {
using parser_type = xo::scm::parser; using parser_type = xo::scm::parser;
using token_type = parser_type::token_type; using token_type = parser_type::token_type;
using xo::scm::GlobalSymtab;
using xo::scm::exprstatetype; using xo::scm::exprstatetype;
using xo::scm::define_xs; using xo::scm::define_xs;
using xo::scm::defexprstatetype; using xo::scm::defexprstatetype;
@ -23,7 +24,9 @@ namespace xo {
for (std::size_t i_tc = 0; i_tc < 2; ++i_tc) { for (std::size_t i_tc = 0; i_tc < 2; ++i_tc) {
constexpr bool c_debug_flag = true; constexpr bool c_debug_flag = true;
parser_type parser(c_debug_flag); rp<GlobalSymtab> toplevel_symtab = GlobalSymtab::make_empty();
parser_type parser(toplevel_symtab, c_debug_flag);
scope log(XO_DEBUG(c_debug_flag), xtag("i_tc", i_tc)); scope log(XO_DEBUG(c_debug_flag), xtag("i_tc", i_tc));

View file

@ -5,6 +5,7 @@
namespace xo { namespace xo {
using xo::scm::reader; using xo::scm::reader;
using xo::scm::GlobalSymtab;
namespace ut { namespace ut {
namespace { namespace {
@ -30,7 +31,9 @@ namespace xo {
for (std::size_t i_tc = 0; i_tc < s_testcase_v.size(); ++i_tc) { for (std::size_t i_tc = 0; i_tc < s_testcase_v.size(); ++i_tc) {
const test_case & tc = s_testcase_v[i_tc]; const test_case & tc = s_testcase_v[i_tc];
reader rdr(c_debug_flag); rp<GlobalSymtab> toplevel_symtab = GlobalSymtab::make_empty();
reader rdr(toplevel_symtab, c_debug_flag);
scope log(XO_ENTER2(always, c_debug_flag, "reader.testcase"), scope log(XO_ENTER2(always, c_debug_flag, "reader.testcase"),
xtag("i_tc", i_tc)); xtag("i_tc", i_tc));