MimIR 0.1
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
clos_conv_prep.cpp
Go to the documentation of this file.
2
3#include <mim/nest.h>
4
5#include <mim/pass/eta_exp.h>
6
8
9namespace mim::plug::clos {
10
11namespace {
12// FIXME: these guys do not work if another pass rewrites curr_mut()'s body
13bool isa_cnt(const App* body, Ref def, size_t i) {
14 return Pi::isa_returning(body->callee_type()) && body->arg() == def && i == def->num_ops() - 1;
15}
16
17Ref isa_br(const App* body, Ref def) {
18 if (!Pi::isa_cn(body->callee_type())) return nullptr;
19 auto proj = body->callee()->isa<Extract>();
20 return (proj && proj->tuple() == def && proj->tuple()->isa<Tuple>()) ? proj->tuple() : nullptr;
21}
22
23bool isa_callee_br(const App* body, Ref def, size_t i) {
24 if (!Pi::isa_cn(body->callee_type())) return false;
25 return isa_callee(def, i) || isa_br(body, def);
26}
27
28Lam* isa_retvar(Ref def) {
29 if (auto [var, lam] = ca_isa_var<Lam>(def); var && lam && var == lam->ret_var()) return lam;
30 return nullptr;
31}
32
33} // namespace
34
36 if (eta_exp_) lam = eta_exp_->new2old(lam);
37 return lam2fscope_[lam];
38}
39
42 lam2fscope_[curr_mut()] = curr_mut();
43 world().DLOG("scope {} -> {}", curr_mut(), curr_mut());
44 auto nest = Nest(curr_mut());
45 for (auto mut : nest.muts()) {
46 if (auto bb_lam = Lam::isa_mut_basicblock(mut)) {
47 world().DLOG("scope {} -> {}", bb_lam, curr_mut());
48 lam2fscope_[bb_lam] = curr_mut();
49 }
50 }
51 }
52
53 auto body = curr_mut()->body()->isa<App>();
54 // Skip if the mutable is already wrapped or the body is undefined/no continuation.
55 ignore_ = !(body && Pi::isa_cn(body->callee_type())) || wrapper_.contains(curr_mut());
56}
57
58const App* ClosConvPrep::rewrite_arg(const App* app) {
59 auto& w = world();
60 auto arg = app->arg();
61
62 if (arg->isa<Var>()) return app;
63
64 for (auto i = 0u; i < arg->num_projs(); i++) {
65 auto op = arg->proj(i);
66
67 auto refine = [&](Ref new_op) {
68 Ref args;
69 if (arg == op)
70 args = new_op;
71 else
72 args = arg->refine(i, new_op);
73 return app->refine(1, args)->as<App>();
74 };
75
76 if (auto lam = isa_retvar(op); lam && from_outer_scope(lam)) {
77 w.DLOG("found return var from enclosing scope: {}", op);
78 return refine(eta_wrap(op, attr::freeBB)->set("free_ret"));
79 }
80 if (auto bb_lam = Lam::isa_mut_basicblock(op); bb_lam && from_outer_scope(bb_lam)) {
81 w.DLOG("found BB from enclosing scope {}", op);
82 return refine(w.call(attr::freeBB, op));
83 }
84 if (isa_cnt(app, arg, i)) {
85 if (match<attr>(attr::returning, op) || isa_retvar(op)) {
86 return app;
87 } else if (auto contlam = op->isa_mut<Lam>()) {
88 return refine(w.call(attr::returning, contlam));
89 } else {
90 auto wrapper = eta_wrap(op, attr::returning)->set("eta_cont");
91 w.DLOG("eta expanded return cont: {} -> {}", op, wrapper);
92 return refine(wrapper);
93 }
94 }
95
96 if (!isa_callee_br(app, arg, i)) {
97 if (auto bb_lam = Lam::isa_mut_basicblock(op)) {
98 w.DLOG("found firstclass use of BB: {}", bb_lam);
99 return refine(w.call(attr::fstclassBB, bb_lam));
100 }
101 // TODO: If EtaRed eta-reduces branches, we have to wrap them again!
102 if (isa_retvar(op)) {
103 w.DLOG("found firstclass use of return var: {}", op);
104 return refine(eta_wrap(op, attr::fstclassBB)->set("fstclass_ret"));
105 }
106 }
107 }
108
109 return app;
110}
111
113 auto& w = world();
114 if (Pi::isa_cn(app->callee_type())) {
115 if (auto br = app->callee()->isa<Extract>()) {
116 auto branches = br->tuple();
117 // Eta-Expand branches
118 if (branches->isa<Tuple>() && branches->type()->isa<Arr>()) {
119 for (size_t i = 0, e = branches->num_ops(); i != e; ++i) {
120 if (!branches->op(i)->isa_mut<Lam>()) {
121 auto wrapper = eta_wrap(branches->op(i), attr::bottom)->set("eta_br");
122 w.DLOG("eta wrap branch: {} -> {}", branches->op(i), wrapper);
123 branches = branches->refine(i, wrapper);
124 }
125 }
126 return app->refine(0, app->callee()->refine(0, branches))->as<App>();
127 }
128 }
129 }
130
131 return app;
132}
133
135 if (ignore_ || match<attr>(def)) return def;
136
137 if (auto app = def->isa<App>()) {
138 app = rewrite_arg(app);
139 app = rewrite_callee(app);
140 return app;
141 }
142
143 return def;
144}
145
146} // namespace mim::plug::clos
Ref arg() const
Definition lam.h:224
const Pi * callee_type() const
Definition lam.h:217
Ref callee() const
Definition lam.h:215
A (possibly paramterized) Array.
Definition tuple.h:67
Def * set(size_t i, Ref)
Successively set from left to right.
Definition def.cpp:243
T * isa_mut() const
If this is *mut*able, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:432
Ref type() const noexcept
Yields the raw type of this Def, i.e. maybe nullptr.
Definition def.h:241
Ref proj(nat_t a, nat_t i) const
Similar to World::extract while assuming an arity of a, but also works on Sigmas and Arrays.
Definition def.cpp:487
Ref refine(size_t i, Ref new_op) const
Definition def.cpp:228
void new2old(Lam *new_lam, Lam *old_lam)
Definition eta_exp.h:22
Extracts from a Sigma or Array-typed Extract::tuple the element at position Extract::index.
Definition tuple.h:154
A function.
Definition lam.h:105
static Lam * isa_mut_basicblock(Ref d)
Only for mutables.
Definition lam.h:140
Ref body() const
Definition lam.h:118
Builds a nesting tree of all immutables‍/binders.
Definition nest.h:11
World & world()
Definition pass.h:296
static const Pi * isa_returning(Ref d)
Is this a continuation (Pi::isa_cn) which has a Pi::ret_pi?
Definition lam.h:46
static const Pi * isa_cn(Ref d)
Is this a continuation - i.e. is the Pi::codom mim::Bottom?
Definition lam.h:44
Helper class to retrieve Infer::arg if present.
Definition def.h:86
Data constructor for a Sigma.
Definition tuple.h:50
const App * rewrite_callee(const App *app)
void enter() override
Invoked just before Pass::rewriteing PassMan::curr_mut's body.
const App * rewrite_arg(const App *app)
Ref eta_wrap(Ref def, attr a)
@ Extract
Definition def.h:40
@ Lam
Definition def.h:40
The clos Plugin
Definition clos.h:7
std::tuple< const Extract *, N * > ca_isa_var(Ref def)
Checks is def is the variable of a mut of type N.
Definition clos.h:79
const App * isa_callee(Ref def, size_t i)
Definition lam.h:245
auto match(Ref def)
Definition axiom.h:112