Exemple #1
0
def inject_print(context, module, node):
    node = function_util.external_call(context,
                                       module,
                                       'PyObject_Str',
                                       args=[node])
    node = function_util.external_call(context, module, 'puts', args=[node])
    return node
Exemple #2
0
 def str_to_int(self, dst_type, node):
     # TODO: int <-> string conversions are explicit, this should not
     # TODO: be a coercion
     if self.nopython:
         node = nodes.CoercionNode(
             function_util.external_call(
                 self.context,
                 self.llvm_module,
                 ('atol' if dst_type.is_int else 'atof'),
                 args=[node.node]),
             dst_type, name=node.name, )
     else:
         if dst_type.is_int:
             cvtobj = function_util.external_call(
                 self.context,
                 self.llvm_module,
                 'PyInt_FromString' if not PY3 else 'PyLong_FromString',
                 args=[node.node, nodes.NULL,
                       nodes.const(10, int_)])
         else:
             cvtobj = function_util.external_call(
                 self.context,
                 self.llvm_module,
                 'PyFloat_FromString',
                 args=[node.node,
                       nodes.const(0, Py_ssize_t)])
         node = nodes.CoerceToNative(nodes.ObjectTempNode(cvtobj),
                                     dst_type, name=node.name)
     result = self.visit(node)
     return result
Exemple #3
0
 def str_to_int(self, dst_type, node):
     # TODO: int <-> string conversions are explicit, this should not
     # TODO: be a coercion
     if self.nopython:
         node = nodes.CoercionNode(
             function_util.external_call(
                 self.context,
                 self.llvm_module,
                 ('atol' if dst_type.is_int else 'atof'),
                 args=[node.node]),
             dst_type, name=node.name, )
     else:
         if dst_type.is_int:
             cvtobj = function_util.external_call(
                 self.context,
                 self.llvm_module,
                 'PyInt_FromString' if not PY3 else 'PyLong_FromString',
                 args=[node.node, nodes.NULL,
                       nodes.const(10, int_)])
         else:
             cvtobj = function_util.external_call(
                 self.context,
                 self.llvm_module,
                 'PyFloat_FromString',
                 args=[node.node,
                       nodes.const(0, Py_ssize_t)])
         node = nodes.CoerceToNative(nodes.ObjectTempNode(cvtobj),
                                     dst_type, name=node.name)
     result = self.visit(node)
     return result
Exemple #4
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
Exemple #5
0
 def _object_Pow(self, node):
     args = [node.left, node.right, nodes.ObjectInjectNode(None)]
     return self.visit(function_util.external_call(self.context,
                                                   self.llvm_module,
                                                   'PyNumber_Power',
                                                   args=args),
                       llvm_module=self.llvm_module)
Exemple #6
0
 def _object_binop(self, node, api_name):
     return self.visit(
         function_util.external_call(self.context,
                                     self.llvm_module,
                                     api_name,
                                     args=[node.left,
                                           node.right]))
Exemple #7
0
 def getiter(self, context, for_node, llvm_module):
     iterator = function_util.external_call(context, llvm_module,
                                            self.getiter_func,
                                            args=[for_node.iter])
     iterator = nodes.CloneableNode(iterator)
     self.iterator = iterator.clone
     return iterator
Exemple #8
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)
Exemple #9
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
Exemple #10
0
 def _object_binop(self, node, api_name):
     return self.visit(
         function_util.external_call(self.context,
                                     self.llvm_module,
                                     api_name,
                                     args=[node.left,
                                           node.right]))
Exemple #11
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)
Exemple #12
0
 def getiter(self, context, for_node, llvm_module):
     iterator = function_util.external_call(context,
                                            llvm_module,
                                            self.getiter_func,
                                            args=[for_node.iter])
     iterator = nodes.CloneableNode(iterator)
     self.iterator = iterator.clone
     return iterator
