void add_defs(unsigned num, expr * const * args, expr * u, expr * identity) { if (m_mc) { add_def(args[0], u); for (unsigned i = 1; i < num; i++) add_def(args[i], identity); } }
app * process_extract(func_decl * f, expr * arg) { if (!uncnstr(arg)) return nullptr; app * r; if (!mk_fresh_uncnstr_var_for(f, arg, r)) return r; if (!m_mc) return r; unsigned high = m_bv_util.get_extract_high(f); unsigned low = m_bv_util.get_extract_low(f); unsigned bv_size = m_bv_util.get_bv_size(m().get_sort(arg)); if (bv_size == high - low + 1) { add_def(arg, r); } else { ptr_buffer<expr> args; if (high < bv_size - 1) args.push_back(m_bv_util.mk_numeral(rational(0), bv_size - high - 1)); args.push_back(r); if (low > 0) args.push_back(m_bv_util.mk_numeral(rational(0), low)); add_def(arg, m_bv_util.mk_concat(args.size(), args.c_ptr())); } return r; }
app * process_array_app(func_decl * f, unsigned num, expr * const * args) { SASSERT(f->get_family_id() == m_ar_util.get_family_id()); switch (f->get_decl_kind()) { case OP_SELECT: if (uncnstr(args[0])) { app * r; if (!mk_fresh_uncnstr_var_for(f, num, args, r)) return r; sort * s = m().get_sort(args[0]); if (m_mc) add_def(args[0], m_ar_util.mk_const_array(s, r)); return r; } return nullptr; case OP_STORE: if (uncnstr(args[0]) && uncnstr(args[num-1])) { app * r; if (!mk_fresh_uncnstr_var_for(f, num, args, r)) return r; if (m_mc) { add_def(args[num-1], m().mk_app(m_ar_util.get_family_id(), OP_SELECT, num-1, args)); add_def(args[0], r); } return r; } default: return nullptr; } }
app * process_datatype_app(func_decl * f, unsigned num, expr * const * args) { if (m_dt_util.is_recognizer(f)) { SASSERT(num == 1); if (uncnstr(args[0])) { if (!m_mc) { app * r; mk_fresh_uncnstr_var_for(f, num, args, r); return r; } // TODO: handle model generation } } else if (m_dt_util.is_accessor(f)) { SASSERT(num == 1); if (uncnstr(args[0])) { if (!m_mc) { app * r; mk_fresh_uncnstr_var_for(f, num, args, r); return r; } func_decl * c = m_dt_util.get_accessor_constructor(f); for (unsigned i = 0; i < c->get_arity(); i++) if (!m().is_fully_interp(c->get_domain(i))) return nullptr; app * u; if (!mk_fresh_uncnstr_var_for(f, num, args, u)) return u; ptr_vector<func_decl> const & accs = *m_dt_util.get_constructor_accessors(c); ptr_buffer<expr> new_args; for (unsigned i = 0; i < accs.size(); i++) { if (accs[i] == f) new_args.push_back(u); else new_args.push_back(m().get_some_value(c->get_domain(i))); } add_def(args[0], m().mk_app(c, new_args.size(), new_args.c_ptr())); return u; } } else if (m_dt_util.is_constructor(f)) { if (uncnstr(num, args)) { app * u; if (!mk_fresh_uncnstr_var_for(f, num, args, u)) return u; if (!m_mc) return u; ptr_vector<func_decl> const & accs = *m_dt_util.get_constructor_accessors(f); for (unsigned i = 0; i < num; i++) { add_def(args[i], m().mk_app(accs[i], u)); } return u; } } return nullptr; }
app * process_bv_div(func_decl * f, expr * arg1, expr * arg2) { if (uncnstr(arg1) && uncnstr(arg2)) { sort * s = m().get_sort(arg1); app * r; if (!mk_fresh_uncnstr_var_for(f, arg1, arg2, r)) return r; if (!m_mc) return r; add_def(arg1, r); add_def(arg2, m_bv_util.mk_numeral(rational(1), s)); return r; } return nullptr; }
/* theta_type -- compute type of a theta-exp or theta-select */ PRIVATE type theta_type(tree t, env e, type a, tree cxt) { def d = get_schema((tok) t->x_the_name, t->x_loc); schema s; env e1 = new_env(e); type b; int i; if (d == NULL) return err_type; s = d->d_schema; check_rename(s, (tok) t->x_the_decor, t->x_the_rename, t); for (i = 0; i < s->z_ncomps; i++) { sym x = s->z_comp[i].z_name; sym xp = get_rename(x, (tok) t->x_the_decor, t->x_the_rename); type tt = (a == NULL ? ref_type(xp, nil, e, t) : comp_type(a, xp, cxt, t->x_loc)); add_def(VAR, x, tt, e1); } b = mk_sproduct(mk_schema(e1)); if (! aflag && d->d_abbrev && d->d_nparams == 0 && type_equal(b, arid, mk_sproduct(s), arid)) return mk_abbrev(d, arid); else return b; }
app * process_le_ge(func_decl * f, expr * arg1, expr * arg2, bool le) { expr * v; expr * t; if (uncnstr(arg1)) { v = arg1; t = arg2; } else if (uncnstr(arg2)) { v = arg2; t = arg1; le = !le; } else { return nullptr; } app * u; if (!mk_fresh_uncnstr_var_for(f, arg1, arg2, u)) return u; if (!m_mc) return u; // v = ite(u, t, t + 1) if le // v = ite(u, t, t - 1) if !le add_def(v, m().mk_ite(u, t, m_a_util.mk_add(t, m_a_util.mk_numeral(rational(le ? 1 : -1), m().get_sort(arg1))))); return u; }
app * process_bv_mul(func_decl * f, unsigned num, expr * const * args) { if (num == 0) return nullptr; if (uncnstr(num, args)) { sort * s = m().get_sort(args[0]); app * r; if (!mk_fresh_uncnstr_var_for(f, num, args, r)) return r; if (m_mc) add_defs(num, args, r, m_bv_util.mk_numeral(rational(1), s)); return r; } // c * v (c is even) case unsigned bv_size; rational val; rational inv; if (num == 2 && uncnstr(args[1]) && m_bv_util.is_numeral(args[0], val, bv_size) && m_bv_util.mult_inverse(val, bv_size, inv)) { app * r; if (!mk_fresh_uncnstr_var_for(f, num, args, r)) return r; sort * s = m().get_sort(args[1]); if (m_mc) add_def(args[1], m_bv_util.mk_bv_mul(m_bv_util.mk_numeral(inv, s), r)); return r; } return nullptr; }
app * process_arith_mul(func_decl * f, unsigned num, expr * const * args) { if (num == 0) return nullptr; sort * s = m().get_sort(args[0]); if (uncnstr(num, args)) { app * r; if (!mk_fresh_uncnstr_var_for(f, num, args, r)) return r; if (m_mc) add_defs(num, args, r, m_a_util.mk_numeral(rational(1), s)); return r; } // c * v case for reals bool is_int; rational val; if (num == 2 && uncnstr(args[1]) && m_a_util.is_numeral(args[0], val, is_int) && !is_int) { if (val.is_zero()) return nullptr; app * r; if (!mk_fresh_uncnstr_var_for(f, num, args, r)) return r; if (m_mc) { val = rational(1) / val; add_def(args[1], m_a_util.mk_mul(m_a_util.mk_numeral(val, false), r)); } return r; } return nullptr; }
app * process_bv_le(func_decl * f, expr * arg1, expr * arg2, bool is_signed) { if (m_produce_proofs) { // The result of bv_le is not just introducing a new fresh name, // we need a side condition. // TODO: the correct proof step return nullptr; } if (uncnstr(arg1)) { // v <= t expr * v = arg1; expr * t = arg2; // v <= t ---> (u or t == MAX) u is fresh // add definition v = ite(u or t == MAX, t, t+1) unsigned bv_sz = m_bv_util.get_bv_size(arg1); rational MAX; if (is_signed) MAX = rational::power_of_two(bv_sz - 1) - rational(1); else MAX = rational::power_of_two(bv_sz) - rational(1); app * u; bool is_new = mk_fresh_uncnstr_var_for(f, arg1, arg2, u); app * r = m().mk_or(u, m().mk_eq(t, m_bv_util.mk_numeral(MAX, bv_sz))); if (m_mc && is_new) add_def(v, m().mk_ite(r, t, m_bv_util.mk_bv_add(t, m_bv_util.mk_numeral(rational(1), bv_sz)))); return r; } if (uncnstr(arg2)) { // v >= t expr * v = arg2; expr * t = arg1; // v >= t ---> (u ot t == MIN) u is fresh // add definition v = ite(u or t == MIN, t, t-1) unsigned bv_sz = m_bv_util.get_bv_size(arg1); rational MIN; if (is_signed) MIN = -rational::power_of_two(bv_sz - 1); else MIN = rational(0); app * u; bool is_new = mk_fresh_uncnstr_var_for(f, arg1, arg2, u); app * r = m().mk_or(u, m().mk_eq(t, m_bv_util.mk_numeral(MIN, bv_sz))); if (m_mc && is_new) add_def(v, m().mk_ite(r, t, m_bv_util.mk_bv_sub(t, m_bv_util.mk_numeral(rational(1), bv_sz)))); return r; } return nullptr; }
void visit_form(Process *process, Obj *env, Obj *bytecodeObj, int *position, Obj *form) { if(eval_error) { return; } else if(form->tag == 'C') { if(form->car->car == NULL) { add_literal(bytecodeObj, position, nil); } else if(HEAD_EQ("quote")) { add_literal(bytecodeObj, position, form->car); } else if(HEAD_EQ("if")) { add_if(process, env, bytecodeObj, position, form); } else if(HEAD_EQ("while")) { add_while(process, env, bytecodeObj, position, form); } else if(HEAD_EQ("do")) { add_do(process, env, bytecodeObj, position, form); } else if(HEAD_EQ("let")) { add_let(process, env, bytecodeObj, position, form); } else if(HEAD_EQ("def")) { add_def(process, env, bytecodeObj, position, form); } else if(HEAD_EQ("reset!")) { add_reset(process, env, bytecodeObj, position, form); } else if(HEAD_EQ("ref")) { add_ref(process, env, bytecodeObj, position, form); } /* else if(HEAD_EQ("or")) { */ /* add_or(process, env, bytecodeObj, position, form); */ /* } */ else if(HEAD_EQ("not")) { add_not(process, env, bytecodeObj, position, form); } else if(HEAD_EQ("fn")) { Obj *lambda = obj_new_lambda(form->cdr->car, form_to_bytecode(process, env, form->cdr->cdr->car), env, form); add_literal(bytecodeObj, position, lambda); } else { add_call(process, env, bytecodeObj, position, form); } } else if(form->tag == 'Y') { add_lookup(bytecodeObj, position, form); } else { add_literal(bytecodeObj, position, form); } /* else { */ /* printf("Bytecode can't handle form: "); */ /* obj_print_cout(form); */ /* exit(1); */ /* } */ }
app * process_add(family_id fid, decl_kind add_k, decl_kind sub_k, unsigned num, expr * const * args) { if (num == 0) return nullptr; unsigned i; expr * v = nullptr; for (i = 0; i < num; i++) { expr * arg = args[i]; if (uncnstr(arg)) { v = arg; break; } } if (v == nullptr) return nullptr; app * u; if (!mk_fresh_uncnstr_var_for(m().mk_app(fid, add_k, num, args), u)) return u; if (!m_mc) return u; ptr_buffer<expr> new_args; for (unsigned j = 0; j < num; j++) { if (j == i) continue; new_args.push_back(args[j]); } if (new_args.empty()) { add_def(v, u); } else { expr * rest; if (new_args.size() == 1) rest = new_args[0]; else rest = m().mk_app(fid, add_k, new_args.size(), new_args.c_ptr()); add_def(v, m().mk_app(fid, sub_k, u, rest)); } return u; }
app * process_bv_app(func_decl * f, unsigned num, expr * const * args) { SASSERT(f->get_family_id() == m_bv_util.get_family_id()); switch (f->get_decl_kind()) { case OP_BADD: return process_add(f->get_family_id(), OP_BADD, OP_BSUB, num, args); case OP_BMUL: return process_bv_mul(f, num, args); case OP_BSDIV: case OP_BUDIV: case OP_BSDIV_I: case OP_BUDIV_I: SASSERT(num == 2); return process_bv_div(f, args[0], args[1]); case OP_SLEQ: SASSERT(num == 2); return process_bv_le(f, args[0], args[1], true); case OP_ULEQ: SASSERT(num == 2); return process_bv_le(f, args[0], args[1], false); case OP_CONCAT: return process_concat(f, num, args); case OP_EXTRACT: SASSERT(num == 1); return process_extract(f, args[0]); case OP_BNOT: SASSERT(num == 1); if (uncnstr(args[0])) { app * r; if (!mk_fresh_uncnstr_var_for(f, num, args, r)) return r; if (m_mc) add_def(args[0], m().mk_app(f, r)); return r; } return nullptr; case OP_BOR: if (num > 0 && uncnstr(num, args)) { sort * s = m().get_sort(args[0]); app * r; if (!mk_fresh_uncnstr_var_for(f, num, args, r)) return r; if (m_mc) add_defs(num, args, r, m_bv_util.mk_numeral(rational(0), s)); return r; } return nullptr; default: return nullptr; } }
app * process_concat(func_decl * f, unsigned num, expr * const * args) { if (num == 0) return nullptr; if (!uncnstr(num, args)) return nullptr; app * r; if (!mk_fresh_uncnstr_var_for(f, num, args, r)) return r; if (m_mc) { unsigned i = num; unsigned low = 0; while (i > 0) { --i; expr * arg = args[i]; unsigned sz = m_bv_util.get_bv_size(arg); add_def(arg, m_bv_util.mk_extract(low + sz - 1, low, r)); low += sz; } } return r; }
int main(int argc, char *argv[]) { int ch, i; args = NULL; cargs = nargs = 0; while ((ch = getopt(argc, argv, "cD:EgI:L:o:O:sU:l:")) != -1) { if (ch == 'l') { /* Gone too far. Back up and get out. */ if (argv[optind - 1][0] == '-') optind -= 1; else optind -= 2; break; } else if (ch == '?') usage(); } addarg("cc"); addarg("-std=iso9899:1990"); addarg("-pedantic"); addarg("-m32"); for (i = 1; i < optind; i++) { /* "--" indicates end of options. Radar 3761967. */ if (strcmp (argv[i], "--") == 0) dash_dash_seen = 1; /* White space is OK between -O and 1 or 2. Radar 3762315. */ else if (strcmp (argv[i], "-O") == 0) { if (i+1 < argc) { if (strcmp (argv[i+1], "1") == 0 || strcmp (argv[i+1], "0") == 0) { combine_and_addarg(argv[i], argv[i+1]); i++; } else addarg(argv[i]); } } else if (strcmp (argv[i], "-U") == 0) { /* Record undefined macros. */ record_undef (argv[i+1]); addarg(argv[i]); addarg(argv[i+1]); i++; } else if (strncmp (argv[i], "-U", 2) == 0) { /* Record undefined macros. */ record_undef (argv[i]+2); addarg(argv[i]); } else if (strcmp (argv[i], "-L") == 0 && i+1 < argc) { combine_and_addarg(argv[i], argv[i+1]); i++; } else if (strcmp (argv[i], "-D") == 0) { add_def (argv[i+1]); i++; } else if (strncmp (argv[i], "-D", 2) == 0) add_def (argv[i]+2); else addarg(argv[i]); } while (i < argc) { if (strncmp(argv[i], "-l", 2) == 0) { if (argv[i][2] != '\0') addlib(argv[i++] + 2); else { if (argv[++i] == NULL) usage(); addlib(argv[i++]); } } else if (strcmp (argv[i], "-L") == 0 && i+1 < argc) { combine_and_addarg(argv[i], argv[i+1]); i+=2; } else if (strcmp (argv[i], "--") == 0) { dash_dash_seen = 1; } else addarg(argv[i++]); } execv("/usr/bin/cc", args); err(1, "/usr/bin/cc"); }
PUBLIC type tc_expr(tree t, env e) #endif { switch (t->x_kind) { case REF: return ref_type((sym) t->x_tag, t->x_params, e, t); case INGEN: return ref_type((sym) t->x_tag, list2(t->x_param1, t->x_param2), e, t); case PREGEN: return ref_type((sym) t->x_tag, list1(t->x_param), e, t); case NUMBER: return nat_type; case SEXPR: { def d; frame params; if (! open_sref(t->x_ref, e, &d, ¶ms)) return err_type; if ((tok) t->x_ref->x_sref_decor != empty) { tc_error(t->x_loc, "Decoration ignored in schema reference"); tc_e_etc("Expression: %z", t); tc_e_end(); } if (t->x_ref->x_sref_renames != nil) { tc_error(t->x_loc, "Renaming ignored in schema reference"); tc_e_etc("Expression: %z", t); tc_e_end(); } if (! aflag && d->d_abbrev) return mk_power(mk_abbrev(d, params)); else return mk_power(seal(mk_sproduct(d->d_schema), params)); } case POWER: { type tt1, tt2; if (! anal_power(tt1 = tc_expr(t->x_arg, e), &tt2, t->x_arg)) { tc_error(t->x_loc, "Argument of \\power must be a set"); tc_e_etc("Expression: %z", t); tc_e_etc("Arg type: %t", tt1); tc_e_end(); } return mk_power(mk_power(tt2)); } case TUPLE : { type a[MAX_ARGS]; int n = 0; tree u; for (u = t->x_elements; u != nil; u = cdr(u)) { if (n >= MAX_ARGS) panic("tc_expr - tuple too big"); a[n++] = tc_expr(car(u), e); } return mk_cproduct(n, a); } case CROSS: { type a[MAX_ARGS]; type tt1, tt2; int n = 0; tree u; for (u = t->x_factors; u != nil; u = cdr(u)) { if (n >= MAX_ARGS) panic("tc_expr - product too big"); tt1 = tc_expr(car(u), e); if (! anal_power(tt1, &tt2, car(u))) { tc_error(t->x_loc, "Argument %d of \\cross must be a set", n+1); tc_e_etc("Expression: %z", t); tc_e_etc("Arg %d type: %t", n+1, tt1); tc_e_end(); } a[n++] = tt2; } return mk_power(mk_cproduct(n, a)); } case EXT: case SEQ: case BAG: { type elem_type; type tt; tree u; if (t->x_elements == nil) elem_type = new_typevar(t); else { elem_type = tc_expr(car(t->x_elements), e); for (u = cdr(t->x_elements); u != nil; u = cdr(u)) { if (unify(elem_type, tt = tc_expr(car(u), e))) elem_type = type_union(elem_type, arid, tt, arid); else { tc_error(t->x_loc, "Type mismatch in %s display", (t->x_kind == EXT ? "set" : t->x_kind == SEQ ? "sequence" : "bag")); tc_e_etc("Expression: %z", car(u)); tc_e_etc("Has type: %t", tt); tc_e_etc("Expected: %t", elem_type); tc_e_end(); } } } switch (t->x_kind) { case EXT: return mk_power(elem_type); case SEQ: return (aflag ? rel_type(num_type, elem_type) : mk_seq(elem_type)); case BAG: return (aflag ? rel_type(elem_type, num_type) : mk_bag(elem_type)); } } case THETA: return theta_type(t, e, (type) NULL, t); case BINDING: { tree u; env e1 = new_env(e); for (u = t->x_elements; u != nil; u = cdr(u)) add_def(VAR, (sym) car(u)->x_lhs, tc_expr(car(u)->x_rhs, e), e1); return mk_sproduct(mk_schema(e1)); } case SELECT: { type a = tc_expr(t->x_arg, e); if (type_kind(a) != SPRODUCT) { tc_error(t->x_loc, "Argument of selection must have schema type"); tc_e_etc("Expression: %z", t); tc_e_etc("Arg type: %t", a); tc_e_end(); mark_error(); return err_type; } switch (t->x_field->x_kind) { case IDENT: return (comp_type(a, (sym) t->x_field, t, t->x_loc)); case THETA: return (theta_type(t->x_field, e, a, t)); default: bad_tag("tc_expr.SELECT", t->x_field->x_kind); return (type) NULL; } } case APPLY: return tc_apply(APPLY, t, t->x_arg1, t->x_arg2, e); case INOP: return tc_apply(INOP, t, simply(t->x_op, t->x_loc), pair(t->x_rand1, t->x_rand2), e); case POSTOP: return tc_apply(POSTOP, t, simply(t->x_op, t->x_loc), t->x_rand, e); case LAMBDA: { env e1 = tc_schema(t->x_bvar, e); type dom = tc_expr(char_tuple(t->x_bvar), e1); type ran = tc_expr(t->x_body, e1); return (aflag ? rel_type(dom, ran) : mk_pfun(dom, ran)); } case COMP: case MU: { env e1 = tc_schema(t->x_bvar, e); type a = tc_expr(exists(t->x_body) ? the(t->x_body) : char_tuple(t->x_bvar), e1); return (t->x_kind == COMP ? mk_power(a) : a); } case LETEXPR: return tc_expr(t->x_body, tc_letdefs(t->x_defs, e)); case IF: { type a, b; tc_pred(t->x_if, e); a = tc_expr(t->x_then, e); b = tc_expr(t->x_else, e); if (unify(a, b)) return type_union(a, arid, b, arid); else { tc_error(t->x_loc, "Type mismatch in conditional expression"); tc_e_etc("Expression: %z", t); tc_e_etc("Then type: %t", a); tc_e_etc("Else type: %t", b); tc_e_end(); return err_type; } } default: bad_tag("tc_expr", t->x_kind); /* dummy */ return (type) NULL; } }
int main(int argc, char *argv[]) { char exec_path[PATH_MAX]; char link_path[PATH_MAX]; uint32_t exec_path_size = sizeof(exec_path); char *compiler_path = exec_path; char *lastslash; int link = 1; int inputs = 0; int verbose = 0; int m_32_64_set = 0; /* Find the path to this executable. */ if (_NSGetExecutablePath(exec_path, &exec_path_size)) memcpy(exec_path, "/usr/bin/c99", sizeof("/usr/bin/c99")); if (realpath(exec_path, link_path)) compiler_path = link_path; /* Chop off c99 and replace it with clang. */ lastslash = strrchr(compiler_path, '/'); if (!lastslash) err(EX_OSERR, "unexpected path name: %s", compiler_path); strcpy(lastslash+1, "clang"); addarg(compiler_path); addarg("-std=iso9899:1999"); addarg("-pedantic"); addarg("-Wextra-tokens"); /* Radar 4205857 */ addarg("-Wno-error=return-type"); /* Radar 13535926 */ addarg("-Wstatic-in-inline"); /* Radar 12866627 */ addarg("-Wignored-qualifiers"); /* Radar 13535742 */ addarg("-fmath-errno"); /* Radar 4011622 */ addarg("-fno-blocks"); /* Radar 13118788 */ for (;;) { int ch = getopt(argc, argv, "cD:EgI:L:o:O:sU:W:l:"); if (optind >= argc && ch == -1) break; switch (ch) { case 'c': addarg ("-c"); link = 0; break; case 'D': add_def (optarg); break; case 'E': addarg ("-E"); link = 0; break; case 'g': addarg ("-g"); break; case 'I': combine_and_addarg ("-I", optarg); break; case 'L': combine_and_addarg ("-L", optarg); break; case 'o': addarg ("-o"); addarg (optarg); break; case 'O': combine_and_addarg ("-O", optarg); break; case 's': addarg ("-s"); break; case 'U': record_undef (optarg); combine_and_addarg ("-U", optarg); break; case 'W': if (strcmp (optarg, "32") == 0) { addarg ("-m32"); m_32_64_set = 1; } else if (strcmp (optarg, "64") == 0) { addarg ("-m64"); m_32_64_set = 1; } else if (strcmp (optarg, "verbose") == 0) { addarg ("-v"); verbose = 1; } else errx(EX_USAGE, "invalid argument `%s' to -W", optarg); break; case 'l': addlib (optarg); break; case -1: if (strcmp (argv[optind-1], "--") == 0) { while (optind < argc) { if (argv[optind][0] == '-') combine_and_addarg ("./", argv[optind]); else addarg (argv[optind]); inputs++; optind++; } } else { addarg (argv[optind++]); inputs++; } break; case '?': usage (); break; } } /* If the user didn't set the width, set it from the current host architecture. */ #ifdef __LP64__ if (!m_32_64_set) addarg("-m64"); #else if (!m_32_64_set) addarg("-m32"); #endif if (link && inputs > 0) { addarg("-liconv"); } if (verbose) { int i; for (i = 0; args[i]; i++) printf ("\"%s\" ", args[i]); putchar ('\n'); } /* Exec clang. */ execv(compiler_path, args); err(EX_OSERR, "failed to exec compiler %s", compiler_path); }
app * process_eq(func_decl * f, expr * arg1, expr * arg2) { expr * v; expr * t; if (uncnstr(arg1)) { v = arg1; t = arg2; } else if (uncnstr(arg2)) { v = arg2; t = arg1; } else { return nullptr; } sort * s = m().get_sort(arg1); // Remark: // I currently do not support unconstrained vars that have // uninterpreted sorts, for the following reasons: // - Soundness // (forall ((x S) (y S)) (= x y)) // (not (= c1 c2)) // // The constants c1 and c2 have only one occurrence in // the formula above, but they are not really unconstrained. // The quantifier forces S to have interpretations of size 1. // If we replace (= c1 c2) with fresh k. The formula will // become satisfiable. // // - Even if the formula is quantifier free, I would still // have to build an interpretation for the eliminated // variables. // if (!m().is_fully_interp(s)) return nullptr; // If the interpreted sort has only one element, // then it is unsound to eliminate the unconstrained variable in the equality sort_size sz = s->get_num_elements(); if (sz.is_finite() && sz.size() <= 1) return nullptr; if (!m_mc) { // easy case, model generation is disabled. app * u; mk_fresh_uncnstr_var_for(f, arg1, arg2, u); return u; } expr_ref d(m()); if (mk_diff(t, d)) { app * u; if (!mk_fresh_uncnstr_var_for(f, arg1, arg2, u)) return u; add_def(v, m().mk_ite(u, t, d)); return u; } return nullptr; }
app * process_basic_app(func_decl * f, unsigned num, expr * const * args) { SASSERT(f->get_family_id() == m().get_basic_family_id()); switch (f->get_decl_kind()) { case OP_ITE: SASSERT(num == 3); if (uncnstr(args[1]) && uncnstr(args[2])) { app * r; if (!mk_fresh_uncnstr_var_for(f, num, args, r)) return r; add_def(args[1], r); add_def(args[2], r); return r; } if (uncnstr(args[0]) && uncnstr(args[1])) { app * r; if (!mk_fresh_uncnstr_var_for(f, num, args, r)) return r; add_def(args[0], m().mk_true()); add_def(args[1], r); return r; } if (uncnstr(args[0]) && uncnstr(args[2])) { app * r; if (!mk_fresh_uncnstr_var_for(f, num, args, r)) return r; add_def(args[0], m().mk_false()); add_def(args[2], r); return r; } return nullptr; case OP_NOT: SASSERT(num == 1); if (uncnstr(args[0])) { app * r; if (!mk_fresh_uncnstr_var_for(f, num, args, r)) return r; if (m_mc) add_def(args[0], m().mk_not(r)); return r; } return nullptr; case OP_AND: if (num > 0 && uncnstr(num, args)) { app * r; if (!mk_fresh_uncnstr_var_for(f, num, args, r)) return r; if (m_mc) add_defs(num, args, r, m().mk_true()); return r; } return nullptr; case OP_OR: if (num > 0 && uncnstr(num, args)) { app * r; if (!mk_fresh_uncnstr_var_for(f, num, args, r)) return r; if (m_mc) add_defs(num, args, r, m().mk_false()); return r; } return nullptr; case OP_IFF: case OP_EQ: SASSERT(num == 2); return process_eq(f, args[0], args[1]); default: return nullptr; } }