/* 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 "util/name_map.h" #include "kernel/expr.h" namespace lean { /** \brief Auxiliary data-structure for storing the local context, and creating metavariables in the scope of the local context efficiently */ class local_context { list m_ctx; // current local context: a list of local constants typedef std::tuple local_decl; list m_ctx_abstracted; // m_ctx where elements have been abstracted static expr abstract_locals(expr const & e, list const & locals); // convert a local constant into a local_decl static local_decl to_local_decl(expr const & l, list const & ctx); public: local_context(); local_context(list const & ctx); void set_ctx(list const & ctx); /** \brief Given e[l_1, ..., l_n] and assuming \c m_ctx is [l_n : A_n[l_1, ..., l_{n-1}], ..., l_1 : A_1 ], then the result is (Pi (x_1 : A_1) ... (x_n : A_n[x_1, ..., x_{n-1}]), e[x_1, ... x_n]). */ expr pi_abstract_context(expr e, tag g) const; /** \brief Assuming \c m_ctx is [l_n : A_n[l_1, ..., l_{n-1}], ..., l_1 : A_1 ], return (f l_1 ... l_n). */ expr apply_context(expr const & f, tag g) const; /** \brief Assuming \c m_ctx is [l_n : A_n[l_1, ..., l_{n-1}], ..., l_1 : A_1 ], return a fresh metavariable \c ?m with type (Pi (x_1 : A_1) ... (x_n : A_n[x_1, ..., x_{n-1}]), Type.{?u}), where \c ?u is a fresh universe metavariable. */ expr mk_type_metavar(name_generator & ngen, tag g) const; /** \brief Assuming \c m_ctx is [l_n : A_n[l_1, ..., l_{n-1}], ..., l_1 : A_1 ], return (?m l_1 ... l_n) where \c ?m is a fresh metavariable with type (Pi (x_1 : A_1) ... (x_n : A_n[x_1, ..., x_{n-1}]), Type.{?u}), and \c ?u is a fresh universe metavariable. \remark The type of the resulting expression is Type.{?u} */ expr mk_type_meta(name_generator & ngen, tag g) const; /** \brief Given type[l_1, ..., l_n] and assuming \c m_ctx is [l_n : A_n[l_1, ..., l_{n-1}], ..., l_1 : A_1 ], then the result is a fresh metavariable \c ?m with type (Pi (x_1 : A_1) ... (x_n : A_n[x_1, ..., x_{n-1}]), type[x_1, ... x_n]). If type is none, then the result is a fresh metavariable \c ?m1 with type (Pi (x_1 : A_1) ... (x_n : A_n[x_1, ..., x_{n-1}]), ?m2 x1 .... xn), where ?m2 is another fresh metavariable with type (Pi (x_1 : A_1) ... (x_n : A_n[x_1, ..., x_{n-1}]), Type.{?u}), and \c ?u is a fresh universe metavariable. \remark If \c suffix is not none, then it is appended to the (fresh) metavariable name. */ expr mk_metavar(name_generator & ngen, optional const & suffix, optional const & type, tag g) const; /** \brief Given type[l_1, ..., l_n] and assuming \c m_ctx is [l_n : A_n[l_1, ..., l_{n-1}], ..., l_1 : A_1 ], return (?m l_1 ... l_n), where ?m is a fresh metavariable created using \c mk_metavar. \see mk_metavar \remark If \c suffix is not none, then it is appended to the (fresh) metavariable name. */ expr mk_meta(name_generator & ngen, optional const & suffix, optional const & type, tag g) const; expr mk_meta(name_generator & ngen, optional const & type, tag g) const { return mk_meta(ngen, optional(), type, g); } /** \brief Return context as a list */ list const & get_data() const; void add_local(expr const & l); /** \brief Instantiate metavariables occurring this local context using \c s, and return updated local_context */ local_context instantiate(substitution s) const; }; }