feat(frontends/lean/builtin_exprs): add 'have' and 'show' expressions
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
2c4175341c
commit
4f3da90443
3 changed files with 60 additions and 0 deletions
|
@ -18,6 +18,8 @@ static name g_in("in");
|
|||
static name g_colon(":");
|
||||
static name g_assign(":=");
|
||||
static name g_comma(",");
|
||||
static name g_from("from");
|
||||
static name g_by("by");
|
||||
|
||||
static expr parse_Type(parser & p, unsigned, expr const *, pos_info const & pos) {
|
||||
if (p.curr_is_token(g_llevel_curly)) {
|
||||
|
@ -97,6 +99,46 @@ static expr parse_by(parser & p, unsigned, expr const *, pos_info const & pos) {
|
|||
return r;
|
||||
}
|
||||
|
||||
static expr parse_proof(parser & p, expr const & prop) {
|
||||
if (p.curr_is_token(g_from)) {
|
||||
p.next();
|
||||
return p.parse_expr();
|
||||
} else if (p.curr_is_token(g_by)) {
|
||||
auto pos = p.pos();
|
||||
p.next();
|
||||
tactic t = p.parse_tactic();
|
||||
expr r = p.save_pos(mk_expr_placeholder(some_expr(prop)), pos);
|
||||
p.save_hint(r, t);
|
||||
return r;
|
||||
} else {
|
||||
throw parser_error("invalid expression, 'by' or 'from' expected", p.pos());
|
||||
}
|
||||
}
|
||||
|
||||
static expr parse_have(parser & p, unsigned, expr const *, pos_info const & pos) {
|
||||
name id = p.check_id_next("invalid 'have' declaration, identifier expected");
|
||||
p.check_token_next(g_colon, "invalid 'have' declaration, ':' expected");
|
||||
expr prop = p.parse_expr();
|
||||
p.check_token_next(g_comma, "invalid 'have' declaration, ',' expected");
|
||||
expr proof = parse_proof(p, prop);
|
||||
p.check_token_next(g_comma, "invalid 'have' declaration, ',' expected");
|
||||
parser::local_scope scope(p);
|
||||
expr l = p.save_pos(mk_local(id, prop), pos);
|
||||
p.add_local(l);
|
||||
expr body = abstract(p.parse_expr(), l);
|
||||
// remark: mk_contextual_info(false) informs the elaborator that prop should not occur inside metavariables.
|
||||
expr r = p.save_pos(mk_lambda(id, prop, body, mk_contextual_info(false)), pos);
|
||||
return p.save_pos(mk_app(r, proof), pos);
|
||||
}
|
||||
|
||||
static name H_show("H_show");
|
||||
static expr parse_show(parser & p, unsigned, expr const *, pos_info const & pos) {
|
||||
expr prop = p.parse_expr();
|
||||
p.check_token_next(g_comma, "invalid 'show' declaration, ',' expected");
|
||||
expr proof = parse_proof(p, prop);
|
||||
return p.save_pos(mk_let(H_show, prop, proof, Var(0)), pos);
|
||||
}
|
||||
|
||||
parse_table init_nud_table() {
|
||||
action Expr(mk_expr_action());
|
||||
action Skip(mk_skip_action());
|
||||
|
@ -105,6 +147,8 @@ parse_table init_nud_table() {
|
|||
parse_table r;
|
||||
r = r.add({transition("_", mk_ext_action(parse_placeholder))}, x0);
|
||||
r = r.add({transition("by", mk_ext_action(parse_by))}, x0);
|
||||
r = r.add({transition("have", mk_ext_action(parse_have))}, x0);
|
||||
r = r.add({transition("show", mk_ext_action(parse_show))}, x0);
|
||||
r = r.add({transition("(", Expr), transition(")", Skip)}, x0);
|
||||
r = r.add({transition("fun", Binders), transition(",", mk_scoped_expr_action(x0))}, x0);
|
||||
r = r.add({transition("Pi", Binders), transition(",", mk_scoped_expr_action(x0, 0, false))}, x0);
|
||||
|
|
|
@ -256,6 +256,7 @@ public:
|
|||
|
||||
inline binder_info mk_implicit_binder_info() { return binder_info(true); }
|
||||
inline binder_info mk_cast_binder_info() { return binder_info(false, true); }
|
||||
inline binder_info mk_contextual_info(bool f) { return binder_info(false, false, f); }
|
||||
|
||||
bool operator==(binder_info const & i1, binder_info const & i2);
|
||||
inline bool operator!=(binder_info const & i1, binder_info const & i2) { return !(i1 == i2); }
|
||||
|
|
15
tests/lean/run/t9.lean
Normal file
15
tests/lean/run/t9.lean
Normal file
|
@ -0,0 +1,15 @@
|
|||
definition [inline] bool : Type.{1} := Type.{0}
|
||||
definition and (p q : bool) : bool
|
||||
:= ∀ c : bool, (p → q → c) → c
|
||||
infixl `∧` 25 := and
|
||||
theorem and_intro (p q : bool) (H1 : p) (H2 : q) : p ∧ q
|
||||
:= λ (c : bool) (H : p → q → c), H H1 H2
|
||||
theorem and_elim_left (p q : bool) (H : p ∧ q) : p
|
||||
:= H p (λ (H1 : p) (H2 : q), H1)
|
||||
theorem and_elim_right (p q : bool) (H : p ∧ q) : q
|
||||
:= H q (λ (H1 : p) (H2 : q), H2)
|
||||
theorem and_comm (p q : bool) (H : p ∧ q) : q ∧ p
|
||||
:= have H1 : p, from and_elim_left p q H,
|
||||
have H2 : q, from and_elim_right p q H,
|
||||
show q ∧ p, from and_intro q p H2 H1
|
||||
|
Loading…
Reference in a new issue