1.1 --- a/translator.py Mon Feb 06 22:30:47 2017 +0100
1.2 +++ b/translator.py Tue Feb 07 23:37:40 2017 +0100
1.3 @@ -91,9 +91,13 @@
1.4
1.5 "A reference to a name in the translation."
1.6
1.7 - def __init__(self, name, ref, expr=None, parameter=None):
1.8 + def __init__(self, name, ref, expr=None, parameter=None, unsuitable=None):
1.9 results.ResolvedNameRef.__init__(self, name, ref, expr)
1.10 self.parameter = parameter
1.11 + self.unsuitable = unsuitable
1.12 +
1.13 + def unsuitable_invocations(self):
1.14 + return self.unsuitable
1.15
1.16 def __str__(self):
1.17
1.18 @@ -189,14 +193,18 @@
1.19
1.20 "A translation result for an attribute access."
1.21
1.22 - def __init__(self, instructions, refs, accessor_kinds):
1.23 + def __init__(self, instructions, refs, accessor_kinds, unsuitable):
1.24 InstructionSequence.__init__(self, instructions)
1.25 self.refs = refs
1.26 self.accessor_kinds = accessor_kinds
1.27 + self.unsuitable = unsuitable
1.28
1.29 def references(self):
1.30 return self.refs
1.31
1.32 + def unsuitable_invocations(self):
1.33 + return self.unsuitable
1.34 +
1.35 def get_origin(self):
1.36 return self.refs and len(self.refs) == 1 and first(self.refs).get_origin()
1.37
1.38 @@ -724,8 +732,9 @@
1.39 name_ref = attr_expr and attr_expr.is_name() and attr_expr
1.40 name = name_ref and self.get_name_for_tracking(name_ref.name, name_ref and name_ref.final()) or None
1.41
1.42 - location = self.get_access_location(name)
1.43 + location = self.get_access_location(name, self.attrs)
1.44 refs = self.get_referenced_attributes(location)
1.45 + unsuitable = self.get_referenced_attribute_invocations(location)
1.46
1.47 # Generate access instructions.
1.48
1.49 @@ -768,13 +777,13 @@
1.50 self.record_temp(temp_subs[sub])
1.51
1.52 del self.attrs[0]
1.53 - return AttrResult(output, refs, self.get_accessor_kinds(location))
1.54 + return AttrResult(output, refs, self.get_accessor_kinds(location), unsuitable)
1.55
1.56 def get_referenced_attributes(self, location):
1.57
1.58 """
1.59 Convert 'location' to the form used by the deducer and retrieve any
1.60 - identified attribute.
1.61 + identified attributes.
1.62 """
1.63
1.64 access_location = self.deducer.const_accesses.get(location)
1.65 @@ -783,17 +792,27 @@
1.66 refs.append(attr)
1.67 return refs
1.68
1.69 + def get_referenced_attribute_invocations(self, location):
1.70 +
1.71 + """
1.72 + Convert 'location' to the form used by the deducer and retrieve any
1.73 + identified attribute invocation details.
1.74 + """
1.75 +
1.76 + access_location = self.deducer.const_accesses.get(location)
1.77 + return self.deducer.reference_invocations_unsuitable.get(access_location or location)
1.78 +
1.79 def get_accessor_kinds(self, location):
1.80
1.81 "Return the accessor kinds for 'location'."
1.82
1.83 return self.optimiser.accessor_kinds[location]
1.84
1.85 - def get_access_location(self, name):
1.86 + def get_access_location(self, name, attrnames=None):
1.87
1.88 """
1.89 - Using the current namespace and the given 'name', return the access
1.90 - location.
1.91 + Using the current namespace, the given 'name', and the 'attrnames'
1.92 + employed in an access, return the access location.
1.93 """
1.94
1.95 path = self.get_path_for_access()
1.96 @@ -801,7 +820,7 @@
1.97 # Get the location used by the deducer and optimiser and find any
1.98 # recorded access.
1.99
1.100 - attrnames = ".".join(self.attrs)
1.101 + attrnames = attrnames and ".".join(self.attrs)
1.102 access_number = self.get_access_number(path, name, attrnames)
1.103 self.update_access_number(path, name, attrnames)
1.104 return (path, name, attrnames, access_number)
1.105 @@ -1203,30 +1222,16 @@
1.106 # Other targets are retrieved at run-time.
1.107
1.108 else:
1.109 - refs = expr.references()
1.110 -
1.111 - # Attempt to test the number of arguments and warn about possible
1.112 - # invocation problems.
1.113 -
1.114 - if refs:
1.115 - for ref in refs:
1.116 + unsuitable = expr.unsuitable_invocations()
1.117 +
1.118 + if unsuitable:
1.119 + for ref in unsuitable:
1.120 _objpath = ref.get_origin()
1.121 - _parameters = self.importer.function_parameters.get(_objpath)
1.122 -
1.123 - if _parameters is None:
1.124 - continue
1.125 -
1.126 - # Determine whether the possible target has a different
1.127 - # number of parameters to the number of arguments given.
1.128 -
1.129 - num_parameters = len(_parameters)
1.130 - _defaults = len(self.importer.function_defaults.get(_objpath, []))
1.131 -
1.132 - if len(n.args) < num_parameters - _defaults or len(n.args) > num_parameters:
1.133 - print "In %s, at line %d, inappropriate number of " \
1.134 - "arguments given. Need %d arguments to call %s." % (
1.135 - self.get_namespace_path(), n.lineno, num_parameters,
1.136 - _objpath)
1.137 + num_parameters = len(self.importer.function_parameters[_objpath])
1.138 + print "In %s, at line %d, inappropriate number of " \
1.139 + "arguments given. Need %d arguments to call %s." % (
1.140 + self.get_namespace_path(), n.lineno, num_parameters,
1.141 + _objpath)
1.142
1.143 # Arguments are presented in a temporary frame array with any context
1.144 # always being the first argument. Where it would be unused, it may be
1.145 @@ -1503,11 +1508,16 @@
1.146 parameter = n.name == "self" and self.in_method() or \
1.147 parameters and n.name in parameters
1.148
1.149 + # Find any invocation details.
1.150 +
1.151 + location = self.get_access_location(n.name)
1.152 + unsuitable = self.get_referenced_attribute_invocations(location)
1.153 +
1.154 # Qualified names are used for resolved static references or for
1.155 # static namespace members. The reference should be configured to return
1.156 # such names.
1.157
1.158 - return TrResolvedNameRef(n.name, ref, expr=expr, parameter=parameter)
1.159 + return TrResolvedNameRef(n.name, ref, expr=expr, parameter=parameter, unsuitable=unsuitable)
1.160
1.161 def process_not_node(self, n):
1.162