feat(frontends/lean): add back (backtracking) command

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2013-12-05 04:39:08 -08:00
parent 029ef57abd
commit 056759880c

View file

@ -95,6 +95,7 @@ static name g_coercion_kwd("Coercion");
static name g_exit_kwd("Exit"); static name g_exit_kwd("Exit");
static name g_apply("apply"); static name g_apply("apply");
static name g_done("done"); static name g_done("done");
static name g_back("back");
/** \brief Table/List with all builtin command keywords */ /** \brief Table/List with all builtin command keywords */
static list<name> g_command_keywords = {g_definition_kwd, g_variable_kwd, g_variables_kwd, g_theorem_kwd, g_axiom_kwd, g_universe_kwd, g_eval_kwd, static list<name> g_command_keywords = {g_definition_kwd, g_variable_kwd, g_variables_kwd, g_theorem_kwd, g_axiom_kwd, g_universe_kwd, g_eval_kwd,
g_show_kwd, g_check_kwd, g_infix_kwd, g_infixl_kwd, g_infixr_kwd, g_notation_kwd, g_echo_kwd, g_show_kwd, g_check_kwd, g_infix_kwd, g_infixl_kwd, g_infixr_kwd, g_notation_kwd, g_echo_kwd,
@ -1071,13 +1072,38 @@ class parser::imp {
m_frontend.mark_implicit_arguments(n, imp_args.size(), imp_args.data()); m_frontend.mark_implicit_arguments(n, imp_args.size(), imp_args.data());
} }
void display_proof_state(proof_state s) {
diagnostic(m_frontend) << "Proof state:\n" << s << endl;
}
void backtrack(std::vector<lazy_list<proof_state>> & stack, proof_state & s) {
if (!stack.empty())
diagnostic(m_frontend) << "Backtracking...\n";
while (!stack.empty()) {
check_interrupted();
lazy_list<proof_state> seq = stack.back();
stack.pop_back();
proof_state_seq::maybe_pair r;
code_with_callbacks([&]() {
r = seq.pull();
});
if (r) {
stack.push_back(r->second);
s = r->first;
return;
}
}
display_proof_state(s);
throw exception("failed to synthesize proof object using tactics");
}
expr parse_tactic(proof_state s) { expr parse_tactic(proof_state s) {
proof_state ini = s; proof_state ini = s;
std::vector<lazy_list<proof_state>> stack; std::vector<lazy_list<proof_state>> stack;
while (true) { while (true) {
auto p = pos(); auto p = pos();
if (!curr_is_identifier()) { if (!curr_is_identifier()) {
diagnostic(m_frontend) << "current state:\n" << s << endl; display_proof_state(s);
throw parser_error("invalid tactic, identifier expected", p); throw parser_error("invalid tactic, identifier expected", p);
} }
name id = curr_name(); name id = curr_name();
@ -1115,9 +1141,10 @@ class parser::imp {
s = r->first; s = r->first;
stack.push_back(r->second); stack.push_back(r->second);
} else { } else {
diagnostic(m_frontend) << "current state:\n" << s << endl; backtrack(stack, s);
throw parser_error(sstream() << "tactic failed", tac_pos);
} }
} else if (id == g_back) {
backtrack(stack, s);
} else if (id == g_done) { } else if (id == g_done) {
if (s.is_proof_final_state()) { if (s.is_proof_final_state()) {
assignment a(s.get_menv()); assignment a(s.get_menv());
@ -1125,8 +1152,8 @@ class parser::imp {
expr pr = s.get_proof_builder()(m, a); expr pr = s.get_proof_builder()(m, a);
return pr; return pr;
} else { } else {
diagnostic(m_frontend) << "final state:\n" << s << endl; display_proof_state(s);
throw exception("failed to synthesize proof object using given tactic"); throw exception("failed to synthesize proof object using tactics");
} }
} else { } else {
throw parser_error(sstream() << "invalid tactical proof, unknown command '" << id << "'", p); throw parser_error(sstream() << "invalid tactical proof, unknown command '" << id << "'", p);