xo-reader2: allow formals w/out explicit type

This commit is contained in:
Roland Conybeare 2026-02-17 16:48:20 -05:00
commit 27c5f66e74
39 changed files with 307 additions and 32 deletions

View file

@ -97,6 +97,10 @@ namespace xo {
case tokentype::tk_colon:
this->on_colon_token(tk, p_psm);
return;
case tokentype::tk_rightparen:
this->on_rightparen_token(tk, p_psm);
return;
// all the not-yet-handled cases
case tokentype::tk_leftparen:
case tokentype::tk_lambda:
@ -110,7 +114,6 @@ namespace xo {
case tokentype::tk_bool:
case tokentype::tk_semicolon:
case tokentype::tk_invalid:
case tokentype::tk_rightparen:
case tokentype::tk_leftbracket:
case tokentype::tk_rightbracket:
case tokentype::tk_leftbrace:
@ -159,6 +162,24 @@ namespace xo {
Super::on_token(tk, p_psm);
}
void
DExpectFormalArgSsm::on_rightparen_token(const Token & tk,
ParserStateMachine * p_psm)
{
if (fstate_ == formalstatetype::formal_1) {
// formal with no type annotation
assert(name_);
p_psm->pop_ssm();
p_psm->on_parsed_formal_with_token(name_, nullptr, tk);
return;
}
Super::on_token(tk, p_psm);
}
void
DExpectFormalArgSsm::on_parsed_symbol(std::string_view sym,
ParserStateMachine * p_psm)

View file

@ -176,6 +176,49 @@ namespace xo {
Super::on_token(tk, p_psm);
}
void
DExpectFormalArglistSsm::_accept_formal(obj<AAllocator> expr_alloc,
DArena & parser_alloc,
const DUniqueString * param_name,
TypeDescr param_type)
{
/* note: param_type can be nullptr */
TypeRef typeref
= TypeRef::dwim(TypeRef::prefix_type::from_chars("formal"), param_type);
DVariable * var = DVariable::make(expr_alloc,
param_name,
typeref);
// need AGCObject facet to use DArray here.
// May want to have gc feature that allows it to use
// FacetRegistry on memory that stores obj<AExpression,..>
//
// In this case doesn't matter since DExpectFormalArglistSsm not actually collected!
obj<AGCObject,DVariable> var_o(var);
if (argl_->size() == argl_->capacity()) {
// need to expand argl_ capacity.
// If DArena were to allow it (i.e. offer a realloc() feature,
// could do this in place since this SSM is at the top of the parser stack.
obj<AAllocator,DArena> mm(&parser_alloc);
DArray * argl_2x = DArray::empty(mm, 2 * argl_->capacity());
for (DArray::size_type i = 0, n = argl_->size(); i < n; ++i) {
// TODO: prefer non-bounds-checked access here
argl_2x->push_back(argl_->at(i));
}
// update in place
this->argl_ = argl_2x;
}
this->argl_->push_back(var_o);
}
void
DExpectFormalArglistSsm::on_parsed_formal(const DUniqueString * param_name,
TypeDescr param_type,
@ -184,46 +227,37 @@ namespace xo {
if (fastate_ == formalarglstatetype::argl_1a) {
this->fastate_ = formalarglstatetype::argl_1b;
TypeRef typeref
= TypeRef::dwim(TypeRef::prefix_type::from_chars("formal"), param_type);
DVariable * var = DVariable::make(p_psm->expr_alloc(),
param_name,
typeref);
// need AGCObject facet to use DArray here.
// May want to have gc feature that allows it to use
// FacetRegistry on memory that stores obj<AExpression,..>
//
// In this case doesn't matter since DExpectFormalArglistSsm not actually collected!
obj<AGCObject,DVariable> var_o(var);
if (argl_->size() == argl_->capacity()) {
// need to expand argl_ capacity.
// If DArena were to allow it (i.e. offer a realloc() feature,
// could do this in place since this SSM is at the top of the parser stack.
obj<AAllocator,DArena> mm(&(p_psm->parser_alloc()));
DArray * argl_2x = DArray::empty(mm, 2 * argl_->capacity());
for (DArray::size_type i = 0, n = argl_->size(); i < n; ++i) {
// TODO: prefer non-bounds-checked access here
argl_2x->push_back(argl_->at(i));
}
// update in place
this->argl_ = argl_2x;
}
this->argl_->push_back(var_o);
this->_accept_formal(p_psm->expr_alloc(),
p_psm->parser_alloc(),
param_name,
param_type);
return;
}
Super::on_parsed_formal(param_name, param_type, p_psm);
}
void
DExpectFormalArglistSsm::on_parsed_formal_with_token(const DUniqueString * param_name,
TypeDescr param_type,
const Token & tk,
ParserStateMachine * p_psm)
{
if (fastate_ == formalarglstatetype::argl_1a) {
this->fastate_ = formalarglstatetype::argl_1b;
this->_accept_formal(p_psm->expr_alloc(),
p_psm->parser_alloc(),
param_name,
param_type);
this->on_token(tk, p_psm);
return;
}
Super::on_parsed_formal_with_token(param_name, param_type, tk, p_psm);
}
void
DExpectFormalArglistSsm::on_leftparen_token(const Token & tk,
ParserStateMachine * p_psm)

View file

@ -58,6 +58,12 @@ ISyntaxStateMachine_Any::on_parsed_formal(Opaque, const DUniqueString *, TypeDes
_fatal();
}
auto
ISyntaxStateMachine_Any::on_parsed_formal_with_token(Opaque, const DUniqueString *, TypeDescr, const Token &, ParserStateMachine *) -> void
{
_fatal();
}
auto
ISyntaxStateMachine_Any::on_parsed_formal_arglist(Opaque, DArray *, ParserStateMachine *) -> void
{

View file

@ -48,6 +48,11 @@ namespace xo {
self.on_parsed_formal(param_name, param_type, p_psm);
}
auto
ISyntaxStateMachine_DApplySsm::on_parsed_formal_with_token(DApplySsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm);
}
auto
ISyntaxStateMachine_DApplySsm::on_parsed_formal_arglist(DApplySsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_arglist(arglist, p_psm);

View file

@ -48,6 +48,11 @@ namespace xo {
self.on_parsed_formal(param_name, param_type, p_psm);
}
auto
ISyntaxStateMachine_DDefineSsm::on_parsed_formal_with_token(DDefineSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm);
}
auto
ISyntaxStateMachine_DDefineSsm::on_parsed_formal_arglist(DDefineSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_arglist(arglist, p_psm);

View file

@ -48,6 +48,11 @@ namespace xo {
self.on_parsed_formal(param_name, param_type, p_psm);
}
auto
ISyntaxStateMachine_DExpectExprSsm::on_parsed_formal_with_token(DExpectExprSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm);
}
auto
ISyntaxStateMachine_DExpectExprSsm::on_parsed_formal_arglist(DExpectExprSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_arglist(arglist, p_psm);

View file

@ -48,6 +48,11 @@ namespace xo {
self.on_parsed_formal(param_name, param_type, p_psm);
}
auto
ISyntaxStateMachine_DExpectFormalArgSsm::on_parsed_formal_with_token(DExpectFormalArgSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm);
}
auto
ISyntaxStateMachine_DExpectFormalArgSsm::on_parsed_formal_arglist(DExpectFormalArgSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_arglist(arglist, p_psm);

View file

@ -48,6 +48,11 @@ namespace xo {
self.on_parsed_formal(param_name, param_type, p_psm);
}
auto
ISyntaxStateMachine_DExpectFormalArglistSsm::on_parsed_formal_with_token(DExpectFormalArglistSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm);
}
auto
ISyntaxStateMachine_DExpectFormalArglistSsm::on_parsed_formal_arglist(DExpectFormalArglistSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_arglist(arglist, p_psm);

View file

@ -48,6 +48,11 @@ namespace xo {
self.on_parsed_formal(param_name, param_type, p_psm);
}
auto
ISyntaxStateMachine_DExpectSymbolSsm::on_parsed_formal_with_token(DExpectSymbolSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm);
}
auto
ISyntaxStateMachine_DExpectSymbolSsm::on_parsed_formal_arglist(DExpectSymbolSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_arglist(arglist, p_psm);

View file

@ -48,6 +48,11 @@ namespace xo {
self.on_parsed_formal(param_name, param_type, p_psm);
}
auto
ISyntaxStateMachine_DExpectTypeSsm::on_parsed_formal_with_token(DExpectTypeSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm);
}
auto
ISyntaxStateMachine_DExpectTypeSsm::on_parsed_formal_arglist(DExpectTypeSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_arglist(arglist, p_psm);

View file

@ -48,6 +48,11 @@ namespace xo {
self.on_parsed_formal(param_name, param_type, p_psm);
}
auto
ISyntaxStateMachine_DIfElseSsm::on_parsed_formal_with_token(DIfElseSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm);
}
auto
ISyntaxStateMachine_DIfElseSsm::on_parsed_formal_arglist(DIfElseSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_arglist(arglist, p_psm);

View file

@ -48,6 +48,11 @@ namespace xo {
self.on_parsed_formal(param_name, param_type, p_psm);
}
auto
ISyntaxStateMachine_DLambdaSsm::on_parsed_formal_with_token(DLambdaSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm);
}
auto
ISyntaxStateMachine_DLambdaSsm::on_parsed_formal_arglist(DLambdaSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_arglist(arglist, p_psm);

View file

@ -48,6 +48,11 @@ namespace xo {
self.on_parsed_formal(param_name, param_type, p_psm);
}
auto
ISyntaxStateMachine_DParenSsm::on_parsed_formal_with_token(DParenSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm);
}
auto
ISyntaxStateMachine_DParenSsm::on_parsed_formal_arglist(DParenSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_arglist(arglist, p_psm);

View file

@ -48,6 +48,11 @@ namespace xo {
self.on_parsed_formal(param_name, param_type, p_psm);
}
auto
ISyntaxStateMachine_DProgressSsm::on_parsed_formal_with_token(DProgressSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm);
}
auto
ISyntaxStateMachine_DProgressSsm::on_parsed_formal_arglist(DProgressSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_arglist(arglist, p_psm);

View file

@ -48,6 +48,11 @@ namespace xo {
self.on_parsed_formal(param_name, param_type, p_psm);
}
auto
ISyntaxStateMachine_DSequenceSsm::on_parsed_formal_with_token(DSequenceSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm);
}
auto
ISyntaxStateMachine_DSequenceSsm::on_parsed_formal_arglist(DSequenceSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_arglist(arglist, p_psm);

View file

@ -48,6 +48,11 @@ namespace xo {
self.on_parsed_formal(param_name, param_type, p_psm);
}
auto
ISyntaxStateMachine_DToplevelSeqSsm::on_parsed_formal_with_token(DToplevelSeqSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm);
}
auto
ISyntaxStateMachine_DToplevelSeqSsm::on_parsed_formal_arglist(DToplevelSeqSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void
{
self.on_parsed_formal_arglist(arglist, p_psm);

View file

@ -286,6 +286,18 @@ namespace xo {
this->stack_->top().on_parsed_formal(sym, td, this);
}
void
ParserStateMachine::on_parsed_formal_with_token(const DUniqueString * sym,
TypeDescr td,
const Token & tk)
{
scope log(XO_DEBUG(debug_flag_), xtag("sym", std::string_view(*sym)), xtag("td", td), xtag("tk", tk));
assert(stack_);
this->stack_->top().on_parsed_formal_with_token(sym, td, tk, this);
}
void
ParserStateMachine::on_parsed_formal_arglist(DArray * arglist)
{
@ -446,6 +458,33 @@ namespace xo {
this->capture_error(ssm_name, errmsg);
}
void
ParserStateMachine::illegal_parsed_formal_with_token(std::string_view ssm_name,
const DUniqueString * param_name,
TypeDescr param_type,
const Token & tk,
std::string_view expect_str)
{
// TODO:
// - want to write error message using DArena
// - need something like log_streambuf and/or tostr() that's arena-aware
auto errmsg_string = tostr("Unexpected formal",
xtag("param_name", std::string_view(*param_name)),
xtag("param_type", param_type),
xtag("tk", tk),
xtag("expecting", expect_str),
xtag("ssm", ssm_name),
xtag("via", "ParserStateMachine::illegal_parsed_formal"));
assert(expr_alloc_);
auto errmsg = DString::from_view(expr_alloc_,
std::string_view(errmsg_string));
this->capture_error(ssm_name, errmsg);
}
void
ParserStateMachine::illegal_parsed_formal_arglist(std::string_view ssm_name,
DArray * arglist,