fix(frontends/lean/builtin_exprs): bug in 'using' expressions

This commit is contained in:
Leonardo de Moura 2015-05-14 17:17:48 -07:00
parent 77c20e99ff
commit 7f8afcf04b
5 changed files with 35 additions and 4 deletions

View file

@ -303,10 +303,14 @@ static expr parse_using_expr(parser & p, expr const & prop, pos_info const & usi
expr l = p.parse_id();
if (!is_local(l))
throw parser_error("invalid 'using' declaration for 'have', local expected", id_pos);
expr new_l = l;
binder_info bi = local_info(l);
if (!bi.is_contextual())
new_l = update_local(l, bi.update_contextual(true));
expr new_l;
binder_info bi = local_info(l).update_contextual(true);
if (p.is_local_variable_parameter(local_pp_name(l))) {
expr new_type = p.save_pos(mk_as_is(mlocal_type(l)), id_pos);
new_l = p.save_pos(mk_local(mlocal_name(l), local_pp_name(l), new_type, bi), id_pos);
} else {
new_l = p.save_pos(update_local(l, bi), id_pos);
}
p.add_local(new_l);
locals.push_back(l);
new_locals.push_back(new_l);

View file

@ -32,6 +32,11 @@ public:
m_map.insert(k, mk_pair(v, m_counter));
m_entries = cons(mk_pair(k, v), m_entries);
m_counter++;
lean_assert(m_counter == length(m_entries)+1);
}
unsigned size() const {
lean_assert(m_counter > 0);
return m_counter - 1;
}
void update(name const & k, V const & v) {
if (auto it = m_map.find(k)) {

View file

@ -110,6 +110,7 @@ parser::parser(environment const & env, io_state const & ios,
m_scanner(strm, strm_name, s ? s->m_line : 1),
m_theorem_queue(*this, num_threads > 1 ? num_threads - 1 : 0),
m_snapshot_vector(sv), m_info_manager(im), m_cache(nullptr), m_index(nullptr) {
m_local_decls_size_at_beg_cmd = 0;
m_profile = ios.get_options().get_bool("profile", false);
if (num_threads > 1 && m_profile)
throw exception("option --profile cannot be used when theorems are compiled in parallel");
@ -1599,6 +1600,7 @@ void parser::parse_command() {
m_cmd_token = get_token_info().token();
if (auto it = cmds().find(cmd_name)) {
next();
m_local_decls_size_at_beg_cmd = m_local_decls.size();
m_env = it->get_fn()(*this);
} else {
auto p = pos();

View file

@ -144,6 +144,9 @@ class parser {
// profiling
bool m_profile;
// auxiliary field used to record the size of m_local_decls before a command is executed.
unsigned m_local_decls_size_at_beg_cmd;
void display_warning_pos(unsigned line, unsigned pos);
void display_error_pos(unsigned line, unsigned pos);
void display_error_pos(pos_info p);
@ -436,6 +439,11 @@ public:
bool is_local_level_variable(name const & n) const { return m_level_variables.contains(n); }
bool is_local_variable(name const & n) const { return m_variables.contains(n); }
bool is_local_variable(expr const & e) const { return is_local_variable(local_pp_name(e)); }
/** \brief Return true iff n is the name of a variable or parameter. */
bool is_local_variable_parameter(name const & n) const {
unsigned idx = m_local_decls.find_idx(n);
return 0 < idx && idx <= m_local_decls_size_at_beg_cmd;
}
/** \brief Update binder information for the section parameter n, return true if success, and false if n is not a section parameter. */
bool update_local_binder_info(name const & n, binder_info const & bi);
void include_variable(name const & n) { m_include_vars.insert(n); }

View file

@ -0,0 +1,12 @@
variable {A : Type}
variable {f : A → A → A}
variable {finv : A → A}
premise (h : ∀ x y : A, finv (f x y) = y)
theorem foo₁ : ∀ x y z : A, f x y = f x z → y = z :=
λ x y z, assume e, using h, from sorry
theorem foo₂ : ∀ x y z : A, f x y = f x z → y = z :=
λ x y z, assume e,
assert s₁ : finv (f x y) = finv (f x z), by rewrite e,
show y = z, using h, by rewrite *h at s₁; exact s₁