Fix bug in ho_unifier
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
959503a69f
commit
d7cc5d2404
2 changed files with 23 additions and 12 deletions
|
@ -236,6 +236,19 @@ class ho_unifier::imp {
|
||||||
bool failed() const { return m_failed; }
|
bool failed() const { return m_failed; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Create the term (fun (x_0 : types[0]) ... (x_{n-1} : types[n-1]) body)
|
||||||
|
*/
|
||||||
|
expr mk_lambda(buffer<expr> const & types, expr const & body) {
|
||||||
|
expr r = body;
|
||||||
|
unsigned i = types.size();
|
||||||
|
while (i > 0) {
|
||||||
|
--i;
|
||||||
|
r = ::lean::mk_lambda(name(g_x_name, i), types[i], r);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Process a constraint <tt>ctx |- a = b</tt> where \c a is of the form <tt>(?m ...)</tt>.
|
\brief Process a constraint <tt>ctx |- a = b</tt> where \c a is of the form <tt>(?m ...)</tt>.
|
||||||
We perform a "case split" using "projection" or "imitation". See Huet&Lang's paper on higher order matching
|
We perform a "case split" using "projection" or "imitation". See Huet&Lang's paper on higher order matching
|
||||||
|
@ -264,12 +277,10 @@ class ho_unifier::imp {
|
||||||
m_state_stack.pop_back();
|
m_state_stack.pop_back();
|
||||||
// add projections
|
// add projections
|
||||||
for (unsigned i = 1; i < num_a; i++) {
|
for (unsigned i = 1; i < num_a; i++) {
|
||||||
expr proj = mk_var(i - 1);
|
|
||||||
for (unsigned j = 1; j < num_a; j++)
|
|
||||||
proj = mk_lambda(name(g_x_name, j), arg_types[j - 1], proj);
|
|
||||||
cqueue new_q = q;
|
cqueue new_q = q;
|
||||||
new_q.push_front(constraint(ctx, arg(a, i), b));
|
new_q.push_front(constraint(ctx, arg(a, i), b));
|
||||||
metavar_env new_s = s;
|
metavar_env new_s = s;
|
||||||
|
expr proj = mk_lambda(arg_types, mk_var(num_a - i - 1));
|
||||||
new_s.assign(midx, proj);
|
new_s.assign(midx, proj);
|
||||||
m_state_stack.push_back(mk_state(new_s, new_q));
|
m_state_stack.push_back(mk_state(new_s, new_q));
|
||||||
}
|
}
|
||||||
|
@ -294,17 +305,13 @@ class ho_unifier::imp {
|
||||||
imitation_args.push_back(mk_app(h_app_var_args.size(), h_app_var_args.data()));
|
imitation_args.push_back(mk_app(h_app_var_args.size(), h_app_var_args.data()));
|
||||||
new_q.push_front(constraint(ctx, mk_app(h_app_subst_args.size(), h_app_subst_args.data()), arg(b, i)));
|
new_q.push_front(constraint(ctx, mk_app(h_app_subst_args.size(), h_app_subst_args.data()), arg(b, i)));
|
||||||
}
|
}
|
||||||
expr imitation = mk_app(imitation_args.size(), imitation_args.data());
|
expr imitation = mk_lambda(arg_types, mk_app(imitation_args.size(), imitation_args.data()));
|
||||||
for (unsigned j = 1; j < num_a; j++)
|
|
||||||
imitation = mk_lambda(name(g_x_name, j), arg_types[j - 1], imitation);
|
|
||||||
new_s.assign(midx, imitation);
|
new_s.assign(midx, imitation);
|
||||||
m_state_stack.push_back(mk_state(new_s, new_q));
|
m_state_stack.push_back(mk_state(new_s, new_q));
|
||||||
} else {
|
} else {
|
||||||
// TODO(Leo) handle eq like we handle applications
|
// TODO(Leo) handle eq like we handle applications
|
||||||
// make f_a the constant function
|
// make f_a the constant function
|
||||||
expr imitation = lift_free_vars(b, 0, num_a - 1);
|
expr imitation = mk_lambda(arg_types, lift_free_vars(b, 0, num_a - 1));
|
||||||
for (unsigned j = 1; j < num_a; j++)
|
|
||||||
imitation = mk_lambda(name(g_x_name, j), arg_types[j - 1], imitation);
|
|
||||||
new_s.assign(midx, imitation);
|
new_s.assign(midx, imitation);
|
||||||
m_state_stack.push_back(mk_state(new_s, new_q));
|
m_state_stack.push_back(mk_state(new_s, new_q));
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,20 +16,24 @@ void tst1() {
|
||||||
metavar_env menv;
|
metavar_env menv;
|
||||||
ho_unifier unify(env);
|
ho_unifier unify(env);
|
||||||
expr N = Const("N");
|
expr N = Const("N");
|
||||||
|
expr M = Const("M");
|
||||||
env.add_var("N", Type());
|
env.add_var("N", Type());
|
||||||
env.add_var("f", N >> (N >> N));
|
env.add_var("M", Type());
|
||||||
|
env.add_var("f", N >> (M >> M));
|
||||||
env.add_var("a", N);
|
env.add_var("a", N);
|
||||||
env.add_var("b", N);
|
env.add_var("b", M);
|
||||||
expr f = Const("f");
|
expr f = Const("f");
|
||||||
expr x = Const("x");
|
expr x = Const("x");
|
||||||
expr a = Const("a");
|
expr a = Const("a");
|
||||||
expr b = Const("b");
|
expr b = Const("b");
|
||||||
expr m1 = menv.mk_metavar();
|
expr m1 = menv.mk_metavar();
|
||||||
expr m2 = menv.mk_metavar();
|
expr m2 = menv.mk_metavar();
|
||||||
expr l = m1(b);
|
expr l = m1(b, a);
|
||||||
expr r = f(b, f(a, b));
|
expr r = f(b, f(a, b));
|
||||||
for (auto sol : unify(context(), l, r, menv)) {
|
for (auto sol : unify(context(), l, r, menv)) {
|
||||||
std::cout << m1 << " -> " << beta_reduce(sol.first.get_subst(m1)) << "\n";
|
std::cout << m1 << " -> " << beta_reduce(sol.first.get_subst(m1)) << "\n";
|
||||||
|
std::cout << beta_reduce(instantiate_metavars(l, sol.first)) << "\n";
|
||||||
|
lean_assert(beta_reduce(instantiate_metavars(l, sol.first)) == r);
|
||||||
std::cout << "--------------\n";
|
std::cout << "--------------\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue