diff --git a/src/kernel/converter.cpp b/src/kernel/converter.cpp index 105cca3e1..fbb234f18 100644 --- a/src/kernel/converter.cpp +++ b/src/kernel/converter.cpp @@ -13,6 +13,35 @@ Author: Leonardo de Moura #include "kernel/type_checker.h" namespace lean { +/** + \brief Predicate for deciding whether \c d is an opaque definition or not. + + Here is the basic idea: + + 1) Each definition has an opaque flag. This flag cannot be modified after a definition is added to the environment. + The opaque flag affects the convertability check. The idea is to minimize the number of delta-reduction steps. + We also believe it increases the modularity of Lean developments by minimizing the dependency on how things are defined. + We should view non-opaque definitions as "inline definitions" used in programming languages such as C++. + + 2) Whenever type checking an expression, the user can provide an additional set of definition names (m_extra_opaque) that + should be considered opaque. Note that, if \c t type checks when using an extra_opaque set S, then t also type checks + (modulo resource constraints) with the empty set. Again, the purpose of extra_opaque is to mimimize the number + of delta-reduction steps. + + 3) To be able to prove theorems about an opaque definition, we treat an opaque definition D in a module M as + transparent when we are type checking another definition/theorem D' also in M. This rule only applies if + D is not a theorem, nor D is in the set m_extra_opaque. To implement this feature, this class has a field + m_module_idx that is not none when this rule should be applied. +*/ +bool is_opaque(declaration const & d, name_set const & extra_opaque, optional const & mod_idx) { + lean_assert(d.is_definition()); + if (d.is_theorem()) return true; // theorems are always opaque + if (extra_opaque.contains(d.get_name())) return true; // extra_opaque set overrides opaque flag + if (!d.is_opaque()) return false; // d is a transparent definition + if (mod_idx && d.get_module_idx() == *mod_idx) return false; // the opaque definitions in mod_idx are considered transparent + return true; // d is opaque +} + static no_delayed_justification g_no_delayed_jst; bool converter::is_def_eq(expr const & t, expr const & s, type_checker & c) { return is_def_eq(t, s, c, g_no_delayed_jst); @@ -138,33 +167,8 @@ struct default_converter : public converter { return r; } - /** - \brief Predicate for deciding whether \c d is an opaque definition or not. - - Here is the basic idea: - - 1) Each definition has an opaque flag. This flag cannot be modified after a definition is added to the environment. - The opaque flag affects the convertability check. The idea is to minimize the number of delta-reduction steps. - We also believe it increases the modularity of Lean developments by minimizing the dependency on how things are defined. - We should view non-opaque definitions as "inline definitions" used in programming languages such as C++. - - 2) Whenever type checking an expression, the user can provide an additional set of definition names (m_extra_opaque) that - should be considered opaque. Note that, if \c t type checks when using an extra_opaque set S, then t also type checks - (modulo resource constraints) with the empty set. Again, the purpose of extra_opaque is to mimimize the number - of delta-reduction steps. - - 3) To be able to prove theorems about an opaque definition, we treat an opaque definition D in a module M as - transparent when we are type checking another definition/theorem D' also in M. This rule only applies if - D is not a theorem, nor D is in the set m_extra_opaque. To implement this feature, this class has a field - m_module_idx that is not none when this rule should be applied. - */ bool is_opaque(declaration const & d) const { - lean_assert(d.is_definition()); - if (d.is_theorem()) return true; // theorems are always opaque - if (m_extra_opaque.contains(d.get_name())) return true; // extra_opaque set overrides opaque flag - if (!d.is_opaque()) return false; // d is a transparent definition - if (m_module_idx && d.get_module_idx() == *m_module_idx) return false; // the opaque definitions in module_idx are considered transparent - return true; // d is opaque + return ::lean::is_opaque(d, m_extra_opaque, m_module_idx); } /** \brief Expand \c e if it is non-opaque constant with weight >= w */ diff --git a/src/kernel/converter.h b/src/kernel/converter.h index cd2dabe27..466e90f53 100644 --- a/src/kernel/converter.h +++ b/src/kernel/converter.h @@ -30,4 +30,6 @@ std::unique_ptr mk_default_converter(environment const & env, name_set const & extra_opaque = name_set()); std::unique_ptr mk_default_converter(environment const & env, bool unfold_opaque_main, bool memoize = true, name_set const & extra_opaque = name_set()); + +bool is_opaque(declaration const & d, name_set const & extra_opaque, optional const & mod_idx); }