# HG changeset patch # User Paul Boddie # Date 1488921718 -3600 # Node ID b5fd9597bfabeac5bed3b739d29771dfc9fd4844 # Parent ff6b931a4b0eca281cb9c3d7e8921e11c7ac0184 Allocate separate targets for arguments in the same argument list. Relocated function target storage allocation to the translator. Removed function argument allocation from the inspection activity. diff -r ff6b931a4b0e -r b5fd9597bfab importer.py --- a/importer.py Tue Mar 07 19:21:09 2017 +0100 +++ b/importer.py Tue Mar 07 22:21:58 2017 +0100 @@ -81,8 +81,6 @@ self.function_parameters = {} self.function_defaults = {} self.function_locals = {} - self.function_targets = {} - self.function_arguments = {} # Unresolved names. diff -r ff6b931a4b0e -r b5fd9597bfab inspector.py --- a/inspector.py Tue Mar 07 19:21:09 2017 +0100 +++ b/inspector.py Tue Mar 07 22:21:58 2017 +0100 @@ -100,10 +100,6 @@ self.resolve() - # Define the invocation requirements in each namespace. - - self.set_invocation_usage() - # Propagate to the importer information needed in subsequent activities. self.propagate() @@ -740,50 +736,44 @@ path = self.get_namespace_path() - self.allocate_arguments(path, n.args) + in_invocation = self.in_invocation + self.in_invocation = None - try: - in_invocation = self.in_invocation - self.in_invocation = None + # Process the arguments. - # Process the arguments. - - keywords = set() + keywords = set() - for arg in n.args: - self.process_structure_node(arg) - if isinstance(arg, compiler.ast.Keyword): - keywords.add(arg.name) + for arg in n.args: + self.process_structure_node(arg) + if isinstance(arg, compiler.ast.Keyword): + keywords.add(arg.name) - keywords = list(keywords) - keywords.sort() + keywords = list(keywords) + keywords.sort() - # Communicate to the invocation target expression that it forms the - # target of an invocation, potentially affecting attribute accesses. + # Communicate to the invocation target expression that it forms the + # target of an invocation, potentially affecting attribute accesses. - self.in_invocation = len(n.args), keywords + self.in_invocation = len(n.args), keywords - # Process the expression, obtaining any identified reference. + # Process the expression, obtaining any identified reference. - name_ref = self.process_structure_node(n.node) - self.in_invocation = in_invocation + name_ref = self.process_structure_node(n.node) + self.in_invocation = in_invocation - # Detect class invocations. - - if isinstance(name_ref, ResolvedNameRef) and name_ref.has_kind(""): - return InstanceRef(name_ref.reference().instance_of()) + # Detect class invocations. - elif isinstance(name_ref, NameRef): - return InvocationRef(name_ref) + if isinstance(name_ref, ResolvedNameRef) and name_ref.has_kind(""): + return InstanceRef(name_ref.reference().instance_of()) + + elif isinstance(name_ref, NameRef): + return InvocationRef(name_ref) - # Provide a general reference to indicate that something is produced - # by the invocation, useful for retaining assignment expression - # details. + # Provide a general reference to indicate that something is produced + # by the invocation, useful for retaining assignment expression + # details. - return VariableRef() - - finally: - self.deallocate_arguments(path, n.args) + return VariableRef() def process_lambda_node(self, n): @@ -1457,55 +1447,6 @@ value = ResolvedNameRef(literal_name, ref) self.set_special(literal_name, value) - # Functions and invocations. - - def set_invocation_usage(self): - - """ - Discard the current invocation storage figures, retaining the maximum - values. - """ - - for path, (current, maximum) in self.function_targets.items(): - self.importer.function_targets[path] = self.function_targets[path] = maximum - - for path, (current, maximum) in self.function_arguments.items(): - self.importer.function_arguments[path] = self.function_arguments[path] = maximum - - def allocate_arguments(self, path, args): - - """ - Allocate temporary argument storage using current and maximum - requirements for the given 'path' and 'args'. - """ - - # Class and module initialisation is ultimately combined. - - if not self.in_function: - path = self.name - - init_item(self.function_targets, path, lambda: [0, 0]) - t = self.function_targets[path] - t[0] += 1 - t[1] = max(t[0], t[1]) - - init_item(self.function_arguments, path, lambda: [0, 0]) - t = self.function_arguments[path] - t[0] += len(args) + 1 - t[1] = max(t[0], t[1]) - - def deallocate_arguments(self, path, args): - - "Deallocate temporary argument storage for the given 'path' and 'args'." - - # Class and module initialisation is ultimately combined. - - if not self.in_function: - path = self.name - - self.function_targets[path][0] -= 1 - self.function_arguments[path][0] -= len(args) + 1 - # Exceptions. def record_exception_handler(self): diff -r ff6b931a4b0e -r b5fd9597bfab modules.py --- a/modules.py Tue Mar 07 19:21:09 2017 +0100 +++ b/modules.py Tue Mar 07 22:21:58 2017 +0100 @@ -67,11 +67,6 @@ self.function_locals = {} self.scope_globals = {} - # Invocation details. - - self.function_targets = {} - self.function_arguments = {} - # Exception handler details. self.exception_namespaces = set() @@ -395,8 +390,6 @@ self._get_function_defaults(f) self._get_function_locals(f) self.from_lines(f, self.scope_globals) # "scope globals:" - self._get_function_targets(f) - self._get_function_arguments(f) self._get_attribute_usage(f) self._get_attr_accesses(f) self._get_const_accesses(f) @@ -537,24 +530,6 @@ self.function_locals[function][name] = decode_reference(value) line = f.readline().rstrip() - def _get_function_targets(self, f): - f.readline() # "function targets:" - line = f.readline().rstrip() - while line: - function, n = self._get_fields(line) - self.importer.function_targets[function] = \ - self.function_targets[function] = int(n) - line = f.readline().rstrip() - - def _get_function_arguments(self, f): - f.readline() # "function arguments:" - line = f.readline().rstrip() - while line: - function, n = self._get_fields(line) - self.importer.function_arguments[function] = \ - self.function_arguments[function] = int(n) - line = f.readline().rstrip() - def _get_attribute_usage(self, f): f.readline() # "attribute usage:" line = f.readline().rstrip() @@ -826,20 +801,6 @@ self.to_lines(f, "scope globals:", self.scope_globals) print >>f - print >>f, "function targets:" - functions = self.function_targets.keys() - functions.sort() - for function in functions: - print >>f, function, self.function_targets[function] - - print >>f - print >>f, "function arguments:" - functions = self.function_arguments.keys() - functions.sort() - for function in functions: - print >>f, function, self.function_arguments[function] - - print >>f print >>f, "attribute usage:" units = self.attr_usage.keys() units.sort() diff -r ff6b931a4b0e -r b5fd9597bfab translator.py --- a/translator.py Tue Mar 07 19:21:09 2017 +0100 +++ b/translator.py Tue Mar 07 22:21:58 2017 +0100 @@ -120,6 +120,10 @@ self.in_try_finally = False self.in_try_except = False + # Invocation adjustments. + + self.in_argument_list = False + # Attribute access and accessor counting. self.attr_accesses = {} @@ -313,6 +317,7 @@ else: self.in_function = False self.function_target = 0 + self.max_function_targets = 0 self.start_module() self.process_structure(node) self.end_module() @@ -803,6 +808,7 @@ in_conditional = self.in_conditional self.in_conditional = False self.function_target = 0 + self.max_function_targets = 0 # Volatile locals for exception handling. @@ -994,7 +1000,10 @@ # Any invocations in the expression will store target details in a # different location. - self.function_target += 1 + self.next_target() + + in_argument_list = self.in_argument_list + self.in_argument_list = False # Process the expression. @@ -1002,6 +1011,7 @@ # Reference the current target again. + self.in_argument_list = in_argument_list self.function_target -= 1 # Obtain details of the invocation expression. @@ -1126,7 +1136,13 @@ # Any invocations in the arguments will store target details in a # different location. - self.function_target += 1 + function_target = self.function_target + + if not target_identity: + self.next_target() + + in_argument_list = self.in_argument_list + self.in_argument_list = True for i, arg in enumerate(n.args): argexpr = self.process_structure_node(arg) @@ -1166,7 +1182,10 @@ # Reference the current target again. - self.function_target -= 1 + self.in_argument_list = in_argument_list + + if not self.in_argument_list: + self.function_target = function_target # Defaults are added to the frame where arguments are missing. @@ -1256,6 +1275,13 @@ len(args), argstr)) return InvocationResult(stages) + def next_target(self): + + "Allocate the next function target storage." + + self.function_target += 1 + self.max_function_targets = max(self.function_target, self.max_function_targets) + def always_callable(self, refs): "Determine whether all 'refs' are callable." @@ -1836,7 +1862,7 @@ # Provide space for the given number of targets. - targets = self.importer.function_targets.get(name) + targets = self.max_function_targets if self.uses_temp(name, "__tmp_targets"): self.writeline("__attr __tmp_targets[%d];" % targets)