// If restricted is true, we don't use (e <-> true) rewrite list<expr_pair> apply(expr const & e, expr const & H, bool restrited) { expr c, Hdec, A, arg1, arg2; if (is_relation(e)) { return mk_singleton(e, H); } else if (is_standard(m_env) && is_not(m_env, e, arg1)) { expr new_e = mk_iff(arg1, mk_false()); expr new_H = mk_app(mk_constant(get_iff_false_intro_name()), arg1, H); return mk_singleton(new_e, new_H); } else if (is_standard(m_env) && is_and(e, arg1, arg2)) { // TODO(Leo): we can extend this trick to any type that has only one constructor expr H1 = mk_app(mk_constant(get_and_elim_left_name()), arg1, arg2, H); expr H2 = mk_app(mk_constant(get_and_elim_right_name()), arg1, arg2, H); auto r1 = apply(arg1, H1, restrited); auto r2 = apply(arg2, H2, restrited); return append(r1, r2); } else if (is_pi(e)) { // TODO(dhs): keep name? expr local = m_tctx.mk_tmp_local(binding_domain(e), binding_info(e)); expr new_e = instantiate(binding_body(e), local); expr new_H = mk_app(H, local); auto r = apply(new_e, new_H, restrited); unsigned len = length(r); if (len == 0) { return r; } else if (len == 1 && head(r).first == new_e && head(r).second == new_H) { return mk_singleton(e, H); } else { return lift(local, r); } } else if (is_standard(m_env) && is_ite(e, c, Hdec, A, arg1, arg2) && is_prop(e)) { // TODO(Leo): support HoTT mode if users request expr not_c = mk_app(mk_constant(get_not_name()), c); expr Hc = m_tctx.mk_tmp_local(c); expr Hnc = m_tctx.mk_tmp_local(not_c); expr H1 = mk_app({mk_constant(get_implies_of_if_pos_name()), c, arg1, arg2, Hdec, e, Hc}); expr H2 = mk_app({mk_constant(get_implies_of_if_neg_name()), c, arg1, arg2, Hdec, e, Hnc}); auto r1 = lift(Hc, apply(arg1, H1, restrited)); auto r2 = lift(Hnc, apply(arg2, H2, restrited)); return append(r1, r2); } else if (!restrited) { expr new_e = m_tctx.whnf(e); if (new_e != e) { if (auto r = apply(new_e, H, true)) return r; } if (is_standard(m_env) && is_prop(e)) { expr new_e = mk_iff(e, mk_true()); expr new_H = mk_app(mk_constant(get_iff_true_intro_name()), e, H); return mk_singleton(new_e, new_H); } else { return list<expr_pair>(); } } else { return list<expr_pair>(); } }
/** * The condition function. * * condition ::= "odd" expression * | expression rel-op expression. * */ int condition(FILE *input_file, token_type *token) { int error_code = 0; token_type relop = nulsym; // oddsym if(*token == oddsym) { relop = *token; *token = get_token(input_file); } // relation symbols else { error_code = expression(input_file, token); if(error_code) return error_code; if(!is_relation(*token)) { // relational operator expected return 20; } relop = *token; *token = get_token(input_file); } error_code = expression(input_file, token); if(error_code) return error_code; switch(relop) { case oddsym: // odd error_code = emit(OPR, 0, OPR_ODD); break; case eqsym: // = error_code = emit(OPR, 0, OPR_EQL); break; case neqsym: // <> error_code = emit(OPR, 0, OPR_NEQ); break; case lessym: // < error_code = emit(OPR, 0, OPR_LSS); break; case leqsym: // <= error_code = emit(OPR, 0, OPR_LEQ); break; case gtrsym: // > error_code = emit(OPR, 0, OPR_GTR); break; case geqsym: // >= error_code = emit(OPR, 0, OPR_GEQ); break; default: break; } return error_code; }