30 for (
size_t i =
scopes_.size(); i-- != 1;)
34 if (
auto var = old_def->
has_var()) scope.old_vars = old_def->
world().
vars().insert(scope.old_vars, var);
35 return scope.old2new[old_def] = new_def;
37 return scopes_.front().old2new[old_def] = new_def;
50 return map(old_def, new_tuple);
54 return map(old_tuple, new_def);
59 return map(old_tuple, new_tuple);
63 if (
auto new_def =
lookup(old_def))
return new_def;
66 return new_def->set(old_def->
dbg_key());
70#define CODE_MUT(N) case Node::N: new_def = rewrite_mut_##N(old_mut->as<N>()); break;
71#define CODE_IMM(N) case Node::N: new_def = rewrite_imm_##N(old_def->as<N>()); break;
76 switch (old_def->
node()) {
78 default: std::unreachable();
80 return map(old_def, new_def);
85 switch (old_mut->
node()) {
87 default: std::unreachable();
96 auto new_ops =
DefVec(ops.size());
97 for (
size_t i = 0, e = ops.size(); i != e; ++i)
136 auto new_callee =
rewrite(
d->callee());
137 return world().
app(new_callee, new_arg);
142 auto new_value =
rewrite(
d->value());
143 if (
d->type()->isa<Variant>())
return world().
inj(new_type,
d->index(), new_value);
144 return world().
inj(new_type, new_value);
148 auto new_tuple =
rewrite(
d->tuple());
149 auto new_index =
rewrite(
d->index());
150 auto new_value =
rewrite(
d->value());
151 return world().
insert(new_tuple, new_index, new_value);
156 auto new_filter =
rewrite(
d->filter());
158 return world().
lam(new_type, new_filter, new_body);
163 auto new_codom =
rewrite(
d->codom());
164 return world().
pi(new_dom, new_codom,
d->is_implicit());
170 return world().
proxy(new_type, new_ops,
d->tag(),
d->tracks_vars(),
d->tracks_muts());
177 auto new_guard =
rewrite(
d->guard());
178 return world().
rule(new_type, new_lhs, new_rhs, new_guard);
205 if (&
a->world() != &
world()) {
207 return world().
axm(
a->normalizer(),
a->curry(),
a->trip(), type,
a->plugin(),
a->tag(),
a->sub());
213 auto new_index =
rewrite(ex->index());
214 if (
auto index =
Lit::isa(new_index)) {
215 if (
auto tuple = ex->tuple()->isa<Tuple>())
return rewrite(tuple->op(*index));
216 if (
auto pack = ex->tuple()->isa_imm<Pack>(); pack && pack->arity()->is_closed())
return rewrite(pack->body());
219 auto new_tuple =
rewrite(ex->tuple());
224 auto [
last,
op] = hole->find();
243 if (
auto var = seq->
has_var(); var && l && *l <
world().flags().scalarize_threshold) {
244 auto new_ops = fe::Vector<const Def*, 32>(*l);
245 for (
size_t i = 0, e = *l; i != e; ++i) {
258 map(old_mut, new_mut);
259 if (!old_mut->
is_set())
return new_mut;
261 auto _ =
enter(old_mut);
262 for (
size_t i = 0, e = old_mut->
num_ops(); i != e; ++i)
265 return seal(old_mut, new_mut);
269 assert(new_mut->
num_ops() == new2old.size());
270 map(old_mut, new_mut);
271 if (!old_mut->
is_set())
return new_mut;
273 auto _ =
enter(old_mut);
274 for (
size_t i = 0, e = new2old.size(); i != e; ++i)
277 return seal(old_mut, new_mut);
283 if (
auto new_imm = new_mut->
immutabilize())
return map(old_mut, new_imm);
294 if (
auto new_def =
lookup(old_def))
return new_def;
296 if (
auto old_mut = old_def->
isa_mut())
314 if (
auto new_def = fe::lookup(
old2new(), old_def);
315 new_def && (new_def == old_def || new_def->
isa_mut() || !new_def->needs_zonk()))
322 auto [last, op] = hole->find();
323 def = op ? op : last;
332 auto old_type = mut->
type();
333 auto old_ops =
DefVec(mut->
ops().begin(), mut->
ops().end());
337 for (
size_t i = 0, e = mut->
num_ops(); i != e; ++i)
350 if (
auto new_def =
lookup(def))
return new_def;
351 if (
auto flags =
world().driver().library()->annexes().flags(def))
return map(def,
world().annex(*flags));
A (possibly paramterized) Array.
constexpr Node node() const noexcept
Def * set(size_t i, const Def *)
Successively set from left to right.
T * as_mut() const
Asserts that this is a mutable, casts constness away and performs a static_cast to T.
const Def * zonk() const
If Holes have been filled, reconstruct the program without them.
World & world() const noexcept
Def * set_type(const Def *)
Update type.
bool is_intro() const noexcept
constexpr auto ops() const noexcept
Vars local_vars() const
Vars reachable by following immutable deps().
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
DbgKey dbg_key() const
Cheap handle for other->set(this->dbg_key()).
bool is_immutabilizable()
Muts local_muts() const
Mutables reachable by following immutable deps(); mut->local_muts() is by definition the set { mut }...
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
const Def * immutabilize()
Def * unset()
Unsets all Def::ops; works even, if not set at all or only partially set.
bool needs_zonk() const
Yields true, if Def::local_muts() contain a Hole that is set.
Muts users()
Set of mutables where this mutable is locally referenced.
const Var * has_var()
Only returns not nullptr, if Var of this mutable has ever been created.
bool has_free_vars_in(Vars) const
Same as vars.has_intersection(free_vars()).
constexpr size_t num_ops() const noexcept
This node is a hole in the IR that is inferred by its context later on.
A built-in constant of type Nat -> *.
const Def * rewrite(const Def *) final
Constructs a Join or Variant value.
Creates a new Tuple / Pack by inserting Insert::value at position Insert::index into Insert::tuple.
A union type whose ops are sorted and deduplicated: T ∪ T is T.
static std::optional< T > isa(const Def *def)
Scrutinize Match::scrutinee() and dispatch to Match::arms.
Nominal newtype term introduction.
Nominal newtype formation.
A (possibly paramterized) Tuple.
A dependent function type.
Used as intermediate value during optimizatinos such as Analysis.
fe::Vector< Scope > scopes_
bool has_intersection(const Def *old_def)
Does old_def depend on the old Vars of any scope?
virtual const Def * rewrite_imm_Top(const Top *)
virtual const Def * rewrite_imm_Join(const Join *)
virtual const Def * rewrite_imm_Match(const Match *)
void bind_old(const Var *var)
Adds the old var - if any - to the innermost scope.
virtual const Def * rewrite_imm_Seq(const Seq *seq)
virtual const Def * rewrite_imm_Extract(const Extract *)
virtual const Def * rewrite_imm_LSucc(const LSucc *)
virtual const Def * rewrite_imm_Wrap(const Wrap *)
virtual const Def * rewrite_mut_Sigma(Sigma *)
virtual const Def * rewrite_imm_Arr(const Arr *)
virtual const Def * rewrite_imm_Insert(const Insert *)
virtual const Def * rewrite_imm_Pack(const Pack *)
virtual const Def * rewrite_mut_Seq(Seq *seq)
virtual const Def * rewrite_mut(Def *)
virtual const Def * rewrite_mut_Variant(Variant *)
virtual const Def * rewrite_mut_Hole(Hole *)
virtual const Def * rewrite_imm_Proxy(const Proxy *)
virtual const Def * rewrite_imm_Name(const Name *)
virtual const Def * rewrite_imm_Tuple(const Tuple *)
virtual const Def * rewrite_stub(Def *, Def *)
const Def * map(const Def *old_def, const Def *new_def)
virtual const Def * rewrite_mut_Lam(Lam *)
virtual const Def * rewrite_imm_Struc(const Struc *)
virtual const Def * rewrite_imm_Axm(const Axm *)
virtual const Def * rewrite_imm_Sigma(const Sigma *)
void bind_new(const Var *var)
Adds the new var - if any - to the innermost scope.
virtual const Def * rewrite_imm_Nom(const Nom *)
virtual const Def * rewrite_imm_Type(const Type *)
virtual const Def * rewrite_mut_Arr(Arr *)
virtual const Def * rewrite_imm_Single(const Single *)
virtual const Def * rewrite_imm_Var(const Var *)
virtual const Def * rewrite_imm_Reform(const Reform *)
virtual const Def * rewrite_imm_Pi(const Pi *)
virtual const Def * rewrite_imm_Inj(const Inj *)
const Def * seal(Def *old_mut, Def *new_mut)
The tail of rewrite_stub: immutabilizes new_mut in hindsight, as rewriting may have made it vacuous.
virtual const Def * rewrite_mut_Pack(Pack *)
virtual const Def * rewrite_imm_Bot(const Bot *)
virtual const Def * rewrite_imm(const Def *)
virtual const Def * rewrite_imm_Idx(const Idx *)
virtual const Def * rewrite(const Def *)
virtual const Def * rewrite_imm_App(const App *)
virtual const Def * rewrite_imm_LMax(const LMax *)
auto enter(Def *new_mut)
Updates curr_mut() to new_mut and restores it at the end of the scope.
virtual const Def * rewrite_mut_Rule(Rule *)
virtual const Def * rewrite_imm_Level(const Level *)
void push(Vars old_vars={}, Vars new_vars={})
Def2Def & old2new()
The map of the innermost push() scope.
virtual const Def * rewrite_imm_Nat(const Nat *)
virtual const Def * lookup(const Def *old_def)
Lookup old_def by searching in reverse through the stack of maps.
virtual const Def * rewrite_imm_Lit(const Lit *)
virtual const Def * rewrite_imm_Rule(const Rule *)
virtual const Def * rewrite_mut_Pi(Pi *)
virtual const Def * rewrite_imm_Lam(const Lam *)
virtual const Def * rewrite_imm_Variant(const Variant *)
Base class for Arr and Pack.
bool is_fused() const
Does this span several axes? Also true for a dynamic rank.
Singleton type formation.
Nominal newtype term elimination.
Data constructor for a Sigma.
const Def * rewrite_mut(Def *) final
const Def * rewrite(const Def *) final
A variable introduced by a binder (mutable).
A sum type whose cases are positional: unlike a Join, they are neither sorted nor deduplicated.
The World represents the whole program and manages creation of MimIR nodes (Defs).
const Def * insert(const Def *d, const Def *i, const Def *val)
const Def * variant(Defs ops)
const Lit * lit(const Def *type, u64 val)
const Def * struc(const Def *nom)
Get the structural part of a nominal.
const Type * type(const Def *level)
const Def * lsucc(const Def *op, level_t offset=1)
const Def * sigma(Defs ops)
const Def * app(const Def *callee, const Def *arg)
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 * bot(const Def *type)
const Def * single(const Def *)
Singleton type formation.
const Reform * reform(const Def *dom)
const Lam * lam(const Pi *pi, Lam::Filter f, const Def *body)
const Def * tuple(Defs ops)
const Def * lmax(Defs levels)
const Def * inj(const Def *type, const Def *value)
const Axm * axm(NormalizeFn n, u8 curry, u8 trip, const Def *type, plugin_t p, tag_t t, sub_t s)
const Def * extract(const Def *d, const Def *i)
const Proxy * proxy(const Def *type, Defs ops, u32 tag, bool vars=false, bool muts=false)
const Def * join(Defs ops)
const Def * var(Def *mut)
const Nom * nom(flags_t key, const Def *type)
Make type Nominal under key.
const Def * prod(bool term, Defs ops)
const Def * wrap(const Def *)
Singleton term introduction.
const Def * top(const Def *type)
const Rule * rule(const Reform *type, const Def *lhs, const Def *rhs, const Def *guard)
const Level * type_level()
Singleton term introduction.
const Def * rewire_mut(Def *)
const Def * lookup(const Def *old_def) final
Lookup old_def by searching in reverse through the stack of maps.
const Def * rewrite(const Def *) final
fe::View< const Def * > Defs
fe::Vector< const Def * > DefVec
fe::Patricia< const Var, DefKey >::Set Vars