[pypy-svn] r26799 - in pypy/dist/pypy: annotation annotation/test rpython/lltypesystem rpython/ootypesystem rpython/test
arigo at codespeak.net
arigo at codespeak.net
Fri May 5 10:55:43 CEST 2006
Author: arigo
Date: Fri May 5 10:55:40 2006
New Revision: 26799
Modified:
pypy/dist/pypy/annotation/classdef.py
pypy/dist/pypy/annotation/test/test_annrpython.py
pypy/dist/pypy/annotation/unaryop.py
pypy/dist/pypy/rpython/lltypesystem/rclass.py
pypy/dist/pypy/rpython/ootypesystem/rclass.py
pypy/dist/pypy/rpython/test/test_rclass.py
Log:
(pedronis, arigo)
Supports reading the __class__ attribute on instances. The result
is a SomePBC of all possible classes, which is quite different from
what type(x) returns, which is just SomeObject(knowntype=type).
It means that .__class__ should be suitable for expressions like
'y = x.__class__()'.
Modified: pypy/dist/pypy/annotation/classdef.py
==============================================================================
--- pypy/dist/pypy/annotation/classdef.py (original)
+++ pypy/dist/pypy/annotation/classdef.py Fri May 5 10:55:40 2006
@@ -67,6 +67,7 @@
# instances that have the attribute set will turn off readonly-ness.
def __init__(self, name, bookkeeper):
+ assert name != '__class__'
self.name = name
self.bookkeeper = bookkeeper
self.s_value = SomeImpossibleValue()
@@ -131,10 +132,12 @@
self.shortname = self.name.split('.')[-1]
self.subdefs = []
self.attr_sources = {} # {name: list-of-sources}
+ self.read_locations_of__class__ = {}
if classdesc.basedesc:
self.basedef = classdesc.basedesc.getuniqueclassdef()
self.basedef.subdefs.append(self)
+ self.basedef.see_new_subclass(self)
else:
self.basedef = None
@@ -370,6 +373,17 @@
else:
return False
+ def see_new_subclass(self, classdef):
+ for position in self.read_locations_of__class__:
+ self.bookkeeper.annotator.reflowfromposition(position)
+ if self.basedef is not None:
+ self.basedef.see_new_subclass(classdef)
+
+ def read_attr__class__(self):
+ position = self.bookkeeper.position_key
+ self.read_locations_of__class__[position] = True
+ return SomePBC([subdef.classdesc for subdef in self.getallsubdefs()])
+
def _freeze_(self):
raise Exception, "ClassDefs are used as knowntype for instances but cannot be used as immutablevalue arguments directly"
Modified: pypy/dist/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/dist/pypy/annotation/test/test_annrpython.py (original)
+++ pypy/dist/pypy/annotation/test/test_annrpython.py Fri May 5 10:55:40 2006
@@ -2035,7 +2035,31 @@
assert isinstance(s.items[0], annmodel.SomeInteger)
assert isinstance(s.items[1], annmodel.SomeChar)
assert isinstance(s.items[2], annmodel.SomeChar)
-
+
+ def test___class___attribute(self):
+ class Base(object): pass
+ class A(Base): pass
+ class B(Base): pass
+ class C(A): pass
+ def seelater():
+ C()
+ def f(n):
+ if n == 1:
+ x = A()
+ else:
+ x = B()
+ y = B()
+ result = x.__class__, y.__class__
+ seelater()
+ return result
+
+ a = self.RPythonAnnotator()
+ s = a.build_types(f, [int])
+ assert isinstance(s.items[0], annmodel.SomePBC)
+ assert len(s.items[0].descriptions) == 4
+ assert isinstance(s.items[1], annmodel.SomePBC)
+ assert len(s.items[1].descriptions) == 1
+
def g(n):
return [0,1,2,n]
Modified: pypy/dist/pypy/annotation/unaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/unaryop.py (original)
+++ pypy/dist/pypy/annotation/unaryop.py Fri May 5 10:55:40 2006
@@ -467,6 +467,8 @@
def getattr(ins, s_attr):
if s_attr.is_constant() and isinstance(s_attr.const, str):
attr = s_attr.const
+ if attr == '__class__':
+ return ins.classdef.read_attr__class__()
attrdef = ins.classdef.find_attribute(attr)
position = getbookkeeper().position_key
attrdef.read_locations[position] = True
Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py Fri May 5 10:55:40 2006
@@ -519,6 +519,10 @@
def rtype_getattr(self, hop):
attr = hop.args_s[1].const
vinst, vattr = hop.inputargs(self, Void)
+ if attr == '__class__' and hop.r_result.lowleveltype is Void:
+ # special case for when the result of '.__class__' is a constant
+ [desc] = hop.s_result.descriptions
+ return hop.inputconst(Void, desc.pyobj)
if attr in self.allinstancefields:
return self.getfield(vinst, attr, hop.llops)
elif attr in self.rclass.allmethods:
Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rclass.py (original)
+++ pypy/dist/pypy/rpython/ootypesystem/rclass.py Fri May 5 10:55:40 2006
@@ -355,6 +355,15 @@
cname = hop.inputconst(ootype.Void, mangled)
return hop.genop("oosend", [cname, v_inst],
resulttype = hop.r_result.lowleveltype)
+ elif attr == '__class__':
+ if hop.r_result.lowleveltype is ootype.Void:
+ # special case for when the result of '.__class__' is constant
+ [desc] = hop.s_result.descriptions
+ return hop.inputconst(ootype.Void, desc.pyobj)
+ else:
+ cmeta = inputconst(ootype.Void, "meta")
+ return hop.genop('oogetfield', [v_inst, cmeta],
+ resulttype=CLASSTYPE)
else:
raise TyperError("no attribute %r on %r" % (attr, self))
Modified: pypy/dist/pypy/rpython/test/test_rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rclass.py (original)
+++ pypy/dist/pypy/rpython/test/test_rclass.py Fri May 5 10:55:40 2006
@@ -463,6 +463,30 @@
res = interpret(f, [], type_system=self.ts)
assert typeOf(res.item0) == Signed
+ def test___class___attribute(self):
+ class Base(object): pass
+ class A(Base): pass
+ class B(Base): pass
+ class C(A): pass
+ def seelater():
+ C()
+ def f(n):
+ if n == 1:
+ x = A()
+ else:
+ x = B()
+ y = B()
+ result = x.__class__, y.__class__
+ seelater()
+ return result
+ def g():
+ cls1, cls2 = f(1)
+ return cls1 is A, cls2 is B
+
+ res = interpret(g, [], type_system=self.ts)
+ assert res.item0
+ assert res.item1
+
class TestLltype(BaseTestRclass):
More information about the Pypy-commit
mailing list