bool contains_local(expr const & e, name const & n) { if (!has_local(e)) return false; bool result = false; for_each(e, [&](expr const & e, unsigned) { if (result || !has_local(e)) { return false; } else if (is_local(e) && mlocal_name(e) == n) { result = true; return false; } else { return true; } }); return result; }
void collect_locals(expr const & e, collected_locals & ls, bool restricted) { if (!has_local(e)) return; expr_set visited; std::function<void(expr const & e)> visit = [&](expr const & e) { if (!has_local(e)) return; if (restricted && is_meta(e)) return; if (visited.find(e) != visited.end()) return; visited.insert(e); switch (e.kind()) { case expr_kind::Var: case expr_kind::Constant: case expr_kind::Sort: break; // do nothing case expr_kind::Local: if (!restricted) visit(mlocal_type(e)); ls.insert(e); break; case expr_kind::Meta: lean_assert(!restricted); visit(mlocal_type(e)); break; case expr_kind::Macro: for (unsigned i = 0; i < macro_num_args(e); i++) visit(macro_arg(e, i)); break; case expr_kind::App: visit(app_fn(e)); visit(app_arg(e)); break; case expr_kind::Lambda: case expr_kind::Pi: visit(binding_domain(e)); visit(binding_body(e)); break; case expr_kind::Let: visit(let_type(e)); visit(let_value(e)); visit(let_body(e)); break; } }; visit(e); }
Value Scope::get_local(Symbol name) { static Symbol self_symbol("self"); if (name == self_symbol && m_Self) return m_Self; ASSERT(has_local(name)); return m_Locals->get_by_index(local_map()->local(name)); }
// see if we have a lexical variable // move down the stack but stop before we // reach the global frame (is not included) bool has_lexical(const string& key) const { auto cur = this; while (cur->is_lexical()) { if (cur->has_local(key)) return true; cur = cur->parent_; } return false; }
void assert_no_locals(name const & n, expr const & e) { if (!has_local(e)) return; collected_locals ls; collect_locals(e, ls); lean_trace(name({"debug", "inductive_compiler"}), tout() << "\n\nerror: found locals in '" << n << "'\n" << e << "\n"; for (expr const & l : ls.get_collected()) { tout() << mlocal_name(l) << "." << mlocal_pp_name(l) << " : " << mlocal_type(l) << "\n"; });
// use array access for getter and setter functions T& operator[](const string& key) { auto cur = this; while (cur) { if (cur->has_local(key)) { return cur->get_local(key); } cur = cur->parent_; } return get_local(key); }
bool Environment<T>::has(const std::string& key) const { auto cur = this; while (cur) { if (cur->has_local(key)) { return true; } cur = cur->parent_; } return false; }
/** \brief Return true iff locals(e1) is a subset of locals(e2) */ bool locals_subset(expr const & e1, expr const & e2) { if (!has_local(e1)) { // empty set is a subset of anything return true; } if (!has_local(e2)) { lean_assert(has_local(e1)); return false; } collected_locals S; collect_locals(e2, S); bool is_sub = true; for_each(e1, [&](expr const & e, unsigned) { if (!is_sub || !has_local(e)) return false; // stop search if (is_local(e) && !S.contains(e)) is_sub = false; return true; }); return is_sub; }
// see if we have a lexical we could update // either update already existing lexical value // or if flag is set, we create one if no lexical found void set_lexical(const string& key, T val) { auto cur = this; while (cur->is_lexical()) { if (cur->has_local(key)) { cur->set_local(key, val); return; } cur = cur->parent_; } set_local(key, val); }
void Environment<T>::set_lexical(const std::string& key, T val) { auto cur = this; bool shadow = false; while (cur->is_lexical() || shadow) { if (cur->has_local(key)) { cur->set_local(key, val); return; } shadow = cur->is_shadow(); cur = cur->parent_; } set_local(key, val); }
static bool validate_locals(expr const & r, unsigned num_locals, expr const * locals) { bool failed = false; for_each(r, [&](expr const & e, unsigned) { if (!has_local(e) || failed) return false; if (is_local(e) && !std::any_of(locals, locals + num_locals, [&](expr const & l) { return mlocal_name(l) == mlocal_name(e); })) { failed = true; return false; } return true; }); return !failed; }
Value Scope::set_local(Symbol name, const Value& val) { if (!m_LocalMap) m_LocalMap = gc_new<LocalMap>(); if (!m_Locals) m_Locals = gc_new<Array>(); uintx idx; if (!has_local(name)) { idx = local_map()->define_local(name); } else { idx = local_map()->local(name); } return m_Locals->set_by_index(idx, val); }
list<unsigned> fun_info_manager::collect_deps(expr const & type, buffer<expr> const & locals) { buffer<unsigned> deps; for_each(type, [&](expr const & e, unsigned) { if (m_ctx.is_tmp_local(e)) { unsigned idx; for (idx = 0; idx < locals.size(); idx++) if (locals[idx] == e) break; if (idx < locals.size() && std::find(deps.begin(), deps.end(), idx) == deps.end()) deps.push_back(idx); } return has_local(e); // continue the search only if e has locals }); std::sort(deps.begin(), deps.end()); return to_list(deps); }