Esempio n. 1
0
    def _resolve_keywords(self, closure_type, args, keywords):
        func_def = closure_type.closure.func_def
        argnames = [name.id for name in func_def.args.args]

        expected = len(argnames) - len(args)
        if len(keywords) != expected:
            raise error.NumbaError(
                self.call_node, "Expected %d arguments, got %d" %
                (len(argnames), len(args) + len(keywords)))

        argpositions = dict(zip(argnames, range(len(argnames))))
        positional = [None] * (len(argnames) - len(args))

        for keyword in keywords:
            argname = keyword.arg
            pos = argpositions.get(argname, None)
            if pos is None:
                raise error.NumbaError(
                    keyword, "Not a valid keyword argument name: %s" % argname)
            elif pos < len(args):
                raise error.NumbaError(
                    keyword, "Got multiple values for positional "
                    "argument %r" % argname)
            else:
                positional[pos] = keyword.value

        return positional
Esempio n. 2
0
    def report(self, post_mortem=False):
        self.messages.sort(key=sort_message)

        if self.messages:
            self.header()

        errors = []
        for node, is_error, message in self.messages:
            if is_error:
                errors.append((node, message))
                type = "Error"
            else:
                type = "Warning"

            self.report_message(message, node, type)

        if self.messages:
            self.buf[-1] = self.buf[-1].rstrip() + '\n'
            self.footer()

        message = "".join(self.buf)

        # clear buffer
        del self.messages[:]
        del self.buf[:]

        if errors and not post_mortem:
            if len(message.splitlines()) == 1:
                raise error.NumbaError(*errors[0])
            raise error.NumbaError("(see below)\n" + message.strip(),
                                   has_report=True)
        else:
            self.file.write(message)
Esempio n. 3
0
def tensordot(typesystem, a, b, axes):
    '''Typing function for numpy.tensordot().

    Defaults to Python object for any caller that isn't using the
    default argument to axes.

    Otherwise, it is similar to inner(), but subtracts four dimensions
    from the result instead of two.

    Without symbolic execution of the actual axes argument, this can't
    determine the number of axes to sum over, so it punts.  This
    typing function could use an array type of unknown dimensionality,
    were one available.  See:
    https://www.pivotaltracker.com/story/show/43687249
    '''
    lhs_type = array_from_object(a)
    rhs_type = array_from_object(b)
    if lhs_type.ndim < 1:
        raise error.NumbaError(a, 'First argument to numpy.tensordot() '
                               'requires array of dimensionality >= 1.')
    elif rhs_type.ndim < 1:
        raise error.NumbaError(b, 'First argument to numpy.tensordot() '
                               'requires array of dimensionality >= 1.')
    dtype = typesystem.promote(lhs_type.dtype, rhs_type.dtype)
    if axes is None:
        result_ndim = lhs_type.ndim + rhs_type.ndim - 4
        if result_ndim < 0:
            raise error.NumbaError(a, 'Arguments to numpy.tensordot() should '
                                   'have combined dimensionality >= 4 (when '
                                   'axes argument is not specified).')
        result_type = typesystem.array(dtype, result_ndim)
    else:
        # XXX Issue warning to user?
        result_type = object_
    return result_type
Esempio n. 4
0
    def visit_CoercionNode(self, node):
        if not isinstance(node, nodes.CoercionNode):
            # CoercionNode.__new__ returns the node to be coerced if it doesn't
            # need coercion
            return node

        node_type = node.node.type
        dst_type = node.dst_type
        if __debug__ and self.env and self.env.debug_coercions:
            logger.debug('coercion: %s --> %s\n%s', node_type, dst_type,
                         utils.pformat_ast(node))

        # TODO: the below is a problem due to implicit string <-> int coercions!
        if (node_type.is_string and dst_type.is_numeric
                and not (node_type.is_pointer or node_type.is_null)):
            if dst_type.typename in ('char', 'uchar'):
                raise error.NumbaError(
                    node,
                    "Conversion from string to (u)char not yet supported")
            result = self.str_to_int(dst_type, node)
        elif self.nopython and (is_obj(node_type) ^ is_obj(dst_type)):
            raise error.NumbaError(
                node, "Cannot coerce to or from object in "
                "nopython context")
        elif is_obj(node.dst_type) and not is_obj(node_type):
            node = nodes.ObjectTempNode(
                nodes.CoerceToObject(node.node, node.dst_type, name=node.name))
            result = self.visit(node)
        elif is_obj(node_type) and not is_obj(node.dst_type):
            node = nodes.CoerceToNative(node.node,
                                        node.dst_type,
                                        name=node.name)
            result = self.visit(node)
        elif node_type.is_null:
            if not dst_type.is_pointer:
                raise error.NumbaError(
                    node.node, "NULL must be cast or implicitly "
                    "coerced to a pointer type")
            result = self.visit(nodes.NULL.coerce(dst_type))
        elif node_type.is_numeric and dst_type.is_bool:
            to_bool = ast.Compare(node.node, [ast.NotEq()],
                                  [nodes.const(0, node_type)])
            to_bool = nodes.typednode(to_bool, bool_)
            result = self.visit(to_bool)
        else:
            self.generic_visit(node)

            if dst_type == node.node.type:
                result = node.node
            else:
                result = node

        if __debug__ and self.env and self.env.debug_coercions:
            logger.debug('result = %s', utils.pformat_ast(result))

        return result