Exemple #13
0
    def visit_CoerceToObject(self, node):
        new_node = node

        node_type = node.node.type
        if node_type.is_bool:
            new_node = function_util.external_call(self.context,
                                                   self.llvm_module,
                                                   "PyBool_FromLong",
                                                   args=[node.node])
        elif node_type.is_numeric:
            cls = None
            args = node.node,
            if node_type.is_int:
                cls = self._get_int_conversion_func(node_type,
                                                    pyapi._from_long)
            elif node_type.is_float:
                cls = pyapi.PyFloat_FromDouble
            elif node_type.is_complex:
                cls = pyapi.PyComplex_FromDoubles
                complex_value = nodes.CloneableNode(node.node)
                args = [
                    nodes.ComplexAttributeNode(complex_value, "real"),
                    nodes.ComplexAttributeNode(complex_value.clone, "imag")
                ]
            else:
                raise error.NumbaError(
                    node,
                    "Don't know how to coerce type %r to PyObject" % node_type)

            if cls:
                new_node = function_util.external_call(self.context,
                                                       self.llvm_module,
                                                       cls.__name__,
                                                       args=args)
        elif node_type.is_pointer and not node_type.is_string():
            # Create ctypes pointer object
            ctypes_pointer_type = node_type.to_ctypes()
            args = [
                nodes.CoercionNode(node.node, int64),
                nodes.ObjectInjectNode(ctypes_pointer_type, object_)
            ]
            new_node = nodes.call_pyfunc(ctypes.cast, args)

        self.generic_visit(new_node)
        return new_node
Exemple #14
0
    def _raise_exception(self, body, node):
        if node.exc_type:
            assert node.exc_msg

            if node.exc_args:
                args = [node.exc_type, node.exc_msg] + node.exc_args
                raise_node = function_util.external_call(self.context,
                                                         self.llvm_module,
                                                         'PyErr_Format',
                                                         args=args)
            else:
                args = [node.exc_type, node.exc_msg]
                raise_node = function_util.external_call(self.context,
                                                         self.llvm_module,
                                                         'PyErr_SetString',
                                                         args=args)

            body.append(raise_node)
Exemple #15
0
 def _object_Pow(self, node):
     args = [node.left,
             node.right,
             nodes.ObjectInjectNode(None)]
     return self.visit(function_util.external_call(self.context,
                                                    self.llvm_module,
                                                    'PyNumber_Power',
                                                    args=args),
                         llvm_module=self.llvm_module)
Exemple #16
0
 def _object_Not(self, node):
     callnode = function_util.external_call(self.function_cache,
                                            self.llvm_module,
                                            'PyObject_IsTrue',
                                            args=[node.operand])
     cmpnode = ast.Compare(callnode, [nodes.Eq()], [nodes.ConstNode(0)])
     return self.visit(
         nodes.IfExp(cmpnode, nodes.ObjectInjectNode(True),
                     nodes.ObjectInjectNode(False)))
Exemple #17
0
 def _object_Not(self, node):
     callnode = function_util.external_call(self.function_cache,
                                            self.llvm_module,
                                            'PyObject_IsTrue',
                                            args=[node.operand])
     cmpnode = ast.Compare(callnode, [nodes.Eq()], [nodes.ConstNode(0)])
     return self.visit(nodes.IfExp(cmpnode,
                                   nodes.ObjectInjectNode(True),
                                   nodes.ObjectInjectNode(False)))
Exemple #18
0
 def visit_PyErr_OccurredNode(self, node):
     check_err = nodes.CheckErrorNode(nodes.ptrtoint(
         function_util.external_call(self.context, self.llvm_module,
                                     'PyErr_Occurred')),
                                      goodval=nodes.ptrtoint(nodes.NULL))
     result = nodes.CloneableNode(node.node)
     result = nodes.ExpressionNode(stmts=[result, check_err],
                                   expr=result.clone)
     return self.visit(result)
Exemple #19
0
    def _raise_exception(self, body, node):
        if node.exc_type:
            assert node.exc_msg

            if node.exc_args:
                args = [node.exc_type, node.exc_msg] + node.exc_args
                raise_node = function_util.external_call(self.context,
                                                         self.llvm_module,
                                                         'PyErr_Format',
                                                         args=args)
            else:
                args = [node.exc_type, node.exc_msg]
                raise_node = function_util.external_call(self.context,
                                                         self.llvm_module,
                                                         'PyErr_SetString',
                                                         args=args)

            body.append(raise_node)
Exemple #20
0
    def visit_CoerceToObject(self, node):
        new_node = node

        node_type = node.node.type
        if node_type.is_numeric:
            cls = None
            args = node.node,
            if node_type.is_int:
                cls = self._get_int_conversion_func(node_type,
                                                    pyapi._from_long)
            elif node_type.is_float:
                cls = pyapi.PyFloat_FromDouble
            elif node_type.is_complex:
                cls = pyapi.PyComplex_FromDoubles
                complex_value = nodes.CloneableNode(node.node)
                args = [
                    nodes.ComplexAttributeNode(complex_value, "real"),
                    nodes.ComplexAttributeNode(complex_value.clone, "imag")
                ]
            else:
                raise error.NumbaError(
                    node, "Don't know how to coerce type %r to PyObject" %
                    node_type)

            if cls:
                new_node = function_util.external_call(self.context,
                                                       self.llvm_module,
                                                       cls.__name__,
                                                       args=args)
        elif node_type.is_pointer and not node_type.is_string():
            # Create ctypes pointer object
            ctypes_pointer_type = node_type.to_ctypes()
            args = [nodes.CoercionNode(node.node, int64),
                    nodes.ObjectInjectNode(ctypes_pointer_type, object_)]
            new_node = nodes.call_pyfunc(ctypes.cast, args)
        elif node_type.is_bool:
            new_node = function_util.external_call(self.context,
                                                   self.llvm_module,
                                                   "PyBool_FromLong",
                                                   args=[node.node])

        self.generic_visit(new_node)
        return new_node
Exemple #21
0
    def _resolve_int_number(self, func, node, argtype, dst_type, ext_name):
        assert len(node.args) == 2

        arg1, arg2 = node.args
        if arg1.variable.type.is_c_string:
            return nodes.CoercionNode(nodes.ObjectTempNode(
                function_util.external_call(self.context,
                                            self.llvm_module,
                                            ext_name,
                                            args=[arg1, nodes.NULL, arg2])),
                                      dst_type=dst_type)
Exemple #22
0
 def visit_PyErr_OccurredNode(self, node):
     check_err = nodes.CheckErrorNode(
         nodes.ptrtoint(function_util.external_call(
             self.context,
             self.llvm_module,
             'PyErr_Occurred')),
         goodval=nodes.ptrtoint(nodes.NULL))
     result = nodes.CloneableNode(node.node)
     result = nodes.ExpressionNode(stmts=[result, check_err],
                                   expr=result.clone)
     return self.visit(result)
Exemple #23
0
    def _resolve_int_number(self, func, node, argtype, dst_type, ext_name):
        assert len(node.args) == 2

        arg1, arg2 = node.args
        if arg1.variable.type.is_c_string:
            return nodes.CoercionNode(
                nodes.ObjectTempNode(
                    function_util.external_call(
                        self.context,
                        self.llvm_module,
                        ext_name,
                        args=[arg1, nodes.NULL, arg2])),
                dst_type=dst_type)
Exemple #24
0
    def _print(self, value, dest=None):
        signature, lfunc = self.context.external_library.declare(
            self.llvm_module, 'PyObject_CallMethod')

        if dest is None:
            dest = nodes.ObjectInjectNode(sys.stdout)

        value = function_util.external_call(self.context,
                                            self.llvm_module,
                                            "PyObject_Str",
                                            args=[value])
        args = [dest, nodes.ConstNode("write"), nodes.ConstNode("O"), value]
        return nodes.NativeCallNode(signature, args, lfunc)
Exemple #25
0
    def _print(self, value, dest=None):
        signature, lfunc = self.context.external_library.declare(
                                                         self.llvm_module,
                                                         'PyObject_CallMethod')

        if dest is None:
            dest = nodes.ObjectInjectNode(sys.stdout)

        value = function_util.external_call(self.context,
                                            self.llvm_module,
                                           "PyObject_Str",
                                            args=[value])
        args = [dest, nodes.ConstNode("write"), nodes.ConstNode("O"), value]
        return nodes.NativeCallNode(signature, args, lfunc)
