MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
lam.cpp
Go to the documentation of this file.
1#include "mim/lam.h"
2
3#include "mim/world.h"
4
5using namespace std::string_literals;
6
7namespace mim {
8
9/*
10 * Pi
11 */
12
13const Pi* Pi::ret_pi() const {
14 // num_doms() has to materialize a Lit for the arity of a Sigma dom - which means a full hash-cons round trip.
15 // So compute it *once* and feed it to the (a, i) projection instead of letting dom(i) re-derive it.
16 if (auto n = num_doms(); n != 0) return Pi::isa_basicblock(dom(n, n - 1));
17 return nullptr;
18}
19
20Pi* Pi::set_dom(Defs doms) { return Def::set(0, world().sigma(doms))->as<Pi>(); }
21
22/*
23 * Lam
24 */
25
26Lam* Lam::set_filter(Filter filter) { return Def::set(0, world().filter(filter))->as<Lam>(); }
27Lam* Lam::set(Filter filter, const Def* body) { return Def::set({world().filter(filter), body})->as<Lam>(); }
28Lam* Lam::app(Filter f, const Def* callee, const Def* arg) {
29 return Def::set({world().filter(f), world().app(callee, arg)})->as<Lam>();
30}
31Lam* Lam::app(Filter filter, const Def* callee, Defs args) { return app(filter, callee, world().tuple(args)); }
32
33Lam* Lam::branch(Filter filter, const Def* cond, const Def* t, const Def* f, const Def* arg) {
34 return app(filter, world().select(cond, t, f), arg ? arg : world().tuple());
35}
36
37Defs Lam::reduce(Defs args) const { return Def::reduce(world().tuple(args)); }
38
39// TODO maybe we can eta-reduce immutable Lams in some edge casess like: lm _: [] = f ();
40
41const Def* Lam::isa_ret_arg(const Def* d) {
42 auto lam = d->isa_mut<Lam>();
43 if (!lam || !lam->is_set()) return nullptr;
44 auto app = lam->body()->isa<App>();
45 return app && app->callee() == lam->ret_var() ? app->arg() : nullptr;
46}
47
48const Def* Lam::eta_reduce() const {
49 if (auto var = has_var()) {
50 if (auto app = body()->isa<App>())
51 if (app->arg() == var && !app->callee()->has_free_var(var)) return app->callee();
52 }
53 return nullptr;
54}
55
56Lam* Lam::eta_expand(Filter filter, const Def* f) {
57 auto& w = f->world();
58 auto eta = w.mut_lam(f->type()->as<Pi>());
59 eta->set(f->dbg_key())->debug_prefix("eta_"s);
60 return eta->app(filter, f, eta->var());
61}
62
63/*
64 * Helpers
65 */
66
67const Def* compose_cn(const Def* f, const Def* g) {
68 auto& world = f->world();
69 auto F = f->type()->as<Pi>();
70 auto G = g->type()->as<Pi>();
71
72 assert(Pi::isa_returning(F));
73 assert(Pi::isa_returning(G));
74
75 auto A = G->dom(2, 0);
76 auto B = G->ret_dom();
77 auto C = F->ret_dom();
78 // The type check of codom G = dom F is better handled by the application type checking
79
80 world.log().d("compose f: {}: {}, g: {}: {}", f, F, g, G);
81 world.log().d(" A = {}, B = {}, C = {}", A, B, C);
82
83 auto name = "comp_"s + f->sym().str() + "_" + g->sym().str();
84 auto h = world.mut_fun(A, C)->set(name);
85 auto hcont = world.mut_con(B)->set(name + "_cont");
86
87 h->app(true, g, {h->var((nat_t)0), hcont});
88
89 auto hcont_var = hcont->var(); // Warning: not var(0) => only one var => normalization flattens tuples down here.
90 hcont->app(true, f, {hcont_var, h->var(1) /* ret_var */});
91
92 return h;
93}
94
95} // namespace mim
Base class for all Defs.
Definition def.h:273
Def * set(size_t i, const Def *)
Successively set from left to right.
Definition def.cpp:196
World & world() const noexcept
Definition def.h:1097
const Def * var(nat_t a, nat_t i) noexcept
Definition def.h:479
bool has_free_var(const Var *) const
Same as free_vars().contains(var).
Definition def.cpp:273
constexpr auto reduce(const Def *arg) const
Definition def.h:660
const Var * has_var()
Only returns not nullptr, if Var of this mutable has ever been created.
Definition def.h:483
std::variant< bool, const Def * > Filter
Definition lam.h:121
const Def * filter() const
Definition lam.h:125
Lam * set(Filter filter, const Def *body)
Definition lam.cpp:27
static Lam * eta_expand(Filter, const Def *f)
Definition lam.cpp:56
Lam * set_filter(Filter)
Set filter first.
Definition lam.cpp:26
Defs reduce(Defs) const
Definition lam.cpp:37
const Def * eta_reduce() const
Yields body(), if eta-convertible and nullptr otherwise.
Definition lam.cpp:48
Lam * branch(Filter filter, const Def *cond, const Def *t, const Def *f, const Def *arg=nullptr)
Set body to an App of (f, t)#cond mem or (f, t)#cond () if mem is nullptr.
Definition lam.cpp:33
Lam * app(Filter filter, const Def *callee, const Def *arg)
Set body to an App of callee and arg.
Definition lam.cpp:28
const Def * body() const
Definition lam.h:126
static const Def * isa_ret_arg(const Def *d)
Yields the y of lm (x, ret) = ret y - the argument d's body hands to its Lam::ret_var.
Definition lam.cpp:41
const Def * ret_var()
Yields the Lam::var of the Lam::ret_pi.
Definition lam.h:159
A dependent function type.
Definition lam.h:14
const Def * ret_dom() const
Pi::domain of Pi::ret_pi.
Definition lam.h:80
Pi(const Def *type, const Def *dom, const Def *codom, bool implicit)
Constructor for an immutable Pi.
Definition lam.h:17
static const Pi * isa_basicblock(const Def *d)
Is this a continuation (Pi::isa_cn) that is not Pi::isa_returning?
Definition lam.h:56
const Def * dom() const
Definition lam.h:35
const Pi * ret_pi() const
Yields the last Pi::dom, if Pi::isa_basicblock.
Definition lam.cpp:13
Pi * set_dom(const Def *dom)
Definition lam.h:88
static const Pi * isa_returning(const Def *d)
Is this a continuation (Pi::isa_cn) which has a Pi::ret_pi?
Definition lam.h:51
const Def * filter(Lam::Filter filter)
Definition world.h:397
const Def * app(const Def *callee, const Def *arg)
Definition world.cpp:237
Definition ast.h:16
u64 nat_t
Definition types.h:37
fe::View< const Def * > Defs
Definition def.h:91
const Def * compose_cn(const Def *f, const Def *g)
The high level view is:
Definition lam.cpp:67