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,
97 level->type());
98
99 return unify<Type>(1, level)->as<Type>();
100}
101
103 if (!op->type()->isa<Univ>())
104 error(op->loc(), "operand '{}' of a universe increment must be of type `.Univ` but is of type `{}`", op,
105 op->type());
106
107 if (auto l = Lit::isa(op)) return lit_univ(*l + 1);
108 return unify<UInc>(1, op, offset);
109}
110
111template<Sort sort> Ref World::umax(Defs ops_) {
112 // consume nested umax
113 DefVec ops;
114 for (auto op : ops_)
115 if (auto um = op->isa<UMax>())
116 ops.insert(ops.end(), um->ops().begin(), um->ops().end());
117 else
118 ops.emplace_back(op);
119
120 level_t lvl = 0;
121 for (auto& op : ops) {
122 Ref r = op;
123 if (sort == Sort::Term) r = r->unfold_type();
124 if (sort <= Sort::Type) r = r->unfold_type();
125 if (sort <= Sort::Kind) {
126 if (auto type = r->isa<Type>())
127 r = type->level();
128 else
129 error(r->loc(), "operand '{}' must be a .Type of some level", r);
130 }
131
132 if (!r->type()->isa<Univ>())
133 error(r->loc(), "operand '{}' of a universe max must be of type '.Univ' but is of type '{}'", r, r->type());
134
135 op = r;
136
137 if (auto l = Lit::isa(op))
138 lvl = std::max(lvl, *l);
139 else
140 lvl = level_t(-1);
141 }
142
143 const Def* ldef;
144 if (lvl != level_t(-1))
145 ldef = lit_univ(lvl);
146 else {
147 std::ranges::sort(ops, [](auto op1, auto op2) { return op1->gid() < op2->gid(); });
148 ops.erase(std::unique(ops.begin(), ops.end()), ops.end());
149 ldef = unify<UMax>(ops.size(), *this, ops);
150 }
151
152 return sort == Sort::Univ ? ldef : type(ldef);
153}
154
155// TODO more thorough & consistent checks for singleton types
156
157Ref World::var(Ref type, Def* mut) {
158 if (auto s = Idx::size(type)) {
159 if (auto l = Lit::isa(s); l && l == 1) return lit_0_1();
160 }
161
162 if (auto var = mut->var_) return var;
163 return mut->var_ = unify<Var>(1, type, mut);
164}
165
166Ref World::iapp(Ref callee, Ref arg) {
167 while (auto pi = callee->type()->isa<Pi>()) {
168 if (pi->is_implicit()) {
169 auto infer = mut_infer(pi->dom());
170 auto a = app(callee, infer);
171 callee = a;
172 } else {
173 // resolve Infers now if possible before normalizers are run
174 if (auto app = callee->isa<App>(); app && app->curry() == 1) {
175 Check::assignable(callee->type()->as<Pi>()->dom(), arg);
176 auto apps = decurry(app);
177 callee = apps.front()->callee();
178 for (auto app : apps) callee = this->app(callee, Ref::refer(app->arg()));
179 }
180 break;
181 }
182 }
183
184 return app(callee, arg);
185}
186
187Ref World::app(Ref callee, Ref arg) {
188 Infer::eliminate(Vector<Ref*>{&callee, &arg});
189 auto pi = callee->type()->isa<Pi>();
190
191 if (!pi) {
192 throw Error()
193 .error(callee->loc(), "called expression not of function type")
194 .error(callee->loc(), "'{}' <--- callee type", callee->type());
195 }
196 if (!Check::assignable(pi->dom(), arg)) {
197 throw Error()
198 .error(arg->loc(), "cannot apply argument to callee")
199 .note(callee->loc(), "callee: '{}'", callee)
200 .note(arg->loc(), "argument: '{}'", arg)
201 .note(callee->loc(), "vvv domain type vvv\n'{}'\n'{}'", pi->dom(), arg->type())
202 .note(arg->loc(), "^^^ argument type ^^^");
203 }
204
205 if (auto imm = callee->isa_imm<Lam>()) return imm->body();
206 if (auto lam = callee->isa_mut<Lam>(); lam && lam->is_set() && lam->filter() != lit_ff()) {
207 VarRewriter rw(lam->var(), arg);
208 if (rw.rewrite(lam->filter()) == lit_tt()) {
209 DLOG("partial evaluate: {} ({})", lam, arg);
210 return rw.rewrite(lam->body());
211 }
212 }
213
214 auto type = pi->reduce(arg).back();
215 return raw_app<true>(type, callee, arg);
216}
217
218template<bool Normalize> Ref World::raw_app(Ref type, Ref callee, Ref arg) {
219 auto [axiom, curry, trip] = Axiom::get(callee);
220 if (axiom) {
221 curry = curry == 0 ? trip : curry;
222 curry = curry == Axiom::Trip_End ? curry : curry - 1;
223
224 if (auto normalize = axiom->normalizer(); Normalize && normalize && curry == 0)
225 return normalize(type, callee, arg);
226 }
227
228 return unify<App>(2, axiom, curry, trip, type, callee, arg);
229}
230
232 auto n = ops.size();
233 if (n == 0) return sigma();
234 if (n == 1) return ops[0];
235 if (auto uni = Check::is_uniform(ops)) return arr(n, uni);
236 return unify<Sigma>(ops.size(), Sigma::infer(*this, ops), ops);
237}
238
240 if (ops.size() == 1) return ops[0];
241
242 auto sigma = infer_sigma(*this, ops);
243 auto t = tuple(sigma, ops);
244 if (!Check::assignable(sigma, t))
245 error(t->loc(), "cannot assign tuple '{}' of type '{}' to incompatible tuple type '{}'", t, t->type(), sigma);
246
247 return t;
248}
249
251 // TODO type-check type vs inferred type
252
253 auto n = ops.size();
254 if (!type->isa_mut<Sigma>()) {
255 if (n == 0) return tuple();
256 if (n == 1) return ops[0];
257 if (auto uni = Check::is_uniform(ops)) return pack(n, uni);
258 }
259
260 if (n != 0) {
261 // eta rule for tuples:
262 // (extract(tup, 0), extract(tup, 1), extract(tup, 2)) -> tup
263 if (auto extract = ops[0]->isa<Extract>()) {
264 auto tup = extract->tuple();
265 bool eta = tup->type() == type;
266 for (size_t i = 0; i != n && eta; ++i) {
267 if (auto extract = ops[i]->isa<Extract>()) {
268 if (auto index = Lit::isa(extract->index())) {
269 if (eta &= u64(i) == *index) {
270 eta &= extract->tuple() == tup;
271 continue;
272 }
273 }
274 }
275 eta = false;
276 }
277
278 if (eta) return tup;
279 }
280 }
281
282 return unify<Tuple>(ops.size(), type, ops);
283}
284
286 DefVec defs;
287 std::ranges::transform(sym, std::back_inserter(defs), [this](auto c) { return lit_i8(c); });
288 return tuple(defs);
289}
290
292 assert(d);
293 if (index->isa<Tuple>()) {
294 auto n = index->num_ops();
295 auto idx = DefVec(n, [&](size_t i) { return index->op(i); });
296 auto ops = DefVec(n, [&](size_t i) { return d->proj(n, Lit::as(idx[i])); });
297 return tuple(ops);
298 } else if (index->isa<Pack>()) {
299 auto ops = DefVec(index->as_lit_arity(), [&](size_t) { return extract(d, index->ops().back()); });
300 return tuple(ops);
301 }
302
303 Ref size = Idx::size(index->type());
304 Ref type = d->unfold_type();
305
306 if (auto l = Lit::isa(size); l && *l == 1) {
307 if (auto l = Lit::isa(index); !l || *l != 0) WLOG("unknown Idx of size 1: {}", index);
308 if (auto sigma = type->isa_mut<Sigma>(); sigma && sigma->num_ops() == 1) {
309 // mut sigmas can be 1-tuples; TODO mutables Arr?
310 } else {
311 return d;
312 }
313 }
314
315 if (auto pack = d->isa_imm<Pack>()) return pack->body();
316
317 if (!Check::alpha(type->arity(), size))
318 error(index->loc(), "index '{}' does not fit within arity '{}'", index, type->arity());
319
320 // extract(insert(x, index, val), index) -> val
321 if (auto insert = d->isa<Insert>()) {
322 if (index == insert->index()) return insert->value();
323 }
324
325 if (auto i = Lit::isa(index)) {
326 if (auto tuple = d->isa<Tuple>()) return tuple->op(*i);
327
328 // extract(insert(x, j, val), i) -> extract(x, i) where i != j (guaranteed by rule above)
329 if (auto insert = d->isa<Insert>()) {
330 if (insert->index()->isa<Lit>()) return extract(insert->tuple(), index);
331 }
332
333 if (auto sigma = type->isa<Sigma>()) {
334 if (auto mut_sigma = sigma->isa_mut<Sigma>()) {
335 auto t = VarRewriter(mut_sigma->var(), d).rewrite(sigma->op(*i));
336 return unify<Extract>(2, t, d, index);
337 }
338
339 return unify<Extract>(2, sigma->op(*i), d, index);
340 }
341 }
342
343 const Def* elem_t;
344 if (auto arr = type->isa<Arr>())
345 elem_t = arr->reduce(index);
346 else
347 elem_t = extract(tuple(type->as<Sigma>()->ops()), index);
348
349 assert(d);
350 return unify<Extract>(2, elem_t, d, index);
351}
352
353Ref World::insert(Ref d, Ref index, Ref val) {
354 auto type = d->unfold_type();
355 auto size = Idx::size(index->type());
356 auto lidx = Lit::isa(index);
357
358 if (!Check::alpha(type->arity(), size))
359 error(index->loc(), "index '{}' does not fit within arity '{}'", index, type->arity());
360
361 if (lidx) {
362 auto elem_type = type->proj(*lidx);
363 if (!Check::assignable(elem_type, val)) {
364 throw Error()
365 .error(val->loc(), "value to be inserted not assignable to element")
366 .note(val->loc(), "vvv value type vvv \n'{}'\n'{}'", val->type(), elem_type)
367 .note(val->loc(), "^^^ element type ^^^", elem_type);
368 }
369 }
370
371 if (auto l = Lit::isa(size); l && *l == 1)
372 return tuple(d, {val}); // d could be mut - that's why the tuple ctor is needed
373
374 // insert((a, b, c, d), 2, x) -> (a, b, x, d)
375 if (auto t = d->isa<Tuple>(); t && lidx) return t->refine(*lidx, val);
376
377 // insert(‹4; x›, 2, y) -> (x, x, y, x)
378 if (auto pack = d->isa<Pack>(); pack && lidx) {
379 if (auto a = pack->isa_lit_arity(); a && *a < flags().scalarize_threshold) {
380 auto new_ops = DefVec(*a, pack->body());
381 new_ops[*lidx] = val;
382 return tuple(type, new_ops);
383 }
384 }
385
386 // insert(insert(x, index, y), index, val) -> insert(x, index, val)
387 if (auto insert = d->isa<Insert>()) {
388 if (insert->index() == index) d = insert->tuple();
389 }
390
391 return unify<Insert>(3, d, index, val);
392}
393
394// TODO merge this code with pack
395Ref World::arr(Ref shape, Ref body) {
396 if (!is_shape(shape->type())) error(shape->loc(), "expected shape but got '{}' of type '{}'", shape, shape->type());
397
398 if (auto a = Lit::isa(shape)) {
399 if (*a == 0) return sigma();
400 if (*a == 1) return body;
401 }
402
403 // «(a, b)#i; T» -> («a, T», <b, T»)#i
404 if (auto ex = shape->isa<Extract>()) {
405 if (auto tup = ex->tuple()->isa<Tuple>()) {
406 auto arrs = DefVec(tup->num_ops(), [&](size_t i) { return arr(tup->op(i), body); });
407 return extract(tuple(arrs), ex->index());
408 }
409 }
410
411 // «(a, b, c); body» -> «a; «(b, c); body»»
412 if (auto tuple = shape->isa<Tuple>()) return arr(tuple->ops().front(), arr(tuple->ops().subspan(1), body));
413
414 // «<n; x>; body» -> «x; «<n-1, x>; body»»
415 if (auto p = shape->isa<Pack>()) {
416 if (auto s = Lit::isa(p->shape())) return arr(*s, arr(pack(*s - 1, p->body()), body));
417 }
418
419 return unify<Arr>(2, body->unfold_type(), shape, body);
420}
421
422Ref World::pack(Ref shape, Ref body) {
423 if (!is_shape(shape->type())) error(shape->loc(), "expected shape but got '{}' of type '{}'", shape, shape->type());
424
425 if (auto a = Lit::isa(shape)) {
426 if (*a == 0) return tuple();
427 if (*a == 1) return body;
428 }
429
430 // <(a, b, c); body> -> <a; «(b, c); body>>
431 if (auto tuple = shape->isa<Tuple>()) return pack(tuple->ops().front(), pack(tuple->ops().subspan(1), body));
432
433 // <<n; x>; body> -> <x; <<n-1, x>; body>>
434 if (auto p = shape->isa<Pack>()) {
435 if (auto s = Lit::isa(p->shape())) return pack(*s, pack(pack(*s - 1, p->body()), body));
436 }
437
438 auto type = arr(shape, body->type());
439 return unify<Pack>(1, type, body);
440}
441
442Ref World::arr(Defs shape, Ref body) {
443 if (shape.empty()) return body;
444 return arr(shape.rsubspan(1), arr(shape.back(), body));
445}
446
447Ref World::pack(Defs shape, Ref body) {
448 if (shape.empty()) return body;
449 return pack(shape.rsubspan(1), pack(shape.back(), body));
450}
451
452const Lit* World::lit(Ref type, u64 val) {
453 if (auto size = Idx::size(type)) {
454 if (auto s = Lit::isa(size)) {
455 if (*s != 0 && val >= *s) error(type->loc(), "index '{}' does not fit within arity '{}'", size, val);
456 } else if (val != 0) { // 0 of any size is allowed
457 error(type->loc(), "cannot create literal '{}' of '.Idx {}' as size is unknown", val, size);
458 }
459 }
460
461 return unify<Lit>(0, type, val);
462}
463
464/*
465 * set
466 */
467
468template<bool Up> Ref World::ext(Ref type) {
469 if (auto arr = type->isa<Arr>()) return pack(arr->shape(), ext<Up>(arr->body()));
470 if (auto sigma = type->isa<Sigma>())
471 return tuple(sigma, DefVec(sigma->num_ops(), [&](size_t i) { return ext<Up>(sigma->op(i)); }));
472 return unify<TExt<Up>>(0, type);
473}
474
475template<bool Up> Ref World::bound(Defs ops) {
476 auto kind = umax<Sort::Type>(ops);
477
478 // has ext<Up> value?
479 if (std::ranges::any_of(ops, [&](Ref op) { return Up ? bool(op->isa<Top>()) : bool(op->isa<Bot>()); }))
480 return ext<Up>(kind);
481
482 // ignore: ext<!Up>
483 DefVec cpy(ops.begin(), ops.end());
484 auto [_, end] = std::ranges::copy_if(ops, cpy.begin(), [&](Ref op) { return !op->isa<Ext>(); });
485
486 // sort and remove duplicates
487 std::sort(cpy.begin(), end, GIDLt<const Def*>());
488 end = std::unique(cpy.begin(), end);
489 cpy.resize(std::distance(cpy.begin(), end));
490
491 if (cpy.size() == 0) return ext<!Up>(kind);
492 if (cpy.size() == 1) return cpy[0];
493
494 // TODO simplify mixed terms with joins and meets
495
496 return unify<TBound<Up>>(cpy.size(), kind, cpy);
497}
498
499Ref World::ac(Ref type, Defs ops) {
500 if (type->isa<Meet>()) {
501 auto types = DefVec(ops.size(), [&](size_t i) { return ops[i]->type(); });
502 return unify<Ac>(ops.size(), meet(types), ops);
503 }
504
505 assert(ops.size() == 1);
506 return ops[0];
507}
508
509Ref World::ac(Defs ops) { return ac(umax<Sort::Term>(ops), ops); }
510
511Ref World::vel(Ref type, Ref value) {
512 if (type->isa<Join>()) return unify<Vel>(1, type, value);
513 return value;
514}
515
516Ref World::pick(Ref type, Ref value) { return unify<Pick>(1, type, value); }
517
518Ref World::test(Ref value, Ref probe, Ref match, Ref clash) {
519 auto m_pi = match->type()->isa<Pi>();
520 auto c_pi = clash->type()->isa<Pi>();
521
522 // TODO proper error msg
523 assert(m_pi && c_pi);
524 auto a = m_pi->dom()->isa_lit_arity();
525 assert_unused(a && *a == 2);
526 assert(Check::alpha(m_pi->dom(2, 0_s), c_pi->dom()));
527
528 auto codom = join({m_pi->codom(), c_pi->codom()});
529 return unify<Test>(4, pi(c_pi->dom(), codom), value, probe, match, clash);
530}
531
532Ref World::singleton(Ref inner_type) { return unify<Singleton>(1, this->type<1>(), inner_type); }
533
534Sym World::append_suffix(Sym symbol, std::string suffix) {
535 auto name = symbol.str();
536
537 auto pos = name.find(suffix);
538 if (pos != std::string::npos) {
539 auto num = name.substr(pos + suffix.size());
540 if (num.empty()) {
541 name += "_1";
542 } else {
543 num = num.substr(1);
544 num = std::to_string(std::stoi(num) + 1);
545 name = name.substr(0, pos + suffix.size()) + "_" + num;
546 }
547 } else {
548 name += suffix;
549 }
550
551 return sym(std::move(name));
552}
553
554/*
555 * debugging
556 */
557
558#ifdef MIM_ENABLE_CHECKS
559
560void World::breakpoint(u32 gid) { state_.breakpoints.emplace(gid); }
561
563 auto i = std::ranges::find_if(move_.defs, [=](auto def) { return def->gid() == gid; });
564 if (i == move_.defs.end()) return nullptr;
565 return *i;
566}
567
569 for (auto [_, mut] : externals()) assert(mut->is_closed() && mut->is_set());
570 for (auto [_, annex] : annexes()) assert(annex->is_closed());
571 return *this;
572}
573
574#endif
575
576#ifndef DOXYGEN
583template Ref World::ext<true>(Ref);
584template Ref World::ext<false>(Ref);
585template Ref World::bound<true>(Defs);
587#endif
588
589} // namespace mim
A (possibly paramterized) Array.
Definition tuple.h:51
NormalizeFn normalizer() const
Definition axiom.h:34
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:43
static bool alpha(Ref d1, Ref d2)
Are d1 and d2 α-equivalent?
Definition check.h:59
static bool assignable(Ref type, Ref value)
Can value be assigned to sth of type?
Definition check.h:63
static Ref is_uniform(Defs defs)
Yields defs.front(), if all defs are Check::alpha-equivalent (infer = false) and nullptr otherwise.
Definition check.cpp:213
Base class for all Defs.
Definition def.h:220
bool is_set() const
Yields true if empty or the last op is set.
Definition def.cpp:311
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:520
size_t num_ops() const
Definition def.h:267
const Def * op(size_t i) const
Definition def.h:266
nat_t as_lit_arity() const
Definition def.h:256
T * isa_mut() const
If this is *mut*able, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:444
DefVec reduce(const Def *arg) const
Rewrites Def::ops by substituting this mutable's Var with arg.
Definition def.cpp:208
const Def * unfold_type() const
Yields the type of this Def and builds a new .Type (UInc n) if necessary.
Definition def.cpp:423
Ref var(nat_t a, nat_t i)
Definition def.h:398
auto ops() const
Definition def.h:265
const Def * type() const
Definition def.h:245
Loc loc() const
Definition def.h:464
Ref arity() const
Definition def.cpp:483
std::optional< nat_t > isa_lit_arity() const
Definition def.cpp:490
const T * isa_imm() const
Definition def.h:438
bool is_closed() const
Has no free_vars()?
Definition def.cpp:397
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:119
static Ref size(Ref def)
Checks if def is a .Idx s and returns s or nullptr otherwise.
Definition def.cpp:558
static bool eliminate(Vector< Ref * >)
Eliminate Infers that may have been resolved in the meantime by rebuilding.
Definition check.cpp:62
Creates a new Tuple / Pack by inserting Insert::value at position Insert::index into Insert::tuple.
Definition tuple.h:138
A function.
Definition lam.h:96
Ref filter() const
Definition lam.h:106
Lam * set(Filter filter, const Def *body)
Definition lam.h:158
Ref body() const
Definition lam.h:107
static std::optional< T > isa(Ref def)
Definition def.h:712
static T as(Ref def)
Definition def.h:717
Facility to log what you are doing.
Definition log.h:17
A (possibly paramterized) Tuple.
Definition tuple.h:88
A dependent function type.
Definition lam.h:11
Ref codom() const
Definition lam.h:40
bool is_implicit() const
Definition lam.h:23
Ref dom() const
Definition lam.h:32
Helper class to retrieve Infer::arg if present.
Definition def.h:85
static const Def * refer(const Def *def)
Retrieves Infer::arg from def.
Definition check.cpp:27
virtual Ref rewrite(Ref)
Definition rewrite.cpp:9
A dependent tuple type.
Definition tuple.h:9
static Ref infer(World &, Defs)
Definition check.cpp:232
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:130
Data constructor for a Sigma.
Definition tuple.h:40
const Def * level() const
Definition def.h:686
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:401
const Pi * cn()
Definition world.h:267
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:562
const Lit * lit_i8()
Definition world.h:395
Ref ext(Ref type)
Definition world.cpp:468
const Driver & driver() const
Definition world.h:81
const Lit * lit_tt()
Definition world.h:427
World(Driver *)
Inherits the state into the new World.
Definition world.cpp:62
const auto & annexes() const
Definition world.h:167
Ref iapp(Ref callee, Ref arg)
Definition world.cpp:166
Ref test(Ref value, Ref probe, Ref match, Ref clash)
Definition world.cpp:518
const Lit * lit_0_1()
Definition world.h:392
World & verify()
Verifies that all externals() and annexes() are Def::is_closed(), if MIM_ENABLE_CHECKS.
Definition world.cpp:568
const Idx * type_idx()
Definition world.h:469
Ref umax(Defs)
Definition world.cpp:111
const Lit * lit_univ_0()
Definition world.h:386
Sym name() const
Definition world.h:84
const Lit * lit_univ_1()
Definition world.h:387
const auto & externals() const
Definition world.h:168
Ref insert(Ref d, Ref i, Ref val)
Definition world.cpp:353
const Nat * type_nat()
Definition world.h:468
Sigma * mut_sigma(Ref type, size_t size)
Definition world.h:322
Ref var(Ref type, Def *mut)
Definition world.cpp:157
Ref arr(Ref shape, Ref body)
Definition world.cpp:395
Ref meet(Defs ops)
Definition world.h:449
Flags & flags()
Retrive compile Flags.
Definition world.cpp:74
const Type * type()
Definition world.h:209
Ref app(Ref callee, Ref arg)
Definition world.cpp:187
Ref ac(Ref type, Defs ops)
Definition world.cpp:499
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:426
Sym append_suffix(Sym name, std::string suffix)
Appends a suffix or an increasing number if the suffix already exists.
Definition world.cpp:534
Ref pack(Ref arity, Ref body)
Definition world.cpp:422
const Lit * lit_univ(u64 level)
Definition world.h:385
Ref pick(Ref type, Ref value)
Definition world.cpp:516
Ref bound(Defs ops)
Definition world.cpp:475
const Tuple * tuple()
the unit value of type []
Definition world.h:347
Ref extract(Ref d, Ref i)
Definition world.cpp:291
const Lit * lit(Ref type, u64 val)
Definition world.cpp:452
Ref vel(Ref type, Ref value)
Definition world.cpp:511
const Sigma * sigma()
The unit type within Type 0.
Definition world.h:326
const Lit * lit_nat(nat_t a)
Definition world.h:388
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:448
Ref raw_app(Ref type, Ref callee, Ref arg)
Definition world.cpp:218
void breakpoint(u32 gid)
Trigger breakpoint in your debugger when creating Def with Def::gid gid.
Definition world.cpp:560
Ref uinc(Ref op, level_t offset=1)
Definition world.cpp:102
Ref singleton(Ref inner_type)
Definition world.cpp:532
const Lam * lam(const Pi *pi, Lam::Filter f, Ref body)
Definition world.h:283
Ref type_bot()
Definition world.h:437
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:39
Definition cfg.h:11
View< const Def * > Defs
Definition def.h:60
u64 nat_t
Definition types.h:43
Vector< const Def * > DefVec
Definition def.h:61
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:105
void error(Loc loc, const char *f, Args &&... args)
Definition dbg.h:122
u64 level_t
Definition types.h:42
std::deque< const App * > decurry(const Def *)
Yields curried Apps in a flat std::deque<const App*>.
Definition lam.cpp:44
uint32_t u32
Definition types.h:34
uint64_t u64
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