Exemple #26
0
    def single_compare_objects(self, node):
        op = type(node.ops[0])
        if op not in opmap:
            raise error.NumbaError(
                    node, "%s comparisons not yet implemented" % (op,))

        # Build arguments for PyObject_RichCompareBool
        operator = nodes.const(opmap[op], int_)
        args = [node.left, node.comparators[0], operator]

        # Call PyObject_RichCompareBool
        compare = function_util.external_call(self.context,
                                              self.llvm_module,
                                              'PyObject_RichCompareBool',
                                              args=args)

        # Coerce int result to bool
        return nodes.CoercionNode(compare, bool_)
Exemple #27
0
    def single_compare_objects(self, node):
        op = type(node.ops[0])
        if op not in opmap:
            raise error.NumbaError(
                node, "%s comparisons not yet implemented" % (op, ))

        # Build arguments for PyObject_RichCompareBool
        operator = nodes.const(opmap[op], int_)
        args = [node.left, node.comparators[0], operator]

        # Call PyObject_RichCompareBool
        compare = function_util.external_call(self.context,
                                              self.llvm_module,
                                              'PyObject_RichCompare',
                                              args=args)

        # Coerce int result to bool
        return nodes.CoercionNode(compare, node.type)
Exemple #28
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 function_util.external_call(
                                       self.context,
                                       self.llvm_module,
                                       'printf',
                                       args=[nodes.const(format, c_string_type),
                                             value])
Exemple #29
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 function_util.external_call(
            self.context,
            self.llvm_module,
            'printf',
            args=[nodes.const(format, c_string_type), value])
Exemple #30
0
    def visit_Subscript(self, node):
        if isinstance(node.value, nodes.ArrayAttributeNode):
            if node.value.is_read_only and isinstance(node.ctx, ast.Store):
                raise error.NumbaError("Attempt to load read-only attribute")

        # Short-circuit visiting a Slice child if this is a nopython
        # string slice.
        if (self.nopython and node.value.type.is_string and
                node.type.is_string):
            return self.visit(self._c_string_slice(node))

        # logging.debug(ast.dump(node))
        # TODO: do this in the respective cases below when needed
        self.generic_visit(node)

        node_type = node.value.type
        if ((node_type.is_object and not node_type.is_array) or
            (node_type.is_array and node.slice.type.is_object)):
            # Array or object slicing
            if isinstance(node.ctx, ast.Load):
                result = function_util.external_call(self.context,
                                                     self.llvm_module,
                                                     'PyObject_GetItem',
                                                     args=[node.value,
                                                           node.slice])
                node = nodes.CoercionNode(result, dst_type=node.type)
                node = self.visit(node)
            else:
                # This is handled in visit_Assign
                pass
        elif (node.value.type.is_array and not node.type.is_array and
                  node.slice.type.is_int):
            # Array index with integer indices
            node = nodes.DataPointerNode(node.value, node.slice, node.ctx)
        elif node.value.type.is_string and node.type.is_string:
            node.value = nodes.CoercionNode(node.value, dst_type = object_)
            node.type = object_
            node = nodes.CoercionNode(nodes.ObjectTempNode(node),
                                      dst_type = c_string_type)
            node = self.visit(node)

        return node
