11bool isa_cnt(
const App* body, Ref def,
size_t i) {
12 return Pi::isa_returning(body->callee_type()) && body->arg() == def && i == def->num_ops() - 1;
15Ref isa_br(
const App* body, Ref def) {
16 if (!
Pi::isa_cn(body->callee_type()))
return nullptr;
17 auto proj = body->callee()->isa<
Extract>();
18 return (proj && proj->tuple() == def && proj->tuple()->isa<Tuple>()) ? proj->tuple() :
nullptr;
21bool isa_callee_br(
const App* body, Ref def,
size_t i) {
22 if (!
Pi::isa_cn(body->callee_type()))
return false;
23 return isa_callee(def, i) || isa_br(body, def);
26Lam* isa_retvar(Ref def) {
27 if (
auto [var, lam] =
ca_isa_var<Lam>(def); var && lam && var == lam->ret_var())
return lam;
34 if (eta_exp_) lam = eta_exp_->
new2old(lam);
35 return lam2fscope_[lam];
42 scope_ = std::make_unique<Scope>(
curr_mut());
43 for (
auto def : scope_->bound()) {
59 auto arg = app->
arg();
61 if (arg->isa<
Var>())
return app;
63 for (
auto i = 0u; i < arg->num_projs(); i++) {
64 auto op = arg->
proj(i);
66 auto refine = [&](
Ref new_op) {
71 args = arg->
refine(i, new_op);
76 w.DLOG(
"found return var from enclosing scope: {}", op);
80 w.DLOG(
"found BB from enclosing scope {}", op);
83 if (isa_cnt(app, arg, i)) {
86 }
else if (
auto contlam = op->
isa_mut<
Lam>()) {
90 w.DLOG(
"eta expanded return cont: {} -> {}", op, wrapper);
91 return refine(wrapper);
95 if (!isa_callee_br(app, arg, i)) {
97 w.DLOG(
"found firstclass use of BB: {}", bb_lam);
101 if (isa_retvar(op)) {
102 w.DLOG(
"found firstclass use of return var: {}", op);
115 auto branches = br->tuple();
117 if (branches->isa<
Tuple>() && branches->
type()->isa<
Arr>()) {
118 for (
size_t i = 0, e = branches->num_ops(); i != e; ++i) {
119 if (!branches->op(i)->isa_mut<
Lam>()) {
121 w.DLOG(
"eta wrap branch: {} -> {}", branches->op(i), wrapper);
122 branches = branches->refine(i, wrapper);
136 if (
auto app = def->isa<
App>()) {
const Pi * callee_type() const
const Def * callee() const
A (possibly paramterized) Array.
Def * set(size_t i, const Def *def)
Successively set from left to right.
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 * refine(size_t i, const Def *new_op) const
T * isa_mut() const
If this is *mut*able, it will cast constness away and perform a dynamic_cast to T.
void new2old(Lam *new_lam, Lam *old_lam)
static Lam * isa_mut_basicblock(Ref d)
Only for mutables.
static const Pi * isa_returning(Ref d)
Is this a continuation (Pi::isa_cn) which has a Pi::ret_pi?
static const Pi * isa_cn(Ref d)
Is this a continuation - i.e. is the Pi::codom mim::Bottom?
Helper class to retrieve Infer::arg if present.
Data constructor for a Sigma.
const App * rewrite_callee(const App *app)
void enter() override
Invoked just before Pass::rewriteing PassMan::curr_mut's body.
const App * rewrite_arg(const App *app)
Ref eta_wrap(Ref def, attr a)
Ref rewrite(Ref) override
bool from_outer_scope(Lam *lam)
std::tuple< const Extract *, N * > ca_isa_var(Ref def)
Checks is def is the variable of a mut of type N.
const App * isa_callee(const Def *def, size_t i)