2.1 --- a/optimiser.py Fri Oct 14 21:32:37 2016 +0200
2.2 +++ b/optimiser.py Fri Oct 14 22:16:45 2016 +0200
2.3 @@ -363,17 +363,29 @@
2.4 attrname = attrnames[0]
2.5 del attrnames[0]
2.6
2.7 - access_first_attribute = final_method == "access" or traversed or attrnames
2.8 + # Perform the first access explicitly if at least one operation
2.9 + # requires it.
2.10 +
2.11 + access_first_attribute = final_method in ("access", "assign") or traversed or attrnames
2.12 +
2.13 + # Determine whether the first access involves assignment.
2.14 +
2.15 + assigning = not traversed and not attrnames and final_method == "assign"
2.16
2.17 # Set the context if already available.
2.18 + # Assigning does not set the context.
2.19
2.20 - if context == "original-accessor":
2.21 - emit(("set_context", original_accessor))
2.22 - accessor = "context"
2.23 - elif context == "base":
2.24 - emit(("set_context", base))
2.25 - accessor = "context"
2.26 - elif context == "final-accessor" or access_first_attribute:
2.27 + if not assigning:
2.28 + if context == "original-accessor":
2.29 + emit(("set_context", original_accessor))
2.30 + accessor = "context"
2.31 + elif context == "base":
2.32 + emit(("set_context", base))
2.33 + accessor = "context"
2.34 + elif context == "final-accessor" or access_first_attribute:
2.35 + emit(("set_accessor", original_accessor))
2.36 + accessor = "accessor"
2.37 + else:
2.38 emit(("set_accessor", original_accessor))
2.39 accessor = "accessor"
2.40
2.41 @@ -398,17 +410,40 @@
2.42 if access_first_attribute:
2.43
2.44 if first_method == "relative-class":
2.45 - emit(("set_accessor", ("load_via_class", accessor, attrname)))
2.46 + if assigning:
2.47 + emit(("store_via_class", accessor, attrname, "<assexpr>"))
2.48 + else:
2.49 + emit(("set_accessor", ("load_via_class", accessor, attrname)))
2.50 +
2.51 elif first_method == "relative-object":
2.52 - emit(("set_accessor", ("load_via_object", accessor, attrname)))
2.53 + if assigning:
2.54 + emit(("store_via_object", accessor, attrname, "<assexpr>"))
2.55 + else:
2.56 + emit(("set_accessor", ("load_via_object", accessor, attrname)))
2.57 +
2.58 elif first_method == "relative-object-class":
2.59 - emit(("set_accessor", ("get_class_and_load", accessor, attrname)))
2.60 + if assigning:
2.61 + emit(("get_class_and_store", accessor, attrname, "<assexpr>"))
2.62 + else:
2.63 + emit(("set_accessor", ("get_class_and_load", accessor, attrname)))
2.64 +
2.65 elif first_method == "check-class":
2.66 - emit(("set_accessor", ("check_and_load_via_class", accessor, attrname)))
2.67 + if assigning:
2.68 + emit(("check_and_store_via_class", accessor, attrname, "<assexpr>"))
2.69 + else:
2.70 + emit(("set_accessor", ("check_and_load_via_class", accessor, attrname)))
2.71 +
2.72 elif first_method == "check-object":
2.73 - emit(("set_accessor", ("check_and_load_via_object", accessor, attrname)))
2.74 + if assigning:
2.75 + emit(("check_and_store_via_object", accessor, attrname, "<assexpr>"))
2.76 + else:
2.77 + emit(("set_accessor", ("check_and_load_via_object", accessor, attrname)))
2.78 +
2.79 elif first_method == "check-object-class":
2.80 - emit(("set_accessor", ("check_and_load_via_any", accessor, attrname)))
2.81 + if assigning:
2.82 + emit(("check_and_store_via_any", accessor, attrname, "<assexpr>"))
2.83 + else:
2.84 + emit(("set_accessor", ("check_and_load_via_any", accessor, attrname)))
2.85
2.86 # Obtain an accessor.
2.87
2.88 @@ -416,39 +451,52 @@
2.89
2.90 if traversed:
2.91 for attrname, traversal_mode in zip(traversed, traversal_modes):
2.92 + assigning = remaining == 1 and final_method == "assign"
2.93
2.94 # Set the context, if appropriate.
2.95
2.96 - if remaining == 1 and context == "final-accessor":
2.97 + if remaining == 1 and final_method != "assign" and context == "final-accessor":
2.98 emit(("set_context", "accessor"))
2.99
2.100 # Perform the access only if not achieved directly.
2.101
2.102 - if remaining > 1 or final_method == "access":
2.103 + if remaining > 1 or final_method in ("access", "assign"):
2.104 +
2.105 if traversal_mode == "class":
2.106 - emit(("set_accessor", ("load_via_class", "accessor", attrname)))
2.107 + if assigning:
2.108 + emit(("store_via_class", "accessor", attrname, "<assexpr>"))
2.109 + else:
2.110 + emit(("set_accessor", ("load_via_class", "accessor", attrname)))
2.111 else:
2.112 - emit(("set_accessor", ("load_via_object", "accessor", attrname)))
2.113 + if assigning:
2.114 + emit(("store_via_object", "accessor", attrname, "<assexpr>"))
2.115 + else:
2.116 + emit(("set_accessor", ("load_via_object", "accessor", attrname)))
2.117
2.118 remaining -= 1
2.119
2.120 if attrnames:
2.121 for attrname in attrnames:
2.122 + assigning = remaining == 1 and final_method == "assign"
2.123
2.124 # Set the context, if appropriate.
2.125
2.126 - if remaining == 1 and context == "final-accessor":
2.127 + if remaining == 1 and final_method != "assign" and context == "final-accessor":
2.128 emit(("set_context", "accessor"))
2.129
2.130 # Perform the access only if not achieved directly.
2.131
2.132 - if remaining > 1 or final_method == "access":
2.133 - emit(("set_accessor", ("check_and_load_via_any", "accessor", attrname)))
2.134 + if remaining > 1 or final_method in ("access", "assign"):
2.135 +
2.136 + if assigning:
2.137 + emit(("check_and_store_via_any", "accessor", attrname, "<assexpr>"))
2.138 + else:
2.139 + emit(("set_accessor", ("check_and_load_via_any", "accessor", attrname)))
2.140
2.141 remaining -= 1
2.142
2.143 - if final_method == "assign":
2.144 - emit(("store_member", origin, "<expr>"))
2.145 + if final_method == "static-assign":
2.146 + emit(("store_member", origin, "<assexpr>"))
2.147 elif final_method == "static":
2.148 emit(("load_static", origin))
2.149