MimIR 0.1
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
world.cpp
Go to the documentation of this file.
1#include "mim/world.h"
2
3#include "mim/check.h"
4#include "mim/def.h"
5#include "mim/driver.h"
6#include "mim/rewrite.h"
7#include "mim/tuple.h"
8
9#include "mim/util/util.h"
10
11namespace mim {
12
13namespace {
14bool is_shape(Ref s) {
15 if (s->isa<Nat>()) return true;
16 if (auto arr = s->isa<Arr>()) return arr->body()->isa<Nat>();
17 if (auto sig = s->isa_imm<Sigma>()) return std::ranges::all_of(sig->ops(), [](Ref op) { return op->isa<Nat>(); });
18
19 return false;
20}
21
22const Def* infer_sigma(World& world, Defs ops) {
23 DefVec elems(ops.size());
24 for (size_t i = 0, e = ops.size(); i != e; ++i) elems[i] = ops[i]->type();
25 return world.sigma(elems);
26}
27} // namespace
28
29/*
30 * constructor & destructor
31 */
32
33#if (!defined(_MSC_VER) && defined(NDEBUG))
34bool World::Lock::guard_ = false;
35#endif
36
37World::World(Driver* driver, const State& state)
38 : driver_(driver)
39 , state_(state) {
40 data_.univ = insert<Univ>(0, *this);
41 data_.lit_univ_0 = lit_univ(0);
42 data_.lit_univ_1 = lit_univ(1);
43 data_.type_0 = type(lit_univ_0());
44 data_.type_1 = type(lit_univ_1());
45 data_.type_bot = insert<Bot>(0, type());
46 data_.type_top = insert<Top>(0, type());
47 data_.sigma = insert<Sigma>(0, type(), Defs{})->as<Sigma>();
48 data_.tuple = insert<Tuple>(0, sigma(), Defs{})->as<Tuple>();
49 data_.type_nat = insert<mim::Nat>(0, *this);
50 data_.type_idx = insert<mim::Idx>(0, pi(type_nat(), type()));
51 data_.top_nat = insert<Top>(0, type_nat());
52 data_.lit_nat_0 = lit_nat(0);
53 data_.lit_nat_1 = lit_nat(1);
54 data_.lit_0_1 = lit_idx(1, 0);
55 data_.type_bool = type_idx(2);
56 data_.lit_bool[0] = lit_idx(2, 0_u64);
57 data_.lit_bool[1] = lit_idx(2, 1_u64);
58 data_.lit_nat_max = lit_nat(nat_t(-1));
59 data_.exit = mut_lam(cn(type_bot()))->set(sym("exit"));
60}
61
63 : World(driver, State()) {}
64
66 for (auto def : move_.defs) def->~Def();
67}
68
69/*
70 * Driver
71 */
72
73Log& World::log() { return driver().log(); }
74Flags& World::flags() { return driver().flags(); }
75
76Sym World::sym(const char* s) { return driver().sym(s); }
77Sym World::sym(std::string_view s) { return driver().sym(s); }
78Sym World::sym(const std::string& s) { return driver().sym(s); }
79
80const Def* World::register_annex(flags_t f, const Def* def) {
81 // TODO enable again
82 /*DLOG("register: 0x{f} -> {}", f, def);*/
83 auto plugin = Annex::demangle(driver(), f);
84 if (driver().is_loaded(plugin)) {
85 assert_emplace(move_.annexes, f, def);
86 return def;
87 }
88 return nullptr;
89}
90/*
91 * factory methods
92 */
93
94const Type* World::type(Ref level) {
95 if (!level->type()->isa<Univ>())
96 error(level->loc(), "argument `{}` to `Type` must be of type `Univ` but is of type `{}`", level, level->type());
97
98 return unify<Type>(1, level)->as<Type>();
99}
100
102 if (!op->type()->isa<Univ>())
103 error(op->loc(), "operand '{}' of a universe increment must be of type `Univ` but is of type `{}`", op,
104 op->type());
105
106 if (auto l = Lit::isa(op)) return lit_univ(*l + 1);
107 return unify<UInc>(1, op, offset);
108}
109
110template<Sort sort> Ref World::umax(Defs ops_) {
111 // consume nested umax
112 DefVec ops;
113 for (auto op : ops_)
114 if (auto um = op->isa<UMax>())
115 ops.insert(ops.end(), um->ops().begin(), um->ops().end());
116 else
117 ops.emplace_back(op);
118
119 level_t lvl = 0;
120 for (auto& op : ops) {
121 Ref r = op;
122 if (sort == Sort::Term) r = r->unfold_type();
123 if (sort <= Sort::Type) r = r->unfold_type();
124 if (sort <= Sort::Kind) {
125 if (auto type = r->isa<Type>())
126 r = type->level();
127 else
128 error(r->loc(), "operand '{}' must be a Type of some level", r);
129 }
130
131 if (!r->type()->isa<Univ>())
132 error(r->loc(), "operand '{}' of a universe max must be of type 'Univ' but is of type '{}'", r, r->type());
133
134 op = r;
135
136 if (auto l = Lit::isa(op))
137 lvl = std::max(lvl, *l);
138 else
139 lvl = level_t(-1);
140 }
141
142 const Def* ldef;
143 if (lvl != level_t(-1))
144 ldef = lit_univ(lvl);
145 else {
146 std::ranges::sort(ops, [](auto op1, auto op2) { return op1->gid() < op2->gid(); });
147 ops.erase(std::unique(ops.begin(), ops.end()), ops.end());
148 ldef = unify<UMax>(ops.size(), *this, ops);
149 }
150
151 return sort == Sort::Univ ? ldef : type(ldef);
152}
153
154// TODO more thorough & consistent checks for singleton types
155
156Ref World::var(Ref type, Def* mut) {
157 if (auto s = Idx::isa(type)) {
158 if (auto l = Lit::isa(s); l && l == 1) return lit_0_1();
159 }
160
161 if (auto var = mut->var_) return var;
162 return mut->var_ = unify<Var>(1, type, mut);
163}
164
165template<bool Normalize> Ref World::implicit_app(Ref callee, Ref arg) {
166 while (auto pi = Pi::isa_implicit(callee->type())) callee = app(callee, mut_infer(pi->dom()));
167 return app<Normalize>(callee, arg);
168}
169
170template<bool Normalize> Ref World::app(Ref callee, Ref arg) {
171 callee = callee->zonk();
172 if (auto pi = callee->type()->isa<Pi>()) {
173 if (auto new_arg = Checker::assignable(pi->dom(), arg)) {
174 arg = new_arg;
175 if (auto imm = callee->isa_imm<Lam>()) return imm->body();
176 if (auto lam = callee->isa_mut<Lam>(); lam && lam->is_set() && lam->filter() != lit_ff()) {
177 VarRewriter rw(lam->var(), arg);
178 if (rw.rewrite(lam->filter()) == lit_tt()) {
179 DLOG("partial evaluate: {} ({})", lam, arg);
180 return rw.rewrite(lam->body());
181 }
182 }
183
184 auto type = pi->reduce(arg);
185 auto [axiom, curry, trip] = Axiom::get(callee);
186 if (axiom) {
187 curry = curry == 0 ? trip : curry;
188 curry = curry == Axiom::Trip_End ? curry : curry - 1;
189
190 if (auto normalizer = axiom->normalizer(); Normalize && normalizer && curry == 0) {
191 if (auto norm = normalizer(type, callee, arg)) return norm;
192 }
193 }
194
195 return raw_app(axiom, curry, trip, type, callee, arg);
196 }
197
198 throw Error()
199 .error(arg->loc(), "cannot apply argument to callee")
200 .note(callee->loc(), "callee: '{}'", callee)
201 .note(arg->loc(), "argument: '{}'", arg)
202 .note(callee->loc(), "vvv domain type vvv\n'{}'\n'{}'", pi->dom(), arg->type())
203 .note(arg->loc(), "^^^ argument type ^^^");
204 }
205
206 throw Error()
207 .error(callee->loc(), "called expression not of function type")
208 .error(callee->loc(), "'{}' <--- callee type", callee->type());
209}
210
211Ref World::raw_app(Ref type, Ref callee, Ref arg) {
212 auto [axiom, curry, trip] = Axiom::get(callee);
213 if (axiom) {
214 curry = curry == 0 ? trip : curry;
215 curry = curry == Axiom::Trip_End ? curry : curry - 1;
216 }
217
218 return raw_app(axiom, curry, trip, type, callee, arg);
219}
220
221Ref World::raw_app(const Axiom* axiom, u8 curry, u8 trip, Ref type, Ref callee, Ref arg) {
222 return unify<App>(2, axiom, curry, trip, type, callee, arg);
223}
224
226 auto n = ops.size();
227 if (n == 0) return sigma();
228 if (n == 1) return ops[0];
229 if (auto uni = Checker::is_uniform(ops)) return arr(n, uni);
230 return unify<Sigma>(ops.size(), Sigma::infer(*this, ops), ops);
231}
232
234 if (ops.size() == 1) return ops[0];
235
236 auto sigma = infer_sigma(*this, ops);
237 auto t = tuple(sigma, ops);
238 auto new_t = Checker::assignable(sigma, t);
239 if (!new_t)
240 error(t->loc(), "cannot assign tuple '{}' of type '{}' to incompatible tuple type '{}'", t, t->type(), sigma);
241
242 return new_t;
243}
244
246 // TODO type-check type vs inferred type
247
248 auto n = ops.size();
249 if (!type->isa_mut<Sigma>()) {
250 if (n == 0) return tuple();
251 if (n == 1) return ops[0];
252 if (auto uni = Checker::is_uniform(ops)) return pack(n, uni);
253 }
254
255 if (n != 0) {
256 // eta rule for tuples:
257 // (extract(tup, 0), extract(tup, 1), extract(tup, 2)) -> tup
258 if (auto extract = ops[0]->isa<Extract>()) {
259 auto tup = extract->tuple();
260 bool eta = tup->type() == type;
261 for (size_t i = 0; i != n && eta; ++i) {
262 if (auto extract = ops[i]->isa<Extract>()) {
263 if (auto index = Lit::isa(extract->index())) {
264 if (eta &= u64(i) == *index) {
265 eta &= extract->tuple() == tup;
266 continue;
267 }
268 }
269 }
270 eta = false;
271 }
272
273 if (eta) return tup;
274 }
275 }
276
277 return unify<Tuple>(ops.size(), type, ops);
278}
279
281 DefVec defs;
282 std::ranges::transform(sym, std::back_inserter(defs), [this](auto c) { return lit_i8(c); });
283 return tuple(defs);
284}
285
287 if (index->isa<Tuple>()) {
288 auto n = index->num_ops();
289 auto idx = DefVec(n, [&](size_t i) { return index->op(i); });
290 auto ops = DefVec(n, [&](size_t i) { return d->proj(n, Lit::as(idx[i])); });
291 return tuple(ops);
292 } else if (index->isa<Pack>()) {
293 auto ops = DefVec(index->as_lit_arity(), [&](size_t) { return extract(d, index->ops().back()); });
294 return tuple(ops);
295 }
296
297 Ref size = Idx::isa(index->type());
298 Ref type = d->unfold_type()->zonk();
299
300 if (auto l = Lit::isa(size); l && *l == 1) {
301 if (auto l = Lit::isa(index); !l || *l != 0) WLOG("unknown Idx of size 1: {}", index);
302 if (auto sigma = type->isa_mut<Sigma>(); sigma && sigma->num_ops() == 1) {
303 // mut sigmas can be 1-tuples; TODO mutables Arr?
304 } else {
305 return d;
306 }
307 }
308
309 if (auto pack = d->isa_imm<Pack>()) return pack->body();
310
312 error(index->loc(), "index '{}' does not fit within arity '{}'", index, type->arity());
313
314 // extract(insert(x, index, val), index) -> val
315 if (auto insert = d->isa<Insert>()) {
316 if (index == insert->index()) return insert->value();
317 }
318
319 if (auto i = Lit::isa(index)) {
320 if (auto infer = d->isa_mut<Infer>()) d = infer->tuplefy();
321 if (auto tuple = d->isa<Tuple>()) return tuple->op(*i);
322
323 // extract(insert(x, j, val), i) -> extract(x, i) where i != j (guaranteed by rule above)
324 if (auto insert = d->isa<Insert>()) {
325 if (insert->index()->isa<Lit>()) return extract(insert->tuple(), index);
326 }
327
328 if (auto sigma = type->isa<Sigma>()) {
329 if (auto mut_sigma = sigma->isa_mut<Sigma>()) {
330 auto t = VarRewriter(mut_sigma->var(), d).rewrite(sigma->op(*i));
331 return unify<Extract>(2, t, d, index);
332 }
333
334 return unify<Extract>(2, sigma->op(*i), d, index);
335 }
336 }
337
338 const Def* elem_t;
339 if (auto arr = type->isa<Arr>())
340 elem_t = arr->reduce(index);
341 else
342 elem_t = extract(tuple(type->as<Sigma>()->ops()), index);
343
344 assert(d);
345 return unify<Extract>(2, elem_t, d, index);
346}
347
348Ref World::insert(Ref d, Ref index, Ref val) {
349 auto type = d->unfold_type();
350 auto size = Idx::isa(index->type());
351 auto lidx = Lit::isa(index);
352
354 error(index->loc(), "index '{}' does not fit within arity '{}'", index, type->arity());
355
356 if (lidx) {
357 auto elem_type = type->proj(*lidx);
358 auto new_val = Checker::assignable(elem_type, val);
359 if (!new_val) {
360 throw Error()
361 .error(val->loc(), "value to be inserted not assignable to element")
362 .note(val->loc(), "vvv value type vvv \n'{}'\n'{}'", val->type(), elem_type)
363 .note(val->loc(), "^^^ element type ^^^", elem_type);
364 }
365 val = new_val;
366 }
367
368 if (auto l = Lit::isa(size); l && *l == 1)
369 return tuple(d, {val}); // d could be mut - that's why the tuple ctor is needed
370
371 // insert((a, b, c, d), 2, x) -> (a, b, x, d)
372 if (auto t = d->isa<Tuple>(); t && lidx) return t->refine(*lidx, val);
373
374 // insert(‹4; x›, 2, y) -> (x, x, y, x)
375 if (auto pack = d->isa<Pack>(); pack && lidx) {
376 if (auto a = pack->isa_lit_arity(); a && *a < flags().scalarize_threshold) {
377 auto new_ops = DefVec(*a, pack->body());
378 new_ops[*lidx] = val;
379 return tuple(type, new_ops);
380 }
381 }
382
383 // insert(insert(x, index, y), index, val) -> insert(x, index, val)
384 if (auto insert = d->isa<Insert>()) {
385 if (insert->index() == index) d = insert->tuple();
386 }
387
388 return unify<Insert>(3, d, index, val);
389}
390
391// TODO merge this code with pack
392Ref World::arr(Ref shape, Ref body) {
393 if (!is_shape(shape->type())) error(shape->loc(), "expected shape but got '{}' of type '{}'", shape, shape->type());
394
395 if (auto a = Lit::isa(shape)) {
396 if (*a == 0) return sigma();
397 if (*a == 1) return body;
398 }
399
400 // «(a, b)#i; T» -> («a, T», <b, T»)#i
401 if (auto ex = shape->isa<Extract>()) {
402 if (auto tup = ex->tuple()->isa<Tuple>()) {
403 auto arrs = DefVec(tup->num_ops(), [&](size_t i) { return arr(tup->op(i), body); });
404 return extract(tuple(arrs), ex->index());
405 }
406 }
407
408 // «(a, b, c); body» -> «a; «(b, c); body»»
409 if (auto tuple = shape->isa<Tuple>()) return arr(tuple->ops().front(), arr(tuple->ops().subspan(1), body));
410
411 // «<n; x>; body» -> «x; «<n-1, x>; body»»
412 if (auto p = shape->isa<Pack>()) {
413 if (auto s = Lit::isa(p->shape())) return arr(*s, arr(pack(*s - 1, p->body()), body));
414 }
415
416 return unify<Arr>(2, body->unfold_type(), shape, body);
417}
418
419Ref World::pack(Ref shape, Ref body) {
420 if (!is_shape(shape->type())) error(shape->loc(), "expected shape but got '{}' of type '{}'", shape, shape->type());
421
422 if (auto a = Lit::isa(shape)) {
423 if (*a == 0) return tuple();
424 if (*a == 1) return body;
425 }
426
427 // <(a, b, c); body> -> <a; «(b, c); body>>
428 if (auto tuple = shape->isa<Tuple>()) return pack(tuple->ops().front(), pack(tuple->ops().subspan(1), body));
429
430 // <<n; x>; body> -> <x; <<n-1, x>; body>>
431 if (auto p = shape->isa<Pack>()) {
432 if (auto s = Lit::isa(p->shape())) return pack(*s, pack(pack(*s - 1, p->body()), body));
433 }
434
435 auto type = arr(shape, body->type());
436 return unify<Pack>(1, type, body);
437}
438
439Ref World::arr(Defs shape, Ref body) {
440 if (shape.empty()) return body;
441 return arr(shape.rsubspan(1), arr(shape.back(), body));
442}
443
444Ref World::pack(Defs shape, Ref body) {
445 if (shape.empty()) return body;
446 return pack(shape.rsubspan(1), pack(shape.back(), body));
447}
448
449const Lit* World::lit(Ref type, u64 val) {
450 if (auto size = Idx::isa(type)) {
451 if (auto s = Lit::isa(size)) {
452 if (*s != 0 && val >= *s) error(type->loc(), "index '{}' does not fit within arity '{}'", size, val);
453 } else if (val != 0) { // 0 of any size is allowed
454 error(type->loc(), "cannot create literal '{}' of 'Idx {}' as size is unknown", val, size);
455 }
456 }
457
458 return unify<Lit>(0, type, val);
459}
460
461/*
462 * set
463 */
464
465template<bool Up> Ref World::ext(Ref type) {
466 if (auto arr = type->isa<Arr>()) return pack(arr->shape(), ext<Up>(arr->body()));
467 if (auto sigma = type->isa<Sigma>())
468 return tuple(sigma, DefVec(sigma->num_ops(), [&](size_t i) { return ext<Up>(sigma->op(i)); }));
469 return unify<TExt<Up>>(0, type);
470}
471
472template<bool Up> Ref World::bound(Defs ops) {
473 auto kind = umax<Sort::Type>(ops);
474
475 // has ext<Up> value?
476 if (std::ranges::any_of(ops, [&](Ref op) { return Up ? bool(op->isa<Top>()) : bool(op->isa<Bot>()); }))
477 return ext<Up>(kind);
478
479 // ignore: ext<!Up>
480 DefVec cpy(ops.begin(), ops.end());
481 auto [_, end] = std::ranges::copy_if(ops, cpy.begin(), [&](Ref op) { return !op->isa<Ext>(); });
482
483 // sort and remove duplicates
484 std::sort(cpy.begin(), end, GIDLt<const Def*>());
485 end = std::unique(cpy.begin(), end);
486 cpy.resize(std::distance(cpy.begin(), end));
487
488 if (cpy.size() == 0) return ext<!Up>(kind);
489 if (cpy.size() == 1) return cpy[0];
490
491 // TODO simplify mixed terms with joins and meets
492
493 return unify<TBound<Up>>(cpy.size(), kind, cpy);
494}
495
496Ref World::ac(Ref type, Defs ops) {
497 if (type->isa<Meet>()) {
498 auto types = DefVec(ops.size(), [&](size_t i) { return ops[i]->type(); });
499 return unify<Ac>(ops.size(), meet(types), ops);
500 }
501
502 assert(ops.size() == 1);
503 return ops[0];
504}
505
506Ref World::ac(Defs ops) { return ac(umax<Sort::Term>(ops), ops); }
507
508Ref World::vel(Ref type, Ref value) {
509 if (type->isa<Join>()) return unify<Vel>(1, type, value);
510 return value;
511}
512
513Ref World::pick(Ref type, Ref value) { return unify<Pick>(1, type, value); }
514
515Ref World::test(Ref value, Ref probe, Ref match, Ref clash) {
516 auto m_pi = match->type()->isa<Pi>();
517 auto c_pi = clash->type()->isa<Pi>();
518
519 // TODO proper error msg
520 assert(m_pi && c_pi);
521 auto a = m_pi->dom()->isa_lit_arity();
522 assert_unused(a && *a == 2);
523 assert(Checker::alpha<Checker::Check>(m_pi->dom(2, 0_s), c_pi->dom()));
524
525 auto codom = join({m_pi->codom(), c_pi->codom()});
526 return unify<Test>(4, pi(c_pi->dom(), codom), value, probe, match, clash);
527}
528
529Ref World::uniq(Ref inhabitant) { return unify<Uniq>(1, inhabitant->type()->unfold_type(), inhabitant); }
530
531Sym World::append_suffix(Sym symbol, std::string suffix) {
532 auto name = symbol.str();
533
534 auto pos = name.find(suffix);
535 if (pos != std::string::npos) {
536 auto num = name.substr(pos + suffix.size());
537 if (num.empty()) {
538 name += "_1";
539 } else {
540 num = num.substr(1);
541 num = std::to_string(std::stoi(num) + 1);
542 name = name.substr(0, pos + suffix.size()) + "_" + num;
543 }
544 } else {
545 name += suffix;
546 }
547
548 return sym(std::move(name));
549}
550
551/*
552 * debugging
553 */
554
555#ifdef MIM_ENABLE_CHECKS
556
557void World::breakpoint(u32 gid) { state_.breakpoints.emplace(gid); }
558
560 auto i = std::ranges::find_if(move_.defs, [=](auto def) { return def->gid() == gid; });
561 if (i == move_.defs.end()) return nullptr;
562 return *i;
563}
564
566 for (auto [_, mut] : externals()) assert(mut->is_closed() && mut->is_set());
567 for (auto [_, annex] : annexes()) assert(annex->is_closed());
568 return *this;
569}
570
571#endif
572
573#ifndef DOXYGEN
578template Ref World::ext<true>(Ref);
579template Ref World::ext<false>(Ref);
580template Ref World::bound<true>(Defs);
582template Ref World::app<true>(Ref, Ref);
583template Ref World::app<false>(Ref, Ref);
586#endif
587
588} // namespace mim
A (possibly paramterized) Array.
Definition tuple.h:67
NormalizeFn normalizer() const
Definition axiom.h:36
static std::tuple< const Axiom *, u8, u8 > get(const Def *def)
Yields currying counter of def.
Definition axiom.cpp:38
static constexpr u8 Trip_End
Definition axiom.h:45
static Ref is_uniform(Defs defs)
Yields defs.front(), if all defs are Check::alpha-equivalent (Mode::Test) and nullptr otherwise.
Definition check.cpp:226
static bool alpha(Ref d1, Ref d2)
Definition check.h:65
static Ref assignable(Ref type, Ref value)
Can value be assigned to sth of type?
Definition check.h:69
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
size_t num_ops() const
Definition def.h:273
Ref type() const
Definition def.h:251
const Def * zonk() const
Definition check.cpp:23
nat_t as_lit_arity() const
Definition def.h:262
Ref unfold_type() const
Yields the type of this Def and builds a new Type (UInc n) if necessary.
Definition def.cpp:417
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
Ref var(nat_t a, nat_t i)
Definition def.h:395
auto ops() const
Definition def.h:271
Loc loc() const
Definition def.h:465
Ref arity() const
Definition def.cpp:477
std::optional< nat_t > isa_lit_arity() const
Definition def.cpp:484
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
const T * isa_imm() const
Definition def.h:439
bool is_closed() const
Has no free_vars()?
Definition def.cpp:390
Some "global" variables needed all over the place.
Definition driver.h:17
Log & log()
Definition driver.h:24
Flags & flags()
Definition driver.h:23
Error & error(Loc loc, const char *s, Args &&... args)
Definition dbg.h:71
Error & note(Loc loc, const char *s, Args &&... args)
Definition dbg.h:73
Extracts from a Sigma or Array-typed Extract::tuple the element at position Extract::index.
Definition tuple.h:154
static Ref isa(Ref def)
Definition def.cpp:552
This node is a hole in the IR that is inferred by its context later on.
Definition check.h:10
Creates a new Tuple / Pack by inserting Insert::value at position Insert::index into Insert::tuple.
Definition tuple.h:180
A function.
Definition lam.h:104
Ref filter() const
Definition lam.h:114
Lam * set(Filter filter, Ref body)
Definition lam.h:161
Ref body() const
Definition lam.h:115
static std::optional< T > isa(Ref def)
Definition def.h:762
static T as(Ref def)
Definition def.h:767
Facility to log what you are doing.
Definition log.h:17
A (possibly paramterized) Tuple.
Definition tuple.h:114
A dependent function type.
Definition lam.h:11
Ref codom() const
Definition lam.h:33
static Pi * isa_implicit(Ref d)
Is d an Pi::is_implicit (mutable) Pi?
Definition lam.h:50
Ref reduce(Ref arg) const
Definition lam.h:88
Ref dom() const
Definition lam.h:32
Helper class to retrieve Infer::arg if present.
Definition def.h:86
virtual Ref rewrite(Ref)
Definition rewrite.cpp:9
A dependent tuple type.
Definition tuple.h:9
static Ref infer(World &, Defs)
Definition check.cpp:247
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
Extremum. Either Top (Up) or Bottom.
Definition lattice.h:156
Data constructor for a Sigma.
Definition tuple.h:50
Ref level() const
Definition def.h:729
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:33
const Lit * lit_idx(nat_t size, u64 val)
Constructs a Lit of type Idx of size size.
Definition world.h:400
const Pi * cn()
Definition world.h:267
Ref uniq(Ref inhabitant)
Definition world.cpp:529
Log & log()
Definition world.cpp:73
Infer * mut_infer(Ref type)
Definition world.h:222
Ref gid2def(u32 gid)
Lookup Def by gid.
Definition world.cpp:559
const Lit * lit_i8()
Definition world.h:394
Ref ext(Ref type)
Definition world.cpp:465
const Driver & driver() const
Definition world.h:81
const Lit * lit_tt()
Definition world.h:426
World(Driver *)
Inherits the state into the new World.
Definition world.cpp:62
const auto & annexes() const
Definition world.h:167
Ref implicit_app(Ref callee, Ref arg)
Definition world.cpp:165
Ref test(Ref value, Ref probe, Ref match, Ref clash)
Definition world.cpp:515
const Lit * lit_0_1()
Definition world.h:391
World & verify()
Verifies that all externals() and annexes() are Def::is_closed(), if MIM_ENABLE_CHECKS.
Definition world.cpp:565
const Idx * type_idx()
Definition world.h:468
Ref umax(Defs)
Definition world.cpp:110
const Lit * lit_univ_0()
Definition world.h:385
Sym name() const
Definition world.h:84
const Lit * lit_univ_1()
Definition world.h:386
const auto & externals() const
Definition world.h:168
Ref insert(Ref d, Ref i, Ref val)
Definition world.cpp:348
const Nat * type_nat()
Definition world.h:467
Sigma * mut_sigma(Ref type, size_t size)
Definition world.h:321
Ref var(Ref type, Def *mut)
Definition world.cpp:156
Ref arr(Ref shape, Ref body)
Definition world.cpp:392
Ref meet(Defs ops)
Definition world.h:448
Flags & flags()
Retrive compile Flags.
Definition world.cpp:74
const Type * type()
Definition world.h:209
Ref ac(Ref type, Defs ops)
Definition world.cpp:496
Sym sym(std::string_view)
Definition world.cpp:77
const Pi * pi(Ref dom, Ref codom, bool implicit=false)
Definition world.h:255
const Lit * lit_ff()
Definition world.h:425
Ref raw_app(const Axiom *axiom, u8 curry, u8 trip, Ref type, Ref callee, Ref arg)
Definition world.cpp:221
Sym append_suffix(Sym name, std::string suffix)
Appends a suffix or an increasing number if the suffix already exists.
Definition world.cpp:531
Ref pack(Ref arity, Ref body)
Definition world.cpp:419
const Lit * lit_univ(u64 level)
Definition world.h:384
Ref pick(Ref type, Ref value)
Definition world.cpp:513
Ref bound(Defs ops)
Definition world.cpp:472
const Tuple * tuple()
the unit value of type []
Definition world.h:346
Ref extract(Ref d, Ref i)
Definition world.cpp:286
Ref app(Ref callee, Ref arg)
Definition world.cpp:170
const Lit * lit(Ref type, u64 val)
Definition world.cpp:449
Ref vel(Ref type, Ref value)
Definition world.cpp:508
const Sigma * sigma()
The unit type within Type 0.
Definition world.h:325
const Lit * lit_nat(nat_t a)
Definition world.h:387
const Axiom * axiom(NormalizeFn n, u8 curry, u8 trip, Ref type, plugin_t p, tag_t t, sub_t s)
Definition world.h:237
const Def * register_annex(flags_t f, const Def *)
Definition world.cpp:80
Ref join(Defs ops)
Definition world.h:447
void breakpoint(u32 gid)
Trigger breakpoint in your debugger when creating Def with Def::gid gid.
Definition world.cpp:557
Ref uinc(Ref op, level_t offset=1)
Definition world.cpp:101
const Lam * lam(const Pi *pi, Lam::Filter f, Ref body)
Definition world.h:283
Ref type_bot()
Definition world.h:436
Lam * mut_lam(const Pi *pi)
Definition world.h:284
const Def * annex()
Get Axiom from a plugin.
Definition world.h:194
#define WLOG(...)
Definition log.h:88
#define DLOG(...)
Vaporizes to nothingness in Debug build.
Definition log.h:93
@ Nat
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
auto assert_emplace(C &container, Args &&... args)
Invokes emplace on container, asserts that insertion actually happened, and returns the iterator.
Definition util.h:102
u64 flags_t
Definition types.h:45
auto match(Ref def)
Definition axiom.h:112
void error(Loc loc, const char *f, Args &&... args)
Definition dbg.h:122
u64 level_t
Definition types.h:42
uint32_t u32
Definition types.h:34
uint64_t u64
Definition types.h:34
uint8_t u8
Definition types.h:34
Compiler switches that must be saved and looked up in later phases of compilation.
Definition flags.h:11
static Sym demangle(Driver &, plugin_t plugin)
Reverts an Axiom::mangled string to a Sym.
Definition plugin.cpp:37
absl::flat_hash_set< uint32_t > breakpoints
Definition world.h:50