MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
emit.cpp
Go to the documentation of this file.
1#include "mim/def.h"
2#include "mim/rewrite.h"
3
4#include "mim/ast/ast.h"
5
6#include "family.h"
7
8using namespace std::literals;
9
10namespace mim::ast {
11
12using Tag = Tok::Tag;
13
14class Emitter {
15public:
17 : ast_(ast) {}
18
19 AST& ast() const { return ast_; }
20 World& world() { return ast().world(); }
21 Driver& driver() { return world().driver(); }
22 fe::Error& error() { return driver().error(); }
23
24 /// @p name is *this* registration's own (unqualified) Dbg::sym; AnnexInfo::qualified turns it into the
25 /// full `plugin.tag[.sub]` name. We must take it from the declaration rather than from Def::sym, since
26 /// hash-consing can make several annexes share a single Def (e.g. `mod foo { anx let bar = 23; anx let baz = 23;
27 /// }`).
28 void attach(AnnexInfo* annex, sub_t sub, Sym name, const Def* def) {
29 if (annex)
30 world().annexes().attach(annex->plugin_id(), annex->id.tag, sub, annex->qualified(driver(), name), def);
31 }
32
33 absl::node_hash_map<Sigma*, fe::SymMap<size_t>, GIDHash<const Def*>> sigma2sym2idx;
34
35private:
36 AST& ast_;
37};
38
39/*
40 * File
41 */
42
43void File::emit(AST& ast) const {
44 auto emitter = Emitter(ast);
45 emit(emitter);
46}
47
48void File::emit(Emitter& e) const {
49 if (emitted_) return;
50 emitted_ = true;
51
52 auto _ = e.world().push(loc());
53 for (auto import : implicit_imports())
54 import->emit(e);
55 emit_decls(e);
56}
57
58void UseDecl::emit(Emitter& e) const {
59 if (file()) file()->emit(e);
60}
61
62/*
63 * Ptrn::emit_value
64 */
65
66const Def* ErrorPtrn::emit_value(Emitter&, const Def* def) const { return def; }
67
68const Def* IdPtrn::emit_value(Emitter& e, const Def* def) const {
69 emit_type(e);
70 return def_ = def->set(dbg());
71}
72
73const Def* GrpPtrn::emit_value(Emitter&, const Def* def) const { return def_ = def->set(dbg()); }
74
75const Def* AliasPtrn::emit_value(Emitter& e, const Def* def) const {
76 return def_ = ptrn()->emit_value(e, def)->set(dbg());
77}
78
79const Def* Ptrn::emit_proj(Emitter& e, const Def* def, size_t n, size_t i) const {
80 auto _ = e.world().push(loc());
81 return emit_value(e, def->proj(n, i));
82}
83
84const Def* TuplePtrn::emit_value(Emitter& e, const Def* def) const {
85 auto _ = e.world().push(loc());
86 emit_type(e);
87 for (size_t i = 0, n = num_ptrns(); i != n; ++i)
88 ptrn(i)->emit_proj(e, def, n, i);
89 return def_ = def;
90}
91
92/*
93 * Ptrn::emit_Type
94 */
95
96const Def* ErrorPtrn::emit_type(Emitter&) const { fe::unreachable(); }
97
98const Def* IdPtrn::emit_type(Emitter& e) const {
99 auto _ = e.world().push(loc());
100 return type() ? type()->emit(e) : e.world().mut_hole_type();
101}
102
103const Def* AliasPtrn::emit_type(Emitter& e) const { return ptrn()->emit_type(e); }
104
105const Def* GrpPtrn::emit_type(Emitter& e) const { return id()->emit_type(e); }
106
107const Def* TuplePtrn::emit_type(Emitter& e) const { return emit_body(e, {}); }
108
109const Def* TuplePtrn::emit_body(Emitter& e, const Def* decl) const {
110 auto _ = e.world().push(loc());
111 auto n = num_ptrns();
112 Sigma* sigma;
113 if (decl) {
114 sigma = decl->as_mut<Sigma>();
115 } else {
116 auto type = e.world().type_infer_univ();
117 sigma = e.world().mut_sigma(type, n);
118 }
119 auto var = sigma->var();
120 auto& sym2idx = e.sigma2sym2idx[sigma];
121
122 for (size_t i = 0; i != n; ++i) {
123 sigma->set(i, ptrn(i)->emit_type(e));
124 ptrn(i)->emit_proj(e, var, n, i);
125 if (auto id = ptrn(i)->isa<IdPtrn>(); id && !id->dbg().is_anon()) sym2idx[id->dbg().sym()] = i;
126 }
127
128 if (auto imm = sigma->immutabilize()) return imm;
129 return sigma;
130}
131
132const Def* TuplePtrn::emit_decl(Emitter& e, const Def* type) const {
133 auto _ = e.world().push(loc());
134 type = type ? type : e.world().type_infer_univ();
135 return e.world().mut_sigma(type, num_ptrns());
136}
137
138/*
139 * Expr
140 */
141
142const Def* Expr::emit(Emitter& e) const {
143 auto _ = e.world().push(loc());
144 return emit_(e);
145}
146
147const Def* Expr::emit_decl(Emitter& e, const Def* type) const {
148 auto _ = e.world().push(loc());
149 return emit_decl_(e, type);
150}
151
152void Expr::emit_body(Emitter& e, const Def* decl) const {
153 auto _ = e.world().push(loc());
154 emit_body_(e, decl);
155}
156
157const Def* ErrorExpr::emit_(Emitter&) const { fe::unreachable(); }
158const Def* HoleExpr::emit_(Emitter& e) const { return e.world().mut_hole_type(); }
159
160const Def* PathExpr::emit_(Emitter& e) const {
161 assert(decl());
162 if (auto def = decl()->def()) return def;
163 e.error().e(loc(), "`{}` is a module and not a value", dbg().sym()).bail();
164}
165
166const Def* TypeExpr::emit_(Emitter& e) const {
167 auto l = level()->emit(e);
168 return e.world().type(l);
169}
170
171const Def* RuleExpr::emit_(Emitter& e) const {
172 auto m = dom()->emit(e);
173 return e.world().reform(m);
174}
175
176const Def* PrimaryExpr ::emit_(Emitter& e) const {
177 // clang-format off
178 switch (tag()) {
179 case Tag::K_Univ: return e.world().univ();
180 case Tag::K_Nat: return e.world().type_nat();
181 case Tag::K_Idx: return e.world().type_idx();
182 case Tag::K_Bool: return e.world().type_bool();
183 case Tag::K_ff: return e.world().lit_ff();
184 case Tag::K_tt: return e.world().lit_tt();
185 case Tag::K_i1: return e.world().lit_i1();
186 case Tag::K_i8: return e.world().lit_i8();
187 case Tag::K_i16: return e.world().lit_i16();
188 case Tag::K_i32: return e.world().lit_i32();
189 case Tag::K_i64: return e.world().lit_i64();
190 case Tag::K_I1: return e.world().type_i1();
191 case Tag::K_I8: return e.world().type_i8();
192 case Tag::K_I16: return e.world().type_i16();
193 case Tag::K_I32: return e.world().type_i32();
194 case Tag::K_I64: return e.world().type_i64();
195 case Tag::T_star: return e.world().type<0>();
196 case Tag::T_box: return e.world().type<1>();
197 default: fe::unreachable();
198 }
199 // clang-format on
200}
201
202/// If @p type is a `math.F` type of known precision/exponent, yields its bit width.
203/// Note that libmim must not depend on the generated math plugin header, so lookup the Axm at runtime instead.
204static std::optional<nat_t> isa_math_f(Emitter& e, const Def* type) {
205 auto math_f = e.world().annex(e.world().sym("math.F"));
206 if (auto app = type->zonk()->isa<App>(); math_f && app && app->callee() == math_f) {
207 if (auto [p, ex] = app->arg()->projs<2>([](auto op) { return Lit::isa(op); }); p && ex) {
208 if (*p == 10 && *ex == 5) return 16;
209 if (*p == 23 && *ex == 8) return 32;
210 if (*p == 52 && *ex == 11) return 64;
211 }
212 }
213 return {};
214}
215
216/// A float Tok stores its value as mim::f64 bits; re-encode them for the width of the annotated type @p t.
217static u64 encode_f(Emitter& e, [[maybe_unused]] Loc loc, const Def* t, u64 bits) {
218 if (auto width = isa_math_f(e, t)) {
219 auto val = std::bit_cast<f64>(bits);
220 switch (*width) {
221#if defined(__STDCPP_FLOAT16_T__)
222 case 16: return std::bit_cast<u16>(f16(val));
223#else
224 case 16: e.error().e(loc, "16-bit floating-point literals are not supported on this platform").bail();
225#endif
226 case 32: return std::bit_cast<u32>(f32(val));
227 default: break;
228 }
229 }
230 return bits;
231}
232
233const Def* LitExpr::emit_(Emitter& e) const {
234 auto t = type() ? type()->emit(e) : nullptr;
235 // clang-format off
236 switch (tag()) {
237 case Tag::L_f: return t ? e.world().lit(t, encode_f(e, loc(), t, tok().lit_u())) : e.world().lit_nat(tok().lit_u());
238 case Tag::L_s:
239 case Tag::L_u: return t ? e.world().lit(t, tok().lit_u()) : e.world().lit_nat(tok().lit_u());
240 case Tag::L_i: { auto [size, val] = tok().lit_i(); return e.world().lit_idx(size, val); }
241 case Tag::L_c: return e.world().lit_i8(tok().lit_c());
242 case Tag::L_str: return e.world().tuple(tok().sym());
243 case Tag::T_bot: return t ? e.world().bot(t) : e.world().type_bot();
244 case Tag::T_top: return t ? e.world().top(t) : e.world().type_top();
245 default: fe::unreachable();
246 }
247 // clang-format on
248}
249
250const Def* DeclExpr::emit_(Emitter& e) const {
251 if (is_where())
252 for (auto decl : decls() | std::views::reverse)
253 decl->emit(e);
254 else
255 for (auto decl : decls())
256 decl->emit(e);
257 return expr()->emit(e);
258}
259
260const Def* InfixExpr::emit_decl_(Emitter& e, const Def* type) const {
261 assert(op().isa(Tag::T_arrow_r));
262 return pi_ = e.world().mut_pi(type, false);
263}
264
265void InfixExpr::emit_body_(Emitter& e, const Def*) const {
266 pi_->set_dom(lhs()->emit(e));
267 pi_->set_codom(rhs()->emit(e)); // TODO try to immutabilize
268}
269
270/// `a ∪ b ∪ c` is one n-ary Join, so flatten the left spine the left-associative parse built.
271static void emit_union(Emitter& e, const Expr* expr, DefVec& types) {
272 if (auto infix = InfixExpr::isa_op(Tag::T_union, expr)) {
273 emit_union(e, infix->lhs(), types);
274 types.emplace_back(infix->rhs()->emit(e));
275 } else {
276 types.emplace_back(expr->emit(e));
277 }
278}
279
280const Def* InfixExpr::emit_index(Emitter& e, const Def* tup) const {
281 auto& w = e.world();
282 // A simple path names a field of tup's Sigma before anything the binder resolved it to.
283 if (auto path = rhs()->isa<PathExpr>(); path && path->path()->dbgs().size() == 1) {
284 auto dbg = path->dbg();
285 if (auto mut = tup->type()->isa_mut<Sigma>()) {
286 if (auto i = e.sigma2sym2idx.find(mut); i != e.sigma2sym2idx.end()) {
287 auto sigma = i->first->as_mut<Sigma>();
288 const auto& sym2idx = i->second;
289 if (auto i = sym2idx.find(dbg.sym()); i != sym2idx.end()) return w.lit_idx(sigma->num_ops(), i->second);
290 }
291 }
292 if (!path->decl()) e.error().e(dbg.loc(), "cannot resolve field `{}` for extraction", dbg).bail();
293 }
294 return rhs()->emit(e);
295}
296
297const Def* InfixExpr::emit_(Emitter& e) const {
298 auto& w = e.world();
299
300 switch (op().tag()) {
301 case Tag::T_union: {
302 DefVec types;
303 emit_union(e, this, types);
304 return w.join(types);
305 }
306 case Tag::T_extract: {
307 auto tup = lhs()->emit(e);
308 return w.extract(tup, emit_index(e, tup));
309 }
310 case Tag::T_arrow_l: {
311 fe::Vector<const InfixExpr*> exs;
312 auto base = lhs();
313 while (auto ex = InfixExpr::isa_op(Tag::T_extract, base)) {
314 exs.emplace_back(ex);
315 base = ex->lhs();
316 }
317
318 if (exs.empty())
319 e.error()
320 .e(lhs()->loc(), "expected `#` on the left-hand side of `{}`", Tok::tag2str(op().tag()))
321 .n("an update needs a component, as in `tuple#index {} value`", Tok::tag2str(op().tag()))
322 .bail();
323
324 auto tup = base->emit(e);
325 DefVec tups, idxs;
326 for (auto ex : exs | std::views::reverse) {
327 auto idx = ex->emit_index(e, tup);
328 tups.emplace_back(tup);
329 idxs.emplace_back(idx);
330 tup = w.extract(tup, idx);
331 }
332
333 auto val = rhs()->emit(e);
334 for (size_t i = tups.size(); i-- != 0;)
335 val = w.insert(tups[i], idxs[i], val);
336 return val;
337 }
338 default: break;
339 }
340
341 auto c = callee() ? callee()->emit(e) : nullptr;
342 auto l = lhs()->emit(e);
343 auto r = rhs()->emit(e);
344
345 switch (op().tag()) {
346 case Tag::T_arrow_r: return w.pi(l, r);
347 case Tag::T_at: return w.app(l, r);
348 case Tag::K_inj: return w.inj(r, l);
349 default: return w.implicit_app(c, w.tuple({l, r})); // MIM_INFIX_SUGAR
350 }
351}
352
354 auto _ = e.world().push(loc());
355 auto dom_t = ptrn()->emit_type(e);
356 auto pi = e.world().pi(dom_t, e.world().mut_hole_type());
357 auto lam = e.world().mut_lam(pi);
358 ptrn()->emit_value(e, lam->var());
359 return lam->set(true, body()->emit(e));
360}
361
362const Def* MatchExpr::emit_(Emitter& e) const {
363 DefVec res;
364 res.emplace_back(scrutinee()->emit(e));
365 for (auto arm : arms())
366 res.emplace_back(arm->emit(e));
367 return e.world().match(res);
368}
369
371 // Created before the push: the Pi belongs to the whole function type, not just to this Dom.
372 pi_ = decl_ ? decl_ : e.world().mut_pi(e.world().type_infer_univ(), is_implicit());
373 auto _ = e.world().push(loc());
374 auto dom_t = ptrn()->emit_type(e);
375
376 if (ret()) {
377 auto sigma = e.world().mut_sigma(2);
378 auto var = sigma->var();
379 sigma->set(0, dom_t);
380 ptrn()->emit_proj(e, var, 2, 0);
381 auto ret_t = e.world().cn(ret()->emit_type(e));
382 sigma->set(1, ret_t);
383
384 if (auto imm = sigma->immutabilize())
385 dom_t = imm;
386 else
387 dom_t = sigma;
388 pi_->set_dom(dom_t);
389 } else {
390 pi_->set_dom(dom_t);
391 ptrn()->emit_value(e, pi_->var());
392 }
393}
394
395const Def* PiExpr::emit_decl_(Emitter& e, const Def* type) const {
396 return dom()->decl_ = e.world().mut_pi(type, dom()->is_implicit());
397}
398
399void PiExpr::emit_body_(Emitter& e, const Def*) const { emit(e); }
400
401const Def* PiExpr::emit_(Emitter& e) const {
402 dom()->emit_type(e);
403 auto cod = codom() ? codom()->emit(e) : e.world().type_bot();
404 auto pi = dom()->pi_->set_codom(cod);
405 if (auto imm = pi->immutabilize()) return imm;
406 return pi;
407}
408
409const Def* LamExpr::emit_decl_(Emitter& e, const Def*) const { return lam()->emit_decl(e), lam()->def(); }
410void LamExpr::emit_body_(Emitter& e, const Def*) const { lam()->emit_body(e); }
411
412const Def* LamExpr::emit_(Emitter& e) const {
413 auto res = emit_decl(e, {});
414 emit_body(e, {});
415 return res;
416}
417
418const Def* AppExpr::emit_(Emitter& e) const {
419 auto c = callee()->emit(e);
420 auto a = arg()->emit(e);
421 return e.world().implicit_app(c, a);
422}
423
424const Def* RetExpr::emit_(Emitter& e) const {
425 auto c = callee()->emit(e);
426 if (auto cn = Pi::has_ret_pi(c->type())) {
427 auto con = e.world().mut_lam(cn);
428 auto pair = e.world().tuple({arg()->emit(e), con});
429 auto app = e.world().app(c, pair);
430 ptrn()->emit_value(e, con->var());
431 con->set(false, body()->emit(e));
432 return app;
433 }
434
435 e.error()
436 .e(callee()->loc(), "callee of a `ret` expression must be a returning continuation, but `{}` has type `{}`", c,
437 c->type())
438 .bail();
439}
440
441const Def* SigmaExpr::emit_decl_(Emitter& e, const Def* type) const { return ptrn()->emit_decl(e, type); }
442void SigmaExpr::emit_body_(Emitter& e, const Def* decl) const { ptrn()->emit_body(e, decl); }
443const Def* SigmaExpr::emit_(Emitter& e) const { return ptrn()->emit_type(e); }
444
445const Def* TupleExpr::emit_(Emitter& e) const {
446 DefVec elems(num_elems(), [&](size_t i) { return elem(i)->emit(e); });
447 return e.world().tuple(elems);
448}
449
450const Def* SeqExpr::emit_(Emitter& e) const {
451 auto s = arity()->emit_type(e);
452 if (auto lit_s = Lit::isa(s); lit_s && *lit_s == 0) return e.world().unit(is_pack());
453
454 if (arity()->dbg().is_anon()) { // immutable
455 auto b = body()->emit(e);
456 return e.world().seq(is_pack(), s, b);
457 }
458
459 auto t = e.world().type_infer_univ();
460 auto a = e.world().mut_arr(t);
461 a->set_arity(s);
462
463 if (is_pack()) {
464 auto p = e.world().mut_pack(a);
465 auto var = p->var();
466 arity()->emit_value(e, var);
467 auto b = body()->emit(e);
468 p->set(b);
469 auto arr_b = b->type();
470 if (auto pvar = var->isa<Var>())
471 // Use array var in array body instead of pack var
472 arr_b = VarRewriter(pvar, a->var()).rewrite(arr_b);
473 a->set_body(arr_b);
474 if (auto imm = p->immutabilize()) return imm;
475 return p;
476 } else {
477 auto var = a->var();
478 arity()->emit_value(e, var);
479 a->set_body(body()->emit(e));
480 if (auto imm = a->immutabilize()) return imm;
481 return a;
482 }
483}
484
485const Def* UniqExpr::emit_(Emitter& e) const { return e.world().uniq(inhabitant()->emit(e)); }
486
487/*
488 * Decl
489 */
490
491void AxmDecl::emit(Emitter& e) const {
492 if (!annex_) return; // Skip emit if binding failed
493 auto _ = e.world().push(loc());
494 mim_type_ = type()->emit(e);
495 auto& id = annex_->id;
496 auto plugin = annex_->plugin_id();
497
498 std::tie(id.curry, id.trip) = Axm::infer_curry_and_trip(mim_type_);
499 if (curry_) {
500 if (curry_.lit_u() > id.curry)
501 e.error().e(curry_.loc(), "curry counter cannot be greater than {}", id.curry).bail();
502 else
503 id.curry = curry_.lit_u();
504 }
505
506 if (trip_) {
507 if (trip_.lit_u() > id.curry)
508 e.error().e(trip_.loc(), "trip counter cannot be greater than curry counter {}", (int)id.curry).bail();
509 else
510 id.trip = trip_.lit_u();
511 }
512
513 auto norm = e.driver().normalizer(plugin, id.tag, sub_);
514 auto name = annex_->qualified(e.driver(), dbg().sym());
515 auto axm = e.world().axm(norm, id.curry, id.trip, mim_type_, plugin, id.tag, sub_)->set(name);
516 def_ = axm;
517 e.world().annexes().attach(plugin, id.tag, sub_, name, axm);
518}
519
521 if (!annex_) return; // skip emit if binding failed
522 auto& id = annex_->id;
523 auto plugin = annex_->plugin_id();
524 auto norm = e.driver().normalizer(plugin, id.tag, sub_);
525 auto name = annex_->qualified(e.driver(), dbg().sym());
526 auto axm = e.world().axm(norm, id.curry, id.trip, owner()->mim_type(), plugin, id.tag, sub_)->set(name);
527 def_ = axm;
528 e.world().annexes().attach(plugin, id.tag, sub_, name, axm);
529}
530
531void AliasDecl::emit(Emitter& e) const {
532 if (!annex_) return; // skip emit if binding failed
533 auto target = path()->decl();
534 def_ = target->def();
535 auto name = annex_->qualified(e.driver(), dbg().sym());
536 e.world().annexes().attach_alias(annex_->plugin_id(), annex_->id.tag, sub_, name);
537}
538
540 for (auto decl : decls())
541 decl->emit(e);
542}
543
544void ModDecl::emit(Emitter& e) const { emit_decls(e); }
545
546void LetDecl::emit(Emitter& e) const {
547 auto _ = e.world().push(loc());
548 auto v = value()->emit(e);
549 def_ = ptrn()->emit_value(e, v);
550 if (auto id = ptrn()->isa<IdPtrn>()) e.attach(id->annex_, id->sub_, id->dbg().sym(), def_);
551}
552
553void RecDecl::emit(Emitter& e) const {
554 for (auto curr = this; curr; curr = curr->next())
555 curr->emit_decl(e);
556 for (auto curr = this; curr; curr = curr->next())
557 curr->emit_body(e);
558}
559
561 auto _ = e.world().push(loc());
562 def_ = body()->emit_decl(e, e.world().type_infer_univ());
563 def_->set(dbg().sym());
564}
565
567 auto _ = e.world().push(loc());
568 body()->emit_body(e, def_);
569 // TODO immutabilize?
570 e.attach(annex_, sub_, dbg().sym(), def_);
571}
572
574 // Created before the push: the Lam belongs to the whole declaration, not just to this Dom.
575 lam_ = e.world().mut_lam(pi_);
576 auto _ = e.world().push(loc());
577 auto var = lam_->var();
578
579 if (ret()) {
580 ptrn()->emit_proj(e, var, 2, 0);
581 ret()->emit_proj(e, var, 2, 1);
582 } else {
583 ptrn()->emit_value(e, var);
584 }
585
586 return lam_;
587}
588
590 auto _ = e.world().push(loc());
591 bool is_cps = !ISA(tag_, C_DS);
592
593 // Iterate over all doms: Build a Lam for curr dom, by first building a curried Pi for the remaining doms.
594 for (size_t i = 0, n = num_doms(); i != n; ++i) {
595 for (auto dom : doms() | std::views::drop(i))
596 dom->emit_type(e);
597
598 auto cod = codom() ? codom()->emit(e) : is_cps ? e.world().type_bot() : e.world().mut_hole_type();
599 for (auto dom : doms() | std::views::drop(i) | std::views::reverse)
600 cod = dom->pi_->set_codom(cod);
601
602 auto cur = dom(i);
603 auto lam = cur->emit_value(e);
604 if (auto filter = cur->filter()) {
605 auto _filter = e.world().push(filter->loc());
606 lam->set_filter(filter->emit(e));
607 } else {
608 lam->set_filter(i + 1 == n && is_cps ? e.world().lit_ff() : e.world().lit_tt());
609 }
610
611 if (i == 0)
612 def_ = lam->set(dbg().sym());
613 else
614 dom(i - 1)->lam_->set_body(lam);
615 }
616}
617
619 if (!body()) return; // extern forward declaration: the implementation lives in a native translation unit
620
621 auto _ = e.world().push(loc());
622 {
623 auto _body = e.world().push(body()->loc());
624 doms().back()->lam_->set_body(body()->emit(e));
625 }
626
627 // rewrite holes
628 for (size_t i = 0, n = num_doms(); i != n; ++i) {
629 auto rw = VarRewriter(e.world());
630 auto lam = dom(i)->lam_;
631 auto pi = lam->type()->as_mut<Pi>();
632 for (auto dom : doms() | std::views::drop(i)) {
633 if (auto var = pi->has_var()) rw.add(dom->lam_->var()->as<Var>(), var);
634 auto cod = pi->codom();
635 if (!cod || !cod->isa_mut<Pi>()) break;
636 pi = cod->as_mut<Pi>();
637 }
638
639 if (auto cod = pi->codom(); cod && cod->has_dep(Dep::Hole)) pi->set(pi->dom(), rw.rewrite(cod));
640 }
641
642 for (auto dom : doms() | std::views::reverse) {
643 if (auto imm = dom->pi_->immutabilize()) {
644 auto f = dom->lam_->filter();
645 auto b = dom->lam_->body();
646 dom->lam_->unset()->set_type(imm)->as<Lam>()->set(f, b);
647 }
648 }
649
650 if (is_external()) {
651 auto lam = doms().front()->lam_;
652 if (!lam->is_closed())
653 e.error()
654 .e(loc(),
655 "external function `{}` is not closed: its inferred type escapes into the scope of `{}`. This "
656 "usually means an unannotated parameter's type could only be inferred to depend on a variable bound "
657 "in an inner/sibling scope; add an explicit type annotation to the offending parameter.",
658 dbg().sym(), lam->free_vars().min()->binder()->sym())
659 .bail();
660 lam->externalize();
661 }
662 e.attach(annex_, sub_, dbg().sym(), def_);
663}
664
665void RuleDecl::emit(Emitter& e) const {
666 auto _ = e.world().push(loc());
667 auto meta_t = e.world().reform(var()->emit_type(e));
668 auto rule = e.world().mut_rule(meta_t)->set(dbg());
669 var()->emit_value(e, rule->var());
670 auto l = lhs()->emit(e);
671 auto r = rhs()->emit(e);
672 auto g = guard()->emit(e);
673 rule->set(l, r, g);
674 def_ = rule;
675}
676
677} // namespace mim::ast
const Def * callee() const
Definition lam.h:275
static std::pair< u8, u8 > infer_curry_and_trip(const Def *type)
Definition axm.cpp:14
Base class for all Defs.
Definition def.h:273
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:623
Def * set(size_t i, const Def *)
Successively set from left to right.
Definition def.cpp:196
T * as_mut() const
Asserts that this is a mutable, casts constness away and performs a static_cast to T.
Definition def.h:589
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:580
const Def * var(nat_t a, nat_t i) noexcept
Definition def.h:479
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Definition def.h:1111
const Def * immutabilize()
Definition def.cpp:555
Some "global" variables needed all over the place.
Definition driver.h:63
A function.
Definition lam.h:113
static std::optional< T > isa(const Def *def)
Definition def.h:937
A dependent function type.
Definition lam.h:14
static const Pi * has_ret_pi(const Def *d)
Yields the Pi::ret_pi() of d, if it is in fact a Pi.
Definition lam.h:67
Pi * set(const Def *dom, const Def *codom)
Definition lam.h:87
A dependent tuple type.
Definition tuple.h:23
Sigma * set(size_t i, const Def *def)
Definition tuple.h:35
VarRewriter(World &world)
Definition rewrite.h:118
A variable introduced by a binder (mutable).
Definition def.h:825
const Def * attach(flags_t, Sym, const Def *)
Definition world.cpp:61
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:40
Driver & driver()
Definition world.h:103
Annexes & annexes()
Definition world.h:281
Owns the arena all AST nodes live in as well as the AnnexInfos of all plugins.
Definition ast.h:99
World & world() const
Definition ast.h:108
void emit(Emitter &) const override
Definition emit.cpp:531
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1121
const Path * path() const
Definition ast.h:1122
const Def * emit_value(Emitter &, const Def *) const override
Definition emit.cpp:75
const Def * emit_type(Emitter &) const override
Definition emit.cpp:103
const Ptrn * ptrn() const
Definition ast.h:375
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:376
const Def * emit_(Emitter &) const override
Definition emit.cpp:418
const Expr * arg() const
Definition ast.h:763
const Expr * callee() const
Definition ast.h:762
const AxmDecl * owner() const
Definition ast.h:978
void emit(Emitter &) const override
Definition emit.cpp:520
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:977
void emit(Emitter &) const override
Definition emit.cpp:491
const Expr * type() const
Definition ast.h:1001
Tok trip() const
Definition ast.h:1004
Tok curry() const
Definition ast.h:1003
const Def * mim_type() const
Definition ast.h:1005
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1000
const Expr * expr() const
Definition ast.h:543
auto decls() const
Definition ast.h:541
const Def * emit_(Emitter &) const override
Definition emit.cpp:250
bool is_where() const
Definition ast.h:542
virtual Dbg dbg() const
The name this Decl introduces; anonymous if it has none.
Definition ast.h:239
const Def * def_
Definition ast.h:252
const Def * def() const
Definition ast.h:236
fe::Error & error()
Definition emit.cpp:22
void attach(AnnexInfo *annex, sub_t sub, Sym name, const Def *def)
name is this registration's own (unqualified) Dbg::sym; AnnexInfo::qualified turns it into the full p...
Definition emit.cpp:28
AST & ast() const
Definition emit.cpp:19
World & world()
Definition emit.cpp:20
Emitter(AST &ast)
Definition emit.cpp:16
absl::node_hash_map< Sigma *, fe::SymMap< size_t >, GIDHash< const Def * > > sigma2sym2idx
Definition emit.cpp:33
Driver & driver()
Definition emit.cpp:21
const Def * emit_(Emitter &) const override
Definition emit.cpp:157
const Def * emit_type(Emitter &) const override
Definition emit.cpp:96
const Def * emit_value(Emitter &, const Def *) const override
Definition emit.cpp:66
Base class of all expressions.
Definition ast.h:207
const Def * emit(Emitter &) const
Definition emit.cpp:142
const Def * emit_decl(Emitter &, const Def *type) const
Definition emit.cpp:147
virtual const Def * emit_decl_(Emitter &, const Def *) const
Definition ast.h:225
virtual const Def * emit_(Emitter &) const =0
void emit_body(Emitter &, const Def *decl) const
Definition emit.cpp:152
virtual void emit_body_(Emitter &, const Def *) const
Definition ast.h:226
auto implicit_imports() const
Imports the driver was told about via -p; they precede everything the file itself declares.
Definition ast.h:1210
void emit(AST &) const
Definition emit.cpp:43
const Def * emit_type(Emitter &) const override
Definition emit.cpp:105
const Def * emit_value(Emitter &, const Def *) const override
Definition emit.cpp:73
const IdPtrn * id() const
Definition ast.h:355
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:354
const Def * emit_(Emitter &) const override
Definition emit.cpp:158
const Def * emit_type(Emitter &) const override
Definition emit.cpp:98
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:318
const Def * emit_value(Emitter &, const Def *) const override
Definition emit.cpp:68
const Expr * type() const
Definition ast.h:319
void emit_body_(Emitter &, const Def *decl) const override
Definition emit.cpp:265
static const InfixExpr * isa_op(Tok::Tag tag, const Expr *expr)
Definition ast.h:610
const Expr * callee() const
Definition ast.h:607
const Expr * rhs() const
Definition ast.h:606
const Def * emit_(Emitter &) const override
Definition emit.cpp:297
const Def * emit_decl_(Emitter &, const Def *type) const override
Definition emit.cpp:260
const Expr * lhs() const
Definition ast.h:604
Tok op() const
Definition ast.h:605
Lam * emit_value(Emitter &) const
Definition emit.cpp:573
bool is_external() const
extern without a body is a forward declaration whose implementation lives in a native translation uni...
Definition ast.h:1091
auto doms() const
Definition ast.h:1092
const Expr * codom() const
Definition ast.h:1095
void emit_decl(Emitter &) const override
Definition emit.cpp:589
size_t num_doms() const
Definition ast.h:1094
void emit_body(Emitter &) const override
Definition emit.cpp:618
const Dom * dom(size_t i) const
Definition ast.h:1093
void emit_body_(Emitter &, const Def *decl) const override
Definition emit.cpp:410
const Def * emit_(Emitter &) const override
Definition emit.cpp:412
const LamDecl * lam() const
Definition ast.h:741
const Def * emit_decl_(Emitter &, const Def *type) const override
Definition emit.cpp:409
const Expr * value() const
Definition ast.h:953
const Ptrn * ptrn() const
Definition ast.h:952
void emit(Emitter &) const override
Definition emit.cpp:546
Tok tok() const
Definition ast.h:517
const Expr * type() const
Definition ast.h:519
const Def * emit_(Emitter &) const override
Definition emit.cpp:233
Tok::Tag tag() const
Definition ast.h:518
Lam * emit(Emitter &) const
Definition emit.cpp:353
const Expr * body() const
Definition ast.h:645
const Ptrn * ptrn() const
Definition ast.h:644
auto arms() const
Definition ast.h:663
const Def * emit_(Emitter &) const override
Definition emit.cpp:362
const Expr * scrutinee() const
Definition ast.h:662
const Arm * arm(size_t i) const
Definition ast.h:664
void emit_decls(Emitter &) const
Definition emit.cpp:539
void emit(Emitter &) const override
Definition emit.cpp:544
auto decls() const
Definition ast.h:1180
Loc loc() const
Definition ast.h:197
const Def * emit_(Emitter &) const override
Definition emit.cpp:160
Dbg dbg() const
Definition ast.h:477
const Decl * decl() const
Definition ast.h:478
virtual void emit_type(Emitter &) const
Definition emit.cpp:370
const IdPtrn * ret() const
Definition ast.h:690
bool is_implicit() const
Definition ast.h:688
const Ptrn * ptrn() const
Definition ast.h:689
const Def * emit_(Emitter &) const override
Definition emit.cpp:401
const Def * emit_decl_(Emitter &, const Def *type) const override
Definition emit.cpp:395
void emit_body_(Emitter &, const Def *decl) const override
Definition emit.cpp:399
Tok::Tag tag() const
Definition ast.h:498
virtual const Def * emit_value(Emitter &, const Def *) const =0
const Def * emit_proj(Emitter &, const Def *def, size_t n, size_t i) const
Ptrn::emit_value on def's i-th of n projections - with this Ptrn's Loc, so the projection is blamed o...
Definition emit.cpp:79
virtual const Def * emit_type(Emitter &) const =0
void emit(Emitter &) const override
Definition emit.cpp:553
virtual void emit_body(Emitter &) const
Definition emit.cpp:566
virtual void emit_decl(Emitter &) const
Definition emit.cpp:560
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1031
const Expr * body() const
Definition ast.h:1032
const Ptrn * ptrn() const
Definition ast.h:785
const Expr * arg() const
Definition ast.h:787
const Def * emit_(Emitter &) const override
Definition emit.cpp:424
const Expr * body() const
Definition ast.h:788
const Expr * callee() const
Definition ast.h:786
const Ptrn * var() const
Definition ast.h:1149
const Expr * guard() const
Definition ast.h:1152
const Expr * rhs() const
Definition ast.h:1151
const Expr * lhs() const
Definition ast.h:1150
void emit(Emitter &) const override
Definition emit.cpp:665
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1148
const Expr * dom() const
Definition ast.h:580
const Def * emit_(Emitter &) const override
Definition emit.cpp:171
bool is_pack() const
Definition ast.h:851
const Expr * body() const
Definition ast.h:853
const IdPtrn * arity() const
Definition ast.h:852
const Def * emit_(Emitter &) const override
Definition emit.cpp:450
const TuplePtrn * ptrn() const
Definition ast.h:810
const Def * emit_decl_(Emitter &, const Def *type) const override
Definition emit.cpp:441
void emit_body_(Emitter &, const Def *decl) const override
Definition emit.cpp:442
const Def * emit_(Emitter &) const override
Definition emit.cpp:443
std::pair< uint64_t, uint64_t > lit_i() const
Definition tok.h:317
static const char * tag2str(Tok::Tag)
Definition tok.cpp:10
auto elems() const
Definition ast.h:831
const Expr * elem(size_t i) const
Definition ast.h:832
const Def * emit_(Emitter &) const override
Definition emit.cpp:445
size_t num_elems() const
Definition ast.h:833
const Ptrn * ptrn(size_t i) const
Definition ast.h:405
const Def * emit_type(Emitter &) const override
Definition emit.cpp:107
const Def * emit_decl(Emitter &, const Def *type) const
Definition emit.cpp:132
size_t num_ptrns() const
Definition ast.h:406
const Def * emit_value(Emitter &, const Def *) const override
Definition emit.cpp:84
const Def * emit_body(Emitter &, const Def *decl) const
Definition emit.cpp:109
const Def * emit_(Emitter &) const override
Definition emit.cpp:166
const Expr * level() const
Definition ast.h:562
const Expr * inhabitant() const
Definition ast.h:873
const Def * emit_(Emitter &) const override
Definition emit.cpp:485
void emit(Emitter &) const override
Definition emit.cpp:58
const File * file() const
Definition ast.h:920
Families of Tok::Tag as reusable case labels; include this in *.cpp files only.
#define C_DS
Direct-style binders; all other binders are CPS.
Definition family.h:84
#define ISA(tag, family)
Turns such a family into a predicate - a case label is of no use outside of a switch.
Definition family.h:142
Definition ast.h:16
static u64 encode_f(Emitter &e, Loc loc, const Def *t, u64 bits)
A float Tok stores its value as mim::f64 bits; re-encode them for the width of the annotated type t.
Definition emit.cpp:217
static void emit_union(Emitter &e, const Expr *expr, DefVec &types)
a ∪ b ∪ c is one n-ary Join, so flatten the left spine the left-associative parse built.
Definition emit.cpp:271
Tok::Tag Tag
Definition bind.cpp:9
static std::optional< nat_t > isa_math_f(Emitter &e, const Def *type)
If type is a math.F type of known precision/exponent, yields its bit width.
Definition emit.cpp:204
u8 sub_t
Definition types.h:42
@ Hole
Depends on a Hole.
Definition def.h:137
float f32
Definition types.h:34
fe::Vector< const Def * > DefVec
Definition def.h:93
uint64_t u64
Definition types.h:27
Bookkeeping of an annex introduced by an AxmDecl.
Definition ast.h:66
Sym qualified(Driver &driver, Sym own) const
Fully-qualified plugin.tag[.sub] name for own (this decl's own Dbg::sym), registered for by-name look...
Definition ast.h:78
struct mim::ast::AnnexInfo::@177100250272201136376142224053244231100060214216 id
plugin_t plugin_id() const
The mangled plugin part of the flags.
Definition ast.h:73