MimIR 0.1
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 "mim/rewrite.h"
6#include "mim/world.h"
7
8#include "mim/util/hash.h"
9
10using namespace std::literals;
11
12namespace mim {
13
14/*
15 * constructors
16 */
17
18Def::Def(World* w, node_t node, const Def* type, Defs ops, flags_t flags)
19 : world_(w)
20 , flags_(flags)
21 , node_(unsigned(node))
22 , mut_(false)
23 , external_(false)
24 , dep_(unsigned(node == Node::Axiom ? Dep::Axiom
25 : node == Node::Infer ? Dep::Infer
26 : node == Node::Proxy ? Dep::Proxy
27 : node == Node::Var ? Dep::Var
28 : Dep::None))
29 , valid_(false)
30 , num_ops_(ops.size())
31 , type_(type) {
32 std::ranges::copy(ops, ops_ptr());
33 gid_ = world().next_gid();
34
35 if (auto var = isa<Var>()) {
36 vars_.local = world().vars().create(var);
37 muts_.local = Muts();
38 } else {
39 vars_.local = Vars();
40 muts_.local = Muts();
41
42 for (auto op : extended_ops()) {
43 vars_.local = world().vars().merge(vars_.local, op->local_vars());
44 muts_.local = world().muts().merge(muts_.local, op->local_muts());
45 }
46 }
47
48 if (node == Node::Univ) {
49 hash_ = mim::hash(gid());
50 } else {
51 hash_ = type ? hash_begin(type->gid()) : 0;
52 for (auto op : ops) hash_ = hash_combine(hash_, u32(op->gid()));
53 hash_ = hash_combine(hash_, flags_);
54 hash_ = hash_combine(hash_, u8(node));
55 hash_ = hash_combine(hash_, num_ops());
56 }
57}
58
59Def::Def(node_t n, const Def* type, Defs ops, flags_t flags)
60 : Def(nullptr, n, type, ops, flags) {}
61
62Def::Def(node_t node, const Def* type, size_t num_ops, flags_t flags)
63 : flags_(flags)
64 , node_(node)
65 , mut_(true)
66 , external_(false)
67 , dep_(Dep::Mut | (node == Node::Infer ? Dep::Infer : Dep::None))
68 , num_ops_(num_ops)
69 , type_(type) {
70 gid_ = world().next_gid();
71 hash_ = mim::hash(gid());
72 var_ = nullptr;
73 vars_.free = Vars();
74 muts_.fv_consumers = Muts();
75 std::fill_n(ops_ptr(), num_ops, nullptr);
76 if (!type->dep_const()) type->uses_.emplace(this, Use::Type);
77}
78
79Nat::Nat(World& world)
80 : Def(Node, world.type(), Defs{}, 0) {}
81
82UMax::UMax(World& world, Defs ops)
83 : Def(Node, world.univ(), ops, 0) {}
84
85// clang-format off
86
87/*
88 * rebuild
89 */
90
91Ref Infer ::rebuild_(World&, Ref, Defs ) const { fe::unreachable(); }
92Ref Global ::rebuild_(World&, Ref, Defs ) const { fe::unreachable(); }
93Ref Idx ::rebuild_(World& w, Ref , Defs ) const { return w.type_idx(); }
94Ref Nat ::rebuild_(World& w, Ref , Defs ) const { return w.type_nat(); }
95Ref Univ ::rebuild_(World& w, Ref , Defs ) const { return w.univ(); }
96Ref Ac ::rebuild_(World& w, Ref t, Defs o) const { return w.ac(t, o); }
97Ref App ::rebuild_(World& w, Ref , Defs o) const { return w.app(o[0], o[1]); }
98Ref Arr ::rebuild_(World& w, Ref , Defs o) const { return w.arr(o[0], o[1]); }
99Ref Extract::rebuild_(World& w, Ref , Defs o) const { return w.extract(o[0], o[1]); }
100Ref Insert ::rebuild_(World& w, Ref , Defs o) const { return w.insert(o[0], o[1], o[2]); }
101Ref Lam ::rebuild_(World& w, Ref t, Defs o) const { return w.lam(t->as<Pi>(), o[0], o[1]); }
102Ref Lit ::rebuild_(World& w, Ref t, Defs ) const { return w.lit(t, get()); }
103Ref Pack ::rebuild_(World& w, Ref t, Defs o) const { return w.pack(t->arity(), o[0]); }
104Ref Pi ::rebuild_(World& w, Ref , Defs o) const { return w.pi(o[0], o[1], is_implicit()); }
105Ref Pick ::rebuild_(World& w, Ref t, Defs o) const { return w.pick(t, o[0]); }
106Ref Proxy ::rebuild_(World& w, Ref t, Defs o) const { return w.proxy(t, o, pass(), tag()); }
107Ref Sigma ::rebuild_(World& w, Ref , Defs o) const { return w.sigma(o); }
108Ref Uniq ::rebuild_(World& w, Ref , Defs o) const { return w.uniq(o[0]); }
109Ref Type ::rebuild_(World& w, Ref , Defs o) const { return w.type(o[0]); }
110Ref Test ::rebuild_(World& w, Ref , Defs o) const { return w.test(o[0], o[1], o[2], o[3]); }
111Ref Tuple ::rebuild_(World& w, Ref t, Defs o) const { return w.tuple(t, o); }
112Ref UInc ::rebuild_(World& w, Ref , Defs o) const { return w.uinc(o[0], offset()); }
113Ref UMax ::rebuild_(World& w, Ref , Defs o) const { return w.umax(o); }
114Ref Var ::rebuild_(World& w, Ref t, Defs o) const { return w.var(t, o[0]->as_mut()); }
115Ref Vel ::rebuild_(World& w, Ref t, Defs o) const { return w.vel(t, o[0])->set(dbg()); }
116
117Ref Axiom ::rebuild_(World& w, Ref t, Defs ) const {
118 if (&w != &world()) return w.axiom(normalizer(), curry(), trip(), t, plugin(), tag(), sub())->set(dbg());
119 assert(Checker::alpha<Checker::Check>(t, type()));
120 return this;
121}
122
123template<bool up> Ref TExt <up>::rebuild_(World& w, Ref t, Defs ) const { return w.ext <up>(t)->set(dbg()); }
124template<bool up> Ref TBound<up>::rebuild_(World& w, Ref , Defs o) const { return w.bound<up>(o)->set(dbg()); }
125
126/*
127 * stub
128 */
129
130Arr* Arr ::stub_(World& w, Ref t) { return w.mut_arr (t); }
131Global* Global::stub_(World& w, Ref t) { return w.global (t, is_mutable()); }
132Infer* Infer ::stub_(World& w, Ref t) { return w.mut_infer(t); }
133Lam* Lam ::stub_(World& w, Ref t) { return w.mut_lam (t->as<Pi>()); }
134Pack* Pack ::stub_(World& w, Ref t) { return w.mut_pack (t); }
135Pi* Pi ::stub_(World& w, Ref t) { return w.mut_pi (t, is_implicit()); }
136Sigma* Sigma ::stub_(World& w, Ref t) { return w.mut_sigma(t, num_ops()); }
137
138template<bool up> TBound<up>* TBound<up>::stub_(World& w, Ref t) { return w.mut_bound<up>(t, num_ops()); }
139template<bool up> TExt <up>* TExt <up>::stub_(World& , Ref ) { fe::unreachable(); }
140
141/*
142 * instantiate templates
143 */
144
145#ifndef DOXYGEN
146template Ref TExt<false> ::rebuild_(World&, Ref, Defs) const;
147template Ref TExt<true > ::rebuild_(World&, Ref, Defs) const;
148template Ref TBound<false>::rebuild_(World&, Ref, Defs) const;
149template Ref TBound<true >::rebuild_(World&, Ref, Defs) const;
154#endif
155
156// clang-format on
157
158/*
159 * immutabilize
160 */
161
162// TODO also check for mutual recursion?
164 auto v = has_var();
165 for (auto op : extended_ops())
166 if ((v && op->free_vars().contains(v)) || op->local_muts().contains(this)) return false;
167 return true;
168}
169
171 if (is_immutabilizable()) return world().pi(dom(), codom());
172 return nullptr;
173}
174
176 if (is_immutabilizable()) return static_cast<const Sigma*>(*world().sigma(ops()));
177 return nullptr;
178}
179
181 auto& w = world();
182 if (is_immutabilizable()) return w.arr(shape(), body());
183
184 if (auto n = Lit::isa(shape()); n && *n < w.flags().scalarize_threshold)
185 return w.sigma(DefVec(*n, [&](size_t i) { return reduce(w.lit_idx(*n, i)); }));
186
187 return nullptr;
188}
189
191 auto& w = world();
192 if (is_immutabilizable()) return w.pack(shape(), body());
193
194 if (auto n = Lit::isa(shape()); n && *n < w.flags().scalarize_threshold)
195 return w.tuple(DefVec(*n, [&](size_t i) { return reduce(w.lit_idx(*n, i)); }));
196
197 return nullptr;
198}
199
200/*
201 * reduce
202 */
203
205 if (auto mut = isa_mut()) return mut->reduce(arg);
206 return DefVec(ops().begin(), ops().end());
207}
208
210 if (auto var = has_var()) {
211 auto& cache = world().move_.cache;
212 if (auto i = cache.find({this, arg}); i != cache.end()) return i->second;
213
214 auto rw = VarRewriter(var, arg);
215 auto res = DefVec(num_ops());
216 for (size_t i = 0, e = res.size(); i != e; ++i) res[i] = rw.rewrite(op(i));
217
218 return cache[{this, arg}] = res;
219 }
220 return DefVec(ops().begin(), ops().end());
221}
222
223Ref Def::reduce(size_t i, Ref arg) const {
224 if (auto mut = isa_mut(); mut && has_var()) return mut->reduce(arg)[i];
225 return op(i);
226}
227
228Ref Def::refine(size_t i, Ref new_op) const {
229 DefVec new_ops(ops().begin(), ops().end());
230 new_ops[i] = new_op;
231 return rebuild(type(), new_ops);
232}
233
234/*
235 * Def - set
236 */
237
238void Def::finalize() {
239 for (size_t i = Use::Type; auto op : partial_ops()) {
240 if (op) {
241 dep_ |= op->dep();
242 if (!op->dep_const()) {
243 const auto& p = op->uses_.emplace(this, i);
244 assert_unused(p.second);
245 }
246 }
247 ++i;
248 }
249}
250
251// clang-format off
252Def* Def:: set(Defs ops) { assert(ops.size() == num_ops()); for (size_t i = 0, e = num_ops(); i != e; ++i) set(i, ops[i]); return this; }
253Def* Def::reset(Defs ops) { assert(ops.size() == num_ops()); for (size_t i = 0, e = num_ops(); i != e; ++i) reset(i, ops[i]); return this; }
254// clang-format on
255
256Def* Def::set(size_t i, Ref def) {
257 invalidate();
258 def = check(i, def);
259 assert(def && !op(i) && curr_op_ == i);
260#ifndef NDEBUG
261 curr_op_ = (curr_op_ + 1) % num_ops();
262#endif
263 ops_ptr()[i] = def;
264 const auto& p = def->uses_.emplace(this, i);
265 assert_unused(p.second);
266
267 if (i == num_ops() - 1) { // set last, op so check kind
268 if (auto t = check(); t != type()) {
269 if (!type_->dep_const()) {
270 assert(type_->uses_.contains(Use(this, Use::Type)));
271 type_->uses_.erase(Use(this, Use::Type));
272 }
273 type_ = t;
274 t->uses_.emplace(this, Use::Type);
275 }
276 }
277
278 return this;
279}
280
282 invalidate();
283#ifndef NDEBUG
284 curr_op_ = 0;
285#endif
286 for (size_t i = 0, e = num_ops(); i != e; ++i) {
287 if (op(i))
288 unset(i);
289 else {
290 assert(std::all_of(ops_ptr() + i + 1, ops_ptr() + num_ops(), [](auto op) { return !op; }));
291 break;
292 }
293 }
294 return this;
295}
296
297Def* Def::unset(size_t i) {
298 invalidate();
299 assert(ops_ptr()[i] && ops_ptr()[i]->uses_.contains(Use(this, i)));
300 ops_ptr()[i]->uses_.erase(Use(this, i));
301 ops_ptr()[i] = nullptr;
302 return this;
303}
304
305bool Def::is_set() const {
306 if (num_ops() == 0) return true;
307 bool result = ops().back();
308 assert((!result || std::ranges::all_of(ops().rsubspan(1), [](auto op) { return op; }))
309 && "the last operand is set but others in front of it aren't");
310 return result;
311}
312
313/*
314 * free_vars
315 */
316
318 if (auto mut = isa_mut()) return world().muts().create(mut);
319 return muts_.local;
320}
321
323 if (auto mut = isa_mut()) return mut->free_vars();
324
325 auto vars = local_vars();
326 for (auto mut : local_muts()) vars = world().vars().merge(vars, mut->free_vars());
327 return vars;
328}
329
331 if (!is_set()) return {};
332
333 if (!valid_) {
334 // fixed-point interation to recompute vars_.free
335 uint32_t run = 1;
336 for (bool todo = true; todo;) {
337 todo = false;
338 free_vars(todo, ++run);
339 }
340 validate();
341 }
342
343 return vars_.free;
344}
345
346Vars Def::free_vars(bool& todo, uint32_t run) {
347 // Recursively recompute vars_.free. If
348 // * valid_ == true: no recomputation is necessary
349 // * mark_ == run: We are running in cycles within the *current* iteration of our fixed-point loop
350 if (valid_ || mark_ == run) return vars_.free;
351 mark_ = run;
352
353 auto fvs0 = vars_.free;
354 auto fvs = fvs0;
355
356 for (auto op : extended_ops()) fvs = world().vars().merge(fvs, op->local_vars());
357
358 for (auto op : extended_ops()) {
359 for (auto local_mut : op->local_muts()) {
360 local_mut->muts_.fv_consumers = world().muts().insert(local_mut->muts_.fv_consumers, this);
361 fvs = world().vars().merge(fvs, local_mut->free_vars(todo, run));
362 }
363 }
364
365 if (auto var = has_var()) fvs = world().vars().erase(fvs, var); // FV(λx.e) = FV(e) \ {x}
366
367 todo |= fvs0 != fvs;
368 return vars_.free = fvs;
369}
370
371void Def::validate() {
372 valid_ = true;
373 mark_ = 0;
374
375 for (auto op : extended_ops()) {
376 for (auto local_mut : op->local_muts())
377 if (!local_mut->valid_) local_mut->validate();
378 }
379}
380
381void Def::invalidate() {
382 if (valid_) {
383 valid_ = false;
384 for (auto mut : fv_consumers()) mut->invalidate();
385 vars_.free.clear();
386 muts_.fv_consumers.clear();
387 }
388}
389
390bool Def::is_closed() const {
391 if (local_vars().empty() && local_muts().empty()) return true;
392#ifdef MIM_ENABLE_CHECKS
393 assert(!is_external() || free_vars().empty());
394#endif
395 return free_vars().empty();
396}
397
398bool Def::is_open() const {
399 if (!local_vars().empty() || !local_muts().empty()) return true;
400 return !free_vars().empty();
401}
402
403/*
404 * Def - misc
405 */
406
407Sym Def::sym(const char* s) const { return world().sym(s); }
408Sym Def::sym(std::string_view s) const { return world().sym(s); }
409Sym Def::sym(std::string s) const { return world().sym(std::move(s)); }
410
412 if (isa<Univ>()) return *world_;
413 if (auto type = isa<Type>()) return type->level()->world();
414 return type()->world(); // TODO unroll
415}
416
418 if (!type_) {
419 if (auto t = isa<Type>()) return world().type(world().uinc(t->level()));
420 assert(isa<Univ>());
421 return nullptr;
422 }
423
424 return type_;
425}
426
427std::string_view Def::node_name() const {
428 switch (node()) {
429#define CODE(op, abbr) \
430 case Node::op: return #abbr;
432#undef CODE
433 default: fe::unreachable();
434 }
435}
436
438 if (isa<Type>() || isa<Univ>()) return Defs();
439 assert(type());
440 return Defs(ops_ptr() - 1, (is_set() ? num_ops_ : 0) + 1);
441}
442
443#ifndef NDEBUG
444const Def* Def::debug_prefix(std::string prefix) const { return dbg_.set(world().sym(prefix + sym().str())), this; }
445const Def* Def::debug_suffix(std::string suffix) const { return dbg_.set(world().sym(sym().str() + suffix)), this; }
446#endif
447
448// clang-format off
449
451 if (var_) return var_;
452 auto& w = world();
453
454 if (w.is_frozen()) return nullptr;
455 if (auto lam = isa<Lam >()) return w.var(lam ->dom(), lam);
456 if (auto pi = isa<Pi >()) return w.var(pi ->dom(), pi);
457 if (auto sig = isa<Sigma>()) return w.var(sig, sig);
458 if (auto arr = isa<Arr >()) return w.var(w.type_idx(arr ->shape()), arr ); // TODO shapes like (2, 3)
459 if (auto pack = isa<Pack >()) return w.var(w.type_idx(pack->shape()), pack); // TODO shapes like (2, 3)
460 if (isa<Bound >()) return w.var(this, this);
461 if (isa<Infer >()) return nullptr;
462 if (isa<Global>()) return nullptr;
463 fe::unreachable();
464}
465
466bool Def::is_term() const {
467 if (auto t = type()) {
468 if (auto u = t->type()) {
469 if (auto type = u->isa<Type>()) {
470 if (auto level = Lit::isa(type->level())) return *level == 0;
471 }
472 }
473 }
474 return false;
475}
476
478 if (auto sigma = isa<Sigma>()) return world().lit_nat(sigma->num_ops());
479 if (auto arr = isa<Arr >()) return arr->shape();
480 if (auto t = type()) return t->arity();
481 return world().lit_nat_1();
482}
483
484std::optional<nat_t> Def::isa_lit_arity() const {
485 if (auto sigma = isa<Sigma>()) return sigma->num_ops();
486 if (auto arr = isa<Arr >()) return Lit::isa(arr->shape());
487 if (auto t = type()) return t->isa_lit_arity();
488 return 1;
489}
490
491// clang-format on
492
493bool Def::equal(const Def* other) const {
494 if (isa<Univ>() || this->isa_mut() || other->isa_mut()) return this == other;
495
496 bool result = this->node() == other->node() && this->flags() == other->flags()
497 && this->num_ops() == other->num_ops() && this->type() == other->type();
498
499 for (size_t i = 0, e = num_ops(); result && i != e; ++i) result &= this->op(i) == other->op(i);
500
501 return result;
502}
503
504void Def::make_external() { return world().make_external(this); }
505void Def::make_internal() { return world().make_internal(this); }
506
507std::string Def::unique_name() const { return sym().str() + "_"s + std::to_string(gid()); }
508
510 if (auto a = isa_lit_arity(); a && *a < world().flags().scalarize_threshold) return *a;
511 return 1;
512}
513
515 static constexpr int Search_In_Uses_Threshold = 8;
516
517 World& w = world();
518
519 if (auto arr = isa<Arr>()) {
520 if (arr->arity()->isa<Top>()) return arr->body();
521 return arr->reduce(w.lit_idx(a, i));
522 } else if (auto pack = isa<Pack>()) {
523 if (pack->arity()->isa<Top>()) return pack->body();
524 assert(!w.is_frozen() && "TODO");
525 return pack->reduce(w.lit_idx(a, i));
526 }
527
528 if (a == 1) {
529 if (!type()) return this;
530 if (!isa_mut<Sigma>() && !type()->isa_mut<Sigma>()) return this;
531 }
532
533 if (isa<Tuple>() || isa<Sigma>()) return op(i);
534
535 if (w.is_frozen() || uses().size() < Search_In_Uses_Threshold) {
536 for (auto u : uses()) {
537 if (auto ex = u->isa<Extract>(); ex && ex->tuple() == this) {
538 if (auto index = Lit::isa(ex->index()); index && *index == i) return ex;
539 }
540 }
541
542 if (w.is_frozen()) return nullptr;
543 }
544
545 return w.extract(this, a, i);
546}
547
548/*
549 * Idx
550 */
551
553 if (auto app = def->isa<App>()) {
554 if (app->callee()->isa<Idx>()) return app->arg();
555 }
556
557 return nullptr;
558}
559
560std::optional<nat_t> Idx::isa_lit(Ref def) {
561 if (auto size = Idx::isa(def))
562 if (auto l = Lit::isa(size)) return l;
563 return {};
564}
565
566std::optional<nat_t> Idx::size2bitwidth(Ref size) {
567 if (size->isa<Top>()) return 64;
568 if (auto s = Lit::isa(size)) return size2bitwidth(*s);
569 return {};
570}
571
572/*
573 * Global
574 */
575
576const App* Global::type() const { return Def::type()->as<App>(); }
577Ref Global::alloced_type() const { return type()->arg(0); }
578
579} // namespace mim
Ref arg() const
Definition lam.h:222
A (possibly paramterized) Array.
Definition tuple.h:67
const Def * immutabilize() override
Tries to make an immutable from a mutable.
Definition def.cpp:180
Ref body() const
Definition tuple.h:78
Ref shape() const
Definition tuple.h:77
Ref reduce(Ref arg) const
Definition tuple.h:92
static bool alpha(Ref d1, Ref d2)
Definition check.h:65
Base class for all Defs.
Definition def.h:226
bool is_set() const
Yields true if empty or the last op is set.
Definition def.cpp:305
const Uses & uses() const
Definition def.h:322
auto vars()
Definition def.h:395
void make_internal()
Definition def.cpp:505
size_t num_ops() const
Definition def.h:273
Ref type() const
Definition def.h:251
Ref var()
Not necessarily a Var: E.g., if the return type is [], this will yield ().
Definition def.cpp:450
nat_t num_tprojs() const
As above but yields 1, if Flags::scalarize_threshold is exceeded.
Definition def.cpp:509
std::string_view node_name() const
Definition def.cpp:427
Defs extended_ops() const
Definition def.cpp:437
Vars local_vars() const
Vars reachable by following immutable extended_ops().
Definition def.h:418
void make_external()
Definition def.cpp:504
Ref unfold_type() const
Yields the type of this Def and builds a new Type (UInc n) if necessary.
Definition def.cpp:417
Muts fv_consumers()
Definition def.h:424
virtual Ref check()
Definition def.h:530
Def * set(size_t i, Ref)
Successively set from left to right.
Definition def.cpp:256
World & world() const
Definition def.cpp:411
Dbg dbg_
Definition def.h:586
Ref op(size_t i) const
Definition def.h:272
T * isa_mut() const
If this is *mut*able, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:445
DefVec reduce(Ref arg) const
Rewrites Def::ops by substituting this mutable's Var with arg.
Definition def.cpp:204
unsigned dep() const
Definition def.h:329
bool is_term() const
Yields true if this:T and T:(Type 0).
Definition def.cpp:466
const Def * debug_prefix(std::string) const
Definition def.cpp:444
bool dep_const() const
Definition def.h:332
bool is_immutabilizable()
Definition def.cpp:163
bool is_external() const
Definition def.h:429
Def * reset(size_t i, Ref def)
Successively reset from left to right.
Definition def.h:294
bool is_open() const
Has free_vars()?
Definition def.cpp:398
auto ops() const
Definition def.h:271
Muts local_muts() const
Mutables reachable by following immutable extended_ops().
Definition def.cpp:317
const Def * debug_suffix(std::string) const
Definition def.cpp:445
node_t node() const
Definition def.h:244
u32 gid() const
Definition def.h:242
Ref arity() const
Definition def.cpp:477
Sym sym() const
Definition def.h:466
flags_t flags() const
Definition def.h:241
std::optional< nat_t > isa_lit_arity() const
Definition def.cpp:484
flags_t flags_
Definition def.h:593
Defs partial_ops() const
Definition def.h:315
Ref rebuild(World &w, Ref type, Defs ops) const
Def::rebuilds this Def while using new_op as substitute for its i'th Def::op.
Definition def.h:507
Ref 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:514
Def * unset()
Unsets all Def::ops; works even, if not set at all or partially.
Definition def.cpp:281
std::string unique_name() const
name + "_" + Def::gid
Definition def.cpp:507
Ref refine(size_t i, Ref new_op) const
Definition def.cpp:228
bool is_closed() const
Has no free_vars()?
Definition def.cpp:390
Vars free_vars() const
Compute a global solution, i.e., by transitively following mutables as well.
Definition def.cpp:322
const Var * has_var()
Only returns not nullptr, if Var of this mutable has ever been created.
Definition def.h:399
Extracts from a Sigma or Array-typed Extract::tuple the element at position Extract::index.
Definition tuple.h:154
Ref tuple() const
Definition tuple.h:164
Ref rebuild_(World &, Ref, Defs) const override
Definition def.cpp:99
Ref alloced_type() const
Definition def.cpp:577
bool is_mutable() const
Definition def.h:883
const App * type() const
Definition def.cpp:576
Global * stub_(World &, Ref) override
Definition def.cpp:131
A built-in constant of type Nat -> *.
Definition def.h:792
static constexpr nat_t size2bitwidth(nat_t n)
Definition def.h:823
static Ref isa(Ref def)
Definition def.cpp:552
static std::optional< nat_t > isa_lit(Ref def)
Definition def.cpp:560
This node is a hole in the IR that is inferred by its context later on.
Definition check.h:10
A function.
Definition lam.h:104
static std::optional< T > isa(Ref def)
Definition def.h:762
A (possibly paramterized) Tuple.
Definition tuple.h:114
Ref shape() const
Definition tuple.cpp:40
Ref body() const
Definition tuple.h:124
Ref reduce(Ref arg) const
Definition tuple.h:139
const Def * immutabilize() override
Tries to make an immutable from a mutable.
Definition def.cpp:190
A dependent function type.
Definition lam.h:11
Ref codom() const
Definition lam.h:33
const Pi * immutabilize() override
Tries to make an immutable from a mutable.
Definition def.cpp:170
Ref dom() const
Definition lam.h:32
constexpr bool contains(const T &elem) const
Definition pool.h:66
constexpr bool empty() const noexcept
Definition pool.h:61
constexpr void clear() noexcept
Definition pool.h:55
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:175
This is a thin wrapper for std::span<T, N> with the following additional features:
Definition span.h:28
Specific Bound depending on Up.
Definition lattice.h:31
Ref rebuild_(World &, Ref, Defs) const override
Definition def.cpp:124
TBound * stub_(World &, Ref) override
Definition def.cpp:138
Extremum. Either Top (Up) or Bottom.
Definition lattice.h:156
Ref rebuild_(World &, Ref, Defs) const override
Definition def.cpp:123
TExt * stub_(World &, Ref) override
Definition def.cpp:139
References a user.
Definition def.h:111
static constexpr size_t Type
Definition def.h:113
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:33
auto & muts()
Definition world.h:516
void make_internal(Def *def)
Definition world.h:175
Flags & flags()
Retrive compile Flags.
Definition world.cpp:74
u32 next_gid()
Definition world.h:90
Sym sym(std::string_view)
Definition world.cpp:77
const Pi * pi(Ref dom, Ref codom, bool implicit=false)
Definition world.h:255
void make_external(Def *def)
Definition world.h:169
const Lit * lit_nat(nat_t a)
Definition world.h:387
Ref sigma(Defs ops)
Definition world.cpp:225
const Type * type(Ref level)
Definition world.cpp:94
auto & vars()
Definition world.h:515
const Lit * lit_nat_1()
Definition world.h:389
#define MIM_NODE(m)
Definition def.h:18
@ Univ
Definition def.h:40
Definition cfg.h:11
View< const Def * > Defs
Definition def.h:61
u64 nat_t
Definition types.h:43
Vector< const Def * > DefVec
Definition def.h:62
Dep
Definition def.h:155
u64 flags_t
Definition types.h:45
uint64_t scalarize_threshold
Definition flags.h:13
u8 node_t
Definition types.h:44
PooledSet< Def * > Muts
Definition def.h:71
size_t hash_combine(size_t seed, T v)
Definition hash.h:58
size_t hash(size_t h)
Definition hash.h:32
PooledSet< const Var * > Vars
Definition def.h:80
uint32_t u32
Definition types.h:34
size_t hash_begin()
Definition hash.h:71
uint8_t u8
Definition types.h:34
Dbg & set(Sym sym)
Definition dbg.h:153
#define CODE(t, str)
Definition tok.h:54