MimIR
0.4-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 :
world
().roots())
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
visit(app->type(), Lattice::Unknown_1);
16
visit(app->callee(), Lattice::Known);
17
visit(app->arg(), Lattice::Unknown_1);
18
}
else
{
19
for
(
auto
d : def->
deps
())
20
visit(d, Lattice::Unknown_1);
21
}
22
}
23
24
void
EtaConv::visit(
const
Def
* def, Lattice l) {
25
if
(
auto
lam = def->isa_mut<Lam>()) {
26
// Wrapper-transparency: a use of `λx.f x` counts as a use of `f` at the same lattice `l`.
27
// Do *not* descend into the wrapper's body (which would classify `f` as Known).
28
if
(
auto
f = lam->eta_reduce()) {
29
++wrapper_uses_[lam];
// a wrapper serving several occurrences must be split into one per occurrence
30
return
visit(f, l);
31
}
32
join(lam, l);
33
}
34
analyze
(def);
35
}
36
37
const
Def
*
EtaConv::rewrite
(
const
Def
* old_def) {
38
if
(old_def->
is_ground
())
return
old_def;
39
40
if
(
auto
lam = old_def->isa<
Lam
>()) {
41
if
(
auto
f = lam->eta_reduce()) {
42
// η-redex `λx.f x`: reduce unless `f` wants to stay expanded.
43
if
(!keep_wrapper(f)) {
44
profile_count
(
"η-reduction"
);
45
log
().d(
"eta-reduce {} → {}"
, lam, f);
46
invalidate
();
47
return
rewrite
(f);
48
}
49
// Keep it - but as a *fresh* expansion wrapper (with the `tt` filter EtaExp uses), so that a
50
// pre-existing wrapper's stale filter does not leak downstream and every occurrence gets its own.
51
// Unless it already is exactly that: re-creating it would churn out a new identity on every run.
52
auto
new_f = rewrite_no_eta(f);
53
if
(new_f == f && is_canonical_wrapper(lam))
return
lam;
54
return
Lam::eta_expand
(new_f);
55
}
else
if
(eta_expand(lam)) {
56
// bare Lam used in an unknown position more than once or in both positions: η-expand.
57
profile_count
(
"η-expansion"
);
58
auto
eta =
Lam::eta_expand
(rewrite_no_eta(lam));
59
log
().d(
"eta-expand {} → {}"
, lam, eta);
60
invalidate
();
61
return
eta;
62
}
63
}
64
65
return
Rewriter::rewrite
(old_def);
66
}
67
68
const
Def
* EtaConv::rewrite_no_exp(
const
Def
* old_def) {
69
if
(
auto
lam = old_def->isa<
Lam
>())
70
if
(
auto
f = lam->eta_reduce(); f && !keep_wrapper(f)) {
71
log
().d(
"eta-reduce {} → {}"
, lam, f);
72
invalidate
();
73
return
rewrite_no_exp(f);
74
}
75
return
Rewriter::rewrite
(old_def);
76
}
77
78
const
Def
*
EtaConv::rewrite_imm_App
(
const
App
* app) {
79
auto
callee = rewrite_no_exp(app->
callee
());
80
return
world
().
app
(callee,
rewrite
(app->
arg
()));
81
}
82
83
const
Def
*
EtaConv::rewrite_imm_Var
(
const
Var
* var) {
return
world
().
var
(rewrite_no_eta(var->
binder
())->as_mut()); }
84
85
}
// namespace mim
mim::App
Definition
lam.h:224
mim::App::callee
const Def * callee() const
Definition
lam.h:275
mim::App::arg
const Def * arg() const
Definition
lam.h:284
mim::Def
Base class for all Defs.
Definition
def.h:273
mim::Def::deps
Defs deps() const noexcept
Definition
def.cpp:468
mim::Def::is_ground
bool is_ground() const
Immutable that contains neither mutables nor Vars.
Definition
def.h:525
mim::EtaConv::rewrite_imm_Var
const Def * rewrite_imm_Var(const Var *) final
Definition
eta_conv.cpp:83
mim::EtaConv::rewrite
const Def * rewrite(const Def *) final
Definition
eta_conv.cpp:37
mim::EtaConv::rewrite_imm_App
const Def * rewrite_imm_App(const App *) final
Definition
eta_conv.cpp:78
mim::EtaConv::analyze
bool analyze() final
Runs the optional pre-analysis on Phase::world, typically to a fixed point, before rewriting begins.
Definition
eta_conv.cpp:5
mim::InplaceRWPhase::world
World & world()
Definition
phase.h:77
mim::Lam
A function.
Definition
lam.h:113
mim::Lam::eta_expand
static Lam * eta_expand(Filter, const Def *f)
Definition
lam.cpp:56
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:98
mim::Phase::log
const fe::Log & log() const
Definition
phase.h:79
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:41
mim::Rewriter::rewrite
virtual const Def * rewrite(const Def *)
Definition
rewrite.cpp:55
mim::Var
A variable introduced by a binder (mutable).
Definition
def.h:825
mim::Var::binder
Def * binder() const
The binder of this Var.
Definition
def.h:835
mim::World::app
const Def * app(const Def *callee, const Def *arg)
Definition
world.cpp:237
mim::World::var
const Def * var(Def *mut)
Definition
world.cpp:216
eta_conv.h
mim
Definition
ast.h:16
src
mim
phase
eta_conv.cpp
Generated by
1.18.0