Author: Carl Friedrich Bolz <[email protected]>
Branch: 
Changeset: r62395:3d242f84ac48
Date: 2013-03-17 22:00 +0100
http://bitbucket.org/pypy/pypy/changeset/3d242f84ac48/

Log:    add an "any" type to rlib.types. It's kind of necessary for a lot of
        practical uses, e.g. when a PBC (like the object space) is involved.

diff --git a/rpython/annotator/description.py b/rpython/annotator/description.py
--- a/rpython/annotator/description.py
+++ b/rpython/annotator/description.py
@@ -306,8 +306,10 @@
             result = schedule(graph, inputcells)
             signature = getattr(self.pyobj, '_signature_', None)
             if signature:
-                result = enforce_signature_return(self, signature[1], result)
-                self.bookkeeper.annotator.addpendingblock(graph, 
graph.returnblock, [result])
+                sigresult = enforce_signature_return(self, signature[1], 
result)
+                if sigresult is not None:
+                    self.bookkeeper.annotator.addpendingblock(graph, 
graph.returnblock, [sigresult])
+                    result = sigresult
         # Some specializations may break the invariant of returning
         # annotations that are always more general than the previous time.
         # We restore it here:
diff --git a/rpython/annotator/signature.py b/rpython/annotator/signature.py
--- a/rpython/annotator/signature.py
+++ b/rpython/annotator/signature.py
@@ -132,11 +132,13 @@
         inputcells[:] = args_s
 
 def finish_type(paramtype, bookkeeper, func):
-    from rpython.rlib.types import SelfTypeMarker
+    from rpython.rlib.types import SelfTypeMarker, AnyTypeMarker
     if isinstance(paramtype, SomeObject):
         return paramtype
     elif isinstance(paramtype, SelfTypeMarker):
         raise Exception("%r argument declared as annotation.types.self(); 
class needs decorator rlib.signature.finishsigs()" % (func,))
+    elif isinstance(paramtype, AnyTypeMarker):
+        return None
     else:
         return paramtype(bookkeeper)
 
@@ -144,15 +146,20 @@
     assert len(paramtypes) == len(actualtypes)
     params_s = [finish_type(paramtype, funcdesc.bookkeeper, funcdesc.pyobj) 
for paramtype in paramtypes]
     for i, (s_param, s_actual) in enumerate(zip(params_s, actualtypes)):
+        if s_param is None: # can be anything
+            continue
         if not s_param.contains(s_actual):
             raise Exception("%r argument %d:\n"
                             "expected %s,\n"
                             "     got %s" % (funcdesc, i+1, s_param, s_actual))
-    actualtypes[:] = params_s
+    for i, s_param in enumerate(params_s):
+        if s_param is None:
+            continue
+        actualtypes[i] = s_param
 
 def enforce_signature_return(funcdesc, sigtype, inferredtype):
     s_sigret = finish_type(sigtype, funcdesc.bookkeeper, funcdesc.pyobj)
-    if not s_sigret.contains(inferredtype):
+    if s_sigret is not None and not s_sigret.contains(inferredtype):
         raise Exception("%r return value:\n"
                         "expected %s,\n"
                         "     got %s" % (funcdesc, s_sigret, inferredtype))
diff --git a/rpython/rlib/test/test_signature.py 
b/rpython/rlib/test/test_signature.py
--- a/rpython/rlib/test/test_signature.py
+++ b/rpython/rlib/test/test_signature.py
@@ -248,3 +248,39 @@
     exc = py.test.raises(Exception, annotate_at, C.incomplete_sig_meth).value
     assert 'incomplete_sig_meth' in repr(exc.args)
     assert 'finishsigs' in repr(exc.args)
+
+def test_any_as_argument():
+    @signature(types.any(), types.int(), returns=types.float())
+    def f(x, y):
+        return x + y
+    @signature(types.int(), returns=types.float())
+    def g(x):
+        return f(x, x)
+    sig = getsig(g)
+    assert sig == [model.SomeInteger(), model.SomeFloat()]
+
+    @signature(types.float(), returns=types.float())
+    def g(x):
+        return f(x, 4)
+    sig = getsig(g)
+    assert sig == [model.SomeFloat(), model.SomeFloat()]
+
+    @signature(types.str(), returns=types.int())
+    def cannot_add_string(x):
+        return f(x, 2)
+    exc = py.test.raises(Exception, annotate_at, cannot_add_string).value
+    assert 'Blocked block' in repr(exc.args)
+
+def test_return_any():
+    @signature(types.int(), returns=types.any())
+    def f(x):
+        return x
+    sig = getsig(f)
+    assert sig == [model.SomeInteger(), model.SomeInteger()]
+
+    @signature(types.str(), returns=types.any())
+    def cannot_add_string(x):
+        return f(3) + x
+    exc = py.test.raises(Exception, annotate_at, cannot_add_string).value
+    assert 'Blocked block' in repr(exc.args)
+    assert 'cannot_add_string' in repr(exc.args)
diff --git a/rpython/rlib/types.py b/rpython/rlib/types.py
--- a/rpython/rlib/types.py
+++ b/rpython/rlib/types.py
@@ -63,3 +63,10 @@
 
 def self():
     return SelfTypeMarker()
+
+
+class AnyTypeMarker(object):
+    pass
+
+def any():
+    return AnyTypeMarker()
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to