func_decl * bv_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned num_args, expr * const * args, sort * range) { int bv_size; if (k == OP_INT2BV && get_int2bv_size(num_parameters, parameters, bv_size)) { // bv_size is filled in. } else if (k == OP_BV_NUM) { return mk_num_decl(num_parameters, parameters, num_args); } else if (k == OP_BIT0) { return m_bit0; } else if (k == OP_BIT1) { return m_bit1; } else if (k == OP_CARRY) { return m_carry; } else if (k == OP_XOR3) { return m_xor3; } else if (k == OP_MKBV) { return decl_plugin::mk_func_decl(k, num_parameters, parameters, num_args, args, range); } else if (num_args == 0 || !get_bv_size(args[0], bv_size)) { m_manager->raise_exception("operator is applied to arguments of the wrong sort"); return 0; } func_decl * r = mk_func_decl(k, bv_size); if (r != 0) { return r; } return decl_plugin::mk_func_decl(k, num_parameters, parameters, num_args, args, range); }
// help get a list of positions from variable int get_pos_from_var(list_t *vars, char *var_name, int **pos) { variable_t *pos_var = find_variable(vars, var_name); int num_pos = 0; if (pos_var->is_id) { // dealing with row id, assign directly num_pos = get_list_size(pos_var->ids); *pos = calloc(num_pos, sizeof(int)); memcpy(*pos, pos_var->ids->data, sizeof(int) * num_pos); } else { // now we need to convert from bit vector num_pos = get_bv_count(pos_var->bv); *pos = calloc(num_pos, sizeof(int)); // go through the whole bit vector to get the values // TODO: should be a better strategy than this! uint32_t size = get_bv_size(pos_var->bv); uint32_t itr = 0; for (uint32_t u=0; u < size; u++) { if (is_marked(pos_var->bv, u)) { (*pos)[itr] = u; itr ++; } } debug("Itr ended at %d\n", itr); dbg_assert(itr == num_pos); } return num_pos; }
func_decl * bv_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned num_args, expr * const * args, sort * range) { ast_manager& m = *m_manager; int bv_size; if (k == OP_INT2BV && get_int2bv_size(num_parameters, parameters, bv_size)) { // bv_size is filled in. } else if (k == OP_BV_NUM) { return mk_num_decl(num_parameters, parameters, num_args); } else if (k == OP_BIT0) { return m_bit0; } else if (k == OP_BIT1) { return m_bit1; } else if (k == OP_CARRY) { return m_carry; } else if (k == OP_XOR3) { return m_xor3; } else if (k == OP_MKBV) { return decl_plugin::mk_func_decl(k, num_parameters, parameters, num_args, args, range); } else if (num_args == 0 || !get_bv_size(args[0], bv_size)) { m.raise_exception("operator is applied to arguments of the wrong sort"); return nullptr; } func_decl * r = mk_func_decl(k, bv_size); if (r != nullptr) { if (num_args != r->get_arity()) { if (r->get_info()->is_associative()) { sort * fs = r->get_domain(0); for (unsigned i = 0; i < num_args; ++i) { if (m.get_sort(args[i]) != fs) { m_manager->raise_exception("declared sorts do not match supplied sorts"); return nullptr; } } return r; } else { m.raise_exception("declared arity mismatches supplied arity"); return nullptr; } } for (unsigned i = 0; i < num_args; ++i) { if (m.get_sort(args[i]) != r->get_domain(i)) { std::ostringstream buffer; buffer << "Argument " << mk_pp(args[i], m) << " at position " << i << " does not match declaration " << mk_pp(r, m); m.raise_exception(buffer.str().c_str()); return nullptr; } } return r; } return decl_plugin::mk_func_decl(k, num_parameters, parameters, num_args, args, range); }
bool bv_decl_plugin::get_extend_size(unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, int & result) { int arg_sz; if (arity != 1 || num_parameters != 1 || !parameters[0].is_int() || !get_bv_size(domain[0], arg_sz)) { return false; } result = arg_sz + parameters[0].get_int(); return true; }
bool bv_decl_plugin::get_concat_size(unsigned arity, sort * const * domain, int & result) { result = 0; for (unsigned i = 0; i < arity; i++) { int sz; if (!get_bv_size(domain[i], sz)) { return false; } result += sz; } return true; }
bool reduce_arg(expr* a, expr_ref& result) { sort* s = get_sort(a); if (!m_imp.is_fd(s)) { return false; } unsigned bv_size = get_bv_size(s); if (is_var(a)) { result = m.mk_var(to_var(a)->get_idx(), m_bv.mk_sort(bv_size)); return true; } SASSERT(is_app(a)); func_decl* f = to_app(a)->get_decl(); if (m_dt.is_constructor(f)) { unsigned idx = m_dt.get_constructor_idx(f); result = m_bv.mk_numeral(idx, bv_size); } else if (is_uninterp_const(a)) { func_decl* f_fresh; if (m_imp.m_enum2bv.find(f, f_fresh)) { result = m.mk_const(f_fresh); return true; } // create a fresh variable, add bounds constraints for it. unsigned nc = m_dt.get_datatype_num_constructors(s); result = m.mk_fresh_const(f->get_name().str().c_str(), m_bv.mk_sort(bv_size)); f_fresh = to_app(result)->get_decl(); if (!is_power_of_two(nc) || nc == 1) { m_imp.m_bounds.push_back(m_bv.mk_ule(result, m_bv.mk_numeral(nc-1, bv_size))); } expr_ref f_def(m); ptr_vector<func_decl> const& cs = *m_dt.get_datatype_constructors(s); f_def = m.mk_const(cs[nc-1]); for (unsigned i = nc - 1; i > 0; ) { --i; f_def = m.mk_ite(m.mk_eq(result, m_bv.mk_numeral(i,bv_size)), m.mk_const(cs[i]), f_def); } m_imp.m_enum2def.insert(f, f_def); m_imp.m_enum2bv.insert(f, f_fresh); m_imp.m_bv2enum.insert(f_fresh, f); m_imp.m_enum_consts.push_back(f); m_imp.m_enum_bvs.push_back(f_fresh); m_imp.m_enum_defs.push_back(f_def); } else { throw_non_fd(a); } ++m_imp.m_num_translated; return true; }
bool reduce_quantifier( quantifier * q, expr * old_body, expr * const * new_patterns, expr * const * new_no_patterns, expr_ref & result, proof_ref & result_pr) { if (q->get_kind() == lambda_k) return false; m_sorts.reset(); expr_ref_vector bounds(m); bool found = false; for (unsigned i = 0; i < q->get_num_decls(); ++i) { sort* s = q->get_decl_sort(i); if (m_imp.is_fd(s)) { unsigned bv_size = get_bv_size(s); m_sorts.push_back(m_bv.mk_sort(bv_size)); unsigned nc = m_dt.get_datatype_num_constructors(s); if (!is_power_of_two(nc) || nc == 1) { bounds.push_back(m_bv.mk_ule(m.mk_var(q->get_num_decls()-i-1, m_sorts[i]), m_bv.mk_numeral(nc-1, bv_size))); } found = true; } else { m_sorts.push_back(s); } } if (!found) { return false; } expr_ref new_body_ref(old_body, m), tmp(m); if (!bounds.empty()) { switch (q->get_kind()) { case forall_k: new_body_ref = m.mk_implies(mk_and(bounds), new_body_ref); break; case exists_k: bounds.push_back(new_body_ref); new_body_ref = mk_and(bounds); break; case lambda_k: UNREACHABLE(); break; } } result = m.mk_quantifier(q->get_kind(), q->get_num_decls(), m_sorts.c_ptr(), q->get_decl_names(), new_body_ref, q->get_weight(), q->get_qid(), q->get_skid(), q->get_num_patterns(), new_patterns, q->get_num_no_patterns(), new_no_patterns); result_pr = nullptr; return true; }
bool bv_decl_plugin::get_int2bv_size(unsigned num_parameters, parameter const * parameters, int & result) { if (num_parameters != 1) { m_manager->raise_exception("int2bv expects one parameter"); return false; } const parameter &p = parameters[0]; if (p.is_int()) { result = p.get_int(); return true; } if (!p.is_ast() || !is_expr(p.get_ast())) { m_manager->raise_exception("int2bv expects one integer parameter"); return false; } return get_bv_size(to_expr(p.get_ast()), result); }
func_decl * bv_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { int bv_size; if (k == OP_INT2BV && get_int2bv_size(num_parameters, parameters, bv_size)) { // bv_size is filled in. } else if (k == OP_BV_NUM) { return mk_num_decl(num_parameters, parameters, arity); } else if (k == OP_BIT0) { return m_bit0; } else if (k == OP_BIT1) { return m_bit1; } else if (k == OP_CARRY) { return m_carry; } else if (k == OP_XOR3) { return m_xor3; } else if (k == OP_MKBV) { return mk_mkbv(arity, domain); } else if (arity == 0) { m_manager->raise_exception("no arguments supplied to bit-vector operator"); return nullptr; } else if (!get_bv_size(domain[0], bv_size)) { m_manager->raise_exception("could not extract bit-vector size"); return nullptr; } func_decl * r = mk_func_decl(k, bv_size); if (r != nullptr) { if (arity != r->get_arity()) { if (r->get_info()->is_associative()) arity = r->get_arity(); else { m_manager->raise_exception("declared arity mismatches supplied arity"); return nullptr; } } for (unsigned i = 0; i < arity; ++i) { if (domain[i] != r->get_domain(i)) { m_manager->raise_exception("declared sorts do not match supplied sorts"); return nullptr; } } return r; } int r_size; switch (k) { case OP_BIT2BOOL: return mk_bit2bool(bv_size, num_parameters, parameters, arity, domain); case OP_INT2BV: return mk_int2bv(bv_size, num_parameters, parameters, arity, domain); case OP_BV2INT: return mk_bv2int(bv_size, num_parameters, parameters, arity, domain); case OP_CONCAT: if (!get_concat_size(arity, domain, r_size)) m_manager->raise_exception("invalid concat application"); return m_manager->mk_func_decl(m_concat_sym, arity, domain, get_bv_sort(r_size), func_decl_info(m_family_id, k)); case OP_SIGN_EXT: if (!get_extend_size(num_parameters, parameters, arity, domain, r_size)) m_manager->raise_exception("invalid sign_extend application"); return m_manager->mk_func_decl(m_sign_extend_sym, arity, domain, get_bv_sort(r_size), func_decl_info(m_family_id, k, num_parameters, parameters)); case OP_ZERO_EXT: if (!get_extend_size(num_parameters, parameters, arity, domain, r_size)) m_manager->raise_exception("invalid zero_extend application"); return m_manager->mk_func_decl(m_zero_extend_sym, arity, domain, get_bv_sort(r_size), func_decl_info(m_family_id, k, num_parameters, parameters)); case OP_EXTRACT: if (!get_extract_size(num_parameters, parameters, arity, domain, r_size)) m_manager->raise_exception("invalid extract application"); return m_manager->mk_func_decl(m_extract_sym, arity, domain, get_bv_sort(r_size), func_decl_info(m_family_id, k, num_parameters, parameters)); case OP_ROTATE_LEFT: if (arity != 1) m_manager->raise_exception("rotate left expects one argument"); return m_manager->mk_func_decl(m_rotate_left_sym, arity, domain, domain[0], func_decl_info(m_family_id, k, num_parameters, parameters)); case OP_ROTATE_RIGHT: if (arity != 1) m_manager->raise_exception("rotate right expects one argument"); return m_manager->mk_func_decl(m_rotate_right_sym, arity, domain, domain[0], func_decl_info(m_family_id, k, num_parameters, parameters)); case OP_REPEAT: if (arity != 1) m_manager->raise_exception("repeat expects one argument"); if (num_parameters != 1 || !parameters[0].is_int() || parameters[0].get_int() == 0) m_manager->raise_exception("repeat expects one nonzero integer parameter"); if (!get_bv_size(domain[0], bv_size)) m_manager->raise_exception("repeat expects an argument with bit-vector sort"); return m_manager->mk_func_decl(m_repeat_sym, arity, domain, get_bv_sort(bv_size * parameters[0].get_int()), func_decl_info(m_family_id, k, num_parameters, parameters)); default: return nullptr; } }
inline bool bv_decl_plugin::get_bv_size(expr * t, int & result) { return get_bv_size(m_manager->get_sort(t), result); }