Esempio n. 5
0
    def __call__(self, *args, **kwargs):
        if self.ctypes_func:
            return self.invoke_compiled(self.ctypes_func, *args, **kwargs)
        else:
            if kwargs:
                raise error.NumbaError("Cannot handle keyword arguments yet")

            nargs = self.py_func.func_code.co_argcount
            if len(args) != nargs:
                raise error.NumbaError("Expected %d arguments, got %d" %
                                       (nargs, len(args)))
            return self.wrapper(self, *args, **kwargs)
Esempio n. 6
0
def parse_argtypes(visit_func, decorator, func_def, jit_args):
    argtypes_node = jit_args['argtypes']
    if argtypes_node is None:
        raise error.NumbaError(func_def.args[0], "Expected an argument type")

    argtypes = assert_constant(visit_func, decorator, argtypes_node)

    if not isinstance(argtypes, (list, tuple)):
        raise error.NumbaError(argtypes_node, 'Invalid argument for argtypes')
    for argtype in argtypes:
        check_valid_argtype(argtypes_node, argtype)

    return argtypes
Esempio n. 7
0
    def visit_CoerceToNative(self, node):
        """
        Try to perform fast coercion using e.g. PyLong_AsLong(), with a
        fallback to PyArg_ParseTuple().
        """
        new_node = None

        from_type = node.node.type
        node_type = node.type
        if node_type.is_numeric:
            cls = None
            if node_type == size_t:
                node_type = ulonglong

            if node_type.is_int: # and not
                cls = self._get_int_conversion_func(node_type,
                                                    functions._as_long)
                if not node_type.signed or node_type == Py_ssize_t:
                    # PyLong_AsLong calls __int__, but
                    # PyLong_AsUnsignedLong doesn't...
                    node.node = nodes.call_pyfunc(long, [node.node])
            elif node_type.is_float:
                cls = functions.PyFloat_AsDouble
            #elif node_type.is_complex:
            #    cls = functions.PyComplex_AsCComplex

            if cls:
                # TODO: error checking!
                new_node = self.function_cache.call(cls.__name__, node.node)
        elif node_type.is_pointer:
            raise error.NumbaError(node, "Obtaining pointers from objects "
                                         "is not yet supported")
        elif node_type.is_void:
            raise error.NumbaError(node, "Cannot coerce %s to void" % (from_type,))

        if new_node is None:
            # Create a tuple for PyArg_ParseTuple
            new_node = node
            new_node.node = ast.Tuple(elts=[node.node], ctx=ast.Load())
        else:
            # Fast coercion
            new_node = nodes.CoercionNode(new_node, node.type)

        if new_node is node:
            self.generic_visit(new_node)
        else:
            new_node = self.visit(new_node)

        return new_node
Esempio n. 8
0
    def _print_nopython(self, value, dest=None):
        if dest is not None:
            raise error.NumbaError(dest, "No file may be given in nopython mode")

        stdin, stdout, stderr = stdio_util.get_stdio_streams()
        stdout = stdio_util.get_stream_as_node(stdout)

        format = codegen.get_printf_specifier(value.type)
        if format is None:
            raise error.NumbaError(
                value, "Printing values of type '%s' is not supported "
                       "in nopython mode" % (value.type,))

        return self.function_cache.call(
                    'printf', nodes.const(format, c_string_type), value)
Esempio n. 9
0
    def _resolve_struct_attribute(self, node, type):
        if not node.attr in type.fielddict:
            raise error.NumbaError(
                node, "Struct %s has no field %r" % (type, node.attr))

        if isinstance(node.ctx, ast.Store):
            if not isinstance(node.value,
                              (ast.Name, ast.Subscript, nodes.StructVariable)):
                raise error.NumbaError(
                    node, "Can only assign to struct attributes of "
                    "variables or array indices")
            node.value.ctx = ast.Store()

        return nodes.StructAttribute(node.value, node.attr, node.ctx,
                                     node.value.variable.type)
