feat(library/unifier): divide constraints in clear groups
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
f242971b55
commit
ac1585fd1a
1 changed files with 40 additions and 28 deletions
|
@ -197,8 +197,36 @@ std::pair<unify_status, substitution> unify_simple(substitution const & s, const
|
|||
}
|
||||
|
||||
static constraint g_dont_care_cnstr = mk_eq_cnstr(expr(), expr(), justification());
|
||||
static unsigned g_first_delayed = 1u << 28;
|
||||
static unsigned g_first_very_delayed = 1u << 30;
|
||||
|
||||
/**
|
||||
The unifier divides the constraints in 6 groups: Simple, Basic, FlexRigid, Reduction, FlexFlex, DelayedChoice
|
||||
|
||||
1) Simple: constraints that never create case-splits. Example: pattern matching constraints (?M l_1 ... l_n) =?= t.
|
||||
The are not even inserted in the constraint priority queue.
|
||||
|
||||
2) Basic: contains user choice constraints used to model coercions and overloaded constraints, and constraints
|
||||
that cannot be solved, and the unification plugin must be invoked.
|
||||
|
||||
3) FlexRigid constraints (?M t_1 ... t_n) =?= t, where t_n is not an introduction application
|
||||
|
||||
4) Reduction: contraints such (elim ... (?m ...)) and (?m ... (intro ...)), where elim is an eliminator/recursor and
|
||||
intro is an introduction/constructor. This constraints are delayed because after ?m is assigned we may be able
|
||||
to reduce them.
|
||||
|
||||
5) FlexFlex: (?m1 ...) =?= (?m2 ...) we don't try to solve this constraint, we delay them and hope the other
|
||||
ones instantiate ?m1 or ?m2. If this kind of constraint is the next to be processed in the queue, then
|
||||
we simply discard it.
|
||||
|
||||
6) DelayedChoice: delayed choice constraints, they are used to model features such as class-instance
|
||||
They are really term synthesizers. We use the unifier just to exploit the non-chronological backtracking
|
||||
infrastructure
|
||||
*/
|
||||
enum class cnstr_group { Basic = 0, FlexRigid, Reduction, FlexFlex, DelayedChoice };
|
||||
static unsigned g_group_size = 1u << 28;
|
||||
static unsigned g_cnstr_group_first_index[5] = { 0, g_group_size, 2*g_group_size, 3*g_group_size, 4*g_group_size};
|
||||
static unsigned get_group_first_index(cnstr_group g) {
|
||||
return g_cnstr_group_first_index[static_cast<unsigned>(g)];
|
||||
}
|
||||
|
||||
/** \brief Auxiliary functional object for implementing simultaneous higher-order unification */
|
||||
struct unifier_fn {
|
||||
|
@ -448,29 +476,13 @@ struct unifier_fn {
|
|||
}
|
||||
|
||||
/** \brief Add constraint to the constraint queue */
|
||||
void add_cnstr(constraint const & c, name_set const * mlvl_occs, name_set const * mvar_occs, unsigned start_cidx = 0) {
|
||||
unsigned cidx = m_next_cidx + start_cidx;
|
||||
void add_cnstr(constraint const & c, name_set const * mlvl_occs, name_set const * mvar_occs, cnstr_group g) {
|
||||
unsigned cidx = m_next_cidx + get_group_first_index(g);
|
||||
m_cnstrs.insert(cnstr(c, cidx));
|
||||
add_occs(cidx, mlvl_occs, mvar_occs);
|
||||
m_next_cidx++;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Add (delayed) constraint to the constraint queue. Delayed constraints are processed after regular constraints
|
||||
added with \c add_cnstr
|
||||
*/
|
||||
void add_delayed_cnstr(constraint const & c, name_set const * mlvl_occs, name_set const * mvar_occs) {
|
||||
add_cnstr(c, mlvl_occs, mvar_occs, g_first_delayed);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Add (very delayed) constraint to the constraint queue. Very delayed constraints are processed after
|
||||
regular and delayed constraints added with \c add_cnstr and \c add_delayed_cnstr.
|
||||
*/
|
||||
void add_very_delayed_cnstr(constraint const & c, name_set const * mlvl_occs, name_set const * mvar_occs) {
|
||||
add_cnstr(c, mlvl_occs, mvar_occs, g_first_very_delayed);
|
||||
}
|
||||
|
||||
bool is_def_eq(expr const & t1, expr const & t2, justification const & j) {
|
||||
if (m_tc.is_def_eq(t1, t2, j)) {
|
||||
return true;
|
||||
|
@ -595,16 +607,16 @@ struct unifier_fn {
|
|||
|
||||
// We delay constraints where lhs or rhs are of the form (elim ... (?m ...))
|
||||
if (is_elim_meta_app(lhs) || is_elim_meta_app(rhs) || is_meta_intro_app(lhs) || is_meta_intro_app(rhs)) {
|
||||
add_very_delayed_cnstr(c, &unassigned_lvls, &unassigned_exprs);
|
||||
add_cnstr(c, &unassigned_lvls, &unassigned_exprs, cnstr_group::Reduction);
|
||||
} else if (is_meta(lhs) && is_meta(rhs)) {
|
||||
// flex-flex constraints are delayed the most.
|
||||
add_very_delayed_cnstr(c, &unassigned_lvls, &unassigned_exprs);
|
||||
add_cnstr(c, &unassigned_lvls, &unassigned_exprs, cnstr_group::FlexFlex);
|
||||
} else if (is_meta(lhs) || is_meta(rhs)) {
|
||||
// flex-rigid constraints are delayed.
|
||||
add_delayed_cnstr(c, &unassigned_lvls, &unassigned_exprs);
|
||||
add_cnstr(c, &unassigned_lvls, &unassigned_exprs, cnstr_group::FlexRigid);
|
||||
} else {
|
||||
// this constraints require the unifier plugin to be solved
|
||||
add_cnstr(c, &unassigned_lvls, &unassigned_exprs);
|
||||
add_cnstr(c, &unassigned_lvls, &unassigned_exprs, cnstr_group::Basic);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -668,9 +680,9 @@ struct unifier_fn {
|
|||
|
||||
if (lhs != cnstr_lhs_level(c) || rhs != cnstr_rhs_level(c)) {
|
||||
constraint new_c = mk_level_eq_cnstr(lhs, rhs, new_jst);
|
||||
add_delayed_cnstr(new_c, &unassigned_lvls, nullptr);
|
||||
add_cnstr(new_c, &unassigned_lvls, nullptr, cnstr_group::FlexRigid);
|
||||
} else {
|
||||
add_delayed_cnstr(c, &unassigned_lvls, nullptr);
|
||||
add_cnstr(c, &unassigned_lvls, nullptr, cnstr_group::FlexRigid);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -689,9 +701,9 @@ struct unifier_fn {
|
|||
case constraint_kind::Choice:
|
||||
// Choice constraints are never considered easy.
|
||||
if (cnstr_delayed(c))
|
||||
add_very_delayed_cnstr(c, nullptr, nullptr);
|
||||
add_cnstr(c, nullptr, nullptr, cnstr_group::DelayedChoice);
|
||||
else
|
||||
add_cnstr(c, nullptr, nullptr);
|
||||
add_cnstr(c, nullptr, nullptr, cnstr_group::Basic);
|
||||
return true;
|
||||
case constraint_kind::Eq:
|
||||
return process_eq_constraint(c);
|
||||
|
|
Loading…
Reference in a new issue