[pypy-svn] r26843 - in pypy/dist/pypy: annotation annotation/test rpython rpython/lltypesystem rpython/lltypesystem/test rpython/test
arigo at codespeak.net
arigo at codespeak.net
Sat May 6 09:54:02 CEST 2006
Author: arigo
Date: Sat May 6 09:53:59 2006
New Revision: 26843
Modified:
pypy/dist/pypy/annotation/builtin.py
pypy/dist/pypy/annotation/description.py
pypy/dist/pypy/annotation/test/test_annrpython.py
pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py
pypy/dist/pypy/rpython/lltypesystem/rtagged.py
pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py
pypy/dist/pypy/rpython/objectmodel.py
pypy/dist/pypy/rpython/test/test_objectmodel.py
Log:
* fix for buggy __slots__ support
* enhanced UnboxedValue to allow the value to also show up
as an attribute, with a name chosen by the user
Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py (original)
+++ pypy/dist/pypy/annotation/builtin.py Sat May 6 09:53:59 2006
@@ -314,9 +314,6 @@
def robjmodel_hint(s, **kwds_s):
return s
-def robjmodel_getvalue_from_unboxed(s):
- return SomeInteger()
-
def llmemory_cast_ptr_to_adr(s):
return SomeAddress()
@@ -373,8 +370,6 @@
BUILTIN_ANALYZERS[pypy.rpython.objectmodel.hlinvoke] = robjmodel_hlinvoke
BUILTIN_ANALYZERS[pypy.rpython.objectmodel.keepalive_until_here] = robjmodel_keepalive_until_here
BUILTIN_ANALYZERS[pypy.rpython.objectmodel.hint] = robjmodel_hint
-BUILTIN_ANALYZERS[pypy.rpython.objectmodel.getvalue_from_unboxed] = \
- robjmodel_getvalue_from_unboxed
BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_ptr_to_adr] = llmemory_cast_ptr_to_adr
BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_adr_to_ptr] = llmemory_cast_adr_to_ptr
BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_adr_to_int] = llmemory_cast_adr_to_int
Modified: pypy/dist/pypy/annotation/description.py
==============================================================================
--- pypy/dist/pypy/annotation/description.py (original)
+++ pypy/dist/pypy/annotation/description.py Sat May 6 09:53:59 2006
@@ -365,41 +365,41 @@
if base is not object:
self.basedesc = bookkeeper.getdesc(base)
+ def add_source_attribute(self, name, value, mixin=False):
+ if isinstance(value, types.FunctionType):
+ # for debugging
+ if not hasattr(value, 'class_'):
+ value.class_ = self.pyobj # remember that this is really a method
+ if self.specialize:
+ # make a custom funcdesc that specializes on its first
+ # argument (i.e. 'self').
+ from pypy.annotation.specialize import specialize_argtype
+ def argtype0(funcdesc, args_s):
+ return specialize_argtype(funcdesc, args_s, 0)
+ funcdesc = FunctionDesc(self.bookkeeper, value,
+ specializer=argtype0)
+ self.classdict[name] = funcdesc
+ return
+ if mixin:
+ # make a new copy of the FunctionDesc for this class,
+ # but don't specialize further for all subclasses
+ funcdesc = FunctionDesc(self.bookkeeper, value)
+ self.classdict[name] = funcdesc
+ return
+ # NB. if value is, say, AssertionError.__init__, then we
+ # should not use getdesc() on it. Never. The problem is
+ # that the py lib has its own AssertionError.__init__ which
+ # is of type FunctionType. But bookkeeper.immutablevalue()
+ # will do the right thing in s_get_value().
+
+ if type(value) is MemberDescriptorType:
+ # skip __slots__, showing up in the class as 'member' objects
+ return
+ self.classdict[name] = Constant(value)
+
def add_sources_for_class(self, cls, mixin=False):
for name, value in cls.__dict__.items():
- ## -- useless? -- ignore some special attributes
- ##if name.startswith('_') and not isinstance(value, types.FunctionType):
- ## continue
- if isinstance(value, types.FunctionType):
- # for debugging
- if not hasattr(value, 'class_'):
- value.class_ = self.pyobj # remember that this is really a method
- if self.specialize:
- # make a custom funcdesc that specializes on its first
- # argument (i.e. 'self').
- from pypy.annotation.specialize import specialize_argtype
- def argtype0(funcdesc, args_s):
- return specialize_argtype(funcdesc, args_s, 0)
- funcdesc = FunctionDesc(self.bookkeeper, value,
- specializer=argtype0)
- self.classdict[name] = funcdesc
- continue
- if mixin:
- # make a new copy of the FunctionDesc for this class,
- # but don't specialize further for all subclasses
- funcdesc = FunctionDesc(self.bookkeeper, value)
- self.classdict[name] = funcdesc
- continue
- # NB. if value is, say, AssertionError.__init__, then we
- # should not use getdesc() on it. Never. The problem is
- # that the py lib has its own AssertionError.__init__ which
- # is of type FunctionType. But bookkeeper.immutablevalue()
- # will do the right thing in s_get_value().
-
- if type(value) is MemberDescriptorType:
- # skip __slots__, showing up in the class as 'member' objects
- continue
- self.classdict[name] = Constant(value)
+ self.add_source_attribute(name, value, mixin)
def getclassdef(self, key):
try:
@@ -531,8 +531,9 @@
# there is a new attribute
cls = self.pyobj
if name in cls.__dict__:
- self.classdict[name] = Constant(cls.__dict__[name])
- return self
+ self.add_source_attribute(name, cls.__dict__[name])
+ if name in self.classdict:
+ return self
return None
def consider_call_site(bookkeeper, family, descs, args, s_result):
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 Sat May 6 09:53:59 2006
@@ -2074,6 +2074,18 @@
s = a.build_types(f, [int])
assert s.knowntype == int
+ def test_unboxed_value(self):
+ class A(object):
+ pass
+ class C(A, objectmodel.UnboxedValue):
+ __slots__ = 'smallint'
+ def f(n):
+ return C(n).smallint
+
+ a = self.RPythonAnnotator()
+ s = a.build_types(f, [int])
+ assert s.knowntype == int
+
def g(n):
return [0,1,2,n]
Modified: pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py Sat May 6 09:53:59 2006
@@ -59,13 +59,8 @@
c = hop.inputconst(pyobj_repr, __import__)
return hop.genop('simple_call', [c] + args_v, resulttype = pyobj_repr)
-def rtype_getvalue_from_unboxed(hop):
- from pypy.rpython.lltypesystem.rtagged import rtype_getvalue_from_unboxed
- return rtype_getvalue_from_unboxed(hop)
-
BUILTIN_TYPER = {}
BUILTIN_TYPER[objectmodel.instantiate] = rtype_instantiate
-BUILTIN_TYPER[objectmodel.getvalue_from_unboxed] = rtype_getvalue_from_unboxed
BUILTIN_TYPER[isinstance] = rtype_builtin_isinstance
BUILTIN_TYPER[hasattr] = rtype_builtin_hasattr
BUILTIN_TYPER[__import__] = rtype_builtin___import__
Modified: pypy/dist/pypy/rpython/lltypesystem/rtagged.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rtagged.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/rtagged.py Sat May 6 09:53:59 2006
@@ -16,9 +16,18 @@
def _setup_repr(self):
InstanceRepr._setup_repr(self)
- if len(self.allinstancefields) != 1:
- raise TyperError("%r cannot have fields besides __class__: %r" % (
- self.classdef, self.allinstancefields.keys()))
+ flds = self.allinstancefields.keys()
+ flds.remove('__class__')
+ if self.is_parent:
+ if flds:
+ raise TyperError("%r is a base class of an UnboxedValue,"
+ "so it cannot have fields: %r" % (
+ self.classdef, flds))
+ else:
+ if len(flds) != 1:
+ raise TyperError("%r must have exactly one field: %r" % (
+ self.classdef, flds))
+ self.specialfieldname = flds[0]
def new_instance(self, llops, classcallhop=None):
if self.is_parent:
@@ -49,9 +58,13 @@
number = value.getvalue()
return ll_int_to_unboxed(self.lowleveltype, number)
- def getfield(self, vinst, attr, llops, force_cast=False):
- if attr != '__class__':
- raise MissingRTypeAttribute(attr)
+ def getvalue_from_unboxed(self, llops, vinst):
+ assert not self.is_parent
+ v2 = llops.genop('cast_ptr_to_int', [vinst], resulttype=lltype.Signed)
+ c_one = inputconst(lltype.Signed, 1)
+ return llops.genop('int_rshift', [v2, c_one], resulttype=lltype.Signed)
+
+ def gettype_from_unboxed(self, llops, vinst):
unboxedclass_repr = getclassrepr(self.rtyper, self.unboxedclassdef)
cunboxedcls = inputconst(CLASSTYPE, unboxedclass_repr.getvtable())
if self.is_parent:
@@ -61,12 +74,21 @@
else:
return cunboxedcls
+ def getfield(self, vinst, attr, llops, force_cast=False):
+ if not self.is_parent and attr == self.specialfieldname:
+ return self.getvalue_from_unboxed(llops, vinst)
+ elif attr == '__class__':
+ return self.gettype_from_unboxed(llops, vinst)
+ else:
+ raise MissingRTypeAttribute(attr)
+
def rtype_type(self, hop):
[vinst] = hop.inputargs(self)
- return self.getfield(vinst, '__class__', hop.llops)
+ return self.gettype_from_unboxed(hop.llops, vinst)
def rtype_setattr(self, hop):
- raise TyperError("cannot set attributes on %r" % (self,))
+ # only for UnboxedValue.__init__(), which is not actually called
+ hop.genop('UnboxedValue_setattr', [])
def ll_str(self, i):
if lltype.cast_ptr_to_int(i) & 1:
@@ -116,12 +138,3 @@
return answer_if_unboxed
else:
return ll_issubclass_const(obj.typeptr, minid, maxid)
-
-def rtype_getvalue_from_unboxed(hop):
- assert isinstance(hop.args_r[0], TaggedInstanceRepr)
- assert not hop.args_r[0].is_parent
- [v_instance] = hop.inputargs(hop.args_r[0])
- v2 = hop.genop('cast_ptr_to_int', [v_instance], resulttype = lltype.Signed)
- c_one = hop.inputconst(lltype.Signed, 1)
- return hop.genop('int_rshift', [v2, c_one], resulttype = lltype.Signed)
-
Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py Sat May 6 09:53:59 2006
@@ -15,15 +15,12 @@
return self.normalint + x + 2
class C(A, UnboxedValue):
+ __slots__ = 'smallint'
def meth(self, x):
- return self.getvalue() + x + 3
+ return self.smallint + x + 3
# ____________________________________________________________
-def test_on_top_of_cpython():
- assert C(17).getvalue() == 17
- assert C(20).meth(10) == 33
-
def test_instantiate():
def fn1(n):
return C(n)
@@ -31,6 +28,12 @@
value = lltype.cast_ptr_to_int(res)
assert value == 42 * 2 + 1 # for now
+def test_attribute():
+ def fn1(n):
+ return C(n).smallint
+ res = interpret(fn1, [42])
+ assert res == 42
+
def test_getvalue():
def fn1(n):
return C(n).getvalue()
@@ -49,7 +52,7 @@
if isinstance(x, B):
return 'B', x.normalint
elif isinstance(x, C):
- return 'C', x.getvalue()
+ return 'C', x.smallint
else:
return 'A', 0
@@ -68,7 +71,7 @@
x = c
else:
x = C(n)
- return x.getvalue()
+ return x.smallint
res = interpret(fn, [12])
assert res == 12
@@ -80,7 +83,7 @@
if x is None:
return sys.maxint
else:
- return x.getvalue()
+ return x.smallint
def fn(n):
if n < 0:
x = None
Modified: pypy/dist/pypy/rpython/objectmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/objectmodel.py (original)
+++ pypy/dist/pypy/rpython/objectmodel.py Sat May 6 09:53:59 2006
@@ -117,25 +117,28 @@
def __new__(cls, value):
assert '__init__' not in cls.__dict__ # won't be called anyway
+ assert isinstance(cls.__slots__, str) or len(cls.__slots__) == 1
+ return super(UnboxedValue, cls).__new__(cls)
+
+ def __init__(self, value):
+ # this funtion is annotated but not included in the translated program
int_as_pointer = value * 2 + 1 # XXX for now
if -sys.maxint-1 <= int_as_pointer <= sys.maxint:
- result = super(UnboxedValue, cls).__new__(cls)
- result._value_ = value
- return result
+ if isinstance(self.__slots__, str):
+ setattr(self, self.__slots__, value)
+ else:
+ setattr(self, self.__slots__[0], value)
else:
raise OverflowError("UnboxedValue: argument out of range")
- def __init__(self, value):
- pass
-
def __repr__(self):
return '<unboxed %d>' % (self.getvalue(),)
- def getvalue(self):
- return getvalue_from_unboxed(self)
-
-def getvalue_from_unboxed(obj):
- return obj._value_ # this function is special-cased by the annotator
+ def getvalue(self): # helper, equivalent to reading the custom field
+ if isinstance(self.__slots__, str):
+ return getattr(self, self.__slots__)
+ else:
+ return getattr(self, self.__slots__[0])
# ____________________________________________________________
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 Sat May 6 09:53:59 2006
@@ -251,3 +251,18 @@
return d[2]
res = interpret(g, [3])
assert res == 77
+
+def test_unboxed_value():
+ class Base(object):
+ pass
+ class C(Base, UnboxedValue):
+ __slots__ = 'smallint'
+
+ assert C(17).smallint == 17
+ assert C(17).getvalue() == 17
+
+ class A(UnboxedValue):
+ __slots__ = ['value']
+
+ assert A(12098).value == 12098
+ assert A(12098).getvalue() == 12098
More information about the Pypy-commit
mailing list