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:
parent
93f04f3034
commit
eceed03044
5 changed files with 128 additions and 12 deletions
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
42
tests/lean/open_tst.lean
Normal 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
|
29
tests/lean/open_tst.lean.expected.out
Normal file
29
tests/lean/open_tst.lean.expected.out
Normal 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
|
Loading…
Reference in a new issue