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