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)
17 if (auto last = dom(n, n - 1)) return Pi::isa_basicblock(last); // a frozen World yields no projection
18 return nullptr;
19}
20
21Pi* Pi::set_dom(Defs doms) { return Def::set(0, world().sigma(doms))->as<Pi>(); }
22
23/*
24 * Lam
25 */
26
27Lam* Lam::forwardee() const {
28 if (auto app = body()->isa<App>())
29 if (auto callee = app->callee()->isa_mut<Lam>(); callee && callee->is_set()) return callee;
30 return nullptr;
31}
32
33Lam* Lam::set_filter(Filter filter) { return Def::set(0, world().filter(filter))->as<Lam>(); }
34Lam* Lam::set(Filter filter, const Def* body) { return Def::set({world().filter(filter), body})->as<Lam>(); }
35Lam* Lam::app(Filter f, const Def* callee, const Def* arg) {
36 return Def::set({world().filter(f), world().app(callee, arg)})->as<Lam>();
37}
38Lam* Lam::app(Filter filter, const Def* callee, Defs args) { return app(filter, callee, world().tuple(args)); }
39
40Lam* Lam::branch(Filter filter, const Def* cond, const Def* t, const Def* f, const Def* arg) {
41 return app(filter, world().select(cond, t, f), arg ? arg : world().tuple());
42}
43
44Defs Lam::reduce(Defs args) const { return Def::reduce(world().tuple(args)); }
45
46const Def* Lam::isa_ret_arg(const Def* d) {
47 auto lam = d->isa_mut<Lam>();
48 if (!lam || !lam->is_set()) return nullptr;
49 auto app = lam->body()->isa<App>();
50 return app && app->callee() == lam->ret_var() ? app->arg() : nullptr;
51}
52
53static const Def* eta_callee(const Lam* lam) {
54 if (lam->is_set())
55 if (auto app = lam->body()->isa<App>()) {
56 auto var = lam->has_var();
57 if (var && app->callee()->has_free_var(var)) return nullptr;
58 // The sole inhabitant of a singleton dom is η-equal to the Var.
59 if (app->arg() == var || app->arg() == lam->world().inhabitant(lam->dom())) return app->callee();
60 }
61 return nullptr;
62}
63
64static const Def* eta_step(const Def* def) {
65 if (auto lam = def->isa<Lam>())
66 if (auto f = eta_callee(lam)) {
67 if (f->isa_mut()) return f;
68 // Reducing to `(e, b)#c` with `b` an η-redex as well might unfold a recursion through `b`.
69 for (auto mut : f->local_muts())
70 if (auto l = mut->isa<Lam>(); l && eta_callee(l)) return def;
71 return f;
72 }
73 return def;
74}
75
76const Def* Lam::eta_reduce(const Def* def) {
77 // Floyd: the chain's end is a fixpoint of eta_step, i.e. a cycle of length 1.
78 auto slow = eta_step(def), fast = eta_step(slow);
79 for (; slow != fast; slow = eta_step(slow), fast = eta_step(eta_step(fast))) {}
80 for (slow = def; slow != fast; slow = eta_step(slow), fast = eta_step(fast)) {}
81 return fast == def ? nullptr : fast;
82}
83
84Lam* Lam::eta_expand(Filter filter, const Def* f) {
85 auto& w = f->world();
86 auto eta = w.mut_lam(f->type()->as<Pi>());
87 eta->set(f->dbg_key())->debug_prefix("eta_"s);
88 return eta->app(filter, f, eta->var());
89}
90
91} // namespace mim
Base class for all Defs.
Definition def.h:289
bool is_set() const
Definition def.h:396
Def * set(size_t i, const Def *)
Successively set from left to right.
Definition def.cpp:188
World & world() const noexcept
Definition def.h:1105
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:588
constexpr auto reduce(const Def *arg) const
Definition def.h:681
const Var * has_var()
Only returns not nullptr, if Var of this mutable has ever been created.
Definition def.h:496
A function.
Definition lam.h:91
std::variant< bool, const Def * > Filter
Definition lam.h:99
const Def * filter() const
Definition lam.h:103
Lam * forwardee() const
λ x = f arg where f is a mut Lam that is_set();
Definition lam.cpp:27
Lam * set(Filter filter, const Def *body)
Definition lam.cpp:34
static Lam * eta_expand(Filter, const Def *f)
Definition lam.cpp:84
Lam * set_filter(Filter)
Set filter first.
Definition lam.cpp:33
Defs reduce(Defs) const
Definition lam.cpp:44
const Def * dom() const
Definition lam.h:113
static const Def * eta_reduce(const Def *def)
Fast-forwards def along its chain of η-redexes λ x = f x where x ∉ FV(f).
Definition lam.cpp:76
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:40
Lam * app(Filter filter, const Def *callee, const Def *arg)
Set body to an App of callee and arg.
Definition lam.cpp:35
const Def * body() const
Definition lam.h:104
static const Def * isa_ret_arg(const Def *d)
Yields the y of λ (x, ret) = ret y - the argument d's body hands to its Lam::ret_var.
Definition lam.cpp:46
const Def * ret_var()
Yields the Lam::var of the Lam::ret_pi.
Definition lam.h:136
A dependent function type.
Definition lam.h:14
auto doms(Projector auto f) const noexcept
Definition lam.h:40
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)
Definition lam.h:52
const Def * dom() const
Definition lam.h:38
const Pi * ret_pi() const
Yields the last Pi::dom, if Pi::isa_basicblock.
Definition lam.cpp:13
nat_t num_doms() const noexcept
Definition lam.h:40
Pi * set_dom(const Def *dom)
Definition lam.h:66
const Def * inhabitant(const Def *type)
The sole inhabitant of type, if it has exactly one, nullptr otherwise.
Definition world.h:342
const Def * filter(Lam::Filter filter)
Definition world.h:410
const Def * app(const Def *callee, const Def *arg)
Definition world.cpp:416
Definition ast.h:16
fe::View< const Def * > Defs
Definition def.h:96
static const Def * eta_step(const Def *def)
Definition lam.cpp:64
static const Def * eta_callee(const Lam *lam)
Definition lam.cpp:53