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:
parent
ffdb43da02
commit
0f44e3c9f4
7 changed files with 43 additions and 27 deletions
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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
17
tests/lean/run/calc.lean
Normal 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
|
Loading…
Reference in a new issue