x += y
x *= y
return x
+
+
+# The following is more subtle than one might expect.
+
+cdef struct Inner:
+ int x
+
+cdef struct Aa:
+ int value
+ Inner inner
+
+cdef struct NestedA:
+ Aa a
+
+cdef struct ArrayOfA:
+ Aa[10] a
+
+def nested_struct_assignment():
+ """
+ >>> nested_struct_assignment()
+ """
+ cdef NestedA nested
+ nested.a.value = 2
+ nested.a.value += 3
+ assert nested.a.value == 5
+
+ nested.a.inner.x = 5
+ nested.a.inner.x += 10
+ assert nested.a.inner.x == 15
+
+def nested_array_assignment():
+ """
+ >>> nested_array_assignment()
+ c side effect 0
+ c side effect 1
+ """
+ cdef ArrayOfA array
+ array.a[0].value = 2
+ array.a[c_side_effect(0)].value += 3
+ assert array.a[0].value == 5
+
+ array.a[1].inner.x = 5
+ array.a[c_side_effect(1)].inner.x += 10
+ assert array.a[1].inner.x == 15
+
+cdef class VerboseDict(object):
+ cdef name
+ cdef dict dict
+ def __init__(self, name, **kwds):
+ self.name = name
+ self.dict = kwds
+ def __getitem__(self, key):
+ print self.name, "__getitem__", key
+ return self.dict[key]
+ def __setitem__(self, key, value):
+ print self.name, "__setitem__", key, value
+ self.dict[key] = value
+ def __repr__(self):
+ return repr(self.name)
+
+def deref_and_increment(o, key):
+ """
+ >>> deref_and_increment({'a': 1}, 'a')
+ side effect a
+ >>> v = VerboseDict('v', a=10)
+ >>> deref_and_increment(v, 'a')
+ side effect a
+ v __getitem__ a
+ v __setitem__ a 11
+ """
+ o[side_effect(key)] += 1
+
+def double_deref_and_increment(o, key1, key2):
+ """
+ >>> v = VerboseDict('v', a=10)
+ >>> w = VerboseDict('w', vkey=v)
+ >>> double_deref_and_increment(w, 'vkey', 'a')
+ side effect vkey
+ w __getitem__ vkey
+ side effect a
+ v __getitem__ a
+ v __setitem__ a 11
+ """
+ o[side_effect(key1)][side_effect(key2)] += 1