# a constant, local var, C global var, struct member
# reference, or temporary.
return self.result_in_temp()
-
+
+ def may_be_none(self):
+ return self.type.is_pyobject
+
def as_cython_attribute(self):
return None
+ def as_none_safe_node(self, error, message):
+ # Wraps the node in a NoneCheckNode if it is not known to be
+ # not-None (e.g. because it is a Python literal).
+ if self.may_be_none():
+ return NoneCheckNode(self, error, message)
+ else:
+ return self
+
+
class AtomicExprNode(ExprNode):
# Abstract base class for expression nodes which have
# no sub-expressions.
def is_simple(self):
return 1
-
+
+ def may_be_none(self):
+ return False
+
def analyse_types(self, env):
pass
def compile_time_value(self, denv):
return None
-
+
+ def may_be_none(self):
+ return True
+
+
class EllipsisNode(PyConstNode):
# '...' in a subscript list.
def is_simple(self):
return 1
-
+
+ def may_be_none(self):
+ return False
+
def analyse_types(self, env):
pass # Types are held in class variables
def analyse_types(self, env):
self.is_temp = 1
+ def may_be_none(self):
+ return False
+
gil_message = "Constructing Python long int"
def generate_result_code(self, code):
def analyse_types(self, env):
self.type.create_declaration_utility_code(env)
+ def may_be_none(self):
+ return False
+
def coerce_to(self, dst_type, env):
if self.type is dst_type:
return self
def analyse_types(self, env):
if self.type is None:
self.infer_type(env)
-
+
+ def may_be_none(self):
+ return False
+
def generate_result_code(self, code):
pass
self.type = tuple_type
self.is_temp = 1
+ def may_be_none(self):
+ return False
+
nogil_check = Node.gil_error
gil_message = "Constructing Python tuple"
self.type = py_object_type
self.is_temp = 1
+ def may_be_none(self):
+ return False
+
def analyse_target_types(self, env):
self.iterator = PyTempNode(self.pos, env)
self.unpacked_items = []
self.type = self.target.type
self.loop.analyse_expressions(env)
+ def may_be_none(self):
+ return False
+
def calculate_result_code(self):
return self.target.result()
self.type = set_type
self.is_temp = 1
+ def may_be_none(self):
+ return False
+
def calculate_constant_result(self):
self.constant_result = set([
arg.constant_result for arg in self.args])
item.analyse_types(env)
self.obj_conversion_errors = held_errors()
release_errors(ignore=True)
+
+ def may_be_none(self):
+ return False
def coerce_to(self, dst_type, env):
if dst_type.is_pyobject:
self.is_temp = 1
env.use_utility_code(create_class_utility_code);
+ def may_be_none(self):
+ return False
+
gil_message = "Constructing Python class"
def generate_result_code(self, code):
def analyse_types(self, env):
self.function.analyse_types(env)
+ def may_be_none(self):
+ return False
+
gil_message = "Constructing an unbound method"
def generate_result_code(self, code):
def analyse_types(self, env):
pass
+
+ def may_be_none(self):
+ return False
gil_message = "Constructing Python function"
self.pos, value=StringEncoding.EncodedString(str(self.operand.type)))
self.literal.analyse_types(env)
self.literal = self.literal.coerce_to_pyobject(env)
-
+
+ def may_be_none(self):
+ return False
+
def generate_evaluation_code(self, code):
self.literal.generate_evaluation_code(code)
self.operand2 = self.operand2.coerce_to(bytes_type, env)
env.use_utility_code(char_in_bytes_utility_code)
if not isinstance(self.operand2, (UnicodeNode, BytesNode)):
- self.operand2 = NoneCheckNode(
- self.operand2, "PyExc_TypeError",
+ self.operand2 = self.operand2.as_none_safe_node(
+ "PyExc_TypeError",
"argument of type 'NoneType' is not iterable")
else:
common_type = py_object_type
def analyse_types(self, env):
pass
+ def may_be_none(self):
+ return False
+
def result_in_temp(self):
return self.arg.result_in_temp()
gil_message = "Converting to Python object"
+ def may_be_none(self):
+ # FIXME: is this always safe?
+ return False
+
def coerce_to_boolean(self, env):
return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
def analyse_types(self, env):
pass
+ def may_be_none(self):
+ return False
+
def calculate_result_code(self):
return Naming.module_cname
return node
unpack_temp_node = UtilNodes.LetRefNode(
- ExprNodes.NoneCheckNode(
- slice_node, "PyExc_TypeError", "'NoneType' is not iterable"))
+ slice_node.as_none_safe_node("PyExc_TypeError", "'NoneType' is not iterable"))
slice_base_node = ExprNodes.PythonCapiCallNode(
slice_node.pos, unpack_func, unpack_func_type,
return node
arg = pos_args[0]
if arg.type is Builtin.dict_type:
- arg = ExprNodes.NoneCheckNode(
- arg, "PyExc_TypeError", "'NoneType' is not iterable")
+ arg = arg.as_none_safe_node("PyExc_TypeError", "'NoneType' is not iterable")
return ExprNodes.PythonCapiCallNode(
node.pos, "PyDict_Copy", self.PyDict_Copy_func_type,
args = [arg],
return node
if not isinstance(list_arg, (ExprNodes.ComprehensionNode,
ExprNodes.ListNode)):
- pos_args[0] = ExprNodes.NoneCheckNode(
- list_arg, "PyExc_TypeError",
- "'NoneType' object is not iterable")
+ pos_args[0] = list_arg.as_none_safe_node(
+ "PyExc_TypeError", "'NoneType' object is not iterable")
return ExprNodes.PythonCapiCallNode(
node.pos, "PyList_AsTuple", self.PyList_AsTuple_func_type,
if cfunc_name is None:
return node
if not arg.is_literal:
- arg = ExprNodes.NoneCheckNode(
- arg, "PyExc_TypeError",
- "object of type 'NoneType' has no len()")
+ arg = arg.as_none_safe_node(
+ "PyExc_TypeError", "object of type 'NoneType' has no len()")
new_node = ExprNodes.PythonCapiCallNode(
node.pos, cfunc_name, self.PyObject_Size_func_type,
args = [arg],
if not type_arg.type_entry:
# arbitrary variable, needs a None check for safety
- type_arg = ExprNodes.NoneCheckNode(
- type_arg, "PyExc_TypeError",
+ type_arg = type_arg.as_none_safe_node(
+ "PyExc_TypeError",
"object.__new__(X): X is not a type object (NoneType)")
return ExprNodes.PythonCapiCallNode(
if args and not args[0].is_literal:
self_arg = args[0]
if is_unbound_method:
- self_arg = ExprNodes.NoneCheckNode(
- self_arg, "PyExc_TypeError",
+ self_arg = self_arg.as_none_safe_node(
+ "PyExc_TypeError",
"descriptor '%s' requires a '%s' object but received a 'NoneType'" % (
- attr_name, node.function.obj.name))
+ attr_name, node.function.obj.name))
else:
- self_arg = ExprNodes.NoneCheckNode(
- self_arg, "PyExc_AttributeError",
+ self_arg = self_arg.as_none_safe_node(
+ "PyExc_AttributeError",
"'NoneType' object has no attribute '%s'" % attr_name)
args[0] = self_arg
return ExprNodes.PythonCapiCallNode(