9bool interesting_type(
const Def* type,
DefSet& visited) {
10 if (
type->isa_mut()) visited.insert(type);
13 return std::ranges::any_of(sigma->ops(),
14 [&](
auto d) { return !visited.contains(d) && interesting_type(d, visited); });
15 if (
auto arr =
type->isa<
Arr>())
return interesting_type(arr->body(), visited);
19bool interesting_type(
const Def* def) {
21 return interesting_type(def->type(), visited);
24void split(
DefSet& out,
const Def* def,
bool as_callee) {
25 if (
auto lam = def->isa<
Lam>()) {
28 if (var->type()->isa<
Pi>() || interesting_type(var)) out.insert(var);
30 split(out,
c.fnc(), as_callee);
32 split(out,
a->arg(), as_callee);
33 }
else if (
auto proj = def->isa<
Extract>()) {
34 split(out, proj->tuple(), as_callee);
35 }
else if (
auto pack = def->isa<
Pack>()) {
36 split(out, pack->body(), as_callee);
37 }
else if (
auto tuple = def->isa<
Tuple>()) {
38 for (
auto op : tuple->ops())
39 split(out, op, as_callee);
40 }
else if (as_callee) {
45DefSet split(
const Def* def,
bool keep_others) {
47 split(out, def, keep_others);
53bool LowerTypedClosPrep::set_esc(
const Def* def) {
55 for (
auto d : split(def,
false)) {
56 if (is_esc(d))
continue;
57 DLOG(
"set esc: {}", d);
68 auto visit = [&](
auto&& visit,
const Def* def) ->
void {
69 if (!done.emplace(def).second)
return;
72 DLOG(
"closure ({}, {})", c.env(), c.fnc());
73 if (!c.fnc_as_lam() || is_esc(c.fnc_as_lam()) || is_esc(c.env_var())) changed |= set_esc(c.env());
75 DLOG(
"store {}", store->arg(2));
76 changed |= set_esc(store->arg(2));
77 }
else if (
auto app = def->isa<
App>(); app &&
Pi::isa_cn(app->callee_type())) {
79 auto callees = split(app->callee(),
true);
80 for (
auto i = 0_u64; i < app->num_args(); i++) {
81 if (!interesting_type(app->arg(i)))
continue;
82 if (std::ranges::any_of(callees, [&](
const Def* callee) {
83 if (
auto lam = callee->
isa_mut<
Lam>())
return is_esc(lam->var(i));
86 changed |= set_esc(app->arg(i));
90 if (
auto mut = def->isa_mut()) {
92 for (
auto op : mut->deps())
95 for (
auto op : def->deps())
109 auto fnc = closure.fnc();
116 return RWPhase::rewrite_imm_Tuple(
tuple);
static auto isa(const Def *def)
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
static const Pi * isa_cn(const Def *d)
Is this a continuation - i.e. is the Pi::codom mim::Bottom?
World & new_world()
Create new Defs into this.
bool is_bootstrapping() const
Returns whether we are currently bootstrapping (rewriting annexes).
World & old_world()
Get old Defs from here.
virtual const Def * rewrite(const Def *)
Data constructor for a Sigma.
const Def * call(const Def *callee, T &&arg, Args &&... args)
const Def * rewrite_imm_Tuple(const Tuple *) final
bool analyze() final
One escape-propagation round over the old world; RWPhase::start() iterates until fixpoint.
#define DLOG(...)
Vaporizes to nothingness in Debug build.
ClosLit isa_clos_lit(const Def *def, bool fn_isa_lam=true)
Tries to match a closure literal.
std::tuple< const Extract *, N * > isa_var_proj(const Def *def)
If def is a projection var#i of the Var of some mutable of type N, returns (projection,...
const Def * clos_pack(const Def *env, const Def *fn, const Def *ct=nullptr)
Pack a typed closure.
const Sigma * isa_clos_type(const Def *def)
GIDSet< const Def * > DefSet