diff --git a/include/xo/reader/expect_expr_xs.hpp b/include/xo/reader/expect_expr_xs.hpp index fa6c4630..740eecc8 100644 --- a/include/xo/reader/expect_expr_xs.hpp +++ b/include/xo/reader/expect_expr_xs.hpp @@ -19,6 +19,9 @@ namespace xo { static std::unique_ptr expect_rhs_expression(); + virtual void on_lambda_token(const token_type & tk, + exprstatestack * p_stack, + rp * p_emit_expr) override; virtual void on_leftparen_token(const token_type & tk, exprstatestack * p_stack, rp * p_emit_expr) override; diff --git a/include/xo/reader/expect_formal_arglist_xs.hpp b/include/xo/reader/expect_formal_arglist_xs.hpp new file mode 100644 index 00000000..88b0adc1 --- /dev/null +++ b/include/xo/reader/expect_formal_arglist_xs.hpp @@ -0,0 +1,55 @@ +/* file expect_formal_arglist_xs.hpp + * + * author: Roland Conybeare, Aug 2024 + */ + +#pragma once + +#include "exprstate.hpp" +#include "formal_arg.hpp" +#include + +namespace xo { + namespace scm { + enum class formalarglstatetype { + invalid = -1, + + argl_0, + argl_1, + + n_formalarglstatetype, + }; + + /** @class expect_formal_arglist + * @brief parser state-machine for a formal parameter list + * + * ( name(1) : type(1), ..., ) + * ^ + * | + * argl_0 + **/ + class expect_formal_arglist_xs : public exprstate { + public: + expect_formal_arglist_xs(); + + static std::unique_ptr make(); + + const std::vector & argl() const { return argl_; } + + virtual void on_leftparen_token(const token_type & tk, + exprstatestack * p_stack, + rp * p_emit_expr) override; + + private: + /** parsing state-machine state **/ + formalarglstatetype farglxs_type_; + /** populate with (parmaeter-name, parameter-type) list + * as they're encountered + **/ + std::vector argl_; + }; + } /*namespace scm*/ +} /*namespace xo*/ + + +/* end expect_formal_arglist_xs.hpp */ diff --git a/include/xo/reader/exprstate.hpp b/include/xo/reader/exprstate.hpp index 74d8f0dc..65dd944e 100644 --- a/include/xo/reader/exprstate.hpp +++ b/include/xo/reader/exprstate.hpp @@ -59,6 +59,7 @@ namespace xo { class exprstate { public: using Expression = xo::ast::Expression; + using Variable = xo::ast::Variable; using exprtype = xo::ast::exprtype; using token_type = token; using TypeDescr = xo::reflect::TypeDescr; @@ -92,9 +93,13 @@ namespace xo { exprstatestack * p_stack, rp * p_emit_expr); /** update exprstate when expecting a formal parameter **/ - virtual void on_formal(const formal_arg & formal, + virtual void on_formal(const rp & formal, exprstatestack * p_stack, rp * p_emit_expr); + /** update expression when epecting a formal parameter list **/ + virtual void on_formal_arglist(const std::vector> & argl, + exprstatestack * p_stack, + rp * p_emit_expr); /** print human-readable representation on @p os **/ virtual void print(std::ostream & os) const; @@ -103,6 +108,10 @@ namespace xo { /** handle incoming 'def' token **/ virtual void on_def_token(const token_type & tk, exprstatestack * p_stack); + /** handle incoming 'lambda' token **/ + virtual void on_lambda_token(const token_type & tk, + exprstatestack * p_stack, + rp * p_emit_expr); /** handle incoming symbol token **/ virtual void on_symbol_token(const token_type & tk, exprstatestack * p_stack, diff --git a/include/xo/reader/lambda_xs.hpp b/include/xo/reader/lambda_xs.hpp index 4c72efe9..4b4fb74c 100644 --- a/include/xo/reader/lambda_xs.hpp +++ b/include/xo/reader/lambda_xs.hpp @@ -10,14 +10,60 @@ namespace xo { namespace scm { + /** + * lambda ( name(1) : type(1), ..., ) body-expr ; + * ^ ^ ^ ^ + * | | | | + * lm_0 lm_1 lm_2 lm_3 + * + * 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) + **/ + enum class lambdastatetype { + invalid = -1, + + lm_0, + lm_1, + lm_2, + lm_3, + + n_lambdastatetype + }; + /** @class lambda_xs * @brief parsing state-machine for a lambda-expression + * **/ class lambda_xs : public exprstate { public: lambda_xs(); + static std::unique_ptr make(); + + virtual void on_lambda_token(const token_type & tk, + exprstatestack * p_stack, + rp * p_emit_expr) override; + virtual void on_formal_arglist(const std::vector> & argl, + exprstatestack * p_stack, + rp * p_emit_expr) override; + virtual void on_expr(ref::brw expr, + exprstatestack * p_stack, + rp * p_emit_expr) override; + virtual void on_semicolon_token(const token_type & tk, + exprstatestack * p_stack, + rp * p_emit_expr) override; + private: + /** parsing state-machine state **/ + lambdastatetype lmxs_type_; + + /** formal parameter list **/ + std::vector> argl_; + + /** body expression **/ + rp body_; }; } /*namespace scm*/ } /*namespace xo*/ diff --git a/src/reader/CMakeLists.txt b/src/reader/CMakeLists.txt index 5be9eb8a..32a4cd5a 100644 --- a/src/reader/CMakeLists.txt +++ b/src/reader/CMakeLists.txt @@ -11,7 +11,9 @@ set(SELF_SRCS exprseq_xs.cpp expect_expr_xs.cpp expect_symbol_xs.cpp + expect_formal_xs.cpp + expect_formal_arglist_xs.cpp expect_type_xs.cpp lambda_xs.cpp) diff --git a/src/reader/expect_expr_xs.cpp b/src/reader/expect_expr_xs.cpp index 131bfc42..fe4a1830 100644 --- a/src/reader/expect_expr_xs.cpp +++ b/src/reader/expect_expr_xs.cpp @@ -4,8 +4,10 @@ */ #include "expect_expr_xs.hpp" +#include "lambda_xs.hpp" #include "paren_xs.hpp" #include "progress_xs.hpp" +#include "xo/expression/Lambda.hpp" #include "xo/expression/Constant.hpp" namespace xo { @@ -23,6 +25,22 @@ namespace xo { : exprstate(exprstatetype::expect_rhs_expression) {} + void + expect_expr_xs::on_lambda_token(const token_type & tk, + exprstatestack * p_stack, + rp * p_emit_expr) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + //constexpr const char * self_name = "exprstate::on_leftparen"; + + /* push lparen_0 to remember to look for subsequent rightparen. */ + p_stack->push_exprstate(lambda_xs::make()); + p_stack->top_exprstate().on_lambda_token(tk, p_stack, p_emit_expr); + //p_stack->push_exprstate(expect_expr_xs::expect_rhs_expression()); + } + void expect_expr_xs::on_leftparen_token(const token_type & /*tk*/, exprstatestack * p_stack, diff --git a/src/reader/expect_formal_arglist_xs.cpp b/src/reader/expect_formal_arglist_xs.cpp new file mode 100644 index 00000000..c540dbd3 --- /dev/null +++ b/src/reader/expect_formal_arglist_xs.cpp @@ -0,0 +1,37 @@ +/* file expect_formal_arglist_xs.cpp + * + * author: Roland Conybeare + */ + +#include "expect_formal_arglist_xs.hpp" + +namespace xo { + namespace scm { + std::unique_ptr + expect_formal_arglist_xs::make() { + return std::make_unique + (expect_formal_arglist_xs()); + } + + expect_formal_arglist_xs::expect_formal_arglist_xs() + : farglxs_type_{formalarglstatetype::argl_0} + {} + + void + expect_formal_arglist_xs::on_leftparen_token(const token_type & tk, + exprstatestack * p_stack, + rp * p_emit_expr) + { + if (farglxs_type_ == formalarglstatetype::argl_0) { + this->farglxs_type_ = formalarglstatetype::argl_1; + return; + } + + exprstate::on_leftparen_token(tk, p_stack, p_emit_expr); + } + + } /*namespace scm*/ +} /*namespace xo*/ + + +/* end expect_formal_arglist_xs.cpp */ diff --git a/src/reader/expect_type_xs.cpp b/src/reader/expect_type_xs.cpp index 6c4c5afb..fa4a517a 100644 --- a/src/reader/expect_type_xs.cpp +++ b/src/reader/expect_type_xs.cpp @@ -11,6 +11,7 @@ namespace xo { using xo::reflect::Reflect; namespace scm { + std::unique_ptr expect_type_xs::make() { return std::make_unique(expect_type_xs()); diff --git a/src/reader/exprstate.cpp b/src/reader/exprstate.cpp index 7e207da8..859d0be8 100644 --- a/src/reader/exprstate.cpp +++ b/src/reader/exprstate.cpp @@ -1,7 +1,9 @@ /* @file exprstate.cpp */ #include "exprstate.hpp" -#include "formal_arg.hpp" +//#include "formal_arg.hpp" +#include "xo/expression/Variable.hpp" +#include "xo/indentlog/print/vector.hpp" #include //#include "define_xs.hpp" //#include "progress_xs.hpp" @@ -49,6 +51,14 @@ namespace xo { this->illegal_input_error("exprstate::on_def_token", tk); } + void + exprstate::on_lambda_token(const token_type & tk, + exprstatestack * /*p_stack*/, + rp * /*p_emit_expr*/) + { + this->illegal_input_error("exprstate::on_lambda_token", tk); + } + void exprstate::on_symbol_token(const token_type & tk, exprstatestack * p_stack, @@ -86,7 +96,7 @@ namespace xo { } void - exprstate::on_formal(const formal_arg & formal, + exprstate::on_formal(const rp & formal, exprstatestack * p_stack, rp * /*p_emit_expr*/) { @@ -102,7 +112,28 @@ namespace xo { throw std::runtime_error(tostr(c_self_name, ": unexpected formal-arg for parsing state", - xtag("formal", formal), + xtag("formal", formal.get()), + xtag("state", *this))); + } + + void + exprstate::on_formal_arglist(const std::vector> & argl, + exprstatestack * p_stack, + rp * /*p_emit_expr*/) + { + /* returning type description to something that wants it */ + + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + log && log(xtag("exstype", + p_stack->top_exprstate().exs_type())); + + constexpr const char * c_self_name = "exprstate::on_formal_arglist"; + + throw std::runtime_error(tostr(c_self_name, + ": unexpected formal-arg for parsing state", + xtag("argl", argl), xtag("state", *this))); } @@ -223,6 +254,10 @@ namespace xo { this->on_def_token(tk, p_stack); return; + case tokentype::tk_lambda: + this->on_lambda_token(tk, p_stack, p_emit_expr); + return; + case tokentype::tk_i64: assert(false); return; @@ -289,7 +324,6 @@ namespace xo { return; case tokentype::tk_type: - case tokentype::tk_lambda: case tokentype::tk_if: case tokentype::tk_let: diff --git a/src/reader/lambda_xs.cpp b/src/reader/lambda_xs.cpp index 603f3585..e38d5718 100644 --- a/src/reader/lambda_xs.cpp +++ b/src/reader/lambda_xs.cpp @@ -1,11 +1,90 @@ /* @file lambda_xs.cpp */ #include "lambda_xs.hpp" +#include "expect_formal_arglist_xs.hpp" +#include "expect_expr_xs.hpp" +#include "xo/expression/Lambda.hpp" namespace xo { + using xo::ast::Lambda; + namespace scm { + std::unique_ptr + lambda_xs::make() { + return std::make_unique(lambda_xs()); + } + lambda_xs::lambda_xs() {} + void + lambda_xs::on_lambda_token(const token_type & tk, + exprstatestack * p_stack, + rp * p_emit_expr) + { + if (lmxs_type_ == lambdastatetype::lm_0) { + this->lmxs_type_ = lambdastatetype::lm_1; + p_stack->push_exprstate(expect_formal_arglist_xs::make()); + return; + } + + exprstate::on_lambda_token(tk, + p_stack, + p_emit_expr); + } + + void + lambda_xs::on_formal_arglist(const std::vector> & argl, + exprstatestack * p_stack, + rp * p_emit_expr) + { + if (lmxs_type_ == lambdastatetype::lm_1) { + this->lmxs_type_ = lambdastatetype::lm_2; + this->argl_ = argl; + p_stack->push_exprstate(expect_expr_xs::expect_rhs_expression()); + return; + } + + exprstate::on_formal_arglist(argl, + p_stack, + p_emit_expr); + } + + void + lambda_xs::on_expr(ref::brw expr, + exprstatestack * p_stack, + rp * p_emit_expr) + { + if (lmxs_type_ == lambdastatetype::lm_2) { + this->lmxs_type_ = lambdastatetype::lm_3; + this->body_ = expr.promote(); + return; + } + + exprstate::on_expr(expr, p_stack, p_emit_expr); + } + + void + lambda_xs::on_semicolon_token(const token_type & tk, + exprstatestack * p_stack, + rp * p_emit_expr) + { + if (lmxs_type_ == lambdastatetype::lm_3) { + /* done! */ + + std::unique_ptr self = p_stack->pop_exprstate(); + + std::string name = "fixmename"; + + rp lm = Lambda::make(name, argl_, body_); + + p_stack->top_exprstate().on_expr(lm, p_stack, p_emit_expr); + p_stack->top_exprstate().on_semicolon_token(tk, p_stack, p_emit_expr); + + return; + } + + exprstate::on_semicolon_token(tk, p_stack, p_emit_expr); + } } /*namespace scm*/ } /*namespace xo*/