3#include <absl/container/flat_hash_set.h>
16class Hole :
public Def,
public Setters<Hole> {
30 std::pair<Hole*, const Def*>
find();
50 static const Def*
isa_set(
const Def* def) {
51 if (
auto hole = def->isa<Hole>(); hole && hole->
is_set())
return hole->
op();
56 if (
auto hole = def->
isa_mut<Hole>(); hole && !hole->is_set())
return hole;
61 static const Def*
find(
const Def* def) {
62 if (
auto hole = def->
isa_mut<Hole>()) {
63 auto [last,
op] = hole->find();
64 return op ?
op : last;
99 if (d1 == d2)
return true;
106 if (type == value->
type())
return value;
107 return Checker(type->world()).assignable_(type, value);
114#ifdef MIM_ENABLE_CHECKS
123 const Def* fail() {
return {}; }
126 [[nodiscard]]
const Def* assignable_(
const Def* type,
const Def* value);
128 [[nodiscard]]
bool alpha_(
const Def* d1,
const Def* d2);
130 [[nodiscard]]
bool alpha_impl_(
const Def* d1,
const Def* d2);
132 [[nodiscard]]
bool check(
const Prod*,
const Def*);
134 [[nodiscard]]
bool check(
const Seq*,
const Def*);
135 [[nodiscard]]
bool check1(
const Seq*,
const Def*);
136 [[nodiscard]]
bool check(Seq*,
const Seq*);
137 [[nodiscard]]
bool check(
const UMax*,
const Def*);
139 auto bind(Def* mut,
const Def* d) {
140 if (!mut)
return std::pair(binders_.end(),
true);
141 auto res = binders_.emplace(mut, d);
144 memo_[
Check].clear();
152 std::array<absl::flat_hash_set<std::pair<const Def*, const Def*>>, 2> memo_;
static const Def * is_uniform(Defs defs)
Yields defs.front(), if all defs are Check::alpha-equivalent (Mode::Test) and nullptr otherwise.
static bool alpha(const Def *d1, const Def *d2)
@ Test
In Mode::Test, no type inference is happening and Holes will not be touched.
@ Check
In Mode::Check, type inference is happening and Holes will be resolved, if possible.
static const Def * assignable(const Def *type, const Def *value)
Can value be assigned to sth of type?
bool is_set() const
Yields true if empty or the last op is set.
Def * set(size_t i, const Def *)
Successively set from left to right.
World & world() const noexcept
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
const Def * op(size_t i) const noexcept
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Def * unset()
Unsets all Def::ops; works even, if not set at all or only partially set.
static constexpr size_t Num_Ops
std::pair< Hole *, const Def * > find()
Transitively walks up Holes until the last one while path-compressing everything.
Hole * set(const Def *op)
static const Def * find(const Def *def)
If def is a Hole, find last in chain, otherwise yields def again.
const Def * tuplefy(nat_t)
If unset, explode to Tuple.
static constexpr auto Node
const Def * rebuild_(World &, const Def *, Defs) const final
static Hole * isa_unset(const Def *def)
Hole * stub(const Def *type)
Hole * stub_(World &, const Def *) final
static const Def * isa_set(const Def *def)
Base class for Sigma and Tuple.
Base class for Arr and Pack.
CRTP-based mixin to declare setters for Def::loc & Def::name using a covariant return type.
The World represents the whole program and manages creation of MimIR nodes (Defs).
GIDMap< Def *, To > MutMap