Example #1
0
    def preprocess_fields(self, fields):
        # temp name to allow Optional instantiation
        self.name = f"numba.PolygonStructType#{id(self)}"
        fields = tuple([
            ('value', types.Optional(types.int64)),
            ('parent', types.Optional(self)),
        ])

        return fields
Example #2
0
def _list_getitem_pop_helper(typingctx, l, index, op):
    """Wrap numba_list_getitem and numba_list_pop

    Returns 2-tuple of (int32, ?item_type)

    This is a helper that is parametrized on the type of operation, which can
    be either 'pop' or 'getitem'. This is because, signature wise, getitem and
    pop and are the same.
    """
    assert (op in ("pop", "getitem"))
    IS_NOT_NONE = not isinstance(l.item_type, types.NoneType)
    resty = types.Tuple([
        types.int32,
        types.Optional(l.item_type if IS_NOT_NONE else types.int64)
    ])
    sig = resty(l, index)

    def codegen(context, builder, sig, args):
        fnty = ir.FunctionType(
            ll_status,
            [ll_list_type, ll_ssize_t, ll_bytes],
        )
        [tl, tindex] = sig.args
        [l, index] = args
        fn = builder.module.get_or_insert_function(
            fnty, name='numba_list_{}'.format(op))

        dm_item = context.data_model_manager[tl.item_type]
        ll_item = context.get_data_type(tl.item_type)
        ptr_item = cgutils.alloca_once(builder, ll_item)

        lp = _container_get_data(context, builder, tl, l)
        status = builder.call(
            fn,
            [
                lp,
                index,
                _as_bytes(builder, ptr_item),
            ],
        )
        # Load item if output is available
        found = builder.icmp_signed('>=', status,
                                    status.type(int(ListStatus.LIST_OK)))
        out = context.make_optional_none(
            builder, tl.item_type if IS_NOT_NONE else types.int64)
        pout = cgutils.alloca_once_value(builder, out)

        with builder.if_then(found):
            if IS_NOT_NONE:
                item = dm_item.load_from_data_pointer(builder, ptr_item)
                context.nrt.incref(builder, tl.item_type, item)
                loaded = context.make_optional_value(builder, tl.item_type,
                                                     item)
                builder.store(loaded, pout)

        out = builder.load(pout)
        return context.make_tuple(builder, resty, [status, out])

    return sig, codegen
Example #3
0
    def test_optional_to_optional(self):
        """
        Test error due mishandling of Optional to Optional casting

        Related issue: https://github.com/numba/numba/issues/1718
        """
        # Attempt to cast optional(intp) to optional(float64)
        opt_int = types.Optional(types.intp)
        opt_flt = types.Optional(types.float64)
        sig = opt_flt(opt_int)

        @njit(sig)
        def foo(a):
            return a

        self.assertEqual(foo(2), 2)
        self.assertIsNone(foo(None))
Example #4
0
    def _builtin_infer(self, py_type):
        # The type hierarchy of python typing library changes in 3.7.
        generic_type_check = _py_version_switch(
            (3, 7),
            lambda x: isinstance(x, py_typing._GenericAlias),
            lambda _: True,
        )
        if not generic_type_check(py_type):
            return

        list_origin = _py_version_switch((3, 7), list, py_typing.List)
        dict_origin = _py_version_switch((3, 7), dict, py_typing.Dict)
        set_origin = _py_version_switch((3, 7), set, py_typing.Set)
        tuple_origin = _py_version_switch((3, 7), tuple, py_typing.Tuple)

        if getattr(py_type, "__origin__", None) is py_typing.Union:
            if len(py_type.__args__) != 2:
                raise errors.TypingError(
                    "Cannot type Union of more than two types")

            (arg_1_py, arg_2_py) = py_type.__args__

            if arg_2_py is type(None):  # noqa: E721
                return types.Optional(self.infer(arg_1_py))
            elif arg_1_py is type(None):  # noqa: E721
                return types.Optional(self.infer(arg_2_py))
            else:
                raise errors.TypingError(
                    "Cannot type Union that is not an Optional "
                    f"(neither type type {arg_2_py} is not NoneType")

        if getattr(py_type, "__origin__", None) is list_origin:
            (element_py, ) = py_type.__args__
            return types.ListType(self.infer(element_py))

        if getattr(py_type, "__origin__", None) is dict_origin:
            key_py, value_py = py_type.__args__
            return types.DictType(self.infer(key_py), self.infer(value_py))

        if getattr(py_type, "__origin__", None) is set_origin:
            (element_py, ) = py_type.__args__
            return types.Set(self.infer(element_py))

        if getattr(py_type, "__origin__", None) is tuple_origin:
            tys = tuple(map(self.infer, py_type.__args__))
            return types.BaseTuple.from_types(tys)
