diff --git a/src/frontends/lean/builtin_cmds.cpp b/src/frontends/lean/builtin_cmds.cpp index 9e057e9fc..ea678aeb2 100644 --- a/src/frontends/lean/builtin_cmds.cpp +++ b/src/frontends/lean/builtin_cmds.cpp @@ -272,16 +272,12 @@ environment opaque_hint_cmd(parser & p) { p.next(); env = set_main_module_opaque_defs(env, hiding); } else { - auto pos = p.pos(); - name id = p.check_id_next("invalid 'opaque_hint', identifier expected"); - found = true; - expr e = p.id_to_expr(id, pos); - if (!is_constant(e)) - throw parser_error(sstream() << "'" << id << "' is not a constant", pos); + name c = p.check_constant_next("invalid 'opaque_hint', constant expected"); + found = true; if (hiding) - env = hide_definition(env, const_name(e)); + env = hide_definition(env, c); else - env = expose_definition(env, const_name(e)); + env = expose_definition(env, c); } } p.next(); diff --git a/src/frontends/lean/calc.cpp b/src/frontends/lean/calc.cpp index 713ede488..437685c4a 100644 --- a/src/frontends/lean/calc.cpp +++ b/src/frontends/lean/calc.cpp @@ -154,17 +154,17 @@ static void calc_trans_reader(deserializer & d, module_idx, shared_environment & register_module_object_reader_fn g_calc_trans_reader(g_calc_trans_key, calc_trans_reader); environment calc_subst_cmd(parser & p) { - name id = p.check_id_next("invalid 'calc_subst' command, identifier expected"); + name id = p.check_constant_next("invalid 'calc_subst' command, constant expected"); return add_calc_subst(p.env(), id); } environment calc_refl_cmd(parser & p) { - name id = p.check_id_next("invalid 'calc_refl' command, identifier expected"); + name id = p.check_constant_next("invalid 'calc_refl' command, constant expected"); return add_calc_refl(p.env(), id); } environment calc_trans_cmd(parser & p) { - name id = p.check_id_next("invalid 'calc_trans' command, identifier expected"); + name id = p.check_constant_next("invalid 'calc_trans' command, constant expected"); return add_calc_trans(p.env(), id); } diff --git a/src/frontends/lean/class.cpp b/src/frontends/lean/class.cpp index 83f6e4f6c..7a9a8d3c8 100644 --- a/src/frontends/lean/class.cpp +++ b/src/frontends/lean/class.cpp @@ -94,12 +94,8 @@ environment add_instance_cmd(parser & p) { environment env = p.env(); while (p.curr_is_identifier()) { found = true; - auto pos = p.pos(); - name c = p.get_name_val(); - p.next(); - expr e = p.id_to_expr(c, pos); - if (!is_constant(e)) throw parser_error(sstream() << "invalid 'class instance' declaration, '" << c << "' is not a constant", pos); - env = add_instance(env, const_name(e)); + name c = p.check_constant_next("invalid 'class instance' declaration, constant expected"); + env = add_instance(env, c); } if (!found) throw parser_error("invalid 'class instance' declaration, at least one identifier expected", p.pos()); diff --git a/src/frontends/lean/parser.cpp b/src/frontends/lean/parser.cpp index a8d0a4dc8..e05b911cd 100644 --- a/src/frontends/lean/parser.cpp +++ b/src/frontends/lean/parser.cpp @@ -856,6 +856,15 @@ expr parser::id_to_expr(name const & id, pos_info const & p) { } } +name parser::check_constant_next(char const * msg) { + auto p = pos(); + name id = check_id_next(msg); + expr e = id_to_expr(id, p); + if (!is_constant(e)) + throw parser_error(msg, p); + return const_name(e); +} + expr parser::parse_id() { auto p = pos(); name id = get_name_val(); diff --git a/src/frontends/lean/parser.h b/src/frontends/lean/parser.h index bfe6fe278..3108b7232 100644 --- a/src/frontends/lean/parser.h +++ b/src/frontends/lean/parser.h @@ -190,9 +190,10 @@ public: void check_token_next(name const & tk, char const * msg); /** \brief Check if the current token is an identifier, if it is return it and move to next token, otherwise throw an exception. */ name check_id_next(char const * msg); - /** \brief Check if the current token is an atomic identifier, if it is return it and move to next token, - otherwise throw an exception. */ + /** \brief Check if the current token is an atomic identifier, if it is, return it and move to next token, otherwise throw an exception. */ name check_atomic_id_next(char const * msg); + /** \brief Check if the current token is a constant, if it is, return it and move to next token, otherwise throw an exception. */ + name check_constant_next(char const * msg); mpq const & get_num_val() const { return m_scanner.get_num_val(); } name const & get_name_val() const { return m_scanner.get_name_val(); } diff --git a/src/frontends/lean/tactic_hint.cpp b/src/frontends/lean/tactic_hint.cpp index 8faa5fd11..0689ff9eb 100644 --- a/src/frontends/lean/tactic_hint.cpp +++ b/src/frontends/lean/tactic_hint.cpp @@ -92,15 +92,12 @@ list get_tactic_hints(environment const & env) { } expr parse_tactic_name(parser & p) { - auto pos = p.pos(); - name id = p.check_id_next("invalid tactic name, identifier expected"); - expr pre_tac = p.id_to_expr(id, pos); - if (!is_constant(pre_tac)) - throw parser_error(sstream() << "invalid tactic name, '" << id << "' is not a constant", pos); - expr pre_tac_type = p.env().get(const_name(pre_tac)).get_type(); + auto pos = p.pos(); + name pre_tac = p.check_constant_next("invalid tactic name, constant expected"); + expr pre_tac_type = p.env().get(pre_tac).get_type(); if (!is_constant(pre_tac_type) || const_name(pre_tac_type) != name({"tactic", "tactic"})) - throw parser_error(sstream() << "invalid tactic name, '" << id << "' is not a tactic", pos); - return pre_tac; + throw parser_error(sstream() << "invalid tactic name, '" << pre_tac << "' is not a tactic", pos); + return mk_constant(pre_tac); } static name g_lbracket("["); diff --git a/tests/lean/run/calc.lean b/tests/lean/run/calc.lean new file mode 100644 index 000000000..5e44e8229 --- /dev/null +++ b/tests/lean/run/calc.lean @@ -0,0 +1,17 @@ +import standard +using num + +namespace foo + variable le : num → num → Bool + axiom le_trans {a b c : num} : le a b → le b c → le a c + calc_trans le_trans + infix `≤`:50 := le +end + +namespace foo + theorem T {a b c d : num} : a ≤ b → b ≤ c → c ≤ d → a ≤ d + := assume H1 H2 H3, + calc a ≤ b : H1 + ... ≤ c : H2 + ... ≤ d : H3 +end