# HG changeset patch # User Paul Boddie # Date 1265761548 -3600 # Node ID 5e5eb65e8d5b42c79559b8fa1dd07bd1563e012b # Parent 946b724d14526e857a936986901f1cc6c76f40a1 Added recording of abandoned attribute usage specifically for attribute users (things which have attributes). Added docstrings and commentary. diff -r 946b724d1452 -r 5e5eb65e8d5b micropython/data.py --- a/micropython/data.py Tue Feb 09 23:32:27 2010 +0100 +++ b/micropython/data.py Wed Feb 10 01:25:48 2010 +0100 @@ -127,6 +127,7 @@ self.attribute_shelves = [] # stack of unmerged definitions self.attribute_users = [{}] # stack of assignments self.abandon_attributes = 0 # used when a block will never contribute + self.attributes_abandoned = [{}] self.abandoned_shelves = [] self.all_attributes_used = [] @@ -341,15 +342,21 @@ "Define 'node' as the user of attributes for the given 'name'." defs = self.attributes_used[-1] + abandoned_defs = self.attributes_abandoned[-1] users = self.attribute_users[-1] + users[name] = node defs[name] = set() + abandoned_defs[name] = set() # Record the attribute combinations for the name. if not hasattr(node, "_attrnames"): node._attrnames = {} + node._attrnames_abandoned = {} + node._attrnames[name] = defs[name] + node._attrnames_abandoned[name] = abandoned_defs[name] # Remember all attribute combinations. @@ -370,16 +377,44 @@ self.abandon_attributes = 1 def _shelve_branch(self): + + """ + Shelve the current control-flow branch, recording the attribute usage + for subsequent merging. If this branch should be abandoned, the usage + observations are still recorded but will not contribute to subsequent + observations after a merge. + """ + if not self.abandon_attributes: collector = self.attribute_shelves[-1] else: collector = self.abandoned_shelves[-1] + collector.append(self.attributes_used.pop()) + + # Forget about any nodes which defined names employing attributes in + # this branch. + self.attribute_users.pop() self.abandon_attributes = 0 def _merge_branches(self): + + """ + Merge control-flow branches. This should find the intersection of the + usage contributions from each branch, which have been "shelved", and + update the active usage dictionary with these contributions. + + Where branches are "abandoned", their attribute usage will not affect + the subsequent usage observations, but such usage will be recorded in + order to deduce function usage. + """ + + # The active dictionary holds the usage for names defined before the + # branches. The abandoned dictionary collects abandoned usage. + active = self.attributes_used[-1] + abandoned = self.attributes_abandoned[-1] # Take each alternative branch, currently shelved, and find the # intersection of their contributions for each name. @@ -406,6 +441,17 @@ else: active[name] = attrnames + # Where abandoned branches exist, record their contributions for the + # attribute users only. + + if abandoned_defs: + for defs in abandoned_defs: + for name, attrnames in defs.items(): + if abandoned.has_key(name): + abandoned[name].add(tuple(attrnames)) + else: + abandoned[name] = attrnames + # Where each shelved set of definitions is a superset of the eventual # definitions for a name, record these specialised sets of usage.