Esempio n. 10
0
def _process_signature(ext_type, method, default_signature,
                       is_static=False, is_class=False):
    if isinstance(method, minitypes.Function):
        # @double(...)
        # def func(self, ...): ...
        return _process_signature(ext_type, method.py_func,
                                  method.signature, is_static, is_class)
    elif isinstance(method, types.FunctionType):
        if default_signature is None:
            # TODO: construct dependency graph, toposort, type infer
            # TODO: delayed types
            raise error.NumbaError(
                "Method '%s' does not have signature" % (method.__name__,))
        validate_method(method, default_signature or object_(), is_static)
        if default_signature is None:
            default_signature = minitypes.FunctionType(return_type=None,
                                                       args=[])
        sig = get_signature(ext_type, is_class, is_static, default_signature)
        return Method(method, is_class, is_static), sig.return_type, sig.args
    else:
        if isinstance(method, staticmethod):
            is_static = True
        elif isinstance(method, classmethod):
            is_class = True
        else:
            return None, None, None

        method, restype, argtypes = _process_signature(
                        ext_type, method.__func__, default_signature,
                        is_static=is_static, is_class=is_class)

    return method, restype, argtypes
Esempio n. 11
0
def validate_method(py_func, sig, is_static):
    assert isinstance(py_func, types.FunctionType)
    nargs = py_func.func_code.co_argcount - 1 + is_static
    if len(sig.args) != nargs:
        raise error.NumbaError(
            "Expected %d argument types in function "
            "%s (don't include 'self')" % (nargs, py_func.__name__))
Esempio n. 12
0
    def visit_With(self, node):
        """
        Rewrite the With statement.

        Python < 3.3:

             With(expr context_expr, expr? optional_vars, stmt* body)

        Python 3.3:

            With(withitem* items, stmt* body)
            withitem = (expr context_expr, expr? optional_vars)
        """
        if sys.version_info[:2] >= (3, 3):
            if len(node.items) > 1:
                raise error.NumbaError(node,
                                       "Only one 'with' context is support")

            withitem = node.items[0]

            new_node = With()
            new_node.context_expr = withitem.context_expr
            new_node.optional_vars = withitem.optional_vars
            new_node.body = node.body

            node = ast.copy_location(new_node, node)

        self.generic_visit(node)
        return node
Esempio n. 13
0
    def visit_Attribute(self, node):
        if (self.nopython and not node.value.type.is_module
                and not node.value.type.is_complex):
            raise error.NumbaError(
                node,
                "Cannot access Python attribute in nopython context (%s)" %
                node.attr)

        if node.value.type.is_complex:
            value = self.visit(node.value)
            return nodes.ComplexAttributeNode(value, node.attr)
        elif node.type.is_numpy_attribute:
            return nodes.ObjectInjectNode(node.type.value)
        elif node.type.is_numpy_dtype:
            dtype_type = node.type.dtype
            return nodes.ObjectInjectNode(dtype_type.get_dtype())
        elif is_obj(node.value.type):
            if node.value.type.is_module:
                # Resolve module attributes as constants
                if node.type.is_module_attribute:
                    new_node = nodes.ObjectInjectNode(node.type.value)
                else:
                    new_node = nodes.ConstNode(
                        getattr(node.value.type.module, node.attr))
            else:
                new_node = function_util.external_call(
                    self.context,
                    self.llvm_module,
                    'PyObject_GetAttrString',
                    args=[node.value, nodes.ConstNode(node.attr)])
            return self.visit(new_node)

        self.generic_visit(node)
        return node
Esempio n. 14
0
    def visit_Slice(self, node):
        """
        Rewrite slice objects. Do this late in the pipeline so that other
        code can still recognize the code structure.
        """
        slice_values = [node.lower, node.upper, node.step]

        if self.nopython:
            raise error.NumbaError(node, "Cannot slice in nopython context")

        if node.variable.is_constant:
            return self.visit(
                nodes.ObjectInjectNode(node.variable.constant_value))

        bounds = []
        for node in slice_values:
            if node is None:
                bounds.append(nodes.NULL_obj)
            else:
                bounds.append(node)

        new_slice = function_util.external_call(self.context,
                                                self.llvm_module,
                                                'PySlice_New',
                                                args=bounds,
                                                temp_name='slice')
        return self.visit(new_slice)