Example #5
0
    def impl(typingctx, l_ty, index_ty):

        is_none = isinstance(l_ty.item_type, types.NoneType)
        if is_none:
            resty = types.Tuple([types.int32, l_ty.item_type])
        else:
            resty = types.Tuple([types.int32, types.Optional(l_ty.item_type)])
        sig = resty(l_ty, index_ty)

        def codegen(context, builder, sig, args):
            [tl, tindex] = sig.args
            [l, index] = args
            fnty = ir.FunctionType(
                ll_voidptr_type,
                [ll_list_type],
            )
            fname = 'numba_list_base_ptr'
            fn = builder.module.get_or_insert_function(fnty, fname)
            fn.attributes.add('alwaysinline')
            fn.attributes.add('nounwind')
            fn.attributes.add('readonly')

            lp = _container_get_data(context, builder, tl, l)

            base_ptr = builder.call(
                fn,
                [
                    lp,
                ],
            )

            llty = context.get_data_type(tl.item_type)
            casted_base_ptr = builder.bitcast(base_ptr, llty.as_pointer())

            item_ptr = cgutils.gep(builder, casted_base_ptr, index)

            if is_none:
                out = builder.load(item_ptr)
            else:
                out = context.make_optional_none(builder, tl.item_type)
                pout = cgutils.alloca_once_value(builder, out)

                dm_item = context.data_model_manager[tl.item_type]
                item = dm_item.load_from_data_pointer(builder, item_ptr)
                if not borrowed:
                    context.nrt.incref(builder, tl.item_type, item)

                if is_none:
                    loaded = item
                else:
                    loaded = context.make_optional_value(
                        builder, tl.item_type, item)
                builder.store(loaded, pout)

                out = builder.load(pout)
            return context.make_tuple(builder, resty, [ll_status(0), out])

        return sig, codegen
Example #6
0
def _list_getitem(typingctx, l, index):
    """Wrap numba_list_getitem

    Returns 2-tuple of (int32, ?item_type)

    """
    IS_NOT_NONE = not isinstance(l.item_type, types.NoneType)
    resty = types.Tuple([types.int32,
                         types.Optional(l.item_type
                                        if IS_NOT_NONE
                                        else types.int64)])
    sig = resty(l, index)

    def codegen(context, builder, sig, args):
        fnty = ir.FunctionType(
            ll_status,
            [ll_list_type, ll_ssize_t, ll_bytes],
        )
        [tl, tindex] = sig.args
        [l, index] = args
        fn = builder.module.get_or_insert_function(
            fnty, name='numba_list_getitem')

        dm_item = context.data_model_manager[tl.item_type]
        ll_item = context.get_data_type(tl.item_type)
        ptr_item = cgutils.alloca_once(builder, ll_item)

        lp = _container_get_data(context, builder, tl, l)
        status = builder.call(
            fn,
            [
                lp,
                index,
                _as_bytes(builder, ptr_item),
            ],
        )
        # Load item if output is available
        found = builder.icmp_signed('>=', status,
                                    status.type(int(ListStatus.LIST_OK)))
        out = context.make_optional_none(builder,
                                         tl.item_type
                                         if IS_NOT_NONE
                                         else types.int64)
        pout = cgutils.alloca_once_value(builder, out)

        with builder.if_then(found):
            if IS_NOT_NONE:
                item = dm_item.load_from_data_pointer(builder, ptr_item)
                context.nrt.incref(builder, tl.item_type, item)
                loaded = context.make_optional_value(
                    builder, tl.item_type, item)
                builder.store(loaded, pout)

        out = builder.load(pout)
        return context.make_tuple(builder, resty, [status, out])

    return sig, codegen
