feat(library/tactic): add 'fixpoint' tactic
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
7fb2b0f6d8
commit
e0501104e2
3 changed files with 20 additions and 2 deletions
|
@ -22,6 +22,7 @@ definition or_else (t1 t2 : tactic) : tactic := builtin_tactic
|
|||
definition append (t1 t2 : tactic) : tactic := builtin_tactic
|
||||
definition interleave (t1 t2 : tactic) : tactic := builtin_tactic
|
||||
definition par (t1 t2 : tactic) : tactic := builtin_tactic
|
||||
definition fixpoint (f : tactic → tactic) : tactic := builtin_tactic
|
||||
definition repeat (t : tactic) : tactic := builtin_tactic
|
||||
definition at_most (t : tactic) (k : num) : tactic := builtin_tactic
|
||||
definition discard (t : tactic) (k : num) : tactic := builtin_tactic
|
||||
|
|
|
@ -27,10 +27,10 @@ void register_expr_to_tactic(name const & n, expr_to_tactic_fn const & fn) {
|
|||
|
||||
static name g_tac("tactic"), g_tac_name(g_tac, "tactic"), g_builtin_tac_name(g_tac, "builtin_tactic");
|
||||
static name g_exact_tac_name(g_tac, "exact"), g_and_then_tac_name(g_tac, "and_then");
|
||||
static name g_or_else_tac_name(g_tac, "or_else"), g_repeat_tac_name(g_tac, "repeat");
|
||||
static name g_or_else_tac_name(g_tac, "or_else"), g_repeat_tac_name(g_tac, "repeat"), g_fixpoint_name(g_tac, "fixpoint");
|
||||
static expr g_exact_tac_fn(Const(g_exact_tac_name)), g_and_then_tac_fn(Const(g_and_then_tac_name));
|
||||
static expr g_or_else_tac_fn(Const(g_or_else_tac_name)), g_repeat_tac_fn(Const(g_repeat_tac_name));
|
||||
static expr g_tac_type(Const(g_tac_name)), g_builtin_tac(Const(g_builtin_tac_name));
|
||||
static expr g_tac_type(Const(g_tac_name)), g_builtin_tac(Const(g_builtin_tac_name)), g_fixpoint_tac(Const(g_fixpoint_name));
|
||||
expr const & get_exact_tac_fn() { return g_exact_tac_fn; }
|
||||
expr const & get_and_then_tac_fn() { return g_and_then_tac_fn; }
|
||||
expr const & get_or_else_tac_fn() { return g_or_else_tac_fn; }
|
||||
|
@ -95,6 +95,12 @@ tactic expr_to_tactic(environment const & env, expr const & e, pos_info_provider
|
|||
return expr_to_tactic(tc, e, p);
|
||||
}
|
||||
|
||||
tactic fixpoint(expr const & b) {
|
||||
return tactic([=](environment const & env, io_state const & ios, proof_state const & s) -> proof_state_seq {
|
||||
return expr_to_tactic(env, b, nullptr)(env, ios, s);
|
||||
});
|
||||
}
|
||||
|
||||
register_simple_tac::register_simple_tac(name const & n, std::function<tactic()> f) {
|
||||
register_expr_to_tactic(n, [=](type_checker &, expr const & e, pos_info_provider const *) {
|
||||
if (!is_constant(e))
|
||||
|
@ -189,6 +195,12 @@ static register_unary_num_tac reg_at_most(name(g_tac, "at_most"), [](tactic cons
|
|||
static register_unary_num_tac reg_discard(name(g_tac, "discard"), [](tactic const & t, unsigned k) { return discard(t, k); });
|
||||
static register_unary_num_tac reg_focus_at(name(g_tac, "focus_at"), [](tactic const & t, unsigned k) { return focus(t, k); });
|
||||
static register_unary_num_tac reg_try_for(name(g_tac, "try_for"), [](tactic const & t, unsigned k) { return try_for(t, k); });
|
||||
static register_tac reg_fixpoint(g_fixpoint_name, [](type_checker & tc, expr const & e, pos_info_provider const *) {
|
||||
if (!is_constant(app_fn(e)))
|
||||
throw expr_to_tactic_exception(e, "invalid fixpoint tactic, it must have one argument");
|
||||
expr r = tc.whnf(mk_app(app_arg(e), e));
|
||||
return fixpoint(r);
|
||||
});
|
||||
|
||||
// We encode the 'by' expression that is used to trigger tactic execution.
|
||||
// This is a trick to avoid creating a new kind of expression.
|
||||
|
|
5
tests/lean/run/tactic22.lean
Normal file
5
tests/lean/run/tactic22.lean
Normal file
|
@ -0,0 +1,5 @@
|
|||
import standard
|
||||
using tactic
|
||||
|
||||
theorem T (a b c d : Bool) (Ha : a) (Hb : b) (Hc : c) (Hd : d) : a ∧ b ∧ c ∧ d
|
||||
:= by fixpoint (λ f, (apply @and_intro; f) | (assumption; f) | id)
|
Loading…
Add table
Reference in a new issue