13bool should_flatten(
const Def* def) {
14 auto type = (def->is_term() ? def->type() : def);
16 if (
auto arr =
type->isa<
Arr>()) {
17 if (
auto a =
Lit::isa(arr->arity()); a && *a > def->world().flags().scalarize_threshold)
return false;
23bool mut_val_or_typ(
const Def* def) {
24 auto typ = def->is_term() ? def->type() : def;
25 return typ->isa_mut();
29 if (!defs.empty() && defs[0]->type() == type)
return defs[j++];
31 flatten_muts == mut_val_or_typ(type) && a && *a != 1 && a <= type->world().flags().scalarize_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);
48 if (
auto arr =
type()->isa<Arr>())
return arr->
arity();
55 if ((extract_ = def->isa<
Extract>())) {
56 pair_ = extract_->tuple();
57 cond_ = extract_->index();
59 if (
auto a =
Lit::isa(pair_->arity()); a && a == 2) {
60 ff_ = pair_->proj(2, 0);
61 tt_ = pair_->proj(2, 1);
70 if ((app_ = def->isa<
App>())) {
71 callee_ = app_->callee();
79 if (def ==
nullptr)
return {};
81 auto& w = def->
world();
82 auto res = std::string();
84 for (
size_t i = 0; i != *n; ++i) {
85 auto elem = def->
proj(*n, i);
86 if (elem->type() == w.type_i8()) {
99 if (
auto a =
Lit::isa(def->
arity()); a && *a != 1 && should_flatten(def) && flatten_muts == mut_val_or_typ(def)) {
101 for (
size_t i = 0; i != *a; ++i)
105 ops.emplace_back(def);
111 if (!should_flatten(def))
return def;
119 auto def =
unflatten(defs, type, j, flatten_muts);
120 assert(j == defs.size());
132 res.reserve(a.size() + b.size());
133 res.insert(res.end(), a.begin(), a.end());
134 res.insert(res.end(), b.begin(), b.end());
141 for (
size_t i = 0, e = n; i != e; ++i)
142 defs.emplace_back(a->proj(e, i));
143 for (
size_t i = 0, e = m; i != e; ++i)
144 defs.emplace_back(b->
proj(e, i));
156 auto& world = t->world();
157 if (
auto sigma = t->isa<
Sigma>())
return world.tuple(sigma->ops());
158 if (
auto arr = t->isa<
Arr>())
return world.pack(arr->arity(), arr->body());
A (possibly paramterized) Array.
const Def * callee() const
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.
World & world() const noexcept
bool is_intro() const noexcept
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
const Def * op(size_t i) const noexcept
auto projs(F f) const
Splits this Def via Def::projections into an Array (if A == std::dynamic_extent) or std::array (other...
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
virtual const Def * arity() const
constexpr size_t num_ops() const noexcept
static std::optional< T > isa(const Def *def)
static T as(const Def *def)
const Def * arity() const final
Def(World *, Node, const Def *type, Defs ops, flags_t flags)
Constructor for an immutable Def.
Def(World *, Node, const Def *type, Defs ops, flags_t flags)
Constructor for an immutable Def.
const Def * arity() const final
The World represents the whole program and manages creation of MimIR nodes (Defs).
const Def * sigma(Defs ops)
const Def * tuple(Defs ops)
const Lit * lit_nat(nat_t a)
const Def * flatten(const Def *def)
Flattens a sigma/array/pack/tuple.
Vector< const Def * > DefVec
const Def * cat_tuple(nat_t n, nat_t m, const Def *a, const Def *b)
bool is_unit(const Def *)
std::string tuple2str(const Def *)
const Def * cat_sigma(nat_t n, nat_t m, const Def *a, const Def *b)
const Def * unflatten(const Def *def, const Def *type)
Applies the reverse transformation on a Pack / Tuple, given the original type.
const Def * tuple_of_types(const Def *t)