MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
normalizers.cpp
Go to the documentation of this file.
1#include <absl/container/btree_set.h>
2#include <absl/container/fixed_array.h>
3
4#include <mim/tuple.h>
5#include <mim/world.h>
6
8
9#include "mim/plug/vec/vec.h"
10
11namespace mim::plug::vec {
12
13template<fold id>
14const Def* normalize_fold(const Def* type, const Def* c, const Def* arg) {
15 auto& w = c->world();
16 auto callee = c->as<App>();
17 auto f = callee->arg();
18
19 auto [acc, vec] = arg->projs<2>();
20 if constexpr (id == fold::r) std::swap(acc, vec);
21
22 if (auto tuple = vec->isa<Tuple>()) {
23 if constexpr (id == fold::l)
24 for (auto op : tuple->ops())
25 acc = w.app(f, {acc, op});
26 else // fold::r
27 for (auto op : tuple->ops() | std::views::reverse)
28 acc = w.app(f, {op, acc});
29 return acc;
30 }
31
32 if (auto seq = vec->isa<Seq>()) {
33 if (auto n = Lit::isa<u64>(seq->arity()); n && type->isa<Nat>()) {
34 if constexpr (id == fold::l)
35 for (auto proj : seq->projs(*n))
36 acc = w.app(f, {acc, proj});
37 else // fold::r
38 for (auto proj : seq->projs(*n) | std::views::reverse)
39 acc = w.app(f, {proj, acc});
40 return acc;
41 }
42 w.log().w("Pack of non-literal arity not yet implemented: {}", seq);
43 }
44
45 if (auto l = vec->isa<Lit>()) {
46 if constexpr (id == fold::l)
47 return w.app(f, {acc, l});
48 else
49 return w.app(f, {l, acc});
50 }
51
52 return nullptr;
53}
54
55const Def* normalize_zip(const Def* type, const Def* c, const Def* arg) {
56 if (arg->is_open()) return {};
57 auto& w = type->world();
58 auto [ni_n, _, f] = App::uncurry_args<3>(c);
59 auto [ni, n] = ni_n->projs<2>([](const Def* def) { return Lit::isa(def); });
60
61 if (!ni || !n) return {};
62 if (ni >= w.flags().scalarize_threshold || n >= w.flags().scalarize_threshold) return {};
63
64 auto res = absl::FixedArray<const Def*>(*n);
65 auto tup = absl::FixedArray<const Def*>(*ni);
66
67 for (size_t j = 0; j != n; ++j) {
68 for (size_t i = 0; i != ni; ++i)
69 tup[i] = arg->proj(*ni, i)->proj(*n, j);
70
71 res[j] = w.app(f, tup);
72 }
73
74 return w.tuple(res);
75}
76
77template<scan id>
78const Def* normalize_scan(const Def*, const Def* c, const Def* vec) {
79 auto& w = c->world();
80 auto callee = c->as<App>();
81 auto p = callee->arg();
82
83 if (auto tuple = vec->isa<Tuple>()) {
84 const Def* acc = w.lit_bool(id != scan::exists);
85 for (auto op : tuple->ops())
86 acc = w.call(id == scan::exists ? core::bit2::or_ : core::bit2::and_, 0_n, Defs{acc, w.app(p, op)});
87 return acc;
88 }
89
90 if (auto pack = vec->isa_imm<Pack>()) w.log().w("Pack not yet implemented: {}", pack);
91
92 return nullptr;
93}
94
95const Def* normalize_is_unique(const Def*, const Def*, const Def* vec) {
96 auto& w = vec->world();
97
98 if (auto tuple = vec->isa<Tuple>()) {
99 auto seen = DefSet();
100 for (auto op : tuple->ops()) {
101 auto [_, ins] = seen.emplace(op);
102 if (!ins) return w.lit_ff();
103 }
104 return tuple->is_closed() ? w.lit_tt() : nullptr;
105 }
106
107 if (auto pack = vec->isa_imm<Pack>()) {
108 if (auto l = Lit::isa(pack->arity())) return w.lit_ff();
109 }
110
111 if (vec->isa<Lit>()) return w.lit_tt();
112
113 return nullptr;
114}
115
116const Def* normalize_cat(const Def*, const Def* callee, const Def* arg) {
117 auto [a, b] = arg->projs<2>();
118 auto [n, m] = callee->as<App>()->decurry()->args<2>([](auto def) { return Lit::isa(def); });
119 if (n && *n == 0) return b;
120 if (m && *m == 0) return a;
121 if (n && m) return mim::cat_tuple(*n, *m, a, b);
122 return nullptr;
123}
124
125const Def* normalize_diff(const Def* type, const Def* c, const Def* arg) {
126 if (auto arr = type->isa<Arr>()) {
127 if (arr->arity()->isa<Bot>()) return nullptr; // ack error
128 }
129
130 auto& w = type->world();
131 auto callee = c->as<App>();
132 auto [n, m] = callee->args<2>([](auto def) { return Lit::isa(def); });
133 auto [vec, is] = arg->projs<2>();
134
135 if (!n || !m) return nullptr;
136 if (n == 1 && m == 1) return w.tuple();
137
138 if (auto tup_vec = vec->isa<Tuple>()) {
139 if (auto tup_is = is->isa<Tuple>(); tup_is && tup_is->is_closed()) {
140 auto defs = DefVec();
141 auto set = absl::btree_set<nat_t>();
142 for (auto opi : tup_is->ops())
143 set.emplace(Lit::as(opi));
144
145 for (size_t i = 0, e = tup_vec->num_ops(); i != e; ++i)
146 if (!set.contains(i)) defs.emplace_back(tup_vec->op(i));
147 return w.tuple(defs);
148 }
149 if (auto lit_is = Lit::isa(is)) {
150 auto defs = DefVec();
151
152 for (size_t i = 0, e = tup_vec->num_ops(); i != e; ++i)
153 if (i != lit_is) defs.emplace_back(tup_vec->op(i));
154 return w.tuple(defs);
155 }
156 }
157
158 if (auto tup_pack = vec->isa_imm<Pack>()) return w.pack(*n - *m, tup_pack->body());
159
160 return nullptr;
161}
162
164
165} // namespace mim::plug::vec
auto uncurry_args() const
Definition lam.h:329
const Def * arg() const
Definition lam.h:284
A (possibly paramterized) Array.
Definition tuple.h:110
Base class for all Defs.
Definition def.h:273
const Def * proj(nat_t a, nat_t i) const
Similar to World::extract while assuming an arity of a, but also works on Sigmas and Arrays.
Definition def.cpp:623
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:440
bool is_open() const
Same as has_free_vars().
Definition def.h:521
bool is_closed() const
Same as !has_free_vars().
Definition def.cpp:353
static std::optional< T > isa(const Def *def)
Definition def.h:937
static T as(const Def *def)
Definition def.h:943
A (possibly paramterized) Tuple.
Definition tuple.h:137
Base class for Arr and Pack.
Definition tuple.h:75
Data constructor for a Sigma.
Definition tuple.h:61
The tuple Plugin
The vec Plugin
const Def * normalize_scan(const Def *, const Def *c, const Def *vec)
const Def * normalize_cat(const Def *, const Def *callee, const Def *arg)
const Def * normalize_fold(const Def *type, const Def *c, const Def *arg)
const Def * normalize_is_unique(const Def *, const Def *, const Def *vec)
const Def * normalize_diff(const Def *type, const Def *c, const Def *arg)
const Def * normalize_zip(const Def *type, const Def *c, const Def *arg)
const Def * cat_tuple(nat_t n, nat_t m, const Def *a, const Def *b)
Definition tuple.cpp:92
fe::View< const Def * > Defs
Definition def.h:91
fe::Vector< const Def * > DefVec
Definition def.h:93
GIDSet< const Def * > DefSet
Definition def.h:89
TExt< false > Bot
Definition lattice.h:164
#define MIM_vec_NORMALIZER_IMPL
Definition autogen.h:91