From: Stefan Behnel Date: Fri, 21 Nov 2008 10:16:40 +0000 (+0100) Subject: fix for assignments to sequences X-Git-Tag: 0.11-beta~230 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=40002217949319837aab4b729090afc17ecc58e6;p=cython.git fix for assignments to sequences - in the case of an unpacking error, no assignment must take place => do the complete unpacking first, then the assignment - a tiny bit slower for tuples (<5%) - shorter, much more readable code --- diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 92c39544..2f4560e9 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -2760,13 +2760,15 @@ class SequenceNode(ExprNode): self.iterator.allocate_temps(env) for arg, node in zip(self.args, self.coerced_unpacked_items): node.allocate_temps(env) - arg.allocate_target_temps(env, node) + arg.allocate_target_temps(env, None) #arg.release_target_temp(env) #node.release_temp(env) if rhs: rhs.release_temp(env) self.iterator.release_temp(env) - + for node in self.coerced_unpacked_items: + node.release_temp(env) + # def release_target_temp(self, env): # #for arg in self.args: # # arg.release_target_temp(env) @@ -2786,18 +2788,13 @@ class SequenceNode(ExprNode): code.putln("PyObject* tuple = %s;" % rhs.py_result()) for i in range(len(self.args)): item = self.unpacked_items[i] - code.putln( - "%s = PyTuple_GET_ITEM(tuple, %s);" % ( + code.put( + "%s = PyTuple_GET_ITEM(tuple, %s); " % ( item.result(), i)) code.put_incref(item.result(), item.ctype()) - value_node = self.coerced_unpacked_items[i] - value_node.generate_evaluation_code(code) - self.args[i].generate_assignment_code(value_node, code) - rhs.generate_disposal_code(code) - code.putln("}") - code.putln("else {") + code.putln("} else {") code.putln( "%s = PyObject_GetIter(%s); %s" % ( @@ -2814,9 +2811,6 @@ class SequenceNode(ExprNode): item.result(), typecast(item.ctype(), py_object_type, unpack_code), code.error_goto_if_null(item.result(), self.pos))) - value_node = self.coerced_unpacked_items[i] - value_node.generate_evaluation_code(code) - self.args[i].generate_assignment_code(value_node, code) code.put_error_if_neg(self.pos, "__Pyx_EndUnpack(%s)" % ( self.iterator.py_result())) @@ -2826,6 +2820,10 @@ class SequenceNode(ExprNode): self.iterator.generate_disposal_code(code) code.putln("}") + for i in range(len(self.args)): + value_node = self.coerced_unpacked_items[i] + value_node.generate_evaluation_code(code) + self.args[i].generate_assignment_code(value_node, code) def annotate(self, code): for arg in self.args: diff --git a/tests/run/tupleassign.pyx b/tests/run/tupleassign.pyx new file mode 100644 index 00000000..3149f2b9 --- /dev/null +++ b/tests/run/tupleassign.pyx @@ -0,0 +1,34 @@ +__doc__ = u""" +>>> assign3(l) +(1, 2, 3) +>>> assign3(t) +(1, 2, 3) +>>> + +>>> a,b = 99,99 +>>> a,b = t +Traceback (most recent call last): +ValueError: too many values to unpack +>>> a,b +(99, 99) + +>>> test_overwrite(l) +(99, 99) +>>> test_overwrite(t) +(99, 99) +""" + +t = (1,2,3) +l = [1,2,3] + +def assign3(t): + a,b,c = t + return (a,b,c) + +def test_overwrite(t): + a,b = 99,99 + try: + a,b = t + except ValueError: + pass + return (a,b)