7 if (
auto app = lam->
body()->isa<
App>()) {
9 return std::ranges::all_of(app->targs(), [&](
const Def* arg) {
10 if (auto ex = arg->isa<Extract>(); ex && ex->tuple() == var) return true;
11 return arg == var || !arg->has_free_var(var);
20 for (
auto def :
old_world().externals().muts())
24 auto worklist = std::deque<Lam*>();
25 for (
auto [lam, once] : once_)
26 if (!once && trivial_.contains(lam) && !cyclic_.contains(lam)) worklist.emplace_back(lam);
28 while (!worklist.empty()) {
29 auto lam = worklist.front();
31 if (
auto callee = lam->forwardee()) {
32 if (
auto& once = once_[callee]; once) {
34 if (trivial_.contains(callee) && !cyclic_.contains(callee)) worklist.emplace_back(callee);
43 if (
auto [_, ins] = analyzed_.emplace(def); !ins) {
45 if (on_stack_.contains(def))
47 if (
auto lam = mut->isa<
Lam>()) cyclic_.emplace(lam);
51 on_stack_.emplace(def);
52 for (
auto d : def->
deps())
57void BetaRed::visit(
const Def* def,
bool candidate) {
58 if (
auto lam = def->isa_mut<Lam>()) {
59 if (
auto [i, ins] = once_.emplace(lam, candidate); !ins)
62 trivial_.emplace(lam);
69 return reduce(old_lam, app->
arg());
73const Def* BetaRed::reduce(
Lam* old_lam,
const Def* old_arg) {
75 log().d(
"β-reduction `{}`", old_lam);
78 if (
auto var = old_lam->
has_var(); var && is_once(old_lam)) {
const Def * callee() const
const Def * rewrite_imm_App(const App *) final
bool analyze() final
Runs the optional pre-analysis on old_world(), typically to a fixed point, before rewriting begins.
Defs deps() const noexcept
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
bool has_free_var(const Var *) const
Same as free_vars().contains(var).
Muts local_muts() const
Mutables reachable by following immutable deps(); mut->local_muts() is by definition the set { mut }...
const Var * has_var()
Only returns not nullptr, if Var of this mutable has ever been created.
const Def * reduce_body(const Def *arg) const
const Def * ret_var()
Yields the Lam::var of the Lam::ret_pi.
void invalidate(bool todo=true)
Signals that another round of fixed-point iteration is required, either as part of.
const fe::Log & log() const
void profile_count(std::string_view key, uint64_t n=1)
Adds n to the custom fe::Profiler counter key of the current run; no-op unless profiling is enabled.
World & old_world()
Get old Defs from here.
const Def * rewrite_imm_App(const App *) override
const Def * map(const Def *old_def, const Def *new_def)
virtual const Def * rewrite(const Def *)
static bool is_trivial(Lam *lam)