Thorin 1.9.0
The Higher ORder INtermediate representation
Loading...
Searching...
No Matches
emit.cpp
Go to the documentation of this file.
1#include "thorin/ast/ast.h"
2
3using namespace std::literals;
4
5namespace thorin::ast {
6
7using Tag = Tok::Tag;
8
9class Emitter {
10public:
12 : ast_(ast) {}
13
14 AST& ast() const { return ast_; }
15 World& world() { return ast().world(); }
16 Driver& driver() { return world().driver(); }
17
18 void register_annex(AnnexInfo* annex, sub_t sub, Ref def) {
19 if (annex) {
20 const auto& id = annex->id;
21 world().register_annex(id.plugin | (id.tag << 8) | sub, def);
22 }
23 }
24
25 absl::node_hash_map<Sigma*, fe::SymMap<size_t>, GIDHash<const Def*>, GIDEq<const Def*>> sigma2sym2idx;
26
27private:
28 AST& ast_;
29};
30
31/*
32 * Module
33 */
34
35void Module::emit(AST& ast) const {
36 auto emitter = Emitter(ast);
37 emit(emitter);
38}
39
40void Module::emit(Emitter& e) const {
41 auto _ = e.world().push(loc());
42 for (const auto& import : implicit_imports()) import->emit(e);
43 for (const auto& import : imports()) import->emit(e);
44 for (const auto& decl : decls()) decl->emit(e);
45}
46
47void Import::emit(Emitter& e) const { module()->emit(e); }
48
49/*
50 * Ptrn::emit_value
51 */
52
54 auto _ = e.world().push(loc());
55 emit_type(e);
56 emit_value_(e, def);
57 return def_ = def->set(dbg());
58}
59
60void TuplePtrn::emit_value_(Emitter& e, Ref def) const {
61 for (size_t i = 0, n = num_ptrns(); i != n; ++i) ptrn(i)->emit_value(e, def->proj(n, i));
62}
63
64/*
65 * Ptrn::emit_Type
66 */
67
69 auto _ = e.world().push(loc());
70 return type() ? type()->emit(e) : e.world().mut_infer_type();
71}
72
73Ref GrpPtrn::emit_type(Emitter& e) const { return id()->emit_type(e); }
74
75Ref TuplePtrn::emit_type(Emitter& e) const { return emit_body(e, {}); }
76
78 auto _ = e.world().push(loc());
79 auto n = num_ptrns();
80 Sigma* sigma;
81 if (decl) {
82 sigma = decl->as_mut<Sigma>();
83 } else {
84 auto type = e.world().type_infer_univ();
85 sigma = e.world().mut_sigma(type, n)->set(dbg().sym());
86 }
87 auto var = sigma->var()->set(dbg());
88 auto& sym2idx = e.sigma2sym2idx[sigma];
89
90 for (size_t i = 0; i != n; ++i) {
91 sigma->set(i, ptrn(i)->emit_type(e));
92 ptrn(i)->emit_value(e, var->proj(n, i));
93 sym2idx[ptrn(i)->dbg().sym()] = i;
94 }
95
96 if (auto imm = sigma->immutabilize()) return imm;
97 return sigma;
98}
99
101 auto _ = e.world().push(loc());
102 type = type ? type : e.world().type_infer_univ();
103 return e.world().mut_sigma(type, num_ptrns())->set(dbg().sym());
104}
105
106/*
107 * Expr
108 */
109
111 auto _ = e.world().push(loc());
112 return emit_(e);
113}
114
115Ref ErrorExpr::emit_(Emitter&) const { fe::unreachable(); }
116Ref InferExpr::emit_(Emitter& e) const { return e.world().mut_infer_type(); }
117
119 assert(decl());
120 return decl()->def();
121}
122
124 auto l = level()->emit(e);
125 return e.world().type(l);
126}
127
128Ref PrimaryExpr ::emit_(Emitter& e) const {
129 // clang-format off
130 switch (tag()) {
131 case Tag::K_Univ: return e.world().univ();
132 case Tag::K_Nat: return e.world().type_nat();
133 case Tag::K_Idx: return e.world().type_idx();
134 case Tag::K_Bool: return e.world().type_bool();
135 case Tag::K_ff: return e.world().lit_ff();
136 case Tag::K_tt: return e.world().lit_tt();
137 case Tag::K_i1: return e.world().lit_i1();
138 case Tag::K_i8: return e.world().lit_i8();
139 case Tag::K_i16: return e.world().lit_i16();
140 case Tag::K_i32: return e.world().lit_i32();
141 case Tag::K_i64: return e.world().lit_i64();
142 case Tag::K_I1: return e.world().type_i1();
143 case Tag::K_I8: return e.world().type_i8();
144 case Tag::K_I16: return e.world().type_i16();
145 case Tag::K_I32: return e.world().type_i32();
146 case Tag::K_I64: return e.world().type_i64();
147 case Tag::T_star: return e.world().type<0>();
148 case Tag::T_box: return e.world().type<1>();
149 default: fe::unreachable();
150 }
151 // clang-format on
152}
153
155 auto t = type() ? type()->emit(e) : nullptr;
156 // clang-format off
157 switch (tag()) {
158 case Tag::L_f:
159 case Tag::L_s:
160 case Tag::L_u: return t ? e.world().lit(t, tok().lit_u()) : e.world().lit_nat(tok().lit_u());
161 case Tag::L_i: return tok().lit_i();
162 case Tag::L_c: return e.world().lit_i8(tok().lit_c());
163 case Tag::L_str: return e.world().tuple(tok().sym());
164 case Tag::T_bot: return t ? e.world().bot(t) : e.world().type_bot();
165 case Tag::T_top: return t ? e.world().top(t) : e.world().type_top();
166 default: fe::unreachable();
167 }
168 // clang-format on
169}
170
172 if (is_where())
173 for (const auto& decl : decls() | std::ranges::views::reverse) decl->emit(e);
174 else
175 for (const auto& decl : decls()) decl->emit(e);
176 return expr()->emit(e);
177}
178
179Ref BlockExpr::emit_(Emitter& e) const { return expr()->emit(e); }
180
182 auto d = dom()->emit(e);
183 auto c = codom()->emit(e);
184 return e.world().pi(d, c);
185}
186
188 pi_ = decl_ ? decl_ : e.world().mut_pi(e.world().type_infer_univ(), is_implicit());
189 auto dom_t = ptrn()->emit_type(e);
190
191 if (ret()) {
192 auto sigma = e.world().mut_sigma(2)->set(loc());
193 auto var = sigma->var()->set(ret()->loc().anew_begin());
194 sigma->set(0, dom_t);
195 ptrn()->emit_value(e, var->proj(2, 0));
196 auto ret_t = e.world().cn(ret()->emit_type(e));
197 sigma->set(1, ret_t);
198
199 if (auto imm = sigma->immutabilize())
200 dom_t = imm;
201 else
202 dom_t = sigma;
203 pi_->set_dom(dom_t);
204 } else {
205 pi_->set_dom(dom_t);
206 ptrn()->emit_value(e, pi_->var());
207 }
208}
209
211 const auto& first = doms().front();
212 return first->decl_ = e.world().mut_pi(type, first->is_implicit())->set(loc());
213}
214
215void PiExpr::emit_body(Emitter& e, Ref) const { emit(e); }
216
218 for (const auto& dom : doms()) dom->emit_type(e);
219
220 auto cod = codom() ? codom()->emit(e) : e.world().type_bot();
221 for (const auto& dom : doms() | std::ranges::views::reverse) {
222 dom->pi_->set_codom(cod);
223 cod = dom->pi_;
224 }
225
226 return doms().front()->pi_;
227}
228
229Ref LamExpr::emit_decl(Emitter& e, Ref) const { return lam()->emit_decl(e), lam()->def(); }
230void LamExpr::emit_body(Emitter& e, Ref) const { lam()->emit_body(e); }
231
233 auto res = emit_decl(e, {});
234 emit_body(e, {});
235 return res;
236}
237
239 auto c = callee()->emit(e);
240 auto a = arg()->emit(e);
241 return is_explicit() ? e.world().app(c, a) : e.world().iapp(c, a);
242}
243
245 auto c = callee()->emit(e);
246 if (auto cn = Pi::ret_pi(c->type())) {
247 auto con = e.world().mut_lam(cn);
248 auto pair = e.world().tuple({arg()->emit(e), con});
249 auto app = e.world().app(c, pair)->set(c->loc() + arg()->loc());
250 ptrn()->emit_value(e, con->var());
251 con->set(false, body()->emit(e));
252 return app;
253 }
254
255 error(c->loc(), "callee of a .ret expression must type as a returning continuation but got '{}' of type '{}'", c,
256 c->type());
257}
258
259Ref SigmaExpr::emit_decl(Emitter& e, Ref type) const { return ptrn()->emit_decl(e, type); }
260void SigmaExpr::emit_body(Emitter& e, Ref decl) const { ptrn()->emit_body(e, decl); }
261Ref SigmaExpr::emit_(Emitter& e) const { return ptrn()->emit_type(e); }
262
264 DefVec elems(num_elems(), [&](size_t i) { return elem(i)->emit(e); });
265 return e.world().tuple(elems);
266}
267
268template<bool arr> Ref ArrOrPackExpr<arr>::emit_(Emitter& e) const {
269 auto s = shape()->emit_type(e);
270 if (shape()->dbg().is_anon()) { // immutable
271 auto b = body()->emit(e);
272 return arr ? e.world().arr(s, b) : e.world().pack(s, b);
273 }
274
275 auto t = e.world().type_infer_univ();
276 auto a = e.world().mut_arr(t);
277 a->set_shape(s);
278
279 if (arr) {
280 auto var = a->var();
281 shape()->emit_value(e, var);
282 a->set_body(body()->emit(e));
283 if (auto imm = a->immutabilize()) return imm;
284 return a;
285 } else {
286 auto p = e.world().mut_pack(a);
287 auto var = p->var();
288 shape()->emit_value(e, var);
289 auto b = body()->emit(e);
290 a->set_body(b->type());
291 p->set(b);
292 if (auto imm = p->immutabilize()) return imm;
293 return p;
294 }
295}
296
297template Ref ArrOrPackExpr<true>::emit_(Emitter&) const;
299
301 auto tup = tuple()->emit(e);
302 if (auto dbg = std::get_if<Dbg>(&index())) {
303 if (auto sigma = tup->type()->isa_mut<Sigma>()) {
304 if (auto i = e.sigma2sym2idx.find(sigma); i != e.sigma2sym2idx.end()) {
305 auto sigma = i->first->as_mut<Sigma>();
306 const auto& sym2idx = i->second;
307 if (auto i = sym2idx.find(dbg->sym()); i != sym2idx.end())
308 return e.world().extract(tup, sigma->num_ops(), i->second);
309 }
310 }
311
312 if (decl()) return e.world().extract(tup, decl()->def());
313 error(dbg->loc(), "cannot resolve index '{}' for extraction", dbg);
314 }
315
316 auto expr = std::get<Ptr<Expr>>(index()).get();
317 auto i = expr->emit(e);
318 return e.world().extract(tup, i);
319}
320
322 auto t = tuple()->emit(e);
323 auto i = index()->emit(e);
324 auto v = value()->emit(e);
325 return e.world().insert(t, i, v);
326}
327
328/*
329 * Decl
330 */
331
332void AxiomDecl::emit(Emitter& e) const {
333 thorin_type_ = type()->emit(e);
334 auto& id = annex_->id;
335
336 std::tie(id.curry, id.trip) = Axiom::infer_curry_and_trip(thorin_type_);
337 if (curry_) {
338 if (curry_.lit_u() > id.curry)
339 error(curry_.loc(), "curry counter cannot be greater than {}", id.curry);
340 else
341 id.curry = curry_.lit_u();
342 }
343
344 if (trip_) {
345 if (trip_.lit_u() > id.curry)
346 error(trip_.loc(), "trip counter cannot be greater than curry counter '{}'", (int)id.curry);
347 else
348 id.trip = trip_.lit_u();
349 }
350
351 auto pi = thorin_type_->isa<Pi>();
352 if (!annex_->pi)
353 annex_->pi = pi;
354 else if (bool(pi) ^ bool(*annex_->pi))
355 error(dbg().loc(), "all declarations of annex '{}' have to be function types if any is", dbg().sym());
356
357 if (num_subs() == 0) {
358 auto norm = e.driver().normalizer(id.plugin, id.tag, 0);
359 auto axiom = e.world().axiom(norm, id.curry, id.trip, thorin_type_, id.plugin, id.tag, 0)->set(dbg());
360 def_ = axiom;
361 e.world().register_annex(id.plugin, id.tag, 0, axiom);
362 } else {
363 sub_t offset = annex_->subs.size();
364 for (sub_t i = 0, n = num_subs(); i != n; ++i) {
365 auto& aliases = annex_->subs.emplace_back(std::deque<Sym>());
366 sub_t s = i + offset;
367 auto norm = e.driver().normalizer(id.plugin, id.tag, s);
368 auto name = e.world().sym(dbg().sym().str() + "."s + sub(i).front()->dbg().sym().str());
369 auto axiom = e.world().axiom(norm, id.curry, id.trip, thorin_type_, id.plugin, id.tag, s)->set(name);
370 e.world().register_annex(id.plugin, id.tag, s, axiom);
371
372 for (const auto& alias : sub(i)) {
373 alias->def_ = axiom;
374 aliases.emplace_back(alias->dbg().sym());
375 }
376 }
377 }
378}
379
380void LetDecl::emit(Emitter& e) const {
381 auto v = value()->emit(e);
382 def_ = ptrn()->emit_value(e, v);
383 e.register_annex(annex_, sub_, def_);
384}
385
386void RecDecl::emit(Emitter& e) const {
387 for (auto curr = this; curr; curr = curr->next()) curr->emit_decl(e);
388 for (auto curr = this; curr; curr = curr->next()) curr->emit_body(e);
389}
390
392 auto t = type() ? type()->emit(e) : e.world().type_infer_univ();
393 def_ = body()->emit_decl(e, t);
394 def_->set(dbg());
395}
396
398 body()->emit_body(e, def_);
399 // TODO immutabilize?
400 e.register_annex(annex_, sub_, def_);
401}
402
404 lam_ = e.world().mut_lam(pi_);
405 auto var = lam_->var();
406
407 if (ret()) {
408 ptrn()->emit_value(e, var->proj(2, 0));
409 ret()->emit_value(e, var->proj(2, 1));
410 } else {
411 ptrn()->emit_value(e, var);
412 }
413
414 return lam_;
415}
416
418 auto _ = e.world().push(loc());
419 bool is_cps = tag_ == Tag::K_cn || tag_ == Tag::K_con || tag_ == Tag::K_fn || tag_ == Tag::K_fun;
420
421 // Iterate over all doms: Build a Lam for cur dom, by first building a curried Pi for the remaining doms.
422 for (size_t i = 0, n = num_doms(); i != n; ++i) {
423 for (const auto& dom : doms() | std::ranges::views::drop(i)) dom->emit_type(e);
424 auto cod = codom() ? codom()->emit(e) : is_cps ? e.world().type_bot() : e.world().mut_infer_type();
425
426 for (const auto& dom : doms() | std::ranges::views::drop(i) | std::ranges::views::reverse) {
427 dom->pi_->set_codom(cod);
428 cod = dom->pi_;
429 }
430
431 auto cur = dom(i);
432 auto lam = cur->emit_value(e);
433 auto filter = cur->filter() ? cur->filter()->emit(e)
434 : i + 1 == n && is_cps ? e.world().lit_ff()
435 : e.world().lit_tt();
436 lam->set_filter(filter);
437
438 if (i == 0)
439 def_ = lam->set(dbg().sym());
440 else
441 dom(i - 1)->lam_->set_body(lam);
442 }
443}
444
446 doms().back()->lam_->set_body(body()->emit(e));
447 if (is_external()) doms().front()->lam_->make_external();
448 e.register_annex(annex_, sub_, def_);
449}
450
451void CDecl::emit(Emitter& e) const {
452 auto dom_t = dom()->emit_type(e);
453 if (tag() == Tag::K_cfun) {
454 auto ret_t = codom()->emit(e);
455 def_ = e.world().mut_fun(dom_t, ret_t)->set(dbg());
456 } else {
457 def_ = e.world().mut_con(dom_t)->set(dbg());
458 }
459}
460
461} // namespace thorin::ast
static std::pair< u8, u8 > infer_curry_and_trip(const Def *type)
Definition axiom.cpp:14
Ref var(nat_t a, nat_t i)
Definition def.h:401
T * as_mut() const
Asserts that this is a mutable, casts constness away and performs a static_cast to T.
Definition def.h:455
Def * set(size_t i, const Def *def)
Successively set from left to right.
Definition def.cpp:248
const Def * proj(nat_t a, nat_t i) const
Similar to World::extract while assuming an arity of a, but also works on Sigmas and Arrays.
Definition def.cpp:520
Some "global" variables needed all over the place.
Definition driver.h:17
A function.
Definition lam.h:97
A dependent function type.
Definition lam.h:11
Pi * set_dom(Ref dom)
Definition lam.h:74
Pi * set_codom(Ref codom)
Definition lam.h:76
const Pi * ret_pi() const
Yields the last Pi::dom, if it Pi::isa_basicblock.
Definition lam.cpp:13
Helper class to retrieve Infer::arg if present.
Definition def.h:85
A dependent tuple type.
Definition tuple.h:9
Sigma * set(size_t i, const Def *def)
Definition tuple.h:20
const Def * immutabilize() override
Tries to make an immutable from a mutable.
Definition def.cpp:168
The World represents the whole program and manages creation of Thorin nodes (Defs).
Definition world.h:33
const Driver & driver() const
Definition world.h:81
const Def * register_annex(flags_t f, const Def *)
Definition world.cpp:80
World & world()
Definition ast.h:61
Ref emit_(Emitter &) const override
Definition emit.cpp:238
Ref emit_(Emitter &) const override
Definition emit.cpp:268
Ref emit_(Emitter &) const override
Definition emit.cpp:181
void emit(Emitter &) const override
Definition emit.cpp:332
const Expr * expr() const
Definition ast.h:366
Ref emit_(Emitter &) const override
Definition emit.cpp:179
void emit(Emitter &) const override
Definition emit.cpp:451
const auto & decls() const
Definition ast.h:386
Ref emit_(Emitter &) const override
Definition emit.cpp:171
bool is_where() const
Definition ast.h:387
const Expr * expr() const
Definition ast.h:388
Ref def() const
Definition ast.h:151
absl::node_hash_map< Sigma *, fe::SymMap< size_t >, GIDHash< const Def * >, GIDEq< const Def * > > sigma2sym2idx
Definition emit.cpp:25
void register_annex(AnnexInfo *annex, sub_t sub, Ref def)
Definition emit.cpp:18
Emitter(AST &ast)
Definition emit.cpp:11
World & world()
Definition emit.cpp:15
Driver & driver()
Definition emit.cpp:16
AST & ast() const
Definition emit.cpp:14
Ref emit_(Emitter &) const override
Definition emit.cpp:115
virtual Ref emit_(Emitter &) const =0
Ref emit(Emitter &) const
Definition emit.cpp:110
Ref emit_(Emitter &) const override
Definition emit.cpp:300
Ref emit_type(Emitter &) const override
Definition emit.cpp:73
const IdPtrn * id() const
Definition ast.h:228
const Decl * decl() const
Definition ast.h:304
Ref emit_(Emitter &) const override
Definition emit.cpp:118
const Expr * type() const
Definition ast.h:202
Ref emit_type(Emitter &) const override
Definition emit.cpp:68
const Module * module() const
Definition ast.h:915
void emit(Emitter &) const
Definition emit.cpp:47
Ref emit_(Emitter &) const override
Definition emit.cpp:116
Ref emit_(Emitter &) const override
Definition emit.cpp:321
Lam * emit_value(Emitter &) const
Definition emit.cpp:403
void emit_decl(Emitter &) const override
Definition emit.cpp:417
void emit_body(Emitter &) const override
Definition emit.cpp:445
Ref emit_(Emitter &) const override
Definition emit.cpp:232
void emit_body(Emitter &, Ref decl) const override
Definition emit.cpp:230
Ref emit_decl(Emitter &, Ref type) const override
Definition emit.cpp:229
void emit(Emitter &) const override
Definition emit.cpp:380
Ref emit_(Emitter &) const override
Definition emit.cpp:154
Tok::Tag tag() const
Definition ast.h:345
const Expr * type() const
Definition ast.h:346
Tok tok() const
Definition ast.h:344
void emit(AST &) const
Definition emit.cpp:35
const auto & decls() const
Definition ast.h:943
const auto & imports() const
Definition ast.h:942
const auto & implicit_imports() const
Definition ast.h:941
Loc loc() const
Definition ast.h:121
const IdPtrn * ret() const
Definition ast.h:458
const Ptrn * ptrn() const
Definition ast.h:457
bool is_implicit() const
Definition ast.h:456
virtual void emit_type(Emitter &) const
Definition emit.cpp:187
void emit_body(Emitter &, Ref decl) const override
Definition emit.cpp:215
Ref emit_decl(Emitter &, Ref type) const override
Definition emit.cpp:210
Ref emit_(Emitter &) const override
Definition emit.cpp:217
virtual Ref emit_type(Emitter &) const =0
Dbg dbg() const
Definition ast.h:179
Ref emit_value(Emitter &, Ref) const
Definition emit.cpp:53
virtual void emit_value_(Emitter &, Ref) const
Definition ast.h:189
virtual void emit_body(Emitter &) const
Definition emit.cpp:397
void emit(Emitter &) const override
Definition emit.cpp:386
virtual void emit_decl(Emitter &) const
Definition emit.cpp:391
Ref emit_(Emitter &) const override
Definition emit.cpp:244
Ref emit_(Emitter &) const override
Definition emit.cpp:261
Ref emit_decl(Emitter &, Ref type) const override
Definition emit.cpp:259
void emit_body(Emitter &, Ref decl) const override
Definition emit.cpp:260
const Lit * lit_i() const
Definition tok.h:175
Ref emit_(Emitter &) const override
Definition emit.cpp:263
Ref emit_decl(Emitter &, Ref type) const
Definition emit.cpp:100
Ref emit_type(Emitter &) const override
Definition emit.cpp:75
const Ptrn * ptrn(size_t i) const
Definition ast.h:252
size_t num_ptrns() const
Definition ast.h:253
Ref emit_body(Emitter &, Ref decl) const
Definition emit.cpp:77
void emit_value_(Emitter &, Ref) const override
Definition emit.cpp:60
const Expr * level() const
Definition ast.h:408
Ref emit_(Emitter &) const override
Definition emit.cpp:123
Tok::Tag Tag
Definition bind.cpp:7
u8 sub_t
Definition types.h:49
void error(Loc loc, const char *f, Args &&... args)
Definition dbg.h:122
Sym sym() const
Definition dbg.h:145
struct thorin::ast::AnnexInfo::@1 id