fix(frontends/lean): calc configuration commands, add check_constant_next auxiliary method

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2014-07-15 01:19:47 +01:00
parent ffdb43da02
commit 0f44e3c9f4
7 changed files with 43 additions and 27 deletions

View file

@ -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();

View file

@ -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);
}

View file

@ -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());

View file

@ -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();

View file

@ -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(); }

View file

@ -92,15 +92,12 @@ list<tactic_hint_entry> 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("[");

17
tests/lean/run/calc.lean Normal file
View file

@ -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