1.1 --- a/deducer.py Fri Mar 03 21:35:02 2017 +0100
1.2 +++ b/deducer.py Sat Mar 04 00:20:25 2017 +0100
1.3 @@ -23,8 +23,8 @@
1.4 get_attrname_from_location, get_attrnames, \
1.5 get_invoked_attributes, get_name_path, init_item, \
1.6 sorted_output, CommonOutput
1.7 -from encoders import encode_access_location, \
1.8 - encode_constrained, encode_location, encode_usage, \
1.9 +from encoders import encode_access_location, encode_constrained, \
1.10 + encode_instruction, encode_location, encode_usage, \
1.11 get_kinds, test_label_for_kind, test_label_for_type
1.12 from errors import DeduceError
1.13 from os.path import join
1.14 @@ -110,6 +110,11 @@
1.15
1.16 self.access_plans = {}
1.17
1.18 + # Specific attribute access information.
1.19 +
1.20 + self.access_instructions = {}
1.21 + self.accessor_kinds = {}
1.22 +
1.23 # Accumulated information about accessors and providers.
1.24
1.25 self.accessor_general_class_types = {}
1.26 @@ -143,6 +148,7 @@
1.27 self.classify_accessors()
1.28 self.classify_accesses()
1.29 self.initialise_access_plans()
1.30 + self.initialise_access_instructions()
1.31 self.identify_dependencies()
1.32
1.33 def to_output(self):
1.34 @@ -407,11 +413,21 @@
1.35 def write_access_plans(self):
1.36
1.37 """
1.38 + Write access and instruction plans.
1.39 +
1.40 Each attribute access is written out as a plan of the following form:
1.41
1.42 location " " name " " test " " test type " " base " " traversed attributes
1.43 - " " attributes to traverse " " context " " access method
1.44 - " " static attribute " " accessor kinds
1.45 + " " traversal access modes " " attributes to traverse
1.46 + " " context " " context test " " first access method
1.47 + " " final access method " " static attribute " " accessor kinds
1.48 +
1.49 + Locations have the following format:
1.50 +
1.51 + qualified name of scope "." local name ":" name version
1.52 +
1.53 + Traversal access modes are either "class" (obtain accessor class to
1.54 + access attribute) or "object" (obtain attribute directly from accessor).
1.55 """
1.56
1.57 f_attrs = open(join(self.output, "attribute_plans"), "w")
1.58 @@ -442,6 +458,20 @@
1.59 finally:
1.60 f_attrs.close()
1.61
1.62 + f = open(join(self.output, "instruction_plans"), "w")
1.63 + try:
1.64 + access_instructions = self.access_instructions.items()
1.65 + access_instructions.sort()
1.66 +
1.67 + for location, instructions in access_instructions:
1.68 + print >>f, encode_access_location(location), "..."
1.69 + for instruction in instructions:
1.70 + print >>f, encode_instruction(instruction)
1.71 + print >>f
1.72 +
1.73 + finally:
1.74 + f.close()
1.75 +
1.76 def classify_accessors(self):
1.77
1.78 "For each program location, classify accessors."
1.79 @@ -1919,6 +1949,7 @@
1.80 * remaining attributes needing to be tested and traversed
1.81 * details of the context
1.82 * any test to apply to the context
1.83 + * the method of obtaining the first attribute
1.84 * the method of obtaining the final attribute
1.85 * any static final attribute
1.86 * the kinds of objects providing the final attribute
1.87 @@ -2223,4 +2254,294 @@
1.88 first_method, final_method, \
1.89 origin, accessor_kinds
1.90
1.91 + def initialise_access_instructions(self):
1.92 +
1.93 + "Expand access plans into instruction sequences."
1.94 +
1.95 + for access_location, access_plan in self.access_plans.items():
1.96 +
1.97 + # Obtain the access details.
1.98 +
1.99 + name, test, test_type, base, \
1.100 + traversed, traversal_modes, attrnames, \
1.101 + context, context_test, \
1.102 + first_method, final_method, \
1.103 + origin, accessor_kinds = access_plan
1.104 +
1.105 + # Emit instructions by appending them to a list.
1.106 +
1.107 + instructions = []
1.108 + emit = instructions.append
1.109 +
1.110 + # Identify any static original accessor.
1.111 +
1.112 + if base:
1.113 + original_accessor = base
1.114 +
1.115 + # Employ names as contexts unless the context needs testing and
1.116 + # potentially updating. In such cases, temporary context storage is
1.117 + # used instead.
1.118 +
1.119 + elif name and not (context_test == "test" and
1.120 + final_method in ("access-invoke", "static-invoke")):
1.121 + original_accessor = "<name>" # refers to the name
1.122 +
1.123 + # Use a generic placeholder representing the access expression in
1.124 + # the general case.
1.125 +
1.126 + else:
1.127 + original_accessor = "<expr>"
1.128 +
1.129 + # Prepare for any first attribute access.
1.130 +
1.131 + if traversed:
1.132 + attrname = traversed[0]
1.133 + del traversed[0]
1.134 + elif attrnames:
1.135 + attrname = attrnames[0]
1.136 + del attrnames[0]
1.137 +
1.138 + # Perform the first access explicitly if at least one operation
1.139 + # requires it.
1.140 +
1.141 + access_first_attribute = final_method in ("access", "access-invoke", "assign") or traversed or attrnames
1.142 +
1.143 + # Determine whether the first access involves assignment.
1.144 +
1.145 + assigning = not traversed and not attrnames and final_method == "assign"
1.146 + set_accessor = assigning and "<set_target_accessor>" or "<set_accessor>"
1.147 + stored_accessor = assigning and "<target_accessor>" or "<accessor>"
1.148 +
1.149 + # Set the context if already available.
1.150 +
1.151 + context_var = None
1.152 +
1.153 + if context == "base":
1.154 + accessor = context_var = (base,)
1.155 + elif context == "original-accessor":
1.156 +
1.157 + # Prevent re-evaluation of any dynamic expression by storing it.
1.158 +
1.159 + if original_accessor == "<expr>":
1.160 + if final_method in ("access-invoke", "static-invoke"):
1.161 + emit(("<set_context>", original_accessor))
1.162 + accessor = context_var = ("<context>",)
1.163 + else:
1.164 + emit((set_accessor, original_accessor))
1.165 + accessor = context_var = (stored_accessor,)
1.166 + else:
1.167 + accessor = context_var = (original_accessor,)
1.168 +
1.169 + # Assigning does not set the context.
1.170 +
1.171 + elif context in ("final-accessor", "unset") and access_first_attribute:
1.172 +
1.173 + # Prevent re-evaluation of any dynamic expression by storing it.
1.174 +
1.175 + if original_accessor == "<expr>":
1.176 + emit((set_accessor, original_accessor))
1.177 + accessor = (stored_accessor,)
1.178 + else:
1.179 + accessor = (original_accessor,)
1.180 +
1.181 + # Apply any test.
1.182 +
1.183 + if test[0] == "test":
1.184 + accessor = ("__%s_%s_%s" % test, accessor, test_type)
1.185 +
1.186 + # Perform the first or final access.
1.187 + # The access only needs performing if the resulting accessor is used.
1.188 +
1.189 + remaining = len(traversed + attrnames)
1.190 +
1.191 + if access_first_attribute:
1.192 +
1.193 + if first_method == "relative-class":
1.194 + if assigning:
1.195 + emit(("__store_via_class", accessor, attrname, "<assexpr>"))
1.196 + else:
1.197 + accessor = ("__load_via_class", accessor, attrname)
1.198 +
1.199 + elif first_method == "relative-object":
1.200 + if assigning:
1.201 + emit(("__store_via_object", accessor, attrname, "<assexpr>"))
1.202 + else:
1.203 + accessor = ("__load_via_object", accessor, attrname)
1.204 +
1.205 + elif first_method == "relative-object-class":
1.206 + if assigning:
1.207 + emit(("__get_class_and_store", accessor, attrname, "<assexpr>"))
1.208 + else:
1.209 + accessor = ("__get_class_and_load", accessor, attrname)
1.210 +
1.211 + elif first_method == "check-class":
1.212 + if assigning:
1.213 + emit(("__check_and_store_via_class", accessor, attrname, "<assexpr>"))
1.214 + else:
1.215 + accessor = ("__check_and_load_via_class", accessor, attrname)
1.216 +
1.217 + elif first_method == "check-object":
1.218 + if assigning:
1.219 + emit(("__check_and_store_via_object", accessor, attrname, "<assexpr>"))
1.220 + else:
1.221 + accessor = ("__check_and_load_via_object", accessor, attrname)
1.222 +
1.223 + elif first_method == "check-object-class":
1.224 + if assigning:
1.225 + emit(("__check_and_store_via_any", accessor, attrname, "<assexpr>"))
1.226 + else:
1.227 + accessor = ("__check_and_load_via_any", accessor, attrname)
1.228 +
1.229 + # Traverse attributes using the accessor.
1.230 +
1.231 + if traversed:
1.232 + for attrname, traversal_mode in zip(traversed, traversal_modes):
1.233 + assigning = remaining == 1 and final_method == "assign"
1.234 +
1.235 + # Set the context, if appropriate.
1.236 +
1.237 + if remaining == 1 and final_method != "assign" and context == "final-accessor":
1.238 +
1.239 + # Invoked attributes employ a separate context accessed
1.240 + # during invocation.
1.241 +
1.242 + if final_method in ("access-invoke", "static-invoke"):
1.243 + emit(("<set_context>", accessor))
1.244 + accessor = context_var = "<context>"
1.245 +
1.246 + # A private context within the access is otherwise
1.247 + # retained.
1.248 +
1.249 + else:
1.250 + emit(("<set_private_context>", accessor))
1.251 + accessor = context_var = "<private_context>"
1.252 +
1.253 + # Perform the access only if not achieved directly.
1.254 +
1.255 + if remaining > 1 or final_method in ("access", "access-invoke", "assign"):
1.256 +
1.257 + if traversal_mode == "class":
1.258 + if assigning:
1.259 + emit(("__store_via_class", accessor, attrname, "<assexpr>"))
1.260 + else:
1.261 + accessor = ("__load_via_class", accessor, attrname)
1.262 + else:
1.263 + if assigning:
1.264 + emit(("__store_via_object", accessor, attrname, "<assexpr>"))
1.265 + else:
1.266 + accessor = ("__load_via_object", accessor, attrname)
1.267 +
1.268 + remaining -= 1
1.269 +
1.270 + if attrnames:
1.271 + for attrname in attrnames:
1.272 + assigning = remaining == 1 and final_method == "assign"
1.273 +
1.274 + # Set the context, if appropriate.
1.275 +
1.276 + if remaining == 1 and final_method != "assign" and context == "final-accessor":
1.277 +
1.278 + # Invoked attributes employ a separate context accessed
1.279 + # during invocation.
1.280 +
1.281 + if final_method in ("access-invoke", "static-invoke"):
1.282 + emit(("<set_context>", accessor))
1.283 + accessor = context_var = "<context>"
1.284 +
1.285 + # A private context within the access is otherwise
1.286 + # retained.
1.287 +
1.288 + else:
1.289 + emit(("<set_private_context>", accessor))
1.290 + accessor = context_var = "<private_context>"
1.291 +
1.292 + # Perform the access only if not achieved directly.
1.293 +
1.294 + if remaining > 1 or final_method in ("access", "access-invoke", "assign"):
1.295 +
1.296 + if assigning:
1.297 + emit(("__check_and_store_via_any", accessor, attrname, "<assexpr>"))
1.298 + else:
1.299 + accessor = ("__check_and_load_via_any", accessor, attrname)
1.300 +
1.301 + remaining -= 1
1.302 +
1.303 + # Define or emit the means of accessing the actual target.
1.304 +
1.305 + # Assignments to known attributes.
1.306 +
1.307 + if final_method == "static-assign":
1.308 + parent, attrname = origin.rsplit(".", 1)
1.309 + emit(("__store_via_object", parent, attrname, "<assexpr>"))
1.310 +
1.311 + # Invoked attributes employ a separate context.
1.312 +
1.313 + elif final_method in ("static", "static-invoke"):
1.314 + accessor = ("__load_static_ignore", origin)
1.315 +
1.316 + # Wrap accesses in context operations.
1.317 +
1.318 + if context_test == "test":
1.319 +
1.320 + # Test and combine the context with static attribute details.
1.321 +
1.322 + if final_method == "static":
1.323 + emit(("__load_static_test", context_var, origin))
1.324 +
1.325 + # Test the context, storing it separately if required for the
1.326 + # immediately invoked static attribute.
1.327 +
1.328 + elif final_method == "static-invoke":
1.329 + emit(("<test_context_static>", context_var, origin))
1.330 +
1.331 + # Test the context, storing it separately if required for an
1.332 + # immediately invoked attribute.
1.333 +
1.334 + elif final_method == "access-invoke":
1.335 + emit(("<test_context_revert>", context_var, accessor))
1.336 +
1.337 + # Test the context and update the attribute details if
1.338 + # appropriate.
1.339 +
1.340 + else:
1.341 + emit(("__test_context", context_var, accessor))
1.342 +
1.343 + elif context_test == "replace":
1.344 +
1.345 + # Produce an object with updated context.
1.346 +
1.347 + if final_method == "static":
1.348 + emit(("__load_static_replace", context_var, origin))
1.349 +
1.350 + # Omit the context update operation where the target is static
1.351 + # and the context is recorded separately.
1.352 +
1.353 + elif final_method == "static-invoke":
1.354 + pass
1.355 +
1.356 + # If a separate context is used for an immediate invocation,
1.357 + # produce the attribute details unchanged.
1.358 +
1.359 + elif final_method == "access-invoke":
1.360 + emit(accessor)
1.361 +
1.362 + # Update the context in the attribute details.
1.363 +
1.364 + else:
1.365 + emit(("__update_context", context_var, accessor))
1.366 +
1.367 + # Omit the accessor for assignments and for invocations of static
1.368 + # targets.
1.369 +
1.370 + elif final_method not in ("assign", "static-assign", "static-invoke"):
1.371 + emit(accessor)
1.372 +
1.373 + # Produce an advisory instruction regarding the context.
1.374 +
1.375 + if context_var:
1.376 + emit(("<context_identity>", context_var))
1.377 +
1.378 + self.access_instructions[access_location] = instructions
1.379 + self.accessor_kinds[access_location] = accessor_kinds
1.380 +
1.381 # vim: tabstop=4 expandtab shiftwidth=4
2.1 --- a/optimiser.py Fri Mar 03 21:35:02 2017 +0100
2.2 +++ b/optimiser.py Sat Mar 04 00:20:25 2017 +0100
2.3 @@ -19,9 +19,8 @@
2.4 this program. If not, see <http://www.gnu.org/licenses/>.
2.5 """
2.6
2.7 -from common import add_counter_item, get_attrname_from_location, init_item, \
2.8 - sorted_output, CommonOutput
2.9 -from encoders import digest, encode_access_location, encode_instruction, get_kinds
2.10 +from common import init_item, sorted_output, CommonOutput
2.11 +from encoders import digest
2.12 from errors import OptimiseError
2.13 from os.path import exists, join
2.14 from os import makedirs
2.15 @@ -89,11 +88,6 @@
2.16 self.existing_paramnames = None
2.17 self.indicated_paramnames = None
2.18
2.19 - # Specific attribute access information.
2.20 -
2.21 - self.access_instructions = {}
2.22 - self.accessor_kinds = {}
2.23 -
2.24 # Object structure information.
2.25
2.26 self.structures = {}
2.27 @@ -124,7 +118,6 @@
2.28 self.position_parameters()
2.29 self.populate_tables()
2.30 self.populate_constants()
2.31 - self.initialise_access_instructions()
2.32
2.33 def need_reset(self):
2.34
2.35 @@ -266,23 +259,6 @@
2.36
2.37 ----
2.38
2.39 - Each attribute plan provides attribute details in the following format:
2.40 -
2.41 - location " " name " " test " " test type " " base
2.42 - " " traversed attributes " " traversed attribute ambiguity
2.43 - " " traversal access modes
2.44 - " " attributes to traverse " " attribute ambiguity
2.45 - " " context " " access method " " static attribute
2.46 -
2.47 - Locations have the following format:
2.48 -
2.49 - qualified name of scope "." local name ":" name version
2.50 -
2.51 - Traversal access modes are either "class" (obtain accessor class to
2.52 - access attribute) or "object" (obtain attribute directly from accessor).
2.53 -
2.54 - ----
2.55 -
2.56 The structures are presented as a table in the following format:
2.57
2.58 qualified name " " attribute names
2.59 @@ -356,20 +332,6 @@
2.60 finally:
2.61 f.close()
2.62
2.63 - f = open(join(self.output, "instruction_plans"), "w")
2.64 - try:
2.65 - access_instructions = self.access_instructions.items()
2.66 - access_instructions.sort()
2.67 -
2.68 - for location, instructions in access_instructions:
2.69 - print >>f, encode_access_location(location), "..."
2.70 - for instruction in instructions:
2.71 - print >>f, encode_instruction(instruction)
2.72 - print >>f
2.73 -
2.74 - finally:
2.75 - f.close()
2.76 -
2.77 f = open(join(self.output, "structures"), "w")
2.78 try:
2.79 structures = self.structures.items()
2.80 @@ -533,296 +495,6 @@
2.81 if not d.has_key(attrname):
2.82 d[attrname] = i
2.83
2.84 - def initialise_access_instructions(self):
2.85 -
2.86 - "Expand access plans into instruction sequences."
2.87 -
2.88 - for access_location, access_plan in self.deducer.access_plans.items():
2.89 -
2.90 - # Obtain the access details.
2.91 -
2.92 - name, test, test_type, base, \
2.93 - traversed, traversal_modes, attrnames, \
2.94 - context, context_test, \
2.95 - first_method, final_method, \
2.96 - origin, accessor_kinds = access_plan
2.97 -
2.98 - # Emit instructions by appending them to a list.
2.99 -
2.100 - instructions = []
2.101 - emit = instructions.append
2.102 -
2.103 - # Identify any static original accessor.
2.104 -
2.105 - if base:
2.106 - original_accessor = base
2.107 -
2.108 - # Employ names as contexts unless the context needs testing and
2.109 - # potentially updating. In such cases, temporary context storage is
2.110 - # used instead.
2.111 -
2.112 - elif name and not (context_test == "test" and
2.113 - final_method in ("access-invoke", "static-invoke")):
2.114 - original_accessor = "<name>" # refers to the name
2.115 -
2.116 - # Use a generic placeholder representing the access expression in
2.117 - # the general case.
2.118 -
2.119 - else:
2.120 - original_accessor = "<expr>"
2.121 -
2.122 - # Prepare for any first attribute access.
2.123 -
2.124 - if traversed:
2.125 - attrname = traversed[0]
2.126 - del traversed[0]
2.127 - elif attrnames:
2.128 - attrname = attrnames[0]
2.129 - del attrnames[0]
2.130 -
2.131 - # Perform the first access explicitly if at least one operation
2.132 - # requires it.
2.133 -
2.134 - access_first_attribute = final_method in ("access", "access-invoke", "assign") or traversed or attrnames
2.135 -
2.136 - # Determine whether the first access involves assignment.
2.137 -
2.138 - assigning = not traversed and not attrnames and final_method == "assign"
2.139 - set_accessor = assigning and "<set_target_accessor>" or "<set_accessor>"
2.140 - stored_accessor = assigning and "<target_accessor>" or "<accessor>"
2.141 -
2.142 - # Set the context if already available.
2.143 -
2.144 - context_var = None
2.145 -
2.146 - if context == "base":
2.147 - accessor = context_var = (base,)
2.148 - elif context == "original-accessor":
2.149 -
2.150 - # Prevent re-evaluation of any dynamic expression by storing it.
2.151 -
2.152 - if original_accessor == "<expr>":
2.153 - if final_method in ("access-invoke", "static-invoke"):
2.154 - emit(("<set_context>", original_accessor))
2.155 - accessor = context_var = ("<context>",)
2.156 - else:
2.157 - emit((set_accessor, original_accessor))
2.158 - accessor = context_var = (stored_accessor,)
2.159 - else:
2.160 - accessor = context_var = (original_accessor,)
2.161 -
2.162 - # Assigning does not set the context.
2.163 -
2.164 - elif context in ("final-accessor", "unset") and access_first_attribute:
2.165 -
2.166 - # Prevent re-evaluation of any dynamic expression by storing it.
2.167 -
2.168 - if original_accessor == "<expr>":
2.169 - emit((set_accessor, original_accessor))
2.170 - accessor = (stored_accessor,)
2.171 - else:
2.172 - accessor = (original_accessor,)
2.173 -
2.174 - # Apply any test.
2.175 -
2.176 - if test[0] == "test":
2.177 - accessor = ("__%s_%s_%s" % test, accessor, test_type)
2.178 -
2.179 - # Perform the first or final access.
2.180 - # The access only needs performing if the resulting accessor is used.
2.181 -
2.182 - remaining = len(traversed + attrnames)
2.183 -
2.184 - if access_first_attribute:
2.185 -
2.186 - if first_method == "relative-class":
2.187 - if assigning:
2.188 - emit(("__store_via_class", accessor, attrname, "<assexpr>"))
2.189 - else:
2.190 - accessor = ("__load_via_class", accessor, attrname)
2.191 -
2.192 - elif first_method == "relative-object":
2.193 - if assigning:
2.194 - emit(("__store_via_object", accessor, attrname, "<assexpr>"))
2.195 - else:
2.196 - accessor = ("__load_via_object", accessor, attrname)
2.197 -
2.198 - elif first_method == "relative-object-class":
2.199 - if assigning:
2.200 - emit(("__get_class_and_store", accessor, attrname, "<assexpr>"))
2.201 - else:
2.202 - accessor = ("__get_class_and_load", accessor, attrname)
2.203 -
2.204 - elif first_method == "check-class":
2.205 - if assigning:
2.206 - emit(("__check_and_store_via_class", accessor, attrname, "<assexpr>"))
2.207 - else:
2.208 - accessor = ("__check_and_load_via_class", accessor, attrname)
2.209 -
2.210 - elif first_method == "check-object":
2.211 - if assigning:
2.212 - emit(("__check_and_store_via_object", accessor, attrname, "<assexpr>"))
2.213 - else:
2.214 - accessor = ("__check_and_load_via_object", accessor, attrname)
2.215 -
2.216 - elif first_method == "check-object-class":
2.217 - if assigning:
2.218 - emit(("__check_and_store_via_any", accessor, attrname, "<assexpr>"))
2.219 - else:
2.220 - accessor = ("__check_and_load_via_any", accessor, attrname)
2.221 -
2.222 - # Traverse attributes using the accessor.
2.223 -
2.224 - if traversed:
2.225 - for attrname, traversal_mode in zip(traversed, traversal_modes):
2.226 - assigning = remaining == 1 and final_method == "assign"
2.227 -
2.228 - # Set the context, if appropriate.
2.229 -
2.230 - if remaining == 1 and final_method != "assign" and context == "final-accessor":
2.231 -
2.232 - # Invoked attributes employ a separate context accessed
2.233 - # during invocation.
2.234 -
2.235 - if final_method in ("access-invoke", "static-invoke"):
2.236 - emit(("<set_context>", accessor))
2.237 - accessor = context_var = "<context>"
2.238 -
2.239 - # A private context within the access is otherwise
2.240 - # retained.
2.241 -
2.242 - else:
2.243 - emit(("<set_private_context>", accessor))
2.244 - accessor = context_var = "<private_context>"
2.245 -
2.246 - # Perform the access only if not achieved directly.
2.247 -
2.248 - if remaining > 1 or final_method in ("access", "access-invoke", "assign"):
2.249 -
2.250 - if traversal_mode == "class":
2.251 - if assigning:
2.252 - emit(("__store_via_class", accessor, attrname, "<assexpr>"))
2.253 - else:
2.254 - accessor = ("__load_via_class", accessor, attrname)
2.255 - else:
2.256 - if assigning:
2.257 - emit(("__store_via_object", accessor, attrname, "<assexpr>"))
2.258 - else:
2.259 - accessor = ("__load_via_object", accessor, attrname)
2.260 -
2.261 - remaining -= 1
2.262 -
2.263 - if attrnames:
2.264 - for attrname in attrnames:
2.265 - assigning = remaining == 1 and final_method == "assign"
2.266 -
2.267 - # Set the context, if appropriate.
2.268 -
2.269 - if remaining == 1 and final_method != "assign" and context == "final-accessor":
2.270 -
2.271 - # Invoked attributes employ a separate context accessed
2.272 - # during invocation.
2.273 -
2.274 - if final_method in ("access-invoke", "static-invoke"):
2.275 - emit(("<set_context>", accessor))
2.276 - accessor = context_var = "<context>"
2.277 -
2.278 - # A private context within the access is otherwise
2.279 - # retained.
2.280 -
2.281 - else:
2.282 - emit(("<set_private_context>", accessor))
2.283 - accessor = context_var = "<private_context>"
2.284 -
2.285 - # Perform the access only if not achieved directly.
2.286 -
2.287 - if remaining > 1 or final_method in ("access", "access-invoke", "assign"):
2.288 -
2.289 - if assigning:
2.290 - emit(("__check_and_store_via_any", accessor, attrname, "<assexpr>"))
2.291 - else:
2.292 - accessor = ("__check_and_load_via_any", accessor, attrname)
2.293 -
2.294 - remaining -= 1
2.295 -
2.296 - # Define or emit the means of accessing the actual target.
2.297 -
2.298 - # Assignments to known attributes.
2.299 -
2.300 - if final_method == "static-assign":
2.301 - parent, attrname = origin.rsplit(".", 1)
2.302 - emit(("__store_via_object", parent, attrname, "<assexpr>"))
2.303 -
2.304 - # Invoked attributes employ a separate context.
2.305 -
2.306 - elif final_method in ("static", "static-invoke"):
2.307 - accessor = ("__load_static_ignore", origin)
2.308 -
2.309 - # Wrap accesses in context operations.
2.310 -
2.311 - if context_test == "test":
2.312 -
2.313 - # Test and combine the context with static attribute details.
2.314 -
2.315 - if final_method == "static":
2.316 - emit(("__load_static_test", context_var, origin))
2.317 -
2.318 - # Test the context, storing it separately if required for the
2.319 - # immediately invoked static attribute.
2.320 -
2.321 - elif final_method == "static-invoke":
2.322 - emit(("<test_context_static>", context_var, origin))
2.323 -
2.324 - # Test the context, storing it separately if required for an
2.325 - # immediately invoked attribute.
2.326 -
2.327 - elif final_method == "access-invoke":
2.328 - emit(("<test_context_revert>", context_var, accessor))
2.329 -
2.330 - # Test the context and update the attribute details if
2.331 - # appropriate.
2.332 -
2.333 - else:
2.334 - emit(("__test_context", context_var, accessor))
2.335 -
2.336 - elif context_test == "replace":
2.337 -
2.338 - # Produce an object with updated context.
2.339 -
2.340 - if final_method == "static":
2.341 - emit(("__load_static_replace", context_var, origin))
2.342 -
2.343 - # Omit the context update operation where the target is static
2.344 - # and the context is recorded separately.
2.345 -
2.346 - elif final_method == "static-invoke":
2.347 - pass
2.348 -
2.349 - # If a separate context is used for an immediate invocation,
2.350 - # produce the attribute details unchanged.
2.351 -
2.352 - elif final_method == "access-invoke":
2.353 - emit(accessor)
2.354 -
2.355 - # Update the context in the attribute details.
2.356 -
2.357 - else:
2.358 - emit(("__update_context", context_var, accessor))
2.359 -
2.360 - # Omit the accessor for assignments and for invocations of static
2.361 - # targets.
2.362 -
2.363 - elif final_method not in ("assign", "static-assign", "static-invoke"):
2.364 - emit(accessor)
2.365 -
2.366 - # Produce an advisory instruction regarding the context.
2.367 -
2.368 - if context_var:
2.369 - emit(("<context_identity>", context_var))
2.370 -
2.371 - self.access_instructions[access_location] = instructions
2.372 - self.accessor_kinds[access_location] = accessor_kinds
2.373 -
2.374 def get_ambiguity_for_attributes(self, attrnames):
2.375
2.376 """
3.1 --- a/translator.py Fri Mar 03 21:35:02 2017 +0100
3.2 +++ b/translator.py Sat Mar 04 00:20:25 2017 +0100
3.3 @@ -556,7 +556,7 @@
3.4 # Obtain encoded versions of each instruction, accumulating temporary
3.5 # variables.
3.6
3.7 - for instruction in self.optimiser.access_instructions[location]:
3.8 + for instruction in self.deducer.access_instructions[location]:
3.9
3.10 # Intercept a special instruction identifying the context.
3.11
3.12 @@ -644,7 +644,7 @@
3.13
3.14 "Return the accessor kinds for 'location'."
3.15
3.16 - return self.optimiser.accessor_kinds.get(location)
3.17 + return self.deducer.accessor_kinds.get(location)
3.18
3.19 def get_access_location(self, name, attrnames=None):
3.20