MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
eta_conv.cpp
Go to the documentation of this file.
2
3namespace mim {
4
6 for (auto def : world().roots())
7 visit(def, Lattice::Known);
8 return false; // no fixed-point necessary
9}
10
11void 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
24void 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
37const 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
68const 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
78const 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
83const Def* EtaConv::rewrite_imm_Var(const Var* var) { return world().var(rewrite_no_eta(var->binder())->as_mut()); }
84
85} // namespace mim
const Def * callee() const
Definition lam.h:275
const Def * arg() const
Definition lam.h:284
Base class for all Defs.
Definition def.h:273
Defs deps() const noexcept
Definition def.cpp:468
bool is_ground() const
Immutable that contains neither mutables nor Vars.
Definition def.h:525
const Def * rewrite_imm_Var(const Var *) final
Definition eta_conv.cpp:83
const Def * rewrite(const Def *) final
Definition eta_conv.cpp:37
const Def * rewrite_imm_App(const App *) final
Definition eta_conv.cpp:78
bool analyze() final
Runs the optional pre-analysis on Phase::world, typically to a fixed point, before rewriting begins.
Definition eta_conv.cpp:5
World & world()
Definition phase.h:77
A function.
Definition lam.h:113
static Lam * eta_expand(Filter, const Def *f)
Definition lam.cpp:56
void invalidate(bool todo=true)
Signals that another round of fixed-point iteration is required, either as part of.
Definition phase.h:98
const fe::Log & log() const
Definition phase.h:79
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
virtual const Def * rewrite(const Def *)
Definition rewrite.cpp:55
A variable introduced by a binder (mutable).
Definition def.h:825
Def * binder() const
The binder of this Var.
Definition def.h:835
const Def * app(const Def *callee, const Def *arg)
Definition world.cpp:237
const Def * var(Def *mut)
Definition world.cpp:216
Definition ast.h:16