xo-reader2: + assemble lambda function type in DLambdaSsm
This commit is contained in:
parent
f5ccd99dd2
commit
fcf171dfb6
8 changed files with 97 additions and 137 deletions
|
|
@ -32,8 +32,7 @@ namespace xo {
|
||||||
bool allow_defs,
|
bool allow_defs,
|
||||||
bool cxl_on_rightparen,
|
bool cxl_on_rightparen,
|
||||||
ParserStateMachine * p_psm);
|
ParserStateMachine * p_psm);
|
||||||
static void start(DArena & parser_mm,
|
static void start(ParserStateMachine * p_psm);
|
||||||
ParserStateMachine * p_psm);
|
|
||||||
|
|
||||||
/** @defgroup scm-expectexpr-access-methods access methods **/
|
/** @defgroup scm-expectexpr-access-methods access methods **/
|
||||||
///@{
|
///@{
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,12 @@ namespace xo {
|
||||||
void on_lambda_token(const Token & tk,
|
void on_lambda_token(const Token & tk,
|
||||||
ParserStateMachine * p_psm);
|
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 **/
|
/** @defgroup scm-lambdassm-syntaxstatemachine-facet **/
|
||||||
///@{
|
///@{
|
||||||
|
|
@ -174,13 +180,11 @@ namespace xo {
|
||||||
/** lambda environment (for formal parameters) **/
|
/** lambda environment (for formal parameters) **/
|
||||||
DLocalSymtab * local_symtab_ = nullptr;
|
DLocalSymtab * local_symtab_ = nullptr;
|
||||||
|
|
||||||
#ifdef NOT_YET
|
|
||||||
/** explicit return type (if supplied) **/
|
/** explicit return type (if supplied) **/
|
||||||
TypeDescr explicit_return_td_ = nullptr;
|
TypeDescr explicit_return_td_ = nullptr;
|
||||||
|
|
||||||
/** lambda signature (when known) **/
|
/** lambda signature (when known) **/
|
||||||
TypeDescr lambda_td_ = nullptr;
|
TypeDescr lambda_td_ = nullptr;
|
||||||
#endif
|
|
||||||
|
|
||||||
/** body expression **/
|
/** body expression **/
|
||||||
obj<AExpression> body_;
|
obj<AExpression> body_;
|
||||||
|
|
|
||||||
|
|
@ -643,8 +643,7 @@ namespace xo {
|
||||||
{
|
{
|
||||||
this->defstate_ = defexprstatetype::def_5;
|
this->defstate_ = defexprstatetype::def_5;
|
||||||
|
|
||||||
DExpectExprSsm::start(p_psm->parser_alloc(),
|
DExpectExprSsm::start(p_psm);
|
||||||
p_psm);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,10 +83,9 @@ namespace xo {
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DExpectExprSsm::start(DArena & mm,
|
DExpectExprSsm::start(ParserStateMachine * p_psm)
|
||||||
ParserStateMachine * p_psm)
|
|
||||||
{
|
{
|
||||||
start(mm,
|
start(p_psm->parser_alloc(),
|
||||||
false /*!allow_defs*/,
|
false /*!allow_defs*/,
|
||||||
false /*!cxl_on_rightbrace*/,
|
false /*!cxl_on_rightbrace*/,
|
||||||
p_psm);
|
p_psm);
|
||||||
|
|
|
||||||
|
|
@ -215,8 +215,7 @@ namespace xo {
|
||||||
if (ifstate_ == ifexprstatetype::if_0) {
|
if (ifstate_ == ifexprstatetype::if_0) {
|
||||||
this->ifstate_ = ifexprstatetype::if_1;
|
this->ifstate_ = ifexprstatetype::if_1;
|
||||||
|
|
||||||
DExpectExprSsm::start(p_psm->parser_alloc(),
|
DExpectExprSsm::start(p_psm);
|
||||||
p_psm);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,7 +235,7 @@ namespace xo {
|
||||||
if (ifstate_ == ifexprstatetype::if_2) {
|
if (ifstate_ == ifexprstatetype::if_2) {
|
||||||
this->ifstate_ = ifexprstatetype::if_3;
|
this->ifstate_ = ifexprstatetype::if_3;
|
||||||
|
|
||||||
DExpectExprSsm::start(p_psm->parser_alloc(), p_psm);
|
DExpectExprSsm::start(p_psm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -279,7 +278,7 @@ namespace xo {
|
||||||
if (ifstate_ == ifexprstatetype::if_4) {
|
if (ifstate_ == ifexprstatetype::if_4) {
|
||||||
this->ifstate_ = ifexprstatetype::if_5;
|
this->ifstate_ = ifexprstatetype::if_5;
|
||||||
|
|
||||||
DExpectExprSsm::start(p_psm->parser_alloc(), p_psm);
|
DExpectExprSsm::start(p_psm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
#include "ssm/ISyntaxStateMachine_DLambdaSsm.hpp"
|
#include "ssm/ISyntaxStateMachine_DLambdaSsm.hpp"
|
||||||
#include "DExpectFormalArglistSsm.hpp"
|
#include "DExpectFormalArglistSsm.hpp"
|
||||||
#include "ssm/ISyntaxStateMachine_DExpectFormalArglistSsm.hpp"
|
#include "ssm/ISyntaxStateMachine_DExpectFormalArglistSsm.hpp"
|
||||||
|
#include "DExpectTypeSsm.hpp"
|
||||||
|
#include "DExpectExprSsm.hpp"
|
||||||
#include "ParserStateMachine.hpp"
|
#include "ParserStateMachine.hpp"
|
||||||
#include "syntaxstatetype.hpp"
|
#include "syntaxstatetype.hpp"
|
||||||
#include <xo/expression2/DVariable.hpp>
|
#include <xo/expression2/DVariable.hpp>
|
||||||
|
|
@ -89,11 +91,11 @@ namespace xo {
|
||||||
DLambdaSsm::get_expect_str() const noexcept
|
DLambdaSsm::get_expect_str() const noexcept
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* lambda (x : f64) : f64 { ... } ;
|
* lambda (x : f64) -> f64 { ... } ;
|
||||||
* ^ ^ ^ ^ ^ ^
|
* ^ ^ ^ ^ ^ ^
|
||||||
* | | | | | lm_5
|
* | | | | | lm_5
|
||||||
* | | | | lm_4:expect_expression
|
* | | | | lm_4:expect_expression
|
||||||
* | | | lm_3
|
* | | | lm_3
|
||||||
* | | lm_2
|
* | | lm_2
|
||||||
* | lm_1:
|
* | lm_1:
|
||||||
* expect_expression
|
* expect_expression
|
||||||
|
|
@ -108,7 +110,7 @@ namespace xo {
|
||||||
case lambdastatetype::lm_1:
|
case lambdastatetype::lm_1:
|
||||||
return "lambda-params";
|
return "lambda-params";
|
||||||
case lambdastatetype::lm_2:
|
case lambdastatetype::lm_2:
|
||||||
return "colon|lambda-body";
|
return "yields|lambda-body";
|
||||||
case lambdastatetype::lm_3:
|
case lambdastatetype::lm_3:
|
||||||
return "type";
|
return "type";
|
||||||
case lambdastatetype::lm_4:
|
case lambdastatetype::lm_4:
|
||||||
|
|
@ -129,6 +131,10 @@ namespace xo {
|
||||||
this->on_lambda_token(tk, p_psm);
|
this->on_lambda_token(tk, p_psm);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case tokentype::tk_yields:
|
||||||
|
this->on_yields_token(tk, p_psm);
|
||||||
|
return;
|
||||||
|
|
||||||
// all the not-yet-handled cases
|
// all the not-yet-handled cases
|
||||||
case tokentype::tk_def:
|
case tokentype::tk_def:
|
||||||
case tokentype::tk_if:
|
case tokentype::tk_if:
|
||||||
|
|
@ -155,7 +161,6 @@ namespace xo {
|
||||||
case tokentype::tk_comma:
|
case tokentype::tk_comma:
|
||||||
case tokentype::tk_doublecolon:
|
case tokentype::tk_doublecolon:
|
||||||
case tokentype::tk_assign:
|
case tokentype::tk_assign:
|
||||||
case tokentype::tk_yields:
|
|
||||||
case tokentype::tk_plus:
|
case tokentype::tk_plus:
|
||||||
case tokentype::tk_minus:
|
case tokentype::tk_minus:
|
||||||
case tokentype::tk_star:
|
case tokentype::tk_star:
|
||||||
|
|
@ -194,25 +199,44 @@ namespace xo {
|
||||||
this->get_expect_str());
|
this->get_expect_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef NOT_YET
|
|
||||||
void
|
void
|
||||||
lambda_xs::on_formal_arglist(const std::vector<rp<Variable>> & argl,
|
DLambdaSsm::on_yields_token(const Token & tk,
|
||||||
parserstatemachine * p_psm)
|
ParserStateMachine * p_psm)
|
||||||
{
|
{
|
||||||
if (lmxs_type_ == lambdastatetype::lm_1) {
|
if (lmstate_ == lambdastatetype::lm_2) {
|
||||||
this->lmxs_type_ = lambdastatetype::lm_2;
|
this->lmstate_ = lambdastatetype::lm_3;
|
||||||
this->parent_env_ = p_psm->top_envframe().promote();
|
|
||||||
this->local_env_ = LocalSymtab::make(argl, parent_env_);
|
|
||||||
|
|
||||||
p_psm->push_envframe(local_env_);
|
DExpectTypeSsm::start(p_psm);
|
||||||
|
|
||||||
//expect_expr_xs::start(p_psm);
|
/* control reenters via .on_parsed_typedescr() */
|
||||||
} else {
|
return;
|
||||||
exprstate::on_formal_arglist(argl, p_psm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
void
|
||||||
lambda_xs::on_expr_with_semicolon(bp<Expression> expr,
|
lambda_xs::on_expr_with_semicolon(bp<Expression> expr,
|
||||||
parserstatemachine * p_psm)
|
parserstatemachine * p_psm)
|
||||||
|
|
@ -221,21 +245,6 @@ namespace xo {
|
||||||
this->on_semicolon_token(token_type::semicolon(), p_psm);
|
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
|
void
|
||||||
lambda_xs::on_leftbrace_token(const token_type & tk,
|
lambda_xs::on_leftbrace_token(const token_type & tk,
|
||||||
parserstatemachine * p_psm)
|
parserstatemachine * p_psm)
|
||||||
|
|
@ -255,84 +264,6 @@ namespace xo {
|
||||||
}
|
}
|
||||||
#endif
|
#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<const define_xs*>(&(p_psm->lookup_exprstate(2)));
|
|
||||||
|
|
||||||
assert(def_xs);
|
|
||||||
|
|
||||||
bp<Variable> 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
|
void
|
||||||
DLambdaSsm::on_parsed_symbol(std::string_view sym,
|
DLambdaSsm::on_parsed_symbol(std::string_view sym,
|
||||||
ParserStateMachine * p_psm)
|
ParserStateMachine * p_psm)
|
||||||
|
|
@ -376,8 +307,9 @@ namespace xo {
|
||||||
for (DArray::size_type i = 0, n = arglist->size(); i < n; ++i) {
|
for (DArray::size_type i = 0, n = arglist->size(); i < n; ++i) {
|
||||||
obj<AGCObject> param = arglist->at(i);
|
obj<AGCObject> param = arglist->at(i);
|
||||||
|
|
||||||
|
// TODO:
|
||||||
// sad! runtime poly conversion from obj<AGCObject>
|
// sad! runtime poly conversion from obj<AGCObject>
|
||||||
// We on need this because of (suboptimally) using DArray to store arglist
|
// We need this because of (suboptimally) using DArray to store arglist
|
||||||
|
|
||||||
obj<AExpression> param_expr
|
obj<AExpression> param_expr
|
||||||
= FacetRegistry::instance().variant<AExpression,AGCObject>(param);
|
= FacetRegistry::instance().variant<AExpression,AGCObject>(param);
|
||||||
|
|
@ -503,12 +435,6 @@ namespace xo {
|
||||||
|
|
||||||
// TODO: on_i64_token, on_bool token
|
// TODO: on_i64_token, on_bool token
|
||||||
|
|
||||||
void
|
|
||||||
lambda_xs::print(std::ostream & os) const {
|
|
||||||
os << "<lambda_xs"
|
|
||||||
<< xtag("lmxs_type", lmxs_type_)
|
|
||||||
<< ">";
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
||||||
|
|
@ -398,7 +398,7 @@ namespace xo {
|
||||||
// tk is the operator this instance was waiting for
|
// tk is the operator this instance was waiting for
|
||||||
this->op_type_ = tk2op(tk.tk_type());
|
this->op_type_ = tk2op(tk.tk_type());
|
||||||
|
|
||||||
DExpectExprSsm::start(p_psm->parser_alloc(), p_psm);
|
DExpectExprSsm::start(p_psm);
|
||||||
return;
|
return;
|
||||||
} else if (rhs_) {
|
} else if (rhs_) {
|
||||||
optype op_type2 = tk2op(tk.tk_type());
|
optype op_type2 = tk2op(tk.tk_type());
|
||||||
|
|
@ -441,15 +441,13 @@ namespace xo {
|
||||||
lhs_,
|
lhs_,
|
||||||
op_type_,
|
op_type_,
|
||||||
p_psm);
|
p_psm);
|
||||||
DExpectExprSsm::start(p_psm->parser_alloc(),
|
DExpectExprSsm::start(p_psm);
|
||||||
p_psm);
|
|
||||||
/* (b * ..) */
|
/* (b * ..) */
|
||||||
DProgressSsm::start(p_psm->parser_alloc(),
|
DProgressSsm::start(p_psm->parser_alloc(),
|
||||||
rhs_,
|
rhs_,
|
||||||
op_type2,
|
op_type2,
|
||||||
p_psm);
|
p_psm);
|
||||||
DExpectExprSsm::start(p_psm->parser_alloc(),
|
DExpectExprSsm::start(p_psm);
|
||||||
p_psm);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -339,7 +339,43 @@ namespace xo {
|
||||||
REQUIRE(result.is_incomplete());
|
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
|
#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"));
|
auto & result = parser.on_token(Token::string_token("fooey"));
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue