refactor(library/tactic): remove 'null' tactic, and operator bool tactics
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
a4afdfeace
commit
8add5571f1
3 changed files with 26 additions and 27 deletions
|
@ -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()) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue