30 for (
auto external :
world().externals().muts())
31 if (
auto lam = external->isa_mut<
Lam>()) {
32 current_external_ = lam;
41const Def* CPS2DSPhase::rewrite_lam(
Lam* lam) {
42 if (
auto i = rewritten_.find(lam); i != rewritten_.end())
return i->second;
43 if (lam2lam_.contains(lam))
return lam;
45 world().DLOG(
"skipped {}", lam);
53 auto filter = rewrite(lam->
filter());
55 if (
auto body = lam->
body()->isa<
App>(); !body) {
56 world().DLOG(
" non-app body {}, skipped", lam->
body());
57 auto new_body = rewrite(lam->
body());
59 return rewritten_[lam] = lam;
62 auto body = lam->
body()->as<
App>();
63 auto new_arg = rewrite(body->arg());
65 auto new_callee = rewrite(body->callee());
66 auto new_lam = result_lam(lam);
68 world().DLOG(
"Result of rewrite {} set for {}", lam->
unique_name(), new_lam->unique_name());
73 new_lam->unset()->app(filter, new_callee, new_arg);
75 return rewritten_[lam] = lam;
78const Def* CPS2DSPhase::rewrite(
const Def* def) {
79 if (
auto i = rewritten_.find(def); i != rewritten_.end())
return i->second;
81 if (
auto lam = def->isa_mut<
Lam>())
return rewrite_lam(lam);
83 if (
auto app = def->isa<
App>()) {
85 auto cps_lam = rewrite(
cps2ds->arg())->as<
Lam>();
87 auto call_arg = rewrite(app->arg());
94 auto early = scheduler(app).early(app);
95 auto late = scheduler(app).late(current_external_, app);
98 world().DLOG(
"scheduling {} between {} (level {}) and {} (level {}) at {}", app,
99 early->mut() ? early->mut()->unique_name() :
"root", early->level(),
100 late->mut() ? late->mut()->unique_name() :
"root", late->level(),
101 node->mut() ? node->mut()->unique_name() :
"root");
103 auto lam = result_lam(node->mut()->as_mut<
Lam>());
109 auto cn_dom = cps_lam->ret_dom();
110 auto cont = make_continuation(cn_dom, app, cps_lam->sym());
112 world().DLOG(
"continuation created: {} : {}", cont, cont->type());
116 auto filter = rewritten_[lam->
filter()] = rewrite(lam->
filter());
117 auto body =
world().
app(cps_lam,
world().tuple({call_arg, cont}));
118 rewritten_[lam] = lam->
unset()->
set(filter, body);
119 lam2lam_[lam] = cont;
134 DefVec new_ops{def->ops(), [
this](
const Def*
d) {
return rewrite(d); }};
135 auto new_def = def->rebuild(def->type(), new_ops);
136 rewritten_[def] = new_def;
140Lam* CPS2DSPhase::make_continuation(
const Def* cn_type,
const Def* arg, Sym prefix) {
142 world().DLOG(
"make_continuation {} : {} ({})", prefix, cn_type, arg);
148 rewritten_[arg] = cont->
var();
153Lam* CPS2DSPhase::result_lam(
Lam* lam) {
154 if (
auto i = lam2lam_.find(lam); i != lam2lam_.end())
155 if (i->second != lam)
return result_lam(i->second);
159Scheduler& CPS2DSPhase::scheduler(
const Def* def) {
160 auto get_or_make = [&](
const Def* lam,
const Nest& nest) -> Scheduler& {
161 if (
auto sched = scheduler_.find(lam); sched != scheduler_.end()) {
163 world().DLOG(
"found existing scheduler for {}", lam);
165 return sched->second;
168 world().DLOG(
"creating new scheduler for {}", lam);
170 auto [it, inserted] = scheduler_.
insert({lam, Scheduler(nest)});
174 for (
auto& [lam, nest] : nests_) {
176 world().DLOG(
"looking for scheduler in {} for {}", lam, def);
178 if (nest.contains(def))
return get_or_make(lam, nest);
181 world().DLOG(
"no scheduler found for {}, using current external {}", def, current_external_);
183 return get_or_make(current_external_, curr_external_nest());
186const Nest& CPS2DSPhase::curr_external_nest()
const {
187 auto i = nests_.find(current_external_);
188 assert(i != nests_.end());
static auto isa(const Def *def)
bool is_set() const
Yields true if empty or the last op is set.
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
const Def * var(nat_t a, nat_t i) noexcept
std::string unique_name() const
name + "_" + Def::gid
const T * isa_imm() const
const Def * filter() const
Lam * set(Filter filter, const Def *body)
Lam * set_filter(Filter)
Set filter first.
const Def * codom() const
Builds a nesting tree of all immutables‍/binders.
static const Node * lca(const Node *n, const Node *m)
Least common ancestor of n and m.
std::string_view name() const
const Def * insert(const Def *d, const Def *i, const Def *val)
const Def * app(const Def *callee, const Def *arg)
void for_each(bool elide_empty, std::function< void(Def *)>)
void debug_dump()
Dump in Debug build if World::log::level is Log::Level::Debug.
Sym append_suffix(Sym name, std::string suffix)
Appends a suffix or an increasing number if the suffix already exists.
const Def * var(Def *mut)
Lam * mut_con(const Def *dom)
void dump(std::ostream &os)
Dump to os.
void start() final
Actual entry.
Vector< const Def * > DefVec