bool projection_converter::postpone_is_def_eq(expr const & t, expr const & s) { if (has_expr_metavar(t) || has_expr_metavar(s)) { auto it1 = is_projection(t); auto it2 = is_projection(s); if (it1 && it2) { return true; } if (it1 && is_stuck(t, *m_tc)) return true; if (it2 && is_stuck(s, *m_tc)) return true; } return default_converter::postpone_is_def_eq(t, s); }
optional<expr> unfold_step(type_context & ctx, expr const & e, name_set const & to_unfold, bool unfold_reducible) { if (!unfold_reducible && to_unfold.empty()) return none_expr(); if (!is_app(e) && !is_constant(e)) return none_expr(); expr const & fn = get_app_fn(e); if (!is_constant(fn)) return none_expr(); name const & fn_name = const_name(fn); bool in_to_unfold = to_unfold.contains(const_name(fn)); if (!in_to_unfold && !unfold_reducible) return none_expr(); if (is_projection(ctx.env(), const_name(fn))) { if (in_to_unfold) { type_context::transparency_scope scope(ctx, transparency_mode::Instances); return ctx.reduce_projection(e); } else { return none_expr(); } } else if (in_to_unfold) { return unfold_term(ctx.env(), e); } else if (unfold_reducible && is_reducible(ctx.env(), fn_name)) { type_context::transparency_scope scope(ctx, transparency_mode::Reducible); return unfold_term(ctx.env(), e); } else { return none_expr(); } }
optional<pair<expr, constraint_seq>> projection_converter::reduce_projection(expr const & t) { projection_info const * info = is_projection(t); if (!info) return optional<pair<expr, constraint_seq>>(); buffer<expr> args; get_app_args(t, args); if (args.size() <= info->m_nparams) { return optional<pair<expr, constraint_seq>>(); } unsigned mkidx = info->m_nparams; expr const & mk = args[mkidx]; pair<expr, constraint_seq> new_mk_cs = whnf(mk); expr new_mk = new_mk_cs.first; expr const & new_mk_fn = get_app_fn(new_mk); if (!is_constant(new_mk_fn) || const_name(new_mk_fn) != info->m_constructor) { return optional<pair<expr, constraint_seq>>(); } buffer<expr> mk_args; get_app_args(new_mk, mk_args); unsigned i = info->m_nparams + info->m_i; if (i >= mk_args.size()) { return optional<pair<expr, constraint_seq>>(); } expr r = mk_args[i]; r = mk_app(r, args.size() - mkidx - 1, args.data() + mkidx + 1); return optional<pair<expr, constraint_seq>>(r, new_mk_cs.second); }
optional<expr> projection_converter::is_stuck(expr const & e, type_checker & c) { projection_info const * info = is_projection(e); if (!info) return default_converter::is_stuck(e, c); buffer<expr> args; get_app_args(e, args); if (args.size() <= info->m_nparams) return none_expr(); expr mk = whnf(args[info->m_nparams], c).first; return c.is_stuck(mk); }
virtual expr visit_app(expr const & e) override { buffer<expr> args; expr const & fn = get_app_args(e, args); if (is_constant(fn)) { name const & n = const_name(fn); if (is_cases_on_recursor(env(), n)) { return visit_cases_on(n, args); } else if (inductive::is_intro_rule(env(), n)) { return visit_constructor(n, args); } else if (is_projection(env(), n)) { return visit_projection(n, args); } } return compiler_step_visitor::visit_app(e); }