1.1 --- a/translator.py Thu Mar 09 21:48:59 2017 +0100
1.2 +++ b/translator.py Thu Mar 09 21:53:55 2017 +0100
1.3 @@ -33,7 +33,7 @@
1.4 from results import Result
1.5 from transresults import TrConstantValueRef, TrInstanceRef, \
1.6 TrLiteralSequenceRef, TrResolvedNameRef, \
1.7 - AttrResult, Expression, InstantiationResult, \
1.8 + AliasResult, AttrResult, Expression, InstantiationResult, \
1.9 InvocationResult, LogicalOperationResult, \
1.10 LogicalResult, NegationResult, PredefinedConstantRef, \
1.11 ReturnRef
1.12 @@ -631,8 +631,10 @@
1.13
1.14 access_location = self.deducer.const_accesses.get(location)
1.15 refs = []
1.16 - for attrtype, objpath, attr in self.deducer.referenced_attrs[access_location or location]:
1.17 - refs.append(attr)
1.18 + l = self.deducer.referenced_attrs.get(access_location or location)
1.19 + if l:
1.20 + for attrtype, objpath, attr in l:
1.21 + refs.append(attr)
1.22 return refs
1.23
1.24 def get_referenced_attribute_invocations(self, location):
1.25 @@ -645,11 +647,16 @@
1.26 access_location = self.deducer.const_accesses.get(location)
1.27 return self.deducer.reference_invocations_unsuitable.get(access_location or location)
1.28
1.29 - def get_accessor_kinds(self, location):
1.30 -
1.31 - "Return the accessor kinds for 'location'."
1.32 -
1.33 - return self.deducer.accessor_kinds.get(location)
1.34 + def get_accessor_kinds(self, locations):
1.35 +
1.36 + "Return the accessor kinds for 'locations'."
1.37 +
1.38 + accessor_kinds = set()
1.39 + for location in locations:
1.40 + kinds = self.deducer.accessor_kinds.get(location)
1.41 + if kinds:
1.42 + accessor_kinds.update(kinds)
1.43 + return accessor_kinds
1.44
1.45 def get_access_location(self, name, attrnames=None):
1.46
1.47 @@ -1018,6 +1025,7 @@
1.48
1.49 objpath = expr.get_origin()
1.50 location = expr.access_location()
1.51 + locations = expr.access_locations()
1.52
1.53 # Identified target details.
1.54
1.55 @@ -1071,7 +1079,10 @@
1.56 # Test for functions and methods.
1.57
1.58 context_required = self.is_method(objpath)
1.59 - accessor_kinds = self.get_accessor_kinds(location)
1.60 +
1.61 + accessor_kinds = location and self.get_accessor_kinds([location]) or \
1.62 + locations and self.get_accessor_kinds(locations)
1.63 +
1.64 instance_accessor = accessor_kinds and \
1.65 len(accessor_kinds) == 1 and \
1.66 first(accessor_kinds) == "<instance>"
1.67 @@ -1105,8 +1116,12 @@
1.68
1.69 # Determine any readily-accessible target identity.
1.70
1.71 - target_identity = target or expr.is_name() and str(expr) or None
1.72 - target_var = target_identity or "__tmp_targets[%d]" % self.function_target
1.73 + target_named = expr.is_name() and str(expr) or None
1.74 + target_stored = "__tmp_targets[%d]" % self.function_target
1.75 +
1.76 + target_identity = target or target_named
1.77 + target_var = target_identity or target_stored
1.78 + context_var = target_named or target_stored
1.79
1.80 if not target_identity:
1.81 self.record_temp("__tmp_targets")
1.82 @@ -1122,7 +1137,7 @@
1.83 if have_access_context:
1.84 args = ["__ATTRVALUE(%s)" % context_identity]
1.85 else:
1.86 - args = ["__CONTEXT_AS_VALUE(%s)" % target_var]
1.87 + args = ["__CONTEXT_AS_VALUE(%s)" % context_var]
1.88 else:
1.89 args = ["__NULL"]
1.90
1.91 @@ -1227,18 +1242,26 @@
1.92 # Without a known specific callable, the expression provides the target.
1.93
1.94 if not target or context_required:
1.95 - if target:
1.96 +
1.97 + # The context is set in the expression.
1.98 +
1.99 + if target and not target_named:
1.100 +
1.101 + # Test whether the expression provides anything.
1.102 +
1.103 if expr:
1.104 stages.append(str(expr))
1.105 +
1.106 elif not target_identity:
1.107 stages.append("%s = %s" % (target_var, expr))
1.108
1.109 - # Any specific callable is then obtained.
1.110 + # Any specific callable is then obtained for invocation.
1.111
1.112 if target:
1.113 stages.append(target)
1.114
1.115 - # Methods accessed via unidentified accessors are obtained.
1.116 + # Methods accessed via unidentified accessors are obtained for
1.117 + # invocation.
1.118
1.119 elif function:
1.120 if context_required:
1.121 @@ -1247,7 +1270,7 @@
1.122 context_identity, target_var))
1.123 else:
1.124 stages.append("__get_function(__CONTEXT_AS_VALUE(%s).value, %s)" % (
1.125 - target_var, target_var))
1.126 + context_var, target_var))
1.127 else:
1.128 stages.append("__load_via_object(%s.value, __fn__).fn" % target_var)
1.129
1.130 @@ -1412,10 +1435,10 @@
1.131 parameter = n.name == "self" and self.in_method() or \
1.132 parameters and n.name in parameters
1.133
1.134 - # Find any invocation details.
1.135 + # Find any invocation or alias details.
1.136
1.137 name = self.get_name_for_tracking(n.name, is_global=is_global)
1.138 - location = self.get_access_location(name)
1.139 + location = not expr and self.get_access_location(name)
1.140
1.141 # Mark any local assignments as volatile in exception blocks.
1.142
1.143 @@ -1426,7 +1449,32 @@
1.144 # static namespace members. The reference should be configured to return
1.145 # such names.
1.146
1.147 - return TrResolvedNameRef(n.name, ref, expr=expr, is_global=is_global, parameter=parameter, location=location)
1.148 + name_ref = TrResolvedNameRef(n.name, ref, expr=expr, is_global=is_global,
1.149 + parameter=parameter, location=location)
1.150 + result = self.get_aliases(name_ref)
1.151 + return result or name_ref
1.152 +
1.153 + def get_aliases(self, name_ref):
1.154 +
1.155 + "Return alias references for the given 'name_ref'."
1.156 +
1.157 + location = name_ref.access_location()
1.158 +
1.159 + accessor_locations = location and self.deducer.get_accessors_for_access(location)
1.160 + alias_refs = set()
1.161 + access_locations = set()
1.162 +
1.163 + if accessor_locations:
1.164 + for accessor_location in accessor_locations:
1.165 + aliased_accesses = self.deducer.alias_index.get(accessor_location)
1.166 + if not aliased_accesses:
1.167 + continue
1.168 + access_locations.update(aliased_accesses)
1.169 + refs = self.deducer.referenced_objects.get(accessor_location)
1.170 + if refs:
1.171 + alias_refs.update(refs)
1.172 +
1.173 + return AliasResult(name_ref, alias_refs, access_locations)
1.174
1.175 def make_volatile(self, name):
1.176