MimIR 0.1
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
tuple.cpp
Go to the documentation of this file.
1#include "mim/tuple.h"
2
3#include <cassert>
4
5#include "mim/tuple.h"
6#include "mim/world.h"
7
8namespace mim {
9
10namespace {
11bool should_flatten(const Def* def) {
12 auto type = (def->is_term() ? def->type() : def);
13 if (type->isa<Sigma>()) return true;
14 if (auto arr = type->isa<Arr>()) {
15 if (auto a = Lit::isa(arr->arity()); a && *a > def->world().flags().scalarize_threshold) return false;
16 return true;
17 }
18 return false;
19}
20
21bool mut_val_or_typ(const Def* def) {
22 auto typ = def->is_term() ? def->type() : def;
23 return typ->isa_mut();
24}
25
26const Def* unflatten(Defs defs, const Def* type, size_t& j, bool flatten_muts) {
27 if (!defs.empty() && defs[0]->type() == type) return defs[j++];
28 if (auto a = Lit::isa(type->arity());
29 flatten_muts == mut_val_or_typ(type) && a && *a != 1 && a <= type->world().flags().scalarize_threshold) {
30 auto& world = type->world();
31 auto ops = DefVec(*a, [&](size_t i) { return unflatten(defs, type->proj(*a, i), j, flatten_muts); });
32 return world.tuple(type, ops);
33 }
34
35 return defs[j++];
36}
37} // namespace
38
39const Def* Sigma::arity() const {
40 auto n = num_ops();
41 if (n != 1 || isa_mut()) return world().lit_nat(n);
42 return op(0)->arity();
43}
44
45const Def* Pack::arity() const {
46 if (auto arr = type()->isa<Arr>()) return arr->arity();
47 if (type() == world().sigma()) return world().lit_nat_0();
48 return world().lit_nat_1();
49}
50
51Select::Select(const Def* def) {
52 if (def) {
53 if (auto extract = def->isa<Extract>(); extract && !Lit::isa(extract->index())) {
54 if (auto a = Lit::isa(extract->tuple()->arity()); a && a == 2) extract_ = extract;
55 }
56 }
57}
58
60 : Select(def->isa<App>() ? def->as<App>()->callee() : nullptr) {
61 if (extract()) app_ = def->as<App>();
62}
63
64const Def* Branch::callee() const { return app()->callee(); }
65const Def* Branch::arg() const { return app()->arg(); }
66
68 if (auto app = def->isa<App>()) {
69 if (auto extract = app->callee()->isa<Extract>(); extract && !Lit::isa(extract->index())) {
70 if (auto a = Lit::isa(extract->tuple()->arity())) {
71 app_ = app;
72 extract_ = extract;
73 }
74 }
75 }
76}
77
78const Def* Dispatch::callee() const { return app()->callee(); }
79const Def* Dispatch::arg() const { return app()->arg(); }
80
81bool is_unit(const Def* def) { return def->type() == def->world().sigma(); }
82
83std::string tuple2str(const Def* def) {
84 if (def == nullptr) return {};
85
86 auto& w = def->world();
87 auto res = std::string();
88 if (auto n = Lit::isa(def->arity())) {
89 for (size_t i = 0; i != *n; ++i) {
90 auto elem = def->proj(*n, i);
91 if (elem->type() == w.type_i8()) {
92 if (auto l = Lit::isa<char>(elem)) {
93 res.push_back(*l);
94 continue;
95 }
96 }
97 return {};
98 }
99 }
100 return res;
101}
102
103// TODO flatten/unflatten needs to be rewritten
104
105size_t flatten(DefVec& ops, const Def* def, bool flatten_muts) {
106 if (auto a = Lit::isa(def->arity()); a && *a != 1 && should_flatten(def) && flatten_muts == mut_val_or_typ(def)) {
107 auto n = 0;
108 for (size_t i = 0; i != *a; ++i)
109 n += flatten(ops, def->proj(*a, i), flatten_muts);
110 return n;
111 } else {
112 ops.emplace_back(def);
113 return 1;
114 }
115}
116
117const Def* flatten(const Def* def) {
118 if (!should_flatten(def)) return def;
119 DefVec ops;
120 flatten(ops, def);
121 return def->is_intro() ? def->world().tuple(def->type(), ops) : def->world().sigma(ops);
122}
123
124const Def* unflatten(Defs defs, const Def* type, bool flatten_muts) {
125 size_t j = 0;
126 auto def = unflatten(defs, type, j, flatten_muts);
127 assert(j == defs.size());
128 return def;
129}
130
131const Def* unflatten(const Def* def, const Def* type) { return unflatten(def->projs(Lit::as(def->arity())), type); }
132
133/*
134 * cat
135 */
136
138 auto res = DefVec();
139 res.reserve(a.size() + b.size());
140 res.insert(res.end(), a.begin(), a.end());
141 res.insert(res.end(), b.begin(), b.end());
142 return res;
143}
144
145DefVec cat(nat_t n, nat_t m, const Def* a, const Def* b) {
146 auto defs = DefVec();
147 defs.reserve(n + m);
148 for (size_t i = 0, e = n; i != e; ++i)
149 defs.emplace_back(a->proj(e, i));
150 for (size_t i = 0, e = m; i != e; ++i)
151 defs.emplace_back(b->proj(e, i));
152
153 return defs;
154}
155
156const Def* cat_tuple(nat_t n, nat_t m, const Def* a, const Def* b) { return a->world().tuple(cat(n, m, a, b)); }
157const Def* cat_sigma(nat_t n, nat_t m, const Def* a, const Def* b) { return a->world().sigma(cat(n, m, a, b)); }
158
159const Def* cat_tuple(World& world, Defs a, Defs b) { return world.tuple(cat(a, b)); }
160const Def* cat_sigma(World& world, Defs a, Defs b) { return world.sigma(cat(a, b)); }
161
162const Def* tuple_of_types(const Def* t) {
163 auto& world = t->world();
164 if (auto sigma = t->isa<Sigma>()) return world.tuple(sigma->ops());
165 if (auto arr = t->isa<Arr>()) return world.pack(arr->arity(), arr->body());
166 return t;
167}
168
169} // namespace mim
const Def * callee() const
Definition lam.h:276
const Def * arg() const
Definition lam.h:285
A (possibly paramterized) Array.
Definition tuple.h:117
const App * app() const
Definition tuple.h:285
const Def * callee() const
Definition tuple.cpp:64
Branch(const Def *)
Definition tuple.cpp:59
const Def * arg() const
Definition tuple.cpp:65
Base class for all Defs.
Definition def.h:251
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:587
World & world() const noexcept
Definition def.cpp:438
bool is_intro() const noexcept
Definition def.h:284
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:486
const Def * op(size_t i) const noexcept
Definition def.h:308
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:390
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Definition def.cpp:446
virtual const Def * arity() const
Definition def.cpp:552
constexpr size_t num_ops() const noexcept
Definition def.h:309
const Def * callee() const
Definition tuple.cpp:78
const Def * arg() const
Definition tuple.cpp:79
Dispatch(const Def *)
Definition tuple.cpp:67
const Extract * extract() const
Definition tuple.h:314
const App * app() const
Definition tuple.h:310
Extracts from a Sigma or Array-typed Extract::tuple the element at position Extract::index.
Definition tuple.h:206
static std::optional< T > isa(const Def *def)
Definition def.h:826
static T as(const Def *def)
Definition def.h:832
const Def * arity() const final
Definition tuple.cpp:45
Def(World *, Node, const Def *type, Defs ops, flags_t flags)
Constructor for an immutable Def.
Definition def.cpp:24
const Extract * extract() const
Definition tuple.h:267
Select(const Def *)
Definition tuple.cpp:51
Def(World *, Node, const Def *type, Defs ops, flags_t flags)
Constructor for an immutable Def.
Definition def.cpp:24
A dependent tuple type.
Definition tuple.h:20
const Def * arity() const final
Definition tuple.cpp:39
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:31
const Def * sigma(Defs ops)
Definition world.cpp:283
const Def * tuple(Defs ops)
Definition world.cpp:293
const Lit * lit_nat_0()
Definition world.h:455
const Lit * lit_nat(nat_t a)
Definition world.h:454
const Lit * lit_nat_1()
Definition world.h:456
Definition ast.h:14
View< const Def * > Defs
Definition def.h:76
u64 nat_t
Definition types.h:43
const Def * flatten(const Def *def)
Flattens a sigma/array/pack/tuple.
Definition tuple.cpp:117
Vector< const Def * > DefVec
Definition def.h:77
const Def * cat_tuple(nat_t n, nat_t m, const Def *a, const Def *b)
Definition tuple.cpp:156
bool is_unit(const Def *)
Definition tuple.cpp:81
std::string tuple2str(const Def *)
Definition tuple.cpp:83
const Def * cat_sigma(nat_t n, nat_t m, const Def *a, const Def *b)
Definition tuple.cpp:157
const Def * unflatten(const Def *def, const Def *type)
Applies the reverse transformation on a Pack / Tuple, given the original type.
Definition tuple.cpp:131
const Def * tuple_of_types(const Def *t)
Definition tuple.cpp:162
DefVec cat(Defs, Defs)
Definition tuple.cpp:137