1.1 --- a/micropython/data.py Sun Feb 07 03:02:39 2010 +0100
1.2 +++ b/micropython/data.py Mon Feb 08 01:05:23 2010 +0100
1.3 @@ -3,7 +3,7 @@
1.4 """
1.5 Data classes.
1.6
1.7 -Copyright (C) 2007, 2008, 2009 Paul Boddie <paul@boddie.org.uk>
1.8 +Copyright (C) 2007, 2008, 2009, 2010 Paul Boddie <paul@boddie.org.uk>
1.9
1.10 This program is free software; you can redistribute it and/or modify it under
1.11 the terms of the GNU General Public License as published by the Free Software
1.12 @@ -126,6 +126,7 @@
1.13 self.attributes_used = [{}] # stack of usage
1.14 self.attribute_shelves = [] # stack of unmerged definitions
1.15 self.attribute_users = [{}] # stack of assignments
1.16 + self.abandon_attributes = 0 # used when a block will never contribute
1.17 self.all_attributes_used = []
1.18
1.19 # Attribute/name definition and access.
1.20 @@ -353,10 +354,6 @@
1.21
1.22 self.all_attributes_used.append(defs[name])
1.23
1.24 - def _reset_all_attributes(self):
1.25 - self.attributes_used[-1] = {}
1.26 - self.attribute_users[-1] = {}
1.27 -
1.28 def _new_branchpoint(self):
1.29 self.attribute_shelves.append([])
1.30
1.31 @@ -367,9 +364,14 @@
1.32 self.attributes_used.append(d)
1.33 self.attribute_users.append({})
1.34
1.35 + def _abandon_branch(self):
1.36 + self.abandon_attributes = 1
1.37 +
1.38 def _shelve_branch(self):
1.39 - self.attribute_shelves[-1].append(self.attributes_used.pop())
1.40 + if not self.abandon_attributes:
1.41 + self.attribute_shelves[-1].append(self.attributes_used.pop())
1.42 self.attribute_users.pop()
1.43 + self.abandon_attributes = 0
1.44
1.45 def _merge_branches(self):
1.46 active = self.attributes_used[-1]
1.47 @@ -378,6 +380,13 @@
1.48 # intersection of their contributions for each name.
1.49
1.50 shelved_defs = self.attribute_shelves.pop()
1.51 +
1.52 + # Where branches contribute attribute usage observations, process these
1.53 + # as described above. Otherwise, preserve the previous observations.
1.54 +
1.55 + if not shelved_defs:
1.56 + return
1.57 +
1.58 defs = dict(shelved_defs[0])
1.59
1.60 for next_defs in shelved_defs[1:]:
2.1 --- a/micropython/inspect.py Sun Feb 07 03:02:39 2010 +0100
2.2 +++ b/micropython/inspect.py Mon Feb 08 01:05:23 2010 +0100
2.3 @@ -3,7 +3,7 @@
2.4 """
2.5 Inspect source files, obtaining details of classes and attributes.
2.6
2.7 -Copyright (C) 2007, 2008, 2009 Paul Boddie <paul@boddie.org.uk>
2.8 +Copyright (C) 2007, 2008, 2009, 2010 Paul Boddie <paul@boddie.org.uk>
2.9
2.10 This program is free software; you can redistribute it and/or modify it under
2.11 the terms of the GNU General Public License as published by the Free Software
2.12 @@ -332,6 +332,9 @@
2.13 def new_branch(self):
2.14 self.get_namespace()._new_branch()
2.15
2.16 + def abandon_branch(self):
2.17 + self.get_namespace()._abandon_branch()
2.18 +
2.19 def shelve_branch(self):
2.20 self.get_namespace()._shelve_branch()
2.21
2.22 @@ -347,9 +350,6 @@
2.23
2.24 self.get_namespace()._define_attribute_user(node)
2.25
2.26 - def reset_all_attributes(self):
2.27 - self.get_namespace()._reset_all_attributes()
2.28 -
2.29 def use_attribute(self, name, attrname):
2.30 return self.get_namespace()._use_attribute(name, attrname)
2.31
2.32 @@ -374,6 +374,10 @@
2.33 self.dispatch(n)
2.34 return None
2.35
2.36 + def NOP_ABANDON(self, node):
2.37 + self.abandon_branch()
2.38 + self.NOP(node)
2.39 +
2.40 def OP(self, node):
2.41 for n in node.getChildNodes():
2.42 self.dispatch(n)
2.43 @@ -558,8 +562,7 @@
2.44
2.45 visitBitxor = _visitBinary
2.46
2.47 - def visitBreak(self, node):
2.48 - self.reset_all_attributes()
2.49 + visitBreak = NOP_ABANDON
2.50
2.51 visitCallFunc = OP
2.52
2.53 @@ -639,8 +642,7 @@
2.54 self.use_name(self.importer.get_constant_type_name(node.value))
2.55 return self.importer.make_constant(node.value)
2.56
2.57 - def visitContinue(self, node):
2.58 - self.reset_all_attributes()
2.59 + visitContinue = NOP_ABANDON
2.60
2.61 visitDecorators = NOP
2.62
2.63 @@ -895,9 +897,9 @@
2.64
2.65 visitPrintnl = NOP
2.66
2.67 - visitRaise = NOP
2.68 + visitRaise = NOP_ABANDON
2.69
2.70 - visitReturn = NOP
2.71 + visitReturn = NOP_ABANDON
2.72
2.73 visitRightShift = _visitBinary
2.74
3.1 --- a/micropython/trans.py Sun Feb 07 03:02:39 2010 +0100
3.2 +++ b/micropython/trans.py Mon Feb 08 01:05:23 2010 +0100
3.3 @@ -3,7 +3,7 @@
3.4 """
3.5 Translate the AST of a Python program into a more interpretable representation.
3.6
3.7 -Copyright (C) 2007, 2008, 2009 Paul Boddie <paul@boddie.org.uk>
3.8 +Copyright (C) 2007, 2008, 2009, 2010 Paul Boddie <paul@boddie.org.uk>
3.9
3.10 This program is free software; you can redistribute it and/or modify it under
3.11 the terms of the GNU General Public License as published by the Free Software
3.12 @@ -330,7 +330,7 @@
3.13 # NOTE: for class equivalence tests.
3.14
3.15 try:
3.16 - attr = self.objtable.access(target_name, target_name)
3.17 + obj = self.objtable.access(target_name, target_name)
3.18
3.19 # Where no attribute entry exists, the target could be a module.
3.20
3.21 @@ -338,9 +338,17 @@
3.22 print "Possible guard for", target_name, "not enforceable."
3.23 continue
3.24
3.25 + # NOTE: Could test the correctness of the guard where the nature
3.26 + # NOTE: of the name is known.
3.27 + # NOTE: The known value would be retrieved from the unit's
3.28 + # NOTE: locals and tested as being a class or an instance of a
3.29 + # NOTE: particular class.
3.30 +
3.31 + # Generate the guard by loading a reference to the class.
3.32 +
3.33 after_test_block = self.new_block()
3.34
3.35 - self.new_op(LoadClass(attr))
3.36 + self.new_op(LoadClass(obj))
3.37 temp_target = self.optimiser.optimise_temp_storage()
3.38
3.39 # For only static attributes, classes are acceptable.
4.1 --- a/tests/attribute_access_type_restriction.py Sun Feb 07 03:02:39 2010 +0100
4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
4.3 @@ -1,60 +0,0 @@
4.4 -#!/usr/bin/env python
4.5 -
4.6 -class C:
4.7 - def f(self):
4.8 - return 1
4.9 -
4.10 -class D:
4.11 - def f(self):
4.12 - return 2
4.13 -
4.14 - def g(self):
4.15 - return 3
4.16 -
4.17 -class E:
4.18 - def f(self):
4.19 - return 4
4.20 -
4.21 - def h(self):
4.22 - return 5
4.23 -
4.24 -def test_new(obj, obj2):
4.25 - # obj: C, D, E (f)
4.26 - # obj2:
4.27 - if obj.f(): # C, D, E (f)
4.28 - obj = obj2 # obj: D (g)
4.29 - obj.g() # D (g)
4.30 - # else:
4.31 - # ... # obj: C, D, E (f)
4.32 - # # (g) ^ (f)
4.33 - return obj.f() # C, D, E (f)
4.34 -
4.35 -def test_neither(obj, obj2):
4.36 - # obj:
4.37 - # obj2:
4.38 - if 0:
4.39 - obj.g() # D (g)
4.40 - else:
4.41 - obj.f() # C, D, E (f)
4.42 - # # (g) ^ (f)
4.43 - return 4
4.44 -
4.45 -def test_new_conditional(obj, obj2):
4.46 - # obj:
4.47 - # obj2:
4.48 - if obj.f(): # C, D, E (f)
4.49 - obj = obj2 # obj: D (g)
4.50 - obj.g() # D (g)
4.51 - else:
4.52 - obj.h() # E (f, h)
4.53 - # # (g) ^ (f, h)
4.54 - return 5
4.55 -
4.56 -c = C()
4.57 -d = D()
4.58 -e = E()
4.59 -result2_2 = test_new(c, d)
4.60 -result1_4 = test_neither(c, d)
4.61 -result1_5 = test_new_conditional(e, d)
4.62 -
4.63 -# vim: tabstop=4 expandtab shiftwidth=4
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/tests/attribute_access_type_restriction_neither.py Mon Feb 08 01:05:23 2010 +0100
5.3 @@ -0,0 +1,35 @@
5.4 +#!/usr/bin/env python
5.5 +
5.6 +class C:
5.7 + def f(self):
5.8 + return 1
5.9 +
5.10 +class D:
5.11 + def f(self):
5.12 + return 2
5.13 +
5.14 + def g(self):
5.15 + return 3
5.16 +
5.17 +class E: # unused
5.18 + def f(self):
5.19 + return 4
5.20 +
5.21 + def h(self):
5.22 + return 5
5.23 +
5.24 +def test_neither(obj, obj2):
5.25 + # obj:
5.26 + # obj2:
5.27 + if 0:
5.28 + obj.g() # D (g)
5.29 + else:
5.30 + obj.f() # C, D, E (f)
5.31 + # # (g) ^ (f)
5.32 + return 4
5.33 +
5.34 +c = C()
5.35 +d = D()
5.36 +result1_4 = test_neither(c, d)
5.37 +
5.38 +# vim: tabstop=4 expandtab shiftwidth=4
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/tests/attribute_access_type_restriction_new.py Mon Feb 08 01:05:23 2010 +0100
6.3 @@ -0,0 +1,37 @@
6.4 +#!/usr/bin/env python
6.5 +
6.6 +class C:
6.7 + def f(self):
6.8 + return 1
6.9 +
6.10 +class D:
6.11 + def f(self):
6.12 + return 2
6.13 +
6.14 + def g(self):
6.15 + return 3
6.16 +
6.17 +class E:
6.18 + def f(self):
6.19 + return 4
6.20 +
6.21 + def h(self): # unused
6.22 + return 5
6.23 +
6.24 +def test_new(obj, obj2):
6.25 + # obj: C, D, E (f)
6.26 + # obj2:
6.27 + if obj.f(): # C, D, E (f)
6.28 + obj = obj2 # obj: D (g)
6.29 + obj.g() # D (g)
6.30 + # else:
6.31 + # ... # obj: C, D, E (f)
6.32 + # # (g) ^ (f)
6.33 + return obj.f() # C, D, E (f)
6.34 +
6.35 +c = C()
6.36 +d = D()
6.37 +e = E()
6.38 +result2_2 = test_new(c, d)
6.39 +
6.40 +# vim: tabstop=4 expandtab shiftwidth=4
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/tests/attribute_access_type_restriction_new_conditional.py Mon Feb 08 01:05:23 2010 +0100
7.3 @@ -0,0 +1,37 @@
7.4 +#!/usr/bin/env python
7.5 +
7.6 +class C:
7.7 + def f(self):
7.8 + return 1
7.9 +
7.10 +class D:
7.11 + def f(self):
7.12 + return 2
7.13 +
7.14 + def g(self):
7.15 + return 3
7.16 +
7.17 +class E:
7.18 + def f(self):
7.19 + return 4
7.20 +
7.21 + def h(self):
7.22 + return 5
7.23 +
7.24 +def test_new_conditional(obj, obj2):
7.25 + # obj:
7.26 + # obj2:
7.27 + if obj.f(): # C, D, E (f)
7.28 + obj = obj2 # obj: D (g)
7.29 + obj.g() # D (g)
7.30 + else:
7.31 + obj.h() # E (f, h)
7.32 + # # (g) ^ (f, h)
7.33 + return 5
7.34 +
7.35 +c = C()
7.36 +d = D()
7.37 +e = E()
7.38 +result1_5 = test_new_conditional(e, d)
7.39 +
7.40 +# vim: tabstop=4 expandtab shiftwidth=4