MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
bind.cpp
Go to the documentation of this file.
1#include "mim/ast/ast.h"
2
3#include "family.h"
4
5using namespace std::literals;
6
7namespace mim::ast {
8
9using Tag = Tok::Tag;
10
11class DummyDecl : public Decl {
12public:
14 : Decl(Loc()) {}
15
16 void stream(fe::Tab&, std::ostream& os) const final { os << "<dummy>"; }
17};
18
19class Scopes {
20public:
22 : ast_(ast)
23 , dummy_(ast.ptr<DummyDecl>()) {
24 push(); // root scope
25 }
26
27 AST& ast() const { return ast_; }
28 Error& error() const { return ast().error(); }
29 Scope& top() { return scopes_.back().scope(); }
30 const Decl* dummy() const { return dummy_.get(); }
31
32 void push() { scopes_.emplace_back(); }
33 void push(Scope& scope) { scopes_.emplace_back(scope); }
34
35 void pop() {
36 assert(scopes_.size() > barrier_);
37 scopes_.pop_back();
38 }
39
40 /// A file must not see the scope of whoever imports it, so its Scope becomes the new lookup floor.
41 size_t push_barrier(Scope& scope) {
42 push(scope);
43 auto old = std::exchange(barrier_, scopes_.size() - 1);
44 mod_stack_.clear();
45 return old;
46 }
47
48 void pop_barrier(size_t old) {
49 barrier_ = old;
50 pop();
51 }
52
53 /// @name Annex nesting
54 /// Tracked by ModDecl::bind so AST::name2annex can derive `tag`/`sub` from lexical nesting.
55 ///@{
56 void push_mod(Sym name) { mod_stack_.emplace_back(name); }
57 void pop_mod() { mod_stack_.pop_back(); }
58 size_t mod_depth() const { return mod_stack_.size(); }
59 Sym enclosing_mod() const { return mod_stack_.empty() ? Sym() : mod_stack_.back(); }
60 ///@}
61
62 const Decl* find(Dbg dbg, bool quiet = false) {
63 // `_` never enters a Scope, so it cannot be planted as a dummy; the recorded error keeps emit from running.
64 if (dbg.is_anon()) {
65 if (!quiet) error().e(dbg.loc(), "`_` never binds an entity and cannot be referenced");
66 return nullptr;
67 }
68
69 for (auto& frame : scopes_ | std::views::drop(barrier_) | std::views::reverse)
70 if (auto bind = fe::lookup(frame.scope(), dbg.sym())) return bind->decl;
71
72 if (!quiet) {
73 auto& diag = error().e(dbg.loc(), "identifier `{}` not found", dbg.sym());
74 // An infix operator only exists as whatever the user bound its escaped name to.
75 if (dbg.sym().view().starts_with('`'))
76 diag.n("an infix operator means whatever you bind its escaped name to");
77 bind(dbg, dummy()); // put into scope to prevent further errors
78 }
79 return nullptr;
80 }
81
82 /// Diagnostic-only: is a module named @p sym reachable, shadowed by whatever `find` would actually return?
83 /// Only `ModDecl`/`Import` ever yield a non-null Decl::scope, so this never confuses a value for a module.
84 const Decl* find_shadowed_module(Sym sym) {
85 for (auto& frame : scopes_ | std::views::drop(barrier_) | std::views::reverse)
86 if (auto bind = fe::lookup(frame.scope(), sym); bind && bind->decl->scope()) return bind->decl;
87 return nullptr;
88 }
89
90 void bind(Dbg dbg, const Decl* decl, bool rebind = false, bool quiet = false) {
91 bind(dbg, decl, decl->vis(), rebind, quiet);
92 }
93
94 /// Binds @p decl under @p dbg with an explicit @p vis - a splice re-exports under its own visibility.
95 void bind(Dbg dbg, const Decl* decl, Vis vis, bool rebind = false, bool quiet = false) {
96 if (dbg.is_anon()) return;
97
98 auto& scope = top();
99 if (rebind) {
100 scope[dbg.sym()] = Bind{decl, vis};
101 } else if (auto [i, ins] = scope.try_emplace(dbg.sym(), Bind{decl, vis}); !ins) {
102 auto prev = i->second.decl;
103 if (!quiet && !prev->isa<DummyDecl>()) // if prev stems from an error - don't complain
104 error().e(dbg.loc(), "redeclaration of `{}`", dbg).n(prev->dbg().loc(), "previous declaration here");
105 } else if (!quiet && !decl->scope()) {
106 if (auto mod = find_shadowed_module(dbg.sym()))
107 error()
108 .w(dbg.loc(), "`{}` shadows a module of the same name", dbg)
109 .n(mod->dbg().loc(), "module declared here; a later `{}.member` would fail to resolve it",
110 dbg.sym());
111 }
112 }
113
114private:
115 /// Owns the Scope of an anonymous binder; a File's or ModDecl's Scope outlives Scopes and is borrowed.
116 class Frame {
117 public:
118 Frame() = default;
119 Frame(Scope& scope)
120 : borrowed_(&scope) {}
121
122 Scope& scope() { return borrowed_ ? *borrowed_ : own_; }
123
124 private:
125 Scope own_;
126 Scope* borrowed_ = nullptr;
127 };
128
129 AST& ast_;
130 Ptr<DummyDecl> dummy_;
131 fe::Vector<Frame> scopes_;
132 size_t barrier_ = 0;
133 fe::Vector<Sym> mod_stack_;
134};
135
136/*
137 * File
138 */
139
140void File::bind(AST& ast) const {
141 auto scopes = Scopes(ast);
142 bind(scopes);
143}
144
145void File::bind(Scopes& s) const {
146 if (bound_) return;
147 bound_ = true;
148
149 auto barrier = s.push_barrier(members());
150 for (auto import : implicit_imports())
151 import->bind(s);
152 bind_decls(s);
153 s.pop_barrier(barrier);
154}
155
156/*
157 * Ptrn
158 */
159
160void ErrorPtrn::bind(Scopes&, bool, bool) const {}
161void GrpPtrn::bind(Scopes& s, bool rebind, bool quiet) const { s.bind(dbg(), this, rebind, quiet); }
162
163void IdPtrn::bind(Scopes& s, bool rebind, bool quiet) const {
164 if (!quiet && type()) type()->bind(s);
165 s.bind(dbg(), this, rebind, quiet);
166}
167
168void AliasPtrn::bind(Scopes& s, bool rebind, bool quiet) const {
169 ptrn()->bind(s, rebind, quiet);
170 s.bind(dbg(), this, rebind, quiet);
171}
172
173void TuplePtrn::bind(Scopes& s, bool rebind, bool quiet) const {
174 for (auto ptrn : ptrns())
175 ptrn->bind(s, rebind, quiet);
176}
177
178/*
179 * Expr
180 */
181
182void Path::bind(Scopes& s, bool quiet) const {
183 decl_ = s.find(front(), quiet);
184 auto prev = front();
185
186 for (auto dbg : dbgs() | std::views::drop(1)) {
187 if (!decl_) return;
188 auto scope = decl_->scope();
189 auto member = scope ? fe::lookup(*scope, dbg.sym()) : nullptr;
190 if (!member) {
191 if (!quiet) {
192 if (scope) {
193 s.error().e(dbg.loc(), "`{}` has no member `{}`", prev.sym(), dbg.sym());
194 } else {
195 auto& err = s.error().e(prev.loc(), "`{}` is not a module", prev.sym());
196 if (auto mod = s.find_shadowed_module(prev.sym()))
197 err.n(mod->dbg().loc(), "a module `{}` exists here but is shadowed by the `{}` in scope",
198 prev.sym(), prev.sym());
199 }
200 }
201 decl_ = nullptr;
202 return;
203 }
204 decl_ = member->decl;
205 prev = dbg;
206
207 // A dotted path always crosses into decl_'s enclosing mod from outside: `priv` blocks it.
208 if (member->vis == Vis::Priv) {
209 if (!quiet) s.error().e(dbg.loc(), "`{}` is private to its enclosing `mod`", dbg.sym());
210 decl_ = nullptr;
211 return;
212 }
213 }
214}
215
216// clang-format off
217void PathExpr ::bind(Scopes& s) const { path()->bind(s); }
218void TypeExpr ::bind(Scopes& s) const { level()->bind(s); }
219void RuleExpr ::bind(Scopes& s) const { dom()->bind(s); }
220void ErrorExpr ::bind(Scopes&) const {}
221void HoleExpr ::bind(Scopes&) const {}
223// clang-format on
224
225void LitExpr::bind(Scopes& s) const {
226 if (type()) {
227 type()->bind(s);
228 if (ISA(tag(), C_LIT_TYPED)) s.error().e(type()->loc(), "a `{}` must not have a type annotation", tag());
229 } else {
230 if (tag() == Tag::L_f) s.error().e(loc(), "floating-point literal requires a type annotation");
231 }
232}
233
234void DeclExpr::bind(Scopes& s) const {
235 if (is_where())
236 for (auto decl : decls() | std::views::reverse)
237 decl->bind(s);
238 else
239 for (auto decl : decls())
240 decl->bind(s);
241 expr()->bind(s);
242}
243
244void InfixExpr::bind(Scopes& s) const {
245 if (callee()) callee()->bind(s);
246 lhs()->bind(s);
247 // `t#x` may name a field of `t`'s Sigma rather than anything in scope; InfixExpr::emit_ resolves that.
248 if (auto path = op().isa(Tag::T_extract) ? rhs()->isa<PathExpr>() : nullptr)
249 path->path()->bind(s, true);
250 else
251 rhs()->bind(s);
252}
253
255 s.push();
256 ptrn()->bind(s, false, false);
257 body()->bind(s);
258 s.pop();
259}
260
261void MatchExpr::bind(Scopes& s) const {
262 scrutinee()->bind(s);
263 for (auto arm : arms())
264 arm->bind(s);
265}
266
267void PiExpr::Dom::bind(Scopes& s, bool quiet) const {
268 ptrn()->bind(s, false, quiet);
269 if (ret()) ret()->bind(s, false, quiet);
270}
271
272void PiExpr::bind(Scopes& s) const {
273 s.push();
274 dom()->bind(s);
275 if (codom()) {
276 if (ISA(tag(), C_CN)) s.error().e(codom()->loc(), "a continuation must not have a codomain");
277 codom()->bind(s);
278 }
279 s.pop();
280}
281
282void LamExpr::bind(Scopes& s) const {
283 lam()->bind_decl(s);
284 lam()->bind_body(s);
285}
286
287void AppExpr::bind(Scopes& s) const {
288 callee()->bind(s);
289 arg()->bind(s);
290}
291
292void RetExpr::bind(Scopes& s) const {
293 callee()->bind(s);
294 arg()->bind(s);
295 ptrn()->bind(s, true, false);
296 body()->bind(s);
297}
298
299void SigmaExpr::bind(Scopes& s) const {
300 s.push();
301 ptrn()->bind(s, false, false);
302 s.pop();
303}
304
305void TupleExpr::bind(Scopes& s) const {
306 for (auto elem : elems())
307 elem->bind(s);
308}
309
310void SeqExpr::bind(Scopes& s) const {
311 s.push();
312 arity()->bind(s, false, false);
313 body()->bind(s);
314 s.pop();
315}
316
317void UniqExpr::bind(Scopes& s) const { inhabitant()->bind(s); }
318
319/*
320 * Decl
321 */
322
323AnnexInfo* AST::name2annex(Scopes& s, Dbg dbg, sub_t* sub_id) {
324 if (!dbg) return nullptr;
325
326 auto depth = s.mod_depth();
327 if (depth > 1) {
328 error().e(dbg.loc(), "`{}` sits {} `mod` levels deep; an `anx` declaration may nest at most one", dbg, depth);
329 return nullptr;
330 }
331
332 auto plugin_s = dbg.loc().src ? sym(fs::path(dbg.loc().src->path()).stem().string()) : sym_error();
333 auto tag_s = depth == 0 ? dbg.sym() : s.enclosing_mod();
334 Sym sub_s = depth == 0 ? Sym() : dbg.sym();
335
336 auto& sym2annex = plugin2sym2annex_[plugin_s];
337 auto tag_id = sym2annex.size();
338
339 if (plugin_s == sym_error()) error().e(dbg.loc(), "plugin name `{}` is reserved", dbg);
340 if (tag_id > std::numeric_limits<tag_t>::max())
341 error().e(dbg.loc(), "exceeded maximum number of annexes in current plugin");
342
343 if (!Annex::mangle(plugin_s)) {
344 error().e(dbg.loc(), "invalid annex name `{}`", dbg);
345 plugin_s = sym_error();
346 }
347
348 auto [i, fresh] = sym2annex.try_emplace(tag_s, AnnexInfo{plugin_s, tag_s, (tag_t)tag_id});
349 auto annex = &i->second;
350
351 if (sub_s) {
352 if (sub_id) {
353 *sub_id = annex->subs.size();
354 auto& aliases = annex->subs.emplace_back();
355 aliases.emplace_back(sub_s);
356 } else {
357 error().e(dbg.loc(), "annex `{}` must not have a subtag", dbg);
358 }
359 }
360
361 if (!fresh) annex->fresh = false;
362 return annex;
363}
364
365void AxmDecl::bind(Scopes& s) const {
366 type()->bind(s);
367
368 annex_ = s.ast().name2annex(s, dbg(), &sub_);
369
370 if (annex_ && annex_->fresh) {
371 annex_->normalizer = normalizer();
372 annex_->pi = type()->isa<PiExpr>() || InfixExpr::isa_op(Tag::T_arrow_r, type());
373 } else if (annex_) {
374 auto pi = type()->isa<PiExpr>() || InfixExpr::isa_op(Tag::T_arrow_r, type());
375 if (pi ^ *annex_->pi)
376 s.error().e(dbg().loc(),
377 "all declarations of annex `{}` must be function types if one of them is (they share one "
378 "annex tag - via mod-nesting or a `tag.(...)` family - and must agree in shape)",
379 dbg().sym());
380
381 if (annex_->normalizer.sym() != normalizer().sym()) {
382 auto l = normalizer().loc() ? normalizer().loc() : loc().anew_end();
383 auto& err = s.error().e(l, "normalizer mismatch for axm `{}`", dbg());
384 if (auto norm = annex_->normalizer)
385 err.n(norm.loc(), "previous normalizer `{}` declared here", norm);
386 else
387 err.n("initially no normalizer was specified");
388 }
389 }
390
391 s.bind(dbg(), this);
392}
393
395 annex_ = s.ast().name2annex(s, dbg(), &sub_);
396 s.bind(dbg(), this);
397}
398
399void AliasDecl::bind(Scopes& s) const {
400 path()->bind(s);
401 s.bind(dbg(), this);
402
403 auto target = path()->decl();
404 if (!target) return;
405
406 if (target->isa<AliasDecl>()) {
407 s.error().e(loc(), "`{}` aliases `{}`, which is itself an alias; alias chains are not supported", dbg(),
408 path()->back());
409 return;
410 }
411
412 std::tie(annex_, sub_) = target->annex_sub();
413 if (!annex_) {
414 s.error().e(loc(), "`{}` must alias a compiler-exposed (`anx`) declaration", dbg());
415 return;
416 }
417
418 // An ungrouped target (the common case) never allocated its own sub-group; seed one now,
419 // named after the target itself, so this alias has a slot to share.
420 if (sub_ >= annex_->subs.size()) {
421 assert(sub_ == annex_->subs.size());
422 annex_->subs.emplace_back(fe::Vector<Sym>{target->dbg().sym()});
423 }
424 annex_->subs[sub_].emplace_back(dbg().sym());
425}
426
427void LetDecl::bind(Scopes& s) const {
428 s.push();
429 value()->bind(s);
430 s.pop();
431
432 auto id = ptrn()->isa<IdPtrn>();
433 // Scopes::bind snapshots Decl::vis, so mirror it onto the Ptrn *before* the Ptrn enters a Scope.
434 if (id) {
435 id->vis_ = vis();
436 id->anx_ = is_anx();
437 }
438 ptrn()->bind(s, true, false);
439 if (id && is_anx()) id->annex_ = s.ast().name2annex(s, id->dbg(), &id->sub_);
440}
441
442void RecDecl::bind(Scopes& s) const {
443 for (auto curr = this; curr; curr = curr->next())
444 curr->bind_decl(s);
445 for (auto curr = this; curr; curr = curr->next())
446 curr->bind_body(s);
447}
448
450 if (!body()->isa<PiExpr>() && !InfixExpr::isa_op(Tag::T_arrow_r, body()) && !body()->isa<SigmaExpr>())
451 s.error()
452 .e(body()->loc(), "unsupported expression in a recursive declaration")
453 .n("must be a sigma or a function type; use `lam`/`con`/`fun` to declare a recursive function");
454
455 s.bind(dbg(), this);
456 if (is_anx()) annex_ = s.ast().name2annex(s, dbg(), &sub_);
457}
458
459void RecDecl::bind_body(Scopes& s) const { body()->bind(s); }
460
461void LamDecl::Dom::bind(Scopes& s, bool quiet) const {
462 PiExpr::Dom::bind(s, quiet);
463 if (filter() && !quiet) filter()->bind(s);
464}
465
467 s.push();
468 for (size_t i = 0, e = num_doms(); i != e; ++i)
469 dom(i)->bind(s);
470
471 if (auto filter = doms().back()->filter()) {
472 if (auto pe = filter->isa<PrimaryExpr>()) {
473 if (pe->tag() == Tag::K_tt && ISA(tag(), C_DS))
474 s.error().w(filter->loc(),
475 "`tt`-filter superfluous as the last curried function group of a `{}` receives a "
476 "`tt`-filter by default",
477 tag());
478 if (pe->tag() == Tag::K_ff && !ISA(tag(), C_DS))
479 s.error().w(filter->loc(),
480 "`ff`-filter superfluous as the last curried function group of a `{}` receives a "
481 "`ff`-filter by default",
482 tag());
483 }
484 }
485
486 if (codom()) {
487 if (ISA(tag(), C_CN)) s.error().e(codom()->loc(), "a continuation must not have a codomain");
488 codom()->bind(s);
489 }
490
491 s.pop();
492 s.bind(dbg(), this);
493 if (is_anx()) annex_ = s.ast().name2annex(s, dbg(), &sub_);
494}
495
497 s.push();
498 for (auto dom : doms())
499 dom->bind(s, true);
500 if (body()) body()->bind(s);
501 s.pop();
502}
503
505 for (auto decl : decls())
506 decl->bind(s);
507}
508
509void ModDecl::bind(Scopes& s) const {
510 s.push(members());
511 s.push_mod(dbg().sym());
512 bind_decls(s);
513 s.pop_mod();
514 s.pop();
515 s.bind(dbg(), this);
516}
517
518const Scope* UseDecl::module(Scopes& s) const {
519 if (is_import()) {
520 if (!file()) return nullptr;
521 file()->bind(s);
522 return file()->scope();
523 }
524
525 path()->bind(s);
526 auto decl = path()->decl();
527 if (!decl) return nullptr;
528
529 auto scope = decl->scope();
530 if (!scope) s.error().e(path()->loc(), "`{}` is not a module", path()->back().sym());
531 return scope;
532}
533
534void UseDecl::bind(Scopes& s) const {
535 auto mod = module(s);
536 if (!mod) return;
537
538 if (is_splice()) {
539 // Quiet: a name already bound here wins, so a splice never shadows and never conflicts.
540 for (const auto& [sym, binding] : *mod)
541 if (binding.vis == Vis::Pub) s.bind(Dbg(loc(), sym), binding.decl, vis(), false, true);
542 return;
543 }
544
545 // The same file may be imported more than once - as `-p foo` plus a `plugin foo;` directive, say.
546 if (file())
547 if (auto prev = s.find(dbg(), true))
548 if (auto use = prev->isa<UseDecl>(); use && use->file() == file()) return;
549
550 scope_ = mod;
551 s.bind(dbg(), this);
552}
553
554void RuleDecl::bind(Scopes& s) const {
555 s.push();
556 var()->bind(s, true, false);
557 lhs()->bind(s);
558 rhs()->bind(s);
559 guard()->bind(s);
560 s.pop();
561 s.bind(dbg(), this);
562}
563
564} // namespace mim::ast
Owns the arena all AST nodes live in as well as the AnnexInfos of all plugins.
Definition ast.h:99
Error & error() const
Definition ast.h:110
Sym sym(const char *s)
Definition ast.h:115
AnnexInfo * name2annex(Scopes &s, Dbg dbg, sub_t *sub_id)
Definition bind.cpp:323
Sym sym_error()
"_error_".
Definition ast.h:120
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1121
void bind(Scopes &) const override
Definition bind.cpp:399
const Path * path() const
Definition ast.h:1122
AliasDecl(Loc loc, Vis vis, Dbg dbg, Ptr< Path > path)
Definition ast.h:1116
const Ptrn * ptrn() const
Definition ast.h:375
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:376
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:168
void bind(Scopes &) const override
Definition bind.cpp:287
const Expr * arg() const
Definition ast.h:763
const Expr * callee() const
Definition ast.h:762
void bind(Scopes &) const override
Definition bind.cpp:394
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:977
const Expr * type() const
Definition ast.h:1001
void bind(Scopes &) const override
Definition bind.cpp:365
Dbg normalizer() const
Definition ast.h:1002
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1000
const Expr * expr() const
Definition ast.h:543
auto decls() const
Definition ast.h:541
void bind(Scopes &) const override
Definition bind.cpp:234
bool is_where() const
Definition ast.h:542
Base class of all declarations; caches the emitted Decl::def.
Definition ast.h:230
Decl(Loc loc)
Definition ast.h:232
virtual Vis vis() const
A ValDecl's own Vis; Pub for anything else (Ptrn, Import, ...), which the priv/pub system ignores.
Definition ast.h:245
virtual const Scope * scope() const
Non-nullptr if this Decl is a module whose members a Path may walk into.
Definition ast.h:241
void stream(fe::Tab &, std::ostream &os) const final
Definition bind.cpp:16
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:160
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:1210
void bind(AST &) const
Definition bind.cpp:140
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:161
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:354
dbg: type
Definition ast.h:311
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:163
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:318
const Expr * type() const
Definition ast.h:319
void bind(Scopes &) const override
Definition bind.cpp:244
static const InfixExpr * isa_op(Tok::Tag tag, const Expr *expr)
Definition ast.h:610
const Expr * callee() const
Definition ast.h:607
const Expr * rhs() const
Definition ast.h:606
const Expr * lhs() const
Definition ast.h:604
Tok op() const
Definition ast.h:605
const Expr * filter() const
Definition ast.h:1069
void bind(Scopes &, bool quiet=false) const override
Definition bind.cpp:461
Tok::Tag tag() const
Definition ast.h:1089
void bind_body(Scopes &) const override
Definition bind.cpp:496
auto doms() const
Definition ast.h:1092
const Expr * codom() const
Definition ast.h:1095
size_t num_doms() const
Definition ast.h:1094
void bind_decl(Scopes &) const override
Definition bind.cpp:466
const Dom * dom(size_t i) const
Definition ast.h:1093
void bind(Scopes &) const override
Definition bind.cpp:282
const LamDecl * lam() const
Definition ast.h:741
void bind(Scopes &) const override
Definition bind.cpp:427
const Expr * value() const
Definition ast.h:953
const Ptrn * ptrn() const
Definition ast.h:952
const Expr * type() const
Definition ast.h:519
Tok::Tag tag() const
Definition ast.h:518
void bind(Scopes &) const override
Definition bind.cpp:225
const Expr * body() const
Definition ast.h:645
virtual void bind(Scopes &) const
Definition bind.cpp:254
const Ptrn * ptrn() const
Definition ast.h:644
auto arms() const
Definition ast.h:663
void bind(Scopes &) const override
Definition bind.cpp:261
const Expr * scrutinee() const
Definition ast.h:662
const Arm * arm(size_t i) const
Definition ast.h:664
void bind_decls(Scopes &) const
Definition bind.cpp:504
void bind(Scopes &) const override
Definition bind.cpp:509
Scope & members() const
Definition ast.h:1188
auto decls() const
Definition ast.h:1180
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1179
Loc loc() const
Definition ast.h:197
const Path * path() const
Definition ast.h:476
auto dbgs() const
Definition ast.h:457
void bind(Scopes &, bool quiet=false) const
Definition bind.cpp:182
Dbg front() const
Definition ast.h:458
virtual void bind(Scopes &, bool quiet=false) const
Definition bind.cpp:267
const IdPtrn * ret() const
Definition ast.h:690
const Ptrn * ptrn() const
Definition ast.h:689
dom → codom, Cn dom, or Fn dom → codom depending on PiExpr::tag.
Definition ast.h:679
void bind(Scopes &) const override
Definition bind.cpp:272
void bind(Scopes &) const override
Definition bind.cpp:222
virtual void bind(Scopes &, bool rebind, bool quiet) const =0
virtual void bind_body(Scopes &) const
Definition bind.cpp:459
virtual void bind_decl(Scopes &) const
Definition bind.cpp:449
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1031
const Expr * body() const
Definition ast.h:1032
void bind(Scopes &) const override
Definition bind.cpp:442
const Ptrn * ptrn() const
Definition ast.h:785
const Expr * arg() const
Definition ast.h:787
void bind(Scopes &) const override
Definition bind.cpp:292
const Expr * body() const
Definition ast.h:788
const Expr * callee() const
Definition ast.h:786
void bind(Scopes &) const override
Definition bind.cpp:554
const Ptrn * var() const
Definition ast.h:1149
const Expr * guard() const
Definition ast.h:1152
const Expr * rhs() const
Definition ast.h:1151
const Expr * lhs() const
Definition ast.h:1150
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1148
const Expr * dom() const
Definition ast.h:580
Scopes(AST &ast)
Definition bind.cpp:21
Scope & top()
Definition bind.cpp:29
void pop_mod()
Definition bind.cpp:57
AST & ast() const
Definition bind.cpp:27
const Decl * dummy() const
Definition bind.cpp:30
Sym enclosing_mod() const
Definition bind.cpp:59
const Decl * find(Dbg dbg, bool quiet=false)
Definition bind.cpp:62
void push(Scope &scope)
Definition bind.cpp:33
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:84
void push()
Definition bind.cpp:32
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:95
void bind(Dbg dbg, const Decl *decl, bool rebind=false, bool quiet=false)
Definition bind.cpp:90
void push_mod(Sym name)
Definition bind.cpp:56
size_t 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:41
void pop_barrier(size_t old)
Definition bind.cpp:48
size_t mod_depth() const
Definition bind.cpp:58
Error & error() const
Definition bind.cpp:28
const Expr * body() const
Definition ast.h:853
const IdPtrn * arity() const
Definition ast.h:852
void bind(Scopes &) const override
Definition bind.cpp:310
const TuplePtrn * ptrn() const
Definition ast.h:810
void bind(Scopes &) const override
Definition bind.cpp:299
auto elems() const
Definition ast.h:831
const Expr * elem(size_t i) const
Definition ast.h:832
void bind(Scopes &) const override
Definition bind.cpp:305
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:173
const Ptrn * ptrn(size_t i) const
Definition ast.h:405
auto ptrns() const
Definition ast.h:404
const Expr * level() const
Definition ast.h:562
const Expr * inhabitant() const
Definition ast.h:873
void bind(Scopes &) const override
Definition bind.cpp:317
Dbg dbg() const override
The name this decl introduces; anonymous if it splices instead.
Definition ast.h:924
UseDecl(Loc loc, Mods mods, Ptr< Path > path, Dbg alias)
use path [as alias|*];; no alias means as *.
Definition ast.h:896
bool is_splice() const
as *: splice the module's public members, bind no name.
Definition ast.h:921
void bind(Scopes &) const override
Definition bind.cpp:534
const File * file() const
Definition ast.h:920
Vis vis() const override
A ValDecl's own Vis; Pub for anything else (Ptrn, Import, ...), which the priv/pub system ignores.
Definition ast.h:263
bool is_anx() const override
Whether this decl is registered as a compiler-exposed annex (anx).
Definition ast.h:265
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:84
#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:142
#define C_CN
Binders whose domain binds as tight as a Cn, i.e. no codomain follows.
Definition family.h:89
Definition ast.h:16
fe::SymMap< Bind > Scope
Maps a name to the Binding introducing it.
Definition ast.h:50
Vis
Visibility tier of a ValDecl.
Definition ast.h:41
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:26
Tok::Tag Tag
Definition bind.cpp:9
One name in a Scope: the Decl it introduces and the Vis of this binding.
Definition ast.h:45
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:5
Bookkeeping of an annex introduced by an AxmDecl.
Definition ast.h:66