# HG changeset patch # User Paul Boddie # Date 1341355324 -7200 # Node ID 41686b1fb1e2093b7826e7b48abc868d80a03dd3 # Parent 7faa219df63741cddeb0276d04b53ef8413b1b80 Simplified the registration of modified globals by making sure they are known before the module-level code is visited, thus helping to avoid the gathering of attribute usage for names that are known to be modified. (External modification of globals may require usage revocation support, however, since such modification would not be known until module code is being visited.) diff -r 7faa219df637 -r 41686b1fb1e2 micropython/data.py --- a/micropython/data.py Wed Jul 04 00:27:29 2012 +0200 +++ b/micropython/data.py Wed Jul 04 00:42:04 2012 +0200 @@ -2015,12 +2015,11 @@ self.all_objects = set() - # A dictionary mapping functions to global names that cannot support - # combined attribute usage observations because they may be modified in - # the given functions during initialisation. Functions could be - # eliminated from this dictionary if not thought to be used. - - self.modified_names = {} + # A set of global names that cannot support combined attribute usage + # observations because they may be modified within functions during + # initialisation. + + self.modified_names = set() # Keyword records. @@ -2065,79 +2064,23 @@ # Attribute usage methods that apply to module globals in certain # circumstances. - def finalise_users(self, objtable): - - """ - Finalise attribute users, first revoking usage for any global names - that might be modified during initialisation. - """ - - NamespaceDict.finalise_users(self, objtable) - - # Collect modified names and revoke attribute usage details for those - # names. - - names = set() - for function_names in self.modified_names.values(): - names.update(function_names) - - self.revoke_attribute_usage(names) - - def revoke_attribute_usage(self, names): - - """ - The definition of attribute users may be overridden or ignored if the - module is found to be involved in circular imports where externally - initiated modification occurs or if a function in the module may rebind - globals, potentially during initialisation. - """ - - for user in self.all_attribute_users: - - # Remove user details for each name. - - for name in names: - - # Remove annotations derived from the combined observations. - - if user._attrtypes.has_key(name): - del user._attrtypes[name] - if user._attrspecifictypes.has_key(name): - del user._attrspecifictypes[name] - if user._attrmerged.has_key(name): - del user._attrmerged[name] - - # Usage nodes that can no longer support combined observations - # of attribute usage must instead support isolated observations. - - if not user._attrcombined.has_key(name): - continue - - usage = user._attrcombined[name] - - # Usage is defined as a collection of attribute name - # observations. - - for attrnames in usage: - - # Each attribute name may have values associated with it - # where such values have been assigned to an attribute of - # the given name. - - for attrname, attrvalues in usage.items(): - if attrvalues: - for value in attrvalues: - self.importer.use_name(attrname, self.full_name(), value) - else: - self.importer.use_name(attrname, self.full_name()) - - del user._attrcombined[name] - - # Remove annotations on contributors. - - for contributor in user._attrcontributors: - if contributor._attrusers.has_key(name): - del contributor._attrusers[name] + def _use_attribute(self, name, attrname, value=None): + if name not in self.modified_names: + return NamespaceDict._use_attribute(self, name, attrname, value) + else: + return [] + + def _define_attribute_user_for_name(self, node, name): + if name not in self.modified_names: + NamespaceDict._define_attribute_user_for_name(self, node, name) + + def _init_attribute_user_for_name(self, node, name): + if name not in self.modified_names: + NamespaceDict._init_attribute_user_for_name(self, node, name) + + def _define_attribute_accessor(self, name, attrname, node, value): + if name not in self.modified_names: + NamespaceDict._define_attribute_accessor(self, name, attrname, node, value) # Pre-made instances. diff -r 7faa219df637 -r 41686b1fb1e2 micropython/inspect.py --- a/micropython/inspect.py Wed Jul 04 00:27:29 2012 +0200 +++ b/micropython/inspect.py Wed Jul 04 00:42:04 2012 +0200 @@ -200,6 +200,8 @@ # NOTE: point and just set an instance instead. self.set(name, make_instance(), False) + self.modified_names.add(name) + else: self.process_globals(n) @@ -1079,19 +1081,6 @@ # The name is recorded in an earlier process. - # Since the presence of a global declaration may - # indicate the modification of a name, and this may - # happen during initialisation, the name is recorded - # and any usage observations ultimately revoked. - - # NOTE: Actual modification could be detected by - # NOTE: establishing a path from the module top-level to - # NOTE: an actual assignment. - - if not self.modified_names.has_key(ns): - self.modified_names[ns] = set() - self.modified_names[ns].add(name) - def visitIf(self, node): self.use_name("__bool__", node) self.new_branchpoint() diff -r 7faa219df637 -r 41686b1fb1e2 tests/changed_globals_function.py --- a/tests/changed_globals_function.py Wed Jul 04 00:27:29 2012 +0200 +++ b/tests/changed_globals_function.py Wed Jul 04 00:42:04 2012 +0200 @@ -12,11 +12,15 @@ global x x = D +def use(y): + return y.p # usage of p + def f(): - return x.p + return x.p # ambiguous change() result1_456 = x.p result2_456 = f() +result3_456 = use(x) # vim: tabstop=4 expandtab shiftwidth=4