fix(frontends/lean): begin-end
automatic tactic notation bug, fixes #262
This commit is contained in:
parent
78bc3ef7e4
commit
60f32fa709
5 changed files with 38 additions and 7 deletions
|
@ -128,9 +128,12 @@ static environment open_tactic_namespace(parser & p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static expr parse_by(parser & p, unsigned, expr const *, pos_info const & pos) {
|
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);
|
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);
|
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);
|
environment env = open_tactic_namespace(p);
|
||||||
parser::local_scope scope2(p, env);
|
parser::local_scope scope2(p, env);
|
||||||
parser::undef_id_to_local_scope scope1(p);
|
parser::undef_id_to_local_scope scope1(p);
|
||||||
|
p.next();
|
||||||
optional<expr> pre_tac = get_begin_end_pre_tactic(env);
|
optional<expr> pre_tac = get_begin_end_pre_tactic(env);
|
||||||
buffer<expr> tacs;
|
buffer<expr> tacs;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
@ -209,7 +213,6 @@ static expr parse_proof(parser & p, expr const & prop) {
|
||||||
return parse_proof_qed_core(p, pos);
|
return parse_proof_qed_core(p, pos);
|
||||||
} else if (p.curr_is_token(get_begin_tk())) {
|
} else if (p.curr_is_token(get_begin_tk())) {
|
||||||
auto pos = p.pos();
|
auto pos = p.pos();
|
||||||
p.next();
|
|
||||||
return parse_begin_end_core(p, pos);
|
return parse_begin_end_core(p, pos);
|
||||||
} else if (p.curr_is_token(get_by_tk())) {
|
} else if (p.curr_is_token(get_by_tk())) {
|
||||||
// parse: 'by' tactic
|
// parse: 'by' tactic
|
||||||
|
@ -420,7 +423,7 @@ parse_table init_nud_table() {
|
||||||
expr x0 = mk_var(0);
|
expr x0 = mk_var(0);
|
||||||
parse_table r;
|
parse_table r;
|
||||||
r = r.add({transition("_", mk_ext_action(parse_placeholder))}, x0);
|
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("have", mk_ext_action(parse_have))}, x0);
|
||||||
r = r.add({transition("show", mk_ext_action(parse_show))}, x0);
|
r = r.add({transition("show", mk_ext_action(parse_show))}, x0);
|
||||||
r = r.add({transition("obtain", mk_ext_action(parse_obtain))}, 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_overwrite_notation))}, x0);
|
||||||
r = r.add({transition("@", mk_ext_action(parse_explicit_expr))}, 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("!", 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("proof", mk_ext_action(parse_proof_qed))}, x0);
|
||||||
r = r.add({transition("sorry", mk_ext_action(parse_sorry))}, x0);
|
r = r.add({transition("sorry", mk_ext_action(parse_sorry))}, x0);
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -12,6 +12,7 @@ Author: Leonardo de Moura
|
||||||
#include "kernel/replace_fn.h"
|
#include "kernel/replace_fn.h"
|
||||||
#include "library/kernel_bindings.h"
|
#include "library/kernel_bindings.h"
|
||||||
#include "frontends/lean/parse_table.h"
|
#include "frontends/lean/parse_table.h"
|
||||||
|
#include "frontends/lean/parser.h"
|
||||||
#include "frontends/lean/no_info.h"
|
#include "frontends/lean/no_info.h"
|
||||||
|
|
||||||
namespace lean {
|
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);
|
expr new_rec = annotate_macro_subterms(rec);
|
||||||
return action(new scoped_expr_action_cell(new_rec, rb, lambda));
|
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 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) {
|
action replace(action const & a, std::function<expr(expr const &)> const & f) {
|
||||||
|
|
|
@ -63,6 +63,7 @@ public:
|
||||||
friend action mk_exprs_action(name const & sep, expr const & rec, expr const & ini,
|
friend action mk_exprs_action(name const & sep, expr const & rec, expr const & ini,
|
||||||
optional<name> const & terminator, bool right, unsigned rbp);
|
optional<name> const & terminator, bool right, unsigned rbp);
|
||||||
friend action mk_scoped_expr_action(expr const & rec, unsigned rbp, bool lambda);
|
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_action(parse_fn const & fn);
|
||||||
friend action mk_ext_lua_action(char const * lua_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_binder_action();
|
||||||
action mk_binders_action();
|
action mk_binders_action();
|
||||||
action mk_scoped_expr_action(expr const & rec, unsigned rbp = 0, bool lambda = true);
|
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_action(parse_fn const & fn);
|
||||||
action mk_ext_lua_action(char const * lua_fn);
|
action mk_ext_lua_action(char const * lua_fn);
|
||||||
|
|
||||||
|
|
|
@ -869,15 +869,17 @@ expr parser::parse_notation(parse_table t, expr * left) {
|
||||||
auto r = t.find(get_token_info().value());
|
auto r = t.find(get_token_info().value());
|
||||||
if (!r)
|
if (!r)
|
||||||
break;
|
break;
|
||||||
next();
|
|
||||||
notation::action const & a = r->first;
|
notation::action const & a = r->first;
|
||||||
switch (a.kind()) {
|
switch (a.kind()) {
|
||||||
case notation::action_kind::Skip:
|
case notation::action_kind::Skip:
|
||||||
|
next();
|
||||||
break;
|
break;
|
||||||
case notation::action_kind::Expr:
|
case notation::action_kind::Expr:
|
||||||
|
next();
|
||||||
args.push_back(parse_expr(a.rbp()));
|
args.push_back(parse_expr(a.rbp()));
|
||||||
break;
|
break;
|
||||||
case notation::action_kind::Exprs: {
|
case notation::action_kind::Exprs: {
|
||||||
|
next();
|
||||||
buffer<expr> r_args;
|
buffer<expr> r_args;
|
||||||
auto terminator = a.get_terminator();
|
auto terminator = a.get_terminator();
|
||||||
if (!terminator || !curr_is_token(*terminator)) {
|
if (!terminator || !curr_is_token(*terminator)) {
|
||||||
|
@ -917,14 +919,17 @@ expr parser::parse_notation(parse_table t, expr * left) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case notation::action_kind::Binder:
|
case notation::action_kind::Binder:
|
||||||
|
next();
|
||||||
binder_pos = pos();
|
binder_pos = pos();
|
||||||
ps.push_back(parse_binder());
|
ps.push_back(parse_binder());
|
||||||
break;
|
break;
|
||||||
case notation::action_kind::Binders:
|
case notation::action_kind::Binders:
|
||||||
|
next();
|
||||||
binder_pos = pos();
|
binder_pos = pos();
|
||||||
lenv = parse_binders(ps);
|
lenv = parse_binders(ps);
|
||||||
break;
|
break;
|
||||||
case notation::action_kind::ScopedExpr: {
|
case notation::action_kind::ScopedExpr: {
|
||||||
|
next();
|
||||||
expr r = parse_scoped_expr(ps, lenv, a.rbp());
|
expr r = parse_scoped_expr(ps, lenv, a.rbp());
|
||||||
bool no_cache = false;
|
bool no_cache = false;
|
||||||
if (is_var(a.get_rec(), 0)) {
|
if (is_var(a.get_rec(), 0)) {
|
||||||
|
@ -953,6 +958,7 @@ expr parser::parse_notation(parse_table t, expr * left) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case notation::action_kind::LuaExt:
|
case notation::action_kind::LuaExt:
|
||||||
|
next();
|
||||||
m_last_script_pos = p;
|
m_last_script_pos = p;
|
||||||
using_script([&](lua_State * L) {
|
using_script([&](lua_State * L) {
|
||||||
scoped_set_parser scope(L, *this);
|
scoped_set_parser scope(L, *this);
|
||||||
|
|
11
tests/lean/run/tactic_notation.lean
Normal file
11
tests/lean/run/tactic_notation.lean
Normal 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
|
Loading…
Reference in a new issue