[pypy-svn] r13449 - in pypy/dist/pypy/rpython: . test

pedronis at codespeak.net pedronis at codespeak.net
Wed Jun 15 21:23:10 CEST 2005


Author: pedronis
Date: Wed Jun 15 21:23:09 2005
New Revision: 13449

Modified:
   pypy/dist/pypy/rpython/lltype.py
   pypy/dist/pypy/rpython/test/test_lltype.py
Log:
support for runtime type info (as unique pointers to special opaque objects) for GcStructs, it is possible to attach a query function
to GcStruct type that will be used to discover the runtime type info at runtime.

attachRuntimeTypeInfo(GSTRUCT) activates the support for GCSTRUCT, optionally the function as functionptr with signature
(Ptr(GCSTRUCT)) -> Ptr(RuntimeTypeInfo) can be passed.

getRuntimeTypeInfo(GCSTRUCT) returns the statically associated runtime type info object of GCSTRUCT,

runtime_type_info(p) is runtime invocable and returns the runtime type info for p, assuming p it's a pointer to a GcStruct.

This support will be used to implement proper deallocation for pointers to inlined GcStructs.

  


Modified: pypy/dist/pypy/rpython/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltype.py	Wed Jun 15 21:23:09 2005
@@ -151,7 +151,15 @@
         return _struct(self, n)
 
 class GcStruct(Struct):
-    pass
+    _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)
+        if funcptr is not None:
+            if not typeOf(funcptr) == Ptr(FuncType([Ptr(self)], Ptr(RuntimeTypeInfo))):
+                raise TypeError, "expected a runtime type info function implementation, got: %s" % funcptr
+            self._runtime_type_info._obj.query_funcptr = funcptr
 
 class Array(ContainerType):
     __name__ = 'array'
@@ -216,6 +224,17 @@
             return self.RESULT._example()
         return _func(self, _callable=ex)
 
+class OpaqueType(ContainerType):
+    
+    def __init__(self, tag):
+        self.tag = tag
+        self.__name__ = tag
+
+    def __str__(self):
+        return "%s (opaque)" % self.tag
+
+RuntimeTypeInfo = OpaqueType("RuntimeTypeInfo")
+
 class PyObjectType(ContainerType):
     __name__ = 'PyObject'
     def __str__(self):
@@ -652,6 +671,25 @@
     def __str__(self):
         return "func %s" % self._name
 
+class _opaque(object):
+    def __init__(self, TYPE, **attrs):
+        self._TYPE = TYPE
+        self._name = "?"
+        self.__dict__.update(attrs)
+
+    def _parentstructure(self):
+        return None
+
+    def _check(self):
+        pass
+
+    def __repr__(self):
+        return '<%s>' % (self,)
+
+    def __str__(self):
+        return "%s %s" % (self._TYPE.__name__, self._name)
+
+
 class _pyobject(Hashable):
     _TYPE = PyObject
 
@@ -681,14 +719,54 @@
 
 def functionptr(TYPE, name, **attrs):
     if not isinstance(TYPE, FuncType):
-        raise TypeError, "function() for FuncTypes only"
+        raise TypeError, "functionptr() for FuncTypes only"
     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, immortal=attrs.get('immortal', True))
+
 def pyobjectptr(obj):
     o = _pyobject(obj)
     return _ptr(Ptr(PyObject), o) 
 
+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 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 TypeError, "no attached runtime type info for %s" % GCSTRUCT
+    return 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:
+        result2 = query_funcptr(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
+    

Modified: pypy/dist/pypy/rpython/test/test_lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_lltype.py	(original)
+++ pypy/dist/pypy/rpython/test/test_lltype.py	Wed Jun 15 21:23:09 2005
@@ -338,3 +338,50 @@
     del p
     p = cast_pointer(Ptr(S), p1)
     assert p.s1.x == 5
+
+def test_getRuntimeTypeInfo():
+    S = GcStruct('s', ('x', Signed))
+    py.test.raises(TypeError, "getRuntimeTypeInfo(S)")
+    pinf0 = attachRuntimeTypeInfo(S)
+    assert pinf0._obj.about == S
+    pinf = getRuntimeTypeInfo(S)
+    assert pinf == pinf0
+    pinf1 = getRuntimeTypeInfo(S)
+    assert pinf == pinf1
+    Z = GcStruct('z', ('x', Unsigned))
+    attachRuntimeTypeInfo(Z)
+    assert getRuntimeTypeInfo(Z) != pinf0
+    Sbis = GcStruct('s', ('x', Signed))
+    attachRuntimeTypeInfo(Sbis)
+    assert getRuntimeTypeInfo(Sbis) != pinf0
+    assert Sbis != S # the attached runtime type info distinguishes them
+
+def test_runtime_type_info():
+    S = GcStruct('s', ('x', Signed))
+    attachRuntimeTypeInfo(S)
+    s = malloc(S)
+    assert runtime_type_info(s) == getRuntimeTypeInfo(S)
+    S1 = GcStruct('s1', ('sub', S), ('x', Signed))
+    attachRuntimeTypeInfo(S1)
+    s1 = malloc(S1)
+    assert runtime_type_info(s1) == getRuntimeTypeInfo(S1)
+    assert runtime_type_info(s1.sub) == getRuntimeTypeInfo(S1)
+    assert runtime_type_info(cast_pointer(Ptr(S), s1)) == getRuntimeTypeInfo(S1)
+    def dynamic_type_info_S(p):
+        if p.x == 0:
+            return getRuntimeTypeInfo(S)
+        else:
+            return getRuntimeTypeInfo(S1)
+    fp = functionptr(FuncType([Ptr(S)], Ptr(RuntimeTypeInfo)), 
+                     "dynamic_type_info_S", 
+                     _callable=dynamic_type_info_S)
+    attachRuntimeTypeInfo(S, fp)
+    assert s.x == 0
+    assert runtime_type_info(s) == getRuntimeTypeInfo(S)
+    s.x = 1
+    py.test.raises(RuntimeError, "runtime_type_info(s)")
+    assert s1.sub.x == 0
+    py.test.raises(RuntimeError, "runtime_type_info(s1.sub)")
+    s1.sub.x = 1
+    assert runtime_type_info(s1.sub) == getRuntimeTypeInfo(S1)
+    



More information about the Pypy-commit mailing list