21 : Def(
Node,
type, 2, implicit ? 1 : 0) {}
29 if (
auto pi = d->isa<
Pi>(); pi && pi->is_implicit())
return pi;
38 const Def*
dom()
const {
return op(0); }
39 const Def*
codom()
const {
return op(1); }
50 static const
Pi*
isa_cn (const Def* d) {
auto pi = d->isa<
Pi>();
return pi && pi->codom()->
node() ==
Node::Bot ? pi :
nullptr; }
51 static const Pi*
isa_returning (
const Def* d) {
auto pi =
isa_cn(d);
return pi && pi->ret_pi() ? pi :
nullptr; }
91class Lam :
public Def,
public Setters<Lam> {
96 : Def(
Node, pi, 2, 0) {}
99 using Filter = std::variant<bool, const Def*>;
104 const Def*
body()
const {
return op(1); }
125 static const Lam*
isa_cn (const Def* d) {
auto lam = d->isa <Lam>();
return lam &&
Pi::isa_cn (lam->type()) ? lam :
nullptr; }
128 static Lam*
isa_mut_cn (
const Def* d) {
auto lam = d->isa_mut<Lam>();
return lam &&
Pi::isa_cn (lam->type()) ? lam :
nullptr; }
137 if (!
ret_pi())
return nullptr;
139 return var(n, n - 1);
194 if (
auto lam = def->
isa_mut<Lam>(); lam && lam->is_rewritable())
return lam;
225 static auto uncurry_args_(
const Def* def) {
226 auto args = std::array<const Def*, N>();
227 for (
size_t i = N; i-- != 0;)
228 if (
auto app = def->isa<App>())
args[i] = app->arg(), def = app->callee();
242 auto app = def->isa<App>();
243 return app ? app->callee() :
nullptr;
251 const Def*
arg()
const {
return op(1); }
274 template<
size_t N>
static auto uncurry_args(
const Def* def) {
return uncurry_args_<N>(def ); }
275 template<
size_t N>
auto uncurry_args()
const {
return uncurry_args_<N>(
this); }
278 static const Def*
uncurry_callee(
const Def* def) {
while (
auto app = def->isa<App>()) def = app->callee();
return def; }
static constexpr size_t Num_Ops
static const Def * uncurry_callee(const Def *def)
The innermost App::callee - the one that isn't an App itself.
const Pi * callee_type() const
auto args(Projector auto f) const noexcept
const App * decurry() const
Returns App::callee again as App.
static constexpr auto Node
const Def * callee() const
static auto uncurry_args(const Def *def)
static const Def * callee_of(const Def *def)
The App::callee of def - or nullptr, if def isn't an App at all.
const Def * uncurry_callee() const
auto uncurry_args() const
constexpr Node node() const noexcept
Def * set(size_t i, const Def *)
Successively set from left to right.
constexpr auto ops() const noexcept
constexpr flags_t flags() 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
const Def * var(nat_t a, nat_t i) noexcept
nat_t num_vars() noexcept
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
bool is_external() const noexcept
Def * unset()
Unsets all Def::ops; works even, if not set at all or only partially set.
constexpr auto reduce(const Def *arg) const
const Var * has_var()
Only returns not nullptr, if Var of this mutable has ever been created.
bool is_annex() const noexcept
std::variant< bool, const Def * > Filter
const Def * filter() const
static const Lam * isa_cn(const Def *d)
static constexpr size_t Num_Ops
Lam * forwardee() const
λ x = f arg where f is a mut Lam that is_set();
Lam * set(Filter filter, const Def *body)
static Lam * eta_expand(Filter, const Def *f)
Lam * set_filter(Filter)
Set filter first.
static Lam * isa_mut_basicblock(const Def *d)
static const Lam * isa_returning(const Def *d)
const Pi * ret_pi() const
static Lam * isa_mut_returning(const Def *d)
static constexpr auto Node
static const Def * eta_reduce(const Def *def)
Fast-forwards def along its chain of η-redexes λ x = f x where x ∉ FV(f).
static const Lam * isa_basicblock(const Def *d)
Lam * branch(Filter filter, const Def *cond, const Def *t, const Def *f, const Def *arg=nullptr)
Set body to an App of (f, t)#cond mem or (f, t)#cond () if mem is nullptr.
bool is_dependent() const
Does this type() itself or dom() has a Var?
Lam * app(Filter filter, const Def *callee, const Def *arg)
Set body to an App of callee and arg.
const Def * ret_dom() const
Lam * set_body(const Def *body)
Set body second.
static Lam * isa_rewritable(const Def *def)
Yields def as a mutable Lam, if it is_rewritable() and nullptr otherwise.
static Lam * isa_mut_cn(const Def *d)
static const Def * isa_ret_arg(const Def *d)
Yields the y of λ (x, ret) = ret y - the argument d's body hands to its Lam::ret_var.
static Lam * eta_expand(const Def *f)
Use true Filter.
const Def * reduce_body(const Def *arg) const
const Def * ret_var()
Yields the Lam::var of the Lam::ret_pi.
const Def * codom() const
A dependent function type.
const Def * ret_dom() const
Pi::domain of Pi::ret_pi.
Pi(const Def *type, bool implicit)
Constructor for a mutable Pi.
Pi * set_codom(const Def *codom)
static constexpr size_t Num_Ops
Pi(const Def *type, const Def *dom, const Def *codom, bool implicit)
Constructor for an immutable Pi.
static const Pi * isa_cn(const Def *d)
static const Pi * isa_basicblock(const Def *d)
static const Def * infer(const Def *dom, const Def *codom)
const Def * codom() const
static const Pi * isa_implicit(const Def *d)
Is d an Pi::is_implicit Pi?
Pi * set(const Def *dom, const Def *codom)
auto doms() const noexcept
static constexpr auto Node
const Def * reduce(const Def *arg) const
const Pi * ret_pi() const
Yields the last Pi::dom, if Pi::isa_basicblock.
Pi * set_dom(const Def *dom)
static const Pi * isa_returning(const Def *d)
CRTP-based mixin to declare setters for Def::loc & Def::name using a covariant return type.
#define MIM_PROJ(NAME, CONST)
Use as mixin to wrap all kind of Def::proj and Def::projs variants.
ankerl::unordered_dense::map< K, V, GIDHash< K > > GIDMap
fe::View< const Def * > Defs
GIDMap< Lam *, To > LamMap
ankerl::unordered_dense::set< K, GIDHash< K > > GIDSet