1.1 --- a/docs/annotations.txt Sun Oct 27 01:00:27 2013 +0200
1.2 +++ b/docs/annotations.txt Sun Oct 27 01:02:05 2013 +0200
1.3 @@ -67,8 +67,14 @@
1.4 branch
1.5 _attrbranches indicates the immediate contributors to attribute usage
1.6 known to a node
1.7 +_attrrevbranches indicates the immediate recipients of attribute usage known
1.8 + to a node (and is thus the inverse of _attrbranches)
1.9 _attrcontributors defines nodes contributing to combined attribute usage known
1.10 - to a node
1.11 + to a node (and is thus the accumulation of all contributors
1.12 + via branches)
1.13 +_attrdefs defines definition-related users which consume usage details
1.14 + from the node (and is thus the accumulation of all
1.15 + definitions affected by the node)
1.16 _attrcombined defines a dictionary mapping local names to sets of
1.17 attribute names found to be used with those names for the
1.18 entire lifetime of a particular attribute user
1.19 @@ -78,8 +84,6 @@
1.20 region of the code
1.21 _attrspecifictypes defines specific types from merged attribute usage details
1.22 (for non-user nodes)
1.23 -_attrdefs defines definition-related users which consume usage details
1.24 - from the node
1.25
1.26 Attribute Accessors
1.27 -------------------
2.1 --- a/micropython/branch.py Sun Oct 27 01:00:27 2013 +0200
2.2 +++ b/micropython/branch.py Sun Oct 27 01:02:05 2013 +0200
2.3 @@ -381,6 +381,11 @@
2.4 if node._attrbranches is None:
2.5 node._attrbranches = []
2.6
2.7 + # Branches receiving usage from this node.
2.8 +
2.9 + if node._attrrevbranches is None:
2.10 + node._attrrevbranches = []
2.11 +
2.12 # Definitions receiving usage from this node.
2.13
2.14 if node._attrdefs is None:
2.15 @@ -537,6 +542,7 @@
2.16 for user in all_users:
2.17 self._init_attribute_user(user)
2.18 user._attrbranches.append(node)
2.19 + node._attrrevbranches.append(user)
2.20
2.21 def _abandon_branch(self, retain_branch=True):
2.22
3.1 --- a/micropython/data.py Sun Oct 27 01:00:27 2013 +0200
3.2 +++ b/micropython/data.py Sun Oct 27 01:02:05 2013 +0200
3.3 @@ -550,21 +550,39 @@
3.4 def __init__(self, position, parent, name, nodes):
3.5 BaseAttr.__init__(self, position, parent, name)
3.6 self.nodes = nodes or set()
3.7 + self.users = None
3.8 +
3.9 + def _get_defining_users(self):
3.10 + if self.users is None:
3.11 + users = set()
3.12 + visited = set()
3.13 + for node in self.nodes:
3.14 + self._get_defining_users_for_node(node, visited, users)
3.15 + self.users = users
3.16 + return self.users
3.17 +
3.18 + def _get_defining_users_for_node(self, node, visited, users):
3.19 + if node in visited:
3.20 + return
3.21 + visited.add(node)
3.22 + if not node._attrrevbranches:
3.23 + if node._values and node._values.has_key(self.name):
3.24 + users.add(node)
3.25 + return
3.26 + for n in node._attrrevbranches:
3.27 + self._get_defining_users_for_node(n, visited, users)
3.28
3.29 def get_assignments(self):
3.30 - # NOTE: Needs to consider loops.
3.31 - return len(self.nodes)
3.32 + return len(self._get_defining_users())
3.33
3.34 def get_context_values(self):
3.35 context_values = set()
3.36 - for node in self.nodes:
3.37 - for def_user in node._attrdefs or [node]:
3.38 - if def_user._values and def_user._values.has_key(self.name):
3.39 - attr = def_user._values[self.name]
3.40 - if isinstance(attr, BaseAttr):
3.41 - context_values.update(attr.get_context_values())
3.42 - else:
3.43 - context_values.add(get_context_and_value(attr))
3.44 + for def_user in self._get_defining_users():
3.45 + attr = def_user._values[self.name]
3.46 + if isinstance(attr, BaseAttr):
3.47 + context_values.update(attr.get_context_values())
3.48 + else:
3.49 + context_values.add(get_context_and_value(attr))
3.50 return context_values
3.51
3.52 class Attr(BaseAttr):