Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
88 lines (73 sloc) 2.49 KB
import space
from builtin import signature
from interface import Object
from rpython.rlib import jit
class Exnihilo(Object):
_immutable_fields_ = ['storage']
__slots__ = ['map', 'storage']
def __init__(self):
self.map = EMPTY_MAP
self.storage = []
def getattr(self, name):
map = jit.promote(self.map)
index = map.getindex(name)
if index != -1:
return self.storage[index]
else:
return Object.getattr(self, name)
def getattr_or(self, name, default):
map = jit.promote(self.map)
index = map.getindex(name)
if index != -1:
return self.storage[index]
else:
return default
def setattr(self, name, value):
map = jit.promote(self.map)
index = map.getindex(name)
if index != -1:
self.storage[index] = value
else:
self.map = map.new_map_with_additional_attribute(name)
self.storage.append(value)
return value
def listattr(self):
listing = Object.listattr(self)
for name in self.map.attribute_indexes:
listing.append(space.String(name))
return listing
def repr(self):
cellnames = u""
for cellname in self.map.attribute_indexes:
if len(cellnames) > 0:
cellnames += u", "
cellnames += cellname
return u"<object %s>" % cellnames
# Exnihilo doesn't exist for the user. He only sees an object.
Exnihilo.interface = Object.interface
@Object.instantiator2(signature(Object, optional=1))
def instantiate(obj):
res = Exnihilo()
if obj is not None:
obj = space.cast(obj, space.Dict, u"object instantiation")
for key, value in obj.data.items():
key = space.cast(key, space.String, u"setattr")
res.setattr(key.string, value)
return res
# Attribute optimization for exnihilo objects.
class Map(object):
def __init__(self):
self.attribute_indexes = {}
self.other_maps = {}
@jit.elidable
def getindex(self, name):
return self.attribute_indexes.get(name, -1)
@jit.elidable
def new_map_with_additional_attribute(self, name):
if name not in self.other_maps:
newmap = Map()
newmap.attribute_indexes.update(self.attribute_indexes)
newmap.attribute_indexes[name] = len(self.attribute_indexes)
self.other_maps[name] = newmap
return self.other_maps[name]
EMPTY_MAP = Map()