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

arigo at codespeak.net arigo at codespeak.net
Fri Sep 9 21:00:39 CEST 2005


Author: arigo
Date: Fri Sep  9 21:00:36 2005
New Revision: 17432

Modified:
   pypy/dist/pypy/annotation/builtin.py
   pypy/dist/pypy/annotation/dictdef.py
   pypy/dist/pypy/annotation/listdef.py
   pypy/dist/pypy/rpython/test/test_objectmodel.py
Log:
Annotating r_dicts.


Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py	(original)
+++ pypy/dist/pypy/annotation/builtin.py	Fri Sep  9 21:00:36 2005
@@ -9,7 +9,7 @@
 from pypy.annotation.model import SomeList, SomeString, SomeTuple, SomeSlice
 from pypy.annotation.model import SomeUnicodeCodePoint, SomeAddress
 from pypy.annotation.model import SomeFloat, unionof
-from pypy.annotation.model import SomePBC, SomeInstance
+from pypy.annotation.model import SomePBC, SomeInstance, SomeDict
 from pypy.annotation.model import annotation_to_lltype
 from pypy.annotation.model import add_knowntypedata
 from pypy.annotation.bookkeeper import getbookkeeper
@@ -236,6 +236,10 @@
 def robjmodel_we_are_translated():
     return immutablevalue(True)
 
+def robjmodel_r_dict(s_eqfn, s_hashfn):
+    dictdef = getbookkeeper().getdictdef()
+    dictdef.dictkey.update_rdict_annotations(s_eqfn, s_hashfn)
+    return SomeDict(dictdef)
 
 ##def rarith_ovfcheck(s_obj):
 ##    if isinstance(s_obj, SomeInteger) and s_obj.unsigned:
@@ -275,6 +279,7 @@
 BUILTIN_ANALYZERS[pypy.rpython.objectmodel.instantiate] = robjmodel_instantiate
 BUILTIN_ANALYZERS[pypy.rpython.objectmodel.we_are_translated] = (
     robjmodel_we_are_translated)
+BUILTIN_ANALYZERS[pypy.rpython.objectmodel.r_dict] = robjmodel_r_dict
 
 BUILTIN_ANALYZERS[Exception.__init__.im_func] = exception_init
 BUILTIN_ANALYZERS[OSError.__init__.im_func] = exception_init

Modified: pypy/dist/pypy/annotation/dictdef.py
==============================================================================
--- pypy/dist/pypy/annotation/dictdef.py	(original)
+++ pypy/dist/pypy/annotation/dictdef.py	Fri Sep  9 21:00:36 2005
@@ -1,12 +1,52 @@
 from pypy.annotation.model import SomeObject, SomeImpossibleValue
+from pypy.annotation.model import SomeInteger, SomeBool, unionof
 from pypy.annotation.listdef import ListItem
 
 
 class DictKey(ListItem):
+    custom_eq_hash = False
+
     def patch(self):
         for dictdef in self.itemof:
             dictdef.dictkey = self
 
+    def merge(self, other):
+        if self is not other:
+            assert self.custom_eq_hash == other.custom_eq_hash, (
+                "mixing plain dictionaries with r_dict()")
+            ListItem.merge(self, other)
+            if self.custom_eq_hash:
+                self.update_rdict_annotations(other.s_rdict_eqfn,
+                                              other.s_rdict_hashfn)
+
+    def generalize(self, s_other_value):
+        updated = ListItem.generalize(self, s_other_value)
+        if updated and self.custom_eq_hash:
+            self.emulate_rdict_calls()
+        return updated
+
+    def update_rdict_annotations(self, s_eqfn, s_hashfn):
+        if not self.custom_eq_hash:
+            self.custom_eq_hash = True
+        else:
+            s_eqfn = unionof(s_eqfn, self.s_rdict_eqfn)
+            s_hashfn = unionof(s_hashfn, self.s_rdict_hashfn)
+        self.s_rdict_eqfn = s_eqfn
+        self.s_rdict_hashfn = s_hashfn
+        self.emulate_rdict_calls()
+
+    def emulate_rdict_calls(self):
+        s_key = self.s_value
+        s1 = self.bookkeeper.emulate_pbc_call(self.s_rdict_eqfn, [s_key, s_key])
+        assert SomeBool().contains(s1), (
+            "the custom eq function of an r_dict must return a boolean"
+            " (got %r)" % (s1,))
+        s2 = self.bookkeeper.emulate_pbc_call(self.s_rdict_hashfn, [s_key])
+        assert SomeInteger().contains(s2), (
+            "the custom hash function of an r_dict must return an integer"
+            " (got %r)" % (s2,))
+
+
 class DictValue(ListItem):
     def patch(self):
         for dictdef in self.itemof:

