@Kha @dselsam: This hack was preventing us from making `Expr` a "real" Lean type. This was bad for a few reasons: - It was hard to extend/modify `Expr` in Lean since we would also have to modify the C++ code that creates the `Expr` objects with the hidden fields. - `Expr.lam` and `Expr.forallE` were not following the Lean layout standard where we sort fields by size. @Kha: recall we used that to avoid a UB. The issue with `Expr.lam` and `Expr.forallE` is that they have a "visible" field (`BinderInfo`), which is smaller than hidden fields such as hash code. - `Expr.fvar` had only one field at `Expr.lean,` but four behind the scenes. I added a new constructor `Local` that is only accessible from C++. It is only used in legacy code we inherited from Lean2. We will eventually delete it. This refactoring was quite painful since many parts of the codebase were mixing the new `Expr.fvar` with the old `Expr.local`. I doubt I would be able to do it without the new staging framework @Kha built. BTW, some of the patches are horrible. I didn't care much since we are going to deleted the super ugly files. That being said, you should expect new weird bevaior due to `Expr.fvar` vs `Expr.local`. Next step: use the new `ExprCachedData` to make all `Expr` hidden visibles accessible from Lean. checkpoint
74 lines
3 KiB
C++
74 lines
3 KiB
C++
/*
|
|
Copyright (c) 2014-2015 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_set.h"
|
|
#include "kernel/expr.h"
|
|
#include "kernel/expr_sets.h"
|
|
namespace lean {
|
|
void collect_univ_params_core(level const & l, name_set & r);
|
|
name_set collect_univ_params(expr const & e, name_set const & ls = name_set());
|
|
/**
|
|
\remark If restricted is true, then locals in meta-variable applications and local constants
|
|
are ignored.
|
|
*/
|
|
class collected_locals {
|
|
name_set m_local_names;
|
|
buffer<expr> m_locals;
|
|
public:
|
|
void insert(expr const & l);
|
|
bool contains(name const & n) const { return m_local_names.contains(n); }
|
|
bool contains(expr const & l) const { return contains(local_or_fvar_name(l)); }
|
|
buffer<expr> const & get_collected() const { return m_locals; }
|
|
bool empty() const { return m_locals.empty(); }
|
|
};
|
|
|
|
void collect_locals(expr const & e, collected_locals & ls, bool restricted = false);
|
|
|
|
/** \brief Return true iff locals(e1) is a subset of locals(e2). */
|
|
bool locals_subset(expr const & e1, expr const & e2);
|
|
|
|
names to_names(name_set const & ls);
|
|
|
|
/** \brief Return true iff \c [begin_locals, end_locals) contains \c local */
|
|
template<typename It>
|
|
bool contains_local(expr const & local, It const & begin_locals, It const & end_locals) {
|
|
return std::any_of(begin_locals, end_locals, [&](expr const & l) { return local_or_fvar_name(local) == local_or_fvar_name(l); });
|
|
}
|
|
|
|
template<typename T>
|
|
bool contains_local(expr const & l, T const & locals) {
|
|
return std::any_of(locals.begin(), locals.end(),
|
|
[&](expr const & l1) { return local_or_fvar_name(l1) == local_or_fvar_name(l); });
|
|
}
|
|
|
|
/** \brief Return true iff \c e contains a local constant \c h s.t. mlocal_name(h) in s */
|
|
bool contains_local(expr const & e, name_set const & s);
|
|
|
|
/** \brief Return true iff \c e contains a local constant named \c n (it uses mlocal_name) */
|
|
bool contains_local(expr const & e, name const & n);
|
|
|
|
/** \brief Return true iff \e contains the local constant \c h */
|
|
inline bool depends_on(expr const & e, expr const & h) {
|
|
return contains_local(e, local_or_fvar_name(h));
|
|
}
|
|
|
|
/** \brief Return true iff one of \c es contains the local constant \c h */
|
|
optional<expr> depends_on(unsigned sz, expr const * es, expr const & h);
|
|
|
|
/** \brief Return true iff \c e depends on any of the local constants in \c hs */
|
|
bool depends_on_any(expr const & e, unsigned hs_sz, expr const * hs);
|
|
inline bool depends_on_any(expr const & e, buffer<expr> const & hs) {
|
|
return depends_on_any(e, hs.size(), hs.data());
|
|
}
|
|
|
|
/** \brief Replace the given local constants occurring in \c e with the given terms */
|
|
expr replace_locals(expr const & e, unsigned sz, expr const * locals, expr const * terms);
|
|
expr replace_locals(expr const & e, buffer<expr> const & locals, buffer<expr> const & terms);
|
|
inline expr replace_local(expr const & e, expr const & local, expr const & term) {
|
|
return replace_locals(e, 1, &local, &term);
|
|
}
|
|
}
|