[pypy-svn] pypy default: Bah, it's too messy to implement. So let's just say it's not RPython
arigo
commits-noreply at bitbucket.org
Sun Mar 13 18:15:46 CET 2011
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r42560:2fb044e92956
Date: 2011-03-13 13:15 -0400
http://bitbucket.org/pypy/pypy/changeset/2fb044e92956/
Log: Bah, it's too messy to implement. So let's just say it's not
RPython to have an __init__ in the subclasses but not in the parent
class in that case.
diff --git a/pypy/annotation/description.py b/pypy/annotation/description.py
--- a/pypy/annotation/description.py
+++ b/pypy/annotation/description.py
@@ -665,6 +665,21 @@
else:
# call to multiple classes: specialization not supported
classdefs = [desc.getuniqueclassdef() for desc in descs]
+ # If some of the classes have an __init__ and others not, then
+ # we complain, even though in theory it could work if all the
+ # __init__s take no argument. But it's messy to implement, so
+ # let's just say it is not RPython and you have to add an empty
+ # __init__ to your base class.
+ has_init = False
+ for desc in descs:
+ s_init = desc.s_read_attribute('__init__')
+ has_init |= isinstance(s_init, SomePBC)
+ basedesc = ClassDesc.getcommonbase(descs)
+ s_init = basedesc.s_read_attribute('__init__')
+ parent_has_init = isinstance(s_init, SomePBC)
+ if has_init and not parent_has_init:
+ raise Exception("some subclasses among %r declare __init__(),"
+ " but not the common parent class" % (descs,))
# make a PBC of MethodDescs, one for the __init__ of each class
initdescs = []
for desc, classdef in zip(descs, classdefs):
@@ -687,6 +702,23 @@
args, s_None)
consider_call_site = staticmethod(consider_call_site)
+ def getallbases(self):
+ desc = self
+ while desc is not None:
+ yield desc
+ desc = desc.basedesc
+
+ def getcommonbase(descs):
+ commondesc = descs[0]
+ for desc in descs[1:]:
+ allbases = set(commondesc.getallbases())
+ while desc not in allbases:
+ assert desc is not None, "no common base for %r" % (descs,)
+ desc = desc.basedesc
+ commondesc = desc
+ return commondesc
+ getcommonbase = staticmethod(getcommonbase)
+
def rowkey(self):
return self
diff --git a/pypy/annotation/test/test_description.py b/pypy/annotation/test/test_description.py
new file mode 100644
--- /dev/null
+++ b/pypy/annotation/test/test_description.py
@@ -0,0 +1,22 @@
+from pypy.annotation.description import ClassDesc
+
+class FakeBookkeeper:
+ def __init__(self):
+ self.seen = {}
+ def getdesc(self, cls):
+ if cls not in self.seen:
+ self.seen[cls] = ClassDesc(self, cls)
+ return self.seen[cls]
+
+def test_getcommonbase():
+ class Base(object): pass
+ class A(Base): pass
+ class B(A): pass
+ class C(B): pass
+ class D(A): pass
+ bk = FakeBookkeeper()
+ dA = bk.getdesc(A)
+ dB = bk.getdesc(B)
+ dC = bk.getdesc(C)
+ dD = bk.getdesc(D)
+ assert ClassDesc.getcommonbase([dC, dD]) is dA
diff --git a/pypy/annotation/test/test_annrpython.py b/pypy/annotation/test/test_annrpython.py
--- a/pypy/annotation/test/test_annrpython.py
+++ b/pypy/annotation/test/test_annrpython.py
@@ -1060,9 +1060,11 @@
assert s.const == True
def test_alloc_like(self):
- class C1(object):
+ class Base(object):
pass
- class C2(object):
+ class C1(Base):
+ pass
+ class C2(Base):
pass
def inst(cls):
@@ -3438,6 +3440,28 @@
a = self.RPythonAnnotator()
a.build_types(f, [int])
+ def test_call_classes_with_noarg_init(self):
+ class A:
+ foo = 21
+ class B(A):
+ foo = 22
+ class C(A):
+ def __init__(self):
+ self.foo = 42
+ class D(A):
+ def __init__(self):
+ self.foo = 43
+ def f(i):
+ if i == 1:
+ cls = B
+ elif i == 2:
+ cls = D
+ else:
+ cls = C
+ return cls().foo
+ a = self.RPythonAnnotator()
+ raises(Exception, a.build_types, f, [int])
+
def g(n):
return [0,1,2,n]
diff --git a/pypy/rpython/test/test_rpbc.py b/pypy/rpython/test/test_rpbc.py
--- a/pypy/rpython/test/test_rpbc.py
+++ b/pypy/rpython/test/test_rpbc.py
@@ -617,32 +617,6 @@
assert self.read_attr(res, "z") == -7645
assert self.read_attr(res, "extra") == 42
- def test_call_classes_with_noarg_init(self):
- class A:
- foo = 21
- class B(A):
- foo = 22
- class C(A):
- def __init__(self):
- self.foo = 42
- class D(A):
- def __init__(self):
- self.foo = 43
- def f(i):
- if i == 1:
- cls = B
- elif i == 2:
- cls = D
- else:
- cls = C
- return cls().foo
- res = self.interpret(f, [0])
- assert res == 42
- res = self.interpret(f, [1])
- assert res == 22
- res = self.interpret(f, [2])
- assert res == 43
-
def test_conv_from_None(self):
class A(object): pass
def none():
More information about the Pypy-commit
mailing list