""" Miscellaneous utilities. """ import types from pypy.rlib.rarithmetic import r_uint class RootStack: pass class Stack(RootStack): """Utility class implementing a stack.""" _annspecialcase_ = "specialize:ctr_location" # polymorphic def __init__(self): self.items = [] def clone(self): s = self.__class__() for item in self.items: try: item = item.clone() except AttributeError: pass s.push(item) return s def push(self, item): self.items.append(item) def pop(self): return self.items.pop() def drop(self, n): if n > 0: del self.items[-n:] def top(self, position=0): """'position' is 0 for the top of the stack, 1 for the item below, and so on. It must not be negative.""" if position < 0: raise ValueError, 'negative stack position' if position >= len(self.items): raise IndexError, 'not enough entries in stack' return self.items[~position] def set_top(self, value, position=0): """'position' is 0 for the top of the stack, 1 for the item below, and so on. It must not be negative.""" if position < 0: raise ValueError, 'negative stack position' if position >= len(self.items): raise IndexError, 'not enough entries in stack' self.items[~position] = value def depth(self): return len(self.items) def empty(self): return len(self.items) == 0 class FixedStack(RootStack): _annspecialcase_ = "specialize:ctr_location" # polymorphic # unfortunately, we have to re-do everything def __init__(self): pass def setup(self, stacksize): self.ptr = r_uint(0) # we point after the last element self.items = [None] * stacksize def clone(self): # this is only needed if we support flow space s = self.__class__() s.setup(len(self.items)) for item in self.items[:self.ptr]: try: item = item.clone() except AttributeError: pass s.push(item) return s def push(self, item): ptr = self.ptr self.items[ptr] = item self.ptr = ptr + 1 def pop(self): ptr = self.ptr - 1 ret = self.items[ptr] # you get OverflowError if the stack is empty self.items[ptr] = None self.ptr = ptr return ret def drop(self, n): while n > 0: n -= 1 self.ptr -= 1 self.items[self.ptr] = None def top(self, position=0): # for a fixed stack, we assume correct indices return self.items[self.ptr + ~position] def set_top(self, value, position=0): # for a fixed stack, we assume correct indices self.items[self.ptr + ~position] = value def depth(self): return self.ptr def empty(self): return not self.ptr class InitializedClass(type): """NOT_RPYTHON. A meta-class that allows a class to initialize itself (or its subclasses) by calling __initclass__() as a class method.""" def __init__(self, name, bases, dict): super(InitializedClass, self).__init__(name, bases, dict) for basecls in self.__mro__: raw = basecls.__dict__.get('__initclass__') if isinstance(raw, types.FunctionType): raw(self) # call it as a class method class RwDictProxy(object): """NOT_RPYTHON. A dict-like class standing for 'cls.__dict__', to work around the fact that the latter is a read-only proxy for new-style classes.""" def __init__(self, cls): self.cls = cls def __getitem__(self, attr): return self.cls.__dict__[attr] def __setitem__(self, attr, value): setattr(self.cls, attr, value) def __contains__(self, value): return value in self.cls.__dict__ def items(self): return self.cls.__dict__.items() class ThreadLocals: """Pseudo thread-local storage, for 'space.threadlocals'. This is not really thread-local at all; the intention is that the PyPy implementation of the 'thread' module knows how to provide a real implementation for this feature, and patches 'space.threadlocals' when 'thread' is initialized. """ _value = None def getvalue(self): return self._value def setvalue(self, value): self._value = value def getmainthreadvalue(self): return self._value