20bool should_flatten(
const Def* def) {
22 if (type->isa<
Sigma>())
return true;
23 if (
auto arr = type->isa<
Arr>()) {
30bool mut_val_or_typ(
const Def* def) {
31 auto typ = def->is_term() ? def->type() : def;
32 return typ->isa_mut();
36 if (!defs.empty() && defs[0]->type() == type)
return defs[j++];
37 if (
auto a =
type->isa_lit_arity();
38 flatten_muts == mut_val_or_typ(type) && a && *a != 1 && a <= type->world().flags().scalarize_threshold) {
39 auto& world =
type->world();
40 auto ops =
DefVec(*a, [&](
size_t i) {
return unflatten(defs,
type->proj(*a, i), j, flatten_muts); });
41 return world.tuple(type, ops);
49 if (
auto arr =
type()->isa<Arr>())
return arr->shape();
57 if (def ==
nullptr)
return {};
59 auto& w = def->
world();
60 auto res = std::string();
62 for (
size_t i = 0; i != *n; ++i) {
63 auto elem = def->
proj(*n, i);
64 if (elem->type() == w.type_i8()) {
77 if (
auto a = def->
isa_lit_arity(); a && *a != 1 && should_flatten(def) && flatten_muts == mut_val_or_typ(def)) {
79 for (
size_t i = 0; i != *a; ++i) n +=
flatten(ops, def->
proj(*a, i), flatten_muts);
82 ops.emplace_back(def);
88 if (!should_flatten(def))
return def;
96 auto def =
unflatten(defs, type, j, flatten_muts);
97 assert(j == defs.size());
104 return DefVec(defs.size() + 1, [&](
size_t i) { return i == 0 ? def : defs[i - 1]; });
108 DefVec result(a.size() + b.size());
109 auto [_, o] = std::ranges::copy(a, result.begin());
110 std::ranges::copy(b, o);
120 auto& w = def->
world();
122 auto a = sigma->num_ops();
123 auto tuple =
DefVec(a, [&](
auto i) {
return w.extract(def, a, i); });
124 return w.tuple(
merge(tuple, defs));
131 auto& world = t->world();
132 if (
auto sigma = t->isa<
Sigma>())
return world.tuple(sigma->ops());
133 if (
auto arr = t->isa<
Arr>())
return world.pack(arr->shape(), arr->body());
A (possibly paramterized) Array.
const Def * shape() const final
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
constexpr auto ops() 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).
std::optional< nat_t > isa_lit_arity() const
const Def * arity() const
const T * isa_imm() const
static std::optional< T > isa(const Def *def)
static T as(const Def *def)
const Def * prod(World &, Defs) const final
Creates either a Tuple or Sigma.
const Def * shape() const final
const Def * rebuild(World &w, const Def *shape, const Def *body) const final
Def(World *, Node, const Def *type, Defs ops, flags_t flags)
Constructor for an immutable Def.
const Def * sigma(Defs ops)
const Def * tuple(Defs ops)
Flags & flags()
Retrieve compile Flags.
const Def * flatten(const Def *def)
Flattens a sigma/array/pack/tuple.
Vector< const Def * > DefVec
bool is_unit(const Def *)
uint64_t scalarize_threshold
const Def * merge_sigma(const Def *def, Defs defs)
std::string tuple2str(const Def *)
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)
const Def * merge_tuple(const Def *def, Defs defs)