lean4-htt/src/library/aliases.cpp
Leonardo de Moura 82095cc018 refactor(kernel): split declaration into declaration and constant_info
This is just another step towards the design described at commit 16598391a07d4a
2018-08-22 17:53:11 -07:00

224 lines
7.6 KiB
C++

/*
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include <utility>
#include <algorithm>
#include "runtime/sstream.h"
#include "util/rb_map.h"
#include "kernel/abstract.h"
#include "kernel/instantiate.h"
#include "library/trace.h"
#include "library/expr_lt.h"
#include "library/aliases.h"
#include "library/placeholder.h"
#include "library/scoped_ext.h"
#include "library/protected.h"
namespace lean {
struct aliases_ext;
static aliases_ext const & get_extension(environment const & env);
static environment update(environment const & env, aliases_ext const & ext);
struct aliases_ext : public environment_extension {
struct state {
bool m_in_section;
name_map<names> m_aliases;
name_map<name> m_inv_aliases;
name_map<name> m_level_aliases;
name_map<name> m_inv_level_aliases;
name_map<expr> m_local_refs;
state():m_in_section(false) {}
void add_local_ref(name const & a, expr const & ref) {
m_local_refs.insert(a, ref);
}
void add_expr_alias(name const & a, name const & e, bool overwrite) {
if (auto ref = m_local_refs.find(e)) {
add_local_ref(a, *ref);
} else {
auto it = m_aliases.find(a);
if (it && !overwrite)
m_aliases.insert(a, cons(e, filter(*it, [&](name const & t) { return t != e; })));
else
m_aliases.insert(a, names(e));
m_inv_aliases.insert(e, a);
}
}
};
state m_state;
list<state> m_scopes;
void add_expr_alias(name const & a, name const & e, bool overwrite) {
m_state.add_expr_alias(a, e, overwrite);
}
void add_level_alias(name const & a, name const & l) {
auto it = m_state.m_level_aliases.find(a);
if (it)
throw exception(sstream() << "universe level alias '" << a << "' shadows existing alias");
m_state.m_level_aliases.insert(a, l);
m_state.m_inv_level_aliases.insert(l, a);
}
list<state> add_expr_alias_rec_core(list<state> const & scopes, name const & a, name const & e, bool overwrite) {
if (empty(scopes)) {
return scopes;
} else {
state s = head(scopes);
s.add_expr_alias(a, e, overwrite);
if (s.m_in_section) {
return cons(s, add_expr_alias_rec_core(tail(scopes), a, e, overwrite));
} else {
return cons(s, tail(scopes));
}
}
}
void add_expr_alias_rec(name const & a, name const & e, bool overwrite = false) {
if (m_state.m_in_section) {
m_scopes = add_expr_alias_rec_core(m_scopes, a, e, overwrite);
}
add_expr_alias(a, e, overwrite);
}
void add_local_ref(name const & a, expr const & ref) {
m_state.add_local_ref(a, ref);
}
void push(bool in_section) {
m_scopes = cons(m_state, m_scopes);
m_state.m_in_section = in_section;
}
void pop() {
m_state = head(m_scopes);
m_scopes = tail(m_scopes);
}
void for_each_expr_alias(std::function<void(name const &, names const &)> const & fn) {
m_state.m_aliases.for_each(fn);
}
static environment push_scope(environment const & env, io_state const &, scope_kind k) {
aliases_ext ext = get_extension(env);
ext.push(k != scope_kind::Namespace);
environment new_env = update(env, ext);
return new_env;
}
static environment pop_scope(environment const & env, io_state const &, scope_kind) {
aliases_ext ext = get_extension(env);
ext.pop();
return update(env, ext);
}
};
struct aliases_ext_reg {
unsigned m_ext_id;
aliases_ext_reg() {
register_scoped_ext(aliases_ext::push_scope, aliases_ext::pop_scope);
m_ext_id = environment::register_extension(std::make_shared<aliases_ext>());
}
};
static aliases_ext_reg * g_ext = nullptr;
static aliases_ext const & get_extension(environment const & env) {
return static_cast<aliases_ext const &>(env.get_extension(g_ext->m_ext_id));
}
static environment update(environment const & env, aliases_ext const & ext) {
return env.update(g_ext->m_ext_id, std::make_shared<aliases_ext>(ext));
}
environment add_expr_alias(environment const & env, name const & a, name const & e, bool overwrite) {
aliases_ext ext = get_extension(env);
ext.add_expr_alias(a, e, overwrite);
return update(env, ext);
}
environment add_expr_alias_rec(environment const & env, name const & a, name const & e, bool overwrite) {
aliases_ext ext = get_extension(env);
ext.add_expr_alias_rec(a, e, overwrite);
return update(env, ext);
}
optional<name> is_expr_aliased(environment const & env, name const & t) {
auto it = get_extension(env).m_state.m_inv_aliases.find(t);
return it ? optional<name>(*it) : optional<name>();
}
names get_expr_aliases(environment const & env, name const & n) {
return names(get_extension(env).m_state.m_aliases.find(n));
}
environment erase_expr_aliases(environment const & env, name const & n) {
aliases_ext ext = get_extension(env);
ext.m_state.m_aliases.erase(n);
return update(env, ext);
}
environment add_local_ref(environment const & env, name const & a, expr const & ref) {
aliases_ext ext = get_extension(env);
ext.add_local_ref(a, ref);
return update(env, ext);
}
optional<expr> get_local_ref(environment const & env, name const & n) {
aliases_ext const & ext = get_extension(env);
if (auto r = ext.m_state.m_local_refs.find(n))
return some_expr(*r);
else
return none_expr();
}
environment add_level_alias(environment const & env, name const & a, name const & l) {
aliases_ext ext = get_extension(env);
ext.add_level_alias(a, l);
return update(env, ext);
}
optional<name> is_level_aliased(environment const & env, name const & l) {
auto it = get_extension(env).m_state.m_inv_level_aliases.find(l);
return it ? optional<name>(*it) : optional<name>();
}
optional<name> get_level_alias(environment const & env, name const & n) {
auto it = get_extension(env).m_state.m_level_aliases.find(n);
return it ? optional<name>(*it) : optional<name>();
}
// Return true iff \c n is (prefix + ex) for some ex in exceptions
bool is_exception(name const & n, name const & prefix, unsigned num_exceptions, name const * exceptions) {
return std::any_of(exceptions, exceptions + num_exceptions, [&](name const & ex) { return (prefix + ex) == n; });
}
environment add_aliases(environment const & env, name const & prefix, name const & new_prefix,
unsigned num_exceptions, name const * exceptions, bool overwrite) {
aliases_ext ext = get_extension(env);
env.for_each_constant([&](constant_info const & info) {
if (is_prefix_of(prefix, info.get_name()) && !is_exception(info.get_name(), prefix, num_exceptions, exceptions)) {
name a = info.get_name().replace_prefix(prefix, new_prefix);
if (!(is_protected(env, info.get_name()) && a.is_atomic()) &&
!(a.is_anonymous()))
ext.add_expr_alias(a, info.get_name(), overwrite);
}
});
return update(env, ext);
}
void for_each_expr_alias(environment const & env, std::function<void(name const &, names const &)> const & fn) {
aliases_ext ext = get_extension(env);
ext.for_each_expr_alias(fn);
}
void initialize_aliases() {
g_ext = new aliases_ext_reg();
}
void finalize_aliases() {
delete g_ext;
}
}