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 auto old_lam = Lam::isa_rewritable(old_app->callee());
11 if (!old_lam) return RWPhase::rewrite_imm_App(old_app);
12
13 // Skip recursion to avoid infinite inlining if not "aggressive_lam_spec".
14 // This is a hack - but we want to get rid off this stage anyway.
15 Nest nest(old_lam);
16 if (!old_world().flags().aggressive_lam_spec && nest.is_recursive()) return RWPhase::rewrite_imm_App(old_app);
17
18 // Specialize the ordinary new-world copy of old_lam; everything below happens in the new world.
19 auto lam = rewrite(old_lam)->as_mut<Lam>();
20
21 DefVec new_doms, new_vars, new_args;
22 auto skip = lam->ret_var() && lam->is_closed();
23 auto doms = lam->doms();
24
25 for (auto dom : doms.view().rsubspan(skip))
26 if (!dom->isa<Pi>()) new_doms.emplace_back(dom);
27
28 if (skip) new_doms.emplace_back(doms.back());
29 if (new_doms.size() == lam->num_doms()) return RWPhase::rewrite_imm_App(old_app);
30
31 auto& w = new_world();
32 auto new_lam = w.mut_lam(w.cn(new_doms))->set(lam->dbg_key());
33
34 // Project new_lam's var with the explicit arity new_doms.size():
35 // a single remaining sigma dom is flattened by cn(), so new_lam->var(i) would project into that sigma.
36 auto num_new = new_doms.size();
37 auto num_old = old_app->num_args();
38
39 for (size_t arg_i = 0, var_i = 0, n = num_old - skip; arg_i != n; ++arg_i) {
40 auto arg = rewrite(old_app->arg(num_old, arg_i));
41 if (doms[arg_i]->isa<Pi>()) {
42 new_vars.emplace_back(arg);
43 } else {
44 new_vars.emplace_back(new_lam->var(num_new, var_i++));
45 new_args.emplace_back(arg);
46 }
47 }
48
49 if (skip) {
50 new_vars.emplace_back(new_lam->var(num_new, num_new - 1));
51 new_args.emplace_back(rewrite(old_app->arg(num_old, num_old - 1)));
52 }
53
54 new_lam->set(lam->reduce(w.tuple(new_vars)));
55 log().d("specialize {} → {}: {} → {}", lam, new_lam, lam->dom(), new_lam->dom());
56
57 return w.app(new_lam, new_args);
58}
59
60} // namespace mim
nat_t num_args() const noexcept
Definition lam.h:252
const Def * callee() const
Definition lam.h:237
const Def * arg() const
Definition lam.h:251
Base class for all Defs.
Definition def.h:289
T * as_mut() const
Asserts that this is a mutable, casts constness away and performs a static_cast to T.
Definition def.h:597
const Def * rewrite_imm_App(const App *) final
Definition lam_spec.cpp:9
A function.
Definition lam.h:91
static Lam * isa_rewritable(const Def *def)
Yields def as a mutable Lam, if it is_rewritable() and nullptr otherwise.
Definition lam.h:193
Builds a nesting tree for all mutables/binders.
Definition nest.h:25
bool is_recursive() const
Definition nest.h:198
const fe::Log & log() const
Definition phase.h:60
A dependent function type.
Definition lam.h:14
World & new_world()
Create new Defs into this.
Definition phase.h:379
World & old_world()
Get old Defs from here.
Definition phase.h:378
const Def * rewrite_imm_App(const App *) override
Definition phase.cpp:223
virtual const Def * rewrite(const Def *)
Definition rewrite.cpp:62
Definition ast.h:16
fe::Vector< const Def * > DefVec
Definition def.h:98