Modified: pypy/dist/pypy/annotation/listdef.py
==============================================================================
--- pypy/dist/pypy/annotation/listdef.py	(original)
+++ pypy/dist/pypy/annotation/listdef.py	Fri Sep  9 21:00:36 2005
@@ -49,11 +49,13 @@
         s_new_value = unionof(self.s_value, s_other_value)
         if isdegenerated(s_new_value):
             self.bookkeeper.ondegenerated(self, s_new_value)        
-        if s_new_value != self.s_value:
+        updated = s_new_value != self.s_value
+        if updated:
             self.s_value = s_new_value
             # reflow from all reading points
             for position_key in self.read_locations:
                 self.bookkeeper.annotator.reflowfromposition(position_key)
+        return updated
 
 
 class ListDef:

Modified: pypy/dist/pypy/rpython/test/test_objectmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_objectmodel.py	(original)
+++ pypy/dist/pypy/rpython/test/test_objectmodel.py	Fri Sep  9 21:00:36 2005
@@ -1,5 +1,5 @@
-import py
 from pypy.rpython.objectmodel import *
+from pypy.translator.translator import Translator
 from pypy.rpython.test.test_llinterp import interpret
 
 
@@ -11,15 +11,23 @@
     res = interpret(fn, [])
     assert res is True
 
+
+def strange_key_eq(key1, key2):
+    return key1[0] == key2[0]   # only the 1st character is relevant
+def strange_key_hash(key):
+    return ord(key[0])
+
 def test_r_dict():
-    def key_eq(key1, key2):
-        return key1[0] == key2[0]   # only the 1st character is relevant
-    def key_hash(key):
-        return ord(key[0])
-    d = r_dict(key_eq, key_hash)
+    # NB. this test function is also annotated/rtyped by the next tests
+    d = r_dict(strange_key_eq, strange_key_hash)
     d['hello'] = 42
     assert d['hi there'] == 42
-    py.test.raises(KeyError, 'd["dumb"]')
+    try:
+        d["dumb"]
+    except KeyError:
+        pass
+    else:
+        assert False, "should have raised"
     assert len(d) == 1
     assert 'oops' not in d
     assert list(d) == ['hello']
@@ -37,3 +45,20 @@
     assert list(d.iteritems()) == [('hello', 42)]
     d.clear()
     assert d.keys() == []
+    return True   # for the tests below
+
+def test_annotate_r_dict():
+    t = Translator(test_r_dict)
+    a = t.annotate([])
+    #t.view()
+    assert strange_key_eq in t.flowgraphs
+    assert strange_key_hash in t.flowgraphs
+    graph = t.flowgraphs[strange_key_eq]
+    assert a.binding(graph.getargs()[0]).knowntype == str
+    assert a.binding(graph.getargs()[1]).knowntype == str
+    graph = t.flowgraphs[strange_key_hash]
+    assert a.binding(graph.getargs()[0]).knowntype == str
+
+def INPROGRESS_test_rtype_r_dict():
+    res = interpret(test_r_dict, [])
+    assert res is True



More information about the Pypy-commit mailing list