Thorin 1.9.0
The Higher ORder INtermediate representation
Loading...
Searching...
No Matches
clos.cpp
Go to the documentation of this file.
2
3#include <thorin/config.h>
4
7#include <thorin/pass/pass.h>
10
17
18using namespace thorin;
19using namespace thorin::plug;
20
22 return {"clos", [](Normalizers& normalizers) { clos::register_normalizers(normalizers); },
23 [](Passes& passes) {
24 register_pass<clos::clos_conv_prep_pass, clos::ClosConvPrep>(passes, nullptr);
25 register_pass<clos::branch_clos_pass, clos::BranchClosElim>(passes);
26 register_pass<clos::lower_typed_clos_prep_pass, clos::LowerTypedClosPrep>(passes);
27 register_pass<clos::clos2sjlj_pass, clos::Clos2SJLJ>(passes);
28 register_phase<clos::clos_conv_phase, clos::ClosConv>(passes);
29 register_phase<clos::lower_typed_clos_phase, clos::LowerTypedClos>(passes);
30 // TODO:; remove after ho_codegen merge
32 auto bb = app->as<App>()->arg();
33 auto bb_only = bb->as<Lit>()->get<u64>();
34 builder.add_pass<EtaRed>(app, bb_only);
35 };
36 },
37 nullptr};
38}
39
40namespace thorin::plug::clos {
41
42/*
43 * ClosLit
44 */
45
47 assert(def_);
48 return std::get<2_u64>(clos_unpack(def_));
49}
50
52 assert(def_);
53 return std::get<1_u64>(clos_unpack(def_));
54}
55
57 auto f = fnc();
58 if (auto a = match<attr>(f)) f = a->arg();
59 return f->isa_mut<Lam>();
60}
61
63
64ClosLit isa_clos_lit(Ref def, bool lambda_or_branch) {
65 auto tpl = def->isa<Tuple>();
66 if (tpl && isa_clos_type(def->type())) {
67 auto a = attr::bot;
68 auto fnc = std::get<1_u64>(clos_unpack(tpl));
69 if (auto fa = match<attr>(fnc)) {
70 fnc = fa->arg();
71 a = fa.id();
72 }
73 if (!lambda_or_branch || fnc->isa<Lam>()) return ClosLit(tpl, a);
74 }
75 return ClosLit(nullptr, attr::bot);
76}
77
78Ref clos_pack(Ref env, Ref lam, Ref ct) {
79 assert(env && lam);
80 assert(!ct || isa_clos_type(ct));
81 auto& w = env->world();
82 auto pi = lam->type()->as<Pi>();
83 assert(env->type() == pi->dom(Clos_Env_Param));
84 ct = (ct) ? ct : clos_type(w.cn(clos_remove_env(pi->dom())));
85 return w.tuple(ct, {env->type(), lam, env})->isa<Tuple>();
86}
87
88std::tuple<Ref, Ref, Ref> clos_unpack(Ref c) {
89 assert(c && isa_clos_type(c->type()));
90 // auto& w = c->world();
91 // auto env_type = c->proj(0_u64);
92 // // auto pi = clos_type_to_pi(c->type(), env_type);
93 // auto fn = w.extract(c, w.lit_idx(3, 1));
94 // auto env = w.extract(c, w.lit_idx(3, 2));
95 // return {env_type, fn, env};
96 auto [ty, pi, env] = c->projs<3>();
97 return {ty, pi, env};
98}
99
100Ref clos_apply(Ref closure, Ref args) {
101 auto& w = closure->world();
102 auto [_, fn, env] = clos_unpack(closure);
103 auto pi = fn->type()->as<Pi>();
104 return w.app(fn, DefVec(pi->num_doms(), [&](auto i) { return clos_insert_env(i, env, args); }));
105}
106
107/*
108 * closure types
109 */
110
112 auto& w = def->world();
113 auto sig = def->isa_mut<Sigma>();
114 if (!sig || sig->num_ops() < 3 || sig->op(0_u64) != w.type()) return nullptr;
115 auto var = sig->var(0_u64);
116 if (sig->op(2_u64) != var) return nullptr;
117 auto pi = sig->op(1_u64)->isa<Pi>();
118 return (pi && Pi::isa_cn(pi) && pi->num_ops() > 1_u64 && pi->dom(Clos_Env_Param) == var) ? sig : nullptr;
119}
120
121Sigma* clos_type(const Pi* pi) { return ctype(pi->world(), pi->doms(), nullptr)->as_mut<Sigma>(); }
122
123const Pi* clos_type_to_pi(Ref ct, Ref new_env_type) {
124 assert(isa_clos_type(ct));
125 auto& w = ct->world();
126 auto pi = ct->op(1_u64)->as<Pi>();
127 auto new_dom = new_env_type ? clos_sub_env(pi->dom(), new_env_type) : clos_remove_env(pi->dom());
128 return w.cn(new_dom);
129}
130
131/*
132 * closure environments
133 */
134
135Ref clos_insert_env(size_t i, Ref env, std::function<Ref(size_t)> f) {
136 return (i == Clos_Env_Param) ? env : f(shift_env(i));
137}
138
139Ref clos_remove_env(size_t i, std::function<Ref(size_t)> f) { return f(skip_env(i)); }
140
141Ref ctype(World& w, Defs doms, Ref env_type) {
142 if (!env_type) {
143 auto sigma = w.mut_sigma(w.type(), 3_u64)->set("Clos");
144 sigma->set(0_u64, w.type());
145 sigma->set(1_u64, ctype(w, doms, sigma->var(0_u64)));
146 sigma->set(2_u64, sigma->var(0_u64));
147 return sigma;
148 }
149 return w.cn(
150 DefVec(doms.size() + 1, [&](auto i) { return clos_insert_env(i, env_type, [&](auto j) { return doms[j]; }); }));
151}
152
153} // namespace thorin::plug::clos
Ref var(nat_t a, nat_t i)
Definition def.h:403
const Def * op(size_t i) const
Definition def.h:269
size_t num_ops() const
Definition def.h:270
const Def * type() const
Yields the raw type of this Def, i.e. maybe nullptr.
Definition def.h:248
T * isa_mut() const
If this is *mut*able, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:449
T * as_mut() const
Asserts that this is a mutable, casts constness away and performs a static_cast to T.
Definition def.h:457
World & world() const
Definition def.cpp:421
Performs η-reduction.
Definition eta_red.h:9
A function.
Definition lam.h:97
A dependent function type.
Definition lam.h:11
static const Pi * isa_cn(Ref d)
Is this a continuation - i.e. is the Pi::codom thorin::Bottom?
Definition lam.h:50
Helper class to retrieve Infer::arg if present.
Definition def.h:87
A dependent tuple type.
Definition tuple.h:9
This is a thin wrapper for std::span<T, N> with the following additional features:
Definition span.h:28
Data constructor for a Sigma.
Definition tuple.h:39
The World represents the whole program and manages creation of Thorin nodes (Defs).
Definition world.h:35
Wrapper around a Def that can be used to match closures (see isa_clos_lit).
Definition clos.h:13
#define THORIN_EXPORT
Definition config.h:16
The clos Plugin
Definition clos.h:7
Ref clos_insert_env(size_t i, Ref env, std::function< Ref(size_t)> f)
Definition clos.cpp:135
Ref clos_pack(Ref env, Ref fn, Ref ct=nullptr)
Pack a typed closure. This assumes that fn expects the environment as its Clos_Env_Paramth argument.
Definition clos.cpp:78
void register_normalizers(Normalizers &normalizers)
static constexpr size_t Clos_Env_Param
Describes where the environment is placed in the argument list.
Definition clos.h:108
Ref clos_apply(Ref closure, Ref args)
Apply a closure to arguments.
Definition clos.cpp:100
const Sigma * isa_clos_type(Ref def)
Returns def if def is a closure and nullptr otherwise.
Definition clos.cpp:111
Sigma * clos_type(const Pi *pi)
Creates a typed closure type from pi.
Definition clos.cpp:121
ClosLit isa_clos_lit(Ref def, bool fn_isa_lam=true)
Tries to match a closure literal.
Definition clos.cpp:64
size_t skip_env(size_t i)
Definition clos.h:114
Ref clos_remove_env(size_t i, std::function< Ref(size_t)> f)
Definition clos.cpp:139
std::tuple< Ref, Ref, Ref > clos_unpack(Ref c)
Deconstruct a closure into (env_type, function, env).
Definition clos.cpp:88
const Pi * clos_type_to_pi(Ref ct, Ref new_env_type=nullptr)
Convert a closure type to a Pi, where the environment type has been removed or replaced by new_env_ty...
Definition clos.cpp:123
Ref clos_sub_env(Ref tup_or_sig, Ref new_env)
Definition clos.h:140
Ref ctype(World &w, Defs doms, Ref env_type=nullptr)
Definition clos.cpp:141
size_t shift_env(size_t i)
Definition clos.h:111
Definition cfg.h:11
absl::flat_hash_map< flags_t, std::function< void(World &, PipelineBuilder &, const Def *)> > Passes
axiom ↦ (pipeline part) × (axiom application) → () The function should inspect Application to const...
Definition plugin.h:22
THORIN_EXPORT thorin::Plugin thorin_get_plugin()
To be implemented and exported by a plugin.
absl::flat_hash_map< flags_t, NormalizeFn > Normalizers
Definition plugin.h:19
Vector< const Def * > DefVec
Definition def.h:63
u64 flags_t
Definition types.h:46
static constexpr flags_t Base
Definition plugin.h:131
Basic info and registration function pointer to be returned from a specific plugin.
Definition plugin.h:29