# HG changeset patch # User Paul Boddie # Date 1267143961 -3600 # Node ID 72af990b63cfcede9d32547dbeb1e8faa7912972 # Parent 1686ed14e71328204797a2386df8fe8e4eca0e63 Introduced loop nodes as attribute users tracking attribute usage. diff -r 1686ed14e713 -r 72af990b63cf micropython/data.py --- a/micropython/data.py Thu Feb 25 01:22:21 2010 +0100 +++ b/micropython/data.py Fri Feb 26 01:26:01 2010 +0100 @@ -135,6 +135,7 @@ self.attribute_users = [{}] # stack of assignments self.user_shelves = [] + self.loop_users = [{}] # stack of loop nodes # Define attribute usage to identify active program sections. @@ -330,13 +331,17 @@ with the given 'attrname'. """ + for users in (self.attribute_users[-1], self.loop_users[-1]): + + # Add the usage to all current users. + + if users.has_key(name): + for user in users[name]: + user._attrnames[name].add(attrname) + users = self.attribute_users[-1] - # Add the usage to all current users. - if users.has_key(name): - for user in users[name]: - user._attrnames[name].add(attrname) return users[name] else: return [] @@ -363,15 +368,30 @@ # Record the attribute combinations for the name. + self._init_attribute_user_for_name(node, name) + + # Propagate any loop usage forward to any redefinition of a name. + + loop_users = self.loop_users[-1] + + if loop_users.has_key(name): + for loop_user in loop_users[name]: + node._attrnames[name].update(loop_user._attrnames[name]) + del loop_users[name] + + # Remember this user. + + self.all_attribute_users.add(node) + + def _init_attribute_user_for_name(self, node, name): + + "Make sure that 'node' is initialised for 'name'." + if not hasattr(node, "_attrnames"): node._attrnames = {} node._attrnames[name] = set() - # Remember this user. - - self.all_attribute_users.add(node) - def _new_branchpoint(self): """ @@ -381,11 +401,14 @@ self.user_shelves.append([]) - def _new_branch(self): + def _new_branch(self, loop_node=None): """ Establish a new control-flow branch, transferring attribute usage to the new branch so that it may be augmented for each name locally. + + If the optional 'loop_node' is given, add it as an active user to be + informed of attribute usage. """ # Retain a record of active users. @@ -394,6 +417,21 @@ d.update(self.attribute_users[-1]) self.attribute_users.append(d) + new_users = self.attribute_users[-1] + + d = {} + d.update(self.loop_users[-1]) + + if loop_node is not None: + for name, nodes in new_users.items(): + if not d.has_key(name): + d[name] = set([loop_node]) + else: + d[name] = d[name].union([loop_node]) + self._init_attribute_user_for_name(loop_node, name) + + self.loop_users.append(d) + def _abandon_branch(self): pass diff -r 1686ed14e713 -r 72af990b63cf micropython/inspect.py --- a/micropython/inspect.py Thu Feb 25 01:22:21 2010 +0100 +++ b/micropython/inspect.py Fri Feb 26 01:26:01 2010 +0100 @@ -329,8 +329,8 @@ def new_branchpoint(self): self.get_namespace()._new_branchpoint() - def new_branch(self): - self.get_namespace()._new_branch() + def new_branch(self, loop_node=None): + self.get_namespace()._new_branch(loop_node) def abandon_branch(self): self.get_namespace()._abandon_branch() @@ -960,13 +960,14 @@ self.in_loop = 1 self.dispatch(node.test) - self.new_branch() + self.new_branch(node) self.dispatch(node.body) self.shelve_branch() self.in_loop = 0 # Maintain a branch for the else clause or the current retained usage # where execution avoids the conditional clauses. + # NOTE: Consider merging here before the else clause. self.new_branch() if node.else_ is not None: