refactor(kernel/type_checker): pass buffer<unification_constraint> as a pointer

The idea is to make it an optional parameter independent of metavar_env.

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2013-12-07 10:27:08 -08:00
parent 5f3b9dbbbd
commit 195ea24d71
10 changed files with 40 additions and 43 deletions

View file

@ -408,7 +408,7 @@ public:
expr new_e = preprocessor(*this)(e); expr new_e = preprocessor(*this)(e);
// std::cout << "After preprocessing\n" << new_e << "\n"; // std::cout << "After preprocessing\n" << new_e << "\n";
if (has_metavar(new_e)) { if (has_metavar(new_e)) {
m_type_checker.infer_type(new_e, context(), &m_menv, m_ucs); m_type_checker.infer_type(new_e, context(), &m_menv, &m_ucs);
// for (auto c : m_ucs) { // for (auto c : m_ucs) {
// formatter fmt = mk_simple_formatter(); // formatter fmt = mk_simple_formatter();
// std::cout << c.pp(fmt, options(), nullptr, false) << "\n"; // std::cout << c.pp(fmt, options(), nullptr, false) << "\n";
@ -427,8 +427,8 @@ public:
expr new_e = preprocessor(*this)(e); expr new_e = preprocessor(*this)(e);
// std::cout << "After preprocessing\n" << new_t << "\n" << new_e << "\n"; // std::cout << "After preprocessing\n" << new_t << "\n" << new_e << "\n";
if (has_metavar(new_e) || has_metavar(new_t)) { if (has_metavar(new_e) || has_metavar(new_t)) {
m_type_checker.infer_type(new_t, context(), &m_menv, m_ucs); m_type_checker.infer_type(new_t, context(), &m_menv, &m_ucs);
expr new_e_t = m_type_checker.infer_type(new_e, context(), &m_menv, m_ucs); expr new_e_t = m_type_checker.infer_type(new_e, context(), &m_menv, &m_ucs);
m_ucs.push_back(mk_convertible_constraint(context(), new_e_t, new_t, m_ucs.push_back(mk_convertible_constraint(context(), new_e_t, new_t,
mk_def_type_match_justification(context(), n, e))); mk_def_type_match_justification(context(), n, e)));
// for (auto c : m_ucs) { // for (auto c : m_ucs) {

View file

@ -53,7 +53,7 @@ class type_checker::imp {
expr r = normalize(e, ctx); expr r = normalize(e, ctx);
if (is_pi(r)) if (is_pi(r))
return r; return r;
if (has_metavar(r) && m_menv) { if (has_metavar(r) && m_menv && m_uc) {
// Create two fresh variables A and B, // Create two fresh variables A and B,
// and assign r == (Pi(x : A), B x) // and assign r == (Pi(x : A), B x)
expr A = m_menv->mk_metavar(ctx); expr A = m_menv->mk_metavar(ctx);
@ -76,7 +76,7 @@ class type_checker::imp {
return u; return u;
if (is_bool(u)) if (is_bool(u))
return Type(); return Type();
if (has_metavar(u) && m_menv) { if (has_metavar(u) && m_menv && m_uc) {
justification jst = mk_type_expected_justification(ctx, s); justification jst = mk_type_expected_justification(ctx, s);
m_uc->push_back(mk_convertible_constraint(ctx, u, TypeU, jst)); m_uc->push_back(mk_convertible_constraint(ctx, u, TypeU, jst));
return u; return u;
@ -256,7 +256,7 @@ class type_checker::imp {
expr new_expected = normalize(expected, ctx); expr new_expected = normalize(expected, ctx);
if (is_convertible_core(new_given, new_expected)) if (is_convertible_core(new_given, new_expected))
return true; return true;
if (m_menv && (has_metavar(new_given) || has_metavar(new_expected))) { if (m_menv && m_uc && (has_metavar(new_given) || has_metavar(new_expected))) {
m_uc->push_back(mk_convertible_constraint(ctx, given, expected, mk_justification())); m_uc->push_back(mk_convertible_constraint(ctx, given, expected, mk_justification()));
return true; return true;
} }
@ -295,10 +295,10 @@ public:
m_uc = nullptr; m_uc = nullptr;
} }
expr infer_type(expr const & e, context const & ctx, metavar_env * menv, buffer<unification_constraint> & uc) { expr infer_type(expr const & e, context const & ctx, metavar_env * menv, buffer<unification_constraint> * uc) {
set_ctx(ctx); set_ctx(ctx);
set_menv(menv); set_menv(menv);
flet<unification_constraints*> set_uc(m_uc, &uc); flet<unification_constraints*> set_uc(m_uc, uc);
return infer_type_core(e, ctx); return infer_type_core(e, ctx);
} }
@ -333,12 +333,11 @@ public:
type_checker::type_checker(environment const & env):m_ptr(new imp(env)) {} type_checker::type_checker(environment const & env):m_ptr(new imp(env)) {}
type_checker::~type_checker() {} type_checker::~type_checker() {}
expr type_checker::infer_type(expr const & e, context const & ctx, metavar_env * menv, buffer<unification_constraint> & uc) { expr type_checker::infer_type(expr const & e, context const & ctx, metavar_env * menv, buffer<unification_constraint> * uc) {
return m_ptr->infer_type(e, ctx, menv, uc); return m_ptr->infer_type(e, ctx, menv, uc);
} }
expr type_checker::infer_type(expr const & e, context const & ctx) { expr type_checker::infer_type(expr const & e, context const & ctx) {
buffer<unification_constraint> uc; return infer_type(e, ctx, nullptr, nullptr);
return infer_type(e, ctx, nullptr, uc);
} }
bool type_checker::is_convertible(expr const & t1, expr const & t2, context const & ctx) { bool type_checker::is_convertible(expr const & t1, expr const & t2, context const & ctx) {
return m_ptr->is_convertible(t1, t2, ctx); return m_ptr->is_convertible(t1, t2, ctx);

View file

@ -34,7 +34,7 @@ public:
New metavariables and unification constraints may be created by the type checker. New metavariables and unification constraints may be created by the type checker.
The new unification constraints are stored in \c new_constraints. The new unification constraints are stored in \c new_constraints.
*/ */
expr infer_type(expr const & e, context const & ctx, metavar_env * menv, buffer<unification_constraint> & new_constraints); expr infer_type(expr const & e, context const & ctx, metavar_env * menv, buffer<unification_constraint> * new_constraints);
/** /**
\brief Return the type of \c e in the context \c ctx. \brief Return the type of \c e in the context \c ctx.

View file

@ -360,7 +360,7 @@ class elaborator::imp {
m_state.m_menv.assign(m, v, jst); m_state.m_menv.assign(m, v, jst);
if (menv.has_type(m)) { if (menv.has_type(m)) {
buffer<unification_constraint> ucs; buffer<unification_constraint> ucs;
expr tv = m_type_inferer(v, ctx, &menv, ucs); expr tv = m_type_inferer(v, ctx, &menv, &ucs);
for (auto c : ucs) for (auto c : ucs)
push_front(c); push_front(c);
justification new_jst(new typeof_mvar_justification(ctx, m, menv.get_type(m), tv, jst)); justification new_jst(new typeof_mvar_justification(ctx, m, menv.get_type(m), tv, jst));
@ -746,7 +746,7 @@ class elaborator::imp {
buffer<expr> arg_types; buffer<expr> arg_types;
buffer<unification_constraint> ucs; buffer<unification_constraint> ucs;
for (unsigned i = 1; i < num_a; i++) { for (unsigned i = 1; i < num_a; i++) {
arg_types.push_back(m_type_inferer(arg(a, i), ctx, &menv, ucs)); arg_types.push_back(m_type_inferer(arg(a, i), ctx, &menv, &ucs));
for (auto uc : ucs) for (auto uc : ucs)
push_front(uc); push_front(uc);
} }

View file

@ -69,7 +69,7 @@ static optional<proof_state> apply_tactic(environment const & env, proof_state c
l.emplace_front(mvar_sol, name()); l.emplace_front(mvar_sol, name());
th_type_c = instantiate(abst_body(th_type_c), mvar_sol); th_type_c = instantiate(abst_body(th_type_c), mvar_sol);
} else { } else {
if (inferer.is_proposition(abst_domain(th_type_c))) { if (inferer.is_proposition(abst_domain(th_type_c), context(), &new_menv)) {
name new_gname(gname, new_goal_idx); name new_gname(gname, new_goal_idx);
new_goal_idx++; new_goal_idx++;
l.emplace_front(expr(), new_gname); l.emplace_front(expr(), new_gname);

View file

@ -46,7 +46,7 @@ class type_inferer::imp {
return u; return u;
if (is_bool(u)) if (is_bool(u))
return Type(); return Type();
if (has_metavar(u) && m_menv) { if (has_metavar(u) && m_menv && m_uc) {
justification jst = mk_type_expected_justification(ctx, s); justification jst = mk_type_expected_justification(ctx, s);
m_uc->push_back(mk_convertible_constraint(ctx, u, TypeU, jst)); m_uc->push_back(mk_convertible_constraint(ctx, u, TypeU, jst));
return u; return u;
@ -64,7 +64,7 @@ class type_inferer::imp {
t = m_normalizer(t, ctx); t = m_normalizer(t, ctx);
if (is_pi(t)) { if (is_pi(t)) {
t = abst_body(t); t = abst_body(t);
} else if (has_metavar(t) && m_menv) { } else if (has_metavar(t) && m_menv && m_uc) {
// Create two fresh variables A and B, // Create two fresh variables A and B,
// and assign r == (Pi(x : A), B x) // and assign r == (Pi(x : A), B x)
expr A = m_menv->mk_metavar(ctx); expr A = m_menv->mk_metavar(ctx);
@ -224,10 +224,10 @@ public:
m_uc = nullptr; m_uc = nullptr;
} }
expr operator()(expr const & e, context const & ctx, metavar_env * menv, buffer<unification_constraint> & uc) { expr operator()(expr const & e, context const & ctx, metavar_env * menv, buffer<unification_constraint> * uc) {
set_ctx(ctx); set_ctx(ctx);
set_menv(menv); set_menv(menv);
flet<unification_constraints*> set(m_uc, &uc); flet<unification_constraints*> set(m_uc, uc);
return infer_type(e, ctx); return infer_type(e, ctx);
} }
@ -239,9 +239,8 @@ public:
m_menv_timestamp = 0; m_menv_timestamp = 0;
} }
bool is_proposition(expr const & e, context const & ctx) { bool is_proposition(expr const & e, context const & ctx, metavar_env * menv) {
buffer<unification_constraint> uc; expr t = operator()(e, ctx, menv, nullptr);
expr t = operator()(e, ctx, nullptr, uc);
if (is_bool(t)) if (is_bool(t))
return true; return true;
else else
@ -250,15 +249,14 @@ public:
}; };
type_inferer::type_inferer(environment const & env):m_ptr(new imp(env)) {} type_inferer::type_inferer(environment const & env):m_ptr(new imp(env)) {}
type_inferer::~type_inferer() {} type_inferer::~type_inferer() {}
expr type_inferer::operator()(expr const & e, context const & ctx, metavar_env * menv, buffer<unification_constraint> & uc) { expr type_inferer::operator()(expr const & e, context const & ctx, metavar_env * menv, buffer<unification_constraint> * uc) {
return m_ptr->operator()(e, ctx, menv, uc); return m_ptr->operator()(e, ctx, menv, uc);
} }
expr type_inferer::operator()(expr const & e, context const & ctx) { expr type_inferer::operator()(expr const & e, context const & ctx) {
buffer<unification_constraint> uc; return operator()(e, ctx, nullptr, nullptr);
return operator()(e, ctx, nullptr, uc);
} }
bool type_inferer::is_proposition(expr const & e, context const & ctx) { bool type_inferer::is_proposition(expr const & e, context const & ctx, metavar_env * menv) {
return m_ptr->is_proposition(e, ctx); return m_ptr->is_proposition(e, ctx, menv);
} }
void type_inferer::clear() { m_ptr->clear(); } void type_inferer::clear() { m_ptr->clear(); }

View file

@ -31,9 +31,9 @@ public:
type_inferer(environment const & env); type_inferer(environment const & env);
~type_inferer(); ~type_inferer();
expr operator()(expr const & e, context const & ctx, metavar_env * menv, buffer<unification_constraint> & uc); expr operator()(expr const & e, context const & ctx, metavar_env * menv, buffer<unification_constraint> * uc);
expr operator()(expr const & e, context const & ctx = context()); expr operator()(expr const & e, context const & ctx = context());
bool is_proposition(expr const & e, context const & ctx = context()); bool is_proposition(expr const & e, context const & ctx = context(), metavar_env * menv = nullptr);
void clear(); void clear();
}; };

View file

@ -474,7 +474,7 @@ static void tst23() {
buffer<unification_constraint> up; buffer<unification_constraint> up;
std::cout << F1 << "\n"; std::cout << F1 << "\n";
try { try {
std::cout << checker.infer_type(F1, context(), &menv, up) << "\n"; std::cout << checker.infer_type(F1, context(), &menv, &up) << "\n";
} catch (kernel_exception & ex) { } catch (kernel_exception & ex) {
formatter fmt = mk_simple_formatter(); formatter fmt = mk_simple_formatter();
io_state st(options(), fmt); io_state st(options(), fmt);
@ -508,7 +508,7 @@ static void tst25() {
env.add_var("b", N); env.add_var("b", N);
expr m = menv.mk_metavar(); expr m = menv.mk_metavar();
expr F = m(a, b); expr F = m(a, b);
std::cout << checker.infer_type(F, context(), &menv, up) << "\n"; std::cout << checker.infer_type(F, context(), &menv, &up) << "\n";
std::cout << menv << "\n"; std::cout << menv << "\n";
std::cout << up << "\n"; std::cout << up << "\n";
} }
@ -554,7 +554,7 @@ static void tst26() {
expr A4 = menv.mk_metavar(); expr A4 = menv.mk_metavar();
expr F = cons(A1, m1(a), cons(A2, m2(n), cons(A3, m3(b), nil(A4)))); expr F = cons(A1, m1(a), cons(A2, m2(n), cons(A3, m3(b), nil(A4))));
std::cout << F << "\n"; std::cout << F << "\n";
std::cout << checker.infer_type(F, context(), &menv, up) << "\n"; std::cout << checker.infer_type(F, context(), &menv, &up) << "\n";
std::cout << menv << "\n"; std::cout << menv << "\n";
std::cout << up << "\n"; std::cout << up << "\n";
} }
@ -588,7 +588,7 @@ static void tst27() {
expr m2 = menv.mk_metavar(); expr m2 = menv.mk_metavar();
expr F = Fun({{x, T1}, {y, T2}}, f(A1, x, y))(m1(a), m2(b)); expr F = Fun({{x, T1}, {y, T2}}, f(A1, x, y))(m1(a), m2(b));
std::cout << F << "\n"; std::cout << F << "\n";
std::cout << checker.infer_type(F, context(), &menv, up) << "\n"; std::cout << checker.infer_type(F, context(), &menv, &up) << "\n";
std::cout << menv << "\n"; std::cout << menv << "\n";
std::cout << up << "\n"; std::cout << up << "\n";
} }

View file

@ -48,7 +48,7 @@ static void tst1() {
expr A4 = menv.mk_metavar(); expr A4 = menv.mk_metavar();
expr F = cons(A1, m1(a), cons(A2, m2(n), cons(A3, m3(b), nil(A4)))); expr F = cons(A1, m1(a), cons(A2, m2(n), cons(A3, m3(b), nil(A4))));
std::cout << F << "\n"; std::cout << F << "\n";
std::cout << checker.infer_type(F, context(), &menv, ucs) << "\n"; std::cout << checker.infer_type(F, context(), &menv, &ucs) << "\n";
expr int_id = Fun({a, Int}, a); expr int_id = Fun({a, Int}, a);
expr nat_id = Fun({a, Nat}, a); expr nat_id = Fun({a, Nat}, a);
ucs.push_back(mk_choice_constraint(context(), m1, { int_id, mk_int_to_real_fn() }, justification())); ucs.push_back(mk_choice_constraint(context(), m1, { int_id, mk_int_to_real_fn() }, justification()));
@ -92,7 +92,7 @@ static void tst2() {
expr nat_id = Fun({a, Nat}, a); expr nat_id = Fun({a, Nat}, a);
expr F = m1(g(m2, m3(a)), m4(nVal(0))); expr F = m1(g(m2, m3(a)), m4(nVal(0)));
std::cout << F << "\n"; std::cout << F << "\n";
std::cout << checker.infer_type(F, context(), &menv, ucs) << "\n"; std::cout << checker.infer_type(F, context(), &menv, &ucs) << "\n";
ucs.push_back(mk_choice_constraint(context(), m1, { mk_nat_le_fn(), mk_int_le_fn(), mk_real_le_fn() }, justification())); ucs.push_back(mk_choice_constraint(context(), m1, { mk_nat_le_fn(), mk_int_le_fn(), mk_real_le_fn() }, justification()));
ucs.push_back(mk_choice_constraint(context(), m3, { int_id, mk_int_to_real_fn() }, justification())); ucs.push_back(mk_choice_constraint(context(), m3, { int_id, mk_int_to_real_fn() }, justification()));
ucs.push_back(mk_choice_constraint(context(), m4, { nat_id, mk_nat_to_int_fn(), mk_nat_to_real_fn() }, justification())); ucs.push_back(mk_choice_constraint(context(), m4, { nat_id, mk_nat_to_int_fn(), mk_nat_to_real_fn() }, justification()));
@ -135,7 +135,7 @@ static void tst3() {
expr x = Const("x"); expr x = Const("x");
expr F = Fun({x, m1}, m2(f(m3, x), m4(nVal(10))))(m5(a)); expr F = Fun({x, m1}, m2(f(m3, x), m4(nVal(10))))(m5(a));
std::cout << F << "\n"; std::cout << F << "\n";
std::cout << checker.infer_type(F, context(), &menv, ucs) << "\n"; std::cout << checker.infer_type(F, context(), &menv, &ucs) << "\n";
ucs.push_back(mk_choice_constraint(context(), m2, { mk_nat_le_fn(), mk_int_le_fn(), mk_real_le_fn() }, justification())); ucs.push_back(mk_choice_constraint(context(), m2, { mk_nat_le_fn(), mk_int_le_fn(), mk_real_le_fn() }, justification()));
ucs.push_back(mk_choice_constraint(context(), m4, { nat_id, mk_nat_to_int_fn(), mk_nat_to_real_fn() }, justification())); ucs.push_back(mk_choice_constraint(context(), m4, { nat_id, mk_nat_to_int_fn(), mk_nat_to_real_fn() }, justification()));
ucs.push_back(mk_choice_constraint(context(), m5, { int_id, mk_int_to_real_fn() }, justification())); ucs.push_back(mk_choice_constraint(context(), m5, { int_id, mk_int_to_real_fn() }, justification()));
@ -180,7 +180,7 @@ static void tst4() {
expr int_id = Fun({a, Int}, a); expr int_id = Fun({a, Int}, a);
expr F = Fun({{x, m1}, {y, m2}}, m3(f(m4, x), f(m5, y)))(m6(a), b); expr F = Fun({{x, m1}, {y, m2}}, m3(f(m4, x), f(m5, y)))(m6(a), b);
std::cout << F << "\n"; std::cout << F << "\n";
std::cout << checker.infer_type(F, context(), &menv, ucs) << "\n"; std::cout << checker.infer_type(F, context(), &menv, &ucs) << "\n";
ucs.push_back(mk_choice_constraint(context(), m3, { mk_nat_le_fn(), mk_int_le_fn(), mk_real_le_fn() }, justification())); ucs.push_back(mk_choice_constraint(context(), m3, { mk_nat_le_fn(), mk_int_le_fn(), mk_real_le_fn() }, justification()));
ucs.push_back(mk_choice_constraint(context(), m6, { int_id, mk_int_to_real_fn() }, justification())); ucs.push_back(mk_choice_constraint(context(), m6, { int_id, mk_int_to_real_fn() }, justification()));
elaborator elb(env, menv, ucs.size(), ucs.data()); elaborator elb(env, menv, ucs.size(), ucs.data());
@ -222,7 +222,7 @@ static void tst5() {
expr int_id = Fun({a, Int}, a); expr int_id = Fun({a, Int}, a);
expr F = Fun({{x, m1}, {y, m2}}, f(m3, x, y))(m4(a), b); expr F = Fun({{x, m1}, {y, m2}}, f(m3, x, y))(m4(a), b);
std::cout << F << "\n"; std::cout << F << "\n";
std::cout << checker.infer_type(F, context(), &menv, ucs) << "\n"; std::cout << checker.infer_type(F, context(), &menv, &ucs) << "\n";
ucs.push_back(mk_choice_constraint(context(), m4, { int_id, mk_int_to_real_fn() }, justification())); ucs.push_back(mk_choice_constraint(context(), m4, { int_id, mk_int_to_real_fn() }, justification()));
elaborator elb(env, menv, ucs.size(), ucs.data()); elaborator elb(env, menv, ucs.size(), ucs.data());
elb.next(); elb.next();
@ -259,7 +259,7 @@ static void tst6() {
env.add_axiom("H2", Eq(a, b)); env.add_axiom("H2", Eq(a, b));
expr V = Subst(m1, m2, m3, m4, H1, H2); expr V = Subst(m1, m2, m3, m4, H1, H2);
expr expected = Eq(f(a, f(b, b)), a); expr expected = Eq(f(a, f(b, b)), a);
expr given = checker.infer_type(V, context(), &menv, ucs); expr given = checker.infer_type(V, context(), &menv, &ucs);
ucs.push_back(mk_eq_constraint(context(), expected, given, justification())); ucs.push_back(mk_eq_constraint(context(), expected, given, justification()));
elaborator elb(env, menv, ucs.size(), ucs.data()); elaborator elb(env, menv, ucs.size(), ucs.data());
metavar_env s = elb.next(); metavar_env s = elb.next();
@ -273,7 +273,7 @@ static expr elaborate(expr const & e, environment const & env) {
buffer<unification_constraint> ucs; buffer<unification_constraint> ucs;
type_checker checker(env); type_checker checker(env);
expr e2 = replace_placeholders_with_metavars(e, menv); expr e2 = replace_placeholders_with_metavars(e, menv);
checker.infer_type(e2, context(), &menv, ucs); checker.infer_type(e2, context(), &menv, &ucs);
elaborator elb(env, menv, ucs.size(), ucs.data()); elaborator elb(env, menv, ucs.size(), ucs.data());
metavar_env s = elb.next(); metavar_env s = elb.next();
return instantiate_metavars(e2, s); return instantiate_metavars(e2, s);
@ -830,7 +830,7 @@ void tst26() {
expr m1 = menv.mk_metavar(); expr m1 = menv.mk_metavar();
expr F = Eq(g(m1, a), a); expr F = Eq(g(m1, a), a);
std::cout << F << "\n"; std::cout << F << "\n";
std::cout << checker.infer_type(F, context(), &menv, ucs) << "\n"; std::cout << checker.infer_type(F, context(), &menv, &ucs) << "\n";
elaborator elb(env, menv, ucs.size(), ucs.data()); elaborator elb(env, menv, ucs.size(), ucs.data());
metavar_env s = elb.next(); metavar_env s = elb.next();
std::cout << instantiate_metavars(F, s) << "\n"; std::cout << instantiate_metavars(F, s) << "\n";
@ -865,7 +865,7 @@ void tst27() {
expr m3 = menv.mk_metavar(); expr m3 = menv.mk_metavar();
expr F = Fun({f, m1}, eq(m2, g(m3, f)(a), a)); expr F = Fun({f, m1}, eq(m2, g(m3, f)(a), a));
std::cout << F << "\n"; std::cout << F << "\n";
std::cout << checker.infer_type(F, context(), &menv, ucs) << "\n"; std::cout << checker.infer_type(F, context(), &menv, &ucs) << "\n";
elaborator elb(env, menv, ucs.size(), ucs.data()); elaborator elb(env, menv, ucs.size(), ucs.data());
metavar_env s = elb.next(); metavar_env s = elb.next();
std::cout << instantiate_metavars(F, s) << "\n"; std::cout << instantiate_metavars(F, s) << "\n";

View file

@ -133,7 +133,7 @@ static void tst4() {
expr A4 = menv.mk_metavar(); expr A4 = menv.mk_metavar();
expr F = cons(A1, m1(a), cons(A2, m2(n), cons(A3, m3(b), nil(A4)))); expr F = cons(A1, m1(a), cons(A2, m2(n), cons(A3, m3(b), nil(A4))));
std::cout << F << "\n"; std::cout << F << "\n";
std::cout << inferer(F, context(), &menv, uc) << "\n"; std::cout << inferer(F, context(), &menv, &uc) << "\n";
std::cout << uc << "\n"; std::cout << uc << "\n";
} }