/* Copyright (c) 2014 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author: Leonardo de Moura */ #pragma once #include #include #include #include "util/list.h" #include "kernel/environment.h" namespace lean { class read_certified_inductive_decl_fn; namespace inductive { /** \brief Normalizer extension for applying inductive datatype computational rules. */ class inductive_normalizer_extension : public normalizer_extension { public: virtual optional operator()(expr const & e, abstract_type_context & ctx) const; virtual optional is_stuck(expr const & e, abstract_type_context & ctx) const; virtual bool supports(name const & feature) const; virtual bool is_recursor(environment const & env, name const & n) const; virtual bool is_builtin(environment const & env, name const & n) const; }; /** \brief Introduction rule */ typedef expr intro_rule; inline intro_rule mk_intro_rule(name const & n, expr const & t) { return mk_local(n, t); } inline name const & intro_rule_name(intro_rule const & r) { return mlocal_name(r); } inline expr const & intro_rule_type(intro_rule const & r) { return mlocal_type(r); } /** \brief Inductive datatype */ struct inductive_decl { name m_name; level_param_names m_level_params; unsigned m_num_params{0}; expr m_type; list m_intro_rules; inductive_decl() {} inductive_decl(name const & n, level_param_names const & ls, unsigned nparams, expr const & type, list const & intro_rules): m_name(n), m_level_params(ls), m_num_params(nparams), m_type(type), m_intro_rules(intro_rules) {} }; /** \brief Auxiliary class that stores the "compiled" version of an inductive declaration. It is used to save/read compiled .olean files efficiently. */ class certified_inductive_decl { public: struct comp_rule { unsigned m_num_bu; // sum of number of arguments u and v in the corresponding introduction rule. expr m_comp_rhs; // computational rule RHS: Fun (A, C, e, b, u), (e_k_i b u v) comp_rule(unsigned num_bu, expr const & rhs):m_num_bu(num_bu), m_comp_rhs(rhs) {} }; private: unsigned m_num_ACe; bool m_elim_prop; // remark: if m_elim_prop == true, then inductive datatype levels == m_levels, otherwise it is tail(m_levels) bool m_dep_elim; level_param_names m_elim_levels; // eliminator levels expr m_elim_type; inductive_decl m_decl; bool m_K_target; unsigned m_num_indices; list m_comp_rules; friend struct add_inductive_fn; friend class ::lean::read_certified_inductive_decl_fn; environment add_core(environment const & env, bool update_ext_only) const; environment add_constant(environment const & env, name const & n, level_param_names const & ls, expr const & t) const; certified_inductive_decl(unsigned num_ACe, bool elim_prop, bool dep_delim, level_param_names const & elim_levels, expr const & elim_type, inductive_decl const & decl, bool K_target, unsigned nindices, list const & crules): m_num_ACe(num_ACe), m_elim_prop(elim_prop), m_dep_elim(dep_delim), m_elim_levels(elim_levels), m_elim_type(elim_type), m_decl(decl), m_K_target(K_target), m_num_indices(nindices), m_comp_rules(crules) {} public: unsigned get_num_ACe() const { return m_num_ACe; } bool elim_prop_only() const { return m_elim_prop; } bool has_dep_elim() const { return m_dep_elim; } level_param_names const & get_elim_levels() const { return m_elim_levels; } expr const & get_elim_type() const { return m_elim_type; } inductive_decl const & get_decl() const { return m_decl; } bool is_K_target() const { return m_K_target; } unsigned get_num_indices() const { return m_num_indices; } list get_comp_rules() const { return m_comp_rules; } /** \brief Update the environment with this "certified declaration" \remark If trust_level is 0, then declaration is rechecked. */ environment add(environment const & env) const; }; /** \brief Declare a finite set of mutually dependent inductive datatypes. */ pair add_inductive(environment env, inductive_decl const & decl); /** \brief If \c n is the name of an inductive declaration in the environment \c env, then return the list of all inductive decls that were simultaneously defined with \c n. Return none otherwise */ optional is_inductive_decl(environment const & env, name const & n); /** \brief If \c n is the name of an introduction rule in \c env, then return the name of the inductive datatype D s.t. \c n is an introduction rule of D. Otherwise, return none. */ optional is_intro_rule(environment const & env, name const & n); /** \brief If \c n is the name of an elimination rule in \c env, then return the name of the inductive datatype D s.t. \c n is an elimination rule of D. Otherwise, return none. */ optional is_elim_rule(environment const & env, name const & n); /** \brief Given the eliminator \c n, this function return the position of major premise */ optional get_elim_major_idx(environment const & env, name const & n); bool is_elim_meta_app(type_checker & tc, expr const & e); /** \brief Return the number of parameters in the given inductive datatype. If \c n is not an inductive datatype in \c env, then return none. */ inline optional get_num_params(environment const & env, name const & n) { if (auto decl = is_inductive_decl(env, n)) return optional(decl->m_num_params); else return optional(); } /** \brief Return the number of indices in the given inductive datatype. If \c n is not an inductive datatype in \c env, then return none. */ optional get_num_indices(environment const & env, name const & n); /** \brief Return the number of minor premises in the given inductive datatype. If \c n is not an inductive datatype in \c env, then return none. */ optional get_num_minor_premises(environment const & env, name const & n); /** \brief Return the number of introduction rules in the given inductive datatype. If \c n is not an inductive datatype in \c env, then return none. */ optional get_num_intro_rules(environment const & env, name const & n); /** \brief Return true if the given datatype uses dependent elimination. */ bool has_dep_elim(environment const & env, name const & n); /** \brief Return the eliminator/recursor associated with an inductive datatype */ name get_elim_name(name const & n); } void initialize_inductive_module(); void finalize_inductive_module(); }