MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
bind.cpp
Go to the documentation of this file.
1#include <fe/restore.h>
2
3#include "mim/ast/ast.h"
4
5#include "family.h"
6
7using namespace std::literals;
8
9namespace mim::ast {
10
11using Tag = Tok::Tag;
12
13class DummyDecl : public Decl {
14public:
16 : Decl(Loc()) {}
17
18 void stream(fe::Tab&, std::ostream& os) const final { os << "<dummy>"; }
19};
20
21class Scopes {
22public:
24 : ast_(ast)
25 , dummy_(ast.ptr<DummyDecl>()) {
26 push(); // root scope
27 }
28
29 AST& ast() const { return ast_; }
30 Error& error() const { return ast().error(); }
31 Scope& top() { return scopes_.back().scope(); }
32 const Decl* dummy() const { return dummy_.get(); }
33
34 void push() { scopes_.emplace_back(); }
35 void push(Scope& scope) { scopes_.emplace_back(scope); }
36
37 void pop() {
38 assert(scopes_.size() > barrier_);
39 scopes_.pop_back();
40 }
41
42 struct Barrier {
43 size_t scopes, mods;
44 };
45
46 /// A file must not see the scope of whoever imports it, so its Scope becomes the new lookup floor.
48 push(scope);
49 return {std::exchange(barrier_, scopes_.size() - 1), std::exchange(mod_barrier_, mod_stack_.size())};
50 }
51
52 void pop_barrier(Barrier old) {
53 barrier_ = old.scopes;
54 mod_barrier_ = old.mods;
55 pop();
56 }
57
58 /// @name Annex nesting
59 /// Tracked by ModDecl::bind so AST::name2annex can derive `tag`/`sub` from lexical nesting.
60 ///@{
61 /// The top-level declaration being bound, if any; see NomDecl::rep_vis.
62 const Decl* top_decl() const { return top_decl_; }
63 auto enter_top_decl(const Decl* decl) { return fe::Restore(top_decl_, decl); }
64
65 void push_mod(Sym name) { mod_stack_.emplace_back(name); }
66 void pop_mod() { mod_stack_.pop_back(); }
67 size_t mod_depth() const { return mod_stack_.size() - mod_barrier_; }
68 Sym enclosing_mod() const { return mod_depth() == 0 ? Sym() : mod_stack_.back(); }
69 ///@}
70
71 const Decl* find(Dbg dbg, bool quiet = false) {
72 // `_` never enters a Scope, so it cannot be planted as a dummy; the recorded error keeps emit from running.
73 if (dbg.is_anon()) {
74 if (!quiet) error().e(dbg.loc(), "`_` never binds an entity and cannot be referenced");
75 return nullptr;
76 }
77
78 for (auto& frame : scopes_ | std::views::drop(barrier_) | std::views::reverse)
79 if (auto bind = fe::lookup(frame.scope(), dbg.sym())) return bind->decl;
80
81 if (!quiet) {
82 auto& diag = error().e(dbg.loc(), "identifier `{}` not found", dbg.sym());
83 // An infix operator only exists as whatever the user bound its escaped name to.
84 if (dbg.sym().view().starts_with('`'))
85 diag.n("an infix operator means whatever you bind its escaped name to");
86 bind(dbg, dummy()); // put into scope to prevent further errors
87 }
88 return nullptr;
89 }
90
91 /// Diagnostic-only: is a module named @p sym reachable, shadowed by whatever `find` would actually return?
92 /// Only a module - a ModDecl, an Import, or an AxmDecl family - yields a non-null Decl::scope.
93 const Decl* find_shadowed_module(Sym sym) {
94 for (auto& frame : scopes_ | std::views::drop(barrier_) | std::views::reverse)
95 if (auto bind = fe::lookup(frame.scope(), sym); bind && bind->decl->scope()) return bind->decl;
96 return nullptr;
97 }
98
99 void bind(Dbg dbg, const Decl* decl, bool rebind = false, bool quiet = false) {
100 bind(dbg, decl, decl->vis(), rebind, quiet);
101 }
102
103 /// Binds @p decl under @p dbg with an explicit @p vis - a splice re-exports under its own visibility.
104 void bind(Dbg dbg, const Decl* decl, Vis vis, bool rebind = false, bool quiet = false) {
105 if (dbg.is_anon()) return;
106
107 auto& scope = top();
108 if (rebind) {
109 scope[dbg.sym()] = Bind{decl, vis};
110 } else if (auto [i, ins] = scope.try_emplace(dbg.sym(), Bind{decl, vis}); !ins) {
111 auto prev = i->second.decl;
112 if (!quiet && !prev->isa<DummyDecl>()) // if prev stems from an error - don't complain
113 error().e(dbg.loc(), "redeclaration of `{}`", dbg).n(prev->dbg().loc(), "previous declaration here");
114 } else if (!quiet && !decl->scope()) {
115 if (auto mod = find_shadowed_module(dbg.sym()))
116 error()
117 .w(dbg.loc(), "`{}` shadows a module of the same name", dbg)
118 .n(mod->dbg().loc(), "module declared here; a later `{}.member` would fail to resolve it",
119 dbg.sym());
120 }
121 }
122
123private:
124 /// Owns the Scope of an anonymous binder; a File's or ModDecl's Scope outlives Scopes and is borrowed.
125 class Frame {
126 public:
127 Frame() = default;
128 Frame(Scope& scope)
129 : borrowed_(&scope) {}
130
131 Scope& scope() { return borrowed_ ? *borrowed_ : own_; }
132
133 private:
134 Scope own_;
135 Scope* borrowed_ = nullptr;
136 };
137
138 AST& ast_;
139 Ptr<DummyDecl> dummy_;
140 fe::Vector<Frame> scopes_;
141 fe::Vector<Sym> mod_stack_;
142 const Decl* top_decl_ = nullptr;
143 size_t barrier_ = 0;
144 size_t mod_barrier_ = 0;
145};
146
147/*
148 * File
149 */
150
151void File::bind(AST& ast) const {
152 auto scopes = Scopes(ast);
153 bind(scopes);
154}
155
156void File::bind(Scopes& s) const {
157 if (bound_) return;
158 bound_ = true;
159
160 auto barrier = s.push_barrier(members());
161 for (auto import : implicit_imports())
162 import->bind(s);
163 bind_decls(s);
164 s.pop_barrier(barrier);
165}
166
167/*
168 * Ptrn
169 */
170
171void ErrorPtrn::bind(Scopes&, bool, bool) const {}
172void GrpPtrn::bind(Scopes& s, bool rebind, bool quiet) const { s.bind(dbg(), this, rebind, quiet); }
173
174void IdPtrn::bind(Scopes& s, bool rebind, bool quiet) const {
175 if (!quiet && type()) type()->bind(s);
176 s.bind(dbg(), this, rebind, quiet);
177}
178
179void IdDecl::bind(Scopes& s, bool quiet) const { s.bind(dbg(), this, false, quiet); }
180
181void AliasPtrn::bind(Scopes& s, bool rebind, bool quiet) const {
182 ptrn()->bind(s, rebind, quiet);
183 s.bind(dbg(), this, rebind, quiet);
184}
185
186void TuplePtrn::bind(Scopes& s, bool rebind, bool quiet) const {
187 for (auto ptrn : ptrns())
188 ptrn->bind(s, rebind, quiet);
189}
190
191/*
192 * Expr
193 */
194
195void Path::bind(Scopes& s, bool quiet) const {
196 decl_ = s.find(front(), quiet);
197 auto prev = front();
198
199 for (auto dbg : dbgs() | std::views::drop(1)) {
200 if (!decl_) return;
201 auto scope = decl_->scope();
202 auto member = scope ? fe::lookup(*scope, dbg.sym()) : nullptr;
203 if (!member) {
204 if (!quiet && !decl_->isa<DummyDecl>()) {
205 if (scope) {
206 s.error().e(dbg.loc(), "`{}` has no member `{}`", prev.sym(), dbg.sym());
207 } else {
208 auto& err = s.error().e(prev.loc(), "`{}` is not a module", prev.sym());
209 if (auto mod = s.find_shadowed_module(prev.sym()))
210 err.n(mod->dbg().loc(), "a module `{}` exists here but is shadowed by the `{}` in scope",
211 prev.sym(), prev.sym());
212 }
213 }
214 decl_ = nullptr;
215 return;
216 }
217 decl_ = member->decl;
218 prev = dbg;
219
220 // A dotted path always crosses into decl_'s enclosing mod from outside: `priv` blocks it.
221 if (member->vis == Vis::Priv) {
222 if (!quiet) s.error().e(dbg.loc(), "`{}` is private to its enclosing `mod`", dbg.sym());
223 decl_ = nullptr;
224 return;
225 }
226 }
227}
228
229// clang-format off
230void PathExpr ::bind(Scopes& s) const { path()->bind(s); }
231void TypeExpr ::bind(Scopes& s) const { level()->bind(s); }
232void RuleExpr ::bind(Scopes& s) const { dom()->bind(s); }
233void ErrorExpr ::bind(Scopes&) const {}
234void HoleExpr ::bind(Scopes&) const {}
236// clang-format on
237
238void LitExpr::bind(Scopes& s) const {
239 if (type()) {
240 type()->bind(s);
241 if (ISA(tag(), C_LIT_TYPED)) s.error().e(type()->loc(), "a `{}` must not have a type annotation", tag());
242 } else if (tag() == Tag::L_f) {
243 s.error().e(loc(), "floating-point literal requires a type annotation");
244 }
245}
246
247void DeclExpr::bind(Scopes& s) const {
248 if (is_where())
249 for (auto decl : decls() | std::views::reverse)
250 decl->bind(s);
251 else
252 for (auto decl : decls())
253 decl->bind(s);
254 expr()->bind(s);
255}
256
257void PrefixExpr::bind(Scopes& s) const { rhs()->bind(s); }
258
259void InfixExpr::bind(Scopes& s) const {
260 if (callee()) callee()->bind(s);
261 lhs()->bind(s);
262 // `t#x` may name a field of `t`'s Sigma rather than anything in scope; InfixExpr::emit_ resolves that.
263 if (auto path = op().isa(Tag::T_extract) ? rhs()->isa<PathExpr>() : nullptr)
264 path->path()->bind(s, true);
265 else
266 rhs()->bind(s);
267}
268
270 s.push();
271 if (ptrn()) ptrn()->bind(s, false, false);
272 body()->bind(s);
273 s.pop();
274}
275
276void VariantExpr::bind(Scopes& s) const {
277 for (auto ctor : ctors())
278 if (ctor->type()) ctor->type()->bind(s);
279}
280
281void MatchExpr::bind(Scopes& s) const {
282 scrutinee()->bind(s);
283 for (auto arm : arms())
284 arm->bind(s);
285}
286
287void PiExpr::Dom::bind(Scopes& s, bool quiet) const {
288 ptrn()->bind(s, false, quiet);
289 if (ret_type() && !quiet) ret_type()->bind(s);
290}
291
292void PiExpr::bind(Scopes& s) const {
293 s.push();
294 dom()->bind(s);
295 if (codom()) codom()->bind(s);
296 s.pop();
297}
298
299void LamExpr::bind(Scopes& s) const {
300 lam()->bind_decl(s);
301 lam()->bind_body(s);
302}
303
304void AppExpr::bind(Scopes& s) const {
305 callee()->bind(s);
306 arg()->bind(s);
307}
308
309void RetExpr::bind(Scopes& s) const {
310 callee()->bind(s);
311 arg()->bind(s);
312 s.push();
313 ptrn()->bind(s, true, false);
314 body()->bind(s);
315 s.pop();
316}
317
318void SigmaExpr::bind(Scopes& s) const {
319 s.push();
320 ptrn()->bind(s, false, false);
321 s.pop();
322}
323
324void TupleExpr::bind(Scopes& s) const {
325 for (auto elem : elems())
326 elem->bind(s);
327}
328
329void SeqExpr::bind(Scopes& s) const {
330 s.push();
331 shape()->bind(s);
332 index()->bind(s);
333 body()->bind(s);
334 s.pop();
335}
336
337void SingleExpr::bind(Scopes& s) const { body()->bind(s); }
338
339/*
340 * Decl
341 */
342
343static Sym loc2plugin(AST& ast, Loc loc) {
344 return loc.src ? ast.sym(fs::path(loc.src->path()).stem().string()) : ast.sym_error();
345}
346
347/// Records the constructor or field names that @p type - the body of an annex declaration - spells out.
348static void add_names(AnnexInfo& annex, const Expr* type) {
349 if (auto variant = type->isa<VariantExpr>()) {
350 annex.names = fe::Vector<Sym>(variant->ctors(), [](const auto& ctor) { return ctor->dbg().sym(); });
351 annex.fields = false;
352 } else if (auto sigma = type->isa<SigmaExpr>()) {
353 auto tuple = sigma->ptrn();
354 annex.names = fe::Vector<Sym>(tuple->num_ptrns(), [tuple](size_t i) { return tuple->field(i); });
355 annex.fields = true;
356 }
357}
358
359AnnexInfo* AST::name2annex(Scopes& s, Dbg dbg, sub_t* sub_id, const Expr* type) {
360 if (!dbg) return nullptr;
361
362 auto depth = s.mod_depth();
363 if (depth > 1) {
364 error().e(dbg.loc(), "`{}` sits {} `mod` levels deep; an `anx` declaration may nest at most one", dbg, depth);
365 return nullptr;
366 }
367
368 auto plugin_s = loc2plugin(*this, dbg.loc());
369 auto tag_s = depth == 0 ? dbg.sym() : s.enclosing_mod();
370 Sym sub_s = depth == 0 ? Sym() : dbg.sym();
371
372 auto& sym2annex = plugin2sym2annex_[plugin_s];
373 auto tag_id = sym2annex.size();
374
375 if (plugin_s == sym_error()) error().e(dbg.loc(), "plugin name `{}` is reserved", dbg);
376 if (tag_id > std::numeric_limits<tag_t>::max())
377 error().e(dbg.loc(), "exceeded maximum number of annexes in current plugin");
378
379 if (!Annex::mangle(plugin_s)) {
380 error().e(dbg.loc(), "invalid annex name `{}`", dbg);
381 plugin_s = sym_error();
382 }
383
384 auto [i, fresh] = sym2annex.try_emplace(tag_s, AnnexInfo{plugin_s, tag_s, (tag_t)tag_id});
385 auto annex = &i->second;
386
387 if (sub_s) {
388 if (sub_id) {
389 *sub_id = annex->subs.size();
390 auto& aliases = annex->subs.emplace_back();
391 aliases.emplace_back(sub_s);
392 } else {
393 error().e(dbg.loc(), "annex `{}` must not have a subtag", dbg);
394 }
395 }
396
397 if (!fresh) annex->fresh = false;
398 if (type) add_names(*annex, type);
399 return annex;
400}
401
402/// Registers @p alias as a further name of the annex slot @p target introduced.
403static void add_alias(AnnexInfo* annex, sub_t sub, Sym target, Sym alias) {
404 // An ungrouped target (the common case) never allocated its own sub-group; seed one now,
405 // named after the target itself, so this alias has a slot to share.
406 if (sub >= annex->subs.size()) {
407 assert(sub == annex->subs.size());
408 annex->subs.emplace_back(fe::Vector<Sym>{target});
409 }
410 annex->subs[sub].emplace_back(alias);
411}
412
413void AxmDecl::bind(Scopes& s) const {
414 type()->bind(s);
415 auto pi = type()->isa<PiExpr>() || InfixExpr::isa_op(Tag::T_arrow_r, type());
416
417 if (members_) {
418 s.push(*members_);
419 s.push_mod(mod_.sym());
420 }
421
422 for (auto name : names()) {
423 auto dbg = name->dbg();
424 auto& annex = name->annex_ = s.ast().name2annex(s, dbg, &name->sub_);
425
426 if (annex && annex->fresh) {
427 annex->normalizer = normalizer();
428 annex->pi = pi;
429 } else if (annex) {
430 if (annex->pi != pi)
431 s.error().e(dbg.loc(),
432 "all declarations of annex `{}` must be function types if one of them is (they share one "
433 "annex tag - via mod-nesting or a `tag.(...)` family - and must agree in shape)",
434 dbg.sym());
435
436 if (annex->normalizer.sym() != normalizer().sym()) {
437 auto l = normalizer().loc() ? normalizer().loc() : loc().anew_end();
438 auto& err = s.error().e(l, "normalizer mismatch for axm `{}`", dbg);
439 if (auto norm = annex->normalizer)
440 err.n(norm.loc(), "previous normalizer `{}` declared here", norm);
441 else
442 err.n("initially no normalizer was specified");
443 }
444 }
445
446 s.bind(dbg, name.get(), vis());
447 for (auto alias : name->aliases()) {
448 s.bind(alias, name.get(), vis());
449 if (annex) add_alias(annex, name->sub_, dbg.sym(), alias.sym());
450 }
451 }
452
453 if (members_) {
454 s.pop_mod();
455 s.pop();
456 // The family is reachable as a module whatever the visibility of its axioms.
457 s.bind(mod_, this, Vis::Pub);
458 }
459}
460
461void AliasDecl::bind(Scopes& s) const {
462 path()->bind(s);
463 s.bind(dbg(), this);
464
465 auto target = path()->decl();
466 if (!target) return;
467
468 if (target->isa<AliasDecl>()) {
469 s.error().e(loc(), "`{}` aliases `{}`, which is itself an alias; alias chains are not supported", dbg(),
470 path()->back());
471 return;
472 }
473
474 std::tie(annex_, sub_) = target->annex_sub();
475 if (!annex_) {
476 s.error().e(loc(), "`{}` must alias a compiler-exposed (`anx`) declaration", dbg());
477 return;
478 }
479
480 auto& ast = s.ast();
481 if (auto plugin = loc2plugin(ast, dbg().loc());
482 plugin != ast.sym_error() && plugin != annex_->sym.plugin && s.mod_depth() == 0) {
483 foreign_ = ast.sym(plugin.str() + "." + dbg().sym().str());
484 ast.add_foreign_alias(plugin, {dbg().sym(), annex_, sub_});
485 return;
486 }
487
488 add_alias(annex_, sub_, target->dbg().sym(), dbg().sym());
489}
490
491void LetDecl::bind(Scopes& s) const {
492 s.push();
493 value()->bind(s);
494 s.pop();
495
496 auto id = ptrn()->isa<IdPtrn>();
497 // Scopes::bind snapshots Decl::vis, so mirror it onto the Ptrn *before* the Ptrn enters a Scope.
498 if (id) {
499 id->vis_ = vis();
500 id->anx_ = is_anx();
501 }
502 ptrn()->bind(s, true, false);
503 if (id && is_anx()) id->annex_ = s.ast().name2annex(s, id->dbg(), &id->sub_, value());
504}
505
506void RecDecl::bind(Scopes& s) const {
507 bind_decl(s);
508 bind_body(s);
509}
510
511void MutualDecl::bind(Scopes& s) const {
512 // Only a top-level `mutual` makes its members top-level.
513 auto is_top = s.top_decl() == this;
514 for (auto decl : decls()) {
515 auto _ = s.enter_top_decl(is_top ? decl.get() : s.top_decl());
516 decl->bind_decl(s);
517 }
518 for (auto decl : decls()) {
519 auto _ = s.enter_top_decl(is_top ? decl.get() : s.top_decl());
520 decl->bind_body(s);
521 }
522}
523
525 return body()->isa<PiExpr>() || InfixExpr::isa_op(Tag::T_arrow_r, body()) || body()->isa<SigmaExpr>()
526 || body()->isa<VariantExpr>();
527}
528
530 // A `nom` over any other body is merely not recursive.
531 if (!isa<NomDecl>() && !has_mut_body())
532 s.error()
533 .e(body()->loc(), "unsupported expression in a recursive declaration")
534 .n("must be a sigma, a variant, or a function type; use `lam`/`con`/`fun` to declare a recursive function");
535
536 s.bind(dbg(), this);
537 if (is_anx()) annex_ = s.ast().name2annex(s, dbg(), &sub_, body());
538}
539
540void RecDecl::bind_body(Scopes& s) const { body()->bind(s); }
541
543 rep_vis_ = s.top_decl() ? s.top_decl()->vis() : Vis::Pub;
545}
546
547void LamDecl::Dom::bind(Scopes& s, bool quiet) const {
548 PiExpr::Dom::bind(s, quiet);
549 if (ret()) ret()->bind(s, quiet);
550 if (filter() && !quiet) filter()->bind(s);
551}
552
554 s.push();
555 for (auto&& dom : doms())
556 dom->bind(s);
557
558 if (auto filter = doms().back()->filter()) {
559 if (auto pe = filter->isa<PrimaryExpr>()) {
560 if (pe->tag() == Tag::K_tt && ISA(tag(), C_DS))
561 s.error().w(filter->loc(),
562 "`tt`-filter superfluous as the last curried function group of a `{}` receives a "
563 "`tt`-filter by default",
564 tag());
565 if (pe->tag() == Tag::K_ff && !ISA(tag(), C_DS))
566 s.error().w(filter->loc(),
567 "`ff`-filter superfluous as the last curried function group of a `{}` receives a "
568 "`ff`-filter by default",
569 tag());
570 }
571 }
572
573 if (codom()) {
574 if (ISA(tag(), C_CN)) s.error().e(codom()->loc(), "a continuation must not have a codomain");
575 codom()->bind(s);
576 }
577
578 s.pop();
579 s.bind(dbg(), this);
580 if (is_anx()) annex_ = s.ast().name2annex(s, dbg(), &sub_, nom_sugar() ? nom_sugar()->body() : nullptr);
581}
582
584 s.push();
585 for (auto dom : doms())
586 dom->bind(s, true);
587 if (auto nom = nom_sugar())
588 nom->bind_body(s);
589 else if (body())
590 body()->bind(s);
591 s.pop();
592}
593
595 for (auto decl : decls()) {
596 auto _ = s.enter_top_decl(decl.get());
597 decl->bind(s);
598 }
599}
600
601void ModDecl::bind(Scopes& s) const {
602 s.push(members());
603 s.push_mod(dbg().sym());
604 bind_decls(s);
605 s.pop_mod();
606 s.pop();
607 s.bind(dbg(), this);
608}
609
610const Scope* UseDecl::module(Scopes& s) const {
611 if (is_import()) {
612 if (!file()) return nullptr;
613 file()->bind(s);
614 return file()->scope();
615 }
616
617 path()->bind(s);
618 auto decl = path()->decl();
619 if (!decl) return nullptr;
620
621 auto scope = decl->scope();
622 if (!scope) s.error().e(path()->loc(), "`{}` is not a module", path()->back().sym());
623 return scope;
624}
625
626void UseDecl::bind(Scopes& s) const {
627 auto mod = module(s);
628 if (!mod) return;
629
630 if (is_splice()) {
631 // Quiet: a name already bound here wins, so a splice never shadows and never conflicts.
632 for (const auto& [sym, binding] : *mod)
633 if (binding.vis == Vis::Pub) s.bind(Dbg(loc(), sym), binding.decl, vis(), false, true);
634 return;
635 }
636
637 // The same file may be imported more than once - as `-p foo` plus a `plugin foo;` directive, say.
638 if (file())
639 if (auto prev = s.find(dbg(), true))
640 if (auto use = prev->isa<UseDecl>(); use && use->file() == file()) return;
641
642 scope_ = mod;
643 s.bind(dbg(), this);
644}
645
646void RuleDecl::bind(Scopes& s) const {
647 s.push();
648 var()->bind(s, true, false);
649 lhs()->bind(s);
650 rhs()->bind(s);
651 guard()->bind(s);
652 s.pop();
653 s.bind(dbg(), this);
654}
655
656} // namespace mim::ast
Owns the arena all AST nodes live in as well as the AnnexInfos of all plugins.
Definition ast.h:107
AnnexInfo * name2annex(Scopes &s, Dbg dbg, sub_t *sub_id, const Expr *type=nullptr)
Definition bind.cpp:359
Error & error() const
Definition ast.h:118
Sym sym_error()
"_error_".
Definition ast.h:127
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1271
void bind(Scopes &) const override
Definition bind.cpp:461
const Path * path() const
Definition ast.h:1272
AliasDecl(Loc loc, Vis vis, Dbg dbg, Ptr< Path > path)
Definition ast.h:1266
const Ptrn * ptrn() const
Definition ast.h:409
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:410
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:181
void bind(Scopes &) const override
Definition bind.cpp:304
const Expr * arg() const
Definition ast.h:864
const Expr * callee() const
Definition ast.h:863
auto names() const
Definition ast.h:1113
const Expr * type() const
Definition ast.h:1116
void bind(Scopes &) const override
Definition bind.cpp:413
Dbg normalizer() const
Definition ast.h:1117
Dbg dbg() const override
The mod. prefix, if any.
Definition ast.h:1111
const Expr * expr() const
Definition ast.h:577
auto decls() const
Definition ast.h:575
void bind(Scopes &) const override
Definition bind.cpp:247
bool is_where() const
Definition ast.h:576
Base class of all declarations; caches the emitted Decl::def.
Definition ast.h:250
Decl(Loc loc)
Definition ast.h:252
virtual Vis vis() const
A ValDecl's own Vis; Pub for anything else (Ptrn, Import, ...), which the priv/pub system ignores.
Definition ast.h:265
virtual const Scope * scope() const
Non-nullptr if this Decl is a module whose members a Path may walk into.
Definition ast.h:261
void stream(fe::Tab &, std::ostream &os) const final
Definition bind.cpp:18
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:171
Base class of all expressions.
Definition ast.h:227
virtual void bind(Scopes &) const =0
auto implicit_imports() const
Imports the driver was told about via -p; they precede everything the file itself declares.
Definition ast.h:1361
void bind(AST &) const
Definition bind.cpp:151
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:172
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:388
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:282
void bind(Scopes &, bool quiet=false) const
Definition bind.cpp:179
dbg: type
Definition ast.h:348
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:174
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:355
const Expr * type() const
Definition ast.h:356
void bind(Scopes &) const override
Definition bind.cpp:259
static const InfixExpr * isa_op(Tok::Tag tag, const Expr *expr)
Definition ast.h:665
const Expr * callee() const
Definition ast.h:662
const Expr * rhs() const
Definition ast.h:661
const Expr * lhs() const
Definition ast.h:659
Tok op() const
Definition ast.h:660
const Expr * filter() const
Definition ast.h:1205
void bind(Scopes &, bool quiet=false) const override
Definition bind.cpp:547
const IdDecl * ret() const
Definition ast.h:1206
Tok::Tag tag() const
Definition ast.h:1228
void bind_body(Scopes &) const override
Definition bind.cpp:583
auto doms() const
Definition ast.h:1229
const Expr * codom() const
Definition ast.h:1232
void bind_decl(Scopes &) const override
Definition bind.cpp:553
const NomDecl * nom_sugar() const
The nom of lam I dom+ = nom I = e; I if nom I dom+ = e desugared to this; within e,...
Definition ast.h:1234
const Dom * dom(size_t i) const
Definition ast.h:1230
void bind(Scopes &) const override
Definition bind.cpp:299
const LamDecl * lam() const
Definition ast.h:842
void bind(Scopes &) const override
Definition bind.cpp:491
const Expr * value() const
Definition ast.h:1060
const Ptrn * ptrn() const
Definition ast.h:1059
const Expr * type() const
Definition ast.h:553
Tok::Tag tag() const
Definition ast.h:552
void bind(Scopes &) const override
Definition bind.cpp:238
const Expr * body() const
Definition ast.h:702
virtual void bind(Scopes &) const
Definition bind.cpp:269
const Ptrn * ptrn() const
Definition ast.h:701
auto arms() const
Definition ast.h:727
void bind(Scopes &) const override
Definition bind.cpp:281
const Expr * scrutinee() const
Definition ast.h:726
const Arm * arm(size_t i) const
Definition ast.h:728
void bind_decls(Scopes &) const
Definition bind.cpp:594
void bind(Scopes &) const override
Definition bind.cpp:601
Scope & members() const
Definition ast.h:1339
auto decls() const
Definition ast.h:1331
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1330
auto decls() const
Definition ast.h:1256
void bind(Scopes &) const override
Definition bind.cpp:511
Loc loc() const
Definition ast.h:217
void bind_body(Scopes &) const override
Definition bind.cpp:542
const Path * path() const
Definition ast.h:510
auto dbgs() const
Definition ast.h:491
void bind(Scopes &, bool quiet=false) const
Definition bind.cpp:195
Dbg front() const
Definition ast.h:492
const Expr * ret_type() const
Definition ast.h:796
virtual void bind(Scopes &, bool quiet=false) const
Definition bind.cpp:287
const Ptrn * ptrn() const
Definition ast.h:795
dom → codom, Cn dom, or Fn dom → codom depending on PiExpr::tag.
Definition ast.h:784
void bind(Scopes &) const override
Definition bind.cpp:292
const Expr * rhs() const
Definition ast.h:636
void bind(Scopes &) const override
Definition bind.cpp:257
void bind(Scopes &) const override
Definition bind.cpp:235
virtual void bind(Scopes &, bool rebind, bool quiet) const =0
virtual void bind_body(Scopes &) const
Definition bind.cpp:540
bool has_mut_body() const
Only such a body is emitted as a mutable, so only it may refer to the declaration itself.
Definition bind.cpp:524
virtual void bind_decl(Scopes &) const
Definition bind.cpp:529
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1142
const Expr * body() const
Definition ast.h:1143
AnnexInfo * annex_
Definition ast.h:1161
void bind(Scopes &) const override
Definition bind.cpp:506
const Ptrn * ptrn() const
Definition ast.h:886
const Expr * arg() const
Definition ast.h:888
void bind(Scopes &) const override
Definition bind.cpp:309
const Expr * body() const
Definition ast.h:889
const Expr * callee() const
Definition ast.h:887
void bind(Scopes &) const override
Definition bind.cpp:646
const Ptrn * var() const
Definition ast.h:1300
const Expr * guard() const
Definition ast.h:1303
const Expr * rhs() const
Definition ast.h:1302
const Expr * lhs() const
Definition ast.h:1301
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1299
const Expr * dom() const
Definition ast.h:614
Scopes(AST &ast)
Definition bind.cpp:23
void pop_barrier(Barrier old)
Definition bind.cpp:52
Scope & top()
Definition bind.cpp:31
void pop_mod()
Definition bind.cpp:66
AST & ast() const
Definition bind.cpp:29
const Decl * dummy() const
Definition bind.cpp:32
const Decl * top_decl() const
Definition bind.cpp:62
Sym enclosing_mod() const
Definition bind.cpp:68
auto enter_top_decl(const Decl *decl)
Definition bind.cpp:63
const Decl * find(Dbg dbg, bool quiet=false)
Definition bind.cpp:71
void push(Scope &scope)
Definition bind.cpp:35
const Decl * find_shadowed_module(Sym sym)
Diagnostic-only: is a module named sym reachable, shadowed by whatever find would actually return?
Definition bind.cpp:93
void push()
Definition bind.cpp:34
void bind(Dbg dbg, const Decl *decl, Vis vis, bool rebind=false, bool quiet=false)
Binds decl under dbg with an explicit vis - a splice re-exports under its own visibility.
Definition bind.cpp:104
void bind(Dbg dbg, const Decl *decl, bool rebind=false, bool quiet=false)
Definition bind.cpp:99
void push_mod(Sym name)
Definition bind.cpp:65
size_t mod_depth() const
Definition bind.cpp:67
Barrier push_barrier(Scope &scope)
A file must not see the scope of whoever imports it, so its Scope becomes the new lookup floor.
Definition bind.cpp:47
Error & error() const
Definition bind.cpp:30
const Expr * body() const
Definition ast.h:956
const IdDecl * index() const
Definition ast.h:954
void bind(Scopes &) const override
Definition bind.cpp:329
const Expr * shape() const
Definition ast.h:955
Wraps a TuplePtrn as Expr.
Definition ast.h:905
const TuplePtrn * ptrn() const
Definition ast.h:911
void bind(Scopes &) const override
Definition bind.cpp:318
void bind(Scopes &) const override
Definition bind.cpp:337
const Expr * body() const
Definition ast.h:979
auto elems() const
Definition ast.h:932
const Expr * elem(size_t i) const
Definition ast.h:933
void bind(Scopes &) const override
Definition bind.cpp:324
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:186
const Ptrn * ptrn(size_t i) const
Definition ast.h:438
auto ptrns() const
Definition ast.h:437
const Expr * level() const
Definition ast.h:596
Dbg dbg() const override
The name this decl introduces; anonymous if it splices instead.
Definition ast.h:1031
UseDecl(Loc loc, Mods mods, Ptr< Path > path, Dbg alias)
use path [as alias|*];; no alias means as *.
Definition ast.h:1003
bool is_splice() const
as *: splice the module's public members, bind no name.
Definition ast.h:1028
void bind(Scopes &) const override
Definition bind.cpp:626
const File * file() const
Definition ast.h:1027
Vis vis() const override
A ValDecl's own Vis; Pub for anything else (Ptrn, Import, ...), which the priv/pub system ignores.
Definition ast.h:300
bool is_anx() const override
Whether this decl is registered as a compiler-exposed annex (anx).
Definition ast.h:302
| ctor_0: type_0 | ... | ctor_n-1: type_n-1; a constructor without a type carries [].
Definition ast.h:742
auto ctors() const
Definition ast.h:767
const Ctor * ctor(size_t i) const
Definition ast.h:768
void bind(Scopes &) const override
Definition bind.cpp:276
Families of Tok::Tag as reusable case labels; include this in *.cpp files only.
#define C_DS
Direct-style binders; all other binders are CPS.
Definition family.h:86
#define C_LIT_TYPED
Literals that already determine their type and hence must not be ascribed one.
Definition family.h:55
#define ISA(tag, family)
Turns such a family into a predicate - a case label is of no use outside of a switch.
Definition family.h:138
#define C_CN
Binders whose domain binds as tight as a Cn, i.e. no codomain follows.
Definition family.h:91
Definition ast.h:16
fe::SymMap< Bind > Scope
Maps a name to the Binding introducing it.
Definition ast.h:51
static void add_names(AnnexInfo &annex, const Expr *type)
Records the constructor or field names that type - the body of an annex declaration - spells out.
Definition bind.cpp:348
Vis
Visibility tier of a ValDecl.
Definition ast.h:42
fe::Arena::Ref< const T > Ptr
Nodes live in the AST's Arena and are never destroyed, so this merely points at one.
Definition ast.h:27
static Sym loc2plugin(AST &ast, Loc loc)
Definition bind.cpp:343
static void add_alias(AnnexInfo *annex, sub_t sub, Sym target, Sym alias)
Registers alias as a further name of the annex slot target introduced.
Definition bind.cpp:403
Tok::Tag Tag
Definition bind.cpp:11
One name in a Scope: the Decl it introduces and the Vis of this binding.
Definition ast.h:46
u8 sub_t
Definition types.h:42
u8 tag_t
Definition types.h:41
static std::optional< plugin_t > mangle(std::string_view plugin)
Mangles s into a dense 48-bit representation.
Definition plugin.cpp:9
Bookkeeping of an annex introduced by an AxmDecl.
Definition ast.h:72
fe::Vector< Sym > names
The constructor or field names its variant or sigma declares, by index; an unnamed field is the empty...
Definition ast.h:99
bool fields
Are AnnexInfo::names the fields of a sigma rather than the constructors of a variant?
Definition ast.h:100
fe::Vector< fe::Vector< Sym > > subs
List of subs which is a list of aliases.
Definition ast.h:97