feat(library/class_instance_resolution): add support for nested type
class resolution
This commit is contained in:
parent
ac01e9e352
commit
a1d200e1c6
2 changed files with 48 additions and 27 deletions
|
@ -173,9 +173,9 @@ struct cienv {
|
||||||
metavariable whose type is a type class, and (?m t_1 ... t_n) must be synthesized
|
metavariable whose type is a type class, and (?m t_1 ... t_n) must be synthesized
|
||||||
by type class resolution, then we return ?m.
|
by type class resolution, then we return ?m.
|
||||||
Otherwise, we return none */
|
Otherwise, we return none */
|
||||||
optional<expr> find_unsynth_metavar(expr const & e) {
|
optional<pair<expr, expr>> find_unsynth_metavar(expr const & e) {
|
||||||
if (!has_meta_arg(e))
|
if (!has_meta_arg(e))
|
||||||
return none_expr();
|
return optional<pair<expr, expr>>();
|
||||||
buffer<expr> args;
|
buffer<expr> args;
|
||||||
expr const & fn = get_app_args(e, args);
|
expr const & fn = get_app_args(e, args);
|
||||||
expr type = m_cienv.infer_type(fn);
|
expr type = m_cienv.infer_type(fn);
|
||||||
|
@ -183,39 +183,46 @@ struct cienv {
|
||||||
while (i < args.size()) {
|
while (i < args.size()) {
|
||||||
type = m_cienv.whnf(type);
|
type = m_cienv.whnf(type);
|
||||||
if (!is_pi(type))
|
if (!is_pi(type))
|
||||||
return none_expr();
|
return optional<pair<expr, expr>>();
|
||||||
expr const & arg = args[i];
|
expr const & arg = args[i];
|
||||||
if (binding_info(type).is_inst_implicit() && is_meta(arg)) {
|
if (binding_info(type).is_inst_implicit() && is_meta(arg)) {
|
||||||
expr const & m = get_app_fn(arg);
|
expr const & m = get_app_fn(arg);
|
||||||
if (is_mvar(m)) {
|
if (is_mvar(m)) {
|
||||||
expr m_type = instantiate_uvars_mvars(infer_metavar(m));
|
expr m_type = instantiate_uvars_mvars(infer_metavar(m));
|
||||||
if (!has_expr_metavar_relaxed(m_type)) {
|
if (!has_expr_metavar_relaxed(m_type)) {
|
||||||
return some_expr(m);
|
return some(mk_pair(m, m_type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
type = instantiate(binding_body(type), arg);
|
type = instantiate(binding_body(type), arg);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return none_expr();
|
return optional<pair<expr, expr>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mk_instance(expr const & m) {
|
bool mk_instance(expr const & m, expr const & m_type) {
|
||||||
lean_assert(m);
|
lean_assert(m);
|
||||||
std::cout << "\n\nFOUND CANDIDATE: " << m << "\n\n";
|
if (auto r = m_cienv.mk_nested_instance(m_type)) {
|
||||||
// TODO(Leo)
|
m_cienv.update_assignment(m, *r);
|
||||||
return false;
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool on_is_def_eq_failure(expr const & e1, expr const & e2) {
|
virtual bool on_is_def_eq_failure(expr & e1, expr & e2) {
|
||||||
if (is_app(e1) && is_app(e2)) {
|
if (is_app(e1) && is_app(e2)) {
|
||||||
if (auto m1 = find_unsynth_metavar(e1)) {
|
if (auto p1 = find_unsynth_metavar(e1)) {
|
||||||
if (mk_instance(*m1))
|
if (mk_instance(p1->first, p1->second)) {
|
||||||
|
e1 = m_cienv.instantiate_uvars_mvars(e1);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (auto m2 = find_unsynth_metavar(e2)) {
|
if (auto p2 = find_unsynth_metavar(e2)) {
|
||||||
if (mk_instance(*m2))
|
if (mk_instance(p2->first, p2->second)) {
|
||||||
|
e2 = m_cienv.instantiate_uvars_mvars(e2);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -497,10 +504,10 @@ struct cienv {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_pos_info(pos_info_provider const * pip, expr const & type) {
|
void set_pos_info(pos_info_provider const * pip, expr const & pos_ref) {
|
||||||
m_pip = pip;
|
m_pip = pip;
|
||||||
if (m_pip)
|
if (m_pip)
|
||||||
m_pos = m_pip->get_pos_info(type);
|
m_pos = m_pip->get_pos_info(pos_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an internal universal metavariable
|
// Create an internal universal metavariable
|
||||||
|
@ -803,10 +810,9 @@ struct cienv {
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_search(expr const & type) {
|
void init_search(expr const & type) {
|
||||||
m_state = state();
|
m_state = state();
|
||||||
m_main_mvar = mk_mvar(type);
|
m_main_mvar = mk_mvar(type);
|
||||||
m_state.m_stack = cons(mk_pair(0u, m_main_mvar), m_state.m_stack);
|
m_state.m_stack = cons(mk_pair(0u, m_main_mvar), m_state.m_stack);
|
||||||
m_displayed_trace_header = false;
|
|
||||||
m_choices.clear();
|
m_choices.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -822,13 +828,7 @@ struct cienv {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<expr> operator()(environment const & env, options const & o, pos_info_provider const * pip, list<expr> const & ctx, expr const & type,
|
optional<expr> mk_instance_core(expr const & type) {
|
||||||
expr const & pos_ref) {
|
|
||||||
set_env(env);
|
|
||||||
set_options(o);
|
|
||||||
set_ctx(ctx);
|
|
||||||
set_pos_info(pip, pos_ref);
|
|
||||||
|
|
||||||
if (auto r = check_cache(type)) {
|
if (auto r = check_cache(type)) {
|
||||||
if (m_trace_instances) {
|
if (m_trace_instances) {
|
||||||
auto out = diagnostic();
|
auto out = diagnostic();
|
||||||
|
@ -842,12 +842,33 @@ struct cienv {
|
||||||
return ensure_no_meta(r);
|
return ensure_no_meta(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
optional<expr> operator()(environment const & env, options const & o, pos_info_provider const * pip, list<expr> const & ctx, expr const & type,
|
||||||
|
expr const & pos_ref) {
|
||||||
|
set_env(env);
|
||||||
|
set_options(o);
|
||||||
|
set_ctx(ctx);
|
||||||
|
set_pos_info(pip, pos_ref);
|
||||||
|
m_displayed_trace_header = false;
|
||||||
|
|
||||||
|
return mk_instance_core(type);
|
||||||
|
}
|
||||||
|
|
||||||
optional<expr> next() {
|
optional<expr> next() {
|
||||||
if (!m_multiple_instances)
|
if (!m_multiple_instances)
|
||||||
return none_expr();
|
return none_expr();
|
||||||
auto r = next_solution();
|
auto r = next_solution();
|
||||||
return ensure_no_meta(r);
|
return ensure_no_meta(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
optional<expr> mk_nested_instance(expr const & type) {
|
||||||
|
std::vector<choice> choices;
|
||||||
|
m_choices.swap(choices); // save choice stack
|
||||||
|
flet<state> save_state(m_state, state());
|
||||||
|
flet<expr> save_main_mvar(m_main_mvar, expr());
|
||||||
|
auto r = mk_instance_core(type);
|
||||||
|
m_choices.swap(choices); // restore choice stack
|
||||||
|
return r;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
MK_THREAD_LOCAL_GET_DEF(cienv, get_cienv);
|
MK_THREAD_LOCAL_GET_DEF(cienv, get_cienv);
|
||||||
|
|
|
@ -144,7 +144,7 @@ public:
|
||||||
/** \brief This method is invoked before failure.
|
/** \brief This method is invoked before failure.
|
||||||
The "customer" may try to assign unassigned mvars in the given expression.
|
The "customer" may try to assign unassigned mvars in the given expression.
|
||||||
The result is true to indicate that some metavariable has been assigned. */
|
The result is true to indicate that some metavariable has been assigned. */
|
||||||
virtual bool on_is_def_eq_failure(expr const &, expr const &) { return false; }
|
virtual bool on_is_def_eq_failure(expr &, expr &) { return false; }
|
||||||
|
|
||||||
bool is_assigned(level const & u) const { return get_assignment(u) != nullptr; }
|
bool is_assigned(level const & u) const { return get_assignment(u) != nullptr; }
|
||||||
bool is_assigned(expr const & m) const { return get_assignment(m) != nullptr; }
|
bool is_assigned(expr const & m) const { return get_assignment(m) != nullptr; }
|
||||||
|
|
Loading…
Reference in a new issue