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