1.1 --- a/simplify/annotate.py Fri Jun 22 01:06:19 2007 +0200
1.2 +++ b/simplify/annotate.py Fri Jun 22 01:11:12 2007 +0200
1.3 @@ -1379,152 +1379,6 @@
1.4
1.5 # Namespace-related abstractions.
1.6
1.7 -class Namespace:
1.8 -
1.9 - """
1.10 - A local namespace which may either relate to a genuine set of function
1.11 - locals or the initialisation of a structure or module.
1.12 - """
1.13 -
1.14 - def __init__(self):
1.15 -
1.16 - """
1.17 - Initialise the namespace with a mapping of local names to possible
1.18 - types, a list of return values and of possible returned local
1.19 - namespaces. The namespace also tracks the "current" types and a mapping
1.20 - of temporary value names to types.
1.21 - """
1.22 -
1.23 - self.names = {}
1.24 - self.returns = set()
1.25 - self.return_locals = set()
1.26 - self.raises = set()
1.27 - self.temp = {}
1.28 - self.types = set()
1.29 -
1.30 - def set_types(self, types):
1.31 -
1.32 - "Set the current collection of 'types'."
1.33 -
1.34 - self.types = types.copy()
1.35 -
1.36 - def add(self, name, types):
1.37 -
1.38 - "Add to the entry with the given 'name' the specified 'types'."
1.39 -
1.40 - if self.names.has_key(name):
1.41 - self.names[name].update(types)
1.42 - else:
1.43 - self.store(name, types)
1.44 -
1.45 - def store(self, name, types):
1.46 -
1.47 - "Store in (or associate with) the given 'name' the specified 'types'."
1.48 -
1.49 - self.names[name] = types.copy()
1.50 -
1.51 - __setitem__ = store
1.52 -
1.53 - def load(self, name):
1.54 -
1.55 - "Load the types associated with the given 'name'."
1.56 -
1.57 - return self.names[name]
1.58 -
1.59 - __getitem__ = load
1.60 -
1.61 - def has_key(self, name):
1.62 - return self.names.has_key(name)
1.63 -
1.64 - def keys(self):
1.65 - return self.names.keys()
1.66 -
1.67 - def values(self):
1.68 - return self.names.values()
1.69 -
1.70 - def items(self):
1.71 - return self.names.items()
1.72 -
1.73 - def get(self, name, default=None):
1.74 - return self.names.get(name, default)
1.75 -
1.76 - def revoke(self, name, type):
1.77 -
1.78 - "Revoke from the entry for the given 'name' the specified 'type'."
1.79 -
1.80 - new_types = self.names[name].copy()
1.81 - new_types.remove(type)
1.82 - self.names[name] = new_types
1.83 -
1.84 - def revoke_exception_type(self, type):
1.85 -
1.86 - "Revoke the given 'type' from the collection of exception types."
1.87 -
1.88 - if type in self.raises:
1.89 - self.raises.remove(type)
1.90 -
1.91 - def revoke_temp_type(self, index, type):
1.92 -
1.93 - "Revoke from the temporary variable 'index' the given 'type'."
1.94 -
1.95 - new_types = self.temp[index][-1].copy()
1.96 - new_types.remove(type)
1.97 - self.temp[index][-1] = new_types
1.98 -
1.99 - def merge_namespace(self, namespace, everything=1):
1.100 -
1.101 - """
1.102 - Merge items from the given 'namespace' with this namespace. When the
1.103 - optional 'everything' parameter is set to a false value (unlike the
1.104 - default), return values and locals snapshots will not be copied to this
1.105 - namespace.
1.106 - """
1.107 -
1.108 - self.merge_items(namespace.names.items())
1.109 - self.raises.update(namespace.raises)
1.110 - if everything:
1.111 - self.returns.update(namespace.returns)
1.112 - self.return_locals.update(namespace.return_locals)
1.113 - for name, values in namespace.temp.items():
1.114 - if values:
1.115 - if not self.temp.has_key(name) or not self.temp[name]:
1.116 - self.temp[name] = [set()]
1.117 - self.temp[name][-1].update(values[-1])
1.118 -
1.119 - def merge_items(self, items):
1.120 -
1.121 - "Merge the given 'items' with this namespace."
1.122 -
1.123 - for name, types in items:
1.124 - self.merge(name, types)
1.125 -
1.126 - def merge(self, name, types):
1.127 -
1.128 - "Merge the entry for the given 'name' and 'types' with this namespace."
1.129 -
1.130 - if not self.names.has_key(name):
1.131 - self.names[name] = types.copy()
1.132 - else:
1.133 - existing = self.names[name]
1.134 - existing.update(types)
1.135 -
1.136 - def snapshot(self):
1.137 -
1.138 - "Make a snapshot of the locals and remember them."
1.139 -
1.140 - namespace = Namespace()
1.141 - namespace.merge_namespace(self)
1.142 - self.return_locals.add(namespace)
1.143 -
1.144 - def reset(self):
1.145 -
1.146 - "Reset a namespace in preparation for merging with returned locals."
1.147 -
1.148 - self.names = {}
1.149 -
1.150 - def __repr__(self):
1.151 - return repr(self.names) + " (temp) " + repr(self.temp)
1.152 -
1.153 class Importer:
1.154
1.155 "An import machine, searching for and loading modules."
1.156 @@ -1745,6 +1599,7 @@
1.157
1.158 if isinstance(structure, Attribute):
1.159 structure = structure.type
1.160 +
1.161 results = []
1.162 for attribute, accessor in find_attributes(structure, name):
1.163
1.164 @@ -1754,9 +1609,18 @@
1.165 attribute = accessor.get_attribute_for_instance(attribute, structure)
1.166
1.167 # Produce an attribute with the appropriate context.
1.168 + # Modules should not affect the context.
1.169
1.170 - if attribute is not None and isinstance(structure, Structure):
1.171 + if attribute is not None and isinstance(structure, Module):
1.172 + results.append((attribute, accessor))
1.173 +
1.174 + # Access via classes and instances should set those as the context.
1.175 +
1.176 + elif attribute is not None and isinstance(structure, Structure):
1.177 results.append((Attribute(structure, attribute.type), accessor))
1.178 +
1.179 + # Other accesses are returned unmodified.
1.180 +
1.181 else:
1.182 results.append((attribute, accessor))
1.183
2.1 --- a/simplify/fixinstances.py Fri Jun 22 01:06:19 2007 +0200
2.2 +++ b/simplify/fixinstances.py Fri Jun 22 01:11:12 2007 +0200
2.3 @@ -74,6 +74,14 @@
2.4 self.current_subprograms = []
2.5
2.6 self.module = module
2.7 +
2.8 + # Visit structures and instances.
2.9 +
2.10 + for structure in self.module.simplifier.structures:
2.11 + for instance in structure.get_instances():
2.12 + for name, attrs in instance.namespace.items():
2.13 + instance.namespace[name] = self._replace(attrs)
2.14 +
2.15 self.process_node(self.module)
2.16
2.17 # Then, process all functions and methods.
2.18 @@ -87,13 +95,6 @@
2.19 for specialised in subprogram.active():
2.20 self.subprograms.append(self.process_node(specialised))
2.21
2.22 - # Visit structures and instances.
2.23 -
2.24 - for structure in self.module.simplifier.structures:
2.25 - for instance in structure.instances.values():
2.26 - for attrs in instance.namespace.values():
2.27 - self._replace(attrs)
2.28 -
2.29 def process_node(self, node):
2.30
2.31 """
2.32 @@ -134,12 +135,12 @@
2.33 for name in ("non_accesses", "non_writes", "raises", "returns", "types"):
2.34 if hasattr(node, name):
2.35 attrs = getattr(node, name)
2.36 - self._replace(attrs)
2.37 + setattr(node, name, self._replace(attrs))
2.38 for name in ("accesses", "writes", "paramtypes"):
2.39 if hasattr(node, name):
2.40 d = getattr(node, name)
2.41 for expr, attrs in d.items():
2.42 - self._replace(attrs, name, d, expr)
2.43 + d[self._get_replacement(expr)] = self._replace(attrs, name)
2.44
2.45 # Visit program nodes.
2.46
2.47 @@ -165,21 +166,23 @@
2.48
2.49 return node
2.50
2.51 - def _replace(self, items, name=None, container=None, key=None):
2.52 + def _replace(self, items, name=None):
2.53 + if name == "accesses":
2.54 + new_items = []
2.55 + else:
2.56 + new_items = set()
2.57 +
2.58 for item in list(items):
2.59 - items.remove(item)
2.60 if name == "accesses":
2.61 attr, accessor = item
2.62 value = attr.type
2.63 - items.append((Attribute(self._get_replacement(attr.context), self._get_replacement(value)), self._get_replacement(accessor)))
2.64 + new_items.append((Attribute(self._get_replacement(attr.context), self._get_replacement(value)), self._get_replacement(accessor)))
2.65 else:
2.66 attr = item
2.67 value = attr.type
2.68 - items.add(Attribute(self._get_replacement(attr.context), self._get_replacement(value)))
2.69 + new_items.add(Attribute(self._get_replacement(attr.context), self._get_replacement(value)))
2.70
2.71 - if name == "accesses":
2.72 - del container[key]
2.73 - container[self._get_replacement(key)] = items
2.74 + return new_items
2.75
2.76 def _get_replacement(self, value):
2.77 if isinstance(value, Instance):
3.1 --- a/simplify/simplified/data.py Fri Jun 22 01:06:19 2007 +0200
3.2 +++ b/simplify/simplified/data.py Fri Jun 22 01:11:12 2007 +0200
3.3 @@ -49,7 +49,7 @@
3.4 "Return all attribute names used by the instances of this class."
3.5
3.6 names = set()
3.7 - for instance in self.instances.values():
3.8 + for instance in self.get_instances():
3.9 for name in instance.namespace.keys():
3.10 names.add(name)
3.11 return names
3.12 @@ -66,7 +66,7 @@
3.13 if distinct:
3.14 instances = set(self.get_distinct_instances().values())
3.15 else:
3.16 - instances = self.instances.values()
3.17 + instances = self.get_instances()
3.18
3.19 for instance in instances:
3.20 name = instance.full_name()
3.21 @@ -129,6 +129,12 @@
3.22 def get_instance_name(self, instance):
3.23 return self._full_name
3.24
3.25 + def get_instances(self):
3.26 + if self.instance is not None:
3.27 + return [self.instance]
3.28 + else:
3.29 + return []
3.30 +
3.31 # Attribute propagation.
3.32
3.33 def get_attribute_for_instance(self, attribute, instance):
3.34 @@ -158,6 +164,9 @@
3.35 def get_instance_name(self, instance):
3.36 return name(instance, self._full_name)
3.37
3.38 + def get_instances(self):
3.39 + return self.instances.values()
3.40 +
3.41 # Attribute propagation.
3.42
3.43 def get_attribute_for_instance(self, attribute, instance):
4.1 --- a/simplify/simplified/program.py Fri Jun 22 01:06:19 2007 +0200
4.2 +++ b/simplify/simplified/program.py Fri Jun 22 01:11:12 2007 +0200
4.3 @@ -23,7 +23,7 @@
4.4 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
4.5 """
4.6
4.7 -from simplify.simplified.utils import Structure, WithName, name
4.8 +from simplify.simplified.utils import Structure, WithName, name, Namespace
4.9 import sys
4.10 import operator
4.11
4.12 @@ -412,7 +412,7 @@
4.13 def full_name(self):
4.14 return "module %s" % self.name
4.15
4.16 -class Subprogram(Node, WithName):
4.17 +class Subprogram(Node, WithName, Structure):
4.18
4.19 "A subprogram: functions, methods and loops."
4.20
4.21 @@ -422,5 +422,6 @@
4.22 self.raises = set()
4.23 self.returns = set()
4.24 self.return_locals = set()
4.25 + self.namespace = Namespace() # NOTE: Temporary.
4.26
4.27 # vim: tabstop=4 expandtab shiftwidth=4
5.1 --- a/simplify/simplified/utils.py Fri Jun 22 01:06:19 2007 +0200
5.2 +++ b/simplify/simplified/utils.py Fri Jun 22 01:11:12 2007 +0200
5.3 @@ -167,4 +167,152 @@
5.4 def __repr__(self):
5.5 return "%s '%s'" % (self.__class__.__name__, self.full_name())
5.6
5.7 +# Namespace classes.
5.8 +
5.9 +class Namespace:
5.10 +
5.11 + """
5.12 + A local namespace which may either relate to a genuine set of function
5.13 + locals or the initialisation of a structure or module.
5.14 + """
5.15 +
5.16 + def __init__(self):
5.17 +
5.18 + """
5.19 + Initialise the namespace with a mapping of local names to possible
5.20 + types, a list of return values and of possible returned local
5.21 + namespaces. The namespace also tracks the "current" types and a mapping
5.22 + of temporary value names to types.
5.23 + """
5.24 +
5.25 + self.names = {}
5.26 + self.returns = set()
5.27 + self.return_locals = set()
5.28 + self.raises = set()
5.29 + self.temp = {}
5.30 + self.types = set()
5.31 +
5.32 + def set_types(self, types):
5.33 +
5.34 + "Set the current collection of 'types'."
5.35 +
5.36 + self.types = types.copy()
5.37 +
5.38 + def add(self, name, types):
5.39 +
5.40 + "Add to the entry with the given 'name' the specified 'types'."
5.41 +
5.42 + if self.names.has_key(name):
5.43 + self.names[name].update(types)
5.44 + else:
5.45 + self.store(name, types)
5.46 +
5.47 + def store(self, name, types):
5.48 +
5.49 + "Store in (or associate with) the given 'name' the specified 'types'."
5.50 +
5.51 + self.names[name] = types.copy()
5.52 +
5.53 + __setitem__ = store
5.54 +
5.55 + def load(self, name):
5.56 +
5.57 + "Load the types associated with the given 'name'."
5.58 +
5.59 + return self.names[name]
5.60 +
5.61 + __getitem__ = load
5.62 +
5.63 + def has_key(self, name):
5.64 + return self.names.has_key(name)
5.65 +
5.66 + def keys(self):
5.67 + return self.names.keys()
5.68 +
5.69 + def values(self):
5.70 + return self.names.values()
5.71 +
5.72 + def items(self):
5.73 + return self.names.items()
5.74 +
5.75 + def get(self, name, default=None):
5.76 + return self.names.get(name, default)
5.77 +
5.78 + def revoke(self, name, type):
5.79 +
5.80 + "Revoke from the entry for the given 'name' the specified 'type'."
5.81 +
5.82 + new_types = self.names[name].copy()
5.83 + new_types.remove(type)
5.84 + self.names[name] = new_types
5.85 +
5.86 + def revoke_exception_type(self, type):
5.87 +
5.88 + "Revoke the given 'type' from the collection of exception types."
5.89 +
5.90 + if type in self.raises:
5.91 + self.raises.remove(type)
5.92 +
5.93 + def revoke_temp_type(self, index, type):
5.94 +
5.95 + "Revoke from the temporary variable 'index' the given 'type'."
5.96 +
5.97 + new_types = self.temp[index][-1].copy()
5.98 + new_types.remove(type)
5.99 + self.temp[index][-1] = new_types
5.100 +
5.101 + def merge_namespace(self, namespace, everything=1):
5.102 +
5.103 + """
5.104 + Merge items from the given 'namespace' with this namespace. When the
5.105 + optional 'everything' parameter is set to a false value (unlike the
5.106 + default), return values and locals snapshots will not be copied to this
5.107 + namespace.
5.108 + """
5.109 +
5.110 + self.merge_items(namespace.names.items())
5.111 + self.raises.update(namespace.raises)
5.112 + if everything:
5.113 + self.returns.update(namespace.returns)
5.114 + self.return_locals.update(namespace.return_locals)
5.115 + for name, values in namespace.temp.items():
5.116 + if values:
5.117 + if not self.temp.has_key(name) or not self.temp[name]:
5.118 + self.temp[name] = [set()]
5.119 + self.temp[name][-1].update(values[-1])
5.120 +
5.121 + def merge_items(self, items):
5.122 +
5.123 + "Merge the given 'items' with this namespace."
5.124 +
5.125 + for name, types in items:
5.126 + self.merge(name, types)
5.127 +
5.128 + def merge(self, name, types):
5.129 +
5.130 + "Merge the entry for the given 'name' and 'types' with this namespace."
5.131 +
5.132 + if not self.names.has_key(name):
5.133 + self.names[name] = types.copy()
5.134 + else:
5.135 + existing = self.names[name]
5.136 + existing.update(types)
5.137 +
5.138 + def snapshot(self):
5.139 +
5.140 + "Make a snapshot of the locals and remember them."
5.141 +
5.142 + namespace = Namespace()
5.143 + namespace.merge_namespace(self)
5.144 + self.return_locals.add(namespace)
5.145 +
5.146 + def reset(self):
5.147 +
5.148 + "Reset a namespace in preparation for merging with returned locals."
5.149 +
5.150 + self.names = {}
5.151 +
5.152 + def __repr__(self):
5.153 + return repr(self.names) + " (temp) " + repr(self.temp)
5.154 +
5.155 # vim: tabstop=4 expandtab shiftwidth=4