1.1 --- a/optimiser.py Fri Oct 14 21:32:37 2016 +0200
1.2 +++ b/optimiser.py Fri Oct 14 22:16:45 2016 +0200
1.3 @@ -363,17 +363,29 @@
1.4 attrname = attrnames[0]
1.5 del attrnames[0]
1.6
1.7 - access_first_attribute = final_method == "access" or traversed or attrnames
1.8 + # Perform the first access explicitly if at least one operation
1.9 + # requires it.
1.10 +
1.11 + access_first_attribute = final_method in ("access", "assign") or traversed or attrnames
1.12 +
1.13 + # Determine whether the first access involves assignment.
1.14 +
1.15 + assigning = not traversed and not attrnames and final_method == "assign"
1.16
1.17 # Set the context if already available.
1.18 + # Assigning does not set the context.
1.19
1.20 - if context == "original-accessor":
1.21 - emit(("set_context", original_accessor))
1.22 - accessor = "context"
1.23 - elif context == "base":
1.24 - emit(("set_context", base))
1.25 - accessor = "context"
1.26 - elif context == "final-accessor" or access_first_attribute:
1.27 + if not assigning:
1.28 + if context == "original-accessor":
1.29 + emit(("set_context", original_accessor))
1.30 + accessor = "context"
1.31 + elif context == "base":
1.32 + emit(("set_context", base))
1.33 + accessor = "context"
1.34 + elif context == "final-accessor" or access_first_attribute:
1.35 + emit(("set_accessor", original_accessor))
1.36 + accessor = "accessor"
1.37 + else:
1.38 emit(("set_accessor", original_accessor))
1.39 accessor = "accessor"
1.40
1.41 @@ -398,17 +410,40 @@
1.42 if access_first_attribute:
1.43
1.44 if first_method == "relative-class":
1.45 - emit(("set_accessor", ("load_via_class", accessor, attrname)))
1.46 + if assigning:
1.47 + emit(("store_via_class", accessor, attrname, "<assexpr>"))
1.48 + else:
1.49 + emit(("set_accessor", ("load_via_class", accessor, attrname)))
1.50 +
1.51 elif first_method == "relative-object":
1.52 - emit(("set_accessor", ("load_via_object", accessor, attrname)))
1.53 + if assigning:
1.54 + emit(("store_via_object", accessor, attrname, "<assexpr>"))
1.55 + else:
1.56 + emit(("set_accessor", ("load_via_object", accessor, attrname)))
1.57 +
1.58 elif first_method == "relative-object-class":
1.59 - emit(("set_accessor", ("get_class_and_load", accessor, attrname)))
1.60 + if assigning:
1.61 + emit(("get_class_and_store", accessor, attrname, "<assexpr>"))
1.62 + else:
1.63 + emit(("set_accessor", ("get_class_and_load", accessor, attrname)))
1.64 +
1.65 elif first_method == "check-class":
1.66 - emit(("set_accessor", ("check_and_load_via_class", accessor, attrname)))
1.67 + if assigning:
1.68 + emit(("check_and_store_via_class", accessor, attrname, "<assexpr>"))
1.69 + else:
1.70 + emit(("set_accessor", ("check_and_load_via_class", accessor, attrname)))
1.71 +
1.72 elif first_method == "check-object":
1.73 - emit(("set_accessor", ("check_and_load_via_object", accessor, attrname)))
1.74 + if assigning:
1.75 + emit(("check_and_store_via_object", accessor, attrname, "<assexpr>"))
1.76 + else:
1.77 + emit(("set_accessor", ("check_and_load_via_object", accessor, attrname)))
1.78 +
1.79 elif first_method == "check-object-class":
1.80 - emit(("set_accessor", ("check_and_load_via_any", accessor, attrname)))
1.81 + if assigning:
1.82 + emit(("check_and_store_via_any", accessor, attrname, "<assexpr>"))
1.83 + else:
1.84 + emit(("set_accessor", ("check_and_load_via_any", accessor, attrname)))
1.85
1.86 # Obtain an accessor.
1.87
1.88 @@ -416,39 +451,52 @@
1.89
1.90 if traversed:
1.91 for attrname, traversal_mode in zip(traversed, traversal_modes):
1.92 + assigning = remaining == 1 and final_method == "assign"
1.93
1.94 # Set the context, if appropriate.
1.95
1.96 - if remaining == 1 and context == "final-accessor":
1.97 + if remaining == 1 and final_method != "assign" and context == "final-accessor":
1.98 emit(("set_context", "accessor"))
1.99
1.100 # Perform the access only if not achieved directly.
1.101
1.102 - if remaining > 1 or final_method == "access":
1.103 + if remaining > 1 or final_method in ("access", "assign"):
1.104 +
1.105 if traversal_mode == "class":
1.106 - emit(("set_accessor", ("load_via_class", "accessor", attrname)))
1.107 + if assigning:
1.108 + emit(("store_via_class", "accessor", attrname, "<assexpr>"))
1.109 + else:
1.110 + emit(("set_accessor", ("load_via_class", "accessor", attrname)))
1.111 else:
1.112 - emit(("set_accessor", ("load_via_object", "accessor", attrname)))
1.113 + if assigning:
1.114 + emit(("store_via_object", "accessor", attrname, "<assexpr>"))
1.115 + else:
1.116 + emit(("set_accessor", ("load_via_object", "accessor", attrname)))
1.117
1.118 remaining -= 1
1.119
1.120 if attrnames:
1.121 for attrname in attrnames:
1.122 + assigning = remaining == 1 and final_method == "assign"
1.123
1.124 # Set the context, if appropriate.
1.125
1.126 - if remaining == 1 and context == "final-accessor":
1.127 + if remaining == 1 and final_method != "assign" and context == "final-accessor":
1.128 emit(("set_context", "accessor"))
1.129
1.130 # Perform the access only if not achieved directly.
1.131
1.132 - if remaining > 1 or final_method == "access":
1.133 - emit(("set_accessor", ("check_and_load_via_any", "accessor", attrname)))
1.134 + if remaining > 1 or final_method in ("access", "assign"):
1.135 +
1.136 + if assigning:
1.137 + emit(("check_and_store_via_any", "accessor", attrname, "<assexpr>"))
1.138 + else:
1.139 + emit(("set_accessor", ("check_and_load_via_any", "accessor", attrname)))
1.140
1.141 remaining -= 1
1.142
1.143 - if final_method == "assign":
1.144 - emit(("store_member", origin, "<expr>"))
1.145 + if final_method == "static-assign":
1.146 + emit(("store_member", origin, "<assexpr>"))
1.147 elif final_method == "static":
1.148 emit(("load_static", origin))
1.149