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/world.h"
6
7// TODO this code needs to be rewritten
8
9namespace mim {
10
11namespace {
12bool should_flatten(const Def* def) {
13 auto type = (def->is_term() ? def->type() : def);
14 if (type->isa<Sigma>()) return true;
15 if (auto arr = type->isa<Arr>()) {
16 if (auto a = Lit::isa(arr->arity()); a && *a > def->world().flags().scalarize_threshold) return false;
17 return true;
18 }
19 return false;
20}
21
22bool mut_val_or_typ(const Def* def) {
23 auto typ = def->is_term() ? def->type() : def;
24 return typ->isa_mut();
25}
26
27const Def* unflatten(Defs defs, const Def* type, size_t& j, bool flatten_muts) {
28 if (!defs.empty() && defs[0]->type() == type) return defs[j++];
29 if (auto a = Lit::isa(type->arity());
30 flatten_muts == mut_val_or_typ(type) && a && *a != 1 && a <= type->world().flags().scalarize_threshold) {
31 auto& world = type->world();
32 auto ops = DefVec(*a, [&](size_t i) { return unflatten(defs, type->proj(*a, i), j, flatten_muts); });
33 return world.tuple(type, ops);
34 }
35
36 return defs[j++];
37}
38} // namespace
39
40const Def* Sigma::arity() const {
41 auto n = num_ops();
42 if (n != 1 || isa_mut()) return world().lit_nat(n);
43 return op(0)->arity();
44}
45
46const Def* Pack::arity() const {
47 if (auto arr = type()->isa<Arr>()) return arr->arity();
48 if (type() == world().sigma()) return world().lit_nat_0();
49 return world().lit_nat_1();
50}
51
52bool is_unit(const Def* def) { return def->type() == def->world().sigma(); }
53
54std::string tuple2str(const Def* def) {
55 if (def == nullptr) return {};
56
57 auto& w = def->world();
58 auto res = std::string();
59 if (auto n = Lit::isa(def->arity())) {
60 for (size_t i = 0; i != *n; ++i) {
61 auto elem = def->proj(*n, i);
62 if (elem->type() == w.type_i8()) {
63 if (auto l = Lit::isa<char>(elem)) {
64 res.push_back(*l);
65 continue;
66 }
67 }
68 return {};
69 }
70 }
71 return res;
72}
73
74size_t flatten(DefVec& ops, const Def* def, bool flatten_muts) {
75 if (auto a = Lit::isa(def->arity()); a && *a != 1 && should_flatten(def) && flatten_muts == mut_val_or_typ(def)) {
76 auto n = 0;
77 for (size_t i = 0; i != *a; ++i)
78 n += flatten(ops, def->proj(*a, i), flatten_muts);
79 return n;
80 } else {
81 ops.emplace_back(def);
82 return 1;
83 }
84}
85
86const Def* flatten(const Def* def) {
87 if (!should_flatten(def)) return def;
88 DefVec ops;
89 flatten(ops, def);
90 return def->is_intro() ? def->world().tuple(def->type(), ops) : def->world().sigma(ops);
91}
92
93const Def* unflatten(Defs defs, const Def* type, bool flatten_muts) {
94 size_t j = 0;
95 auto def = unflatten(defs, type, j, flatten_muts);
96 assert(j == defs.size());
97 return def;
98}
99
100const Def* unflatten(const Def* def, const Def* type) { return unflatten(def->projs(Lit::as(def->arity())), type); }
101
102DefVec merge(const Def* def, Defs defs) {
103 return DefVec(defs.size() + 1, [&](size_t i) { return i == 0 ? def : defs[i - 1]; });
104}
105
107 DefVec result(a.size() + b.size());
108 auto [_, o] = std::ranges::copy(a, result.begin());
109 std::ranges::copy(b, o);
110 return result;
111}
112
113const Def* merge_sigma(const Def* def, Defs defs) {
114 if (auto sigma = def->isa_imm<Sigma>()) return def->world().sigma(merge(sigma->ops(), defs));
115 return def->world().sigma(merge(def, defs));
116}
117
118const Def* merge_tuple(const Def* def, Defs defs) {
119 auto& w = def->world();
120 if (auto sigma = def->type()->isa_imm<Sigma>()) {
121 auto a = sigma->num_ops();
122 auto tuple = DefVec(a, [&](auto i) { return w.extract(def, a, i); });
123 return w.tuple(merge(tuple, defs));
124 }
125
126 return def->world().tuple(merge(def, defs));
127}
128
129const Def* tuple_of_types(const Def* t) {
130 auto& world = t->world();
131 if (auto sigma = t->isa<Sigma>()) return world.tuple(sigma->ops());
132 if (auto arr = t->isa<Arr>()) return world.pack(arr->arity(), arr->body());
133 return t;
134}
135
136} // namespace mim
A (possibly paramterized) Array.
Definition tuple.h:120
Base class for all Defs.
Definition def.h:216
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:552
World & world() const noexcept
Definition def.cpp:413
bool is_intro() const noexcept
Definition def.h:249
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:445
const Def * op(size_t i) const noexcept
Definition def.h:273
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:355
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Definition def.h:260
virtual const Def * arity() const
Definition def.cpp:523
const T * isa_imm() const
Definition def.h:439
constexpr size_t num_ops() const noexcept
Definition def.h:274
static std::optional< T > isa(const Def *def)
Definition def.h:773
static T as(const Def *def)
Definition def.h:779
const Def * arity() const final
Definition tuple.cpp:46
Def(World *, Node, const Def *type, Defs ops, flags_t flags)
Constructor for an immutable Def.
Definition def.cpp:23
Def(World *, Node, const Def *type, Defs ops, flags_t flags)
Constructor for an immutable Def.
Definition def.cpp:23
A dependent tuple type.
Definition tuple.h:20
const Def * arity() const final
Definition tuple.cpp:40
const Def * sigma(Defs ops)
Definition world.cpp:277
const Def * tuple(Defs ops)
Definition world.cpp:287
const Lit * lit_nat_0()
Definition world.h:409
const Lit * lit_nat(nat_t a)
Definition world.h:408
const Lit * lit_nat_1()
Definition world.h:410
Definition ast.h:14
View< const Def * > Defs
Definition def.h:51
const Def * flatten(const Def *def)
Flattens a sigma/array/pack/tuple.
Definition tuple.cpp:86
Vector< const Def * > DefVec
Definition def.h:52
bool is_unit(const Def *)
Definition tuple.cpp:52
const Def * merge_sigma(const Def *def, Defs defs)
Definition tuple.cpp:113
std::string tuple2str(const Def *)
Definition tuple.cpp:54
DefVec merge(Defs, Defs)
Definition tuple.cpp:106
const Def * unflatten(const Def *def, const Def *type)
Applies the reverse transformation on a Pack / Tuple, given the original type.
Definition tuple.cpp:100
const Def * tuple_of_types(const Def *t)
Definition tuple.cpp:129
const Def * merge_tuple(const Def *def, Defs defs)
Definition tuple.cpp:118