def type_compatibility(self, fromty, toty): """ Returns None or a string describing the conversion e.g. exact, promote, unsafe, safe, tuple-coerce """ if fromty == toty: return 'exact' elif (isinstance(fromty, types.UniTuple) and isinstance(toty, types.UniTuple) and len(fromty) == len(toty)): return self.type_compatibility(fromty.dtype, toty.dtype) elif (types.is_int_tuple(fromty) and types.is_int_tuple(toty) and len(fromty) == len(toty)): return 'int-tuple-coerce' return self.tm.check_compatible(fromty, toty)
def cast(self, builder, val, fromty, toty): if fromty == toty or toty == types.Any or isinstance(toty, types.Kind): return val elif ((fromty in types.unsigned_domain and toty in types.signed_domain) or (fromty in types.integer_domain and toty in types.unsigned_domain)): lfrom = self.get_value_type(fromty) lto = self.get_value_type(toty) if lfrom.width <= lto.width: return builder.zext(val, lto) elif lfrom.width > lto.width: return builder.trunc(val, lto) elif fromty in types.signed_domain and toty in types.signed_domain: lfrom = self.get_value_type(fromty) lto = self.get_value_type(toty) if lfrom.width <= lto.width: return builder.sext(val, lto) elif lfrom.width > lto.width: return builder.trunc(val, lto) elif fromty in types.real_domain and toty in types.real_domain: lty = self.get_value_type(toty) if fromty == types.float32 and toty == types.float64: return builder.fpext(val, lty) elif fromty == types.float64 and toty == types.float32: return builder.fptrunc(val, lty) elif fromty in types.real_domain and toty in types.complex_domain: if fromty == types.float32: if toty == types.complex128: real = self.cast(builder, val, fromty, types.float64) else: real = val elif fromty == types.float64: if toty == types.complex64: real = self.cast(builder, val, fromty, types.float32) else: real = val if toty == types.complex128: imag = self.get_constant(types.float64, 0) elif toty == types.complex64: imag = self.get_constant(types.float32, 0) else: raise Exception("unreachable") cmplx = self.make_complex(toty)(self, builder) cmplx.real = real cmplx.imag = imag return cmplx._getvalue() elif fromty in types.integer_domain and toty in types.real_domain: lty = self.get_value_type(toty) if fromty in types.signed_domain: return builder.sitofp(val, lty) else: return builder.uitofp(val, lty) elif toty in types.integer_domain and fromty in types.real_domain: lty = self.get_value_type(toty) if toty in types.signed_domain: return builder.fptosi(val, lty) else: return builder.fptoui(val, lty) elif fromty in types.integer_domain and toty in types.complex_domain: cmplxcls, flty = builtins.get_complex_info(toty) cmpl = cmplxcls(self, builder) cmpl.real = self.cast(builder, val, fromty, flty) cmpl.imag = self.get_constant(flty, 0) return cmpl._getvalue() elif fromty in types.complex_domain and toty in types.complex_domain: srccls, srcty = builtins.get_complex_info(fromty) dstcls, dstty = builtins.get_complex_info(toty) src = srccls(self, builder, value=val) dst = dstcls(self, builder) dst.real = self.cast(builder, src.real, srcty, dstty) dst.imag = self.cast(builder, src.imag, srcty, dstty) return dst._getvalue() elif (isinstance(toty, types.UniTuple) and isinstance(fromty, types.UniTuple) and len(fromty) == len(toty)): olditems = cgutils.unpack_tuple(builder, val, len(fromty)) items = [self.cast(builder, i, fromty.dtype, toty.dtype) for i in olditems] tup = self.get_constant_undef(toty) for idx, val in enumerate(items): tup = builder.insert_value(tup, val, idx) return tup elif (types.is_int_tuple(toty) and types.is_int_tuple(fromty) and len(toty) == len(fromty)): olditems = cgutils.unpack_tuple(builder, val, len(fromty)) items = [self.cast(builder, i, t, toty.dtype) for i, t in zip(olditems, fromty.types)] tup = self.get_constant_undef(toty) for idx, val in enumerate(items): tup = builder.insert_value(tup, val, idx) return tup elif toty == types.boolean: return self.is_true(builder, fromty, val) elif fromty == types.boolean: # first promote to int32 asint = builder.zext(val, Type.int()) # then promote to number return self.cast(builder, asint, types.int32, toty) elif fromty == types.none and isinstance(toty, types.Optional): return self.make_optional_none(builder, toty.type) elif isinstance(toty, types.Optional): casted = self.cast(builder, val, fromty, toty.type) return self.make_optional_value(builder, toty.type, casted) elif isinstance(fromty, types.Optional): optty = self.make_optional(fromty) optval = optty(self, builder, value=val) validbit = cgutils.as_bool_bit(builder, optval.valid) with cgutils.if_unlikely(builder, builder.not_(validbit)): self.return_errcode(builder, errcode.NONE_TYPE_ERROR) return optval.data elif (isinstance(fromty, types.Array) and isinstance(toty, types.Array)): # Type inference should have prevented illegal array casting. assert toty.layout == 'A' return val raise NotImplementedError("cast", val, fromty, toty)
def cast(self, builder, val, fromty, toty): if fromty == toty or toty == types.Any or isinstance(toty, types.Kind): return val elif ((fromty in types.unsigned_domain and toty in types.signed_domain) or (fromty in types.integer_domain and toty in types.unsigned_domain)): lfrom = self.get_value_type(fromty) lto = self.get_value_type(toty) if lfrom.width <= lto.width: return builder.zext(val, lto) elif lfrom.width > lto.width: return builder.trunc(val, lto) elif fromty in types.signed_domain and toty in types.signed_domain: lfrom = self.get_value_type(fromty) lto = self.get_value_type(toty) if lfrom.width <= lto.width: return builder.sext(val, lto) elif lfrom.width > lto.width: return builder.trunc(val, lto) elif fromty in types.real_domain and toty in types.real_domain: lty = self.get_value_type(toty) if fromty == types.float32 and toty == types.float64: return builder.fpext(val, lty) elif fromty == types.float64 and toty == types.float32: return builder.fptrunc(val, lty) elif fromty in types.real_domain and toty in types.complex_domain: if fromty == types.float32: if toty == types.complex128: real = self.cast(builder, val, fromty, types.float64) else: real = val elif fromty == types.float64: if toty == types.complex64: real = self.cast(builder, val, fromty, types.float32) else: real = val if toty == types.complex128: imag = self.get_constant(types.float64, 0) elif toty == types.complex64: imag = self.get_constant(types.float32, 0) else: raise Exception("unreachable") cmplx = self.make_complex(toty)(self, builder) cmplx.real = real cmplx.imag = imag return cmplx._getvalue() elif fromty in types.integer_domain and toty in types.real_domain: lty = self.get_value_type(toty) if fromty in types.signed_domain: return builder.sitofp(val, lty) else: return builder.uitofp(val, lty) elif toty in types.integer_domain and fromty in types.real_domain: lty = self.get_value_type(toty) if toty in types.signed_domain: return builder.fptosi(val, lty) else: return builder.fptoui(val, lty) elif fromty in types.integer_domain and toty in types.complex_domain: cmplxcls, flty = builtins.get_complex_info(toty) cmpl = cmplxcls(self, builder) cmpl.real = self.cast(builder, val, fromty, flty) cmpl.imag = self.get_constant(flty, 0) return cmpl._getvalue() elif fromty in types.complex_domain and toty in types.complex_domain: srccls, srcty = builtins.get_complex_info(fromty) dstcls, dstty = builtins.get_complex_info(toty) src = srccls(self, builder, value=val) dst = dstcls(self, builder) dst.real = self.cast(builder, src.real, srcty, dstty) dst.imag = self.cast(builder, src.imag, srcty, dstty) return dst._getvalue() elif (isinstance(toty, types.UniTuple) and isinstance(fromty, types.UniTuple) and len(fromty) == len(toty)): olditems = cgutils.unpack_tuple(builder, val, len(fromty)) items = [self.cast(builder, i, fromty.dtype, toty.dtype) for i in olditems] tup = self.get_constant_undef(toty) for idx, val in enumerate(items): tup = builder.insert_value(tup, val, idx) return tup elif (types.is_int_tuple(toty) and types.is_int_tuple(fromty) and len(toty) == len(fromty)): olditems = cgutils.unpack_tuple(builder, val, len(fromty)) items = [self.cast(builder, i, t, toty.dtype) for i, t in zip(olditems, fromty.items)] tup = self.get_constant_undef(toty) for idx, val in enumerate(items): tup = builder.insert_value(tup, val, idx) return tup elif toty == types.boolean: return self.is_true(builder, fromty, val) elif fromty == types.boolean: # first promote to int32 asint = builder.zext(val, Type.int()) # then promote to number return self.cast(builder, asint, types.int32, toty) raise NotImplementedError("cast", val, fromty, toty)
def cast(self, builder, val, fromty, toty): if fromty == toty or toty == types.Any or isinstance(toty, types.Kind): return val elif ((fromty in types.unsigned_domain and toty in types.signed_domain) or (fromty in types.integer_domain and toty in types.unsigned_domain)): lfrom = self.get_value_type(fromty) lto = self.get_value_type(toty) if lfrom.width <= lto.width: return builder.zext(val, lto) elif lfrom.width > lto.width: return builder.trunc(val, lto) elif fromty in types.signed_domain and toty in types.signed_domain: lfrom = self.get_value_type(fromty) lto = self.get_value_type(toty) if lfrom.width <= lto.width: return builder.sext(val, lto) elif lfrom.width > lto.width: return builder.trunc(val, lto) elif fromty in types.real_domain and toty in types.real_domain: lty = self.get_value_type(toty) if fromty == types.float32 and toty == types.float64: return builder.fpext(val, lty) elif fromty == types.float64 and toty == types.float32: return builder.fptrunc(val, lty) elif fromty in types.real_domain and toty in types.complex_domain: if fromty == types.float32: if toty == types.complex128: real = self.cast(builder, val, fromty, types.float64) else: real = val elif fromty == types.float64: if toty == types.complex64: real = self.cast(builder, val, fromty, types.float32) else: real = val if toty == types.complex128: imag = self.get_constant(types.float64, 0) elif toty == types.complex64: imag = self.get_constant(types.float32, 0) else: raise Exception("unreachable") cmplx = self.make_complex(toty)(self, builder) cmplx.real = real cmplx.imag = imag return cmplx._getvalue() elif fromty in types.integer_domain and toty in types.real_domain: lty = self.get_value_type(toty) if fromty in types.signed_domain: return builder.sitofp(val, lty) else: return builder.uitofp(val, lty) elif toty in types.integer_domain and fromty in types.real_domain: lty = self.get_value_type(toty) if toty in types.signed_domain: return builder.fptosi(val, lty) else: return builder.fptoui(val, lty) elif fromty in types.integer_domain and toty in types.complex_domain: cmplxcls, flty = builtins.get_complex_info(toty) cmpl = cmplxcls(self, builder) cmpl.real = self.cast(builder, val, fromty, flty) cmpl.imag = self.get_constant(flty, 0) return cmpl._getvalue() elif fromty in types.complex_domain and toty in types.complex_domain: srccls, srcty = builtins.get_complex_info(fromty) dstcls, dstty = builtins.get_complex_info(toty) src = srccls(self, builder, value=val) dst = dstcls(self, builder) dst.real = self.cast(builder, src.real, srcty, dstty) dst.imag = self.cast(builder, src.imag, srcty, dstty) return dst._getvalue() elif (isinstance(toty, types.UniTuple) and isinstance(fromty, types.UniTuple) and len(fromty) == len(toty)): olditems = cgutils.unpack_tuple(builder, val, len(fromty)) items = [ self.cast(builder, i, fromty.dtype, toty.dtype) for i in olditems ] tup = self.get_constant_undef(toty) for idx, val in enumerate(items): tup = builder.insert_value(tup, val, idx) return tup elif (types.is_int_tuple(toty) and types.is_int_tuple(fromty) and len(toty) == len(fromty)): olditems = cgutils.unpack_tuple(builder, val, len(fromty)) items = [ self.cast(builder, i, t, toty.dtype) for i, t in zip(olditems, fromty.types) ] tup = self.get_constant_undef(toty) for idx, val in enumerate(items): tup = builder.insert_value(tup, val, idx) return tup elif toty == types.boolean: return self.is_true(builder, fromty, val) elif fromty == types.boolean: # first promote to int32 asint = builder.zext(val, Type.int()) # then promote to number return self.cast(builder, asint, types.int32, toty) elif fromty == types.none and isinstance(toty, types.Optional): return self.make_optional_none(builder, toty.type) elif isinstance(toty, types.Optional): casted = self.cast(builder, val, fromty, toty.type) return self.make_optional_value(builder, toty.type, casted) elif isinstance(fromty, types.Optional): optty = self.make_optional(fromty) optval = optty(self, builder, value=val) validbit = cgutils.as_bool_bit(builder, optval.valid) with cgutils.if_unlikely(builder, builder.not_(validbit)): self.return_errcode(builder, errcode.NONE_TYPE_ERROR) return optval.data elif (isinstance(fromty, types.Array) and isinstance(toty, types.Array)): # Type inference should have prevented illegal array casting. assert toty.layout == 'A' return val raise NotImplementedError("cast", val, fromty, toty)
def cast(self, builder, val, fromty, toty): if fromty == toty or toty == types.Any or isinstance(toty, types.Kind): return val elif ((fromty in types.unsigned_domain and toty in types.signed_domain) or (fromty in types.integer_domain and toty in types.unsigned_domain)): lfrom = self.get_value_type(fromty) lto = self.get_value_type(toty) if lfrom.width <= lto.width: return builder.zext(val, lto) elif lfrom.width > lto.width: return builder.trunc(val, lto) elif fromty in types.signed_domain and toty in types.signed_domain: lfrom = self.get_value_type(fromty) lto = self.get_value_type(toty) if lfrom.width <= lto.width: return builder.sext(val, lto) elif lfrom.width > lto.width: return builder.trunc(val, lto) elif fromty in types.real_domain and toty in types.real_domain: lty = self.get_value_type(toty) if fromty == types.float32 and toty == types.float64: return builder.fpext(val, lty) elif fromty == types.float64 and toty == types.float32: return builder.fptrunc(val, lty) elif fromty in types.real_domain and toty in types.complex_domain: if fromty == types.float32: if toty == types.complex128: real = self.cast(builder, val, fromty, types.float64) else: real = val elif fromty == types.float64: if toty == types.complex64: real = self.cast(builder, val, fromty, types.float32) else: real = val if toty == types.complex128: imag = self.get_constant(types.float64, 0) elif toty == types.complex64: imag = self.get_constant(types.float32, 0) else: raise Exception("unreachable") cmplx = self.make_complex(toty)(self, builder) cmplx.real = real cmplx.imag = imag return cmplx._getvalue() elif fromty in types.integer_domain and toty in types.real_domain: lty = self.get_value_type(toty) if fromty in types.signed_domain: return builder.sitofp(val, lty) else: return builder.uitofp(val, lty) elif toty in types.integer_domain and fromty in types.real_domain: lty = self.get_value_type(toty) if toty in types.signed_domain: return builder.fptosi(val, lty) else: return builder.fptoui(val, lty) elif fromty in types.integer_domain and toty in types.complex_domain: cmplxcls, flty = builtins.get_complex_info(toty) cmpl = cmplxcls(self, builder) cmpl.real = self.cast(builder, val, fromty, flty) cmpl.imag = self.get_constant(flty, 0) return cmpl._getvalue() elif fromty in types.complex_domain and toty in types.complex_domain: srccls, srcty = builtins.get_complex_info(fromty) dstcls, dstty = builtins.get_complex_info(toty) src = srccls(self, builder, value=val) dst = dstcls(self, builder) dst.real = self.cast(builder, src.real, srcty, dstty) dst.imag = self.cast(builder, src.imag, srcty, dstty) return dst._getvalue() elif (isinstance(toty, types.UniTuple) and isinstance(fromty, types.UniTuple) and len(fromty) == len(toty)): olditems = cgutils.unpack_tuple(builder, val, len(fromty)) items = [self.cast(builder, i, fromty.dtype, toty.dtype) for i in olditems] tup = self.get_constant_undef(toty) for idx, val in enumerate(items): tup = builder.insert_value(tup, val, idx) return tup elif (types.is_int_tuple(toty) and types.is_int_tuple(fromty) and len(toty) == len(fromty)): olditems = cgutils.unpack_tuple(builder, val, len(fromty)) items = [self.cast(builder, i, t, toty.dtype) for i, t in zip(olditems, fromty.types)] tup = self.get_constant_undef(toty) for idx, val in enumerate(items): tup = builder.insert_value(tup, val, idx) return tup elif toty == types.boolean: return self.is_true(builder, fromty, val) elif fromty == types.boolean: # first promote to int32 asint = builder.zext(val, Type.int()) # then promote to number return self.cast(builder, asint, types.int32, toty) raise NotImplementedError("cast", val, fromty, toty)