[pypy-svn] r18520 - in pypy/branch/hl-backend/pypy/rpython: . lltypesystem
boria at codespeak.net
boria at codespeak.net
Thu Oct 13 16:47:44 CEST 2005
Author: boria
Date: Thu Oct 13 16:47:44 2005
New Revision: 18520
Added:
pypy/branch/hl-backend/pypy/rpython/lltypesystem/ (props changed)
pypy/branch/hl-backend/pypy/rpython/lltypesystem/__init__.py (contents, props changed)
pypy/branch/hl-backend/pypy/rpython/lltypesystem/exceptiondata.py
- copied, changed from r18504, pypy/branch/hl-backend/pypy/rpython/exceptiondata.py
pypy/branch/hl-backend/pypy/rpython/lltypesystem/lltype.py
- copied, changed from r18479, pypy/branch/hl-backend/pypy/rpython/lltype.py
pypy/branch/hl-backend/pypy/rpython/lltypesystem/rbuiltin.py
- copied, changed from r18504, pypy/branch/hl-backend/pypy/rpython/rbuiltin.py
pypy/branch/hl-backend/pypy/rpython/lltypesystem/rclass.py
- copied, changed from r18479, pypy/branch/hl-backend/pypy/rpython/rclass.py
Removed:
pypy/branch/hl-backend/pypy/rpython/exceptiondata.py
Modified:
pypy/branch/hl-backend/pypy/rpython/lltype.py
pypy/branch/hl-backend/pypy/rpython/rbuiltin.py
pypy/branch/hl-backend/pypy/rpython/rclass.py
pypy/branch/hl-backend/pypy/rpython/rlist.py
pypy/branch/hl-backend/pypy/rpython/rpbc.py
pypy/branch/hl-backend/pypy/rpython/rstr.py
pypy/branch/hl-backend/pypy/rpython/rtyper.py
pypy/branch/hl-backend/pypy/rpython/typesystem.py
Log:
(Samuele, Boris)
* Continuing work on decoupling RTyper from lltypes.
* Lazy imports in typesystem.py to avoid circular import problems.
* Refactor rclass.py and rbuiltin.py into common and lltype-specific parts.
* Several tests still failing in rpython/test/ due to rpbc.py.
Modified: pypy/branch/hl-backend/pypy/rpython/lltype.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/lltype.py (original)
+++ pypy/branch/hl-backend/pypy/rpython/lltype.py Thu Oct 13 16:47:44 2005
@@ -1,965 +1 @@
-import weakref, operator
-import py
-from pypy.rpython.rarithmetic import r_uint
-from pypy.tool.uid import Hashable
-from pypy.tool.tls import tlsobject
-from types import NoneType
-
-log = py.log.Producer('lltype')
-
-TLS = tlsobject()
-
-def saferecursive(func, defl):
- def safe(*args):
- try:
- seeing = TLS.seeing
- except AttributeError:
- seeing = TLS.seeing = {}
- seeingkey = tuple([func] + [id(arg) for arg in args])
- if seeingkey in seeing:
- return defl
- seeing[seeingkey] = True
- try:
- return func(*args)
- finally:
- del seeing[seeingkey]
- return safe
-
-#safe_equal = saferecursive(operator.eq, True)
-def safe_equal(x, y):
- # a specialized version for performance
- try:
- seeing = TLS.seeing_eq
- except AttributeError:
- seeing = TLS.seeing_eq = {}
- seeingkey = (id(x), id(y))
- if seeingkey in seeing:
- return True
- seeing[seeingkey] = True
- try:
- return x == y
- finally:
- del seeing[seeingkey]
-
-
-class frozendict(dict):
-
- def __hash__(self):
- items = self.items()
- items.sort()
- return hash(tuple(items))
-
-
-class LowLevelType(object):
- # the following line prevents '__cached_hash' to be in the __dict__ of
- # the instance, which is needed for __eq__() and __hash__() to work.
- __slots__ = ['__dict__', '__cached_hash']
-
- def __eq__(self, other):
- return self.__class__ is other.__class__ and (
- self is other or safe_equal(self.__dict__, other.__dict__))
-
- def __ne__(self, other):
- return not (self == other)
-
- def __hash__(self):
- # cannot use saferecursive() -- see test_lltype.test_hash().
- # NB. the __cached_hash should neither be used nor updated
- # if we enter with hash_level > 0, because the computed
- # __hash__ can be different in this situation.
- hash_level = 0
- try:
- hash_level = TLS.nested_hash_level
- if hash_level == 0:
- return self.__cached_hash
- except AttributeError:
- pass
- if hash_level >= 3:
- return 0
- items = self.__dict__.items()
- items.sort()
- TLS.nested_hash_level = hash_level + 1
- try:
- result = hash((self.__class__,) + tuple(items))
- finally:
- TLS.nested_hash_level = hash_level
- if hash_level == 0:
- self.__cached_hash = result
- return result
-
- # due to this dynamic hash value, we should forbid
- # pickling, until we have an algorithm for that.
- # but we just provide a tag for external help.
- __hash_is_not_constant__ = True
-
- def __repr__(self):
- return '<%s>' % (self,)
-
- def __str__(self):
- return self.__class__.__name__
-
- def _short_name(self):
- return str(self)
-
- def _defl(self, parent=None, parentindex=None):
- raise NotImplementedError
-
- def _freeze_(self):
- return True
-
- def _inline_is_varsize(self, last):
- return False
-
- def _is_atomic(self):
- return False
-
- def _is_varsize(self):
- return False
-
-
-class ContainerType(LowLevelType):
- def _gcstatus(self):
- return isinstance(self, GC_CONTAINER)
-
- def _inline_is_varsize(self, last):
- raise TypeError, "%r cannot be inlined in structure" % self
-
-
-class Struct(ContainerType):
- def __init__(self, name, *fields):
- self._name = self.__name__ = name
- flds = {}
- names = []
- self._arrayfld = None
- for name, typ in fields:
- if name.startswith('_'):
- raise NameError, ("%s: field name %r should not start with "
- "an underscore" % (self._name, name,))
- names.append(name)
- if name in flds:
- raise TypeError("%s: repeated field name" % self._name)
- flds[name] = typ
- if isinstance(typ, GC_CONTAINER):
- if name == fields[0][0] and isinstance(self, GC_CONTAINER):
- pass # can inline a GC_CONTAINER as 1st field of GcStruct
- else:
- raise TypeError("%s: cannot inline GC container %r" % (
- self._name, typ))
-
- # look if we have an inlined variable-sized array as the last field
- if fields:
- for name, typ in fields[:-1]:
- typ._inline_is_varsize(False)
- first = False
- name, typ = fields[-1]
- if typ._inline_is_varsize(True):
- self._arrayfld = name
- self._flds = frozendict(flds)
- self._names = tuple(names)
-
- def _first_struct(self):
- if self._names:
- first = self._names[0]
- FIRSTTYPE = self._flds[first]
- if isinstance(FIRSTTYPE, Struct) and self._gcstatus() == FIRSTTYPE._gcstatus():
- return first, FIRSTTYPE
- return None, None
-
- def _inline_is_varsize(self, last):
- if self._arrayfld:
- raise TypeError("cannot inline a var-sized struct "
- "inside another container")
- return False
-
- def _is_atomic(self):
- for typ in self._flds.values():
- if not typ._is_atomic():
- return False
- return True
-
- def _is_varsize(self):
- return self._arrayfld is not None
-
- def __getattr__(self, name):
- try:
- return self._flds[name]
- except KeyError:
- raise AttributeError, 'struct %s has no field %r' % (self._name,
- name)
-
- def _names_without_voids(self):
- names_without_voids = [name for name in self._names if self._flds[name] is not Void]
- return names_without_voids
-
- def _str_fields_without_voids(self):
- return ', '.join(['%s: %s' % (name, self._flds[name])
- for name in self._names_without_voids(False)])
- _str_fields_without_voids = saferecursive(_str_fields_without_voids, '...')
-
- def _str_without_voids(self):
- return "%s %s { %s }" % (self.__class__.__name__,
- self._name, self._str_fields_without_voids())
-
- def _str_fields(self):
- return ', '.join(['%s: %s' % (name, self._flds[name])
- for name in self._names])
- _str_fields = saferecursive(_str_fields, '...')
-
- def __str__(self):
- return "%s %s { %s }" % (self.__class__.__name__,
- self._name, self._str_fields())
-
- def _short_name(self):
- return "%s %s" % (self.__class__.__name__, self._name)
-
- def _defl(self, parent=None, parentindex=None):
- return _struct(self, parent=parent, parentindex=parentindex)
-
- def _container_example(self):
- if self._arrayfld is None:
- n = None
- else:
- n = 1
- return _struct(self, n)
-
-class GcStruct(Struct):
- _runtime_type_info = None
-
- def _attach_runtime_type_info_funcptr(self, funcptr):
- if self._runtime_type_info is None:
- self._runtime_type_info = opaqueptr(RuntimeTypeInfo, name=self._name, about=self)._obj
- if funcptr is not None:
- T = typeOf(funcptr)
- if (not isinstance(T, Ptr) or
- not isinstance(T.TO, FuncType) or
- len(T.TO.ARGS) != 1 or
- T.TO.RESULT != Ptr(RuntimeTypeInfo) or
- castable(T.TO.ARGS[0], Ptr(self)) < 0):
- raise TypeError("expected a runtime type info function "
- "implementation, got: %s" % funcptr)
- self._runtime_type_info.query_funcptr = funcptr
-
-class Array(ContainerType):
- __name__ = 'array'
- _anonym_struct = False
-
- def __init__(self, *fields):
- if len(fields) == 1 and isinstance(fields[0], LowLevelType):
- self.OF = fields[0]
- else:
- self.OF = Struct("<arrayitem>", *fields)
- self._anonym_struct = True
- if isinstance(self.OF, GcStruct):
- raise TypeError("cannot have a GC structure as array item type")
- self.OF._inline_is_varsize(False)
-
- def _inline_is_varsize(self, last):
- if not last:
- raise TypeError("cannot inline an array in another container"
- " unless as the last field of a structure")
- return True
-
- def _is_atomic(self):
- return self.OF._is_atomic()
-
- def _is_varsize(self):
- return True
-
- def _str_fields(self):
- if isinstance(self.OF, Struct):
- of = self.OF
- if self._anonym_struct:
- return "{ %s }" % of._str_fields()
- else:
- return "%s { %s }" % (of._name, of._str_fields())
- else:
- return self.OF
-
- def __str__(self):
- return "%s of %s " % (self.__class__.__name__,
- self._str_fields(),)
-
- def _short_name(self):
- return "%s %s" % (self.__class__.__name__,
- self.OF._short_name(),)
-
- def _container_example(self):
- return _array(self, 1)
-
-class GcArray(Array):
- def _inline_is_varsize(self, last):
- raise TypeError("cannot inline a GC array inside a structure")
-
-class FuncType(ContainerType):
- __name__ = 'func'
- def __init__(self, args, result):
- for arg in args:
- assert isinstance(arg, LowLevelType)
- if isinstance(arg, ContainerType):
- raise TypeError, "function arguments can only be primitives or pointers"
- self.ARGS = tuple(args)
- assert isinstance(result, LowLevelType)
- if isinstance(result, ContainerType):
- raise TypeError, "function result can only be primitive or pointer"
- self.RESULT = result
-
- def __str__(self):
- args = ', '.join(map(str, self.ARGS))
- return "Func ( %s ) -> %s" % (args, self.RESULT)
-
- def _short_name(self):
- args = ', '.join([ARG._short_name() for ARG in self.ARGS])
- return "Func(%s)->%s" % (args, self.RESULT._short_name)
-
- def _container_example(self):
- def ex(*args):
- return self.RESULT._defl()
- return _func(self, _callable=ex)
-
- def _trueargs(self):
- return [arg for arg in self.ARGS if arg is not Void]
-
-
-class OpaqueType(ContainerType):
-
- def __init__(self, tag):
- self.tag = tag
- self.__name__ = tag
-
- def __str__(self):
- return "%s (opaque)" % self.tag
-
- def _inline_is_varsize(self, last):
- return False # OpaqueType can be inlined
-
- def _container_example(self):
- return _opaque(self)
-
- def _defl(self, parent=None, parentindex=None):
- return _opaque(self, parent=parent, parentindex=parentindex)
-
-RuntimeTypeInfo = OpaqueType("RuntimeTypeInfo")
-
-class PyObjectType(ContainerType):
- __name__ = 'PyObject'
- def __str__(self):
- return "PyObject"
-PyObject = PyObjectType()
-
-class ForwardReference(ContainerType):
- def become(self, realcontainertype):
- if not isinstance(realcontainertype, ContainerType):
- raise TypeError("ForwardReference can only be to a container, "
- "not %r" % (realcontainertype,))
- self.__class__ = realcontainertype.__class__
- self.__dict__ = realcontainertype.__dict__
-
- def __hash__(self):
- raise TypeError("%r object is not hashable" % self.__class__.__name__)
-
-class GcForwardReference(ForwardReference):
- def become(self, realcontainertype):
- if not isinstance(realcontainertype, GC_CONTAINER):
- raise TypeError("GcForwardReference can only be to GcStruct or "
- "GcArray, not %r" % (realcontainertype,))
- self.__class__ = realcontainertype.__class__
- self.__dict__ = realcontainertype.__dict__
-
-GC_CONTAINER = (GcStruct, GcArray, PyObjectType, GcForwardReference)
-
-
-class Primitive(LowLevelType):
- def __init__(self, name, default):
- self._name = self.__name__ = name
- self._default = default
-
- def __str__(self):
- return self._name
-
- def _defl(self, parent=None, parentindex=None):
- return self._default
-
- def _is_atomic(self):
- return True
-
- _example = _defl
-
-
-Signed = Primitive("Signed", 0)
-Unsigned = Primitive("Unsigned", r_uint(0))
-Float = Primitive("Float", 0.0)
-Char = Primitive("Char", '\x00')
-Bool = Primitive("Bool", False)
-Void = Primitive("Void", None)
-UniChar = Primitive("UniChar", u'\x00')
-
-
-class Ptr(LowLevelType):
- __name__ = property(lambda self: '%sPtr' % self.TO.__name__)
-
- def __init__(self, TO):
- if not isinstance(TO, ContainerType):
- raise TypeError, ("can only point to a Container type, "
- "not to %s" % (TO,))
- self.TO = TO
-
- def _needsgc(self):
- return self.TO._gcstatus()
-
- def __str__(self):
- return '* %s' % (self.TO, )
-
- def _short_name(self):
- return 'Ptr %s' % (self.TO._short_name(), )
-
- def _is_atomic(self):
- return not self.TO._gcstatus()
-
- def _defl(self, parent=None, parentindex=None):
- return _ptr(self, None)
-
- def _example(self):
- o = self.TO._container_example()
- return _ptr(self, o, solid=True)
-
-
-# ____________________________________________________________
-
-
-def typeOf(val):
- try:
- return val._TYPE
- except AttributeError:
- tp = type(val)
- if tp is NoneType:
- return Void # maybe
- if tp is int:
- return Signed
- if tp is bool:
- return Bool
- if tp is r_uint:
- return Unsigned
- if tp is float:
- return Float
- if tp is str:
- assert len(val) == 1
- return Char
- if tp is unicode:
- assert len(val) == 1
- return UniChar
- raise TypeError("typeOf(%r object)" % (tp.__name__,))
-
-class InvalidCast(TypeError):
- pass
-
-def _castdepth(OUTSIDE, INSIDE):
- if OUTSIDE == INSIDE:
- return 0
- dwn = 0
- while True:
- first, FIRSTTYPE = OUTSIDE._first_struct()
- if first is None:
- return -1
- dwn += 1
- if FIRSTTYPE == INSIDE:
- return dwn
- OUTSIDE = getattr(OUTSIDE, first)
-
-def castable(PTRTYPE, CURTYPE):
- if CURTYPE._needsgc() != PTRTYPE._needsgc():
- raise TypeError("cast_pointer() cannot change the gc status: %s to %s"
- % (CURTYPE, PTRTYPE))
- if (not isinstance(CURTYPE.TO, Struct) or
- not isinstance(PTRTYPE.TO, Struct)):
- raise InvalidCast(CURTYPE, PTRTYPE)
- CURSTRUC = CURTYPE.TO
- PTRSTRUC = PTRTYPE.TO
- d = _castdepth(CURSTRUC, PTRSTRUC)
- if d >= 0:
- return d
- u = _castdepth(PTRSTRUC, CURSTRUC)
- if u == -1:
- raise InvalidCast(CURTYPE, PTRTYPE)
- return -u
-
-def cast_pointer(PTRTYPE, ptr):
- if not isinstance(ptr, _ptr) or not isinstance(PTRTYPE, Ptr):
- raise TypeError, "can only cast pointers to other pointers"
- CURTYPE = ptr._TYPE
- down_or_up = castable(PTRTYPE, CURTYPE)
- if down_or_up == 0:
- return ptr
- if not ptr: # null pointer cast
- return PTRTYPE._defl()
- if down_or_up > 0:
- p = ptr
- while down_or_up:
- p = getattr(p, typeOf(p).TO._names[0])
- down_or_up -= 1
- return _ptr(PTRTYPE, p._obj)
- u = -down_or_up
- struc = ptr._obj
- while u:
- parent = struc._parentstructure()
- if parent is None:
- raise RuntimeError("widening to trash: %r" % ptr)
- PARENTTYPE = struc._parent_type
- if getattr(parent, PARENTTYPE._names[0]) is not struc:
- raise InvalidCast(CURTYPE, PTRTYPE) # xxx different exception perhaps?
- struc = parent
- u -= 1
- if PARENTTYPE != PTRTYPE.TO:
- raise TypeError("widening %r inside %r instead of %r" % (CURTYPE, PARENTTYPE, PTRTYPE.TO))
- return _ptr(PTRTYPE, struc)
-
-def _expose(val):
- """XXX A nice docstring here"""
- T = typeOf(val)
- if isinstance(T, ContainerType):
- val = _ptr(Ptr(T), val)
- return val
-
-def parentlink(container):
- parent = container._parentstructure()
- if parent is not None:
- return parent, container._parent_index
-## if isinstance(parent, _struct):
-## for name in parent._TYPE._names:
-## if getattr(parent, name) is container:
-## return parent, name
-## raise RuntimeError("lost ourselves")
-## if isinstance(parent, _array):
-## raise TypeError("cannot fish a pointer to an array item or an "
-## "inlined substructure of it")
-## raise AssertionError("don't know about %r" % (parent,))
- else:
- return None, None
-
-
-class _ptr(object):
- __slots__ = ('_TYPE', '_T',
- '_weak', '_solid',
- '_obj0', '__weakref__')
-
- def _set_TYPE(self, TYPE):
- _ptr._TYPE.__set__(self, TYPE)
-
- def _set_T(self, T):
- _ptr._T.__set__(self, T)
-
- def _set_weak(self, weak):
- _ptr._weak.__set__(self, weak)
-
- def _set_solid(self, solid):
- _ptr._solid.__set__(self, solid)
-
- def _set_obj0(self, obj):
- _ptr._obj0.__set__(self, obj)
-
- def _needsgc(self):
- return self._TYPE._needsgc() # xxx other rules?
-
- def __init__(self, TYPE, pointing_to, solid=False):
- self._set_TYPE(TYPE)
- self._set_T(TYPE.TO)
- self._set_weak(False)
- self._setobj(pointing_to, solid)
-
- def __eq__(self, other):
- if not isinstance(other, _ptr):
- raise TypeError("comparing pointer with %r object" % (
- type(other).__name__,))
- if self._TYPE != other._TYPE:
- raise TypeError("comparing %r and %r" % (self._TYPE, other._TYPE))
- return self._obj is other._obj
-
- def __ne__(self, other):
- return not (self == other)
-
- def __hash__(self):
- raise TypeError("pointer objects are not hashable")
-
- def __nonzero__(self):
- return self._obj is not None
-
- # _setobj, _getobj and _obj0 are really _internal_ implementations details of _ptr,
- # use _obj if necessary instead !
- def _setobj(self, pointing_to, solid=False):
- if pointing_to is None:
- obj0 = None
- elif solid or isinstance(self._T, (GC_CONTAINER, FuncType)):
- obj0 = pointing_to
- else:
- self._set_weak(True)
- obj0 = weakref.ref(pointing_to)
- self._set_solid(solid)
- self._set_obj0(obj0)
-
- def _getobj(self):
- obj = self._obj0
- if obj is not None and self._weak:
- obj = obj()
- if obj is None:
- raise RuntimeError("accessing already garbage collected %r"
- % (self._T,))
- obj._check()
- return obj
- _obj = property(_getobj)
-
- def __getattr__(self, field_name): # ! can only return basic or ptr !
- if isinstance(self._T, Struct):
- if field_name in self._T._flds:
- o = getattr(self._obj, field_name)
- return _expose(o)
- raise AttributeError("%r instance has no field %r" % (self._T,
- field_name))
-
- #def _setfirst(self, p):
- # if isinstance(self._T, Struct) and self._T._names:
- # if not isinstance(p, _ptr) or not isinstance(p._obj, _struct):
- # raise InvalidCast(typeOf(p), typeOf(self))
- # field_name = self._T._names[0]
- # T1 = self._T._flds[field_name]
- # T2 = typeOf(p._obj)
- # if T1 != T2:
- # raise InvalidCast(typeOf(p), typeOf(self))
- # setattr(self._obj, field_name, p._obj)
- # p._obj._setparentstructure(self._obj, 0)
- # return
- # raise TypeError("%r instance has no first field" % (self._T,))
-
- def __setattr__(self, field_name, val):
- if isinstance(self._T, Struct):
- if field_name in self._T._flds:
- T1 = self._T._flds[field_name]
- T2 = typeOf(val)
- if T1 == T2:
- setattr(self._obj, field_name, val)
- else:
- raise TypeError("%r instance field %r:\n"
- "expects %r\n"
- " got %r" % (self._T, field_name, T1, T2))
- return
- raise AttributeError("%r instance has no field %r" % (self._T,
- field_name))
-
- def __getitem__(self, i): # ! can only return basic or ptr !
- if isinstance(self._T, Array):
- if not (0 <= i < len(self._obj.items)):
- raise IndexError("array index out of bounds")
- o = self._obj.items[i]
- return _expose(o)
- raise TypeError("%r instance is not an array" % (self._T,))
-
- def __setitem__(self, i, val):
- if isinstance(self._T, Array):
- T1 = self._T.OF
- if isinstance(T1, ContainerType):
- raise TypeError("cannot directly assign to container array items")
- T2 = typeOf(val)
- if T2 != T1:
- raise TypeError("%r items:\n"
- "expect %r\n"
- " got %r" % (self._T, T1, T2))
- if not (0 <= i < len(self._obj.items)):
- raise IndexError("array index out of bounds")
- self._obj.items[i] = val
- return
- raise TypeError("%r instance is not an array" % (self._T,))
-
- def __len__(self):
- if isinstance(self._T, Array):
- return len(self._obj.items)
- raise TypeError("%r instance is not an array" % (self._T,))
-
- def __repr__(self):
- return '<%s>' % (self,)
-
- def __str__(self):
- return '* %s' % (self._obj, )
-
- def __call__(self, *args):
- if isinstance(self._T, FuncType):
- if len(args) != len(self._T.ARGS):
- raise TypeError,"calling %r with wrong argument number: %r" % (self._T, args)
- for a, ARG in zip(args, self._T.ARGS):
- if typeOf(a) != ARG:
- raise TypeError,"calling %r with wrong argument types: %r" % (self._T, args)
- callb = self._obj._callable
- if callb is None:
- raise RuntimeError,"calling undefined function"
- return callb(*args)
- raise TypeError("%r instance is not a function" % (self._T,))
-
-assert not '__dict__' in dir(_ptr)
-
-class _parentable(object):
- _kind = "?"
-
- __slots__ = ('_TYPE',
- '_parent_type', '_parent_index', '_keepparent',
- '_wrparent',
- '__weakref__')
-
- def __init__(self, TYPE):
- self._wrparent = None
- self._TYPE = TYPE
-
- def _setparentstructure(self, parent, parentindex):
- self._wrparent = weakref.ref(parent)
- self._parent_type = typeOf(parent)
- self._parent_index = parentindex
- if (isinstance(self._parent_type, Struct)
- and parentindex == self._parent_type._names[0]
- and self._TYPE._gcstatus() == typeOf(parent)._gcstatus()):
- # keep strong reference to parent, we share the same allocation
- self._keepparent = parent
-
- def _parentstructure(self):
- if self._wrparent is not None:
- parent = self._wrparent()
- if parent is None:
- raise RuntimeError("accessing sub%s %r,\n"
- "but already garbage collected parent %r"
- % (self._kind, self, self._parent_type))
- parent._check()
- return parent
- return None
-
- def _check(self):
- self._parentstructure()
-
-
-def _struct_variety(flds, cache={}):
- flds = list(flds)
- flds.sort()
- tag = tuple(flds)
- try:
- return cache[tag]
- except KeyError:
- class _struct1(_struct):
- __slots__ = flds
- cache[tag] = _struct1
- return _struct1
-
-class _struct(_parentable):
- _kind = "structure"
-
- __slots__ = ()
-
- def __new__(self, TYPE, n=None, parent=None, parentindex=None):
- my_variety = _struct_variety(TYPE._names)
- return object.__new__(my_variety)
-
- def __init__(self, TYPE, n=None, parent=None, parentindex=None):
- _parentable.__init__(self, TYPE)
- if n is not None and TYPE._arrayfld is None:
- raise TypeError("%r is not variable-sized" % (TYPE,))
- if n is None and TYPE._arrayfld is not None:
- raise TypeError("%r is variable-sized" % (TYPE,))
- for fld, typ in TYPE._flds.items():
- if fld == TYPE._arrayfld:
- value = _array(typ, n, parent=self, parentindex=fld)
- else:
- value = typ._defl(parent=self, parentindex=fld)
- setattr(self, fld, value)
- if parent is not None:
- self._setparentstructure(parent, parentindex)
-
- def __repr__(self):
- return '<%s>' % (self,)
-
- def _str_fields(self):
- fields = []
- for name in self._TYPE._names:
- T = self._TYPE._flds[name]
- if isinstance(T, Primitive):
- reprvalue = repr(getattr(self, name))
- else:
- reprvalue = '...'
- fields.append('%s=%s' % (name, reprvalue))
- return ', '.join(fields)
-
- def __str__(self):
- return 'struct %s { %s }' % (self._TYPE._name, self._str_fields())
-
-class _array(_parentable):
- _kind = "array"
-
- __slots__ = ('items',)
-
- def __init__(self, TYPE, n, parent=None, parentindex=None):
- if not isinstance(n, int):
- raise TypeError, "array length must be an int"
- if n < 0:
- raise ValueError, "negative array length"
- _parentable.__init__(self, TYPE)
- self.items = [TYPE.OF._defl(parent=self, parentindex=j)
- for j in range(n)]
- if parent is not None:
- self._setparentstructure(parent, parentindex)
-
- def __repr__(self):
- return '<%s>' % (self,)
-
- def _str_item(self, item):
- if isinstance(self._TYPE.OF, Struct):
- of = self._TYPE.OF
- if self._TYPE._anonym_struct:
- return "{%s}" % item._str_fields()
- else:
- return "%s {%s}" % (of._name, item._str_fields())
- else:
- return item
-
- def __str__(self):
- return 'array [ %s ]' % (', '.join(['%s' % self._str_item(item)
- for item in self.items]),)
-
-assert not '__dict__' in dir(_array)
-assert not '__dict__' in dir(_struct)
-
-
-class _func(object):
- def __init__(self, TYPE, **attrs):
- self._TYPE = TYPE
- self._name = "?"
- self._callable = None
- self.__dict__.update(attrs)
-
- def _parentstructure(self):
- return None
-
- def _check(self):
- pass
-
- def __repr__(self):
- return '<%s>' % (self,)
-
- def __str__(self):
- return "fn %s" % self._name
-
- def __eq__(self, other):
- return (self.__class__ is other.__class__ and
- self.__dict__ == other.__dict__)
-
- def __ne__(self, other):
- return not (self == other)
-
- def __hash__(self):
- return hash(frozendict(self.__dict__))
-
-class _opaque(_parentable):
- def __init__(self, TYPE, parent=None, parentindex=None, **attrs):
- _parentable.__init__(self, TYPE)
- self._name = "?"
- self.__dict__.update(attrs)
- if parent is not None:
- self._setparentstructure(parent, parentindex)
-
- def __repr__(self):
- return '<%s>' % (self,)
-
- def __str__(self):
- return "%s %s" % (self._TYPE.__name__, self._name)
-
-
-class _pyobject(Hashable):
- __slots__ = [] # or we get in trouble with pickling
-
- _TYPE = PyObject
-
- def _parentstructure(self):
- return None
-
- def _check(self):
- pass
-
- def __repr__(self):
- return '<%s>' % (self,)
-
- def __str__(self):
- return "pyobject %s" % (super(_pyobject, self).__str__(),)
-
-
-def malloc(T, n=None, flavor='gc', immortal=False):
- if isinstance(T, Struct):
- o = _struct(T, n)
- elif isinstance(T, Array):
- o = _array(T, n)
- else:
- raise TypeError, "malloc for Structs and Arrays only"
- if not isinstance(T, GC_CONTAINER) and not immortal and flavor.startswith('gc'):
- raise TypeError, "gc flavor malloc of a non-GC non-immortal structure"
- solid = immortal or not flavor.startswith('gc') # immortal or non-gc case
- return _ptr(Ptr(T), o, solid)
-
-def flavored_malloc(flavor, T, n=None): # avoids keyword argument usage
- return malloc(T, n, flavor=flavor)
-
-
-def functionptr(TYPE, name, **attrs):
- if not isinstance(TYPE, FuncType):
- raise TypeError, "functionptr() for FuncTypes only"
- try:
- hash(tuple(attrs.items()))
- except TypeError:
- raise TypeError("'%r' must be hashable"%attrs)
- o = _func(TYPE, _name=name, **attrs)
- return _ptr(Ptr(TYPE), o)
-
-def nullptr(T):
- return Ptr(T)._defl()
-
-def opaqueptr(TYPE, name, **attrs):
- if not isinstance(TYPE, OpaqueType):
- raise TypeError, "opaqueptr() for OpaqueTypes only"
- o = _opaque(TYPE, _name=name, **attrs)
- return _ptr(Ptr(TYPE), o, solid=attrs.get('immortal', True))
-
-def pyobjectptr(obj):
- o = _pyobject(obj)
- return _ptr(Ptr(PyObject), o)
-
-def cast_ptr_to_int(ptr):
- obj = ptr._obj
- while obj._parentstructure():
- obj = obj._parentstructure()
- return id(obj)
-
-
-def attachRuntimeTypeInfo(GCSTRUCT, funcptr=None):
- if not isinstance(GCSTRUCT, GcStruct):
- raise TypeError, "expected a GcStruct: %s" % GCSTRUCT
- GCSTRUCT._attach_runtime_type_info_funcptr(funcptr)
- return _ptr(Ptr(RuntimeTypeInfo), GCSTRUCT._runtime_type_info)
-
-def getRuntimeTypeInfo(GCSTRUCT):
- if not isinstance(GCSTRUCT, GcStruct):
- raise TypeError, "expected a GcStruct: %s" % GCSTRUCT
- if GCSTRUCT._runtime_type_info is None:
- raise ValueError, "no attached runtime type info for %s" % GCSTRUCT
- return _ptr(Ptr(RuntimeTypeInfo), GCSTRUCT._runtime_type_info)
-
-def runtime_type_info(p):
- T = typeOf(p)
- if not isinstance(T, Ptr) or not isinstance(T.TO, GcStruct):
- raise TypeError, "runtime_type_info on non-GcStruct pointer: %s" % p
- top_parent = struct = p._obj
- while True:
- parent = top_parent._parentstructure()
- if parent is None:
- break
- top_parent = parent
- result = getRuntimeTypeInfo(top_parent._TYPE)
- static_info = getRuntimeTypeInfo(T.TO)
- query_funcptr = getattr(static_info._obj, 'query_funcptr', None)
- if query_funcptr is not None:
- T = typeOf(query_funcptr).TO.ARGS[0]
- result2 = query_funcptr(cast_pointer(T, p))
- if result != result2:
- raise RuntimeError, ("runtime type-info function for %s:\n"
- " returned: %s,\n"
- "should have been: %s" % (p, result2, result))
- return result
-
+from pypy.rpython.lltypesystem.lltype import * # FIXME
Added: pypy/branch/hl-backend/pypy/rpython/lltypesystem/__init__.py
==============================================================================
Modified: pypy/branch/hl-backend/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/rbuiltin.py (original)
+++ pypy/branch/hl-backend/pypy/rpython/rbuiltin.py Thu Oct 13 16:47:44 2005
@@ -10,7 +10,6 @@
from pypy.rpython.rfloat import float_repr, FloatRepr
from pypy.rpython.rbool import bool_repr
from pypy.rpython.rdict import rtype_r_dict
-from pypy.rpython import rclass
from pypy.tool import sourcetools
class __extend__(annmodel.SomeBuiltin):
@@ -55,8 +54,12 @@
try:
bltintyper = BUILTIN_TYPER[self.builtinfunc]
except KeyError:
- raise TyperError("don't know about built-in function %r" % (
- self.builtinfunc,))
+ try:
+ rtyper = hop.rtyper
+ bltintyper = rtyper.type_system.BUILTIN_TYPER[self.builtinfunc]
+ except KeyError:
+ raise TyperError("don't know about built-in function %r" % (
+ self.builtinfunc,))
hop2 = hop.copy()
hop2.r_s_popfirstarg()
return bltintyper(hop2)
@@ -129,36 +132,6 @@
def rtype_builtin_list(hop):
return hop.args_r[0].rtype_bltn_list(hop)
-def rtype_builtin_isinstance(hop):
- if hop.s_result.is_constant():
- return hop.inputconst(lltype.Bool, hop.s_result.const)
- if hop.args_r[0] == pyobj_repr or hop.args_r[1] == pyobj_repr:
- v_obj, v_typ = hop.inputargs(pyobj_repr, pyobj_repr)
- c = hop.inputconst(pyobj_repr, isinstance)
- v = hop.genop('simple_call', [c, v_obj, v_typ], resulttype = pyobj_repr)
- return hop.llops.convertvar(v, pyobj_repr, bool_repr)
-
- if hop.args_s[1].is_constant() and hop.args_s[1].const == list:
- if hop.args_s[0].knowntype != list:
- raise TyperError("isinstance(x, list) expects x to be known statically to be a list or None")
- rlist = hop.args_r[0]
- vlist = hop.inputarg(rlist, arg=0)
- cnone = hop.inputconst(rlist, None)
- return hop.genop('ptr_ne', [vlist, cnone], resulttype=lltype.Bool)
-
- class_repr = rclass.get_type_repr(hop.rtyper)
- assert isinstance(hop.args_r[0], rclass.InstanceRepr)
- instance_repr = hop.args_r[0].common_repr()
-
- v_obj, v_cls = hop.inputargs(instance_repr, class_repr)
- if isinstance(v_cls, Constant):
- minid = hop.inputconst(lltype.Signed, v_cls.value.subclassrange_min)
- maxid = hop.inputconst(lltype.Signed, v_cls.value.subclassrange_max)
- return hop.gendirectcall(rclass.ll_isinstance_const, v_obj, minid,
- maxid)
- else:
- return hop.gendirectcall(rclass.ll_isinstance, v_obj, v_cls)
-
#def rtype_builtin_range(hop): see rrange.py
#def rtype_builtin_xrange(hop): see rrange.py
@@ -212,24 +185,6 @@
v_errno = hop.inputarg(lltype.Signed, arg=1)
r_self.setfield(v_self, 'errno', v_errno, hop.llops)
-def ll_instantiate(typeptr):
- my_instantiate = typeptr.instantiate
- return my_instantiate()
-
-def rtype_instantiate(hop):
- s_class = hop.args_s[0]
- assert isinstance(s_class, annmodel.SomePBC)
- if len(s_class.prebuiltinstances) != 1:
- # instantiate() on a variable class
- vtypeptr, = hop.inputargs(rclass.get_type_repr(hop.rtyper))
- v_inst = hop.gendirectcall(ll_instantiate, vtypeptr)
- return hop.genop('cast_pointer', [v_inst], # v_type implicit in r_result
- resulttype = hop.r_result.lowleveltype)
-
-
- klass = s_class.const
- return rclass.rtype_new_instance(hop.rtyper, klass, hop.llops)
-
def rtype_we_are_translated(hop):
return hop.inputconst(lltype.Bool, True)
@@ -319,7 +274,6 @@
BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask
BUILTIN_TYPER[rarithmetic.r_uint] = rtype_r_uint
BUILTIN_TYPER[objectmodel.r_dict] = rtype_r_dict
-BUILTIN_TYPER[objectmodel.instantiate] = rtype_instantiate
BUILTIN_TYPER[objectmodel.we_are_translated] = rtype_we_are_translated
BUILTIN_TYPER[objectmodel.hlinvoke] = rtype_hlinvoke
Modified: pypy/branch/hl-backend/pypy/rpython/rclass.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/rclass.py (original)
+++ pypy/branch/hl-backend/pypy/rpython/rclass.py Thu Oct 13 16:47:44 2005
@@ -4,61 +4,7 @@
from pypy.annotation import model as annmodel
from pypy.annotation.classdef import isclassdef
from pypy.objspace.flow.model import Constant
-from pypy.rpython.rmodel import Repr, TyperError, inputconst, warning, needsgc
-from pypy.rpython.lltype import ForwardReference, GcForwardReference
-from pypy.rpython.lltype import Ptr, Struct, GcStruct, malloc
-from pypy.rpython.lltype import cast_pointer, castable, nullptr
-from pypy.rpython.lltype import RuntimeTypeInfo, getRuntimeTypeInfo, typeOf
-from pypy.rpython.lltype import Array, Char, Void, attachRuntimeTypeInfo
-from pypy.rpython.lltype import FuncType, Bool, Signed
-
-#
-# There is one "vtable" per user class, with the following structure:
-# A root class "object" has:
-#
-# struct object_vtable {
-# struct object_vtable* parenttypeptr;
-# RuntimeTypeInfo * rtti;
-# Signed subclassrange_min; //this is also the id of the class itself
-# Signed subclassrange_max;
-# array { char } * name;
-# struct object * instantiate();
-# }
-#
-# Every other class X, with parent Y, has the structure:
-#
-# struct vtable_X {
-# struct vtable_Y super; // inlined
-# ... // extra class attributes
-# }
-
-# The type of the instances is:
-#
-# struct object { // for the root class
-# struct object_vtable* typeptr;
-# }
-#
-# struct X {
-# struct Y super; // inlined
-# ... // extra instance attributes
-# }
-#
-# there's also a nongcobject
-
-OBJECT_VTABLE = ForwardReference()
-TYPEPTR = Ptr(OBJECT_VTABLE)
-OBJECT = GcStruct('object', ('typeptr', TYPEPTR))
-OBJECTPTR = Ptr(OBJECT)
-OBJECT_VTABLE.become(Struct('object_vtable',
- ('parenttypeptr', TYPEPTR),
- ('subclassrange_min', Signed),
- ('subclassrange_max', Signed),
- ('rtti', Ptr(RuntimeTypeInfo)),
- ('name', Ptr(Array(Char))),
- ('instantiate', Ptr(FuncType([], OBJECTPTR)))))
-# non-gc case
-NONGCOBJECT = Struct('nongcobject', ('typeptr', TYPEPTR))
-NONGCOBJECTPTR = Ptr(OBJECT)
+from pypy.rpython.rmodel import Repr, TyperError, needsgc
def getclassrepr(rtyper, classdef):
try:
@@ -74,7 +20,7 @@
"have any attribute attached to it")
result = getclassrepr(rtyper, None)
else:
- result = ClassRepr(rtyper, classdef)
+ result = rtyper.type_system.rclass.ClassRepr(rtyper, classdef)
rtyper.class_reprs[classdef] = result
rtyper.add_pendingsetup(result)
return result
@@ -88,7 +34,9 @@
# see getclassrepr()
result = getinstancerepr(rtyper, None, nogc=False)
else:
- result = InstanceRepr(rtyper,classdef, does_need_gc=does_need_gc)
+ result = rtyper.type_system.rclass.InstanceRepr(
+ rtyper, classdef, does_need_gc=does_need_gc)
+
rtyper.instance_reprs[classdef, does_need_gc] = result
rtyper.add_pendingsetup(result)
return result
@@ -96,23 +44,13 @@
class MissingRTypeAttribute(TyperError):
pass
-
-def cast_vtable_to_typeptr(vtable):
- while typeOf(vtable).TO != OBJECT_VTABLE:
- vtable = vtable.super
- return vtable
-
-
-class ClassRepr(Repr):
+class AbstractClassRepr(Repr):
def __init__(self, rtyper, classdef):
self.rtyper = rtyper
self.classdef = classdef
- if classdef is None:
- # 'object' root type
- self.vtable_type = OBJECT_VTABLE
- else:
- self.vtable_type = ForwardReference()
- self.lowleveltype = Ptr(self.vtable_type)
+
+ def _setup_repr(self):
+ pass
def __repr__(self):
if self.classdef is None:
@@ -128,79 +66,6 @@
cls = self.classdef.cls
return 'ClassR %s.%s' % (cls.__module__, cls.__name__)
- def _setup_repr(self):
- # NOTE: don't store mutable objects like the dicts below on 'self'
- # before they are fully built, to avoid strange bugs in case
- # of recursion where other code would uses these
- # partially-initialized dicts.
- clsfields = {}
- pbcfields = {}
- allmethods = {}
- if self.classdef is not None:
- # class attributes
- llfields = []
- attrs = self.classdef.attrs.items()
- attrs.sort()
- for name, attrdef in attrs:
- if attrdef.readonly:
- s_value = attrdef.s_value
- s_value = self.prepare_method(name, s_value, allmethods)
- r = self.rtyper.getrepr(s_value)
- mangled_name = 'cls_' + name
- clsfields[name] = mangled_name, r
- llfields.append((mangled_name, r.lowleveltype))
- # attributes showing up in getattrs done on the class as a PBC
- extra_access_sets = self.rtyper.class_pbc_attributes.get(
- self.classdef, {})
- for access_set, counter in extra_access_sets.items():
- for attr, s_value in access_set.attrs.items():
- r = self.rtyper.getrepr(s_value)
- mangled_name = 'pbc%d_%s' % (counter, attr)
- pbcfields[access_set, attr] = mangled_name, r
- llfields.append((mangled_name, r.lowleveltype))
- #
- self.rbase = getclassrepr(self.rtyper, self.classdef.basedef)
- self.rbase.setup()
- vtable_type = Struct('%s_vtable' % self.classdef.cls.__name__,
- ('super', self.rbase.vtable_type),
- *llfields)
- self.vtable_type.become(vtable_type)
- allmethods.update(self.rbase.allmethods)
- self.clsfields = clsfields
- self.pbcfields = pbcfields
- self.allmethods = allmethods
- self.vtable = None
-
- def prepare_method(self, name, s_value, allmethods):
- # special-casing for methods:
- # - a class (read-only) attribute that would contain a PBC
- # with {func: classdef...} is probably meant to be used as a
- # method, but in corner cases it could be a constant object
- # of type MethodType that just sits here in the class. But
- # as MethodType has a custom __get__ too and we don't support
- # it, it's a very bad idea anyway.
- if isinstance(s_value, annmodel.SomePBC):
- s_value = self.classdef.matching(s_value)
- debound = {}
- count = 0
- for x, classdef in s_value.prebuiltinstances.items():
- if isclassdef(classdef):
- #if classdef.commonbase(self.classdef) != self.classdef:
- # raise TyperError("methods from PBC set %r don't belong "
- # "in %r" % (s_value.prebuiltinstances,
- # self.classdef.cls))
- count += 1
- classdef = True
- debound[x] = classdef
- if count > 0:
- if count != len(s_value.prebuiltinstances):
- raise TyperError("mixing functions and methods "
- "in PBC set %r" % (
- s_value.prebuiltinstances,))
- s_value = annmodel.SomePBC(debound)
- allmethods[name] = True
- return s_value
-
def convert_const(self, value):
if not isinstance(value, (type, types.ClassType)):
raise TyperError("not a class: %r" % (value,))
@@ -213,150 +78,11 @@
raise TyperError("not a subclass of %r: %r" % (
self.classdef.cls, value))
#
- return getclassrepr(self.rtyper, subclassdef).getvtable()
+ return getclassrepr(self.rtyper, subclassdef).getruntime()
def get_ll_eq_function(self):
return None
- def getvtable(self, cast_to_typeptr=True):
- """Return a ptr to the vtable of this type."""
- if self.vtable is None:
- self.vtable = malloc(self.vtable_type, immortal=True)
- self.setup_vtable(self.vtable, self)
- #
- vtable = self.vtable
- if cast_to_typeptr:
- vtable = cast_vtable_to_typeptr(vtable)
- return vtable
-
- def setup_vtable(self, vtable, rsubcls):
- """Initialize the 'self' portion of the 'vtable' belonging to the
- given subclass."""
- if self.classdef is None:
- # initialize the 'parenttypeptr' and 'name' fields
- if rsubcls.classdef is not None:
- vtable.parenttypeptr = rsubcls.rbase.getvtable()
- vtable.subclassrange_min = rsubcls.classdef.minid
- vtable.subclassrange_max = rsubcls.classdef.maxid
- else: #for the root class
- vtable.subclassrange_min = 0
- vtable.subclassrange_max = sys.maxint
- rinstance = getinstancerepr(self.rtyper, rsubcls.classdef)
- rinstance.setup()
- if rinstance.needsgc: # only gc-case
- vtable.rtti = getRuntimeTypeInfo(rinstance.object_type)
- if rsubcls.classdef is None:
- name = 'object'
- else:
- name = rsubcls.classdef.cls.__name__
- vtable.name = malloc(Array(Char), len(name)+1, immortal=True)
- for i in range(len(name)):
- vtable.name[i] = name[i]
- vtable.name[len(name)] = '\x00'
- if hasattr(rsubcls.classdef, 'my_instantiate'):
- fn = rsubcls.classdef.my_instantiate
- vtable.instantiate = self.rtyper.getfunctionptr(fn)
- #else: the classdef was created recently, so no instantiate()
- # could reach it
- else:
- # setup class attributes: for each attribute name at the level
- # of 'self', look up its value in the subclass rsubcls
- def assign(mangled_name, value):
- if isinstance(value, staticmethod):
- value = value.__get__(42) # staticmethod => bare function
- llvalue = r.convert_const(value)
- setattr(vtable, mangled_name, llvalue)
-
- mro = list(rsubcls.classdef.getmro())
- for fldname in self.clsfields:
- mangled_name, r = self.clsfields[fldname]
- if r.lowleveltype is Void:
- continue
- for clsdef in mro:
- if fldname in clsdef.cls.__dict__:
- value = clsdef.cls.__dict__[fldname]
- assign(mangled_name, value)
- break
- # extra PBC attributes
- for (access_set, attr), (mangled_name, r) in self.pbcfields.items():
- if r.lowleveltype is Void:
- continue
- for clsdef in mro:
- try:
- thisattrvalue = access_set.values[clsdef.cls, attr]
- except KeyError:
- if attr not in clsdef.cls.__dict__:
- continue
- thisattrvalue = clsdef.cls.__dict__[attr]
- assign(mangled_name, thisattrvalue)
- break
-
- # then initialize the 'super' portion of the vtable
- self.rbase.setup_vtable(vtable.super, rsubcls)
-
- #def fromparentpart(self, v_vtableptr, llops):
- # """Return the vtable pointer cast from the parent vtable's type
- # to self's vtable type."""
-
- def fromtypeptr(self, vcls, llops):
- """Return the type pointer cast to self's vtable type."""
- castable(self.lowleveltype, vcls.concretetype) # sanity check
- return llops.genop('cast_pointer', [vcls],
- resulttype=self.lowleveltype)
-
- def getclsfieldrepr(self, attr):
- """Return the repr used for the given attribute."""
- if attr in self.clsfields:
- mangled_name, r = self.clsfields[attr]
- return r
- else:
- if self.classdef is None:
- raise MissingRTypeAttribute(attr)
- return self.rbase.getfieldrepr(attr)
-
- def getclsfield(self, vcls, attr, llops):
- """Read the given attribute of 'vcls'."""
- if attr in self.clsfields:
- mangled_name, r = self.clsfields[attr]
- v_vtable = self.fromtypeptr(vcls, llops)
- cname = inputconst(Void, mangled_name)
- return llops.genop('getfield', [v_vtable, cname], resulttype=r)
- else:
- if self.classdef is None:
- raise MissingRTypeAttribute(attr)
- return self.rbase.getclsfield(vcls, attr, llops)
-
- def setclsfield(self, vcls, attr, vvalue, llops):
- """Write the given attribute of 'vcls'."""
- if attr in self.clsfields:
- mangled_name, r = self.clsfields[attr]
- v_vtable = self.fromtypeptr(vcls, llops)
- cname = inputconst(Void, mangled_name)
- llops.genop('setfield', [v_vtable, cname, vvalue])
- else:
- if self.classdef is None:
- raise MissingRTypeAttribute(attr)
- self.rbase.setclsfield(vcls, attr, vvalue, llops)
-
- def getpbcfield(self, vcls, access_set, attr, llops):
- if (access_set, attr) not in self.pbcfields:
- raise TyperError("internal error: missing PBC field")
- mangled_name, r = self.pbcfields[access_set, attr]
- v_vtable = self.fromtypeptr(vcls, llops)
- cname = inputconst(Void, mangled_name)
- return llops.genop('getfield', [v_vtable, cname], resulttype=r)
-
- def rtype_issubtype(self, hop):
- class_repr = get_type_repr(self.rtyper)
- v_cls1, v_cls2 = hop.inputargs(class_repr, class_repr)
- if isinstance(v_cls2, Constant):
- minid = hop.inputconst(Signed, v_cls2.value.subclassrange_min)
- maxid = hop.inputconst(Signed, v_cls2.value.subclassrange_max)
- return hop.gendirectcall(ll_issubclass_const, v_cls1, minid, maxid)
- else:
- v_cls1, v_cls2 = hop.inputargs(class_repr, class_repr)
- return hop.gendirectcall(ll_issubclass, v_cls1, v_cls2)
-
def get_type_repr(rtyper):
return getclassrepr(rtyper, None)
@@ -370,24 +96,13 @@
return self.__class__, self.classdef
-class InstanceRepr(Repr):
- def __init__(self, rtyper, classdef, does_need_gc=True):
+class AbstractInstanceRepr(Repr):
+ def __init__(self, rtyper, classdef):
self.rtyper = rtyper
self.classdef = classdef
- if classdef is None:
- if does_need_gc:
- self.object_type = OBJECT
- else:
- self.object_type = NONGCOBJECT
- else:
- if does_need_gc:
- self.object_type = GcForwardReference()
- else:
- self.object_type = ForwardReference()
-
- self.prebuiltinstances = {} # { id(x): (x, _ptr) }
- self.lowleveltype = Ptr(self.object_type)
- self.needsgc = does_need_gc
+
+ def _setup_repr(self):
+ pass
def __repr__(self):
if self.classdef is None:
@@ -403,308 +118,29 @@
cls = self.classdef.cls
return 'InstanceR %s.%s' % (cls.__module__, cls.__name__)
- def _setup_repr(self):
- # NOTE: don't store mutable objects like the dicts below on 'self'
- # before they are fully built, to avoid strange bugs in case
- # of recursion where other code would uses these
- # partially-initialized dicts.
- self.rclass = getclassrepr(self.rtyper, self.classdef)
- fields = {}
- allinstancefields = {}
- if self.classdef is None:
- fields['__class__'] = 'typeptr', get_type_repr(self.rtyper)
- else:
- # instance attributes
- llfields = []
- attrs = self.classdef.attrs.items()
- attrs.sort()
- for name, attrdef in attrs:
- if not attrdef.readonly:
- r = self.rtyper.getrepr(attrdef.s_value)
- mangled_name = 'inst_' + name
- fields[name] = mangled_name, r
- llfields.append((mangled_name, r.lowleveltype))
- #
- # hash() support
- if self.rtyper.needs_hash_support(self.classdef.cls):
- from pypy.rpython import rint
- fields['_hash_cache_'] = 'hash_cache', rint.signed_repr
- llfields.append(('hash_cache', Signed))
-
- self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef, not self.needsgc)
- self.rbase.setup()
- if self.needsgc:
- MkStruct = GcStruct
- else:
- MkStruct = Struct
-
- object_type = MkStruct(self.classdef.cls.__name__,
- ('super', self.rbase.object_type),
- *llfields)
- self.object_type.become(object_type)
- allinstancefields.update(self.rbase.allinstancefields)
- allinstancefields.update(fields)
- self.fields = fields
- self.allinstancefields = allinstancefields
- if self.needsgc: # only gc-case
- attachRuntimeTypeInfo(self.object_type)
-
def _setup_repr_final(self):
- if self.needsgc: # only gc-case
- self.rtyper.attachRuntimeTypeInfoFunc(self.object_type,
- ll_runtime_type_info,
- OBJECT)
- def common_repr(self): # -> object or nongcobject reprs
- return getinstancerepr(self.rtyper, None, nogc=not self.needsgc)
-
- def getflavor(self):
- return getattr(self.classdef.cls, '_alloc_flavor_', 'gc')
-
- def convert_const(self, value):
- if value is None:
- return nullptr(self.object_type)
- try:
- classdef = self.rtyper.annotator.getuserclasses()[value.__class__]
- except KeyError:
- raise TyperError("no classdef: %r" % (value.__class__,))
- if classdef != self.classdef:
- # if the class does not match exactly, check that 'value' is an
- # instance of a subclass and delegate to that InstanceRepr
- if classdef is None:
- raise TyperError("not implemented: object() instance")
- if classdef.commonbase(self.classdef) != self.classdef:
- raise TyperError("not an instance of %r: %r" % (
- self.classdef.cls, value))
- rinstance = getinstancerepr(self.rtyper, classdef)
- result = rinstance.convert_const(value)
- return cast_pointer(self.lowleveltype, result)
- # common case
- try:
- return self.prebuiltinstances[id(value)][1]
- except KeyError:
- self.setup()
- result = malloc(self.object_type, flavor=self.getflavor()) # pick flavor
- self.prebuiltinstances[id(value)] = value, result
- self.initialize_prebuilt_instance(value, classdef, result)
- return result
-
- def get_ll_eq_function(self):
- return ll_inst_eq
-
- def get_ll_hash_function(self):
- if self.classdef is None:
- return None
- if self.rtyper.needs_hash_support( self.classdef.cls):
- try:
- return self._ll_hash_function
- except AttributeError:
- INSPTR = self.lowleveltype
- def _ll_hash_function(ins):
- return ll_inst_hash(cast_pointer(INSPTR, ins))
- self._ll_hash_function = _ll_hash_function
- return _ll_hash_function
- else:
- return self.rbase.get_ll_hash_function()
-
- def initialize_prebuilt_instance(self, value, classdef, result):
- if self.classdef is not None:
- # recursively build the parent part of the instance
- self.rbase.initialize_prebuilt_instance(value, classdef,
- result.super)
- # then add instance attributes from this level
- for name, (mangled_name, r) in self.fields.items():
- if r.lowleveltype is Void:
- llattrvalue = None
- elif name == '_hash_cache_': # hash() support
- llattrvalue = hash(value)
- else:
- try:
- attrvalue = getattr(value, name)
- except AttributeError:
- warning("prebuilt instance %r has no attribute %r" % (
- value, name))
- continue
- llattrvalue = r.convert_const(attrvalue)
- setattr(result, mangled_name, llattrvalue)
- else:
- # OBJECT part
- rclass = getclassrepr(self.rtyper, classdef)
- result.typeptr = rclass.getvtable()
-
- #def parentpart(self, vinst, llops):
- # """Return the pointer 'vinst' cast to the parent type."""
- # cname = inputconst(Void, 'super')
- # return llops.genop('getsubstruct', [vinst, cname],
- # resulttype=self.rbase.lowleveltype)
-
- def getfieldrepr(self, attr):
- """Return the repr used for the given attribute."""
- if attr in self.fields:
- mangled_name, r = self.fields[attr]
- return r
- else:
- if self.classdef is None:
- raise MissingRTypeAttribute(attr)
- return self.rbase.getfieldrepr(attr)
-
- def getfield(self, vinst, attr, llops, force_cast=False):
- """Read the given attribute (or __class__ for the type) of 'vinst'."""
- if attr in self.fields:
- mangled_name, r = self.fields[attr]
- cname = inputconst(Void, mangled_name)
- if force_cast:
- vinst = llops.genop('cast_pointer', [vinst], resulttype=self)
- return llops.genop('getfield', [vinst, cname], resulttype=r)
- else:
- if self.classdef is None:
- raise MissingRTypeAttribute(attr)
- return self.rbase.getfield(vinst, attr, llops, force_cast=True)
-
- def setfield(self, vinst, attr, vvalue, llops, force_cast=False):
- """Write the given attribute (or __class__ for the type) of 'vinst'."""
- if attr in self.fields:
- mangled_name, r = self.fields[attr]
- cname = inputconst(Void, mangled_name)
- if force_cast:
- vinst = llops.genop('cast_pointer', [vinst], resulttype=self)
- llops.genop('setfield', [vinst, cname, vvalue])
- else:
- if self.classdef is None:
- raise MissingRTypeAttribute(attr)
- self.rbase.setfield(vinst, attr, vvalue, llops, force_cast=True)
+ pass
def new_instance(self, llops):
- """Build a new instance, without calling __init__."""
- mallocop = 'malloc'
- ctype = inputconst(Void, self.object_type)
- vlist = [ctype]
- if self.classdef is not None:
- flavor = self.getflavor()
- if flavor != 'gc': # not defalut flavor
- mallocop = 'flavored_malloc'
- vlist = [inputconst(Void, flavor)] + vlist
- vptr = llops.genop(mallocop, vlist,
- resulttype = Ptr(self.object_type)) # xxx flavor
- ctypeptr = inputconst(TYPEPTR, self.rclass.getvtable())
- self.setfield(vptr, '__class__', ctypeptr, llops)
- # initialize instance attributes from their defaults from the class
- if self.classdef is not None:
- flds = self.allinstancefields.keys()
- flds.sort()
- mro = list(self.classdef.getmro())
- for fldname in flds:
- if fldname == '__class__':
- continue
- mangled_name, r = self.allinstancefields[fldname]
- if r.lowleveltype is Void:
- continue
- for clsdef in mro:
- if fldname in clsdef.cls.__dict__:
- value = clsdef.cls.__dict__[fldname]
- cvalue = inputconst(r, value)
- self.setfield(vptr, fldname, cvalue, llops)
- break
- return vptr
+ pass
def rtype_type(self, hop):
- instance_repr = self.common_repr()
- vinst, = hop.inputargs(instance_repr)
- if hop.args_s[0].can_be_none():
- return hop.gendirectcall(ll_inst_type, vinst)
- else:
- return instance_repr.getfield(vinst, '__class__', hop.llops)
+ pass
def rtype_hash(self, hop):
- if self.classdef is None:
- raise TyperError, "hash() not supported for this class"
- if self.rtyper.needs_hash_support( self.classdef.cls):
- vinst, = hop.inputargs(self)
- return hop.gendirectcall(ll_inst_hash, vinst)
- else:
- return self.rbase.rtype_hash(hop)
+ pass
def rtype_getattr(self, hop):
- attr = hop.args_s[1].const
- vinst, vattr = hop.inputargs(self, Void)
- if attr in self.allinstancefields:
- return self.getfield(vinst, attr, hop.llops)
- elif attr in self.rclass.allmethods:
- # special case for methods: represented as their 'self' only
- # (see MethodsPBCRepr)
- return hop.r_result.get_method_from_instance(self, vinst,
- hop.llops)
- else:
- vcls = self.getfield(vinst, '__class__', hop.llops)
- return self.rclass.getclsfield(vcls, attr, hop.llops)
+ pass
def rtype_setattr(self, hop):
- attr = hop.args_s[1].const
- r_value = self.getfieldrepr(attr)
- vinst, vattr, vvalue = hop.inputargs(self, Void, r_value)
- self.setfield(vinst, attr, vvalue, hop.llops)
+ pass
def rtype_is_true(self, hop):
- vinst, = hop.inputargs(self)
- return hop.genop('ptr_nonzero', [vinst], resulttype=Bool)
+ pass
- def ll_str(self, i): # doesn't work for non-gc classes!
- instance = cast_pointer(OBJECTPTR, i)
- from pypy.rpython import rstr
- nameLen = len(instance.typeptr.name)
- nameString = malloc(rstr.STR, nameLen-1)
- i = 0
- while i < nameLen - 1:
- nameString.chars[i] = instance.typeptr.name[i]
- i += 1
- return rstr.ll_strconcat(rstr.instance_str_prefix,
- rstr.ll_strconcat(nameString,
- rstr.instance_str_suffix))
-
-
-class __extend__(pairtype(InstanceRepr, InstanceRepr)):
- def convert_from_to((r_ins1, r_ins2), v, llops):
- # which is a subclass of which?
- if r_ins1.classdef is None or r_ins2.classdef is None:
- basedef = None
- else:
- basedef = r_ins1.classdef.commonbase(r_ins2.classdef)
- if basedef == r_ins2.classdef:
- # r_ins1 is an instance of the subclass: converting to parent
- v = llops.genop('cast_pointer', [v],
- resulttype = r_ins2.lowleveltype)
- return v
- elif basedef == r_ins1.classdef:
- # r_ins2 is an instance of the subclass: potentially unsafe
- # casting, but we do it anyway (e.g. the annotator produces
- # such casts after a successful isinstance() check)
- v = llops.genop('cast_pointer', [v],
- resulttype = r_ins2.lowleveltype)
- return v
- else:
- return NotImplemented
-
- def rtype_is_((r_ins1, r_ins2), hop):
- if r_ins1.needsgc != r_ins2.needsgc:
- # obscure logic, the is can be true only if both are None
- v_ins1, v_ins2 = hop.inputargs(r_ins1.common_repr(), r_ins2.common_repr())
- return hop.gendirectcall(ll_both_none, v_ins1, v_ins2)
- nogc = not (r_ins1.needsgc and r_ins2.needsgc)
- if r_ins1.classdef is None or r_ins2.classdef is None:
- basedef = None
- else:
- basedef = r_ins1.classdef.commonbase(r_ins2.classdef)
- r_ins = getinstancerepr(r_ins1.rtyper, basedef, nogc=nogc)
- return pairtype(Repr, Repr).rtype_is_(pair(r_ins, r_ins), hop)
-
- rtype_eq = rtype_is_
-
- def rtype_ne(rpair, hop):
- v = rpair.rtype_eq(hop)
- return hop.genop("bool_not", [v], resulttype=Bool)
-
-
-def ll_both_none(ins1, ins2):
- return not ins1 and not ins2
+ def ll_str(self, i):
+ pass
# ____________________________________________________________
@@ -719,52 +155,3 @@
except KeyError:
raise TyperError("no classdef: %r" % (cls,))
return annmodel.SomeInstance(classdef)
-
-# ____________________________________________________________
-#
-# Low-level implementation of operations on classes and instances
-
-# doesn't work for non-gc stuff!
-def ll_cast_to_object(obj):
- return cast_pointer(OBJECTPTR, obj)
-
-# doesn't work for non-gc stuff!
-def ll_type(obj):
- return cast_pointer(OBJECTPTR, obj).typeptr
-
-def ll_issubclass(subcls, cls):
- return cls.subclassrange_min <= subcls.subclassrange_min < cls.subclassrange_max
-
-def ll_issubclass_const(subcls, minid, maxid):
- return minid <= subcls.subclassrange_min < maxid
-
-
-def ll_isinstance(obj, cls): # obj should be cast to OBJECT or NONGCOBJECT
- if not obj:
- return False
- obj_cls = obj.typeptr
- return ll_issubclass(obj_cls, cls)
-
-def ll_isinstance_const(obj, minid, maxid):
- if not obj:
- return False
- return ll_issubclass_const(obj.typeptr, minid, maxid)
-
-def ll_runtime_type_info(obj):
- return obj.typeptr.rtti
-
-def ll_inst_hash(ins):
- cached = ins.hash_cache
- if cached == 0:
- cached = ins.hash_cache = id(ins)
- return cached
-
-def ll_inst_eq(ins1, ins2):
- return ins1 == ins2
-
-def ll_inst_type(obj):
- if obj:
- return obj.typeptr
- else:
- # type(None) -> NULL (for now)
- return nullptr(typeOf(obj).TO.typeptr.TO)
Modified: pypy/branch/hl-backend/pypy/rpython/rlist.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/rlist.py (original)
+++ pypy/branch/hl-backend/pypy/rpython/rlist.py Thu Oct 13 16:47:44 2005
@@ -6,7 +6,6 @@
from pypy.rpython.rslice import SliceRepr
from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr
from pypy.rpython.rslice import minusone_slice_repr
-from pypy.rpython.rclass import InstanceRepr
from pypy.rpython.lltype import GcForwardReference, Ptr, GcArray, GcStruct
from pypy.rpython.lltype import Void, Signed, malloc, typeOf, Primitive
from pypy.rpython.lltype import Bool, nullptr
Modified: pypy/branch/hl-backend/pypy/rpython/rpbc.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/rpbc.py (original)
+++ pypy/branch/hl-backend/pypy/rpython/rpbc.py Thu Oct 13 16:47:44 2005
@@ -684,7 +684,7 @@
class_repr = self.get_class_repr()
return class_repr.getpbcfield(vcls, access_set, attr, llops)
-class __extend__(pairtype(ClassesPBCRepr, rclass.ClassRepr)):
+class __extend__(pairtype(ClassesPBCRepr, rclass.AbstractClassRepr)):
def convert_from_to((r_clspbc, r_cls), v, llops):
if r_cls.lowleveltype != r_clspbc.lowleveltype:
return NotImplemented # good enough for now
Modified: pypy/branch/hl-backend/pypy/rpython/rstr.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/rstr.py (original)
+++ pypy/branch/hl-backend/pypy/rpython/rstr.py Thu Oct 13 16:47:44 2005
@@ -12,7 +12,6 @@
from pypy.rpython.rslice import minusone_slice_repr
from pypy.rpython.lltype import GcStruct, Signed, Array, Char, Ptr, malloc
from pypy.rpython.lltype import Bool, Void, GcArray, nullptr, typeOf, pyobjectptr
-from pypy.rpython.rclass import InstanceRepr
# ____________________________________________________________
@@ -334,6 +333,7 @@
argsiter = iter(sourcevarsrepr)
+ InstanceRepr = hop.rtyper.type_system.rclass.InstanceRepr
for i, thing in enumerate(things):
if isinstance(thing, tuple):
code = thing[0]
Modified: pypy/branch/hl-backend/pypy/rpython/rtyper.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/rtyper.py (original)
+++ pypy/branch/hl-backend/pypy/rpython/rtyper.py Thu Oct 13 16:47:44 2005
@@ -30,8 +30,6 @@
from pypy.rpython.rmodel import warning
from pypy.rpython.normalizecalls import perform_normalizations
from pypy.rpython.annlowlevel import annotate_lowlevel_helper
-from pypy.rpython.exceptiondata import ExceptionData
-
from pypy.rpython.rmodel import log
from pypy.rpython.typesystem import LowLevelTypeSystem,\
ObjectOrientedTypeSystem
@@ -74,7 +72,13 @@
for s_primitive, lltype in annmodel.annotation_to_ll_map:
r = self.getrepr(s_primitive)
self.primitive_to_repr[r.lowleveltype] = r
- self.exceptiondata = ExceptionData(self)
+ if type_system == "lltype":
+ from pypy.rpython.lltypesystem.exceptiondata import ExceptionData
+
+ self.exceptiondata = ExceptionData(self)
+ else:
+ self.exceptiondata = None
+
try:
self.seed = int(os.getenv('RTYPERSEED'))
s = 'Using %d as seed for block shuffling' % self.seed
Modified: pypy/branch/hl-backend/pypy/rpython/typesystem.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/typesystem.py (original)
+++ pypy/branch/hl-backend/pypy/rpython/typesystem.py Thu Oct 13 16:47:44 2005
@@ -3,8 +3,8 @@
from pypy.annotation.pairtype import extendabletype
-from pypy.rpython.ootype import ootype
-from pypy.rpython import lltype # FIXME lltype in separate directory
+from pypy.rpython.ootype import ootype # FIXME ootype dir to ootypesystem
+from pypy.rpython.lltypesystem import lltype
class TypeSystem(object):
__metaclass__ = extendabletype
@@ -35,6 +35,19 @@
class LowLevelTypeSystem(TypeSystem):
callable_trait = (lltype.FuncType, lltype.functionptr)
+ def __getattr__(self, name):
+ """Lazy import to avoid circular dependencies."""
+ if name == "rclass":
+ from pypy.rpython.lltypesystem import rclass
+ self.rclass = rclass
+
+ return rclass
+ elif name == "BUILTIN_TYPER":
+ from pypy.rpython.lltypesystem import rbuiltin
+ self.BUILTIN_TYPER = rbuiltin.BUILTIN_TYPER
+
+ return self.BUILTIN_TYPER
+
def deref(self, obj):
assert isinstance(lltype.typeOf(obj), lltype.Ptr)
return obj._obj
@@ -45,6 +58,8 @@
class ObjectOrientedTypeSystem(TypeSystem):
callable_trait = (ootype.StaticMethod, ootype.static_meth)
+ # FIXME rclass
+
def deref(self, obj):
assert isinstance(ootype.typeOf(obj), ootype.OOType)
return obj
@@ -66,5 +81,3 @@
if hasattr(s_obj, "rtyper_makekey_ex"):
return s_obj.rtyper_makekey_ex(rtyper)
return s_obj.rtyper_makekey()
-
-
More information about the Pypy-commit
mailing list