Exemple #31
0
    def visit_Subscript(self, node):
        if isinstance(node.value, nodes.ArrayAttributeNode):
            if node.value.is_read_only and isinstance(node.ctx, ast.Store):
                raise error.NumbaError("Attempt to load read-only attribute")

        # Short-circuit visiting a Slice child if this is a nopython
        # string slice.
        if (self.nopython and node.value.type.is_c_string
                and node.type.is_c_string):
            return self.visit(self._c_string_slice(node))

        # logging.debug(ast.dump(node))
        # TODO: do this in the respective cases below when needed
        self.generic_visit(node)

        node_type = node.value.type
        if node_type.is_object or (node_type.is_array
                                   and node.slice.type.is_object):
            # Array or object slicing
            if isinstance(node.ctx, ast.Load):
                result = function_util.external_call(
                    self.context,
                    self.llvm_module,
                    'PyObject_GetItem',
                    args=[node.value, node.slice])
                node = nodes.CoercionNode(result, dst_type=node.type)
                node = self.visit(node)
            else:
                # This is handled in visit_Assign
                pass
        elif (node.value.type.is_array and not node.type.is_array
              and node.slice.type.is_int):
            # Array index with integer indices
            node = nodes.DataPointerNode(node.value, node.slice, node.ctx)
        elif node.value.type.is_c_string and node.type.is_c_string:
            node.value = nodes.CoercionNode(node.value, dst_type=object_)
            node.type = object_
            node = nodes.CoercionNode(nodes.ObjectTempNode(node),
                                      dst_type=c_string_type)
            node = self.visit(node)

        return node
Exemple #32
0
    def _resolve_abs(self, func, node, argtype):
        is_math = is_math_function(node.args, abs)

        # TODO: generate efficient inline code
        if is_math and argtype.is_float:
            return resolve_math_call(node, abs)
        elif is_math and argtype.is_int:
            if argtype.signed:
                type = promote_closest(self.context, argtype, [long_, longlong])
                funcs = {long_: 'labs', longlong: 'llabs'}
                return function_util.external_call(
                                            self.context,
                                            self.llvm_module,
                                            funcs[type],
                                            args=[node.args[0]])
            else:
                # abs() on unsigned integral value
                return node.args[0]

        return None
Exemple #33
0
    def _resolve_abs(self, func, node, argtype):
        is_math = is_math_function(node.args, abs)

        # TODO: generate efficient inline code
        if is_math and argtype.is_float:
            return resolve_math_call(node, abs)
        elif is_math and argtype.is_int:
            if argtype.signed:
                type = promote_closest(self.context, argtype,
                                       [long_, longlong])
                funcs = {long_: 'labs', longlong: 'llabs'}
                return function_util.external_call(self.context,
                                                   self.llvm_module,
                                                   funcs[type],
                                                   args=[node.args[0]])
            else:
                # abs() on unsigned integral value
                return node.args[0]

        return None
Exemple #34
0
    def _trap(self, body, node):
        if node.exc_msg and node.print_on_trap:
            pos = error.format_pos(node)
            if node.exception_type:
                exc_type = '%s: ' % node.exception_type.__name__
            else:
                exc_type = ''

            msg = '%s%s%%s' % (exc_type, pos)
            format = nodes.const(msg, c_string_type)
            print_msg = function_util.external_call(self.context,
                                                    self.llvm_module,
                                                    'printf',
                                                    args=[format,
                                                          node.exc_msg])
            body.append(print_msg)

        trap = nodes.LLVMIntrinsicNode(signature=void(), args=[],
                                       func_name='TRAP')
        body.append(trap)
Exemple #35
0
    def _trap(self, body, node):
        if node.exc_msg and node.print_on_trap:
            pos = error.format_pos(node)
            if node.exception_type:
                exc_type = '%s: ' % node.exception_type.__name__
            else:
                exc_type = ''

            msg = '%s%s%%s' % (exc_type, pos)
            format = nodes.const(msg, c_string_type)
            print_msg = function_util.external_call(
                self.context,
                self.llvm_module,
                'printf',
                args=[format, node.exc_msg])
            body.append(print_msg)

        trap = nodes.LLVMIntrinsicNode(signature=void(),
                                       args=[],
                                       func_name='TRAP')
        body.append(trap)
Exemple #36
0
    def visit_Assign(self, node):
        target = node.targets[0]
        target_is_subscript = (len(node.targets) == 1
                               and isinstance(target, ast.Subscript))
        if target_is_subscript and is_obj(target.type):
            # Slice assignment / index assignment w/ objects
            # TODO: discount array indexing with dtype object
            target = self.visit(target)
            obj = target.value
            key = target.slice
            value = self.visit(node.value)
            call = function_util.external_call(self.context,
                                               self.llvm_module,
                                               'PyObject_SetItem',
                                               args=[obj, key, value])
            return self.visit(call)

        elif target.type.is_struct and nodes.is_name(target):
            node = self.allocate_struct_on_stack(node, target)
            return node

        self.generic_visit(node)
        return node
