MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
def.cpp
Go to the documentation of this file.
1#include "mim/def.h"
2
3#include <algorithm>
4
5#include <absl/container/fixed_array.h>
6#include <fe/assert.h>
7
8#include "mim/rule.h"
9#include "mim/world.h"
10
11#include "mim/util/hash.h"
12
13using namespace std::literals;
14
15namespace mim {
16
17template void Sets<const Var>::dot();
18template void Sets<Def>::dot();
19
20/*
21 * constructors
22 */
23
24Def::Def(World* world, Node node, const Def* type, Defs ops, flags_t flags)
25 : world_(world)
26 , flags_(flags)
27 , node_(node)
28 , mut_(false)
29 , external_(false)
30 , annex_(false)
31 , dirty_(false)
32 , dep_(node == Node::Hole ? fe::to_underlying(Dep::Hole)
33 : node == Node::Proxy ? fe::to_underlying(Dep::Proxy)
34 : node == Node::Var ? fe::to_underlying(Dep::Var | Dep::Mut)
35 : 0)
36 , num_ops_(ops.size())
37 , type_(type) {
38 if (node == Node::Univ) {
39 gid_ = world->next_gid();
41 } else {
42 hash_ = hash_begin(u8(node));
43 hash_ = hash_combine(hash_, flags_);
44
45 if (type) {
46 world = &type->world();
47 dep_ |= type->dep_;
48 vars_ = type->local_vars();
49 muts_ = type->local_muts();
50 hash_ = hash_combine(hash_, type->gid());
51 } else {
52 world = &ops[0]->world();
53 }
54
55 auto vars = &world->vars();
56 auto muts = &world->muts();
57 auto ptr = ops_ptr();
58 gid_ = world->next_gid();
59
60 for (size_t i = 0, e = ops.size(); i != e; ++i) {
61 auto op = ops[i];
62 ptr[i] = op;
63 dep_ |= op->dep_;
64 vars_ = vars->merge(vars_, op->local_vars());
65 muts_ = muts->merge(muts_, op->local_muts());
66 hash_ = hash_combine(hash_, op->gid());
67 }
68 }
69}
70
71Def::Def(Node n, const Def* type, Defs ops, flags_t flags)
72 : Def(nullptr, n, type, ops, flags) {}
73
74Def::Def(Node node, const Def* type, size_t num_ops, flags_t flags)
75 : flags_(flags)
76 , node_(node)
77 , mut_(true)
78 , external_(false)
79 , annex_(false)
80 , dirty_(false)
81 , dep_(fe::to_underlying(Dep::Mut | (node == Node::Hole ? Dep::Hole : Dep::None)))
82 , num_ops_(num_ops)
83 , type_(type) {
84 gid_ = world().next_gid();
85 hash_ = mim::hash(gid());
86 var_ = nullptr;
87 std::fill_n(ops_ptr(), num_ops, nullptr);
88}
89
90Def::Def(Node node, Def* binder)
91 : binder_(binder) // the binder is stored here instead of as an op, so a Var stays out of the operand graph
92 , flags_(0)
93 , node_(node)
94 , mut_(false)
95 , external_(false)
96 , annex_(false)
97 , dirty_(false)
98 , dep_(fe::to_underlying(Dep::Var | Dep::Mut))
99 , num_ops_(0)
100 , type_(nullptr) {
101 gid_ = binder->world().next_gid();
102 vars_ = Vars(as<Var>());
103 hash_ = hash_begin(node_t(Node::Var));
104 hash_ = hash_combine(hash_, binder->gid());
105}
106
107Nat::Nat(World& world)
108 : Def(Node, world.type(), Defs{}, 0) {}
109
110UMax::UMax(World& world, Defs ops)
111 : Def(Node, world.univ(), ops, 0) {}
112
113// clang-format off
114
115/*
116 * rebuild
117 */
118
119const Def* Hole ::rebuild_(World&, const Def*, Defs ) const { fe::unreachable(); }
120const Def* Global ::rebuild_(World&, const Def*, Defs ) const { fe::unreachable(); }
121const Def* Idx ::rebuild_(World& w, const Def* , Defs ) const { return w.type_idx(); }
122const Def* Nat ::rebuild_(World& w, const Def* , Defs ) const { return w.type_nat(); }
123const Def* Univ ::rebuild_(World& w, const Def* , Defs ) const { return w.univ(); }
124const Def* App ::rebuild_(World& w, const Def* , Defs o) const { return w.app(o[0], o[1]); }
125const Def* Arr ::rebuild_(World& w, const Def* , Defs o) const { return w.arr(o[0], o[1]); }
126const Def* Extract::rebuild_(World& w, const Def* , Defs o) const { return w.extract(o[0], o[1]); }
127const Def* Inj ::rebuild_(World& w, const Def* t, Defs o) const { return w.inj(t, o[0])->set(dbg()); }
128const Def* Insert ::rebuild_(World& w, const Def* , Defs o) const { return w.insert(o[0], o[1], o[2]); }
129const Def* Lam ::rebuild_(World& w, const Def* t, Defs o) const { return w.lam(t->as<Pi>(), o[0], o[1]); }
130const Def* Lit ::rebuild_(World& w, const Def* t, Defs ) const { return w.lit(t, get()); }
131const Def* Merge ::rebuild_(World& w, const Def* t, Defs o) const { return w.merge(t, o); }
132const Def* Pack ::rebuild_(World& w, const Def* t, Defs o) const { return w.pack(t->arity(), o[0]); }
133const Def* Pi ::rebuild_(World& w, const Def* , Defs o) const { return w.pi(o[0], o[1], is_implicit()); }
134const Def* Proxy ::rebuild_(World& w, const Def* t, Defs o) const { return w.proxy(t, o, tag()); }
135const Def* Rule ::rebuild_(World& w, const Def* t, Defs o) const { return w.rule(t->as<Reform>(), o[0], o[1], o[2]); }
136const Def* Reform ::rebuild_(World& w, const Def* , Defs o) const { return w.reform(o[0]); }
137const Def* Sigma ::rebuild_(World& w, const Def* , Defs o) const { return w.sigma(o); }
138const Def* Split ::rebuild_(World& w, const Def* t, Defs o) const { return w.split(t, o[0]); }
139const Def* Match ::rebuild_(World& w, const Def* , Defs o) const { return w.match(o); }
140const Def* Tuple ::rebuild_(World& w, const Def* t, Defs o) const { return w.tuple(t, o); }
141const Def* Type ::rebuild_(World& w, const Def* , Defs o) const { return w.type(o[0]); }
142const Def* UInc ::rebuild_(World& w, const Def* , Defs o) const { return w.uinc(o[0], offset()); }
143const Def* UMax ::rebuild_(World& w, const Def* , Defs o) const { return w.umax(o); }
144const Def* Uniq ::rebuild_(World& w, const Def* , Defs o) const { return w.uniq(o[0]); }
145const Def* Var ::rebuild_(World&, const Def*, Defs ) const { fe::unreachable(); } // binder is in binder_, not an op; rewrite via Rewriter::rewrite_imm_Var
146
147const Def* Axm ::rebuild_(World& w, const Def* t, Defs ) const {
148 if (&w != &world()) return w.axm(normalizer(), curry(), trip(), t, plugin(), tag(), sub())->set(dbg());
150 return this;
151}
152
153template<bool up> const Def* TExt <up>::rebuild_(World& w, const Def* t, Defs ) const { return w.ext <up>(t)->set(dbg()); }
154template<bool up> const Def* TBound<up>::rebuild_(World& w, const Def* , Defs o) const { return w.bound<up>(o)->set(dbg()); }
155
156/*
157 * stub
158 */
159
160Arr* Arr ::stub_(World& w, const Def* t) { return w.mut_arr (t); }
161Global* Global::stub_(World& w, const Def* t) { return w.global (t, is_mutable()); }
162Hole* Hole ::stub_(World& w, const Def* t) { return w.mut_hole (t); }
163Lam* Lam ::stub_(World& w, const Def* t) { return w.mut_lam (t->as<Pi>()); }
164Pack* Pack ::stub_(World& w, const Def* t) { return w.mut_pack (t); }
165Pi* Pi ::stub_(World& w, const Def* t) { return w.mut_pi (t, is_implicit()); }
166Rule* Rule ::stub_(World& w, const Def* t) { return w.mut_rule(t->as<Reform>()); }
167Sigma* Sigma ::stub_(World& w, const Def* t) { return w.mut_sigma(t, num_ops()); }
168
169/*
170 * instantiate templates
171 */
172
173#ifndef DOXYGEN
174template const Def* TExt<false> ::rebuild_(World&, const Def*, Defs) const;
175template const Def* TExt<true > ::rebuild_(World&, const Def*, Defs) const;
176template const Def* TBound<false>::rebuild_(World&, const Def*, Defs) const;
177template const Def* TBound<true >::rebuild_(World&, const Def*, Defs) const;
178#endif
179
180// clang-format on
181
182/*
183 * immutabilize
184 */
185
187 if (!is_set()) return false;
188
189 if (auto v = has_var()) {
190 for (auto op : deps())
191 if (op->free_vars().contains(v)) return false;
192 }
193 for (auto op : deps()) {
194 for (auto mut : op->local_muts())
195 if (mut == this) return false; // recursion
196 }
197 return true;
198}
199
201 if (is_immutabilizable()) return world().pi(dom(), codom());
202 return nullptr;
203}
204
205// TODO should we ever immutabilize Rules?
206const Rule* Rule::immutabilize() { return nullptr; }
207
209 if (is_immutabilizable()) return static_cast<const Sigma*>(world().sigma(ops()));
210 return nullptr;
211}
212
214 auto& w = world();
215 if (is_immutabilizable()) return w.arr(arity(), body());
216
217 if (auto n = Lit::isa(arity()); n && *n < w.flags().scalarize_threshold)
218 return w.sigma(DefVec(*n, [&](size_t i) { return reduce(w.lit_idx(*n, i)); }));
219
220 return nullptr;
221}
222
224 auto& w = world();
225 if (is_immutabilizable()) return w.pack(arity(), body());
226
227 if (auto n = Lit::isa(arity()); n && *n < w.flags().scalarize_threshold)
228 return w.tuple(DefVec(*n, [&](size_t i) { return reduce(w.lit_idx(*n, i)); }));
229
230 return nullptr;
231}
232
233/*
234 * reduce
235 */
236
237Defs Def::reduce_(const Def* arg) const {
238 if (auto var = has_var()) return world().reduce(var, arg);
239 return {ops().begin() + reduction_offset(), num_ops() - reduction_offset()};
240}
241
242const Def* Def::refine(size_t i, const Def* new_op) const {
243 auto new_ops = absl::FixedArray<const Def*>(num_ops());
244 for (size_t j = 0, e = num_ops(); j != e; ++j)
245 new_ops[j] = i == j ? new_op : op(j);
246 return rebuild(type(), new_ops);
247}
248
249/*
250 * Def - set
251 */
252
254#ifdef MIM_ENABLE_CHECKS
255 if (world().watchpoints().contains(gid())) fe::breakpoint();
256#endif
257 invalidate();
258
259 size_t n = ops.size();
260 assert(n == num_ops() && "num ops don't match");
261
262 for (size_t i = 0; i != n; ++i) {
263 auto def = check(i, ops[i]);
264 assert(def);
265 ops_ptr()[i] = def;
266 }
267#ifndef NDEBUG
268 curr_op_ = n;
269#endif
271 if (auto t = check()->zonk(); t != type()) type_ = t;
273 return this;
274}
275
276Def* Def::set(size_t i, const Def* def) {
277#ifdef MIM_ENABLE_CHECKS
278 if (world().watchpoints().contains(gid())) fe::breakpoint();
279#endif
280
281 invalidate();
282 def = check(i, def);
283 assert(def && !op(i) && curr_op_++ == i);
284 ops_ptr()[i] = def;
285
286 if (i + 1 == num_ops()) { // set last op, so check kind
287 if (auto t = check()->zonk(); t != type()) type_ = t;
288 }
289
290 return this;
291}
292
293Def* Def::set_type(const Def* type) {
294 invalidate();
295 type_ = type;
296 return this;
297}
298
300 invalidate();
301#ifndef NDEBUG
302 curr_op_ = 0;
303#endif
304 std::ranges::fill(ops_ptr(), ops_ptr() + num_ops(), nullptr);
305 return this;
306}
307
308bool Def::is_set() const {
309 if (num_ops() == 0) return true;
310 bool result = ops().back();
311 assert((!result || std::ranges::all_of(ops().rsubspan(1), [](auto op) { return op; }))
312 && "the last operand is set but others in front of it aren't");
313 return result;
314}
315
316/*
317 * free_vars
318 */
319
320const Def* Def::var() {
321 if (var_) return var_;
322 return world().var(this);
323}
324
325const Def* Def::var_type() {
326 auto& w = world();
327
328 // clang-format off
329 if (auto lam = isa<Lam >()) return lam->dom();
330 if (auto pi = isa<Pi >()) return pi ->dom();
331 if (auto sig = isa<Sigma>()) return sig;
332 if (auto arr = isa<Arr >()) return w.type_idx(arr ->arity()); // TODO shapes like (2, 3)
333 if (auto pack = isa<Pack >()) return w.type_idx(pack->arity()); // TODO shapes like (2, 3)
334 if (auto rule = isa<Rule >()) return rule->type()->dom();
335 if (isa<Bound >()) return this;
336 if (isa<Hole >()) return nullptr;
337 if (isa<Global>()) return nullptr;
338 // clang-format on
339 fe::unreachable();
340}
341
343 if (auto mut = isa_mut()) return Muts(mut);
344 return muts_;
345}
346
348 if (auto mut = isa_mut()) return mut->free_vars();
349
350 auto& vars = world().vars();
351 auto fvs = local_vars();
352 for (auto mut : local_muts())
353 fvs = vars.merge(fvs, mut->free_vars());
354
355 return fvs;
356}
357
358Vars Def::local_vars() const { return mut_ ? Vars() : vars_; }
359
361 if (mark_ == 0) {
362 // fixed-point iteration to recompute free vars:
363 // (run - 1) identifies the previous iteration; so make sure to offset run by 2 for the first iteration
364 auto& w = world();
365 bool cyclic = false;
366 w.next_run();
367 free_vars<true>(cyclic, w.next_run());
368
369 for (bool todo = cyclic; todo;) {
370 todo = false;
371 free_vars<false>(todo, w.next_run());
372 }
373 }
374
375 return vars_;
376}
377
378template<bool init>
379Vars Def::free_vars(bool& todo, uint32_t run) {
380 // If init == true : todo flag detects cycle.
381 // If init == false: todo flag keeps track whether sth changed.
382 //
383 // Recursively recompute free vars. If
384 // * mark_ == 0: Invalid - need to recompute.
385 // * mark_ == run - 1: Previous iteration - need to recompute.
386 // * mark_ == run: We are running in cycles within the *current* iteration of our fixed-point loop.
387 // * otherwise: Valid!
388 if (mark_ != 0 && mark_ != run - 1) {
389 if constexpr (init) todo |= mark_ == run;
390 return vars_;
391 }
392
393 mark_ = run;
394
395 auto fvs0 = vars_;
396 auto fvs = fvs0;
397 auto& w = world();
398 auto& muts = w.muts();
399 auto& vars = w.vars();
400
401 for (auto op : deps()) {
402 if constexpr (init) fvs = vars.merge(fvs, op->local_vars());
403
404 for (auto mut : op->local_muts()) {
405 if constexpr (init) mut->muts_ = muts.insert(mut->muts_, this); // register "this" as user of local_mut
406 fvs = vars.merge(fvs, mut->free_vars<init>(todo, run));
407 }
408 }
409
410 if (auto var = has_var()) fvs = vars.erase(fvs, var); // FV(λx.e) = FV(e) \ {x}
411
412 if constexpr (!init) todo |= fvs0 != fvs;
413
414 return vars_ = fvs;
415}
416
417void Def::invalidate() {
418 if (mark_ != 0) {
419 mark_ = 0;
420 // TODO optimize if vars empty?
421 for (auto mut : users())
422 mut->invalidate();
423 vars_ = Vars();
424 muts_ = Muts();
425 }
426}
427
428bool Def::is_closed() const {
429 if (local_vars().empty() && local_muts().empty()) return true;
430#ifdef MIM_ENABLE_CHECKS
431 assert(!is_external() || free_vars().empty());
432#endif
433 return free_vars().empty();
434}
435
436bool Def::is_open() const {
437 if (!local_vars().empty()) return true;
438 return !free_vars().empty();
439}
440
442 if (is_closed()) return isa_mut();
443 return (*free_vars().begin())->outermost_binder();
444}
445
446bool Def::nests(Def* mut, MutSet& checked) {
447 if (mut->free_vars().contains(this->has_var())) return true;
448 if (auto [_, ins] = checked.emplace(mut); !ins) return false;
449
450 for (auto fv : mut->free_vars())
451 if (this->nests(fv->binder(), checked)) return true;
452
453 return false;
454}
455
456bool Def::nests(Def* mut) {
457 if (this->has_var()) {
458 auto checked = MutSet{};
459 return this->nests(mut, checked);
460 }
461 return false;
462}
463
464bool Def::nests(const Def* def) {
465 if (auto mut = def->isa_mut()) return this->nests(mut);
466
467 if (has_var()) {
468 auto checked = MutSet();
469 for (auto fv : def->free_vars())
470 if (this->nests(fv->binder(), checked)) return true;
471 }
472 return false;
473}
474
475/*
476 * Def - misc
477 */
478
479Sym Def::sym(const char* s) const { return world().sym(s); }
480Sym Def::sym(std::string_view s) const { return world().sym(s); }
481Sym Def::sym(std::string s) const { return world().sym(std::move(s)); }
482
483World& Def::world() const noexcept {
484 if (auto var = isa<Var>()) return var->binder()->world();
485
486 for (auto def = this;; def = def->type()) {
487 if (def->isa<Univ>()) return *def->world_;
488 if (auto type = def->isa<Type>()) return *type->level()->type()->as<Univ>()->world_;
489 }
490}
491const Def* Def::type() const noexcept {
492 if (auto var = isa<Var>()) return var->binder()->var_type();
493 return type_;
494}
495
496const Def* Def::unfold_type() const {
497 if (auto t = type()) return t;
498 auto& w = world();
499 if (auto t = isa<Type>()) return w.type(w.uinc(t->level()));
500 assert(isa<Univ>());
501 return nullptr;
502}
503
504std::string_view Def::node_name() const {
505 switch (node()) {
506#define CODE(name, _) \
507 case Node::name: return #name;
509#undef CODE
510 default: fe::unreachable();
511 }
512}
513
514Defs Def::deps() const noexcept {
515 if (isa<Type>() || isa<Univ>()) return Defs();
516 if (isa<Var>()) return Defs(); // the binder lives in binder_, not in an op
517 assert(type_);
518 return Defs(ops_ptr() - 1, (is_set() ? num_ops_ : 0) + 1);
519}
520
521Judge Def::judge() const noexcept {
522 switch (node()) {
523#define CODE(n, j) \
524 case Node::n: return j;
526#undef CODE
527 default: fe::unreachable();
528 }
529}
530
531bool Def::is_term() const {
532 if (auto t = type()) {
533 if (auto u = t->type()) {
534 if (auto type = u->isa<Type>()) {
535 if (auto level = Lit::isa(type->level())) return *level == 0;
536 }
537 }
538 }
539 return false;
540}
541
542#ifndef NDEBUG
543const Def* Def::debug_prefix(std::string prefix) const { return dbg_.set(world().sym(prefix + sym().str())), this; }
544const Def* Def::debug_suffix(std::string suffix) const { return dbg_.set(world().sym(sym().str() + suffix)), this; }
545#endif
546
547/*
548 * cmp
549 */
550
551Def::Cmp Def::cmp(const Def* a, const Def* b) {
552 if (a == b) return Cmp::E;
553
554 if (a->isa_imm() && b->isa_mut()) return Cmp::L;
555 if (a->isa_mut() && b->isa_imm()) return Cmp::G;
556
557 // clang-format off
558 if (a->node() != b->node() ) return a->node() < b->node() ? Cmp::L : Cmp::G;
559 if (a->num_ops() != b->num_ops()) return a->num_ops() < b->num_ops() ? Cmp::L : Cmp::G;
560 if (a->flags() != b->flags() ) return a->flags() < b->flags() ? Cmp::L : Cmp::G;
561 // clang-format on
562
563 if (a->isa_mut() && b->isa_mut()) return Cmp::U;
564 assert(a->isa_imm() && b->isa_imm());
565
566 if (auto va = a->isa<Var>()) {
567 auto vb = b->as<Var>();
568 auto ma = va->binder();
569 auto mb = vb->binder();
570 if (ma->is_set() && ma->free_vars().contains(vb)) return Cmp::L;
571 if (mb->is_set() && mb->free_vars().contains(va)) return Cmp::G;
572 return Cmp::U;
573 }
574
575 // heuristic: iterate backwards as index (often a Lit) comes last and will faster find a solution
576 for (size_t i = a->num_ops(); i-- != 0;)
577 if (auto res = cmp(a->op(i), b->op(i)); res == Cmp::L || res == Cmp::G) return res;
578
579 return cmp(a->type(), b->type());
580}
581
582template<Def::Cmp c>
583bool Def::cmp_(const Def* a, const Def* b) {
584 auto res = cmp(a, b);
585 if (res == Cmp::U) {
586 a->world().WLOG("resorting to unstable gid-based compare for commute check");
587 return c == Cmp::L ? a->gid() < b->gid() : a->gid() > b->gid();
588 }
589 return res == c;
590}
591
592// clang-format off
593bool Def::less (const Def* a, const Def* b) { return cmp_<Cmp::L>(a, b); }
594bool Def::greater(const Def* a, const Def* b) { return cmp_<Cmp::G>(a, b); }
595// clang-format on
596
597const Def* Def::arity() const {
598 if (auto t = type(); t && !t->isa<Type>()) return t->arity();
599 return world().lit_nat_1();
600}
601
602bool Def::equal(const Def* other) const {
603 if (isa<Univ>() || this->isa_mut() || other->isa_mut()) return this == other;
604
605 // A Var carries no ops and flags == 0, so it is identified solely by its binder (stored in binder_).
606 if (auto var = isa<Var>()) return other->isa<Var>() && var->binder() == other->as<Var>()->binder();
607
608 bool result = this->node() == other->node() && this->flags() == other->flags()
609 && this->num_ops() == other->num_ops() && this->type() == other->type();
610
611 for (size_t i = 0, e = num_ops(); result && i != e; ++i)
612 result &= this->op(i) == other->op(i);
613
614 return result;
615}
616
617void Def::externalize() { return world().externals().externalize(this); }
618void Def::internalize() { return world().externals().internalize(this); }
619
621 assert(this->sym() == to->sym());
622 internalize();
623 to->externalize();
624}
625
626std::string Def::unique_name() const { return sym().str() + "_"s + std::to_string(gid()); }
627
628nat_t Def::num_projs() const { return Lit::isa(arity()).value_or(1); }
629
631 if (auto a = Lit::isa(arity()); a && *a < world().flags().scalarize_threshold) return *a;
632 return 1;
633}
634
635const Def* Def::proj(nat_t a, nat_t i) const {
636 World& w = world();
637
638 if (a == 1) {
639 assert(i == 0 && "only inhabitant of Idx 2 is 0_1");
640 if (!type()) return this;
641 if (!isa_mut<Sigma>() && !type()->isa_mut<Sigma>()) return this;
642 }
643
644 if (auto seq = isa<Seq>()) {
645 if (seq->has_var()) return seq->reduce(world().lit_idx(a, i));
646 return seq->body();
647 }
648
649 if (isa<Prod>()) return op(i);
650
651 return w.extract(this, a, i);
652}
653
654/*
655 * Idx
656 */
657
658const Def* Idx::isa(const Def* def) {
659 if (auto app = def->isa<App>()) {
660 if (app->callee()->isa<Idx>()) return app->arg();
661 }
662
663 return nullptr;
664}
665
666std::optional<nat_t> Idx::isa_lit(const Def* def) {
667 if (auto size = Idx::isa(def))
668 if (auto l = Lit::isa(size)) return l;
669 return {};
670}
671
672std::optional<nat_t> Idx::size2bitwidth(const Def* size) {
673 if (size->isa<Top>()) return 64;
674 if (auto s = Lit::isa(size)) return size2bitwidth(*s);
675 return {};
676}
677
678/*
679 * Global
680 */
681
682const App* Global::type() const { return Def::type()->as<App>(); }
683const Def* Global::alloced_type() const { return type()->arg(0); }
684
685} // namespace mim
friend class World
Definition lam.h:340
const Def * arg() const
Definition lam.h:285
const Def * arity() const final
Number of elements available to Extract / Insert (may be dynamic).
Definition tuple.h:131
const Def * reduce(const Def *arg) const final
Definition tuple.h:148
friend class World
Definition tuple.h:165
const Def * immutabilize() final
Tries to make an immutable from a mutable.
Definition def.cpp:213
tag_t tag() const
Definition axm.h:55
u8 trip() const
Definition axm.h:38
friend class World
Definition axm.h:151
NormalizeFn normalizer() const
Definition axm.h:36
sub_t sub() const
Definition axm.h:56
plugin_t plugin() const
Definition axm.h:54
u8 curry() const
Definition axm.h:37
static bool alpha(const Def *d1, const Def *d2)
Definition check.h:98
Base class for all Defs.
Definition def.h:261
bool is_set() const
Yields true if empty or the last op is set.
Definition def.cpp:308
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:635
constexpr Node node() const noexcept
Definition def.h:286
Def * set(size_t i, const Def *)
Successively set from left to right.
Definition def.cpp:276
Defs deps() const noexcept
Definition def.cpp:514
nat_t num_tprojs() const
As above but yields 1, if Flags::scalarize_threshold is exceeded.
Definition def.cpp:630
const Def * zonk() const
If Holes have been filled, reconstruct the program without them.
Definition check.cpp:21
World & world() const noexcept
Definition def.cpp:483
virtual const Def * check()
After all Def::ops have been Def::set, this method will be invoked to check the type of this mutable.
Definition def.h:634
const Def * refine(size_t i, const Def *new_op) const
Definition def.cpp:242
Def * set_type(const Def *)
Update type.
Definition def.cpp:293
std::string_view node_name() const
Definition def.cpp:504
constexpr auto ops() const noexcept
Definition def.h:317
Vars local_vars() const
Vars reachable by following immutable deps().
Definition def.cpp:358
constexpr flags_t flags() const noexcept
Definition def.h:281
Dbg dbg_
Definition def.h:713
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:527
auto vars() noexcept
Definition def.h:441
Judge judge() const noexcept
Definition def.cpp:521
void externalize()
Definition def.cpp:617
bool is_term() const
Is this Def a term, i.e. is its type() a Type?
Definition def.cpp:531
const Def * debug_prefix(std::string) const
Definition def.cpp:543
const Def * op(size_t i) const noexcept
Definition def.h:320
bool is_immutabilizable()
Definition def.cpp:186
const Def * var(nat_t a, nat_t i) noexcept
Definition def.h:441
void transfer_external(Def *to)
Definition def.cpp:620
const Def * unfold_type() const
Yields the type of this Def and builds a new Type (UInc n) if necessary.
Definition def.cpp:496
bool is_open() const
Has free_vars()?
Definition def.cpp:436
friend class World
Definition def.h:746
Muts local_muts() const
Mutables reachable by following immutable deps(); mut->local_muts() is by definition the set { mut }...
Definition def.cpp:342
const Def * debug_suffix(std::string) const
Definition def.cpp:544
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Definition def.cpp:491
Def * outermost_binder() const
Transitively walks up free_vars() till the outermoust binder has been found.
Definition def.cpp:441
bool nests(Def *mut)
Does this nest mut?
Definition def.cpp:456
bool is_external() const noexcept
Definition def.h:500
auto vars(F f) noexcept
Definition def.h:441
const Def * rebuild(World &w, const Def *type, Defs ops) const
Def::rebuilds this Def while using new_op as substitute for its i'th Def::op.
Definition def.h:599
void internalize()
Definition def.cpp:618
static bool less(const Def *a, const Def *b)
Definition def.cpp:593
static bool greater(const Def *a, const Def *b)
Definition def.cpp:594
const Def * var()
Not necessarily a Var: E.g., if the return type is [], this will yield ().
Definition def.cpp:320
static Cmp cmp(const Def *a, const Def *b)
Definition def.cpp:551
virtual constexpr size_t reduction_offset() const noexcept
First Def::op that needs to be dealt with during reduction; e.g.
Definition def.h:620
Sym sym() const
Definition def.h:558
nat_t num_projs() const
Yields Def::arity(), if it is a Lit, or 1 otherwise.
Definition def.cpp:628
flags_t flags_
Definition def.h:721
const Def * var_type()
If this is a binder, compute the type of its Variable.
Definition def.cpp:325
constexpr u32 gid() const noexcept
Global id - unique number for this Def.
Definition def.h:282
virtual const Def * arity() const
Number of elements available to Extract / Insert (may be dynamic).
Definition def.cpp:597
Def * unset()
Unsets all Def::ops; works even, if not set at all or only partially set.
Definition def.cpp:299
std::string unique_name() const
name + "_" + Def::gid
Definition def.cpp:626
const T * isa_imm() const
Definition def.h:521
Muts users()
Set of mutables where this mutable is locally referenced.
Definition def.h:482
bool is_closed() const
Has no free_vars()?
Definition def.cpp:428
Vars free_vars() const
Global set of free Vars: extends local_vars() by transitively following mutables as well.
Definition def.cpp:347
Dbg dbg() const
Definition def.h:556
const Var * has_var()
Only returns not nullptr, if Var of this mutable has ever been created.
Definition def.h:445
constexpr size_t num_ops() const noexcept
Definition def.h:321
@ E
Equal.
Definition def.h:669
@ U
Unknown.
Definition def.h:670
@ L
Less.
Definition def.h:667
@ G
Greater.
Definition def.h:668
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:126
friend class World
Definition tuple.h:230
const Def * alloced_type() const
Definition def.cpp:683
friend class World
Definition def.h:1043
bool is_mutable() const
Definition def.h:1028
const App * type() const
Definition def.cpp:682
Global * stub_(World &, const Def *) final
Definition def.cpp:161
This node is a hole in the IR that is inferred by its context later on.
Definition check.h:16
friend class World
Definition check.h:77
static constexpr nat_t size2bitwidth(nat_t n)
Definition def.h:951
static const Def * isa(const Def *def)
Checks if def is a Idx s and returns s or nullptr otherwise.
Definition def.cpp:658
friend class World
Definition def.h:972
static std::optional< nat_t > isa_lit(const Def *def)
Definition def.cpp:666
friend class World
Definition lattice.h:91
friend class World
Definition tuple.h:258
friend class World
Definition lam.h:212
static std::optional< T > isa(const Def *def)
Definition def.h:878
friend class World
Definition def.h:901
friend class World
Definition lattice.h:142
friend class World
Definition lattice.h:67
friend class World
Definition def.h:915
const Def * immutabilize() final
Tries to make an immutable from a mutable.
Definition def.cpp:223
const Def * arity() const final
Number of elements available to Extract / Insert (may be dynamic).
Definition tuple.cpp:19
friend class World
Definition tuple.h:206
const Def * reduce(const Def *arg) const final
Definition tuple.h:195
A dependent function type.
Definition lam.h:14
Pi(const Def *type, const Def *dom, const Def *codom, bool implicit)
Constructor for an immutable Pi.
Definition lam.h:17
bool is_implicit() const
Definition lam.h:26
const Def * dom() const
Definition lam.h:35
friend class World
Definition lam.h:105
const Def * codom() const
Definition lam.h:36
const Pi * immutabilize() final
Tries to make an immutable from a mutable.
Definition def.cpp:200
Def(World *, Node, const Def *type, Defs ops, flags_t flags)
Constructor for an immutable Def.
Definition def.cpp:24
flags_t tag() const
Definition def.h:985
friend class World
Definition def.h:1000
Type formation of a rewrite Rule.
Definition rule.h:9
friend class World
Definition rule.h:39
friend class World
Definition rule.h:110
const Rule * immutabilize() override
Tries to make an immutable from a mutable.
Definition def.cpp:206
const Def * body() const
Definition tuple.h:95
Def(World *, Node, const Def *type, Defs ops, flags_t flags)
Constructor for an immutable Def.
Definition def.cpp:24
constexpr bool empty() const noexcept
Is empty?
Definition sets.h:245
bool contains(D *d) const noexcept
Is ?.
Definition sets.h:257
void dot()
Definition sets.h:567
const TExt< Up > * set(Loc l) const
Definition def.h:200
friend class World
Definition tuple.h:65
const Def * immutabilize() final
Tries to make an immutable from a mutable.
Definition def.cpp:208
friend class World
Definition lattice.h:114
friend class World
Definition lattice.h:50
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:154
Extremum. Either Top (Up) or Bottom.
Definition lattice.h:157
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:153
friend class World
Definition lattice.h:171
friend class World
Definition tuple.h:82
friend class World
Definition def.h:851
friend class World
Definition def.h:829
level_t offset() const
Definition def.h:820
friend class World
Definition def.h:806
friend class World
Definition lattice.h:204
friend class World
Definition def.h:790
A variable introduced by a binder (mutable).
Definition def.h:756
friend class World
Definition def.h:775
Def * binder() const
The binder of this Var.
Definition def.h:766
void internalize(Def *)
Definition world.cpp:36
void externalize(Def *)
Definition world.cpp:29
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:36
const Def * sigma(Defs ops)
Definition world.cpp:298
const Pi * pi(const Def *dom, const Def *codom, bool implicit=false)
Definition world.h:359
Flags & flags()
Retrieve compile Flags.
Definition world.cpp:102
u32 next_gid()
Definition world.h:103
Sym sym(std::string_view)
Definition world.cpp:105
const Def * var(Def *mut)
Definition world.cpp:184
const Externals & externals() const
Definition world.h:264
auto & vars()
Definition world.h:674
Defs reduce(const Var *var, const Def *arg)
Yields the new body of [mut->var() -> arg]mut.
Definition world.cpp:694
const Lit * lit_nat_1()
Definition world.h:524
#define MIM_NODE(X)
Definition def.h:20
Definition ast.h:14
View< const Def * > Defs
Definition def.h:78
u64 nat_t
Definition types.h:37
Vector< const Def * > DefVec
Definition def.h:79
Dep
Tracks whether a Def transitively depends - through its Def::deps() but only up to (and excluding) th...
Definition def.h:120
@ None
Depends on nothing of interest.
Definition def.h:121
u64 flags_t
Definition types.h:39
u8 node_t
Definition types.h:38
constexpr size_t hash_combine(size_t seed, T v) noexcept
Definition hash.h:62
Sets< Def >::Set Muts
Definition def.h:89
constexpr decltype(auto) get(Span< T, N > span) noexcept
Definition span.h:119
TExt< true > Top
Definition lattice.h:177
GIDSet< Def * > MutSet
Definition def.h:87
consteval size_t hash_begin() noexcept
Definition hash.h:75
constexpr size_t hash(size_t h) noexcept
Definition hash.h:32
Sets< const Var >::Set Vars
Definition def.h:99
Mut
Classifies whether a Node may occur as a mutable, an immutable, or both.
Definition def.h:141
Judge
Judgement.
Definition def.h:129
uint8_t u8
Definition types.h:27
Node
Definition def.h:107
@ Univ
Definition def.h:109
@ Var
Definition def.h:109
uint64_t scalarize_threshold
Definition flags.h:20
#define CODE(name,...)
Definition tok.h:39