MimIR 0.1
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
3using namespace std::literals;
4
5namespace mim::ast {
6
7using Tag = Tok::Tag;
8
9class DummyDecl : public Decl {
10public:
12 : Decl(Loc()) {}
13
14 std::ostream& stream(Tab&, std::ostream& os) const final { return os << "<dummy>"; }
15};
16
17class Scopes {
18public:
19 using Scope = fe::SymMap<std::pair<Loc, const Decl*>>;
20
22 : ast_(ast)
23 , dummy_(ast.ptr<DummyDecl>()) {
24 push(); // root scope
25 }
26
27 AST& ast() const { return ast_; }
28 Driver& driver() const { return ast().driver(); }
29 Scope& top() { return scopes_.back(); }
30 const Decl* dummy() const { return dummy_.get(); }
31
32 void push() { scopes_.emplace_back(); }
33
34 void pop() {
35 assert(!scopes_.empty());
36 scopes_.pop_back();
37 }
38
39 const Decl* find(Dbg dbg, bool quiet = false) {
40 if (dbg.is_anon()) return nullptr;
41
42 for (auto& scope : scopes_ | std::ranges::views::reverse)
43 if (auto i = scope.find(dbg.sym()); i != scope.end()) return i->second.second;
44
45 if (!quiet) {
46 ast().error(dbg.loc(), "'{}' not found", dbg.sym());
47 bind(dbg, dummy()); // put into scope to prevent further errors
48 }
49 return nullptr;
50 }
51
52 void bind(Dbg dbg, const Decl* decl, bool rebind = false, bool quiet = false) {
53 if (dbg.is_anon()) return;
54
55 if (rebind) {
56 top()[dbg.sym()] = std::pair(dbg.loc(), decl);
57 } else if (auto [i, ins] = top().try_emplace(dbg.sym(), std::pair(dbg.loc(), decl)); !ins) {
58 auto [prev_loc, prev_decl] = i->second;
59 if (!quiet && !prev_decl->isa<DummyDecl>()) { // if prev_decl stems from an error - don't complain
60 ast().error(dbg.loc(), "redeclaration of '{}'", dbg);
61 ast().note(prev_loc, "previous declaration here");
62 }
63 }
64 }
65
66private:
67 AST& ast_;
68 Ptr<DummyDecl> dummy_;
69 std::deque<Scope> scopes_;
70 absl::flat_hash_map<plugin_t, tag_t> plugin2tag_;
71};
72
73/*
74 * Module
75 */
76
77void Module::bind(AST& ast) const {
78 auto scopes = Scopes(ast);
79 bind(scopes);
80}
81
82void Module::bind(Scopes& s) const {
83 for (const auto& import : implicit_imports())
84 import->bind(s);
85 for (const auto& import : imports())
86 import->bind(s);
87 for (const auto& decl : decls())
88 decl->bind(s);
89}
90
91void Import::bind(Scopes& s) const { module()->bind(s); }
92
93/*
94 * Ptrn
95 */
96
97void ErrorPtrn::bind(Scopes&, bool, bool) const {}
98void GrpPtrn::bind(Scopes& s, bool rebind, bool quiet) const { s.bind(dbg(), this, rebind, quiet); }
99
100void IdPtrn::bind(Scopes& s, bool rebind, bool quiet) const {
101 if (!quiet && type()) type()->bind(s);
102 s.bind(dbg(), this, rebind, quiet);
103}
104
105void AliasPtrn::bind(Scopes& s, bool rebind, bool quiet) const {
106 ptrn()->bind(s, rebind, quiet);
107 s.bind(dbg(), this, rebind, quiet);
108}
109
110void TuplePtrn::bind(Scopes& s, bool rebind, bool quiet) const {
111 for (const auto& ptrn : ptrns())
112 ptrn->bind(s, rebind, quiet);
113}
114
115/*
116 * Expr
117 */
118
119// clang-format off
120void IdExpr ::bind(Scopes& s) const { decl_ = s.find(dbg()); }
121void TypeExpr ::bind(Scopes& s) const { level()->bind(s); }
122void RuleExpr ::bind(Scopes& s) const { meta_type()->bind(s); }
123void ErrorExpr ::bind(Scopes&) const {}
124void HoleExpr ::bind(Scopes&) const {}
126// clang-format on
127
128void LitExpr::bind(Scopes& s) const {
129 if (type()) {
130 type()->bind(s);
131 if (tag() == Tag::L_str || tag() == Tag::L_c || tag() == Tag::L_i)
132 s.ast().error(type()->loc(), "a {} shall not have a type annotation", tag());
133 } else {
134 if (tag() == Tag::L_f) s.ast().error(loc(), "type annotation mandatory for floating point literal");
135 }
136}
137
138void DeclExpr::bind(Scopes& s) const {
139 if (is_where())
140 for (const auto& decl : decls() | std::ranges::views::reverse)
141 decl->bind(s);
142 else
143 for (const auto& decl : decls())
144 decl->bind(s);
145 expr()->bind(s);
146}
147
148void ArrowExpr::bind(Scopes& s) const {
149 dom()->bind(s);
150 codom()->bind(s);
151}
152
153void UnionExpr::bind(Scopes& s) const {
154 for (auto& type : types())
155 type->bind(s);
156}
157
158void InjExpr::bind(Scopes& s) const {
159 value()->bind(s);
160 type()->bind(s);
161}
162
164 s.push();
165 ptrn()->bind(s, false, false);
166 body()->bind(s);
167 s.pop();
168}
169
170void MatchExpr::bind(Scopes& s) const {
171 scrutinee()->bind(s);
172 for (const auto& arm : arms())
173 arm->bind(s);
174}
175
176void PiExpr::Dom::bind(Scopes& s, bool quiet) const {
177 ptrn()->bind(s, false, quiet);
178 if (ret()) ret()->bind(s, false, quiet);
179}
180
181void PiExpr::bind(Scopes& s) const {
182 s.push();
183 dom()->bind(s);
184 if (codom()) {
185 if (tag() == Tag::K_Cn) s.ast().error(codom()->loc(), "a continuation shall not have a codomain");
186 codom()->bind(s);
187 }
188 s.pop();
189}
190
191void LamExpr::bind(Scopes& s) const {
192 lam()->bind_decl(s);
193 lam()->bind_body(s);
194}
195
196void AppExpr::bind(Scopes& s) const {
197 callee()->bind(s);
198 arg()->bind(s);
199}
200
201void RetExpr::bind(Scopes& s) const {
202 callee()->bind(s);
203 arg()->bind(s);
204 ptrn()->bind(s, true, false);
205 body()->bind(s);
206}
207
208void SigmaExpr::bind(Scopes& s) const {
209 s.push();
210 ptrn()->bind(s, false, false);
211 s.pop();
212}
213
214void TupleExpr::bind(Scopes& s) const {
215 for (const auto& elem : elems())
216 elem->bind(s);
217}
218
219void SeqExpr::bind(Scopes& s) const {
220 s.push();
221 arity()->bind(s, false, false);
222 body()->bind(s);
223 s.pop();
224}
225
226void ExtractExpr::bind(Scopes& s) const {
227 tuple()->bind(s);
228 if (auto expr = std::get_if<Ptr<Expr>>(&index()))
229 (*expr)->bind(s);
230 else {
231 auto dbg = std::get<Dbg>(index());
232 decl_ = s.find(dbg, true);
233 }
234}
235
236void InsertExpr::bind(Scopes& s) const {
237 tuple()->bind(s);
238 index()->bind(s);
239 value()->bind(s);
240}
241
242void UniqExpr::bind(Scopes& s) const { inhabitant()->bind(s); }
243
244/*
245 * Decl
246 */
247
248void AxmDecl::Alias::bind(Scopes& s, const AxmDecl* axm) const {
249 auto sym = s.ast().sym(axm->dbg().sym().str() + "."s + dbg().sym().str());
250 full_ = Dbg(dbg().loc(), sym);
251 s.bind(full_, this);
252}
253
254void AxmDecl::bind(Scopes& s) const {
255 type()->bind(s);
256
257 annex_ = s.ast().name2annex(dbg(), nullptr);
258
259 if (annex_ && annex_->fresh) {
260 annex_->normalizer = normalizer();
261 annex_->pi = type()->isa<PiExpr>() || type()->isa<ArrowExpr>();
262 } else {
263 auto pi = type()->isa<PiExpr>() || type()->isa<ArrowExpr>();
264 if (annex_ && pi ^ *annex_->pi)
265 s.ast().error(dbg().loc(), "all declarations of annex '{}' have to be function types if any is",
266 dbg().sym());
267
268 if (annex_ && annex_->normalizer.sym() != normalizer().sym()) {
269 auto l = normalizer().loc() ? normalizer().loc() : loc().anew_finis();
270 s.ast().error(l, "normalizer mismatch for axm '{}'", dbg());
271 if (auto norm = annex_->normalizer)
272 s.ast().note(norm.loc(), "previous normalizer '{}'", norm);
273 else
274 s.ast().note(l, "initially no normalizer specified");
275 }
276 }
277
278 if (num_subs() == 0) {
279 s.bind(dbg(), this);
280 } else {
281 if (auto old = s.find(dbg(), true)) {
282 if (auto old_ax = old->isa<AxmDecl>()) {
283 if (old_ax->num_subs() == 0) {
284 s.ast().error(dbg().loc(), "redeclared sub-less axm '{}' with subs", dbg());
285 s.ast().note(old_ax->dbg().loc(), "previous location here");
286 }
287 }
288 }
289
290 if (annex_) {
291 offset_ = annex_->subs.size();
292 for (const auto& aliases : subs())
293 for (const auto& alias : aliases)
294 alias->bind(s, this);
295
296 for (auto& sub : subs()) {
297 auto& aliases = annex_->subs.emplace_back(std::deque<Sym>());
298 for (const auto& alias : sub)
299 aliases.emplace_back(alias->dbg().sym());
300 }
301 }
302 }
303}
304
305void LetDecl::bind(Scopes& s) const {
306 s.push();
307 value()->bind(s);
308 s.pop();
309 ptrn()->bind(s, true, false);
310
311 if (auto id = ptrn()->isa<IdPtrn>()) annex_ = s.ast().name2annex(id->dbg(), &sub_);
312}
313
314void RecDecl::bind(Scopes& s) const {
315 for (auto curr = this; curr; curr = curr->next())
316 curr->bind_decl(s);
317 for (auto curr = this; curr; curr = curr->next())
318 curr->bind_body(s);
319 annex_ = s.ast().name2annex(dbg(), &sub_);
320}
321
323 if (auto t = type()) t->bind(s);
324 if (!type()->isa<HoleExpr>() && body()->isa<LamExpr>())
325 s.ast().warn(type()->loc(), "type of recursive declaration ignored for function expression");
326
327 if (!body()->isa<LamExpr>() && !body()->isa<PiExpr>() && !body()->isa<ArrowExpr>() && !body()->isa<SigmaExpr>())
328 s.ast().error(body()->loc(), "unsupported expression for a recursive declaration");
329
330 s.bind(dbg(), this);
331}
332
333void RecDecl::bind_body(Scopes& s) const { body()->bind(s); }
334
335void LamDecl::Dom::bind(Scopes& s, bool quiet) const {
336 PiExpr::Dom::bind(s, quiet);
337 if (filter() && !quiet) filter()->bind(s);
338}
339
341 s.push();
342 for (size_t i = 0, e = num_doms(); i != e; ++i)
343 dom(i)->bind(s);
344
345 if (auto filter = doms().back()->filter()) {
346 if (auto pe = filter->isa<PrimaryExpr>()) {
347 if (pe->tag() == Tag::K_tt && (tag() == Tag::K_lam || tag() == Tag::T_lm))
348 s.ast().warn(filter->loc(),
349 "'tt'-filter superfluous as the last curried function group of a '{}' receives a "
350 "'tt'-filter by default",
351 tag());
352 if (pe->tag() == Tag::K_ff && (tag() != Tag::K_lam && tag() != Tag::T_lm))
353 s.ast().warn(filter->loc(),
354 "'ff'-filter superfluous as the last curried function group of a '{}' receives a "
355 "'ff'-filter by default",
356 tag());
357 }
358 }
359
360 if (codom()) {
361 if (tag() == Tag::K_con || tag() == Tag::K_cn)
362 s.ast().error(codom()->loc(), "a continuation shall not have a codomain");
363 codom()->bind(s);
364 }
365
366 s.pop();
367 s.bind(dbg(), this);
368 annex_ = s.ast().name2annex(dbg(), &sub_);
369}
370
372 s.push();
373 for (const auto& dom : doms())
374 dom->bind(s, true);
375 body()->bind(s);
376 s.pop();
377}
378
379void CDecl::bind(Scopes& s) const {
380 s.push();
381 dom()->bind(s, false, false);
382 s.pop(); // we don't allow codom to depent on dom
383 if (codom()) codom()->bind(s);
384 s.bind(dbg(), this);
385}
386
387void RuleDecl::bind(Scopes& s) const {
388 s.push();
389 var()->bind(s, true, false);
390 lhs()->bind(s);
391 rhs()->bind(s);
392 guard()->bind(s);
393 s.pop();
394 s.bind(dbg(), this);
395}
396
397} // namespace mim::ast
Some "global" variables needed all over the place.
Definition driver.h:17
Keeps track of indentation level.
Definition print.h:206
Driver & driver()
Definition ast.h:62
Error & note(Loc loc, const char *fmt, Args &&... args) const
Definition ast.h:87
Error & error()
Definition ast.h:63
Dbg dbg() const
Definition ast.h:276
const Ptrn * ptrn() const
Definition ast.h:275
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:105
void bind(Scopes &) const override
Definition bind.cpp:196
const Expr * arg() const
Definition ast.h:672
const Expr * callee() const
Definition ast.h:671
dom -> codom
Definition ast.h:559
void bind(Scopes &) const override
Definition bind.cpp:148
void bind(Scopes &, const AxmDecl *) const
Definition bind.cpp:248
Dbg dbg() const
Definition ast.h:883
friend class AxmDecl
Definition ast.h:892
const auto & subs() const
Definition ast.h:905
const Expr * type() const
Definition ast.h:908
size_t num_subs() const
Definition ast.h:906
AxmDecl(Loc loc, Dbg dbg, std::deque< Ptrs< Alias > > &&subs, Ptr< Expr > &&type, Dbg normalizer, Tok curry, Tok trip)
Definition ast.h:895
void bind(Scopes &) const override
Definition bind.cpp:254
Dbg normalizer() const
Definition ast.h:909
Dbg dbg() const
Definition ast.h:904
const auto & sub(size_t i) const
Definition ast.h:907
const Ptrn * dom() const
Definition ast.h:1041
const Expr * codom() const
Definition ast.h:1042
Dbg dbg() const
Definition ast.h:1039
void bind(Scopes &) const override
Definition bind.cpp:379
const Expr * expr() const
Definition ast.h:420
const auto & decls() const
Definition ast.h:418
void bind(Scopes &) const override
Definition bind.cpp:138
bool is_where() const
Definition ast.h:419
Decl(Loc loc)
Definition ast.h:166
std::ostream & stream(Tab &, std::ostream &os) const final
Definition bind.cpp:14
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:97
virtual void bind(Scopes &) const =0
const auto & index() const
Definition ast.h:792
const Expr * tuple() const
Definition ast.h:791
void bind(Scopes &) const override
Definition bind.cpp:226
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:98
Dbg dbg() const
Definition ast.h:254
Dbg dbg() const
Definition ast.h:354
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:100
Dbg dbg() const
Definition ast.h:224
const Expr * type() const
Definition ast.h:225
void bind(Scopes &) const
Definition bind.cpp:91
const Module * module() const
Definition ast.h:1105
const Expr * type() const
Definition ast.h:500
void bind(Scopes &) const override
Definition bind.cpp:158
const Expr * value() const
Definition ast.h:499
const Expr * index() const
Definition ast.h:816
void bind(Scopes &) const override
Definition bind.cpp:236
const Expr * tuple() const
Definition ast.h:815
const Expr * value() const
Definition ast.h:817
const Expr * filter() const
Definition ast.h:978
void bind(Scopes &, bool quiet=false) const override
Definition bind.cpp:335
Tok::Tag tag() const
Definition ast.h:1007
void bind_body(Scopes &) const override
Definition bind.cpp:371
const Ptrs< Dom > & doms() const
Definition ast.h:1009
const Expr * codom() const
Definition ast.h:1012
size_t num_doms() const
Definition ast.h:1011
void bind_decl(Scopes &) const override
Definition bind.cpp:340
const Dom * dom(size_t i) const
Definition ast.h:1010
void bind(Scopes &) const override
Definition bind.cpp:191
const LamDecl * lam() const
Definition ast.h:648
void bind(Scopes &) const override
Definition bind.cpp:305
const Expr * value() const
Definition ast.h:861
const Ptrn * ptrn() const
Definition ast.h:860
const Expr * type() const
Definition ast.h:397
Tok::Tag tag() const
Definition ast.h:396
void bind(Scopes &) const override
Definition bind.cpp:128
const Expr * body() const
Definition ast.h:525
virtual void bind(Scopes &) const
Definition bind.cpp:163
const Ptrn * ptrn() const
Definition ast.h:524
void bind(Scopes &) const override
Definition bind.cpp:170
const Expr * scrutinee() const
Definition ast.h:541
const Arm * arm(size_t i) const
Definition ast.h:543
const auto & arms() const
Definition ast.h:542
const auto & decls() const
Definition ast.h:1133
const auto & implicit_imports() const
Definition ast.h:1131
void bind(AST &) const
Definition bind.cpp:77
const auto & imports() const
Definition ast.h:1132
Loc loc() const
Definition ast.h:122
virtual void bind(Scopes &, bool quiet=false) const
Definition bind.cpp:176
const IdPtrn * ret() const
Definition ast.h:597
const Ptrn * ptrn() const
Definition ast.h:596
One of:
Definition ast.h:587
void bind(Scopes &) const override
Definition bind.cpp:181
void bind(Scopes &) const override
Definition bind.cpp:125
virtual void bind(Scopes &, bool rebind, bool quiet) const =0
Dbg dbg() const
Definition ast.h:938
virtual void bind_body(Scopes &) const
Definition bind.cpp:333
virtual void bind_decl(Scopes &) const
Definition bind.cpp:322
const Expr * body() const
Definition ast.h:940
const Expr * type() const
Definition ast.h:939
void bind(Scopes &) const override
Definition bind.cpp:314
const Ptrn * ptrn() const
Definition ast.h:695
const Expr * arg() const
Definition ast.h:697
void bind(Scopes &) const override
Definition bind.cpp:201
const Expr * body() const
Definition ast.h:698
const Expr * callee() const
Definition ast.h:696
void bind(Scopes &) const override
Definition bind.cpp:387
const Ptrn * var() const
Definition ast.h:1071
const Expr * guard() const
Definition ast.h:1074
const Expr * rhs() const
Definition ast.h:1073
const Expr * lhs() const
Definition ast.h:1072
Dbg dbg() const
Definition ast.h:1070
const Expr * meta_type() const
Definition ast.h:458
Scopes(AST &ast)
Definition bind.cpp:21
Scope & top()
Definition bind.cpp:29
AST & ast() const
Definition bind.cpp:27
const Decl * dummy() const
Definition bind.cpp:30
const Decl * find(Dbg dbg, bool quiet=false)
Definition bind.cpp:39
void push()
Definition bind.cpp:32
void bind(Dbg dbg, const Decl *decl, bool rebind=false, bool quiet=false)
Definition bind.cpp:52
Driver & driver() const
Definition bind.cpp:28
fe::SymMap< std::pair< Loc, const Decl * > > Scope
Definition bind.cpp:19
const Expr * body() const
Definition ast.h:766
const IdPtrn * arity() const
Definition ast.h:765
void bind(Scopes &) const override
Definition bind.cpp:219
const TuplePtrn * ptrn() const
Definition ast.h:720
void bind(Scopes &) const override
Definition bind.cpp:208
const Expr * elem(size_t i) const
Definition ast.h:743
void bind(Scopes &) const override
Definition bind.cpp:214
const auto & elems() const
Definition ast.h:742
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:110
const Ptrn * ptrn(size_t i) const
Definition ast.h:304
const auto & ptrns() const
Definition ast.h:303
const Expr * level() const
Definition ast.h:440
void bind(Scopes &) const override
Definition bind.cpp:153
const auto & types() const
Definition ast.h:478
const Expr * inhabitant() const
Definition ast.h:837
void bind(Scopes &) const override
Definition bind.cpp:242
Definition ast.h:14
fe::Arena::Ptr< const T > Ptr
Definition ast.h:22
Tok::Tag Tag
Definition bind.cpp:7
Sym sym() const
Definition dbg.h:148