Example #7
0
def _dict_lookup(typingctx, d, key, hashval):
    """Wrap numba_dict_lookup

    Returns 2-tuple of (intp, ?value_type)
    """
    resty = types.Tuple([types.intp, types.Optional(d.value_type)])
    sig = resty(d, key, hashval)

    def codegen(context, builder, sig, args):
        fnty = ir.FunctionType(
            ll_ssize_t,
            [ll_dict_type, ll_bytes, ll_hash, ll_bytes],
        )
        [td, tkey, thashval] = sig.args
        [d, key, hashval] = args
        fn = cgutils.get_or_insert_function(builder.module, fnty,
                                            'numba_dict_lookup')

        dm_key = context.data_model_manager[tkey]
        dm_val = context.data_model_manager[td.value_type]

        data_key = dm_key.as_data(builder, key)
        ptr_key = cgutils.alloca_once_value(builder, data_key)
        cgutils.memset_padding(builder, ptr_key)

        ll_val = context.get_data_type(td.value_type)
        ptr_val = cgutils.alloca_once(builder, ll_val)

        dp = _container_get_data(context, builder, td, d)
        ix = builder.call(
            fn,
            [
                dp,
                _as_bytes(builder, ptr_key),
                hashval,
                _as_bytes(builder, ptr_val),
            ],
        )
        # Load value if output is available
        found = builder.icmp_signed('>', ix, ix.type(int(DKIX.EMPTY)))

        out = context.make_optional_none(builder, td.value_type)
        pout = cgutils.alloca_once_value(builder, out)

        with builder.if_then(found):
            val = dm_val.load_from_data_pointer(builder, ptr_val)
            context.nrt.incref(builder, td.value_type, val)
            loaded = context.make_optional_value(builder, td.value_type, val)
            builder.store(loaded, pout)

        out = builder.load(pout)
        return context.make_tuple(builder, resty, [ix, out])

    return sig, codegen
    def test_optional(self):
        self.assertEqual(
            as_numba_type(py_typing.Optional[float]),
            types.Optional(self.float_nb_type),
        )
        self.assertEqual(
            as_numba_type(py_typing.Union[str, None]),
            types.Optional(self.str_nb_type),
        )
        self.assertEqual(
            as_numba_type(py_typing.Union[None, bool]),
            types.Optional(self.bool_nb_type),
        )

        # Optional[x] is a special case of Union[x, None].  We raise a
        # TypingError if the right type is not NoneType.
        with self.assertRaises(TypingError) as raises:
            as_numba_type(py_typing.Union[int, float])
        self.assertIn("Cannot type Union that is not an Optional",
                      str(raises.exception))
Example #9
0
 def test_optional_tuple(self):
     # Unify to optional tuple
     aty = types.none
     bty = types.UniTuple(i32, 2)
     self.assert_unify(aty, bty, types.Optional(types.UniTuple(i32, 2)))
     aty = types.Optional(types.UniTuple(i16, 2))
     bty = types.UniTuple(i32, 2)
     self.assert_unify(aty, bty, types.Optional(types.UniTuple(i32, 2)))
     # Unify to tuple of optionals
     aty = types.Tuple((types.none, i32))
     bty = types.Tuple((i16, types.none))
     self.assert_unify(aty, bty, types.Tuple((types.Optional(i16),
                                              types.Optional(i32))))
     aty = types.Tuple((types.Optional(i32), i64))
     bty = types.Tuple((i16, types.Optional(i8)))
     self.assert_unify(aty, bty, types.Tuple((types.Optional(i32),
                                              types.Optional(i64))))
Example #10
0
 def test_optional(self):
     aty = types.int32
     bty = types.Optional(i32)
     self.assert_can_convert(types.none, bty, Conversion.promote)
     self.assert_can_convert(aty, bty, Conversion.promote)
     self.assert_cannot_convert(bty, types.none)
     self.assert_can_convert(bty, aty, Conversion.safe)  # XXX ???
     # Optional array
     aty = types.Array(i32, 2, "C")
     bty = types.Optional(aty)
     self.assert_can_convert(types.none, bty, Conversion.promote)
     self.assert_can_convert(aty, bty, Conversion.promote)
     self.assert_can_convert(bty, aty, Conversion.safe)
     aty = types.Array(i32, 2, "C")
     bty = types.Optional(aty.copy(layout="A"))
     self.assert_can_convert(aty, bty, Conversion.safe)  # C -> A
     self.assert_cannot_convert(bty, aty)                # A -> C
     aty = types.Array(i32, 2, "C")
     bty = types.Optional(aty.copy(layout="F"))
     self.assert_cannot_convert(aty, bty)
     self.assert_cannot_convert(bty, aty)