Esempio n. 15
0
    def visit_ArrayNewNode(self, node):
        if self.nopython:
            raise error.NumbaError(
                node, "Cannot yet allocate new array in nopython context")

        PyArray_Type = nodes.ObjectInjectNode(np.ndarray)
        descr = nodes.ObjectInjectNode(node.type.dtype.get_dtype()).cloneable
        ndim = nodes.const(node.type.ndim, int_)
        flags = nodes.const(0, int_)
        args = [PyArray_Type, descr.clone, ndim,
                node.shape, node.strides, node.data, flags]

        incref_descr = nodes.IncrefNode(descr)
        incref_base = None
        setbase = None

        if node.base is None:
            args.append(nodes.NULL_obj)
        else:
            base = nodes.CloneableNode(node.base)
            incref_base = nodes.IncrefNode(base)
            args.append(base.clone)

        array = nodes.PyArray_NewFromDescr(args)
        array = nodes.ObjectTempNode(array).cloneable
        body = [incref_descr, incref_base, array, setbase]

        if node.base is not None:
            body.append(nodes.PyArray_SetBaseObject([array.clone, base.clone]))

        # TODO: PyArray_UpdateFlags()
        result = nodes.ExpressionNode(filter(None, body), array.clone)
        return self.visit(result)
Esempio n. 16
0
    def init_locals(self):
        arg_types = self.func_signature.args
        if len(arg_types) > len(self.local_names):
            raise error.NumbaError("Too many types specified in @jit()")

        for i, arg_type in enumerate(arg_types):
            varname = self.local_names[i]
            self.symtab[varname] = Variable(arg_type,
                                            is_local=True,
                                            name=varname)

        for varname in self.local_names[len(arg_types):]:
            self.symtab[varname] = Variable(None, is_local=True, name=varname)

        self.symtab['None'] = Variable(numba_types.none,
                                       is_constant=True,
                                       constant_value=None)

        arg_types = list(arg_types)
        for local_name, local_type in self.locals.iteritems():
            if local_name not in self.symtab:
                self.symtab[local_name] = Variable(local_type,
                                                   is_local=True,
                                                   name=local_name)
            variable = self.symtab[local_name]
            variable.type = local_type
            variable.promotable_type = False

            if local_name in self.argnames:
                idx = self.argnames.index(local_name)
                arg_types[idx] = local_type

        self.func_signature.args = tuple(arg_types)
Esempio n. 17
0
 def visit_While(self, node):
     if node.orelse:
         raise error.NumbaError(node.orelse,
                                'Else in for-loop is not implemented.')
     node.test = nodes.CoercionNode(self.visit(node.test), minitypes.bool_)
     node.body = self.visitlist(node.body)
     return node
Esempio n. 18
0
    def single_compare(self, node):
        rhs = node.comparators[0]

        if is_obj(node.left.type):
            node = self.single_compare_objects(node)

        elif node.left.type.is_pointer and rhs.type.is_pointer:
            # Coerce pointers to integer values before comparing
            node.left = nodes.CoercionNode(node.left, Py_uintptr_t)
            node.comparators = [nodes.CoercionNode(rhs, Py_uintptr_t)]

        elif node.left.type.is_complex and rhs.type.is_complex:
            real1, imag1 = extract(node.left)
            real2, imag2 = extract(rhs)
            op = type(node.ops[0])
            if op == ast.Eq:
                lhs = compare(real1, ast.Eq(), real2)
                rhs = compare(imag1, ast.Eq(), imag2)
                result = ast.BoolOp(ast.And(), [lhs, rhs])
            elif op == ast.NotEq:
                lhs = compare(real1, ast.NotEq(), real2)
                rhs = compare(imag1, ast.NotEq(), imag2)
                result = ast.BoolOp(ast.Or(), [lhs, rhs])
            else:
                raise NotImplementedError("ordered comparisons are not "
                                          "implemented for complex numbers")
            node = nodes.typednode(result, bool_)

        elif node.left.type.is_complex and rhs.type.is_datetime:
            raise error.NumbaError(
                node, "datetime comparisons not yet implemented")

        return node
Esempio n. 19
0
    def visit_ExtensionMethod(self, node, call_node=None):
        """
        Resolve an extension method:

            typedef {
                double (*method1)(double);
                ...
            } vtab_struct;

            vtab_struct *vtab = *(vtab_struct **) (((char *) obj) + vtab_offset)
            void *method = vtab[index]
        """
        if call_node is None:
            raise error.NumbaError(node, "Referenced extension method '%s' "
                                         "must be called" % node.attr)

        # Make the object we call the method on clone-able
        node.value = nodes.CloneableNode(self.visit(node.value))

        ext_type = node.value.type
        offset = ext_type.vtab_offset
        struct_type = ext_type.vtab_type.pointer()
        vmethod = self.lookup_offset_attribute(node.attr, ast.Load(), node, offset,
                                               struct_type, is_pointer=True)

        # Visit argument list for call
        args = self.visitlist(call_node.args)
        # Insert first argument 'self' in args list
        args.insert(0, nodes.CloneNode(node.value))
        result = nodes.NativeFunctionCallNode(node.type, vmethod, args)
        result.signature.is_bound_method = False
        return self.visit(result)
