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