feat(library/tactic): allow user to name generalized term in the 'generalize' tactic
closes #421
This commit is contained in:
parent
3912bc24c8
commit
3233008039
11 changed files with 56 additions and 18 deletions
|
@ -68,7 +68,7 @@ opaque definition apply (e : expr) : tactic := builtin
|
||||||
opaque definition fapply (e : expr) : tactic := builtin
|
opaque definition fapply (e : expr) : tactic := builtin
|
||||||
opaque definition rename (a b : identifier) : tactic := builtin
|
opaque definition rename (a b : identifier) : tactic := builtin
|
||||||
opaque definition intro (e : identifier_list) : tactic := builtin
|
opaque definition intro (e : identifier_list) : tactic := builtin
|
||||||
opaque definition generalize (e : expr) : tactic := builtin
|
opaque definition generalize_tac (e : expr) (id : identifier) : tactic := builtin
|
||||||
opaque definition clear (e : identifier_list) : tactic := builtin
|
opaque definition clear (e : identifier_list) : tactic := builtin
|
||||||
opaque definition revert (e : identifier_list) : tactic := builtin
|
opaque definition revert (e : identifier_list) : tactic := builtin
|
||||||
opaque definition refine (e : expr) : tactic := builtin
|
opaque definition refine (e : expr) : tactic := builtin
|
||||||
|
|
|
@ -68,7 +68,7 @@ opaque definition apply (e : expr) : tactic := builtin
|
||||||
opaque definition fapply (e : expr) : tactic := builtin
|
opaque definition fapply (e : expr) : tactic := builtin
|
||||||
opaque definition rename (a b : identifier) : tactic := builtin
|
opaque definition rename (a b : identifier) : tactic := builtin
|
||||||
opaque definition intro (e : identifier_list) : tactic := builtin
|
opaque definition intro (e : identifier_list) : tactic := builtin
|
||||||
opaque definition generalize (e : expr) : tactic := builtin
|
opaque definition generalize_tac (e : expr) (id : identifier) : tactic := builtin
|
||||||
opaque definition clear (e : identifier_list) : tactic := builtin
|
opaque definition clear (e : identifier_list) : tactic := builtin
|
||||||
opaque definition revert (e : identifier_list) : tactic := builtin
|
opaque definition revert (e : identifier_list) : tactic := builtin
|
||||||
opaque definition refine (e : expr) : tactic := builtin
|
opaque definition refine (e : expr) : tactic := builtin
|
||||||
|
|
|
@ -5,6 +5,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
|
||||||
Author: Leonardo de Moura
|
Author: Leonardo de Moura
|
||||||
*/
|
*/
|
||||||
#include "library/tactic/let_tactic.h"
|
#include "library/tactic/let_tactic.h"
|
||||||
|
#include "library/tactic/generalize_tactic.h"
|
||||||
#include "frontends/lean/tokens.h"
|
#include "frontends/lean/tokens.h"
|
||||||
#include "frontends/lean/parser.h"
|
#include "frontends/lean/parser.h"
|
||||||
#include "frontends/lean/parse_rewrite_tactic.h"
|
#include "frontends/lean/parse_rewrite_tactic.h"
|
||||||
|
@ -38,6 +39,23 @@ static expr parse_let_tactic(parser & p, unsigned, expr const *, pos_info const
|
||||||
return p.save_pos(mk_let_tactic_expr(id, value), pos);
|
return p.save_pos(mk_let_tactic_expr(id, value), pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static expr parse_generalize_tactic(parser & p, unsigned, expr const *, pos_info const & pos) {
|
||||||
|
expr e = p.parse_expr();
|
||||||
|
name id;
|
||||||
|
if (p.curr_is_token(get_as_tk())) {
|
||||||
|
p.next();
|
||||||
|
id = p.check_atomic_id_next("invalid 'generalize' tactic, identifier expected");
|
||||||
|
} else {
|
||||||
|
if (is_constant(e))
|
||||||
|
id = const_name(e);
|
||||||
|
else if (is_local(e))
|
||||||
|
id = local_pp_name(e);
|
||||||
|
else
|
||||||
|
id = name("x");
|
||||||
|
}
|
||||||
|
return p.save_pos(mk_generalize_tactic_expr(e, id), pos);
|
||||||
|
}
|
||||||
|
|
||||||
parse_table init_tactic_nud_table() {
|
parse_table init_tactic_nud_table() {
|
||||||
action Expr(mk_expr_action());
|
action Expr(mk_expr_action());
|
||||||
expr x0 = mk_var(0);
|
expr x0 = mk_var(0);
|
||||||
|
@ -45,6 +63,7 @@ parse_table init_tactic_nud_table() {
|
||||||
r = r.add({transition("(", Expr), transition(")", mk_ext_action(parse_rparen))}, x0);
|
r = r.add({transition("(", Expr), transition(")", mk_ext_action(parse_rparen))}, x0);
|
||||||
r = r.add({transition("rewrite", mk_ext_action(parse_rewrite_tactic_expr))}, x0);
|
r = r.add({transition("rewrite", mk_ext_action(parse_rewrite_tactic_expr))}, x0);
|
||||||
r = r.add({transition("esimp", mk_ext_action(parse_esimp_tactic_expr))}, x0);
|
r = r.add({transition("esimp", mk_ext_action(parse_esimp_tactic_expr))}, x0);
|
||||||
|
r = r.add({transition("generalize", mk_ext_action(parse_generalize_tactic))}, x0);
|
||||||
r = r.add({transition("unfold", mk_ext_action(parse_unfold_tactic_expr))}, x0);
|
r = r.add({transition("unfold", mk_ext_action(parse_unfold_tactic_expr))}, x0);
|
||||||
r = r.add({transition("fold", mk_ext_action(parse_fold_tactic_expr))}, x0);
|
r = r.add({transition("fold", mk_ext_action(parse_fold_tactic_expr))}, x0);
|
||||||
r = r.add({transition("let", mk_ext_action(parse_let_tactic))}, x0);
|
r = r.add({transition("let", mk_ext_action(parse_let_tactic))}, x0);
|
||||||
|
|
|
@ -95,6 +95,7 @@ void init_token_table(token_table & t) {
|
||||||
{"{|", g_max_prec}, {"|}", 0}, {"⊢", 0}, {"⟨", g_max_prec}, {"⟩", 0}, {"^", 0}, {"↑", 0}, {"▸", 0},
|
{"{|", g_max_prec}, {"|}", 0}, {"⊢", 0}, {"⟨", g_max_prec}, {"⟩", 0}, {"^", 0}, {"↑", 0}, {"▸", 0},
|
||||||
{"using", 0}, {"|", 0}, {"!", g_max_prec}, {"?", 0}, {"with", 0}, {"...", 0}, {",", 0},
|
{"using", 0}, {"|", 0}, {"!", g_max_prec}, {"?", 0}, {"with", 0}, {"...", 0}, {",", 0},
|
||||||
{".", 0}, {":", 0}, {"::", 0}, {"calc", 0}, {"rewrite", 0}, {"esimp", 0}, {"fold", 0}, {"unfold", 0},
|
{".", 0}, {":", 0}, {"::", 0}, {"calc", 0}, {"rewrite", 0}, {"esimp", 0}, {"fold", 0}, {"unfold", 0},
|
||||||
|
{"generalize", 0}, {"as", 0},
|
||||||
{":=", 0}, {"--", 0}, {"#", 0},
|
{":=", 0}, {"--", 0}, {"#", 0},
|
||||||
{"(*", 0}, {"/-", 0}, {"begin", g_max_prec}, {"proof", g_max_prec}, {"qed", 0}, {"@", g_max_prec},
|
{"(*", 0}, {"/-", 0}, {"begin", g_max_prec}, {"proof", g_max_prec}, {"qed", 0}, {"@", g_max_prec},
|
||||||
{"sorry", g_max_prec}, {"+", g_plus_prec}, {g_cup, g_cup_prec}, {"->", g_arrow_prec},
|
{"sorry", g_max_prec}, {"+", g_plus_prec}, {g_cup, g_cup_prec}, {"->", g_arrow_prec},
|
||||||
|
|
|
@ -91,7 +91,7 @@ name const * g_tactic_opt_identifier_list = nullptr;
|
||||||
name const * g_tactic_fail = nullptr;
|
name const * g_tactic_fail = nullptr;
|
||||||
name const * g_tactic_fixpoint = nullptr;
|
name const * g_tactic_fixpoint = nullptr;
|
||||||
name const * g_tactic_focus_at = nullptr;
|
name const * g_tactic_focus_at = nullptr;
|
||||||
name const * g_tactic_generalize = nullptr;
|
name const * g_tactic_generalize_tac = nullptr;
|
||||||
name const * g_tactic_generalizes = nullptr;
|
name const * g_tactic_generalizes = nullptr;
|
||||||
name const * g_tactic_id = nullptr;
|
name const * g_tactic_id = nullptr;
|
||||||
name const * g_tactic_interleave = nullptr;
|
name const * g_tactic_interleave = nullptr;
|
||||||
|
@ -210,7 +210,7 @@ void initialize_constants() {
|
||||||
g_tactic_fail = new name{"tactic", "fail"};
|
g_tactic_fail = new name{"tactic", "fail"};
|
||||||
g_tactic_fixpoint = new name{"tactic", "fixpoint"};
|
g_tactic_fixpoint = new name{"tactic", "fixpoint"};
|
||||||
g_tactic_focus_at = new name{"tactic", "focus_at"};
|
g_tactic_focus_at = new name{"tactic", "focus_at"};
|
||||||
g_tactic_generalize = new name{"tactic", "generalize"};
|
g_tactic_generalize_tac = new name{"tactic", "generalize_tac"};
|
||||||
g_tactic_generalizes = new name{"tactic", "generalizes"};
|
g_tactic_generalizes = new name{"tactic", "generalizes"};
|
||||||
g_tactic_id = new name{"tactic", "id"};
|
g_tactic_id = new name{"tactic", "id"};
|
||||||
g_tactic_interleave = new name{"tactic", "interleave"};
|
g_tactic_interleave = new name{"tactic", "interleave"};
|
||||||
|
@ -330,7 +330,7 @@ void finalize_constants() {
|
||||||
delete g_tactic_fail;
|
delete g_tactic_fail;
|
||||||
delete g_tactic_fixpoint;
|
delete g_tactic_fixpoint;
|
||||||
delete g_tactic_focus_at;
|
delete g_tactic_focus_at;
|
||||||
delete g_tactic_generalize;
|
delete g_tactic_generalize_tac;
|
||||||
delete g_tactic_generalizes;
|
delete g_tactic_generalizes;
|
||||||
delete g_tactic_id;
|
delete g_tactic_id;
|
||||||
delete g_tactic_interleave;
|
delete g_tactic_interleave;
|
||||||
|
@ -449,7 +449,7 @@ name const & get_tactic_opt_identifier_list_name() { return *g_tactic_opt_identi
|
||||||
name const & get_tactic_fail_name() { return *g_tactic_fail; }
|
name const & get_tactic_fail_name() { return *g_tactic_fail; }
|
||||||
name const & get_tactic_fixpoint_name() { return *g_tactic_fixpoint; }
|
name const & get_tactic_fixpoint_name() { return *g_tactic_fixpoint; }
|
||||||
name const & get_tactic_focus_at_name() { return *g_tactic_focus_at; }
|
name const & get_tactic_focus_at_name() { return *g_tactic_focus_at; }
|
||||||
name const & get_tactic_generalize_name() { return *g_tactic_generalize; }
|
name const & get_tactic_generalize_tac_name() { return *g_tactic_generalize_tac; }
|
||||||
name const & get_tactic_generalizes_name() { return *g_tactic_generalizes; }
|
name const & get_tactic_generalizes_name() { return *g_tactic_generalizes; }
|
||||||
name const & get_tactic_id_name() { return *g_tactic_id; }
|
name const & get_tactic_id_name() { return *g_tactic_id; }
|
||||||
name const & get_tactic_interleave_name() { return *g_tactic_interleave; }
|
name const & get_tactic_interleave_name() { return *g_tactic_interleave; }
|
||||||
|
|
|
@ -93,7 +93,7 @@ name const & get_tactic_opt_identifier_list_name();
|
||||||
name const & get_tactic_fail_name();
|
name const & get_tactic_fail_name();
|
||||||
name const & get_tactic_fixpoint_name();
|
name const & get_tactic_fixpoint_name();
|
||||||
name const & get_tactic_focus_at_name();
|
name const & get_tactic_focus_at_name();
|
||||||
name const & get_tactic_generalize_name();
|
name const & get_tactic_generalize_tac_name();
|
||||||
name const & get_tactic_generalizes_name();
|
name const & get_tactic_generalizes_name();
|
||||||
name const & get_tactic_id_name();
|
name const & get_tactic_id_name();
|
||||||
name const & get_tactic_interleave_name();
|
name const & get_tactic_interleave_name();
|
||||||
|
|
|
@ -86,7 +86,7 @@ tactic.opt_identifier_list
|
||||||
tactic.fail
|
tactic.fail
|
||||||
tactic.fixpoint
|
tactic.fixpoint
|
||||||
tactic.focus_at
|
tactic.focus_at
|
||||||
tactic.generalize
|
tactic.generalize_tac
|
||||||
tactic.generalizes
|
tactic.generalizes
|
||||||
tactic.id
|
tactic.id
|
||||||
tactic.interleave
|
tactic.interleave
|
||||||
|
|
|
@ -12,6 +12,11 @@ Author: Leonardo de Moura
|
||||||
#include "library/tactic/expr_to_tactic.h"
|
#include "library/tactic/expr_to_tactic.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
|
expr mk_generalize_tactic_expr(expr const & e, name const & id) {
|
||||||
|
return mk_app(mk_constant(get_tactic_generalize_tac_name()),
|
||||||
|
e, mk_constant(id));
|
||||||
|
}
|
||||||
|
|
||||||
tactic generalize_tactic(elaborate_fn const & elab, expr const & e, name const & x) {
|
tactic generalize_tactic(elaborate_fn const & elab, expr const & e, name const & x) {
|
||||||
return tactic01([=](environment const & env, io_state const & ios, proof_state const & s) {
|
return tactic01([=](environment const & env, io_state const & ios, proof_state const & s) {
|
||||||
proof_state new_s = s;
|
proof_state new_s = s;
|
||||||
|
@ -60,11 +65,11 @@ tactic generalize_tactic(elaborate_fn const & elab, expr const & e, name const &
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize_generalize_tactic() {
|
void initialize_generalize_tactic() {
|
||||||
register_tac(get_tactic_generalize_name(),
|
register_tac(get_tactic_generalize_tac_name(),
|
||||||
[](type_checker &, elaborate_fn const & fn, expr const & e, pos_info_provider const *) {
|
[](type_checker &, elaborate_fn const & fn, expr const & e, pos_info_provider const *) {
|
||||||
check_tactic_expr(app_arg(e), "invalid 'generalize' tactic, invalid argument");
|
check_tactic_expr(app_arg(app_fn(e)), "invalid 'generalize' tactic, invalid argument");
|
||||||
// TODO(Leo): allow user to provide name to abstract variable
|
name id = tactic_expr_to_id(app_arg(e), "invalid 'generalize' tactic, argument must be an identifier");
|
||||||
return generalize_tactic(fn, get_tactic_expr_expr(app_arg(e)), "x");
|
return generalize_tactic(fn, get_tactic_expr_expr(app_arg(app_fn(e))), id);
|
||||||
});
|
});
|
||||||
|
|
||||||
register_tac(get_tactic_generalizes_name(),
|
register_tac(get_tactic_generalizes_name(),
|
||||||
|
|
|
@ -8,7 +8,7 @@ Author: Leonardo de Moura
|
||||||
#include "library/tactic/elaborate.h"
|
#include "library/tactic/elaborate.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
tactic generalize_tactic(elaborate_fn const & elab, expr const & e);
|
expr mk_generalize_tactic_expr(expr const & e, name const & id);
|
||||||
void initialize_generalize_tactic();
|
void initialize_generalize_tactic();
|
||||||
void finalize_generalize_tactic();
|
void finalize_generalize_tactic();
|
||||||
}
|
}
|
||||||
|
|
9
tests/lean/gen_as.lean
Normal file
9
tests/lean/gen_as.lean
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import data.nat
|
||||||
|
open nat
|
||||||
|
|
||||||
|
example (x y : nat) : x + y + y ≥ 0 :=
|
||||||
|
begin
|
||||||
|
generalize x + y + y as n,
|
||||||
|
state,
|
||||||
|
intro n, exact zero_le n
|
||||||
|
end
|
4
tests/lean/gen_as.lean.expected.out
Normal file
4
tests/lean/gen_as.lean.expected.out
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
gen_as.lean:7:2: proof state
|
||||||
|
x y : ℕ
|
||||||
|
⊢ ∀ (n : ℕ),
|
||||||
|
n ≥ 0
|
Loading…
Reference in a new issue