# HG changeset patch # User paulb@jeremy # Date 1162247558 -3600 # Node ID 01b51f1f7450422e4a1c7f860003be56bf4efb7d # Parent c9d690ff694b907943f6b42b8188d25bc969ec9a Fixed namespace replacement for module-level/global namespaces, ensuring that Conditional nodes replace the global namespace correctly. Added a non_types annotation for LoadAttr nodes. Reset the raised exceptions for else clauses in try...except...else statements. When merging namespaces, the temporary variables dictionary is copied, not acquired. diff -r c9d690ff694b -r 01b51f1f7450 annotate.py --- a/annotate.py Sun Oct 29 22:47:42 2006 +0100 +++ b/annotate.py Mon Oct 30 23:32:38 2006 +0100 @@ -124,6 +124,7 @@ self.current_subprograms = [] self.current_namespaces = [] self.namespace = None + self.module = module # Give constants their own namespace. @@ -153,11 +154,11 @@ # Record the current subprogram and namespace. self.current_subprograms.append(node) - self.current_namespaces.append(self.namespace) # Determine the namespace. if locals is not None: + self.current_namespaces.append(self.namespace) self.namespace = locals else: self.namespace = self.global_namespace @@ -190,7 +191,8 @@ # Restore the previous subprogram and namespace. - self.namespace = self.current_namespaces.pop() + if locals is not None: + self.namespace = self.current_namespaces.pop() self.current_subprograms.pop() return result @@ -238,18 +240,25 @@ conditional.test = self.dispatch(conditional.test) saved_namespace = self.namespace + is_global = self.namespace is self.global_namespace self.namespace = Namespace() + if is_global: + self.module.namespace = self.global_namespace = self.namespace self.namespace.merge_namespace(saved_namespace) conditional.body = self.dispatches(conditional.body) body_namespace = self.namespace self.namespace = Namespace() + if is_global: + self.module.namespace = self.global_namespace = self.namespace self.namespace.merge_namespace(saved_namespace) conditional.else_ = self.dispatches(conditional.else_) else_namespace = self.namespace self.namespace = Namespace() + if is_global: + self.module.namespace = self.global_namespace = self.namespace self.namespace.merge_namespace(body_namespace) self.namespace.merge_namespace(else_namespace) @@ -269,7 +278,14 @@ def visitTry(self, try_): try_.body = self.dispatches(try_.body) try_.handler = self.dispatches(try_.handler) + raises = self.namespace.raises + + # Empty the raised exceptions for the else clause. + + self.namespace.raises = [] try_.else_ = self.dispatches(try_.else_) + self.namespace.raises = raises + try_.finally_ = self.dispatches(try_.finally_) return try_ @@ -278,12 +294,14 @@ def visitLoadAttr(self, loadattr): loadattr.expr = self.dispatch(loadattr.expr) types = [] + non_types = [] accesses = {} - non_accesses = {} for attr in self.namespace.types: attributes = get_attributes(attr.type, loadattr.name) if not attributes: print "No attributes for", loadattr.name, "in", attr.type + if not attr.type in non_types: + non_types.append(attr) for attribute, accessor in attributes: if attribute is not None: types.append(attribute) @@ -293,13 +311,11 @@ accesses[attr.type].append((attribute, accessor)) else: print "Empty attribute", loadattr.name, "via accessor", accessor - if not non_accesses.has_key(attr.type): - non_accesses[attr.type] = [] - if not (attribute, accessor) in non_accesses[attr.type]: - non_accesses[attr.type].append((attribute, accessor)) + if not attr.type in non_types: + non_types.append(attr) self.namespace.set_types(types) + loadattr.non_types = non_types loadattr.accesses = accesses - loadattr.non_accesses = non_accesses self.annotate(loadattr) return loadattr @@ -831,7 +847,8 @@ self.merge_items(namespace.names.items()) combine(self.returns, namespace.returns) combine(self.raises, namespace.raises) - self.temp = namespace.temp + self.temp = {} + self.temp.update(namespace.temp) def merge_items(self, items): for name, types in items: