16using namespace std::string_literals;
26void Parser::parse_module() {
28 if (ahead().tag() == Tag::K_import)
30 else if (ahead().tag() == Tag::K_plugin)
36 expect(Tag::EoF,
"module");
40 world().VLOG(
"import: {}", name);
41 auto filename = fs::path(name.view());
43 if (!filename.has_extension()) filename.replace_extension(
"thorin");
47 std::error_code ignore;
48 rel_path = path / filename;
49 if (
bool reg_file = fs::is_regular_file(rel_path, ignore); reg_file && !ignore)
break;
50 rel_path = path / name.view() / filename;
51 if (
bool reg_file = fs::is_regular_file(rel_path, ignore); reg_file && !ignore)
break;
55 auto ifs = std::ifstream(*path);
56 import(ifs, path, md);
60void Parser::import(std::istream& is,
const fs::path* path, std::ostream* md) {
61 world().VLOG(
"reading: {}", path ? path->string() :
"<unknown file>"s);
62 if (!is)
error(
"cannot read file '{}'", *path);
64 auto state = std::tuple(prev_, ahead_, lexer_);
69 std::tie(prev_, ahead_, lexer_) = state;
81void Parser::parse_import() {
83 auto name = expect(Tag::M_id,
"import name");
84 expect(Tag::T_semicolon,
"end of import");
88void Parser::parse_plugin() {
90 auto name = expect(Tag::M_id,
"thorin/plugin name");
91 expect(Tag::T_semicolon,
"end of import");
95Dbg Parser::parse_id(std::string_view ctxt) {
96 if (
auto id = accept(Tag::M_id))
return id.dbg();
97 syntax_err(
"identifier", ctxt);
98 return {prev_,
world().
sym(
"<error>")};
101std::pair<Dbg, bool> Parser::parse_name(std::string_view ctxt) {
102 if (
auto tok = accept(Tag::M_anx))
return {tok.dbg(),
true};
103 if (
auto tok = accept(Tag::M_id))
return {tok.dbg(),
false};
104 syntax_err(
"identifier or annex name", ctxt);
111void Parser::register_annex(Dbg dbg, Ref def) {
117 sub_t s = annex.subs.size();
120 auto& aliases = annex.subs.emplace_back();
121 aliases.emplace_back(sub);
127Ref Parser::parse_type_ascr(std::string_view ctxt) {
128 if (accept(Tag::T_colon))
return parse_expr(ctxt, Tok::Prec::Bot);
129 if (ctxt.empty())
return nullptr;
130 syntax_err(
"':'", ctxt);
137Ref Parser::parse_expr(std::string_view ctxt,
Tok::Prec p) {
138 auto track = tracker();
139 auto lhs = parse_primary_expr(ctxt);
140 return parse_infix_expr(track, lhs, p);
143Ref Parser::parse_infix_expr(Tracker track,
const Def* lhs,
Tok::Prec p) {
146 if (ahead().isa(Tag::T_extract)) {
147 if (
auto extract = parse_extract_expr(track, lhs, p))
151 }
else if (ahead().isa(Tag::T_arrow)) {
155 auto rhs = parse_expr(
"right-hand side of an function type", r);
160 bool is_explicit = (bool)accept(Tag::T_at);
161 if (
auto rhs = parse_expr({},
r))
162 lhs = (is_explicit ?
world().
app(lhs, rhs) :
world().
iapp(lhs, rhs))->set(track.loc());
171Ref Parser::parse_extract_expr(Tracker track,
const Def* lhs,
Tok::Prec p) {
173 if (l < p)
return nullptr;
176 if (ahead().isa(Tag::M_id)) {
177 if (
auto sigma = lhs->type()->isa_mut<Sigma>()) {
178 auto tok = eat(Tag::M_id);
179 if (tok.sym() ==
'_')
error(tok.loc(),
"you cannot use special symbol '_' as field access");
181 if (
auto i = def2fields_.find(sigma); i != def2fields_.end()) {
182 if (
auto& fields = i->second; fields.size() == sigma->num_ops()) {
183 for (
size_t i = 0, n = sigma->num_ops(); i != n; ++i)
184 if (fields[i] == tok.sym())
return world().
extract(lhs, n, i)->
set(track.loc());
187 error(tok.loc(),
"could not find elemement '{}' to extract from '{}' of type '{}'", tok.sym(), lhs, sigma);
191 auto rhs = parse_expr(
"right-hand side of an extract", r);
195Ref Parser::parse_insert_expr() {
197 auto track = tracker();
199 expect(Tag::D_paren_l,
"opening paren for insert arguments");
200 auto tuple = parse_expr(
"the tuple to insert into");
201 expect(Tag::T_comma,
"comma after tuple to insert into");
202 auto index = parse_expr(
"insert index");
203 expect(Tag::T_comma,
"comma after insert index");
204 auto value = parse_expr(
"insert value");
205 expect(Tag::D_paren_r,
"closing paren for insert arguments");
210Ref Parser::parse_primary_expr(std::string_view ctxt) {
212 switch (ahead().tag()) {
213 case Tag::D_quote_l:
return parse_arr_expr();
214 case Tag::D_angle_l:
return parse_pack_expr();
215 case Tag::D_brace_l:
return parse_block_expr();
216 case Tag::D_brckt_l:
return parse_sigma_expr();
217 case Tag::D_paren_l:
return parse_tuple_expr();
218 case Tag::K_Type:
return parse_type_expr();
219 case Tag::K_Univ: lex();
return world().
univ();
237 case Tag::T_Pi:
return parse_pi_expr();
240 case Tag::T_lm:
return parse_lam();
241 case Tag::T_star: lex();
return world().
type();
242 case Tag::T_box: lex();
return world().
type<1>();
247 case Tag::L_f:
return parse_lit_expr();
248 case Tag::L_c:
return world().
lit_i8(lex().lit_c());
249 case Tag::L_i:
return lex().lit_i();
250 case Tag::K_ins:
return parse_insert_expr();
251 case Tag::K_ret:
return parse_ret_expr();
253 case Tag::M_id:
return scopes_.
find(lex().
dbg());
254 case Tag::M_str:
return world().
tuple(lex().sym())->
set(prev_);
256 if (ctxt.empty())
return nullptr;
257 syntax_err(
"primary expression", ctxt);
263Ref Parser::parse_arr_expr() {
264 auto track = tracker();
268 const Def*
shape =
nullptr;
270 if (ahead(0).isa(Tag::M_id) && ahead(1).isa(Tag::T_colon)) {
271 auto id = eat(Tag::M_id);
274 auto shape = parse_expr(
"shape of an array");
277 scopes_.
bind(
id.
dbg(), arr->var()->set(
id.dbg()));
279 shape = parse_expr(
"shape of an array");
282 expect(Tag::T_semicolon,
"array");
283 auto body = parse_expr(
"body of an array");
284 expect(Tag::D_quote_r,
"closing delimiter of an array");
287 if (arr)
return arr->set_body(body);
291Ref Parser::parse_pack_expr() {
292 auto track = tracker();
296 if (ahead(0).isa(Tag::M_id) && ahead(1).isa(Tag::T_colon)) {
297 auto id = eat(Tag::M_id);
300 auto shape = parse_expr(
"shape of a pack");
304 expect(Tag::T_semicolon,
"pack");
305 auto body = parse_expr(
"body of a pack");
306 expect(Tag::D_angle_r,
"closing delimiter of a pack");
309 auto arr =
world().
arr(shape, body->type());
311 auto var = pack->
var();
313 return pack->
reset(pack->reduce(var));
316 auto shape = parse_expr(
"shape of a pack");
317 expect(Tag::T_semicolon,
"pack");
318 auto body = parse_expr(
"body of a pack");
319 expect(Tag::D_angle_r,
"closing delimiter of a pack");
324Ref Parser::parse_block_expr() {
327 auto res = parse_decls(
"block expression");
328 expect(Tag::D_brace_r,
"block expression");
333Ref Parser::parse_sigma_expr() {
334 auto track = tracker();
335 auto ptrn = parse_tuple_ptrn(track,
false, anonymous_);
336 return ptrn->type(
world(), def2fields_);
339Ref Parser::parse_tuple_expr() {
340 auto track = tracker();
342 parse_list(
"tuple", Tag::D_paren_l, [&]() { ops.emplace_back(parse_expr(
"tuple element")); });
346Ref Parser::parse_type_expr() {
347 auto track = tracker();
350 auto level = parse_expr(
"type level", r);
354Pi* Parser::parse_pi_expr(Pi* outer) {
355 auto track = tracker();
360 case Tag::T_Pi: entity =
"dependent function type";
break;
361 case Tag::K_Cn: entity =
"continuation type";
break;
362 case Tag::K_Fn: entity =
"returning continuation type";
break;
363 default: fe::unreachable();
370 auto implicit = (bool)accept(Tag::T_dot);
371 auto prec = tok.isa(Tag::K_Cn) ? Tok::Prec::Bot : Tok::Prec::App;
372 auto dom = parse_ptrn(Tag::D_brckt_l,
"domain of a "s + entity, prec);
373 auto dom_t = dom->type(
world(), def2fields_);
374 auto pi = (outer ? outer :
world().
mut_pi(
world().type_infer_univ()))->set_dom(dom_t)->set(dom->dbg());
375 auto var = pi->var()->set(dom->sym());
376 first = first ? first : pi;
378 if (implicit) pi->make_implicit();
379 dom->bind(scopes_, var);
380 pis.emplace_back(pi);
381 }
while (ahead().isa(Tag::T_dot) || ahead().isa(Tag::D_brckt_l) || ahead().isa(Tag::T_backtick)
382 || (ahead(0).isa(Tag::M_id) && ahead(1).isa(Tag::T_colon_colon)));
387 expect(Tag::T_arrow, entity);
388 codom = parse_expr(
"codomain of a dependent function type", Tok::Prec::Arrow);
390 case Tag::K_Cn: codom =
world().
Bot();
break;
392 expect(Tag::T_arrow, entity);
394 auto ret = parse_expr(
"domain of return continuation", Tok::Prec::Arrow);
395 auto pi = pis.back();
397 pi->
unset()->set_dom(last);
400 default: fe::unreachable();
403 for (
auto pi : pis |
std::ranges::views::reverse) {
404 pi->set_codom(codom);
408 first->set(track.loc());
413Lam* Parser::parse_lam(
bool is_decl) {
414 auto track = tracker();
416 auto prec = tok.isa(Tag::K_cn) || tok.isa(Tag::K_con) ? Tok::Prec::Bot : Tok::Prec::Pi;
417 bool external = is_decl && (bool)accept(Tag::K_extern);
422 case Tag::T_lm: entity =
"function expression";
break;
423 case Tag::K_cn: entity =
"continuation expression";
break;
424 case Tag::K_fn: entity =
"returning continuation expression";
break;
425 case Tag::K_lam: entity =
"function declaration";
break;
426 case Tag::K_con: entity =
"continuation declaration";
break;
427 case Tag::K_fun: entity =
"returning continuation declaration";
break;
428 default: fe::unreachable();
432 auto [
dbg, anx] = is_decl ? parse_name(entity) :
std::pair(Dbg{prev_, anonymous_}, false);
433 auto outer = scopes_.
curr();
436 if (
auto def = scopes_.
query(dbg)) {
437 if (
auto lam = def->isa_mut<Lam>())
440 error(
dbg.loc,
"'{}' has not been declared as a function",
dbg.sym);
443 std::unique_ptr<Ptrn> dom_p;
445 std::deque<std::tuple<Pi*, Lam*, const Def*>> funs;
447 const Def* filter = accept(Tag::T_bang) ?
world().
lit_tt() :
nullptr;
448 bool implicit = (bool)accept(Tag::T_dot);
449 dom_p = parse_ptrn(Tag::D_paren_l,
"domain pattern of a "s + entity, prec);
450 auto dom_t = dom_p->type(
world(), def2fields_);
452 auto lam = (funs.empty() && decl) ? decl :
world().mut_lam(pi);
453 auto var = lam->
var()->
set<
true>(dom_p->loc(), dom_p->sym());
454 dom_p->bind(scopes_, var);
456 if (
auto tok = accept(Tag::T_at)) {
457 if (filter)
error(tok.loc(),
"filter already specified via '!'");
458 expect(Tag::D_paren_l,
"opening parenthesis of a filter");
459 filter = parse_expr(
"filter");
460 expect(Tag::D_paren_r,
"closing parenthesis of a filter");
463 funs.emplace_back(std::tuple(pi, lam, filter));
464 }
while (!ahead().isa(Tag::T_colon) && !ahead().isa(Tag::T_assign) && !ahead().isa(Tag::T_semicolon));
470 codom = accept(Tag::T_colon) ? parse_expr(
"return type of a "s + entity) :
world().mut_infer_type();
474 case Tag::K_con: codom =
world().
Bot();
break;
477 auto& [pi, lam, filter] = funs.back();
480 auto track = tracker();
481 auto ret = accept(Tag::T_colon) ? parse_expr(
"return type of a "s + entity) :
world().mut_infer_type();
482 auto ret_loc = dom_p->loc() + track.loc();
489 if (filter) lam->set_filter(filter);
490 auto old_var = lam->
var()->as<
Var>();
491 auto rw = VarRewriter(old_var, sigma->var(2, 0));
492 sigma->set(1,
world().cn({rw.rewrite(ret)}));
496 auto new_var = new_lam->
var()->
set(ret_loc);
499 if (filter) filter =
rewrite(filter, lam, new_lam->var(2, 0)->set(lam->var()->dbg()));
506 dom_p->bind(scopes_, new_var->proj(2, 0),
true);
507 scopes_.
bind({ret_loc, return_}, new_var->proj(2, 1)->set(Dbg{ret_loc, return_}));
510 default: fe::unreachable();
513 auto [_, first, __] = funs.front();
516 for (
auto [pi, lam, _] : funs |
std::ranges::views::reverse) {
518 pi->set_codom(codom);
519 auto rw = VarRewriter(lam->var()->as<Var>(), pi->var()->set(lam->var()->dbg()));
520 auto dom = pi->dom();
521 codom = rw.rewrite(codom);
522 pi->reset({dom, codom});
527 scopes_.
bind(outer, dbg, first);
528 if (external) first->make_external();
531 auto body = accept(Tag::T_assign) ? parse_decls(
"body of a "s + entity) : nullptr;
533 if (!is_decl)
error(prev_,
"body of a {}", entity);
534 if (
auto [_, __, filter] = funs.back(); filter)
error(prev_,
"cannot specify filter of a {}", entity);
539 for (
auto [_, lam, filter] : funs |
std::ranges::views::reverse) {
542 && (tok.tag() == Tag::K_con || tok.tag() == Tag::K_cn || tok.tag() == Tag::K_fun || tok.tag() == Tag::K_fn);
543 if (body) lam->set(filter ? filter : is_cn ?
world().lit_ff() :
world().lit_tt(), body);
548 if (is_decl) expect(Tag::T_semicolon,
"end of "s + entity);
549 if (anx) register_annex(dbg, first);
551 first->set(track.loc());
557Ref Parser::parse_ret_expr() {
559 auto ptrn = parse_ptrn(Tag::D_paren_l,
"binding pattern of a ret expression");
560 expect(Tag::T_assign,
"let expression");
562 auto cn = parse_expr(
"continuation expression of a ret expression");
563 expect(Tag::T_dollar,
"separator of a ret expression");
565 auto arg = parse_expr(
"argument of ret expression");
566 expect(Tag::T_semicolon,
"let expression");
568 ptrn->bind(scopes_, lam->var());
569 auto body = parse_decls(
"body of a ret expression");
570 lam->set(
false, body);
574 error(prev_,
"continuation of the ret expression is not a returning continuation but has type '{}'", cn->type());
577Ref Parser::parse_lit_expr() {
578 auto track = tracker();
582 if (accept(Tag::T_colon)) {
583 auto type = parse_expr(
"literal", r);
589 case Tag::L_f:
break;
590 case Tag::T_bot:
return world().
bot(type)->
set(track.loc());
591 case Tag::T_top:
return world().
top(type)->
set(track.loc());
592 default: fe::unreachable();
595 return world().
lit(type, tok.lit_u())->
set(track.loc());
598 if (tok.tag() == Tag::T_bot)
return world().
bot(
world().type())->
set(track.loc());
599 if (tok.tag() == Tag::T_top)
return world().
top(
world().type())->
set(track.loc());
600 if (tok.tag() == Tag::L_s)
error(prev_,
".Nat literal specified as signed but must be unsigned");
601 if (tok.tag() == Tag::L_f)
error(prev_,
".Nat literal specified as floating-point but must be unsigned");
610std::unique_ptr<Ptrn> Parser::parse_ptrn(
Tag delim_l, std::string_view ctxt,
Tok::Prec prec ) {
611 auto track = tracker();
612 auto sym = anonymous_;
613 bool p = delim_l == Tag::D_paren_l;
614 bool b = delim_l == Tag::D_brckt_l;
615 assert((p ^ b) &&
"left delimiter must either be '(' or '['");
627 if (p && ahead().isa(Tag::D_paren_l)) {
629 return parse_tuple_ptrn(track,
false, sym);
630 }
else if (ahead().isa(Tag::D_brckt_l)) {
632 return parse_tuple_ptrn(track,
false, sym);
635 auto backtick = accept(Tag::T_backtick);
636 bool rebind = (bool)backtick;
638 if (ahead(0).isa(Tag::M_id)) {
647 if (ahead(1).isa(Tag::T_colon_colon)) {
648 sym = eat(Tag::M_id).sym();
649 eat(Tag::T_colon_colon);
650 if (b && ahead().isa(Tag::D_paren_l))
651 error(ahead().loc(),
"switching from []-style patterns to ()-style patterns is not allowed");
656 if (ahead().isa(Tag::D_paren_l) || ahead().isa(Tag::D_brckt_l))
657 return parse_tuple_ptrn(track, rebind, sym);
659 syntax_err(
"tuple pattern after '" + sym.str() +
"::'", ctxt);
660 }
else if (ahead(1).isa(Tag::T_colon)) {
663 sym = eat(Tag::M_id).sym();
665 auto type = parse_expr(ctxt, prec);
666 return std::make_unique<IdPtrn>(
dbg(track, sym), rebind, type);
673 sym = eat(Tag::M_id).sym();
674 return std::make_unique<IdPtrn>(
dbg(track, sym), rebind,
nullptr);
677 auto type = parse_expr(ctxt, prec);
678 return std::make_unique<IdPtrn>(
dbg(track, sym), rebind, type);
683 if (backtick)
error(backtick.loc(),
"you can only prefix identifiers with backtick for rebinding");
684 auto type = parse_expr(ctxt, prec);
685 return std::make_unique<IdPtrn>(
dbg(track, sym), rebind, type);
686 }
else if (!ctxt.empty()) {
688 syntax_err(
"pattern", ctxt);
694std::unique_ptr<TuplePtrn> Parser::parse_tuple_ptrn(Tracker track,
bool rebind, Sym sym, Def* decl) {
695 auto delim_l = ahead().tag();
696 bool p = delim_l == Tag::D_paren_l;
697 bool b = delim_l == Tag::D_brckt_l;
700 std::deque<std::unique_ptr<Ptrn>> ptrns;
701 std::vector<Infer*> infers;
705 parse_list(
"tuple pattern", delim_l, [&]() {
707 auto track = tracker();
708 if (!ptrns.empty()) ptrns.back()->bind(scopes_, infers.back());
709 std::unique_ptr<Ptrn> ptrn;
711 if (ahead(0).isa(Tag::M_id) && ahead(1).isa(Tag::M_id)) {
712 std::vector<Tok> sym_toks;
713 while (
auto tok = accept(Tag::M_id)) sym_toks.emplace_back(tok);
715 if (accept(Tag::T_colon)) {
716 auto type = parse_expr(
"type of an identifier group within a tuple pattern");
718 for (
size_t i = 0, e = sym_toks.size(); i !=
e; ++i) {
719 auto tok = sym_toks[i];
721 ops.emplace_back(type);
722 auto ptrn = std::make_unique<IdPtrn>(tok.dbg(),
false, type);
723 if (i != e - 1) ptrn->bind(scopes_, infers.back());
724 ptrns.emplace_back(std::move(ptrn));
730 auto lhs = scopes_.
find(sym_toks.front().dbg());
731 for (
auto sym_tok : sym_toks |
std::views::drop(1)) {
732 auto rhs = scopes_.
find(sym_tok.dbg());
733 lhs =
world().
iapp(lhs, rhs)->
set(lhs->loc() + sym_tok.loc());
736 auto expr = parse_infix_expr(track, lhs, r);
737 ptrn = std::make_unique<IdPtrn>(
dbg(track, anonymous_),
false, expr);
739 ptrn = parse_ptrn(delim_l,
"element of a tuple pattern");
740 auto type = ptrn->type(
world(), def2fields_);
743 if (
auto expr = parse_infix_expr(track, type); expr != type)
744 ptrn = std::make_unique<IdPtrn>(
dbg(track, anonymous_),
false, expr);
748 auto type = ptrn->type(
world(), def2fields_);
749 infers.emplace_back(
world().mut_infer(type)->set(ptrn->sym()));
750 ops.emplace_back(type);
751 ptrns.emplace_back(std::move(ptrn));
756 return std::make_unique<TuplePtrn>(
dbg(track, sym), rebind, std::move(ptrns),
nullptr, std::move(infers), decl);
763Ref Parser::parse_decls(std::string_view ctxt) {
766 switch (ahead().tag()) {
767 case Tag::T_semicolon: lex();
break;
768 case Tag::K_ax: parse_ax_decl();
break;
769 case Tag::K_let: parse_let_decl();
break;
770 case Tag::K_Sigma: parse_sigma_decl();
break;
771 case Tag::K_Pi: parse_pi_decl();
break;
774 case Tag::K_lam: parse_lam(
true);
break;
775 default:
return ctxt.empty() ? nullptr : parse_expr(ctxt);
781void Parser::parse_ax_decl() {
782 auto track = tracker();
784 auto dbg = expect(Tag::M_anx,
"annex name of an axiom").dbg();
789 if (sub)
error(
dbg.loc,
"axiom '{}' must not have a subtag",
dbg.sym);
791 std::deque<std::deque<Sym>> new_subs;
792 if (ahead().isa(Tag::D_paren_l)) {
793 parse_list(
"tag list of an axiom", Tag::D_paren_l, [&]() {
794 auto& aliases = new_subs.emplace_back();
795 auto [_, tag] = parse_id(
"tag of an axiom");
796 aliases.emplace_back(tag);
797 while (accept(Tag::T_assign)) {
798 auto [_, alias] = parse_id(
"alias of an axiom tag");
799 aliases.emplace_back(alias);
804 if (!is_new && new_subs.empty() && !annex.subs.empty())
805 error(
dbg.loc,
"redeclaration of axiom '{}' without specifying new subs",
dbg.sym);
806 else if (!is_new && !new_subs.empty() && annex.subs.empty())
807 error(
dbg.loc,
"cannot extend subs of axiom '{}' because it was declared as a subless axiom",
dbg.sym);
809 auto type = parse_type_ascr(
"type ascription of an axiom");
810 if (!is_new && annex.pi != (type->isa<Pi>() !=
nullptr))
811 error(
dbg.loc,
"all declarations of annex '{}' have to be function types if any is",
dbg.sym);
812 annex.pi = type->isa<
Pi>() !=
nullptr;
815 if (ahead().isa(Tag::T_comma) && ahead(1).isa(Tag::M_id)) {
817 normalizer = parse_id(
"normalizer of an axiom").
sym;
820 if (!is_new && (annex.normalizer && normalizer) && annex.normalizer != normalizer)
821 error(
dbg.loc,
"all declarations of axiom '{}' must use the same normalizer name",
dbg.sym);
822 annex.normalizer = normalizer;
826 if (accept(Tag::T_comma)) {
827 auto c = expect(Tag::L_u,
"curry counter for axiom");
828 if (
c.lit_u() > curry)
error(
c.loc(),
"curry counter cannot be greater than {}", curry);
832 if (accept(Tag::T_comma)) trip = expect(Tag::L_u,
"trip count for axiom").lit_u();
836 sub_t s = annex.subs.size();
837 if (new_subs.empty()) {
839 auto axiom =
world().
axiom(norm, curry, trip, type, p, t, 0)->
set(dbg);
841 scopes_.
bind(dbg, axiom);
843 for (
const auto& sub : new_subs) {
844 auto name =
world().
sym(
dbg.sym.str() +
"."s +
sub.front().str());
846 auto axiom =
world().
axiom(norm, curry, trip, type, p, t, s)->
set(track.loc(), name);
848 for (
auto& alias :
sub) {
849 auto sym =
world().
sym(
dbg.sym.str() +
"."s + alias.str());
850 scopes_.
bind({prev_, sym}, axiom);
854 annex.subs.insert(annex.subs.end(), new_subs.begin(), new_subs.end());
856 expect(Tag::T_semicolon,
"end of an axiom");
859void Parser::parse_let_decl() {
860 auto track = tracker();
863 std::variant<std::unique_ptr<Ptrn>, Dbg> name;
865 if (
auto tok = accept(Tag::M_anx)) {
867 type = parse_type_ascr();
869 auto ptrn = parse_ptrn(Tag::D_paren_l,
"binding pattern of a let declaration");
870 type = ptrn->type(
world(), def2fields_);
871 name = std::move(ptrn);
874 expect(Tag::T_assign,
"let");
875 auto value = parse_expr(
"value of a let declaration");
878 error(track.loc(),
"cannot assign value `{}` of type `{}` to its declared type `{}` in a let declaration",
879 value, value->type(), type);
881 if (
auto dbg = std::get_if<Dbg>(&name)) {
882 scopes_.
bind(*dbg, value);
883 register_annex(*dbg, value);
885 std::get<std::unique_ptr<Ptrn>>(name)->bind(scopes_, value);
888 expect(Tag::T_semicolon,
"let declaration");
891void Parser::parse_sigma_decl() {
892 auto track = tracker();
894 auto [
dbg, anx] = parse_name(
"sigma declaration");
895 auto type = accept(Tag::T_colon) ? parse_expr(
"type of a sigma declaration") :
world().type();
896 auto arity = std::optional<nat_t>{};
897 if (accept(Tag::T_comma)) arity = expect(Tag::L_u,
"arity of a sigma").lit_u();
899 if (accept(Tag::T_assign)) {
901 if (
auto def = scopes_.
query(dbg)) {
902 if ((!def->isa_mut<Sigma>() && !def->isa<Infer>()) || !def->isa_lit_arity())
903 error(
dbg.loc,
"'{}' has not been declared as a sigma",
dbg.sym);
905 error(
dbg.loc,
"'{}' of type '{}' has been redeclared with a different type '{}'; here: {}",
dbg.sym,
906 def->type(), type, def->loc());
907 if (arity && *arity != def->as_lit_arity())
908 error(
dbg.loc,
"sigma '{}' redeclared with a different arity '{}'; previous arity was '{}' here: {}",
909 dbg.sym, *arity, def->arity(), def->loc());
910 decl = def->as_mut();
912 error(
dbg.loc,
"redefinition of '{}'; previous definition here: '{}'",
dbg.sym, decl->loc());
915 scopes_.
bind(dbg, decl);
918 if (!ahead().isa(Tag::D_brckt_l)) syntax_err(
"sigma expression",
"definition of a sigma declaration");
920 auto ptrn = parse_tuple_ptrn(track,
false,
dbg.sym, decl);
921 auto t = ptrn->type(
world(), def2fields_);
923 assert(
t->isa_mut<Sigma>());
924 t->set<
true>(track.loc());
925 if (anx) register_annex(dbg, t);
927 if (
auto infer = decl->isa<Infer>()) {
928 assert(infer->op() == t);
929 infer->set<
true>(track.loc());
930 scopes_.
bind(dbg, t,
true);
936 scopes_.
bind(dbg, decl);
939 expect(Tag::T_semicolon,
"end of a sigma declaration");
942void Parser::parse_pi_decl() {
943 auto track = tracker();
945 auto [
dbg, anx] = parse_name(
"pi declaration");
946 auto type = accept(Tag::T_colon) ? parse_expr(
"type of a pi declaration") :
world().type();
948 if (accept(Tag::T_assign)) {
950 if (
auto def = scopes_.
query(dbg)) {
951 if (
auto mut = def->isa_mut<Pi>()) {
953 error(
dbg.loc,
"'{}' of type '{}' has been redeclared with a different type '{}'; here: {}",
954 dbg.sym, mut->type(), type, mut->loc());
956 error(
dbg.loc,
"redefinition of '{}'; previous definition here: '{}'",
dbg.sym, mut->loc());
959 error(
dbg.loc,
"'{}' has not been declared as a pi",
dbg.sym);
963 scopes_.
bind(dbg, pi);
965 if (anx) register_annex(dbg, pi);
967 if (!ahead().isa(Tag::T_Pi) && !ahead().isa(Tag::K_Cn) && !ahead().isa(Tag::K_Fn))
968 syntax_err(
"pi expression",
"definition of a pi declaration");
970 auto other = parse_pi_expr(pi);
971 assert_unused(other == pi);
972 pi->set<
true>(track.loc());
975 scopes_.
bind(dbg, pi);
978 expect(Tag::T_semicolon,
"end of a pi declaration");
Arr * set_shape(const Def *shape)
static std::pair< u8, u8 > infer_curry_and_trip(const Def *type)
static bool alpha(Ref d1, Ref d2)
Are d1 and d2 α-equivalent?
static bool assignable(Ref type, Ref value)
Can value be assigned to sth of type?
Def * reset(size_t i, const Def *def)
Successively reset from left to right.
Ref var(nat_t a, nat_t i)
Def * unset()
Unsets all Def::ops; works even, if not set at all or partially.
Def * set(size_t i, const Def *def)
Successively set from left to right.
std::pair< Annex &, bool > name2annex(Sym sym, Sym plugin, Sym tag, Loc loc)
const auto & search_paths() const
const fs::path * add_import(fs::path, Sym)
Yields a fs::path* if not already added that you can use in Location; returns nullptr otherwise.
auto normalizer(flags_t flags) const
Infer * set(const Def *op)
Pack * set(const Def *body)
void import(std::string_view sv)
Pi * set(Ref dom, Ref codom)
const Pi * ret_pi() const
Yields the last Pi::dom, if it Pi::isa_basicblock.
const Def * query(Dbg) const
void bind(Scope *, Dbg, const Def *, bool rebind=false)
const Def * find(Dbg) const
Same as Scopes::query but potentially raises an error.
Sigma * set(size_t i, const Def *def)
static constexpr std::array< Prec, 2 > prec(Prec p)
Ref insert(Ref d, Ref i, Ref val)
Pi * mut_pi(Ref type, bool implicit=false)
Ref iapp(Ref callee, Ref arg)
Places Infer arguments as demanded by Pi::implicit and then apps arg.
const Lit * lit(Ref type, u64 val)
Pack * mut_pack(Ref type)
Sym sym(std::string_view)
Ref var(Ref type, Def *mut)
Ref pack(Ref arity, Ref body)
Sigma * mut_sigma(Ref type, size_t size)
const Axiom * axiom(NormalizeFn n, u8 curry, u8 trip, Ref type, plugin_t p, tag_t t, sub_t s)
const Pi * pi(Ref dom, Ref codom, bool implicit=false)
Ref extract(Ref d, Ref i)
const Lit * lit_nat(nat_t a)
Ref arr(Ref shape, Ref body)
const Def * register_annex(flags_t f, const Def *)
Ref app(Ref callee, Ref arg)
Infer * mut_infer(Ref type)
Lam * mut_lam(const Pi *pi)
const Type * type(Ref level)
DefVec rewrite(Def *mut, Ref arg)
void error(const Def *def, const char *fmt, Args &&... args)
void bootstrap(Driver &, Sym, std::ostream &)
Vector< const Def * > DefVec
static std::optional< plugin_t > mangle(Sym s)
Mangles s into a dense 48-bit representation.
static std::array< Sym, 3 > split(World &, Sym)