From 44f463e3591a61f062da2a08cdb9f8334e4292ca Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 28 Jul 2025 13:16:09 -0400 Subject: [PATCH] xo-expression: generalize envframestack + handle explicit lm retturn --- include/xo/reader/define_xs.hpp | 1 + include/xo/reader/envframestack.hpp | 16 ++++++------ include/xo/reader/parser.hpp | 6 +++++ include/xo/reader/parserstatemachine.hpp | 6 ++--- src/reader/envframestack.cpp | 10 ++++---- src/reader/lambda_xs.cpp | 11 +++++--- src/reader/parser.cpp | 12 ++++++--- src/reader/parserstatemachine.cpp | 32 +++++++++--------------- src/reader/reader.cpp | 4 +++ 9 files changed, 55 insertions(+), 43 deletions(-) diff --git a/include/xo/reader/define_xs.hpp b/include/xo/reader/define_xs.hpp index 47a4712d..d10a080f 100644 --- a/include/xo/reader/define_xs.hpp +++ b/include/xo/reader/define_xs.hpp @@ -79,6 +79,7 @@ namespace xo { static void start(parserstatemachine * p_psm); defexprstatetype defxs_type() const { return defxs_type_; } + bp lhs_variable() const { return def_expr_->lhs_variable(); } /** @return expected input in current state **/ virtual const char * get_expect_str() const override; diff --git a/include/xo/reader/envframestack.hpp b/include/xo/reader/envframestack.hpp index 81de3ec3..56063924 100644 --- a/include/xo/reader/envframestack.hpp +++ b/include/xo/reader/envframestack.hpp @@ -14,8 +14,6 @@ namespace xo { **/ class envframestack { public: - using LocalEnv = xo::scm::LocalEnv; - using Variable = xo::scm::Variable; using ppstate = xo::print::ppstate; using ppindentinfo = xo::print::ppindentinfo; @@ -29,23 +27,23 @@ namespace xo { * Visit frames in fifo order, report first match; * nullptr if no matches. **/ - bp lookup(const std::string & x) const; + bp lookup(const std::string & x) const; /** update/replace binding for variable @p target. * New binding may have a different type. **/ void upsert(bp target); - bp top_envframe() const; - void push_envframe(const rp & x); - rp pop_envframe(); + bp top_envframe() const; + void push_envframe(const rp & x); + rp pop_envframe(); void reset_to_toplevel() { stack_.resize(1); } /** relative to top-of-stack. * 0 -> top (last in), z-1 -> bottom (first in) **/ - bp operator[](std::size_t i) { + bp operator[](std::size_t i) { std::size_t z = stack_.size(); assert(i < z); @@ -53,7 +51,7 @@ namespace xo { return stack_[z - i - 1].get(); } - bp operator[](std::size_t i) const { + bp operator[](std::size_t i) const { std::size_t z = stack_.size(); assert(i < z); @@ -65,7 +63,7 @@ namespace xo { bool pretty_print(const ppindentinfo & ppii) const; private: - std::vector> stack_; + std::vector> stack_; }; inline std::ostream & diff --git a/include/xo/reader/parser.hpp b/include/xo/reader/parser.hpp index 6f6b459b..d13f36ed 100644 --- a/include/xo/reader/parser.hpp +++ b/include/xo/reader/parser.hpp @@ -219,6 +219,12 @@ namespace xo { **/ const parser_result & include_token(const token_type & tk); + /** reset parsed result expression; use using return value from + * @ref include_token. Complicating api here to avoid copying parser_result + * on each token + **/ + void reset_result(); + /** reset to starting parsing state. * use this after encountering an error, to avoid cascade of * spurious secondary errors.. particularly important when diff --git a/include/xo/reader/parserstatemachine.hpp b/include/xo/reader/parserstatemachine.hpp index cecf5c95..76c4e03c 100644 --- a/include/xo/reader/parserstatemachine.hpp +++ b/include/xo/reader/parserstatemachine.hpp @@ -59,13 +59,13 @@ namespace xo { void upsert_var(bp x); /** @return available variable bindings in current parsing state **/ - bp top_envframe() const; + bp top_envframe() const; /** @return frame @p i levels from the top **/ - bp lookup_envframe(std::size_t i) const; + bp lookup_envframe(std::size_t i) const; /** push frame @p x (with new variable bindings) onto environment stack **/ void push_envframe(const rp & x); /** @return pop innermost environment frame and return it **/ - rp pop_envframe(); + rp pop_envframe(); /** @return number of stacked environment frames **/ size_t env_stack_size() const { return env_stack_.size(); } diff --git a/src/reader/envframestack.cpp b/src/reader/envframestack.cpp index 3dff60da..350bab48 100644 --- a/src/reader/envframestack.cpp +++ b/src/reader/envframestack.cpp @@ -12,7 +12,7 @@ namespace xo { using xo::scm::Variable; namespace scm { - bp + bp envframestack::top_envframe() const { std::size_t z = stack_.size(); @@ -25,7 +25,7 @@ namespace xo { } void - envframestack::push_envframe(const rp & frame) + envframestack::push_envframe(const rp & frame) { constexpr bool c_debug_flag = true; scope log(XO_DEBUG(c_debug_flag), @@ -38,7 +38,7 @@ namespace xo { stack_[z] = frame; } - rp + rp envframestack::pop_envframe() { constexpr bool c_debug_flag = true; scope log(XO_DEBUG(c_debug_flag)); @@ -48,7 +48,7 @@ namespace xo { if (z > 0) { //std::unique_ptr top = std::move(stack_[z-1]); - rp retval = stack_.at(z-1); + rp retval = stack_.at(z-1); stack_.resize(z-1); @@ -58,7 +58,7 @@ namespace xo { } } - bp + bp envframestack::lookup(const std::string & x) const { for (std::size_t i = 0, z = this->size(); i < z; ++i) { const auto & frame = (*this)[i]; diff --git a/src/reader/lambda_xs.cpp b/src/reader/lambda_xs.cpp index c2a2ea0f..89e2f972 100644 --- a/src/reader/lambda_xs.cpp +++ b/src/reader/lambda_xs.cpp @@ -156,6 +156,7 @@ namespace xo { parserstatemachine * p_psm) { constexpr const char * c_self_name = "lambda_xs::on_typedescr"; + scope log(XO_DEBUG(p_psm->debug_flag())); assert(td); @@ -189,13 +190,17 @@ namespace xo { && (p_psm->env_stack_size() >= 2) ) { - bp def_env = p_psm->lookup_envframe(1); + const define_xs * def_xs = dynamic_cast(&(p_psm->lookup_exprstate(2))); - assert(def_env->n_arg() == 1); + assert(def_xs); - bp def_var = def_env->lookup_arg(0).get(); + bp def_var = def_xs->lhs_variable(); if (def_var->valuetype() == nullptr) { + log && log("assign discovered lambda type T to enclosing define", + xtag("lhs", def_var), + xtag("T", print::unq(this->lambda_td_->canonical_name()))); + def_var->assign_valuetype(lambda_td_); } else { /* don't need to unify here. if def already hasa a type, diff --git a/src/reader/parser.cpp b/src/reader/parser.cpp index e06eb4d0..41eeae96 100644 --- a/src/reader/parser.cpp +++ b/src/reader/parser.cpp @@ -11,8 +11,8 @@ #include "xo/expression/DefineExpr.hpp" #include "xo/expression/Constant.hpp" #include "xo/expression/ConvertExpr.hpp" -//#include "xo/expression/GlobalEnv.hpp" -#include "xo/expression/LocalEnv.hpp" +#include "xo/expression/GlobalEnv.hpp" +//#include "xo/expression/LocalEnv.hpp" //#include #include @@ -28,7 +28,7 @@ namespace xo { : psm_{debug_flag} { /* top-level environment. initially empty */ - rp toplevel_env = LocalEnv::make_empty(); + rp toplevel_env = GlobalEnv::make_empty(); this->psm_.env_stack_.push_envframe(toplevel_env); } @@ -70,6 +70,12 @@ namespace xo { return psm_.result_; } /*include_token*/ + void + parser::reset_result() + { + psm_.result_ = parser_result::none(); + } + void parser::reset_to_idle_toplevel() { diff --git a/src/reader/parserstatemachine.cpp b/src/reader/parserstatemachine.cpp index a7c97f79..f85a0ae0 100644 --- a/src/reader/parserstatemachine.cpp +++ b/src/reader/parserstatemachine.cpp @@ -17,7 +17,7 @@ namespace xo { namespace scm { bp parserstatemachine::lookup_var(const std::string & x) const { - return env_stack_.lookup(x); + return Variable::from(env_stack_.lookup(x)); } void @@ -45,30 +45,28 @@ namespace xo { xs_stack_.push_exprstate(std::move(x)); } - bp + bp parserstatemachine::top_envframe() const { return env_stack_.top_envframe(); } - bp + bp parserstatemachine::lookup_envframe(std::size_t i) const { return env_stack_[i]; } void parserstatemachine::push_envframe(const rp & x) { - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(debug_flag_)); log && log(xtag("frame", x)); env_stack_.push_envframe(x); } - rp + rp parserstatemachine::pop_envframe() { - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(debug_flag_)); return env_stack_.pop_envframe(); } @@ -76,8 +74,7 @@ namespace xo { void parserstatemachine::on_expr(bp x) { - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(debug_flag_)); log && log(xtag("x", x), xtag("psm", this)); @@ -88,8 +85,7 @@ namespace xo { void parserstatemachine::on_expr_with_semicolon(bp x) { - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(debug_flag_)); log && log(xtag("x", x), xtag("psm", this)); @@ -102,8 +98,7 @@ namespace xo { void parserstatemachine::on_symbol(const std::string & x) { - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(debug_flag_)); log && log(xtag("x", x), xtag("psm", this)); @@ -114,8 +109,7 @@ namespace xo { void parserstatemachine::on_semicolon_token(const token_type & tk) { - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(debug_flag_)); log && log(xtag("tk", tk), xtag("psm", this)); @@ -126,8 +120,7 @@ namespace xo { void parserstatemachine::on_operator_token(const token_type & tk) { - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(debug_flag_)); log && log(xtag("tk", tk), xtag("psm", this)); @@ -138,8 +131,7 @@ namespace xo { void parserstatemachine::on_leftbrace_token(const token_type & tk) { - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(debug_flag_)); log && log(xtag("tk", tk), xtag("psm", this)); diff --git a/src/reader/reader.cpp b/src/reader/reader.cpp index 37a64d6b..2a615fd9 100644 --- a/src/reader/reader.cpp +++ b/src/reader/reader.cpp @@ -63,6 +63,10 @@ namespace xo { log && log(xtag("outcome", "victory!"), xtag("expr", parser_result.result_expr())); + rp result_expr = parser_result.result_expr(); + + this->parser_.reset_result(); + /* token completes an expression -> victory */ return reader_result(parser_result.result_expr(), expr_span, parser_.stack_size(), reader_error());