10using namespace std::literals;
21 auto track = tracker();
22 auto decls = parse_decls();
23 bool where = ahead().isa(Tag::K_where);
24 expect(Tag::EoF,
"file");
25 auto file = ptr<File>(track,
ast().scope(),
ast().
copy(decls));
27 if (where)
error().n(curr_,
"did you accidentally end your declaration expression with a `;`?");
32 auto name = dbg.sym();
35 auto filename = fs::path(name.view());
36 driver().
log().v(
"📥 import `{}`", name);
38 if (!filename.has_extension()) filename.replace_extension(
"mim");
41 auto is_file = [](
const fs::path& p) {
42 std::error_code ignore;
43 bool reg_file = fs::is_regular_file(p, ignore);
44 return reg_file && !ignore;
48 if (is_path && !filename.is_absolute()) {
49 rel_path = curr_dir() / filename;
50 if (!is_file(rel_path)) rel_path.clear();
54 if (rel_path.empty() && !is_path && tag == Tag::K_plugin) {
55 if (
auto dir =
driver().plugin_dir(name.view())) {
56 rel_path = *dir / filename;
57 if (!is_file(rel_path)) rel_path = *dir / name.view() / filename;
58 if (!is_file(rel_path)) rel_path.clear();
62 if (rel_path.empty()) {
63 for (
const auto& path :
driver().import_paths()) {
64 rel_path = path / filename;
65 if (is_file(rel_path))
break;
66 if (is_path)
continue;
67 rel_path = path / name.view() / filename;
68 if (is_file(rel_path))
break;
72 auto [src, _] =
driver().src().add(rel_path);
75 if (fs::exists(rel_path))
76 error().e(dbg.loc(),
"cannot read file `{}`", rel_path.string());
78 error().e(dbg.loc(),
"cannot find `{}` in the search paths", name);
83 return import(*src, md, dbg.loc());
88 error().e(loc,
"cannot read file `{}`", path.string());
91 auto [src, _] =
driver().src().add(std::move(path), fe::SrcMap::slurp(is));
92 return import(*src, md, loc);
96 auto [slot, fresh] =
ast().
file(&src);
99 if (!slot) error().e(loc,
"cyclic import of `{}`", src.path().string());
103 driver().
log().v(
"📄 read `{}`", src.path().string());
105 auto state = std::tuple(curr_, ahead_, lexer_);
109 auto parsed = parse_file();
110 std::tie(curr_, ahead_, lexer_) = state;
118 for (
const auto& name : plugins) {
119 auto dbg = Dbg(Loc(),
driver().sym(name));
120 if (
auto file =
import(dbg,
false, tag))
121 imports.emplace_back(ptr<UseDecl>(Loc(),
Mods{}, tag, path(dbg), Sym(), Dbg(),
false, file));
128 auto file =
import({Loc(),
driver().sym(input)},
true, Tag::K_import, md,
false);
129 if (file) file->add_implicit_imports(
ast().copy(imports));
138 auto tag = lex().tag();
139 auto entity = fe::Cite(tag == Tag::K_import ?
"import" :
"plugin");
140 if (mods.
is_extern) error().e(curr_,
"`extern` is only meaningful on a function declaration, not on `{}`", entity);
141 if (mods.
is_anx) error().e(curr_,
"`anx` doesn't apply to `{}` - it never represents a single value", entity);
146 if (tag == Tag::K_import && ahead().isa(Tag::L_str)) {
148 file_path = name.sym();
151 auto tok = expect(Tag::M_id,
"{} name", entity);
158 if (accept(Tag::K_as)) {
159 if (accept(Tag::T_star))
162 alias = parse_id(
"alias of an import");
164 expect(Tag::T_semicolon,
"end of {}", entity);
168 auto stem = fs::path(file_path.view()).stem().string();
170 if (!is_id && !alias && !splice) {
172 .e(name.loc(),
"cannot derive a module name from `{}`", file_path)
173 .n(
"name it explicitly with `as`")
174 .n(
"or splice its members into this scope with `as *`");
177 mod.set(is_id ?
ast().sym(stem) : Sym());
180 if (
auto file =
import(name, (
bool)file_path, tag))
181 return ptr<UseDecl>(track, Mods{vis}, tag, path(mod), file_path, alias, splice, file);
185Dbg Parser::parse_id(fe::Cite ctxt) {
186 if (
auto id = accept(Tag::M_id))
return id.dbg();
187 syntax_err(
"identifier", ctxt);
188 return {missing(),
driver().sym(
"<error>")};
191Ptr<Path> Parser::parse_path(fe::Cite ctxt) {
192 auto track = tracker();
193 auto dbgs =
Dbgs{parse_id(ctxt)};
194 while (accept(Tag::T_dot))
195 dbgs.emplace_back(parse_id(
"component of a path"));
196 return ptr<Path>(track, dbgs);
199Ptr<Expr> Parser::parse_type_ascr(fe::Cite ctxt) {
200 if (accept(Tag::T_colon))
return parse_expr(ctxt);
201 if (!ctxt)
return nullptr;
202 syntax_err(
"`:`", ctxt);
203 return ptr<ErrorExpr>(missing());
212 if (ctxt) recover(ctxt);
213 auto track = tracker();
214 auto lhs = parse_primary_expr(ctxt);
215 return parse_infix_expr(track, lhs, curr_prec, ctxt);
219 auto prev = Prec::Err;
222 recover(ctxt ? ctxt : fe::Cite(
"expression"));
228 .e(ahead().loc(),
"operator `{}` is not associative", ahead())
229 .n(
"parenthesize the left- or right-hand side");
232 auto rhs = parse_expr(*prec,
"right-hand side of the `{}` operator", op);
233 lhs = ptr<InfixExpr>(track, lhs, op, rhs, sugar_callee(op));
242 .w(ahead().loc(),
"you are passing a declaration expression as argument")
243 .n(lhs->loc(),
"passed to this expression")
244 .n(
"if this was your intention, consider parenthesizing the declaration expression")
245 .n(lhs->loc().anew_end(),
"or insert a `;` here");
246 auto rhs = parse_expr(
"argument to an application", Prec::App);
247 lhs = ptr<AppExpr>(track, lhs, rhs);
252 if (ahead().isa(Tag::K_where)) {
255 auto decls = parse_decls();
256 lhs = ptr<DeclExpr>(track, lhs,
true, decls);
258 bool where = ahead().tag() == Tag::K_where;
259 expect(Tag::K_end,
"end of a where declaration block");
260 if (where)
error().n(curr_,
"did you accidentally end your declaration expression with a `;`?");
269 return sym.empty() ? nullptr : path_expr(Dbg(
op.loc(),
driver().sym(sym)));
273 auto track = tracker();
274 expect(Tag::D_curly_l,
"opening curly bracket for singleton type");
275 auto _ = this->anchor(Tag::D_curly_r);
276 auto inhabitant = parse_expr(
"singleton type");
277 recover(
"singleton type");
278 expect(Tag::D_curly_r,
"closing curly bracket for singleton type");
279 return ptr<UniqExpr>(track, inhabitant);
283 auto track = tracker();
284 expect(Tag::K_match,
"opening match for union destruction");
285 auto scrutinee = parse_expr(
"destroyed union element");
286 expect(Tag::K_with,
"match");
290 auto track = tracker();
291 auto ptrn = parse_ptrn({},
"right-hand side of a match-arm", Prec::Bot);
292 expect(Tag::T_fat_arrow,
"arm of a match-expression");
293 auto body = parse_expr(
"arm of a match-expression");
294 arms.emplace_back(ptr<MatchExpr::Arm>(track, ptrn, body));
295 }
while (accept(Tag::T_pipe));
297 return ptr<MatchExpr>(track, scrutinee, arms);
300Ptr<Expr> Parser::parse_primary_expr(fe::Cite ctxt) {
302 switch (ahead().tag()) {
303 case Tag::C_PRIMARY:
return ptr<PrimaryExpr>(lex());
304 case Tag::C_ID:
return ptr<PathExpr>(parse_path());
306 case Tag::C_SIGN:
return parse_lit_expr();
307 case Tag::C_DECL:
return parse_decl_expr();
308 case Tag::C_PI:
return parse_pi_expr();
309 case Tag::C_LM:
return parse_lam_expr();
310 case Tag::C_SEQ:
return parse_seq_expr();
311 case Tag::K_ret:
return parse_ret_expr();
312 case Tag::D_curly_l:
return parse_uniq_expr();
313 case Tag::D_brckt_l:
return parse_sigma_expr();
314 case Tag::D_paren_l:
return parse_tuple_expr();
315 case Tag::K_Type:
return parse_type_expr();
316 case Tag::K_Rule:
return parse_rule_expr();
317 case Tag::K_match:
return parse_match_expr();
319 if (!ctxt)
return nullptr;
320 syntax_err(
"primary expression", ctxt);
323 return ptr<ErrorExpr>(missing());
327 auto track = tracker();
328 bool is_pack = ahead().isa(Tag::D_angle_l);
329 auto delim_l = is_pack ? Tag::D_angle_l : Tag::D_quote_l;
337 if (ahead(0).isa(Tag::M_id) && ahead(1).isa(Tag::T_colon)) {
338 dbg = eat(Tag::M_id).dbg();
342 auto expr = parse_expr(fe::Cite(is_pack ?
"shape of pack" :
"shape of a array"));
344 }
while (accept(Tag::T_comma));
346 expect(Tag::T_semicolon, fe::Cite(is_pack ?
"pack" :
"array"));
347 auto body = parse_expr(fe::Cite(is_pack ?
"body of a pack" :
"body of an array"));
348 recover(fe::Cite(is_pack ?
"pack" :
"array"));
350 fe::Cite(is_pack ?
"closing delimiter of a pack" :
"closing delimiter of an array"));
353 for (
auto& ptrn : arities | std::views::reverse) {
354 auto loc = &ptrn == &arities.front() ? Loc(track) : ptrn->loc() + curr_;
355 body = ptr<SeqExpr>(loc, is_pack, ptrn, body);
362 auto track = tracker();
363 auto decls = parse_decls();
364 auto expr = parse_expr(
"final expression of a declaration expression");
365 return ptr<DeclExpr>(track, expr,
false, decls);
372 case Tag::L_u:
return {tok.
loc(), -
s64(tok.
lit_u())};
373 case Tag::L_f:
return {tok.
loc(), -std::bit_cast<f64>(tok.
lit_u())};
375 auto [mod, val] = tok.
lit_i();
376 return {tok.
loc(), mod, mod == 0 ? -val : (mod - val % mod) % mod};
378 default: fe::unreachable();
383 auto track = tracker();
384 auto sign =
ISA(ahead().tag(),
C_SIGN) ? lex() : Tok();
387 syntax_err(
"numeric literal",
"signed literal");
388 return ptr<ErrorExpr>(missing());
391 auto tok = sign.isa(Tag::T_sub) ?
negate(lex()) : lex();
392 auto type = accept(Tag::T_colon) ? parse_expr(
"literal", Prec::Lit) : nullptr;
393 return ptr<LitExpr>(track, tok, type);
397 auto track = tracker();
398 auto ptrn = parse_tuple_ptrn({.brckt =
true});
399 switch (ahead().tag()) {
402 auto alias = ptr<AliasPtrn>(track, ptrn, parse_id(
"alias pattern"));
403 return parse_pi_expr(alias);
405 case Tag::C_CURRIED_B:
406 case Tag::T_arrow_r:
return parse_pi_expr(ptrn);
407 default:
return ptr<SigmaExpr>(ptrn);
412 auto track = tracker();
414 parse_list(
"tuple", Tag::D_paren_l, [&]() { elems.emplace_back(parse_expr(
"tuple element")); });
415 return ptr<TupleExpr>(track, elems);
419 auto track = tracker();
421 auto level = parse_expr(
"type level", Prec::App);
422 return ptr<TypeExpr>(track, level);
426 auto track = tracker();
428 return ptr<RuleExpr>(track, parse_expr(
"domain of rule", Prec::App));
432 auto track = tracker();
433 auto tag = ahead().tag();
434 fe::Cite entity =
"dependent function type";
436 if (accept(Tag::K_Cn))
437 entity =
"continuation type";
438 else if (accept(Tag::K_Fn))
439 entity =
"returning continuation type";
441 auto domt = tracker();
442 auto prec =
ISA(tag,
C_CN) ? Prec::Bot : Prec::Pi;
443 auto ptrn = parse_ptrn({.brckt =
true, .implicit =
true}, prec,
"domain of a {}", entity);
444 auto dom = ptr<PiExpr::Dom>(domt, ptrn);
446 auto codom =
ISA(tag,
C_CN) ? nullptr
447 : (expect(Tag::T_arrow_r, entity), parse_expr(Prec::Arrow,
"codomain of a {}", entity));
450 dom->add_ret(
ast(), codom ? codom : ptr<HoleExpr>(missing()));
453 return ptr<PiExpr>(track, tag, dom, codom);
457 auto track = tracker(ptrn->loc());
458 fe::Cite entity =
"dependent function type";
459 auto dom = ptr<PiExpr::Dom>(ptrn->loc(), ptrn);
460 expect(Tag::T_arrow_r, entity);
461 auto codom = parse_expr(Prec::Arrow,
"codomain of a {}", entity);
462 return ptr<PiExpr>(track, Tag::Nil, dom, codom);
465Ptr<Expr> Parser::parse_lam_expr() {
return ptr<LamExpr>(parse_lam_decl(tracker(), {})); }
468 auto track = tracker();
470 auto ptrn = parse_ptrn({},
"binding pattern of a ret expression");
471 expect(Tag::T_assign,
"ret expression");
472 auto callee = parse_expr(
"continuation expression of a ret expression");
473 expect(Tag::T_dollar,
"separator of a ret expression");
474 auto arg = parse_expr(
"argument of ret expression");
475 expect(Tag::T_semicolon,
"ret expression");
476 auto body = parse_expr(
"body of a ret expression");
477 return ptr<RetExpr>(track, ptrn, callee, arg, body);
484Ptr<Ptrn> Parser::parse_ptrn(PtrnStyle style, fe::Cite ctxt,
Prec prec) {
485 auto track = tracker();
486 auto ptrn = parse_ptrn_(style, ctxt, prec);
487 if (accept(Tag::K_as))
return ptr<AliasPtrn>(track, ptrn, parse_id(
"alias pattern"));
491Ptr<Ptrn> Parser::parse_ptrn_(PtrnStyle style, fe::Cite ctxt,
Prec prec) {
492 auto track = tracker();
497 if (!style.brckt && ahead().isa(Tag::D_paren_l))
return parse_tuple_ptrn(style);
498 if (style.implicit && ahead().isa(Tag::D_brace_l))
return parse_tuple_ptrn(style);
499 if (style.brckt && ahead().isa(Tag::D_brckt_l))
return parse_tuple_ptrn(style);
502 if (ahead(0).isa(Tag::M_id) && ahead(1).isa(Tag::T_colon)) {
503 auto dbg = eat(Tag::M_id).dbg();
505 auto type = parse_expr(ctxt, prec);
506 return ptr<IdPtrn>(track, dbg, type);
511 if (
auto id = accept(Tag::M_id))
return ptr<IdPtrn>(track,
id.
dbg(),
nullptr);
513 syntax_err(
"pattern", ctxt);
514 return ptr<ErrorPtrn>(missing());
518 auto type = parse_expr(ctxt, prec);
519 return anon_ptrn(Loc(track), type);
523 auto track = tracker();
524 auto delim_l = ahead().tag();
527 parse_list(
"tuple pattern", delim_l, [&]() {
528 auto track = tracker();
530 if (ahead(0).isa(Tag::M_id) && ahead(1).isa(Tag::M_id)) {
532 while (
auto tok = accept(Tag::M_id))
533 dbgs.emplace_back(tok.dbg());
535 if (accept(Tag::T_colon)) {
536 auto dbg = dbgs.back();
537 auto type = parse_expr(
"type of an identifier group within a tuple pattern");
538 auto id = ptr<IdPtrn>(
dbg.loc() +
type->loc().end, dbg, type);
540 for (
auto dbg : dbgs | std::views::take(dbgs.size() - 1))
541 ptrns.emplace_back(ptr<GrpPtrn>(dbg,
id.
get()));
542 ptrns.emplace_back(
id);
547 error().e(dbgs[1].loc(),
"expected `,` or `:` between the binders of a tuple pattern");
548 for (
auto dbg : dbgs)
549 ptrns.emplace_back(ptr<IdPtrn>(
dbg.loc(), dbg,
nullptr));
555 for (
auto dbg : dbgs | std::views::drop(1)) {
556 auto loc = lhs->loc() +
dbg.loc();
557 lhs = ptr<AppExpr>(loc, lhs, path_expr(dbg));
559 auto app = parse_infix_expr(track, lhs, Prec::Bot,
"element of a tuple pattern");
560 auto loc = app->loc();
561 ptrns.emplace_back(anon_ptrn(loc, app));
565 auto ptrn = parse_ptrn({.brckt = style.brckt},
"element of a tuple pattern");
569 if (ahead().isa(Tag::T_arrow_r)) {
570 auto loc = ptrn->loc();
571 ptrn = anon_ptrn(loc, parse_pi_expr(ptrn));
573 auto addr = expr.get();
574 expr = parse_infix_expr(track, expr, Prec::Bot,
"element of a tuple pattern");
575 if (expr.get() != addr) ptrn = anon_ptrn(expr->loc(), expr);
579 ptrns.emplace_back(ptrn);
582 return ptr<TuplePtrn>(track, delim_l, ptrns);
589Mods Parser::parse_modifiers() {
593 switch (ahead().tag()) {
597 if (mods.vis)
error().e(curr_,
"visibility already specified");
603 if (mods.is_extern)
error().e(curr_,
"`extern` already specified");
604 mods.is_extern =
true;
608 if (mods.is_anx)
error().e(curr_,
"`anx` already specified");
612 default:
return mods;
618void Parser::check_no_extern(
const Mods& mods, fe::Cite entity) {
619 if (mods.is_extern)
error().e(curr_,
"`extern` is only meaningful on a function declaration, not a {}", entity);
625 auto track = tracker();
626 auto mods = parse_modifiers();
627 switch (ahead().tag()) {
628 case Tag::T_semicolon: lex();
break;
629 case Tag::K_axm: parse_axm_decl(track, mods, decls);
break;
630 case Tag::K_let: decls.emplace_back(parse_let_decl(track, mods));
break;
631 case Tag::K_mod: decls.emplace_back(parse_mod_decl(track, mods));
break;
632 case Tag::K_use: decls.emplace_back(parse_use_decl(track, mods));
break;
633 case Tag::K_rec: decls.emplace_back(parse_rec_decl(track,
true, mods));
break;
634 case Tag::C_LAM: decls.emplace_back(parse_lam_decl(track, mods));
break;
635 case Tag::C_RULE: decls.emplace_back(parse_rule_decl());
break;
637 if (
auto i = parse_import_or_plugin(track, mods)) decls.emplace_back(i);
641 decls.emplace_back(parse_alias_decl(track, mods));
646 if (mods.vis || mods.is_extern || mods.is_anx)
647 error().e(curr_,
"expected a declaration after a modifier");
653std::tuple<Ptr<Expr>, Dbg,
Tok,
Tok> Parser::parse_axm_tail() {
654 auto type = parse_type_ascr(
"type ascription of an axm");
657 if (ahead(0).isa(Tag::T_comma) && ahead(1).isa(Tag::M_id)) {
659 normalizer = lex().dbg();
661 if (accept(Tag::T_comma)) {
662 if (
auto c = expect(Tag::L_u,
"curry counter for axm")) curry =
c;
663 if (accept(Tag::T_comma)) {
664 if (
auto t = expect(Tag::L_u,
"trip count for axm")) trip =
t;
667 return {
type, normalizer, curry, trip};
673 if (mods.is_extern)
error().e(curr_,
"`axm` is implicitly `anx`; cannot combine with `extern`");
674 auto vis = mods.vis.value_or(
Vis::Pub);
676 if (ahead().isa(Tag::D_paren_l)) {
677 for (
auto decl : parse_axm_group(vis))
678 decls.emplace_back(decl);
682 auto dbg = parse_id(
"name of an axm");
683 if (accept(Tag::T_dot)) {
684 auto group = parse_axm_group(vis);
685 decls.emplace_back(ptr<ModDecl>(track,
Vis::Pub, dbg,
ast().scope(),
ast().
copy(group)));
689 auto [
type, normalizer, curry, trip] = parse_axm_tail();
690 decls.emplace_back(ptr<AxmDecl>(track, vis, dbg, type, normalizer, curry, trip));
694 fe::Vector<Dbgs> members;
695 parse_list(
"tag list of an axm", Tag::D_paren_l, [&]() {
697 names.emplace_back(parse_id(
"tag of an axm"));
698 while (accept(Tag::T_assign))
699 names.emplace_back(parse_id(
"alias of an axm tag"));
700 members.emplace_back(std::move(names));
703 auto [
type, normalizer, curry, trip] = parse_axm_tail();
706 const AxmDecl* owner =
nullptr;
707 for (
auto& names : members) {
708 auto primary = names.front();
710 auto axm = ptr<AxmDecl>(primary.loc(), vis, primary, type, normalizer, curry, trip);
712 decls.emplace_back(axm);
714 decls.emplace_back(ptr<AxmDecl::Sibling>(primary.loc(), vis, primary, owner));
716 for (
auto alias : names | std::views::drop(1))
717 decls.emplace_back(ptr<AliasDecl>(alias.loc(),
Vis::Pub, alias, path(primary)));
723 if (mods.is_extern)
error().e(curr_,
"`extern` and `anx` cannot be combined on an alias declaration");
724 auto vis = mods.vis.value_or(
Vis::Pub);
725 auto dbg = parse_id(
"name of an alias declaration");
726 expect(Tag::T_assign,
"alias declaration");
727 auto path = parse_path(
"target of an alias declaration");
728 return ptr<AliasDecl>(track, vis, dbg, path);
732 check_no_extern(mods,
"let declaration");
734 auto ptrn = parse_ptrn({},
"binding pattern of a let declaration", Prec::Bot);
735 expect(Tag::T_assign,
"let");
737 auto value = parse_expr(
"value of a let declaration");
738 return ptr<LetDecl>(track, mods, ptrn, value);
743 if (mods.is_extern)
error().e(curr_,
"`extern` is only meaningful on a function declaration, not a module");
744 if (mods.is_anx)
error().e(curr_,
"`anx` doesn't apply to a module - it groups declarations, not a single value");
747 auto dbg = parse_id(
"name of a module");
748 expect(Tag::D_brace_l,
"opening brace of a module");
749 auto _ = this->anchor(Tag::D_brace_r);
750 auto decls = parse_decls();
752 expect(Tag::D_brace_r,
"closing brace of a module");
753 return ptr<ModDecl>(track, vis, dbg,
ast().scope(),
ast().
copy(decls));
757 check_no_extern(mods,
"use declaration");
758 if (mods.is_anx)
error().e(curr_,
"`anx` doesn't apply to a use declaration - it never represents a single value");
760 auto path = parse_path(
"module of a use declaration");
763 if (accept(Tag::K_as) && !accept(Tag::T_star)) alias = parse_id(
"alias of a use declaration");
764 expect(Tag::T_semicolon,
"end of a use declaration");
765 return ptr<UseDecl>(track, Mods{mods.vis.value_or(
Vis::Priv)}, path, alias);
769 check_no_extern(mods,
"recursive declaration");
770 eat(first ? Tag::K_rec : Tag::K_and);
771 auto dbg = parse_id(
"recursive declaration");
772 expect(Tag::T_assign,
"recursive declaration");
773 auto body = parse_expr(
"body of a recursive declaration");
774 auto next = ahead().isa(Tag::K_and) ? parse_and_decl() : nullptr;
775 return ptr<RecDecl>(track, mods, dbg, body, next);
779 auto track = tracker();
780 auto is_norm = lex().tag() == Tag::K_norm;
781 auto dbg = parse_id(
"rewrite rule");
782 auto ptrn = parse_ptrn({},
"meta variables in rewrite rule");
783 expect(Tag::T_colon,
"rewrite rule declaration");
784 auto lhs = parse_expr(
"rewrite pattern");
785 auto guard = ahead().isa(Tag::K_when) ? (eat(Tag::K_when), parse_expr(
"rewrite guard"))
786 : ptr<PrimaryExpr>(missing(),
Tag::K_tt);
787 expect(Tag::T_fat_arrow,
"rewrite rule declaration");
788 auto rhs = parse_expr(
"rewrite result");
789 return ptr<RuleDecl>(track, dbg, ptrn, lhs, rhs, guard, is_norm);
794 if (mods.is_extern && mods.is_anx)
795 error().e(curr_,
"`extern` and `anx` cannot be combined on a function declaration");
796 auto tag = lex().tag();
797 auto prec =
ISA(tag,
C_CN) ? Prec::Bot : Prec::Pi;
803 case Tag::T_lm: decl =
false; entity =
"function expression";
break;
804 case Tag::K_cn: decl =
false; entity =
"continuation expression";
break;
805 case Tag::K_fn: decl =
false; entity =
"returning continuation expression";
break;
806 case Tag::K_lam: decl = true ; entity =
"function declaration";
break;
807 case Tag::K_con: decl = true ; entity =
"continuation declaration";
break;
808 case Tag::K_fun: decl = true ; entity =
"returning continuation declaration";
break;
809 default: fe::unreachable();
813 auto dbg = decl ? parse_id(entity) : Dbg();
816 auto track = tracker();
818 auto style = ahead().isa(Tag::D_brckt_l) ? PtrnStyle{.brckt =
true} : PtrnStyle{.implicit =
true};
819 auto ptrn = parse_ptrn(style, prec,
"domain pattern of a {}", entity);
820 auto filter = accept(Tag::T_at) ? parse_expr(
"filter") : nullptr;
821 doms.emplace_back(ptr<LamDecl::Dom>(track, ptrn, filter));
827 auto codom = accept(Tag::T_colon) ? parse_expr(
Prec(
int(Prec::Where) + 1),
"codomain of a {}", entity) : nullptr;
829 doms.back()->add_ret(
ast(), codom ? codom : ptr<HoleExpr>(missing()));
834 if (decl && mods.is_extern && ahead().isa(Tag::T_semicolon)) {
837 expect(Tag::T_assign,
"body of a {}", entity);
838 body = parse_expr(
"body of a {}", entity);
841 for (
auto dom : doms)
842 if (
auto tuple = dom->ptrn()->isa<TuplePtrn>(); tuple && tuple->is_brckt())
844 .e(tuple->loc(),
"a {} with a body must spell its domain as a `(...)` pattern", entity)
845 .n(
"`[...]` describes a type, so its names bind nothing here")
846 .n(
"write an unnamed component as `_: T`");
848 auto next = ahead().isa(Tag::K_and) ? parse_and_decl() : nullptr;
850 return ptr<LamDecl>(track, mods, tag, dbg, codom, body, next, doms);
856 auto track = tracker();
857 return parse_lam_decl(track, {});
859 return parse_rec_decl(tracker(),
false, {});
void add(const fe::Src *src, Sym, ast::Tok::Tag, bool path)
Remembers the directive that pulled in src; a repeated import of the same file adds nothing.
const Imports & imports() const
void load(std::string_view name)
std::pair< Ptr< File > &, bool > file(const fe::Src *src)
The AST of one source file: an anonymous ModDecl that a UseDecl binds under a name of its own.
static Ptr< IdPtrn > make_id(AST &ast, Dbg dbg, Ptr< Expr > type)
static bool is_id(std::string_view str)
Does str match the id production - the same rule Lexer::lex_id applies to the input?
Lexer(Driver &driver, const fe::Src &src, std::ostream *md=nullptr)
Creates a lexer to read *.mim files (see Lexical Structure).
const File * import_main(std::string_view input, fe::View< std::string > plugins, std::ostream *md=nullptr)
const File * import(std::string_view sv, Tok::Tag tag=Tok::Tag::K_import)
Ptrs< UseDecl > import_plugins(fe::View< std::string > plugins, Tok::Tag)
Imports the plugins the Driver was told about via -p as anonymous, unaliased UseDecls.
Driver & driver()
fe::Parser's default diagnostics go to its Driver::error.
static Ptr< Expr > to_expr(AST &, Ptr< Ptrn >)
static constexpr std::string_view infix_sym(Tag tag)
Name the infix operator tag desugars to - including the leading ` ; empty for MIM_INFIX_CORE.
std::pair< uint64_t, uint64_t > lit_i() const
static constexpr std::optional< Prec > infix_prec(Tag tag)
Precedence of the infix operator tag; std::nullopt if tag isn't one.
static constexpr Tok::Tag delim_l2r(Tag tag)
Families of Tok::Tag as reusable case labels; include this in *.cpp files only.
#define C_SIGN
Leading sign of a numeric literal.
#define C_LIT_NUM
Numeric literals that a leading sign may be applied to.
#define ISA(tag, family)
Turns such a family into a predicate - a case label is of no use outside of a switch.
#define C_FN
Binders that receive an implicit ret continuation.
#define C_CN
Binders whose domain binds as tight as a Cn, i.e. no codomain follows.
Vis
Visibility tier of a ValDecl.
constexpr bool should_reduce(Prec curr, Prec op)
Should a Pratt parser reduce when the current binding power is curr and the infix operator has preced...
fe::Arena::Ref< const T > Ptr
Nodes live in the AST's Arena and are never destroyed, so this merely points at one.
static Tok negate(Tok tok)
Applies a leading - to a numeric literal Tok.
fe::Vector< Ptr< T > > Ptrs
constexpr Assoc prec_assoc(Prec p)
Associativity of precedence level p.
Prec
Expression precedences used by the parser and the dumper; ordered low to high.
Raw, unvalidated combination of priv/pub/extern/anx modifiers written before a declaration.