fixup! also allow shadowing non-constructor definitions
This commit is contained in:
parent
d7789fa58a
commit
e9a6a532ab
5 changed files with 45 additions and 26 deletions
|
@ -258,8 +258,8 @@ definition rotl : ∀ {n : nat} m : nat, fin n → fin n
|
|||
| (succ n) := take m, madd (mk_mod n (n*m))
|
||||
|
||||
definition rotr : ∀ {n : nat} m : nat, fin n → fin n
|
||||
| (0:nat) := take m i, elim0 i
|
||||
| (nat.succ n) := take m, madd (-(mk_mod n (n*m)))
|
||||
| 0 := take m i, elim0 i
|
||||
| (succ n) := take m, madd (-(mk_mod n (n*m)))
|
||||
|
||||
lemma rotl_succ' {n m : nat} : rotl m = madd (mk_mod n (n*m)) := rfl
|
||||
|
||||
|
|
|
@ -441,13 +441,8 @@ static bool is_curr_with_or_comma_or_bar(parser & p) {
|
|||
}
|
||||
|
||||
/**
|
||||
For convenience, the left-hand-side of a recursive equation may contain
|
||||
undeclared variables.
|
||||
We use parser::undef_id_to_local_scope to force the parser to create a local constant for
|
||||
each undefined identifier.
|
||||
|
||||
This method validates occurrences of these variables. They can only occur as an application
|
||||
or macro argument.
|
||||
This method validates occurrences of local variables (i.e., variables bound in the pattern).
|
||||
They can only occur as an application or macro argument.
|
||||
*/
|
||||
static void validate_equation_lhs(parser const & p, expr const & lhs, buffer<expr> const & locals) {
|
||||
if (is_app(lhs)) {
|
||||
|
|
|
@ -18,6 +18,7 @@ Author: Leonardo de Moura
|
|||
#include "kernel/replace_fn.h"
|
||||
#include "kernel/abstract.h"
|
||||
#include "kernel/instantiate.h"
|
||||
#include "kernel/inductive/inductive.h"
|
||||
#include "kernel/error_msgs.h"
|
||||
#include "library/trace.h"
|
||||
#include "library/parser_nested_exception.h"
|
||||
|
@ -108,7 +109,7 @@ parser::undef_id_to_const_scope::undef_id_to_const_scope(parser & p):
|
|||
parser::undef_id_to_local_scope::undef_id_to_local_scope(parser & p):
|
||||
flet<undef_id_behavior>(p.m_undef_id_behavior, undef_id_behavior::AssumeLocal) {}
|
||||
parser::local_and_undef_id_to_local_scope::local_and_undef_id_to_local_scope(parser & p):
|
||||
flet<undef_id_behavior>(p.m_undef_id_behavior, undef_id_behavior::AssumeLocalAndAlsoDefinedLocals) {}
|
||||
flet<undef_id_behavior>(p.m_undef_id_behavior, undef_id_behavior::AssumeLocalAndAlsoDefinedNonConstructors) {}
|
||||
|
||||
static name * g_tmp_prefix = nullptr;
|
||||
|
||||
|
@ -1459,6 +1460,13 @@ expr parser::parse_led_notation(expr left) {
|
|||
}
|
||||
}
|
||||
|
||||
expr parser::mk_placeholder_local(name const & id, pos_info const & p) {
|
||||
expr local = mk_local(id, mk_expr_placeholder());
|
||||
m_undef_ids.push_back(local);
|
||||
save_identifier_info(p, local_pp_name(local));
|
||||
return save_pos(local, p);
|
||||
}
|
||||
|
||||
expr parser::id_to_expr(name const & id, pos_info const & p) {
|
||||
buffer<level> lvl_buffer;
|
||||
levels ls;
|
||||
|
@ -1476,11 +1484,8 @@ expr parser::id_to_expr(name const & id, pos_info const & p) {
|
|||
if (ls && m_undef_id_behavior != undef_id_behavior::AssumeConstant)
|
||||
throw parser_error("invalid use of explicit universe parameter, identifier is a variable, "
|
||||
"parameter or a constant bound to parameters in a section", p);
|
||||
if (m_undef_id_behavior == undef_id_behavior::AssumeLocalAndAlsoDefinedLocals) {
|
||||
expr local = mk_local(id, mk_expr_placeholder());
|
||||
m_undef_ids.push_back(local);
|
||||
return save_pos(local, p);
|
||||
}
|
||||
if (m_undef_id_behavior == undef_id_behavior::AssumeLocalAndAlsoDefinedNonConstructors)
|
||||
return mk_placeholder_local(id, p);
|
||||
auto r = copy_with_new_pos(*it1, p);
|
||||
save_type_info(r);
|
||||
save_identifier_info(p, id);
|
||||
|
@ -1491,6 +1496,10 @@ expr parser::id_to_expr(name const & id, pos_info const & p) {
|
|||
auto new_id = ns + id;
|
||||
if (!ns.is_anonymous() && m_env.find(new_id) &&
|
||||
(!id.is_atomic() || !is_protected(m_env, new_id))) {
|
||||
if (m_undef_id_behavior == undef_id_behavior::AssumeLocalAndAlsoDefinedNonConstructors &&
|
||||
id.is_atomic() && !inductive::is_intro_rule(m_env, new_id)) {
|
||||
return mk_placeholder_local(id, p);
|
||||
}
|
||||
auto r = save_pos(mk_constant(new_id, ls), p);
|
||||
save_type_info(r);
|
||||
add_ref_index(new_id, p);
|
||||
|
@ -1513,27 +1522,42 @@ expr parser::id_to_expr(name const & id, pos_info const & p) {
|
|||
|
||||
optional<expr> r;
|
||||
// globals
|
||||
if (m_env.find(id))
|
||||
if (m_env.find(id)) {
|
||||
if (m_undef_id_behavior == undef_id_behavior::AssumeLocalAndAlsoDefinedNonConstructors && id.is_atomic()) {
|
||||
bool has_constructor = false;
|
||||
for (auto & c : to_constants(id, "", p)) {
|
||||
if (inductive::is_intro_rule(m_env, c))
|
||||
has_constructor = true;
|
||||
}
|
||||
if (!has_constructor)
|
||||
return mk_placeholder_local(id, p);
|
||||
}
|
||||
r = save_pos(mk_constant(id, ls), p);
|
||||
}
|
||||
// aliases
|
||||
auto as = get_expr_aliases(m_env, id);
|
||||
if (!is_nil(as)) {
|
||||
buffer<expr> new_as;
|
||||
if (r)
|
||||
new_as.push_back(*r);
|
||||
bool has_constructor = false;
|
||||
for (auto const & e : as) {
|
||||
has_constructor |= (bool)inductive::is_intro_rule(m_env, e);
|
||||
new_as.push_back(copy_with_new_pos(mk_constant(e, ls), p));
|
||||
}
|
||||
if (m_undef_id_behavior == undef_id_behavior::AssumeLocalAndAlsoDefinedNonConstructors &&
|
||||
id.is_atomic() && !has_constructor) {
|
||||
return mk_placeholder_local(id, p);
|
||||
}
|
||||
r = save_pos(mk_choice(new_as.size(), new_as.data()), p);
|
||||
save_overload(*r);
|
||||
}
|
||||
if (!r) {
|
||||
if (m_undef_id_behavior == undef_id_behavior::AssumeConstant) {
|
||||
r = save_pos(mk_constant(get_namespace(m_env) + id, ls), p);
|
||||
} else if (m_undef_id_behavior == undef_id_behavior::AssumeLocal || m_undef_id_behavior == undef_id_behavior::AssumeLocalAndAlsoDefinedLocals) {
|
||||
expr local = mk_local(id, mk_expr_placeholder());
|
||||
m_undef_ids.push_back(local);
|
||||
r = save_pos(local, p);
|
||||
} else if (m_undef_id_behavior == undef_id_behavior::AssumeLocal ||
|
||||
m_undef_id_behavior == undef_id_behavior::AssumeLocalAndAlsoDefinedNonConstructors) {
|
||||
return mk_placeholder_local(id, p);
|
||||
}
|
||||
}
|
||||
if (!r)
|
||||
|
@ -1542,8 +1566,6 @@ expr parser::id_to_expr(name const & id, pos_info const & p) {
|
|||
if (is_constant(*r)) {
|
||||
add_ref_index(const_name(*r), p);
|
||||
save_identifier_info(p, const_name(*r));
|
||||
} else if (is_local(*r)) {
|
||||
save_identifier_info(p, local_pp_name(*r));
|
||||
}
|
||||
return *r;
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ typedef std::vector<snapshot> snapshot_vector;
|
|||
|
||||
enum class keep_theorem_mode { All, DiscardImported, DiscardAll };
|
||||
|
||||
enum class undef_id_behavior { Error, AssumeConstant, AssumeLocal, AssumeLocalAndAlsoDefinedLocals };
|
||||
enum class undef_id_behavior { Error, AssumeConstant, AssumeLocal, AssumeLocalAndAlsoDefinedNonConstructors };
|
||||
|
||||
class parser {
|
||||
environment m_env;
|
||||
|
@ -533,6 +533,8 @@ public:
|
|||
public:
|
||||
in_notation_ctx(parser & p):m_ctx(p.m_scanner) {}
|
||||
};
|
||||
|
||||
expr mk_placeholder_local(const name &id, const pos_info &p);
|
||||
};
|
||||
|
||||
bool parse_commands(environment & env, io_state & ios, std::istream & in, char const * strm_name, optional<std::string> const & base_dir,
|
||||
|
|
|
@ -27,9 +27,9 @@ infix `+` := expr.add
|
|||
set_option pp.notation false
|
||||
|
||||
definition ev : expr → nat
|
||||
| zero := 0
|
||||
| one := 1
|
||||
| ((a : expr) + b) := ev a + ev b
|
||||
| zero := 0
|
||||
| one := 1
|
||||
| (a + b) := ev a + ev b
|
||||
|
||||
definition foo : expr := add zero (add one one)
|
||||
|
||||
|
|
Loading…
Reference in a new issue