MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
lam_spec.cpp
Go to the documentation of this file.
2
3#include "mim/nest.h"
4
5// TODO This is supposed to recreate what lower2cff did, but we should really consider another strategy and nuke this.
6
7namespace mim {
8
9const Def* LamSpec::rewrite_imm_App(const App* old_app) {
10 if (is_bootstrapping()) return RWPhase::rewrite_imm_App(old_app);
11 if (auto i = old2new_.find(old_app); i != old2new_.end()) return i->second;
12
13 auto old_lam = old_app->callee()->isa_mut<Lam>();
14 if (!isa_optimizable(old_lam)) return RWPhase::rewrite_imm_App(old_app);
15
16 // Skip recursion to avoid infinite inlining if not "aggressive_lam_spec".
17 // This is a hack - but we want to get rid off this stage anyway.
18 Nest nest(old_lam);
19 if (!old_world().flags().aggressive_lam_spec && nest.is_recursive()) return RWPhase::rewrite_imm_App(old_app);
20
21 // Specialize the ordinary new-world copy of old_lam; everything below happens in the new world.
22 auto lam = rewrite(old_lam)->as_mut<Lam>();
23
24 DefVec new_doms, new_vars, new_args;
25 auto skip = lam->ret_var() && lam->is_closed();
26 auto doms = lam->doms();
27
28 for (auto dom : doms.view().rsubspan(skip))
29 if (!dom->isa<Pi>()) new_doms.emplace_back(dom);
30
31 if (skip) new_doms.emplace_back(doms.back());
32 if (new_doms.size() == lam->num_doms()) return RWPhase::rewrite_imm_App(old_app);
33
34 auto& w = new_world();
35 auto new_lam = lam->stub(w.cn(new_doms));
36
37 // Project new_lam's var with the explicit arity new_doms.size():
38 // a single remaining sigma dom is flattened by cn(), so new_lam->var(i) would project into that sigma.
39 auto num_new = new_doms.size();
40 auto num_old = old_app->num_args();
41
42 for (size_t arg_i = 0, var_i = 0, n = num_old - skip; arg_i != n; ++arg_i) {
43 auto arg = rewrite(old_app->arg(num_old, arg_i));
44 if (lam->dom(arg_i)->isa<Pi>()) {
45 new_vars.emplace_back(arg);
46 } else {
47 new_vars.emplace_back(new_lam->var(num_new, var_i++));
48 new_args.emplace_back(arg);
49 }
50 }
51
52 if (skip) {
53 new_vars.emplace_back(new_lam->var(num_new, num_new - 1));
54 new_args.emplace_back(rewrite(old_app->arg(num_old, num_old - 1)));
55 }
56
57 new_lam->set(lam->reduce(w.tuple(new_vars)));
58 DLOG("{} -> {}: {} -> {})", lam, new_lam, lam->dom(), new_lam->dom());
59
60 return old2new_[old_app] = w.app(new_lam, new_args);
61}
62
63} // 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
Def * set(size_t i, const Def *)
Successively set from left to right.
Definition def.cpp:276
T * as_mut() const
Asserts that this is a mutable, casts constness away and performs a static_cast to T.
Definition def.h:536
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:527
const Def * rewrite_imm_App(const App *) final
Definition lam_spec.cpp:9
A function.
Definition lam.h:110
Builds a nesting tree for all mutables/binders.
Definition nest.h:30
bool is_recursive() const
Definition nest.h:226
A dependent function type.
Definition lam.h:14
World & new_world()
Create new Defs into this.
Definition phase.h:368
bool is_bootstrapping() const
Returns whether we are currently bootstrapping (rewriting annexes).
Definition phase.h:356
World & old_world()
Get old Defs from here.
Definition phase.h:367
virtual const Def * rewrite(const Def *)
Definition rewrite.cpp:56
#define DLOG(...)
Vaporizes to nothingness in Debug build.
Definition log.h:94
Definition ast.h:14
Vector< const Def * > DefVec
Definition def.h:79
Lam * isa_optimizable(Lam *lam)
These are Lams that are.
Definition lam.h:352