Thorin 1.9.0
The Higher ORder INtermediate representation
Loading...
Searching...
No Matches
tuple.cpp
Go to the documentation of this file.
1#include "thorin/tuple.h"
2
3#include <cassert>
4
5#include "thorin/rewrite.h"
6#include "thorin/world.h"
7
8// TODO this code needs to be rewritten
9
10namespace thorin {
11
12namespace {
13bool should_flatten(const Def* def) {
14 auto type = (def->is_term() ? def->type() : def);
15 if (type->isa<Sigma>()) return true;
16 if (auto arr = type->isa<Arr>()) {
17 if (auto a = arr->isa_lit_arity(); a && *a > def->world().flags().scalerize_threshold) return false;
18 return true;
19 }
20 return false;
21}
22
23bool mut_val_or_typ(const Def* def) {
24 auto typ = def->is_term() ? def->type() : def;
25 return typ->isa_mut();
26}
27
28const Def* unflatten(Defs defs, const Def* type, size_t& j, bool flatten_muts) {
29 if (!defs.empty() && defs[0]->type() == type) return defs[j++];
30 if (auto a = type->isa_lit_arity();
31 flatten_muts == mut_val_or_typ(type) && a && *a != 1 && a <= type->world().flags().scalerize_threshold) {
32 auto& world = type->world();
33 auto ops = DefVec(*a, [&](size_t i) { return unflatten(defs, type->proj(*a, i), j, flatten_muts); });
34 return world.tuple(type, ops);
35 }
36
37 return defs[j++];
38}
39} // namespace
40
41const Def* Pack::shape() const {
42 if (auto arr = type()->isa<Arr>()) return arr->shape();
43 if (type() == world().sigma()) return world().lit_nat_0();
44 return world().lit_nat_1();
45}
46
47bool is_unit(const Def* def) { return def->type() == def->world().sigma(); }
48
49std::string tuple2str(const Def* def) {
50 if (def == nullptr) return {};
51
52 auto array = def->projs(Lit::as(def->arity()), [](auto op) { return Lit::as(op); });
53 return std::string(array.begin(), array.end());
54}
55
56size_t flatten(DefVec& ops, const Def* def, bool flatten_muts) {
57 if (auto a = def->isa_lit_arity(); a && *a != 1 && should_flatten(def) && flatten_muts == mut_val_or_typ(def)) {
58 auto n = 0;
59 for (size_t i = 0; i != *a; ++i) n += flatten(ops, def->proj(*a, i), flatten_muts);
60 return n;
61 } else {
62 ops.emplace_back(def);
63 return 1;
64 }
65}
66
67const Def* flatten(const Def* def) {
68 if (!should_flatten(def)) return def;
69 DefVec ops;
70 flatten(ops, def);
71 return def->is_term() ? def->world().tuple(def->type(), ops) : def->world().sigma(ops);
72}
73
74const Def* unflatten(Defs defs, const Def* type, bool flatten_muts) {
75 size_t j = 0;
76 auto def = unflatten(defs, type, j, flatten_muts);
77 assert(j == defs.size());
78 return def;
79}
80
81const Def* unflatten(const Def* def, const Def* type) { return unflatten(def->projs(Lit::as(def->arity())), type); }
82
83DefVec merge(const Def* def, Defs defs) {
84 return DefVec(defs.size() + 1, [&](auto i) { return i == 0 ? def : defs[i - 1]; });
85}
86
88 DefVec result(a.size() + b.size());
89 auto [_, o] = std::ranges::copy(a, result.begin());
90 std::ranges::copy(b, o);
91 return result;
92}
93
94const Def* merge_sigma(const Def* def, Defs defs) {
95 if (auto sigma = def->isa_imm<Sigma>()) return def->world().sigma(merge(sigma->ops(), defs));
96 return def->world().sigma(merge(def, defs));
97}
98
99const Def* merge_tuple(const Def* def, Defs defs) {
100 auto& w = def->world();
101 if (auto sigma = def->type()->isa_imm<Sigma>()) {
102 auto a = sigma->num_ops();
103 auto tuple = DefVec(a, [&](auto i) { return w.extract(def, a, i); });
104 return w.tuple(merge(tuple, defs));
105 }
106
107 return def->world().tuple(merge(def, defs));
108}
109
111 auto& world = t->world();
112 if (auto sigma = t->isa<Sigma>()) return world.tuple(sigma->ops());
113 if (auto arr = t->isa<Arr>()) return world.pack(arr->shape(), arr->body());
114 return t;
115}
116
117} // namespace thorin
A (possibly paramterized) Array.
Definition tuple.h:50
Base class for all Defs.
Definition def.h:222
Ref arity() const
Definition def.cpp:494
std::optional< nat_t > isa_lit_arity() const
Definition def.cpp:501
auto projs(F f) const
Splits this Def via Def::projections into an Array (if A == -1_n) or std::array (otherwise).
Definition def.h:369
const T * isa_imm() const
Definition def.h:443
const Def * type() const
Yields the raw type of this Def, i.e. maybe nullptr.
Definition def.h:248
bool is_term() const
Yields true if this:T and T:(.Type 0).
Definition def.cpp:483
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:531
World & world() const
Definition def.cpp:421
static T as(Ref def)
Definition def.h:731
const Def * shape() const
Definition tuple.cpp:41
Helper class to retrieve Infer::arg if present.
Definition def.h:87
A dependent tuple type.
Definition tuple.h:9
This is a thin wrapper for std::span<T, N> with the following additional features:
Definition span.h:28
Ref sigma(Defs ops)
Definition world.cpp:218
const Lit * lit_nat_1()
Definition world.h:369
const Lit * lit_nat_0()
Definition world.h:368
Ref tuple(Defs ops)
Definition world.cpp:226
Definition cfg.h:11
Ref tuple_of_types(Ref t)
Definition tuple.cpp:110
const Def * flatten(const Def *def)
Flattens a sigma/array/pack/tuple.
Definition tuple.cpp:67
const Def * merge_tuple(const Def *def, Defs defs)
Definition tuple.cpp:99
View< const Def * > Defs
Definition def.h:62
bool is_unit(const Def *)
Definition tuple.cpp:47
const Def * unflatten(const Def *def, const Def *type)
Applies the reverse transformation on a pack/tuple, given the original type.
Definition tuple.cpp:81
DefVec merge(Defs, Defs)
Definition tuple.cpp:87
const Def * merge_sigma(const Def *def, Defs defs)
Definition tuple.cpp:94
Vector< const Def * > DefVec
Definition def.h:63
std::string tuple2str(const Def *)
Definition tuple.cpp:49