feat(frontends/lean): allow backticks in binder declarations

This commit is contained in:
Leonardo de Moura 2015-07-22 13:54:47 -07:00
parent fbaa8b21f6
commit cc396cba76
3 changed files with 23 additions and 7 deletions

View file

@ -79,9 +79,9 @@ have ¬ (∀ m, m < succ n → m n → m = 1 m = n), from
assume h, absurd (λ m hl hd, h m (lt_succ_of_le hl) hd) this, assume h, absurd (λ m hl hd, h m (lt_succ_of_le hl) hd) this,
have {m | m < succ n ∧ ¬(m n → m = 1 m = n)}, from bsub_not_of_not_ball this, have {m | m < succ n ∧ ¬(m n → m = 1 m = n)}, from bsub_not_of_not_ball this,
obtain m hlt (h₃ : ¬(m n → m = 1 m = n)), from this, obtain m hlt (h₃ : ¬(m n → m = 1 m = n)), from this,
obtain (h₄ : m n) (h₅ : ¬ (m = 1 m = n)), from iff.mp !not_implies_iff_and_not h₃, obtain `m n` (h₅ : ¬ (m = 1 m = n)), from iff.mp !not_implies_iff_and_not h₃,
have ¬ m = 1 ∧ ¬ m = n, from iff.mp !not_or_iff_not_and_not h₅, have ¬ m = 1 ∧ ¬ m = n, from iff.mp !not_or_iff_not_and_not h₅,
subtype.tag m (and.intro h₄ this) subtype.tag m (and.intro `m n` this)
theorem ex_dvd_of_not_prime {n : nat} : n ≥ 2 → ¬ prime n → ∃ m, m n ∧ m ≠ 1 ∧ m ≠ n := theorem ex_dvd_of_not_prime {n : nat} : n ≥ 2 → ¬ prime n → ∃ m, m n ∧ m ≠ 1 ∧ m ≠ n :=
assume h₁ h₂, ex_of_sub (sub_dvd_of_not_prime h₁ h₂) assume h₁ h₂, ex_of_sub (sub_dvd_of_not_prime h₁ h₂)
@ -125,7 +125,7 @@ definition infinite_primes (n : nat) : {p | p ≥ n ∧ prime p} :=
let m := fact (n + 1) in let m := fact (n + 1) in
have m ≥ 1, from le_of_lt_succ (succ_lt_succ (fact_pos _)), have m ≥ 1, from le_of_lt_succ (succ_lt_succ (fact_pos _)),
have m + 1 ≥ 2, from succ_le_succ this, have m + 1 ≥ 2, from succ_le_succ this,
obtain p (pp : prime p) (pd : p m + 1), from sub_prime_and_dvd this, obtain p `prime p` `p m + 1`, from sub_prime_and_dvd this,
have p ≥ 2, from ge_two_of_prime `prime p`, have p ≥ 2, from ge_two_of_prime `prime p`,
have p > 0, from lt_of_succ_lt (lt_of_succ_le `p ≥ 2`), have p > 0, from lt_of_succ_lt (lt_of_succ_le `p ≥ 2`),
have p ≥ n, from by_contradiction have p ≥ n, from by_contradiction
@ -144,8 +144,8 @@ ex_of_sub (infinite_primes n)
lemma odd_of_prime {p : nat} : prime p → p > 2 → odd p := lemma odd_of_prime {p : nat} : prime p → p > 2 → odd p :=
λ pp p_gt_2, by_contradiction (λ hn, λ pp p_gt_2, by_contradiction (λ hn,
have even p, from even_of_not_odd hn, have even p, from even_of_not_odd hn,
obtain k (hk : p = 2*k), from exists_of_even this, obtain k `p = 2*k`, from exists_of_even this,
assert 2 p, by rewrite [hk]; apply dvd_mul_right, assert 2 p, by rewrite [`p = 2*k`]; apply dvd_mul_right,
or.elim (eq_one_or_eq_self_of_prime_of_dvd pp this) or.elim (eq_one_or_eq_self_of_prime_of_dvd pp this)
(suppose 2 = 1, absurd this dec_trivial) (suppose 2 = 1, absurd this dec_trivial)
(suppose 2 = p, by subst this; exact absurd p_gt_2 !lt.irrefl)) (suppose 2 = p, by subst this; exact absurd p_gt_2 !lt.irrefl))

