From 12f5362b4d86a9f6af2a6f677c549cba8370f458 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sat, 26 Jul 2025 17:28:41 -0400 Subject: [PATCH] xo-expression xo-reader: type unifier + misc improvements --- README | 6 +- include/xo/reader/formal_arg.hpp | 2 +- include/xo/reader/lambda_xs.hpp | 26 ++++- include/xo/reader/pretty_envframestack.hpp | 1 + .../xo/reader/pretty_parserstatemachine.hpp | 5 + include/xo/reader/sequence_xs.hpp | 4 + src/reader/expect_expr_xs.cpp | 6 +- src/reader/exprstate.cpp | 6 +- src/reader/exprstatestack.cpp | 1 + src/reader/lambda_xs.cpp | 98 +++++++++++++++---- src/reader/let1_xs.cpp | 1 + src/reader/pretty_parserstatemachine.cpp | 14 +++ src/reader/sequence_xs.cpp | 16 ++- 13 files changed, 148 insertions(+), 38 deletions(-) diff --git a/README b/README index 59a6e677..cee8b46c 100644 --- a/README +++ b/README @@ -17,7 +17,7 @@ a. create DefineExpr with TypeVariable. // compose these into Expressions. // -struct TypeTemplateRef { +struct type_ref { bool is_concrete() const { return td_ && td_->is_concrete(); } // generated name, so we can map between types. Don't want to create TypeDescr @@ -29,10 +29,10 @@ struct TypeTemplateRef { // what we know about a type // -struct TypeTemplate : public Refcounted { +struct TypeBlueprint : public Refcounted { static bool equal(bp lhs, bp rhs); - TypeTemplateRef ref_; + type_ref ref_; // additional descriptive info... }; diff --git a/include/xo/reader/formal_arg.hpp b/include/xo/reader/formal_arg.hpp index 4f0afaef..a94f45eb 100644 --- a/include/xo/reader/formal_arg.hpp +++ b/include/xo/reader/formal_arg.hpp @@ -42,7 +42,7 @@ namespace xo { /** formal parameter name **/ std::string name_; /** type description for variable @p name **/ - TypeDescr td_; + TypeDescr td_ = nullptr; }; inline std::ostream & diff --git a/include/xo/reader/lambda_xs.hpp b/include/xo/reader/lambda_xs.hpp index 3f49b973..0832add2 100644 --- a/include/xo/reader/lambda_xs.hpp +++ b/include/xo/reader/lambda_xs.hpp @@ -12,15 +12,20 @@ namespace xo { namespace scm { /** - * lambda ( name(1) : type(1), ..., ) body-expr ; - * ^ ^ ^ ^ - * | | | | - * lm_0 lm_1 lm_2 lm_3 + * @text + * + * lambda ( name(1) : type(1), ..., ) : type body-expr ; + * ^ ^ ^ ^ ^ ^ + * | | | | lm_4 lm_5 + * | | | lm_3 + * lm_0 lm_1 lm_2 * * lm_0 --on_lambda_token()--> lm_1 * lm_1 --on_formal_arglist()--> lm_2 * lm_2 --on_expr()--> lm_3 - * lm_3 --on_semicolon_token()--> (done) + * lm_5 --on_semicolon_token()--> (done) + * + * @endtext **/ enum class lambdastatetype { invalid = -1, @@ -29,6 +34,8 @@ namespace xo { lm_1, lm_2, lm_3, + lm_4, + lm_5, n_lambdastatetype }; @@ -60,12 +67,18 @@ namespace xo { virtual void on_lambda_token(const token_type & tk, parserstatemachine * p_psm) override; + virtual void on_typedescr(TypeDescr td, + parserstatemachine * p_psm) override; virtual void on_formal_arglist(const std::vector> & argl, parserstatemachine * p_psm) override; virtual void on_expr(bp expr, parserstatemachine * p_psm) override; virtual void on_expr_with_semicolon(bp expr, parserstatemachine * p_psm) override; + virtual void on_leftbrace_token(const token_type & tk, + parserstatemachine * p_psm) override; + virtual void on_colon_token(const token_type & tk, + parserstatemachine * p_psm) override; virtual void on_semicolon_token(const token_type & tk, parserstatemachine * p_psm) override; @@ -81,6 +94,9 @@ namespace xo { /** lambda environment (for formal parameters) **/ rp local_env_; + /** explicit return type (if supplied) **/ + TypeDescr explicit_return_td_ = nullptr; + /** body expression **/ rp body_; diff --git a/include/xo/reader/pretty_envframestack.hpp b/include/xo/reader/pretty_envframestack.hpp index 043b0eb2..be890b59 100644 --- a/include/xo/reader/pretty_envframestack.hpp +++ b/include/xo/reader/pretty_envframestack.hpp @@ -16,5 +16,6 @@ namespace xo { return p->pretty_print(ppii); } }; + } /*namespace print*/ } /*namespace xo*/ diff --git a/include/xo/reader/pretty_parserstatemachine.hpp b/include/xo/reader/pretty_parserstatemachine.hpp index 512a6844..50e6737f 100644 --- a/include/xo/reader/pretty_parserstatemachine.hpp +++ b/include/xo/reader/pretty_parserstatemachine.hpp @@ -14,5 +14,10 @@ namespace xo { struct ppdetail { static bool print_pretty(const ppindentinfo & ppii, const xo::scm::parserstatemachine & x); }; + + template<> + struct ppdetail { + static bool print_pretty(const ppindentinfo & ppii, const xo::scm::parserstatemachine * x); + }; } } /*namespace xo*/ diff --git a/include/xo/reader/sequence_xs.hpp b/include/xo/reader/sequence_xs.hpp index fd16ffb5..22e9a325 100644 --- a/include/xo/reader/sequence_xs.hpp +++ b/include/xo/reader/sequence_xs.hpp @@ -26,10 +26,14 @@ namespace xo { virtual void on_expr(bp expr, parserstatemachine * p_psm) override; + virtual void on_expr_with_semicolon(bp expr, + parserstatemachine * p_psm) override; virtual void on_rightbrace_token(const token_type & tk, parserstatemachine * p_psm) override; + virtual void print(std::ostream & os) const override; + private: sequence_xs(); diff --git a/src/reader/expect_expr_xs.cpp b/src/reader/expect_expr_xs.cpp index e899f3cb..68f5a12d 100644 --- a/src/reader/expect_expr_xs.cpp +++ b/src/reader/expect_expr_xs.cpp @@ -229,8 +229,7 @@ namespace xo { expect_expr_xs::on_expr(bp expr, parserstatemachine * p_psm) { - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(p_psm->debug_flag())); log && log(xtag("exstype", this->exs_type_), xtag("expr", expr.promote())); @@ -244,8 +243,7 @@ namespace xo { expect_expr_xs::on_expr_with_semicolon(bp expr, parserstatemachine * p_psm) { - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(p_psm->debug_flag())); log && log(xtag("exstype", this->exs_type_), xtag("expr", expr.promote())); diff --git a/src/reader/exprstate.cpp b/src/reader/exprstate.cpp index 07612db4..e4311bd8 100644 --- a/src/reader/exprstate.cpp +++ b/src/reader/exprstate.cpp @@ -109,8 +109,7 @@ namespace xo { { /* returning type description to something that wants it */ - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(p_psm->debug_flag())); log && log(xtag("exstype", p_psm->top_exprstate().exs_type())); @@ -171,8 +170,7 @@ namespace xo { exprstate::on_colon_token(const token_type & tk, parserstatemachine * p_psm) { - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(p_psm->debug_flag())); constexpr const char * c_self_name = "exprstate::on_colon"; const char * exp = get_expect_str(); diff --git a/src/reader/exprstatestack.cpp b/src/reader/exprstatestack.cpp index effff3a9..4ccad6d6 100644 --- a/src/reader/exprstatestack.cpp +++ b/src/reader/exprstatestack.cpp @@ -4,6 +4,7 @@ */ #include "exprstatestack.hpp" +#include "pretty_exprstatestack.hpp" #include namespace xo { diff --git a/src/reader/lambda_xs.cpp b/src/reader/lambda_xs.cpp index e8111e66..61144b54 100644 --- a/src/reader/lambda_xs.cpp +++ b/src/reader/lambda_xs.cpp @@ -5,6 +5,7 @@ #include "exprstatestack.hpp" #include "expect_formal_arglist_xs.hpp" #include "expect_expr_xs.hpp" +#include "expect_type_xs.hpp" #include "xo/expression/Lambda.hpp" namespace xo { @@ -20,6 +21,8 @@ namespace xo { case lambdastatetype::lm_1: return "lm_1"; case lambdastatetype::lm_2: return "lm_2"; case lambdastatetype::lm_3: return "lm_3"; + case lambdastatetype::lm_4: return "lm_4"; + case lambdastatetype::lm_5: return "lm_5"; default: break; } @@ -47,9 +50,11 @@ namespace xo { lambda_xs::get_expect_str() const { /* - * lambda (x : f64) { ... } ; - * ^ ^ ^ ^ - * | | | lm_3 + * lambda (x : f64) : f64 { ... } ; + * ^ ^ ^ ^ ^ ^ + * | | | | | lm_5 + * | | | | lm_4:expect_expression + * | | | lm_3 * | | lm_2 * | lm_1: * expect_expression @@ -63,8 +68,12 @@ namespace xo { case lambdastatetype::lm_1: return "lambda-params"; case lambdastatetype::lm_2: - return "lambda-body"; + return "colon|lambda-body"; case lambdastatetype::lm_3: + return "type"; + case lambdastatetype::lm_4: + return "lambda-body"; + case lambdastatetype::lm_5: return "semicolon"; } @@ -94,24 +103,12 @@ namespace xo { p_psm->push_envframe(local_env_); - expect_expr_xs::start(p_psm); + //expect_expr_xs::start(p_psm); } else { exprstate::on_formal_arglist(argl, p_psm); } } - void - lambda_xs::on_expr(bp expr, - parserstatemachine * p_psm) - { - if (lmxs_type_ == lambdastatetype::lm_2) { - this->lmxs_type_ = lambdastatetype::lm_3; - this->body_ = expr.promote(); - } else { - exprstate::on_expr(expr, p_psm); - } - } - void lambda_xs::on_expr_with_semicolon(bp expr, parserstatemachine * p_psm) @@ -120,11 +117,74 @@ namespace xo { this->on_semicolon_token(token_type::semicolon(), p_psm); } + void + lambda_xs::on_colon_token(const token_type & tk, + parserstatemachine * p_psm) + { + constexpr const char * c_self_name = "lambda_xs::on_colon_token"; + + if (lmxs_type_ == lambdastatetype::lm_2) { + this->lmxs_type_ = lambdastatetype::lm_3; + expect_type_xs::start(p_psm); + /* control reenters via .on_typedescr() */ + } else { + this->illegal_input_on_token(c_self_name, tk, this->get_expect_str(), p_psm); + } + } + + void + lambda_xs::on_leftbrace_token(const token_type & tk, + parserstatemachine * p_psm) + { + constexpr const char * c_self_name = "lambda_xs::on_leftbrace_token"; + + if (lmxs_type_ == lambdastatetype::lm_2) + this->lmxs_type_ = lambdastatetype::lm_4; + + if (lmxs_type_ == lambdastatetype::lm_4) { + expect_expr_xs::start(p_psm); + /* want { to start expr sequence, that finishes on matching } */ + p_psm->on_leftbrace_token(token_type::leftbrace()); + } else { + this->illegal_input_on_token(c_self_name, tk, this->get_expect_str(), p_psm); + } + } + + void + lambda_xs::on_typedescr(TypeDescr td, + parserstatemachine * p_psm) + { + constexpr const char * c_self_name = "lambda_xs::on_typedescr"; + + if (lmxs_type_ == lambdastatetype::lm_3) { + this->lmxs_type_ = lambdastatetype::lm_4; + this->explicit_return_td_ = td; + expect_expr_xs::start(p_psm); + /* control reenters via .on_expr() or .on_expr_with_semicolon() */ + } else { + this->illegal_input_on_type(c_self_name, td, this->get_expect_str(), p_psm); + } + } + + void + lambda_xs::on_expr(bp expr, + parserstatemachine * p_psm) + { + constexpr const char * c_self_name = "lambda_xs::on_expr"; + + if (lmxs_type_ == lambdastatetype::lm_4) { + this->lmxs_type_ = lambdastatetype::lm_5; + this->body_ = expr.promote(); + } else { + this->illegal_input_on_expr(c_self_name, expr, this->get_expect_str(), p_psm); + } + } + void lambda_xs::on_semicolon_token(const token_type & tk, parserstatemachine * p_psm) { - if (lmxs_type_ == lambdastatetype::lm_3) { + if (lmxs_type_ == lambdastatetype::lm_5) { /* done! */ std::unique_ptr self = p_psm->pop_exprstate(); @@ -134,7 +194,7 @@ namespace xo { /* top env frame recorded arguments to this lambda */ p_psm->pop_envframe(); - rp lm = Lambda::make_from_env(name, local_env_, body_); + rp lm = Lambda::make_from_env(name, local_env_, explicit_return_td_, body_); p_psm->top_exprstate().on_expr(lm, p_psm); p_psm->top_exprstate().on_semicolon_token(tk, p_psm); diff --git a/src/reader/let1_xs.cpp b/src/reader/let1_xs.cpp index 99cae693..1a2c444e 100644 --- a/src/reader/let1_xs.cpp +++ b/src/reader/let1_xs.cpp @@ -141,6 +141,7 @@ namespace xo { rp lambda = Lambda::make_from_env(lambda_name, local_env_, + nullptr /*explicit_return_td*/, expr); rp result diff --git a/src/reader/pretty_parserstatemachine.cpp b/src/reader/pretty_parserstatemachine.cpp index 693c1983..3e03b136 100644 --- a/src/reader/pretty_parserstatemachine.cpp +++ b/src/reader/pretty_parserstatemachine.cpp @@ -36,5 +36,19 @@ namespace xo { } } + bool + ppdetail::print_pretty(const ppindentinfo & ppii, const xo::scm::parserstatemachine * x) + { + if (x) { + return ppdetail::print_pretty(ppii, *x); + } else { + if (ppii.upto()) { + return ppii.pps()->print_upto(""); + } else { + ppii.pps()->write(""); + return false; + } + } + } } /*namespace print*/ } /*namespace xo*/ diff --git a/src/reader/sequence_xs.cpp b/src/reader/sequence_xs.cpp index 365b9747..0d5b51ab 100644 --- a/src/reader/sequence_xs.cpp +++ b/src/reader/sequence_xs.cpp @@ -36,8 +36,7 @@ namespace xo { sequence_xs::on_expr(bp expr, parserstatemachine * p_psm) { - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(p_psm->debug_flag())); log && log(xtag("expr", expr.promote())); @@ -93,6 +92,14 @@ namespace xo { } } + void + sequence_xs::on_expr_with_semicolon(bp expr, + parserstatemachine * p_psm) + { + /* sequence continues until right brace */ + this->on_expr(expr, p_psm); + } + void sequence_xs::on_rightbrace_token(const token_type & /*tk*/, parserstatemachine * p_psm) @@ -107,6 +114,11 @@ namespace xo { p_psm->top_exprstate().on_expr(expr, p_psm); } + void + sequence_xs::print(std::ostream & os) const { + os << ""; + } + } /*namespace scm*/ } /*namespace xo*/