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}
320
322 if (auto t = type()) t->bind(s);
323 if (!type()->isa<HoleExpr>() && body()->isa<LamExpr>())
324 s.ast().warn(type()->loc(), "type of recursive declaration ignored for function expression");
325
326 if (!body()->isa<LamExpr>() && !body()->isa<PiExpr>() && !body()->isa<ArrowExpr>() && !body()->isa<SigmaExpr>())
327 s.ast().error(body()->loc(), "unsupported expression for a recursive declaration");
328
329 s.bind(dbg(), this);
330 annex_ = s.ast().name2annex(dbg(), &sub_);
331
332}
333
334void RecDecl::bind_body(Scopes& s) const { body()->bind(s); }
335
336void LamDecl::Dom::bind(Scopes& s, bool quiet) const {
337 PiExpr::Dom::bind(s, quiet);
338 if (filter() && !quiet) filter()->bind(s);
339}
340
342 s.push();
343 for (size_t i = 0, e = num_doms(); i != e; ++i)
344 dom(i)->bind(s);
345
346 if (auto filter = doms().back()->filter()) {
347 if (auto pe = filter->isa<PrimaryExpr>()) {
348 if (pe->tag() == Tag::K_tt && (tag() == Tag::K_lam || tag() == Tag::T_lm))
349 s.ast().warn(filter->loc(),
350 "'tt'-filter superfluous as the last curried function group of a '{}' receives a "
351 "'tt'-filter by default",
352 tag());
353 if (pe->tag() == Tag::K_ff && (tag() != Tag::K_lam && tag() != Tag::T_lm))
354 s.ast().warn(filter->loc(),
355 "'ff'-filter superfluous as the last curried function group of a '{}' receives a "
356 "'ff'-filter by default",
357 tag());
358 }
359 }
360
361 if (codom()) {
362 if (tag() == Tag::K_con || tag() == Tag::K_cn)
363 s.ast().error(codom()->loc(), "a continuation shall not have a codomain");
364 codom()->bind(s);
365 }
366
367 s.pop();
368 s.bind(dbg(), this);
369 annex_ = s.ast().name2annex(dbg(), &sub_);
370}
371
373 s.push();
374 for (const auto& dom : doms())
375 dom->bind(s, true);
376 body()->bind(s);
377 s.pop();
378}
379
380void CDecl::bind(Scopes& s) const {
381 s.push();
382 dom()->bind(s, false, false);
383 s.pop(); // we don't allow codom to depent on dom
384 if (codom()) codom()->bind(s);
385 s.bind(dbg(), this);
386}
387
388void RuleDecl::bind(Scopes& s) const {
389 s.push();
390 var()->bind(s, true, false);
391 lhs()->bind(s);
392 rhs()->bind(s);
393 guard()->bind(s);
394 s.pop();
395 s.bind(dbg(), this);
396}
397
398} // namespace mim::ast
Some "global" variables needed all over the place.
Definition driver.h:19
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:260
const Ptrn * ptrn() const
Definition ast.h:259
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:656
const Expr * callee() const
Definition ast.h:655
dom -> codom
Definition ast.h:543
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:867
friend class AxmDecl
Definition ast.h:876
const auto & subs() const
Definition ast.h:889
const Expr * type() const
Definition ast.h:892
size_t num_subs() const
Definition ast.h:890
AxmDecl(Loc loc, Dbg dbg, std::deque< Ptrs< Alias > > &&subs, Ptr< Expr > &&type, Dbg normalizer, Tok curry, Tok trip)
Definition ast.h:879
void bind(Scopes &) const override
Definition bind.cpp:254
Dbg normalizer() const
Definition ast.h:893
Dbg dbg() const
Definition ast.h:888
const auto & sub(size_t i) const
Definition ast.h:891
const Ptrn * dom() const
Definition ast.h:1025
const Expr * codom() const
Definition ast.h:1026
Dbg dbg() const
Definition ast.h:1023
void bind(Scopes &) const override
Definition bind.cpp:380
const Expr * expr() const
Definition ast.h:404
const auto & decls() const
Definition ast.h:402
void bind(Scopes &) const override
Definition bind.cpp:138
bool is_where() const
Definition ast.h:403
Decl(Loc loc)
Definition ast.h:150
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:776
const Expr * tuple() const
Definition ast.h:775
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:238
Dbg dbg() const
Definition ast.h:338
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:100
Dbg dbg() const
Definition ast.h:208
const Expr * type() const
Definition ast.h:209
void bind(Scopes &) const
Definition bind.cpp:91
const Module * module() const
Definition ast.h:1089
const Expr * type() const
Definition ast.h:484
void bind(Scopes &) const override
Definition bind.cpp:158
const Expr * value() const
Definition ast.h:483
const Expr * index() const
Definition ast.h:800
void bind(Scopes &) const override
Definition bind.cpp:236
const Expr * tuple() const
Definition ast.h:799
const Expr * value() const
Definition ast.h:801
const Expr * filter() const
Definition ast.h:962
void bind(Scopes &, bool quiet=false) const override
Definition bind.cpp:336
Tok::Tag tag() const
Definition ast.h:991
void bind_body(Scopes &) const override
Definition bind.cpp:372
const Ptrs< Dom > & doms() const
Definition ast.h:993
const Expr * codom() const
Definition ast.h:996
size_t num_doms() const
Definition ast.h:995
void bind_decl(Scopes &) const override
Definition bind.cpp:341
const Dom * dom(size_t i) const
Definition ast.h:994
void bind(Scopes &) const override
Definition bind.cpp:191
const LamDecl * lam() const
Definition ast.h:632
void bind(Scopes &) const override
Definition bind.cpp:305
const Expr * value() const
Definition ast.h:845
const Ptrn * ptrn() const
Definition ast.h:844
const Expr * type() const
Definition ast.h:381
Tok::Tag tag() const
Definition ast.h:380
void bind(Scopes &) const override
Definition bind.cpp:128
const Expr * body() const
Definition ast.h:509
virtual void bind(Scopes &) const
Definition bind.cpp:163
const Ptrn * ptrn() const
Definition ast.h:508
void bind(Scopes &) const override
Definition bind.cpp:170
const Expr * scrutinee() const
Definition ast.h:525
const Arm * arm(size_t i) const
Definition ast.h:527
const auto & arms() const
Definition ast.h:526
const auto & decls() const
Definition ast.h:1117
const auto & implicit_imports() const
Definition ast.h:1115
void bind(AST &) const
Definition bind.cpp:77
const auto & imports() const
Definition ast.h:1116
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:581
const Ptrn * ptrn() const
Definition ast.h:580
One of:
Definition ast.h:571
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:922
virtual void bind_body(Scopes &) const
Definition bind.cpp:334
virtual void bind_decl(Scopes &) const
Definition bind.cpp:321
const Expr * body() const
Definition ast.h:924
const Expr * type() const
Definition ast.h:923
void bind(Scopes &) const override
Definition bind.cpp:314
const Ptrn * ptrn() const
Definition ast.h:679
const Expr * arg() const
Definition ast.h:681
void bind(Scopes &) const override
Definition bind.cpp:201
const Expr * body() const
Definition ast.h:682
const Expr * callee() const
Definition ast.h:680
void bind(Scopes &) const override
Definition bind.cpp:388
const Ptrn * var() const
Definition ast.h:1055
const Expr * guard() const
Definition ast.h:1058
const Expr * rhs() const
Definition ast.h:1057
const Expr * lhs() const
Definition ast.h:1056
Dbg dbg() const
Definition ast.h:1054
const Expr * meta_type() const
Definition ast.h:442
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:750
const IdPtrn * arity() const
Definition ast.h:749
void bind(Scopes &) const override
Definition bind.cpp:219
const TuplePtrn * ptrn() const
Definition ast.h:704
void bind(Scopes &) const override
Definition bind.cpp:208
const Expr * elem(size_t i) const
Definition ast.h:727
void bind(Scopes &) const override
Definition bind.cpp:214
const auto & elems() const
Definition ast.h:726
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:110
const Ptrn * ptrn(size_t i) const
Definition ast.h:288
const auto & ptrns() const
Definition ast.h:287
const Expr * level() const
Definition ast.h:424
void bind(Scopes &) const override
Definition bind.cpp:153
const auto & types() const
Definition ast.h:462
const Expr * inhabitant() const
Definition ast.h:821
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