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