# Convenience routine performing both the Type
# Analysis and Temp Allocation phases for a whole
# expression.
- self.analyse_types(env)
+ return self.analyse_types(env)
def analyse_target_expression(self, env, rhs):
# Convenience routine performing both the Type
# Analysis and Temp Allocation phases for the LHS of
# an assignment.
- self.analyse_target_types(env)
+ return self.analyse_target_types(env)
def analyse_boolean_expression(self, env):
# Analyse expression and coerce to a boolean.
- self.analyse_types(env)
- bool = self.coerce_to_boolean(env)
+ node = self.analyse_types(env)
+ bool = node.coerce_to_boolean(env)
return bool
def analyse_temp_boolean_expression(self, env):
# afterwards. By forcing the result into a temporary,
# we ensure that all disposal has been done by the
# time we get the result.
- self.analyse_types(env)
- return self.coerce_to_boolean(env).coerce_to_simple(env)
+ node = self.analyse_types(env)
+ return node.coerce_to_boolean(env).coerce_to_simple(env)
# --------------- Type Inference -----------------
self.not_implemented("analyse_types")
def analyse_target_types(self, env):
- self.analyse_types(env)
+ return self.analyse_types(env)
def nogil_check(self, env):
# By default, any expression based on Python objects is
return False
def analyse_types(self, env):
- pass
+ return self
def calculate_result_code(self):
return self.value
return False
def analyse_types(self, env):
- pass # Types are held in class variables
+ return self # Types are held in class variables
def check_const(self):
return True
pos = (self.pos[0], self.pos[1], self.pos[2]-7)
declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
sizeof_node = declaration.root.stats[0].expr
- sizeof_node.analyse_types(env)
+ sizeof_node = sizeof_node.analyse_types(env)
if isinstance(sizeof_node, SizeofTypeNode):
return sizeof_node.arg_type
def analyse_types(self, env):
self.is_temp = 1
+ return self
def may_be_none(self):
return False
def analyse_types(self, env):
self.type.create_declaration_utility_code(env)
+ return self
def may_be_none(self):
return False
def analyse_types(self, env):
if self.type is None:
self.infer_type(env)
+ return self
def may_be_none(self):
return False
self.entry = env.declare_builtin(self.name, self.pos)
if not self.entry:
self.type = PyrexTypes.error_type
- return
+ return self
entry = self.entry
if entry:
entry.used = 1
import Buffer
Buffer.used_buffer_aux_vars(entry)
self.analyse_rvalue_entry(env)
+ return self
def analyse_target_types(self, env):
self.analyse_entry(env)
if self.entry.type.is_buffer:
import Buffer
Buffer.used_buffer_aux_vars(self.entry)
+ return self
def analyse_rvalue_entry(self, env):
#print "NameNode.analyse_rvalue_entry:", self.name ###
subexprs = ['arg']
def analyse_types(self, env):
- self.arg.analyse_types(env)
+ self.arg = self.arg.analyse_types(env)
self.arg = self.arg.coerce_to_pyobject(env)
self.is_temp = 1
+ return self
gil_message = "Backquote expression"
self.level = -1
else:
self.level = 0
- self.module_name.analyse_types(env)
- self.module_name = self.module_name.coerce_to_pyobject(env)
+ module_name = self.module_name.analyse_types(env)
+ self.module_name = module_name.coerce_to_pyobject(env)
if self.name_list:
- self.name_list.analyse_types(env)
- self.name_list.coerce_to_pyobject(env)
+ name_list = self.name_list.analyse_types(env)
+ self.name_list = name_list.coerce_to_pyobject(env)
self.is_temp = 1
env.use_utility_code(UtilityCode.load_cached("Import", "ImportExport.c"))
+ return self
gil_message = "Python import"
subexprs = ['sequence']
def analyse_types(self, env):
- self.sequence.analyse_types(env)
+ self.sequence = self.sequence.analyse_types(env)
if (self.sequence.type.is_array or self.sequence.type.is_ptr) and \
not self.sequence.type.is_string:
# C array iteration will be transformed later on
self.sequence.type is tuple_type:
self.sequence = self.sequence.as_none_safe_node("'NoneType' object is not iterable")
self.is_temp = 1
+ return self
gil_message = "Iterating over Python object"
def analyse_types(self, env):
self.type = self.infer_type(env, self.iterator.type)
self.is_temp = 1
+ return self
def generate_result_code(self, code):
self.iterator.generate_iter_next_result_code(self.result(), code)
subexprs = ['args']
def analyse_types(self, env):
- self.args.analyse_types(env)
+ self.args = self.args.analyse_types(env)
self.type = PyrexTypes.c_bint_type
self.is_temp = True
+ return self
def generate_result_code(self, code):
if isinstance(self.args, TupleNode):
pass
def analyse_types(self, env):
- pass
+ return self
class TempNode(ExprNode):
self.is_temp = 1
def analyse_types(self, env):
- return self.type
+ return self
def analyse_target_declaration(self, env):
pass
self.cname = cname
def analyse_types(self, env):
- return self.type
+ return self
def set_cname(self, cname):
self.cname = cname
def analyse_types(self, env):
self.is_temp = True
# env.add_include_file("omp.h")
- return self.type
+ return self
def generate_result_code(self, code):
code.putln("#ifdef _OPENMP")
def analyse_types(self, env):
self.is_temp = True
# env.add_include_file("omp.h")
- return self.type
+ return self
def generate_result_code(self, code):
code.putln("#ifdef _OPENMP")
def analyse_types(self, env):
self.analyse_base_and_index_types(env, getting = 1)
+ return self
def analyse_target_types(self, env):
self.analyse_base_and_index_types(env, setting = 1)
error(self.pos, "Assignment to const dereference")
if not self.is_lvalue():
error(self.pos, "Assignment to non-lvalue of type '%s'" % self.type)
+ return self
def analyse_base_and_index_types(self, env, getting = 0, setting = 0, analyse_base = True):
# Note: This might be cleaned up by having IndexNode
self.memslice_index = False
if analyse_base:
- self.base.analyse_types(env)
+ self.base = self.base.analyse_types(env)
if self.base.type.is_error:
# Do not visit child tree if base is undeclared to avoid confusing
axis_idx = 0
for i, index in enumerate(indices[:]):
- index.analyse_types(env)
+ index = index.analyse_types(env)
if not index.is_none:
access, packing = self.base.type.axes[axis_idx]
axis_idx += 1
buffer_access = True
skip_child_analysis = True
for x in indices:
- x.analyse_types(env)
+ x = x.analyse_types(env)
if not x.type.is_int:
buffer_access = False
fused_index_operation = base_type.is_cfunction and base_type.is_fused
if not fused_index_operation:
if isinstance(self.index, TupleNode):
- self.index.analyse_types(env, skip_children=skip_child_analysis)
+ self.index = self.index.analyse_types(
+ env, skip_children=skip_child_analysis)
elif not skip_child_analysis:
- self.index.analyse_types(env)
+ self.index = self.index.analyse_types(env)
self.original_index_type = self.index.type
if base_type.is_unicode_char:
specific_types = [False]
if not Utils.all(specific_types):
- self.index.analyse_types(env)
+ self.index = self.index.analyse_types(env)
if not self.base.entry.as_variable:
error(self.pos, "Can only index fused functions with types")
pass
def analyse_target_types(self, env):
- self.analyse_types(env, getting=False)
+ node = self.analyse_types(env, getting=False)
# when assigning, we must accept any Python type
- if self.type.is_pyobject:
- self.type = py_object_type
+ if node.type.is_pyobject:
+ node.type = py_object_type
+ return node
def analyse_types(self, env, getting=True):
- self.base.analyse_types(env)
+ self.base = self.base.analyse_types(env)
if self.base.type.is_memoryviewslice:
# Gross hack here! But we do not know the type until this point,
getting=getting,
setting=not getting,
analyse_base=False)
- return
+ return self
if self.start:
- self.start.analyse_types(env)
+ self.start = self.start.analyse_types(env)
if self.stop:
- self.stop.analyse_types(env)
+ self.stop = self.stop.analyse_types(env)
base_type = self.base.type
if base_type.is_string or base_type.is_cpp_string:
self.type = bytes_type
if self.stop:
self.stop = self.stop.coerce_to(c_int, env)
self.is_temp = 1
+ return self
nogil_check = Node.gil_error
gil_message = "Slicing Python object"
self.compile_time_value_error(e)
def analyse_types(self, env):
- self.start.analyse_types(env)
- self.stop.analyse_types(env)
- self.step.analyse_types(env)
- self.start = self.start.coerce_to_pyobject(env)
- self.stop = self.stop.coerce_to_pyobject(env)
- self.step = self.step.coerce_to_pyobject(env)
+ start = self.start.analyse_types(env)
+ stop = self.stop.analyse_types(env)
+ step = self.step.analyse_types(env)
+ self.start = start.coerce_to_pyobject(env)
+ self.stop = stop.coerce_to_pyobject(env)
+ self.step = step.coerce_to_pyobject(env)
if self.start.is_literal and self.stop.is_literal and self.step.is_literal:
self.is_literal = True
self.is_temp = False
+ return self
gil_message = "Constructing Python slice object"
items += kwds.key_value_pairs
self.key_value_pairs = items
self.__class__ = DictNode
- self.analyse_types(env)
+ self.analyse_types(env) # FIXME
self.coerce_to(type, env)
return True
elif type and type.is_cpp_class:
- for arg in self.args:
- arg.analyse_types(env)
+ self.args = [ arg.analyse_types(env) for arg in self.args ]
constructor = type.scope.lookup("<init>")
self.function = RawCNameExprNode(self.function.pos, constructor.type)
self.function.entry = constructor
def analyse_types(self, env):
if self.analyse_as_type_constructor(env):
- return
+ return self
if self.analysed:
- return
+ return self
self.analysed = True
+ self.function.is_called = 1
+ self.function = self.function.analyse_types(env)
function = self.function
- function.is_called = 1
- self.function.analyse_types(env)
if function.is_attribute and function.entry and function.entry.is_cmethod:
# Take ownership of the object from which the attribute
func_type = self.function_type()
if func_type.is_pyobject:
self.arg_tuple = TupleNode(self.pos, args = self.args)
- self.arg_tuple.analyse_types(env)
+ self.arg_tuple = self.arg_tuple.analyse_types(env)
self.args = None
if func_type is Builtin.type_type and function.is_name and \
function.entry and \
self.type = py_object_type
self.is_temp = 1
else:
- for arg in self.args:
- arg.analyse_types(env)
+ self.args = [ arg.analyse_types(env) for arg in self.args ]
if self.self and func_type.args:
# Coerce 'self' to the type expected by the method.
# Insert coerced 'self' argument into argument list.
self.args.insert(0, self.coerced_self)
self.analyse_c_function_call(env)
+ return self
def function_type(self):
# Return the type of the function being called, coercing a function
return True
def analyse_types(self, env):
- self.function_name.analyse_types(env)
-
- for arg in self.args:
- arg.analyse_types(env)
+ self.function_name = self.function_name.analyse_types(env)
+ self.args = [ arg.analyse_types(env) for arg in self.args ]
func_type = self.function.def_node
actual_nargs = len(self.args)
if i > 0:
warning(arg.pos, "Argument evaluation order in C function call is undefined and may not be as expected", 0)
break
+ return self
def generate_result_code(self, code):
arg_code = [self.function_name.py_result()]
type=func_type, utility_code=utility_code)
def analyse_types(self, env):
- pass
+ return self
def generate_result_code(self, code):
if self.utility_code:
def analyse_types(self, env):
if self.analyse_as_type_constructor(env):
- return
- self.function.analyse_types(env)
+ return self
+ self.function = self.function.analyse_types(env)
if not self.function.type.is_pyobject:
if self.function.type.is_error:
self.type = error_type
- return
+ return self
if hasattr(self.function, 'entry'):
self.map_keywords_to_posargs()
if not self.is_simple_call:
else:
self.function = self.function.coerce_to_pyobject(env)
if self.keyword_args:
- self.keyword_args.analyse_types(env)
- self.positional_args.analyse_types(env)
+ self.keyword_args = self.keyword_args.analyse_types(env)
+ self.positional_args = self.positional_args.analyse_types(env)
self.positional_args = \
self.positional_args.coerce_to_pyobject(env)
function = self.function
else:
self.type = py_object_type
self.is_temp = 1
+ return self
def map_keywords_to_posargs(self):
if not isinstance(self.positional_args, TupleNode):
self.compile_time_value_error(e)
def analyse_types(self, env):
- self.arg.analyse_types(env)
+ self.arg = self.arg.analyse_types(env)
self.arg = self.arg.coerce_to_pyobject(env)
self.type = tuple_type
self.is_temp = 1
+ return self
def may_be_none(self):
return False
pass
def analyse_target_types(self, env):
- self.analyse_types(env, target = 1)
- if self.type.is_const:
+ node = self.analyse_types(env, target = 1)
+ if node.type.is_const:
error(self.pos, "Assignment to const attribute '%s'" % self.attribute)
- if not self.is_lvalue():
+ if not node.is_lvalue():
error(self.pos, "Assignment to non-lvalue of type '%s'" % self.type)
+ return node
def analyse_types(self, env, target = 0):
self.initialized_check = env.directives['initializedcheck']
# may be mutated in a namenode now :)
if self.is_attribute:
self.wrap_obj_in_nonecheck(env)
+ return self
def analyse_as_cimported_attribute(self, env, target):
# Try to interpret this as a reference to an imported
if entry and (
entry.is_cglobal or entry.is_cfunction
or entry.is_type or entry.is_const):
- self.mutate_into_name_node(env, entry, target)
+ self.mutate_into_name_node(env, entry, target) # FIXME
entry.used = 1
return 1
return 0
ubcm_entry.is_cfunction = 1
ubcm_entry.func_cname = entry.func_cname
ubcm_entry.is_unbound_cmethod = 1
- self.mutate_into_name_node(env, ubcm_entry, None)
+ self.mutate_into_name_node(env, ubcm_entry, None) # FIXME
return 1
return 0
del self.obj
del self.attribute
if target:
- NameNode.analyse_target_types(self, env)
+ NameNode.analyse_target_types(self, env) # FIXME
else:
NameNode.analyse_rvalue_entry(self, env)
def analyse_as_ordinary_attribute(self, env, target):
- self.obj.analyse_types(env)
+ self.obj = self.obj.analyse_types(env)
self.analyse_attribute(env)
if self.entry and self.entry.is_cmethod and not self.is_called:
# error(self.pos, "C method can only be called")
def analyse_types(self, env):
error(self.pos, "can use starred expression only as assignment target")
- self.target.analyse_types(env)
+ self.target = self.target.analyse_types(env)
self.type = self.target.type
+ return self
def analyse_target_declaration(self, env):
self.target.analyse_target_declaration(env)
def analyse_target_types(self, env):
- self.target.analyse_target_types(env)
+ self.target = self.target.analyse_target_types(env)
self.type = self.target.type
+ return self
def calculate_result_code(self):
return ""
def analyse_types(self, env, skip_children=False):
for i in range(len(self.args)):
arg = self.args[i]
- if not skip_children: arg.analyse_types(env)
+ if not skip_children: arg = arg.analyse_types(env)
self.args[i] = arg.coerce_to_pyobject(env)
if self.mult_factor:
- self.mult_factor.analyse_types(env)
+ self.mult_factor = self.mult_factor.analyse_types(env)
if not self.mult_factor.type.is_int:
self.mult_factor = self.mult_factor.coerce_to_pyobject(env)
self.is_temp = 1
# not setting self.type here, subtypes do this
+ return self
def may_be_none(self):
return False
self.unpacked_items = []
self.coerced_unpacked_items = []
self.any_coerced_items = False
- for arg in self.args:
- arg.analyse_target_types(env)
+ for i, arg in enumerate(self.args):
+ arg = self.args[i] = arg.analyse_target_types(env)
if arg.is_starred:
if not arg.type.assignable_from(Builtin.list_type):
error(arg.pos,
self.unpacked_items.append(unpacked_item)
self.coerced_unpacked_items.append(coerced_unpacked_item)
self.type = py_object_type
+ return self
def generate_result_code(self, code):
self.generate_operation_code(code)
def analyse_types(self, env, skip_children=False):
if len(self.args) == 0:
- self.is_temp = False
- self.is_literal = True
+ node = self
+ node.is_temp = False
+ node.is_literal = True
else:
- SequenceNode.analyse_types(self, env, skip_children)
- for child in self.args:
+ node = SequenceNode.analyse_types(self, env, skip_children)
+ for child in node.args:
if not child.is_literal:
break
else:
- if not self.mult_factor or self.mult_factor.is_literal and \
- isinstance(self.mult_factor.constant_result, (int, long)):
- self.is_temp = False
- self.is_literal = True
+ if not node.mult_factor or node.mult_factor.is_literal and \
+ isinstance(node.mult_factor.constant_result, (int, long)):
+ node.is_temp = False
+ node.is_literal = True
else:
- if not self.mult_factor.type.is_pyobject:
- self.mult_factor = self.mult_factor.coerce_to_pyobject(env)
- self.is_temp = True
- self.is_partly_literal = True
+ if not node.mult_factor.type.is_pyobject:
+ node.mult_factor = node.mult_factor.coerce_to_pyobject(env)
+ node.is_temp = True
+ node.is_partly_literal = True
+ return node
def is_simple(self):
# either temp or constant => always simple
return list_type
def analyse_expressions(self, env):
- SequenceNode.analyse_expressions(self, env)
- self.coerce_to_pyobject(env)
+ node = SequenceNode.analyse_expressions(self, env)
+ return node.coerce_to_pyobject(env)
def analyse_types(self, env):
hold_errors()
self.original_args = list(self.args)
- SequenceNode.analyse_types(self, env)
- self.obj_conversion_errors = held_errors()
+ node = SequenceNode.analyse_types(self, env)
+ node.obj_conversion_errors = held_errors()
release_errors(ignore=True)
+ return node
def coerce_to(self, dst_type, env):
if dst_type.is_pyobject:
def analyse_types(self, env):
# no recursion here, the children will be analysed separately below
- pass
+ return self
def analyse_scoped_expressions(self, env):
# this is called with the expr_scope as env
- pass
+ return self
def generate_evaluation_code(self, code):
# set up local variables and free their references on exit
self.loop.analyse_declarations(env)
def analyse_types(self, env):
- self.target.analyse_expressions(env)
+ self.target = self.target.analyse_expressions(env)
self.type = self.target.type
if not self.has_local_scope:
- self.loop.analyse_expressions(env)
+ self.loop = self.loop.analyse_expressions(env)
+ return self
def analyse_scoped_expressions(self, env):
if self.has_local_scope:
- self.loop.analyse_expressions(env)
+ self.loop = self.loop.analyse_expressions(env)
+ return self
def may_be_none(self):
return False
type = PyrexTypes.c_int_type
def analyse_expressions(self, env):
- self.expr.analyse_expressions(env)
+ self.expr = self.expr.analyse_expressions(env)
if not self.expr.type.is_pyobject:
self.expr = self.expr.coerce_to_pyobject(env)
+ return self
def generate_execution_code(self, code):
if self.target.type is list_type:
child_attrs = ['key_expr', 'value_expr']
def analyse_expressions(self, env):
- self.key_expr.analyse_expressions(env)
+ self.key_expr = self.key_expr.analyse_expressions(env)
if not self.key_expr.type.is_pyobject:
self.key_expr = self.key_expr.coerce_to_pyobject(env)
- self.value_expr.analyse_expressions(env)
+ self.value_expr = self.value_expr.analyse_expressions(env)
if not self.value_expr.type.is_pyobject:
self.value_expr = self.value_expr.coerce_to_pyobject(env)
+ return self
def generate_execution_code(self, code):
self.key_expr.generate_evaluation_code(code)
def analyse_types(self, env):
if not self.has_local_scope:
self.loop_analysed = True
- self.loop.analyse_expressions(env)
+ self.loop = self.loop.analyse_expressions(env)
self.type = self.result_node.type
self.is_temp = True
+ return self
def analyse_scoped_expressions(self, env):
self.loop_analysed = True
if self.has_local_scope:
- self.loop.analyse_expressions(env)
+ self.loop = self.loop.analyse_expressions(env)
+ return self
def coerce_to(self, dst_type, env):
if self.orig_func == 'sum' and dst_type.is_numeric and not self.loop_analysed:
def analyse_types(self, env):
for i in range(len(self.args)):
arg = self.args[i]
- arg.analyse_types(env)
+ arg = arg.analyse_types(env)
self.args[i] = arg.coerce_to_pyobject(env)
self.type = set_type
self.is_temp = 1
+ return self
def may_be_none(self):
return False
def analyse_types(self, env):
hold_errors()
- for item in self.key_value_pairs:
- item.analyse_types(env)
+ self.key_value_pairs = [ item.analyse_types(env)
+ for item in self.key_value_pairs ]
self.obj_conversion_errors = held_errors()
release_errors(ignore=True)
+ return self
def may_be_none(self):
return False
self.key.constant_result, self.value.constant_result)
def analyse_types(self, env):
- self.key.analyse_types(env)
- self.value.analyse_types(env)
+ self.key = self.key.analyse_types(env)
+ self.value = self.value.analyse_types(env)
self.key = self.key.coerce_to_pyobject(env)
self.value = self.value.coerce_to_pyobject(env)
+ return self
def generate_evaluation_code(self, code):
self.key.generate_evaluation_code(code)
subexprs = ['bases', 'doc']
def analyse_types(self, env):
- self.bases.analyse_types(env)
+ self.bases = self.bases.analyse_types(env)
if self.doc:
- self.doc.analyse_types(env)
+ self.doc = self.doc.analyse_types(env)
self.doc = self.doc.coerce_to_pyobject(env)
self.type = py_object_type
self.is_temp = 1
env.use_utility_code(UtilityCode.load_cached("CreateClass", "ObjectHandling.c"))
#TODO(craig,haoyu) This should be moved to a better place
self.set_qualified_name(env, self.name)
+ return self
def may_be_none(self):
return True
def analyse_types(self, env):
self.type = py_object_type
self.is_temp = 1
+ return self
def may_be_none(self):
return True
return dict_type
def analyse_types(self, env):
- self.starstar_arg.analyse_types(env)
- self.starstar_arg = self.starstar_arg.coerce_to_pyobject(env).as_none_safe_node(
+ arg = self.starstar_arg.analyse_types(env)
+ arg = arg.coerce_to_pyobject(env)
+ self.starstar_arg = arg.as_none_safe_node(
# FIXME: CPython's error message starts with the runtime function name
'argument after ** must be a mapping, not NoneType')
- for item in self.keyword_args:
- item.analyse_types(env)
+ self.keyword_args = [ item.analyse_types(env)
+ for item in self.keyword_args ]
+ return self
def may_be_none(self):
return False
def analyse_types(self, env):
self.type = py_object_type
self.is_temp = True
+ return self
def may_be_none(self):
return True
subexprs = ['doc']
def analyse_types(self, env):
- self.bases.analyse_types(env)
+ self.bases = self.bases.analyse_types(env)
if self.doc:
- self.doc.analyse_types(env)
+ self.doc = self.doc.analyse_types(env)
self.doc = self.doc.coerce_to_pyobject(env)
self.type = py_object_type
self.is_temp = 1
#TODO(craig,haoyu) This should be moved to a better place
self.set_qualified_name(env, self.name)
+ return self
def may_be_none(self):
return True
if self.is_active:
env.use_utility_code(
UtilityCode.load_cached("CyFunctionClassCell", "CythonFunction.c"))
+ return self
def generate_evaluation_code(self, code):
if self.is_active:
type = py_object_type
def analyse_types(self, env):
- pass
+ return self
def generate_result_code(self, code):
if not self.is_generator:
subexprs = ['function']
def analyse_types(self, env):
- self.function.analyse_types(env)
+ self.function = self.function.analyse_types(env)
self.type = py_object_type
self.is_temp = 1
+ return self
gil_message = "Constructing an bound method"
subexprs = ['function']
def analyse_types(self, env):
- self.function.analyse_types(env)
+ self.function = self.function.analyse_types(env)
+ return self
def may_be_none(self):
return False
#TODO(craig,haoyu) This should be moved to a better place
self.set_qualified_name(env, self.def_node.name)
+ return self
def analyse_default_args(self, env):
"""
if default_args:
if self.defaults_struct is None:
- self.defaults_tuple = TupleNode(self.pos, args=[
+ defaults_tuple = TupleNode(self.pos, args=[
arg.default for arg in default_args])
- self.defaults_tuple.analyse_types(env)
+ self.defaults_tuple = defaults_tuple.analyse_types(env)
else:
defaults_getter = Nodes.DefNode(
self.pos, args=[], star_arg=None, starstar_arg=None,
self.defaults_struct)),
decorators=None, name=StringEncoding.EncodedString("__defaults__"))
defaults_getter.analyse_declarations(env)
- defaults_getter.analyse_expressions(env)
- defaults_getter.body.analyse_expressions(
+ defaults_getter = defaults_getter.analyse_expressions(env)
+ defaults_getter.body = defaults_getter.body.analyse_expressions(
defaults_getter.local_scope)
defaults_getter.py_wrapper_required = False
defaults_getter.pymethdef_required = False
self.evaluated = False
def analyse_types(self, env):
- pass
+ return self
def generate_result_code(self, code):
pass
def analyse_types(self, env):
self.type = self.arg.type
self.is_temp = False
+ return self
def generate_result_code(self, code):
pass
env.add_lambda_def(self.def_node)
def analyse_types(self, env):
- self.def_node.analyse_expressions(env)
- super(LambdaNode, self).analyse_types(env)
+ self.def_node = self.def_node.analyse_expressions(env)
+ return super(LambdaNode, self).analyse_types(env)
def generate_result_code(self, code):
self.def_node.generate_execution_code(code)
error(self.pos, "'yield' not supported here")
self.is_temp = 1
if self.arg is not None:
- self.arg.analyse_types(env)
+ self.arg = self.arg.analyse_types(env)
if not self.arg.type.is_pyobject:
self.coerce_yield_argument(env)
+ return self
def coerce_yield_argument(self, env):
self.arg = self.arg.coerce_to_pyobject(env)
def analyse_types(self, env):
env.use_utility_code(Builtin.globals_utility_code)
+ return self
gil_message = "Constructing globals dict"
class LocalsDictItemNode(DictItemNode):
def analyse_types(self, env):
- self.key.analyse_types(env)
- self.value.analyse_types(env)
+ self.key = self.key.analyse_types(env)
+ self.value = self.value.analyse_types(env)
self.key = self.key.coerce_to_pyobject(env)
if self.value.type.can_coerce_to_pyobject(env):
self.value = self.value.coerce_to_pyobject(env)
else:
self.value = None
+ return self
class FuncLocalsExprNode(DictNode):
exclude_null_values=True)
def analyse_types(self, env):
- super(FuncLocalsExprNode, self).analyse_types(env)
- self.key_value_pairs = [i for i in self.key_value_pairs
- if i.value is not None]
+ node = super(FuncLocalsExprNode, self).analyse_types(env)
+ node.key_value_pairs = [ i for i in node.key_value_pairs
+ if i.value is not None ]
+ return node
class PyClassLocalsExprNode(AtomicExprNode):
def analyse_types(self, env):
self.type = self.pyclass_dict.type
self.is_temp = False
+ return self
def result(self):
return self.pyclass_dict.result()
return operand_type
def analyse_types(self, env):
- self.operand.analyse_types(env)
+ self.operand = self.operand.analyse_types(env)
if self.is_py_operation():
self.coerce_operand_to_pyobject(env)
self.type = py_object_type
self.analyse_cpp_operation(env)
else:
self.analyse_c_operation(env)
+ return self
def check_const(self):
return self.operand.check_const()
return PyrexTypes.c_bint_type
def analyse_types(self, env):
- self.operand.analyse_types(env)
+ self.operand = self.operand.analyse_types(env)
operand_type = self.operand.type
if operand_type.is_cpp_class:
cpp_type = operand_type.find_cpp_operation_type(self.operator)
self.type = cpp_type
else:
self.operand = self.operand.coerce_to_boolean(env)
+ return self
def calculate_result_code(self):
return "(!%s)" % self.operand.result()
return PyrexTypes.c_ptr_type(operand_type)
def analyse_types(self, env):
- self.operand.analyse_types(env)
+ self.operand = self.operand.analyse_types(env)
argtype = self.operand.type
if argtype.is_cpp_class:
cpp_type = argtype.find_cpp_operation_type(self.operator)
if cpp_type is not None:
self.type = cpp_type
- return
+ return self
if not (argtype.is_cfunction or argtype.is_reference or self.operand.is_addressable()):
if argtype.is_memoryviewslice:
self.error("Cannot take address of memoryview slice")
else:
self.error("Taking address of non-lvalue")
- return
+ return self
if argtype.is_pyobject:
self.error("Cannot take address of Python variable")
- return
+ return self
self.type = PyrexTypes.c_ptr_type(argtype)
+ return self
def check_const(self):
return self.operand.check_const_addr()
error(self.pos,
"Cannot cast to a function type")
self.type = PyrexTypes.error_type
- self.operand.analyse_types(env)
+ self.operand = self.operand.analyse_types(env)
to_py = self.type.is_pyobject
from_py = self.operand.type.is_pyobject
if from_py and not to_py and self.operand.is_ephemeral():
elif self.operand.type.is_fused:
self.operand = self.operand.coerce_to(self.type, env)
#self.type = self.operand.type
+ return self
def is_simple(self):
# either temp or a C cast => no side effects other than the operand's
def analyse_types(self, env):
import MemoryView
- self.operand.analyse_types(env)
+ self.operand = self.operand.analyse_types(env)
if self.array_dtype:
array_dtype = self.array_dtype
else:
if not self.operand.type.is_ptr and not self.operand.type.is_array:
error(self.operand.pos, ERR_NOT_POINTER)
- return
+ return self
# Dimension sizes of C array
array_dimension_sizes = []
base_type = base_type.base_type
else:
error(self.pos, "unexpected base type %s found" % base_type)
- return
+ return self
if not (base_type.same_as(array_dtype) or base_type.is_void):
error(self.operand.pos, ERR_BASE_TYPE)
- return
+ return self
elif self.operand.type.is_array and len(array_dimension_sizes) != ndim:
error(self.operand.pos,
"Expected %d dimensions, array has %d dimensions" %
(ndim, len(array_dimension_sizes)))
- return
+ return self
# Verify the start, stop and step values
# In case of a C array, use the size of C array in each dimension to
for axis_no, axis in enumerate(axes):
if not axis.start.is_none:
error(axis.start.pos, ERR_START)
- return
+ return self
if axis.stop.is_none:
if array_dimension_sizes:
type=PyrexTypes.c_int_type)
else:
error(axis.pos, ERR_NOT_STOP)
- return
+ return self
- axis.stop.analyse_types(env)
+ axis.stop = axis.stop.analyse_types(env)
shape = axis.stop.coerce_to(self.shape_type, env)
if not shape.is_literal:
shape.coerce_to_temp(env)
first_or_last = axis_no in (0, ndim - 1)
if not axis.step.is_none and first_or_last:
# '1' in the first or last dimension denotes F or C contiguity
- axis.step.analyse_types(env)
+ axis.step = axis.step.analyse_types(env)
if (not axis.step.type.is_int and axis.step.is_literal and not
axis.step.type.is_error):
error(axis.step.pos, "Expected an integer literal")
- return
+ return self
if axis.step.compile_time_value(env) != 1:
error(axis.step.pos, ERR_STEPS)
- return
+ return self
if axis_no == 0:
self.mode = "fortran"
elif not axis.step.is_none and not first_or_last:
# step provided in some other dimension
error(axis.step.pos, ERR_STEPS)
- return
+ return self
if not self.operand.is_name:
self.operand = self.operand.coerce_to_temp(env)
self.type = self.get_cython_array_type(env)
MemoryView.use_cython_array_utility_code(env)
env.use_utility_code(MemoryView.typeinfo_to_format_code)
+ return self
def allocate_temp_result(self, code):
if self.temp_code:
base_type_node=base_type)
result = CythonArrayNode(pos, base_type_node=memslicenode,
operand=src_node, array_dtype=base_type)
- result.analyse_types(env)
+ result = result.analyse_types(env)
return result
class SizeofNode(ExprNode):
operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
self.operand = operand
self.__class__ = SizeofVarNode
- self.analyse_types(env)
- return
+ node = self.analyse_types(env)
+ return node
if self.arg_type is None:
base_type = self.base_type.analyse(env)
_, arg_type = self.declarator.analyse(base_type, env)
self.arg_type = arg_type
self.check_type()
+ return self
def check_type(self):
arg_type = self.arg_type
self.__class__ = SizeofTypeNode
self.check_type()
else:
- self.operand.analyse_types(env)
+ self.operand = self.operand.analyse_types(env)
+ return self
def calculate_result_code(self):
return "(sizeof(%s))" % self.operand.result()
subexprs = ['literal'] # 'operand' will be ignored after type analysis!
def analyse_types(self, env):
- self.operand.analyse_types(env)
+ self.operand = self.operand.analyse_types(env)
value = StringEncoding.EncodedString(str(self.operand.type)) #self.operand.type.typeof_name())
- self.literal = StringNode(self.pos, value=value)
- self.literal.analyse_types(env)
- self.literal = self.literal.coerce_to_pyobject(env)
+ literal = StringNode(self.pos, value=value)
+ literal = literal.analyse_types(env)
+ self.literal = literal.coerce_to_pyobject(env)
+ return self
def may_be_none(self):
return False
self.operand2.infer_type(env))
def analyse_types(self, env):
- self.operand1.analyse_types(env)
- self.operand2.analyse_types(env)
+ self.operand1 = self.operand1.analyse_types(env)
+ self.operand2 = self.operand2.analyse_types(env)
self.analyse_operation(env)
+ return self
def analyse_operation(self, env):
if self.is_py_operation():
class CBinopNode(BinopNode):
def analyse_types(self, env):
- BinopNode.analyse_types(self, env)
- if self.is_py_operation():
- self.type = PyrexTypes.error_type
+ node = BinopNode.analyse_types(self, env)
+ if node.is_py_operation():
+ node.type = PyrexTypes.error_type
+ return node
def py_operation_function(self):
return ""
is_temp = self.is_temp)
def analyse_types(self, env):
- self.operand1.analyse_types(env)
- self.operand2.analyse_types(env)
+ self.operand1 = self.operand1.analyse_types(env)
+ self.operand2 = self.operand2.analyse_types(env)
self.type = PyrexTypes.independent_spanning_type(self.operand1.type, self.operand2.type)
self.operand1 = self.operand1.coerce_to(self.type, env)
self.operand2 = self.operand2.coerce_to(self.type, env)
self.operand1 = self.operand1.coerce_to_simple(env)
self.operand2 = self.operand2.coerce_to_simple(env)
self.is_temp = 1
+ return self
gil_message = "Truth-testing Python object"
self.constant_result = self.false_val.constant_result
def analyse_types(self, env):
- self.test.analyse_types(env)
- self.test = self.test.coerce_to_boolean(env)
- self.true_val.analyse_types(env)
- self.false_val.analyse_types(env)
+ self.test = self.test.analyse_types(env).coerce_to_boolean(env)
+ self.true_val = self.true_val.analyse_types(env)
+ self.false_val = self.false_val.analyse_types(env)
self.type = PyrexTypes.independent_spanning_type(self.true_val.type, self.false_val.type)
if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
self.true_val = self.true_val.coerce_to(self.type, env)
self.is_temp = 1
if self.type == PyrexTypes.error_type:
self.type_error()
+ return self
def type_error(self):
if not (self.true_val.type.is_error or self.false_val.type.is_error):
return self.cascaded_compile_time_value(operand1, denv)
def analyse_types(self, env):
- self.operand1.analyse_types(env)
- self.operand2.analyse_types(env)
+ self.operand1 = self.operand1.analyse_types(env)
+ self.operand2 = self.operand2.analyse_types(env)
if self.is_cpp_comparison():
self.analyse_cpp_comparison(env)
if self.cascade:
error(self.pos, "Cascading comparison not yet supported for cpp types.")
- return
+ return self
if self.analyse_memoryviewslice_comparison(env):
- return
+ return self
if self.cascade:
- self.cascade.analyse_types(env)
+ self.cascade = self.cascade.analyse_types(env)
if self.operator in ('in', 'not_in'):
if self.is_c_string_contains():
common_type = None
if self.cascade:
error(self.pos, "Cascading comparison not yet supported for 'int_val in string'.")
- return
+ return self
if self.operand2.type is unicode_type:
env.use_utility_code(UtilityCode.load_cached("PyUCS4InUnicode", "StringTools.c"))
else:
error(self.pos, "Cascading comparison not supported for 'val in sliced pointer'.")
self.type = PyrexTypes.c_bint_type
# Will be transformed by IterationTransform
- return
+ return self
elif self.find_special_bool_compare_function(env, self.operand1):
if not self.operand1.type.is_pyobject:
self.operand1 = self.operand1.coerce_to_pyobject(env)
if self.is_pycmp or self.cascade or self.special_bool_cmp_function:
# 1) owned reference, 2) reused value, 3) potential function error return value
self.is_temp = 1
+ return self
def analyse_cpp_comparison(self, env):
type1 = self.operand1.type
self.constant_result is not not_a_constant
def analyse_types(self, env):
- self.operand2.analyse_types(env)
+ self.operand2 = self.operand2.analyse_types(env)
if self.cascade:
- self.cascade.analyse_types(env)
+ self.cascade = self.cascade.analyse_types(env)
+ return self
def has_python_operands(self):
return self.operand2.type.is_pyobject
gil_message = "Python type test"
def analyse_types(self, env):
- pass
+ return self
def may_be_none(self):
if self.notnone:
nogil_check = None # this node only guards an operation that would fail already
def analyse_types(self, env):
- pass
+ return self
def may_be_none(self):
return False
def analyse_types(self, env):
# The arg is always already analysed
- pass
+ return self
def generate_result_code(self, code):
if self.arg.type.is_memoryviewslice:
def analyse_types(self, env):
# The arg is always already analysed
- pass
+ return self
def generate_result_code(self, code):
function = self.type.from_py_function
def analyse_types(self, env):
# The arg is always already analysed
- pass
+ return self
def coerce_to_boolean(self, env):
self.arg = self.arg.coerce_to_boolean(env)
self._proxy_type()
def analyse_expressions(self, env):
- self.arg.analyse_expressions(env)
+ self.arg = self.arg.analyse_expressions(env)
self._proxy_type()
+ return self
def _proxy_type(self):
if hasattr(self.arg, 'type'):
self.is_temp = 1
if hasattr(self.arg, 'entry'):
self.entry = self.arg.entry
+ return self
def is_simple(self):
return True # result is always in a temp (or a name)
subexprs = []
def analyse_types(self, env):
- pass
+ return self
def may_be_none(self):
return False
self.body = body
def analyse_types(self, env):
- pass
+ return self
def generate_result_code(self, code):
code.putln('%s = __Pyx_GetAttr(%s, %s); %s' % (
return doc
-from Code import CCodeWriter
-from types import FunctionType
-
-def write_func_call(func):
+def write_func_call(func, codewriter_class):
def f(*args, **kwds):
- if len(args) > 1 and isinstance(args[1], CCodeWriter):
+ if len(args) > 1 and isinstance(args[1], codewriter_class):
# here we annotate the code with this function call
# but only if new code is generated
node, code = args[:2]
# Set this as a metaclass to trace function calls in code.
# This slows down code generation and makes much larger files.
def __new__(cls, name, bases, attrs):
+ from types import FunctionType
+ from Code import CCodeWriter
attrs = dict(attrs)
for mname, m in attrs.items():
if isinstance(m, FunctionType):
- attrs[mname] = write_func_call(m)
+ attrs[mname] = write_func_call(m, CCodeWriter)
return super(VerboseCodeWriter, cls).__new__(cls, name, bases, attrs)
+class CheckAnalysers(type):
+ """Metaclass to check that type analysis functions return a node.
+ """
+ methods = set(['analyse_types',
+ 'analyse_expressions',
+ 'analyse_target_types'])
+
+ def __new__(cls, name, bases, attrs):
+ from types import FunctionType
+ def check(name, func):
+ def call(*args, **kwargs):
+ retval = func(*args, **kwargs)
+ if retval is None:
+ print name, args, kwargs
+ return retval
+ return call
+
+ attrs = dict(attrs)
+ for mname, m in attrs.items():
+ if isinstance(m, FunctionType) and mname in cls.methods:
+ attrs[mname] = check(mname, m)
+ return super(CheckAnalysers, cls).__new__(cls, name, bases, attrs)
+
+
class Node(object):
# pos (string, int, int) Source file position
# is_name boolean Is a NameNode
# is_literal boolean Is a ConstNode
+ #__metaclass__ = CheckAnalysers
if DebugFlags.debug_trace_code_generation:
__metaclass__ = VerboseCodeWriter
def analyse_expressions(self, env):
old = env.directives
env.directives = self.directives
- self.body.analyse_expressions(env)
+ self.body = self.body.analyse_expressions(env)
env.directives = old
+ return self
def generate_function_definitions(self, env, code):
env_old = env.directives
def analyse_expressions(self, env):
#print "StatListNode.analyse_expressions" ###
- for stat in self.stats:
- stat.analyse_expressions(env)
+ self.stats = [ stat.analyse_expressions(env)
+ for stat in self.stats ]
+ return self
def generate_function_definitions(self, env, code):
#print "StatListNode.generate_function_definitions" ###
env.in_cinclude = old_cinclude_flag
def analyse_expressions(self, env):
- pass
+ return self
def generate_execution_code(self, code):
pass
if self.exception_value:
self.exception_value.analyse_const_expression(env)
if self.exception_check == '+':
- self.exception_value.analyse_types(env)
+ self.exception_value = self.exception_value.analyse_types(env)
exc_val_type = self.exception_value.type
if not exc_val_type.is_error and \
not exc_val_type.is_pyobject and \
error(attr.pos, "Struct cannot contain itself as a member.")
def analyse_expressions(self, env):
- pass
+ return self
def generate_execution_code(self, code):
pass
self.scope = scope
def analyse_expressions(self, env):
- self.body.analyse_expressions(self.entry.type.scope)
+ self.body = self.body.analyse_expressions(self.entry.type.scope)
+ return self
def generate_function_definitions(self, env, code):
self.body.generate_function_definitions(self.entry.type.scope, code)
item.analyse_declarations(env, self.entry)
def analyse_expressions(self, env):
- pass
+ return self
def generate_execution_code(self, code):
if self.visibility == 'public' or self.api:
entry.defined_in_pxd = 1
def analyse_expressions(self, env):
- pass
+ return self
+
def generate_execution_code(self, code):
pass
if arg.default:
default_seen = 1
if arg.is_generic:
- arg.default.analyse_types(env)
+ arg.default = arg.default.analyse_types(env)
arg.default = arg.default.coerce_to(arg.type, env)
else:
error(arg.pos,
self.local_scope.directives = env.directives
if self.py_func is not None:
# this will also analyse the default values
- self.py_func.analyse_expressions(env)
+ self.py_func = self.py_func.analyse_expressions(env)
else:
self.analyse_default_values(env)
self.acquire_gil = self.need_gil_acquisition(self.local_scope)
+ return self
def needs_assignment_synthesis(self, env, code=None):
return False
if not self.needs_assignment_synthesis(env) and self.decorators:
for decorator in self.decorators[::-1]:
- decorator.decorator.analyse_expressions(env)
+ decorator.decorator = decorator.decorator.analyse_expressions(env)
self.py_wrapper.prepare_argument_coercion(env)
+ return self
def needs_assignment_synthesis(self, env, code=None):
if self.is_wrapper or self.specialized_cpdefs or self.entry.is_fused_specialized:
self.func_node = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
call_node = ExprNodes.SimpleCallNode(
self.pos, function=self.func_node,
- args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
+ args=[ ExprNodes.NameNode(self.pos, name=arg.name)
+ for arg in self.args[first_arg:] ])
self.body = ReturnStatNode(self.pos, value=call_node)
- self.body.analyse_expressions(env)
+ self.body = self.body.analyse_expressions(env)
+ return self
def generate_execution_code(self, code):
interned_attr_cname = code.intern_identifier(self.py_func.entry.name)
def analyse_expressions(self, env):
if self.py3_style_class:
- self.bases.analyse_expressions(env)
- self.metaclass.analyse_expressions(env)
- self.mkw.analyse_expressions(env)
- self.dict.analyse_expressions(env)
- self.class_result.analyse_expressions(env)
+ self.bases = self.bases.analyse_expressions(env)
+ self.metaclass = self.metaclass.analyse_expressions(env)
+ self.mkw = self.mkw.analyse_expressions(env)
+ self.dict = self.dict.analyse_expressions(env)
+ self.class_result = self.class_result.analyse_expressions(env)
genv = env.global_scope()
cenv = self.scope
- self.body.analyse_expressions(cenv)
+ self.body = self.body.analyse_expressions(cenv)
self.target.analyse_target_expression(env, self.classobj)
- self.class_cell.analyse_expressions(cenv)
+ self.class_cell = self.class_cell.analyse_expressions(cenv)
+ return self
def generate_function_definitions(self, env, code):
self.generate_lambda_definitions(self.scope, code)
def analyse_expressions(self, env):
if self.body:
scope = self.entry.type.scope
- self.body.analyse_expressions(scope)
+ self.body = self.body.analyse_expressions(scope)
+ return self
def generate_function_definitions(self, env, code):
if self.body:
self.body.analyse_declarations(entry.scope)
def analyse_expressions(self, env):
- self.body.analyse_expressions(env)
+ self.body = self.body.analyse_expressions(env)
+ return self
def generate_function_definitions(self, env, code):
self.body.generate_function_definitions(env, code)
env.declare_global(name, self.pos)
def analyse_expressions(self, env):
- pass
+ return self
def generate_execution_code(self, code):
pass
env.declare_nonlocal(name, self.pos)
def analyse_expressions(self, env):
- pass
+ return self
def generate_execution_code(self, code):
pass
def analyse_expressions(self, env):
self.expr.result_is_used = False # hint that .result() may safely be left empty
- self.expr.analyse_expressions(env)
+ self.expr = self.expr.analyse_expressions(env)
+ return self
def nogil_check(self, env):
if self.expr.type.is_pyobject and self.expr.is_temp:
# to any of the left hand sides.
def analyse_expressions(self, env):
- self.analyse_types(env)
+ return self.analyse_types(env)
# def analyse_expressions(self, env):
# self.analyse_expressions_1(env)
def analyse_types(self, env, use_temp = 0):
import ExprNodes
- self.rhs.analyse_types(env)
- self.lhs.analyse_target_types(env)
+ self.rhs = self.rhs.analyse_types(env)
+ self.lhs = self.lhs.analyse_target_types(env)
self.lhs.gil_assignment_check(env)
if self.lhs.memslice_broadcast or self.rhs.memslice_broadcast:
self.rhs = self.rhs.coerce_to_temp(env)
elif self.rhs.type.is_pyobject:
self.rhs = self.rhs.coerce_to_simple(env)
+ return self
def generate_rhs_evaluation_code(self, code):
self.rhs.generate_evaluation_code(code)
def analyse_types(self, env, use_temp = 0):
from ExprNodes import CloneNode, ProxyNode
- self.rhs.analyse_types(env)
+ self.rhs = self.rhs.analyse_types(env)
if use_temp or self.rhs.is_attribute:
# (cdef) attribute access is not safe as it traverses pointers
self.rhs = self.rhs.coerce_to_temp(env)
rhs = CloneNode(self.rhs)
rhs = rhs.coerce_to(lhs.type, env)
self.coerced_rhs_list.append(rhs)
+ return self
def generate_rhs_evaluation_code(self, code):
self.rhs.generate_evaluation_code(code)
stat.analyse_declarations(env)
def analyse_expressions(self, env):
- for stat in self.stats:
- stat.analyse_types(env, use_temp = 1)
+ self.stats = [ stat.analyse_types(env, use_temp = 1)
+ for stat in self.stats ]
+ return self
# def analyse_expressions(self, env):
# for stat in self.stats:
def analyse_types(self, env):
import ExprNodes
- self.rhs.analyse_types(env)
- self.lhs.analyse_target_types(env)
+ self.rhs = self.rhs.analyse_types(env)
+ self.lhs = self.lhs.analyse_target_types(env)
# When assigning to a fully indexed buffer or memoryview, coerce the rhs
if (isinstance(self.lhs, ExprNodes.IndexNode) and
(self.lhs.memslice_index or self.lhs.is_buffer_access)):
self.rhs = self.rhs.coerce_to(self.lhs.type, env)
+ return self
def generate_execution_code(self, code):
import ExprNodes
def analyse_expressions(self, env):
if self.stream:
- self.stream.analyse_expressions(env)
- self.stream = self.stream.coerce_to_pyobject(env)
- self.arg_tuple.analyse_expressions(env)
- self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
+ stream = self.stream.analyse_expressions(env)
+ self.stream = stream.coerce_to_pyobject(env)
+ arg_tuple = self.arg_tuple.analyse_expressions(env)
+ self.arg_tuple = arg_tuple.coerce_to_pyobject(env)
env.use_utility_code(printing_utility_code)
if len(self.arg_tuple.args) == 1 and self.append_newline:
env.use_utility_code(printing_one_utility_code)
+ return self
nogil_check = Node.gil_error
gil_message = "Python print statement"
def analyse_expressions(self, env):
for i, arg in enumerate(self.args):
- arg.analyse_expressions(env)
+ arg = arg.analyse_expressions(env)
arg = arg.coerce_to_pyobject(env)
self.args[i] = arg
env.use_utility_code(Builtin.pyexec_utility_code)
+ return self
nogil_check = Node.gil_error
gil_message = "Python exec statement"
arg.analyse_target_declaration(env)
def analyse_expressions(self, env):
- for arg in self.args:
- arg.analyse_target_expression(env, None)
+ for i, arg in enumerate(self.args):
+ arg = self.args[i] = arg.analyse_target_expression(env, None)
if arg.type.is_pyobject or (arg.is_name and
arg.type.is_memoryviewslice):
pass
else:
error(arg.pos, "Deletion of non-Python, non-C++ object")
#arg.release_target_temp(env)
+ return self
def nogil_check(self, env):
for arg in self.args:
child_attrs = []
def analyse_expressions(self, env):
- pass
+ return self
def generate_execution_code(self, code):
pass
is_terminator = True
def analyse_expressions(self, env):
- pass
+ return self
def generate_execution_code(self, code):
if not code.break_label:
is_terminator = True
def analyse_expressions(self, env):
- pass
+ return self
def generate_execution_code(self, code):
if code.funcstate.in_try_finally:
self.return_type = return_type
if not return_type:
error(self.pos, "Return not inside a function body")
- return
+ return self
if self.value:
- self.value.analyse_types(env)
+ self.value = self.value.analyse_types(env)
if return_type.is_void or return_type.is_returncode:
error(self.value.pos,
"Return with value in void function")
and not return_type.is_pyobject
and not return_type.is_returncode):
error(self.pos, "Return value required")
+ return self
def nogil_check(self, env):
if self.return_type.is_pyobject:
def analyse_expressions(self, env):
if self.exc_type:
- self.exc_type.analyse_types(env)
- self.exc_type = self.exc_type.coerce_to_pyobject(env)
+ exc_type = self.exc_type.analyse_types(env)
+ self.exc_type = exc_type.coerce_to_pyobject(env)
if self.exc_value:
- self.exc_value.analyse_types(env)
- self.exc_value = self.exc_value.coerce_to_pyobject(env)
+ exc_value = self.exc_value.analyse_types(env)
+ self.exc_value = exc_value.coerce_to_pyobject(env)
if self.exc_tb:
- self.exc_tb.analyse_types(env)
- self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
+ exc_tb = self.exc_tb.analyse_types(env)
+ self.exc_tb = exc_tb.coerce_to_pyobject(env)
if self.cause:
- self.cause.analyse_types(env)
- self.cause = self.cause.coerce_to_pyobject(env)
+ cause = self.cause.analyse_types(env)
+ self.cause = cause.coerce_to_pyobject(env)
# special cases for builtin exceptions
self.builtin_exc_name = None
if self.exc_type and not self.exc_value and not self.exc_tb:
self.builtin_exc_name = exc.name
if self.builtin_exc_name == 'MemoryError':
self.exc_type = None # has a separate implementation
+ return self
nogil_check = Node.gil_error
gil_message = "Raising exception"
is_terminator = True
def analyse_expressions(self, env):
- pass
+ return self
nogil_check = Node.gil_error
gil_message = "Raising exception"
def analyse_expressions(self, env):
self.cond = self.cond.analyse_boolean_expression(env)
if self.value:
- self.value.analyse_types(env)
- self.value = self.value.coerce_to_pyobject(env)
+ value = self.value.analyse_types(env)
+ self.value = value.coerce_to_pyobject(env)
+ return self
nogil_check = Node.gil_error
gil_message = "Raising exception"
self.else_clause.analyse_declarations(env)
def analyse_expressions(self, env):
- for if_clause in self.if_clauses:
- if_clause.analyse_expressions(env)
+ self.if_clauses = [ if_clause.analyse_expressions(env)
+ for if_clause in self.if_clauses ]
if self.else_clause:
- self.else_clause.analyse_expressions(env)
+ self.else_clause = self.else_clause.analyse_expressions(env)
+ return self
def generate_execution_code(self, code):
code.mark_pos(self.pos)
def analyse_expressions(self, env):
self.condition = \
self.condition.analyse_temp_boolean_expression(env)
- self.body.analyse_expressions(env)
+ self.body = self.body.analyse_expressions(env)
+ return self
def get_constant_condition_result(self):
if self.condition.has_constant_result():
def analyse_expressions(self, env):
if self.condition:
self.condition = self.condition.analyse_temp_boolean_expression(env)
- self.body.analyse_expressions(env)
+ self.body = self.body.analyse_expressions(env)
if self.else_clause:
- self.else_clause.analyse_expressions(env)
+ self.else_clause = self.else_clause.analyse_expressions(env)
+ return self
def generate_execution_code(self, code):
old_loop_labels = code.new_loop_labels()
def analyse_expressions(self, env):
import ExprNodes
- self.dict_obj.analyse_types(env)
- self.expected_size.analyse_types(env)
- if self.pos_index_var: self.pos_index_var.analyse_types(env)
+ self.dict_obj = self.dict_obj.analyse_types(env)
+ self.expected_size = self.expected_size.analyse_types(env)
+ if self.pos_index_var:
+ self.pos_index_var = self.pos_index_var.analyse_types(env)
if self.key_target:
- self.key_target.analyse_target_types(env)
+ self.key_target = self.key_target.analyse_target_types(env)
self.key_ref = ExprNodes.TempNode(self.key_target.pos, PyrexTypes.py_object_type)
self.coerced_key_var = self.key_ref.coerce_to(self.key_target.type, env)
if self.value_target:
- self.value_target.analyse_target_types(env)
+ self.value_target = self.value_target.analyse_target_types(env)
self.value_ref = ExprNodes.TempNode(self.value_target.pos, type=PyrexTypes.py_object_type)
self.coerced_value_var = self.value_ref.coerce_to(self.value_target.type, env)
if self.tuple_target:
- self.tuple_target.analyse_target_types(env)
+ self.tuple_target = self.tuple_target.analyse_target_types(env)
self.tuple_ref = ExprNodes.TempNode(self.tuple_target.pos, PyrexTypes.py_object_type)
self.coerced_tuple_var = self.tuple_ref.coerce_to(self.tuple_target.type, env)
- self.is_dict_flag.analyse_types(env)
+ self.is_dict_flag = self.is_dict_flag.analyse_types(env)
+ return self
def generate_function_definitions(self, env, code):
self.dict_obj.generate_function_definitions(env, code)
self.item = ExprNodes.NextNode(self.iterator)
def analyse_expressions(self, env):
- self.target.analyse_target_types(env)
- self.iterator.analyse_expressions(env)
+ self.target = self.target.analyse_target_types(env)
+ self.iterator = self.iterator.analyse_expressions(env)
if self.item is None:
# Hack. Sometimes analyse_declarations not called.
import ExprNodes
self.item = ExprNodes.NextNode(self.iterator)
- self.item.analyse_expressions(env)
+ self.item = self.item.analyse_expressions(env)
if (self.iterator.type.is_ptr or self.iterator.type.is_array) and \
self.target.type.assignable_from(self.iterator.type):
# C array slice optimization.
pass
else:
self.item = self.item.coerce_to(self.target.type, env)
- self.body.analyse_expressions(env)
+ self.body = self.body.analyse_expressions(env)
if self.else_clause:
- self.else_clause.analyse_expressions(env)
+ self.else_clause = self.else_clause.analyse_expressions(env)
+ return self
def generate_execution_code(self, code):
old_loop_labels = code.new_loop_labels()
def analyse_expressions(self, env):
import ExprNodes
- self.target.analyse_target_types(env)
- self.bound1.analyse_types(env)
- self.bound2.analyse_types(env)
+ self.target = self.target.analyse_target_types(env)
+ self.bound1 = self.bound1.analyse_types(env)
+ self.bound2 = self.bound2.analyse_types(env)
if self.step is not None:
if isinstance(self.step, ExprNodes.UnaryMinusNode):
warning(self.step.pos, "Probable infinite loop in for-from-by statement. Consider switching the directions of the relations.", 2)
- self.step.analyse_types(env)
+ self.step = self.step.analyse_types(env)
if self.target.type.is_numeric:
loop_type = self.target.type
self.loopvar_node = c_loopvar_node
self.py_loopvar_node = \
ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
- self.body.analyse_expressions(env)
+ self.body = self.body.analyse_expressions(env)
if self.else_clause:
- self.else_clause.analyse_expressions(env)
+ self.else_clause = self.else_clause.analyse_expressions(env)
+ return self
def generate_execution_code(self, code):
old_loop_labels = code.new_loop_labels()
self.body.analyse_declarations(env)
def analyse_expressions(self, env):
- self.manager.analyse_types(env)
- self.enter_call.analyse_types(env)
- self.body.analyse_expressions(env)
+ self.manager = self.manager.analyse_types(env)
+ self.enter_call = self.enter_call.analyse_types(env)
+ self.body = self.body.analyse_expressions(env)
+ return self
def generate_function_definitions(self, env, code):
self.manager.generate_function_definitions(env, code)
self.lhs.analyse_target_declaration(env)
def analyse_expressions(self, env):
- self.rhs.analyse_types(env)
- self.lhs.analyse_target_types(env)
+ self.rhs = self.rhs.analyse_types(env)
+ self.lhs = self.lhs.analyse_target_types(env)
self.lhs.gil_assignment_check(env)
self.rhs = self.rhs.coerce_to(self.lhs.type, env)
+ return self
def generate_execution_code(self, code):
if self.orig_rhs.type.is_pyobject:
env.use_utility_code(reset_exception_utility_code)
def analyse_expressions(self, env):
- self.body.analyse_expressions(env)
+ self.body = self.body.analyse_expressions(env)
default_clause_seen = 0
- for except_clause in self.except_clauses:
- except_clause.analyse_expressions(env)
+ for i, except_clause in enumerate(self.except_clauses):
+ except_clause = self.except_clauses[i] = except_clause.analyse_expressions(env)
if default_clause_seen:
error(except_clause.pos, "default 'except:' must be last")
if not except_clause.pattern:
default_clause_seen = 1
self.has_default_clause = default_clause_seen
if self.else_clause:
- self.else_clause.analyse_expressions(env)
+ self.else_clause = self.else_clause.analyse_expressions(env)
+ return self
nogil_check = Node.gil_error
gil_message = "Try-except statement"
if self.pattern:
# normalise/unpack self.pattern into a list
for i, pattern in enumerate(self.pattern):
- pattern.analyse_expressions(env)
+ pattern = pattern.analyse_expressions(env)
self.pattern[i] = pattern.coerce_to_pyobject(env)
if self.target:
import ExprNodes
self.exc_value = ExprNodes.ExcValueNode(self.pos, env)
- self.target.analyse_target_expression(env, self.exc_value)
+ self.target = self.target.analyse_target_expression(env, self.exc_value)
if self.excinfo_target is not None:
import ExprNodes
- self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
+ excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
ExprNodes.ExcValueNode(pos=self.pos, env=env) for _ in range(3)])
- self.excinfo_tuple.analyse_expressions(env)
+ self.excinfo_tuple = excinfo_tuple.analyse_expressions(env)
- self.body.analyse_expressions(env)
+ self.body = self.body.analyse_expressions(env)
+ return self
def generate_handling_code(self, code, end_label):
code.mark_pos(self.pos)
self.finally_clause.analyse_declarations(env)
def analyse_expressions(self, env):
- self.body.analyse_expressions(env)
- self.finally_clause.analyse_expressions(env)
+ self.body = self.body.analyse_expressions(env)
+ self.finally_clause = self.finally_clause.analyse_expressions(env)
+ return self
nogil_check = Node.gil_error
gil_message = "Try-finally statement"
UtilityCode.load_cached("ForceInitThreads", "ModuleSetupCode.c"))
was_nogil = env.nogil
env.nogil = self.state == 'nogil'
- TryFinallyStatNode.analyse_expressions(self, env)
+ node = TryFinallyStatNode.analyse_expressions(self, env)
env.nogil = was_nogil
+ return node
def generate_execution_code(self, code):
code.mark_pos(self.pos)
child_attrs = []
def analyse_expressions(self, env):
- pass
+ return self
def generate_execution_code(self, code):
if self.state == 'gil':
*utility_code_for_cimports[self.module_name]))
def analyse_expressions(self, env):
- pass
+ return self
def generate_execution_code(self, code):
pass
return 1
def analyse_expressions(self, env):
- pass
+ return self
def generate_execution_code(self, code):
pass
def analyse_expressions(self, env):
import ExprNodes
- self.module.analyse_expressions(env)
+ self.module = self.module.analyse_expressions(env)
self.item = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
self.interned_items = []
for name, target in self.items:
continue
except AttributeError:
pass
- target.analyse_target_expression(env, None)
+ target = target.analyse_target_expression(env, None) # FIXME?
if target.type is py_object_type:
coerced_item = None
else:
self.interned_items.append((name, target, coerced_item))
if self.interned_items:
env.use_utility_code(raise_import_error_utility_code)
+ return self
def generate_execution_code(self, code):
self.module.generate_evaluation_code(code)
def analyse_expressions(self, env):
if self.num_threads:
- self.num_threads.analyse_expressions(env)
+ self.num_threads = self.num_threads.analyse_expressions(env)
if self.chunksize:
- self.chunksize.analyse_expressions(env)
+ self.chunksize = self.chunksize.analyse_expressions(env)
- self.body.analyse_expressions(env)
+ self.body = self.body.analyse_expressions(env)
self.analyse_sharing_attributes(env)
if self.num_threads is not None:
if not self.num_threads.is_simple():
self.num_threads = self.num_threads.coerce_to(
- PyrexTypes.c_int_type, env).coerce_to_temp(env)
+ PyrexTypes.c_int_type, env).coerce_to_temp(env)
+ return self
def analyse_sharing_attributes(self, env):
"""
if self.target is None:
error(self.pos, "prange() can only be used as part of a for loop")
- return
+ return self
- self.target.analyse_target_types(env)
+ self.target = self.target.analyse_target_types(env)
if not self.target.type.is_numeric:
# Not a valid type, assume one for now anyway
self.index_type, node.type)
if self.else_clause is not None:
- self.else_clause.analyse_expressions(env)
+ self.else_clause = self.else_clause.analyse_expressions(env)
# Although not actually an assignment in this scope, it should be
# treated as such to ensure it is unpacked if a closure temp, and to
if hasattr(self.target, 'entry'):
self.assignments[self.target.entry] = self.target.pos, None
- super(ParallelRangeNode, self).analyse_expressions(env)
+ node = super(ParallelRangeNode, self).analyse_expressions(env)
- if self.chunksize:
- if not self.schedule:
- error(self.chunksize.pos,
+ if node.chunksize:
+ if not node.schedule:
+ error(node.chunksize.pos,
"Must provide schedule with chunksize")
- elif self.schedule == 'runtime':
- error(self.chunksize.pos,
+ elif node.schedule == 'runtime':
+ error(node.chunksize.pos,
"Chunksize not valid for the schedule runtime")
- elif (self.chunksize.type.is_int and
- self.chunksize.is_literal and
- self.chunksize.compile_time_value(env) <= 0):
- error(self.chunksize.pos, "Chunksize must not be negative")
+ elif (node.chunksize.type.is_int and
+ node.chunksize.is_literal and
+ node.chunksize.compile_time_value(env) <= 0):
+ error(node.chunksize.pos, "Chunksize must not be negative")
- self.chunksize = self.chunksize.coerce_to(
- PyrexTypes.c_int_type, env).coerce_to_temp(env)
+ node.chunksize = node.chunksize.coerce_to(
+ PyrexTypes.c_int_type, env).coerce_to_temp(env)
- if self.nogil:
+ if node.nogil:
env.nogil = was_nogil
- self.is_nested_prange = self.parent and self.parent.is_prange
- if self.is_nested_prange:
- parent = self
+ node.is_nested_prange = node.parent and node.parent.is_prange
+ if node.is_nested_prange:
+ parent = node
while parent.parent and parent.parent.is_prange:
parent = parent.parent
- parent.assignments.update(self.assignments)
- parent.privates.update(self.privates)
- parent.assigned_nodes.extend(self.assigned_nodes)
+ parent.assignments.update(node.assignments)
+ parent.privates.update(node.privates)
+ parent.assigned_nodes.extend(node.assigned_nodes)
+ return node
def nogil_check(self, env):
names = 'start', 'stop', 'step', 'target'
return '%s_%s' % (self.cname, cname)
def analyse_expressions(self, env):
- self.node.analyse_expressions(env)
+ self.node = self.node.analyse_expressions(env)
+ return self
def generate_function_definitions(self, env, code):
"Ensure a prototype for every @cname method in the right place"