std::pair<level, justification> substitution::instantiate_metavars(level const & l, bool use_jst) { if (!has_meta(l)) return mk_pair(l, justification()); justification j; auto save_jst = [&](justification const & j2) { j = mk_composite1(j, j2); }; level r = replace(l, [&](level const & l) { if (!has_meta(l)) { return some_level(l); } else if (is_meta(l)) { auto p1 = get_assignment(l); if (p1) { auto p2 = instantiate_metavars(p1->first, use_jst); if (use_jst) { justification new_jst = mk_composite1(p1->second, p2.second); assign(meta_id(l), p2.first, new_jst); save_jst(new_jst); } else { assign(meta_id(l), p2.first); } return some_level(p2.first); } } return none_level(); }); return mk_pair(r, j); }
bool is_lt_no_level_params(level const & a, level const & b) { if (is_eqp(a, b)) return false; if (kind(a) != kind(b)) { if (kind(a) == level_kind::Param || kind(b) == level_kind::Param) return false; return kind(a) < kind(b); } switch (kind(a)) { case level_kind::Zero: lean_unreachable(); // LCOV_EXCL_LINE case level_kind::Param: return false; case level_kind::Global: return global_id(a) < global_id(b); case level_kind::Meta: return meta_id(a) < meta_id(b); case level_kind::Max: if (is_lt_no_level_params(max_lhs(a), max_lhs(b))) return true; else if (is_lt_no_level_params(max_lhs(b), max_lhs(a))) return false; else return is_lt_no_level_params(max_rhs(a), max_rhs(b)); case level_kind::IMax: if (is_lt_no_level_params(imax_lhs(a), imax_lhs(b))) return true; else if (is_lt_no_level_params(imax_lhs(b), imax_lhs(a))) return false; else return is_lt_no_level_params(imax_rhs(a), imax_rhs(b)); case level_kind::Succ: return is_lt_no_level_params(succ_of(a), succ_of(b)); } lean_unreachable(); }
unsigned level_cases_on(vm_obj const & o, buffer<vm_obj> & data) { level const & l = to_level(o); switch (l.kind()) { case level_kind::Zero: break; case level_kind::Succ: data.push_back(to_obj(succ_of(l))); break; case level_kind::Max: data.push_back(to_obj(max_lhs(l))); data.push_back(to_obj(max_rhs(l))); break; case level_kind::IMax: data.push_back(to_obj(imax_lhs(l))); data.push_back(to_obj(imax_rhs(l))); break; case level_kind::Param: data.push_back(to_obj(param_id(l))); break; case level_kind::Global: data.push_back(to_obj(global_id(l))); break; case level_kind::Meta: data.push_back(to_obj(meta_id(l))); break; } return static_cast<unsigned>(l.kind()); }
level collect(level const & l) { return replace(l, [&](level const & l) { if (is_meta(l)) { name const & id = meta_id(l); if (auto r = m_univ_meta_to_param.find(id)) { return some_level(*r); } else { name n = m_prefix.append_after(m_next_idx); m_next_idx++; level new_r = mk_param_univ(n); m_univ_meta_to_param.insert(id, new_r); m_univ_meta_to_param_inv.insert(n, l); m_level_params.push_back(n); return some_level(new_r); } } else if (is_param(l)) { name const & id = param_id(l); if (!m_found_univ_params.contains(id)) { m_found_univ_params.insert(id); m_level_params.push_back(id); } } return none_level(); }); }
format pp(level l, bool unicode, unsigned indent) { if (is_explicit(l)) { lean_assert(get_depth(l) > 0); return format(get_depth(l) - 1); } else { switch (kind(l)) { case level_kind::Zero: lean_unreachable(); // LCOV_EXCL_LINE case level_kind::Param: case level_kind::Global: return format(to_param_core(l).m_id); case level_kind::Meta: return format("?") + format(meta_id(l)); case level_kind::Succ: { auto p = to_offset(l); return pp_child(p.first, unicode, indent) + format("+") + format(p.second); } case level_kind::Max: case level_kind::IMax: { format r = format(is_max(l) ? "max" : "imax"); r += nest(indent, compose(line(), pp_child(to_max_core(l).m_lhs, unicode, indent))); // max and imax are right associative while (kind(to_max_core(l).m_rhs) == kind(l)) { l = to_max_core(l).m_rhs; r += nest(indent, compose(line(), pp_child(to_max_core(l).m_lhs, unicode, indent))); } r += nest(indent, compose(line(), pp_child(to_max_core(l).m_rhs, unicode, indent))); return group(r); }} lean_unreachable(); // LCOV_EXCL_LINE } }
static void print(std::ostream & out, level l) { if (is_explicit(l)) { lean_assert(get_depth(l) > 0); out << get_depth(l) - 1; } else { switch (kind(l)) { case level_kind::Zero: lean_unreachable(); // LCOV_EXCL_LINE case level_kind::Param: case level_kind::Global: out << to_param_core(l).m_id; break; case level_kind::Meta: out << "?" << meta_id(l); break; case level_kind::Succ: out << "succ "; print_child(out, succ_of(l)); break; case level_kind::Max: case level_kind::IMax: if (is_max(l)) out << "max "; else out << "imax "; print_child(out, to_max_core(l).m_lhs); // max and imax are right associative while (kind(to_max_core(l).m_rhs) == kind(l)) { l = to_max_core(l).m_rhs; out << " "; print_child(out, to_max_core(l).m_lhs); } out << " "; print_child(out, to_max_core(l).m_rhs); break; } } }
unsigned to_meta_idx(level const & l) { lean_assert(is_idx_metauniv(l)); return meta_id(l).get_numeral(); }
bool is_idx_metauniv(level const & l) { if (!is_meta(l)) return false; name const & n = meta_id(l); return !n.is_atomic() && n.is_numeral() && n.get_prefix() == *g_tmp_prefix; }