refactor(kernel): remove convertability constraints
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
d4400d6135
commit
9d96f24766
5 changed files with 35 additions and 72 deletions
|
@ -15,11 +15,11 @@ struct constraint_cell {
|
|||
justification m_jst;
|
||||
constraint_cell(constraint_kind k, unsigned h, justification const & j):m_rc(1), m_kind(k), m_hash(h), m_jst(j) {}
|
||||
};
|
||||
struct eqc_constraint_cell : public constraint_cell {
|
||||
struct eq_constraint_cell : public constraint_cell {
|
||||
expr m_lhs;
|
||||
expr m_rhs;
|
||||
eqc_constraint_cell(constraint_kind k, expr const & lhs, expr const & rhs, justification const & j):
|
||||
constraint_cell(k, hash(hash(lhs.hash(), rhs.hash()), static_cast<unsigned>(k)), j),
|
||||
eq_constraint_cell(expr const & lhs, expr const & rhs, justification const & j):
|
||||
constraint_cell(constraint_kind::Eq, hash(lhs.hash(), rhs.hash()), j),
|
||||
m_lhs(lhs), m_rhs(rhs) {}
|
||||
};
|
||||
struct level_constraint_cell : public constraint_cell {
|
||||
|
@ -42,8 +42,8 @@ struct choice_constraint_cell : public constraint_cell {
|
|||
|
||||
void constraint_cell::dealloc() {
|
||||
switch (m_kind) {
|
||||
case constraint_kind::Eq: case constraint_kind::Convertible:
|
||||
delete static_cast<eqc_constraint_cell*>(this); break;
|
||||
case constraint_kind::Eq:
|
||||
delete static_cast<eq_constraint_cell*>(this); break;
|
||||
case constraint_kind::Level:
|
||||
delete static_cast<level_constraint_cell*>(this); break;
|
||||
case constraint_kind::Choice:
|
||||
|
@ -62,10 +62,7 @@ unsigned constraint::hash() const { lean_assert(m_ptr); return m_ptr->m_hash; }
|
|||
justification const & constraint::get_justification() const { lean_assert(m_ptr); return m_ptr->m_jst; }
|
||||
|
||||
constraint mk_eq_cnstr(expr const & lhs, expr const & rhs, justification const & j) {
|
||||
return constraint(new eqc_constraint_cell(constraint_kind::Eq, lhs, rhs, j));
|
||||
}
|
||||
constraint mk_conv_cnstr(expr const & lhs, expr const & rhs, justification const & j) {
|
||||
return constraint(new eqc_constraint_cell(constraint_kind::Convertible, lhs, rhs, j));
|
||||
return constraint(new eq_constraint_cell(lhs, rhs, j));
|
||||
}
|
||||
constraint mk_level_cnstr(level const & lhs, level const & rhs, justification const & j) {
|
||||
return constraint(new level_constraint_cell(lhs, rhs, j));
|
||||
|
@ -78,7 +75,7 @@ bool operator==(constraint const & c1, constraint const & c2) {
|
|||
if (c1.kind() != c2.kind() || c1.hash() != c2.hash())
|
||||
return false;
|
||||
switch (c1.kind()) {
|
||||
case constraint_kind::Eq: case constraint_kind::Convertible:
|
||||
case constraint_kind::Eq:
|
||||
return cnstr_lhs_expr(c1) == cnstr_lhs_expr(c2) && cnstr_rhs_expr(c1) == cnstr_rhs_expr(c2);
|
||||
case constraint_kind::Level:
|
||||
return cnstr_lhs_level(c1) == cnstr_lhs_level(c2) && cnstr_rhs_level(c1) == cnstr_rhs_level(c2);
|
||||
|
@ -90,14 +87,10 @@ bool operator==(constraint const & c1, constraint const & c2) {
|
|||
lean_unreachable(); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
expr const & cnstr_lhs_expr(constraint const & c) { lean_assert(is_eqc_cnstr(c)); return static_cast<eqc_constraint_cell*>(c.raw())->m_lhs; }
|
||||
expr const & cnstr_rhs_expr(constraint const & c) { lean_assert(is_eqc_cnstr(c)); return static_cast<eqc_constraint_cell*>(c.raw())->m_rhs; }
|
||||
level const & cnstr_lhs_level(constraint const & c) {
|
||||
lean_assert(is_level_cnstr(c)); return static_cast<level_constraint_cell*>(c.raw())->m_lhs;
|
||||
}
|
||||
level const & cnstr_rhs_level(constraint const & c) {
|
||||
lean_assert(is_level_cnstr(c)); return static_cast<level_constraint_cell*>(c.raw())->m_rhs;
|
||||
}
|
||||
expr const & cnstr_lhs_expr(constraint const & c) { lean_assert(is_eq_cnstr(c)); return static_cast<eq_constraint_cell*>(c.raw())->m_lhs; }
|
||||
expr const & cnstr_rhs_expr(constraint const & c) { lean_assert(is_eq_cnstr(c)); return static_cast<eq_constraint_cell*>(c.raw())->m_rhs; }
|
||||
level const & cnstr_lhs_level(constraint const & c) { lean_assert(is_level_cnstr(c)); return static_cast<level_constraint_cell*>(c.raw())->m_lhs; }
|
||||
level const & cnstr_rhs_level(constraint const & c) { lean_assert(is_level_cnstr(c)); return static_cast<level_constraint_cell*>(c.raw())->m_rhs; }
|
||||
expr const & cnstr_choice_expr(constraint const & c) {
|
||||
lean_assert(is_choice_cnstr(c)); return static_cast<choice_constraint_cell*>(c.raw())->m_expr;
|
||||
}
|
||||
|
@ -105,19 +98,15 @@ list<expr> const & cnstr_choice_set(constraint const & c) {
|
|||
lean_assert(is_choice_cnstr(c)); return static_cast<choice_constraint_cell*>(c.raw())->m_choices;
|
||||
}
|
||||
|
||||
constraint updt_eqc_cnstr(constraint const & c, expr const & new_lhs, expr const & new_rhs, justification const & new_jst) {
|
||||
lean_assert(is_eqc_cnstr(c));
|
||||
if (!is_eqp(cnstr_lhs_expr(c), new_lhs) || !is_eqp(cnstr_rhs_expr(c), new_rhs)) {
|
||||
if (is_eq_cnstr(c))
|
||||
return mk_eq_cnstr(new_lhs, new_rhs, new_jst);
|
||||
else
|
||||
return mk_conv_cnstr(new_lhs, new_rhs, new_jst);
|
||||
} else {
|
||||
constraint updt_eq_cnstr(constraint const & c, expr const & new_lhs, expr const & new_rhs, justification const & new_jst) {
|
||||
lean_assert(is_eq_cnstr(c));
|
||||
if (!is_eqp(cnstr_lhs_expr(c), new_lhs) || !is_eqp(cnstr_rhs_expr(c), new_rhs))
|
||||
return mk_eq_cnstr(new_lhs, new_rhs, new_jst);
|
||||
else
|
||||
return c;
|
||||
}
|
||||
}
|
||||
constraint updt_eqc_cnstr(constraint const & c, expr const & new_lhs, expr const & new_rhs) {
|
||||
return updt_eqc_cnstr(c, new_lhs, new_rhs, c.get_justification());
|
||||
constraint updt_eq_cnstr(constraint const & c, expr const & new_lhs, expr const & new_rhs) {
|
||||
return updt_eq_cnstr(c, new_lhs, new_rhs, c.get_justification());
|
||||
}
|
||||
constraint updt_level_cnstr(constraint const & c, level const & new_lhs, level const & new_rhs, justification const & new_jst) {
|
||||
lean_assert(is_level_cnstr(c));
|
||||
|
@ -135,11 +124,8 @@ std::ostream & operator<<(std::ostream & out, constraint const & c) {
|
|||
case constraint_kind::Eq:
|
||||
out << cnstr_lhs_expr(c) << " ≈ " << cnstr_rhs_expr(c);
|
||||
break;
|
||||
case constraint_kind::Convertible:
|
||||
out << cnstr_lhs_expr(c) << " ↠ " << cnstr_rhs_expr(c);
|
||||
break;
|
||||
case constraint_kind::Level:
|
||||
out << cnstr_lhs_level(c) << " ≤ " << cnstr_rhs_level(c);
|
||||
out << cnstr_lhs_level(c) << " = " << cnstr_rhs_level(c);
|
||||
break;
|
||||
case constraint_kind::Choice:
|
||||
out << cnstr_choice_expr(c) << " ∊ {";
|
||||
|
|
|
@ -10,17 +10,15 @@ Author: Leonardo de Moura
|
|||
#include "kernel/justification.h"
|
||||
namespace lean {
|
||||
/**
|
||||
\brief The lean kernel type checker produces three kinds of constraints:
|
||||
\brief The lean kernel type checker produces two kinds of constraints:
|
||||
|
||||
- Equality constraint: t ≈ s
|
||||
The terms t and s must be definitionally equal.
|
||||
- Convertability constraint: t ↠ s
|
||||
The term t must be convertible to s
|
||||
- Universe level constaint: l ≤ m
|
||||
- Universe level constaint: l = m
|
||||
The universe level l must be less than or equal to m.
|
||||
|
||||
\remark The first two kinds are only generated if the input term
|
||||
contains metavariables.
|
||||
\remark The constraints are only generated if the input term contains
|
||||
metavariables or level metavariables.
|
||||
|
||||
Each constraint is associated with a justification object.
|
||||
|
||||
|
@ -32,7 +30,7 @@ namespace lean {
|
|||
It means, t must be definitionally equal to one of the terms in the (finite)
|
||||
set {s_1, ..., s_k}.
|
||||
*/
|
||||
enum class constraint_kind { Eq, Convertible, Level, Choice };
|
||||
enum class constraint_kind { Eq, Level, Choice };
|
||||
struct constraint_cell;
|
||||
class constraint {
|
||||
constraint_cell * m_ptr;
|
||||
|
@ -53,7 +51,6 @@ public:
|
|||
friend void swap(constraint & l1, constraint & l2) { std::swap(l1, l2); }
|
||||
|
||||
friend constraint mk_eq_cnstr(expr const & lhs, expr const & rhs, justification const & j);
|
||||
friend constraint mk_conv_cnstr(expr const & lhs, expr const & rhs, justification const & j);
|
||||
friend constraint mk_level_cnstr(level const & lhs, level const & rhs, justification const & j);
|
||||
friend constraint mk_choice_cnstr(expr const & t, list<expr> const & s, justification const & j);
|
||||
|
||||
|
@ -64,19 +61,16 @@ bool operator==(constraint const & c1, constraint const & c2);
|
|||
inline bool operator!=(constraint const & c1, constraint const & c2) { return !(c1 == c2); }
|
||||
|
||||
constraint mk_eq_cnstr(expr const & lhs, expr const & rhs, justification const & j);
|
||||
constraint mk_conv_cnstr(expr const & lhs, expr const & rhs, justification const & j);
|
||||
constraint mk_level_cnstr(level const & lhs, level const & rhs, justification const & j);
|
||||
constraint mk_choice_cnstr(expr const & t, list<expr> const & s, justification const & j);
|
||||
|
||||
inline bool is_eq_cnstr(constraint const & c) { return c.kind() == constraint_kind::Eq; }
|
||||
inline bool is_conv_cnstr(constraint const & c) { return c.kind() == constraint_kind::Convertible; }
|
||||
inline bool is_level_cnstr(constraint const & c) { return c.kind() == constraint_kind::Level; }
|
||||
inline bool is_choice_cnstr(constraint const & c) { return c.kind() == constraint_kind::Choice; }
|
||||
inline bool is_eqc_cnstr(constraint const & c) { return is_eq_cnstr(c) || is_conv_cnstr(c); }
|
||||
|
||||
/** \brief Return the lhs of an equality/convertability constraint. */
|
||||
/** \brief Return the lhs of an equality constraint. */
|
||||
expr const & cnstr_lhs_expr(constraint const & c);
|
||||
/** \brief Return the rhs of an equality/convertability constraint. */
|
||||
/** \brief Return the rhs of an equality constraint. */
|
||||
expr const & cnstr_rhs_expr(constraint const & c);
|
||||
/** \brief Return the lhs of an level constraint. */
|
||||
level const & cnstr_lhs_level(constraint const & c);
|
||||
|
@ -87,10 +81,10 @@ expr const & cnstr_choice_expr(constraint const & c);
|
|||
/** \brief Return the choice set of a choice constraint. */
|
||||
list<expr> const & cnstr_choice_set(constraint const & c);
|
||||
|
||||
/** \brief Update equality/convertability constraint c with new_lhs, new_rhs and justification. */
|
||||
constraint updt_eqc_cnstr(constraint const & c, expr const & new_lhs, expr const & new_rhs, justification const & new_jst);
|
||||
/** \brief Update equality/convertability constraint c with new_lhs and new_rhs, but keeping the same justification. */
|
||||
constraint updt_eqc_cnstr(constraint const & c, expr const & new_lhs, expr const & new_rhs);
|
||||
/** \brief Update equality constraint c with new_lhs, new_rhs and justification. */
|
||||
constraint updt_eq_cnstr(constraint const & c, expr const & new_lhs, expr const & new_rhs, justification const & new_jst);
|
||||
/** \brief Update equality constraint c with new_lhs and new_rhs, but keeping the same justification. */
|
||||
constraint updt_eq_cnstr(constraint const & c, expr const & new_lhs, expr const & new_rhs);
|
||||
/** \brief Update level constraint c with new_lhs, new_rhs and justification. */
|
||||
constraint updt_level_cnstr(constraint const & c, level const & new_lhs, level const & new_rhs, justification const & new_jst);
|
||||
/** \brief Update level constraint c with new_lhs and new_rhs, but keeping the same justification. */
|
||||
|
|
|
@ -327,10 +327,7 @@ struct default_converter : public converter {
|
|||
return l_true; // t and s are structurally equal
|
||||
if (is_meta(t) || is_meta(s)) {
|
||||
// if t or s is a metavariable (or the application of a metavariable), then add constraint
|
||||
if (def_eq)
|
||||
c.add_cnstr(mk_eq_cnstr(t, s, jst.get()));
|
||||
else
|
||||
c.add_cnstr(mk_conv_cnstr(t, s, jst.get()));
|
||||
c.add_cnstr(mk_eq_cnstr(t, s, jst.get()));
|
||||
return l_true;
|
||||
}
|
||||
if (t.kind() == s.kind()) {
|
||||
|
|
|
@ -1180,8 +1180,6 @@ DECL_UDATA(constraint)
|
|||
|
||||
#define CNSTR_PRED(P) static int constraint_ ## P(lua_State * L) { return push_boolean(L, P(to_constraint(L, 1))); }
|
||||
CNSTR_PRED(is_eq_cnstr)
|
||||
CNSTR_PRED(is_conv_cnstr)
|
||||
CNSTR_PRED(is_eqc_cnstr)
|
||||
CNSTR_PRED(is_level_cnstr)
|
||||
CNSTR_PRED(is_choice_cnstr)
|
||||
static int constraint_eq(lua_State * L) { return push_boolean(L, to_constraint(L, 1) == to_constraint(L, 2)); }
|
||||
|
@ -1191,21 +1189,21 @@ static int constraint_hash(lua_State * L) { return push_integer(L, to_constraint
|
|||
static int constraint_jst(lua_State * L) { return push_justification(L, to_constraint(L, 1).get_justification()); }
|
||||
static int constraint_lhs(lua_State * L) {
|
||||
constraint const & c = to_constraint(L, 1);
|
||||
if (is_eqc_cnstr(c))
|
||||
if (is_eq_cnstr(c))
|
||||
return push_expr(L, cnstr_lhs_expr(c));
|
||||
else if (is_level_cnstr(c))
|
||||
return push_level(L, cnstr_lhs_level(c));
|
||||
else
|
||||
throw exception("arg #1 must be an equality/convertability/level constraint");
|
||||
throw exception("arg #1 must be an equality/level constraint");
|
||||
}
|
||||
static int constraint_rhs(lua_State * L) {
|
||||
constraint const & c = to_constraint(L, 1);
|
||||
if (is_eqc_cnstr(c))
|
||||
if (is_eq_cnstr(c))
|
||||
return push_expr(L, cnstr_rhs_expr(c));
|
||||
else if (is_level_cnstr(c))
|
||||
return push_level(L, cnstr_rhs_level(c));
|
||||
else
|
||||
throw exception("arg #1 must be an equality/convertability/level constraint");
|
||||
throw exception("arg #1 must be an equality/level constraint");
|
||||
}
|
||||
static int constraint_choice_expr(lua_State * L) { return push_expr(L, cnstr_choice_expr(to_constraint(L, 1))); }
|
||||
static int constraint_choice_set(lua_State * L) { return push_list_expr(L, cnstr_choice_set(to_constraint(L, 1))); }
|
||||
|
@ -1215,7 +1213,6 @@ static int constraint_tostring(lua_State * L) {
|
|||
return push_string(L, out.str().c_str());
|
||||
}
|
||||
static int mk_eq_cnstr(lua_State * L) { return push_constraint(L, mk_eq_cnstr(to_expr(L, 1), to_expr(L, 2), to_justification(L, 3))); }
|
||||
static int mk_conv_cnstr(lua_State * L) { return push_constraint(L, mk_conv_cnstr(to_expr(L, 1), to_expr(L, 2), to_justification(L, 3))); }
|
||||
static int mk_level_cnstr(lua_State * L) { return push_constraint(L, mk_level_cnstr(to_level(L, 1), to_level(L, 2), to_justification(L, 3))); }
|
||||
static int mk_choice_cnstr(lua_State * L) { return push_constraint(L, mk_choice_cnstr(to_expr(L, 1), to_list_expr_ext(L, 2), to_justification(L, 3))); }
|
||||
|
||||
|
@ -1224,8 +1221,6 @@ static const struct luaL_Reg constraint_m[] = {
|
|||
{"__tostring", safe_function<constraint_tostring>},
|
||||
{"__eq", safe_function<constraint_eq>},
|
||||
{"is_eq", safe_function<constraint_is_eq_cnstr>},
|
||||
{"is_conv", safe_function<constraint_is_conv_cnstr>},
|
||||
{"is_eqc", safe_function<constraint_is_eqc_cnstr>},
|
||||
{"is_level", safe_function<constraint_is_level_cnstr>},
|
||||
{"is_choice", safe_function<constraint_is_choice_cnstr>},
|
||||
{"is_eqp", safe_function<constraint_is_eqp>},
|
||||
|
@ -1247,13 +1242,11 @@ static void open_constraint(lua_State * L) {
|
|||
|
||||
SET_GLOBAL_FUN(constraint_pred, "is_constraint");
|
||||
SET_GLOBAL_FUN(mk_eq_cnstr, "mk_eq_cnstr");
|
||||
SET_GLOBAL_FUN(mk_conv_cnstr, "mk_conv_cnstr");
|
||||
SET_GLOBAL_FUN(mk_level_cnstr, "mk_level_cnstr");
|
||||
SET_GLOBAL_FUN(mk_choice_cnstr, "mk_choice_cnstr");
|
||||
|
||||
lua_newtable(L);
|
||||
SET_ENUM("Eq", constraint_kind::Eq);
|
||||
SET_ENUM("Convertible", constraint_kind::Convertible);
|
||||
SET_ENUM("Level", constraint_kind::Level);
|
||||
SET_ENUM("Choice", constraint_kind::Choice);
|
||||
lua_setglobal(L, "constraint_kind");
|
||||
|
|
|
@ -4,19 +4,12 @@ local m = mk_metavar("m", Bool)
|
|||
local j = justification("type match")
|
||||
local c = mk_eq_cnstr(f(a), m, j)
|
||||
assert(c:is_eq())
|
||||
assert(c:is_eqc())
|
||||
assert(not c:is_choice())
|
||||
assert(not c:is_level())
|
||||
assert(c:lhs() == f(a))
|
||||
assert(c:rhs() == m)
|
||||
assert(c:justification():is_eqp(j))
|
||||
print(c)
|
||||
local c2 = mk_conv_cnstr(f(m), f(a), j)
|
||||
print(c2)
|
||||
assert(not c2:is_eq())
|
||||
assert(c2:is_conv())
|
||||
assert(c2:is_eqc())
|
||||
assert(c2:lhs() == f(m))
|
||||
local c3 = mk_level_cnstr(mk_level_zero(), mk_level_one(), j)
|
||||
assert(c3:is_level())
|
||||
print(c3)
|
||||
|
|
Loading…
Reference in a new issue