MimIR
0.5-dev
MimIR is my Intermediate Representation
Toggle main menu visibility
Loading...
Searching...
No Matches
eta_conv.cpp
Go to the documentation of this file.
1
#include "
mim/phase/eta_conv.h
"
2
3
namespace
mim
{
4
5
bool
EtaConv::analyze
() {
6
for
(
auto
def :
old_world
().externals().muts())
7
visit(def, Lattice::Known);
8
return
false
;
// no fixed-point necessary
9
}
10
11
void
EtaConv::analyze
(
const
Def
* def) {
12
if
(
auto
[_, ins] = analyzed_.emplace(def); !ins)
return
;
13
14
if
(
auto
app = def->isa<
App
>()) {
15
// clang-format off
16
visit(app->type(), Lattice::Unknown_1);
17
visit(app->callee(), Lattice::Known);
18
visit(app->arg(), Lattice::Unknown_1);
19
// clang-format on
20
}
else
{
21
for
(
auto
d : def->
deps
())
22
visit(d, Lattice::Unknown_1);
23
}
24
}
25
26
void
EtaConv::visit(
const
Def
* def, Lattice l) {
27
// Wrapper-transparency: a use of `λx.f x` counts as a use of `f` at the same lattice `l`.
28
// Do *not* descend into the wrapper's body (which would classify `f` as Known).
29
if
(
auto
f =
Lam::eta_reduce
(def))
return
visit(f, l);
30
if
(
auto
lam = def->isa_mut<Lam>()) join(lam, l);
31
analyze
(def);
32
}
33
34
const
Def
*
EtaConv::rewrite
(
const
Def
* old_def) {
35
if
(
auto
lam = old_def->isa<
Lam
>()) {
36
if
(
auto
f =
Lam::eta_reduce
(lam)) {
37
// η-redex `λx.f x`: reduce unless `f` wants to stay expanded.
38
if
(!expand(f))
return
rewrite_no_exp(lam);
39
// Keep it - but as a *fresh* expansion wrapper (with a `tt` filter), so that a
40
// pre-existing wrapper's stale filter does not leak downstream and every occurrence gets its own.
41
return
Lam::eta_expand
(rewrite_no_eta(f));
42
}
else
if
(expand(lam)) {
43
// bare Lam used in an unknown position more than once or in both positions: η-expand.
44
profile_count
(
"η-expansion"
);
45
auto
eta =
Lam::eta_expand
(rewrite_no_eta(lam));
46
log
().d(
"eta-expand {} → {}"
, lam, eta);
47
invalidate
();
48
return
eta;
49
}
50
}
51
52
return
RWPhase::rewrite
(old_def);
53
}
54
55
const
Def
* EtaConv::rewrite_no_exp(
const
Def
* old_def) {
56
if
(
auto
f =
Lam::eta_reduce
(old_def); f && !expand(f)) {
57
profile_count
(
"η-reduction"
);
58
log
().d(
"eta-reduce {} → {}"
, old_def, f);
59
invalidate
();
60
return
rewrite_no_eta(f);
61
}
62
return
rewrite_no_eta(old_def);
63
}
64
65
const
Def
*
EtaConv::rewrite_imm_App
(
const
App
* app) {
66
auto
callee = rewrite_no_exp(app->
callee
());
67
return
new_world
().
app
(callee,
rewrite
(app->
arg
()));
68
}
69
70
const
Def
*
EtaConv::rewrite_imm_Var
(
const
Var
* var) {
return
new_world
().
var
(rewrite_no_eta(var->
binder
())->as_mut()); }
71
72
}
// namespace mim
mim::App
Definition
lam.h:215
mim::App::callee
const Def * callee() const
Definition
lam.h:237
mim::App::arg
const Def * arg() const
Definition
lam.h:251
mim::Def
Base class for all Defs.
Definition
def.h:289
mim::Def::deps
Defs deps() const noexcept
Definition
def.cpp:486
mim::EtaConv::rewrite_imm_Var
const Def * rewrite_imm_Var(const Var *) final
Definition
eta_conv.cpp:70
mim::EtaConv::rewrite
const Def * rewrite(const Def *) final
Definition
eta_conv.cpp:34
mim::EtaConv::rewrite_imm_App
const Def * rewrite_imm_App(const App *) final
Definition
eta_conv.cpp:65
mim::EtaConv::analyze
bool analyze() final
Runs the optional pre-analysis on old_world(), typically to a fixed point, before rewriting begins.
Definition
eta_conv.cpp:5
mim::Lam
A function.
Definition
lam.h:91
mim::Lam::eta_expand
static Lam * eta_expand(Filter, const Def *f)
Definition
lam.cpp:84
mim::Lam::eta_reduce
static const Def * eta_reduce(const Def *def)
Fast-forwards def along its chain of η-redexes λ x = f x where x ∉ FV(f).
Definition
lam.cpp:76
mim::Phase::invalidate
void invalidate(bool todo=true)
Signals that another round of fixed-point iteration is required, either as part of.
Definition
phase.h:79
mim::Phase::log
const fe::Log & log() const
Definition
phase.h:60
mim::Phase::profile_count
void profile_count(std::string_view key, uint64_t n=1)
Adds n to the custom fe::Profiler counter key of the current run; no-op unless profiling is enabled.
Definition
phase.cpp:60
mim::RWPhase::new_world
World & new_world()
Create new Defs into this.
Definition
phase.h:379
mim::RWPhase::old_world
World & old_world()
Get old Defs from here.
Definition
phase.h:378
mim::Rewriter::rewrite
virtual const Def * rewrite(const Def *)
Definition
rewrite.cpp:62
mim::Var
A variable introduced by a binder (mutable).
Definition
def.h:857
mim::Var::binder
Def * binder() const
The binder of this Var.
Definition
def.h:867
mim::World::app
const Def * app(const Def *callee, const Def *arg)
Definition
world.cpp:416
mim::World::var
const Def * var(Def *mut)
Definition
world.cpp:392
eta_conv.h
mim
Definition
ast.h:16
src
mim
phase
eta_conv.cpp
Generated by
1.18.0