self.put_nonecheck(code)
select_code = self.result()
- if self.type.is_pyobject:
+ if self.type.is_pyobject and self.use_managed_ref:
rhs.make_owned_reference(code)
code.put_giveref(rhs.py_result())
code.put_gotref(select_code)
if left_names or right_names:
# lhs/rhs names must be a non-redundant permutation
- lnames = [n.name for n in left_names]
- rnames = [n.name for n in right_names]
+ lnames = [ path for path, n in left_names ]
+ rnames = [ path for path, n in right_names ]
if set(lnames) != set(rnames):
return node
if len(set(lnames)) != len(right_names):
for temp in temps:
temp.use_managed_ref = False
- for name_node in left_names + right_names:
+ for _, name_node in left_names + right_names:
if name_node not in temp_args:
name_node.use_managed_ref = False
if isinstance(node, ExprNodes.CoerceToTempNode):
temps.append(node)
node = node.arg
- if isinstance(node, ExprNodes.NameNode):
- if node.entry.is_builtin or node.entry.is_pyglobal:
+ name_path = []
+ obj_node = node
+ while isinstance(obj_node, ExprNodes.AttributeNode):
+ if obj_node.is_py_attr:
return False
- names.append(node)
+ name_path.append(obj_node.member)
+ obj_node = obj_node.obj
+ if isinstance(obj_node, ExprNodes.NameNode):
+ name_path.append(obj_node.name)
+ names.append( ('.'.join(name_path[::-1]), node) )
elif isinstance(node, ExprNodes.IndexNode):
if node.base.type != Builtin.list_type:
return False
"//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode[@use_managed_ref=False]",
)
def swap_py(a,b):
+ """
+ >>> swap_py(1,2)
+ (1, 2)
+ """
a,a = b,a
return a,b
+cdef class A:
+ cdef readonly object x
+ cdef readonly object y
+ def __init__(self, x, y):
+ self.x, self.y = x, y
+
+@cython.test_assert_path_exists(
+ "//ParallelAssignmentNode",
+ "//ParallelAssignmentNode/SingleAssignmentNode",
+ "//ParallelAssignmentNode/SingleAssignmentNode//AttributeNode/NameNode",
+ "//ParallelAssignmentNode/SingleAssignmentNode//AttributeNode[@use_managed_ref=False]/NameNode",
+ )
+@cython.test_fail_if_path_exists(
+# "//ParallelAssignmentNode/SingleAssignmentNode//AttributeNode[@use_managed_ref=True]",
+ )
+def swap_attr_values(A a, A b):
+ """
+ >>> a, b = A(1,2), A(3,4)
+ >>> a.x, a.y, b.x, b.y
+ (1, 2, 3, 4)
+ >>> swap_attr_values(a,b)
+ >>> a.x, a.y, b.x, b.y
+ (3, 2, 1, 4)
+ """
+ a.x, a.y, b.x, b.y = a.y, b.x, b.y, a.x # shift by one
+ a.x, a.y, b.x, b.y = b.x, b.y, a.x, a.y # shift by two
+ a.x, a.y, b.x, b.y = b.y, b.x, a.y, a.x # reverse
+
+
@cython.test_assert_path_exists(
# "//ParallelAssignmentNode",
# "//ParallelAssignmentNode/SingleAssignmentNode",