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;
23bool mut_val_or_typ(
const Def* def) {
24 auto typ = def->is_term() ? def->type() : def;
25 return typ->isa_mut();
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);
42 if (
auto arr =
type()->isa<Arr>())
return arr->shape();
50 if (def ==
nullptr)
return {};
52 auto array = def->
projs(
Lit::as(def->
arity()), [](
auto op) { return Lit::as(op); });
53 return std::string(array.begin(), array.end());
57 if (
auto a = def->
isa_lit_arity(); a && *a != 1 && should_flatten(def) && flatten_muts == mut_val_or_typ(def)) {
59 for (
size_t i = 0; i != *a; ++i) n +=
flatten(ops, def->
proj(*a, i), flatten_muts);
62 ops.emplace_back(def);
68 if (!should_flatten(def))
return def;
76 auto def =
unflatten(defs, type, j, flatten_muts);
77 assert(j == defs.size());
84 return DefVec(defs.size() + 1, [&](
auto i) { return i == 0 ? def : defs[i - 1]; });
88 DefVec result(a.size() + b.size());
89 auto [_, o] = std::ranges::copy(a, result.begin());
90 std::ranges::copy(b, o);
100 auto& w = def->
world();
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));
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());
A (possibly paramterized) Array.
std::optional< nat_t > isa_lit_arity() const
auto projs(F f) const
Splits this Def via Def::projections into an Array (if A == -1_n) or std::array (otherwise).
const T * isa_imm() const
const Def * type() const
Yields the raw type of this Def, i.e. maybe nullptr.
bool is_term() const
Yields true if this:T and T:(.Type 0).
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.
const Def * shape() const
Helper class to retrieve Infer::arg if present.
This is a thin wrapper for std::span<T, N> with the following additional features:
Ref tuple_of_types(Ref t)
const Def * flatten(const Def *def)
Flattens a sigma/array/pack/tuple.
const Def * merge_tuple(const Def *def, Defs defs)
bool is_unit(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 * merge_sigma(const Def *def, Defs defs)
Vector< const Def * > DefVec
std::string tuple2str(const Def *)