14 :
Shape(w.tuple(shape)) {}
17 auto t = def_ ? def_->unfold_type() :
nullptr;
20 return t->zonk_mut()->isa<
Nat>();
26 if (!def_ ||
is_dim())
return def_;
27 if (
auto r =
rank())
return def_->
proj(*r, 0);
29 auto& w = def_->world();
30 return w.extract(def_, w.lit(w.type_idx(def_->arity()), 0));
40 if (leaf(type))
return true;
41 if (
auto sigma = type->isa<
Sigma>())
return std::ranges::all_of(sigma->ops(), leaf);
42 if (
auto arr = type->isa<
Arr>())
return leaf(arr->body()->zonk());
47 return isa_axes(type, [](
const Def* l) {
return l->isa<
Nat>() !=
nullptr; });
57 if (begin == 0 && end == *r)
return *
this;
58 return def_->world().tuple(
DefVec(end - begin, [&](
size_t i) {
return def_->proj(*r, begin + i); }));
67 if (!def_ || !other)
return {};
77 if (!shape.rank())
return *
this;
78 assert(
rank() == shape.rank() &&
"an index folds against the shape of the very Seq it indexes");
100 auto app = def->isa<
App>();
116 auto& w = def->
world();
117 auto res = std::string();
120 for (
size_t i = 0; i != *n; ++i) {
121 auto elem = def->
proj(*n, i);
122 if (elem->type() == w.type_i8()) {
140 res.reserve(a.size() + b.size());
147 return DefVec(n + m, [=](
size_t i) {
return i < n ? a->proj(n, i) : b->
proj(m, i - n); });
151 auto& w = a->world();
155 && sb->is_intro() == term && sa->elem() == sb->elem())
156 return w.seq(term, n + m, sa->elem());
158 return w.prod(term,
cat_projs(n, m, a, b));
164 return n && m ?
cat(term, *n, *m, a, b) :
nullptr;
168 auto& world = t->world();
169 if (
auto sigma = t->isa<
Sigma>())
return world.tuple(sigma->ops());
170 if (
auto arr = t->isa<
Arr>()) {
172 if (
auto elem = arr->elem())
return world.pack(arr->arity(), elem);
const Def * callee() const
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
static DefVec cat(Defs a, Defs b)
const Def * unfold_type() const
Yields the type of this Def and builds a new Type (UInc n) if necessary.
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
const Def * arity() const
Number of elements available to Extract / Insert (may be dynamic).
const T * isa_imm() const
const Def * callee() const
const Extract * extract() const
static const Def * isa(const Def *def)
Checks if def is a Idx s and returns s or nullptr otherwise.
static std::optional< T > isa(const Def *def)
static DefVec cat_projs(nat_t n, nat_t m, const Def *a, const Def *b)
The spliced components themselves - for when you want to build something other than a Prod from them.
static const Def * cat(bool term, nat_t n, nat_t m, const Def *a, const Def *b)
Def(World *, Node, const Def *type, Defs ops, flags_t flags)
Constructor for an immutable Def.
const Extract * extract() const
Base class for Arr and Pack.
const Def * elem() const
The element one axis down: Seq::body for a one-dimensional Seq, the Seq of the remaining axes otherwi...
Def(World *, Node, const Def *type, Defs ops, flags_t flags)
Constructor for an immutable Def.
std::optional< nat_t > rank() const
Number of axes; std::nullopt if not statically known.
bool is_fused() const
Does this span several axes? Also true for a dynamic rank.
static std::optional< nat_t > extent(const Def *axis)
The extent of axis: the axis itself for a shape, its Idx size for an index.
const Def * front() const
The outermost axis - the Def::arity of the Seq this shape describes; null for a null Shape.
Shape operator+(Shape) const
Concatenation - what fuses «a; «b; T»» into «a, b; T».
bool is_dim() const
Is this a single axis - a Nat/Idx rather than an aggregate of them?
Shape slice(nat_t begin, nat_t end) const
The axes [begin, end).
Shape fold() const
Drops every literal size-1 axis, mirroring «1; T» ≡ T; all of them folded away leaves rank 0.
static bool isa_extents(const Def *)
Is type Nat - or an aggregate of Nats, i.e. a shape?
Shape drop(nat_t n) const
All but the leading n axes.
Shape filter(auto keep) const
This Shape with only the axes keep accepts; *this, if it accepts all of them or the rank is dynamic.
constexpr Shape() noexcept=default
static bool isa_indices(const Def *)
Is type Idx - or an aggregate of Idxs, i.e. a fused index?
static const Def * cat(nat_t n, nat_t m, const Def *a, const Def *b)
The World represents the whole program and manages creation of MimIR nodes (Defs).
const Def * sigma(Defs ops)
const Def * drop(const Seq *s, nat_t k)
s without its leading k axes - its body once k covers all of them; nullptr if that isn't a type.
bool is_unit(const Def *)
fe::View< const Def * > Defs
std::string tuple2str(const Def *)
static bool isa_axes(const Def *type, auto leaf)
Is type a leaf - or an aggregate of them? This is what makes a shape a shape and an index an index.
const Def * tuple_of_types(const Def *t)
fe::Vector< const Def * > DefVec