1.1 --- a/optimiser.py Sat Dec 10 17:35:58 2016 +0100
1.2 +++ b/optimiser.py Sat Dec 10 18:52:54 2016 +0100
1.3 @@ -375,6 +375,8 @@
1.4 # Determine whether the first access involves assignment.
1.5
1.6 assigning = not traversed and not attrnames and final_method == "assign"
1.7 + set_accessor = assigning and "__set_target_accessor" or "__set_accessor"
1.8 + stored_accessor = assigning and "<target_accessor>" or "<accessor>"
1.9
1.10 # Set the context if already available.
1.11
1.12 @@ -385,8 +387,8 @@
1.13 # Prevent re-evaluation of any dynamic expression by storing it.
1.14
1.15 if original_accessor == "<expr>":
1.16 - emit(("__set_accessor", original_accessor))
1.17 - accessor = context_var = ("<accessor>",)
1.18 + emit((set_accessor, original_accessor))
1.19 + accessor = context_var = (stored_accessor,)
1.20 else:
1.21 accessor = context_var = (original_accessor,)
1.22
1.23 @@ -397,8 +399,8 @@
1.24 # Prevent re-evaluation of any dynamic expression by storing it.
1.25
1.26 if original_accessor == "<expr>":
1.27 - emit(("__set_accessor", original_accessor))
1.28 - accessor = ("<accessor>",)
1.29 + emit((set_accessor, original_accessor))
1.30 + accessor = (stored_accessor,)
1.31 else:
1.32 accessor = (original_accessor,)
1.33
2.1 --- a/templates/ops.h Sat Dec 10 17:35:58 2016 +0100
2.2 +++ b/templates/ops.h Sat Dec 10 18:52:54 2016 +0100
2.3 @@ -73,6 +73,7 @@
2.4
2.5 #define __set_context(__ATTR) (__tmp_context = (__ATTR).value)
2.6 #define __set_accessor(__ATTR) (__tmp_value = (__ATTR).value)
2.7 +#define __set_target_accessor(__ATTR) (__tmp_target_value = (__ATTR).value)
2.8
2.9 /* Basic structure tests. */
2.10
3.1 --- a/translator.py Sat Dec 10 17:35:58 2016 +0100
3.2 +++ b/translator.py Sat Dec 10 18:52:54 2016 +0100
3.3 @@ -647,20 +647,7 @@
3.4
3.5 def process_attribute_access(self, n):
3.6
3.7 - """
3.8 - Process the given attribute access node 'n'.
3.9 -
3.10 - Where a name is provided, a single access should be recorded
3.11 - involving potentially many attributes, thus providing a path to an
3.12 - object. The remaining attributes are then accessed dynamically.
3.13 - The remaining accesses could be deduced and computed, but they would
3.14 - also need to be tested.
3.15 -
3.16 - Where no name is provided, potentially many accesses should be
3.17 - recorded, one per attribute name. These could be used to provide
3.18 - computed accesses, but the accessors would need to be tested in each
3.19 - case.
3.20 - """
3.21 + "Process the given attribute access node 'n'."
3.22
3.23 # Obtain any completed chain and return the reference to it.
3.24
3.25 @@ -684,6 +671,7 @@
3.26 "<assexpr>" : str(self.in_assignment),
3.27 "<context>" : "__tmp_context",
3.28 "<accessor>" : "__tmp_value",
3.29 + "<target_accessor>" : "__tmp_target_value",
3.30 }
3.31
3.32 output = []
3.33 @@ -1687,7 +1675,7 @@
3.34
3.35 targets = targets is not None and "__tmp_targets[%d], " % targets or ""
3.36
3.37 - self.writeline("__ref __tmp_context, __tmp_value;")
3.38 + self.writeline("__ref __tmp_context, __tmp_value, __tmp_target_value;")
3.39 self.writeline("__attr %s__tmp_result;" % targets)
3.40 self.writeline("__exc __tmp_exc;")
3.41