refactor(kernel/constraint): rename: level constraints are also equality constraints
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
1c47bd4847
commit
644c387cfe
6 changed files with 35 additions and 47 deletions
|
@ -25,7 +25,7 @@ struct level_constraint_cell : public constraint_cell {
|
||||||
level m_lhs;
|
level m_lhs;
|
||||||
level m_rhs;
|
level m_rhs;
|
||||||
level_constraint_cell(level const & lhs, level const & rhs, justification const & j):
|
level_constraint_cell(level const & lhs, level const & rhs, justification const & j):
|
||||||
constraint_cell(constraint_kind::Level, j),
|
constraint_cell(constraint_kind::LevelEq, j),
|
||||||
m_lhs(lhs), m_rhs(rhs) {}
|
m_lhs(lhs), m_rhs(rhs) {}
|
||||||
};
|
};
|
||||||
struct choice_constraint_cell : public constraint_cell {
|
struct choice_constraint_cell : public constraint_cell {
|
||||||
|
@ -40,7 +40,7 @@ void constraint_cell::dealloc() {
|
||||||
switch (m_kind) {
|
switch (m_kind) {
|
||||||
case constraint_kind::Eq:
|
case constraint_kind::Eq:
|
||||||
delete static_cast<eq_constraint_cell*>(this); break;
|
delete static_cast<eq_constraint_cell*>(this); break;
|
||||||
case constraint_kind::Level:
|
case constraint_kind::LevelEq:
|
||||||
delete static_cast<level_constraint_cell*>(this); break;
|
delete static_cast<level_constraint_cell*>(this); break;
|
||||||
case constraint_kind::Choice:
|
case constraint_kind::Choice:
|
||||||
delete static_cast<choice_constraint_cell*>(this); break;
|
delete static_cast<choice_constraint_cell*>(this); break;
|
||||||
|
@ -59,7 +59,7 @@ justification const & constraint::get_justification() const { lean_assert(m_ptr)
|
||||||
constraint mk_eq_cnstr(expr const & lhs, expr const & rhs, justification const & j) {
|
constraint mk_eq_cnstr(expr const & lhs, expr const & rhs, justification const & j) {
|
||||||
return constraint(new eq_constraint_cell(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) {
|
constraint mk_level_eq_cnstr(level const & lhs, level const & rhs, justification const & j) {
|
||||||
return constraint(new level_constraint_cell(lhs, rhs, j));
|
return constraint(new level_constraint_cell(lhs, rhs, j));
|
||||||
}
|
}
|
||||||
constraint mk_choice_cnstr(expr const & m, choice_fn const & fn, justification const & j) {
|
constraint mk_choice_cnstr(expr const & m, choice_fn const & fn, justification const & j) {
|
||||||
|
@ -69,40 +69,25 @@ constraint mk_choice_cnstr(expr const & m, choice_fn const & fn, justification c
|
||||||
|
|
||||||
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_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; }
|
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_lhs_level(constraint const & c) {
|
||||||
level const & cnstr_rhs_level(constraint const & c) { lean_assert(is_level_cnstr(c)); return static_cast<level_constraint_cell*>(c.raw())->m_rhs; }
|
lean_assert(is_level_eq_cnstr(c));
|
||||||
|
return static_cast<level_constraint_cell*>(c.raw())->m_lhs;
|
||||||
|
}
|
||||||
|
level const & cnstr_rhs_level(constraint const & c) {
|
||||||
|
lean_assert(is_level_eq_cnstr(c));
|
||||||
|
return static_cast<level_constraint_cell*>(c.raw())->m_rhs;
|
||||||
|
}
|
||||||
expr const & cnstr_mvar(constraint const & c) { lean_assert(is_choice_cnstr(c)); return static_cast<choice_constraint_cell*>(c.raw())->m_mvar; }
|
expr const & cnstr_mvar(constraint const & c) { lean_assert(is_choice_cnstr(c)); return static_cast<choice_constraint_cell*>(c.raw())->m_mvar; }
|
||||||
choice_fn const & cnstr_choice_fn(constraint const & c) {
|
choice_fn const & cnstr_choice_fn(constraint const & c) {
|
||||||
lean_assert(is_choice_cnstr(c)); return static_cast<choice_constraint_cell*>(c.raw())->m_fn;
|
lean_assert(is_choice_cnstr(c)); return static_cast<choice_constraint_cell*>(c.raw())->m_fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_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));
|
|
||||||
if (!is_eqp(cnstr_lhs_level(c), new_lhs) || !is_eqp(cnstr_rhs_level(c), new_rhs))
|
|
||||||
return mk_level_cnstr(new_lhs, new_rhs, new_jst);
|
|
||||||
else
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
constraint updt_level_cnstr(constraint const & c, level const & new_lhs, level const & new_rhs) {
|
|
||||||
return updt_level_cnstr(c, new_lhs, new_rhs, c.get_justification());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream & operator<<(std::ostream & out, constraint const & c) {
|
std::ostream & operator<<(std::ostream & out, constraint const & c) {
|
||||||
switch (c.kind()) {
|
switch (c.kind()) {
|
||||||
case constraint_kind::Eq:
|
case constraint_kind::Eq:
|
||||||
out << cnstr_lhs_expr(c) << " ≈ " << cnstr_rhs_expr(c);
|
out << cnstr_lhs_expr(c) << " ≈ " << cnstr_rhs_expr(c);
|
||||||
break;
|
break;
|
||||||
case constraint_kind::Level:
|
case constraint_kind::LevelEq:
|
||||||
out << cnstr_lhs_level(c) << " = " << cnstr_rhs_level(c);
|
out << cnstr_lhs_level(c) << " = " << cnstr_rhs_level(c);
|
||||||
break;
|
break;
|
||||||
case constraint_kind::Choice:
|
case constraint_kind::Choice:
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace lean {
|
||||||
the possible solutions for a metavariable. The choice constraints are not used by
|
the possible solutions for a metavariable. The choice constraints are not used by
|
||||||
the kernel.
|
the kernel.
|
||||||
*/
|
*/
|
||||||
enum class constraint_kind { Eq, Level, Choice };
|
enum class constraint_kind { Eq, LevelEq, Choice };
|
||||||
class constraint;
|
class constraint;
|
||||||
typedef list<constraint> constraints;
|
typedef list<constraint> constraints;
|
||||||
typedef std::tuple<expr, justification, constraints> choice_fn_result;
|
typedef std::tuple<expr, justification, constraints> choice_fn_result;
|
||||||
|
@ -70,18 +70,18 @@ public:
|
||||||
friend void swap(constraint & l1, constraint & l2) { std::swap(l1, l2); }
|
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_eq_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_level_eq_cnstr(level const & lhs, level const & rhs, justification const & j);
|
||||||
friend constraint mk_choice_cnstr(expr const & m, choice_fn const & fn, justification const & j);
|
friend constraint mk_choice_cnstr(expr const & m, choice_fn const & fn, justification const & j);
|
||||||
|
|
||||||
constraint_cell * raw() const { return m_ptr; }
|
constraint_cell * raw() const { return m_ptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
constraint mk_eq_cnstr(expr const & lhs, expr const & rhs, justification const & j);
|
constraint mk_eq_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_level_eq_cnstr(level const & lhs, level const & rhs, justification const & j);
|
||||||
constraint mk_choice_cnstr(expr const & m, choice_fn const & fn, justification const & j);
|
constraint mk_choice_cnstr(expr const & m, choice_fn const & fn, justification const & j);
|
||||||
|
|
||||||
inline bool is_eq_cnstr(constraint const & c) { return c.kind() == constraint_kind::Eq; }
|
inline bool is_eq_cnstr(constraint const & c) { return c.kind() == constraint_kind::Eq; }
|
||||||
inline bool is_level_cnstr(constraint const & c) { return c.kind() == constraint_kind::Level; }
|
inline bool is_level_eq_cnstr(constraint const & c) { return c.kind() == constraint_kind::LevelEq; }
|
||||||
inline bool is_choice_cnstr(constraint const & c) { return c.kind() == constraint_kind::Choice; }
|
inline bool is_choice_cnstr(constraint const & c) { return c.kind() == constraint_kind::Choice; }
|
||||||
|
|
||||||
/** \brief Return the lhs of an equality constraint. */
|
/** \brief Return the lhs of an equality constraint. */
|
||||||
|
|
|
@ -309,7 +309,7 @@ struct default_converter : public converter {
|
||||||
if (is_equivalent(sort_level(t), sort_level(s))) {
|
if (is_equivalent(sort_level(t), sort_level(s))) {
|
||||||
return l_true;
|
return l_true;
|
||||||
} else if (has_meta(sort_level(t)) || has_meta(sort_level(s))) {
|
} else if (has_meta(sort_level(t)) || has_meta(sort_level(s))) {
|
||||||
c.add_cnstr(mk_level_cnstr(sort_level(t), sort_level(s), jst.get()));
|
c.add_cnstr(mk_level_eq_cnstr(sort_level(t), sort_level(s), jst.get()));
|
||||||
return l_true;
|
return l_true;
|
||||||
} else {
|
} else {
|
||||||
return l_false;
|
return l_false;
|
||||||
|
|
|
@ -1594,7 +1594,8 @@ DECL_UDATA(constraint)
|
||||||
|
|
||||||
#define CNSTR_PRED(P) static int constraint_ ## P(lua_State * L) { check_num_args(L, 1); return push_boolean(L, P(to_constraint(L, 1))); }
|
#define CNSTR_PRED(P) static int constraint_ ## P(lua_State * L) { check_num_args(L, 1); return push_boolean(L, P(to_constraint(L, 1))); }
|
||||||
CNSTR_PRED(is_eq_cnstr)
|
CNSTR_PRED(is_eq_cnstr)
|
||||||
CNSTR_PRED(is_level_cnstr)
|
CNSTR_PRED(is_level_eq_cnstr)
|
||||||
|
CNSTR_PRED(is_choice_cnstr)
|
||||||
static int constraint_is_eqp(lua_State * L) { return push_boolean(L, is_eqp(to_constraint(L, 1), to_constraint(L, 2))); }
|
static int constraint_is_eqp(lua_State * L) { return push_boolean(L, is_eqp(to_constraint(L, 1), to_constraint(L, 2))); }
|
||||||
static int constraint_get_kind(lua_State * L) { return push_integer(L, static_cast<int>(to_constraint(L, 1).kind())); }
|
static int constraint_get_kind(lua_State * L) { return push_integer(L, static_cast<int>(to_constraint(L, 1).kind())); }
|
||||||
static int constraint_jst(lua_State * L) { return push_justification(L, to_constraint(L, 1).get_justification()); }
|
static int constraint_jst(lua_State * L) { return push_justification(L, to_constraint(L, 1).get_justification()); }
|
||||||
|
@ -1602,7 +1603,7 @@ static int constraint_lhs(lua_State * L) {
|
||||||
constraint const & c = to_constraint(L, 1);
|
constraint const & c = to_constraint(L, 1);
|
||||||
if (is_eq_cnstr(c))
|
if (is_eq_cnstr(c))
|
||||||
return push_expr(L, cnstr_lhs_expr(c));
|
return push_expr(L, cnstr_lhs_expr(c));
|
||||||
else if (is_level_cnstr(c))
|
else if (is_level_eq_cnstr(c))
|
||||||
return push_level(L, cnstr_lhs_level(c));
|
return push_level(L, cnstr_lhs_level(c));
|
||||||
else
|
else
|
||||||
throw exception("arg #1 must be an equality/level constraint");
|
throw exception("arg #1 must be an equality/level constraint");
|
||||||
|
@ -1611,7 +1612,7 @@ static int constraint_rhs(lua_State * L) {
|
||||||
constraint const & c = to_constraint(L, 1);
|
constraint const & c = to_constraint(L, 1);
|
||||||
if (is_eq_cnstr(c))
|
if (is_eq_cnstr(c))
|
||||||
return push_expr(L, cnstr_rhs_expr(c));
|
return push_expr(L, cnstr_rhs_expr(c));
|
||||||
else if (is_level_cnstr(c))
|
else if (is_level_eq_cnstr(c))
|
||||||
return push_level(L, cnstr_rhs_level(c));
|
return push_level(L, cnstr_rhs_level(c));
|
||||||
else
|
else
|
||||||
throw exception("arg #1 must be an equality/level constraint");
|
throw exception("arg #1 must be an equality/level constraint");
|
||||||
|
@ -1622,13 +1623,14 @@ static int constraint_tostring(lua_State * L) {
|
||||||
return push_string(L, out.str().c_str());
|
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_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_level_cnstr(lua_State * L) { return push_constraint(L, mk_level_cnstr(to_level_ext(L, 1), to_level_ext(L, 2),
|
static int mk_level_eq_cnstr(lua_State * L) { return push_constraint(L, mk_level_eq_cnstr(to_level_ext(L, 1), to_level_ext(L, 2),
|
||||||
to_justification(L, 3))); }
|
to_justification(L, 3))); }
|
||||||
static const struct luaL_Reg constraint_m[] = {
|
static const struct luaL_Reg constraint_m[] = {
|
||||||
{"__gc", constraint_gc}, // never throws
|
{"__gc", constraint_gc}, // never throws
|
||||||
{"__tostring", safe_function<constraint_tostring>},
|
{"__tostring", safe_function<constraint_tostring>},
|
||||||
{"is_eq", safe_function<constraint_is_eq_cnstr>},
|
{"is_eq", safe_function<constraint_is_eq_cnstr>},
|
||||||
{"is_level", safe_function<constraint_is_level_cnstr>},
|
{"is_level_eq", safe_function<constraint_is_level_eq_cnstr>},
|
||||||
|
{"is_choice", safe_function<constraint_is_choice_cnstr>},
|
||||||
{"is_eqp", safe_function<constraint_is_eqp>},
|
{"is_eqp", safe_function<constraint_is_eqp>},
|
||||||
{"kind", safe_function<constraint_get_kind>},
|
{"kind", safe_function<constraint_get_kind>},
|
||||||
{"lhs", safe_function<constraint_lhs>},
|
{"lhs", safe_function<constraint_lhs>},
|
||||||
|
@ -1643,13 +1645,14 @@ static void open_constraint(lua_State * L) {
|
||||||
lua_setfield(L, -2, "__index");
|
lua_setfield(L, -2, "__index");
|
||||||
setfuncs(L, constraint_m, 0);
|
setfuncs(L, constraint_m, 0);
|
||||||
|
|
||||||
SET_GLOBAL_FUN(constraint_pred, "is_constraint");
|
SET_GLOBAL_FUN(constraint_pred, "is_constraint");
|
||||||
SET_GLOBAL_FUN(mk_eq_cnstr, "mk_eq_cnstr");
|
SET_GLOBAL_FUN(mk_eq_cnstr, "mk_eq_cnstr");
|
||||||
SET_GLOBAL_FUN(mk_level_cnstr, "mk_level_cnstr");
|
SET_GLOBAL_FUN(mk_level_eq_cnstr, "mk_level_eq_cnstr");
|
||||||
|
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
SET_ENUM("Eq", constraint_kind::Eq);
|
SET_ENUM("Eq", constraint_kind::Eq);
|
||||||
SET_ENUM("Level", constraint_kind::Level);
|
SET_ENUM("LevelEq", constraint_kind::LevelEq);
|
||||||
|
SET_ENUM("Choice", constraint_kind::Choice);
|
||||||
lua_setglobal(L, "constraint_kind");
|
lua_setglobal(L, "constraint_kind");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,7 @@ std::pair<unify_status, substitution> unify_simple(substitution const & s, level
|
||||||
std::pair<unify_status, substitution> unify_simple(substitution const & s, constraint const & c) {
|
std::pair<unify_status, substitution> unify_simple(substitution const & s, constraint const & c) {
|
||||||
if (is_eq_cnstr(c))
|
if (is_eq_cnstr(c))
|
||||||
return unify_simple(s, cnstr_lhs_expr(c), cnstr_rhs_expr(c), c.get_justification());
|
return unify_simple(s, cnstr_lhs_expr(c), cnstr_rhs_expr(c), c.get_justification());
|
||||||
else if (is_level_cnstr(c))
|
else if (is_level_eq_cnstr(c))
|
||||||
return unify_simple(s, cnstr_lhs_level(c), cnstr_rhs_level(c), c.get_justification());
|
return unify_simple(s, cnstr_lhs_level(c), cnstr_rhs_level(c), c.get_justification());
|
||||||
else
|
else
|
||||||
return mk_pair(unify_status::Unsupported, s);
|
return mk_pair(unify_status::Unsupported, s);
|
||||||
|
@ -393,7 +393,7 @@ struct unifier_fn {
|
||||||
return true;
|
return true;
|
||||||
case constraint_kind::Eq:
|
case constraint_kind::Eq:
|
||||||
return process_eq_constraint(c);
|
return process_eq_constraint(c);
|
||||||
case constraint_kind::Level:
|
case constraint_kind::LevelEq:
|
||||||
return process_lvl_constraint(c);
|
return process_lvl_constraint(c);
|
||||||
}
|
}
|
||||||
lean_unreachable(); // LCOV_EXCL_LINE
|
lean_unreachable(); // LCOV_EXCL_LINE
|
||||||
|
|
|
@ -4,13 +4,13 @@ local m = mk_metavar("m", Bool)
|
||||||
local j = justification("type match")
|
local j = justification("type match")
|
||||||
local c = mk_eq_cnstr(f(a), m, j)
|
local c = mk_eq_cnstr(f(a), m, j)
|
||||||
assert(c:is_eq())
|
assert(c:is_eq())
|
||||||
assert(not c:is_level())
|
assert(not c:is_level_eq())
|
||||||
assert(c:lhs() == f(a))
|
assert(c:lhs() == f(a))
|
||||||
assert(c:rhs() == m)
|
assert(c:rhs() == m)
|
||||||
assert(c:justification():is_eqp(j))
|
assert(c:justification():is_eqp(j))
|
||||||
print(c)
|
print(c)
|
||||||
local c3 = mk_level_cnstr(mk_level_zero(), mk_level_one(), j)
|
local c3 = mk_level_eq_cnstr(mk_level_zero(), mk_level_one(), j)
|
||||||
assert(c3:is_level())
|
assert(c3:is_level_eq())
|
||||||
print(c3)
|
print(c3)
|
||||||
assert(c:is_eqp(c))
|
assert(c:is_eqp(c))
|
||||||
assert(not c:is_eqp(mk_eq_cnstr(f(a), m, j)))
|
assert(not c:is_eqp(mk_eq_cnstr(f(a), m, j)))
|
||||||
|
|
Loading…
Reference in a new issue