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();
34 if (tag == Tag::K_plugin && !
driver().is_loaded(plugin) && !
driver().flags().bootstrap)
37 driver().
log().v(
"📥 import `{}`", name);
39 auto file = fs::path(name.view());
40 if (!file.has_extension()) file.replace_extension(
"mim");
42 auto path = fs::path();
43 auto probe = [&path](fs::path p) {
44 if (std::error_code ec; !fs::is_regular_file(p, ec))
return false;
50 if (
auto dir = plugin.empty() ?
nullptr :
driver().plugin_dir(plugin)) {
51 auto mim = fs::path(plugin).replace_extension(
"mim");
52 if (!probe(*dir /
mim)) probe(*dir / plugin /
mim);
56 if (path.empty() && is_path && !file.is_absolute()) probe(curr_dir() / file);
59 for (
const auto& dir :
driver().import_paths())
61 if (probe(dir / file) || (!is_path && probe(dir / name.view() / file)))
break;
65 if (std::error_code ec; fs::is_directory(fs::path(name.view()), ec))
66 error().e(dbg.loc(),
"`{}` is a directory, not a Mim file", name);
68 error().e(dbg.loc(),
"cannot find `{}` in the search paths", name);
72 auto [src, _] =
driver().src().add(path);
74 error().e(dbg.loc(),
"cannot read file `{}`", path.string());
79 return import(*src, md, dbg.loc());
84 error().e(loc,
"cannot read file `{}`", path.string());
87 auto [src, _] =
driver().src().add(std::move(path), fe::SrcMap::slurp(is));
88 return import(*src, md, loc);
92 auto [slot, fresh] =
ast().
file(&src);
95 if (!slot) error().e(loc,
"cyclic import of `{}`", src.path().string());
99 driver().
log().v(
"📄 read `{}`", src.path().string());
101 auto state = std::tuple(curr_, ahead_, lexer_);
105 auto parsed = parse_file();
106 std::tie(curr_, ahead_, lexer_) = state;
114 for (
const auto& name : plugins) {
115 auto dbg = Dbg(Loc(),
driver().sym(name));
116 bool is_path = fs::path(name).has_parent_path();
117 if (
auto file =
import(dbg, is_path, tag))
118 imports.emplace_back(ptr<UseDecl>(Loc(),
Mods{}, tag, path(dbg), Sym(), Dbg(),
false, file));
125 auto file =
import({Loc(),
driver().sym(input)},
true, Tag::K_import, md,
false);
126 if (file) file->add_implicit_imports(
ast().copy(imports));
135 auto tag = lex().tag();
136 auto entity = fe::Cite(tag == Tag::K_import ?
"import" :
"plugin");
137 if (mods.
is_extern) error().e(curr_,
"`extern` is only meaningful on a function declaration, not on `{}`", entity);
138 if (mods.
is_anx) error().e(curr_,
"`anx` doesn't apply to `{}` - it never represents a single value", entity);
143 if (ahead().isa(Tag::L_str)) {
145 file_path = name.sym();
147 auto tok = expect(Tag::M_id,
"{} name", entity);
154 if (accept(Tag::K_as)) {
155 if (accept(Tag::T_star))
158 alias = parse_id(
"alias of an import");
160 expect(Tag::T_semicolon,
"end of {}", entity);
164 auto stem = fs::path(file_path.view()).stem().string();
166 if (!is_id && !alias && !splice) {
168 .e(name.loc(),
"cannot derive a module name from `{}`", file_path)
169 .n(
"name it explicitly with `as`")
170 .n(
"or splice its members into this scope with `as *`");
173 mod.set(is_id ?
ast().sym(stem) : Sym());
176 if (
auto file =
import(name, (
bool)file_path, tag))
177 return ptr<UseDecl>(track, Mods{vis}, tag, path(mod), file_path, alias, splice, file);
181Dbg Parser::parse_id(fe::Cite ctxt) {
182 if (
auto id = accept(Tag::M_id))
return id.dbg();
183 syntax_err(
"identifier", ctxt);
184 return {missing(),
driver().sym(
"<error>")};
187Ptr<Path> Parser::parse_path(fe::Cite ctxt) {
188 auto track = tracker();
189 auto dbgs =
Dbgs{parse_id(ctxt)};
190 while (accept(Tag::T_dot))
191 dbgs.emplace_back(parse_id(
"component of a path"));
192 return ptr<Path>(track, dbgs);
195Ptr<Expr> Parser::parse_type_ascr(fe::Cite ctxt) {
196 if (accept(Tag::T_colon))
return parse_expr(ctxt);
197 syntax_err(
"`:`", ctxt);
198 return ptr<ErrorExpr>(missing());
207 if (ctxt) recover(ctxt);
208 auto track = tracker();
209 auto lhs = parse_primary_expr(ctxt);
210 return parse_infix_expr(track, lhs, curr_prec, ctxt);
214 auto prev = Prec::Err;
217 recover(ctxt ? ctxt : fe::Cite(
"expression"));
223 .e(ahead().loc(),
"operator `{}` is not associative", ahead())
224 .n(
"parenthesize the left- or right-hand side");
227 auto rhs = parse_expr(*prec,
"right-hand side of the `{}` operator", op);
228 lhs = ptr<InfixExpr>(track, lhs, op, rhs, sugar_callee(op));
237 .w(ahead().loc(),
"you are passing a declaration expression as argument")
238 .n(lhs->loc(),
"passed to this expression")
239 .n(
"if this was your intention, consider parenthesizing the declaration expression")
240 .n(lhs->loc().anew_end(),
"or insert a `;` here");
241 auto rhs = parse_expr(
"argument to an application", Prec::App);
242 lhs = ptr<AppExpr>(track, lhs, rhs);
247 if (ahead().isa(Tag::K_where)) {
250 auto decls = parse_decls();
251 lhs = ptr<DeclExpr>(track, lhs,
true, decls);
253 bool where = ahead().tag() == Tag::K_where;
254 expect(Tag::K_end,
"end of a where declaration block");
255 if (where)
error().n(curr_,
"did you accidentally end your declaration expression with a `;`?");
263 auto track = tracker();
265 auto rhs = parse_expr(Prec::Prefix,
"operand of the prefix `{}` operator", op);
266 return ptr<PrefixExpr>(track, op, rhs);
271 return sym.empty() ? nullptr : path_expr(Dbg(
op.loc(),
driver().sym(sym)));
275 auto track = tracker();
276 expect(Tag::K_match,
"opening match for union destruction");
277 auto scrutinee = parse_expr(
"destroyed union element");
278 expect(Tag::K_with,
"match");
282 auto track = tracker();
283 auto index = std::optional<nat_t>();
286 auto payload = [&] {
return parse_ptrn({},
"payload of a constructor in a match-arm", Prec::Bot); };
287 if (
auto lit = accept(Tag::L_u)) {
289 if (!ahead().isa(Tag::T_fat_arrow)) ptrn = payload();
291 ptrn = parse_ptrn({},
"right-hand side of a match-arm", Prec::Bot);
292 if (
auto id = ptrn->isa<IdPtrn>();
id && !
id->type() && !ahead().isa(Tag::T_fat_arrow)) {
297 expect(Tag::T_fat_arrow,
"arm of a match-expression");
298 auto body = parse_expr(
"arm of a match-expression");
299 arms.emplace_back(ptr<MatchExpr::Arm>(track, index, ctor, ptrn, body));
300 }
while (accept(Tag::T_pipe));
302 return ptr<MatchExpr>(track, scrutinee, arms);
306 auto track = tracker();
310 if (ahead().isa(Tag::M_id)) {
312 auto track = tracker();
313 auto dbg = parse_id(
"constructor of a variant");
315 if (
auto colon = accept(Tag::T_colon)) {
316 if (ahead().isa(Tag::T_pipe))
318 .w(colon.loc(),
"payload of constructor `{}` swallows the remaining constructors",
dbg.sym())
319 .n(
"drop the `:` if `{}` carries no payload",
dbg.sym())
320 .n(
"parenthesize the payload if a nested variant is intended");
321 type = parse_expr(
"payload of a variant constructor");
323 ctors.emplace_back(ptr<VariantExpr::Ctor>(track, dbg, type));
324 }
while (accept(Tag::T_pipe));
326 return ptr<VariantExpr>(track, ctors);
329Ptr<Expr> Parser::parse_primary_expr(fe::Cite ctxt) {
332 switch (ahead().tag()) {
333 case Tag::C_PRIMARY:
return ptr<PrimaryExpr>(lex());
334 case Tag::C_ID:
return ptr<PathExpr>(parse_path());
336 case Tag::C_SIGN:
return parse_lit_expr();
337 case Tag::C_DECL:
return parse_decl_expr();
338 case Tag::C_PI:
return parse_pi_expr();
339 case Tag::C_LM:
return parse_lam_expr();
340 case Tag::C_SEQ:
return parse_seq_or_single_expr();
341 case Tag::K_ret:
return parse_ret_expr();
342 case Tag::D_brckt_l:
return parse_sigma_expr();
343 case Tag::D_paren_l:
return parse_tuple_expr();
344 case Tag::K_Type:
return parse_type_expr();
345 case Tag::K_Rule:
return parse_rule_expr();
346 case Tag::K_match:
return parse_match_expr();
347 case Tag::T_pipe:
return parse_variant_expr();
349 if (!ctxt)
return nullptr;
350 syntax_err(
"primary expression", ctxt);
353 return ptr<ErrorExpr>(missing());
356Ptr<Expr> Parser::parse_seq_or_single_expr() {
357 auto track = tracker();
358 bool is_pack = ahead().isa(Tag::D_angle_l);
359 auto delim_l = is_pack ? Tag::D_angle_l : Tag::D_quote_l;
361 auto arities = fe::Vector<std::pair<Ptr<IdDecl>,
Ptr<Expr>>>();
362 auto _ = anchor(eat(delim_l), delim_r);
363 auto ctxt = fe::Cite(is_pack ?
"shape of a pack or a singleton term introduction"
364 :
"shape of an array or a singleton type formation");
368 if (ahead(0).isa(Tag::M_id) && ahead(1).isa(Tag::T_colon)) {
369 dbg = eat(Tag::M_id).dbg();
373 auto expr = parse_expr(ctxt);
375 if (arities.empty() && !dbg && ahead().isa(delim_r)) {
377 return ptr<SingleExpr>(track, is_pack, expr);
379 arities.emplace_back(ptr<IdDecl>(dbg), expr);
380 ctxt = fe::Cite(is_pack ?
"shape of a pack" :
"shape of an array");
381 }
while (accept(Tag::T_comma) && !ahead().isa(Tag::T_semicolon));
383 expect(Tag::T_semicolon, fe::Cite(is_pack ?
"pack" :
"array"));
384 auto body = parse_expr(fe::Cite(is_pack ?
"body of a pack" :
"body of an array"));
385 recover(fe::Cite(is_pack ?
"pack" :
"array"));
386 expect(delim_r, fe::Cite(is_pack ?
"closing delimiter of a pack" :
"closing delimiter of an array"));
389 for (
auto& [index, shape] : arities | std::views::reverse) {
390 auto loc = &index == &arities.front().first ? Loc(track) : (index->
dbg() ? index->loc() :
shape->loc()) + curr_;
391 body = ptr<SeqExpr>(loc, is_pack, index, shape, body);
398 auto track = tracker();
399 auto decls = parse_decls();
400 auto expr = parse_expr(
"final expression of a declaration expression");
401 return ptr<DeclExpr>(track, expr,
false, decls);
407 case Tag::L_u:
return {tok.
loc(), std::bit_cast<s64>(-tok.
lit_u())};
408 case Tag::L_f:
return {tok.
loc(), -std::bit_cast<f64>(tok.
lit_u())};
410 auto [mod, val] = tok.
lit_i();
411 return {tok.
loc(), mod, mod == 0 ? -val : (mod - val % mod) % mod};
413 default: std::unreachable();
418 auto track = tracker();
419 auto sign =
ISA(ahead().tag(),
C_SIGN) ? lex() : Tok();
422 syntax_err(
"numeric literal",
"signed literal");
423 return ptr<ErrorExpr>(missing());
426 auto tok = sign.isa(Tag::T_sub) ?
negate(lex()) : lex();
427 auto type = accept(Tag::T_colon) ? parse_expr(
"literal", Prec::Lit) : nullptr;
428 return ptr<LitExpr>(track, tok, type);
432 auto track = tracker();
433 auto ptrn = parse_tuple_ptrn({.brckt =
true});
434 switch (ahead().tag()) {
437 auto alias = ptr<AliasPtrn>(track, ptrn, parse_id(
"alias pattern"));
438 return parse_pi_expr(alias);
440 case Tag::T_arrow_r:
return parse_pi_expr(ptrn);
441 default:
return ptr<SigmaExpr>(ptrn);
446 auto track = tracker();
448 parse_list(
"tuple", Tag::D_paren_l, [&]() { elems.emplace_back(parse_expr(
"tuple element")); });
449 return ptr<TupleExpr>(track, elems);
453 auto track = tracker();
455 auto level = parse_expr(
"type level", Prec::App);
456 return ptr<TypeExpr>(track, level);
460 auto track = tracker();
462 return ptr<RuleExpr>(track, parse_expr(
"domain of rule", Prec::App));
466 auto track = tracker();
467 auto tag = ahead().tag();
468 fe::Cite entity =
"dependent function type";
470 if (accept(Tag::K_Cn))
471 entity =
"continuation type";
472 else if (accept(Tag::K_Fn))
473 entity =
"returning continuation type";
475 auto domt = tracker();
476 auto prec =
ISA(tag,
C_CN) ? Prec::Bot : Prec::Pi;
477 auto ptrn = parse_ptrn({.brckt =
true, .implicit =
true}, prec,
"domain of a {}", entity);
478 auto dloc = Loc(domt);
480 auto codom =
ISA(tag,
C_CN) ? nullptr
481 : (expect(Tag::T_arrow_r, entity), parse_expr(Prec::Arrow,
"codomain of a {}", entity));
485 return ptr<PiExpr>(track, tag, ptr<PiExpr::Dom>(dloc, ptrn, fn ? codom :
nullptr), fn ?
nullptr : codom);
489 auto track = tracker(ptrn->loc());
490 fe::Cite entity =
"dependent function type";
491 auto dom = ptr<PiExpr::Dom>(ptrn->loc(), ptrn,
nullptr);
492 expect(Tag::T_arrow_r, entity);
493 auto codom = parse_expr(Prec::Arrow,
"codomain of a {}", entity);
494 return ptr<PiExpr>(track, Tag::Nil, dom, codom);
497Ptr<Expr> Parser::parse_lam_expr() {
return ptr<LamExpr>(parse_lam_decl(tracker(), {})); }
500 auto track = tracker();
502 auto ptrn = parse_ptrn({},
"binding pattern of a ret expression");
503 expect(Tag::T_assign,
"ret expression");
504 auto callee = parse_expr(
"continuation expression of a ret expression");
505 expect(Tag::T_dollar,
"separator of a ret expression");
506 auto arg = parse_expr(
"argument of ret expression");
507 expect(Tag::T_semicolon,
"ret expression");
508 auto body = parse_expr(
"body of a ret expression");
509 return ptr<RetExpr>(track, ptrn, callee, arg, body);
516Ptr<Ptrn> Parser::parse_ptrn(PtrnStyle style, fe::Cite ctxt,
Prec prec) {
517 auto track = tracker();
518 auto ptrn = parse_ptrn_(style, ctxt, prec);
519 if (accept(Tag::K_as))
return ptr<AliasPtrn>(track, ptrn, parse_id(
"alias pattern"));
523Ptr<Ptrn> Parser::parse_ptrn_(PtrnStyle style, fe::Cite ctxt,
Prec prec) {
524 auto track = tracker();
529 if (!style.brckt && ahead().isa(Tag::D_paren_l))
return parse_tuple_ptrn(style);
530 if (style.implicit && ahead().isa(Tag::D_brace_l))
return parse_tuple_ptrn(style);
531 if (style.brckt && ahead().isa(Tag::D_brckt_l))
return parse_tuple_ptrn(style);
534 if (ahead(0).isa(Tag::M_id) && ahead(1).isa(Tag::T_colon)) {
535 auto dbg = eat(Tag::M_id).dbg();
537 auto type = parse_expr(ctxt, prec);
538 return ptr<IdPtrn>(track, dbg, type);
543 if (
auto id = accept(Tag::M_id))
return ptr<IdPtrn>(track,
id.
dbg(),
nullptr);
545 syntax_err(
"pattern", ctxt);
546 return ptr<ErrorPtrn>(missing());
550 auto type = parse_expr(ctxt, prec);
551 return anon_ptrn(Loc(track), type);
555 auto track = tracker();
556 auto delim_l = ahead().tag();
559 parse_list(
"tuple pattern", delim_l, [&]() {
560 auto track = tracker();
562 if (ahead(0).isa(Tag::M_id) && ahead(1).isa(Tag::M_id)) {
564 while (
auto tok = accept(Tag::M_id))
565 dbgs.emplace_back(tok.dbg());
567 if (accept(Tag::T_colon)) {
568 auto type = parse_expr(
"type of an identifier group within a tuple pattern");
569 auto id = ptr<IdPtrn>(dbgs.front().loc() +
type->loc().end, dbgs.front(), type);
571 ptrns.emplace_back(
id);
572 for (
auto dbg : dbgs | std::views::drop(1))
573 ptrns.emplace_back(ptr<GrpPtrn>(dbg,
id.
get()));
578 error().e(dbgs[1].loc(),
"expected `,` or `:` between the binders of a tuple pattern");
579 for (
auto dbg : dbgs)
580 ptrns.emplace_back(ptr<IdPtrn>(
dbg.loc(), dbg,
nullptr));
586 for (
auto dbg : dbgs | std::views::drop(1)) {
587 auto loc = lhs->loc() +
dbg.loc();
588 lhs = ptr<AppExpr>(loc, lhs, path_expr(dbg));
590 auto app = parse_infix_expr(track, lhs, Prec::Bot,
"element of a tuple pattern");
591 auto loc = app->loc();
592 ptrns.emplace_back(anon_ptrn(loc, app));
596 auto ptrn = parse_ptrn({.brckt = style.brckt},
"element of a tuple pattern");
600 if (ahead().isa(Tag::T_arrow_r)) {
601 auto loc = ptrn->loc();
602 ptrn = anon_ptrn(loc, parse_pi_expr(ptrn));
604 auto addr = expr.get();
605 expr = parse_infix_expr(track, expr, Prec::Bot,
"element of a tuple pattern");
606 if (expr.get() != addr) ptrn = anon_ptrn(expr->loc(), expr);
610 ptrns.emplace_back(ptrn);
613 return ptr<TuplePtrn>(track, delim_l, ptrns);
620Mods Parser::parse_modifiers() {
624 switch (ahead().tag()) {
628 if (mods.vis)
error().e(curr_,
"visibility already specified");
634 if (mods.is_extern)
error().e(curr_,
"`extern` already specified");
635 mods.is_extern =
true;
639 if (mods.is_anx)
error().e(curr_,
"`anx` already specified");
643 default:
return mods;
649void Parser::check_no_extern(
const Mods& mods, fe::Cite entity) {
650 if (mods.is_extern)
error().e(curr_,
"`extern` is only meaningful on a function declaration, not a {}", entity);
656 auto track = tracker();
657 auto own = parse_modifiers();
658 auto mods = own.inherit(group);
659 switch (ahead().tag()) {
660 case Tag::T_semicolon: lex();
break;
661 case Tag::K_axm: decls.emplace_back(parse_axm_decl(track, mods));
break;
662 case Tag::K_let: decls.emplace_back(parse_let_decl(track, mods));
break;
663 case Tag::K_mod: decls.emplace_back(parse_mod_decl(track, mods));
break;
664 case Tag::K_nom: decls.emplace_back(parse_nom_decl(track, mods));
break;
665 case Tag::K_use: decls.emplace_back(parse_use_decl(track, mods));
break;
666 case Tag::K_mutual: decls.emplace_back(parse_mutual_decl(track, mods));
break;
667 case Tag::K_rec: decls.emplace_back(parse_rec_decl(track, mods));
break;
668 case Tag::C_LAM: decls.emplace_back(parse_lam_decl(track, mods));
break;
669 case Tag::C_RULE: decls.emplace_back(parse_rule_decl(track, mods));
break;
671 if (
auto i = parse_import_or_plugin(track, mods)) decls.emplace_back(i);
675 decls.emplace_back(parse_alias_decl(track, mods));
680 if (own.any())
error().e(curr_,
"expected a declaration after a modifier");
686std::tuple<Ptr<Expr>, Dbg,
Tok,
Tok> Parser::parse_axm_tail() {
687 auto type = parse_type_ascr(
"type ascription of an axm");
690 if (ahead(0).isa(Tag::T_comma) && ahead(1).isa(Tag::M_id)) {
692 normalizer = lex().dbg();
694 if (accept(Tag::T_comma)) {
695 curry = expect(Tag::L_u,
"curry counter for axm");
696 if (accept(Tag::T_comma)) trip = expect(Tag::L_u,
"trip count for axm");
698 return {
type, normalizer, curry, trip};
704 if (mods.is_extern)
error().e(curr_,
"`axm` is implicitly `anx`; cannot combine with `extern`");
705 auto vis = mods.vis.value_or(
Vis::Pub);
709 bool is_family = ahead().isa(Tag::D_paren_l);
711 auto dbg = parse_id(
"name of an axm");
712 if (accept(Tag::T_dot)) {
716 names.emplace_back(ptr<AxmDecl::Name>(
dbg.loc(),
Dbgs{dbg}));
719 if (is_family) names = parse_axm_names();
721 auto [
type, normalizer, curry, trip] = parse_axm_tail();
722 auto members = mod ? &
ast().
scope() :
nullptr;
723 return ptr<AxmDecl>(track, vis, mod, members, is_family, type, normalizer, curry, trip, names);
728 parse_list(
"tag list of an axm", Tag::D_paren_l, [&]() {
729 Dbgs dbgs{parse_id(
"tag of an axm")};
730 while (accept(Tag::T_assign))
731 dbgs.emplace_back(parse_id(
"alias of an axm tag"));
732 names.emplace_back(ptr<AxmDecl::Name>(dbgs.front().loc() + dbgs.back().loc(), dbgs));
738 if (mods.is_extern)
error().e(curr_,
"`extern` and `anx` cannot be combined on an alias declaration");
739 auto vis = mods.vis.value_or(
Vis::Pub);
740 auto dbg = parse_id(
"name of an alias declaration");
741 expect(Tag::T_assign,
"alias declaration");
742 auto path = parse_path(
"target of an alias declaration");
743 return ptr<AliasDecl>(track, vis, dbg, path);
747 check_no_extern(mods,
"let declaration");
749 auto ptrn = parse_ptrn({},
"binding pattern of a let declaration", Prec::Bot);
750 expect(Tag::T_assign,
"let");
751 auto value = parse_expr(
"value of a let declaration");
752 return ptr<LetDecl>(track, mods, ptrn, value);
757 check_no_extern(mods,
"module");
758 if (mods.is_anx)
error().e(curr_,
"`anx` doesn't apply to a module - it groups declarations, not a single value");
761 auto dbg = parse_id(
"name of a module");
762 auto decls = parse_decls();
763 expect(Tag::K_end,
"end of a module");
764 return ptr<ModDecl>(track, vis, dbg,
ast().scope(),
ast().
copy(decls));
768 check_no_extern(mods,
"use declaration");
769 if (mods.is_anx)
error().e(curr_,
"`anx` doesn't apply to a use declaration - it never represents a single value");
771 auto path = parse_path(
"module of a use declaration");
774 if (accept(Tag::K_as) && !accept(Tag::T_star)) alias = parse_id(
"alias of a use declaration");
775 expect(Tag::T_semicolon,
"end of a use declaration");
776 return ptr<UseDecl>(track, Mods{mods.vis.value_or(
Vis::Priv)}, path, alias);
780 check_no_extern(mods,
"recursive declaration");
782 auto dbg = parse_id(
"recursive declaration");
783 expect(Tag::T_assign,
"recursive declaration");
784 auto body = parse_expr(
"body of a recursive declaration");
785 return ptr<RecDecl>(track, mods, dbg, body);
791 for (
auto decl : parse_decls(mods))
792 if (
auto rec = decl->isa<RecDecl>())
793 decls.emplace_back(rec);
795 error().e(decl->loc(),
"only `rec`, `nom`, `lam`, `con`, and `fun` declarations may be mutually recursive");
796 expect(Tag::K_end,
"end of a mutual block");
797 return ptr<MutualDecl>(track, decls);
801 check_no_extern(mods,
"nominal type declaration");
803 auto dbg = parse_id(
"nominal type declaration");
804 if (accept(Tag::T_assign)) {
805 auto body = parse_expr(
"underlying type of a nominal type declaration");
806 return ptr<NomDecl>(track, mods, dbg, body);
812 auto dom_track = tracker();
813 auto ptrn = parse_ptrn({.implicit =
true}, Prec::Pi,
"domain pattern of a nominal type declaration");
814 doms.emplace_back(ptr<LamDecl::Dom>(dom_track, ptrn,
nullptr,
nullptr,
nullptr));
816 expect(Tag::T_assign,
"nominal type declaration");
817 auto body = parse_expr(
"underlying type of a nominal type declaration");
818 auto nom = ptr<NomDecl>(track, Mods{},
dbg, body);
819 auto sugar = nom.get();
821 decls.emplace_back(std::move(nom));
822 auto inst = ptr<DeclExpr>(track, ptr<PathExpr>(ptr<Path>(
dbg.loc(),
Dbgs{dbg})),
false, decls);
823 return ptr<LamDecl>(track, mods, Tag::K_lam, dbg,
nullptr, inst, sugar, doms);
827 check_no_extern(mods,
"rewrite rule");
828 if (mods.is_anx)
error().e(curr_,
"`anx` doesn't apply to a rewrite rule");
829 auto is_norm = lex().tag() == Tag::K_norm;
830 auto dbg = parse_id(
"rewrite rule");
831 auto ptrn = parse_ptrn({},
"meta variables in rewrite rule");
832 expect(Tag::T_colon,
"rewrite rule declaration");
833 auto lhs = parse_expr(
"rewrite pattern");
834 auto guard = accept(Tag::K_when) ? parse_expr(
"rewrite guard") : ptr<PrimaryExpr>(missing(),
Tag::K_tt);
835 expect(Tag::T_fat_arrow,
"rewrite rule declaration");
836 auto rhs = parse_expr(
"rewrite result");
837 return ptr<RuleDecl>(track, mods, dbg, ptrn, lhs, rhs, guard, is_norm);
842 if (mods.is_extern && mods.is_anx)
843 error().e(curr_,
"`extern` and `anx` cannot be combined on a function declaration");
844 auto tag = lex().tag();
845 auto prec =
ISA(tag,
C_CN) ? Prec::Bot : Prec::Pi;
851 case Tag::T_lm: decl =
false; entity =
"function expression";
break;
852 case Tag::K_cn: decl =
false; entity =
"continuation expression";
break;
853 case Tag::K_fn: decl =
false; entity =
"returning continuation expression";
break;
854 case Tag::K_lam: decl = true ; entity =
"function declaration";
break;
855 case Tag::K_con: decl = true ; entity =
"continuation declaration";
break;
856 case Tag::K_fun: decl = true ; entity =
"returning continuation declaration";
break;
857 default: std::unreachable();
862 if (
auto late = parse_modifiers(); late.any()) {
863 error().e(curr_,
"modifiers must precede the keyword of a {}", entity);
864 mods = late.inherit(mods);
867 auto dbg = decl ? parse_id(entity) : Dbg();
874 auto track = tracker();
876 auto style = ahead().isa(Tag::D_brckt_l) ? PtrnStyle{.brckt =
true} : PtrnStyle{.implicit =
true};
877 ptrn = parse_ptrn(style, prec,
"domain pattern of a {}", entity);
878 filter = accept(Tag::T_at) ? parse_expr(
"filter") : nullptr;
882 doms.emplace_back(ptr<LamDecl::Dom>(loc, ptrn, filter,
nullptr,
nullptr));
886 auto codom = accept(Tag::T_colon) ? parse_expr(
Prec(
int(Prec::Where) + 1),
"codomain of a {}", entity) : nullptr;
890 ret_type = codom ? codom : ptr<HoleExpr>(missing());
891 ret = ptr<IdDecl>(Dbg(ret_type->loc(),
ast().sym_return()));
894 doms.emplace_back(ptr<LamDecl::Dom>(loc, ptrn, filter, ret_type, ret));
897 if (decl && mods.is_extern && ahead().isa(Tag::T_semicolon)) {
900 expect(Tag::T_assign,
"body of a {}", entity);
901 body = parse_expr(
"body of a {}", entity);
904 for (
auto dom : doms)
905 if (
auto tuple = dom->ptrn()->isa<TuplePtrn>(); tuple && tuple->is_brckt())
907 .e(tuple->loc(),
"a {} with a body must spell its domain as a `(...)` pattern", entity)
908 .n(
"`[...]` describes a type, so its names bind nothing here")
909 .n(
"write an unnamed component as `_: T`");
912 return ptr<LamDecl>(track, mods, tag, dbg, codom, body,
nullptr, doms);
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, Loc loc={})
static std::string plugin_name(std::string_view name)
Bare plugin name of a possibly path-qualified name: foo/libmim_bar.so → bar.
Scope & scope()
A fresh Scope for a ModDecl; owned here, as an AST node never runs a destructor.
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 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)
Lexer & lexer()
fe::Parser::lex pulls the next Token from here.
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)
static constexpr bool is_prefix(Tag tag)
Is tag a prefix operator?
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.
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.