fix(frontends/lean): begin-end automatic tactic notation bug, fixes #262

This commit is contained in:
Leonardo de Moura 2014-10-27 17:12:25 -07:00
parent 78bc3ef7e4
commit 60f32fa709
5 changed files with 38 additions and 7 deletions

View file

@ -128,9 +128,12 @@ static environment open_tactic_namespace(parser & p) {
}
static expr parse_by(parser & p, unsigned, expr const *, pos_info const & pos) {
parser::undef_id_to_local_scope scope(p);
environment env = open_tactic_namespace(p);
expr t = p.parse_scoped_expr(0, nullptr, env);
parser::undef_id_to_local_scope scope(p);
parser::local_scope scope2(p, env);
parser::undef_id_to_local_scope scope1(p);
p.next();
expr t = p.parse_expr();
return p.mk_by(t, pos);
}
@ -140,6 +143,7 @@ static expr parse_begin_end_core(parser & p, pos_info const & pos) {
environment env = open_tactic_namespace(p);
parser::local_scope scope2(p, env);
parser::undef_id_to_local_scope scope1(p);
p.next();
optional<expr> pre_tac = get_begin_end_pre_tactic(env);
buffer<expr> tacs;
bool first = true;
@ -209,7 +213,6 @@ static expr parse_proof(parser & p, expr const & prop) {
return parse_proof_qed_core(p, pos);
} else if (p.curr_is_token(get_begin_tk())) {
auto pos = p.pos();
p.next();
return parse_begin_end_core(p, pos);
} else if (p.curr_is_token(get_by_tk())) {
// parse: 'by' tactic
@ -420,7 +423,7 @@ parse_table init_nud_table() {
expr x0 = mk_var(0);
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("by", mk_ext_action_core(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("obtain", mk_ext_action(parse_obtain))}, x0);
@ -433,7 +436,7 @@ parse_table init_nud_table() {
r = r.add({transition("#", mk_ext_action(parse_overwrite_notation))}, x0);
r = r.add({transition("@", mk_ext_action(parse_explicit_expr))}, x0);
r = r.add({transition("!", mk_ext_action(parse_consume_args_expr))}, x0);
r = r.add({transition("begin", mk_ext_action(parse_begin_end))}, x0);
r = r.add({transition("begin", mk_ext_action_core(parse_begin_end))}, x0);
r = r.add({transition("proof", mk_ext_action(parse_proof_qed))}, x0);
r = r.add({transition("sorry", mk_ext_action(parse_sorry))}, x0);
return r;

View file

@ -12,6 +12,7 @@ Author: Leonardo de Moura
#include "kernel/replace_fn.h"
#include "library/kernel_bindings.h"
#include "frontends/lean/parse_table.h"
#include "frontends/lean/parser.h"
#include "frontends/lean/no_info.h"
namespace lean {
@ -251,7 +252,15 @@ action mk_scoped_expr_action(expr const & rec, unsigned rb, bool lambda) {
expr new_rec = annotate_macro_subterms(rec);
return action(new scoped_expr_action_cell(new_rec, rb, lambda));
}
action mk_ext_action(parse_fn const & fn) { return action(new ext_action_cell(fn)); }
action mk_ext_action_core(parse_fn const & fn) { return action(new ext_action_cell(fn)); }
action mk_ext_action(parse_fn const & fn) {
auto new_fn = [=](parser & p, unsigned num, expr const * args, pos_info const & pos) -> expr {
p.next();
return fn(p, num, args, pos);
};
return action(new ext_action_cell(new_fn));
}
action mk_ext_lua_action(char const * fn) { return action(new ext_lua_action_cell(fn)); }
action replace(action const & a, std::function<expr(expr const &)> const & f) {

View file

@ -63,6 +63,7 @@ public:
friend action mk_exprs_action(name const & sep, expr const & rec, expr const & ini,
optional<name> const & terminator, bool right, unsigned rbp);
friend action mk_scoped_expr_action(expr const & rec, unsigned rbp, bool lambda);
friend action mk_ext_action_core(parse_fn const & fn);
friend action mk_ext_action(parse_fn const & fn);
friend action mk_ext_lua_action(char const * lua_fn);
@ -93,6 +94,7 @@ action mk_exprs_action(name const & sep, expr const & rec, expr const & ini, opt
action mk_binder_action();
action mk_binders_action();
action mk_scoped_expr_action(expr const & rec, unsigned rbp = 0, bool lambda = true);
action mk_ext_action_core(parse_fn const & fn);
action mk_ext_action(parse_fn const & fn);
action mk_ext_lua_action(char const * lua_fn);

View file

@ -869,15 +869,17 @@ expr parser::parse_notation(parse_table t, expr * left) {
auto r = t.find(get_token_info().value());
if (!r)
break;
next();
notation::action const & a = r->first;
switch (a.kind()) {
case notation::action_kind::Skip:
next();
break;
case notation::action_kind::Expr:
next();
args.push_back(parse_expr(a.rbp()));
break;
case notation::action_kind::Exprs: {
next();
buffer<expr> r_args;
auto terminator = a.get_terminator();
if (!terminator || !curr_is_token(*terminator)) {
@ -917,14 +919,17 @@ expr parser::parse_notation(parse_table t, expr * left) {
break;
}
case notation::action_kind::Binder:
next();
binder_pos = pos();
ps.push_back(parse_binder());
break;
case notation::action_kind::Binders:
next();
binder_pos = pos();
lenv = parse_binders(ps);
break;
case notation::action_kind::ScopedExpr: {
next();
expr r = parse_scoped_expr(ps, lenv, a.rbp());
bool no_cache = false;
if (is_var(a.get_rec(), 0)) {
@ -953,6 +958,7 @@ expr parser::parse_notation(parse_table t, expr * left) {
break;
}
case notation::action_kind::LuaExt:
next();
m_last_script_pos = p;
using_script([&](lua_State * L) {
scoped_set_parser scope(L, *this);

View file

@ -0,0 +1,11 @@
import logic
theorem tst1 (a b c : Prop) : a → b → a ∧ b :=
begin
intros,
apply and.intro,
assumption
end
theorem tst2 (a b c : Prop) : a → b → a ∧ b :=
by intros; apply and.intro; assumption