expr mk_resolvent(environment const & env, extension_context & ctx, expr const & m, expr const & l, expr const & not_l, expr const C1, expr const & C2) const { buffer<expr> R; // resolvent if (!collect(C1, l, R, ctx)) throw_kernel_exception(env, "invalid resolve macro, positive literal was not found", m); if (!collect(C2, not_l, R, ctx)) throw_kernel_exception(env, "invalid resolve macro, negative literal was not found", m); return mk_bin_rop(*g_or, *g_false, R.size(), R.data()); }
environment environment::replace(certified_declaration const & t) const { if (!m_id.is_descendant(t.get_id())) throw_incompatible_environment(*this); name const & n = t.get_declaration().get_name(); auto ax = find(n); if (!ax) throw_kernel_exception(*this, "invalid replacement of axiom with theorem, the environment does not have an axiom with the given name"); if (!ax->is_axiom()) throw_kernel_exception(*this, "invalid replacement of axiom with theorem, the current declaration in the environment is not an axiom"); if (!t.get_declaration().is_theorem()) throw_kernel_exception(*this, "invalid replacement of axiom with theorem, the new declaration is not a theorem"); if (ax->get_type() != t.get_declaration().get_type()) throw_kernel_exception(*this, "invalid replacement of axiom with theorem, the 'replace' operation can only be used when the axiom and theorem have the same type"); return environment(m_header, m_id, insert(m_declarations, n, t.get_declaration()), m_global_levels, m_extensions); }
environment environment::add(declaration const & d) const { if (trust_lvl() == 0) throw_kernel_exception(*this, "environment trust level does not allow users to add declarations that were not type checked"); name const & n = d.get_name(); if (find(n)) throw_already_declared(*this, n); return environment(m_header, m_id, insert(m_declarations, n, d), m_global_levels, m_extensions); }
virtual expr check_type(expr const & m, abstract_type_context & ctx, bool infer_only) const { check_macro(m); environment const & env = ctx.env(); expr s = macro_arg(m, 0); expr s_t = ctx.whnf(ctx.check(s, infer_only)); buffer<expr> I_args; expr const & I = get_app_args(s_t, I_args); if (!is_constant(I)) { // remark: this is not an issue since this macro should not be used during elaboration. throw_kernel_exception(env, sstream() << "projection macros do not support arbitrary terms " << "containing metavariables yet (solution: use trust-level 0)", m); } if (length(const_levels(I)) != length(m_ps)) throw_kernel_exception(env, sstream() << "invalid projection application '" << m_proj_name << "', incorrect number of universe parameters", m); expr t = instantiate_univ_params(m_type, m_ps, const_levels(I)); I_args.push_back(s); return instantiate_rev(t, I_args.size(), I_args.data()); }
virtual expr check_type(expr const & m, abstract_type_context & ctx, bool infer_only) const { check_macro(m); expr given_type = macro_arg(m, 0); if (!infer_only) { ctx.check(given_type, infer_only); expr inferred_type = ctx.check(macro_arg(m, 1), infer_only); if (!ctx.is_def_eq(inferred_type, given_type)) { throw_kernel_exception(ctx.env(), m, [=](formatter const & fmt) { return format("type mismatch at term") + pp_type_mismatch(fmt, macro_arg(m, 1), inferred_type, given_type); }); } } return given_type; }
/** \brief Given l : H, and R == (or ... l ...), create a proof term for R using or_intro_left and or_intro_right */ expr mk_or_intro(expr const & l, expr const & H, expr const & R, extension_context & ctx) const { check_system("resolve macro"); if (is_or_app(R)) { expr lhs = app_arg(app_fn(R)); expr rhs = app_arg(R); // or_intro_left {a : Prop} (H : a) (b : Prop) : a ∨ b // or_intro_right {b : Prop} (a : Prop) (H : b) : a ∨ b if (is_def_eq(l, lhs, ctx)) { return mk_app(*g_or_intro_left, l, H, rhs); } else if (is_def_eq(l, rhs, ctx)) { return mk_app(*g_or_intro_right, l, lhs, H); } else { return mk_app(*g_or_intro_right, rhs, lhs, mk_or_intro(l, H, rhs, ctx)); } } else if (is_def_eq(l, R, ctx)) { return H; } else { throw_kernel_exception(ctx.env(), "bug in resolve macro"); } }
virtual pair<expr, constraint_seq> check_type(expr const & m, extension_context & ctx, bool infer_only) const { constraint_seq cseq; check_macro(m); expr given_type = macro_arg(m, 0); if (!infer_only) { cseq += ctx.check_type(given_type, infer_only).second; auto p = ctx.check_type(macro_arg(m, 1), infer_only); expr inferred_type = p.first; cseq += p.second; justification jst = mk_type_mismatch_jst(macro_arg(m, 1), inferred_type, given_type, m); as_delayed_justification djst(jst); if (!ctx.is_def_eq(inferred_type, given_type, djst, cseq)) { throw_kernel_exception(ctx.env(), m, [=](formatter const & fmt) { return pp_type_mismatch(fmt, macro_arg(m, 1), inferred_type, given_type); }); } } return mk_pair(given_type, cseq); }
expr infer_type(expr const & e, extension_context & ctx, bool infer_only) const { auto r = ctx.check_type(e, infer_only); if (r.second) throw_kernel_exception(ctx.env(), "invalid resolve macro, constraints were generated while inferring type", e); return r.first; }
expr whnf(expr const & e, extension_context & ctx) const { auto r = ctx.whnf(e); if (r.second) throw_kernel_exception(ctx.env(), "invalid resolve macro, constraints were generated while computing whnf", e); return r.first; }
static void check_num_args(environment const & env, expr const & m) { lean_assert(is_macro(m)); if (macro_num_args(m) != 3) throw_kernel_exception(env, "invalid number of arguments for resolve macro", m); }
[[ noreturn ]] void throw_incompatible_environment(environment const & env) { throw_kernel_exception(env, "invalid declaration, it was checked/certified in an incompatible environment"); }
[[ noreturn ]] void throw_invalid_extension(environment const & env) { throw_kernel_exception(env, "invalid environment extension identifier"); }
environment environment::remove_universe(name const & n) const { if (!m_global_levels.contains(n)) throw_kernel_exception(*this, "no universe of the given name"); return environment(m_header, m_id, m_declarations, erase(m_global_levels, n), m_extensions); }
environment environment::add_universe(name const & n) const { if (m_global_levels.contains(n)) throw_kernel_exception(*this, "invalid global universe level declaration, environment already contains a universe level with the given name"); return environment(m_header, m_id, m_declarations, insert(m_global_levels, n), m_extensions); }