View file

@ -934,6 +934,13 @@ void parser::parse_binders_core(buffer<expr> & r, buffer<notation_entry> * nentr
if (curr_is_identifier()) { if (curr_is_identifier()) {
parse_binder_block(r, binder_info(), rbp); parse_binder_block(r, binder_info(), rbp);
last_block_delimited = false; last_block_delimited = false;
} else if (curr_is_backtick()) {
auto p = pos();
name n = mk_fresh_name();
expr type = parse_backtick_expr_core();
expr local = save_pos(mk_local(n, type, binder_info()), p);
add_local(local);
r.push_back(local);
} else { } else {
optional<binder_info> bi = parse_optional_binder_info(simple_only); optional<binder_info> bi = parse_optional_binder_info(simple_only);
if (bi) { if (bi) {
@ -1330,8 +1337,8 @@ expr parser::parse_string_expr() {
return from_string(v); return from_string(v);
} }
expr parser::parse_backtick_expr() {
auto p = pos(); expr parser::parse_backtick_expr_core() {
next(); next();
flet<bool> set(m_in_backtick, true); flet<bool> set(m_in_backtick, true);
expr type = parse_expr(); expr type = parse_expr();
@ -1339,6 +1346,12 @@ expr parser::parse_backtick_expr() {
throw parser_error("invalid expression, '`' expected", pos()); throw parser_error("invalid expression, '`' expected", pos());
} }
next(); next();
return type;
}
expr parser::parse_backtick_expr() {
auto p = pos();
expr type = parse_backtick_expr_core();
expr assump = mk_by_plus(save_pos(mk_constant(get_tactic_assumption_name()), p), p); expr assump = mk_by_plus(save_pos(mk_constant(get_tactic_assumption_name()), p), p);
return save_pos(mk_typed_expr(type, assump), p); return save_pos(mk_typed_expr(type, assump), p);
} }

View file

@ -234,6 +234,7 @@ class parser {
elaborator_context mk_elaborator_context(environment const & env, local_level_decls const & lls, pos_info_provider const & pp); elaborator_context mk_elaborator_context(environment const & env, local_level_decls const & lls, pos_info_provider const & pp);
bool m_in_backtick; // true if parser `expr` notation bool m_in_backtick; // true if parser `expr` notation
expr parse_backtick_expr_core();
expr parse_backtick_expr(); expr parse_backtick_expr();
optional<expr> is_tactic_command(name & id); optional<expr> is_tactic_command(name & id);
@ -338,6 +339,8 @@ public:
bool curr_is_token_or_id(name const & tk) const; bool curr_is_token_or_id(name const & tk) const;
/** \brief Return true iff the current token is a command, EOF, period or script block */ /** \brief Return true iff the current token is a command, EOF, period or script block */
bool curr_is_command_like() const; bool curr_is_command_like() const;
/** \brief Return true iff the current token is a backtick ` */
bool curr_is_backtick() const { return curr() == scanner::token_kind::Backtick; }
/** \brief Read the next token if the current one is not End-of-file. */ /** \brief Read the next token if the current one is not End-of-file. */
void next() { if (m_curr != scanner::token_kind::Eof) scan(); } void next() { if (m_curr != scanner::token_kind::Eof) scan(); }
/** \brief Return true iff the current token is a keyword (or command keyword) named \c tk */ /** \brief Return true iff the current token is a keyword (or command keyword) named \c tk */