feat(frontends/lean): add notation for then tactic

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2014-06-29 11:24:56 -07:00
parent 15f270d9f3
commit a1bbb09de4
4 changed files with 40 additions and 8 deletions

View file

@ -8,20 +8,42 @@ Author: Leonardo de Moura
#include "frontends/lean/parser.h" #include "frontends/lean/parser.h"
namespace lean { namespace lean {
static name g_comma(",");
static name g_rbracket("]");
tactic parse_fail_tactic(parser &) { return fail_tactic(); } tactic parse_fail_tactic(parser &) { return fail_tactic(); }
tactic parse_id_tactic(parser &) { return id_tactic(); } tactic parse_id_tactic(parser &) { return id_tactic(); }
tactic parse_assumption_tactic(parser &) { return assumption_tactic(); } tactic parse_assumption_tactic(parser &) { return assumption_tactic(); }
tactic parse_echo_tactic(parser & p) {
if (!p.curr_is_string())
throw parser_error("invalid 'echo' tactic, string expected", p.pos());
tactic r = trace_tactic(p.get_str_val());
p.next();
return r;
}
tactic parse_tactic_seq(parser & p) {
tactic r = p.parse_tactic();
while (p.curr_is_token(g_comma)) {
p.next();
r = then(r, p.parse_tactic());
}
p.check_token_next(g_rbracket, "invalid tactic sequence, ']' expected");
return r;
}
void add_tactic(tactic_cmd_table & t, tactic_cmd_info && info) { t.insert(info.get_name(), info); } void add_tactic(tactic_cmd_table & t, tactic_cmd_info && info) { t.insert(info.get_name(), info); }
tactic_cmd_table get_builtin_tactic_cmds() { tactic_cmd_table get_builtin_tactic_cmds() {
tactic_cmd_table t; tactic_cmd_table t;
add_tactic(t, tactic_cmd_info("fail", "always fail tactic", parse_fail_tactic)); add_tactic(t, tactic_cmd_info("fail", "always fail tactic", parse_fail_tactic));
add_tactic(t, tactic_cmd_info("echo", "trace tactic: display message", parse_echo_tactic));
add_tactic(t, tactic_cmd_info("id", "do nothing tactic", parse_id_tactic)); add_tactic(t, tactic_cmd_info("id", "do nothing tactic", parse_id_tactic));
add_tactic(t, tactic_cmd_info("assumption", "solve goal if there is an assumption that is identical to the conclusion", add_tactic(t, tactic_cmd_info("assumption", "solve goal if there is an assumption that is identical to the conclusion",
parse_assumption_tactic)); parse_assumption_tactic));
add_tactic(t, tactic_cmd_info("exact", "solve goal if there is an assumption that is identical to the conclusion", add_tactic(t, tactic_cmd_info("exact", "solve goal if there is an assumption that is identical to the conclusion",
parse_assumption_tactic)); parse_assumption_tactic));
add_tactic(t, tactic_cmd_info("[", "tactic command sequence",
parse_tactic_seq));
return t; return t;
} }
} }

View file

@ -961,17 +961,23 @@ tactic parser::parse_tactic(unsigned /* rbp */) {
auto r = parse_tactic(); auto r = parse_tactic();
check_token_next(g_rparen, "invalid tactic, ')' expected"); check_token_next(g_rparen, "invalid tactic, ')' expected");
return r; return r;
} else if (curr_is_identifier()) { } else {
auto p = pos(); name id;
name id = get_name_val(); auto p = pos();
next(); if (curr_is_identifier()) {
id = get_name_val();
next();
} else if (curr_is_keyword()) {
id = get_token_info().value();
next();
} else {
throw parser_error("invalid tactic, '(' or tactic command expected", p);
}
if (auto it = tactic_cmds().find(id)) { if (auto it = tactic_cmds().find(id)) {
return it->get_fn()(*this); return it->get_fn()(*this);
} else { } else {
throw parser_error(sstream() << "unknown tactic '" << id << "'", p); throw parser_error(sstream() << "unknown tactic command '" << id << "'", p);
} }
} else {
throw parser_error("invalid tactic, '(' or tactic name expected", pos());
} }
} }

View file

@ -56,7 +56,7 @@ tactic now_tactic() {
}); });
} }
tactic cond(proof_state_pred const & p, tactic const & t1, tactic const & t2) { tactic cond(proof_state_pred p, tactic const & t1, tactic const & t2) {
return tactic([=](environment const & env, io_state const & ios, proof_state const & s) -> proof_state_seq { return tactic([=](environment const & env, io_state const & ios, proof_state const & s) -> proof_state_seq {
return mk_proof_state_seq([=]() { return mk_proof_state_seq([=]() {
if (p(env, ios, s)) { if (p(env, ios, s)) {

View file

@ -0,0 +1,4 @@
import logic
theorem tst {A B : Bool} (H1 : A) (H2 : B) : A
:= by [echo "executing simple tactic", assumption]