Exemple #37
0
    def visit_Assign(self, node):
        target = node.targets[0]
        target_is_subscript = (len(node.targets) == 1 and
                               isinstance(target, ast.Subscript))
        if target_is_subscript and is_obj(target.type):
            # Slice assignment / index assignment w/ objects
            # TODO: discount array indexing with dtype object
            target = self.visit(target)
            obj = target.value
            key = target.slice
            value = self.visit(node.value)
            call = function_util.external_call(self.context,
                                               self.llvm_module,
                                               'PyObject_SetItem',
                                               args=[obj, key, value])
            return self.visit(call)

        elif target.type.is_struct and nodes.is_name(target):
            node = self.allocate_struct_on_stack(node, target)
            return node

        self.generic_visit(node)
        return node
Exemple #38
0
 def next(self, context, for_node, llvm_module):
     return function_util.external_call(context, llvm_module, self.next_func, args=[self.iterator])
Exemple #39
0
def inject_print(context, module, node):
    node = function_util.external_call(context, module, "PyObject_Str", args=[node])
    node = function_util.external_call(context, module, "puts", args=[node])
    return node
Exemple #40
0
 def _object_unaryop(self, node, api_name):
     return self.visit(
         function_util.external_call(self.context,
                                     self.llvm_module,
                                     api_name,
                                     args=[node.operand]))
Exemple #41
0
 def _object_unaryop(self, node, api_name):
     return self.visit(
         function_util.external_call(self.context,
                                     self.llvm_module,
                                     api_name,
                                     args=[node.operand]))
Exemple #42
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))

        if self.nopython and is_obj(node_type):
            raise error.NumbaError(node, "Cannot coerce to or from object in "
                                         "nopython context")

        if 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)
        elif node_type.is_c_string and dst_type.is_numeric:
            # TODO: int <-> string conversions are explicit, this should not
            # TODO: be a coercion
            if self.nopython:
                node = nodes.CoercionNode(
                    function_util.external_call(
                                self.context,
                                self.llvm_module,
                                ('atol' if dst_type.is_int else 'atof'),
                                args=[node.node]),
                    dst_type, name=node.name,)
            else:
                if dst_type.is_int:
                    cvtobj = function_util.external_call(
                                              self.context,
                                              self.llvm_module,
                                              'PyInt_FromString' if not PY3 else 'PyLong_FromString',
                                              args=[node.node, nodes.NULL,
                                                    nodes.const(10, int_)])
                else:
                    cvtobj = function_util.external_call(
                                          self.context,
                                          self.llvm_module,
                                          'PyFloat_FromString',
                                          args=[node.node,
                                                nodes.const(0, Py_ssize_t)])
                node = nodes.CoerceToNative(nodes.ObjectTempNode(cvtobj),
                                            dst_type, name=node.name)
            result = self.visit(node)
        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
Exemple #43
0
 def next(self, context, for_node, llvm_module):
     return function_util.external_call(context,
                                        llvm_module,
                                        self.next_func,
                                        args=[self.iterator])
