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

arigo at codespeak.net arigo at codespeak.net
Mon Jun 6 13:01:11 CEST 2005


Author: arigo
Date: Mon Jun  6 13:01:08 2005
New Revision: 13095

Added:
   pypy/dist/pypy/rpython/test/test_rpbc.py   (contents, props changed)
Modified:
   pypy/dist/pypy/rpython/rpbc.py
   pypy/dist/pypy/rpython/rtyper.py
   pypy/dist/pypy/rpython/test/test_rclass.py
Log:
Some work on rpbc: variables pointing to multiple functions.


Modified: pypy/dist/pypy/rpython/rpbc.py
==============================================================================
--- pypy/dist/pypy/rpython/rpbc.py	(original)
+++ pypy/dist/pypy/rpython/rpbc.py	Mon Jun  6 13:01:08 2005
@@ -1,6 +1,7 @@
 import types
 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.rmodel import Repr, TyperError
 from pypy.rpython import rclass
@@ -8,41 +9,153 @@
 
 class __extend__(annmodel.SomePBC):
     def rtyper_makerepr(self, rtyper):
-        return PBCRepr(self.prebuiltinstances)
+        # for now, we require that the PBC fits neatly into one of the Repr
+        # categories below, and doesn't for example mix functions, classes
+        # and methods.
+        callb = rtyper.annotator.getpbccallables()
+        choices = {}
+        for x, classdef in self.prebuiltinstances.items():
+            cdefflag = isclassdef(classdef)
+
+            # consider unbound methods as plain functions
+            if isinstance(x, types.MethodType) and x.im_self is None:
+                x = x.im_func
+
+            # callable or frozen object?
+            if x in callb:
+                # what type of callable?
+                if isinstance(x, types.FunctionType):
+                    if cdefflag:
+                        choice = MethodsPBCRepr
+                        cdefflag = False
+                    else:
+                        choice = FunctionsPBCRepr
+                elif isinstance(x, (type, types.ClassType)):
+                    choice = ClassesPBCRepr
+                #elif isinstance(x, types.MethodType):
+                #    choice = ConstMethodsPBCRepr
+                else:
+                    raise TyperError("don't know about callable %r" % (x,))
+            else:
+                # frozen object
+                choice = FrozenPBCRepr
 
+            if cdefflag:
+                raise TyperError("unexpected classdef in PBC set %r" % (
+                    self.prebuiltinstances,))
+            choices[choice] = True
 
-class PBCRepr(Repr):
+        if len(choices) > 1:
+            raise TyperError("mixed kinds of PBC in the set %r" % (
+                self.prebuiltinstances,))
+        reprcls, = choices
+        return reprcls(rtyper, self)
 
-    def __init__(self, prebuiltinstances):
-        self.prebuiltinstances = prebuiltinstances
-        assert len(prebuiltinstances) == 1, "Not Implemented: multiPBCs"
-        self.lowleveltype = Void
+
+# ____________________________________________________________
+
+
+class FrozenPBCRepr(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 hop.s_result.is_constant():
-            return hop.inputconst(hop.r_result, hop.s_result.const)
+        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)
+
+
+# ____________________________________________________________
+
+
+def getsignature(rtyper, func):
+    f = rtyper.getfunctionptr(func)
+    graph = f._obj.graph
+    FUNCPTR = typeOf(f)
+    rinputs = [rtyper.bindingrepr(v) for v in graph.getargs()]
+    if graph.getreturnvar() in rtyper.annotator.bindings:
+        rresult = rtyper.bindingrepr(graph.getreturnvar())
+    else:
+        rresult = Void
+    return f, rinputs, rresult
+
+
+class FunctionsPBCRepr(Repr):
+    """Representation selected for a PBC of function(s)."""
+
+    def __init__(self, rtyper, s_pbc):
+        self.rtyper = rtyper
+        self.s_pbc = s_pbc
+        self.function_signatures = {}
+        for func in s_pbc.prebuiltinstances:
+            self.function_signatures[func] = getsignature(rtyper, func)
+
+        if len(self.function_signatures) == 1:
+            # a single function
+            self.lowleveltype = Void
         else:
-            NotImplementedYet
-
-    def rtype_simple_call(_, hop):
-        r_func, s_func = hop.r_s_popfirstarg()
-        if not s_func.is_constant():
-            NotImplementedYet
-        func = s_func.const
-        if isinstance(func, types.FunctionType):
-            # XXX hackish
-            f = hop.rtyper.getfunctionptr(func)
-            graph = f._obj.graph
-            FUNCPTR = typeOf(f)
-            rinputs = [hop.rtyper.bindingrepr(v) for v in graph.getargs()]
-            if FUNCPTR.TO.RESULT == Void:
-                rresult = Void
-            else:
-                rresult = hop.rtyper.bindingrepr(graph.getreturnvar())
-            args_v = hop.inputargs(*rinputs)
-            c = hop.inputconst(FUNCPTR, f)
-            return hop.genop('direct_call', [c] + args_v,
-                             resulttype = rresult)
-        elif isinstance(func, (types.ClassType, type)):
-            return rclass.rtype_new_instance(s_func.const, hop)
-            # XXX call __init__ somewhere
+            signatures = self.function_signatures.values()
+            sig0 = signatures[0]
+            for sig1 in signatures[1:]:
+                assert typeOf(sig0[0]) == typeOf(sig1[0])  # XXX not implemented
+                assert sig0[1:] == sig1[1:]                # XXX not implemented
+            self.lowleveltype = typeOf(sig0[0])
+
+##            callfamilies = rtyper.annotator.getpbccallfamilies()
+##            try:
+##                _, _, callfamily = callfamilies[None, functions[0]]
+##            except KeyError:
+##                self.lowleveltype = Void   # no call family found
+##            else:
+##                shapes = callfamily.patterns
+##                assert len(shapes) == 1, "XXX not implemented"
+##                shape, = shapes
+##                shape_cnt, shape_keys, shape_star, shape_stst = shape
+##                assert not shape_keys, "XXX not implemented"
+##                assert not shape_star, "XXX not implemented"
+##                assert not shape_stst, "XXX not implemented"
+
+    def convert_const(self, value):
+        if value not in self.function_signatures:
+            raise TyperError("%r not in %r" % (value,
+                                               self.s_pbc.prebuiltinstances))
+        f, rinputs, rresult = self.function_signatures[value]
+        return f
+
+    def rtype_simple_call(self, hop):
+        f, rinputs, rresult = self.function_signatures.itervalues().next()
+        vlist = hop.inputargs(self, *rinputs)
+        if self.lowleveltype == Void:
+            assert len(self.function_signatures) == 1
+            vlist[0] = hop.inputconst(typeOf(f), f)
+        return hop.genop('direct_call', vlist, resulttype = rresult)
+
+
+# ____________________________________________________________
+
+
+class ClassesPBCRepr(Repr):
+    """Representation selected for a PBC of class(es)."""
+
+    def __init__(self, rtyper, s_pbc):
+        self.rtyper = rtyper
+        self.s_pbc = s_pbc
+        assert s_pbc.is_constant()      # XXX not implemented
+        self.lowleveltype = Void
+##        self.classdefs = {}
+##        for cls in s_pbc.prebuiltinstances:
+##            self.classdefs[cls] = rtyper.annotator.getuserclasses()[cls]
+##        classdefslist = self.classdefs.values()
+##        commonbase = classdefslist[0]
+##        for cdef in classdefslist[1:]:
+##            commonbase = cdef.commonbase(commonbase)
+##            if commonbase is None:
+##                raise TyperError("no common base class in PBC set %r" % (
+##                    s_pbc.prebuiltinstances,))
+
+    def rtype_simple_call(self, hop):
+        return rclass.rtype_new_instance(self.s_pbc.const, hop)
+        # XXX call __init__ somewhere

Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py	(original)
+++ pypy/dist/pypy/rpython/rtyper.py	Mon Jun  6 13:01:08 2005
@@ -12,7 +12,7 @@
 
 
 debug = False
-crash_on_first_typeerror = False
+crash_on_first_typeerror = True
 
 # XXX copied from pypy.translator.typer and modified.
 #     We'll remove pypy.translator.typer at some point.

Modified: pypy/dist/pypy/rpython/test/test_rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rclass.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rclass.py	Mon Jun  6 13:01:08 2005
@@ -47,4 +47,4 @@
         x = Random()
         x.xyzzy += 1
         return x.xyzzy
-    rtype(dummyfn).view()
+    rtype(dummyfn)

Added: pypy/dist/pypy/rpython/test/test_rpbc.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/test/test_rpbc.py	Mon Jun  6 13:01:08 2005
@@ -0,0 +1,34 @@
+from pypy.translator.translator import Translator
+from pypy.rpython.lltype import *
+from pypy.rpython.rtyper import RPythonTyper
+
+
+def rtype(fn, argtypes=[]):
+    t = Translator(fn)
+    t.annotate(argtypes)
+    typer = RPythonTyper(t.annotator)
+    typer.specialize()
+    #t.view()
+    t.checkgraphs()
+    return t
+
+
+def test_easy_call():
+    def f(x):
+        return x+1
+    def g(y):
+        return f(y+2)
+    rtype(g, [int])
+
+def test_multiple_call():
+    def f1(x):
+        return x+1
+    def f2(x):
+        return x+2
+    def g(y):
+        if y < 0:
+            f = f1
+        else:
+            f = f2
+        return f(y+3)
+    rtype(g, [int])



More information about the Pypy-commit mailing list