2014-05-20 16:40:30 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
2015-02-06 21:27:10 +00:00
|
|
|
#include <string>
|
2014-10-27 23:49:29 +00:00
|
|
|
#include "util/interrupt.h"
|
2014-05-20 16:40:30 +00:00
|
|
|
#include "util/name_generator.h"
|
|
|
|
#include "kernel/type_checker.h"
|
|
|
|
#include "kernel/instantiate.h"
|
|
|
|
#include "kernel/abstract.h"
|
2015-03-12 07:31:10 +00:00
|
|
|
#include "kernel/free_vars.h"
|
2014-12-15 02:49:48 +00:00
|
|
|
#include "kernel/inductive/inductive.h"
|
2014-09-27 03:16:03 +00:00
|
|
|
#include "library/reducible.h"
|
2015-02-06 20:12:52 +00:00
|
|
|
#include "library/util.h"
|
|
|
|
#include "library/scoped_ext.h"
|
|
|
|
#include "library/kernel_serializer.h"
|
2014-05-20 16:40:30 +00:00
|
|
|
|
|
|
|
namespace lean {
|
2015-02-06 20:12:52 +00:00
|
|
|
/**
|
2015-04-05 09:47:37 +00:00
|
|
|
\brief unfold hints instruct the normalizer (and simplifier) that
|
|
|
|
a function application. We have two kinds of hints:
|
|
|
|
- unfold_c (f a_1 ... a_i ... a_n) should be unfolded
|
|
|
|
when argument a_i is a constructor.
|
|
|
|
- unfold_f (f a_1 ... a_i ... a_n) should be unfolded when it is fully applied.
|
2015-05-07 18:56:42 +00:00
|
|
|
- constructor (f ...) should be unfolded when it is the major premise of a recursor-like operator
|
2015-02-06 20:12:52 +00:00
|
|
|
*/
|
2015-04-05 09:47:37 +00:00
|
|
|
struct unfold_hint_entry {
|
2015-05-04 21:23:04 +00:00
|
|
|
enum kind {UnfoldC, UnfoldF, UnfoldM};
|
|
|
|
kind m_kind; //!< true if it is an unfold_c hint
|
|
|
|
bool m_add; //!< add/remove hint
|
2015-04-05 09:47:37 +00:00
|
|
|
name m_decl_name;
|
|
|
|
unsigned m_arg_idx;
|
2015-05-04 21:23:04 +00:00
|
|
|
unfold_hint_entry():m_kind(UnfoldC), m_add(false), m_arg_idx(0) {}
|
|
|
|
unfold_hint_entry(kind k, bool add, name const & n, unsigned idx):
|
|
|
|
m_kind(k), m_add(add), m_decl_name(n), m_arg_idx(idx) {}
|
2015-02-06 20:12:52 +00:00
|
|
|
};
|
|
|
|
|
2015-05-04 21:23:04 +00:00
|
|
|
unfold_hint_entry mk_add_unfold_c_entry(name const & n, unsigned idx) { return unfold_hint_entry(unfold_hint_entry::UnfoldC, true, n, idx); }
|
|
|
|
unfold_hint_entry mk_erase_unfold_c_entry(name const & n) { return unfold_hint_entry(unfold_hint_entry::UnfoldC, false, n, 0); }
|
|
|
|
unfold_hint_entry mk_add_unfold_f_entry(name const & n) { return unfold_hint_entry(unfold_hint_entry::UnfoldF, true, n, 0); }
|
|
|
|
unfold_hint_entry mk_erase_unfold_f_entry(name const & n) { return unfold_hint_entry(unfold_hint_entry::UnfoldF, false, n, 0); }
|
2015-05-07 18:56:42 +00:00
|
|
|
unfold_hint_entry mk_add_constructor_entry(name const & n) { return unfold_hint_entry(unfold_hint_entry::UnfoldM, true, n, 0); }
|
|
|
|
unfold_hint_entry mk_erase_constructor_entry(name const & n) { return unfold_hint_entry(unfold_hint_entry::UnfoldM, false, n, 0); }
|
2015-04-05 09:47:37 +00:00
|
|
|
|
|
|
|
static name * g_unfold_hint_name = nullptr;
|
2015-02-06 20:12:52 +00:00
|
|
|
static std::string * g_key = nullptr;
|
|
|
|
|
2015-04-05 09:47:37 +00:00
|
|
|
struct unfold_hint_state {
|
|
|
|
name_map<unsigned> m_unfold_c;
|
|
|
|
name_set m_unfold_f;
|
2015-05-07 18:56:42 +00:00
|
|
|
name_set m_constructor;
|
2015-04-05 09:47:37 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct unfold_hint_config {
|
|
|
|
typedef unfold_hint_state state;
|
|
|
|
typedef unfold_hint_entry entry;
|
2015-02-06 20:12:52 +00:00
|
|
|
|
|
|
|
static void add_entry(environment const &, io_state const &, state & s, entry const & e) {
|
2015-05-04 21:23:04 +00:00
|
|
|
switch (e.m_kind) {
|
|
|
|
case unfold_hint_entry::UnfoldC:
|
2015-04-05 09:47:37 +00:00
|
|
|
if (e.m_add)
|
|
|
|
s.m_unfold_c.insert(e.m_decl_name, e.m_arg_idx);
|
|
|
|
else
|
|
|
|
s.m_unfold_c.erase(e.m_decl_name);
|
2015-05-04 21:23:04 +00:00
|
|
|
break;
|
|
|
|
case unfold_hint_entry::UnfoldF:
|
2015-04-05 09:47:37 +00:00
|
|
|
if (e.m_add)
|
|
|
|
s.m_unfold_f.insert(e.m_decl_name);
|
|
|
|
else
|
|
|
|
s.m_unfold_f.erase(e.m_decl_name);
|
2015-05-04 21:23:04 +00:00
|
|
|
break;
|
|
|
|
case unfold_hint_entry::UnfoldM:
|
|
|
|
if (e.m_add)
|
2015-05-07 18:56:42 +00:00
|
|
|
s.m_constructor.insert(e.m_decl_name);
|
2015-05-04 21:23:04 +00:00
|
|
|
else
|
2015-05-07 18:56:42 +00:00
|
|
|
s.m_constructor.erase(e.m_decl_name);
|
2015-05-04 21:23:04 +00:00
|
|
|
break;
|
2015-04-05 09:47:37 +00:00
|
|
|
}
|
2015-02-06 20:12:52 +00:00
|
|
|
}
|
|
|
|
static name const & get_class_name() {
|
2015-04-05 09:47:37 +00:00
|
|
|
return *g_unfold_hint_name;
|
2015-02-06 20:12:52 +00:00
|
|
|
}
|
|
|
|
static std::string const & get_serialization_key() {
|
|
|
|
return *g_key;
|
|
|
|
}
|
|
|
|
static void write_entry(serializer & s, entry const & e) {
|
2015-05-04 21:23:04 +00:00
|
|
|
s << static_cast<char>(e.m_kind) << e.m_add << e.m_decl_name << e.m_arg_idx;
|
2015-02-06 20:12:52 +00:00
|
|
|
}
|
|
|
|
static entry read_entry(deserializer & d) {
|
2015-05-04 21:23:04 +00:00
|
|
|
char k;
|
2015-02-06 20:12:52 +00:00
|
|
|
entry e;
|
2015-05-04 21:23:04 +00:00
|
|
|
d >> k >> e.m_add >> e.m_decl_name >> e.m_arg_idx;
|
|
|
|
e.m_kind = static_cast<unfold_hint_entry::kind>(k);
|
2015-02-06 20:12:52 +00:00
|
|
|
return e;
|
|
|
|
}
|
|
|
|
static optional<unsigned> get_fingerprint(entry const & e) {
|
|
|
|
return some(e.m_decl_name.hash());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-04-05 09:47:37 +00:00
|
|
|
template class scoped_ext<unfold_hint_config>;
|
|
|
|
typedef scoped_ext<unfold_hint_config> unfold_hint_ext;
|
2015-02-06 20:12:52 +00:00
|
|
|
|
2015-04-05 09:47:37 +00:00
|
|
|
environment add_unfold_c_hint(environment const & env, name const & n, unsigned idx, bool persistent) {
|
2015-02-06 20:42:53 +00:00
|
|
|
declaration const & d = env.get(n);
|
2015-05-08 22:42:42 +00:00
|
|
|
if (!d.is_definition())
|
2015-02-06 20:42:53 +00:00
|
|
|
throw exception("invalid unfold-c hint, declaration must be a non-opaque definition");
|
2015-04-05 09:47:37 +00:00
|
|
|
return unfold_hint_ext::add_entry(env, get_dummy_ios(), mk_add_unfold_c_entry(n, idx), persistent);
|
2015-02-06 20:12:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
optional<unsigned> has_unfold_c_hint(environment const & env, name const & d) {
|
2015-04-05 09:47:37 +00:00
|
|
|
unfold_hint_state const & s = unfold_hint_ext::get_state(env);
|
|
|
|
if (auto it = s.m_unfold_c.find(d))
|
2015-02-06 20:12:52 +00:00
|
|
|
return optional<unsigned>(*it);
|
|
|
|
else
|
|
|
|
return optional<unsigned>();
|
|
|
|
}
|
|
|
|
|
2015-04-05 09:47:37 +00:00
|
|
|
environment erase_unfold_c_hint(environment const & env, name const & n, bool persistent) {
|
|
|
|
return unfold_hint_ext::add_entry(env, get_dummy_ios(), mk_erase_unfold_c_entry(n), persistent);
|
|
|
|
}
|
|
|
|
|
|
|
|
environment add_unfold_f_hint(environment const & env, name const & n, bool persistent) {
|
|
|
|
declaration const & d = env.get(n);
|
2015-05-08 22:42:42 +00:00
|
|
|
if (!d.is_definition())
|
2015-04-05 09:47:37 +00:00
|
|
|
throw exception("invalid unfold-f hint, declaration must be a non-opaque definition");
|
|
|
|
return unfold_hint_ext::add_entry(env, get_dummy_ios(), mk_add_unfold_f_entry(n), persistent);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool has_unfold_f_hint(environment const & env, name const & d) {
|
|
|
|
unfold_hint_state const & s = unfold_hint_ext::get_state(env);
|
|
|
|
return s.m_unfold_f.contains(d);
|
|
|
|
}
|
|
|
|
|
|
|
|
environment erase_unfold_f_hint(environment const & env, name const & n, bool persistent) {
|
|
|
|
return unfold_hint_ext::add_entry(env, get_dummy_ios(), mk_erase_unfold_f_entry(n), persistent);
|
|
|
|
}
|
|
|
|
|
2015-05-07 18:56:42 +00:00
|
|
|
environment add_constructor_hint(environment const & env, name const & n, bool persistent) {
|
|
|
|
env.get(n);
|
|
|
|
return unfold_hint_ext::add_entry(env, get_dummy_ios(), mk_add_constructor_entry(n), persistent);
|
2015-05-04 21:23:04 +00:00
|
|
|
}
|
|
|
|
|
2015-05-07 18:56:42 +00:00
|
|
|
bool has_constructor_hint(environment const & env, name const & d) {
|
2015-05-04 21:23:04 +00:00
|
|
|
unfold_hint_state const & s = unfold_hint_ext::get_state(env);
|
2015-05-07 18:56:42 +00:00
|
|
|
return s.m_constructor.contains(d);
|
2015-05-04 21:23:04 +00:00
|
|
|
}
|
|
|
|
|
2015-05-07 18:56:42 +00:00
|
|
|
environment erase_constructor_hint(environment const & env, name const & n, bool persistent) {
|
|
|
|
return unfold_hint_ext::add_entry(env, get_dummy_ios(), mk_erase_constructor_entry(n), persistent);
|
2015-05-04 21:23:04 +00:00
|
|
|
}
|
|
|
|
|
2015-02-06 20:12:52 +00:00
|
|
|
void initialize_normalize() {
|
2015-04-05 09:47:37 +00:00
|
|
|
g_unfold_hint_name = new name("unfold-hints");
|
|
|
|
g_key = new std::string("unfoldh");
|
|
|
|
unfold_hint_ext::initialize();
|
2015-02-06 20:12:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void finalize_normalize() {
|
2015-04-05 09:47:37 +00:00
|
|
|
unfold_hint_ext::finalize();
|
|
|
|
delete g_unfold_hint_name;
|
2015-02-06 20:12:52 +00:00
|
|
|
delete g_key;
|
|
|
|
}
|
|
|
|
|
2014-05-20 16:40:30 +00:00
|
|
|
class normalize_fn {
|
2014-10-27 21:49:11 +00:00
|
|
|
type_checker & m_tc;
|
|
|
|
name_generator m_ngen;
|
2014-10-27 23:49:29 +00:00
|
|
|
std::function<bool(expr const &)> m_pred; // NOLINT
|
2014-10-27 21:49:11 +00:00
|
|
|
bool m_save_cnstrs;
|
|
|
|
constraint_seq m_cnstrs;
|
2015-03-12 07:31:10 +00:00
|
|
|
bool m_use_eta;
|
2014-05-20 16:40:30 +00:00
|
|
|
|
|
|
|
expr normalize_binding(expr const & e) {
|
|
|
|
expr d = normalize(binding_domain(e));
|
2014-06-30 16:14:55 +00:00
|
|
|
expr l = mk_local(m_ngen.next(), binding_name(e), d, binding_info(e));
|
2014-05-20 16:40:30 +00:00
|
|
|
expr b = abstract(normalize(instantiate(binding_body(e), l)), l);
|
|
|
|
return update_binding(e, d, b);
|
|
|
|
}
|
|
|
|
|
2015-02-06 20:12:52 +00:00
|
|
|
optional<unsigned> has_unfold_c_hint(expr const & f) {
|
|
|
|
if (!is_constant(f))
|
|
|
|
return optional<unsigned>();
|
|
|
|
return ::lean::has_unfold_c_hint(m_tc.env(), const_name(f));
|
|
|
|
}
|
|
|
|
|
2015-04-05 09:47:37 +00:00
|
|
|
bool has_unfold_f_hint(expr const & f) {
|
|
|
|
return is_constant(f) && ::lean::has_unfold_f_hint(m_tc.env(), const_name(f));
|
|
|
|
}
|
|
|
|
|
2015-05-04 21:23:04 +00:00
|
|
|
optional<expr> is_constructor_like(expr const & e) {
|
|
|
|
if (is_constructor_app(m_tc.env(), e))
|
|
|
|
return some_expr(e);
|
|
|
|
expr const & f = get_app_fn(e);
|
2015-05-07 18:56:42 +00:00
|
|
|
if (is_constant(f) && has_constructor_hint(m_tc.env(), const_name(f))) {
|
|
|
|
if (auto r = unfold_app(m_tc.env(), e))
|
|
|
|
return r;
|
|
|
|
else
|
|
|
|
return some_expr(e);
|
2015-05-04 21:23:04 +00:00
|
|
|
} else {
|
|
|
|
return none_expr();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
optional<expr> unfold_recursor_core(expr const & f, unsigned idx, buffer<expr> & args, bool is_rec) {
|
|
|
|
if (idx < args.size()) {
|
|
|
|
expr & arg = args[args.size() - idx - 1];
|
|
|
|
if (optional<expr> new_arg = is_constructor_like(arg)) {
|
|
|
|
flet<expr> set_arg(arg, *new_arg);
|
|
|
|
expr new_app = mk_rev_app(f, args);
|
|
|
|
if (is_rec)
|
|
|
|
return some_expr(normalize(new_app));
|
|
|
|
else if (optional<expr> r = unfold_app(m_tc.env(), new_app))
|
|
|
|
return some_expr(normalize(*r));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return none_expr();
|
|
|
|
}
|
|
|
|
|
|
|
|
optional<expr> unfold_recursor_like(expr const & f, unsigned idx, buffer<expr> & args) {
|
|
|
|
return unfold_recursor_core(f, idx, args, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
optional<expr> unfold_recursor_major(expr const & f, unsigned idx, buffer<expr> & args) {
|
|
|
|
return unfold_recursor_core(f, idx, args, true);
|
|
|
|
}
|
|
|
|
|
2014-05-20 18:53:58 +00:00
|
|
|
expr normalize_app(expr const & e) {
|
|
|
|
buffer<expr> args;
|
2014-12-15 02:49:48 +00:00
|
|
|
bool modified = false;
|
2014-05-20 18:53:58 +00:00
|
|
|
expr f = get_app_rev_args(e, args);
|
2014-12-15 02:49:48 +00:00
|
|
|
for (expr & a : args) {
|
|
|
|
expr new_a = normalize(a);
|
|
|
|
if (new_a != a)
|
|
|
|
modified = true;
|
|
|
|
a = new_a;
|
|
|
|
}
|
2015-04-05 09:47:37 +00:00
|
|
|
if (has_unfold_f_hint(f)) {
|
|
|
|
if (!is_pi(m_tc.whnf(m_tc.infer(e).first).first)) {
|
|
|
|
if (optional<expr> r = unfold_app(m_tc.env(), mk_rev_app(f, args)))
|
|
|
|
return normalize(*r);
|
|
|
|
}
|
|
|
|
}
|
2015-02-06 20:12:52 +00:00
|
|
|
if (auto idx = has_unfold_c_hint(f)) {
|
2015-05-04 21:23:04 +00:00
|
|
|
if (auto r = unfold_recursor_like(f, *idx, args))
|
|
|
|
return *r;
|
|
|
|
}
|
|
|
|
if (is_constant(f)) {
|
|
|
|
if (auto idx = inductive::get_elim_major_idx(m_tc.env(), const_name(f))) {
|
|
|
|
if (auto r = unfold_recursor_major(f, *idx, args))
|
|
|
|
return *r;
|
2015-02-06 20:12:52 +00:00
|
|
|
}
|
|
|
|
}
|
2014-12-15 02:49:48 +00:00
|
|
|
if (!modified)
|
|
|
|
return e;
|
|
|
|
expr r = mk_rev_app(f, args);
|
|
|
|
if (is_constant(f) && inductive::is_elim_rule(m_tc.env(), const_name(f))) {
|
|
|
|
return normalize(r);
|
|
|
|
} else {
|
|
|
|
return r;
|
|
|
|
}
|
2014-05-20 18:53:58 +00:00
|
|
|
}
|
|
|
|
|
2015-03-12 07:31:10 +00:00
|
|
|
expr try_eta(expr const & e) {
|
|
|
|
lean_assert(is_lambda(e));
|
|
|
|
expr const & b = binding_body(e);
|
|
|
|
if (is_lambda(b)) {
|
|
|
|
expr new_b = try_eta(b);
|
|
|
|
if (is_eqp(b, new_b)) {
|
|
|
|
return e;
|
|
|
|
} else if (is_app(new_b) && is_var(app_arg(new_b), 0) && !has_free_var(app_fn(new_b), 0)) {
|
|
|
|
return lower_free_vars(app_fn(new_b), 1);
|
|
|
|
} else {
|
|
|
|
return update_binding(e, binding_domain(e), new_b);
|
|
|
|
}
|
|
|
|
} else if (is_app(b) && is_var(app_arg(b), 0) && !has_free_var(app_fn(b), 0)) {
|
|
|
|
return lower_free_vars(app_fn(b), 1);
|
|
|
|
} else {
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-20 16:40:30 +00:00
|
|
|
expr normalize(expr e) {
|
2014-10-27 23:49:29 +00:00
|
|
|
check_system("normalize");
|
2014-10-27 21:49:11 +00:00
|
|
|
if (!m_pred(e))
|
|
|
|
return e;
|
|
|
|
auto w = m_tc.whnf(e);
|
|
|
|
e = w.first;
|
|
|
|
if (m_save_cnstrs)
|
|
|
|
m_cnstrs += w.second;
|
2014-05-20 16:40:30 +00:00
|
|
|
switch (e.kind()) {
|
|
|
|
case expr_kind::Var: case expr_kind::Constant: case expr_kind::Sort:
|
|
|
|
case expr_kind::Meta: case expr_kind::Local: case expr_kind::Macro:
|
|
|
|
return e;
|
2015-03-12 07:31:10 +00:00
|
|
|
case expr_kind::Lambda: {
|
|
|
|
e = normalize_binding(e);
|
|
|
|
if (m_use_eta)
|
|
|
|
return try_eta(e);
|
|
|
|
else
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
case expr_kind::Pi:
|
2014-05-20 16:40:30 +00:00
|
|
|
return normalize_binding(e);
|
|
|
|
case expr_kind::App:
|
2014-05-20 18:53:58 +00:00
|
|
|
return normalize_app(e);
|
2014-05-20 16:40:30 +00:00
|
|
|
}
|
|
|
|
lean_unreachable(); // LCOV_EXCL_LINE
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2015-03-12 07:31:10 +00:00
|
|
|
normalize_fn(type_checker & tc, bool save, bool eta):
|
2014-10-27 21:49:11 +00:00
|
|
|
m_tc(tc), m_ngen(m_tc.mk_ngen()),
|
|
|
|
m_pred([](expr const &) { return true; }),
|
2015-03-12 07:31:10 +00:00
|
|
|
m_save_cnstrs(save), m_use_eta(eta) {}
|
2014-10-27 21:49:11 +00:00
|
|
|
|
2015-03-12 07:31:10 +00:00
|
|
|
normalize_fn(type_checker & tc, std::function<bool(expr const &)> const & fn, bool eta): // NOLINT
|
2014-10-27 21:49:11 +00:00
|
|
|
m_tc(tc), m_ngen(m_tc.mk_ngen()),
|
2015-03-12 07:31:10 +00:00
|
|
|
m_pred(fn), m_save_cnstrs(true), m_use_eta(eta) {}
|
2014-10-27 21:49:11 +00:00
|
|
|
|
|
|
|
expr operator()(expr const & e) {
|
|
|
|
m_cnstrs = constraint_seq();
|
|
|
|
return normalize(e);
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:16:03 +00:00
|
|
|
expr operator()(level_param_names const & ls, expr const & e) {
|
2014-10-27 21:49:11 +00:00
|
|
|
m_cnstrs = constraint_seq();
|
|
|
|
return m_tc.with_params(ls, [&]() {
|
2014-09-27 03:16:03 +00:00
|
|
|
return normalize(e);
|
|
|
|
});
|
|
|
|
}
|
2014-10-27 21:49:11 +00:00
|
|
|
|
|
|
|
constraint_seq get_cnstrs() const { return m_cnstrs; }
|
2014-05-20 16:40:30 +00:00
|
|
|
};
|
|
|
|
|
2015-03-12 07:31:10 +00:00
|
|
|
expr normalize(environment const & env, expr const & e, bool eta) {
|
2015-05-08 21:36:38 +00:00
|
|
|
auto tc = mk_type_checker(env);
|
2014-10-27 21:49:11 +00:00
|
|
|
bool save_cnstrs = false;
|
2015-03-12 07:31:10 +00:00
|
|
|
return normalize_fn(*tc, save_cnstrs, eta)(e);
|
2014-10-27 21:49:11 +00:00
|
|
|
}
|
|
|
|
|
2015-03-12 07:31:10 +00:00
|
|
|
expr normalize(environment const & env, level_param_names const & ls, expr const & e, bool eta) {
|
2015-05-08 21:36:38 +00:00
|
|
|
auto tc = mk_type_checker(env);
|
2014-10-27 21:49:11 +00:00
|
|
|
bool save_cnstrs = false;
|
2015-03-12 07:31:10 +00:00
|
|
|
return normalize_fn(*tc, save_cnstrs, eta)(ls, e);
|
2014-10-27 21:49:11 +00:00
|
|
|
}
|
|
|
|
|
2015-03-12 07:31:10 +00:00
|
|
|
expr normalize(type_checker & tc, expr const & e, bool eta) {
|
2014-10-27 21:49:11 +00:00
|
|
|
bool save_cnstrs = false;
|
2015-03-12 07:31:10 +00:00
|
|
|
return normalize_fn(tc, save_cnstrs, eta)(e);
|
2014-10-27 21:49:11 +00:00
|
|
|
}
|
|
|
|
|
2015-03-12 07:31:10 +00:00
|
|
|
expr normalize(type_checker & tc, level_param_names const & ls, expr const & e, bool eta) {
|
2015-02-07 23:19:41 +00:00
|
|
|
bool save_cnstrs = false;
|
2015-03-12 07:31:10 +00:00
|
|
|
return normalize_fn(tc, save_cnstrs, eta)(ls, e);
|
2015-02-07 23:19:41 +00:00
|
|
|
}
|
|
|
|
|
2015-03-12 07:31:10 +00:00
|
|
|
expr normalize(type_checker & tc, expr const & e, constraint_seq & cs, bool eta) {
|
|
|
|
bool save_cnstrs = false;
|
|
|
|
normalize_fn fn(tc, save_cnstrs, eta);
|
2014-10-27 21:49:11 +00:00
|
|
|
expr r = fn(e);
|
|
|
|
cs += fn.get_cnstrs();
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2014-10-27 23:49:29 +00:00
|
|
|
expr normalize(type_checker & tc, expr const & e, std::function<bool(expr const &)> const & pred, // NOLINT
|
2015-03-12 07:31:10 +00:00
|
|
|
constraint_seq & cs, bool eta) {
|
|
|
|
normalize_fn fn(tc, pred, eta);
|
2014-10-27 21:49:11 +00:00
|
|
|
expr r = fn(e);
|
|
|
|
cs += fn.get_cnstrs();
|
|
|
|
return r;
|
|
|
|
}
|
2014-05-20 16:40:30 +00:00
|
|
|
}
|