# HG changeset patch # User Paul Boddie # Date 1382828525 -7200 # Node ID 354ef688b44695a4876f592cef2af9f94acf5e2d # Parent 17378d84907359a9bdea94301fc5cfdb0e9f6ba7 Added "reverse" branches in order to immediately obtain assignment details. diff -r 17378d849073 -r 354ef688b446 docs/annotations.txt --- a/docs/annotations.txt Sun Oct 27 01:00:27 2013 +0200 +++ b/docs/annotations.txt Sun Oct 27 01:02:05 2013 +0200 @@ -67,8 +67,14 @@ branch _attrbranches indicates the immediate contributors to attribute usage known to a node +_attrrevbranches indicates the immediate recipients of attribute usage known + to a node (and is thus the inverse of _attrbranches) _attrcontributors defines nodes contributing to combined attribute usage known - to a node + to a node (and is thus the accumulation of all contributors + via branches) +_attrdefs defines definition-related users which consume usage details + from the node (and is thus the accumulation of all + definitions affected by the node) _attrcombined defines a dictionary mapping local names to sets of attribute names found to be used with those names for the entire lifetime of a particular attribute user @@ -78,8 +84,6 @@ region of the code _attrspecifictypes defines specific types from merged attribute usage details (for non-user nodes) -_attrdefs defines definition-related users which consume usage details - from the node Attribute Accessors ------------------- diff -r 17378d849073 -r 354ef688b446 micropython/branch.py --- a/micropython/branch.py Sun Oct 27 01:00:27 2013 +0200 +++ b/micropython/branch.py Sun Oct 27 01:02:05 2013 +0200 @@ -381,6 +381,11 @@ if node._attrbranches is None: node._attrbranches = [] + # Branches receiving usage from this node. + + if node._attrrevbranches is None: + node._attrrevbranches = [] + # Definitions receiving usage from this node. if node._attrdefs is None: @@ -537,6 +542,7 @@ for user in all_users: self._init_attribute_user(user) user._attrbranches.append(node) + node._attrrevbranches.append(user) def _abandon_branch(self, retain_branch=True): diff -r 17378d849073 -r 354ef688b446 micropython/data.py --- a/micropython/data.py Sun Oct 27 01:00:27 2013 +0200 +++ b/micropython/data.py Sun Oct 27 01:02:05 2013 +0200 @@ -550,21 +550,39 @@ def __init__(self, position, parent, name, nodes): BaseAttr.__init__(self, position, parent, name) self.nodes = nodes or set() + self.users = None + + def _get_defining_users(self): + if self.users is None: + users = set() + visited = set() + for node in self.nodes: + self._get_defining_users_for_node(node, visited, users) + self.users = users + return self.users + + def _get_defining_users_for_node(self, node, visited, users): + if node in visited: + return + visited.add(node) + if not node._attrrevbranches: + if node._values and node._values.has_key(self.name): + users.add(node) + return + for n in node._attrrevbranches: + self._get_defining_users_for_node(n, visited, users) def get_assignments(self): - # NOTE: Needs to consider loops. - return len(self.nodes) + return len(self._get_defining_users()) def get_context_values(self): context_values = set() - for node in self.nodes: - for def_user in node._attrdefs or [node]: - if def_user._values and def_user._values.has_key(self.name): - attr = def_user._values[self.name] - if isinstance(attr, BaseAttr): - context_values.update(attr.get_context_values()) - else: - context_values.add(get_context_and_value(attr)) + for def_user in self._get_defining_users(): + attr = def_user._values[self.name] + if isinstance(attr, BaseAttr): + context_values.update(attr.get_context_values()) + else: + context_values.add(get_context_and_value(attr)) return context_values class Attr(BaseAttr):