MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
conv.cpp
Go to the documentation of this file.
2
3#include "mim/plug/cps/cps.h"
4
5namespace mim::plug::cps {
6
7/// A term-level, direct-style function that we can and want to convert.
8/// Type-level and higher-order functions stay in direct style.
9static bool convertible(Lam* lam) {
10 if (!lam->is_set() || lam->is_external() || lam->is_annex() || Lam::isa_cn(lam)) return false;
11 auto codom = lam->codom();
12 return !codom->isa<Type>() && !codom->isa<Pi>();
13}
14
15const Def* Conv::rewrite_mut_Lam(Lam* old_lam) {
16 if (convertible(old_lam)) return convert(old_lam);
17
18 auto new_lam = new_world().mut_lam(rewrite(old_lam->type())->as<Pi>());
19 map(old_lam, new_lam);
20 if (!old_lam->is_set()) return new_lam;
21
22 auto scope = Scope(*this, Lam::isa_cn(old_lam));
23 auto new_filter = rewrite(old_lam->filter());
24 auto new_body = wire(scope.base(), rewrite(old_lam->body()));
25 return new_lam->set(new_filter, new_body);
26}
27
28const Def* Conv::convert(Lam* old_lam) {
29 auto& w = new_world();
30 auto old_pi = old_lam->type();
31 auto new_dom = rewrite(old_pi->dom());
32
33 Lam* new_lam;
34 if (auto old_var = old_pi->has_var()) {
35 // dependent codom: bind it against a fresh mutable Sigma [a: A, Cn B[old_var → a]]
36 auto sigma = w.mut_sigma(2);
37 sigma->set(0, new_dom); // the codom may project sigma->var(2, 0), which needs its type
38 sigma->var();
39 push({}, Vars(sigma->has_var()));
40 map(old_var, sigma->var(2, 0));
41 auto new_codom = rewrite(old_pi->codom());
42 pop();
43 sigma->set(1, w.cn(new_codom));
44 new_lam = w.mut_con(sigma);
45 } else {
46 new_lam = w.mut_fun(new_dom, rewrite(old_pi->codom()));
47 }
48 new_lam->set(old_lam->dbg_key())->debug_suffix("_cps");
49
50 auto [param, ret] = new_lam->vars<2>();
51 map(old_lam->var(), param);
52 auto wrapper = map(old_lam, op_cps2ds_dep(new_lam));
53
54 log().d("convert {}: {} → {}: {}", old_lam, old_pi, new_lam, new_lam->type());
55
56 auto scope = Scope(*this, true);
57 auto new_filter = rewrite(old_lam->filter());
58 auto tail = w.app(ret, rewrite(old_lam->body()));
59 new_lam->set(new_filter, wire(scope.base(), tail));
60
61 return wrapper;
62}
63
64const Def* Conv::rewrite_imm_App(const App* old_app) {
65 auto new_arg = rewrite(old_app->arg());
66 auto new_callee = rewrite(old_app->callee());
67
68 if (liftable_)
69 if (auto wrapped = Axm::isa<cps2ds_dep>(new_callee)) return lift(wrapped->arg(), new_arg, old_app);
70
71 return new_world().app(new_callee, new_arg);
72}
73
74const Def* Conv::lift(const Def* k, const Def* new_arg, const App* old_app) {
75 auto& w = new_world();
76 auto cont = w.mut_con(rewrite(old_app->type()))->set_filter(false);
77 auto res = cont->var();
78 cont->set(w.append_suffix(k->sym(), "_cont"));
79 bind_new(cont->has_var());
80 pending_.emplace_back(k, new_arg, cont);
81
82 log().d("lift {} → {} ({}, {})", old_app, k, new_arg, cont);
83
84 return res;
85}
86
87const Def* Conv::wire(size_t base, const Def* body) {
88 auto& w = new_world();
89 while (pending_.size() > base) {
90 auto [callee, arg, cont] = pending_.back();
91 pending_.pop_back();
92 cont->set_body(body);
93 body = w.app(callee, Defs{arg, cont});
94 }
95 return body;
96}
97
98} // namespace mim::plug::cps
const Def * callee() const
Definition lam.h:237
const Def * arg() const
Definition lam.h:251
static auto isa(const Def *def)
Definition axm.h:112
Base class for all Defs.
Definition def.h:289
bool is_set() const
Definition def.h:396
DbgKey dbg_key() const
Cheap handle for other->set(this->dbg_key()).
Definition def.h:631
const Def * var(nat_t a, nat_t i) noexcept
Definition def.h:492
auto vars(Projector auto f) noexcept
Definition def.h:492
const Def * debug_suffix(std::string) const
Definition def.cpp:507
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Definition def.h:1119
bool is_external() const noexcept
Definition def.h:569
Sym sym() const
Definition def.h:633
bool is_annex() const noexcept
Definition def.h:573
A function.
Definition lam.h:91
const Def * filter() const
Definition lam.h:103
static const Lam * isa_cn(const Def *d)
Definition lam.h:125
Lam * set(Filter filter, const Def *body)
Definition lam.cpp:34
const Pi * type() const
Definition lam.h:112
const Def * body() const
Definition lam.h:104
const Def * codom() const
Definition lam.h:114
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
void pop()
Definition rewrite.h:41
const Def * map(const Def *old_def, const Def *new_def)
Definition rewrite.cpp:29
void bind_new(const Var *var)
Adds the new var - if any - to the innermost scope.
Definition rewrite.cpp:44
virtual const Def * rewrite(const Def *)
Definition rewrite.cpp:62
void push(Vars old_vars={}, Vars new_vars={})
Definition rewrite.h:40
const Def * app(const Def *callee, const Def *arg)
Definition world.cpp:416
Lam * mut_lam(const Pi *pi)
Definition world.h:415
const Def * rewrite_mut_Lam(Lam *) final
Definition conv.cpp:15
const Def * rewrite_imm_App(const App *) final
Definition conv.cpp:64
The CPS Plugin
Definition cps.h:8
const Def * op_cps2ds_dep(const Def *k)
Definition cps.h:16
static bool convertible(Lam *lam)
A term-level, direct-style function that we can and want to convert.
Definition conv.cpp:9
fe::View< const Def * > Defs
Definition def.h:96
fe::Patricia< const Var, DefKey >::Set Vars
Definition def.h:115