perf(kernel/replace_fn): use 'recursive' replace_fn for "small" terms

This commit is contained in:
Leonardo de Moura 2014-10-17 14:15:09 -07:00
parent c21c8c582f
commit b6afbcb7f5

View file

@ -197,7 +197,65 @@ public:
} }
}; };
class replace_rec_fn {
replace_cache_ref m_cache;
std::function<optional<expr>(expr const &, unsigned)> m_f;
expr save_result(expr const & e, unsigned offset, expr const & r, bool shared) {
if (shared)
m_cache->insert(e, offset, r);
return r;
}
expr apply(expr const & e, unsigned offset) {
bool shared = false;
if (is_shared(e)) {
if (auto r = m_cache->find(e, offset))
return *r;
shared = true;
}
if (optional<expr> r = m_f(e, offset)) {
return save_result(e, offset, *r, shared);
} else {
switch (e.kind()) {
case expr_kind::Constant: case expr_kind::Sort: case expr_kind::Var:
return save_result(e, offset, e, shared);
case expr_kind::Meta: case expr_kind::Local: {
expr new_t = apply(mlocal_type(e), offset);
return save_result(e, offset, update_mlocal(e, new_t), shared);
}
case expr_kind::App: {
expr new_f = apply(app_fn(e), offset);
expr new_a = apply(app_arg(e), offset);
return save_result(e, offset, update_app(e, new_f, new_a), shared);
}
case expr_kind::Pi: case expr_kind::Lambda: {
expr new_d = apply(binding_domain(e), offset);
expr new_b = apply(binding_body(e), offset+1);
return save_result(e, offset, update_binding(e, new_d, new_b), shared);
}
case expr_kind::Macro: {
buffer<expr> new_args;
unsigned nargs = macro_num_args(e);
for (unsigned i = 0; i < nargs; i++)
new_args.push_back(apply(macro_arg(e, i), offset));
return save_result(e, offset, update_macro(e, new_args.size(), new_args.data()), shared);
}}
lean_unreachable();
}
}
public:
template<typename F>
replace_rec_fn(F const & f):m_f(f) {}
expr operator()(expr const & e) { return apply(e, 0); }
};
expr replace(expr const & e, std::function<optional<expr>(expr const &, unsigned)> const & f) { expr replace(expr const & e, std::function<optional<expr>(expr const &, unsigned)> const & f) {
if (get_weight(e) < 10000)
return replace_rec_fn(f)(e);
else
return replace_fn(f)(e); return replace_fn(f)(e);
} }
} }