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().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 ErrorExpr ::bind(Scopes&) const {}
123void HoleExpr ::bind(Scopes&) const {}
125// clang-format on
126
127void LitExpr::bind(Scopes& s) const {
128 if (type()) {
129 type()->bind(s);
130 if (tag() == Tag::L_str || tag() == Tag::L_c || tag() == Tag::L_i)
131 s.ast().error(type()->loc(), "a {} shall not have a type annotation", tag());
132 } else {
133 if (tag() == Tag::L_f) s.ast().error(loc(), "type annotation mandatory for floating point literal");
134 }
135}
136
137void DeclExpr::bind(Scopes& s) const {
138 if (is_where())
139 for (const auto& decl : decls() | std::ranges::views::reverse)
140 decl->bind(s);
141 else
142 for (const auto& decl : decls())
143 decl->bind(s);
144 expr()->bind(s);
145}
146
147void ArrowExpr::bind(Scopes& s) const {
148 dom()->bind(s);
149 codom()->bind(s);
150}
151
152void UnionExpr::bind(Scopes& s) const {
153 for (auto& type : types())
154 type->bind(s);
155}
156
157void InjExpr::bind(Scopes& s) const {
158 value()->bind(s);
159 type()->bind(s);
160}
161
163 s.push();
164 ptrn()->bind(s, false, false);
165 body()->bind(s);
166 s.pop();
167}
168
169void MatchExpr::bind(Scopes& s) const {
170 scrutinee()->bind(s);
171 for (const auto& arm : arms())
172 arm->bind(s);
173}
174
175void PiExpr::Dom::bind(Scopes& s, bool quiet) const {
176 ptrn()->bind(s, false, quiet);
177 if (ret()) ret()->bind(s, false, quiet);
178}
179
180void PiExpr::bind(Scopes& s) const {
181 s.push();
182 dom()->bind(s);
183 if (codom()) {
184 if (tag() == Tag::K_Cn) s.ast().error(codom()->loc(), "a continuation shall not have a codomain");
185 codom()->bind(s);
186 }
187 s.pop();
188}
189
190void LamExpr::bind(Scopes& s) const {
191 lam()->bind_decl(s);
192 lam()->bind_body(s);
193}
194
195void AppExpr::bind(Scopes& s) const {
196 callee()->bind(s);
197 arg()->bind(s);
198}
199
200void RetExpr::bind(Scopes& s) const {
201 callee()->bind(s);
202 arg()->bind(s);
203 ptrn()->bind(s, true, false);
204 body()->bind(s);
205}
206
207void SigmaExpr::bind(Scopes& s) const {
208 s.push();
209 ptrn()->bind(s, false, false);
210 s.pop();
211}
212
213void TupleExpr::bind(Scopes& s) const {
214 for (const auto& elem : elems())
215 elem->bind(s);
216}
217
218void SeqExpr::bind(Scopes& s) const {
219 s.push();
220 arity()->bind(s, false, false);
221 body()->bind(s);
222 s.pop();
223}
224
225void ExtractExpr::bind(Scopes& s) const {
226 tuple()->bind(s);
227 if (auto expr = std::get_if<Ptr<Expr>>(&index()))
228 (*expr)->bind(s);
229 else {
230 auto dbg = std::get<Dbg>(index());
231 decl_ = s.find(dbg, true);
232 }
233}
234
235void InsertExpr::bind(Scopes& s) const {
236 tuple()->bind(s);
237 index()->bind(s);
238 value()->bind(s);
239}
240
241void UniqExpr::bind(Scopes& s) const { inhabitant()->bind(s); }
242
243/*
244 * Decl
245 */
246
247void AxmDecl::Alias::bind(Scopes& s, const AxmDecl* axm) const {
248 auto sym = s.ast().sym(axm->dbg().sym().str() + "."s + dbg().sym().str());
249 full_ = Dbg(dbg().loc(), sym);
250 s.bind(full_, this);
251}
252
253void AxmDecl::bind(Scopes& s) const {
254 type()->bind(s);
255 annex_ = s.ast().name2annex(dbg(), nullptr);
256
257 if (annex_->fresh) {
258 annex_->normalizer = normalizer();
259 annex_->pi = type()->isa<PiExpr>() || type()->isa<ArrowExpr>();
260 } else {
261 auto pi = type()->isa<PiExpr>() || type()->isa<ArrowExpr>();
262 if (pi ^ *annex_->pi)
263 error(dbg().loc(), "all declarations of annex '{}' have to be function types if any is", dbg().sym());
264
265 if (annex_->normalizer.sym() != normalizer().sym()) {
266 auto l = normalizer().loc() ? normalizer().loc() : loc().anew_finis();
267 s.ast().error(l, "normalizer mismatch for axm '{}'", dbg());
268 if (auto norm = annex_->normalizer)
269 s.ast().note(norm.loc(), "previous normalizer '{}'", norm);
270 else
271 s.ast().note(l, "initially no normalizer specified");
272 }
273 }
274
275 if (num_subs() == 0) {
276 s.bind(dbg(), this);
277 } else {
278 if (auto old = s.find(dbg(), true)) {
279 if (auto old_ax = old->isa<AxmDecl>()) {
280 if (old_ax->num_subs() == 0) {
281 s.ast().error(dbg().loc(), "redeclared sub-less axm '{}' with subs", dbg());
282 s.ast().note(old_ax->dbg().loc(), "previous location here");
283 }
284 }
285 }
286
287 offset_ = annex_->subs.size();
288 for (const auto& aliases : subs())
289 for (const auto& alias : aliases)
290 alias->bind(s, this);
291
292 for (auto& sub : subs()) {
293 auto& aliases = annex_->subs.emplace_back(std::deque<Sym>());
294 for (const auto& alias : sub)
295 aliases.emplace_back(alias->dbg().sym());
296 }
297 }
298}
299
300void LetDecl::bind(Scopes& s) const {
301 s.push();
302 value()->bind(s);
303 s.pop();
304 ptrn()->bind(s, true, false);
305
306 if (auto id = ptrn()->isa<IdPtrn>()) annex_ = s.ast().name2annex(id->dbg(), &sub_);
307}
308
309void RecDecl::bind(Scopes& s) const {
310 for (auto curr = this; curr; curr = curr->next())
311 curr->bind_decl(s);
312 for (auto curr = this; curr; curr = curr->next())
313 curr->bind_body(s);
314 annex_ = s.ast().name2annex(dbg(), &sub_);
315}
316
318 if (auto t = type()) t->bind(s);
319 if (!type()->isa<HoleExpr>() && body()->isa<LamExpr>())
320 s.ast().warn(type()->loc(), "type of recursive declaration ignored for function expression");
321
322 if (!body()->isa<LamExpr>() && !body()->isa<PiExpr>() && !body()->isa<ArrowExpr>() && !body()->isa<SigmaExpr>())
323 s.ast().error(body()->loc(), "unsupported expression for a recursive declaration");
324
325 s.bind(dbg(), this);
326}
327
328void RecDecl::bind_body(Scopes& s) const { body()->bind(s); }
329
330void LamDecl::Dom::bind(Scopes& s, bool quiet) const {
331 PiExpr::Dom::bind(s, quiet);
332 if (filter() && !quiet) filter()->bind(s);
333}
334
336 s.push();
337 for (size_t i = 0, e = num_doms(); i != e; ++i)
338 dom(i)->bind(s);
339
340 if (auto filter = doms().back()->filter()) {
341 if (auto pe = filter->isa<PrimaryExpr>()) {
342 if (pe->tag() == Tag::K_tt && (tag() == Tag::K_lam || tag() == Tag::T_lm))
343 s.ast().warn(filter->loc(),
344 "'tt'-filter superfluous as the last curried function group of a '{}' receives a "
345 "'tt'-filter by default",
346 tag());
347 if (pe->tag() == Tag::K_ff && (tag() != Tag::K_lam && tag() != Tag::T_lm))
348 s.ast().warn(filter->loc(),
349 "'ff'-filter superfluous as the last curried function group of a '{}' receives a "
350 "'ff'-filter by default",
351 tag());
352 }
353 }
354
355 if (codom()) {
356 if (tag() == Tag::K_con || tag() == Tag::K_cn)
357 s.ast().error(codom()->loc(), "a continuation shall not have a codomain");
358 codom()->bind(s);
359 }
360
361 s.pop();
362 s.bind(dbg(), this);
363 annex_ = s.ast().name2annex(dbg(), &sub_);
364}
365
367 s.push();
368 for (const auto& dom : doms())
369 dom->bind(s, true);
370 body()->bind(s);
371 s.pop();
372}
373
374void CDecl::bind(Scopes& s) const {
375 s.push();
376 dom()->bind(s, false, false);
377 s.pop(); // we don't allow codom to depent on dom
378 if (codom()) codom()->bind(s);
379 s.bind(dbg(), this);
380}
381
382void RuleDecl::bind(Scopes& s) const {
383 s.push();
384 var()->bind(s, true, false);
385 lhs()->bind(s);
386 rhs()->bind(s);
387 guard()->bind(s);
388 s.pop();
389}
390
391} // 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:195
const Expr * arg() const
Definition ast.h:654
const Expr * callee() const
Definition ast.h:653
dom -> codom
Definition ast.h:541
void bind(Scopes &) const override
Definition bind.cpp:147
void bind(Scopes &, const AxmDecl *) const
Definition bind.cpp:247
Dbg dbg() const
Definition ast.h:865
friend class AxmDecl
Definition ast.h:874
const auto & subs() const
Definition ast.h:887
const Expr * type() const
Definition ast.h:890
size_t num_subs() const
Definition ast.h:888
AxmDecl(Loc loc, Dbg dbg, std::deque< Ptrs< Alias > > &&subs, Ptr< Expr > &&type, Dbg normalizer, Tok curry, Tok trip)
Definition ast.h:877
void bind(Scopes &) const override
Definition bind.cpp:253
Dbg normalizer() const
Definition ast.h:891
Dbg dbg() const
Definition ast.h:886
const auto & sub(size_t i) const
Definition ast.h:889
const Ptrn * dom() const
Definition ast.h:1023
const Expr * codom() const
Definition ast.h:1024
Dbg dbg() const
Definition ast.h:1021
void bind(Scopes &) const override
Definition bind.cpp:374
const Expr * expr() const
Definition ast.h:420
const auto & decls() const
Definition ast.h:418
void bind(Scopes &) const override
Definition bind.cpp:137
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:774
const Expr * tuple() const
Definition ast.h:773
void bind(Scopes &) const override
Definition bind.cpp:225
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:1086
const Expr * type() const
Definition ast.h:482
void bind(Scopes &) const override
Definition bind.cpp:157
const Expr * value() const
Definition ast.h:481
const Expr * index() const
Definition ast.h:798
void bind(Scopes &) const override
Definition bind.cpp:235
const Expr * tuple() const
Definition ast.h:797
const Expr * value() const
Definition ast.h:799
const Expr * filter() const
Definition ast.h:960
void bind(Scopes &, bool quiet=false) const override
Definition bind.cpp:330
Tok::Tag tag() const
Definition ast.h:989
void bind_body(Scopes &) const override
Definition bind.cpp:366
const Ptrs< Dom > & doms() const
Definition ast.h:991
const Expr * codom() const
Definition ast.h:994
size_t num_doms() const
Definition ast.h:993
void bind_decl(Scopes &) const override
Definition bind.cpp:335
const Dom * dom(size_t i) const
Definition ast.h:992
void bind(Scopes &) const override
Definition bind.cpp:190
const LamDecl * lam() const
Definition ast.h:630
void bind(Scopes &) const override
Definition bind.cpp:300
const Expr * value() const
Definition ast.h:843
const Ptrn * ptrn() const
Definition ast.h:842
const Expr * type() const
Definition ast.h:397
Tok::Tag tag() const
Definition ast.h:396
void bind(Scopes &) const override
Definition bind.cpp:127
const Expr * body() const
Definition ast.h:507
virtual void bind(Scopes &) const
Definition bind.cpp:162
const Ptrn * ptrn() const
Definition ast.h:506
void bind(Scopes &) const override
Definition bind.cpp:169
const Expr * scrutinee() const
Definition ast.h:523
const Arm * arm(size_t i) const
Definition ast.h:525
const auto & arms() const
Definition ast.h:524
const auto & decls() const
Definition ast.h:1114
const auto & implicit_imports() const
Definition ast.h:1112
void bind(AST &) const
Definition bind.cpp:77
const auto & imports() const
Definition ast.h:1113
Loc loc() const
Definition ast.h:122
virtual void bind(Scopes &, bool quiet=false) const
Definition bind.cpp:175
const IdPtrn * ret() const
Definition ast.h:579
const Ptrn * ptrn() const
Definition ast.h:578
One of:
Definition ast.h:569
void bind(Scopes &) const override
Definition bind.cpp:180
void bind(Scopes &) const override
Definition bind.cpp:124
virtual void bind(Scopes &, bool rebind, bool quiet) const =0
Dbg dbg() const
Definition ast.h:920
virtual void bind_body(Scopes &) const
Definition bind.cpp:328
virtual void bind_decl(Scopes &) const
Definition bind.cpp:317
const Expr * body() const
Definition ast.h:922
const Expr * type() const
Definition ast.h:921
void bind(Scopes &) const override
Definition bind.cpp:309
const Ptrn * ptrn() const
Definition ast.h:677
const Expr * arg() const
Definition ast.h:679
void bind(Scopes &) const override
Definition bind.cpp:200
const Expr * body() const
Definition ast.h:680
const Expr * callee() const
Definition ast.h:678
void bind(Scopes &) const override
Definition bind.cpp:382
const Ptrn * var() const
Definition ast.h:1052
const Expr * guard() const
Definition ast.h:1055
const Expr * rhs() const
Definition ast.h:1054
const Expr * lhs() const
Definition ast.h:1053
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:748
const IdPtrn * arity() const
Definition ast.h:747
void bind(Scopes &) const override
Definition bind.cpp:218
const TuplePtrn * ptrn() const
Definition ast.h:702
void bind(Scopes &) const override
Definition bind.cpp:207
const Expr * elem(size_t i) const
Definition ast.h:725
void bind(Scopes &) const override
Definition bind.cpp:213
const auto & elems() const
Definition ast.h:724
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:152
const auto & types() const
Definition ast.h:460
const Expr * inhabitant() const
Definition ast.h:819
void bind(Scopes &) const override
Definition bind.cpp:241
Definition ast.h:14
fe::Arena::Ptr< const T > Ptr
Definition ast.h:22
Tok::Tag Tag
Definition bind.cpp:7
void error(Loc loc, const char *f, Args &&... args)
Definition dbg.h:125
Sym sym() const
Definition dbg.h:148