[pypy-svn] r23433 - in pypy/dist/pypy: annotation rpython rpython/test

pedronis at codespeak.net pedronis at codespeak.net
Fri Feb 17 02:31:34 CET 2006


Author: pedronis
Date: Fri Feb 17 02:31:32 2006
New Revision: 23433

Modified:
   pypy/dist/pypy/annotation/description.py
   pypy/dist/pypy/rpython/normalizecalls.py
   pypy/dist/pypy/rpython/test/test_normalizecalls.py
Log:
make perform_normalizations callable again (for now favoring sanity-checking over skipping work)

simple testing for this based on test_normalizecalls and annotate_mixlevel_helper

it seems that annotating and rtyping new classes after a first phase of rtyping
works.



Modified: pypy/dist/pypy/annotation/description.py
==============================================================================
--- pypy/dist/pypy/annotation/description.py	(original)
+++ pypy/dist/pypy/annotation/description.py	Fri Feb 17 02:31:32 2006
@@ -13,6 +13,7 @@
     'd1~d2 if d1 and d2 might be called at the same call site'.
     """
     overridden = False
+    normalized = False
     
     def __init__(self, desc):
         self.descs = { desc: True }
@@ -20,6 +21,7 @@
         self.total_calltable_size = 0
 
     def update(self, other):
+        self.normalized = self.normalized or other.normalized
         self.descs.update(other.descs)
         for shape, table in other.calltables.items():
             for row in table:

Modified: pypy/dist/pypy/rpython/normalizecalls.py
==============================================================================
--- pypy/dist/pypy/rpython/normalizecalls.py	(original)
+++ pypy/dist/pypy/rpython/normalizecalls.py	Fri Feb 17 02:31:32 2006
@@ -1,5 +1,5 @@
 import py
-import types
+import types, sys
 import inspect
 from pypy.objspace.flow.model import Variable, Constant, Block, Link
 from pypy.objspace.flow.model import checkgraph, FunctionGraph, SpaceOperation
@@ -14,6 +14,7 @@
 def normalize_call_familes(annotator):
     for callfamily in annotator.bookkeeper.pbc_maximal_call_families.infos():
         normalize_calltable(annotator, callfamily)
+        callfamily.normalized = True
 
 def normalize_calltable(annotator, callfamily):
     """Try to normalize all rows of a table."""
@@ -32,6 +33,7 @@
             did_something = normalize_calltable_row_signature(annotator, shape,
                                                               row)
             if did_something:
+                assert not callfamily.normalized, "change in call family normalisation"
                 assert nshapes == 1, "XXX call table too complex"
     while True: 
         progress = False
@@ -40,6 +42,7 @@
                 progress |= normalize_calltable_row_annotation(annotator, row)
         if not progress:
             return   # done
+        assert not callfamily.normalized, "change in call family normalisation"
 
 def normalize_calltable_row_signature(annotator, shape, row):
     graphs = row.values()
@@ -198,10 +201,14 @@
                 raise TyperError("reading attributes %r: no common base class "
                                  "for %r" % (
                     access_set.attrs.keys(), descs.keys()))
-        access_set.commonbase = commonbase
         extra_access_sets = rtyper.class_pbc_attributes.setdefault(commonbase,
                                                                    {})
-        extra_access_sets[access_set] = len(extra_access_sets)
+        if commonbase in rtyper.class_reprs:
+            assert access_set in extra_access_sets # minimal sanity check
+            return
+        access_set.commonbase = commonbase
+        if access_set not in extra_access_sets:
+            extra_access_sets[access_set] = len(extra_access_sets)
 
 # ____________________________________________________________
 
@@ -218,7 +225,10 @@
         # Note that a callfamily of classes must really be in the same
         # attrfamily as well; This property is relied upon on various
         # places in the rtyper
-        descs[0].mergeattrfamilies(*descs[1:])
+        change = descs[0].mergeattrfamilies(*descs[1:])
+        if hasattr(descs[0].getuniqueclassdef(), 'my_instantiate_graph'):
+            assert not change, "after the fact change to a family of classes" # minimal sanity check
+            return
         attrfamily = descs[0].getattrfamily()
         # Put __init__ into the attr family, for ClassesPBCRepr.call()
         s_value = attrfamily.attrs.get('__init__', annmodel.s_ImpossibleValue)
@@ -246,6 +256,8 @@
     # def my_instantiate():
     #     return instantiate(cls)
     #
+    if hasattr(classdef, 'my_instantiate_graph'):
+        return
     v = Variable()
     block = Block([])
     block.operations.append(SpaceOperation('instantiate1', [], v))
@@ -272,7 +284,9 @@
     id_ = 0
     for classdef in annotator.bookkeeper.classdefs:
         if classdef.basedef is None:
+            prevmaxid = getattr(classdef, 'maxid', sys.maxint)
             id_ = assign_id(classdef, id_)
+            assert id_ <= prevmaxid, "non-orthogonal class hierarchy growth"
 
 # ____________________________________________________________
 

Modified: pypy/dist/pypy/rpython/test/test_normalizecalls.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_normalizecalls.py	(original)
+++ pypy/dist/pypy/rpython/test/test_normalizecalls.py	Fri Feb 17 02:31:32 2006
@@ -1,132 +1,186 @@
 from pypy.annotation import model as annmodel
 from pypy.translator.translator import TranslationContext, graphof
+from pypy.rpython.llinterp import LLInterpreter
 from pypy.rpython.test.test_llinterp import interpret
 from pypy.rpython.lltypesystem import lltype
 
 
-def rtype(fn, argtypes=[]):
-    t = TranslationContext()
-    t.buildannotator().build_types(fn, argtypes)
-    typer = t.buildrtyper()
-    typer.specialize()
-    #t.view()
-    t.checkgraphs()
-    return t
 
 # ____________________________________________________________
 
-def test_normalize_f2_as_taking_string_argument():
-    def f1(l1):
-        pass
-    def f2(l2):
-        pass
-    def g(n):
-        if n > 0:
-            f1("123")
-            f = f1
-        else:
-            f2("b")
-            f = f2
-        f("a")
-
-    # The call table looks like:
-    #
-    #                 FuncDesc(f1)  FuncDesc(f2)
-    #   --------------------------------------------
-    #   line g+2:       graph1
-    #   line g+5:                      graph2
-    #   line g+7:       graph1         graph2
-    #
-    # But all lines get compressed to a single line.
-
-    translator = rtype(g, [int])
-    f1graph = graphof(translator, f1)
-    f2graph = graphof(translator, f2)
-    s_l1 = translator.annotator.binding(f1graph.getargs()[0])
-    s_l2 = translator.annotator.binding(f2graph.getargs()[0])
-    assert s_l1.__class__ == annmodel.SomeString   # and not SomeChar
-    assert s_l2.__class__ == annmodel.SomeString   # and not SomeChar
-    #translator.view()
-
-def test_normalize_keyword_call():
-    def f1(a, b):
-        return (a, b, 0, 0)
-    def f2(b, c=123, a=456, d=789):
-        return (a, b, c, d)
-    def g(n):
-        if n > 0:
-            f = f1
-        else:
-            f = f2
-        f(a=5, b=6)
-
-    translator = rtype(g, [int])
-    f1graph = graphof(translator, f1)
-    f2graph = graphof(translator, f2)
-    assert len(f1graph.getargs()) == 2
-    assert len(f2graph.getargs()) == 2   # normalized to the common call pattern
-    #translator.view()
-
-def test_normalize_returnvar():
-    def add_one(n):
-        return n+1
-    def add_half(n):
-        return n+0.5
-    def dummyfn(n, i):
-        if i == 1:
-            adder = add_one
-        else:
-            adder = add_half
-        return adder(n)
-
-    res = interpret(dummyfn, [52, 1])
-    assert type(res) is float and res == 53.0
-    res = interpret(dummyfn, [7, 2])
-    assert type(res) is float and res == 7.5
-
-def test_normalize_missing_return():
-    def add_one(n):
-        return n+1
-    def oups(n):
-        raise ValueError
-    def dummyfn(n, i):
-        if i == 1:
-            adder = add_one
-        else:
-            adder = oups
-        try:
+class TestNormalize(object):
+
+    def rtype(self, fn, argtypes=[]):
+        t = TranslationContext()
+        t.buildannotator().build_types(fn, argtypes)
+        typer = t.buildrtyper()
+        typer.specialize()
+        #t.view()
+        t.checkgraphs()
+        return t
+
+
+    def test_normalize_f2_as_taking_string_argument(self):
+        def f1(l1):
+            pass
+        def f2(l2):
+            pass
+        def g(n):
+            if n > 0:
+                f1("123")
+                f = f1
+            else:
+                f2("b")
+                f = f2
+            f("a")
+
+        # The call table looks like:
+        #
+        #                 FuncDesc(f1)  FuncDesc(f2)
+        #   --------------------------------------------
+        #   line g+2:       graph1
+        #   line g+5:                      graph2
+        #   line g+7:       graph1         graph2
+        #
+        # But all lines get compressed to a single line.
+
+        translator = self.rtype(g, [int])
+        f1graph = graphof(translator, f1)
+        f2graph = graphof(translator, f2)
+        s_l1 = translator.annotator.binding(f1graph.getargs()[0])
+        s_l2 = translator.annotator.binding(f2graph.getargs()[0])
+        assert s_l1.__class__ == annmodel.SomeString   # and not SomeChar
+        assert s_l2.__class__ == annmodel.SomeString   # and not SomeChar
+        #translator.view()
+
+    def test_normalize_keyword_call(self):
+        def f1(a, b):
+            return (a, b, 0, 0)
+        def f2(b, c=123, a=456, d=789):
+            return (a, b, c, d)
+        def g(n):
+            if n > 0:
+                f = f1
+            else:
+                f = f2
+            f(a=5, b=6)
+
+        translator = self.rtype(g, [int])
+        f1graph = graphof(translator, f1)
+        f2graph = graphof(translator, f2)
+        assert len(f1graph.getargs()) == 2
+        assert len(f2graph.getargs()) == 2   # normalized to the common call pattern
+        #translator.view()
+
+    def test_normalize_returnvar(self):
+        def add_one(n):
+            return n+1
+        def add_half(n):
+            return n+0.5
+        def dummyfn(n, i):
+            if i == 1:
+                adder = add_one
+            else:
+                adder = add_half
             return adder(n)
-        except ValueError:
-            return -1
 
-    translator = rtype(dummyfn, [int, int])
-    add_one_graph = graphof(translator, add_one)
-    oups_graph    = graphof(translator, oups)
-    assert add_one_graph.getreturnvar().concretetype == lltype.Signed
-    assert oups_graph   .getreturnvar().concretetype == lltype.Signed
-    #translator.view()
-
-def test_normalize_abstract_method():
-    class Base:
-        def fn(self):
-            raise NotImplementedError
-    class Sub1(Base):
-        def fn(self):
-            return 1
-    class Sub2(Base):
-        def fn(self):
-            return 2
-    def dummyfn(n):
-        if n == 1:
-            x = Sub1()
-        else:
-            x = Sub2()
-        return x.fn()
-
-    translator = rtype(dummyfn, [int])
-    base_graph = graphof(translator, Base.fn.im_func)
-    sub1_graph = graphof(translator, Sub1.fn.im_func)
-    sub2_graph = graphof(translator, Sub2.fn.im_func)
-    assert base_graph.getreturnvar().concretetype == lltype.Signed
-    assert sub1_graph.getreturnvar().concretetype == lltype.Signed
-    assert sub2_graph.getreturnvar().concretetype == lltype.Signed
+        res = interpret(dummyfn, [52, 1])
+        assert type(res) is float and res == 53.0
+        res = interpret(dummyfn, [7, 2])
+        assert type(res) is float and res == 7.5
+
+    def test_normalize_missing_return(self):
+        def add_one(n):
+            return n+1
+        def oups(n):
+            raise ValueError
+        def dummyfn(n, i):
+            if i == 1:
+                adder = add_one
+            else:
+                adder = oups
+            try:
+                return adder(n)
+            except ValueError:
+                return -1
+
+        translator = self.rtype(dummyfn, [int, int])
+        add_one_graph = graphof(translator, add_one)
+        oups_graph    = graphof(translator, oups)
+        assert add_one_graph.getreturnvar().concretetype == lltype.Signed
+        assert oups_graph   .getreturnvar().concretetype == lltype.Signed
+        #translator.view()
+
+    def test_normalize_abstract_method(self):
+        class Base:
+            def fn(self):
+                raise NotImplementedError
+        class Sub1(Base):
+            def fn(self):
+                return 1
+        class Sub2(Base):
+            def fn(self):
+                return 2
+        def dummyfn(n):
+            if n == 1:
+                x = Sub1()
+            else:
+                x = Sub2()
+            return x.fn()
+
+        translator = self.rtype(dummyfn, [int])
+        base_graph = graphof(translator, Base.fn.im_func)
+        sub1_graph = graphof(translator, Sub1.fn.im_func)
+        sub2_graph = graphof(translator, Sub2.fn.im_func)
+        assert base_graph.getreturnvar().concretetype == lltype.Signed
+        assert sub1_graph.getreturnvar().concretetype == lltype.Signed
+        assert sub2_graph.getreturnvar().concretetype == lltype.Signed
+
+        llinterp = LLInterpreter(translator.rtyper)
+        res = llinterp.eval_graph(graphof(translator, dummyfn), [1])
+        assert res == 1
+        res = llinterp.eval_graph(graphof(translator, dummyfn), [2])
+        assert res == 2
+
+class TestNormalizeAfterTheFact(TestNormalize):
+
+    def rtype(self, fn, argtypes=[]):
+        class Base:
+            def fn(self):
+                raise NotImplementedError
+        class Sub1(Base):
+            def fn(self):
+                return 1
+        class Sub2(Base):
+            def fn(self):
+                return 2
+        def prefn(n):
+            if n == 1:
+                x = Sub1()
+            else:
+                x = Sub2()
+            return x.fn()
+        
+        t = TranslationContext()
+        a = t.buildannotator()
+        a.build_types(prefn, [int])
+        typer = t.buildrtyper()
+        typer.specialize()
+        #t.view()
+
+        from pypy.rpython import annlowlevel
+        # normalize and rtype fn after the fact
+        graph = annlowlevel.annotate_mixlevel_helper(typer, fn, [a.typeannotation(argtype) for argtype in argtypes])
+        from pypy.rpython.normalizecalls import perform_normalizations
+        perform_normalizations(typer)
+        typer.specialize_more_blocks()
+
+        # sanity check prefn
+        llinterp = LLInterpreter(typer)
+        res = llinterp.eval_graph(graphof(t, prefn), [1])
+        assert res == 1
+        res = llinterp.eval_graph(graphof(t, prefn), [2])
+        assert res == 2
+
+        t.checkgraphs()
+        return t



More information about the Pypy-commit mailing list