Example #11
0
 def test_none_to_optional(self):
     """
     Test unification of `none` and multiple number types to optional type
     """
     ctx = typing.Context()
     for tys in itertools.combinations(types.number_domain, 2):
         # First unify without none, to provide the control value
         tys = list(tys)
         expected = types.Optional(ctx.unify_types(*tys))
         results = [ctx.unify_types(*comb)
                    for comb in itertools.permutations(tys  + [types.none])]
         # All results must be equal
         for res in results:
             self.assertEqual(res, expected)
Example #12
0
def _dict_popitem(typingctx, d):
    """Wrap numba_dict_popitem
    """

    keyvalty = types.Tuple([d.key_type, d.value_type])
    resty = types.Tuple([types.int32, types.Optional(keyvalty)])
    sig = resty(d)

    def codegen(context, builder, sig, args):
        fnty = ir.FunctionType(
            ll_status,
            [ll_dict_type, ll_bytes, ll_bytes],
        )
        [d] = args
        [td] = sig.args
        fn = builder.module.get_or_insert_function(fnty,
                                                   name='numba_dict_popitem')

        dm_key = context.data_model_manager[td.key_type]
        dm_val = context.data_model_manager[td.value_type]

        ptr_key = cgutils.alloca_once(builder, dm_key.get_data_type())
        ptr_val = cgutils.alloca_once(builder, dm_val.get_data_type())

        dp = _container_get_data(context, builder, td, d)
        status = builder.call(
            fn,
            [
                dp,
                _as_bytes(builder, ptr_key),
                _as_bytes(builder, ptr_val),
            ],
        )
        out = context.make_optional_none(builder, keyvalty)
        pout = cgutils.alloca_once_value(builder, out)

        cond = builder.icmp_signed('==', status, status.type(int(Status.OK)))
        with builder.if_then(cond):
            key = dm_key.load_from_data_pointer(builder, ptr_key)
            val = dm_val.load_from_data_pointer(builder, ptr_val)
            keyval = context.make_tuple(builder, keyvalty, [key, val])
            optkeyval = context.make_optional_value(builder, keyvalty, keyval)
            builder.store(optkeyval, pout)

        out = builder.load(pout)
        return cgutils.pack_struct(builder, [status, out])

    return sig, codegen
Example #13
0
 def test_optional(self):
     aty = types.Optional(i32)
     bty = types.none
     self.assert_unify(aty, bty, aty)
     aty = types.Optional(i32)
     bty = types.Optional(i64)
     self.assert_unify(aty, bty, bty)
     aty = types.Optional(i32)
     bty = i64
     self.assert_unify(aty, bty, types.Optional(i64))
     # Failure
     aty = types.Optional(i32)
     bty = types.Optional(types.slice3_type)
     self.assert_unify_failure(aty, bty)
    def test_optional_unpack(self):
        """
        Issue 2171
        """
        def pyfunc(x):
            if x is None:
                return
            else:
                a, b = x
                return a, b

        tup = types.Tuple([types.intp] * 2)
        opt_tup = types.Optional(tup)
        sig = (opt_tup, )
        cfunc = njit(sig)(pyfunc)
        self.assertEqual(pyfunc(None), cfunc(None))
        self.assertEqual(pyfunc((1, 2)), cfunc((1, 2)))
 def test_nested_containers(self):
     IntList = py_typing.List[int]
     self.assertEqual(
         as_numba_type(py_typing.List[IntList]),
         types.ListType(types.ListType(self.int_nb_type)),
     )
     self.assertEqual(
         as_numba_type(py_typing.List[py_typing.Dict[float, bool]]),
         types.ListType(
             types.DictType(self.float_nb_type, self.bool_nb_type)),
     )
     self.assertEqual(
         as_numba_type(
             py_typing.Set[py_typing.Tuple[py_typing.Optional[int],
                                           float]]),
         types.Set(
             types.Tuple(
                 [types.Optional(self.int_nb_type), self.float_nb_type])),
     )
Example #16
0
 def make_optional_value(self, builder, valtype, value):
     optval = self.make_helper(builder, types.Optional(valtype))
     optval.valid = cgutils.true_bit
     optval.data = value
     return optval._getvalue()
Example #17
0
 def make_optional_none(self, builder, valtype):
     optval = self.make_helper(builder, types.Optional(valtype))
     optval.valid = cgutils.false_bit
     return optval._getvalue()
Example #18
0
 def test_optional(self):
     ty = types.Optional(types.int32)
     self.check_pickling(ty)
 def test_cleanup_optional(self):
     mem = memoryview(bytearray(b"xyz"))
     tp = types.Optional(types.Buffer(types.intc, 1, "C"))
     self.check_argument_cleanup(tp, mem)