# HG changeset patch # User paulb@jeremy # Date 1161392185 -7200 # Node ID 0f582479c9eaac8f8213ea1c85aa09f308f7cd82 # Parent 4039d2d409513c28ded391f6ebea092243a88fd5 Changed instantiation to use one instance per class, adding equality testing to enforce this. Fixed return value propagation from certain kinds of blocks. diff -r 4039d2d40951 -r 0f582479c9ea annotate.py --- a/annotate.py Sat Oct 21 02:54:39 2006 +0200 +++ b/annotate.py Sat Oct 21 02:56:25 2006 +0200 @@ -340,6 +340,7 @@ self.namespace = Namespace() self.namespace.merge_namespace(body_namespace) self.namespace.merge_namespace(else_namespace) + return conditional def visitReturn(self, return_): @@ -454,9 +455,18 @@ node.instances = {} if not node.instances.has_key((reason, target, type)): - instance = Instance() - instance.namespace = Namespace() - instance.namespace.store("__class__", [Attribute(None, type)]) + + # Insist on a single instance per type. + # NOTE: Strategy-dependent instantiation. + + if len(type.instances) == 0: + instance = Instance() + instance.namespace = Namespace() + instance.namespace.store("__class__", [Attribute(None, type)]) + type.instances.append(instance) + else: + instance = type.instances[0] + node.instances[(reason, target, type)] = instance return node.instances[(reason, target, type)] @@ -498,12 +508,15 @@ self.process_node(target, namespace) # NOTE: Improve and verify this. + # If the invocation returns a value, acquire the return types. if getattr(target, "returns_value", 0): self.namespace.set_types(self.last_returns) self.annotate(invoke) - if isinstance(invoke, InvokeBlock): + # Otherwise, if it is a normal block, merge the locals. + + elif isinstance(invoke, InvokeBlock): for locals in self.returned_locals: self.namespace.merge_namespace(locals) @@ -795,10 +808,19 @@ return "Attribute(%s, %s)" % (repr(self.context), repr(self.type)) class Self: + + "A node encapsulating object/context information in an argument list." + def __init__(self, attribute): self.types = [attribute] def combine(target, additions): + + """ + Merge into the 'target' sequence the given 'additions', preventing duplicate + items. + """ + for addition in additions: if addition not in target: target.append(addition) diff -r 4039d2d40951 -r 0f582479c9ea simplified.py --- a/simplified.py Sat Oct 21 02:54:39 2006 +0200 +++ b/simplified.py Sat Oct 21 02:56:25 2006 +0200 @@ -335,13 +335,12 @@ def full_name(self): return self._full_name -class Module(Node, WithName): +class Module(Node): "A Python module." - def __init__(self, *args, **kw): - Node.__init__(self, *args, **kw) - WithName.__init__(self) + def full_name(self): + return self.name class Subprogram(Node, WithName): @@ -362,17 +361,27 @@ def __init__(self, *args, **kw): Structure.__init__(self, *args, **kw) WithName.__init__(self) + self.instances = [] class Instance(Structure): "An instance." def full_name(self): + # NOTE: Wrap the result in a call to name(self, ...) where multiple + # NOTE: instances per class can occur. return self.namespace.load("__class__")[0].type.full_name() def __repr__(self): return "Instance of type '%s'" % self.full_name() + def __eq__(self, other): + # NOTE: Assuming that multiple instances of the same class are equal. + return self.full_name() == other.full_name() + + def __hash__(self): + return id(self) + class Constant(Instance): "A constant initialised with a type name for future processing."