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) {
|
static void check_identifier(parser & p, environment const & env, name const & ns, name const & id) {
|
||||||
name full_id = ns + id;
|
name full_id = ns + id;
|
||||||
if (!env.find(full_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 open_export_cmd(parser & p, bool open) {
|
||||||
environment env = p.env();
|
environment env = p.env();
|
||||||
while (true) {
|
while (true) {
|
||||||
name cls = parse_metaclass(p);
|
buffer<name> metacls;
|
||||||
bool decls = cls.is_anonymous() || cls == get_decls_tk() || cls == get_declarations_tk();
|
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();
|
auto pos = p.pos();
|
||||||
name ns = p.check_id_next("invalid 'open/export' command, identifier expected");
|
name ns = p.check_id_next("invalid 'open/export' command, identifier expected");
|
||||||
optional<name> real_ns = to_valid_namespace_name(env, ns);
|
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");
|
as = p.check_id_next("invalid 'open/export' command, identifier expected");
|
||||||
}
|
}
|
||||||
if (open)
|
if (open)
|
||||||
env = using_namespace(env, p.ios(), ns, cls);
|
env = using_namespace(env, p.ios(), ns, metacls);
|
||||||
else
|
else
|
||||||
env = export_namespace(env, p.ios(), ns, cls);
|
env = export_namespace(env, p.ios(), ns, metacls);
|
||||||
if (decls) {
|
if (decls) {
|
||||||
// Remark: we currently to not allow renaming and hiding of universe levels
|
// Remark: we currently to not allow renaming and hiding of universe levels
|
||||||
buffer<name> exceptions;
|
buffer<name> exceptions;
|
||||||
|
|
|
@ -80,24 +80,43 @@ bool is_metaclass(name const & n) {
|
||||||
return false;
|
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;
|
environment r = env;
|
||||||
for (auto const & t : get_exts()) {
|
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);
|
r = std::get<1>(t)(r, ios, n);
|
||||||
}
|
}
|
||||||
return r;
|
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;
|
environment r = env;
|
||||||
for (auto const & t : get_exts()) {
|
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);
|
r = std::get<2>(t)(r, ios, n);
|
||||||
}
|
}
|
||||||
return r;
|
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) {
|
optional<name> to_valid_namespace_name(environment const & env, name const & n) {
|
||||||
scope_mng_ext const & ext = get_extension(env);
|
scope_mng_ext const & ext = get_extension(env);
|
||||||
if (ext.m_namespace_set.contains(n))
|
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);
|
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);
|
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. */
|
/** \brief Use objects defined in the namespace \c n.
|
||||||
environment using_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 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.
|
/** \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. */
|
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, name const & c = name());
|
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. */
|
/** \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());
|
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