/* Copyright (c) 2018 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_generator.h" #include "util/rb_map.h" #include "util/name_map.h" #include "kernel/expr.h" namespace lean { /* TODO(Leo): implement using runtime objects */ class local_decl { public: struct cell { /* : := m_user_name is used for interacting with the user, and it may not be not unique. */ name m_name; /* this one is unique */ name m_user_name; expr m_type; optional m_value; binder_info m_bi; unsigned m_idx; MK_LEAN_RC(); // Declare m_rc counter void dealloc(); cell(unsigned idx, name const & n, name const & un, expr const & t, optional const & v, binder_info bi); }; private: cell * m_ptr; friend class local_ctx; friend class local_context; friend void initialize_local_ctx(); local_decl(unsigned idx, name const & n, name const & un, expr const & t, optional const & v, binder_info bi); local_decl(local_decl const & d, expr const & t, optional const & v); public: local_decl(); local_decl(local_decl const & s):m_ptr(s.m_ptr) { if (m_ptr) m_ptr->inc_ref(); } local_decl(local_decl && s):m_ptr(s.m_ptr) { s.m_ptr = nullptr; } ~local_decl() { if (m_ptr) m_ptr->dec_ref(); } local_decl & operator=(local_decl const & s) { LEAN_COPY_REF(s); } local_decl & operator=(local_decl && s) { LEAN_MOVE_REF(s); } friend bool is_eqp(local_decl const & a, local_decl const & b) { return a.m_ptr == b.m_ptr; } name const & get_name() const { return m_ptr->m_name; } name const & get_user_name() const { return m_ptr->m_user_name; } expr const & get_type() const { return m_ptr->m_type; } optional const & get_value() const { return m_ptr->m_value; } binder_info get_info() const { return m_ptr->m_bi; } expr mk_ref() const; unsigned get_idx() const { return m_ptr->m_idx; } }; /* Plain local context object used by the kernel type checker. */ class local_ctx { protected: typedef unsigned_map idx2local_decl; unsigned m_next_idx; idx2local_decl m_idx2local_decl; name_map m_name2local_decl; // mapping from unique identifier to local_decl template expr mk_binding(unsigned num, expr const * fvars, expr const & b) const; local_decl mk_local_decl(name const & n, name const & un, expr const & type, optional const & value, binder_info bi); public: local_ctx():m_next_idx(0) {} bool empty() const { return m_idx2local_decl.empty(); } expr mk_local_decl(name const & n, expr const & type, binder_info bi = mk_binder_info()) { return mk_local_decl(n, n, type, none_expr(), bi).mk_ref(); } expr mk_local_decl(name const & n, expr const & type, expr const & value) { return mk_local_decl(n, n, type, some_expr(value), mk_binder_info()).mk_ref(); } expr mk_local_decl(name const & n, name const & un, expr const & type, binder_info bi = mk_binder_info()) { return mk_local_decl(n, un, type, none_expr(), bi).mk_ref(); } expr mk_local_decl(name const & n, name const & un, expr const & type, expr const & value) { return mk_local_decl(n, un, type, some_expr(value), mk_binder_info()).mk_ref(); } expr mk_local_decl(name_generator & g, name const & un, expr const & type, binder_info bi = mk_binder_info()) { return mk_local_decl(g.next(), un, type, bi); } expr mk_local_decl(name_generator & g, name const & un, expr const & type, expr const & value) { return mk_local_decl(g.next(), un, type, some_expr(value), mk_binder_info()).mk_ref(); } /** \brief Return the local declarations for the given reference. \pre is_fvar(e) */ optional find_local_decl(expr const & e) const; optional find_local_decl(name const & n) const; local_decl const & get_local_decl(name const & n) const; local_decl const & get_local_decl(expr const & e) const { return get_local_decl(mlocal_name(e)); } /** \brief Traverse local declarations based on the order they were created */ void for_each(std::function const & fn) const; optional find_if(std::function const & pred) const; // NOLINT optional back_find_if(std::function const & pred) const; // NOLINT /** Return the free variable associated with the given name. \pre get_local_decl(n) */ expr get_local(name const & n) const; /** \brief Remove the given local decl. */ void clear(local_decl const & d); expr mk_lambda(unsigned num, expr const * fvars, expr const & e) const; expr mk_pi(unsigned num, expr const * fvars, expr const & e) const; expr mk_lambda(buffer const & fvars, expr const & e) const { return mk_lambda(fvars.size(), fvars.data(), e); } expr mk_pi(buffer const & fvars, expr const & e) const { return mk_pi(fvars.size(), fvars.data(), e); } expr mk_lambda(expr const & fvar, expr const & e) { return mk_lambda(1, &fvar, e); } expr mk_pi(expr const & fvar, expr const & e) { return mk_pi(1, &fvar, e); } expr mk_lambda(std::initializer_list const & fvars, expr const & e) { return mk_lambda(fvars.size(), fvars.begin(), e); } expr mk_pi(std::initializer_list const & fvars, expr const & e) { return mk_pi(fvars.size(), fvars.begin(), e); } friend bool is_decl_eqp(local_ctx const & ctx1, local_ctx const & ctx2) { return is_eqp(ctx1.m_name2local_decl, ctx2.m_name2local_decl); } friend bool equal_locals(local_ctx const & ctx1, local_ctx const & ctx2) { return is_decl_eqp(ctx1, ctx2) || ctx1.m_name2local_decl.equal_keys(ctx2.m_name2local_decl); } }; void initialize_local_ctx(); void finalize_local_ctx(); }