Exemple #44
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
                new_node = self.object_to_int(node.node, node_type)
            elif node_type.is_float:
                cls = pyapi.PyFloat_AsDouble
            elif node_type.is_complex:
                # FIXME: This conversion has to be pretty slow.  We
                # need to move towards being ABI-savvy enough to just
                # call PyComplex_AsCComplex().
                cloneable = nodes.CloneableNode(node.node)
                new_node = nodes.ComplexNode(
                    real=function_util.external_call(self.context,
                                                     self.llvm_module,
                                                     "PyComplex_RealAsDouble",
                                                     args=[cloneable]),
                    imag=function_util.external_call(self.context,
                                                     self.llvm_module,
                                                     "PyComplex_ImagAsDouble",
                                                     args=[cloneable.clone]))
            else:
                raise error.NumbaError(
                    node, "Don't know how to coerce a Python object to a %r" %
                    node_type)

            if cls:
                # TODO: error checking!
                new_node = function_util.external_call(self.context,
                                                       self.llvm_module,
                                                       cls.__name__,
                                                       args=[node.node])
        elif node_type.is_pointer:
            if from_type.is_jit_function and node_type.base_type.is_function:
                new_node = self.coerce_to_function_pointer(
                    node, from_type, node_type)
            else:
                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())
            self.generic_visit(node)
            return node

        if new_node.type != node.type:
            # Fast native coercion. E.g. coercing an object to an int_
            # will use PyLong_AsLong, but that will return a long_. We
            # need to coerce the long_ to an int_
            new_node = nodes.CoercionNode(new_node, node.type)

        # Specialize replacement node
        new_node = self.visit(new_node)
        return new_node
Exemple #45
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))

        if self.nopython and (is_obj(node_type) ^ is_obj(dst_type)):
            raise error.NumbaError(
                node, "Cannot coerce to or from object in "
                "nopython context")

        if 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)
        elif node_type.is_c_string and dst_type.is_numeric:
            # TODO: int <-> string conversions are explicit, this should not
            # TODO: be a coercion
            if self.nopython:
                node = nodes.CoercionNode(
                    function_util.external_call(
                        self.context,
                        self.llvm_module,
                        ('atol' if dst_type.is_int else 'atof'),
                        args=[node.node]),
                    dst_type,
                    name=node.name,
                )
            else:
                if dst_type.is_int:
                    cvtobj = function_util.external_call(
                        self.context,
                        self.llvm_module,
                        'PyInt_FromString' if not PY3 else 'PyLong_FromString',
                        args=[node.node, nodes.NULL,
                              nodes.const(10, int_)])
                else:
                    cvtobj = function_util.external_call(
                        self.context,
                        self.llvm_module,
                        'PyFloat_FromString',
                        args=[node.node, nodes.const(0, Py_ssize_t)])
                node = nodes.CoerceToNative(nodes.ObjectTempNode(cvtobj),
                                            dst_type,
                                            name=node.name)
            result = self.visit(node)
        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
Exemple #46
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
                new_node = self.object_to_int(node.node, node_type)
            elif node_type.is_float:
                cls = pyapi.PyFloat_AsDouble
            elif node_type.is_complex:
                # FIXME: This conversion has to be pretty slow.  We
                # need to move towards being ABI-savvy enough to just
                # call PyComplex_AsCComplex().
                cloneable = nodes.CloneableNode(node.node)
                new_node = nodes.ComplexNode(
                    real=function_util.external_call(
                        self.context, self.llvm_module,
                        "PyComplex_RealAsDouble", args=[cloneable]),
                    imag=function_util.external_call(
                        self.context, self.llvm_module,
                        "PyComplex_ImagAsDouble", args=[cloneable.clone]))
            else:
                raise error.NumbaError(
                    node, "Don't know how to coerce a Python object to a %r" %
                    node_type)

            if cls:
                # TODO: error checking!
                new_node = function_util.external_call(self.context,
                                                       self.llvm_module,
                                                       cls.__name__,
                                                       args=[node.node])
        elif node_type.is_pointer and not node_type.is_string:
            if from_type.is_jit_function and node_type.base_type.is_function:
                new_node = self.coerce_to_function_pointer(
                    node, from_type, node_type)
            else:
                raise error.NumbaError(node, "Obtaining pointers from objects "
                                             "is not yet supported (%s)" % node_type)
        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())
            self.generic_visit(node)
            return node

        if new_node.type != node.type:
            # Fast native coercion. E.g. coercing an object to an int_
            # will use PyLong_AsLong, but that will return a long_. We
            # need to coerce the long_ to an int_
            new_node = nodes.CoercionNode(new_node, node.type)

        # Specialize replacement node
        new_node = self.visit(new_node)
        return new_node