MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
def.h
Go to the documentation of this file.
1#pragma once
2
3#include <format>
4#include <limits>
5#include <optional>
6#include <span>
7
8#include <fe/assert.h>
9#include <fe/cast.h>
10#include <fe/enum.h>
11
12#include "mim/config.h"
13
14#include "mim/util/dbg.h"
15#include "mim/util/sets.h"
16#include "mim/util/util.h"
17#include "mim/util/vector.h"
18
19// clang-format off
20#define MIM_NODE(X) \
21 X(Lit, Judge::Intro) /* keep this first - causes Lit to appear left in Def::less/Def::greater*/ \
22 X(Axm, Judge::Intro) \
23 X(Var, Judge::Intro) \
24 X(Global, Judge::Intro) \
25 X(Proxy, Judge::Intro) \
26 X(Hole, Judge::Hole ) \
27 X(Type, Judge::Meta ) X(Univ, Judge::Meta ) X(UMax, Judge::Meta) X(UInc, (Judge::Meta )) \
28 X(Pi, Judge::Form ) X(Lam, Judge::Intro) X(App, Judge::Elim) \
29 X(Sigma, Judge::Form ) X(Tuple, Judge::Intro) X(Extract, Judge::Elim) X(Insert, (Judge::Intro | Judge::Elim)) \
30 X(Arr, Judge::Form ) X(Pack, Judge::Intro) \
31 X(Join, Judge::Form ) X(Inj, Judge::Intro) X(Match, Judge::Elim) X(Top, (Judge::Intro )) \
32 X(Meet, Judge::Form ) X(Merge, Judge::Intro) X(Split, Judge::Elim) X(Bot, (Judge::Intro )) \
33 X(Reform, Judge::Form ) X(Rule, Judge::Intro) \
34 X(Uniq, Judge::Form ) \
35 X(Nat, Judge::Form ) \
36 X(Idx, Judge::Intro)
37
38#define MIM_IMM_NODE(X) \
39 X(Lit) \
40 X(Axm) \
41 X(Var) \
42 X(Proxy) \
43 X(Type) X(Univ) X(UMax) X(UInc) \
44 X(Pi) X(Lam) X(App) \
45 X(Sigma) X(Tuple) X(Extract) X(Insert) \
46 X(Arr) X(Pack) \
47 X(Join) X(Inj) X(Match) X(Top) \
48 X(Meet) X(Merge) X(Split) X(Bot) \
49 X(Reform) X(Rule) \
50 X(Uniq) \
51 X(Nat) \
52 X(Idx)
53
54#define MIM_MUT_NODE(X) \
55 X(Global) \
56 X(Hole) \
57 X(Pi) X(Lam) \
58 X(Sigma) \
59 X(Arr) X(Pack) \
60 X(Rule)
61// clang-format on
62
63namespace mim {
64
65class App;
66class Axm;
67class Var;
68class Def;
69class World;
70
71/// @name Def
72/// GIDSet / GIDMap keyed by Def::gid of `conset Def*`.
73///@{
74template<class To>
80///@}
81
82/// @name Def (Mutable)
83/// GIDSet / GIDMap keyed by Def::gid of `Def*`.
84///@{
85template<class To>
90///@}
91
92/// @name Var
93/// GIDSet / GIDMap keyed by Var::gid of `const Var*`.
94///@{
95template<class To>
100///@}
101
102using NormalizeFn = const Def* (*)(const Def*, const Def*, const Def*);
103
104/// @name Enums that classify certain aspects of Def%s.
105///@{
106
107enum class Node : node_t {
108#define CODE(node, _) node,
110#undef CODE
111};
112
113#define CODE(node, _) +size_t(1)
114static constexpr size_t Num_Nodes = size_t(0) MIM_NODE(CODE);
115#undef CODE
116
117/// Tracks a dependency to certain Def%s transitively through the Def::deps() up to but excliding *mutables*.
118enum class Dep : unsigned {
119 None = 0,
120 Mut = 1 << 0,
121 Var = 1 << 1,
122 Hole = 1 << 2,
123 Proxy = 1 << 3,
124};
125
126/// [Judgement](https://ncatlab.org/nlab/show/judgment).
127enum class Judge : u32 {
128 // clang-format off
129 Form = 1 << 0, ///< [Type Formation](https://ncatlab.org/nlab/show/type+formation) like `T -> T`.
130 Intro = 1 << 1, ///< [Term Introduction](https://ncatlab.org/nlab/show/natural+deduction) like `λ(x: Nat): Nat = x`.
131 Elim = 1 << 2, ///< [Term Elimination](https://ncatlab.org/nlab/show/term+elimination) like `f a`.
132 Meta = 1 << 3, ///< Meta rules for Univ%erse and Type levels.
133 Hole = 1 << 4, ///< Special rule for Hole.
134 // clang-format on
135};
136
137/// [Judgement](https://ncatlab.org/nlab/show/judgment).
138enum class Mut {
139 // clang-format off
140 Mut = 1 << 0, ///< Node may be mutable.
141 Imm = 1 << 1, ///< Node may be immmutable.
142 // clang-format on
143};
144///@}
145
146} // namespace mim
147
148#ifndef DOXYGEN
149// clang-format off
150template<> struct fe::is_bit_enum<mim::Dep> : std::true_type {};
151template<> struct fe::is_bit_enum<mim::Judge> : std::true_type {};
152template<> struct fe::is_bit_enum<mim::Mut> : std::true_type {};
153// clang-format on
154#endif
155
156namespace mim {
157
158/// Use as mixin to wrap all kind of Def::proj and Def::projs variants.
159#define MIM_PROJ(NAME, CONST) \
160 nat_t num_##NAME##s() CONST noexcept { return ((const Def*)NAME())->num_projs(); } \
161 nat_t num_t##NAME##s() CONST noexcept { return ((const Def*)NAME())->num_tprojs(); } \
162 const Def* NAME(nat_t a, nat_t i) CONST noexcept { return ((const Def*)NAME())->proj(a, i); } \
163 const Def* NAME(nat_t i) CONST noexcept { return ((const Def*)NAME())->proj(i); } \
164 const Def* t##NAME(nat_t i) CONST noexcept { return ((const Def*)NAME())->tproj(i); } \
165 template<nat_t A = std::dynamic_extent, class F> \
166 auto NAME##s(F f) CONST noexcept { \
167 return ((const Def*)NAME())->projs<A, F>(f); \
168 } \
169 template<class F> \
170 auto t##NAME##s(F f) CONST noexcept { \
171 return ((const Def*)NAME())->tprojs<F>(f); \
172 } \
173 template<nat_t A = std::dynamic_extent> \
174 auto NAME##s() CONST noexcept { \
175 return ((const Def*)NAME())->projs<A>(); \
176 } \
177 auto t##NAME##s() CONST noexcept { return ((const Def*)NAME())->tprojs(); } \
178 template<class F> \
179 auto NAME##s(nat_t a, F f) CONST noexcept { \
180 return ((const Def*)NAME())->projs<F>(a, f); \
181 } \
182 auto NAME##s(nat_t a) CONST noexcept { return ((const Def*)NAME())->projs(a); }
183
184/// CRTP-based mixin to declare setters for Def::loc \& Def::name using a *covariant* return type.
185template<class P, class D = Def>
186class // D is only needed to make the resolution `D::template set` lazy
187#ifdef _MSC_VER
188 __declspec(empty_bases)
189#endif
190 Setters {
191private:
192 P* super() { return static_cast<P*>(this); }
193 const P* super() const { return static_cast<const P*>(this); }
194
195public:
196 // clang-format off
197 template<bool Ow = false> const P* set(Loc l ) const { super()->D::template set<Ow>(l); return super(); }
198 template<bool Ow = false> P* set(Loc l ) { super()->D::template set<Ow>(l); return super(); }
199 template<bool Ow = false> const P* set( Sym s ) const { super()->D::template set<Ow>(s); return super(); }
200 template<bool Ow = false> P* set( Sym s ) { super()->D::template set<Ow>(s); return super(); }
201 template<bool Ow = false> const P* set( std::string s) const { super()->D::template set<Ow>(std::move(s)); return super(); }
202 template<bool Ow = false> P* set( std::string s) { super()->D::template set<Ow>(std::move(s)); return super(); }
203 template<bool Ow = false> const P* set(Loc l, Sym s ) const { super()->D::template set<Ow>(l, s); return super(); }
204 template<bool Ow = false> P* set(Loc l, Sym s ) { super()->D::template set<Ow>(l, s); return super(); }
205 template<bool Ow = false> const P* set(Loc l, std::string s) const { super()->D::template set<Ow>(l, std::move(s)); return super(); }
206 template<bool Ow = false> P* set(Loc l, std::string s) { super()->D::template set<Ow>(l, std::move(s)); return super(); }
207 template<bool Ow = false> const P* set(Dbg d ) const { super()->D::template set<Ow>(d); return super(); }
208 template<bool Ow = false> P* set(Dbg d ) { super()->D::template set<Ow>(d); return super(); }
209 // clang-format on
210};
211
212/// Base class for all Def%s.
213///
214/// These are the most important subclasses:
215/// | Type Formation | Term Introduction | Term Elimination |
216/// | ----------------- | ----------------- | ----------------- |
217/// | Pi | Lam | App |
218/// | Sigma / Arr | Tuple / Pack | Extract |
219/// | | Insert | Insert |
220/// | Uniq | Wrap | Unwrap |
221/// | Join | Inj | Match |
222/// | Meet | Merge | Split |
223/// | Reform | Rule | |
224/// | Nat | Lit | |
225/// | Idx | Lit | |
226/// In addition there is:
227/// * Var: A variable. Currently the following Def%s may be binders:
228/// * Pi, Lam, Sigma, Arr, Pack
229/// * Axm: To introduce new entities.
230/// * Proxy: Used for intermediate values during optimizations.
231/// * Hole: A metavariable filled in by the type inference (always mutable as holes are filled in later).
232/// * Type, Univ, UMax, UInc: To keep track of type levels.
233///
234/// The data layout (see World::alloc and Def::deps) looks like this:
235/// ```
236/// Def| type | op(0) ... op(num_ops-1) |
237/// |-----------ops-----------|
238/// deps
239/// |--------------------------------| if type() != nullptr && is_set()
240/// |-------------------------| if type() == nullptr && is_set()
241/// |------| if type() != nullptr && !is_set()
242/// || if type() == nullptr && !is_set()
243/// ```
244/// @attention This means that any subclass of Def **must not** introduce additional members.
245/// @see @ref mut
246class Def : public fe::RuntimeCast<Def> {
247private:
248 Def& operator=(const Def&) = delete;
249 Def(const Def&) = delete;
250 Def(Def&&) = delete;
251
252protected:
253 /// @name C'tors and D'tors
254 ///@{
255 Def(World*, Node, const Def* type, Defs ops, flags_t flags); ///< Constructor for an *immutable* Def.
256 Def(Node, const Def* type, Defs ops, flags_t flags); ///< As above but World retrieved from @p type.
257 Def(Node, const Def* type, size_t num_ops, flags_t flags); ///< Constructor for a *mutable* Def.
258 virtual ~Def() = default;
259 ///@}
260
261public:
262 /// @name Getters
263 ///@{
264 World& world() const noexcept;
265 constexpr flags_t flags() const noexcept { return flags_; }
266 constexpr u32 gid() const noexcept { return gid_; } ///< Global id - *unique* number for this Def.
267 constexpr u32 tid() const noexcept { return tid_; } ///< Trie id - only used in Trie.
268 constexpr u32 mark() const noexcept { return mark_; } ///< Used internally by free_vars().
269 constexpr size_t hash() const noexcept { return hash_; }
270 constexpr Node node() const noexcept { return node_; }
271 std::string_view node_name() const;
272 ///@}
273
274 /// @name Judgement
275 /// What kind of Judge%ment represents this Def?
276 ///@{
277 Judge judge() const noexcept;
278 // clang-format off
279 bool is_form() const noexcept { return fe::has_flag(judge(), Judge::Form); }
280 bool is_intro() const noexcept { return fe::has_flag(judge(), Judge::Intro); }
281 bool is_elim() const noexcept { return fe::has_flag(judge(), Judge::Elim); }
282 bool is_meta() const noexcept { return fe::has_flag(judge(), Judge::Meta); }
283 // clang-format on
284 ///@}
285
286 /// @name type
287 ///@{
288
289 /// Yields the "raw" type of this Def (maybe `nullptr`).
290 /// @see Def::unfold_type.
291 const Def* type() const noexcept;
292 /// Yields the type of this Def and builds a new `Type (UInc n)` if necessary.
293 const Def* unfold_type() const;
294 bool is_term() const;
295 virtual const Def* arity() const;
296 ///@}
297
298 /// @name ops
299 ///@{
300 template<size_t N = std::dynamic_extent>
301 constexpr auto ops() const noexcept {
302 return View<const Def*, N>(ops_ptr(), num_ops_);
303 }
304 const Def* op(size_t i) const noexcept { return ops()[i]; }
305 constexpr size_t num_ops() const noexcept { return num_ops_; }
306 ///@}
307
308 /// @name Setting Ops (Mutables Only)
309 /// @anchor set_ops
310 /// You can set and change the Def::ops of a mutable after construction.
311 /// However, you have to obey the following rules:
312 /// If Def::is_set() is ...
313 /// * `false`, [set](@ref Def::set) the [operands](@ref Def::ops) from left to right.
314 /// * `true`, Def::unset() the operands first and then start over:
315 /// ```
316 /// mut->unset()->set({a, b, c});
317 /// ```
318 ///
319 /// MimIR assumes that a mutable is *final*, when its last operand is set.
320 /// Then, Def::check() will be invoked.
321 ///@{
322 bool is_set() const; ///< Yields `true` if empty or the last op is set.
323 Def* set(size_t i, const Def*); ///< Successively set from left to right.
324 Def* set(Defs ops); ///< Set @p ops all at once (no Def::unset necessary beforehand).
325 Def* unset(); ///< Unsets all Def::ops; works even, if not set at all or only partially set.
326
327 /// Update type.
328 /// @warning Only make type-preserving updates such as removing Hole%s.
329 /// Do this even before updating all other ops()!
330 Def* set_type(const Def*);
331 ///@}
332
333 /// @name deps
334 /// All *dependencies* of a Def and includes:
335 /// * Def::type() (if not `nullptr`) and
336 /// * the other Def::ops() (only included, if Def::is_set()) in this order.
337 ///@{
338 Defs deps() const noexcept;
339 const Def* dep(size_t i) const noexcept { return deps()[i]; }
340 size_t num_deps() const noexcept { return deps().size(); }
341 ///@}
342
343 /// @name has_dep
344 /// Checks whether one Def::deps() contains specific elements defined in Dep.
345 /// This works up to the next *mutable*.
346 /// For example, consider the Tuple `tup`: `(?, lam (x: Nat) = y)`:
347 /// ```
348 /// bool has_hole = tup->has_dep(Dep::Hole); // true
349 /// bool has_mut = tup->has_dep(Dep::Mut); // true
350 /// bool has_var = tup->has_dep(Dep::Var); // false - y is contained in another mutable
351 /// ```
352 ///@{
353 Dep dep() const noexcept { return Dep(dep_); }
354 bool has_dep() const noexcept { return dep_ != 0; }
355 bool has_dep(Dep d) const noexcept { return fe::has_flag(dep(), d); }
356 ///@}
357
358 /// @name proj
359 /// @anchor proj
360 /// Splits this Def via Extract%s or directly accessing the Def::ops in the case of Sigma%s or Arr%ays.
361 /// ```
362 /// std::array<const Def*, 2> ab = def->projs<2>();
363 /// std::array<u64, 2> xy = def->projs<2>([](auto def) { return Lit::as(def); });
364 /// auto [a, b] = def->projs<2>();
365 /// auto [x, y] = def->projs<2>([](auto def) { return Lit::as(def); });
366 /// Vector<const Def*> projs1 = def->projs(); // "projs1" has def->num_projs() many elements
367 /// Vector<const Def*> projs2 = def->projs(n);// "projs2" has n elements - asserts if incorrect
368 /// // same as above but applies Lit::as<nat_t>(def) to each element
369 /// Vector<const Lit*> lits1 = def->projs( [](auto def) { return Lit::as(def); });
370 /// Vector<const Lit*> lits2 = def->projs(n, [](auto def) { return Lit::as(def); });
371 /// ```
372 ///@{
373
374 /// Yields Def::arity(), if it is a Lit, or `1` otherwise.
375 nat_t num_projs() const;
376 nat_t num_tprojs() const; ///< As above but yields 1, if Flags::scalarize_threshold is exceeded.
377
378 /// Similar to World::extract while assuming an arity of @p a, but also works on Sigma%s and Arr%ays.
379 const Def* proj(nat_t a, nat_t i) const;
380 const Def* proj(nat_t i) const { return proj(num_projs(), i); } ///< As above but takes Def::num_projs as arity.
381 const Def* tproj(nat_t i) const { return proj(num_tprojs(), i); } ///< As above but takes Def::num_tprojs.
382
383 /// Splits this Def via Def::proj%ections into an Array (if `A == std::dynamic_extent`) or `std::array` (otherwise).
384 /// Applies @p f to each element.
385 template<nat_t A = std::dynamic_extent, class F>
386 auto projs(F f) const {
387 using R = std::decay_t<decltype(f(this))>;
388 if constexpr (A == std::dynamic_extent) {
389 return projs(num_projs(), f);
390 } else {
391 std::array<R, A> array;
392 for (nat_t i = 0; i != A; ++i)
393 array[i] = f(proj(A, i));
394 return array;
395 }
396 }
397
398 template<class F>
399 auto tprojs(F f) const {
400 return projs(num_tprojs(), f);
401 }
402
403 template<class F>
404 auto projs(nat_t a, F f) const {
405 using R = std::decay_t<decltype(f(this))>;
406 return Vector<R>(a, [&](nat_t i) { return f(proj(a, i)); });
407 }
408 template<nat_t A = std::dynamic_extent>
409 auto projs() const {
410 return projs<A>([](const Def* def) { return def; });
411 }
412 auto tprojs() const {
413 return tprojs([](const Def* def) { return def; });
414 }
415 auto projs(nat_t a) const {
416 return projs(a, [](const Def* def) { return def; });
417 }
418 ///@}
419
420 /// @name var
421 /// @anchor var
422 /// Retrieve Var for *mutables*.
423 /// @see @ref proj
424 ///@{
426 const Def* var(); ///< Not necessarily a Var: E.g., if the return type is `[]`, this will yield `()`.
427 const Def* var_type(); ///< If `this` is a binder, compute the type of its Var%iable.
428
429 const Var* has_var() { return var_; } ///< Only returns not `nullptr`, if Var of this mutable has ever been created.
430 /// As above if `this` is a *mutable*.
431 const Var* has_var() const {
432 if (auto mut = isa_mut()) return mut->has_var();
433 return nullptr;
434 }
435
436 /// Is `this` a mutable that introduces a Var?
437 /// @returns `{nullptr, nullptr}` otherwise.
438 template<class D = Def>
439 std::pair<D*, const Var*> isa_binder() const {
440 if (auto mut = isa_mut<D>()) {
441 if (auto var = mut->has_var()) return {mut, var};
442 }
443 return {nullptr, nullptr};
444 }
445 ///@}
446
447 /// @name Free Vars and Muts
448 /// * local_muts() / local_vars() are cached and hash-consed.
449 /// * free_vars() are computed on demand and cached in mutables.
450 /// They will be transitively invalidated by following users(), if a mutable is mutated.
451 ///@{
452
453 /// Mutables reachable by following *immutable* deps(); `mut->local_muts()` is by definition the set `{ mut }`.
454 Muts local_muts() const;
455
456 /// Var%s reachable by following *immutable* deps().
457 /// @note `var->local_vars()` is by definition the set `{ var }`.
458 Vars local_vars() const;
459
460 /// Compute a global solution by transitively following *mutables* as well.
461 Vars free_vars() const;
462 Vars free_vars();
463 Muts users() { return muts_; } ///< Set of mutables where this mutable is locally referenced.
464 bool is_open() const; ///< Has free_vars()?
465 bool is_closed() const; ///< Has no free_vars()?
466
467 /// Transitively walks up free_vars() till the outermoust binder has been found.
468 /// @returns `nullptr`, if is_closed() and not a mutable.
469 Def* outermost_binder() const;
470 ///@}
471
472 /// @name external
473 ///@{
474 bool is_external() const noexcept { return external_; }
475 void externalize();
476 void internalize();
477 void transfer_external(Def* to);
478 bool is_annex() const noexcept { return annex_; }
479 ///@}
480
481 /// @name Casts
482 /// @see @ref cast_builtin
483 ///@{
484 bool is_mutable() const noexcept { return mut_; }
485
486 // clang-format off
487 template<class T = Def> const T* isa_imm() const { return isa_mut<T, true>(); }
488 template<class T = Def> const T* as_imm() const { return as_mut<T, true>(); }
489 // clang-format on
490
491 /// If `this` is *mutable*, it will cast `const`ness away and perform a `dynamic_cast` to @p T.
492 template<class T = Def, bool invert = false>
493 T* isa_mut() const {
494 if constexpr (std::is_same<T, Def>::value)
495 return mut_ ^ invert ? const_cast<Def*>(this) : nullptr;
496 else
497 return mut_ ^ invert ? const_cast<Def*>(this)->template isa<T>() : nullptr;
498 }
499
500 /// Asserts that `this` is a *mutable*, casts `const`ness away and performs a `static_cast` to @p T.
501 template<class T = Def, bool invert = false>
502 T* as_mut() const {
503 assert(mut_ ^ invert);
504 if constexpr (std::is_same<T, Def>::value)
505 return const_cast<Def*>(this);
506 else
507 return const_cast<Def*>(this)->template as<T>();
508 }
509 ///@}
510
511 /// @name Dbg Getters
512 ///@{
513 Dbg dbg() const { return dbg_; }
514 Loc loc() const { return dbg_.loc(); }
515 Sym sym() const { return dbg_.sym(); }
516 std::string unique_name() const; ///< name + "_" + Def::gid
517 ///@}
518
519 /// @name Dbg Setters
520 /// Every subclass `S` of Def has the same setters that return `S*`/`const S*` via the mixin Setters.
521 ///@{
522 // clang-format off
523 template<bool Ow = false> const Def* set(Loc l) const { if (Ow || !dbg_.loc()) dbg_.set(l); return this; }
524 template<bool Ow = false> Def* set(Loc l) { if (Ow || !dbg_.loc()) dbg_.set(l); return this; }
525 template<bool Ow = false> const Def* set(Sym s) const { if (Ow || !dbg_.sym()) dbg_.set(s); return this; }
526 template<bool Ow = false> Def* set(Sym s) { if (Ow || !dbg_.sym()) dbg_.set(s); return this; }
527 template<bool Ow = false> const Def* set( std::string s) const { set<Ow>(sym(std::move(s))); return this; }
528 template<bool Ow = false> Def* set( std::string s) { set<Ow>(sym(std::move(s))); return this; }
529 template<bool Ow = false> const Def* set(Loc l, Sym s ) const { set<Ow>(l); set<Ow>(s); return this; }
530 template<bool Ow = false> Def* set(Loc l, Sym s ) { set<Ow>(l); set<Ow>(s); return this; }
531 template<bool Ow = false> const Def* set(Loc l, std::string s) const { set<Ow>(l); set<Ow>(sym(std::move(s))); return this; }
532 template<bool Ow = false> Def* set(Loc l, std::string s) { set<Ow>(l); set<Ow>(sym(std::move(s))); return this; }
533 template<bool Ow = false> const Def* set(Dbg d) const { set<Ow>(d.loc(), d.sym()); return this; }
534 template<bool Ow = false> Def* set(Dbg d) { set<Ow>(d.loc(), d.sym()); return this; }
535 // clang-format on
536 ///@}
537
538 /// @name debug_prefix/suffix
539 /// Prepends/Appends a prefix/suffix to Def::name - but only in `Debug` build.
540 ///@{
541#ifndef NDEBUG
542 const Def* debug_prefix(std::string) const;
543 const Def* debug_suffix(std::string) const;
544#else
545 const Def* debug_prefix(std::string) const { return this; }
546 const Def* debug_suffix(std::string) const { return this; }
547#endif
548 ///@}
549
550 /// @name Rebuild
551 ///@{
552 Def* stub(World& w, const Def* type) { return stub_(w, type)->set(dbg()); }
553 Def* stub(const Def* type) { return stub(world(), type); }
554
555 /// Def::rebuild%s this Def while using @p new_op as substitute for its @p i'th Def::op
556 const Def* rebuild(World& w, const Def* type, Defs ops) const {
557 assert(isa_imm());
558 return rebuild_(w, type, ops)->set(dbg());
559 }
560 const Def* rebuild(const Def* type, Defs ops) const { return rebuild(world(), type, ops); }
561
562 /// Tries to make an immutable from a mutable.
563 /// This usually works if the mutable isn't recursive and its var isn't used.
564 virtual const Def* immutabilize() { return nullptr; }
565 bool is_immutabilizable();
566
567 const Def* refine(size_t i, const Def* new_op) const;
568
569 /// @see World::reduce
570 template<size_t N = std::dynamic_extent>
571 constexpr auto reduce(const Def* arg) const {
572 return reduce_(arg).span<N>();
573 }
574
575 /// First Def::op that needs to be dealt with during reduction; e.g. for a Pi we don't reduce the Pi::dom.
576 /// @see World::reduce
577 virtual constexpr size_t reduction_offset() const noexcept { return size_t(-1); }
578 ///@}
579
580 /// @name Type Checking
581 ///@{
582
583 /// Checks whether the `i`th operand can be set to `def`.
584 /// The method returns a possibly updated version of `def` (e.g. where Hole%s have been resolved).
585 /// This is the actual `def` that will be set as the `i`th operand.
586 virtual const Def* check([[maybe_unused]] size_t i, const Def* def) { return def; }
587
588 /// After all Def::ops have been Def::set, this method will be invoked to check the type of this mutable.
589 /// The method returns a possibly updated version of its type (e.g. where Hole%s have been resolved).
590 /// If different from Def::type, it will update its Def::type to a Def::zonk%ed version of that.
591 virtual const Def* check() { return type(); }
592
593 /// Yields `true`, if Def::local_muts() contain a Hole that is set.
594 /// Rewriting (Def::zonk%ing) will resolve the Hole to its operand.
595 bool needs_zonk() const;
596
597 /// If Hole%s have been filled, reconstruct the program without them.
598 /// Only goes up to but excluding other mutables.
599 /// @see https://stackoverflow.com/questions/31889048/what-does-the-ghc-source-mean-by-zonk
600 const Def* zonk() const;
601
602 /// If *mutable*, zonk()%s all ops and tries to immutabilize it; otherwise just zonk.
603 const Def* zonk_mut() const;
604 ///@}
605
606 /// zonk%s all @p defs and returns a new DefVec.
607 static DefVec zonk(Defs defs);
608
609 /// @name dump
610 /// @note While this output uses Mim syntax, it does usually **not** produce programs that can be read back.
611 /// It uses an unscheduled visiting algorithm, and is only meant for debugging purposes.
612 ///@{
613 void dump() const;
614 void dump(int max) const;
615 void write(int max) const;
616 void write(int max, const char* file) const;
617 std::ostream& stream(std::ostream&, int max) const;
618 ///@}
619
620 /// @name Syntactic Comparison
621 ///
622 enum class Cmp {
623 L, ///< Less
624 G, ///< Greater
625 E, ///< Equal
626 U, ///< Unknown
627 };
628 /// @name Syntactic Comparison
629 ///@{
630 [[nodiscard]] static Cmp cmp(const Def* a, const Def* b);
631 [[nodiscard]] static bool less(const Def* a, const Def* b);
632 [[nodiscard]] static bool greater(const Def* a, const Def* b);
633 ///@}
634
635 /// @name dot
636 /// Streams dot to @p os while obeying maximum recursion depth of @p max.
637 /// if @p types is `true`, Def::type() dependencies will be followed as well.
638 ///@{
639 void dot(std::ostream& os, int max = std::numeric_limits<int>::max(), bool types = false) const;
640 /// Same as above but write to @p file or `std::cout` if @p file is `nullptr`.
641 void dot(const char* file = nullptr, int max = std::numeric_limits<int>::max(), bool types = false) const;
642 void dot(const std::string& file, int max = std::numeric_limits<int>::max(), bool types = false) const {
643 return dot(file.c_str(), max, types);
644 }
645 ///@}
646
647protected:
648 /// @name Wrappers for World::sym
649 /// These are here to have Def::set%ters inline without including `mim/world.h`.
650 ///@{
651 Sym sym(const char*) const;
652 Sym sym(std::string_view) const;
653 Sym sym(std::string) const;
654 ///@}
655
656private:
657 Defs reduce_(const Def* arg) const;
658 virtual Def* stub_(World&, const Def*) { fe::unreachable(); }
659 virtual const Def* rebuild_(World& w, const Def* type, Defs ops) const = 0;
660
661 template<bool init>
662 Vars free_vars(bool&, uint32_t);
663 void invalidate();
664 const Def** ops_ptr() const {
665 return reinterpret_cast<const Def**>(reinterpret_cast<char*>(const_cast<Def*>(this + 1)));
666 }
667 bool equal(const Def* other) const;
668
669 template<Cmp>
670 [[nodiscard]] static bool cmp_(const Def* a, const Def* b);
671
672protected:
673 mutable Dbg dbg_;
674 union {
675 NormalizeFn normalizer_; ///< Axm only: Axm%s use this member to store their normalizer.
676 const Axm* axm_; ///< App only: Curried App%s of Axm%s use this member to propagate the Axm.
677 const Var* var_; ///< Mutable only: Var of a mutable.
678 mutable World* world_;
679 };
683
684private:
685 Node node_; // 8
686 bool mut_ : 1;
687 bool external_ : 1;
688 mutable bool annex_ : 1;
689 unsigned dep_ : 5;
690 u32 mark_ = 0;
691#ifndef NDEBUG
692 size_t curr_op_ = 0;
693#endif
694 u32 gid_;
695 u32 num_ops_;
696 size_t hash_;
697 Vars vars_; // Mutable: local vars; Immutable: free vars.
698 Muts muts_; // Immutable: local_muts; Mutable: users;
699 mutable u32 tid_ = 0;
700 mutable const Def* type_;
701
702 template<class D, size_t N>
703 friend class Sets;
704 friend class World;
705 friend void swap(World&, World&) noexcept;
706 friend std::ostream& operator<<(std::ostream&, const Def*);
707};
708
709/// A variable introduced by a binder (mutable).
710/// @note Var will keep its type_ field as `nullptr`.
711/// Instead, Def::type() and Var::type() will compute the type via Def::var_type().
712/// The reason is that the type could need a Def::zonk().
713/// But we don't want to have several Var%s that belong to the same binder.
714class Var : public Def, public Setters<Var> {
715private:
716 Var(Def* mut)
717 : Def(Node, nullptr, Defs{mut}, 0) {}
718
719public:
720 using Setters<Var>::set;
721
722 const Def* type() const { return mut()->var_type(); }
723
724 /// @name ops
725 ///@{
726 Def* mut() const { return op(0)->as_mut(); }
727 ///@}
728
729 static constexpr auto Node = mim::Node::Var;
730 static constexpr size_t Num_Ops = 1;
731
732private:
733 const Def* rebuild_(World&, const Def*, Defs) const final;
734
735 friend class World;
736};
737
738class Univ : public Def, public Setters<Univ> {
739public:
740 using Setters<Univ>::set;
741 static constexpr auto Node = mim::Node::Univ;
742 static constexpr size_t Num_Ops = 0;
743
744private:
745 Univ(World& world)
746 : Def(&world, Node, nullptr, Defs{}, 0) {}
747
748 const Def* rebuild_(World&, const Def*, Defs) const final;
749
750 friend class World;
751};
752
753class UMax : public Def, public Setters<UMax> {
754public:
755 using Setters<UMax>::set;
756 static constexpr auto Node = mim::Node::UMax;
757 static constexpr size_t Num_Ops = std::dynamic_extent;
758
759 enum Sort { Univ, Kind, Type, Term };
760
761private:
762 UMax(World&, Defs ops);
763
764 const Def* rebuild_(World&, const Def*, Defs) const final;
765
766 friend class World;
767};
768
769class UInc : public Def, public Setters<UInc> {
770private:
771 UInc(const Def* op, level_t offset)
772 : Def(Node, op->type()->as<Univ>(), {op}, offset) {}
773
774public:
775 using Setters<UInc>::set;
776
777 /// @name ops
778 ///@{
779 const Def* op() const { return Def::op(0); }
780 level_t offset() const { return flags(); }
781 ///@}
782
783 static constexpr auto Node = mim::Node::UInc;
784 static constexpr size_t Num_Ops = 1;
785
786private:
787 const Def* rebuild_(World&, const Def*, Defs) const final;
788
789 friend class World;
790};
791
792class Type : public Def, public Setters<Type> {
793private:
794 Type(const Def* level)
795 : Def(Node, nullptr, {level}, 0) {}
796
797public:
798 using Setters<Type>::set;
799
800 /// @name ops
801 ///@{
802 const Def* level() const { return op(0); }
803 ///@}
804
805 static constexpr auto Node = mim::Node::Type;
806 static constexpr size_t Num_Ops = 1;
807
808private:
809 const Def* rebuild_(World&, const Def*, Defs) const final;
810
811 friend class World;
812};
813
814class Lit : public Def, public Setters<Lit> {
815private:
816 Lit(const Def* type, flags_t val)
817 : Def(Node, type, Defs{}, val) {}
818
819public:
820 using Setters<Lit>::set;
821
822 /// @name Get actual Constant
823 ///@{
824 template<class T = flags_t>
825 T get() const {
826 static_assert(sizeof(T) <= 8);
828 }
829 ///@}
830
831 using Def::as;
832 using Def::isa;
833
834 /// @name Casts
835 ///@{
836 /// @see @ref cast_lit
837 template<class T = nat_t>
838 static std::optional<T> isa(const Def* def) {
839 if (!def) return {};
840 if (auto lit = def->isa<Lit>()) return lit->get<T>();
841 return {};
842 }
843 template<class T = nat_t>
844 static T as(const Def* def) {
845 return def->as<Lit>()->get<T>();
846 }
847 ///@}
848
849 static constexpr auto Node = mim::Node::Lit;
850 static constexpr size_t Num_Ops = 0;
851
852private:
853 const Def* rebuild_(World&, const Def*, Defs) const final;
854
855 friend class World;
856};
857
858class Nat : public Def, public Setters<Nat> {
859public:
860 using Setters<Nat>::set;
861 static constexpr auto Node = mim::Node::Nat;
862 static constexpr size_t Num_Ops = 0;
863
864private:
865 Nat(World& world);
866
867 const Def* rebuild_(World&, const Def*, Defs) const final;
868
869 friend class World;
870};
871
872/// A built-in constant of type `Nat -> *`.
873class Idx : public Def, public Setters<Idx> {
874private:
875 Idx(const Def* type)
876 : Def(Node, type, Defs{}, 0) {}
877
878public:
879 using Setters<Idx>::set;
880 using Def::as;
881 using Def::isa;
882
883 /// @name isa
884 ///@{
885
886 /// Checks if @p def is a `Idx s` and returns `s` or `nullptr` otherwise.
887 static const Def* isa(const Def* def);
888 static const Def* as(const Def* def) {
889 auto res = isa(def);
890 assert(res);
891 return res;
892 }
893 static std::optional<nat_t> isa_lit(const Def* def);
894 static nat_t as_lit(const Def* def) {
895 auto res = isa_lit(def);
896 assert(res.has_value());
897 return *res;
898 }
899 ///@}
900
901 /// @name Convert between Idx::isa and bitwidth and vice versa
902 ///@{
903 // clang-format off
904 static constexpr nat_t bitwidth2size(nat_t n) { assert(n != 0); return n == 64 ? 0 : (1_n << n); }
905 static constexpr nat_t size2bitwidth(nat_t n) { return n == 0 ? 64 : std::bit_width(n - 1_n); }
906 // clang-format on
907 static std::optional<nat_t> size2bitwidth(const Def* size);
908 ///@}
909
910 static constexpr auto Node = mim::Node::Idx;
911 static constexpr size_t Num_Ops = 0;
912
913private:
914 const Def* rebuild_(World&, const Def*, Defs) const final;
915
916 friend class World;
917};
918
919class Proxy : public Def, public Setters<Proxy> {
920private:
921 Proxy(const Def* type, u32 pass, u32 tag, Defs ops)
922 : Def(Node, type, ops, (u64(pass) << 32_u64) | u64(tag)) {}
923
924public:
925 using Setters<Proxy>::set;
926
927 /// @name Getters
928 ///@{
929 u32 pass() const { return u32(flags() >> 32_u64); } ///< IPass::index within PassMan.
930 u32 tag() const { return u32(flags()); }
931 ///@}
932
933 static constexpr auto Node = mim::Node::Proxy;
934 static constexpr size_t Num_Ops = std::dynamic_extent;
935
936private:
937 const Def* rebuild_(World&, const Def*, Defs) const final;
938
939 friend class World;
940};
941
942/// @deprecated A global variable in the data segment.
943/// A Global may be mutable or immutable.
944/// @deprecated Will be removed.
945class Global : public Def, public Setters<Global> {
946private:
947 Global(const Def* type, bool is_mutable)
948 : Def(Node, type, 1, is_mutable) {}
949
950public:
951 using Setters<Global>::set;
952
953 /// @name ops
954 ///@{
955 const Def* init() const { return op(0); }
956 void set(const Def* init) { Def::set(0, init); }
957 ///@}
958
959 /// @name type
960 ///@{
961 const App* type() const;
962 const Def* alloced_type() const;
963 ///@}
964
965 /// @name Getters
966 ///@{
967 bool is_mutable() const { return flags(); }
968 ///@}
969
970 /// @name Rebuild
971 ///@{
972 Global* stub(const Def* type) { return stub_(world(), type)->set(dbg()); }
973 ///@}
974
975 static constexpr auto Node = mim::Node::Global;
976 static constexpr size_t Num_Ops = 1;
977
978private:
979 const Def* rebuild_(World&, const Def*, Defs) const final;
980 Global* stub_(World&, const Def*) final;
981
982 friend class World;
983};
984
985} // namespace mim
986
987#ifndef DOXYGEN // clang-format off
988/// Format any pointer to a `mim::Def` (or subclass) via its `operator<<`.
989template<class T> requires std::derived_from<T, mim::Def> struct std::formatter< T*> : fe::ostream_formatter {};
990template<class T> requires std::derived_from<T, mim::Def> struct std::formatter<const T*> : fe::ostream_formatter {};
991template<> struct std::formatter<mim::Muts> : fe::ostream_formatter {};
992template<> struct std::formatter<mim::Vars> : fe::ostream_formatter {};
993#endif // clang-format on
Definition axm.h:9
Base class for all Defs.
Definition def.h:246
bool is_set() const
Yields true if empty or the last op is set.
Definition def.cpp:298
size_t num_deps() const noexcept
Definition def.h:340
const Def * zonk_mut() const
If mutable, zonk()s all ops and tries to immutabilize it; otherwise just zonk.
Definition check.cpp:23
const Def * set(Dbg d) const
Definition def.h:533
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:593
constexpr Node node() const noexcept
Definition def.h:270
Def * set(size_t i, const Def *)
Successively set from left to right.
Definition def.cpp:266
virtual const Def * check(size_t i, const Def *def)
Checks whether the ith operand can be set to def.
Definition def.h:586
void dot(std::ostream &os, int max=std::numeric_limits< int >::max(), bool types=false) const
Definition dot.cpp:160
T * as_mut() const
Asserts that this is a mutable, casts constness away and performs a static_cast to T.
Definition def.h:502
const Var * has_var() const
As above if this is a mutable.
Definition def.h:431
void dump() const
Definition dump.cpp:549
bool has_dep() const noexcept
Definition def.h:354
Defs deps() const noexcept
Definition def.cpp:475
auto projs() const
Definition def.h:409
u8 trip_
Definition def.h:682
bool is_elim() const noexcept
Definition def.h:281
nat_t num_tprojs() const
As above but yields 1, if Flags::scalarize_threshold is exceeded.
Definition def.cpp:588
virtual ~Def()=default
const Def * zonk() const
If Holes have been filled, reconstruct the program without them.
Definition check.cpp:21
World & world() const noexcept
Definition def.cpp:444
virtual const Def * check()
After all Def::ops have been Def::set, this method will be invoked to check the type of this mutable.
Definition def.h:591
const Def * refine(size_t i, const Def *new_op) const
Definition def.cpp:232
Def * set_type(const Def *)
Update type.
Definition def.cpp:283
std::string_view node_name() const
Definition def.cpp:465
auto projs(nat_t a, F f) const
Definition def.h:404
bool is_intro() const noexcept
Definition def.h:280
constexpr auto ops() const noexcept
Definition def.h:301
Vars local_vars() const
Vars reachable by following immutable deps().
Definition def.cpp:348
constexpr flags_t flags() const noexcept
Definition def.h:265
Dbg dbg_
Definition def.h:673
virtual Def * stub_(World &, const Def *)
Definition def.h:658
bool has_dep(Dep d) const noexcept
Definition def.h:355
const Def * set(std::string s) const
Definition def.h:527
Dep dep() const noexcept
Definition def.h:353
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:493
constexpr u32 mark() const noexcept
Used internally by free_vars().
Definition def.h:268
constexpr u32 tid() const noexcept
Trie id - only used in Trie.
Definition def.h:267
auto projs(nat_t a) const
Definition def.h:415
u8 curry_
Definition def.h:681
auto tprojs() const
Definition def.h:412
Judge judge() const noexcept
Definition def.cpp:482
void externalize()
Definition def.cpp:575
friend std::ostream & operator<<(std::ostream &, const Def *)
This will stream def as an operand.
Definition dump.cpp:520
bool is_term() const
Definition def.cpp:492
const Def * debug_prefix(std::string) const
Definition def.cpp:504
const Def * op(size_t i) const noexcept
Definition def.h:304
bool is_immutabilizable()
Definition def.cpp:176
virtual const Def * rebuild_(World &w, const Def *type, Defs ops) const =0
std::pair< D *, const Var * > isa_binder() const
Is this a mutable that introduces a Var?
Definition def.h:439
const Def * var(nat_t a, nat_t i) noexcept
Definition def.h:425
void transfer_external(Def *to)
Definition def.cpp:578
const Def * unfold_type() const
Yields the type of this Def and builds a new Type (UInc n) if necessary.
Definition def.cpp:457
const Def * proj(nat_t i) const
As above but takes Def::num_projs as arity.
Definition def.h:380
auto projs(F f) const
Splits this Def via Def::projections into an Array (if A == std::dynamic_extent) or std::array (other...
Definition def.h:386
bool is_open() const
Has free_vars()?
Definition def.cpp:426
constexpr size_t hash() const noexcept
Definition def.h:269
friend class World
Definition def.h:704
virtual const Def * immutabilize()
Tries to make an immutable from a mutable.
Definition def.h:564
bool is_form() const noexcept
Definition def.h:279
Def * set(Dbg d)
Definition def.h:534
Muts local_muts() const
Mutables reachable by following immutable deps(); mut->local_muts() is by definition the set { mut }...
Definition def.cpp:332
Def * set(Sym s)
Definition def.h:526
const Def * debug_suffix(std::string) const
Definition def.cpp:505
const Def * set(Sym s) const
Definition def.h:525
Def * set(Loc l)
Definition def.h:524
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Definition def.cpp:452
Def * outermost_binder() const
Transitively walks up free_vars() till the outermoust binder has been found.
Definition def.cpp:431
const Def * dep(size_t i) const noexcept
Definition def.h:339
bool is_mutable() const noexcept
Definition def.h:484
bool is_external() const noexcept
Definition def.h:474
const Def * rebuild(World &w, const Def *type, Defs ops) const
Def::rebuilds this Def while using new_op as substitute for its i'th Def::op.
Definition def.h:556
void internalize()
Definition def.cpp:576
const Def * set(Loc l, Sym s) const
Definition def.h:529
static bool less(const Def *a, const Def *b)
Definition def.cpp:554
Def * set(std::string s)
Definition def.h:528
bool is_meta() const noexcept
Definition def.h:282
static bool greater(const Def *a, const Def *b)
Definition def.cpp:555
const Def * set(Loc l) const
Definition def.h:523
Loc loc() const
Definition def.h:514
void write(int max) const
Definition dump.cpp:557
auto tprojs(F f) const
Definition def.h:399
Def * set(Loc l, std::string s)
Definition def.h:532
friend class Sets
Definition def.h:703
const T * as_imm() const
Definition def.h:488
Def * stub(const Def *type)
Definition def.h:553
static Cmp cmp(const Def *a, const Def *b)
Definition def.cpp:512
virtual constexpr size_t reduction_offset() const noexcept
First Def::op that needs to be dealt with during reduction; e.g.
Definition def.h:577
Sym sym() const
Definition def.h:515
nat_t num_projs() const
Yields Def::arity(), if it is a Lit, or 1 otherwise.
Definition def.cpp:586
std::ostream & stream(std::ostream &, int max) const
Definition dump.cpp:529
flags_t flags_
Definition def.h:680
friend void swap(World &, World &) noexcept
const Def * var_type()
If this is a binder, compute the type of its Variable.
Definition def.cpp:315
constexpr u32 gid() const noexcept
Global id - unique number for this Def.
Definition def.h:266
virtual const Def * arity() const
Definition def.cpp:558
Def * unset()
Unsets all Def::ops; works even, if not set at all or only partially set.
Definition def.cpp:289
std::string unique_name() const
name + "_" + Def::gid
Definition def.cpp:584
constexpr auto reduce(const Def *arg) const
Definition def.h:571
const Def * set(Loc l, std::string s) const
Definition def.h:531
const T * isa_imm() const
Definition def.h:487
bool needs_zonk() const
Yields true, if Def::local_muts() contain a Hole that is set.
Definition check.cpp:12
Muts users()
Set of mutables where this mutable is locally referenced.
Definition def.h:463
bool is_closed() const
Has no free_vars()?
Definition def.cpp:418
void dot(const std::string &file, int max=std::numeric_limits< int >::max(), bool types=false) const
Definition def.h:642
const Def * rebuild(const Def *type, Defs ops) const
Definition def.h:560
Vars free_vars() const
Compute a global solution by transitively following mutables as well.
Definition def.cpp:337
Def * set(Loc l, Sym s)
Definition def.h:530
Dbg dbg() const
Definition def.h:513
Def * stub(World &w, const Def *type)
Definition def.h:552
const Def * tproj(nat_t i) const
As above but takes Def::num_tprojs.
Definition def.h:381
const Var * has_var()
Only returns not nullptr, if Var of this mutable has ever been created.
Definition def.h:429
bool is_annex() const noexcept
Definition def.h:478
constexpr size_t num_ops() const noexcept
Definition def.h:305
@ E
Equal.
Definition def.h:625
@ U
Unknown.
Definition def.h:626
@ L
Less.
Definition def.h:623
@ G
Greater.
Definition def.h:624
const Def * init() const
Definition def.h:955
void set(const Def *init)
Definition def.h:956
Global * stub(const Def *type)
Definition def.h:972
const Def * alloced_type() const
Definition def.cpp:641
friend class World
Definition def.h:982
bool is_mutable() const
Definition def.h:967
const App * type() const
Definition def.cpp:640
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:110
static constexpr size_t Num_Ops
Definition def.h:976
Global * stub_(World &, const Def *) final
Definition def.cpp:151
static constexpr auto Node
Definition def.h:975
This node is a hole in the IR that is inferred by its context later on.
Definition check.h:14
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:111
static constexpr auto Node
Definition def.h:910
static nat_t as_lit(const Def *def)
Definition def.h:894
static constexpr nat_t size2bitwidth(nat_t n)
Definition def.h:905
static constexpr nat_t bitwidth2size(nat_t n)
Definition def.h:904
static const Def * isa(const Def *def)
Checks if def is a Idx s and returns s or nullptr otherwise.
Definition def.cpp:616
friend class World
Definition def.h:916
static std::optional< nat_t > isa_lit(const Def *def)
Definition def.cpp:624
static constexpr size_t Num_Ops
Definition def.h:911
static const Def * as(const Def *def)
Definition def.h:888
static constexpr auto Node
Definition def.h:849
static std::optional< T > isa(const Def *def)
Definition def.h:838
friend class World
Definition def.h:855
T get() const
Definition def.h:825
static T as(const Def *def)
Definition def.h:844
static constexpr size_t Num_Ops
Definition def.h:850
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:120
friend class World
Definition def.h:869
static constexpr auto Node
Definition def.h:861
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:112
static constexpr size_t Num_Ops
Definition def.h:862
static constexpr size_t Num_Ops
Definition def.h:934
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:124
friend class World
Definition def.h:939
static constexpr auto Node
Definition def.h:933
u32 pass() const
IPass::index within PassMan.
Definition def.h:929
u32 tag() const
Definition def.h:930
CRTP-based mixin to declare setters for Def::loc & Def::name using a covariant return type.
Definition def.h:190
P * set(Loc l, Sym s)
Definition def.h:204
P * set(std::string s)
Definition def.h:202
const P * set(Sym s) const
Definition def.h:199
const P * set(Loc l, Sym s) const
Definition def.h:203
const P * set(Loc l) const
Definition def.h:197
P * set(Loc l)
Definition def.h:198
const P * set(Dbg d) const
Definition def.h:207
const P * set(Loc l, std::string s) const
Definition def.h:205
P * set(Sym s)
Definition def.h:200
P * set(Dbg d)
Definition def.h:208
P * set(Loc l, std::string s)
Definition def.h:206
const P * set(std::string s) const
Definition def.h:201
friend class World
Definition def.h:811
static constexpr size_t Num_Ops
Definition def.h:806
static constexpr auto Node
Definition def.h:805
const Def * level() const
Definition def.h:802
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:131
const Def * op() const
Definition def.h:779
static constexpr auto Node
Definition def.h:783
friend class World
Definition def.h:789
level_t offset() const
Definition def.h:780
static constexpr size_t Num_Ops
Definition def.h:784
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:132
@ Type
Definition def.h:759
@ Univ
Definition def.h:759
@ Term
Definition def.h:759
@ Kind
Definition def.h:759
static constexpr auto Node
Definition def.h:756
friend class World
Definition def.h:766
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:133
static constexpr size_t Num_Ops
Definition def.h:757
static constexpr size_t Num_Ops
Definition def.h:742
static constexpr auto Node
Definition def.h:741
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:113
friend class World
Definition def.h:750
A variable introduced by a binder (mutable).
Definition def.h:714
const Def * type() const
Definition def.h:722
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:135
static constexpr auto Node
Definition def.h:729
friend class World
Definition def.h:735
static constexpr size_t Num_Ops
Definition def.h:730
Def * mut() const
Definition def.h:726
This is a thin wrapper for absl::InlinedVector<T, N, A> which is a drop-in replacement for std::vecto...
Definition vector.h:18
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:36
#define MIM_NODE(X)
Definition def.h:20
#define MIM_PROJ(NAME, CONST)
Use as mixin to wrap all kind of Def::proj and Def::projs variants.
Definition def.h:159
Definition ast.h:14
View< const Def * > Defs
Definition def.h:78
u64 nat_t
Definition types.h:37
DefMap< const Def * > Def2Def
Definition def.h:77
Vector< const Def * > DefVec
Definition def.h:79
Dep
Tracks a dependency to certain Defs transitively through the Def::deps() up to but excliding mutables...
Definition def.h:118
@ None
Definition def.h:119
u64 flags_t
Definition types.h:39
u8 node_t
Definition types.h:38
Span< const T, N > View
Definition span.h:98
absl::flat_hash_map< K, V, GIDHash< K > > GIDMap
Definition util.h:168
GIDSet< const Var * > VarSet
Definition def.h:97
GIDMap< const Var *, To > VarMap
Definition def.h:96
Sets< Def >::Set Muts
Definition def.h:89
u64 level_t
Definition types.h:36
GIDMap< const Def *, To > DefMap
Definition def.h:75
GIDSet< Def * > MutSet
Definition def.h:87
MutMap< Def * > Mut2Mut
Definition def.h:88
GIDSet< const Def * > DefSet
Definition def.h:76
static constexpr size_t Num_Nodes
Definition def.h:114
const Def *(*)(const Def *, const Def *, const Def *) NormalizeFn
Definition def.h:102
Sets< const Var >::Set Vars
Definition def.h:99
uint32_t u32
Definition types.h:27
Mut
Judgement.
Definition def.h:138
@ Imm
Node may be immmutable.
Definition def.h:141
uint64_t u64
Definition types.h:27
Judge
Judgement.
Definition def.h:127
@ Intro
Term Introduction like λ(x: Nat): Nat = x.
Definition def.h:130
@ Meta
Meta rules for Universe and Type levels.
Definition def.h:132
@ Form
Type Formation like T -> T.
Definition def.h:129
@ Elim
Term Elimination like f a.
Definition def.h:131
absl::flat_hash_set< K, GIDHash< K > > GIDSet
Definition util.h:169
uint8_t u8
Definition types.h:27
constexpr D bitcast_resize(const S &src) noexcept
A bitcast from src of type S to D, supporting different sizes.
Definition util.h:31
Node
Definition def.h:107
@ Nat
Definition def.h:109
@ Univ
Definition def.h:109
@ Idx
Definition def.h:109
@ UInc
Definition def.h:109
@ Global
Definition def.h:109
@ Var
Definition def.h:109
@ Axm
Definition def.h:109
@ Type
Definition def.h:109
@ App
Definition def.h:109
@ Lit
Definition def.h:109
@ Proxy
Definition def.h:109
@ UMax
Definition def.h:109
Vector(I, I, A=A()) -> Vector< typename std::iterator_traits< I >::value_type, Default_Inlined_Size< typename std::iterator_traits< I >::value_type >, A >
GIDMap< Def *, To > MutMap
Definition def.h:86
VarMap< const Var * > Var2Var
Definition def.h:98
Definition span.h:122
#define CODE(name,...)
Definition tok.h:39