Simplify metavariable context. Now, we have only 'lift' and 'inst' instead of 'subst', 'lift' and 'lower'

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2013-09-16 19:21:40 -07:00
parent cad562a448
commit 99a163f11d
19 changed files with 119 additions and 262 deletions

View file

@ -576,12 +576,12 @@ class elaborator::imp {
/**
\brief Temporary hack until we build the new elaborator.
*/
bool is_lower_lift_core(meta_entry_kind k, expr const & e, expr & c, unsigned & s, unsigned & n) {
bool is_lift(expr const & e, expr & c, unsigned & s, unsigned & n) {
if (!is_metavar(e) || !has_context(e))
return false;
meta_ctx const & ctx = metavar_ctx(e);
meta_entry const & entry = head(ctx);
if (entry.kind() == k) {
if (entry.kind() == meta_entry_kind::Lift) {
c = ::lean::mk_metavar(metavar_idx(e), tail(ctx));
add_trace(e, c);
s = entry.s();
@ -595,26 +595,12 @@ class elaborator::imp {
/**
\brief Temporary hack until we build the new elaborator.
*/
bool is_lower(expr const & e, expr & c, unsigned & s, unsigned & n) {
return is_lower_lift_core(meta_entry_kind::Lower, e, c, s, n);
}
/**
\brief Temporary hack until we build the new elaborator.
*/
bool is_lift(expr const & e, expr & c, unsigned & s, unsigned & n) {
return is_lower_lift_core(meta_entry_kind::Lift, e, c, s, n);
}
/**
\brief Temporary hack until we build the new elaborator.
*/
bool is_subst(expr const & e, expr & c, unsigned & s, expr & v) {
bool is_inst(expr const & e, expr & c, unsigned & s, expr & v) {
if (!is_metavar(e) || !has_context(e))
return false;
meta_ctx const & ctx = metavar_ctx(e);
meta_entry const & entry = head(ctx);
if (entry.kind() == meta_entry_kind::Subst) {
if (entry.kind() == meta_entry_kind::Inst) {
c = ::lean::mk_metavar(metavar_idx(e), tail(ctx));
add_trace(e, c);
s = entry.s();
@ -639,11 +625,6 @@ class elaborator::imp {
}
if (!has_metavar(t)) {
if (is_lower(e, a, s, n)) {
m_constraints.push_back(constraint(a, lift_free_vars(t, s-n, n), c));
return true;
}
if (is_lift(e, a, s, n)) {
if (!has_free_var(t, s, s+n)) {
m_constraints.push_back(constraint(a, lower_free_vars(t, s+n, n), c));
@ -660,9 +641,9 @@ class elaborator::imp {
return true;
}
if (is_subst(e, a, i, v) && is_lift(a, b, s, n) && has_free_var(t, s, s+n)) {
if (is_inst(e, a, i, v) && is_lift(a, b, s, n) && !has_free_var(t, s, s+n)) {
// subst (lift b s n) i v == t
// (lift b s n) does not have free-variables in the range [s, s+n)
// t does not have free-variables in the range [s, s+n)
// Thus, if t has a free variables in [s, s+n), then the only possible solution is
// (lift b s n) == i
// v == t
@ -670,7 +651,6 @@ class elaborator::imp {
m_constraints.push_back(constraint(v, t, c));
return true;
}
return false;
}

View file

@ -15,10 +15,10 @@ Author: Leonardo de Moura
#include "util/interruptable_ptr.h"
#include "kernel/context.h"
#include "kernel/for_each.h"
#include "kernel/instantiate.h"
#include "kernel/occurs.h"
#include "kernel/builtin.h"
#include "kernel/free_vars.h"
#include "kernel/replace.h"
#include "library/context_to_lambda.h"
#include "library/placeholder.h"
#include "frontends/lean/notation.h"
@ -75,8 +75,7 @@ static format g_in_fmt = highlight_keyword(format("in"));
static format g_assign_fmt = highlight_keyword(format(":="));
static format g_geq_fmt = format("\u2265");
static format g_lift_fmt = highlight_keyword(format("lift"));
static format g_lower_fmt = highlight_keyword(format("lower"));
static format g_subst_fmt = highlight_keyword(format("subst"));
static format g_inst_fmt = highlight_keyword(format("inst"));
static name g_pp_max_depth {"lean", "pp", "max_depth"};
static name g_pp_max_steps {"lean", "pp", "max_steps"};
@ -129,6 +128,24 @@ name get_unused_name(expr const & e) {
return n1;
}
/**
\brief Replace free variable \c 0 in \c a with the name \c n.
\remark Metavariable context is ignored.
*/
expr replace_var_with_name(expr const & a, name const & n) {
expr c = mk_constant(n);
auto f = [=](expr const & m, unsigned offset) -> expr {
if (is_var(m)) {
unsigned vidx = var_idx(m);
if (vidx >= offset)
return vidx == offset ? c : mk_var(vidx - 1);
}
return m;
};
return replace_fn<decltype(f)>(f)(a);
}
/** \brief Functional object for pretty printing expressions */
class pp_fn {
typedef scoped_map<expr, name, expr_hash, expr_eqp> aliases;
@ -288,7 +305,7 @@ class pp_fn {
name n1 = get_unused_name(lambda);
m_local_names.insert(n1);
r.push_back(mk_pair(n1, abst_domain(lambda)));
expr b = instantiate_with_closed(abst_body(lambda), mk_constant(n1));
expr b = replace_var_with_name(abst_body(lambda), n1);
if (is_quant_expr(b, is_forall))
return collect_nested_quantifiers(b, is_forall, r);
else
@ -696,9 +713,9 @@ class pp_fn {
name n1 = get_unused_name(e);
m_local_names.insert(n1);
r.push_back(mk_pair(n1, abst_domain(e)));
expr b = instantiate_with_closed(abst_body(e), mk_constant(n1));
expr b = replace_var_with_name(abst_body(e), n1);
if (T)
T = instantiate_with_closed(abst_body(T), mk_constant(n1));
T = replace_var_with_name(abst_body(T), n1);
return collect_nested(b, T, k, r);
} else {
return mk_pair(e, T);
@ -931,7 +948,7 @@ class pp_fn {
name n1 = get_unused_name(e);
m_local_names.insert(n1);
bindings.push_back(std::make_tuple(n1, let_type(e), let_value(e)));
expr b = instantiate_with_closed(let_body(e), mk_constant(n1));
expr b = replace_var_with_name(let_body(e), n1);
return collect_nested_let(b, bindings);
} else {
return e;
@ -1017,18 +1034,17 @@ class pp_fn {
format e_fmt;
switch (e.kind()) {
case meta_entry_kind::Lift: e_fmt = format{g_lift_fmt, colon(), format(e.s()), colon(), format(e.n())}; break;
case meta_entry_kind::Lower: e_fmt = format{g_lower_fmt, colon(), format(e.s()), colon(), format(e.n())}; break;
case meta_entry_kind::Subst: {
case meta_entry_kind::Inst: {
auto p_e = pp_child_with_paren(e.v(), depth);
r_weight += p_e.second;
e_fmt = format{g_subst_fmt, colon(), format(e.s()), space(), nest(m_indent, p_e.first)};
e_fmt = format{g_inst_fmt, colon(), format(e.s()), space(), nest(m_indent, p_e.first)};
break;
}}
if (first) {
ctx_fmt = e_fmt;
first = false;
} else {
ctx_fmt += compose(line(), e_fmt);
ctx_fmt += format{comma(), line(), e_fmt};
}
}
return mk_result(group(compose(mv_fmt, nest(m_indent, format{lsb(), ctx_fmt, rsb()}))), r_weight);
@ -1195,7 +1211,7 @@ class pp_formatter_cell : public formatter_cell {
} else {
r += format{line(), group(entry)};
}
c2 = instantiate_with_closed(fake_context_rest(c2), mk_constant(n1));
c2 = replace_var_with_name(fake_context_rest(c2), n1);
}
if (include_e) {
if (first)
@ -1319,7 +1335,7 @@ public:
name n1 = get_unused_name(c2);
fn.register_local(n1);
expr const & rest = fake_context_rest(c2);
c2 = instantiate_with_closed(rest, mk_constant(n1));
c2 = replace_var_with_name(rest, n1);
}
return fn(c2);
}

View file

@ -13,8 +13,8 @@ Author: Leonardo de Moura
#include "kernel/expr_eq.h"
namespace lean {
meta_entry::meta_entry(meta_entry_kind k, unsigned s, unsigned n):m_kind(k), m_s(s), m_n(n) {}
meta_entry::meta_entry(unsigned s, expr const & v):m_kind(meta_entry_kind::Subst), m_s(s), m_v(v) {}
meta_entry::meta_entry(unsigned s, unsigned n):m_kind(meta_entry_kind::Lift), m_s(s), m_n(n) {}
meta_entry::meta_entry(unsigned s, expr const & v):m_kind(meta_entry_kind::Inst), m_s(s), m_v(v) {}
meta_entry::~meta_entry() {}
unsigned hash_args(unsigned size, expr const * args) {

View file

@ -36,8 +36,7 @@ class value;
meta_ctx ::= [meta_entry]
meta_entry ::= lift idx idx
| lower idx idx
| subst idx expr
| inst idx expr
TODO(Leo): match expressions.
@ -248,27 +247,26 @@ public:
/**
\see meta_entry
*/
enum class meta_entry_kind { Lift, Lower, Subst };
enum class meta_entry_kind { Lift, Inst };
/**
\brief An entry in a metavariable context.
It represents objects of the form:
<code>
| Lift s n
| Lower s n
| Subst s v
| Inst s v
</code>
where \c s and \c n are unsigned integers, and
\c v is an expression
The meaning of <tt>Lift s n</tt> is: lift the free variables greater than or equal to \c s by \c n.
The meaning of <tt>Lower s n</tt> is: lower the free variables greater than or equal to \c s by \c n.
The meaning of <tt>Subst s v</tt> is: substitute the free variable \c s with the expression \c v.
The meaning of <tt>Inst s v</tt> is: instantiate free variable \c s with the expression \c v, and
lower free variables greater than \c s.
The metavariable context records operations that must be applied
whenever we substitute a metavariable with an actual expression.
For example, let ?M be a metavariable with context
<code>
[ Lower 1 1, Subst 0 a, Lift 1 2 ]
[ Inst 0 a, Lift 1 2 ]
</code>
Now, assume we want to instantiate \c ?M with <tt>f #0 (g #2)</tt>.
Then, we apply the metavariable entries from right to left.
@ -276,11 +274,7 @@ enum class meta_entry_kind { Lift, Lower, Subst };
<code>
f #0 (g #4)
</code>
Then, we apply <tt>(Subst 0 a)</tt> and produce
<code>
f a (g #4)
</code>
Finally, we apply <tt>(Lower 1 1)</tt> and get the final result
Then, we apply <tt>(Inst 0 a)</tt> and produce
<code>
f a (g #3)
</code>
@ -290,22 +284,20 @@ class meta_entry {
unsigned m_s;
unsigned m_n;
expr m_v;
meta_entry(meta_entry_kind k, unsigned s, unsigned n);
meta_entry(unsigned s, unsigned n);
meta_entry(unsigned s, expr const & v);
public:
~meta_entry();
friend meta_entry mk_lift(unsigned s, unsigned n);
friend meta_entry mk_lower(unsigned s, unsigned n);
friend meta_entry mk_subst(unsigned s, expr const & v);
friend meta_entry mk_inst(unsigned s, expr const & v);
meta_entry_kind kind() const { return m_kind; }
bool is_subst() const { return kind() == meta_entry_kind::Subst; }
bool is_inst() const { return kind() == meta_entry_kind::Inst; }
unsigned s() const { return m_s; }
unsigned n() const { lean_assert(kind() != meta_entry_kind::Subst); return m_n; }
expr const & v() const { lean_assert(kind() == meta_entry_kind::Subst); return m_v; }
unsigned n() const { lean_assert(kind() == meta_entry_kind::Lift); return m_n; }
expr const & v() const { lean_assert(kind() == meta_entry_kind::Inst); return m_v; }
};
inline meta_entry mk_lift(unsigned s, unsigned n) { return meta_entry(meta_entry_kind::Lift, s, n); }
inline meta_entry mk_lower(unsigned s, unsigned n) { return meta_entry(meta_entry_kind::Lower, s, n); }
inline meta_entry mk_subst(unsigned s, expr const & v) { return meta_entry(s, v); }
inline meta_entry mk_lift(unsigned s, unsigned n) { return meta_entry(s, n); }
inline meta_entry mk_inst(unsigned s, expr const & v) { return meta_entry(s, v); }
/** \brief Metavariables */
class expr_metavar : public expr_cell {
@ -586,7 +578,7 @@ template<typename F> expr update_metavar(expr const & e, unsigned i, F f) {
meta_entry new_me = f(me);
if (new_me.kind() != me.kind() || new_me.s() != me.s()) {
modified = true;
} else if (new_me.is_subst()) {
} else if (new_me.is_inst()) {
if (!is_eqp(new_me.v(), me.v()))
modified = true;
} else if (new_me.n() != me.n()) {

View file

@ -68,7 +68,7 @@ class expr_eq_fn {
compare(metavar_ctx(a), metavar_ctx(b), [&](meta_entry const & e1, meta_entry const & e2) {
if (e1.kind() != e2.kind() || e1.s() != e2.s())
return false;
if (e1.is_subst())
if (e1.is_inst())
return apply(e1.v(), e2.v());
else
return e1.n() == e2.n();

View file

@ -175,13 +175,15 @@ bool has_free_var(expr const & e, unsigned low, unsigned high) {
}
expr lower_free_vars(expr const & e, unsigned s, unsigned d) {
lean_assert(d > 0);
lean_assert(s >= d);
lean_assert(!has_free_var(e, s-d, s));
auto f = [=](expr const & e, unsigned offset) -> expr {
if (is_var(e) && var_idx(e) >= s + offset) {
lean_assert(var_idx(e) >= offset + d);
return mk_var(var_idx(e) - d);
} else if (is_metavar(e)) {
return add_lower(e, s + offset, d);
lean_unreachable();
return e;
} else {
return e;
}

View file

@ -35,7 +35,7 @@ bool has_free_var(expr const & e, unsigned low, unsigned high);
\pre !has_free_var(e, 0, d)
*/
expr lower_free_vars(expr const & e, unsigned s, unsigned d);
inline expr lower_free_vars(expr const & e, unsigned d) { return lower_free_vars(e, 0, d); }
inline expr lower_free_vars(expr const & e, unsigned d) { return lower_free_vars(e, d, d); }
/**
\brief Lift free variables >= s in \c e by d.

View file

@ -27,21 +27,21 @@ expr instantiate_with_closed(expr const & a, unsigned n, expr const * s) {
} else if (is_metavar(m)) {
expr r = m;
for (unsigned i = 0; i < n; i++)
r = add_subst(r, offset + i, s[n - i - 1]);
return add_lower(r, offset + n, n);
r = add_inst(r, offset + n - i - 1, s[i]);
return r;
} else {
return m;
}
};
return replace_fn<decltype(f)>(f)(a);
}
expr instantiate(expr const & a, unsigned n, expr const * s) {
expr instantiate(expr const & a, unsigned s, unsigned n, expr const * subst) {
auto f = [=](expr const & m, unsigned offset) -> expr {
if (is_var(m)) {
unsigned vidx = var_idx(m);
if (vidx >= offset) {
if (vidx < offset + n)
return lift_free_vars(s[n - (vidx - offset) - 1], offset);
if (vidx >= offset + s) {
if (vidx < offset + s + n)
return lift_free_vars(subst[n - (vidx - s - offset) - 1], offset);
else
return mk_var(vidx - n);
} else {
@ -50,12 +50,18 @@ expr instantiate(expr const & a, unsigned n, expr const * s) {
} else if (is_metavar(m)) {
expr r = m;
for (unsigned i = 0; i < n; i++)
r = add_subst(r, offset + i, lift_free_vars(s[n - i - 1], offset + n));
return add_lower(r, offset + n, n);
r = add_inst(r, offset + s + n - i - 1, lift_free_vars(subst[i], offset + n - i - 1));
return r;
} else {
return m;
}
};
return replace_fn<decltype(f)>(f)(a);
}
expr instantiate(expr const & e, unsigned n, expr const * s) {
return instantiate(e, 0, n, s);
}
expr instantiate(expr const & e, unsigned i, expr const & s) {
return instantiate(e, i, 1, &s);
}
}

View file

@ -25,4 +25,8 @@ inline expr instantiate_with_closed(expr const & e, expr const & s) { return ins
expr instantiate(expr const & e, unsigned n, expr const * s);
inline expr instantiate(expr const & e, std::initializer_list<expr> const & l) { return instantiate(e, l.size(), l.begin()); }
inline expr instantiate(expr const & e, expr const & s) { return instantiate(e, 1, &s); }
/**
\brief Replace free variable \c i with \c s in \c e.
*/
expr instantiate(expr const & e, unsigned i, expr const & s);
}

View file

@ -9,6 +9,7 @@ Author: Leonardo de Moura
#include "kernel/metavar.h"
#include "kernel/replace.h"
#include "kernel/free_vars.h"
#include "kernel/instantiate.h"
#include "kernel/occurs.h"
#include "kernel/for_each.h"
@ -66,31 +67,13 @@ void metavar_env::assign(unsigned midx, expr const & v) {
m_env[midx] = data(v, p->m_type, p->m_ctx);
}
expr subst(expr const & a, unsigned i, expr const & c) {
auto f = [&](expr const & e, unsigned offset) -> expr {
if (is_var(e)) {
unsigned vidx = var_idx(e);
if (vidx == offset + i)
return lift_free_vars(c, 0, offset);
else
return e;
} else if (is_metavar(e)) {
return add_subst(e, offset, lift_free_vars(c, 0, offset));
} else {
return e;
}
};
return replace_fn<decltype(f)>(f)(a);
}
expr instantiate(expr const & s, meta_ctx const & ctx, metavar_env const & env) {
if (ctx) {
expr r = instantiate(s, tail(ctx), env);
meta_entry const & e = head(ctx);
switch (e.kind()) {
case meta_entry_kind::Lift: return lift_free_vars(r, e.s(), e.n());
case meta_entry_kind::Lower: return lower_free_vars(r, e.s(), e.n());
case meta_entry_kind::Subst: return subst(r, e.s(), instantiate_metavars(e.v(), env));
case meta_entry_kind::Inst: return ::lean::instantiate(r, e.s(), instantiate_metavars(e.v(), env));
}
lean_unreachable();
return s;
@ -143,69 +126,23 @@ expr add_lift(expr const & m, unsigned s, unsigned n) {
return mk_metavar(metavar_idx(m), add_lift(metavar_ctx(m), s, n));
}
meta_ctx add_lower(meta_ctx const & ctx, unsigned s2, unsigned n2) {
meta_ctx add_inst(meta_ctx const & ctx, unsigned s, expr const & v) {
if (ctx) {
meta_entry e = head(ctx);
unsigned s1, n1;
switch (e.kind()) {
case meta_entry_kind::Lift:
s1 = e.s();
n1 = e.n();
if (s1 <= s2 && s2 <= s1 + n1) {
if (n1 == n2)
return tail(ctx);
else if (n1 > n2)
return cons(mk_lift(s1, n1 - n2), tail(ctx));
}
break;
case meta_entry_kind::Lower:
s1 = e.s();
n1 = e.n();
if (s2 == s1 - n1)
return add_lower(tail(ctx), s1, n1 + n2);
break;
case meta_entry_kind::Subst:
break;
}
}
return cons(mk_lower(s2, n2), ctx);
}
expr add_lower(expr const & m, unsigned s, unsigned n) {
return mk_metavar(metavar_idx(m), add_lower(metavar_ctx(m), s, n));
}
meta_ctx add_subst(meta_ctx const & ctx, unsigned s, expr const & v) {
if (ctx) {
meta_entry e = head(ctx);
switch (e.kind()) {
case meta_entry_kind::Subst:
return cons(mk_subst(s, v), ctx);
case meta_entry_kind::Lower:
if (s >= e.s())
return cons(e, add_subst(tail(ctx), s + e.n(), lift_free_vars(v, e.s(), e.n())));
else
return cons(e, add_subst(tail(ctx), s, lift_free_vars(v, e.s(), e.n())));
case meta_entry_kind::Lift:
if (e.kind() == meta_entry_kind::Lift) {
if (e.s() <= s && s < e.s() + e.n()) {
return ctx;
} else if (s < e.s() && !has_free_var(v, e.s(), std::numeric_limits<unsigned>::max())) {
return cons(e, add_subst(tail(ctx), s, v));
} else if (s >= e.s() + e.n() && !has_free_var(v, e.s(), std::numeric_limits<unsigned>::max())) {
return cons(e, add_subst(tail(ctx), s - e.n(), v));
} else {
return cons(mk_subst(s, v), ctx);
if (e.n() == 1)
return tail(ctx);
else
return add_lift(tail(ctx), e.s(), e.n() - 1);
}
}
lean_unreachable();
return ctx;
} else {
return cons(mk_subst(s, v), ctx);
}
return cons(mk_inst(s, v), ctx);
}
expr add_subst(expr const & m, unsigned s, expr const & v) {
return mk_metavar(metavar_idx(m), add_subst(metavar_ctx(m), s, v));
expr add_inst(expr const & m, unsigned s, expr const & v) {
return mk_metavar(metavar_idx(m), add_inst(metavar_ctx(m), s, v));
}
bool has_context(expr const & m) {

View file

@ -163,31 +163,16 @@ meta_ctx add_lift(meta_ctx const & ctx, unsigned s, unsigned n);
expr add_lift(expr const & m, unsigned s, unsigned n);
/**
\brief Add a lower:s:n operation to the context of the given metavariable.
\brief Add an inst:s:v operation to the context of the given metavariable.
\pre is_metavar(m)
\pre n <= s
*/
expr add_lower(expr const & m, unsigned s, unsigned n);
expr add_inst(expr const & m, unsigned s, expr const & v);
/**
\brief Extend the context \c ctx with the entry <tt>lower:s:n</tt>
\brief Extend the context \c ctx with the entry <tt>inst:s v</tt>
*/
meta_ctx add_lower(meta_ctx const & ctx, unsigned s, unsigned n);
/**
\brief Add a subst:s:v operation to the context of the given metavariable.
\pre is_metavar(m)
\pre !occurs(m, v)
*/
expr add_subst(expr const & m, unsigned s, expr const & v);
/**
\brief Extend the context \c ctx with the entry <tt>subst:s v</tt>
*/
meta_ctx add_subst(meta_ctx const & ctx, unsigned s, expr const & v);
meta_ctx add_inst(meta_ctx const & ctx, unsigned s, expr const & v);
/**
\brief Return true iff the given metavariable has a non-empty

View file

@ -141,46 +141,6 @@ class normalizer::imp {
return expr();
}
bool is_identity_stack(value_stack const & s, unsigned k) {
if (length(s) != k)
return false;
unsigned i = 0;
for (auto e : s) {
if (e.kind() != svalue_kind::BoundedVar || k - to_bvar(e) - 1 != i)
return false;
++i;
}
return true;
}
/**
\brief Update the metavariable context for \c m based on the
value_stack \c s and the number of binders \c k.
\pre is_metavar(m)
*/
expr updt_metavar(expr const & m, value_stack const & s, unsigned k) {
lean_assert(is_metavar(m));
if (is_identity_stack(s, k))
return m;
meta_ctx ctx = metavar_ctx(m);
unsigned midx = metavar_idx(m);
unsigned s_len = length(s);
unsigned i = 0;
ctx = add_lift(ctx, s_len, s_len);
for (auto e : s) {
ctx = add_subst(ctx, i, lift_free_vars(reify(e, k), s_len));
++i;
}
ctx = add_lower(ctx, s_len, s_len);
unsigned m_ctx_len = m_ctx.size();
lean_assert(s_len + m_ctx_len >= k);
if (s_len + m_ctx_len > k)
ctx = add_lower(ctx, s_len, s_len + m_ctx_len - k);
return mk_metavar(midx, ctx);
}
/** \brief Normalize the expression \c a in a context composed of stack \c s and \c k binders. */
svalue normalize(expr const & a, value_stack const & s, unsigned k) {
flet<unsigned> l(m_depth, m_depth+1);
@ -201,7 +161,8 @@ class normalizer::imp {
if (m_menv && m_menv->contains(a) && m_menv->is_assigned(a)) {
r = normalize(m_menv->get_subst(a), s, k);
} else {
r = svalue(updt_metavar(a, s, k));
// TODO(Leo): update metavariable
r = svalue(a);
}
break;
case expr_kind::Var:

View file

@ -42,8 +42,8 @@ class deep_copy_fn {
}
case expr_kind::MetaVar:
r = update_metavar(a, [&](meta_entry const & e) -> meta_entry {
if (e.is_subst())
return mk_subst(e.s(), apply(e.v()));
if (e.is_inst())
return mk_inst(e.s(), apply(e.v()));
else
return e;
});

View file

@ -64,8 +64,8 @@ struct max_sharing_fn::imp {
}
case expr_kind::MetaVar: {
expr r = update_metavar(a, [=](meta_entry const & e) -> meta_entry {
if (e.is_subst())
return mk_subst(e.s(), apply(e.v()));
if (e.is_inst())
return mk_inst(e.s(), apply(e.v()));
else
return e;
});

View file

@ -84,8 +84,7 @@ struct print_expr_fn {
if (first) first = false; else out() << ", ";
switch (e.kind()) {
case meta_entry_kind::Lift: out() << "lift:" << e.s() << ":" << e.n(); break;
case meta_entry_kind::Lower: out() << "lower:" << e.s() << ":" << e.n(); break;
case meta_entry_kind::Subst: out() << "subst:" << e.s() << " "; print_child(e.v(), c); break;
case meta_entry_kind::Inst: out() << "inst:" << e.s() << " "; print_child(e.v(), c); break;
}
}
out() << "]";

View file

@ -72,14 +72,14 @@ static void tst2() {
expr m1 = menv.mk_metavar();
expr m2 = menv.mk_metavar();
// move m1 to a different context, and store new metavariable + context in m11
expr m11 = add_lower(add_subst(m1, 0, f(a, m2)), 1, 1);
std::cout << "---------------------\n";
expr m11 = add_inst(m1, 0, f(a, m2));
std::cout << m11 << "\n";
menv.assign(m1, f(Var(0)));
std::cout << instantiate_metavars(m11, menv) << "\n";
lean_assert(instantiate_metavars(m11, menv) == f(f(a, add_lower(m2, 1, 1))));
menv.assign(m2, g(a, Var(1)));
std::cout << instantiate_metavars(h(m11), menv) << "\n";
lean_assert(instantiate_metavars(h(m11), menv) == h(f(f(a, g(a, Var(0))))));
lean_assert(instantiate_metavars(h(m11), menv) == h(f(f(a, g(a, Var(1))))));
}
static void tst3() {
@ -115,34 +115,7 @@ static void tst4() {
}
static void tst5() {
metavar_env menv;
expr m1 = menv.mk_metavar();
expr f = Const("f");
expr m11 = add_lower(m1, 2, 1);
std::cout << add_subst(add_lower(m1, 2, 1), 1, f(Var(0))) << "\n";
std::cout << add_subst(add_lower(m1, 2, 1), 1, f(Var(3))) << "\n";
std::cout << add_subst(add_lower(m1, 2, 1), 3, f(Var(0))) << "\n";
std::cout << add_subst(add_lower(add_lower(m1, 2, 1), 3, 1), 3, f(Var(0))) << "\n";
std::cout << add_lower(add_lift(m1, 1, 1), 1, 1) << "\n";
std::cout << add_lower(add_lift(m1, 1, 1), 2, 1) << "\n";
std::cout << add_lower(add_lift(m1, 1, 1), 2, 2) << "\n";
std::cout << add_lower(add_lift(m1, 1, 3), 2, 2) << "\n";
std::cout << add_subst(add_lift(m1, 1, 1), 0, f(Var(0))) << "\n";
std::cout << add_subst(add_lift(m1, 1, 1), 1, f(Var(0))) << "\n";
lean_assert(add_subst(add_lower(m1, 2, 1), 1, f(Var(0))) ==
add_lower(add_subst(m1, 1, f(Var(0))), 2, 1));
lean_assert(add_subst(add_lower(m1, 2, 1), 1, f(Var(3))) ==
add_lower(add_subst(m1, 1, f(Var(4))), 2, 1));
lean_assert(add_subst(add_lower(m1, 2, 1), 2, f(Var(0))) ==
add_lower(add_subst(m1, 3, f(Var(0))), 2, 1));
lean_assert(add_subst(add_lower(add_lower(m1, 2, 1), 3, 1), 3, f(Var(0))) ==
add_lower(add_lower(add_subst(m1, 5, f(Var(0))), 2, 1), 3, 1));
lean_assert(add_lower(add_lift(m1, 1, 1), 2, 1) == m1);
lean_assert(add_lower(add_lift(m1, 1, 3), 2, 2) == add_lift(m1, 1, 1));
lean_assert(add_subst(add_lift(m1, 1, 1), 0, f(Var(0))) ==
add_lift(add_subst(m1, 0, f(Var(0))), 1, 1));
lean_assert(add_subst(add_lift(m1, 1, 1), 1, f(Var(0))) ==
add_lift(m1, 1, 1));
return;
}
static void tst6() {
@ -256,6 +229,7 @@ static void tst12() {
std::cout << instantiate(f(m), {Var(1), Var(0)}) << "\n";
}
#if 0
static void tst13() {
environment env;
metavar_env menv;
@ -384,6 +358,7 @@ static void tst17() {
lean_assert(instantiate_metavars(norm(F, ctx), menv2) ==
norm(instantiate_metavars(F, menv2), ctx));
}
#endif
int main() {
tst1();
@ -398,11 +373,11 @@ int main() {
tst10();
tst11();
tst12();
tst13();
tst14();
tst15();
tst16();
tst17();
// tst13();
// tst14();
// tst15();
// tst16();
// tst17();
return has_violations() ? 1 : 0;
}

View file

@ -19,7 +19,7 @@ Function type:
Π (A : Type), A → A
Arguments types:
A : Type
x : ?M0
x : ?M0[lift:0:2]
Elaborator state
#0 ≈ ?M0[lift:0:2]
Assumed: eq
@ -29,8 +29,8 @@ Function type:
Π (A : Type), A → A → Bool
Arguments types:
C : Type
a : ?M0[lower:5:5 lift:0:3 subst:0 B subst:1 A]
b : ?M2[lower:5:5 lift:0:2 subst:0 a subst:1 B subst:2 A]
a : ?M0[lift:0:3]
b : ?M2[lift:0:2]
Elaborator state
#0 ≈ ?M2[lift:0:2]
#0 ≈ ?M0[lift:0:3]

View file

@ -15,8 +15,8 @@ Candidates:
Int::add :
Nat::add :
Arguments:
a : ?M0
b : ?M2[lower:2:2 lift:0:1 subst:0 a]
a : ?M0[lift:0:2]
b : ?M2[lift:0:1]
λ a b c : , a + c + b
Error (line: 17, pos: 19) ambiguous overloads
Candidates:
@ -24,7 +24,7 @@ Candidates:
Int::add :
Nat::add :
Arguments:
a : ?M0
b : ?M2[lower:2:2 lift:0:1 subst:0 a]
a : ?M0[lift:0:2]
b : ?M2[lift:0:1]
Assumed: x
λ a b : , a + x + b

View file

@ -8,7 +8,7 @@ Function type:
Π (A : Type), A → Bool
Arguments types:
B : Type
a : ?M0[lower:3:3 lift:0:2 subst:0 A]
a : ?M0[lift:0:2]
Elaborator state
#0 ≈ ?M0[lift:0:2]
Assumed: myeq