[pypy-commit] pypy default: Implement "x in (constant-tuple)" not by doing a dictionary lookup,

arigo noreply at buildbot.pypy.org
Tue Mar 11 09:59:56 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r69851:c823adbf0d32
Date: 2014-03-11 09:59 +0100
http://bitbucket.org/pypy/pypy/changeset/c823adbf0d32/

Log:	Implement "x in (constant-tuple)" not by doing a dictionary lookup,
	but instead as a chain of equalities.

diff --git a/rpython/rtyper/rtuple.py b/rpython/rtyper/rtuple.py
--- a/rpython/rtyper/rtuple.py
+++ b/rpython/rtyper/rtuple.py
@@ -290,20 +290,23 @@
         if not s_tup.is_constant():
             raise TyperError("contains() on non-const tuple")
         t = s_tup.const
-        typ = type(t[0])
-        for x in t[1:]:
-            if type(x) is not typ:
-                raise TyperError("contains() on mixed-type tuple "
-                                 "constant %r" % (t,))
-        d = {}
+        if len(t) == 0:
+            hop.exception_cannot_occur()
+            return hop.inputconst(Bool, False)
+        r_item = hop.args_r[1]
+        v_arg = hop.inputarg(r_item, arg=1)
+        ll_eq = r_item.get_ll_eq_function() or _ll_equal
+        v_result = None
         for x in t:
-            d[x] = None
-        hop2 = hop.copy()
-        _, _ = hop2.r_s_popfirstarg()
-        v_dict = Constant(d)
-        s_dict = hop.rtyper.annotator.bookkeeper.immutablevalue(d)
-        hop2.v_s_insertfirstarg(v_dict, s_dict)
-        return hop2.dispatch()
+            c_tuple_item = hop.inputconst(r_item, x)
+            v_equal = hop.gendirectcall(ll_eq, v_arg, c_tuple_item)
+            if v_result is None:
+                v_result = v_equal
+            else:
+                v_result = hop.genop("int_or", [v_result, v_equal],
+                                     resulttype = Bool)
+        hop.exception_cannot_occur()
+        return v_result or hop.inputconst(Bool, False)
 
 class __extend__(pairtype(TupleRepr, TupleRepr)):
 
@@ -400,3 +403,6 @@
         return t.item0
     else:
         raise StopIteration
+
+def _ll_equal(x, y):
+    return x == y
diff --git a/rpython/rtyper/test/test_rtuple.py b/rpython/rtyper/test/test_rtuple.py
--- a/rpython/rtyper/test/test_rtuple.py
+++ b/rpython/rtyper/test/test_rtuple.py
@@ -73,6 +73,20 @@
         res = self.interpret(f, [0])
         assert res is False
 
+    def test_constant_tuple_contains3(self):
+        def f(i):
+            return i in ()
+        res = self.interpret(f, [3])
+        assert res is False
+
+    def test_constant_tuple_contains4(self):
+        def f(i):
+            return i in (3,)
+        res = self.interpret(f, [3])
+        assert res is True
+        res = self.interpret(f, [4])
+        assert res is False
+
     def test_constant_unichar_tuple_contains(self):
         def f(i):
             return unichr(i) in (u'1', u'9')


More information about the pypy-commit mailing list