refactor(kernel/expr): tag expressions at "creation" time

This commit is contained in:
Leonardo de Moura 2014-10-15 13:12:09 -07:00
parent d960c1994e
commit 814778abb1
4 changed files with 185 additions and 135 deletions

View file

@ -20,7 +20,7 @@ expr abstract(expr const & e, unsigned s, unsigned n, expr const * subst) {
while (i > 0) { while (i > 0) {
--i; --i;
if (subst[i] == e) if (subst[i] == e)
return some_expr(copy_tag(e, mk_var(offset + s + n - i - 1))); return some_expr(mk_var(offset + s + n - i - 1, e.get_tag()));
} }
} }
return none_expr(); return none_expr();
@ -41,7 +41,7 @@ expr abstract_locals(expr const & e, unsigned n, expr const * subst) {
while (i > 0) { while (i > 0) {
--i; --i;
if (mlocal_name(subst[i]) == mlocal_name(m)) if (mlocal_name(subst[i]) == mlocal_name(m))
return some_expr(copy_tag(m, mk_var(offset + n - i - 1))); return some_expr(mk_var(offset + n - i - 1, m.get_tag()));
} }
} }
return none_expr(); return none_expr();

View file

@ -52,7 +52,8 @@ unsigned hash_levels(levels const & ls) {
LEAN_THREAD_VALUE(unsigned, g_hash_alloc_counter, 0); LEAN_THREAD_VALUE(unsigned, g_hash_alloc_counter, 0);
expr_cell::expr_cell(expr_kind k, unsigned h, bool has_expr_mv, bool has_univ_mv, bool has_local, bool has_param_univ): expr_cell::expr_cell(expr_kind k, unsigned h, bool has_expr_mv, bool has_univ_mv,
bool has_local, bool has_param_univ, tag g):
m_flags(0), m_flags(0),
m_kind(static_cast<unsigned>(k)), m_kind(static_cast<unsigned>(k)),
m_has_expr_mv(has_expr_mv), m_has_expr_mv(has_expr_mv),
@ -60,7 +61,7 @@ expr_cell::expr_cell(expr_kind k, unsigned h, bool has_expr_mv, bool has_univ_mv
m_has_local(has_local), m_has_local(has_local),
m_has_param_univ(has_param_univ), m_has_param_univ(has_param_univ),
m_hash(h), m_hash(h),
m_tag(nulltag), m_tag(g),
m_rc(0) { m_rc(0) {
// m_hash_alloc does not need to be a unique identifier. // m_hash_alloc does not need to be a unique identifier.
// We want diverse hash codes because given expr_cell * c1 and expr_cell * c2, // We want diverse hash codes because given expr_cell * c1 and expr_cell * c2,
@ -110,8 +111,8 @@ bool is_meta(expr const & e) {
// Expr variables // Expr variables
DEF_THREAD_MEMORY_POOL(get_var_allocator, sizeof(expr_var)); DEF_THREAD_MEMORY_POOL(get_var_allocator, sizeof(expr_var));
expr_var::expr_var(unsigned idx): expr_var::expr_var(unsigned idx, tag g):
expr_cell(expr_kind::Var, idx, false, false, false, false), expr_cell(expr_kind::Var, idx, false, false, false, false, g),
m_vidx(idx) { m_vidx(idx) {
if (idx == std::numeric_limits<unsigned>::max()) if (idx == std::numeric_limits<unsigned>::max())
throw exception("invalid free variable index, de Bruijn index is too big"); throw exception("invalid free variable index, de Bruijn index is too big");
@ -123,8 +124,9 @@ void expr_var::dealloc() {
// Expr constants // Expr constants
DEF_THREAD_MEMORY_POOL(get_const_allocator, sizeof(expr_const)); DEF_THREAD_MEMORY_POOL(get_const_allocator, sizeof(expr_const));
expr_const::expr_const(name const & n, levels const & ls): expr_const::expr_const(name const & n, levels const & ls, tag g):
expr_cell(expr_kind::Constant, ::lean::hash(n.hash(), hash_levels(ls)), false, has_meta(ls), false, has_param(ls)), expr_cell(expr_kind::Constant, ::lean::hash(n.hash(), hash_levels(ls)), false,
has_meta(ls), false, has_param(ls), g),
m_name(n), m_name(n),
m_levels(ls) { m_levels(ls) {
} }
@ -139,10 +141,10 @@ unsigned binder_info::hash() const {
// Expr metavariables and local variables // Expr metavariables and local variables
DEF_THREAD_MEMORY_POOL(get_mlocal_allocator, sizeof(expr_mlocal)); DEF_THREAD_MEMORY_POOL(get_mlocal_allocator, sizeof(expr_mlocal));
expr_mlocal::expr_mlocal(bool is_meta, name const & n, expr const & t): expr_mlocal::expr_mlocal(bool is_meta, name const & n, expr const & t, tag g):
expr_composite(is_meta ? expr_kind::Meta : expr_kind::Local, n.hash(), is_meta || t.has_expr_metavar(), t.has_univ_metavar(), expr_composite(is_meta ? expr_kind::Meta : expr_kind::Local, n.hash(), is_meta || t.has_expr_metavar(), t.has_univ_metavar(),
!is_meta || t.has_local(), t.has_param_univ(), !is_meta || t.has_local(), t.has_param_univ(),
1, get_free_var_range(t)), 1, get_free_var_range(t), g),
m_name(n), m_name(n),
m_type(t) {} m_type(t) {}
void expr_mlocal::dealloc(buffer<expr_cell*> & todelete) { void expr_mlocal::dealloc(buffer<expr_cell*> & todelete) {
@ -152,8 +154,8 @@ void expr_mlocal::dealloc(buffer<expr_cell*> & todelete) {
} }
DEF_THREAD_MEMORY_POOL(get_local_allocator, sizeof(expr_local)); DEF_THREAD_MEMORY_POOL(get_local_allocator, sizeof(expr_local));
expr_local::expr_local(name const & n, name const & pp_name, expr const & t, binder_info const & bi): expr_local::expr_local(name const & n, name const & pp_name, expr const & t, binder_info const & bi, tag g):
expr_mlocal(false, n, t), expr_mlocal(false, n, t, g),
m_pp_name(pp_name), m_pp_name(pp_name),
m_bi(bi) {} m_bi(bi) {}
void expr_local::dealloc(buffer<expr_cell*> & todelete) { void expr_local::dealloc(buffer<expr_cell*> & todelete) {
@ -164,21 +166,22 @@ void expr_local::dealloc(buffer<expr_cell*> & todelete) {
// Composite expressions // Composite expressions
expr_composite::expr_composite(expr_kind k, unsigned h, bool has_expr_mv, bool has_univ_mv, expr_composite::expr_composite(expr_kind k, unsigned h, bool has_expr_mv, bool has_univ_mv,
bool has_local, bool has_param_univ, unsigned w, unsigned fv_range): bool has_local, bool has_param_univ, unsigned w, unsigned fv_range, tag g):
expr_cell(k, h, has_expr_mv, has_univ_mv, has_local, has_param_univ), expr_cell(k, h, has_expr_mv, has_univ_mv, has_local, has_param_univ, g),
m_weight(w), m_weight(w),
m_free_var_range(fv_range) {} m_free_var_range(fv_range) {}
// Expr applications // Expr applications
DEF_THREAD_MEMORY_POOL(get_app_allocator, sizeof(expr_app)); DEF_THREAD_MEMORY_POOL(get_app_allocator, sizeof(expr_app));
expr_app::expr_app(expr const & fn, expr const & arg): expr_app::expr_app(expr const & fn, expr const & arg, tag g):
expr_composite(expr_kind::App, ::lean::hash(fn.hash(), arg.hash()), expr_composite(expr_kind::App, ::lean::hash(fn.hash(), arg.hash()),
fn.has_expr_metavar() || arg.has_expr_metavar(), fn.has_expr_metavar() || arg.has_expr_metavar(),
fn.has_univ_metavar() || arg.has_univ_metavar(), fn.has_univ_metavar() || arg.has_univ_metavar(),
fn.has_local() || arg.has_local(), fn.has_local() || arg.has_local(),
fn.has_param_univ() || arg.has_param_univ(), fn.has_param_univ() || arg.has_param_univ(),
inc_weight(add_weight(get_weight(fn), get_weight(arg))), inc_weight(add_weight(get_weight(fn), get_weight(arg))),
std::max(get_free_var_range(fn), get_free_var_range(arg))), std::max(get_free_var_range(fn), get_free_var_range(arg)),
g),
m_fn(fn), m_arg(arg) { m_fn(fn), m_arg(arg) {
m_hash = ::lean::hash(m_hash, m_weight); m_hash = ::lean::hash(m_hash, m_weight);
} }
@ -202,14 +205,15 @@ bool operator==(binder_info const & i1, binder_info const & i2) {
// Expr binders (Lambda, Pi) // Expr binders (Lambda, Pi)
DEF_THREAD_MEMORY_POOL(get_binding_allocator, sizeof(expr_binding)); DEF_THREAD_MEMORY_POOL(get_binding_allocator, sizeof(expr_binding));
expr_binding::expr_binding(expr_kind k, name const & n, expr const & t, expr const & b, binder_info const & i): expr_binding::expr_binding(expr_kind k, name const & n, expr const & t, expr const & b, binder_info const & i, tag g):
expr_composite(k, ::lean::hash(t.hash(), b.hash()), expr_composite(k, ::lean::hash(t.hash(), b.hash()),
t.has_expr_metavar() || b.has_expr_metavar(), t.has_expr_metavar() || b.has_expr_metavar(),
t.has_univ_metavar() || b.has_univ_metavar(), t.has_univ_metavar() || b.has_univ_metavar(),
t.has_local() || b.has_local(), t.has_local() || b.has_local(),
t.has_param_univ() || b.has_param_univ(), t.has_param_univ() || b.has_param_univ(),
inc_weight(add_weight(get_weight(t), get_weight(b))), inc_weight(add_weight(get_weight(t), get_weight(b))),
std::max(get_free_var_range(t), dec(get_free_var_range(b)))), std::max(get_free_var_range(t), dec(get_free_var_range(b))),
g),
m_binder(n, t, i), m_binder(n, t, i),
m_body(b) { m_body(b) {
m_hash = ::lean::hash(m_hash, m_weight); m_hash = ::lean::hash(m_hash, m_weight);
@ -224,8 +228,8 @@ void expr_binding::dealloc(buffer<expr_cell*> & todelete) {
// Expr Sort // Expr Sort
DEF_THREAD_MEMORY_POOL(get_sort_allocator, sizeof(expr_sort)); DEF_THREAD_MEMORY_POOL(get_sort_allocator, sizeof(expr_sort));
expr_sort::expr_sort(level const & l): expr_sort::expr_sort(level const & l, tag g):
expr_cell(expr_kind::Sort, ::lean::hash(l), false, has_meta(l), false, has_param(l)), expr_cell(expr_kind::Sort, ::lean::hash(l), false, has_meta(l), false, has_param(l), g),
m_level(l) { m_level(l) {
} }
expr_sort::~expr_sort() {} expr_sort::~expr_sort() {}
@ -274,7 +278,7 @@ static unsigned get_free_var_range(unsigned num, expr const * args) {
return r; return r;
} }
expr_macro::expr_macro(macro_definition const & m, unsigned num, expr const * args): expr_macro::expr_macro(macro_definition const & m, unsigned num, expr const * args, tag g):
expr_composite(expr_kind::Macro, expr_composite(expr_kind::Macro,
lean::hash(num, [&](unsigned i) { return args[i].hash(); }, m.hash()), lean::hash(num, [&](unsigned i) { return args[i].hash(); }, m.hash()),
std::any_of(args, args+num, [](expr const & e) { return e.has_expr_metavar(); }), std::any_of(args, args+num, [](expr const & e) { return e.has_expr_metavar(); }),
@ -282,7 +286,8 @@ expr_macro::expr_macro(macro_definition const & m, unsigned num, expr const * ar
std::any_of(args, args+num, [](expr const & e) { return e.has_local(); }), std::any_of(args, args+num, [](expr const & e) { return e.has_local(); }),
std::any_of(args, args+num, [](expr const & e) { return e.has_param_univ(); }), std::any_of(args, args+num, [](expr const & e) { return e.has_param_univ(); }),
inc_weight(add_weight(num, args)), inc_weight(add_weight(num, args)),
get_free_var_range(num, args)), get_free_var_range(num, args),
g),
m_definition(m), m_definition(m),
m_num_args(num) { m_num_args(num) {
m_args = new expr[num]; m_args = new expr[num];
@ -321,20 +326,30 @@ inline expr cache(expr && e) { return e; }
bool enable_expr_caching(bool) { return true; } // NOLINT bool enable_expr_caching(bool) { return true; } // NOLINT
#endif #endif
expr mk_var(unsigned idx) { return cache(expr(new (get_var_allocator().allocate()) expr_var(idx))); } expr mk_var(unsigned idx, tag g) {
expr mk_constant(name const & n, levels const & ls) { return cache(expr(new (get_const_allocator().allocate()) expr_const(n, ls))); } return cache(expr(new (get_var_allocator().allocate()) expr_var(idx, g)));
expr mk_macro(macro_definition const & m, unsigned num, expr const * args) { return cache(expr(new expr_macro(m, num, args))); }
expr mk_metavar(name const & n, expr const & t) { return cache(expr(new (get_mlocal_allocator().allocate()) expr_mlocal(true, n, t))); }
expr mk_local(name const & n, name const & pp_n, expr const & t, binder_info const & bi) {
return cache(expr(new (get_local_allocator().allocate()) expr_local(n, pp_n, t, bi)));
} }
expr mk_app(expr const & f, expr const & a) { expr mk_constant(name const & n, levels const & ls, tag g) {
return cache(expr(new (get_app_allocator().allocate()) expr_app(f, a))); return cache(expr(new (get_const_allocator().allocate()) expr_const(n, ls, g)));
} }
expr mk_binding(expr_kind k, name const & n, expr const & t, expr const & e, binder_info const & i) { expr mk_macro(macro_definition const & m, unsigned num, expr const * args, tag g) {
return cache(expr(new (get_binding_allocator().allocate()) expr_binding(k, n, t, e, i))); return cache(expr(new expr_macro(m, num, args, g)));
}
expr mk_metavar(name const & n, expr const & t, tag g) {
return cache(expr(new (get_mlocal_allocator().allocate()) expr_mlocal(true, n, t, g)));
}
expr mk_local(name const & n, name const & pp_n, expr const & t, binder_info const & bi, tag g) {
return cache(expr(new (get_local_allocator().allocate()) expr_local(n, pp_n, t, bi, g)));
}
expr mk_app(expr const & f, expr const & a, tag g) {
return cache(expr(new (get_app_allocator().allocate()) expr_app(f, a, g)));
}
expr mk_binding(expr_kind k, name const & n, expr const & t, expr const & e, binder_info const & i, tag g) {
return cache(expr(new (get_binding_allocator().allocate()) expr_binding(k, n, t, e, i, g)));
}
expr mk_sort(level const & l, tag g) {
return cache(expr(new (get_sort_allocator().allocate()) expr_sort(l, g)));
} }
expr mk_sort(level const & l) { return cache(expr(new (get_sort_allocator().allocate()) expr_sort(l))); }
// ======================================= // =======================================
typedef buffer<expr_cell*> del_buffer; typedef buffer<expr_cell*> del_buffer;
@ -365,38 +380,38 @@ void expr_cell::dealloc() {
} }
// Auxiliary constructors // Auxiliary constructors
expr mk_app(expr const & f, unsigned num_args, expr const * args) { expr mk_app(expr const & f, unsigned num_args, expr const * args, tag g) {
expr r = f; expr r = f;
for (unsigned i = 0; i < num_args; i++) for (unsigned i = 0; i < num_args; i++)
r = mk_app(r, args[i]); r = mk_app(r, args[i], g);
return r; return r;
} }
expr mk_app(unsigned num_args, expr const * args) { expr mk_app(unsigned num_args, expr const * args, tag g) {
lean_assert(num_args >= 2); lean_assert(num_args >= 2);
return mk_app(mk_app(args[0], args[1]), num_args - 2, args+2); return mk_app(mk_app(args[0], args[1], g), num_args - 2, args+2, g);
} }
expr mk_rev_app(expr const & f, unsigned num_args, expr const * args) { expr mk_rev_app(expr const & f, unsigned num_args, expr const * args, tag g) {
expr r = f; expr r = f;
unsigned i = num_args; unsigned i = num_args;
while (i > 0) { while (i > 0) {
--i; --i;
r = mk_app(r, args[i]); r = mk_app(r, args[i], g);
} }
return r; return r;
} }
expr mk_rev_app(unsigned num_args, expr const * args) { expr mk_rev_app(unsigned num_args, expr const * args, tag g) {
lean_assert(num_args >= 2); lean_assert(num_args >= 2);
return mk_rev_app(mk_app(args[num_args-1], args[num_args-2]), num_args-2, args); return mk_rev_app(mk_app(args[num_args-1], args[num_args-2], g), num_args-2, args, g);
} }
expr mk_app_vars(expr const & f, unsigned n) { expr mk_app_vars(expr const & f, unsigned n, tag g) {
expr r = f; expr r = f;
while (n > 0) { while (n > 0) {
--n; --n;
r = mk_app(r, Var(n)); r = mk_app(r, mk_var(n, g), g);
} }
return r; return r;
} }
@ -453,14 +468,16 @@ static name const & get_default_var_name() {
static name const & g_default_var_name = get_default_var_name(); // force it to be initialized static name const & g_default_var_name = get_default_var_name(); // force it to be initialized
bool is_default_var_name(name const & n) { return n == get_default_var_name(); } bool is_default_var_name(name const & n) { return n == get_default_var_name(); }
expr mk_arrow(expr const & t, expr const & e) { return mk_pi(get_default_var_name(), t, e); } expr mk_arrow(expr const & t, expr const & e, tag g) {
return mk_pi(get_default_var_name(), t, e, binder_info(), g);
}
expr mk_pi(unsigned sz, expr const * domain, expr const & range) { expr mk_pi(unsigned sz, expr const * domain, expr const & range, tag g) {
expr r = range; expr r = range;
unsigned i = sz; unsigned i = sz;
while (i > 0) { while (i > 0) {
--i; --i;
r = mk_pi(name(g_default_var_name, i), domain[i], r); r = mk_pi(name(g_default_var_name, i), domain[i], r, binder_info(), g);
} }
return r; return r;
} }
@ -494,7 +511,7 @@ expr copy_tag(expr const & e, expr && new_e) {
expr update_app(expr const & e, expr const & new_fn, expr const & new_arg) { expr update_app(expr const & e, expr const & new_fn, expr const & new_arg) {
if (!is_eqp(app_fn(e), new_fn) || !is_eqp(app_arg(e), new_arg)) if (!is_eqp(app_fn(e), new_fn) || !is_eqp(app_arg(e), new_arg))
return copy_tag(e, mk_app(new_fn, new_arg)); return mk_app(new_fn, new_arg, e.get_tag());
else else
return e; return e;
} }
@ -503,24 +520,24 @@ expr update_rev_app(expr const & e, unsigned num, expr const * new_args) {
expr const * it = &e; expr const * it = &e;
for (unsigned i = 0; i < num - 1; i++) { for (unsigned i = 0; i < num - 1; i++) {
if (!is_app(*it) || !is_eqp(app_arg(*it), new_args[i])) if (!is_app(*it) || !is_eqp(app_arg(*it), new_args[i]))
return copy_tag(e, mk_rev_app(num, new_args)); return mk_rev_app(num, new_args, e.get_tag());
it = &app_fn(*it); it = &app_fn(*it);
} }
if (!is_eqp(*it, new_args[num - 1])) if (!is_eqp(*it, new_args[num - 1]))
return copy_tag(e, mk_rev_app(num, new_args)); return mk_rev_app(num, new_args, e.get_tag());
return e; return e;
} }
expr update_binding(expr const & e, expr const & new_domain, expr const & new_body) { expr update_binding(expr const & e, expr const & new_domain, expr const & new_body) {
if (!is_eqp(binding_domain(e), new_domain) || !is_eqp(binding_body(e), new_body)) if (!is_eqp(binding_domain(e), new_domain) || !is_eqp(binding_body(e), new_body))
return copy_tag(e, mk_binding(e.kind(), binding_name(e), new_domain, new_body, binding_info(e))); return mk_binding(e.kind(), binding_name(e), new_domain, new_body, binding_info(e), e.get_tag());
else else
return e; return e;
} }
expr update_binding(expr const & e, expr const & new_domain, expr const & new_body, binder_info const & bi) { expr update_binding(expr const & e, expr const & new_domain, expr const & new_body, binder_info const & bi) {
if (!is_eqp(binding_domain(e), new_domain) || !is_eqp(binding_body(e), new_body) || bi != binding_info(e)) if (!is_eqp(binding_domain(e), new_domain) || !is_eqp(binding_body(e), new_body) || bi != binding_info(e))
return copy_tag(e, mk_binding(e.kind(), binding_name(e), new_domain, new_body, bi)); return mk_binding(e.kind(), binding_name(e), new_domain, new_body, bi, e.get_tag());
else else
return e; return e;
} }
@ -529,16 +546,16 @@ expr update_mlocal(expr const & e, expr const & new_type) {
if (is_eqp(mlocal_type(e), new_type)) if (is_eqp(mlocal_type(e), new_type))
return e; return e;
else if (is_metavar(e)) else if (is_metavar(e))
return copy_tag(e, mk_metavar(mlocal_name(e), new_type)); return mk_metavar(mlocal_name(e), new_type, e.get_tag());
else else
return copy_tag(e, mk_local(mlocal_name(e), local_pp_name(e), new_type, local_info(e))); return mk_local(mlocal_name(e), local_pp_name(e), new_type, local_info(e), e.get_tag());
} }
expr update_local(expr const & e, expr const & new_type, binder_info const & bi) { expr update_local(expr const & e, expr const & new_type, binder_info const & bi) {
if (is_eqp(mlocal_type(e), new_type) && local_info(e) == bi) if (is_eqp(mlocal_type(e), new_type) && local_info(e) == bi)
return e; return e;
else else
return copy_tag(e, mk_local(mlocal_name(e), local_pp_name(e), new_type, bi)); return mk_local(mlocal_name(e), local_pp_name(e), new_type, bi, e.get_tag());
} }
expr update_local(expr const & e, binder_info const & bi) { expr update_local(expr const & e, binder_info const & bi) {
@ -547,14 +564,14 @@ expr update_local(expr const & e, binder_info const & bi) {
expr update_sort(expr const & e, level const & new_level) { expr update_sort(expr const & e, level const & new_level) {
if (!is_eqp(sort_level(e), new_level)) if (!is_eqp(sort_level(e), new_level))
return copy_tag(e, mk_sort(new_level)); return mk_sort(new_level, e.get_tag());
else else
return e; return e;
} }
expr update_constant(expr const & e, levels const & new_levels) { expr update_constant(expr const & e, levels const & new_levels) {
if (!is_eqp(const_levels(e), new_levels)) if (!is_eqp(const_levels(e), new_levels))
return copy_tag(e, mk_constant(const_name(e), new_levels)); return mk_constant(const_name(e), new_levels, e.get_tag());
else else
return e; return e;
} }
@ -569,7 +586,7 @@ expr update_macro(expr const & e, unsigned num, expr const * args) {
if (i == num) if (i == num)
return e; return e;
} }
return copy_tag(e, mk_macro(to_macro(e)->m_definition, num, args)); return mk_macro(to_macro(e)->m_definition, num, args, e.get_tag());
} }
bool is_atomic(expr const & e) { bool is_atomic(expr const & e) {

View file

@ -69,7 +69,7 @@ protected:
static void dec_ref(expr & c, buffer<expr_cell*> & todelete); static void dec_ref(expr & c, buffer<expr_cell*> & todelete);
public: public:
expr_cell(expr_kind k, unsigned h, bool has_expr_mv, bool has_univ_mv, bool has_local, bool has_param_univ); expr_cell(expr_kind k, unsigned h, bool has_expr_mv, bool has_univ_mv, bool has_local, bool has_param_univ, tag g);
expr_kind kind() const { return static_cast<expr_kind>(m_kind); } expr_kind kind() const { return static_cast<expr_kind>(m_kind); }
unsigned hash() const { return m_hash; } unsigned hash() const { return m_hash; }
unsigned hash_alloc() const { return m_hash_alloc; } unsigned hash_alloc() const { return m_hash_alloc; }
@ -128,29 +128,35 @@ public:
expr_cell * raw() const { return m_ptr; } expr_cell * raw() const { return m_ptr; }
friend expr mk_var(unsigned idx); friend expr mk_var(unsigned idx, tag g);
friend expr mk_sort(level const & l); friend expr mk_sort(level const & l, tag g);
friend expr mk_constant(name const & n, levels const & ls); friend expr mk_constant(name const & n, levels const & ls, tag g);
friend expr mk_metavar(name const & n, expr const & t); friend expr mk_metavar(name const & n, expr const & t, tag g);
friend expr mk_local(name const & n, name const & pp_n, expr const & t, binder_info const & bi); friend expr mk_local(name const & n, name const & pp_n, expr const & t, binder_info const & bi,
friend expr mk_app(expr const & f, expr const & a); tag g);
friend expr mk_pair(expr const & f, expr const & s, expr const & t); friend expr mk_app(expr const & f, expr const & a, tag g);
friend expr mk_proj(bool fst, expr const & p); friend expr mk_pair(expr const & f, expr const & s, expr const & t, tag g);
friend expr mk_binding(expr_kind k, name const & n, expr const & t, expr const & e, binder_info const & i); friend expr mk_proj(bool fst, expr const & p, tag g);
friend expr mk_macro(macro_definition const & m, unsigned num, expr const * args); friend expr mk_binding(expr_kind k, name const & n, expr const & t, expr const & e, binder_info const & i,
tag g);
friend expr mk_macro(macro_definition const & m, unsigned num, expr const * args, tag g);
friend bool is_eqp(expr const & a, expr const & b) { return a.m_ptr == b.m_ptr; } friend bool is_eqp(expr const & a, expr const & b) { return a.m_ptr == b.m_ptr; }
// Overloaded operator() can be used to create applications // Overloaded operator() can be used to create applications
expr operator()(expr const & a1) const; expr operator()(expr const & a1, tag g = nulltag) const;
expr operator()(expr const & a1, expr const & a2) const; expr operator()(expr const & a1, expr const & a2, tag g = nulltag) const;
expr operator()(expr const & a1, expr const & a2, expr const & a3) const; expr operator()(expr const & a1, expr const & a2, expr const & a3, tag g = nulltag) const;
expr operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4) const; expr operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4,
expr operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4, expr const & a5) const; tag g = nulltag) const;
expr operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4, expr const & a5, expr const & a6) const; expr operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4,
expr operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4, expr const & a5, expr const & a6, expr const & a5, tag g = nulltag) const;
expr const & a7) const; expr operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4,
expr operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4, expr const & a5, expr const & a6, expr const & a5, expr const & a6, tag g = nulltag) const;
expr const & a7, expr const & a8) const; expr operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4,
expr const & a5, expr const & a6, expr const & a7, tag g = nulltag) const;
expr operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4,
expr const & a5, expr const & a6, expr const & a7, expr const & a8,
tag g = nulltag) const;
}; };
expr copy_tag(expr const & e, expr && new_e); expr copy_tag(expr const & e, expr && new_e);
@ -181,7 +187,7 @@ class expr_var : public expr_cell {
friend expr_cell; friend expr_cell;
void dealloc(); void dealloc();
public: public:
expr_var(unsigned idx); expr_var(unsigned idx, tag g);
unsigned get_vidx() const { return m_vidx; } unsigned get_vidx() const { return m_vidx; }
}; };
@ -192,7 +198,7 @@ class expr_const : public expr_cell {
friend expr_cell; friend expr_cell;
void dealloc(); void dealloc();
public: public:
expr_const(name const & n, levels const & ls); expr_const(name const & n, levels const & ls, tag g);
name const & get_name() const { return m_name; } name const & get_name() const { return m_name; }
levels const & get_levels() const { return m_levels; } levels const & get_levels() const { return m_levels; }
}; };
@ -206,7 +212,7 @@ protected:
friend unsigned get_free_var_range(expr const & e); friend unsigned get_free_var_range(expr const & e);
public: public:
expr_composite(expr_kind k, unsigned h, bool has_expr_mv, bool has_univ_mv, bool has_local, expr_composite(expr_kind k, unsigned h, bool has_expr_mv, bool has_univ_mv, bool has_local,
bool has_param_univ, unsigned w, unsigned fv_range); bool has_param_univ, unsigned w, unsigned fv_range, tag g);
}; };
/** \brief Metavariables and local constants */ /** \brief Metavariables and local constants */
@ -217,7 +223,7 @@ protected:
friend expr_cell; friend expr_cell;
void dealloc(buffer<expr_cell*> & todelete); void dealloc(buffer<expr_cell*> & todelete);
public: public:
expr_mlocal(bool is_meta, name const & n, expr const & t); expr_mlocal(bool is_meta, name const & n, expr const & t, tag g);
name const & get_name() const { return m_name; } name const & get_name() const { return m_name; }
expr const & get_type() const { return m_type; } expr const & get_type() const { return m_type; }
}; };
@ -273,7 +279,7 @@ class expr_local : public expr_mlocal {
friend expr_cell; friend expr_cell;
void dealloc(buffer<expr_cell*> & todelete); void dealloc(buffer<expr_cell*> & todelete);
public: public:
expr_local(name const & n, name const & pp_name, expr const & t, binder_info const & bi); expr_local(name const & n, name const & pp_name, expr const & t, binder_info const & bi, tag g);
name const & get_pp_name() const { return m_pp_name; } name const & get_pp_name() const { return m_pp_name; }
binder_info const & get_info() const { return m_bi; } binder_info const & get_info() const { return m_bi; }
}; };
@ -285,7 +291,7 @@ class expr_app : public expr_composite {
friend expr_cell; friend expr_cell;
void dealloc(buffer<expr_cell*> & todelete); void dealloc(buffer<expr_cell*> & todelete);
public: public:
expr_app(expr const & fn, expr const & arg); expr_app(expr const & fn, expr const & arg, tag g);
expr const & get_fn() const { return m_fn; } expr const & get_fn() const { return m_fn; }
expr const & get_arg() const { return m_arg; } expr const & get_arg() const { return m_arg; }
}; };
@ -296,7 +302,7 @@ class binder {
expr m_type; expr m_type;
binder_info m_info; binder_info m_info;
public: public:
binder(name const & n, expr const & t, binder_info const & bi = binder_info()): binder(name const & n, expr const & t, binder_info const & bi):
m_name(n), m_type(t), m_info(bi) {} m_name(n), m_type(t), m_info(bi) {}
name const & get_name() const { return m_name; } name const & get_name() const { return m_name; }
expr const & get_type() const { return m_type; } expr const & get_type() const { return m_type; }
@ -311,7 +317,8 @@ class expr_binding : public expr_composite {
friend class expr_cell; friend class expr_cell;
void dealloc(buffer<expr_cell*> & todelete); void dealloc(buffer<expr_cell*> & todelete);
public: public:
expr_binding(expr_kind k, name const & n, expr const & t, expr const & e, binder_info const & i = binder_info()); expr_binding(expr_kind k, name const & n, expr const & t, expr const & e,
binder_info const & i, tag g);
name const & get_name() const { return m_binder.get_name(); } name const & get_name() const { return m_binder.get_name(); }
expr const & get_domain() const { return m_binder.get_type(); } expr const & get_domain() const { return m_binder.get_type(); }
expr const & get_body() const { return m_body; } expr const & get_body() const { return m_body; }
@ -325,7 +332,7 @@ class expr_sort : public expr_cell {
friend expr_cell; friend expr_cell;
void dealloc(); void dealloc();
public: public:
expr_sort(level const & l); expr_sort(level const & l, tag g);
~expr_sort(); ~expr_sort();
level const & get_level() const { return m_level; } level const & get_level() const { return m_level; }
}; };
@ -399,7 +406,7 @@ class expr_macro : public expr_composite {
friend expr update_macro(expr const & e, unsigned num, expr const * args); friend expr update_macro(expr const & e, unsigned num, expr const * args);
void dealloc(buffer<expr_cell*> & todelete); void dealloc(buffer<expr_cell*> & todelete);
public: public:
expr_macro(macro_definition const & v, unsigned num, expr const * args); expr_macro(macro_definition const & v, unsigned num, expr const * args, tag g);
~expr_macro(); ~expr_macro();
macro_definition const & get_def() const { return m_definition; } macro_definition const & get_def() const { return m_definition; }
@ -442,79 +449,105 @@ bool is_meta(expr const & e);
// ======================================= // =======================================
// Constructors // Constructors
expr mk_var(unsigned idx); expr mk_var(unsigned idx, tag g = nulltag);
inline expr Var(unsigned idx) { return mk_var(idx); } inline expr Var(unsigned idx) { return mk_var(idx); }
expr mk_constant(name const & n, levels const & ls); expr mk_constant(name const & n, levels const & ls, tag g = nulltag);
inline expr mk_constant(name const & n) { return mk_constant(n, levels()); } inline expr mk_constant(name const & n) { return mk_constant(n, levels()); }
inline expr Const(name const & n) { return mk_constant(n); } inline expr Const(name const & n) { return mk_constant(n); }
expr mk_macro(macro_definition const & m, unsigned num = 0, expr const * args = nullptr); expr mk_macro(macro_definition const & m, unsigned num = 0, expr const * args = nullptr, tag g = nulltag);
expr mk_metavar(name const & n, expr const & t); expr mk_metavar(name const & n, expr const & t, tag g = nulltag);
expr mk_local(name const & n, name const & pp_n, expr const & t, binder_info const & bi); expr mk_local(name const & n, name const & pp_n, expr const & t, binder_info const & bi, tag g = nulltag);
inline expr mk_local(name const & n, expr const & t) { return mk_local(n, n, t, binder_info()); } inline expr mk_local(name const & n, expr const & t, tag g = nulltag) { return mk_local(n, n, t, binder_info(), g); }
inline expr mk_local(name const & n, expr const & t, binder_info const & bi) { return mk_local(n, n, t, bi); } inline expr mk_local(name const & n, expr const & t, binder_info const & bi, tag g = nulltag) {
inline expr Local(name const & n, expr const & t, binder_info const & bi = binder_info()) { return mk_local(n, t, bi); } return mk_local(n, n, t, bi, g);
expr mk_app(expr const & f, expr const & a);
expr mk_app(expr const & f, unsigned num_args, expr const * args);
expr mk_app(unsigned num_args, expr const * args);
inline expr mk_app(std::initializer_list<expr> const & l) { return mk_app(l.size(), l.begin()); }
template<typename T> expr mk_app(T const & args) { return mk_app(args.size(), args.data()); }
template<typename T> expr mk_app(expr const & f, T const & args) { return mk_app(f, args.size(), args.data()); }
expr mk_rev_app(expr const & f, unsigned num_args, expr const * args);
expr mk_rev_app(unsigned num_args, expr const * args);
template<typename T> expr mk_rev_app(T const & args) { return mk_rev_app(args.size(), args.data()); }
template<typename T> expr mk_rev_app(expr const & f, T const & args) { return mk_rev_app(f, args.size(), args.data()); }
expr mk_binding(expr_kind k, name const & n, expr const & t, expr const & e, binder_info const & i = binder_info());
inline expr mk_lambda(name const & n, expr const & t, expr const & e, binder_info const & i = binder_info()) {
return mk_binding(expr_kind::Lambda, n, t, e, i);
} }
inline expr mk_pi(name const & n, expr const & t, expr const & e, binder_info const & i = binder_info()) { inline expr Local(name const & n, expr const & t, binder_info const & bi = binder_info(), tag g = nulltag) {
return mk_binding(expr_kind::Pi, n, t, e, i); return mk_local(n, t, bi, g);
} }
expr mk_sort(level const & l); expr mk_app(expr const & f, expr const & a, tag g = nulltag);
expr mk_app(expr const & f, unsigned num_args, expr const * args, tag g = nulltag);
expr mk_app(unsigned num_args, expr const * args, tag g = nulltag);
inline expr mk_app(std::initializer_list<expr> const & l, tag g = nulltag) {
return mk_app(l.size(), l.begin(), g);
}
template<typename T> expr mk_app(T const & args, tag g = nulltag) { return mk_app(args.size(), args.data(), g); }
template<typename T> expr mk_app(expr const & f, T const & args, tag g = nulltag) {
return mk_app(f, args.size(), args.data(), g);
}
expr mk_rev_app(expr const & f, unsigned num_args, expr const * args, tag g = nulltag);
expr mk_rev_app(unsigned num_args, expr const * args, tag g = nulltag);
template<typename T> expr mk_rev_app(T const & args, tag g = nulltag) { return mk_rev_app(args.size(), args.data(), g); }
template<typename T> expr mk_rev_app(expr const & f, T const & args, tag g = nulltag) {
return mk_rev_app(f, args.size(), args.data(), g);
}
expr mk_binding(expr_kind k, name const & n, expr const & t, expr const & e,
binder_info const & i = binder_info(), tag g = nulltag);
inline expr mk_lambda(name const & n, expr const & t, expr const & e,
binder_info const & i = binder_info(), tag g = nulltag) {
return mk_binding(expr_kind::Lambda, n, t, e, i, g);
}
inline expr mk_pi(name const & n, expr const & t, expr const & e, binder_info const & i = binder_info(), tag g = nulltag) {
return mk_binding(expr_kind::Pi, n, t, e, i, g);
}
expr mk_sort(level const & l, tag g = nulltag);
/** \brief Return <tt>Pi(x.{sz-1}, domain[sz-1], ..., Pi(x.{0}, domain[0], range)...)</tt> */ /** \brief Return <tt>Pi(x.{sz-1}, domain[sz-1], ..., Pi(x.{0}, domain[0], range)...)</tt> */
expr mk_pi(unsigned sz, expr const * domain, expr const & range); expr mk_pi(unsigned sz, expr const * domain, expr const & range, tag g = nulltag);
inline expr mk_pi(buffer<expr> const & domain, expr const & range) { return mk_pi(domain.size(), domain.data(), range); } inline expr mk_pi(buffer<expr> const & domain, expr const & range, tag g = nulltag) {
return mk_pi(domain.size(), domain.data(), range, g);
}
expr mk_Prop(); expr mk_Prop();
expr mk_Type(); expr mk_Type();
bool is_default_var_name(name const & n); bool is_default_var_name(name const & n);
expr mk_arrow(expr const & t, expr const & e); expr mk_arrow(expr const & t, expr const & e, tag g = nulltag);
inline expr operator>>(expr const & t, expr const & e) { return mk_arrow(t, e); } inline expr operator>>(expr const & t, expr const & e) { return mk_arrow(t, e); }
// Auxiliary // Auxiliary
inline expr mk_app(expr const & e1, expr const & e2, expr const & e3) { return mk_app({e1, e2, e3}); } inline expr mk_app(expr const & e1, expr const & e2, expr const & e3, tag g = nulltag) {
inline expr mk_app(expr const & e1, expr const & e2, expr const & e3, expr const & e4) { return mk_app({e1, e2, e3, e4}); } return mk_app({e1, e2, e3}, g);
inline expr mk_app(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5) {
return mk_app({e1, e2, e3, e4, e5});
} }
inline expr expr::operator()(expr const & a1) const { return mk_app({*this, a1}); } inline expr mk_app(expr const & e1, expr const & e2, expr const & e3, expr const & e4, tag g = nulltag) {
inline expr expr::operator()(expr const & a1, expr const & a2) const { return mk_app({*this, a1, a2}); } return mk_app({e1, e2, e3, e4}, g);
inline expr expr::operator()(expr const & a1, expr const & a2, expr const & a3) const { return mk_app({*this, a1, a2, a3}); }
inline expr expr::operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4) const {
return mk_app({*this, a1, a2, a3, a4});
} }
inline expr expr::operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4, expr const & a5) const { inline expr mk_app(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5,
return mk_app({*this, a1, a2, a3, a4, a5}); tag g = nulltag) {
return mk_app({e1, e2, e3, e4, e5}, g);
}
inline expr expr::operator()(expr const & a, tag g) const {
return mk_app({*this, a}, g);
}
inline expr expr::operator()(expr const & a1, expr const & a2, tag g) const {
return mk_app({*this, a1, a2}, g);
}
inline expr expr::operator()(expr const & a1, expr const & a2, expr const & a3, tag g) const {
return mk_app({*this, a1, a2, a3}, g);
}
inline expr expr::operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4, tag g) const {
return mk_app({*this, a1, a2, a3, a4}, g);
}
inline expr expr::operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4,
expr const & a5, tag g) const {
return mk_app({*this, a1, a2, a3, a4, a5}, g);
} }
inline expr expr::operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4, expr const & a5, inline expr expr::operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4, expr const & a5,
expr const & a6) const { expr const & a6, tag g) const {
return mk_app({*this, a1, a2, a3, a4, a5, a6}); return mk_app({*this, a1, a2, a3, a4, a5, a6}, g);
} }
inline expr expr::operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4, expr const & a5, inline expr expr::operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4, expr const & a5,
expr const & a6, expr const & a7) const { expr const & a6, expr const & a7, tag g) const {
return mk_app({*this, a1, a2, a3, a4, a5, a6, a7}); return mk_app({*this, a1, a2, a3, a4, a5, a6, a7}, g);
} }
inline expr expr::operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4, expr const & a5, inline expr expr::operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4, expr const & a5,
expr const & a6, expr const & a7, expr const & a8) const { expr const & a6, expr const & a7, expr const & a8, tag g) const {
return mk_app({*this, a1, a2, a3, a4, a5, a6, a7, a8}); return mk_app({*this, a1, a2, a3, a4, a5, a6, a7, a8}, g);
} }
/** \brief Return application (...((f x_{n-1}) x_{n-2}) ... x_0) */ /** \brief Return application (...((f x_{n-1}) x_{n-2}) ... x_0) */
expr mk_app_vars(expr const & f, unsigned n); expr mk_app_vars(expr const & f, unsigned n, tag g = nulltag);
expr mk_local_for(expr const & b, name_generator const & ngen); expr mk_local_for(expr const & b, name_generator const & ngen, tag g = nulltag);
bool enable_expr_caching(bool f); bool enable_expr_caching(bool f);
/** \brief Helper class for temporarily enabling/disabling expression caching */ /** \brief Helper class for temporarily enabling/disabling expression caching */

View file

@ -30,7 +30,7 @@ struct instantiate_easy_fn {
if (app && is_app(a)) if (app && is_app(a))
if (auto new_a = operator()(app_arg(a), false)) if (auto new_a = operator()(app_arg(a), false))
if (auto new_f = operator()(app_fn(a), true)) if (auto new_f = operator()(app_fn(a), true))
return some_expr(copy_tag(a, mk_app(*new_f, *new_a))); return some_expr(mk_app(*new_f, *new_a, a.get_tag()));
return none_expr(); return none_expr();
} }
}; };