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