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()) import->bind(s);
84 for (const auto& import : imports()) import->bind(s);
85 for (const auto& decl : decls()) decl->bind(s);
86}
87
88void Import::bind(Scopes& s) const { module()->bind(s); }
89
90/*
91 * Ptrn
92 */
93
94void ErrorPtrn::bind(Scopes&, bool, bool) const {}
95void GrpPtrn::bind(Scopes& s, bool rebind, bool quiet) const { s.bind(dbg(), this, rebind, quiet); }
96
97void IdPtrn::bind(Scopes& s, bool rebind, bool quiet) const {
98 if (!quiet && type()) type()->bind(s);
99 s.bind(dbg(), this, rebind, quiet);
100}
101
102void AliasPtrn::bind(Scopes& s, bool rebind, bool quiet) const {
103 ptrn()->bind(s, rebind, quiet);
104 s.bind(dbg(), this, rebind, quiet);
105}
106
107void TuplePtrn::bind(Scopes& s, bool rebind, bool quiet) const {
108 for (const auto& ptrn : ptrns()) ptrn->bind(s, rebind, quiet);
109}
110
111/*
112 * Expr
113 */
114
115// clang-format off
116void IdExpr ::bind(Scopes& s) const { decl_ = s.find(dbg()); }
117void TypeExpr ::bind(Scopes& s) const { level()->bind(s); }
118void ErrorExpr ::bind(Scopes&) const {}
119void HoleExpr ::bind(Scopes&) const {}
121// clang-format on
122
123void LitExpr::bind(Scopes& s) const {
124 if (type()) {
125 type()->bind(s);
126 if (tag() == Tag::L_str || tag() == Tag::L_c || tag() == Tag::L_i)
127 s.ast().error(type()->loc(), "a {} shall not have a type annotation", tag());
128 } else {
129 if (tag() == Tag::L_f) s.ast().error(loc(), "type annotation mandatory for floating point literal");
130 }
131}
132
133void DeclExpr::bind(Scopes& s) const {
134 if (is_where())
135 for (const auto& decl : decls() | std::ranges::views::reverse) decl->bind(s);
136 else
137 for (const auto& decl : decls()) decl->bind(s);
138 expr()->bind(s);
139}
140
141void ArrowExpr::bind(Scopes& s) const {
142 dom()->bind(s);
143 codom()->bind(s);
144}
145
146void UnionExpr::bind(Scopes& s) const {
147 for (auto& type : types()) type->bind(s);
148}
149
150void InjExpr::bind(Scopes& s) const {
151 value()->bind(s);
152 type()->bind(s);
153}
154
156 s.push();
157 ptrn()->bind(s, false, false);
158 body()->bind(s);
159 s.pop();
160}
161
162void MatchExpr::bind(Scopes& s) const {
163 scrutinee()->bind(s);
164 for (const auto& arm : arms()) arm->bind(s);
165}
166
167void PiExpr::Dom::bind(Scopes& s, bool quiet) const {
168 ptrn()->bind(s, false, quiet);
169 if (ret()) ret()->bind(s, false, quiet);
170}
171
172void PiExpr::bind(Scopes& s) const {
173 s.push();
174 dom()->bind(s);
175 if (codom()) {
176 if (tag() == Tag::K_Cn) s.ast().error(codom()->loc(), "a continuation shall not have a codomain");
177 codom()->bind(s);
178 }
179 s.pop();
180}
181
182void LamExpr::bind(Scopes& s) const {
183 lam()->bind_decl(s);
184 lam()->bind_body(s);
185}
186
187void AppExpr::bind(Scopes& s) const {
188 callee()->bind(s);
189 arg()->bind(s);
190}
191
192void RetExpr::bind(Scopes& s) const {
193 callee()->bind(s);
194 arg()->bind(s);
195 ptrn()->bind(s, true, false);
196 body()->bind(s);
197}
198
199void SigmaExpr::bind(Scopes& s) const {
200 s.push();
201 ptrn()->bind(s, false, false);
202 s.pop();
203}
204
205void TupleExpr::bind(Scopes& s) const {
206 for (const auto& elem : elems()) elem->bind(s);
207}
208
209void SeqExpr::bind(Scopes& s) const {
210 s.push();
211 shape()->bind(s, false, false);
212 body()->bind(s);
213 s.pop();
214}
215
216void ExtractExpr::bind(Scopes& s) const {
217 tuple()->bind(s);
218 if (auto expr = std::get_if<Ptr<Expr>>(&index()))
219 (*expr)->bind(s);
220 else {
221 auto dbg = std::get<Dbg>(index());
222 decl_ = s.find(dbg, true);
223 }
224}
225
226void InsertExpr::bind(Scopes& s) const {
227 tuple()->bind(s);
228 index()->bind(s);
229 value()->bind(s);
230}
231
232void UniqExpr::bind(Scopes& s) const { inhabitant()->bind(s); }
233
234/*
235 * Decl
236 */
237
238void AxmDecl::Alias::bind(Scopes& s, const AxmDecl* axm) const {
239 auto sym = s.ast().sym(axm->dbg().sym().str() + "."s + dbg().sym().str());
240 full_ = Dbg(dbg().loc(), sym);
241 s.bind(full_, this);
242}
243
244void AxmDecl::bind(Scopes& s) const {
245 type()->bind(s);
246 annex_ = s.ast().name2annex(dbg(), nullptr);
247
248 if (annex_->fresh) {
249 annex_->normalizer = normalizer();
250 annex_->pi = type()->isa<PiExpr>() || type()->isa<ArrowExpr>();
251 } else {
252 auto pi = type()->isa<PiExpr>() || type()->isa<ArrowExpr>();
253 if (pi ^ *annex_->pi)
254 error(dbg().loc(), "all declarations of annex '{}' have to be function types if any is", dbg().sym());
255
256 if (annex_->normalizer.sym() != normalizer().sym()) {
257 auto l = normalizer().loc() ? normalizer().loc() : loc().anew_finis();
258 s.ast().error(l, "normalizer mismatch for axm '{}'", dbg());
259 if (auto norm = annex_->normalizer)
260 s.ast().note(norm.loc(), "previous normalizer '{}'", norm);
261 else
262 s.ast().note(l, "initially no normalizer specified");
263 }
264 }
265
266 if (num_subs() == 0) {
267 s.bind(dbg(), this);
268 } else {
269 if (auto old = s.find(dbg(), true)) {
270 if (auto old_ax = old->isa<AxmDecl>()) {
271 if (old_ax->num_subs() == 0) {
272 s.ast().error(dbg().loc(), "redeclared sub-less axm '{}' with subs", dbg());
273 s.ast().note(old_ax->dbg().loc(), "previous location here");
274 }
275 }
276 }
277
278 offset_ = annex_->subs.size();
279 for (const auto& aliases : subs())
280 for (const auto& alias : aliases) alias->bind(s, this);
281
282 for (auto& sub : subs()) {
283 auto& aliases = annex_->subs.emplace_back(std::deque<Sym>());
284 for (const auto& alias : sub) aliases.emplace_back(alias->dbg().sym());
285 }
286 }
287}
288
289void LetDecl::bind(Scopes& s) const {
290 s.push();
291 value()->bind(s);
292 s.pop();
293 ptrn()->bind(s, true, false);
294
295 if (auto id = ptrn()->isa<IdPtrn>()) annex_ = s.ast().name2annex(id->dbg(), &sub_);
296}
297
298void RecDecl::bind(Scopes& s) const {
299 for (auto curr = this; curr; curr = curr->next()) curr->bind_decl(s);
300 for (auto curr = this; curr; curr = curr->next()) curr->bind_body(s);
301 annex_ = s.ast().name2annex(dbg(), &sub_);
302}
303
305 if (auto t = type()) t->bind(s);
306 if (!type()->isa<HoleExpr>() && body()->isa<LamExpr>())
307 s.ast().warn(type()->loc(), "type of recursive declaration ignored for function expression");
308
309 if (!body()->isa<LamExpr>() && !body()->isa<PiExpr>() && !body()->isa<ArrowExpr>() && !body()->isa<SigmaExpr>())
310 s.ast().error(body()->loc(), "unsupported expression for a recursive declaration");
311
312 s.bind(dbg(), this);
313}
314
315void RecDecl::bind_body(Scopes& s) const { body()->bind(s); }
316
317void LamDecl::Dom::bind(Scopes& s, bool quiet) const {
318 PiExpr::Dom::bind(s, quiet);
319 if (filter() && !quiet) filter()->bind(s);
320}
321
323 s.push();
324 for (size_t i = 0, e = num_doms(); i != e; ++i) dom(i)->bind(s);
325
326 if (auto filter = doms().back()->filter()) {
327 if (auto pe = filter->isa<PrimaryExpr>()) {
328 if (pe->tag() == Tag::K_tt && (tag() == Tag::K_lam || tag() == Tag::T_lm))
329 s.ast().warn(filter->loc(),
330 "'tt'-filter superfluous as the last curried function group of a '{}' receives a "
331 "'tt'-filter by default",
332 tag());
333 if (pe->tag() == Tag::K_ff && (tag() != Tag::K_lam && tag() != Tag::T_lm))
334 s.ast().warn(filter->loc(),
335 "'ff'-filter superfluous as the last curried function group of a '{}' receives a "
336 "'ff'-filter by default",
337 tag());
338 }
339 }
340
341 if (codom()) {
342 if (tag() == Tag::K_con || tag() == Tag::K_cn)
343 s.ast().error(codom()->loc(), "a continuation shall not have a codomain");
344 codom()->bind(s);
345 }
346
347 s.pop();
348 s.bind(dbg(), this);
349 annex_ = s.ast().name2annex(dbg(), &sub_);
350}
351
353 s.push();
354 for (const auto& dom : doms()) dom->bind(s, true);
355 body()->bind(s);
356 s.pop();
357}
358
359void CDecl::bind(Scopes& s) const {
360 s.push();
361 dom()->bind(s, false, false);
362 s.pop(); // we don't allow codom to depent on dom
363 if (codom()) codom()->bind(s);
364 s.bind(dbg(), this);
365}
366
367} // namespace mim::ast
Some "global" variables needed all over the place.
Definition driver.h:17
Keeps track of indentation level.
Definition print.h:196
Driver & driver()
Definition ast.h:60
Error & note(Loc loc, const char *fmt, Args &&... args) const
Definition ast.h:84
Error & error()
Definition ast.h:61
Dbg dbg() const
Definition ast.h:273
const Ptrn * ptrn() const
Definition ast.h:272
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:102
void bind(Scopes &) const override
Definition bind.cpp:187
const Expr * arg() const
Definition ast.h:651
const Expr * callee() const
Definition ast.h:650
dom -> codom
Definition ast.h:538
void bind(Scopes &) const override
Definition bind.cpp:141
void bind(Scopes &, const AxmDecl *) const
Definition bind.cpp:238
Dbg dbg() const
Definition ast.h:862
friend class AxmDecl
Definition ast.h:871
const auto & subs() const
Definition ast.h:884
const Expr * type() const
Definition ast.h:887
size_t num_subs() const
Definition ast.h:885
AxmDecl(Loc loc, Dbg dbg, std::deque< Ptrs< Alias > > &&subs, Ptr< Expr > &&type, Dbg normalizer, Tok curry, Tok trip)
Definition ast.h:874
void bind(Scopes &) const override
Definition bind.cpp:244
Dbg normalizer() const
Definition ast.h:888
Dbg dbg() const
Definition ast.h:883
const auto & sub(size_t i) const
Definition ast.h:886
const Ptrn * dom() const
Definition ast.h:1020
const Expr * codom() const
Definition ast.h:1021
Dbg dbg() const
Definition ast.h:1018
void bind(Scopes &) const override
Definition bind.cpp:359
const Expr * expr() const
Definition ast.h:417
const auto & decls() const
Definition ast.h:415
void bind(Scopes &) const override
Definition bind.cpp:133
bool is_where() const
Definition ast.h:416
Decl(Loc loc)
Definition ast.h:163
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:94
virtual void bind(Scopes &) const =0
const auto & index() const
Definition ast.h:771
const Expr * tuple() const
Definition ast.h:770
void bind(Scopes &) const override
Definition bind.cpp:216
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:95
Dbg dbg() const
Definition ast.h:251
Dbg dbg() const
Definition ast.h:351
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:97
Dbg dbg() const
Definition ast.h:221
const Expr * type() const
Definition ast.h:222
void bind(Scopes &) const
Definition bind.cpp:88
const Module * module() const
Definition ast.h:1048
const Expr * type() const
Definition ast.h:479
void bind(Scopes &) const override
Definition bind.cpp:150
const Expr * value() const
Definition ast.h:478
const Expr * index() const
Definition ast.h:795
void bind(Scopes &) const override
Definition bind.cpp:226
const Expr * tuple() const
Definition ast.h:794
const Expr * value() const
Definition ast.h:796
const Expr * filter() const
Definition ast.h:957
void bind(Scopes &, bool quiet=false) const override
Definition bind.cpp:317
Tok::Tag tag() const
Definition ast.h:986
void bind_body(Scopes &) const override
Definition bind.cpp:352
const Ptrs< Dom > & doms() const
Definition ast.h:988
const Expr * codom() const
Definition ast.h:991
size_t num_doms() const
Definition ast.h:990
void bind_decl(Scopes &) const override
Definition bind.cpp:322
const Dom * dom(size_t i) const
Definition ast.h:989
void bind(Scopes &) const override
Definition bind.cpp:182
const LamDecl * lam() const
Definition ast.h:627
void bind(Scopes &) const override
Definition bind.cpp:289
const Expr * value() const
Definition ast.h:840
const Ptrn * ptrn() const
Definition ast.h:839
const Expr * type() const
Definition ast.h:394
Tok::Tag tag() const
Definition ast.h:393
void bind(Scopes &) const override
Definition bind.cpp:123
const Expr * body() const
Definition ast.h:504
virtual void bind(Scopes &) const
Definition bind.cpp:155
const Ptrn * ptrn() const
Definition ast.h:503
void bind(Scopes &) const override
Definition bind.cpp:162
const Expr * scrutinee() const
Definition ast.h:520
const Arm * arm(size_t i) const
Definition ast.h:522
const auto & arms() const
Definition ast.h:521
const auto & decls() const
Definition ast.h:1076
const auto & implicit_imports() const
Definition ast.h:1074
void bind(AST &) const
Definition bind.cpp:77
const auto & imports() const
Definition ast.h:1075
Loc loc() const
Definition ast.h:119
virtual void bind(Scopes &, bool quiet=false) const
Definition bind.cpp:167
const IdPtrn * ret() const
Definition ast.h:576
const Ptrn * ptrn() const
Definition ast.h:575
One of:
Definition ast.h:566
void bind(Scopes &) const override
Definition bind.cpp:172
void bind(Scopes &) const override
Definition bind.cpp:120
virtual void bind(Scopes &, bool rebind, bool quiet) const =0
Dbg dbg() const
Definition ast.h:917
virtual void bind_body(Scopes &) const
Definition bind.cpp:315
virtual void bind_decl(Scopes &) const
Definition bind.cpp:304
const Expr * body() const
Definition ast.h:919
const Expr * type() const
Definition ast.h:918
void bind(Scopes &) const override
Definition bind.cpp:298
const Ptrn * ptrn() const
Definition ast.h:674
const Expr * arg() const
Definition ast.h:676
void bind(Scopes &) const override
Definition bind.cpp:192
const Expr * body() const
Definition ast.h:677
const Expr * callee() const
Definition ast.h:675
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:745
void bind(Scopes &) const override
Definition bind.cpp:209
const IdPtrn * shape() const
Definition ast.h:744
const TuplePtrn * ptrn() const
Definition ast.h:699
void bind(Scopes &) const override
Definition bind.cpp:199
const Expr * elem(size_t i) const
Definition ast.h:722
void bind(Scopes &) const override
Definition bind.cpp:205
const auto & elems() const
Definition ast.h:721
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:107
const Ptrn * ptrn(size_t i) const
Definition ast.h:301
const auto & ptrns() const
Definition ast.h:300
const Expr * level() const
Definition ast.h:437
void bind(Scopes &) const override
Definition bind.cpp:146
const auto & types() const
Definition ast.h:457
const Expr * inhabitant() const
Definition ast.h:816
void bind(Scopes &) const override
Definition bind.cpp:232
Definition ast.h:14
fe::Arena::Ptr< const T > Ptr
Definition ast.h:21
Tok::Tag Tag
Definition bind.cpp:7
void error(Loc loc, const char *f, Args &&... args)
Definition dbg.h:122
Sym sym() const
Definition dbg.h:145