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 : old_world().roots())
7 visit(def, Lattice::Known);
8 return false; // no fixed-point neccessary
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()) return visit(f, l);
29 join(lam, l);
30 }
31 analyze(def);
32}
33
34void EtaConv::rewrite_annex(flags_t flags, Sym sym, const Def* def) {
35 new_world().annexes().attach(flags, sym, rewrite_no_eta(def));
36}
37
39 auto new_mut = rewrite_no_eta(old_mut)->as_mut();
40 if (old_mut->is_external()) new_mut->externalize();
41}
42
43const Def* EtaConv::rewrite(const Def* old_def) {
44 if (auto lam = old_def->isa<Lam>()) {
45 if (auto f = lam->eta_reduce()) {
46 // η-redex `λx.f x`: reduce unless `f` wants to stay expanded.
47 if (!keep_wrapper(f)) {
48 profile_count("η-reduction");
49 DLOG("eta-reduce: `{}` → `{}`", lam, f);
50 invalidate();
51 return rewrite(f);
52 }
53 // Keep it - but canonicalize as a fresh expansion wrapper (with the `tt` filter EtaExp uses), so a
54 // pre-existing wrapper's stale filter does not leak downstream.
55 return Lam::eta_expand(rewrite_no_eta(f));
56 } else if (eta_expand(lam)) {
57 // bare Lam used in an unknown position more than once or in both positions: η-expand.
58 profile_count("η-expansion");
59 auto eta = Lam::eta_expand(rewrite_no_eta(lam));
60 DLOG("eta-expand: `{}` → `{}`", lam, eta);
61 invalidate();
62 return eta;
63 }
64 }
65
66 return RWPhase::rewrite(old_def);
67}
68
69const Def* EtaConv::rewrite_no_exp(const Def* old_def) {
70 if (auto lam = old_def->isa<Lam>())
71 if (auto f = lam->eta_reduce(); f && !keep_wrapper(f)) {
72 DLOG("eta-reduce: `{}` → `{}`", lam, f);
73 invalidate();
74 return rewrite_no_exp(f);
75 }
76 return RWPhase::rewrite(old_def);
77}
78
79const Def* EtaConv::rewrite_imm_App(const App* app) {
80 auto callee = rewrite_no_exp(app->callee());
81 return new_world().app(callee, rewrite(app->arg()));
82}
83
84const Def* EtaConv::rewrite_imm_Var(const Var* var) { return new_world().var(rewrite_no_eta(var->binder())->as_mut()); }
85
86} // namespace mim
const Def * callee() const
Definition lam.h:276
const Def * arg() const
Definition lam.h:285
Base class for all Defs.
Definition def.h:261
T * as_mut() const
Asserts that this is a mutable, casts constness away and performs a static_cast to T.
Definition def.h:536
Defs deps() const noexcept
Definition def.cpp:514
bool is_external() const noexcept
Definition def.h:500
const Def * rewrite_imm_Var(const Var *) final
Definition eta_conv.cpp:84
const Def * rewrite(const Def *) final
Definition eta_conv.cpp:43
void rewrite_annex(flags_t, Sym, const Def *) final
Definition eta_conv.cpp:34
void rewrite_external(Def *) final
Definition eta_conv.cpp:38
const Def * rewrite_imm_App(const App *) final
Definition eta_conv.cpp:79
bool analyze() final
Runs the optional pre-analysis on RWPhase::old_world(), typically to a fixed point,...
Definition eta_conv.cpp:5
A function.
Definition lam.h:110
static Lam * eta_expand(Filter, const Def *f)
Definition lam.cpp:51
void invalidate(bool todo=true)
Signals that another round of fixed-point iteration is required, either as part of.
Definition phase.h:98
void profile_count(std::string_view key, uint64_t n=1)
Adds n to the custom Profiler counter key of the current run; no-op unless profiling is enabled.
Definition phase.cpp:43
World & new_world()
Create new Defs into this.
Definition phase.h:368
World & old_world()
Get old Defs from here.
Definition phase.h:367
virtual const Def * rewrite(const Def *)
Definition rewrite.cpp:56
A variable introduced by a binder (mutable).
Definition def.h:756
Def * binder() const
The binder of this Var.
Definition def.h:766
const Def * attach(flags_t, Sym, const Def *)
Definition world.cpp:43
const Def * app(const Def *callee, const Def *arg)
Definition world.cpp:205
Annexes & annexes()
Definition world.h:267
const Def * var(Def *mut)
Definition world.cpp:184
#define DLOG(...)
Vaporizes to nothingness in Debug build.
Definition log.h:94
Definition ast.h:14
u64 flags_t
Definition types.h:39
@ Lam
Definition def.h:109