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:
parent
cad562a448
commit
99a163f11d
19 changed files with 119 additions and 262 deletions
|
@ -576,12 +576,12 @@ class elaborator::imp {
|
||||||
/**
|
/**
|
||||||
\brief Temporary hack until we build the new elaborator.
|
\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))
|
if (!is_metavar(e) || !has_context(e))
|
||||||
return false;
|
return false;
|
||||||
meta_ctx const & ctx = metavar_ctx(e);
|
meta_ctx const & ctx = metavar_ctx(e);
|
||||||
meta_entry const & entry = head(ctx);
|
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));
|
c = ::lean::mk_metavar(metavar_idx(e), tail(ctx));
|
||||||
add_trace(e, c);
|
add_trace(e, c);
|
||||||
s = entry.s();
|
s = entry.s();
|
||||||
|
@ -595,26 +595,12 @@ class elaborator::imp {
|
||||||
/**
|
/**
|
||||||
\brief Temporary hack until we build the new elaborator.
|
\brief Temporary hack until we build the new elaborator.
|
||||||
*/
|
*/
|
||||||
bool is_lower(expr const & e, expr & c, unsigned & s, unsigned & n) {
|
bool is_inst(expr const & e, expr & c, unsigned & s, expr & v) {
|
||||||
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) {
|
|
||||||
if (!is_metavar(e) || !has_context(e))
|
if (!is_metavar(e) || !has_context(e))
|
||||||
return false;
|
return false;
|
||||||
meta_ctx const & ctx = metavar_ctx(e);
|
meta_ctx const & ctx = metavar_ctx(e);
|
||||||
meta_entry const & entry = head(ctx);
|
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));
|
c = ::lean::mk_metavar(metavar_idx(e), tail(ctx));
|
||||||
add_trace(e, c);
|
add_trace(e, c);
|
||||||
s = entry.s();
|
s = entry.s();
|
||||||
|
@ -639,11 +625,6 @@ class elaborator::imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!has_metavar(t)) {
|
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 (is_lift(e, a, s, n)) {
|
||||||
if (!has_free_var(t, s, s+n)) {
|
if (!has_free_var(t, s, s+n)) {
|
||||||
m_constraints.push_back(constraint(a, lower_free_vars(t, s+n, n), c));
|
m_constraints.push_back(constraint(a, lower_free_vars(t, s+n, n), c));
|
||||||
|
@ -660,9 +641,9 @@ class elaborator::imp {
|
||||||
return true;
|
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
|
// 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
|
// Thus, if t has a free variables in [s, s+n), then the only possible solution is
|
||||||
// (lift b s n) == i
|
// (lift b s n) == i
|
||||||
// v == t
|
// v == t
|
||||||
|
@ -670,7 +651,6 @@ class elaborator::imp {
|
||||||
m_constraints.push_back(constraint(v, t, c));
|
m_constraints.push_back(constraint(v, t, c));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,10 @@ Author: Leonardo de Moura
|
||||||
#include "util/interruptable_ptr.h"
|
#include "util/interruptable_ptr.h"
|
||||||
#include "kernel/context.h"
|
#include "kernel/context.h"
|
||||||
#include "kernel/for_each.h"
|
#include "kernel/for_each.h"
|
||||||
#include "kernel/instantiate.h"
|
|
||||||
#include "kernel/occurs.h"
|
#include "kernel/occurs.h"
|
||||||
#include "kernel/builtin.h"
|
#include "kernel/builtin.h"
|
||||||
#include "kernel/free_vars.h"
|
#include "kernel/free_vars.h"
|
||||||
|
#include "kernel/replace.h"
|
||||||
#include "library/context_to_lambda.h"
|
#include "library/context_to_lambda.h"
|
||||||
#include "library/placeholder.h"
|
#include "library/placeholder.h"
|
||||||
#include "frontends/lean/notation.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_assign_fmt = highlight_keyword(format(":="));
|
||||||
static format g_geq_fmt = format("\u2265");
|
static format g_geq_fmt = format("\u2265");
|
||||||
static format g_lift_fmt = highlight_keyword(format("lift"));
|
static format g_lift_fmt = highlight_keyword(format("lift"));
|
||||||
static format g_lower_fmt = highlight_keyword(format("lower"));
|
static format g_inst_fmt = highlight_keyword(format("inst"));
|
||||||
static format g_subst_fmt = highlight_keyword(format("subst"));
|
|
||||||
|
|
||||||
static name g_pp_max_depth {"lean", "pp", "max_depth"};
|
static name g_pp_max_depth {"lean", "pp", "max_depth"};
|
||||||
static name g_pp_max_steps {"lean", "pp", "max_steps"};
|
static name g_pp_max_steps {"lean", "pp", "max_steps"};
|
||||||
|
@ -129,6 +128,24 @@ name get_unused_name(expr const & e) {
|
||||||
return n1;
|
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 */
|
/** \brief Functional object for pretty printing expressions */
|
||||||
class pp_fn {
|
class pp_fn {
|
||||||
typedef scoped_map<expr, name, expr_hash, expr_eqp> aliases;
|
typedef scoped_map<expr, name, expr_hash, expr_eqp> aliases;
|
||||||
|
@ -288,7 +305,7 @@ class pp_fn {
|
||||||
name n1 = get_unused_name(lambda);
|
name n1 = get_unused_name(lambda);
|
||||||
m_local_names.insert(n1);
|
m_local_names.insert(n1);
|
||||||
r.push_back(mk_pair(n1, abst_domain(lambda)));
|
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))
|
if (is_quant_expr(b, is_forall))
|
||||||
return collect_nested_quantifiers(b, is_forall, r);
|
return collect_nested_quantifiers(b, is_forall, r);
|
||||||
else
|
else
|
||||||
|
@ -696,9 +713,9 @@ class pp_fn {
|
||||||
name n1 = get_unused_name(e);
|
name n1 = get_unused_name(e);
|
||||||
m_local_names.insert(n1);
|
m_local_names.insert(n1);
|
||||||
r.push_back(mk_pair(n1, abst_domain(e)));
|
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)
|
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);
|
return collect_nested(b, T, k, r);
|
||||||
} else {
|
} else {
|
||||||
return mk_pair(e, T);
|
return mk_pair(e, T);
|
||||||
|
@ -931,7 +948,7 @@ class pp_fn {
|
||||||
name n1 = get_unused_name(e);
|
name n1 = get_unused_name(e);
|
||||||
m_local_names.insert(n1);
|
m_local_names.insert(n1);
|
||||||
bindings.push_back(std::make_tuple(n1, let_type(e), let_value(e)));
|
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);
|
return collect_nested_let(b, bindings);
|
||||||
} else {
|
} else {
|
||||||
return e;
|
return e;
|
||||||
|
@ -1017,18 +1034,17 @@ class pp_fn {
|
||||||
format e_fmt;
|
format e_fmt;
|
||||||
switch (e.kind()) {
|
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::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::Inst: {
|
||||||
case meta_entry_kind::Subst: {
|
|
||||||
auto p_e = pp_child_with_paren(e.v(), depth);
|
auto p_e = pp_child_with_paren(e.v(), depth);
|
||||||
r_weight += p_e.second;
|
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;
|
break;
|
||||||
}}
|
}}
|
||||||
if (first) {
|
if (first) {
|
||||||
ctx_fmt = e_fmt;
|
ctx_fmt = e_fmt;
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} 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);
|
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 {
|
} else {
|
||||||
r += format{line(), group(entry)};
|
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 (include_e) {
|
||||||
if (first)
|
if (first)
|
||||||
|
@ -1319,7 +1335,7 @@ public:
|
||||||
name n1 = get_unused_name(c2);
|
name n1 = get_unused_name(c2);
|
||||||
fn.register_local(n1);
|
fn.register_local(n1);
|
||||||
expr const & rest = fake_context_rest(c2);
|
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);
|
return fn(c2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ Author: Leonardo de Moura
|
||||||
#include "kernel/expr_eq.h"
|
#include "kernel/expr_eq.h"
|
||||||
|
|
||||||
namespace lean {
|
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, 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::Subst), m_s(s), m_v(v) {}
|
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() {}
|
meta_entry::~meta_entry() {}
|
||||||
|
|
||||||
unsigned hash_args(unsigned size, expr const * args) {
|
unsigned hash_args(unsigned size, expr const * args) {
|
||||||
|
|
|
@ -35,9 +35,8 @@ class value;
|
||||||
|
|
||||||
meta_ctx ::= [meta_entry]
|
meta_ctx ::= [meta_entry]
|
||||||
|
|
||||||
meta_entry ::= lift idx idx
|
meta_entry ::= lift idx idx
|
||||||
| lower idx idx
|
| inst idx expr
|
||||||
| subst idx expr
|
|
||||||
|
|
||||||
TODO(Leo): match expressions.
|
TODO(Leo): match expressions.
|
||||||
|
|
||||||
|
@ -248,27 +247,26 @@ public:
|
||||||
/**
|
/**
|
||||||
\see meta_entry
|
\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.
|
\brief An entry in a metavariable context.
|
||||||
It represents objects of the form:
|
It represents objects of the form:
|
||||||
<code>
|
<code>
|
||||||
| Lift s n
|
| Lift s n
|
||||||
| Lower s n
|
| Inst s v
|
||||||
| Subst s v
|
|
||||||
</code>
|
</code>
|
||||||
where \c s and \c n are unsigned integers, and
|
where \c s and \c n are unsigned integers, and
|
||||||
\c v is an expression
|
\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>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>Inst s v</tt> is: instantiate free variable \c s with the expression \c v, and
|
||||||
The meaning of <tt>Subst s v</tt> is: substitute the free variable \c s with the expression \c v.
|
lower free variables greater than \c s.
|
||||||
|
|
||||||
The metavariable context records operations that must be applied
|
The metavariable context records operations that must be applied
|
||||||
whenever we substitute a metavariable with an actual expression.
|
whenever we substitute a metavariable with an actual expression.
|
||||||
For example, let ?M be a metavariable with context
|
For example, let ?M be a metavariable with context
|
||||||
<code>
|
<code>
|
||||||
[ Lower 1 1, Subst 0 a, Lift 1 2 ]
|
[ Inst 0 a, Lift 1 2 ]
|
||||||
</code>
|
</code>
|
||||||
Now, assume we want to instantiate \c ?M with <tt>f #0 (g #2)</tt>.
|
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.
|
Then, we apply the metavariable entries from right to left.
|
||||||
|
@ -276,36 +274,30 @@ enum class meta_entry_kind { Lift, Lower, Subst };
|
||||||
<code>
|
<code>
|
||||||
f #0 (g #4)
|
f #0 (g #4)
|
||||||
</code>
|
</code>
|
||||||
Then, we apply <tt>(Subst 0 a)</tt> and produce
|
Then, we apply <tt>(Inst 0 a)</tt> and produce
|
||||||
<code>
|
|
||||||
f a (g #4)
|
|
||||||
</code>
|
|
||||||
Finally, we apply <tt>(Lower 1 1)</tt> and get the final result
|
|
||||||
<code>
|
<code>
|
||||||
f a (g #3)
|
f a (g #3)
|
||||||
</code>
|
</code>
|
||||||
*/
|
*/
|
||||||
class meta_entry {
|
class meta_entry {
|
||||||
meta_entry_kind m_kind;
|
meta_entry_kind m_kind;
|
||||||
unsigned m_s;
|
unsigned m_s;
|
||||||
unsigned m_n;
|
unsigned m_n;
|
||||||
expr m_v;
|
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);
|
meta_entry(unsigned s, expr const & v);
|
||||||
public:
|
public:
|
||||||
~meta_entry();
|
~meta_entry();
|
||||||
friend meta_entry mk_lift(unsigned s, unsigned n);
|
friend meta_entry mk_lift(unsigned s, unsigned n);
|
||||||
friend meta_entry mk_lower(unsigned s, unsigned n);
|
friend meta_entry mk_inst(unsigned s, expr const & v);
|
||||||
friend meta_entry mk_subst(unsigned s, expr const & v);
|
|
||||||
meta_entry_kind kind() const { return m_kind; }
|
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 s() const { return m_s; }
|
||||||
unsigned n() const { lean_assert(kind() != meta_entry_kind::Subst); return m_n; }
|
unsigned n() const { lean_assert(kind() == meta_entry_kind::Lift); return m_n; }
|
||||||
expr const & v() const { lean_assert(kind() == meta_entry_kind::Subst); return m_v; }
|
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_lift(unsigned s, unsigned n) { return meta_entry(s, n); }
|
||||||
inline meta_entry mk_lower(unsigned s, unsigned n) { return meta_entry(meta_entry_kind::Lower, s, n); }
|
inline meta_entry mk_inst(unsigned s, expr const & v) { return meta_entry(s, v); }
|
||||||
inline meta_entry mk_subst(unsigned s, expr const & v) { return meta_entry(s, v); }
|
|
||||||
|
|
||||||
/** \brief Metavariables */
|
/** \brief Metavariables */
|
||||||
class expr_metavar : public expr_cell {
|
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);
|
meta_entry new_me = f(me);
|
||||||
if (new_me.kind() != me.kind() || new_me.s() != me.s()) {
|
if (new_me.kind() != me.kind() || new_me.s() != me.s()) {
|
||||||
modified = true;
|
modified = true;
|
||||||
} else if (new_me.is_subst()) {
|
} else if (new_me.is_inst()) {
|
||||||
if (!is_eqp(new_me.v(), me.v()))
|
if (!is_eqp(new_me.v(), me.v()))
|
||||||
modified = true;
|
modified = true;
|
||||||
} else if (new_me.n() != me.n()) {
|
} else if (new_me.n() != me.n()) {
|
||||||
|
|
|
@ -68,7 +68,7 @@ class expr_eq_fn {
|
||||||
compare(metavar_ctx(a), metavar_ctx(b), [&](meta_entry const & e1, meta_entry const & e2) {
|
compare(metavar_ctx(a), metavar_ctx(b), [&](meta_entry const & e1, meta_entry const & e2) {
|
||||||
if (e1.kind() != e2.kind() || e1.s() != e2.s())
|
if (e1.kind() != e2.kind() || e1.s() != e2.s())
|
||||||
return false;
|
return false;
|
||||||
if (e1.is_subst())
|
if (e1.is_inst())
|
||||||
return apply(e1.v(), e2.v());
|
return apply(e1.v(), e2.v());
|
||||||
else
|
else
|
||||||
return e1.n() == e2.n();
|
return e1.n() == e2.n();
|
||||||
|
|
|
@ -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) {
|
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 {
|
auto f = [=](expr const & e, unsigned offset) -> expr {
|
||||||
if (is_var(e) && var_idx(e) >= s + offset) {
|
if (is_var(e) && var_idx(e) >= s + offset) {
|
||||||
lean_assert(var_idx(e) >= offset + d);
|
lean_assert(var_idx(e) >= offset + d);
|
||||||
return mk_var(var_idx(e) - d);
|
return mk_var(var_idx(e) - d);
|
||||||
} else if (is_metavar(e)) {
|
} else if (is_metavar(e)) {
|
||||||
return add_lower(e, s + offset, d);
|
lean_unreachable();
|
||||||
|
return e;
|
||||||
} else {
|
} else {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ bool has_free_var(expr const & e, unsigned low, unsigned high);
|
||||||
\pre !has_free_var(e, 0, d)
|
\pre !has_free_var(e, 0, d)
|
||||||
*/
|
*/
|
||||||
expr lower_free_vars(expr const & e, unsigned s, unsigned 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.
|
\brief Lift free variables >= s in \c e by d.
|
||||||
|
|
|
@ -27,21 +27,21 @@ expr instantiate_with_closed(expr const & a, unsigned n, expr const * s) {
|
||||||
} else if (is_metavar(m)) {
|
} else if (is_metavar(m)) {
|
||||||
expr r = m;
|
expr r = m;
|
||||||
for (unsigned i = 0; i < n; i++)
|
for (unsigned i = 0; i < n; i++)
|
||||||
r = add_subst(r, offset + i, s[n - i - 1]);
|
r = add_inst(r, offset + n - i - 1, s[i]);
|
||||||
return add_lower(r, offset + n, n);
|
return r;
|
||||||
} else {
|
} else {
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return replace_fn<decltype(f)>(f)(a);
|
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 {
|
auto f = [=](expr const & m, unsigned offset) -> expr {
|
||||||
if (is_var(m)) {
|
if (is_var(m)) {
|
||||||
unsigned vidx = var_idx(m);
|
unsigned vidx = var_idx(m);
|
||||||
if (vidx >= offset) {
|
if (vidx >= offset + s) {
|
||||||
if (vidx < offset + n)
|
if (vidx < offset + s + n)
|
||||||
return lift_free_vars(s[n - (vidx - offset) - 1], offset);
|
return lift_free_vars(subst[n - (vidx - s - offset) - 1], offset);
|
||||||
else
|
else
|
||||||
return mk_var(vidx - n);
|
return mk_var(vidx - n);
|
||||||
} else {
|
} else {
|
||||||
|
@ -50,12 +50,18 @@ expr instantiate(expr const & a, unsigned n, expr const * s) {
|
||||||
} else if (is_metavar(m)) {
|
} else if (is_metavar(m)) {
|
||||||
expr r = m;
|
expr r = m;
|
||||||
for (unsigned i = 0; i < n; i++)
|
for (unsigned i = 0; i < n; i++)
|
||||||
r = add_subst(r, offset + i, lift_free_vars(s[n - i - 1], offset + n));
|
r = add_inst(r, offset + s + n - i - 1, lift_free_vars(subst[i], offset + n - i - 1));
|
||||||
return add_lower(r, offset + n, n);
|
return r;
|
||||||
} else {
|
} else {
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return replace_fn<decltype(f)>(f)(a);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
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, 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); }
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ Author: Leonardo de Moura
|
||||||
#include "kernel/metavar.h"
|
#include "kernel/metavar.h"
|
||||||
#include "kernel/replace.h"
|
#include "kernel/replace.h"
|
||||||
#include "kernel/free_vars.h"
|
#include "kernel/free_vars.h"
|
||||||
|
#include "kernel/instantiate.h"
|
||||||
#include "kernel/occurs.h"
|
#include "kernel/occurs.h"
|
||||||
#include "kernel/for_each.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);
|
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) {
|
expr instantiate(expr const & s, meta_ctx const & ctx, metavar_env const & env) {
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
expr r = instantiate(s, tail(ctx), env);
|
expr r = instantiate(s, tail(ctx), env);
|
||||||
meta_entry const & e = head(ctx);
|
meta_entry const & e = head(ctx);
|
||||||
switch (e.kind()) {
|
switch (e.kind()) {
|
||||||
case meta_entry_kind::Lift: return lift_free_vars(r, e.s(), e.n());
|
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::Inst: return ::lean::instantiate(r, e.s(), instantiate_metavars(e.v(), env));
|
||||||
case meta_entry_kind::Subst: return subst(r, e.s(), instantiate_metavars(e.v(), env));
|
|
||||||
}
|
}
|
||||||
lean_unreachable();
|
lean_unreachable();
|
||||||
return s;
|
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));
|
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) {
|
if (ctx) {
|
||||||
meta_entry e = head(ctx);
|
meta_entry e = head(ctx);
|
||||||
unsigned s1, n1;
|
if (e.kind() == meta_entry_kind::Lift) {
|
||||||
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.s() <= s && s < e.s() + e.n()) {
|
if (e.s() <= s && s < e.s() + e.n()) {
|
||||||
return ctx;
|
if (e.n() == 1)
|
||||||
} else if (s < e.s() && !has_free_var(v, e.s(), std::numeric_limits<unsigned>::max())) {
|
return tail(ctx);
|
||||||
return cons(e, add_subst(tail(ctx), s, v));
|
else
|
||||||
} else if (s >= e.s() + e.n() && !has_free_var(v, e.s(), std::numeric_limits<unsigned>::max())) {
|
return add_lift(tail(ctx), e.s(), e.n() - 1);
|
||||||
return cons(e, add_subst(tail(ctx), s - e.n(), v));
|
|
||||||
} else {
|
|
||||||
return cons(mk_subst(s, v), ctx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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) {
|
expr add_inst(expr const & m, unsigned s, expr const & v) {
|
||||||
return mk_metavar(metavar_idx(m), add_subst(metavar_ctx(m), s, v));
|
return mk_metavar(metavar_idx(m), add_inst(metavar_ctx(m), s, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_context(expr const & m) {
|
bool has_context(expr const & m) {
|
||||||
|
|
|
@ -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);
|
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 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);
|
meta_ctx add_inst(meta_ctx const & ctx, unsigned s, expr const & v);
|
||||||
|
|
||||||
/**
|
|
||||||
\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);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Return true iff the given metavariable has a non-empty
|
\brief Return true iff the given metavariable has a non-empty
|
||||||
|
|
|
@ -141,46 +141,6 @@ class normalizer::imp {
|
||||||
return expr();
|
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. */
|
/** \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) {
|
svalue normalize(expr const & a, value_stack const & s, unsigned k) {
|
||||||
flet<unsigned> l(m_depth, m_depth+1);
|
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)) {
|
if (m_menv && m_menv->contains(a) && m_menv->is_assigned(a)) {
|
||||||
r = normalize(m_menv->get_subst(a), s, k);
|
r = normalize(m_menv->get_subst(a), s, k);
|
||||||
} else {
|
} else {
|
||||||
r = svalue(updt_metavar(a, s, k));
|
// TODO(Leo): update metavariable
|
||||||
|
r = svalue(a);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case expr_kind::Var:
|
case expr_kind::Var:
|
||||||
|
|
|
@ -42,8 +42,8 @@ class deep_copy_fn {
|
||||||
}
|
}
|
||||||
case expr_kind::MetaVar:
|
case expr_kind::MetaVar:
|
||||||
r = update_metavar(a, [&](meta_entry const & e) -> meta_entry {
|
r = update_metavar(a, [&](meta_entry const & e) -> meta_entry {
|
||||||
if (e.is_subst())
|
if (e.is_inst())
|
||||||
return mk_subst(e.s(), apply(e.v()));
|
return mk_inst(e.s(), apply(e.v()));
|
||||||
else
|
else
|
||||||
return e;
|
return e;
|
||||||
});
|
});
|
||||||
|
|
|
@ -64,8 +64,8 @@ struct max_sharing_fn::imp {
|
||||||
}
|
}
|
||||||
case expr_kind::MetaVar: {
|
case expr_kind::MetaVar: {
|
||||||
expr r = update_metavar(a, [=](meta_entry const & e) -> meta_entry {
|
expr r = update_metavar(a, [=](meta_entry const & e) -> meta_entry {
|
||||||
if (e.is_subst())
|
if (e.is_inst())
|
||||||
return mk_subst(e.s(), apply(e.v()));
|
return mk_inst(e.s(), apply(e.v()));
|
||||||
else
|
else
|
||||||
return e;
|
return e;
|
||||||
});
|
});
|
||||||
|
|
|
@ -84,8 +84,7 @@ struct print_expr_fn {
|
||||||
if (first) first = false; else out() << ", ";
|
if (first) first = false; else out() << ", ";
|
||||||
switch (e.kind()) {
|
switch (e.kind()) {
|
||||||
case meta_entry_kind::Lift: out() << "lift:" << e.s() << ":" << e.n(); break;
|
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::Inst: out() << "inst:" << e.s() << " "; print_child(e.v(), c); break;
|
||||||
case meta_entry_kind::Subst: out() << "subst:" << e.s() << " "; print_child(e.v(), c); break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out() << "]";
|
out() << "]";
|
||||||
|
|
|
@ -72,14 +72,14 @@ static void tst2() {
|
||||||
expr m1 = menv.mk_metavar();
|
expr m1 = menv.mk_metavar();
|
||||||
expr m2 = menv.mk_metavar();
|
expr m2 = menv.mk_metavar();
|
||||||
// move m1 to a different context, and store new metavariable + context in m11
|
// 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";
|
std::cout << m11 << "\n";
|
||||||
menv.assign(m1, f(Var(0)));
|
menv.assign(m1, f(Var(0)));
|
||||||
std::cout << instantiate_metavars(m11, menv) << "\n";
|
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)));
|
menv.assign(m2, g(a, Var(1)));
|
||||||
std::cout << instantiate_metavars(h(m11), menv) << "\n";
|
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() {
|
static void tst3() {
|
||||||
|
@ -115,34 +115,7 @@ static void tst4() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tst5() {
|
static void tst5() {
|
||||||
metavar_env menv;
|
return;
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tst6() {
|
static void tst6() {
|
||||||
|
@ -256,6 +229,7 @@ static void tst12() {
|
||||||
std::cout << instantiate(f(m), {Var(1), Var(0)}) << "\n";
|
std::cout << instantiate(f(m), {Var(1), Var(0)}) << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void tst13() {
|
static void tst13() {
|
||||||
environment env;
|
environment env;
|
||||||
metavar_env menv;
|
metavar_env menv;
|
||||||
|
@ -384,6 +358,7 @@ static void tst17() {
|
||||||
lean_assert(instantiate_metavars(norm(F, ctx), menv2) ==
|
lean_assert(instantiate_metavars(norm(F, ctx), menv2) ==
|
||||||
norm(instantiate_metavars(F, menv2), ctx));
|
norm(instantiate_metavars(F, menv2), ctx));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
tst1();
|
tst1();
|
||||||
|
@ -398,11 +373,11 @@ int main() {
|
||||||
tst10();
|
tst10();
|
||||||
tst11();
|
tst11();
|
||||||
tst12();
|
tst12();
|
||||||
tst13();
|
// tst13();
|
||||||
tst14();
|
// tst14();
|
||||||
tst15();
|
// tst15();
|
||||||
tst16();
|
// tst16();
|
||||||
tst17();
|
// tst17();
|
||||||
return has_violations() ? 1 : 0;
|
return has_violations() ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ Function type:
|
||||||
Π (A : Type), A → A
|
Π (A : Type), A → A
|
||||||
Arguments types:
|
Arguments types:
|
||||||
A : Type
|
A : Type
|
||||||
x : ?M0
|
x : ?M0[lift:0:2]
|
||||||
Elaborator state
|
Elaborator state
|
||||||
#0 ≈ ?M0[lift:0:2]
|
#0 ≈ ?M0[lift:0:2]
|
||||||
Assumed: eq
|
Assumed: eq
|
||||||
|
@ -29,8 +29,8 @@ Function type:
|
||||||
Π (A : Type), A → A → Bool
|
Π (A : Type), A → A → Bool
|
||||||
Arguments types:
|
Arguments types:
|
||||||
C : Type
|
C : Type
|
||||||
a : ?M0[lower:5:5 lift:0:3 subst:0 B subst:1 A]
|
a : ?M0[lift:0:3]
|
||||||
b : ?M2[lower:5:5 lift:0:2 subst:0 a subst:1 B subst:2 A]
|
b : ?M2[lift:0:2]
|
||||||
Elaborator state
|
Elaborator state
|
||||||
#0 ≈ ?M2[lift:0:2]
|
#0 ≈ ?M2[lift:0:2]
|
||||||
#0 ≈ ?M0[lift:0:3]
|
#0 ≈ ?M0[lift:0:3]
|
||||||
|
|
|
@ -15,8 +15,8 @@ Candidates:
|
||||||
Int::add : ℤ → ℤ → ℤ
|
Int::add : ℤ → ℤ → ℤ
|
||||||
Nat::add : ℕ → ℕ → ℕ
|
Nat::add : ℕ → ℕ → ℕ
|
||||||
Arguments:
|
Arguments:
|
||||||
a : ?M0
|
a : ?M0[lift:0:2]
|
||||||
b : ?M2[lower:2:2 lift:0:1 subst:0 a]
|
b : ?M2[lift:0:1]
|
||||||
λ a b c : ℤ, a + c + b
|
λ a b c : ℤ, a + c + b
|
||||||
Error (line: 17, pos: 19) ambiguous overloads
|
Error (line: 17, pos: 19) ambiguous overloads
|
||||||
Candidates:
|
Candidates:
|
||||||
|
@ -24,7 +24,7 @@ Candidates:
|
||||||
Int::add : ℤ → ℤ → ℤ
|
Int::add : ℤ → ℤ → ℤ
|
||||||
Nat::add : ℕ → ℕ → ℕ
|
Nat::add : ℕ → ℕ → ℕ
|
||||||
Arguments:
|
Arguments:
|
||||||
a : ?M0
|
a : ?M0[lift:0:2]
|
||||||
b : ?M2[lower:2:2 lift:0:1 subst:0 a]
|
b : ?M2[lift:0:1]
|
||||||
Assumed: x
|
Assumed: x
|
||||||
λ a b : ℤ, a + x + b
|
λ a b : ℤ, a + x + b
|
||||||
|
|
|
@ -8,7 +8,7 @@ Function type:
|
||||||
Π (A : Type), A → Bool
|
Π (A : Type), A → Bool
|
||||||
Arguments types:
|
Arguments types:
|
||||||
B : Type
|
B : Type
|
||||||
a : ?M0[lower:3:3 lift:0:2 subst:0 A]
|
a : ?M0[lift:0:2]
|
||||||
Elaborator state
|
Elaborator state
|
||||||
#0 ≈ ?M0[lift:0:2]
|
#0 ≈ ?M0[lift:0:2]
|
||||||
Assumed: myeq
|
Assumed: myeq
|
||||||
|
|
Loading…
Reference in a new issue