xo-reader2: + assemble lambda function type in DLambdaSsm
This commit is contained in:
parent
94efaf46cd
commit
6f2c793b1d
11 changed files with 137 additions and 140 deletions
|
|
@ -47,6 +47,14 @@ namespace xo {
|
|||
const DUniqueString * name,
|
||||
DLocalSymtab * local_symtab,
|
||||
obj<AExpression> 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 **/
|
||||
///@{
|
||||
|
|
|
|||
|
|
@ -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<TypeDescr> 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;
|
||||
|
|
|
|||
|
|
@ -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 **/
|
||||
///@{
|
||||
|
|
|
|||
|
|
@ -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<AExpression> body_;
|
||||
|
|
|
|||
|
|
@ -643,8 +643,7 @@ namespace xo {
|
|||
{
|
||||
this->defstate_ = defexprstatetype::def_5;
|
||||
|
||||
DExpectExprSsm::start(p_psm->parser_alloc(),
|
||||
p_psm);
|
||||
DExpectExprSsm::start(p_psm);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <xo/expression2/DVariable.hpp>
|
||||
|
|
@ -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<rp<Variable>> & 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<Expression> 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<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
|
||||
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<AGCObject> param = arglist->at(i);
|
||||
|
||||
// TODO:
|
||||
// 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
|
||||
= FacetRegistry::instance().variant<AExpression,AGCObject>(param);
|
||||
|
|
@ -503,12 +435,6 @@ namespace xo {
|
|||
|
||||
// TODO: on_i64_token, on_bool token
|
||||
|
||||
void
|
||||
lambda_xs::print(std::ostream & os) const {
|
||||
os << "<lambda_xs"
|
||||
<< xtag("lmxs_type", lmxs_type_)
|
||||
<< ">";
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue