def _cvc4_type_to_type(self, type_): if type_.isBoolean(): return types.BOOL elif type_.isInteger(): return types.INT elif type_.isReal(): return types.REAL elif type_.isArray(): # Casting Type into ArrayType type_ = CVC4.ArrayType(type_) # Recursively convert the types of index and elem idx_type = self._cvc4_type_to_type(type_.getIndexType()) elem_type = self._cvc4_type_to_type(type_.getConstituentType()) return types.ArrayType(idx_type, elem_type) elif type_.isBitVector(): # Casting Type into BitVectorType type_ = CVC4.BitVectorType(type_) return types.BVType(type_.getSize()) elif type_.isFunction(): # Casting Type into FunctionType type_ = CVC4.FunctionType(type_) return_type = type_.getRangeType() param_types = tuple( self._cvc4_type_to_type(ty) for ty in type_.getArgTypes()) return types.FunctionType(return_type, param_types) else: raise NotImplementedError("Unsupported type: %s" % type_)
def get_type(self): """Returns the type of variables: either INT or BV depending on the use_bv flag of the constructor """ if self.use_bv: return typing.BVType(self.bv_size) else: return typing.INT
def _z3_to_type(self, sort): if sort.kind() == z3.Z3_BOOL_SORT: return types.BOOL elif sort.kind() == z3.Z3_INT_SORT: return types.INT elif sort.kind() == z3.Z3_REAL_SORT: return types.REAL elif sort.kind() == z3.Z3_ARRAY_SORT: return types.ArrayType(self._z3_to_type(sort.domain()), self._z3_to_type(sort.range())) elif sort.kind() == z3.Z3_BV_SORT: return types.BVType(sort.size()) else: raise NotImplementedError("Unsupported sort in conversion: %s" % sort)
def _convert_sort(self, sort): kind = sort.get_sort_kind() if kind is ss.sortkinds.ARRAY: Kt = self._convert_sort(sort.get_indexsort()) Vt = self._convert_sort(sort.get_elemsort()) return pysmt_types.ArrayType(Kt, Vt) elif kind is ss.sortkinds.BOOL: return pysmt_types.BOOL elif kind is ss.sortkinds.BV: return pysmt_types.BVType(sort.get_width()) elif kind is ss.sortkinds.FUNCTION: domain = [self._convert_sort(s) for s in sort.get_domain_sorts()] codomain = self._convert_sort(sort.get_codomain()) return pysmt_types.FunctionType(codomain, domain) elif kind is ss.sortkinds.INT: return pysmt_types.INT else: assert kind is ss.sortkinds.REAL return pysmt_types.REAL
def test_bv2pysmt(self): bvx, bvy = Variable("x", 8), Variable("y", 8) psx, psy = bv2pysmt(bvx), bv2pysmt(bvy) self.assertEqual(bv2pysmt(Constant(0, 8)), sc.BV(0, 8)) self.assertEqual(psx, sc.Symbol("x", typing.BVType(8))) self.assertEqual(bv2pysmt(~bvx), sc.BVNot(psx)) self.assertEqual(bv2pysmt(bvx & bvy), sc.BVAnd(psx, psy)) self.assertEqual(bv2pysmt(bvx | bvy), sc.BVOr(psx, psy)) self.assertEqual(bv2pysmt(bvx ^ bvy), sc.BVXor(psx, psy)) self.assertEqual(bv2pysmt(BvComp(bvx, bvy)), sc.Equals(psx, psy)) self.assertEqual(bv2pysmt(BvNot(BvComp(bvx, bvy))), sc.Not(sc.Equals(psx, psy))) self.assertEqual(bv2pysmt(bvx < bvy), sc.BVULT(psx, psy)) self.assertEqual(bv2pysmt(bvx <= bvy), sc.BVULE(psx, psy)) self.assertEqual(bv2pysmt(bvx > bvy), sc.BVUGT(psx, psy)) self.assertEqual(bv2pysmt(bvx >= bvy), sc.BVUGE(psx, psy)) self.assertEqual(bv2pysmt(bvx << bvy), sc.BVLShl(psx, psy)) self.assertEqual(bv2pysmt(bvx >> bvy), sc.BVLShr(psx, psy)) self.assertEqual(bv2pysmt(RotateLeft(bvx, 1)), sc.BVRol(psx, 1)) self.assertEqual(bv2pysmt(RotateRight(bvx, 1)), sc.BVRor(psx, 1)) self.assertEqual(bv2pysmt(bvx[4:2]), sc.BVExtract(psx, 2, 4)) self.assertEqual(bv2pysmt(Concat(bvx, bvy)), sc.BVConcat(psx, psy)) # zeroextend reduces to Concat # self.assertEqual(bv2pysmt(ZeroExtend(bvx, 2)), sc.BVZExt(psx, 2)) self.assertEqual(bv2pysmt(Repeat(bvx, 2)), psx.BVRepeat(2)) self.assertEqual(bv2pysmt(-bvx), sc.BVNeg(psx)) self.assertEqual(bv2pysmt(bvx + bvy), sc.BVAdd(psx, psy)) # bvsum reduces to add # self.assertEqual(bv2pysmt(bvx - bvy), sc.BVSub(psx, psy)) self.assertEqual(bv2pysmt(bvx * bvy), sc.BVMul(psx, psy)) self.assertEqual(bv2pysmt(bvx / bvy), sc.BVUDiv(psx, psy)) self.assertEqual(bv2pysmt(bvx % bvy), sc.BVURem(psx, psy))
def nud(self, parser): return types.BVType(self.width)
def _back_single_term(self, term, mgr, args): """Builds the pysmt formula given a term and the list of formulae obtained by converting the term children. :param term: The MathSAT term to be transformed in pysmt formulae :type term: MathSAT term :param mgr: The formula manager to be sued to build the formulae, it should allow for type unsafety. :type mgr: Formula manager :param args: List of the pysmt formulae obtained by converting all the args (obtained by mathsat.msat_term_get_arg()) to pysmt formulae :type args: List of pysmt formulae :returns The pysmt formula representing the given term :rtype Pysmt formula """ res = None arity = len(args) if mathsat.msat_term_is_true(self.msat_env, term): res = mgr.TRUE() elif mathsat.msat_term_is_false(self.msat_env, term): res = mgr.FALSE() elif mathsat.msat_term_is_number(self.msat_env, term): ty = mathsat.msat_term_get_type(term) if mathsat.msat_is_integer_type(self.msat_env, ty): res = mgr.Int(int(mathsat.msat_term_repr(term))) elif mathsat.msat_is_rational_type(self.msat_env, ty): res = mgr.Real(Fraction(mathsat.msat_term_repr(term))) else: assert "_" in str( term), "Unsupported type for '%s'" % str(term) val, width = str(term).split("_") val = int(val) width = int(width) res = mgr.BV(val, width) elif mathsat.msat_term_is_and(self.msat_env, term): res = mgr.And(args) elif mathsat.msat_term_is_or(self.msat_env, term): res = mgr.Or(args) elif mathsat.msat_term_is_not(self.msat_env, term): assert arity == 1 res = mgr.Not(args[0]) elif mathsat.msat_term_is_iff(self.msat_env, term): assert arity == 2 res = mgr.Iff(args[0], args[1]) elif mathsat.msat_term_is_term_ite(self.msat_env, term): assert arity == 3 res = mgr.Ite(args[0], args[1], args[2]) elif mathsat.msat_term_is_equal(self.msat_env, term): assert arity == 2 res = mgr.Equals(args[0], args[1]) elif mathsat.msat_term_is_leq(self.msat_env, term): assert arity == 2 res = mgr.LE(args[0], args[1]) elif mathsat.msat_term_is_plus(self.msat_env, term): res = mgr.Plus(args) elif mathsat.msat_term_is_times(self.msat_env, term): assert arity == 2 res = mgr.Times(args[0], args[1]) elif mathsat.msat_term_is_boolean_constant(self.msat_env, term): rep = mathsat.msat_term_repr(term) res = mgr.Symbol(rep, types.BOOL) elif mathsat.msat_term_is_constant(self.msat_env, term): rep = mathsat.msat_term_repr(term) ty = mathsat.msat_term_get_type(term) if mathsat.msat_is_rational_type(self.msat_env, ty): res = mgr.Symbol(rep, types.REAL) elif mathsat.msat_is_integer_type(self.msat_env, ty): res = mgr.Symbol(rep, types.INT) else: _, width = mathsat.msat_is_bv_type(self.msat_env, ty) assert width is not None, "Unsupported variable type for '%s'" % str( term) res = mgr.Symbol(rep, types.BVType(width)) elif mathsat.msat_term_is_uf(self.msat_env, term): d = mathsat.msat_term_get_decl(term) fun = self.get_symbol_from_declaration(d) res = mgr.Function(fun, args) elif mathsat.msat_term_is_bv_times(self.msat_env, term): assert arity == 2 res = mgr.BVMul(args[0], args[1]) elif mathsat.msat_term_is_bv_plus(self.msat_env, term): assert arity == 2 res = mgr.BVAdd(args[0], args[1]) elif mathsat.msat_term_is_bv_udiv(self.msat_env, term): assert arity == 2 res = mgr.BVUDiv(args[0], args[1]) elif mathsat.msat_term_is_bv_urem(self.msat_env, term): assert arity == 2 res = mgr.BVURem(args[0], args[1]) elif mathsat.msat_term_is_bv_extract(self.msat_env, term)[0]: assert arity == 1 res, msb, lsb = mathsat.msat_term_is_bv_extract( self.msat_env, term) assert res res = mgr.BVExtract(args[0], lsb, msb) elif mathsat.msat_term_is_bv_concat(self.msat_env, term): assert arity == 2 res = mgr.BVConcat(args[0], args[1]) elif mathsat.msat_term_is_bv_or(self.msat_env, term): assert arity == 2 res = mgr.BVOr(args[0], args[1]) elif mathsat.msat_term_is_bv_xor(self.msat_env, term): assert arity == 2 res = mgr.BVXor(args[0], args[1]) elif mathsat.msat_term_is_bv_and(self.msat_env, term): assert arity == 2 res = mgr.BVAnd(args[0], args[1]) elif mathsat.msat_term_is_bv_not(self.msat_env, term): assert arity == 1 res = mgr.BVNot(args[0]) elif mathsat.msat_term_is_bv_minus(self.msat_env, term): assert arity == 2 res = mgr.BVSub(args[0], args[1]) elif mathsat.msat_term_is_bv_neg(self.msat_env, term): assert arity == 1 res = mgr.BVSub(args[0]) elif mathsat.msat_term_is_bv_srem(self.msat_env, term): assert arity == 2 res = mgr.BVSRem(args[0], args[1]) elif mathsat.msat_term_is_bv_sdiv(self.msat_env, term): assert arity == 2 res = mgr.BVSDiv(args[0], args[1]) elif mathsat.msat_term_is_bv_ult(self.msat_env, term): assert arity == 2 res = mgr.BVULT(args[0], args[1]) elif mathsat.msat_term_is_bv_slt(self.msat_env, term): assert arity == 2 res = mgr.BVSLT(args[0], args[1]) elif mathsat.msat_term_is_bv_uleq(self.msat_env, term): assert arity == 2 res = mgr.BVULE(args[0], args[1]) elif mathsat.msat_term_is_bv_sleq(self.msat_env, term): assert arity == 2 res = mgr.BVSLE(args[0], args[1]) elif mathsat.msat_term_is_bv_lshl(self.msat_env, term): assert arity == 2 res = mgr.BVLShl(args[0], args[1]) elif mathsat.msat_term_is_bv_lshr(self.msat_env, term): assert arity == 2 res = mgr.BVLShr(args[0], args[1]) elif mathsat.msat_term_is_bv_ashr(self.msat_env, term): assert arity == 2 res = mgr.BVAShr(args[0], args[1]) elif mathsat.msat_term_is_bv_comp(self.msat_env, term): assert arity == 2 res = mgr.BVComp(args[0], args[1]) elif mathsat.msat_term_is_bv_zext(self.msat_env, term)[0]: assert arity == 2 res, amount = mathsat.msat_term_is_bv_zext(self.msat_env, term) assert res res = mgr.BVZExt(args[0], amount) elif mathsat.msat_term_is_bv_sext(self.msat_env, term)[0]: assert arity == 2 res, amount = mathsat.msat_term_is_bv_sext(self.msat_env, term) assert res res = mgr.BVSExt(args[0], amount) elif mathsat.msat_term_is_bv_rol(self.msat_env, term)[0]: assert arity == 2 res, amount = mathsat.msat_term_is_bv_ror(self.msat_env, term) assert res res = mgr.BVRol(args[0], amount) elif mathsat.msat_term_is_bv_ror(self.msat_env, term)[0]: assert arity == 2 res, amount = mathsat.msat_term_is_bv_ror(self.msat_env, term) assert res res = mgr.BVRor(args[0], amount) else: raise TypeError("Unsupported expression:", mathsat.msat_term_repr(term)) return res
def _get_signature(self, term, args): """Returns the signature of the given term. For example: - a term x & y returns a function type Bool -> Bool -> Bool, - a term 14 returns Int - a term x ? 13 : 15.0 returns Bool -> Real -> Real -> Real """ res = None if mathsat.msat_term_is_true(self.msat_env, term) or \ mathsat.msat_term_is_false(self.msat_env, term) or \ mathsat.msat_term_is_boolean_constant(self.msat_env, term): res = types.BOOL elif mathsat.msat_term_is_number(self.msat_env, term): ty = mathsat.msat_term_get_type(term) if mathsat.msat_is_integer_type(self.msat_env, ty): res = types.INT elif mathsat.msat_is_rational_type(self.msat_env, ty): res = types.REAL else: assert "_" in str( term), "Unrecognized type for '%s'" % str(term) width = int(str(term).split("_")[1]) res = types.BVType(width) elif mathsat.msat_term_is_and(self.msat_env, term) or \ mathsat.msat_term_is_or(self.msat_env, term) or \ mathsat.msat_term_is_iff(self.msat_env, term): res = types.FunctionType(types.BOOL, [types.BOOL, types.BOOL]) elif mathsat.msat_term_is_not(self.msat_env, term): res = types.FunctionType(types.BOOL, [types.BOOL]) elif mathsat.msat_term_is_term_ite(self.msat_env, term): t1 = self.env.stc.get_type(args[1]) t2 = self.env.stc.get_type(args[2]) t = self._most_generic(t1, t2) res = types.FunctionType(t, [types.BOOL, t, t]) elif mathsat.msat_term_is_equal(self.msat_env, term) or \ mathsat.msat_term_is_leq(self.msat_env, term): t1 = self.env.stc.get_type(args[0]) t2 = self.env.stc.get_type(args[1]) t = self._most_generic(t1, t2) res = types.FunctionType(types.BOOL, [t, t]) elif mathsat.msat_term_is_plus(self.msat_env, term) or \ mathsat.msat_term_is_times(self.msat_env, term): t1 = self.env.stc.get_type(args[0]) t2 = self.env.stc.get_type(args[1]) t = self._most_generic(t1, t2) res = types.FunctionType(t, [t, t]) elif mathsat.msat_term_is_constant(self.msat_env, term): ty = mathsat.msat_term_get_type(term) if mathsat.msat_is_rational_type(self.msat_env, ty): res = types.REAL elif mathsat.msat_is_integer_type(self.msat_env, ty): res = types.INT else: _, width = mathsat.msat_is_bv_type(self.msat_env, ty) assert width is not None, "Unsupported type for '%s'" % str( term) res = types.BVType(width) elif mathsat.msat_term_is_uf(self.msat_env, term): d = mathsat.msat_term_get_decl(term) fun = self.get_symbol_from_declaration(d) res = fun.symbol_type() elif mathsat.msat_term_is_bv_times(self.msat_env, term) or \ mathsat.msat_term_is_bv_plus(self.msat_env, term) or \ mathsat.msat_term_is_bv_minus(self.msat_env, term) or \ mathsat.msat_term_is_bv_or(self.msat_env, term) or \ mathsat.msat_term_is_bv_and(self.msat_env, term) or \ mathsat.msat_term_is_bv_lshl(self.msat_env, term) or \ mathsat.msat_term_is_bv_lshr(self.msat_env, term) or \ mathsat.msat_term_is_bv_ashr(self.msat_env, term) or \ mathsat.msat_term_is_bv_xor(self.msat_env, term) or \ mathsat.msat_term_is_bv_urem(self.msat_env, term) or \ mathsat.msat_term_is_bv_udiv(self.msat_env, term) or \ mathsat.msat_term_is_bv_sdiv(self.msat_env, term) or \ mathsat.msat_term_is_bv_srem(self.msat_env, term) or \ mathsat.msat_term_is_bv_concat(self.msat_env, term): t = self.env.stc.get_type(args[0]) res = types.FunctionType(t, [t, t]) elif mathsat.msat_term_is_bv_not(self.msat_env, term) or \ mathsat.msat_term_is_bv_neg(self.msat_env, term): t = self.env.stc.get_type(args[0]) res = types.FunctionType(t, [t]) elif mathsat.msat_term_is_bv_ult(self.msat_env, term) or \ mathsat.msat_term_is_bv_slt(self.msat_env, term) or \ mathsat.msat_term_is_bv_uleq(self.msat_env, term) or \ mathsat.msat_term_is_bv_sleq(self.msat_env, term): t = self.env.stc.get_type(args[0]) res = types.FunctionType(types.BOOL, [t, t]) elif mathsat.msat_term_is_bv_comp(self.msat_env, term): t = self.env.stc.get_type(args[0]) res = types.FunctionType(types.BVType(1), [t, t]) elif mathsat.msat_term_is_bv_rol(self.msat_env, term)[0] or \ mathsat.msat_term_is_bv_ror(self.msat_env, term)[0]: t = self.env.stc.get_type(args[0]) res = types.FunctionType(t, [t]) elif mathsat.msat_term_is_bv_sext(self.msat_env, term)[0]: _, amount = mathsat.msat_term_is_bv_sext(self.msat_env, term) t = self.env.stc.get_type(args[0]) res = types.FunctionType(types.BVType(amount + t.width), [t]) elif mathsat.msat_term_is_bv_zext(self.msat_env, term)[0]: _, amount = mathsat.msat_term_is_bv_zext(self.msat_env, term) t = self.env.stc.get_type(args[0]) res = types.FunctionType(types.BVType(amount + t.width), [t]) elif mathsat.msat_term_is_bv_extract(self.msat_env, term)[0]: _, msb, lsb = mathsat.msat_term_is_bv_extract(self.msat_env, term) t = self.env.stc.get_type(args[0]) res = types.FunctionType(types.BVType(msb - lsb + 1), [t]) else: raise TypeError("Unsupported expression:", mathsat.msat_term_repr(term)) return res
def bv2pysmt(bv): """Convert a bit-vector type to a pySMT type. >>> from arxpy.bitvector.core import Constant, Variable >>> from arxpy.diffcrypt.smt import bv2pysmt >>> bv2pysmt(Constant(0b00000001, 8)) 1_8 >>> x, y = Variable("x", 8), Variable("y", 8) >>> bv2pysmt(x) x >>> bv2pysmt(x + y) (x + y) >>> bv2pysmt(x <= y) (x u<= y) >>> bv2pysmt(x[4: 2]) x[2:4] """ msg = "unknown conversion of {} to a pySMT type".format(type(bv).__name__) if isinstance(bv, int): return bv if isinstance(bv, core.Variable): return sc.Symbol(bv.name, typing.BVType(bv.width)) if isinstance(bv, core.Constant): return sc.BV(bv.val, bv.width) if isinstance(bv, operation.Operation): args = [bv2pysmt(a) for a in bv.args] if type(bv) == operation.BvNot: if args[0].is_equals(): return sc.Not(*args) else: return sc.BVNot(*args) if type(bv) == operation.BvAnd: return sc.BVAnd(*args) if type(bv) == operation.BvOr: return sc.BVOr(*args) if type(bv) == operation.BvXor: return sc.BVXor(*args) if type(bv) == operation.BvComp: # return sc.BVComp(*args) return sc.Equals(*args) if type(bv) == operation.BvUlt: return sc.BVULT(*args) if type(bv) == operation.BvUle: return sc.BVULE(*args) if type(bv) == operation.BvUgt: return sc.BVUGT(*args) if type(bv) == operation.BvUge: return sc.BVUGE(*args) if type(bv) == operation.BvShl: # Left hand side width must be a power of 2 if (args[0].bv_width() & (args[0].bv_width() - 1)) == 0: return sc.BVLShl(*args) else: x, r = bv.args offset = 0 while (x.width & (x.width - 1)) != 0: x = operation.ZeroExtend(x, 1) r = operation.ZeroExtend(r, 1) offset += 1 shift = bv2pysmt(x << r) return sc.BVExtract(shift, end=shift.bv_width() - offset - 1) # width = args[0].bv_width() # assert (width & (width - 1)) == 0 # power of 2 # return sc.BVLShl(*args) if type(bv) == operation.BvLshr: # Left hand side width must be a power of 2 if (args[0].bv_width() & (args[0].bv_width() - 1)) == 0: return sc.BVLShr(*args) else: x, r = bv.args offset = 0 while (x.width & (x.width - 1)) != 0: x = operation.ZeroExtend(x, 1) r = operation.ZeroExtend(r, 1) offset += 1 shift = bv2pysmt(x >> r) return sc.BVExtract(shift, end=shift.bv_width() - offset - 1) # width = args[1].bv_width() # assert (width & (width - 1)) == 0 # power of 2 # return sc.BVLShr(*args) if type(bv) == operation.RotateLeft: # Left hand side width must be a power of 2 if (args[0].bv_width() & (args[0].bv_width() - 1)) == 0: return sc.BVRol(*args) else: x, r = bv.args n = x.width return bv2pysmt(operation.Concat(x[n - r - 1:], x[n - 1:n - r])) if type(bv) == operation.RotateRight: # Left hand side width must be a power of 2 if (args[0].bv_width() & (args[0].bv_width() - 1)) == 0: return sc.BVRor(*args) else: x, r = bv.args n = x.width return bv2pysmt(operation.Concat(x[r - 1:], x[n - 1:r])) if type(bv) == operation.Ite: if args[0].is_equals(): a0 = args[0] else: a0 = sc.Equals(args[0], bv2pysmt(core.Constant(1, 1))) return sc.Ite(a0, *args[1:]) if type(bv) == operation.Extract: return sc.BVExtract(args[0], args[2], args[1]) if type(bv) == operation.Concat: return sc.BVConcat(*args) if type(bv) == operation.ZeroExtend: return sc.BVZExt(*args) if type(bv) == operation.Repeat: return args[0].BVRepeat(args[1]) if type(bv) == operation.BvNeg: return sc.BVNeg(*args) if type(bv) == operation.BvAdd: return sc.BVAdd(*args) if type(bv) == operation.BvSub: return sc.BVSub(*args) if type(bv) == operation.BvMul: return sc.BVMul(*args) if type(bv) == operation.BvMul: return sc.BVMul(*args) if type(bv) == operation.BvUdiv: return sc.BVUDiv(*args) if type(bv) == operation.BvUrem: return sc.BVURem(*args) raise NotImplementedError(msg)