Esempio n. 20
0
    def _handle_jit_decorator(self, func_def, decorator):
        from numba import ast_type_inference

        jit_args = ast_type_inference._parse_args(
            decorator,
            ['restype', 'argtypes', 'backend', 'target', 'nopython'])

        if decorator.args or decorator.keywords:
            restype = self._parse_restype(decorator, jit_args)
            if restype is not None and restype.is_function:
                signature = restype
            else:
                argtypes = self._parse_argtypes(decorator, func_def, jit_args)
                signature = minitypes.FunctionType(restype,
                                                   argtypes,
                                                   name=func_def.name)
        else:  #elif func_def.args:
            raise error.NumbaError(
                decorator, "The argument types and return type "
                "need to be specified")
        #else:
        #    signature = minitypes.FunctionType(None, [])

        # TODO: Analyse closure at call or outer function return time to
        # TODO:     infer return type
        # TODO: parse out nopython argument
        return signature
Esempio n. 21
0
def require(ast_nodes, properties):
    "Assert that the types of the given nodes meets a certain requirement"
    for ast_node in ast_nodes:
        if not any(getattr(get_type(ast_node), p) for p in properties):
            typenames = ", or ".join(
                p[3:] for p in properties)  # remove 'is_' prefix
            raise error.NumbaError(ast_node, "Expected an %s" % (typenames, ))
Esempio n. 22
0
def expect_n_args(node, name, nargs):
    if not isinstance(nargs, tuple):
        nargs = (nargs, )

    if len(node.args) not in nargs:
        expected = " or ".join(map(str, nargs))
        raise error.NumbaError(
            node, "builtin %s expects %s arguments" % (name, expected))
Esempio n. 23
0
    def visit_With(self, node):
        self.visit(node.context_expr)
        if node.optional_vars:
            raise error.NumbaError(
                node.context_expr, "Only 'with python' and 'with nopython' is "
                "supported at this moment")

        self.generic_visit(node)
Esempio n. 24
0
    def visit_For(self, node):
        if not isinstance(node.target,
                          (ast.Name, ast.Attribute, nodes.TempStoreNode)):
            raise error.NumbaError(
                node.target, "Only a single target iteration variable is "
                "supported at the moment")

        self.generic_visit(node)
Esempio n. 25
0
    def visit_For(self, node):
        if not isinstance(node.target, (ast.Name, ast.Attribute)):
            raise error.NumbaError(
                node.target, "Only a single target iteration variable is "
                "supported at the moment")

        self.visitchildren(node)
        return node
Esempio n. 26
0
def validate_signature(tree, env):
    arg_types = env.translation.crnt.func_signature.args
    if (isinstance(tree, ast_module.FunctionDef) and
        len(arg_types) != len(tree.args.args)):
        raise error.NumbaError(
            "Incorrect number of types specified in @jit() for function %r" %
            env.crnt.func_name)

    return tree
Esempio n. 27
0
    def visit_WithNoPythonNode(self, node, errorcheck=True):
        if self.nopython and errorcheck:
            raise error.NumbaError(node, "Not in 'with python' context")

        self.nopython += 1
        self.visitlist(node.body)
        self.nopython -= 1

        return node
Esempio n. 28
0
    def visit_Raise(self, node):
        raise error.NumbaError(node, "Raise statement not implemented yet")

        self.visitchildren(node)
        if self.flow.exceptions:
            self.flow.block.add_child(self.flow.exceptions[-1].entry_point)

        self.flow.block = None
        return node
Esempio n. 29
0
    def visit_With(self, node):
        node.context_expr = self.visit(node.context_expr)
        if node.optional_vars:
            raise error.NumbaError(
                node.context_expr, "Only 'with python' and 'with nopython' is "
                "supported at this moment")

        self.visitlist(node.body)
        return node
Esempio n. 30
0
def find_iterator_impl(node):
    "Find a suitable iterator type for which we have an implementation"
    type = node.iter.type

    for pattern, impl in iterator_impls:
        if typematch(pattern, type):
            return impl

    raise error.NumbaError(node, "Unsupported iterator " "type: %s" % (type, ))