Commit 40002217 authored by Stefan Behnel's avatar Stefan Behnel

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
parent d5df4c24
...@@ -2760,13 +2760,15 @@ class SequenceNode(ExprNode): ...@@ -2760,13 +2760,15 @@ class SequenceNode(ExprNode):
self.iterator.allocate_temps(env) self.iterator.allocate_temps(env)
for arg, node in zip(self.args, self.coerced_unpacked_items): for arg, node in zip(self.args, self.coerced_unpacked_items):
node.allocate_temps(env) node.allocate_temps(env)
arg.allocate_target_temps(env, node) arg.allocate_target_temps(env, None)
#arg.release_target_temp(env) #arg.release_target_temp(env)
#node.release_temp(env) #node.release_temp(env)
if rhs: if rhs:
rhs.release_temp(env) rhs.release_temp(env)
self.iterator.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): # def release_target_temp(self, env):
# #for arg in self.args: # #for arg in self.args:
# # arg.release_target_temp(env) # # arg.release_target_temp(env)
...@@ -2786,18 +2788,13 @@ class SequenceNode(ExprNode): ...@@ -2786,18 +2788,13 @@ class SequenceNode(ExprNode):
code.putln("PyObject* tuple = %s;" % rhs.py_result()) code.putln("PyObject* tuple = %s;" % rhs.py_result())
for i in range(len(self.args)): for i in range(len(self.args)):
item = self.unpacked_items[i] item = self.unpacked_items[i]
code.putln( code.put(
"%s = PyTuple_GET_ITEM(tuple, %s);" % ( "%s = PyTuple_GET_ITEM(tuple, %s); " % (
item.result(), item.result(),
i)) i))
code.put_incref(item.result(), item.ctype()) 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) rhs.generate_disposal_code(code)
code.putln("}") code.putln("} else {")
code.putln("else {")
code.putln( code.putln(
"%s = PyObject_GetIter(%s); %s" % ( "%s = PyObject_GetIter(%s); %s" % (
...@@ -2814,9 +2811,6 @@ class SequenceNode(ExprNode): ...@@ -2814,9 +2811,6 @@ class SequenceNode(ExprNode):
item.result(), item.result(),
typecast(item.ctype(), py_object_type, unpack_code), typecast(item.ctype(), py_object_type, unpack_code),
code.error_goto_if_null(item.result(), self.pos))) 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, code.put_error_if_neg(self.pos,
"__Pyx_EndUnpack(%s)" % ( "__Pyx_EndUnpack(%s)" % (
self.iterator.py_result())) self.iterator.py_result()))
...@@ -2826,6 +2820,10 @@ class SequenceNode(ExprNode): ...@@ -2826,6 +2820,10 @@ class SequenceNode(ExprNode):
self.iterator.generate_disposal_code(code) self.iterator.generate_disposal_code(code)
code.putln("}") 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): def annotate(self, code):
for arg in self.args: for arg in self.args:
......
__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)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment