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

arigo at codespeak.net arigo at codespeak.net
Thu Jun 16 20:28:53 CEST 2005


Author: arigo
Date: Thu Jun 16 20:28:50 2005
New Revision: 13488

Modified:
   pypy/dist/pypy/rpython/rpbc.py
   pypy/dist/pypy/rpython/rtyper.py
   pypy/dist/pypy/rpython/test/test_rpbc.py
Log:
rtyper support for PBC structures, implemented as a pointer to one of a set of
prebuilt Structs.  The shape of the Struct is deduced from annotator-supplied
usage patterns.



Modified: pypy/dist/pypy/rpython/rpbc.py
==============================================================================
--- pypy/dist/pypy/rpython/rpbc.py	(original)
+++ pypy/dist/pypy/rpython/rpbc.py	Thu Jun 16 20:28:50 2005
@@ -2,7 +2,8 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
 from pypy.annotation.classdef import isclassdef
-from pypy.rpython.lltype import typeOf, Void
+from pypy.rpython.lltype import typeOf, Void, ForwardReference, Struct
+from pypy.rpython.lltype import Ptr, malloc, nullptr
 from pypy.rpython.rmodel import Repr, TyperError
 from pypy.rpython import rclass
 
@@ -38,7 +39,7 @@
                     raise TyperError("don't know about callable %r" % (x,))
             else:
                 # frozen object
-                choice = FrozenPBCRepr
+                choice = getFrozenPBCRepr
 
             if cdefflag:
                 raise TyperError("unexpected classdef in PBC set %r" % (
@@ -60,18 +61,92 @@
 # ____________________________________________________________
 
 
-class FrozenPBCRepr(Repr):
+def getFrozenPBCRepr(rtyper, s_pbc):
+    if len(s_pbc.prebuiltinstances) <= 1:
+        return single_frozen_pbc_repr
+    else:
+        pbcs = [pbc for pbc in s_pbc.prebuiltinstances.keys()
+                    if pbc is not None]
+        access_sets = rtyper.annotator.getpbcaccesssets()
+        _, _, access = access_sets.find(pbcs[0])
+        for obj in pbcs[1:]:
+            _, _, access1 = access_sets.find(obj)
+            assert access1 is access       # XXX not implemented
+        try:
+            return rtyper.pbc_reprs[access]
+        except KeyError:
+            result = MultipleFrozenPBCRepr(rtyper, access)
+            rtyper.pbc_reprs[access] = result
+            return result
+
+
+class SingleFrozenPBCRepr(Repr):
     """Representation selected for a single non-callable pre-built constant."""
     lowleveltype = Void
 
-    def __init__(self, rtyper, s_pbc):
-        assert len(s_pbc.prebuiltinstances) == 1   # XXX not implemented
-
     def rtype_getattr(_, hop):
         if not hop.s_result.is_constant():
             raise TyperError("getattr on a constant PBC returns a non-constant")
         return hop.inputconst(hop.r_result, hop.s_result.const)
 
+single_frozen_pbc_repr = SingleFrozenPBCRepr()
+
+
+class MultipleFrozenPBCRepr(Repr):
+    """Representation selected for multiple non-callable pre-built constants."""
+    initialized = False
+
+    def __init__(self, rtyper, access_set):
+        self.rtyper = rtyper
+        self.access_set = access_set
+        self.pbc_type = ForwardReference()
+        self.lowleveltype = Ptr(self.pbc_type)
+        self.pbc_cache = {}
+
+    def setup(self):
+        if self.initialized:
+            assert self.initialized == True
+            return
+        self.initialized = "in progress"
+        llfields = []
+        llfieldmap = {}
+        attrlist = self.access_set.attrs.keys()
+        attrlist.sort()
+        for attr in attrlist:
+            s_value = self.access_set.attrs[attr]
+            r_value = self.rtyper.getrepr(s_value)
+            mangled_name = 'pbc_' + attr
+            llfields.append((mangled_name, r_value.lowleveltype))
+            llfieldmap[attr] = mangled_name, r_value
+        self.pbc_type.become(Struct('pbc', *llfields))
+        self.llfieldmap = llfieldmap
+        self.initialized = True
+
+    def convert_const(self, pbc):
+        if pbc is None:
+            return nullptr(self.pbc_type)
+        if pbc not in self.access_set.objects:
+            raise TyperError("not found in PBC set: %r" % (pbc,))
+        try:
+            return self.pbc_cache[pbc]
+        except KeyError:
+            self.setup()
+            result = malloc(self.pbc_type, immortal=True)
+            self.pbc_cache[pbc] = result
+            for attr, (mangled_name, r_value) in self.llfieldmap.items():
+                thisattrvalue = getattr(pbc, attr)
+                llvalue = r_value.convert_const(thisattrvalue)
+                setattr(result, mangled_name, llvalue)
+            return result
+
+    def rtype_getattr(self, hop):
+        attr = hop.args_s[1].const
+        vpbc, vattr = hop.inputargs(self, Void)
+        mangled_name, r_value = self.llfieldmap[attr]
+        cmangledname = hop.inputconst(Void, mangled_name)
+        return hop.genop('getfield', [vpbc, cmangledname],
+                         resulttype = r_value)
+
 
 # ____________________________________________________________
 

Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py	(original)
+++ pypy/dist/pypy/rpython/rtyper.py	Thu Jun 16 20:28:50 2005
@@ -42,6 +42,7 @@
         self.specialized_ll_functions = {}
         self.class_reprs = {}
         self.instance_reprs = {}
+        self.pbc_reprs = {}
         self.typererror = None
         # make the primitive_to_repr constant mapping
         self.primitive_to_repr = {}

Modified: pypy/dist/pypy/rpython/test/test_rpbc.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rpbc.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rpbc.py	Thu Jun 16 20:28:50 2005
@@ -57,3 +57,25 @@
         obj.z = a
         return obj.m(b)
     rtype(f, [int, int])
+
+
+class Freezing:
+    def _freeze_(self):
+        return True
+
+def test_freezing():
+    fr1 = Freezing()
+    fr2 = Freezing()
+    fr1.x = 5
+    fr2.x = 6
+    def g(fr):
+        return fr.x
+    def f(n):
+        if n > 0:
+            fr = fr1
+        elif n < 0:
+            fr = fr2
+        else:
+            fr = None
+        return g(fr)
+    rtype(f, [int])



More information about the Pypy-commit mailing list