11bool isa_cnt(
const App* body, Ref def,
size_t i) {
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)) {
84 if (match<attr>(
attr::ret, op) || isa_retvar(op)) {
86 }
else if (
auto contlam = op->
isa_mut<
Lam>()) {
87 return refine(w.call(
attr::ret, contlam));
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);
134 if (ignore_ || match<attr>(def))
return def;
136 if (
auto app = def->isa<
App>()) {
const Def * callee() const
const Pi * callee_type() const
A (possibly paramterized) Array.
const Def * refine(size_t i, const Def *new_op) const
const Def * type() const
Yields the raw type of this Def, i.e. maybe nullptr.
T * isa_mut() const
If this is *mut*able, it will cast constness away and perform a dynamic_cast to T.
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.
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 thorin::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)
bool from_outer_scope(Lam *lam)
Ref eta_wrap(Ref def, attr a)
Ref rewrite(Ref) override
const App * isa_callee(const Def *def, size_t i)