feat(frontends/lean): add "except" notation for "open" command, allow multiple metaclasses to be opened in a single "open" command

This commit is contained in:
Leonardo de Moura 2015-02-11 11:02:59 -08:00
parent 93f04f3034
commit eceed03044
5 changed files with 128 additions and 12 deletions

View file

@ -445,6 +445,24 @@ static name parse_metaclass(parser & p) {
}
}
static void parse_metaclasses(parser & p, buffer<name> & r) {
if (p.curr_is_token(get_sub_tk())) {
p.next();
buffer<name> tmp;
get_metaclasses(tmp);
tmp.push_back(get_decls_tk());
while (p.curr_is_token(get_lbracket_tk())) {
name m = parse_metaclass(p);
tmp.erase_elem(m);
}
r.append(tmp);
} else {
while (p.curr_is_token(get_lbracket_tk())) {
r.push_back(parse_metaclass(p));
}
}
}
static void check_identifier(parser & p, environment const & env, name const & ns, name const & id) {
name full_id = ns + id;
if (!env.find(full_id))
@ -473,8 +491,13 @@ static environment add_abbrev(parser & p, environment const & env, name const &
environment open_export_cmd(parser & p, bool open) {
environment env = p.env();
while (true) {
name cls = parse_metaclass(p);
bool decls = cls.is_anonymous() || cls == get_decls_tk() || cls == get_declarations_tk();
buffer<name> metacls;
parse_metaclasses(p, metacls);
bool decls = false;
if (metacls.empty() ||
std::find(metacls.begin(), metacls.end(), get_decls_tk()) != metacls.end() ||
std::find(metacls.begin(), metacls.end(), get_declarations_tk()) != metacls.end())
decls = true;
auto pos = p.pos();
name ns = p.check_id_next("invalid 'open/export' command, identifier expected");
optional<name> real_ns = to_valid_namespace_name(env, ns);
@ -487,9 +510,9 @@ environment open_export_cmd(parser & p, bool open) {
as = p.check_id_next("invalid 'open/export' command, identifier expected");
}
if (open)
env = using_namespace(env, p.ios(), ns, cls);
env = using_namespace(env, p.ios(), ns, metacls);
else
env = export_namespace(env, p.ios(), ns, cls);
env = export_namespace(env, p.ios(), ns, metacls);
if (decls) {
// Remark: we currently to not allow renaming and hiding of universe levels
buffer<name> exceptions;

View file

@ -80,24 +80,43 @@ bool is_metaclass(name const & n) {
return false;
}
environment using_namespace(environment const & env, io_state const & ios, name const & n, name const & c) {
environment using_namespace(environment const & env, io_state const & ios, name const & n, buffer<name> const & metaclasses) {
environment r = env;
for (auto const & t : get_exts()) {
if (c.is_anonymous() || c == std::get<0>(t))
if (metaclasses.empty() ||
std::find(metaclasses.begin(), metaclasses.end(), std::get<0>(t)) != metaclasses.end())
r = std::get<1>(t)(r, ios, n);
}
return r;
}
environment export_namespace(environment const & env, io_state const & ios, name const & n, name const & c) {
static environment using_namespace(environment const & env, io_state const & ios, name const & n, name const & metaclass) {
buffer<name> tmp;
if (!metaclass.is_anonymous())
tmp.push_back(metaclass);
return using_namespace(env, ios, n, tmp);
}
environment using_namespace(environment const & env, io_state const & ios, name const & n) {
buffer<name> metaclasses;
return using_namespace(env, ios, n, metaclasses);
}
environment export_namespace(environment const & env, io_state const & ios, name const & n, buffer<name> const & metaclasses) {
environment r = env;
for (auto const & t : get_exts()) {
if (c.is_anonymous() || c == std::get<0>(t))
if (metaclasses.empty() ||
std::find(metaclasses.begin(), metaclasses.end(), std::get<0>(t)) != metaclasses.end())
r = std::get<2>(t)(r, ios, n);
}
return r;
}
environment export_namespace(environment const & env, io_state const & ios, name const & n) {
buffer<name> metaclasses;
return export_namespace(env, ios, n, metaclasses);
}
optional<name> to_valid_namespace_name(environment const & env, name const & n) {
scope_mng_ext const & ext = get_extension(env);
if (ext.m_namespace_set.contains(n))

View file

@ -23,11 +23,14 @@ typedef environment (*push_scope_fn)(environment const &, scope_kind);
typedef environment (*pop_scope_fn)(environment const &, scope_kind);
void register_scoped_ext(name const & n, using_namespace_fn use, export_namespace_fn ex, push_scope_fn push, pop_scope_fn pop);
/** \brief Use objects defined in the namespace \c n. If \c c is not the anonymous name, then only objects from "class" \c c are considered. */
environment using_namespace(environment const & env, io_state const & ios, name const & n, name const & c = name());
/** \brief Use objects defined in the namespace \c n.
If \c metaclasses is not empty, then only objects in the given "metaclasses" \c c are considered. */
environment using_namespace(environment const & env, io_state const & ios, name const & n, buffer<name> const & metaclasses);
environment using_namespace(environment const & env, io_state const & ios, name const & n);
/** \brief Export objects defined in the namespace \c n to current namespace.
If \c c is not the anonymous name, then only objects from "class" \c c are considered. */
environment export_namespace(environment const & env, io_state const & ios, name const & n, name const & c = name());
If \c metaclasses is not empty, then only objects in the given "metaclasses" \c c are considered. */
environment export_namespace(environment const & env, io_state const & ios, name const & n, buffer<name> const & metaclasses);
environment export_namespace(environment const & env, io_state const & ios, name const & n);
/** \brief Create a new scope, all scoped extensions are notified. */
environment push_scope(environment const & env, io_state const & ios, scope_kind k, name const & n = name());

42
tests/lean/open_tst.lean Normal file
View file

@ -0,0 +1,42 @@
context
open [notations] [coercions] nat
check 1 + 2
check add -- Error aliases were not created
end
context
open [declarations] [notations] nat
variable a : nat
check a + a
check add a a
check a + 1 -- Error coercion from num to nat was not loaded
end
context
open - [classes] nat
variable a : nat
check a + a
check add a a
check a + 1
definition foo1 : inhabited nat :=
_ -- Error inhabited instances was not loaded
end
context
open - [classes] [decls] nat
variable a : nat
check a + a
check add a a -- Error aliases were not created
check a + 1
definition foo2 : inhabited nat :=
_ -- Error inhabited instances was not loaded
end
context
open [classes] nat
definition foo3 : inhabited nat :=
_
variable a : nat
check a + a -- Error notation declarations were not loaded
end

View file

@ -0,0 +1,29 @@
1 + 2 :
open_tst.lean:4:8: error: unknown identifier 'add'
a + a :
a + a :
open_tst.lean:12:10: error: type mismatch at application
a + 1
term
1
has type
num
but is expected to have type
a + a :
a + a :
a + 1 :
open_tst.lean:22:2: error: don't know how to synthesize placeholder
⊢ inhabited
open_tst.lean:22:2: error: failed to add declaration 'foo1' to environment, value has metavariables
?M_1
a + a :
open_tst.lean:29:8: error: unknown identifier 'add'
a + 1 :
open_tst.lean:32:2: error: don't know how to synthesize placeholder
⊢ inhabited
open_tst.lean:32:2: error: failed to add declaration 'foo2' to environment, value has metavariables
?M_1
open_tst.lean:41:10: error: invalid expression