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 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)) return 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) return self.visit(node) if node.node.type == node.type: node = self.visit(node.node) else: self.generic_visit(node) return node
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 logger.getEffectiveLevel() < logging.DEBUG: logger.debug('coercion: %s --> %s\n%s' % ( node_type, dst_type, pprint.pformat(utils.ast2tree(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)) return 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) return result elif node_type.is_c_string and dst_type.is_numeric: if self.nopython: node = nodes.CoercionNode( self.function_cache.call('atol' if dst_type.is_int else 'atof', node.node), dst_type, name=node.name) else: if dst_type.is_int: cvtobj = self.function_cache.call( 'PyInt_FromString', node.node, nodes.NULL, nodes.const(10, int_)) else: cvtobj = self.function_cache.call( 'PyFloat_FromString', node.node, nodes.const(0, Py_ssize_t)) node = nodes.CoerceToNative(nodes.ObjectTempNode(cvtobj), dst_type, name=node.name) return self.visit(node) self.generic_visit(node) if not node.node.type == node_type: return self.visit(node) if dst_type == node.node.type: return node.node return node
def visit_FunctionDef(self, node): self.handle_phis() node.decorator_list = self.visitlist(node.decorator_list) node.body = self.visitlist(node.body) ret_type = self.func_signature.return_type if ret_type.is_object or ret_type.is_array: # This will require some increfs, but allow it if people # use 'with python' later on. If 'with python' isn't used, a # return will issue the error #if self.nopython: # raise error.NumbaError( # node, "Function cannot return object in " # "nopython context") pass value = badval(ret_type) if value is not None: value = nodes.CoercionNode(value, dst_type=ret_type).cloneable error_return = ast.Return(value=value) if self.nopython and is_obj(self.func_signature.return_type): error_return = nodes.WithPythonNode(body=[error_return]) node.error_return = error_return return node
def visit_FunctionDef(self, node): # self.generic_visit(node) node.decorator_list = self.visitlist(node.decorator_list) node.body = self.visitlist(node.body) ret_type = self.func_signature.return_type if ret_type.is_object or ret_type.is_array: # This will require some increfs, but allow it if people # use 'with python' later on. If 'with python' isn't used, a # return will issue the error #if self.nopython: # raise error.NumbaError( # node, "Function cannot return object in " # "nopython context") value = nodes.NULL_obj elif ret_type.is_void: value = None elif ret_type.is_float: value = nodes.ConstNode(float('nan'), type=ret_type) elif ret_type.is_int or ret_type.is_complex: value = nodes.ConstNode(0xbadbadbad, type=ret_type) else: value = None if value is not None: value = nodes.CoercionNode(value, dst_type=ret_type).cloneable error_return = ast.Return(value=value) if self.nopython and is_obj(self.func_signature.return_type): error_return = nodes.WithPythonNode(body=[error_return]) node.error_return = error_return return node
def visit_NativeCallNode(self, node): self.generic_visit(node) if is_obj(node.signature.return_type): if self.nopython: raise error.NumbaError( node, "Cannot call function returning object in " "nopython context") node = nodes.ObjectTempNode(node) return node
def visit_Attribute(self, node): if self.nopython: raise error.NumbaError( node, "Cannot access Python attribute in nopython context") if node.type.is_numpy_attribute: return nodes.ObjectInjectNode(node.type.value) elif is_obj(node.value.type): node = self.function_cache.call( 'PyObject_GetAttrString', node.value, nodes.ConstNode(node.attr)) return self.visit(node) self.generic_visit(node) return node
def visit_Assign(self, node): target = node.targets[0] if (len(node.targets) == 1 and isinstance(target, ast.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 = self.function_cache.call('PyObject_SetItem', obj, key, value) return call self.generic_visit(node) return node
def visit_Assign(self, node): target = node.targets[0] if (len(node.targets) == 1 and isinstance(target, ast.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 = self.function_cache.call('PyObject_SetItem', obj, key, value) return self.visit(call) self.generic_visit(node) return node
def visit_Attribute(self, node): if self.nopython: raise error.NumbaError( node, "Cannot access Python attribute in nopython context") if node.type.is_numpy_attribute: return nodes.ObjectInjectNode(node.type.value) elif is_obj(node.value.type): if node.type.is_module_attribute: new_node = nodes.ObjectInjectNode(node.type.value) else: new_node = self.function_cache.call( 'PyObject_GetAttrString', node.value, nodes.ConstNode(node.attr)) return self.visit(new_node) self.generic_visit(node) return node
def visit_NativeCallNode(self, node): if is_obj(node.signature.return_type): if self.nopython: raise error.NumbaError( node, "Cannot call function returning object in " "nopython context") self.generic_visit(node) return nodes.ObjectTempNode(node) elif node.badval is not None: cloneable_node = node.cloneable body = nodes.CheckErrorNode(cloneable_node, node.badval, node.exc_type, node.exc_msg, node.exc_args) node = nodes.ExpressionNode(stmts=[body], expr=cloneable_node.clone) return self.visit(node) else: self.generic_visit(node) return node
def visit_NativeCallNode(self, node): if is_obj(node.signature.return_type): if self.nopython: raise error.NumbaError( node, "Cannot call function returning object in " "nopython context") self.generic_visit(node) return nodes.ObjectTempNode(node) elif node.badval is not None: result = node.cloneable body = nodes.CheckErrorNode( result, node.badval, node.goodval, node.exc_type, node.exc_msg, node.exc_args) node = nodes.ExpressionNode(stmts=[body], expr=result.clone) return self.visit(node) else: self.generic_visit(node) return node
def visit_Name(self, node): if node.type.is_builtin and not node.variable.is_local: obj = getattr(builtins, node.name) return nodes.ObjectInjectNode(obj, node.type) if (is_obj(node.type) and isinstance(node.ctx, ast.Load) and getattr(node, 'cf_maybe_null', False)): # Check for unbound objects and raise UnboundLocalError if so value = nodes.LLVMValueRefNode(Py_uintptr_t, None) node.loaded_name = value exc_msg = node.variable.name if hasattr(node, 'lineno'): exc_msg = '%s%s' % (error.format_pos(node), exc_msg) check_unbound = nodes.CheckErrorNode( value, badval=nodes.const(0, Py_uintptr_t), exc_type=UnboundLocalError, exc_msg=exc_msg) node.check_unbound = self.visit(check_unbound) return super(LateSpecializer, self).visit_Name(node)
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 logger.getEffectiveLevel() < logging.DEBUG: logger.debug('coercion: %s --> %s\n%s' % ( node_type, dst_type, pprint.pformat(utils.ast2tree(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)) return 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) return result 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") return self.visit(nodes.NULL.coerce(dst_type)) elif node_type.is_numeric and dst_type.is_bool: return self.visit(ast.Compare(node.node, [ast.NotEq()], [nodes.const(0, node_type)])) 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( self.function_cache.call('atol' if dst_type.is_int else 'atof', node.node), dst_type, name=node.name) else: if dst_type.is_int: cvtobj = self.function_cache.call( 'PyInt_FromString', node.node, nodes.NULL, nodes.const(10, int_)) else: cvtobj = self.function_cache.call( 'PyFloat_FromString', node.node, nodes.const(0, Py_ssize_t)) node = nodes.CoerceToNative(nodes.ObjectTempNode(cvtobj), dst_type, name=node.name) return self.visit(node) self.generic_visit(node) if not node.node.type == node_type: return self.visit(node) if dst_type == node.node.type: return node.node return node