# HG changeset patch # User Paul Boddie # Date 1258935726 -3600 # Node ID 54a2867eb4651d381769dee67263cfcb9bac2be4 # Parent 4435e910a9d35b290fc2170ba4654fa9ffbc2479 Added attribute usage registration for branches where more specific attribute usage occurs, but where such usage cannot be merged back into the active usage definition for a given name. This should ensure that attributes are not forgotten because their usage was not merged and carried forward. Added more specific tests. diff -r 4435e910a9d3 -r 54a2867eb465 micropython/data.py --- a/micropython/data.py Sun Nov 22 23:53:30 2009 +0100 +++ b/micropython/data.py Mon Nov 23 01:22:06 2009 +0100 @@ -374,20 +374,33 @@ def _merge_branches(self): active = self.attributes_used[-1] + # Take each alternative branch, currently shelved, and find the + # intersection of their contributions for each name. + shelved_defs = self.attribute_shelves.pop() - defs = shelved_defs[0] + defs = dict(shelved_defs[0]) for next_defs in shelved_defs[1:]: for name, attrnames in next_defs.items(): if defs.has_key(name): defs[name] = defs[name].intersection(attrnames) + # Intersect the contributions with the previous state for each name. + for name, attrnames in defs.items(): if active.has_key(name): active[name].intersection_update(attrnames) else: active[name] = attrnames + # Where each shelved set of definitions is a superset of the eventual + # definitions for a name, record these specialised sets of usage. + + for defs in shelved_defs: + for name, attrnames in defs.items(): + if attrnames.issuperset(active[name]): + self.all_attributes_used.append(attrnames) + # Program data structures. There are two separate kinds of structures: those # with context, which are the values manipulated by programs, and those without # context, which are typically constant things which are stored alongside the diff -r 4435e910a9d3 -r 54a2867eb465 tests/attribute_access_type_restriction.py --- a/tests/attribute_access_type_restriction.py Sun Nov 22 23:53:30 2009 +0100 +++ b/tests/attribute_access_type_restriction.py Mon Nov 23 01:22:06 2009 +0100 @@ -18,15 +18,6 @@ def h(self): return 5 -def test_conditional(obj): - # obj: C, D, E (f) - if obj.f(): # C, D, E (f) - obj.g() # D (f, g) - # else: - # ... # obj: C, D, E (f) - # # (f, g) ^ (f) - return 2 - def test_new(obj, obj2): # obj: C, D, E (f) # obj2: @@ -62,7 +53,6 @@ c = C() d = D() e = E() -result1_2 = test_conditional(d) result2_2 = test_new(c, d) result1_4 = test_neither(c, d) result1_5 = test_new_conditional(e, d) diff -r 4435e910a9d3 -r 54a2867eb465 tests/attribute_access_type_restriction_conditional.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/attribute_access_type_restriction_conditional.py Mon Nov 23 01:22:06 2009 +0100 @@ -0,0 +1,35 @@ +#!/usr/bin/env python + +class C: + def f(self): + return 1 + +class D: + def f(self): + return 2 + + def g(self): + return 3 + +class E: + def f(self): + return 4 + + def h(self): + return 5 + +def test_conditional(obj): + # obj: C, D, E (f) + if obj.f(): # C, D, E (f) + obj.g() # D (f, g) + # else: + # ... # obj: C, D, E (f) + # # (f, g) ^ (f) + return 2 + +c = C() +d = D() +e = E() +result1_2 = test_conditional(d) + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 4435e910a9d3 -r 54a2867eb465 tests/attribute_access_type_restriction_conditional_choice.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/attribute_access_type_restriction_conditional_choice.py Mon Nov 23 01:22:06 2009 +0100 @@ -0,0 +1,35 @@ +#!/usr/bin/env python + +class C: + def f(self): + return 1 + +class D: + def f(self): + return 2 + + def g(self): + return 3 + +class E: + def f(self): + return 4 + + def h(self): + return 5 + +def test_conditional(obj): + # obj: C, D, E (f) + if obj.f(): # C, D, E (f) + obj.g() # D (f, g) + else: + obj.h() # E (f, h) + # # (f, g) ^ (f, h) + return 2 + +c = C() +d = D() +e = E() +result1_2 = test_conditional(d) + +# vim: tabstop=4 expandtab shiftwidth=4