1.1 --- a/simplified/data.py Sun May 27 18:19:01 2007 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,237 +0,0 @@
1.4 -#!/usr/bin/env python
1.5 -
1.6 -"""
1.7 -Simplified program data.
1.8 -
1.9 -Copyright (C) 2006, 2007 Paul Boddie <paul@boddie.org.uk>
1.10 -
1.11 -This software is free software; you can redistribute it and/or
1.12 -modify it under the terms of the GNU General Public License as
1.13 -published by the Free Software Foundation; either version 2 of
1.14 -the License, or (at your option) any later version.
1.15 -
1.16 -This software is distributed in the hope that it will be useful,
1.17 -but WITHOUT ANY WARRANTY; without even the implied warranty of
1.18 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.19 -GNU General Public License for more details.
1.20 -
1.21 -You should have received a copy of the GNU General Public
1.22 -License along with this library; see the file LICENCE.txt
1.23 -If not, write to the Free Software Foundation, Inc.,
1.24 -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
1.25 -"""
1.26 -
1.27 -from simplified.utils import Structure, WithName, name
1.28 -
1.29 -# Special non-program nodes.
1.30 -
1.31 -class _Class(Structure, WithName):
1.32 -
1.33 - "A Python class."
1.34 -
1.35 - def __init__(self, *args, **kw):
1.36 - Structure.__init__(self, *args, **kw)
1.37 - WithName.__init__(self)
1.38 -
1.39 - def full_name(self):
1.40 - return "class %s" % self._full_name
1.41 -
1.42 -class SingleInstanceClass(_Class):
1.43 -
1.44 - "A Python class."
1.45 -
1.46 - def __init__(self, *args, **kw):
1.47 - _Class.__init__(self, *args, **kw)
1.48 - self.instance = None
1.49 -
1.50 - def has_instance(self, node):
1.51 - return self.instance is not None
1.52 -
1.53 - def add_instance(self, node, instance):
1.54 - self.instance = instance
1.55 -
1.56 - def get_instance(self, node):
1.57 - return self.instance
1.58 -
1.59 - def get_instance_name(self, instance):
1.60 - return self._full_name
1.61 -
1.62 - # Attribute propagation.
1.63 -
1.64 - def get_attribute_for_instance(self, attribute, instance):
1.65 - return attribute
1.66 -
1.67 -class MultipleInstanceClass(_Class):
1.68 -
1.69 - "A Python class."
1.70 -
1.71 - def __init__(self, *args, **kw):
1.72 - _Class.__init__(self, *args, **kw)
1.73 - self.instances = {}
1.74 - self.attributes_for_instances = {}
1.75 -
1.76 - def _get_key(self, node):
1.77 - return id(getattr(node, "original", None)) # self.module.original
1.78 -
1.79 - def has_instance(self, node):
1.80 - return self.instances.has_key(self._get_key(node))
1.81 -
1.82 - def add_instance(self, node, instance):
1.83 - self.instances[self._get_key(node)] = instance
1.84 -
1.85 - def get_instance(self, node):
1.86 - return self.instances[self._get_key(node)]
1.87 -
1.88 - def get_instance_name(self, instance):
1.89 - return name(instance, self._full_name)
1.90 -
1.91 - # Attribute propagation.
1.92 -
1.93 - def get_attribute_for_instance(self, attribute, instance):
1.94 -
1.95 - # Create specialised methods.
1.96 -
1.97 - if isinstance(attribute.type, Subprogram):
1.98 - subprogram = attribute.type
1.99 -
1.100 - # Each instance may have its own version of the subprogram.
1.101 -
1.102 - key = (subprogram, instance)
1.103 - if not self.attributes_for_instances.has_key(key):
1.104 - new_subprogram = subprogram.copy(instance, subprogram.full_name())
1.105 - subprogram.module.simplifier.subnames[new_subprogram.full_name()] = new_subprogram
1.106 - self.attributes_for_instances[key] = Attribute(attribute.context, new_subprogram)
1.107 - print "New subprogram", new_subprogram, "for", key
1.108 -
1.109 - return self.attributes_for_instances[key]
1.110 -
1.111 - # The original nodes are returned for other attributes.
1.112 -
1.113 - else:
1.114 - return attribute
1.115 -
1.116 -class SelectiveMultipleInstanceClass(MultipleInstanceClass):
1.117 -
1.118 - "A Python class which provides multiple instances depending on the class."
1.119 -
1.120 - def _get_key(self, node):
1.121 - if self.namespace.has_key("__atomic__"):
1.122 - return id(self)
1.123 - else:
1.124 - return MultipleInstanceClass._get_key(self, node)
1.125 -
1.126 -class ProlificMultipleInstanceClass(MultipleInstanceClass):
1.127 -
1.128 - """
1.129 - A Python class which provides multiple instances for different versions of
1.130 - methods. In order to avoid unbounded instance production (since new
1.131 - instances cause new copies of methods which in turn would cause new
1.132 - instances), a relations dictionary is maintained which attempts to map
1.133 - "requesting instances" to existing instances, suggesting such instances in
1.134 - preference to new ones.
1.135 - """
1.136 -
1.137 - def __init__(self, *args, **kw):
1.138 - MultipleInstanceClass.__init__(self, *args, **kw)
1.139 - self.instance_relations = {}
1.140 -
1.141 - def _get_key(self, node):
1.142 - if self.namespace.has_key("__atomic__"):
1.143 - return id(self)
1.144 - else:
1.145 - return id(node)
1.146 -
1.147 - def has_instance(self, node):
1.148 - requesting_instance = getattr(node, "instance", None)
1.149 - #return requesting_instance is not None and requesting_instance.get_class() is self or \
1.150 - return self.instance_relations.has_key(requesting_instance) or self.instances.has_key(self._get_key(node))
1.151 -
1.152 - def add_instance(self, node, instance):
1.153 - requesting_instance = getattr(node, "instance", None)
1.154 - print "New instance", instance, "for", id(node), requesting_instance
1.155 - self.instances[self._get_key(node)] = instance
1.156 - if requesting_instance is not None:
1.157 - self.instance_relations[requesting_instance] = instance
1.158 - requesting_instance.get_class().instance_relations[instance] = requesting_instance
1.159 -
1.160 - def get_instance(self, node):
1.161 - requesting_instance = getattr(node, "instance", None)
1.162 - #if requesting_instance is not None and requesting_instance.get_class() is self:
1.163 - # return requesting_instance
1.164 - return self.instance_relations.get(requesting_instance) or self.instances[self._get_key(node)]
1.165 -
1.166 -class Instance(Structure):
1.167 -
1.168 - "An instance."
1.169 -
1.170 - def full_name(self):
1.171 - return self.get_class().get_instance_name(self)
1.172 -
1.173 - def get_class(self):
1.174 - for n in self.namespace.load("__class__"):
1.175 - return n.type
1.176 - else:
1.177 - raise ValueError, "__class__"
1.178 -
1.179 - def __repr__(self):
1.180 - return "Instance of type '%s'" % self.full_name()
1.181 -
1.182 - def __eq__(self, other):
1.183 - # NOTE: Single instance: all instances are the same
1.184 - # NOTE: Multiple instances: all instances are different
1.185 - return self.full_name() == other.full_name()
1.186 -
1.187 - def __hash__(self):
1.188 - return id(self)
1.189 -
1.190 -class Constant:
1.191 -
1.192 - "A constant initialised with a type name for future processing."
1.193 -
1.194 - def __init__(self, name, value):
1.195 - self.name = name
1.196 - self.value = value
1.197 - self.typename = self.value.__class__.__name__
1.198 -
1.199 -class Attribute:
1.200 -
1.201 - """
1.202 - An attribute abstraction, indicating the type of the attribute along with
1.203 - its context or origin.
1.204 - """
1.205 -
1.206 - def __init__(self, context, type):
1.207 - self.context = context
1.208 - self.type = type
1.209 -
1.210 - def __eq__(self, other):
1.211 - return hasattr(other, "type") and other.type == self.type or other == self.type
1.212 -
1.213 - def __repr__(self):
1.214 - return "Attribute(%s, %s)" % (repr(self.context), repr(self.type))
1.215 -
1.216 - def __hash__(self):
1.217 - return id(self.type)
1.218 -
1.219 -# Configuration setting.
1.220 -
1.221 -Class = SingleInstanceClass
1.222 -#Class = MultipleInstanceClass
1.223 -
1.224 -def set_single_instance_mode():
1.225 - global Class
1.226 - Class = SingleInstanceClass
1.227 -
1.228 -def set_multiple_instance_mode():
1.229 - global Class
1.230 - Class = MultipleInstanceClass
1.231 -
1.232 -def set_selective_multiple_instance_mode():
1.233 - global Class
1.234 - Class = SelectiveMultipleInstanceClass
1.235 -
1.236 -def set_prolific_multiple_instance_mode():
1.237 - global Class
1.238 - Class = ProlificMultipleInstanceClass
1.239 -
1.240 -# vim: tabstop=4 expandtab shiftwidth=4