# HG changeset patch # User paulb@localhost.localdomain # Date 1182467472 -7200 # Node ID d4e3068a5c19c4bffcdcb7cc9fa64a68d91c4a39 # Parent 963f28594cbf47826a677ea0474aa29353bf8030 Moved Namespace from annotate to simplified.utils. Made Subprogram a Structure in order to support namespaces and operations dependent on namespaces (such as __bool__). Prevented context alteration on attributes acquired through modules (as globals). Added a get_instances method for classes. Attempted to improve instance fixing - still needs much work. diff -r 963f28594cbf -r d4e3068a5c19 simplify/annotate.py --- a/simplify/annotate.py Fri Jun 22 01:06:19 2007 +0200 +++ b/simplify/annotate.py Fri Jun 22 01:11:12 2007 +0200 @@ -1379,152 +1379,6 @@ # Namespace-related abstractions. -class Namespace: - - """ - A local namespace which may either relate to a genuine set of function - locals or the initialisation of a structure or module. - """ - - def __init__(self): - - """ - Initialise the namespace with a mapping of local names to possible - types, a list of return values and of possible returned local - namespaces. The namespace also tracks the "current" types and a mapping - of temporary value names to types. - """ - - self.names = {} - self.returns = set() - self.return_locals = set() - self.raises = set() - self.temp = {} - self.types = set() - - def set_types(self, types): - - "Set the current collection of 'types'." - - self.types = types.copy() - - def add(self, name, types): - - "Add to the entry with the given 'name' the specified 'types'." - - if self.names.has_key(name): - self.names[name].update(types) - else: - self.store(name, types) - - def store(self, name, types): - - "Store in (or associate with) the given 'name' the specified 'types'." - - self.names[name] = types.copy() - - __setitem__ = store - - def load(self, name): - - "Load the types associated with the given 'name'." - - return self.names[name] - - __getitem__ = load - - def has_key(self, name): - return self.names.has_key(name) - - def keys(self): - return self.names.keys() - - def values(self): - return self.names.values() - - def items(self): - return self.names.items() - - def get(self, name, default=None): - return self.names.get(name, default) - - def revoke(self, name, type): - - "Revoke from the entry for the given 'name' the specified 'type'." - - new_types = self.names[name].copy() - new_types.remove(type) - self.names[name] = new_types - - def revoke_exception_type(self, type): - - "Revoke the given 'type' from the collection of exception types." - - if type in self.raises: - self.raises.remove(type) - - def revoke_temp_type(self, index, type): - - "Revoke from the temporary variable 'index' the given 'type'." - - new_types = self.temp[index][-1].copy() - new_types.remove(type) - self.temp[index][-1] = new_types - - def merge_namespace(self, namespace, everything=1): - - """ - Merge items from the given 'namespace' with this namespace. When the - optional 'everything' parameter is set to a false value (unlike the - default), return values and locals snapshots will not be copied to this - namespace. - """ - - self.merge_items(namespace.names.items()) - self.raises.update(namespace.raises) - if everything: - self.returns.update(namespace.returns) - self.return_locals.update(namespace.return_locals) - for name, values in namespace.temp.items(): - if values: - if not self.temp.has_key(name) or not self.temp[name]: - self.temp[name] = [set()] - self.temp[name][-1].update(values[-1]) - - def merge_items(self, items): - - "Merge the given 'items' with this namespace." - - for name, types in items: - self.merge(name, types) - - def merge(self, name, types): - - "Merge the entry for the given 'name' and 'types' with this namespace." - - if not self.names.has_key(name): - self.names[name] = types.copy() - else: - existing = self.names[name] - existing.update(types) - - def snapshot(self): - - "Make a snapshot of the locals and remember them." - - namespace = Namespace() - namespace.merge_namespace(self) - self.return_locals.add(namespace) - - def reset(self): - - "Reset a namespace in preparation for merging with returned locals." - - self.names = {} - - def __repr__(self): - return repr(self.names) + " (temp) " + repr(self.temp) - class Importer: "An import machine, searching for and loading modules." @@ -1745,6 +1599,7 @@ if isinstance(structure, Attribute): structure = structure.type + results = [] for attribute, accessor in find_attributes(structure, name): @@ -1754,9 +1609,18 @@ attribute = accessor.get_attribute_for_instance(attribute, structure) # Produce an attribute with the appropriate context. + # Modules should not affect the context. - if attribute is not None and isinstance(structure, Structure): + if attribute is not None and isinstance(structure, Module): + results.append((attribute, accessor)) + + # Access via classes and instances should set those as the context. + + elif attribute is not None and isinstance(structure, Structure): results.append((Attribute(structure, attribute.type), accessor)) + + # Other accesses are returned unmodified. + else: results.append((attribute, accessor)) diff -r 963f28594cbf -r d4e3068a5c19 simplify/fixinstances.py --- a/simplify/fixinstances.py Fri Jun 22 01:06:19 2007 +0200 +++ b/simplify/fixinstances.py Fri Jun 22 01:11:12 2007 +0200 @@ -74,6 +74,14 @@ self.current_subprograms = [] self.module = module + + # Visit structures and instances. + + for structure in self.module.simplifier.structures: + for instance in structure.get_instances(): + for name, attrs in instance.namespace.items(): + instance.namespace[name] = self._replace(attrs) + self.process_node(self.module) # Then, process all functions and methods. @@ -87,13 +95,6 @@ for specialised in subprogram.active(): self.subprograms.append(self.process_node(specialised)) - # Visit structures and instances. - - for structure in self.module.simplifier.structures: - for instance in structure.instances.values(): - for attrs in instance.namespace.values(): - self._replace(attrs) - def process_node(self, node): """ @@ -134,12 +135,12 @@ for name in ("non_accesses", "non_writes", "raises", "returns", "types"): if hasattr(node, name): attrs = getattr(node, name) - self._replace(attrs) + setattr(node, name, self._replace(attrs)) for name in ("accesses", "writes", "paramtypes"): if hasattr(node, name): d = getattr(node, name) for expr, attrs in d.items(): - self._replace(attrs, name, d, expr) + d[self._get_replacement(expr)] = self._replace(attrs, name) # Visit program nodes. @@ -165,21 +166,23 @@ return node - def _replace(self, items, name=None, container=None, key=None): + def _replace(self, items, name=None): + if name == "accesses": + new_items = [] + else: + new_items = set() + for item in list(items): - items.remove(item) if name == "accesses": attr, accessor = item value = attr.type - items.append((Attribute(self._get_replacement(attr.context), self._get_replacement(value)), self._get_replacement(accessor))) + new_items.append((Attribute(self._get_replacement(attr.context), self._get_replacement(value)), self._get_replacement(accessor))) else: attr = item value = attr.type - items.add(Attribute(self._get_replacement(attr.context), self._get_replacement(value))) + new_items.add(Attribute(self._get_replacement(attr.context), self._get_replacement(value))) - if name == "accesses": - del container[key] - container[self._get_replacement(key)] = items + return new_items def _get_replacement(self, value): if isinstance(value, Instance): diff -r 963f28594cbf -r d4e3068a5c19 simplify/simplified/data.py --- a/simplify/simplified/data.py Fri Jun 22 01:06:19 2007 +0200 +++ b/simplify/simplified/data.py Fri Jun 22 01:11:12 2007 +0200 @@ -49,7 +49,7 @@ "Return all attribute names used by the instances of this class." names = set() - for instance in self.instances.values(): + for instance in self.get_instances(): for name in instance.namespace.keys(): names.add(name) return names @@ -66,7 +66,7 @@ if distinct: instances = set(self.get_distinct_instances().values()) else: - instances = self.instances.values() + instances = self.get_instances() for instance in instances: name = instance.full_name() @@ -129,6 +129,12 @@ def get_instance_name(self, instance): return self._full_name + def get_instances(self): + if self.instance is not None: + return [self.instance] + else: + return [] + # Attribute propagation. def get_attribute_for_instance(self, attribute, instance): @@ -158,6 +164,9 @@ def get_instance_name(self, instance): return name(instance, self._full_name) + def get_instances(self): + return self.instances.values() + # Attribute propagation. def get_attribute_for_instance(self, attribute, instance): diff -r 963f28594cbf -r d4e3068a5c19 simplify/simplified/program.py --- a/simplify/simplified/program.py Fri Jun 22 01:06:19 2007 +0200 +++ b/simplify/simplified/program.py Fri Jun 22 01:11:12 2007 +0200 @@ -23,7 +23,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ -from simplify.simplified.utils import Structure, WithName, name +from simplify.simplified.utils import Structure, WithName, name, Namespace import sys import operator @@ -412,7 +412,7 @@ def full_name(self): return "module %s" % self.name -class Subprogram(Node, WithName): +class Subprogram(Node, WithName, Structure): "A subprogram: functions, methods and loops." @@ -422,5 +422,6 @@ self.raises = set() self.returns = set() self.return_locals = set() + self.namespace = Namespace() # NOTE: Temporary. # vim: tabstop=4 expandtab shiftwidth=4 diff -r 963f28594cbf -r d4e3068a5c19 simplify/simplified/utils.py --- a/simplify/simplified/utils.py Fri Jun 22 01:06:19 2007 +0200 +++ b/simplify/simplified/utils.py Fri Jun 22 01:11:12 2007 +0200 @@ -167,4 +167,152 @@ def __repr__(self): return "%s '%s'" % (self.__class__.__name__, self.full_name()) +# Namespace classes. + +class Namespace: + + """ + A local namespace which may either relate to a genuine set of function + locals or the initialisation of a structure or module. + """ + + def __init__(self): + + """ + Initialise the namespace with a mapping of local names to possible + types, a list of return values and of possible returned local + namespaces. The namespace also tracks the "current" types and a mapping + of temporary value names to types. + """ + + self.names = {} + self.returns = set() + self.return_locals = set() + self.raises = set() + self.temp = {} + self.types = set() + + def set_types(self, types): + + "Set the current collection of 'types'." + + self.types = types.copy() + + def add(self, name, types): + + "Add to the entry with the given 'name' the specified 'types'." + + if self.names.has_key(name): + self.names[name].update(types) + else: + self.store(name, types) + + def store(self, name, types): + + "Store in (or associate with) the given 'name' the specified 'types'." + + self.names[name] = types.copy() + + __setitem__ = store + + def load(self, name): + + "Load the types associated with the given 'name'." + + return self.names[name] + + __getitem__ = load + + def has_key(self, name): + return self.names.has_key(name) + + def keys(self): + return self.names.keys() + + def values(self): + return self.names.values() + + def items(self): + return self.names.items() + + def get(self, name, default=None): + return self.names.get(name, default) + + def revoke(self, name, type): + + "Revoke from the entry for the given 'name' the specified 'type'." + + new_types = self.names[name].copy() + new_types.remove(type) + self.names[name] = new_types + + def revoke_exception_type(self, type): + + "Revoke the given 'type' from the collection of exception types." + + if type in self.raises: + self.raises.remove(type) + + def revoke_temp_type(self, index, type): + + "Revoke from the temporary variable 'index' the given 'type'." + + new_types = self.temp[index][-1].copy() + new_types.remove(type) + self.temp[index][-1] = new_types + + def merge_namespace(self, namespace, everything=1): + + """ + Merge items from the given 'namespace' with this namespace. When the + optional 'everything' parameter is set to a false value (unlike the + default), return values and locals snapshots will not be copied to this + namespace. + """ + + self.merge_items(namespace.names.items()) + self.raises.update(namespace.raises) + if everything: + self.returns.update(namespace.returns) + self.return_locals.update(namespace.return_locals) + for name, values in namespace.temp.items(): + if values: + if not self.temp.has_key(name) or not self.temp[name]: + self.temp[name] = [set()] + self.temp[name][-1].update(values[-1]) + + def merge_items(self, items): + + "Merge the given 'items' with this namespace." + + for name, types in items: + self.merge(name, types) + + def merge(self, name, types): + + "Merge the entry for the given 'name' and 'types' with this namespace." + + if not self.names.has_key(name): + self.names[name] = types.copy() + else: + existing = self.names[name] + existing.update(types) + + def snapshot(self): + + "Make a snapshot of the locals and remember them." + + namespace = Namespace() + namespace.merge_namespace(self) + self.return_locals.add(namespace) + + def reset(self): + + "Reset a namespace in preparation for merging with returned locals." + + self.names = {} + + def __repr__(self): + return repr(self.names) + " (temp) " + repr(self.temp) + # vim: tabstop=4 expandtab shiftwidth=4