2013-07-29 05:34:39 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
2013-11-18 02:11:44 +00:00
|
|
|
#include <cstdlib>
|
2013-07-29 05:34:39 +00:00
|
|
|
#include <algorithm>
|
|
|
|
#include <vector>
|
2013-10-26 18:07:06 +00:00
|
|
|
#include <tuple>
|
2013-11-18 02:11:44 +00:00
|
|
|
#include <set>
|
2013-08-05 03:52:14 +00:00
|
|
|
#include <unordered_map>
|
2013-12-09 22:56:48 +00:00
|
|
|
#include "util/thread.h"
|
2013-09-13 03:04:10 +00:00
|
|
|
#include "util/safe_arith.h"
|
2013-11-18 17:52:47 +00:00
|
|
|
#include "util/realpath.h"
|
2013-11-19 19:24:02 +00:00
|
|
|
#include "kernel/for_each_fn.h"
|
2013-11-19 21:03:46 +00:00
|
|
|
#include "kernel/find_fn.h"
|
2013-09-13 03:04:10 +00:00
|
|
|
#include "kernel/kernel_exception.h"
|
|
|
|
#include "kernel/environment.h"
|
2013-11-12 04:29:53 +00:00
|
|
|
#include "kernel/threadsafe_environment.h"
|
2013-09-13 03:04:10 +00:00
|
|
|
#include "kernel/type_checker.h"
|
|
|
|
#include "kernel/normalizer.h"
|
2013-07-29 05:34:39 +00:00
|
|
|
|
|
|
|
namespace lean {
|
2013-11-18 02:11:44 +00:00
|
|
|
static name g_builtin_module("builtin_module");
|
2013-11-07 03:21:22 +00:00
|
|
|
class extension_factory {
|
|
|
|
std::vector<environment::mk_extension> m_makers;
|
2013-12-09 22:56:48 +00:00
|
|
|
mutex m_makers_mutex;
|
2013-11-07 03:21:22 +00:00
|
|
|
public:
|
|
|
|
unsigned register_extension(environment::mk_extension mk) {
|
2013-12-09 22:56:48 +00:00
|
|
|
lock_guard<mutex> lock(m_makers_mutex);
|
2013-11-07 03:21:22 +00:00
|
|
|
unsigned r = m_makers.size();
|
|
|
|
m_makers.push_back(mk);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<environment::extension> mk(unsigned extid) {
|
2013-12-09 22:56:48 +00:00
|
|
|
lock_guard<mutex> lock(m_makers_mutex);
|
2013-11-07 03:21:22 +00:00
|
|
|
return m_makers[extid]();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static std::unique_ptr<extension_factory> g_extension_factory;
|
|
|
|
static extension_factory & get_extension_factory() {
|
|
|
|
if (!g_extension_factory)
|
|
|
|
g_extension_factory.reset(new extension_factory());
|
|
|
|
return *g_extension_factory;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned environment::register_extension(mk_extension mk) {
|
|
|
|
return get_extension_factory().register_extension(mk);
|
|
|
|
}
|
|
|
|
|
2013-07-30 02:44:26 +00:00
|
|
|
/** \brief Implementation of the Lean environment. */
|
2013-07-29 05:34:39 +00:00
|
|
|
struct environment::imp {
|
2013-08-13 22:13:54 +00:00
|
|
|
// Remark: only named objects are stored in the dictionary.
|
2013-08-16 22:09:26 +00:00
|
|
|
typedef std::unordered_map<name, object, name_hash, name_eq> object_dictionary;
|
2013-08-05 22:17:58 +00:00
|
|
|
typedef std::tuple<level, level, int> constraint;
|
|
|
|
// Universe variable management
|
|
|
|
std::vector<constraint> m_constraints;
|
2013-08-05 03:52:14 +00:00
|
|
|
std::vector<level> m_uvars;
|
2013-08-05 22:17:58 +00:00
|
|
|
// Children environment management
|
2013-12-09 22:56:48 +00:00
|
|
|
atomic<unsigned> m_num_children;
|
2013-08-05 03:52:14 +00:00
|
|
|
std::shared_ptr<imp> m_parent;
|
2013-08-05 22:17:58 +00:00
|
|
|
// Object management
|
2013-08-16 22:09:26 +00:00
|
|
|
std::vector<object> m_objects;
|
2013-08-05 03:52:14 +00:00
|
|
|
object_dictionary m_object_dictionary;
|
2013-11-07 19:29:01 +00:00
|
|
|
std::unique_ptr<type_checker> m_type_checker;
|
2013-11-18 02:11:44 +00:00
|
|
|
std::set<name> m_imported_modules; // set of imported files and builtin modules
|
2013-08-14 02:12:23 +00:00
|
|
|
|
2013-11-07 03:21:22 +00:00
|
|
|
std::vector<std::unique_ptr<extension>> m_extensions;
|
|
|
|
friend class extension;
|
|
|
|
|
2013-11-12 04:29:53 +00:00
|
|
|
// This mutex is only used to implement threadsafe environment objects
|
|
|
|
// in the external APIs
|
|
|
|
shared_mutex m_mutex;
|
|
|
|
|
2013-11-07 19:29:01 +00:00
|
|
|
extension & get_extension_core(unsigned extid) {
|
2013-11-07 03:21:22 +00:00
|
|
|
if (extid >= m_extensions.size())
|
|
|
|
m_extensions.resize(extid+1);
|
|
|
|
if (!m_extensions[extid]) {
|
|
|
|
std::unique_ptr<extension> ext = get_extension_factory().mk(extid);
|
|
|
|
ext->m_extid = extid;
|
|
|
|
ext->m_env = this;
|
|
|
|
m_extensions[extid].swap(ext);
|
|
|
|
}
|
|
|
|
return *(m_extensions[extid].get());
|
|
|
|
}
|
|
|
|
|
2013-10-15 21:50:08 +00:00
|
|
|
unsigned get_max_weight(expr const & e) {
|
|
|
|
unsigned w = 0;
|
|
|
|
auto proc = [&](expr const & c, unsigned) {
|
|
|
|
if (is_constant(c)) {
|
2013-12-08 22:37:38 +00:00
|
|
|
optional<object> obj = get_object_core(const_name(c));
|
2013-10-15 21:50:08 +00:00
|
|
|
if (obj)
|
2013-12-08 22:37:38 +00:00
|
|
|
w = std::max(w, obj->get_weight());
|
2013-10-15 21:50:08 +00:00
|
|
|
}
|
2013-10-25 21:58:02 +00:00
|
|
|
return true;
|
2013-10-15 21:50:08 +00:00
|
|
|
};
|
|
|
|
for_each_fn<decltype(proc)> visitor(proc);
|
|
|
|
visitor(e);
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
2013-08-13 22:13:54 +00:00
|
|
|
/**
|
|
|
|
\brief Return true iff this environment has children.
|
|
|
|
|
|
|
|
\remark If an environment has children than it cannot be
|
|
|
|
updated. That is, it is read-only.
|
|
|
|
*/
|
2013-08-04 23:07:37 +00:00
|
|
|
bool has_children() const { return m_num_children > 0; }
|
|
|
|
void inc_children() { m_num_children++; }
|
|
|
|
void dec_children() { m_num_children--; }
|
|
|
|
|
2013-08-13 22:13:54 +00:00
|
|
|
/** \brief Return true iff this environment has a parent environment */
|
2013-08-04 23:07:37 +00:00
|
|
|
bool has_parent() const { return m_parent != nullptr; }
|
2013-07-29 05:34:39 +00:00
|
|
|
|
2013-08-16 22:09:26 +00:00
|
|
|
/** \brief Throw exception if environment or its ancestors already have an object with the given name. */
|
|
|
|
void check_name_core(name const & n, environment const & env) {
|
|
|
|
if (has_parent())
|
|
|
|
m_parent->check_name_core(n, env);
|
|
|
|
if (m_object_dictionary.find(n) != m_object_dictionary.end())
|
|
|
|
throw already_declared_exception(env, n);
|
|
|
|
}
|
|
|
|
|
|
|
|
void check_name(name const & n, environment const & env) {
|
|
|
|
if (has_children())
|
|
|
|
throw read_only_environment_exception(env);
|
|
|
|
check_name_core(n, env);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Store new named object inside internal data-structures */
|
|
|
|
void register_named_object(object const & new_obj) {
|
|
|
|
m_objects.push_back(new_obj);
|
|
|
|
m_object_dictionary.insert(std::make_pair(new_obj.get_name(), new_obj));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
\brief Return the object named \c n in the environment or its
|
|
|
|
ancestors. Return null object if there is no object with the
|
|
|
|
given name.
|
|
|
|
*/
|
2013-12-08 22:37:38 +00:00
|
|
|
optional<object> get_object_core(name const & n) const {
|
2013-08-16 22:09:26 +00:00
|
|
|
auto it = m_object_dictionary.find(n);
|
|
|
|
if (it == m_object_dictionary.end()) {
|
|
|
|
if (has_parent())
|
|
|
|
return m_parent->get_object_core(n);
|
|
|
|
else
|
2013-12-08 22:37:38 +00:00
|
|
|
return none_object();
|
2013-08-16 22:09:26 +00:00
|
|
|
} else {
|
2013-12-08 22:37:38 +00:00
|
|
|
return some_object(it->second);
|
2013-08-16 22:09:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-08 22:37:38 +00:00
|
|
|
object get_object(name const & n, environment const & env) const {
|
|
|
|
optional<object> obj = get_object_core(n);
|
2013-12-08 07:21:07 +00:00
|
|
|
if (obj) {
|
2013-12-08 22:37:38 +00:00
|
|
|
return *obj;
|
2013-12-08 07:21:07 +00:00
|
|
|
} else {
|
2013-08-16 22:09:26 +00:00
|
|
|
throw unknown_object_exception(env, n);
|
2013-12-08 07:21:07 +00:00
|
|
|
}
|
2013-08-16 22:09:26 +00:00
|
|
|
}
|
|
|
|
|
2013-08-13 22:13:54 +00:00
|
|
|
/**
|
|
|
|
\brief Return true if u >= v + k is implied by constraints
|
|
|
|
\pre is_uvar(u) && is_uvar(v)
|
|
|
|
*/
|
|
|
|
bool is_implied(level const & u, level const & v, int k) {
|
|
|
|
lean_assert(is_uvar(u) && is_uvar(v));
|
|
|
|
if (u == v)
|
2013-08-05 22:17:58 +00:00
|
|
|
return k <= 0;
|
|
|
|
else
|
|
|
|
return std::any_of(m_constraints.begin(), m_constraints.end(),
|
2013-08-13 22:13:54 +00:00
|
|
|
[&](constraint const & c) { return std::get<0>(c) == u && std::get<1>(c) == v && std::get<2>(c) >= k; });
|
2013-07-29 05:34:39 +00:00
|
|
|
}
|
|
|
|
|
2013-08-13 22:13:54 +00:00
|
|
|
/** \brief Return true iff l1 >= l2 + k by asserted universe constraints. */
|
2013-07-30 02:05:43 +00:00
|
|
|
bool is_ge(level const & l1, level const & l2, int k) {
|
2013-08-05 22:17:58 +00:00
|
|
|
if (l1 == l2)
|
2013-08-19 01:25:34 +00:00
|
|
|
return k <= 0;
|
2013-07-29 05:34:39 +00:00
|
|
|
switch (kind(l2)) {
|
|
|
|
case level_kind::UVar:
|
|
|
|
switch (kind(l1)) {
|
2013-08-05 22:17:58 +00:00
|
|
|
case level_kind::UVar: return is_implied(l1, l2, k);
|
|
|
|
case level_kind::Lift: return is_ge(lift_of(l1), l2, safe_sub(k, lift_offset(l1)));
|
2013-08-02 01:52:28 +00:00
|
|
|
case level_kind::Max: return std::any_of(max_begin_levels(l1), max_end_levels(l1), [&](level const & l) { return is_ge(l, l2, k); });
|
2013-07-29 05:34:39 +00:00
|
|
|
}
|
2013-08-05 22:17:58 +00:00
|
|
|
case level_kind::Lift: return is_ge(l1, lift_of(l2), safe_add(k, lift_offset(l2)));
|
2013-08-02 01:52:28 +00:00
|
|
|
case level_kind::Max: return std::all_of(max_begin_levels(l2), max_end_levels(l2), [&](level const & l) { return is_ge(l1, l, k); });
|
2013-07-29 05:34:39 +00:00
|
|
|
}
|
2013-11-11 17:19:38 +00:00
|
|
|
lean_unreachable(); // LCOV_EXCL_LINE
|
2013-07-29 05:34:39 +00:00
|
|
|
}
|
|
|
|
|
2013-08-13 22:13:54 +00:00
|
|
|
/** \brief Return true iff l1 >= l2 is implied by asserted universe constraints. */
|
2013-07-30 02:05:43 +00:00
|
|
|
bool is_ge(level const & l1, level const & l2) {
|
2013-08-05 00:47:54 +00:00
|
|
|
if (has_parent())
|
2013-08-04 23:07:37 +00:00
|
|
|
return m_parent->is_ge(l1, l2);
|
2013-08-05 00:47:54 +00:00
|
|
|
else
|
|
|
|
return is_ge(l1, l2, 0);
|
2013-07-29 05:34:39 +00:00
|
|
|
}
|
|
|
|
|
2013-08-13 22:13:54 +00:00
|
|
|
/** \brief Add a new universe variable */
|
2013-08-16 22:09:26 +00:00
|
|
|
level add_uvar(name const & n, environment const & env) {
|
|
|
|
check_name(n, env);
|
2013-08-05 22:17:58 +00:00
|
|
|
level r(n);
|
2013-07-29 05:34:39 +00:00
|
|
|
m_uvars.push_back(r);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2013-08-13 22:13:54 +00:00
|
|
|
/**
|
|
|
|
\brief Add basic constraint u >= v + d, and all basic
|
|
|
|
constraints implied by transitivity.
|
|
|
|
|
|
|
|
\pre is_uvar(u) && is_uvar(v)
|
|
|
|
*/
|
|
|
|
void add_constraint(level const & u, level const & v, int d) {
|
|
|
|
lean_assert(is_uvar(u) && is_uvar(v));
|
|
|
|
if (is_implied(u, v, d))
|
2013-08-05 22:17:58 +00:00
|
|
|
return; // redundant
|
|
|
|
buffer<constraint> to_add;
|
|
|
|
for (constraint const & c : m_constraints) {
|
2013-08-13 22:13:54 +00:00
|
|
|
if (std::get<0>(c) == v) {
|
2013-08-05 22:17:58 +00:00
|
|
|
level const & l3 = std::get<1>(c);
|
2013-08-13 22:13:54 +00:00
|
|
|
int u_l3_d = safe_add(d, std::get<2>(c));
|
|
|
|
if (!is_implied(u, l3, u_l3_d))
|
2013-11-10 19:09:04 +00:00
|
|
|
to_add.emplace_back(u, l3, u_l3_d);
|
2013-07-29 05:34:39 +00:00
|
|
|
}
|
|
|
|
}
|
2013-11-10 19:09:04 +00:00
|
|
|
m_constraints.emplace_back(u, v, d);
|
2013-09-13 23:14:24 +00:00
|
|
|
for (constraint const & c : to_add) {
|
2013-08-05 22:17:58 +00:00
|
|
|
m_constraints.push_back(c);
|
|
|
|
}
|
2013-07-29 05:34:39 +00:00
|
|
|
}
|
|
|
|
|
2013-08-13 22:13:54 +00:00
|
|
|
/**
|
|
|
|
\brief Add all basic constraints implied by n >= l + k
|
|
|
|
|
|
|
|
A basic constraint is a constraint of the form u >= v + k
|
|
|
|
where u and v are universe variables.
|
|
|
|
*/
|
2013-08-05 22:17:58 +00:00
|
|
|
void add_constraints(level const & n, level const & l, int k) {
|
|
|
|
lean_assert(is_uvar(n));
|
2013-07-29 05:34:39 +00:00
|
|
|
switch (kind(l)) {
|
2013-08-05 22:17:58 +00:00
|
|
|
case level_kind::UVar: add_constraint(n, l, k); return;
|
|
|
|
case level_kind::Lift: add_constraints(n, lift_of(l), safe_add(k, lift_offset(l))); return;
|
|
|
|
case level_kind::Max: std::for_each(max_begin_levels(l), max_end_levels(l), [&](level const & l1) { add_constraints(n, l1, k); }); return;
|
2013-07-29 05:34:39 +00:00
|
|
|
}
|
2013-11-11 17:19:38 +00:00
|
|
|
lean_unreachable(); // LCOV_EXCL_LINE
|
2013-07-29 05:34:39 +00:00
|
|
|
}
|
|
|
|
|
2013-08-13 22:13:54 +00:00
|
|
|
/** \brief Add a new universe variable with constraint n >= l */
|
2013-08-16 19:51:12 +00:00
|
|
|
level add_uvar(name const & n, level const & l, environment const & env) {
|
2013-08-04 23:07:37 +00:00
|
|
|
if (has_parent())
|
2013-08-16 19:51:12 +00:00
|
|
|
throw kernel_exception(env, "invalid universe declaration, universe variables can only be declared in top-level environments");
|
2013-08-04 23:07:37 +00:00
|
|
|
if (has_children())
|
2013-08-16 19:51:12 +00:00
|
|
|
throw read_only_environment_exception(env);
|
2013-08-16 22:09:26 +00:00
|
|
|
level r = add_uvar(n, env);
|
2013-08-05 22:17:58 +00:00
|
|
|
add_constraints(r, l, 0);
|
2013-08-16 22:09:26 +00:00
|
|
|
register_named_object(mk_uvar_decl(n, l));
|
2013-07-29 05:34:39 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2013-08-13 22:13:54 +00:00
|
|
|
/**
|
|
|
|
\brief Return the universe variable with given name. Throw an
|
|
|
|
exception if the environment and its ancestors do not
|
|
|
|
contain a universe variable named \c n.
|
|
|
|
*/
|
2013-08-16 19:51:12 +00:00
|
|
|
level get_uvar(name const & n, environment const & env) const {
|
2013-08-05 00:47:54 +00:00
|
|
|
if (has_parent()) {
|
2013-08-16 19:51:12 +00:00
|
|
|
return m_parent->get_uvar(n, env);
|
2013-08-05 00:47:54 +00:00
|
|
|
} else {
|
|
|
|
auto it = std::find_if(m_uvars.begin(), m_uvars.end(), [&](level const & l) { return uvar_name(l) == n; });
|
2013-08-16 19:51:12 +00:00
|
|
|
if (it == m_uvars.end())
|
|
|
|
throw unknown_universe_variable_exception(env, n);
|
|
|
|
else
|
2013-08-05 00:47:54 +00:00
|
|
|
return *it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-13 22:13:54 +00:00
|
|
|
/**
|
|
|
|
\brief Initialize the set of universe variables with bottom
|
|
|
|
*/
|
2013-07-29 05:34:39 +00:00
|
|
|
void init_uvars() {
|
2013-11-10 19:09:04 +00:00
|
|
|
m_uvars.emplace_back();
|
2013-07-29 05:34:39 +00:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:03:46 +00:00
|
|
|
/**
|
|
|
|
The kernel should *not* accept expressions containing cached types.
|
|
|
|
Reason: Cached types may introduce unsoundness.
|
|
|
|
For example, in the environment env, the constant x may have type T.
|
|
|
|
Now suppose we are trying to add a new definition D that contains x,
|
|
|
|
and x is associated with a cached type T'. The cached type may allow
|
|
|
|
us to accept a definition that is type incorrect with respect to env.
|
|
|
|
*/
|
2013-11-19 19:21:45 +00:00
|
|
|
void check_no_cached_type(expr const & e, environment const & env) {
|
2013-11-19 21:03:46 +00:00
|
|
|
if (find(e, [](expr const & a) { return is_constant(a) && const_type(a); }))
|
2013-11-19 19:21:45 +00:00
|
|
|
throw kernel_exception(env, "expression has a constant with a cached type, this is a bug in one of Lean tactics and/or solvers");
|
|
|
|
}
|
|
|
|
|
2013-08-13 22:13:54 +00:00
|
|
|
/**
|
|
|
|
\brief Throw an exception if \c t is not a type or type of \c
|
|
|
|
v is not convertible to \c t.
|
|
|
|
|
|
|
|
\remark env is the smart pointer of imp. We need it because
|
|
|
|
infer_universe and infer_type expect an environment instead of environment::imp.
|
|
|
|
*/
|
|
|
|
void check_type(name const & n, expr const & t, expr const & v, environment const & env) {
|
2013-11-07 19:29:01 +00:00
|
|
|
m_type_checker->check_type(t);
|
|
|
|
expr v_t = m_type_checker->infer_type(v);
|
|
|
|
if (!m_type_checker->is_convertible(v_t, t))
|
2013-08-16 19:51:12 +00:00
|
|
|
throw def_type_mismatch_exception(env, n, t, v, v_t);
|
2013-08-13 22:13:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Throw exception if it is not a valid new definition */
|
|
|
|
void check_new_definition(name const & n, expr const & t, expr const & v, environment const & env) {
|
2013-08-16 19:51:12 +00:00
|
|
|
check_name(n, env);
|
2013-08-13 22:13:54 +00:00
|
|
|
check_type(n, t, v, env);
|
2013-08-06 03:06:07 +00:00
|
|
|
}
|
|
|
|
|
2013-09-04 15:30:04 +00:00
|
|
|
/** \brief Add a new builtin value to this environment */
|
2013-09-04 15:53:00 +00:00
|
|
|
void add_builtin(expr const & v, environment const & env) {
|
|
|
|
if (!is_value(v))
|
|
|
|
throw invalid_builtin_value_declaration(env, v);
|
|
|
|
name const & n = to_value(v).get_name();
|
|
|
|
check_name(n, env);
|
|
|
|
name const & u = to_value(v).get_unicode_name();
|
|
|
|
check_name(u, env);
|
|
|
|
register_named_object(mk_builtin(v));
|
|
|
|
if (u != n) {
|
|
|
|
add_definition(u, to_value(v).get_type(), mk_constant(n), false, env);
|
|
|
|
}
|
2013-09-04 15:30:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Add a new builtin value set to this environment */
|
|
|
|
void add_builtin_set(expr const & r, environment const & env) {
|
|
|
|
if (!is_value(r))
|
|
|
|
throw invalid_builtin_value_declaration(env, r);
|
|
|
|
check_name(to_value(r).get_name(), env);
|
|
|
|
register_named_object(mk_builtin_set(r));
|
|
|
|
}
|
|
|
|
|
2013-08-13 22:13:54 +00:00
|
|
|
/** \brief Add new definition. */
|
|
|
|
void add_definition(name const & n, expr const & t, expr const & v, bool opaque, environment const & env) {
|
2013-11-19 19:21:45 +00:00
|
|
|
check_no_cached_type(t, env);
|
|
|
|
check_no_cached_type(v, env);
|
2013-08-13 22:13:54 +00:00
|
|
|
check_new_definition(n, t, v, env);
|
2013-10-15 21:50:08 +00:00
|
|
|
unsigned w = get_max_weight(v) + 1;
|
|
|
|
register_named_object(mk_definition(n, t, v, opaque, w));
|
2013-08-06 09:03:22 +00:00
|
|
|
}
|
|
|
|
|
2013-08-13 22:13:54 +00:00
|
|
|
/**
|
|
|
|
\brief Add new definition.
|
|
|
|
The type of the new definition is the type of \c v.
|
|
|
|
*/
|
|
|
|
void add_definition(name const & n, expr const & v, bool opaque, environment const & env) {
|
2013-11-19 19:21:45 +00:00
|
|
|
check_no_cached_type(v, env);
|
2013-08-16 19:51:12 +00:00
|
|
|
check_name(n, env);
|
2013-11-07 19:29:01 +00:00
|
|
|
expr v_t = m_type_checker->infer_type(v);
|
2013-10-15 21:50:08 +00:00
|
|
|
unsigned w = get_max_weight(v) + 1;
|
|
|
|
register_named_object(mk_definition(n, v_t, v, opaque, w));
|
2013-08-13 22:13:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Add new theorem. */
|
|
|
|
void add_theorem(name const & n, expr const & t, expr const & v, environment const & env) {
|
2013-11-19 19:21:45 +00:00
|
|
|
check_no_cached_type(t, env);
|
|
|
|
check_no_cached_type(v, env);
|
2013-08-13 22:13:54 +00:00
|
|
|
check_new_definition(n, t, v, env);
|
2013-08-16 22:09:26 +00:00
|
|
|
register_named_object(mk_theorem(n, t, v));
|
2013-08-13 22:13:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Add new axiom. */
|
|
|
|
void add_axiom(name const & n, expr const & t, environment const & env) {
|
2013-11-19 19:21:45 +00:00
|
|
|
check_no_cached_type(t, env);
|
2013-08-16 19:51:12 +00:00
|
|
|
check_name(n, env);
|
2013-11-07 19:29:01 +00:00
|
|
|
m_type_checker->check_type(t);
|
2013-08-16 22:09:26 +00:00
|
|
|
register_named_object(mk_axiom(n, t));
|
2013-08-06 03:06:07 +00:00
|
|
|
}
|
|
|
|
|
2013-08-13 22:13:54 +00:00
|
|
|
/** \brief Add new variable. */
|
|
|
|
void add_var(name const & n, expr const & t, environment const & env) {
|
2013-11-19 19:21:45 +00:00
|
|
|
check_no_cached_type(t, env);
|
2013-08-16 19:51:12 +00:00
|
|
|
check_name(n, env);
|
2013-11-07 19:29:01 +00:00
|
|
|
m_type_checker->check_type(t);
|
2013-08-16 22:09:26 +00:00
|
|
|
register_named_object(mk_var_decl(n, t));
|
2013-08-05 03:52:14 +00:00
|
|
|
}
|
|
|
|
|
2013-08-15 16:29:42 +00:00
|
|
|
unsigned get_num_objects(bool local) const {
|
|
|
|
if (local || !has_parent()) {
|
|
|
|
return m_objects.size();
|
|
|
|
} else {
|
|
|
|
return m_objects.size() + m_parent->get_num_objects(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object const & get_object(unsigned i, bool local) const {
|
|
|
|
if (local || !has_parent()) {
|
2013-08-16 22:09:26 +00:00
|
|
|
return m_objects[i];
|
2013-08-15 16:29:42 +00:00
|
|
|
} else {
|
|
|
|
unsigned num_parent_objects = m_parent->get_num_objects(false);
|
|
|
|
if (i >= num_parent_objects)
|
2013-08-16 22:09:26 +00:00
|
|
|
return m_objects[i - num_parent_objects];
|
2013-08-15 16:29:42 +00:00
|
|
|
else
|
|
|
|
return m_parent->get_object(i, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-01 23:59:15 +00:00
|
|
|
expr infer_type(expr const & e, context const & ctx) {
|
2013-11-07 19:29:01 +00:00
|
|
|
return m_type_checker->infer_type(e, ctx);
|
2013-09-01 23:59:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
expr normalize(expr const & e, context const & ctx) {
|
2013-11-07 19:29:01 +00:00
|
|
|
return m_type_checker->get_normalizer()(e, ctx);
|
2013-09-01 23:59:15 +00:00
|
|
|
}
|
|
|
|
|
2013-08-06 03:06:07 +00:00
|
|
|
/** \brief Display universal variable constraints and objects stored in this environment and its parents. */
|
2013-08-08 02:10:12 +00:00
|
|
|
void display(std::ostream & out, environment const & env) const {
|
2013-08-06 03:06:07 +00:00
|
|
|
if (has_parent())
|
2013-08-08 02:10:12 +00:00
|
|
|
m_parent->display(out, env);
|
2013-08-16 22:09:26 +00:00
|
|
|
for (object const & obj : m_objects) {
|
|
|
|
if (obj.has_name()) {
|
|
|
|
out << obj.keyword() << " " << obj.get_name() << "\n";
|
|
|
|
}
|
2013-08-15 15:52:10 +00:00
|
|
|
}
|
2013-08-06 03:06:07 +00:00
|
|
|
}
|
|
|
|
|
2013-11-18 02:11:44 +00:00
|
|
|
bool already_imported(name const & n) const {
|
|
|
|
if (m_imported_modules.find(n) != m_imported_modules.end())
|
|
|
|
return true;
|
|
|
|
else if (has_parent())
|
|
|
|
return m_parent->already_imported(n);
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool mark_imported_core(name n, environment const & env) {
|
|
|
|
if (already_imported(n)) {
|
|
|
|
return false;
|
|
|
|
} else if (has_children()) {
|
|
|
|
throw read_only_environment_exception(env);
|
|
|
|
} else {
|
|
|
|
m_imported_modules.insert(n);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool mark_imported(char const * fname, environment const & env) {
|
2013-11-18 17:52:47 +00:00
|
|
|
return mark_imported_core(name(realpath(fname)), env);
|
2013-11-18 02:11:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool mark_builtin_imported(char const * id, environment const & env) {
|
|
|
|
return mark_imported_core(name(g_builtin_module, id), env);
|
|
|
|
}
|
|
|
|
|
2013-11-07 19:29:01 +00:00
|
|
|
imp():
|
|
|
|
m_num_children(0) {
|
2013-07-29 05:34:39 +00:00
|
|
|
init_uvars();
|
|
|
|
}
|
2013-08-04 23:07:37 +00:00
|
|
|
|
2013-11-07 19:29:01 +00:00
|
|
|
imp(std::shared_ptr<imp> const & parent):
|
2013-08-04 23:07:37 +00:00
|
|
|
m_num_children(0),
|
2013-11-07 19:29:01 +00:00
|
|
|
m_parent(parent) {
|
2013-08-04 23:07:37 +00:00
|
|
|
m_parent->inc_children();
|
|
|
|
}
|
|
|
|
|
|
|
|
~imp() {
|
|
|
|
if (m_parent)
|
|
|
|
m_parent->dec_children();
|
|
|
|
}
|
2013-07-29 05:34:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
environment::environment():
|
2013-11-07 19:29:01 +00:00
|
|
|
m_ptr(new imp()) {
|
|
|
|
m_ptr->m_type_checker.reset(new type_checker(*this));
|
2013-08-04 23:07:37 +00:00
|
|
|
}
|
|
|
|
|
2013-08-24 23:11:35 +00:00
|
|
|
// used when creating a new child environment
|
2013-09-17 14:37:33 +00:00
|
|
|
environment::environment(std::shared_ptr<imp> const & parent, bool):
|
2013-11-07 19:29:01 +00:00
|
|
|
m_ptr(new imp(parent)) {
|
|
|
|
m_ptr->m_type_checker.reset(new type_checker(*this));
|
2013-08-04 23:07:37 +00:00
|
|
|
}
|
|
|
|
|
2013-08-24 23:11:35 +00:00
|
|
|
// used when creating a reference to the parent environment
|
2013-08-04 23:07:37 +00:00
|
|
|
environment::environment(std::shared_ptr<imp> const & ptr):
|
2013-09-17 21:42:44 +00:00
|
|
|
m_ptr(ptr) {
|
2013-07-29 05:34:39 +00:00
|
|
|
}
|
|
|
|
|
2013-11-17 02:35:17 +00:00
|
|
|
environment::environment(weak_ref const & r) {
|
|
|
|
if (r.expired())
|
|
|
|
throw exception("weak reference to environment object has expired (i.e., the environment has been deleted)");
|
|
|
|
m_ptr = r.lock();
|
|
|
|
}
|
|
|
|
|
2013-07-29 05:34:39 +00:00
|
|
|
environment::~environment() {
|
|
|
|
}
|
|
|
|
|
2013-08-04 23:07:37 +00:00
|
|
|
environment environment::mk_child() const {
|
2013-09-17 21:42:44 +00:00
|
|
|
return environment(m_ptr, true);
|
2013-08-04 23:07:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool environment::has_children() const {
|
2013-09-17 21:42:44 +00:00
|
|
|
return m_ptr->has_children();
|
2013-08-04 23:07:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool environment::has_parent() const {
|
2013-09-17 21:42:44 +00:00
|
|
|
return m_ptr->has_parent();
|
2013-08-04 23:07:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
environment environment::parent() const {
|
|
|
|
lean_assert(has_parent());
|
2013-09-17 21:42:44 +00:00
|
|
|
return environment(m_ptr->m_parent);
|
2013-08-04 23:07:37 +00:00
|
|
|
}
|
2013-08-09 22:33:34 +00:00
|
|
|
|
|
|
|
level environment::add_uvar(name const & n, level const & l) {
|
2013-09-17 21:42:44 +00:00
|
|
|
return m_ptr->add_uvar(n, l, *this);
|
2013-08-09 22:33:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool environment::is_ge(level const & l1, level const & l2) const {
|
2013-09-17 21:42:44 +00:00
|
|
|
return m_ptr->is_ge(l1, l2);
|
2013-08-09 22:33:34 +00:00
|
|
|
}
|
|
|
|
|
2013-08-05 00:47:54 +00:00
|
|
|
level environment::get_uvar(name const & n) const {
|
2013-09-17 21:42:44 +00:00
|
|
|
return m_ptr->get_uvar(n, *this);
|
2013-08-05 00:47:54 +00:00
|
|
|
}
|
|
|
|
|
2013-09-04 15:30:04 +00:00
|
|
|
void environment::add_builtin(expr const & v) {
|
2013-09-17 21:42:44 +00:00
|
|
|
return m_ptr->add_builtin(v, *this);
|
2013-09-04 15:30:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void environment::add_builtin_set(expr const & r) {
|
2013-09-17 21:42:44 +00:00
|
|
|
return m_ptr->add_builtin_set(r, *this);
|
2013-09-04 15:30:04 +00:00
|
|
|
}
|
|
|
|
|
2013-08-06 19:24:20 +00:00
|
|
|
void environment::add_definition(name const & n, expr const & t, expr const & v, bool opaque) {
|
2013-09-17 21:42:44 +00:00
|
|
|
m_ptr->add_definition(n, t, v, opaque, *this);
|
2013-08-05 03:52:14 +00:00
|
|
|
}
|
|
|
|
|
2013-08-06 19:24:20 +00:00
|
|
|
void environment::add_theorem(name const & n, expr const & t, expr const & v) {
|
2013-09-17 21:42:44 +00:00
|
|
|
m_ptr->add_theorem(n, t, v, *this);
|
2013-08-06 19:24:20 +00:00
|
|
|
}
|
|
|
|
|
2013-08-05 03:52:14 +00:00
|
|
|
void environment::add_definition(name const & n, expr const & v, bool opaque) {
|
2013-09-17 21:42:44 +00:00
|
|
|
m_ptr->add_definition(n, v, opaque, *this);
|
2013-08-05 03:52:14 +00:00
|
|
|
}
|
|
|
|
|
2013-08-06 03:06:07 +00:00
|
|
|
void environment::add_axiom(name const & n, expr const & t) {
|
2013-09-17 21:42:44 +00:00
|
|
|
m_ptr->add_axiom(n, t, *this);
|
2013-08-06 03:06:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void environment::add_var(name const & n, expr const & t) {
|
2013-09-17 21:42:44 +00:00
|
|
|
m_ptr->add_var(n, t, *this);
|
2013-08-05 03:52:14 +00:00
|
|
|
}
|
|
|
|
|
2013-08-16 22:09:26 +00:00
|
|
|
void environment::add_neutral_object(neutral_object_cell * o) {
|
2013-09-17 21:42:44 +00:00
|
|
|
m_ptr->m_objects.push_back(mk_neutral(o));
|
2013-08-15 01:16:11 +00:00
|
|
|
}
|
|
|
|
|
2013-12-08 22:37:38 +00:00
|
|
|
object environment::get_object(name const & n) const {
|
2013-09-17 21:42:44 +00:00
|
|
|
return m_ptr->get_object(n, *this);
|
2013-08-05 03:52:14 +00:00
|
|
|
}
|
|
|
|
|
2013-12-08 22:37:38 +00:00
|
|
|
optional<object> environment::find_object(name const & n) const {
|
2013-09-17 21:42:44 +00:00
|
|
|
return m_ptr->get_object_core(n);
|
2013-08-17 17:55:42 +00:00
|
|
|
}
|
|
|
|
|
2013-08-15 16:29:42 +00:00
|
|
|
unsigned environment::get_num_objects(bool local) const {
|
2013-09-17 21:42:44 +00:00
|
|
|
return m_ptr->get_num_objects(local);
|
2013-08-08 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2013-08-15 16:29:42 +00:00
|
|
|
object const & environment::get_object(unsigned i, bool local) const {
|
2013-09-17 21:42:44 +00:00
|
|
|
return m_ptr->get_object(i, local);
|
2013-08-08 23:12:46 +00:00
|
|
|
}
|
|
|
|
|
2013-11-12 04:29:53 +00:00
|
|
|
expr environment::infer_type(expr const & e, context const & ctx) const {
|
2013-09-17 21:42:44 +00:00
|
|
|
return m_ptr->infer_type(e, ctx);
|
2013-09-01 23:59:15 +00:00
|
|
|
}
|
|
|
|
|
2013-11-12 04:29:53 +00:00
|
|
|
expr environment::normalize(expr const & e, context const & ctx) const {
|
2013-09-17 21:42:44 +00:00
|
|
|
return m_ptr->normalize(e, ctx);
|
2013-09-01 23:59:15 +00:00
|
|
|
}
|
|
|
|
|
2013-08-06 03:06:07 +00:00
|
|
|
void environment::display(std::ostream & out) const {
|
2013-09-17 21:42:44 +00:00
|
|
|
m_ptr->display(out, *this);
|
2013-08-06 03:06:07 +00:00
|
|
|
}
|
2013-08-24 23:11:35 +00:00
|
|
|
|
2013-11-18 02:11:44 +00:00
|
|
|
bool environment::mark_imported(char const * fname) {
|
|
|
|
return m_ptr->mark_imported(fname, *this);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool environment::mark_builtin_imported(char const * id) {
|
|
|
|
return m_ptr->mark_builtin_imported(id, *this);
|
|
|
|
}
|
|
|
|
|
2013-11-07 19:29:01 +00:00
|
|
|
environment::extension const & environment::get_extension_core(unsigned extid) const {
|
|
|
|
return m_ptr->get_extension_core(extid);
|
|
|
|
}
|
|
|
|
|
|
|
|
environment::extension & environment::get_extension_core(unsigned extid) {
|
|
|
|
return m_ptr->get_extension_core(extid);
|
2013-11-07 03:21:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
environment::extension::extension():
|
|
|
|
m_env(nullptr),
|
|
|
|
m_extid(0) {
|
|
|
|
}
|
|
|
|
|
|
|
|
environment::extension::~extension() {
|
|
|
|
}
|
|
|
|
|
|
|
|
environment::extension const * environment::extension::get_parent_core() const {
|
|
|
|
if (m_env == nullptr)
|
|
|
|
return nullptr;
|
|
|
|
imp * parent = m_env->m_parent.get();
|
|
|
|
while (parent) {
|
|
|
|
if (m_extid < parent->m_extensions.size()) {
|
|
|
|
extension * ext = parent->m_extensions[m_extid].get();
|
|
|
|
if (ext)
|
|
|
|
return ext;
|
|
|
|
}
|
|
|
|
parent = parent->m_parent.get();
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
2013-11-12 04:29:53 +00:00
|
|
|
|
2013-12-12 19:19:09 +00:00
|
|
|
read_only_shared_environment::read_only_shared_environment(environment const & env):
|
2013-11-12 04:29:53 +00:00
|
|
|
m_env(env),
|
|
|
|
m_lock(m_env.m_ptr->m_mutex) {
|
|
|
|
}
|
2013-12-12 19:19:09 +00:00
|
|
|
read_only_shared_environment::~read_only_shared_environment() {}
|
2013-11-12 04:29:53 +00:00
|
|
|
|
2013-12-12 19:19:09 +00:00
|
|
|
read_write_shared_environment::read_write_shared_environment(environment const & env):
|
2013-11-12 04:29:53 +00:00
|
|
|
m_env(env),
|
|
|
|
m_lock(m_env.m_ptr->m_mutex) {
|
|
|
|
}
|
2013-12-12 19:19:09 +00:00
|
|
|
read_write_shared_environment::~read_write_shared_environment() {}
|
2013-07-29 05:34:39 +00:00
|
|
|
}
|