1.1 --- a/translator.py Fri Feb 24 16:13:28 2017 +0100
1.2 +++ b/translator.py Sat Feb 25 22:19:53 2017 +0100
1.3 @@ -22,7 +22,7 @@
1.4 from common import CommonModule, CommonOutput, InstructionSequence, \
1.5 first, get_builtin_class, init_item, is_newer, \
1.6 predefined_constants
1.7 -from encoders import encode_access_instruction, \
1.8 +from encoders import encode_access_instruction, encode_access_instruction_arg, \
1.9 encode_function_pointer, encode_literal_constant, \
1.10 encode_literal_instantiator, encode_instantiator_pointer, \
1.11 encode_instructions, \
1.12 @@ -205,10 +205,11 @@
1.13
1.14 "A translation result for an attribute access."
1.15
1.16 - def __init__(self, instructions, refs, location):
1.17 + def __init__(self, instructions, refs, location, context_identity):
1.18 InstructionSequence.__init__(self, instructions)
1.19 self.refs = refs
1.20 self.location = location
1.21 + self.context_identity = context_identity
1.22
1.23 def references(self):
1.24 return self.refs
1.25 @@ -216,6 +217,9 @@
1.26 def access_location(self):
1.27 return self.location
1.28
1.29 + def context(self):
1.30 + return self.context_identity
1.31 +
1.32 def get_origin(self):
1.33 return self.refs and len(self.refs) == 1 and first(self.refs).get_origin()
1.34
1.35 @@ -227,6 +231,9 @@
1.36 return True
1.37 return False
1.38
1.39 + def __nonzero__(self):
1.40 + return bool(self.instructions)
1.41 +
1.42 def __str__(self):
1.43 return encode_instructions(self.instructions)
1.44
1.45 @@ -751,6 +758,7 @@
1.46
1.47 subs = {
1.48 "<expr>" : attr_expr,
1.49 + "<name>" : "%s.value" % attr_expr,
1.50 "<assexpr>" : self.in_assignment,
1.51 }
1.52
1.53 @@ -764,11 +772,22 @@
1.54 # invocation.
1.55
1.56 context_index = self.function_target - 1
1.57 + context_identity = None
1.58
1.59 # Obtain encoded versions of each instruction, accumulating temporary
1.60 # variables.
1.61
1.62 for instruction in self.optimiser.access_instructions[location]:
1.63 +
1.64 + # Intercept a special instruction identifying the context.
1.65 +
1.66 + if instruction[0] == "<context_identity>":
1.67 + context_identity, _substituted = encode_access_instruction_arg(instruction[1], subs, instruction[0], context_index)
1.68 + continue
1.69 +
1.70 + # Collect the encoded instruction, noting any temporary variables
1.71 + # required by it.
1.72 +
1.73 encoded, _substituted = encode_access_instruction(instruction, subs, context_index)
1.74 output.append(encoded)
1.75 substituted.update(_substituted)
1.76 @@ -780,7 +799,7 @@
1.77 self.record_temp(self.temp_subs[sub])
1.78
1.79 del self.attrs[0]
1.80 - return AttrResult(output, refs, location)
1.81 + return AttrResult(output, refs, location, context_identity)
1.82
1.83 def init_substitutions(self):
1.84
1.85 @@ -1225,6 +1244,7 @@
1.86
1.87 context_required = True
1.88 have_access_context = isinstance(expr, AttrResult)
1.89 + context_identity = have_access_context and expr.context()
1.90 parameters = None
1.91
1.92 # Obtain details of the callable and of its parameters.
1.93 @@ -1296,8 +1316,9 @@
1.94
1.95 if context_required:
1.96 if have_access_context:
1.97 - self.record_temp("__tmp_contexts")
1.98 - args = ["(__attr) {.value=__tmp_contexts[%d]}" % self.function_target]
1.99 + if context_identity.startswith("__tmp_contexts"):
1.100 + self.record_temp("__tmp_contexts")
1.101 + args = ["(__attr) {.value=%s}" % context_identity]
1.102 else:
1.103 self.record_temp("__tmp_targets")
1.104 args = ["__CONTEXT_AS_VALUE(__tmp_targets[%d])" % self.function_target]
1.105 @@ -1398,7 +1419,8 @@
1.106
1.107 if not target or context_required:
1.108 if target:
1.109 - stages.append(str(expr))
1.110 + if expr:
1.111 + stages.append(str(expr))
1.112 else:
1.113 self.record_temp("__tmp_targets")
1.114 stages.append("__tmp_targets[%d] = %s" % (self.function_target, expr))
1.115 @@ -1415,9 +1437,10 @@
1.116
1.117 if context_required:
1.118 if have_access_context:
1.119 - self.record_temp("__tmp_contexts")
1.120 - stages.append("__get_function(__tmp_contexts[%d], __tmp_targets[%d])" % (
1.121 - self.function_target, self.function_target))
1.122 + if context_identity.startswith("__tmp_contexts"):
1.123 + self.record_temp("__tmp_contexts")
1.124 + stages.append("__get_function(%s, __tmp_targets[%d])" % (
1.125 + context_identity, self.function_target))
1.126 else:
1.127 stages.append("__get_function(__CONTEXT_AS_VALUE(__tmp_targets[%d]).value, __tmp_targets[%d])" % (
1.128 self.function_target, self.function_target))