1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/TO_DO.txt Fri Feb 12 01:34:28 2010 +0100
1.3 @@ -0,0 +1,19 @@
1.4 +Abandoned branches: should alternative type candidates be proposed by abandoned usage?
1.5 +(This involves using both _attrnames and _attrnames_abandoned on user nodes to decide on whether guards are appropriate.)
1.6 +
1.7 +Usage should not be instantly fed back to users.
1.8 +Branches should have an empty set of users and usage should only feed back to users defined on a branch or merged from sub-branches.
1.9 +
1.10 +Attribute users should be merged so that many users can be maintained for a name:
1.11 +
1.12 + def f(x):
1.13 + if ...:
1.14 + x = ...
1.15 + x.a() # affects assignment node
1.16 + x.b() # affects assignment and parameter nodes
1.17 +
1.18 +Constant attribute users need not maintain usage since they are already resolved.
1.19 +
1.20 +Consider handling CallFunc in micropython.inspect in order to produce instances of specific classes.
1.21 +Then, consider adding support for guard removal/verification where known instances are involved.
1.22 +Consider handling branches of values within namespaces in order to support more precise value usage.
2.1 --- a/micropython/data.py Wed Feb 10 01:25:48 2010 +0100
2.2 +++ b/micropython/data.py Fri Feb 12 01:34:28 2010 +0100
2.3 @@ -125,10 +125,10 @@
2.4
2.5 self.attributes_used = [{}] # stack of usage
2.6 self.attribute_shelves = [] # stack of unmerged definitions
2.7 + self.abandon_attributes = 0 # used when a block will never contribute
2.8 + self.abandoned_shelves = []
2.9 self.attribute_users = [{}] # stack of assignments
2.10 - self.abandon_attributes = 0 # used when a block will never contribute
2.11 - self.attributes_abandoned = [{}]
2.12 - self.abandoned_shelves = []
2.13 + self.user_shelves = []
2.14 self.all_attributes_used = []
2.15
2.16 # Attribute/name definition and access.
2.17 @@ -310,7 +310,7 @@
2.18 def _use_attribute(self, name, attrname):
2.19
2.20 """
2.21 - Indicate the use on the given 'name' in this namespace of an attribute
2.22 + Indicate the use of the given 'name' in this namespace of an attribute
2.23 with the given 'attrname'.
2.24 """
2.25
2.26 @@ -325,6 +325,13 @@
2.27 defs[name] = set()
2.28
2.29 defs[name].add(attrname)
2.30 +
2.31 + # Add the usage to all current users.
2.32 +
2.33 + if users.has_key(name):
2.34 + for user in users[name]:
2.35 + user._attrnames[name].add(attrname)
2.36 +
2.37 return defs[name]
2.38
2.39 def _define_attribute_user(self, node):
2.40 @@ -342,21 +349,20 @@
2.41 "Define 'node' as the user of attributes for the given 'name'."
2.42
2.43 defs = self.attributes_used[-1]
2.44 - abandoned_defs = self.attributes_abandoned[-1]
2.45 users = self.attribute_users[-1]
2.46
2.47 - users[name] = node
2.48 + users[name] = set([node])
2.49 defs[name] = set()
2.50 - abandoned_defs[name] = set()
2.51
2.52 # Record the attribute combinations for the name.
2.53
2.54 if not hasattr(node, "_attrnames"):
2.55 node._attrnames = {}
2.56 - node._attrnames_abandoned = {}
2.57
2.58 - node._attrnames[name] = defs[name]
2.59 - node._attrnames_abandoned[name] = abandoned_defs[name]
2.60 + # Copy the current usage for the user since this may eventually become
2.61 + # independent from the current usage.
2.62 +
2.63 + node._attrnames[name] = set(defs[name])
2.64
2.65 # Remember all attribute combinations.
2.66
2.67 @@ -365,12 +371,16 @@
2.68 def _new_branchpoint(self):
2.69 self.attribute_shelves.append([])
2.70 self.abandoned_shelves.append([])
2.71 + self.user_shelves.append([])
2.72
2.73 def _new_branch(self):
2.74 d = {}
2.75 for name, attrnames in self.attributes_used[-1].items():
2.76 d[name] = set(attrnames)
2.77 self.attributes_used.append(d)
2.78 +
2.79 + # The users apply also to the new branch.
2.80 +
2.81 self.attribute_users.append({})
2.82
2.83 def _abandon_branch(self):
2.84 @@ -393,9 +403,13 @@
2.85 collector.append(self.attributes_used.pop())
2.86
2.87 # Forget about any nodes which defined names employing attributes in
2.88 - # this branch.
2.89 + # this branch if the branch is abandoned.
2.90 +
2.91 + users = self.attribute_users.pop()
2.92
2.93 - self.attribute_users.pop()
2.94 + if not self.abandon_attributes:
2.95 + self.user_shelves[-1].append(users)
2.96 +
2.97 self.abandon_attributes = 0
2.98
2.99 def _merge_branches(self):
2.100 @@ -414,7 +428,6 @@
2.101 # branches. The abandoned dictionary collects abandoned usage.
2.102
2.103 active = self.attributes_used[-1]
2.104 - abandoned = self.attributes_abandoned[-1]
2.105
2.106 # Take each alternative branch, currently shelved, and find the
2.107 # intersection of their contributions for each name.
2.108 @@ -441,16 +454,13 @@
2.109 else:
2.110 active[name] = attrnames
2.111
2.112 - # Where abandoned branches exist, record their contributions for the
2.113 - # attribute users only.
2.114 + # Combine the attribute users.
2.115 +
2.116 + users = self.attribute_users[-1]
2.117
2.118 - if abandoned_defs:
2.119 - for defs in abandoned_defs:
2.120 - for name, attrnames in defs.items():
2.121 - if abandoned.has_key(name):
2.122 - abandoned[name].add(tuple(attrnames))
2.123 - else:
2.124 - abandoned[name] = attrnames
2.125 + for shelved_users in self.user_shelves.pop():
2.126 + for name, nodes in shelved_users.items():
2.127 + users[name].update(nodes)
2.128
2.129 # Where each shelved set of definitions is a superset of the eventual
2.130 # definitions for a name, record these specialised sets of usage.
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/tests/abandoned_attribute_usage_multiple_candidates.py Fri Feb 12 01:34:28 2010 +0100
3.3 @@ -0,0 +1,32 @@
3.4 +#!/usr/bin/env python
3.5 +
3.6 +"""
3.7 +This test attempts to cause the recording of the usage of 'C' in the function
3.8 +'f', alongside the expectation that 'D' might be used instead. A guard
3.9 +stipulating constraints for all of 'f' cannot therefore be generated. Meanwhile,
3.10 +the method 'E.h' should be eliminated.
3.11 +"""
3.12 +
3.13 +class C:
3.14 + def f(self):
3.15 + return 1
3.16 +
3.17 +class D:
3.18 + def g(self):
3.19 + return 2
3.20 +
3.21 +class E:
3.22 + def h(self): # unused
3.23 + return 3
3.24 +
3.25 +def f(c):
3.26 + if 1:
3.27 + return c.f()
3.28 + return c.g()
3.29 +
3.30 +c = C()
3.31 +d = D()
3.32 +e = E()
3.33 +result1_1 = f(c)
3.34 +
3.35 +# vim: tabstop=4 expandtab shiftwidth=4