2013-07-29 05:34:39 +00:00
|
|
|
/*
|
2014-04-18 21:21:49 +00:00
|
|
|
Copyright (c) 2013-2014 Microsoft Corporation. All rights reserved.
|
2013-07-29 05:34:39 +00:00
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
|
|
|
#pragma once
|
2013-12-30 05:59:57 +00:00
|
|
|
#include <utility>
|
2014-04-18 21:21:49 +00:00
|
|
|
#include <memory>
|
2014-04-22 22:36:52 +00:00
|
|
|
#include <vector>
|
2014-04-18 21:21:49 +00:00
|
|
|
#include "util/rc.h"
|
|
|
|
#include "util/optional.h"
|
2014-04-21 21:28:50 +00:00
|
|
|
#include "util/list.h"
|
2014-04-18 21:21:49 +00:00
|
|
|
#include "util/rb_map.h"
|
2014-04-28 17:47:50 +00:00
|
|
|
#include "util/name_set.h"
|
2014-04-18 21:21:49 +00:00
|
|
|
#include "kernel/expr.h"
|
|
|
|
#include "kernel/constraint.h"
|
2014-05-20 17:41:36 +00:00
|
|
|
#include "kernel/declaration.h"
|
2013-07-29 05:34:39 +00:00
|
|
|
|
2014-05-21 17:56:26 +00:00
|
|
|
#ifndef LEAN_BELIEVER_TRUST_LEVEL
|
|
|
|
// If an environment E is created with a trust level > LEAN_BELIEVER_TRUST_LEVEL, then
|
|
|
|
// we can add declarations to E without type checking them.
|
|
|
|
#define LEAN_BELIEVER_TRUST_LEVEL 1024
|
|
|
|
#endif
|
|
|
|
|
2013-07-29 05:34:39 +00:00
|
|
|
namespace lean {
|
2013-12-13 00:33:31 +00:00
|
|
|
class type_checker;
|
2014-04-18 21:21:49 +00:00
|
|
|
class environment;
|
2014-05-20 17:41:36 +00:00
|
|
|
class certified_declaration;
|
2013-11-17 03:18:15 +00:00
|
|
|
|
2014-04-18 21:21:49 +00:00
|
|
|
/**
|
|
|
|
\brief The Lean kernel can be instantiated with different normalization extensions.
|
|
|
|
Each extension is part of the trusted code base. The extensions allow us to support
|
|
|
|
different flavors of the core type theory. We will use these extensions to implement
|
|
|
|
inductive datatype (ala Coq), HIT, record types, etc.
|
|
|
|
*/
|
|
|
|
class normalizer_extension {
|
2013-12-13 00:33:31 +00:00
|
|
|
public:
|
2014-04-28 17:58:14 +00:00
|
|
|
virtual ~normalizer_extension() {}
|
2014-04-28 21:01:44 +00:00
|
|
|
virtual optional<expr> operator()(expr const & e, extension_context & ctx) const = 0;
|
2014-07-04 05:31:05 +00:00
|
|
|
/** \brief Return true if the extension may reduce \c e after metavariables are instantiated. */
|
|
|
|
virtual bool may_reduce_later(expr const & e, extension_context & ctx) const = 0;
|
2014-04-18 21:21:49 +00:00
|
|
|
};
|
2013-08-05 03:52:14 +00:00
|
|
|
|
2014-04-18 21:21:49 +00:00
|
|
|
/**
|
|
|
|
\brief The header of an environment is created when we create the empty environment.
|
|
|
|
Moreover if environment B is an extension of environment A, then A and B share the same header.
|
|
|
|
*/
|
|
|
|
class environment_header {
|
2014-04-21 20:38:39 +00:00
|
|
|
/* In the following field, 0 means untrusted mode (i.e., check everything),
|
2014-05-21 17:56:26 +00:00
|
|
|
higher level allow us to trust the implementation of macros, and even
|
|
|
|
allow us to add declarations without type checking them (e.g., m_trust_lvl > LEAN_BELIEVER_TRUST_LEVEL)
|
2014-04-21 20:38:39 +00:00
|
|
|
*/
|
2014-05-21 17:56:26 +00:00
|
|
|
unsigned m_trust_lvl;
|
2014-07-22 16:43:18 +00:00
|
|
|
bool m_prop_proof_irrel; //!< true if the kernel assumes proof irrelevance for Prop (aka Type.{0})
|
2014-05-16 22:04:34 +00:00
|
|
|
bool m_eta; //!< true if the kernel uses eta-reduction in convertability checks
|
2014-07-22 16:43:18 +00:00
|
|
|
bool m_impredicative; //!< true if the kernel should treat (universe level 0) as a impredicative Prop.
|
2014-05-16 22:04:34 +00:00
|
|
|
list<name> m_cls_proof_irrel; //!< list of proof irrelevant classes, if we want Id types to be proof irrelevant, we the name 'Id' in this list.
|
2014-04-18 21:21:49 +00:00
|
|
|
std::unique_ptr<normalizer_extension const> m_norm_ext;
|
|
|
|
void dealloc();
|
|
|
|
public:
|
2014-05-16 22:04:34 +00:00
|
|
|
environment_header(unsigned trust_lvl, bool prop_proof_irrel, bool eta, bool impredicative,
|
|
|
|
list<name> const & cls_proof_irrel, std::unique_ptr<normalizer_extension const> ext);
|
2014-04-21 20:38:39 +00:00
|
|
|
unsigned trust_lvl() const { return m_trust_lvl; }
|
2014-05-16 22:04:34 +00:00
|
|
|
bool prop_proof_irrel() const { return m_prop_proof_irrel; }
|
2014-04-18 21:21:49 +00:00
|
|
|
bool eta() const { return m_eta; }
|
2014-05-05 21:08:36 +00:00
|
|
|
bool impredicative() const { return m_impredicative; }
|
2014-05-16 22:04:34 +00:00
|
|
|
list<name> const & cls_proof_irrel() const { return m_cls_proof_irrel; }
|
2014-04-18 21:21:49 +00:00
|
|
|
normalizer_extension const & norm_ext() const { return *(m_norm_ext.get()); }
|
|
|
|
};
|
2013-08-15 01:16:11 +00:00
|
|
|
|
2014-04-18 21:21:49 +00:00
|
|
|
class environment_extension {
|
|
|
|
public:
|
|
|
|
virtual ~environment_extension();
|
|
|
|
};
|
2013-08-06 03:06:07 +00:00
|
|
|
|
2014-04-18 21:21:49 +00:00
|
|
|
typedef std::vector<std::shared_ptr<environment_extension const>> environment_extensions;
|
2013-08-17 17:55:42 +00:00
|
|
|
|
2014-05-28 05:25:54 +00:00
|
|
|
/** \brief environment identifier for tracking descendants of a given environment. */
|
2014-04-21 21:28:50 +00:00
|
|
|
class environment_id {
|
2014-05-28 05:25:54 +00:00
|
|
|
friend class environment_id_tester;
|
2014-04-21 21:28:50 +00:00
|
|
|
friend class environment; // Only the environment class can create object of this type.
|
2014-05-28 05:25:54 +00:00
|
|
|
struct path;
|
|
|
|
path * m_ptr;
|
|
|
|
unsigned m_depth;
|
2014-04-21 21:28:50 +00:00
|
|
|
/**
|
|
|
|
\brief Create an identifier for an environment that is a direct descendant of the given one.
|
|
|
|
The bool field is just to make sure this constructor is not confused with a copy constructor
|
|
|
|
*/
|
|
|
|
environment_id(environment_id const & ancestor, bool);
|
|
|
|
/** \brief Create an identifier for an environment without ancestors (e.g., empty environment) */
|
|
|
|
environment_id();
|
|
|
|
/** Create an identifier for an environment that is a direct descendant of the given one. */
|
|
|
|
static environment_id mk_descendant(environment_id const & ancestor) { return environment_id(ancestor, true); }
|
|
|
|
public:
|
2014-05-28 05:25:54 +00:00
|
|
|
environment_id(environment_id const & id);
|
|
|
|
environment_id(environment_id && id);
|
|
|
|
~environment_id();
|
|
|
|
environment_id & operator=(environment_id const & s);
|
|
|
|
environment_id & operator=(environment_id && s);
|
|
|
|
|
2014-04-21 21:28:50 +00:00
|
|
|
/** \brief Return true iff this object is a descendant of the given one. */
|
|
|
|
bool is_descendant(environment_id const & id) const;
|
|
|
|
};
|
|
|
|
|
2014-04-18 21:21:49 +00:00
|
|
|
/**
|
|
|
|
\brief Lean core environment. An environment object can be extended/customized in different ways:
|
2013-08-15 01:16:11 +00:00
|
|
|
|
2014-04-18 21:21:49 +00:00
|
|
|
1- By providing a normalizer_extension when creating an empty environment.
|
|
|
|
2- By setting the proof_irrel and eta flags when creating an empty environment.
|
|
|
|
3- By attaching additional data as environment::extensions. The additional data can be added
|
|
|
|
at any time. They contain information used by the automation (e.g., rewriting sets, unification hints, etc).
|
|
|
|
*/
|
|
|
|
class environment {
|
|
|
|
typedef std::shared_ptr<environment_header const> header;
|
2014-05-20 17:41:36 +00:00
|
|
|
typedef rb_map<name, declaration, name_quick_cmp> declarations;
|
2014-04-18 21:21:49 +00:00
|
|
|
typedef std::shared_ptr<environment_extensions const> extensions;
|
2013-12-22 19:51:38 +00:00
|
|
|
|
2014-04-21 21:28:50 +00:00
|
|
|
header m_header;
|
|
|
|
environment_id m_id;
|
2014-05-20 17:41:36 +00:00
|
|
|
declarations m_declarations;
|
2014-05-07 23:07:31 +00:00
|
|
|
name_set m_global_levels;
|
2014-04-21 21:28:50 +00:00
|
|
|
extensions m_extensions;
|
2013-09-01 23:59:15 +00:00
|
|
|
|
2014-05-20 17:41:36 +00:00
|
|
|
environment(header const & h, environment_id const & id, declarations const & d, name_set const & global_levels, extensions const & ext);
|
2013-09-01 23:59:15 +00:00
|
|
|
|
2014-04-18 21:21:49 +00:00
|
|
|
public:
|
2014-05-16 22:04:34 +00:00
|
|
|
environment(unsigned trust_lvl = 0, bool prop_proof_irrel = true, bool eta = true, bool impredicative = true,
|
|
|
|
list<name> const & cls_proof_irrel = list<name>());
|
|
|
|
environment(unsigned trust_lvl, bool prop_proof_irrel, bool eta, bool impredicative, list<name> const & cls_proof_irrel,
|
|
|
|
std::unique_ptr<normalizer_extension> ext);
|
2014-04-18 21:21:49 +00:00
|
|
|
~environment();
|
2014-01-15 19:02:47 +00:00
|
|
|
|
2014-04-21 21:28:50 +00:00
|
|
|
/** \brief Return the environment unique identifier. */
|
|
|
|
environment_id const & get_id() const { return m_id; }
|
|
|
|
|
|
|
|
/** \brief Return true iff this environment is a descendant of \c env. */
|
|
|
|
bool is_descendant(environment const & env) const { return m_id.is_descendant(env.m_id); }
|
2013-11-13 22:26:01 +00:00
|
|
|
|
2014-04-21 20:38:39 +00:00
|
|
|
/** \brief Return the trust level of this environment. */
|
|
|
|
unsigned trust_lvl() const { return m_header->trust_lvl(); }
|
|
|
|
|
2014-07-22 16:43:18 +00:00
|
|
|
/** \brief Return true iff the environment assumes proof irrelevance for Type.{0} (i.e., Prop) */
|
2014-05-16 22:04:34 +00:00
|
|
|
bool prop_proof_irrel() const { return m_header->prop_proof_irrel(); }
|
|
|
|
|
|
|
|
/** \brief Return the list of classes marked as proof irrelevant */
|
|
|
|
list<name> const & cls_proof_irrel() const { return m_header->cls_proof_irrel(); }
|
2013-08-08 23:12:46 +00:00
|
|
|
|
2014-04-18 21:21:49 +00:00
|
|
|
/** \brief Return true iff the environment assumes Eta-reduction */
|
|
|
|
bool eta() const { return m_header->eta(); }
|
2013-08-15 16:29:42 +00:00
|
|
|
|
2014-07-22 16:43:18 +00:00
|
|
|
/** \brief Return true iff the environment treats universe level 0 as an impredicative Prop */
|
2014-05-05 21:08:36 +00:00
|
|
|
bool impredicative() const { return m_header->impredicative(); }
|
|
|
|
|
2014-04-18 21:21:49 +00:00
|
|
|
/** \brief Return reference to the normalizer extension associatied with this environment. */
|
|
|
|
normalizer_extension const & norm_ext() const { return m_header->norm_ext(); }
|
2013-08-15 16:29:42 +00:00
|
|
|
|
2014-05-20 17:41:36 +00:00
|
|
|
/** \brief Return declaration with name \c n (if it is defined in this environment). */
|
|
|
|
optional<declaration> find(name const & n) const;
|
2013-08-15 16:29:42 +00:00
|
|
|
|
2014-05-20 17:41:36 +00:00
|
|
|
/** \brief Return declaration with name \c n. Throws and exception if declaration does not exist in this environment. */
|
|
|
|
declaration get(name const & n) const;
|
2013-08-15 16:29:42 +00:00
|
|
|
|
2014-05-07 23:07:31 +00:00
|
|
|
/**
|
|
|
|
\brief Add a new global universe level with name \c n
|
|
|
|
This method throws an exception if the environment already contains a level named \c n.
|
|
|
|
*/
|
2014-06-13 15:26:05 +00:00
|
|
|
environment add_universe(name const & n) const;
|
2014-05-07 23:07:31 +00:00
|
|
|
|
|
|
|
/** \brief Return true iff the environment has a universe level named \c n. */
|
2014-06-13 15:26:05 +00:00
|
|
|
bool is_universe(name const & n) const;
|
2014-05-07 23:07:31 +00:00
|
|
|
|
2013-08-15 16:29:42 +00:00
|
|
|
/**
|
2014-05-20 17:41:36 +00:00
|
|
|
\brief Extends the current environment with the given (certified) declaration
|
2014-04-18 21:21:49 +00:00
|
|
|
This method throws an exception if:
|
2014-05-20 17:41:36 +00:00
|
|
|
- The declaration was certified in an environment which is not an ancestor of this one.
|
|
|
|
- The environment already contains a declaration with the given name.
|
2013-08-15 16:29:42 +00:00
|
|
|
*/
|
2014-05-20 17:41:36 +00:00
|
|
|
environment add(certified_declaration const & d) const;
|
2013-08-08 23:12:46 +00:00
|
|
|
|
2014-05-21 17:56:26 +00:00
|
|
|
/**
|
|
|
|
\brief Adds a declaration that was not type checked. This method throws an excetion if
|
|
|
|
trust_lvl() <= LEAN_BELIEVER_TRUST_LEVEL.
|
|
|
|
It is mainly when importing pre-compiled .olean files, and trust_lvl() > LEAN_BELIEVER_TRUST_LEVEL.
|
|
|
|
|
|
|
|
\remark If trust_lvl() == 0, then this method will always throw an exception. No matter what is
|
|
|
|
the value of LEAN_BELIEVER_TRUST_LEVEL used to compile Lean.
|
|
|
|
*/
|
|
|
|
environment add(declaration const & d) const;
|
|
|
|
|
2013-08-15 16:29:42 +00:00
|
|
|
/**
|
2014-05-20 17:41:36 +00:00
|
|
|
\brief Replace the axiom with name <tt>t.get_declaration().get_name()</tt> with the theorem t.get_declaration().
|
2014-04-18 21:21:49 +00:00
|
|
|
This method throws an exception if:
|
|
|
|
- The theorem was certified in an environment which is not an ancestor of this one.
|
2014-05-20 17:41:36 +00:00
|
|
|
- The environment does not contain an axiom named <tt>t.get_declaration().get_name()</tt>
|
2013-08-15 16:29:42 +00:00
|
|
|
*/
|
2014-05-20 17:41:36 +00:00
|
|
|
environment replace(certified_declaration const & t) const;
|
2013-08-08 23:12:46 +00:00
|
|
|
|
2013-11-07 03:21:22 +00:00
|
|
|
/**
|
|
|
|
\brief Register an environment extension. Every environment
|
2014-04-18 21:21:49 +00:00
|
|
|
object may contain this extension. The argument \c initial is
|
|
|
|
the initial value for the new extensions. The extension object
|
|
|
|
can be retrieved using the given token (unsigned integer) returned
|
|
|
|
by this method.
|
2013-11-07 03:21:22 +00:00
|
|
|
|
|
|
|
\remark The extension objects are created on demand.
|
|
|
|
|
|
|
|
\see get_extension
|
|
|
|
*/
|
2014-04-18 21:21:49 +00:00
|
|
|
static unsigned register_extension(std::shared_ptr<environment_extension const> const & initial);
|
2013-11-07 03:21:22 +00:00
|
|
|
|
2014-04-18 21:21:49 +00:00
|
|
|
/** \brief Return the extension with the given id. */
|
|
|
|
environment_extension const & get_extension(unsigned extid) const;
|
2013-11-07 19:29:01 +00:00
|
|
|
|
2014-04-18 21:21:49 +00:00
|
|
|
/** \brief Update the environment extension with the given id. */
|
|
|
|
environment update(unsigned extid, std::shared_ptr<environment_extension const> const & ext) const;
|
2014-05-13 15:40:46 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
\brief Return a new environment, where its "history" has been truncated/forgotten.
|
|
|
|
That is, <tt>is_descendant(e)</tt> will return false for any environment \c e that
|
|
|
|
is not pointer equal to the result.
|
|
|
|
*/
|
|
|
|
environment forget() const;
|
2014-05-20 17:15:28 +00:00
|
|
|
|
2014-05-20 17:41:36 +00:00
|
|
|
/** \brief Apply the function \c f to each declaration */
|
2014-06-13 15:26:05 +00:00
|
|
|
void for_each_declaration(std::function<void(declaration const & d)> const & f) const;
|
|
|
|
|
|
|
|
/** \brief Apply the function \c f to each universe */
|
|
|
|
void for_each_universe(std::function<void(name const & u)> const & f) const;
|
2013-12-13 00:33:31 +00:00
|
|
|
};
|
|
|
|
|
2014-04-28 17:47:50 +00:00
|
|
|
class name_generator;
|
|
|
|
|
2013-12-13 00:33:31 +00:00
|
|
|
/**
|
2014-05-20 17:41:36 +00:00
|
|
|
\brief A certified declaration is one that has been type checked.
|
|
|
|
Only the type_checker class can create certified declarations.
|
2013-12-13 00:33:31 +00:00
|
|
|
*/
|
2014-05-20 17:41:36 +00:00
|
|
|
class certified_declaration {
|
|
|
|
friend certified_declaration check(environment const & env, declaration const & d, name_generator const & g, name_set const & extra_opaque, bool memoize);
|
2014-04-21 21:28:50 +00:00
|
|
|
environment_id m_id;
|
2014-05-20 17:41:36 +00:00
|
|
|
declaration m_declaration;
|
|
|
|
certified_declaration(environment_id const & id, declaration const & d):m_id(id), m_declaration(d) {}
|
2013-12-13 00:33:31 +00:00
|
|
|
public:
|
2014-05-20 17:41:36 +00:00
|
|
|
/** \brief Return the id of the environment that was used to type check this declaration. */
|
2014-04-21 21:28:50 +00:00
|
|
|
environment_id const & get_id() const { return m_id; }
|
2014-05-20 17:41:36 +00:00
|
|
|
declaration const & get_declaration() const { return m_declaration; }
|
2013-12-13 00:33:31 +00:00
|
|
|
};
|
2013-07-29 05:34:39 +00:00
|
|
|
}
|