refactor(library/tactic): remove 'null' tactic, and operator bool tactics

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2013-12-08 15:00:16 -08:00
parent a4afdfeace
commit 8add5571f1
3 changed files with 26 additions and 27 deletions

View file

@ -176,11 +176,11 @@ class parser::imp {
}; };
template<typename F> template<typename F>
void using_script(F && f) { typename std::result_of<F(lua_State * L)>::type using_script(F && f) {
m_script_state->apply([&](lua_State * L) { return m_script_state->apply([&](lua_State * L) {
set_io_state set1(L, m_frontend.get_state()); set_io_state set1(L, m_frontend.get_state());
set_environment set2(L, m_frontend.get_environment()); set_environment set2(L, m_frontend.get_environment());
f(L); return f(L);
}); });
} }
@ -1142,12 +1142,11 @@ class parser::imp {
*/ */
tactic parse_tactic_expr() { tactic parse_tactic_expr() {
auto p = pos(); auto p = pos();
tactic t;
if (curr() == scanner::token::ScriptBlock) { if (curr() == scanner::token::ScriptBlock) {
parse_script_expr(); parse_script_expr();
using_script([&](lua_State * L) { return using_script([&](lua_State * L) {
try { try {
t = to_tactic_ext(L, -1); return to_tactic_ext(L, -1);
} catch (...) { } catch (...) {
throw parser_error("invalid script-block, it must return a tactic", p); throw parser_error("invalid script-block, it must return a tactic", p);
} }
@ -1157,25 +1156,26 @@ class parser::imp {
expr pr = parse_expr(); expr pr = parse_expr();
check_rparen_next("invalid apply command, ')' expected"); check_rparen_next("invalid apply command, ')' expected");
expr pr_type = m_type_inferer(pr); expr pr_type = m_type_inferer(pr);
t = ::lean::apply_tactic(pr, pr_type); return ::lean::apply_tactic(pr, pr_type);
} else { } else {
name n = check_identifier_next("invalid apply command, identifier, '(' expr ')', or 'script-block' expected"); name n = check_identifier_next("invalid apply command, identifier, '(' expr ')', or 'script-block' expected");
optional<object> o = m_frontend.find_object(n); optional<object> o = m_frontend.find_object(n);
if (o && (o->is_theorem() || o->is_axiom())) { if (o && (o->is_theorem() || o->is_axiom())) {
t = ::lean::apply_tactic(n); return ::lean::apply_tactic(n);
} else { } else {
using_script([&](lua_State * L) { return using_script([&](lua_State * L) {
lua_getglobal(L, n.to_string().c_str()); lua_getglobal(L, n.to_string().c_str());
try { try {
t = to_tactic_ext(L, -1); tactic t = to_tactic_ext(L, -1);
lua_pop(L, 1);
return t;
} catch (...) { } catch (...) {
lua_pop(L, 1);
throw parser_error(sstream() << "unknown tactic '" << n << "'", p); throw parser_error(sstream() << "unknown tactic '" << n << "'", p);
} }
lua_pop(L, 1);
}); });
} }
} }
return t;
} }
/** \brief Parse <tt>'show' expr 'by' tactic</tt> */ /** \brief Parse <tt>'show' expr 'by' tactic</tt> */
@ -1186,7 +1186,7 @@ class parser::imp {
check_next(scanner::token::By, "invalid 'show _ by _' expression, 'by' expected"); check_next(scanner::token::By, "invalid 'show _ by _' expression, 'by' expected");
tactic tac = parse_tactic_expr(); tactic tac = parse_tactic_expr();
expr r = mk_placeholder(some_expr(t)); expr r = mk_placeholder(some_expr(t));
m_tactic_hints[r] = tac; m_tactic_hints.insert(mk_pair(r, tac));
return save(r, p); return save(r, p);
} }
@ -1196,7 +1196,7 @@ class parser::imp {
next(); next();
tactic tac = parse_tactic_expr(); tactic tac = parse_tactic_expr();
expr r = mk_placeholder(); expr r = mk_placeholder();
m_tactic_hints[r] = tac; m_tactic_hints.insert(mk_pair(r, tac));
return save(r, p); return save(r, p);
} }
@ -1513,13 +1513,13 @@ class parser::imp {
If the metavariable is not associated with any hint, then return the If the metavariable is not associated with any hint, then return the
null tactic. The method also returns the position of the hint. null tactic. The method also returns the position of the hint.
*/ */
std::pair<tactic, pos_info> get_tactic_tactic_for(expr const & mvar) { std::pair<optional<tactic>, pos_info> get_tactic_for(expr const & mvar) {
expr placeholder = m_elaborator.get_original(mvar); expr placeholder = m_elaborator.get_original(mvar);
auto it = m_tactic_hints.find(placeholder); auto it = m_tactic_hints.find(placeholder);
if (it != m_tactic_hints.end()) { if (it != m_tactic_hints.end()) {
return mk_pair(it->second, pos_of(placeholder, pos())); return mk_pair(some_tactic(it->second), pos_of(placeholder, pos()));
} else { } else {
return mk_pair(tactic(), pos_of(placeholder, pos())); return mk_pair(none_tactic(), pos_of(placeholder, pos()));
} }
} }
@ -1559,10 +1559,10 @@ class parser::imp {
if (!m_type_inferer.is_proposition(mvar_type, mvar_ctx)) if (!m_type_inferer.is_proposition(mvar_type, mvar_ctx))
throw exception("failed to synthesize metavar, its type is not a proposition"); throw exception("failed to synthesize metavar, its type is not a proposition");
proof_state s = to_proof_state(m_frontend, mvar_ctx, mvar_type); proof_state s = to_proof_state(m_frontend, mvar_ctx, mvar_type);
std::pair<tactic, pos_info> hint_and_pos = get_tactic_tactic_for(mvar); std::pair<optional<tactic>, pos_info> hint_and_pos = get_tactic_for(mvar);
if (hint_and_pos.first) { if (hint_and_pos.first) {
// metavariable has an associated tactic hint // metavariable has an associated tactic hint
s = apply_tactic(s, hint_and_pos.first, hint_and_pos.second).first; s = apply_tactic(s, *(hint_and_pos.first), hint_and_pos.second).first;
menv.assign(mvar, mk_proof_for(s, hint_and_pos.second, mvar_ctx, mvar_type)); menv.assign(mvar, mk_proof_for(s, hint_and_pos.second, mvar_ctx, mvar_type));
} else { } else {
if (curr_is_period()) { if (curr_is_period()) {

View file

@ -521,9 +521,8 @@ DECL_UDATA(tactic)
ORELSE(assumption_tactic(), conj_tactic()) ORELSE(assumption_tactic(), conj_tactic())
*/ */
tactic to_tactic_ext(lua_State * L, int i) { tactic to_tactic_ext(lua_State * L, int i) {
tactic t;
if (is_tactic(L, i)) { if (is_tactic(L, i)) {
t = to_tactic(L, i); return to_tactic(L, i);
} else if (lua_isfunction(L, i)) { } else if (lua_isfunction(L, i)) {
try { try {
lua_pushvalue(L, i); lua_pushvalue(L, i);
@ -532,17 +531,15 @@ tactic to_tactic_ext(lua_State * L, int i) {
throw_tactic_expected(i); throw_tactic_expected(i);
} }
if (is_tactic(L, -1)) { if (is_tactic(L, -1)) {
t = to_tactic(L, -1); tactic t = to_tactic(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
} else {
throw_tactic_expected(i);
}
} else {
throw_tactic_expected(i);
}
if (!t)
throw exception(sstream() << "arg #" << i << " must be a nonnull tactic");
return t; return t;
} else {
throw_tactic_expected(i);
}
} else {
throw_tactic_expected(i);
}
} }
static void check_ios(io_state * ios) { static void check_ios(io_state * ios) {

View file

@ -69,12 +69,10 @@ class tactic {
protected: protected:
tactic_cell * m_ptr; tactic_cell * m_ptr;
public: public:
tactic():m_ptr(nullptr) {}
explicit tactic(tactic_cell * ptr):m_ptr(ptr) { if (m_ptr) m_ptr->inc_ref(); } explicit tactic(tactic_cell * ptr):m_ptr(ptr) { if (m_ptr) m_ptr->inc_ref(); }
tactic(tactic const & s):m_ptr(s.m_ptr) { if (m_ptr) m_ptr->inc_ref(); } tactic(tactic const & s):m_ptr(s.m_ptr) { if (m_ptr) m_ptr->inc_ref(); }
tactic(tactic && s):m_ptr(s.m_ptr) { s.m_ptr = nullptr; } tactic(tactic && s):m_ptr(s.m_ptr) { s.m_ptr = nullptr; }
~tactic() { if (m_ptr) m_ptr->dec_ref(); } ~tactic() { if (m_ptr) m_ptr->dec_ref(); }
explicit operator bool() const { return m_ptr != nullptr; }
friend void swap(tactic & a, tactic & b) { std::swap(a.m_ptr, b.m_ptr); } friend void swap(tactic & a, tactic & b) { std::swap(a.m_ptr, b.m_ptr); }
tactic & operator=(tactic const & s); tactic & operator=(tactic const & s);
tactic & operator=(tactic && s); tactic & operator=(tactic && s);
@ -88,6 +86,10 @@ public:
solve_result solve(environment const & env, io_state const & io, context const & ctx, expr const & t); solve_result solve(environment const & env, io_state const & io, context const & ctx, expr const & t);
}; };
inline optional<tactic> none_tactic() { return optional<tactic>(); }
inline optional<tactic> some_tactic(tactic const & o) { return optional<tactic>(o); }
inline optional<tactic> some_tactic(tactic && o) { return optional<tactic>(std::forward<tactic>(o)); }
/** /**
\brief Create a tactic using the given functor. \brief Create a tactic using the given functor.
The functor must contain the operator: The functor must contain the operator: