# HG changeset patch # User Paul Boddie # Date 1266194117 -3600 # Node ID 505512c40ea55c716f9ace2a66c07f86f300d093 # Parent 9f1f0b79c182ff1dc67b57218d5d718db22e319b Fixed usage merging where names are defined below the current level in the control-flow hierarchy. Fixed alternative usage retrieval when generating guards, adding a test for conflicting types deduced from attribute usage. diff -r 9f1f0b79c182 -r 505512c40ea5 micropython/data.py --- a/micropython/data.py Sun Feb 14 23:49:17 2010 +0100 +++ b/micropython/data.py Mon Feb 15 01:35:17 2010 +0100 @@ -483,6 +483,10 @@ self.speculative_shelves[-1].append(speculative) + # NOTE: Could record contributing usage as speculative usage. + + #self.speculative_shelves[-1].append(usage) + # Forget about any nodes which defined names employing attributes in # this branch if the branch is abandoned. @@ -564,7 +568,13 @@ for shelved_users in self.user_shelves.pop(): for name, nodes in shelved_users.items(): - users[name].update(nodes) + + # Handle cases where the name is not known at this level. + + if users.has_key(name): + users[name].update(nodes) + else: + users[name] = nodes # Where each shelved set of definitions is a superset of the eventual # definitions for a name, record these specialised sets of usage. diff -r 9f1f0b79c182 -r 505512c40ea5 micropython/trans.py --- a/micropython/trans.py Sun Feb 14 23:49:17 2010 +0100 +++ b/micropython/trans.py Mon Feb 15 01:35:17 2010 +0100 @@ -319,7 +319,7 @@ if node._alternative_attrnames.has_key(name): all_names_used = set() - all_names_used.update(node._alternative_attrnames) + all_names_used.update(node._alternative_attrnames[name]) all_names_used.add(tuple(names_used)) else: all_names_used = [names_used] @@ -327,14 +327,31 @@ # Get the names of all object types supporting these names. targets = set() + common_targets = None + for names_used in all_names_used: - targets.update(self.objtable.all_possible_objects_plus_status(names_used)) + found_targets = self.objtable.all_possible_objects_plus_status(names_used) + found_target_names = [target_name for (target_name, is_static) in found_targets] + targets.update(found_targets) + + if common_targets is None: + common_targets = set(found_target_names) + else: + common_targets.intersection_update(found_target_names) + + # Report cases where no common targets can be found. + + if not common_targets: + raise TranslateError(self.module.full_name(), node, "No common types found for expected attribute usage.") + + # NOTE: Need to merge targets using the same type but suggesting + # NOTE: different kinds of attributes. # Where only one object type is suggested, produce a guard. # NOTE: This only supports classes as types, not modules. if len(targets) == 1: - target_name, is_static = targets[0] + target_name, is_static = list(targets)[0] # Access the object table to get the attribute. # NOTE: This depends on the special entry in the table diff -r 9f1f0b79c182 -r 505512c40ea5 tests/attribute_access_type_restriction_multiple_candidates.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/attribute_access_type_restriction_multiple_candidates.py Mon Feb 15 01:35:17 2010 +0100 @@ -0,0 +1,34 @@ +#!/usr/bin/env python + +""" +This test attempts to cause the recording of the usage of 'C' in the function +'f', alongside the expectation that 'D' might be used instead. A guard +stipulating constraints for all of 'f' cannot therefore be generated. Meanwhile, +the method 'E.h' should be eliminated. +""" + +class C: + def f(self): + return 1 + +class D: + def g(self): + return 2 + +class E: + def h(self): # unused + return 3 + +def f(c): + if 1: + if 1: + x = c.f() + return x + return c.g() + +c = C() +d = D() +e = E() +result1_1 = f(c) + +# vim: tabstop=4 expandtab shiftwidth=4