1.1 --- a/importer.py Tue Mar 07 19:21:09 2017 +0100
1.2 +++ b/importer.py Tue Mar 07 22:21:58 2017 +0100
1.3 @@ -81,8 +81,6 @@
1.4 self.function_parameters = {}
1.5 self.function_defaults = {}
1.6 self.function_locals = {}
1.7 - self.function_targets = {}
1.8 - self.function_arguments = {}
1.9
1.10 # Unresolved names.
1.11
2.1 --- a/inspector.py Tue Mar 07 19:21:09 2017 +0100
2.2 +++ b/inspector.py Tue Mar 07 22:21:58 2017 +0100
2.3 @@ -100,10 +100,6 @@
2.4
2.5 self.resolve()
2.6
2.7 - # Define the invocation requirements in each namespace.
2.8 -
2.9 - self.set_invocation_usage()
2.10 -
2.11 # Propagate to the importer information needed in subsequent activities.
2.12
2.13 self.propagate()
2.14 @@ -740,50 +736,44 @@
2.15
2.16 path = self.get_namespace_path()
2.17
2.18 - self.allocate_arguments(path, n.args)
2.19 + in_invocation = self.in_invocation
2.20 + self.in_invocation = None
2.21
2.22 - try:
2.23 - in_invocation = self.in_invocation
2.24 - self.in_invocation = None
2.25 + # Process the arguments.
2.26
2.27 - # Process the arguments.
2.28 -
2.29 - keywords = set()
2.30 + keywords = set()
2.31
2.32 - for arg in n.args:
2.33 - self.process_structure_node(arg)
2.34 - if isinstance(arg, compiler.ast.Keyword):
2.35 - keywords.add(arg.name)
2.36 + for arg in n.args:
2.37 + self.process_structure_node(arg)
2.38 + if isinstance(arg, compiler.ast.Keyword):
2.39 + keywords.add(arg.name)
2.40
2.41 - keywords = list(keywords)
2.42 - keywords.sort()
2.43 + keywords = list(keywords)
2.44 + keywords.sort()
2.45
2.46 - # Communicate to the invocation target expression that it forms the
2.47 - # target of an invocation, potentially affecting attribute accesses.
2.48 + # Communicate to the invocation target expression that it forms the
2.49 + # target of an invocation, potentially affecting attribute accesses.
2.50
2.51 - self.in_invocation = len(n.args), keywords
2.52 + self.in_invocation = len(n.args), keywords
2.53
2.54 - # Process the expression, obtaining any identified reference.
2.55 + # Process the expression, obtaining any identified reference.
2.56
2.57 - name_ref = self.process_structure_node(n.node)
2.58 - self.in_invocation = in_invocation
2.59 + name_ref = self.process_structure_node(n.node)
2.60 + self.in_invocation = in_invocation
2.61
2.62 - # Detect class invocations.
2.63 -
2.64 - if isinstance(name_ref, ResolvedNameRef) and name_ref.has_kind("<class>"):
2.65 - return InstanceRef(name_ref.reference().instance_of())
2.66 + # Detect class invocations.
2.67
2.68 - elif isinstance(name_ref, NameRef):
2.69 - return InvocationRef(name_ref)
2.70 + if isinstance(name_ref, ResolvedNameRef) and name_ref.has_kind("<class>"):
2.71 + return InstanceRef(name_ref.reference().instance_of())
2.72 +
2.73 + elif isinstance(name_ref, NameRef):
2.74 + return InvocationRef(name_ref)
2.75
2.76 - # Provide a general reference to indicate that something is produced
2.77 - # by the invocation, useful for retaining assignment expression
2.78 - # details.
2.79 + # Provide a general reference to indicate that something is produced
2.80 + # by the invocation, useful for retaining assignment expression
2.81 + # details.
2.82
2.83 - return VariableRef()
2.84 -
2.85 - finally:
2.86 - self.deallocate_arguments(path, n.args)
2.87 + return VariableRef()
2.88
2.89 def process_lambda_node(self, n):
2.90
2.91 @@ -1457,55 +1447,6 @@
2.92 value = ResolvedNameRef(literal_name, ref)
2.93 self.set_special(literal_name, value)
2.94
2.95 - # Functions and invocations.
2.96 -
2.97 - def set_invocation_usage(self):
2.98 -
2.99 - """
2.100 - Discard the current invocation storage figures, retaining the maximum
2.101 - values.
2.102 - """
2.103 -
2.104 - for path, (current, maximum) in self.function_targets.items():
2.105 - self.importer.function_targets[path] = self.function_targets[path] = maximum
2.106 -
2.107 - for path, (current, maximum) in self.function_arguments.items():
2.108 - self.importer.function_arguments[path] = self.function_arguments[path] = maximum
2.109 -
2.110 - def allocate_arguments(self, path, args):
2.111 -
2.112 - """
2.113 - Allocate temporary argument storage using current and maximum
2.114 - requirements for the given 'path' and 'args'.
2.115 - """
2.116 -
2.117 - # Class and module initialisation is ultimately combined.
2.118 -
2.119 - if not self.in_function:
2.120 - path = self.name
2.121 -
2.122 - init_item(self.function_targets, path, lambda: [0, 0])
2.123 - t = self.function_targets[path]
2.124 - t[0] += 1
2.125 - t[1] = max(t[0], t[1])
2.126 -
2.127 - init_item(self.function_arguments, path, lambda: [0, 0])
2.128 - t = self.function_arguments[path]
2.129 - t[0] += len(args) + 1
2.130 - t[1] = max(t[0], t[1])
2.131 -
2.132 - def deallocate_arguments(self, path, args):
2.133 -
2.134 - "Deallocate temporary argument storage for the given 'path' and 'args'."
2.135 -
2.136 - # Class and module initialisation is ultimately combined.
2.137 -
2.138 - if not self.in_function:
2.139 - path = self.name
2.140 -
2.141 - self.function_targets[path][0] -= 1
2.142 - self.function_arguments[path][0] -= len(args) + 1
2.143 -
2.144 # Exceptions.
2.145
2.146 def record_exception_handler(self):
3.1 --- a/modules.py Tue Mar 07 19:21:09 2017 +0100
3.2 +++ b/modules.py Tue Mar 07 22:21:58 2017 +0100
3.3 @@ -67,11 +67,6 @@
3.4 self.function_locals = {}
3.5 self.scope_globals = {}
3.6
3.7 - # Invocation details.
3.8 -
3.9 - self.function_targets = {}
3.10 - self.function_arguments = {}
3.11 -
3.12 # Exception handler details.
3.13
3.14 self.exception_namespaces = set()
3.15 @@ -395,8 +390,6 @@
3.16 self._get_function_defaults(f)
3.17 self._get_function_locals(f)
3.18 self.from_lines(f, self.scope_globals) # "scope globals:"
3.19 - self._get_function_targets(f)
3.20 - self._get_function_arguments(f)
3.21 self._get_attribute_usage(f)
3.22 self._get_attr_accesses(f)
3.23 self._get_const_accesses(f)
3.24 @@ -537,24 +530,6 @@
3.25 self.function_locals[function][name] = decode_reference(value)
3.26 line = f.readline().rstrip()
3.27
3.28 - def _get_function_targets(self, f):
3.29 - f.readline() # "function targets:"
3.30 - line = f.readline().rstrip()
3.31 - while line:
3.32 - function, n = self._get_fields(line)
3.33 - self.importer.function_targets[function] = \
3.34 - self.function_targets[function] = int(n)
3.35 - line = f.readline().rstrip()
3.36 -
3.37 - def _get_function_arguments(self, f):
3.38 - f.readline() # "function arguments:"
3.39 - line = f.readline().rstrip()
3.40 - while line:
3.41 - function, n = self._get_fields(line)
3.42 - self.importer.function_arguments[function] = \
3.43 - self.function_arguments[function] = int(n)
3.44 - line = f.readline().rstrip()
3.45 -
3.46 def _get_attribute_usage(self, f):
3.47 f.readline() # "attribute usage:"
3.48 line = f.readline().rstrip()
3.49 @@ -826,20 +801,6 @@
3.50 self.to_lines(f, "scope globals:", self.scope_globals)
3.51
3.52 print >>f
3.53 - print >>f, "function targets:"
3.54 - functions = self.function_targets.keys()
3.55 - functions.sort()
3.56 - for function in functions:
3.57 - print >>f, function, self.function_targets[function]
3.58 -
3.59 - print >>f
3.60 - print >>f, "function arguments:"
3.61 - functions = self.function_arguments.keys()
3.62 - functions.sort()
3.63 - for function in functions:
3.64 - print >>f, function, self.function_arguments[function]
3.65 -
3.66 - print >>f
3.67 print >>f, "attribute usage:"
3.68 units = self.attr_usage.keys()
3.69 units.sort()
4.1 --- a/translator.py Tue Mar 07 19:21:09 2017 +0100
4.2 +++ b/translator.py Tue Mar 07 22:21:58 2017 +0100
4.3 @@ -120,6 +120,10 @@
4.4 self.in_try_finally = False
4.5 self.in_try_except = False
4.6
4.7 + # Invocation adjustments.
4.8 +
4.9 + self.in_argument_list = False
4.10 +
4.11 # Attribute access and accessor counting.
4.12
4.13 self.attr_accesses = {}
4.14 @@ -313,6 +317,7 @@
4.15 else:
4.16 self.in_function = False
4.17 self.function_target = 0
4.18 + self.max_function_targets = 0
4.19 self.start_module()
4.20 self.process_structure(node)
4.21 self.end_module()
4.22 @@ -803,6 +808,7 @@
4.23 in_conditional = self.in_conditional
4.24 self.in_conditional = False
4.25 self.function_target = 0
4.26 + self.max_function_targets = 0
4.27
4.28 # Volatile locals for exception handling.
4.29
4.30 @@ -994,7 +1000,10 @@
4.31 # Any invocations in the expression will store target details in a
4.32 # different location.
4.33
4.34 - self.function_target += 1
4.35 + self.next_target()
4.36 +
4.37 + in_argument_list = self.in_argument_list
4.38 + self.in_argument_list = False
4.39
4.40 # Process the expression.
4.41
4.42 @@ -1002,6 +1011,7 @@
4.43
4.44 # Reference the current target again.
4.45
4.46 + self.in_argument_list = in_argument_list
4.47 self.function_target -= 1
4.48
4.49 # Obtain details of the invocation expression.
4.50 @@ -1126,7 +1136,13 @@
4.51 # Any invocations in the arguments will store target details in a
4.52 # different location.
4.53
4.54 - self.function_target += 1
4.55 + function_target = self.function_target
4.56 +
4.57 + if not target_identity:
4.58 + self.next_target()
4.59 +
4.60 + in_argument_list = self.in_argument_list
4.61 + self.in_argument_list = True
4.62
4.63 for i, arg in enumerate(n.args):
4.64 argexpr = self.process_structure_node(arg)
4.65 @@ -1166,7 +1182,10 @@
4.66
4.67 # Reference the current target again.
4.68
4.69 - self.function_target -= 1
4.70 + self.in_argument_list = in_argument_list
4.71 +
4.72 + if not self.in_argument_list:
4.73 + self.function_target = function_target
4.74
4.75 # Defaults are added to the frame where arguments are missing.
4.76
4.77 @@ -1256,6 +1275,13 @@
4.78 len(args), argstr))
4.79 return InvocationResult(stages)
4.80
4.81 + def next_target(self):
4.82 +
4.83 + "Allocate the next function target storage."
4.84 +
4.85 + self.function_target += 1
4.86 + self.max_function_targets = max(self.function_target, self.max_function_targets)
4.87 +
4.88 def always_callable(self, refs):
4.89
4.90 "Determine whether all 'refs' are callable."
4.91 @@ -1836,7 +1862,7 @@
4.92
4.93 # Provide space for the given number of targets.
4.94
4.95 - targets = self.importer.function_targets.get(name)
4.96 + targets = self.max_function_targets
4.97
4.98 if self.uses_temp(name, "__tmp_targets"):
4.99 self.writeline("__attr __tmp_targets[%d];" % targets)