cython-devel

changeset 1376:e490ccfecad0

handle value coercion correctly in dict iteration
author Stefan Behnel <scoder@users.berlios.de>
date Tue Nov 25 18:24:52 2008 +0100 (3 years ago)
parents 9e5fcb49d029
children 9f94f4e5b3d7
files Cython/Compiler/ExprNodes.py Cython/Compiler/Optimize.py tests/run/iterdict.pyx
line diff
1.1 --- a/Cython/Compiler/ExprNodes.py Tue Nov 25 15:56:09 2008 +0100 1.2 +++ b/Cython/Compiler/ExprNodes.py Tue Nov 25 18:24:52 2008 +0100 1.3 @@ -4504,8 +4504,6 @@ 1.4 self.type = dst_type 1.5 self.gil_check(env) 1.6 self.result_ctype = arg.ctype() 1.7 - if not dst_type.is_builtin_type: 1.8 - env.use_utility_code(type_test_utility_code) 1.9 1.10 gil_message = "Python type test" 1.11 1.12 @@ -4523,6 +4521,8 @@ 1.13 1.14 def generate_result_code(self, code): 1.15 if self.type.typeobj_is_available(): 1.16 + if not dst_type.is_builtin_type: 1.17 + code.globalstate.use_utility_code(type_test_utility_code) 1.18 code.putln( 1.19 "if (!(%s)) %s" % ( 1.20 self.type.type_test_code(self.arg.py_result()),
2.1 --- a/Cython/Compiler/Optimize.py Tue Nov 25 15:56:09 2008 +0100 2.2 +++ b/Cython/Compiler/Optimize.py Tue Nov 25 18:24:52 2008 +0100 2.3 @@ -111,16 +111,25 @@ 2.4 else: 2.5 tuple_target = node.target 2.6 2.7 - if keys: 2.8 - key_cast = ExprNodes.TypecastNode( 2.9 - pos = key_target.pos, 2.10 - operand = key_temp, 2.11 - type = key_target.type) 2.12 - if values: 2.13 - value_cast = ExprNodes.TypecastNode( 2.14 - pos = value_target.pos, 2.15 - operand = value_temp, 2.16 - type = value_target.type) 2.17 + def coerce_object_to(obj_node, dest_type): 2.18 + class FakeEnv(object): 2.19 + nogil = False 2.20 + if dest_type.is_pyobject: 2.21 + if dest_type.is_extension_type or dest_type.is_builtin_type: 2.22 + return (obj_node, ExprNodes.PyTypeTestNode(obj_node, dest_type, FakeEnv())) 2.23 + else: 2.24 + return (obj_node, None) 2.25 + else: 2.26 + temp = UtilNodes.TempHandle(dest_type) 2.27 + temps.append(temp) 2.28 + temp_result = temp.ref(obj_node.pos) 2.29 + class CoercedTempNode(ExprNodes.CoerceFromPyTypeNode): 2.30 + # FIXME: remove this after result-code refactoring 2.31 + def result(self): 2.32 + return temp_result.result() 2.33 + def generate_execution_code(self, code): 2.34 + self.generate_result_code(code) 2.35 + return (temp_result, CoercedTempNode(dest_type, obj_node, FakeEnv())) 2.36 2.37 if isinstance(node.body, Nodes.StatListNode): 2.38 body = node.body 2.39 @@ -129,7 +138,7 @@ 2.40 stats = [node.body]) 2.41 2.42 if tuple_target: 2.43 - temp = UtilNodes.TempHandle(py_object_ptr) 2.44 + temp = UtilNodes.TempHandle(PyrexTypes.py_object_type) 2.45 temps.append(temp) 2.46 temp_tuple = temp.ref(tuple_target.pos) 2.47 class TempTupleNode(ExprNodes.TupleNode): 2.48 @@ -139,7 +148,7 @@ 2.49 2.50 tuple_result = TempTupleNode( 2.51 pos = tuple_target.pos, 2.52 - args = [key_cast, value_cast], 2.53 + args = [key_temp, value_temp], 2.54 is_temp = 1, 2.55 type = Builtin.tuple_type, 2.56 ) 2.57 @@ -148,18 +157,30 @@ 2.58 lhs = tuple_target, 2.59 rhs = tuple_result)) 2.60 else: 2.61 + # execute all coercions before the assignments 2.62 + coercion_stats = [] 2.63 + assign_stats = [] 2.64 + if keys: 2.65 + temp_result, coercion = coerce_object_to( 2.66 + key_temp, key_target.type) 2.67 + if coercion: 2.68 + coercion_stats.append(coercion) 2.69 + assign_stats.append( 2.70 + Nodes.SingleAssignmentNode( 2.71 + pos = key_temp.pos, 2.72 + rhs = temp_result, 2.73 + lhs = key_target)) 2.74 if values: 2.75 - body.stats.insert( 2.76 - 0, Nodes.SingleAssignmentNode( 2.77 - pos = value_target.pos, 2.78 - lhs = value_target, 2.79 - rhs = value_cast)) 2.80 - if keys: 2.81 - body.stats.insert( 2.82 - 0, Nodes.SingleAssignmentNode( 2.83 - pos = key_target.pos, 2.84 - lhs = key_target, 2.85 - rhs = key_cast)) 2.86 + temp_result, coercion = coerce_object_to( 2.87 + value_temp, value_target.type) 2.88 + if coercion: 2.89 + coercion_stats.append(coercion) 2.90 + assign_stats.append( 2.91 + Nodes.SingleAssignmentNode( 2.92 + pos = value_temp.pos, 2.93 + rhs = temp_result, 2.94 + lhs = value_target)) 2.95 + body.stats[0:0] = coercion_stats + assign_stats 2.96 2.97 result_code = [ 2.98 Nodes.SingleAssignmentNode(
3.1 --- a/tests/run/iterdict.pyx Tue Nov 25 15:56:09 2008 +0100 3.2 +++ b/tests/run/iterdict.pyx Tue Nov 25 18:24:52 2008 +0100 3.3 @@ -6,14 +6,22 @@ 3.4 [(10, 0), (11, 1), (12, 2), (13, 3)] 3.5 >>> iteritems(d) 3.6 [(10, 0), (11, 1), (12, 2), (13, 3)] 3.7 +>>> iteritems_int(d) 3.8 +[(10, 0), (11, 1), (12, 2), (13, 3)] 3.9 >>> iteritems_tuple(d) 3.10 [(10, 0), (11, 1), (12, 2), (13, 3)] 3.11 >>> iterkeys(d) 3.12 [10, 11, 12, 13] 3.13 +>>> iterkeys_int(d) 3.14 +[10, 11, 12, 13] 3.15 >>> iterdict(d) 3.16 [10, 11, 12, 13] 3.17 +>>> iterdict_int(d) 3.18 +[10, 11, 12, 13] 3.19 >>> itervalues(d) 3.20 [0, 1, 2, 3] 3.21 +>>> itervalues_int(d) 3.22 +[0, 1, 2, 3] 3.23 """ 3.24 3.25 def items(dict d): 3.26 @@ -30,6 +38,14 @@ 3.27 l.sort() 3.28 return l 3.29 3.30 +def iteritems_int(dict d): 3.31 + cdef int k,v 3.32 + l = [] 3.33 + for k,v in d.iteritems(): 3.34 + l.append((k,v)) 3.35 + l.sort() 3.36 + return l 3.37 + 3.38 def iteritems_tuple(dict d): 3.39 l = [] 3.40 for t in d.iteritems(): 3.41 @@ -44,6 +60,14 @@ 3.42 l.sort() 3.43 return l 3.44 3.45 +def iterkeys_int(dict d): 3.46 + cdef int k 3.47 + l = [] 3.48 + for k in d.iterkeys(): 3.49 + l.append(k) 3.50 + l.sort() 3.51 + return l 3.52 + 3.53 def iterdict(dict d): 3.54 l = [] 3.55 for k in d: 3.56 @@ -51,9 +75,25 @@ 3.57 l.sort() 3.58 return l 3.59 3.60 +def iterdict_int(dict d): 3.61 + cdef int k 3.62 + l = [] 3.63 + for k in d: 3.64 + l.append(k) 3.65 + l.sort() 3.66 + return l 3.67 + 3.68 def itervalues(dict d): 3.69 l = [] 3.70 for v in d.itervalues(): 3.71 l.append(v) 3.72 l.sort() 3.73 return l 3.74 + 3.75 +def itervalues_int(dict d): 3.76 + cdef int v 3.77 + l = [] 3.78 + for v in d.itervalues(): 3.79 + l.append(v) 3.80 + l.sort() 3.81 + return l