expr visit_projection(name const & fn, buffer<expr> const & args) { projection_info const & info = *get_projection_info(env(), fn); expr major = visit(args[info.m_nparams]); buffer<bool> rel_fields; name I_name = *inductive::is_intro_rule(env(), info.m_constructor); get_constructor_info(info.m_constructor, rel_fields); lean_assert(info.m_i < rel_fields.size()); lean_assert(rel_fields[info.m_i]); /* We already erased irrelevant information */ /* Adjust projection index by ignoring irrelevant fields */ unsigned j = 0; for (unsigned i = 0; i < info.m_i; i++) { if (rel_fields[i]) j++; } expr r; if (has_trivial_structure(I_name, rel_fields)) { lean_assert(j == 0); r = major; } else { r = mk_app(mk_proj(j), major); } /* Add additional arguments */ for (unsigned i = info.m_nparams + 1; i < args.size(); i++) r = mk_app(r, visit(args[i])); return r; }
expr apply(expr const & a) { bool sh = false; if (is_shared(a)) { auto r = m_cache.find(a.raw()); if (r != m_cache.end()) return r->second; sh = true; } switch (a.kind()) { case expr_kind::Var: case expr_kind::Constant: case expr_kind::Type: case expr_kind::Value: return save_result(a, copy(a), sh); case expr_kind::App: { buffer<expr> new_args; for (expr const & old_arg : args(a)) new_args.push_back(apply(old_arg)); return save_result(a, mk_app(new_args), sh); } case expr_kind::HEq: return save_result(a, mk_heq(apply(heq_lhs(a)), apply(heq_rhs(a))), sh); case expr_kind::Pair: return save_result(a, mk_pair(apply(pair_first(a)), apply(pair_second(a)), apply(pair_type(a))), sh); case expr_kind::Proj: return save_result(a, mk_proj(proj_first(a), apply(proj_arg(a))), sh); case expr_kind::Lambda: return save_result(a, mk_lambda(abst_name(a), apply(abst_domain(a)), apply(abst_body(a))), sh); case expr_kind::Pi: return save_result(a, mk_pi(abst_name(a), apply(abst_domain(a)), apply(abst_body(a))), sh); case expr_kind::Sigma: return save_result(a, mk_sigma(abst_name(a), apply(abst_domain(a)), apply(abst_body(a))), sh); case expr_kind::Let: return save_result(a, mk_let(let_name(a), apply(let_type(a)), apply(let_value(a)), apply(let_body(a))), sh); case expr_kind::MetaVar: return save_result(a, update_metavar(a, [&](local_entry const & e) -> local_entry { if (e.is_inst()) return mk_inst(e.s(), apply(e.v())); else return e; }), sh); } lean_unreachable(); // LCOV_EXCL_LINE }