1.1 --- a/optimiser.py Mon Feb 13 21:49:59 2017 +0100
1.2 +++ b/optimiser.py Tue Feb 14 00:17:39 2017 +0100
1.3 @@ -371,7 +371,7 @@
1.4 # Perform the first access explicitly if at least one operation
1.5 # requires it.
1.6
1.7 - access_first_attribute = final_method in ("access", "assign") or traversed or attrnames
1.8 + access_first_attribute = final_method in ("access", "access-invoke", "assign") or traversed or attrnames
1.9
1.10 # Determine whether the first access involves assignment.
1.11
1.12 @@ -388,8 +388,12 @@
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 = (stored_accessor,)
1.18 + if final_method in ("access-invoke", "static-invoke"):
1.19 + emit(("<set_context>", original_accessor))
1.20 + accessor = context_var = ("<context>",)
1.21 + else:
1.22 + emit((set_accessor, original_accessor))
1.23 + accessor = context_var = (stored_accessor,)
1.24 else:
1.25 accessor = context_var = (original_accessor,)
1.26
1.27 @@ -462,12 +466,12 @@
1.28 # Set the context, if appropriate.
1.29
1.30 if remaining == 1 and final_method != "assign" and context == "final-accessor":
1.31 - emit(("__set_context", accessor))
1.32 + emit(("<set_context>", accessor))
1.33 accessor = context_var = "<context>"
1.34
1.35 # Perform the access only if not achieved directly.
1.36
1.37 - if remaining > 1 or final_method in ("access", "assign"):
1.38 + if remaining > 1 or final_method in ("access", "access-invoke", "assign"):
1.39
1.40 if traversal_mode == "class":
1.41 if assigning:
1.42 @@ -489,12 +493,12 @@
1.43 # Set the context, if appropriate.
1.44
1.45 if remaining == 1 and final_method != "assign" and context == "final-accessor":
1.46 - emit(("__set_context", accessor))
1.47 + emit(("<set_context>", accessor))
1.48 accessor = context_var = "<context>"
1.49
1.50 # Perform the access only if not achieved directly.
1.51
1.52 - if remaining > 1 or final_method in ("access", "assign"):
1.53 + if remaining > 1 or final_method in ("access", "access-invoke", "assign"):
1.54
1.55 if assigning:
1.56 emit(("__check_and_store_via_any", accessor, attrname, "<assexpr>"))
1.57 @@ -505,10 +509,14 @@
1.58
1.59 # Define or emit the means of accessing the actual target.
1.60
1.61 + # Assignments to known attributes.
1.62 +
1.63 if final_method == "static-assign":
1.64 parent, attrname = origin.rsplit(".", 1)
1.65 emit(("__store_via_object", parent, attrname, "<assexpr>"))
1.66
1.67 + # Invoked attributes employ a separate context.
1.68 +
1.69 elif final_method in ("static", "static-invoke"):
1.70 accessor = ("__load_static_ignore", origin)
1.71
1.72 @@ -521,10 +529,19 @@
1.73 emit(("__test_context", context_var, accessor))
1.74
1.75 elif context_test == "replace":
1.76 - if final_method in ("static", "static-invoke"):
1.77 +
1.78 + # Produce an object with updated context.
1.79 +
1.80 + if final_method == "static":
1.81 emit(("__load_static_replace", context_var, origin))
1.82 +
1.83 + # Only update any context if no separate context is used.
1.84 +
1.85 + elif final_method not in ("access-invoke", "static-invoke"):
1.86 + emit(("__update_context", context_var, accessor))
1.87 +
1.88 else:
1.89 - emit(("__update_context", context_var, accessor))
1.90 + emit(accessor)
1.91
1.92 elif final_method not in ("assign", "static-assign"):
1.93 emit(accessor)