16#include <fe/restore.h>
29concept Enum = std::is_enum_v<std::remove_reference_t<T>>;
68#ifdef MIM_ENABLE_CHECKS
74 assert((!s1.pod.curr_loc.loc || !s2.pod.curr_loc.loc) &&
"Why is get_loc() still set?");
76#ifdef MIM_ENABLE_CHECKS
77 swap(s1.breakpoints, s2.breakpoints);
78 swap(s1.watchpoints, s2.watchpoints);
90 :
World(&other.driver(), other.state()) {
99 s.pod.curr_gid += move_.sea.size();
100 return std::make_unique<World>(&
driver(), s);
110 const fe::Error&
error()
const;
113 Sym
name()
const {
return state_.pod.name; }
132 Loc
get_loc()
const {
return state_.pod.curr_loc.loc; }
133 DbgKey
dbg_key()
const {
return state_.pod.curr_loc.key; }
139 Sym
sym(std::string_view);
140 Sym
sym(
const char*);
141 Sym
sym(
const std::string&);
160 [[nodiscard]]
auto freeze()
const {
return fe::Restore(state_.pod.frozen,
true); }
168 [[nodiscard]]
auto lenient()
const {
return fe::Restore(state_.pod.lenient,
true); }
173#ifdef MIM_ENABLE_CHECKS
191 auto muts()
const {
return sym2mut_ | std::views::values; }
196 size_t size()
const {
return sym2mut_.size(); }
207 auto begin()
const {
return sym2mut_.cbegin(); }
208 auto end()
const {
return sym2mut_.cend(); }
213 swap(ex1.sym2mut_, ex2.sym2mut_);
217 std::map<Sym, Def*> sym2mut_;
236 auto entries()
const {
return flags2entry_ | std::views::values; }
238 return entries() | std::views::transform([](
const Entry& e) {
return e.def; });
243 const flags_t*
flags(
const Def* d)
const {
return d->is_annex() ? fe::lookup(def2flags_, d) :
nullptr; }
246 size_t size()
const {
return flags2entry_.size(); }
263 auto begin()
const {
return flags2entry_.cbegin(); }
264 auto end()
const {
return flags2entry_.cend(); }
270 swap(a1.driver_, a2.driver_);
271 swap(a1.flags2entry_, a2.flags2entry_);
272 swap(a1.sym2flags_, a2.sym2flags_);
273 swap(a1.def2flags_, a2.def2flags_);
279 std::map<flags_t, Entry> flags2entry_;
280 std::map<Sym, flags_t> sym2flags_;
298 if (
auto e = fe::lookup(
annexes().flags2entry(),
flags))
return e->def;
299 return annex_miss(
flags);
308 template<annex_without_subs
id>
314 const Def*
import(
const Def* def) {
return importer_.import(def); }
331 template<level_t level = 0>
333 if constexpr (
level == 0)
335 else if constexpr (
level == 1)
344 switch (
type->node()) {
353 default:
return nullptr;
358 return unify<Proxy>(
type, Proxy::mk_flags(tag,
vars,
muts), ops);
369 return unify<Axm>(n, curry, trip,
type, p, t, s);
386 const Pi*
pi(
const Def* dom,
const Def* codom,
bool implicit =
false) {
return unify<Pi>(
Pi::infer(dom, codom), dom, codom, implicit); }
387 const Pi*
pi(
Defs dom,
const Def* codom,
bool implicit =
false) {
return pi(
sigma(dom), codom, implicit); }
388 const Pi*
pi(
const Def* dom,
Defs codom,
bool implicit =
false) {
return pi(dom,
sigma(codom), implicit); }
401 const Pi*
fn(
const Def* dom,
const Def* codom,
bool implicit =
false) {
return cn({ dom ,
cn(codom)}, implicit); }
402 const Pi*
fn(
Defs dom,
const Def* codom,
bool implicit =
false) {
return fn(
sigma(dom), codom, implicit); }
403 const Pi*
fn(
const Def* dom,
Defs codom,
bool implicit =
false) {
return fn( dom ,
sigma(codom), implicit); }
412 return std::get<const Def*>(
filter);
445 return unify<Rule>(
type, lhs, rhs, guard);
451 template<
bool Normalize = true>
453 template<
bool Normalize = true>
466 template<level_t level = 0>
477 template<level_t level = 0>
487 const Def*
arr (fe::View<u64> shape,
const Def* body) {
return seq(
false, shape, body); }
488 const Def*
pack(fe::View<u64> shape,
const Def* body) {
return seq(
true , shape, body); }
509 const Def*
seq(
bool is_pack, fe::View<u64> shape,
const Def* body) {
595 const Lit*
lit_bool(
bool val) {
return data_.lit_bool[size_t(val)]; }
653 template<
bool Normalize = true>
655 template<
bool Normalize = true>
659 template<
bool Normalize = true>
663 template<
bool Normalize = true>
665 requires std::is_same_v<std::underlying_type_t<
decltype(arg)>,
nat_t> {
673 template<
bool Normalize =
true,
class... Args>
674 const Def*
call(
const Def* callee,
auto&& arg, Args&&... args) {
676 std::forward<Args>(args)...);
680 template<
bool Normalize = true>
686 template<
Enum Id,
bool Normalize =
true,
class... Args>
692 template<
class Id,
bool Normalize =
true,
class... Args>
693 requires std::is_enum_v<Id>
const Def*
call(Args&&... args) {
698 template<
bool Normalize =
true,
class... Args>
714 [[nodiscard]]
auto&
vars() {
return move_.vars; }
715 [[nodiscard]]
auto&
muts() {
return move_.muts; }
716 [[nodiscard]]
const auto&
vars()
const {
return move_.vars; }
717 [[nodiscard]]
const auto&
muts()
const {
return move_.muts; }
736 void for_each(
bool elide_empty, std::function<
void(
Def*)>,
bool schedule =
false);
739 void for_each(
bool elide_empty, std::invocable<M*>
auto f,
bool schedule =
false) {
743 if (
auto mut = m->template isa<M>()) f(mut);
751 const fe::Log&
log()
const;
752 void dump(std::ostream& os);
755 void write(
const char* file);
766 void dot(
const char* file =
nullptr, DotConfig cfg = {})
const;
770 const Def* annex_miss(
flags_t);
771 const Def*
tuple(
const Def*
type,
Defs ops,
bool may_be_uniform);
772 void check_tuple(
const Tuple*);
774 Shape check_index(
const Def* index);
776 bool is_folded_axis(
const Def*
type,
const Def* index,
const Def* size);
777 const Def* extract1(
const Def* d,
const Def* i);
778 const Def* extract_fused(
const Def* d, Shape i);
779 const Def* inhabitant_(
const Def*
type);
784 void stamp(
auto* def) {
786#ifdef MIM_ENABLE_CHECKS
787 if (
flags().trace_gids) std::println(
"{}: {} - {}", def->node_name(), def->gid(), def->flags());
791 template<
class T,
class... Args>
792 const T* unify(Args&&... args) {
793 auto num_ops = T::Num_Ops;
794 if constexpr (T::Num_Ops == std::dynamic_extent) {
795 auto&&
last = std::get<
sizeof...(Args) - 1>(std::forward_as_tuple(std::forward<Args>(args)...));
796 num_ops =
last.size();
799 auto state = move_.arena.defs.state();
800 auto def = allocate<T>(num_ops, std::forward<Args>(args)...);
801 assert(!def->isa_mut());
804#ifdef MIM_ENABLE_CHECKS
806 for (
auto op : def->ops())
807 assert(&
op->world() ==
this &&
"op of new Def belongs to a different World");
808 assert((!def->type() || &def->type()->world() ==
this) &&
"type of new Def belongs to a different World");
812 auto i = move_.sea.find(def);
813 deallocate<T>(
state, def);
814 if (i != move_.sea.end())
return static_cast<const T*
>(*i);
818 if (
auto [i, ins] = move_.sea.emplace(def); !ins) {
819 deallocate<T>(
state, def);
820 return static_cast<const T*
>(*i);
823 if constexpr (!std::is_same_v<T, Var>) def->collect_locals();
825#ifdef MIM_ENABLE_CHECKS
832 template<
class T,
class... Args>
833 const Def* unify_elim(
const Def*
type, Args&&... args) {
836 return unify<T>(
type, std::forward<Args>(args)...);
840 void deallocate(fe::Arena::State
state,
const T* ptr) {
841 --state_.pod.curr_gid;
843 move_.arena.defs.deallocate(
state);
846 template<
class T,
class... Args>
847 T*
insert(Args&&... args) {
850 auto num_ops = T::Num_Ops;
851 if constexpr (T::Num_Ops == std::dynamic_extent)
852 num_ops = std::get<
sizeof...(Args) - 1>(std::forward_as_tuple(std::forward<Args>(args)...));
854 auto def = allocate<T>(num_ops, std::forward<Args>(args)...);
855 if (def->mut_) def->hash_ = fe::hash_combine(0, def->gid());
858#ifdef MIM_ENABLE_CHECKS
861 fe::assert_emplace(move_.sea, def);
862 if constexpr (!std::is_same_v<T, Var>)
863 if (!def->mut_) def->collect_locals();
867#if !defined(_MSC_VER) && !defined(NDEBUG)
869 Lock() { assert((guard_ = !guard_) &&
"you are not allowed to recursively invoke allocate"); }
870 ~Lock() { guard_ = !guard_; }
871 static inline bool guard_ =
false;
879 template<
class T,
class... Args>
880 T* allocate(
size_t num_ops, Args&&... args) {
881 static_assert(
sizeof(Def) ==
sizeof(T),
882 "you are not allowed to introduce any additional data in subclasses of Def");
884 auto num_bytes =
sizeof(Def) +
sizeof(uintptr_t) * num_ops;
885 auto ptr = move_.arena.defs.allocate(num_bytes,
alignof(T));
886 auto res =
new (ptr) T(std::forward<Args>(args)...);
888 assert(res->num_ops() == num_ops);
899 using is_avalanching = void;
901 size_t operator()(
const Def* def)
const {
return def->hash(); }
905 bool operator()(
const Def* d1,
const Def* d2)
const {
return d1->equal(d2); }
909 class Reduct :
public fe::VLA<Reduct> {
911 using VLA_Types = std::tuple<const Def*>;
914 template<
size_t N = std::dynamic_extent>
auto ops() const noexcept {
return vla<0, N>(); }
915 template<
size_t N = std::dynamic_extent>
auto ops() noexcept {
return vla<0, N>(); }
921 Reduct* reduct(
const Var*
var,
const Def* arg) {
922 auto [i, ins] = move_.substs.try_emplace(std::pair{
var, arg},
nullptr);
924 auto n =
var->binder()->num_ops() -
var->binder()->reduction_offset();
925 i->second = move_.arena.substs.ref<Reduct>(
DefVec(n,
nullptr)).
get();
932 const Def* cached_reduct(
const Var*
var,
const Def* arg,
size_t i);
950 ankerl::unordered_dense::set<const Def*, SeaHash, SeaEq> sea;
951 fe::Patricia<Def, DefKey> muts;
952 fe::Patricia<const Var, DefKey> vars;
953 ankerl::unordered_dense::map<std::pair<const Var*, const Def*>, Reduct*> substs;
954 fe::Vector<LevelEq> levels;
956 friend void swap(Move& m1, Move& m2)
noexcept {
959 swap(m1.arena.defs, m2.arena.defs);
960 swap(m1.arena.substs, m2.arena.substs);
961 swap(m1.sea, m2.sea);
962 swap(m1.substs, m2.substs);
963 swap(m1.vars, m2.vars);
964 swap(m1.muts, m2.muts);
965 swap(m1.externals, m2.externals);
966 swap(m1.annexes, m2.annexes);
967 swap(m1.levels, m2.levels);
988 std::array<const Lit*, Num_Lit_Nats> lit_nats = {};
996 swap(w1.driver_, w2.driver_ );
997 swap(w1.zonker_, w2.zonker_ );
998 swap(w1.state_, w2.state_ );
999 swap(w1.importer_, w2.importer_);
1000 swap(w1.data_, w2.data_ );
1001 swap(w1.move_, w2.move_ );
1004 swap(w1.data_.type_level->world_, w2.data_.type_level->world_);
1005 assert(&w1.type_level()->world() == &w1);
1006 assert(&w2.type_level()->world() == &w2);
A (possibly paramterized) Array.
Some "global" variables needed all over the place.
This node is a hole in the IR that is inferred by its context later on.
A built-in constant of type Nat -> *.
static constexpr nat_t bitwidth2size(nat_t n)
std::variant< bool, const Def * > Filter
static std::optional< T > isa(const Def *def)
static T as(const Def *def)
Nominal newtype formation.
A (possibly paramterized) Tuple.
A dependent function type.
static const Def * infer(const Def *dom, const Def *codom)
Used as intermediate value during optimizatinos such as Analysis.
Base class for Arr and Pack.
The extents of a Seq's axes: a plain Nat for a single axis, an aggregate of them for several.
Data constructor for a Sigma.
A variable introduced by a binder (mutable).
A sum type whose cases are positional: unlike a Join, they are neither sorted nor deduplicated.
const flags_t * flags(const Def *d) const
The flags of the annex def, if it is one.
void attach_alias(flags_t, Sym)
Registers a further Sym for an already attach()ed annex, sharing its flags_t;.
const Def * attach(flags_t, Sym, const Def *)
const auto & sym2flags() const
const Def * attach(plugin_t p, tag_t t, sub_t s, Sym sym, const Def *def)
const auto & flags2entry() const
friend void swap(Annexes &a1, Annexes &a2) noexcept
void attach_alias(plugin_t p, tag_t t, sub_t s, Sym sym)
const flags_t * opaque(const Def *d) const
Like flags() but only for an Axm or a non-Lam mutable - whose identity phases must preserve.
auto & flags2entry()
An annex's flags map to its full name and its Def.
Def * operator[](Sym name) const
Lookup by name.
friend void swap(Externals &ex1, Externals &ex2) noexcept
fe::Vector< Def * > mutate() const
Returns a copy of muts() in a fe::Vector; this allows you to modify the Externals while iterating.
The World represents the whole program and manages creation of MimIR nodes (Defs).
const Lit * lit_idx(nat_t size, u64 val)
Constructs a Lit of type Idx of size size.
const Def * arr(Defs shape, const Def *body)
const Def * insert(const Def *d, const Def *i, const Def *val)
const Pi * fn(Defs dom, const Def *codom, bool implicit=false)
Variant * mut_variant(const Def *type, size_t size)
std::unique_ptr< World > inherit()
Inherits the State into the new World.
const Lam * con(Defs dom, Lam::Filter f, const Def *body)
const Def * variant(Defs ops)
const Lit * lit(const Def *type, u64 val)
const Def * arr(u64 n, const Def *body)
const Def * inhabitant(const Def *type)
The sole inhabitant of type, if it has exactly one, nullptr otherwise.
const Def * call(flags_t id, Args &&... args)
Annex overload with flags_t as first argument.
friend void swap(World &w1, World &w2) noexcept
const Def * struc(const Def *nom)
Get the structural part of a nominal.
const Def * implicit_app(const Def *callee, nat_t arg)
const Def * extract(const Def *d, u64 a, u64 i)
const Def * pack(Shape shape, const Def *body)
const Def * level(Defs types)
The lmax of the levels of all types, each of which must be a Type level.
const Pi * cn(const Def *dom, bool implicit=false)
const Def * type_int(nat_t width)
Constructs a type Idx of size 2^width.
World & operator=(World)=delete
World(Driver *, Sym name)
const Lit * lit_i16(u16 val)
void watchpoint(u32 gid)
Trigger breakpoint in your debugger when Def::setting a Def with this gid.
const Lit * lit_i1(bool val)
const Def * call(const Def *callee, auto &&arg, Args &&... args)
Lam * mut_fun(const Def *dom, Defs codom)
const Type * type(const Def *level)
const Def * component(const Def *type, Defs parts, size_t n, size_t i)
The type of component i of the n-ary type, given its leading components parts.
const Def * lsucc(const Def *op, level_t offset=1)
const Driver & driver() const
const Lam * lam(const Def *dom, const Def *codom, Lam::Filter f, const Def *body)
const Lit * lit_level_1()
Lam * mut_lam(const Def *dom, Defs codom)
const Def * filter(Lam::Filter filter)
const auto & watchpoints()
const Def * sigma(Defs ops)
const Def * seq(bool is_pack, u64 n, const Def *body)
const Type * type_infer_level()
const Def * type_idx(nat_t size)
void set(std::string_view name)
const Def * app(const Def *callee, const Def *arg)
u32 curr_gid() const
Manage global identifier - a unique number for each Def.
const Axm * axm(const Def *type)
See above.
const Def * arr(Shape shape, const Def *body)
const Def * seq(bool is_pack, Shape shape, const Def *body)
const Pi * pi(const Def *dom, const Def *codom, bool implicit=false)
const Def * pack(u64 n, const Def *body)
const Def * insert(const Def *d, u64 a, u64 i, const Def *val)
const auto & muts() const
const Def * implicit_holes(const Def *callee)
Only places the Holes.
const Lam * lam(Defs dom, const Def *codom, Lam::Filter f, const Def *body)
void postpone(const LMax *lmax, const Def *level)
Postpones lmax = level as it does not determine the level Holes of lmax yet.
const Def * annex(Enum auto id)
Lookup annex by Axm::id.
const Lam * fun(Defs dom, const Def *codom, Lam::Filter f, const Def *body)
Rule * mut_rule(const Reform *type)
World & verify()
Verifies that all externals() and annexes() are Def::is_closed(), if MIM_ENABLE_CHECKS.
const Def * bot(const Def *type)
Arr * mut_arr(const Def *type)
const Def * call(const Def *callee, auto &&arg)
Base case.
const Lam * lam(const Def *dom, Defs codom, Lam::Filter f, const Def *body)
const Lit * lit_idx_mod(nat_t mod, u64 val)
Constructs a Lit of type Idx of size mod.
const Def * single(const Def *)
Singleton type formation.
Seq * mut_seq(bool is_pack, const Def *type)
Pi * mut_pi(const Def *type, bool implicit=false)
const Level * type_pending()
Placeholder type of a mutable whose sort Def::finalize infers from its ops.
const fe::Log & log() const
Log via log().e("...", args) etc.; owned by the Driver.
const Pi * cn(Defs dom, bool implicit=false)
void dump()
Dump to std::cout.
const Lam * fun(const Def *dom, Defs codom, Lam::Filter f, const Def *body)
const Reform * reform(const Def *dom)
void dot(std::ostream &os, DotConfig cfg={}) const
Dumps DOT to os, configured via cfg (see DotConfig).
void write()
Same above but file name defaults to World::name.
const Lam * lam(Defs dom, Defs codom, Lam::Filter f, const Def *body)
Lam * mut_fun(Defs dom, const Def *codom)
const Def * fuse(Seq *seq)
«i: a; «j: b; T»» -> «v: (a, b); T» - the inverse of World::peel, for a nest that World::seq cannot f...
Lam * mut_fun(const Def *dom, const Def *codom)
const Def * annex(Sym sym)
Lookup annex by Sym.
const Axm * axm(NormalizeFn n, u8 curry, u8 trip, const Def *type)
Builds a fresh Axm with descending Axm::sub.
const Pi * fn(const Def *dom, Defs codom, bool implicit=false)
void for_each(bool elide_empty, std::function< void(Def *)>, bool schedule=false)
const Def * call(Args &&... args)
Annex overload with enum tempalte argument Id for annexes w/o subtag.
Hole * mut_hole(const Def *type)
const Axm * axm(const Def *type, plugin_t p, tag_t t, sub_t s)
const Lam * lam(const Pi *pi, Lam::Filter f, const Def *body)
const Def * tuple(Defs ops)
const Lam * fun(Defs dom, Defs codom, Lam::Filter f, const Def *body)
const Def * pack(fe::View< u64 > shape, const Def *body)
Lam * mut_lam(const Def *dom, const Def *codom)
const Def * gid2def(u32 gid)
Lookup Def by gid.
const Def * lmax(Defs levels)
Flags & flags()
Retrieve compile Flags.
const Def * implicit_app(const Def *callee, const Def *arg)
const Def * unwrap(const Def *)
Singleton term elimination.
const Def * implicit_app(const Def *callee, Defs args)
void debug_dump()
Dump in Debug build if World::log::level is fe::Log::Level::Debug.
const Def * extract(const Def *d, u64 i)
const Lam * fun(const Def *dom, const Def *codom, Lam::Filter f, const Def *body)
const Def * inj(const Def *type, const Def *value)
const auto & breakpoints()
const Axm * axm(NormalizeFn n, u8 curry, u8 trip, const Def *type, plugin_t p, tag_t t, sub_t s)
const Def * pack(Defs shape, const Def *body)
const Lit * lit_level_0()
const Def * app(const Def *callee, Defs args)
Lam * mut_fun(Defs dom, Defs codom)
void solve_levels()
Defaults the level Holes of all postponed constraints that are still unknown to 0 and checks them.
const Def * extract(const Def *d, const Def *i)
Pack * mut_pack(const Def *type)
const Proxy * proxy(const Def *type, Defs ops, u32 tag, bool vars=false, bool muts=false)
const Def * arr(fe::View< u64 > shape, const Def *body)
Sym sym(std::string_view)
Lam * mut_lam(Defs dom, const Def *codom)
const Lit * lit_nat_max()
const Def * raw_app(const Def *type, const Def *callee, Defs args)
const Pi * pi(Defs dom, const Def *codom, bool implicit=false)
fe::Restore< CurrLoc > ScopedLoc
const Def * join(Defs ops)
const Def * ext(const Def *type)
Sym append_suffix(Sym name, std::string suffix)
Appends a suffix or an increasing number if the suffix already exists.
const Annexes & annexes() const
static constexpr nat_t Num_Lit_Nats
Def::arity of a Sigma is lit_nat(num_ops()) and Def::num_projs reads it straight back out,...
const Lit * lit_i32(u32 val)
const Lit * lit_i8(u8 val)
const Def * implicit_app(const Def *callee, Enum auto arg)
Lam * mut_lam(Defs dom, Defs codom)
const Lit * lit_idx_1_0()
Sigma * mut_sigma(size_t size)
A mutable Sigma of type level.
const Pi * pi(Defs dom, Defs codom, bool implicit=false)
const Def * var(Def *mut)
const Tuple * tuple()
the unit value of type []
const Def * annex(flags_t flags)
Lookup annex by flags.
const Def * call(Id id, Args &&... args)
Annex overload with enum instance as first argument.
const Nom * nom(flags_t key, const Def *type)
Make type Nominal under key.
const Def * raw_app(const Axm *axm, u8 curry, u8 trip, const Def *type, const Def *callee, const Def *arg)
DbgKey dbg_key() const
World::get_loc, already interned.
const Def * prod(bool term, Defs ops)
const Externals & externals() const
void for_each(bool elide_empty, std::invocable< M * > auto f, bool schedule=false)
const Def * peel(const Seq *seq, const Def *index)
seq with the axes covered by index peeled off - the element itself once index covers all of them.
const Def * prod(bool term)
() or [].
const Def * type_indices(Shape shape)
The type of an index into shape: Idx n, a Sigma of those, or «i: r; Idx (s#i)» for a dynamic rank.
const Lam * con(const Def *dom, Lam::Filter f, const Def *body)
const Lit * lit_idx(std::integral auto val)
const Lit * lit_i64(u64 val)
const Sigma * sigma()
The unit type within Type 0.
const Lit * lit_nat(nat_t a)
const State & state() const
const Def * wrap(const Def *)
Singleton term introduction.
const auto & vars() const
const Def * drop(const Seq *s, nat_t k)
s without its leading k axes - its body once k covers all of them; nullptr if that isn't a type.
const Def * top(const Def *type)
const Def * type_idx(const Def *size)
Lam * mut_con(const Def *dom)
const Lit * lit_level(u64 level)
Defs reduce(const Var *var, const Def *arg)
Yields the new body of [mut->var() -> arg]mut.
const Lit * lit_int(nat_t width, u64 val)
Constructs a Lit of type Idx of size 2^width.
auto freeze() const
Freezes the World until the end of the scope and restores the previous frozen state afterwards:
const Lit * lit_bool(bool val)
void breakpoint(u32 gid)
Trigger breakpoint in your debugger when creating a Def with this gid.
const Def * select(const Def *cond, const Def *t, const Def *f)
Builds (f, t)#cond.
Sigma * mut_sigma(const Def *type, size_t size)
const Def * seq(bool is_pack, fe::View< u64 > shape, const Def *body)
const Pi * fn(const Def *dom, const Def *codom, bool implicit=false)
const Rule * rule(const Reform *type, const Def *lhs, const Def *rhs, const Def *guard)
u32 curr_run() const
Manage run - used to track fixed-point iterations to compute Def::free_vars.
World(World &&other) noexcept
const Pi * pi(const Def *dom, Defs codom, bool implicit=false)
const Def * insert(const Def *d, u64 i, const Def *val)
const Pi * fn(Defs dom, Defs codom, bool implicit=false)
Lam * mut_lam(const Pi *pi)
const Def * annex()
Get Axm from a plugin.
const Level * type_level()
World::get_loc together with its interned DbgKey, so pushing/popping a Loc never re-interns it.
fe::View< const Def * > Defs
GIDMap< const Def *, To > DefMap
fe::Vector< const Def * > DefVec
const Def *(*)(const Def *, const Def *, const Def *) NormalizeFn
Options for Def::dot, World::dot, and Nest::dot.
static constexpr flags_t flags(plugin_t p, tag_t t, sub_t s=0)
Assembles the full flags from its plugin, tag, and sub fields.
static constexpr plugin_t Global_Plugin
static consteval flags_t base()
Compiler switches that must be saved and looked up in later phases of compilation.
friend void swap(State &s1, State &s2) noexcept
ankerl::unordered_dense::set< uint32_t > watchpoints
ankerl::unordered_dense::set< uint32_t > breakpoints
struct mim::World::State::POD pod