示例#1
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
示例#2
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)
示例#3
0
    def visit_ConstNode(self, node):
        constant = node.pyval

        if node.type.is_complex:
            real = nodes.ConstNode(constant.real, node.type.base_type)
            imag = nodes.ConstNode(constant.imag, node.type.base_type)
            node = nodes.ComplexNode(real, imag)

        elif node.type.is_pointer:
            addr_int = constnodes.get_pointer_address(constant, node.type)
            node = nodes.ptrfromint(addr_int, node.type)

        elif node.type.is_object and not nodes.is_null_constant(constant):
            node = nodes.ObjectInjectNode(constant, node.type)

        return node
示例#4
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)))
示例#5
0
    def visit_Tuple(self, node):
        self.check_context(node)

        sig, lfunc = self.context.external_library.declare(
            self.llvm_module, 'PyTuple_Pack')
        objs = self.visitlist(nodes.CoercionNode.coerce(node.elts, object_))
        n = nodes.ConstNode(len(node.elts), minitypes.Py_ssize_t)
        args = [n] + objs
        new_node = nodes.NativeCallNode(sig, args, lfunc, name='tuple')
        # TODO: determine element type of node.elts
        new_node.type = typesystem.TupleType(object_, size=len(node.elts))
        return nodes.ObjectTempNode(new_node)
示例#6
0
    def handle_method_call(self, env, node, call_node):
        """
        Resolve an extension method of a dynamic hash-based vtable:

            PyCustomSlots_Table ***vtab_slot = (((char *) obj) + vtab_offset)
            lookup_virtual_method(*vtab_slot)

        We may cache (*vtab_slot), but we may not cache (**vtab_slot), since
        compilations may regenerate the table.

        However, we could *preload* (**vtab_slot), where function calls
        invalidate the preload, if we were so inclined.
        """
        # Make the object we call the method on clone-able
        node.value = nodes.CloneableNode(node.value)

        ext_type = node.ext_type
        func_signature = node.type  #typesystem.extmethod_to_function(node.type)
        offset = ext_type.vtab_offset

        # __________________________________________________________________
        # Retrieve vtab

        vtab_ppp = nodes.value_at_offset(node.value, offset,
                                         void.pointer().pointer())
        vtab_struct_pp = nodes.DereferenceNode(vtab_ppp)

        # __________________________________________________________________
        # Calculate pre-hash

        prehash = virtual.hash_signature(func_signature, func_signature.name)
        prehash_node = nodes.ConstNode(prehash, uint64)

        # __________________________________________________________________
        # Retrieve method pointer

        # A method is always present when it was given a static signature,
        # e.g. @double(double)
        always_present = node.attr in ext_type.vtab_type.methodnames
        args = [vtab_struct_pp, prehash_node]

        # lookup_impl = NumbaVirtualLookup()
        lookup_impl = DebugVirtualLookup()
        ptr = lookup_impl.lookup(env, always_present, node, args)
        vmethod = ptr.coerce(func_signature.pointer())
        vmethod = vmethod.cloneable

        # __________________________________________________________________
        # Call method pointer

        # Insert first argument 'self' in args list
        args = call_node.args
        args.insert(0, nodes.CloneNode(node.value))
        method_call = nodes.NativeFunctionCallNode(func_signature, vmethod,
                                                   args)

        # __________________________________________________________________
        # Generate fallback

        # TODO: Subclassing!
        # if not always_present:
        #     # TODO: Enable this path and generate a phi for the result
        #     # Generate object call
        #     obj_args = [nodes.CoercionNode(arg, object_) for arg in args]
        #     obj_args.append(nodes.NULL)
        #     object_call = function_util.external_call(
        #         env.context, env.crnt.llvm_module,
        #         'PyObject_CallMethodObjArgs', obj_args)
        #
        #     # if vmethod != NULL: vmethod(obj, ...)
        #     # else: obj.method(...)
        #     method_call = nodes.if_else(
        #         ast.NotEq(),
        #         vmethod.clone, nodes.NULL,
        #         lhs=method_call, rhs=object_call)

        return method_call
示例#7
0
文件: coerce.py 项目: jgors/numba
 def _create_llvm_string(self, str):
     return self.translator.visit(nodes.ConstNode(str, char.pointer()))
示例#8
0
    def rewrite_array_iteration(self, node):
        """
        Convert 1D array iteration to for-range and indexing:

            for value in my_array:
                ...

        becomes

            for i in my_array.shape[0]:
                value = my_array[i]
                ...
        """
        logger.debug(ast.dump(node))

        orig_target = node.target
        orig_iter = node.iter

        #--------------------------------------------------------------------
        # Replace node.target with a temporary
        #--------------------------------------------------------------------

        target_name = orig_target.id + '.idx'
        target_temp = nodes.TempNode(Py_ssize_t)
        node.target = target_temp.store()

        #--------------------------------------------------------------------
        # Create range(A.shape[0])
        #--------------------------------------------------------------------

        call_func = ast.Name(id='range', ctx=ast.Load())
        nodes.typednode(call_func, typesystem.range_)

        shape_index = ast.Index(nodes.ConstNode(0, typesystem.Py_ssize_t))
        shape_index.type = typesystem.npy_intp

        stop = ast.Subscript(value=nodes.ShapeAttributeNode(orig_iter),
                             slice=shape_index,
                             ctx=ast.Load())
        nodes.typednode(stop, npy_intp)

        #--------------------------------------------------------------------
        # Create range iterator and replace node.iter
        #--------------------------------------------------------------------

        call_args = [
            nodes.ConstNode(0, typesystem.Py_ssize_t),
            nodes.CoercionNode(stop, typesystem.Py_ssize_t),
            nodes.ConstNode(1, typesystem.Py_ssize_t),
        ]

        node.iter = ast.Call(func=call_func, args=call_args)
        nodes.typednode(node.iter, call_func.type)

        node.index = target_temp.load(invariant=True)

        #--------------------------------------------------------------------
        # Add assignment to new target variable at the start of the body
        #--------------------------------------------------------------------

        index = ast.Index(value=node.index)
        index.type = target_temp.type
        subscript = ast.Subscript(value=orig_iter, slice=index, ctx=ast.Load())
        nodes.typednode(subscript, get_type(orig_iter).dtype)

        #--------------------------------------------------------------------
        # Add assignment to new target variable at the start of the body
        #--------------------------------------------------------------------

        assign = ast.Assign(targets=[orig_target], value=subscript)
        node.body = [assign] + node.body

        #--------------------------------------------------------------------
        # Specialize new for loop through range iteration
        #--------------------------------------------------------------------

        return self.visit(node)
示例#9
0
def cast(node, dst_type):
    if len(node.args) == 0:
        return nodes.ConstNode(0, dst_type)
    else:
        return nodes.CoercionNode(node.args[0], dst_type=dst_type)
示例#10
0
 def _create_llvm_string(self, str):
     return self.translator.visit(nodes.ConstNode(str, c_string_type))