/* Copyright (c) 2016 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author: Leonardo de Moura */ #pragma once #include "kernel/expr.h" #include "library/deep_copy.h" #include "library/equations_compiler/equations.h" #include "frontends/lean/decl_attributes.h" namespace lean { class parser; class elaborator; enum def_cmd_kind { Theorem, Definition, Example }; struct decl_modifiers { bool m_is_private{false}; bool m_is_protected{false}; bool m_is_meta{false}; bool m_is_mutual{false}; bool m_is_noncomputable{false}; bool m_is_instance{false}; bool m_is_class{false}; }; /** \brief In Lean, declarations may contain nested definitions. This object is used to propagate relevant flags to nested definitions. */ class declaration_info_scope { declaration_info_scope(name const & ns, def_cmd_kind kind, decl_modifiers const & modifiers); public: declaration_info_scope(parser const & p, def_cmd_kind kind, decl_modifiers const & modifiers); ~declaration_info_scope(); bool gen_aux_lemmas() const; }; /** \brief Similar to declaration_info_scope, but it is used to update naming prefix for nested definitions. */ class declaration_name_scope { name m_name; name m_old_prefix; unsigned m_old_next_match_idx; public: declaration_name_scope(name const & n); declaration_name_scope(); ~declaration_name_scope(); void set_name(name const & n); name const & get_name() const { return m_name; } }; /** \brief Auxiliary scope to compute the name for a nested match expression. In Lean, we create auxiliary declarations for match expressions. */ class match_definition_scope { name m_name; public: match_definition_scope(); name const & get_name() const { return m_name; } }; /** \brief Return true if the current scope used match-expressions */ bool used_match_idx(); /** \brief Parse explict universe parameters of the form: {u_1 ... u_k} The universe parameters are automatically added to the parser scope. */ bool parse_univ_params(parser & p, buffer & lp_names); /** \brief Parse a declaration header of the form {u_1 ... u_k} id (params) : type The result is the local constant (c : type). The explicit universe level parameters are stored at lp_names, and the optional parameters at params. Both lp_names and params are added to the parser scope. \remark Caller is responsible for using: parser::local_scope scope2(p, env); */ expr parse_single_header(parser & p, declaration_name_scope & s, buffer & lp_names, buffer & params, bool is_example = false, bool is_instance = false, bool allow_default = false); /** \brief Parse the header of a mutually recursive declaration. It has the form {u_1 ... u_k} id_1, ... id_n (params) The explicit universe parameters are stored at lp_names, The constant names id_i are stored at cs. The names are local constants. Position information for a constant cs[i] can be retrieved using p.pos_of(cs[i]). Both lp_names, params and cs are added to the parser scope. \remark Caller is responsible for adding expressions encoding the c_names to the parser scope. \remark Caller is responsible for using: parser::local_scope scope2(p, env); */ void parse_mutual_header(parser & p, buffer & lp_names, buffer & cs, buffer & params, bool allow_default = false); /** \brief Parse the header for one of the declarations in a mutually recursive declaration. It has the form with id : type The result is (type, attrs). */ pair parse_inner_header(parser & p, name const & c_expected); /** \brief Add section/namespace parameters (and universes) used by params and all_exprs. We also add parameters included using the command 'include'. lp_names and params are input/output. */ void collect_implicit_locals(parser & p, buffer & lp_names, buffer & params, buffer const & all_exprs); void collect_implicit_locals(parser & p, buffer & lp_names, buffer & params, std::initializer_list const & all_exprs); void collect_implicit_locals(parser & p, buffer & lp_names, buffer & params, expr const & e); /** \brief Elaborate the types of the parameters \c params, and update the elaborator local context using them. Store the elaborated parameters at new_params. \post params.size() == new_params.size() */ void elaborate_params(elaborator & elab, buffer const & params, buffer & new_params); /** \brief Create an alias c_name --> (c_real_name.{level_params} params) level_params and params are subsets of lp_names and var_params that were declared using the parameter command. */ environment add_local_ref(parser & p, environment const & env, name const & c_name, name const & c_real_name, buffer const & lp_names, buffer const & var_params); /** \brief Add alias for new declaration. */ environment add_alias(environment const & env, bool is_protected, name const & c_name, name const & c_real_name); /** \brief Create an equations header for the given function names. It uses the information set using declaration_info_scope */ equations_header mk_equations_header(list const & fn_names); equations_header mk_equations_header(name const & fn_name); expr replace_locals_preserving_pos_info(expr const & e, buffer const & from, buffer const & to); expr replace_local_preserving_pos_info(expr const & e, expr const & from, expr const & to); }