MimIR 0.1
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
normalizers.cpp
Go to the documentation of this file.
1#include <mim/tuple.h>
2#include <mim/world.h>
3
5
6namespace mim::plug::tuple {
7
8const Def* normalize_cat(const Def* type, const Def* callee, const Def* arg) {
9 auto& world = type->world();
10 auto [a, b] = arg->projs<2>();
11 auto [n, m] = callee->as<App>()->decurry()->args<2>([](auto def) { return Lit::isa(def); });
12
13 if (n && *n == 0) return b;
14 if (m && *m == 0) return a;
15
16 if (n && m) {
17 auto defs = DefVec();
18 for (size_t i = 0, e = *n; i != e; ++i) defs.emplace_back(a->proj(e, i));
19 for (size_t i = 0, e = *m; i != e; ++i) defs.emplace_back(b->proj(e, i));
20 return world.tuple(defs);
21 }
22
23 return nullptr;
24}
25
26const Def* normalize_cat_uniform(const Def* type, const Def* callee, const Def* arg) {
27 return normalize_cat(type, callee, arg);
28}
29
30const Def* normalize_contains(const Def* type, const Def*, const Def* arg) {
31 auto& w = type->world();
32 auto [xs, x] = arg->projs<2>();
33
34 if (auto mut_pack = xs->isa_mut<Pack>()) {
35 if (auto imm = mut_pack->immutabilize())
36 xs = imm;
37 else
38 return nullptr;
39 }
40
41 if (auto tuple = xs->isa<Tuple>()) {
42 for (auto op : tuple->ops())
43 if (op == x) return w.lit_tt();
44
45 return tuple->is_closed() ? w.lit_ff() : nullptr;
46 }
47
48 if (auto pack = xs->isa<Pack>()) {
49 if (pack->body() == x) return w.lit_tt();
50 return pack->is_closed() ? w.lit_ff() : nullptr;
51 }
52
53 return nullptr;
54}
55
56const Def* normalize_zip(const Def* type, const Def* c, const Def* arg) {
57 auto& w = type->world();
58 auto callee = c->as<App>();
59 auto is_os = callee->arg();
60 auto [n_i, Is, n_o, Os, f] = is_os->projs<5>();
61 auto [r, s] = callee->decurry()->args<2>();
62 auto lr = Lit::isa(r);
63 auto ls = Lit::isa(s);
64
65 // TODO commute
66 // TODO reassociate
67 // TODO more than one Os
68 // TODO select which Is/Os to zip
69
70 if (lr && ls && *lr == 1 && *ls == 1) return w.app(f, arg);
71
72 if (auto l_in = Lit::isa(n_i)) {
73 auto args = arg->projs(*l_in);
74
75 if (lr && std::ranges::all_of(args, [](const Def* arg) { return arg->isa<Prod>(); })) {
76 auto shapes = s->projs(*lr);
77 auto s_n = Lit::isa(shapes.front());
78
79 if (s_n) {
80 auto elems = DefVec(*s_n, [&, f = f](size_t s_i) {
81 auto inner_args = DefVec(args.size(), [&](size_t i) { return args[i]->proj(*s_n, s_i); });
82 if (*lr == 1) {
83 return w.app(f, inner_args);
84 } else {
85 auto app_zip = w.app(w.annex<zip>(), {w.lit_nat(*lr - 1), w.tuple(shapes.view().subspan(1))});
86 return w.app(w.app(app_zip, is_os), inner_args);
87 }
88 });
89 return w.tuple(elems);
90 }
91 }
92 }
93
94 return {};
95}
96
98
99} // namespace mim::plug::tuple
const Def * arg() const
Definition lam.h:230
Base class for all Defs.
Definition def.h:203
auto projs(F f) const
Splits this Def via Def::projections into an Array (if A == std::dynamic_extent) or std::array (other...
Definition def.h:350
static std::optional< T > isa(const Def *def)
Definition def.h:733
A (possibly paramterized) Tuple.
Definition tuple.h:150
Base class for Sigma and Tuple.
Definition tuple.h:8
Data constructor for a Sigma.
Definition tuple.h:62
The tuple Plugin
const Def * normalize_cat_uniform(const Def *type, const Def *callee, const Def *arg)
const Def * normalize_cat(const Def *type, const Def *callee, const Def *arg)
const Def * normalize_zip(const Def *type, const Def *c, const Def *arg)
const Def * normalize_contains(const Def *type, const Def *, const Def *arg)
Vector< const Def * > DefVec
Definition def.h:50
std::deque< const App * > decurry(const Def *)
Yields curried Apps in a flat std::deque<const App*>.
Definition lam.cpp:40
#define MIM_tuple_NORMALIZER_IMPL
Definition autogen.h:60