MimIR
0.4-dev
MimIR is my Intermediate Representation
Toggle main menu visibility
Loading...
Searching...
No Matches
conv.h
Go to the documentation of this file.
1
#pragma once
2
3
#include <
mim/def.h
>
4
#include <
mim/phase.h
>
5
6
namespace
mim::plug::cps
{
7
8
/// Full CPS conversion in one recursive rewrite.
9
///
10
/// Each term-level, direct-style function
11
/// ```
12
/// f: [a: A] → B
13
/// ```
14
/// becomes
15
/// ```
16
/// f_cps: Cn [a: A, Cn B]
17
/// ```
18
/// and every use of `f` is replaced by `cps.cps2ds_dep (A, λ a: B) f_cps` to remain type-correct.
19
///
20
/// Call sites are lifted on the fly:
21
/// When the recursive rewrite encounters `App (cps.cps2ds_dep (T, U) k) arg` inside a continuation,
22
/// it allocates a fresh continuation `cont` receiving the result, records the pending call `k (arg, cont)`,
23
/// and uses `cont`'s variable as the value of the App.
24
/// Once the enclosing Lam is done, the pending calls are wired up in encounter order - which respects
25
/// data dependencies, because operands are always rewritten before their users:
26
/// ```
27
/// lam = k₀ (arg₀, cont₀)
28
/// cont₀ = k₁ (arg₁, cont₁)
29
/// ...
30
/// contₙ = rewritten body of lam
31
/// ```
32
/// A lifted call simply lives in the Lam whose body rewriting first reaches it.
33
/// Rewrites whose result mentions such a continuation variable are scoped to that Lam (see Conv::map) and
34
/// re-derived - and thus re-lifted - in sibling scopes.
35
class
Conv
:
public
RWPhase
{
36
public
:
37
Conv
(
World
&
world
,
flags_t
annex
)
38
:
RWPhase
(
world
,
annex
) {}
39
40
private
:
41
/// A lifted call `callee (arg, cont)` waiting to be wired into the body of the enclosing Lam.
42
struct
Pending {
43
const
Def
* callee;
///< CPS callee `k: Cn [T, Cn U]`.
44
const
Def
* arg;
///< Rewritten argument - still without the continuation.
45
Lam
* cont;
///< Fresh continuation receiving the result of the call.
46
};
47
48
/// RAII guard for rewriting the body of one mutable Lam:
49
/// fences pending_, pushes a map scope for contaminated rewrites, and tracks whether lifting is legal here.
50
class
Scope {
51
public
:
52
Scope(
Conv
&
conv
,
bool
liftable)
53
: conv_(
conv
)
54
, base_(
conv
.pending_.size())
55
, old_liftable_(
conv
.liftable_) {
56
conv_.
push
();
57
conv_.liftable_ = liftable;
58
}
59
~Scope() {
60
assert(conv_.pending_.size() == base_ &&
"pending calls must have been wire()d"
);
61
conv_.
pop
();
62
conv_.liftable_ = old_liftable_;
63
}
64
65
size_t
base()
const
{
return
base_; }
66
67
private
:
68
Conv
& conv_;
69
size_t
base_;
70
bool
old_liftable_;
71
};
72
73
const
Def*
rewrite_mut_Lam
(Lam*)
final
;
74
const
Def*
rewrite_imm_App
(
const
App*)
final
;
75
76
/// Routes rewrites that mention scoped (continuation/binder) variables into the current Lam's map scope;
77
/// everything else goes into the root map and is shared globally.
78
using
Rewriter::map
;
79
const
Def*
map
(
const
Def*,
const
Def*)
final
;
80
81
/// Converts direct-style `f: [a: A] → B` to `f_cps: Cn [a: A, Cn B]` and returns the `cps2ds_dep`-wrapped f_cps.
82
const
Def* convert(Lam*);
83
/// Turns the call `k (arg, cont)` into a Pending entry and returns `cont`'s variable as call result.
84
const
Def* lift(
const
Def* k,
const
Def* arg,
const
App* old_app);
85
/// Wires all Pending calls above @p base around @p body and returns the new body.
86
const
Def* wire(
size_t
base,
const
Def* body);
87
88
fe::Vector<Pending> pending_;
89
Vars
scoped_;
90
bool
liftable_ =
false
;
91
};
92
93
}
// namespace mim::plug::cps
mim::Def
Base class for all Defs.
Definition
def.h:273
mim::Lam
A function.
Definition
lam.h:113
mim::Phase::annex
flags_t annex() const
Definition
phase.h:81
mim::RWPhase::RWPhase
RWPhase(World &world, std::string name, Analysis *analysis=nullptr)
Definition
phase.h:431
mim::RWPhase::world
World & world()=delete
Hides both and forbids direct access.
mim::Rewriter::push
virtual void push()
Definition
rewrite.h:40
mim::Rewriter::map
virtual const Def * map(const Def *old_def, const Def *new_def)
Definition
rewrite.h:47
mim::Rewriter::pop
virtual void pop()
Definition
rewrite.h:41
mim::World
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition
world.h:40
mim::plug::cps::Conv::rewrite_mut_Lam
const Def * rewrite_mut_Lam(Lam *) final
Definition
conv.cpp:20
mim::plug::cps::Conv::Conv
Conv(World &world, flags_t annex)
Definition
conv.h:37
mim::plug::cps::Conv::rewrite_imm_App
const Def * rewrite_imm_App(const App *) final
Definition
conv.cpp:70
mim::plug::cps::Conv::map
const Def * map(const Def *, const Def *) final
Definition
conv.cpp:15
def.h
mim::plug::cps
The CPS Plugin
Definition
cps.h:8
mim::plug::cps::conv
conv
Definition
autogen.h:28
mim::flags_t
u64 flags_t
Definition
types.h:39
mim::Vars
fe::Patricia< const Var, DefKey >::Set Vars
Definition
def.h:112
phase.h
include
mim
plug
cps
phase
conv.h
Generated by
1.18.0