diff --git a/xo-expression2/include/xo/expression2/DLambdaExpr.hpp b/xo-expression2/include/xo/expression2/DLambdaExpr.hpp index bd9ff2c5..14be115f 100644 --- a/xo-expression2/include/xo/expression2/DLambdaExpr.hpp +++ b/xo-expression2/include/xo/expression2/DLambdaExpr.hpp @@ -47,6 +47,14 @@ namespace xo { const DUniqueString * name, DLocalSymtab * local_symtab, obj body); + + /** create type description for lambda with arguments described by @p symtab + * and return type @p return_td. + * Load-bearing for DLambdaSsm in xo-reader2/ + **/ + static TypeDescr assemble_lambda_td(DLocalSymtab * symtab, + TypeDescr return_td); + ///@} /** @defgroup scm-lambdaexpr-methods **/ ///@{ diff --git a/xo-expression2/src/expression2/DLambdaExpr.cpp b/xo-expression2/src/expression2/DLambdaExpr.cpp index fec939ac..a27e788b 100644 --- a/xo-expression2/src/expression2/DLambdaExpr.cpp +++ b/xo-expression2/src/expression2/DLambdaExpr.cpp @@ -14,6 +14,8 @@ namespace xo { using xo::print::APrintable; using xo::facet::FacetRegistry; using xo::reflect::TypeDescr; + using xo::reflect::TypeDescrBase; + using xo::reflect::FunctionTdxInfo; using xo::reflect::typeseq; namespace scm { @@ -82,6 +84,33 @@ namespace xo { body); } + TypeDescr + DLambdaExpr::assemble_lambda_td(DLocalSymtab * symtab, + TypeDescr return_td) + { + assert(return_td); + + std::vector arg_td_v; + { + DLocalSymtab::size_type z = symtab->size(); + + arg_td_v.reserve(z); + + for (DLocalSymtab::size_type i = 0; i < z; ++i) { + auto param = symtab->lookup_var(Binding::local(i)); + + assert(param); + arg_td_v.push_back(param->valuetype()); + } + } + + auto function_tdx = FunctionTdxInfo(return_td, arg_td_v, false /*!is_noexcept*/); + + TypeDescr lambda_td = TypeDescrBase::require_by_fn_info(function_tdx); + + return lambda_td; + } + exprtype DLambdaExpr::extype() const noexcept { return exprtype::lambda; diff --git a/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp b/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp index ae4154ef..accdbff3 100644 --- a/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp +++ b/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp @@ -32,8 +32,7 @@ namespace xo { bool allow_defs, bool cxl_on_rightparen, ParserStateMachine * p_psm); - static void start(DArena & parser_mm, - ParserStateMachine * p_psm); + static void start(ParserStateMachine * p_psm); /** @defgroup scm-expectexpr-access-methods access methods **/ ///@{ diff --git a/xo-reader2/include/xo/reader2/DLambdaSsm.hpp b/xo-reader2/include/xo/reader2/DLambdaSsm.hpp index 22185269..1be39031 100644 --- a/xo-reader2/include/xo/reader2/DLambdaSsm.hpp +++ b/xo-reader2/include/xo/reader2/DLambdaSsm.hpp @@ -88,6 +88,12 @@ namespace xo { void on_lambda_token(const Token & tk, ParserStateMachine * p_psm); + /** update ssm on yield token @p tk, + * with overall parser state in @p p_psm + **/ + void on_yields_token(const Token & tk, + ParserStateMachine * p_psm); + ///@} /** @defgroup scm-lambdassm-syntaxstatemachine-facet **/ ///@{ @@ -174,13 +180,11 @@ namespace xo { /** lambda environment (for formal parameters) **/ DLocalSymtab * local_symtab_ = nullptr; -#ifdef NOT_YET /** explicit return type (if supplied) **/ TypeDescr explicit_return_td_ = nullptr; /** lambda signature (when known) **/ TypeDescr lambda_td_ = nullptr; -#endif /** body expression **/ obj body_; diff --git a/xo-reader2/src/reader2/DDefineSsm.cpp b/xo-reader2/src/reader2/DDefineSsm.cpp index 1636c4b0..4e2bcf97 100644 --- a/xo-reader2/src/reader2/DDefineSsm.cpp +++ b/xo-reader2/src/reader2/DDefineSsm.cpp @@ -643,8 +643,7 @@ namespace xo { { this->defstate_ = defexprstatetype::def_5; - DExpectExprSsm::start(p_psm->parser_alloc(), - p_psm); + DExpectExprSsm::start(p_psm); return; } diff --git a/xo-reader2/src/reader2/DExpectExprSsm.cpp b/xo-reader2/src/reader2/DExpectExprSsm.cpp index c7fe298a..3f99daca 100644 --- a/xo-reader2/src/reader2/DExpectExprSsm.cpp +++ b/xo-reader2/src/reader2/DExpectExprSsm.cpp @@ -83,10 +83,9 @@ namespace xo { } void - DExpectExprSsm::start(DArena & mm, - ParserStateMachine * p_psm) + DExpectExprSsm::start(ParserStateMachine * p_psm) { - start(mm, + start(p_psm->parser_alloc(), false /*!allow_defs*/, false /*!cxl_on_rightbrace*/, p_psm); diff --git a/xo-reader2/src/reader2/DIfElseSsm.cpp b/xo-reader2/src/reader2/DIfElseSsm.cpp index f0bf9556..fb66701a 100644 --- a/xo-reader2/src/reader2/DIfElseSsm.cpp +++ b/xo-reader2/src/reader2/DIfElseSsm.cpp @@ -215,8 +215,7 @@ namespace xo { if (ifstate_ == ifexprstatetype::if_0) { this->ifstate_ = ifexprstatetype::if_1; - DExpectExprSsm::start(p_psm->parser_alloc(), - p_psm); + DExpectExprSsm::start(p_psm); return; } @@ -236,7 +235,7 @@ namespace xo { if (ifstate_ == ifexprstatetype::if_2) { this->ifstate_ = ifexprstatetype::if_3; - DExpectExprSsm::start(p_psm->parser_alloc(), p_psm); + DExpectExprSsm::start(p_psm); return; } @@ -279,7 +278,7 @@ namespace xo { if (ifstate_ == ifexprstatetype::if_4) { this->ifstate_ = ifexprstatetype::if_5; - DExpectExprSsm::start(p_psm->parser_alloc(), p_psm); + DExpectExprSsm::start(p_psm); return; } diff --git a/xo-reader2/src/reader2/DLambdaSsm.cpp b/xo-reader2/src/reader2/DLambdaSsm.cpp index 4bcbb844..3e33c627 100644 --- a/xo-reader2/src/reader2/DLambdaSsm.cpp +++ b/xo-reader2/src/reader2/DLambdaSsm.cpp @@ -7,6 +7,8 @@ #include "ssm/ISyntaxStateMachine_DLambdaSsm.hpp" #include "DExpectFormalArglistSsm.hpp" #include "ssm/ISyntaxStateMachine_DExpectFormalArglistSsm.hpp" +#include "DExpectTypeSsm.hpp" +#include "DExpectExprSsm.hpp" #include "ParserStateMachine.hpp" #include "syntaxstatetype.hpp" #include @@ -89,11 +91,11 @@ namespace xo { DLambdaSsm::get_expect_str() const noexcept { /* - * lambda (x : f64) : f64 { ... } ; - * ^ ^ ^ ^ ^ ^ - * | | | | | lm_5 - * | | | | lm_4:expect_expression - * | | | lm_3 + * lambda (x : f64) -> f64 { ... } ; + * ^ ^ ^ ^ ^ ^ + * | | | | | lm_5 + * | | | | lm_4:expect_expression + * | | | lm_3 * | | lm_2 * | lm_1: * expect_expression @@ -108,7 +110,7 @@ namespace xo { case lambdastatetype::lm_1: return "lambda-params"; case lambdastatetype::lm_2: - return "colon|lambda-body"; + return "yields|lambda-body"; case lambdastatetype::lm_3: return "type"; case lambdastatetype::lm_4: @@ -129,6 +131,10 @@ namespace xo { this->on_lambda_token(tk, p_psm); return; + case tokentype::tk_yields: + this->on_yields_token(tk, p_psm); + return; + // all the not-yet-handled cases case tokentype::tk_def: case tokentype::tk_if: @@ -155,7 +161,6 @@ namespace xo { case tokentype::tk_comma: case tokentype::tk_doublecolon: case tokentype::tk_assign: - case tokentype::tk_yields: case tokentype::tk_plus: case tokentype::tk_minus: case tokentype::tk_star: @@ -194,25 +199,44 @@ namespace xo { this->get_expect_str()); } - -#ifdef NOT_YET void - lambda_xs::on_formal_arglist(const std::vector> & argl, - parserstatemachine * p_psm) + DLambdaSsm::on_yields_token(const Token & tk, + ParserStateMachine * p_psm) { - if (lmxs_type_ == lambdastatetype::lm_1) { - this->lmxs_type_ = lambdastatetype::lm_2; - this->parent_env_ = p_psm->top_envframe().promote(); - this->local_env_ = LocalSymtab::make(argl, parent_env_); + if (lmstate_ == lambdastatetype::lm_2) { + this->lmstate_ = lambdastatetype::lm_3; - p_psm->push_envframe(local_env_); + DExpectTypeSsm::start(p_psm); - //expect_expr_xs::start(p_psm); - } else { - exprstate::on_formal_arglist(argl, p_psm); + /* control reenters via .on_parsed_typedescr() */ + return; } + + p_psm->illegal_input_on_token("DLambdaSsm::on_yields_token", + tk, + this->get_expect_str()); } + + void + DLambdaSsm::on_parsed_typedescr(TypeDescr td, + ParserStateMachine * p_psm) + { + if (lmstate_ == lambdastatetype::lm_3) { + this->lmstate_ = lambdastatetype::lm_4; + this->explicit_return_td_ = td; + this->lambda_td_ = DLambdaExpr::assemble_lambda_td(local_symtab_, td); + + DExpectExprSsm::start(p_psm); + return; + } + + p_psm->illegal_input_on_typedescr("DLambdaSsm::on_parsed_typedescr", + td, + this->get_expect_str()); + } + +#ifdef NOT_YET void lambda_xs::on_expr_with_semicolon(bp expr, parserstatemachine * p_psm) @@ -221,21 +245,6 @@ 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) @@ -255,84 +264,6 @@ namespace xo { } #endif - void - DLambdaSsm::on_parsed_typedescr(TypeDescr td, - ParserStateMachine * p_psm) - { - p_psm->illegal_input_on_typedescr("DLambdaSsm::on_parsed_typedescr", - td, - this->get_expect_str()); - } - -#ifdef NOT_YET - void - lambda_xs::on_typedescr(TypeDescr td, - parserstatemachine * p_psm) - { - constexpr const char * c_self_name = "lambda_xs::on_typedescr"; - scope log(XO_DEBUG(p_psm->debug_flag())); - - assert(td); - - if (lmxs_type_ == lambdastatetype::lm_3) { - this->lmxs_type_ = lambdastatetype::lm_4; - this->explicit_return_td_ = td; - - this->lambda_td_ = Lambda::assemble_lambda_td(local_env_->argv(), - explicit_return_td_); - - /* 1. at this point we know function signature (@ref lambda_td_) - * 2. if this lambda appears on the rhs of a define, - * propagate function signature to the define. - * 3. this makes recursive function definitions like this work - * without relying on type inference: - * def fact = lambda (n : i64) : i64 { - * if (n == 0) then - * 1 - * else - * n * fact(n - 1) - * } - * 4. while parsing the body of the lambda, we want environment - * to already associate the lambda's signature with variable 'fact', - * so that when parser encounters 'fact(n - 1)' the expression has - * known valuetype. - */ - - if ((p_psm->exprstate_stack_size() >= 3) - && (p_psm->lookup_exprstate(1).exs_type() == exprstatetype::expect_rhs_expression) - && (p_psm->lookup_exprstate(2).exs_type() == exprstatetype::defexpr) - && (p_psm->env_stack_size() >= 2) - ) - { - const define_xs * def_xs = dynamic_cast(&(p_psm->lookup_exprstate(2))); - - assert(def_xs); - - 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.get()), - 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, - * that's because it was explicitly specified. - * will discover any conflict after reporting parsed lambda - * to define_xs - */ - } - } - - 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); - } - } -#endif - void DLambdaSsm::on_parsed_symbol(std::string_view sym, ParserStateMachine * p_psm) @@ -376,8 +307,9 @@ namespace xo { for (DArray::size_type i = 0, n = arglist->size(); i < n; ++i) { obj param = arglist->at(i); + // TODO: // sad! runtime poly conversion from obj - // We on need this because of (suboptimally) using DArray to store arglist + // We need this because of (suboptimally) using DArray to store arglist obj param_expr = FacetRegistry::instance().variant(param); @@ -503,12 +435,6 @@ namespace xo { // TODO: on_i64_token, on_bool token - void - lambda_xs::print(std::ostream & os) const { - os << ""; - } #endif bool diff --git a/xo-reader2/src/reader2/DProgressSsm.cpp b/xo-reader2/src/reader2/DProgressSsm.cpp index 57e21ec8..5a6317a3 100644 --- a/xo-reader2/src/reader2/DProgressSsm.cpp +++ b/xo-reader2/src/reader2/DProgressSsm.cpp @@ -398,7 +398,7 @@ namespace xo { // tk is the operator this instance was waiting for this->op_type_ = tk2op(tk.tk_type()); - DExpectExprSsm::start(p_psm->parser_alloc(), p_psm); + DExpectExprSsm::start(p_psm); return; } else if (rhs_) { optype op_type2 = tk2op(tk.tk_type()); @@ -441,15 +441,13 @@ namespace xo { lhs_, op_type_, p_psm); - DExpectExprSsm::start(p_psm->parser_alloc(), - p_psm); + DExpectExprSsm::start(p_psm); /* (b * ..) */ DProgressSsm::start(p_psm->parser_alloc(), rhs_, op_type2, p_psm); - DExpectExprSsm::start(p_psm->parser_alloc(), - p_psm); + DExpectExprSsm::start(p_psm); return; } } diff --git a/xo-reader2/utest/SchematikaParser.test.cpp b/xo-reader2/utest/SchematikaParser.test.cpp index cc1e51fa..0d7dbba4 100644 --- a/xo-reader2/utest/SchematikaParser.test.cpp +++ b/xo-reader2/utest/SchematikaParser.test.cpp @@ -339,7 +339,43 @@ namespace xo { REQUIRE(result.is_incomplete()); } + { + auto & result = parser.on_token(Token::yields_token()); + + log && log("after yields token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == true); + REQUIRE(!result.is_error()); + REQUIRE(result.is_incomplete()); + } + + { + auto & result = parser.on_token(Token::symbol_token("i64")); + + log && log("after symbol(i64) token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == true); + REQUIRE(!result.is_error()); + REQUIRE(result.is_incomplete()); + } + #ifdef NOT_YET + { + auto & result = parser.on_token(Token::leftbrace_token()); + + log && log("after leftbrace token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == true); + REQUIRE(!result.is_error()); + REQUIRE(result.is_incomplete()); + } + { auto & result = parser.on_token(Token::string_token("fooey")); diff --git a/xo-tokenizer2/include/xo/tokenizer2/Token.hpp b/xo-tokenizer2/include/xo/tokenizer2/Token.hpp index 66427c3e..fc5dfc9a 100644 --- a/xo-tokenizer2/include/xo/tokenizer2/Token.hpp +++ b/xo-tokenizer2/include/xo/tokenizer2/Token.hpp @@ -100,7 +100,7 @@ namespace xo { /** token representing right bracket @c "]" **/ static Token rightbracket() { return Token(tokentype::tk_rightbracket); } /** token representing left brace @c "{" **/ - static Token leftbrace() { return Token(tokentype::tk_leftbrace); } + static Token leftbrace_token() { return Token(tokentype::tk_leftbrace); } /** token representing right brace @c "}" **/ static Token rightbrace() { return Token(tokentype::tk_rightbrace); } /** token representing period @c "." **/ @@ -117,8 +117,8 @@ namespace xo { static Token singleassign_token() { return Token(tokentype::tk_singleassign); } /** token representing unrestricted assignment @c ":=" **/ static Token assign_token() { return Token(tokentype::tk_assign); } - /** token representing indirection @c "->" **/ - static Token yields() { return Token(tokentype::tk_yields); } + /** token representing indirection @c "->" / function return type **/ + static Token yields_token() { return Token(tokentype::tk_yields); } /** token for @c "+" **/ static Token plus_token() { return Token(tokentype::tk_plus); }