feat(library/blast): basic sanity checking for blast data-structures

This commit is contained in:
Leonardo de Moura 2015-09-28 18:55:24 -07:00
parent 465a939146
commit 48e8b8b866
6 changed files with 78 additions and 9 deletions

View file

@ -195,6 +195,7 @@ class context {
expr new_target = to_blast_expr(g.get_type()); expr new_target = to_blast_expr(g.get_type());
s.set_target(new_target); s.set_target(new_target);
init_mvar2mref(mvar2meta_mref); init_mvar2mref(mvar2meta_mref);
lean_assert(s.check_invariant());
return s; return s;
} }

View file

@ -99,6 +99,14 @@ expr branch::add_hypothesis(expr const & type, optional<expr> const & value, opt
return add_hypothesis(name(*g_prefix, m_next), type, value, jst); return add_hypothesis(name(*g_prefix, m_next), type, value, jst);
} }
bool branch::hidx_depends_on(unsigned hidx_user, unsigned hidx_provider) const {
if (auto s = m_forward_deps.find(hidx_provider)) {
return s->contains(hidx_user);
} else {
return false;
}
}
void branch::set_target(expr const & t) { void branch::set_target(expr const & t) {
m_target = t; m_target = t;
m_target_deps.clear(); m_target_deps.clear();

View file

@ -40,21 +40,29 @@ class branch {
public: public:
branch():m_next(0) {} branch():m_next(0) {}
/** \brief Store in \c r the hypotheses in this branch sorted by depth */
void get_sorted_hypotheses(hypothesis_idx_buffer & r) const;
expr add_hypothesis(name const & n, expr const & type, optional<expr> const & value, optional<expr> const & jst); expr add_hypothesis(name const & n, expr const & type, optional<expr> const & value, optional<expr> const & jst);
expr add_hypothesis(expr const & type, optional<expr> const & value, optional<expr> const & jst); expr add_hypothesis(expr const & type, optional<expr> const & value, optional<expr> const & jst);
void set_target(expr const & t); /** \brief Return true iff the hypothesis with index \c hidx_user depends on the hypothesis with index
\c hidx_provider. */
bool hidx_depends_on(unsigned hidx_user, unsigned hidx_provider) const;
hypothesis const * get(unsigned idx) const { return m_context.find(idx); } hypothesis const * get(unsigned hidx) const { return m_context.find(hidx); }
hypothesis const * get(expr const & e) const { hypothesis const * get(expr const & h) const {
lean_assert(is_lref(e)); lean_assert(is_lref(h));
return get(lref_index(e)); return get(lref_index(h));
} }
void for_each_hypothesis(std::function<void(unsigned, hypothesis const &)> const & fn) const { m_context.for_each(fn); }
/** \brief Store in \c r the hypotheses in this branch sorted by depth */
void get_sorted_hypotheses(hypothesis_idx_buffer & r) const;
void set_target(expr const & t);
expr const & get_target() const { return m_target; } expr const & get_target() const { return m_target; }
/** \brief Return true iff the target depends on the given hypothesis */
bool target_depends_on(expr const & h) const { return m_target_deps.contains(lref_index(h)); }
bool has_mvar(expr const & e) const { return m_mvar_idxs.contains(mref_index(e)); }
}; };
void initialize_branch(); void initialize_branch();

View file

@ -7,7 +7,7 @@ Author: Leonardo de Moura
#pragma once #pragma once
#include "util/rc.h" #include "util/rc.h"
#include "util/rb_map.h" #include "util/rb_map.h"
#include "kernel/expr.h" #include "library/blast/expr.h"
namespace lean { namespace lean {
namespace blast { namespace blast {
@ -41,5 +41,7 @@ public:
optional<expr> const & get_value() const { return m_value; } optional<expr> const & get_value() const { return m_value; }
optional<expr> const & get_justification() const { return m_justification; } optional<expr> const & get_justification() const { return m_justification; }
void mark_fixed() { m_fixed = true; } void mark_fixed() { m_fixed = true; }
/** \brief Return true iff this hypothesis depends on \c h. */
bool depends_on(expr const & h) const { return m_deps.contains(lref_index(h)); }
}; };
}} }}

View file

@ -93,4 +93,46 @@ goal state::to_goal(branch const & b) const {
goal state::to_goal() const { goal state::to_goal() const {
return to_goal(m_main); return to_goal(m_main);
} }
#ifdef LEAN_DEBUG
bool state::check_deps(expr const & e, branch const & b, unsigned hidx, hypothesis const & h) const {
for_each(e, [&](expr const & n, unsigned) {
if (is_lref(n)) {
lean_assert(h.depends_on(n));
lean_assert(b.hidx_depends_on(hidx, lref_index(n)));
} else if (is_mref(n)) {
// metavariable is in the set of used metavariables
lean_assert(b.has_mvar(n));
}
return true;
});
return true;
}
bool state::check_deps(branch const & b, unsigned hidx, hypothesis const & h) const {
lean_assert(check_deps(h.get_type(), b, hidx, h));
lean_assert(!h.get_value() || check_deps(*h.get_value(), b, hidx, h));
return true;
}
bool state::check_invariant(branch const & b) const {
b.for_each_hypothesis([&](unsigned hidx, hypothesis const & h) {
lean_assert(check_deps(b, hidx, h));
});
for_each(b.get_target(), [&](expr const & n, unsigned) {
if (is_lref(n)) {
lean_assert(b.target_depends_on(n));
} else if (is_mref(n)) {
// metavariable is in the set of used metavariables
lean_assert(b.has_mvar(n));
}
return true;
});
return true;
}
bool state::check_invariant() const {
return check_invariant(m_main);
}
#endif
}} }}

View file

@ -37,6 +37,11 @@ class state {
unsigned add_metavar_decl(metavar_decl const & decl); unsigned add_metavar_decl(metavar_decl const & decl);
goal to_goal(branch const &) const; goal to_goal(branch const &) const;
#ifdef LEAN_DEBUG
bool check_deps(expr const & e, branch const & b, unsigned hidx, hypothesis const & h) const;
bool check_deps(branch const & b, unsigned hidx, hypothesis const & h) const;
bool check_invariant(branch const &) const;
#endif
public: public:
state(); state();
/** \brief Create a new metavariable using the given type and context. /** \brief Create a new metavariable using the given type and context.
@ -63,12 +68,15 @@ public:
} }
metavar_decl const * get_metavar_decl(unsigned idx) const { return m_metavar_decls.find(idx); } metavar_decl const * get_metavar_decl(unsigned idx) const { return m_metavar_decls.find(idx); }
metavar_decl const * get_metavar_decl(expr const & e) const { return get_metavar_decl(mref_index(e)); } metavar_decl const * get_metavar_decl(expr const & e) const { return get_metavar_decl(mref_index(e)); }
/** \brief Convert main branch to a goal. /** \brief Convert main branch to a goal.
This is mainly used for pretty printing. However, in the future, we may use this capability This is mainly used for pretty printing. However, in the future, we may use this capability
to invoke the tactic framework from the blast tactic. */ to invoke the tactic framework from the blast tactic. */
goal to_goal() const; goal to_goal() const;
#ifdef LEAN_DEBUG
bool check_invariant() const;
#endif
}; };
}} }}