[pypy-svn] r33500 - in pypy/dist/pypy: annotation rpython/ootypesystem rpython/ootypesystem/test
antocuni at codespeak.net
antocuni at codespeak.net
Fri Oct 20 14:44:58 CEST 2006
Author: antocuni
Date: Fri Oct 20 14:44:55 2006
New Revision: 33500
Modified:
pypy/dist/pypy/annotation/unaryop.py
pypy/dist/pypy/rpython/ootypesystem/ootype.py
pypy/dist/pypy/rpython/ootypesystem/rootype.py
pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py
pypy/dist/pypy/rpython/ootypesystem/test/test_ootype.py
Log:
Support for overloaded bound methods in ootype. This is quite useless
in plain RPython, but it can be exploited by high level backends such
as gencli to expose native classes.
Modified: pypy/dist/pypy/annotation/unaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/unaryop.py (original)
+++ pypy/dist/pypy/annotation/unaryop.py Fri Oct 20 14:44:55 2006
@@ -11,7 +11,6 @@
unionof, set, missing_operation, add_knowntypedata
from pypy.annotation.bookkeeper import getbookkeeper
from pypy.annotation import builtin
-
from pypy.annotation.binaryop import _clone ## XXX where to put this?
from pypy.rpython import extregistry
@@ -705,9 +704,23 @@
class __extend__(SomeOOBoundMeth):
def simple_call(m, *args_s):
inst = m.ootype._example()
- RESULT = ootype.typeOf(m.ootype._lookup(m.name)[1]).RESULT
+ _, meth = m.ootype._lookup(m.name)
+ if isinstance(meth, ootype._overloaded_meth):
+ ARGS = tuple([m._annotation_to_lltype(arg_s) for arg_s in args_s])
+ METH = meth._resolve_overloading(ARGS)._TYPE
+ else:
+ METH = ootype.typeOf(meth)
+ RESULT = METH.RESULT
return lltype_to_annotation(RESULT)
+ def _annotation_to_lltype(self, ann):
+ if isinstance(ann, SomeChar):
+ return ootype.Char
+ elif isinstance(ann, SomeString):
+ return ootype.String
+ else:
+ return annotation_to_lltype(ann)
+
class __extend__(SomeOOStaticMeth):
def simple_call(m, *args_s):
llargs = [annotation_to_lltype(arg_s)._example() for arg_s in args_s]
Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py (original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py Fri Oct 20 14:44:55 2006
@@ -6,6 +6,11 @@
from pypy.rpython import objectmodel
from pypy.tool.uid import uid
+try:
+ set
+except NameError:
+ from sets import Set as set
+
STATICNESS = True
class OOType(LowLevelType):
@@ -732,7 +737,7 @@
res = getattr(self._inst, name)
if meth:
assert isinstance(res, _bound_meth)
- return _bound_meth(res.DEFINST, _view(res.DEFINST, res.inst), res.meth)
+ return res.__class__(res.DEFINST, _view(res.DEFINST, res.inst), res.meth)
return res
def _instanceof(self, INSTANCE):
@@ -826,25 +831,84 @@
def __repr__(self):
return 'sm %s' % self._name
+
+class _bound_meth(object):
+ def __init__(self, DEFINST, inst, meth):
+ self.DEFINST = DEFINST
+ self.inst = inst
+ self.meth = meth
+
+ def __call__(self, *args):
+ callb, checked_args = self.meth._checkargs(args)
+ return callb(self.inst, *checked_args)
+
+
class _meth(_callable):
-
+ _bound_class = _bound_meth
+
def __init__(self, METHOD, **attrs):
assert isinstance(METHOD, Meth)
_callable.__init__(self, METHOD, **attrs)
def _bound(self, DEFINST, inst):
- assert isinstance(inst, _instance) or isinstance(inst, _builtin_type)
- return _bound_meth(DEFINST, inst, self)
+ TYPE = typeOf(inst)
+ assert isinstance(TYPE, (Instance, BuiltinType))
+ return self._bound_class(DEFINST, inst, self)
-class _bound_meth(object):
+
+class _overloaded_meth_desc:
+ def __init__(self, name, TYPE):
+ self.name = name
+ self.TYPE = TYPE
+
+
+class _overloaded_bound_meth(_bound_meth):
def __init__(self, DEFINST, inst, meth):
self.DEFINST = DEFINST
self.inst = inst
self.meth = meth
+ def _get_bound_meth(self, *args):
+ ARGS = tuple([typeOf(arg) for arg in args])
+ meth = self.meth._resolve_overloading(ARGS)
+ assert isinstance(meth, _meth)
+ return meth._bound(self.DEFINST, self.inst)
+
def __call__(self, *args):
- callb, checked_args = self.meth._checkargs(args)
- return callb(self.inst, *checked_args)
+ bound_meth = self._get_bound_meth(*args)
+ return bound_meth(*args)
+
+
+class _overloaded_meth(_meth):
+ _bound_class = _overloaded_bound_meth
+
+ def __init__(self, *overloadings, **attrs):
+ assert '_callable' not in attrs
+ _meth.__init__(self, Meth([], Void), _callable=None, **attrs) # use a fake method type
+ self._overloadings = overloadings
+ self._check_overloadings()
+
+ def _check_overloadings(self):
+ signatures = set()
+ for meth in self._overloadings:
+ ARGS = meth._TYPE.ARGS
+ if ARGS in signatures:
+ raise TypeError, 'Bad overloading'
+ signatures.add(ARGS)
+
+ def _resolve_overloading(self, ARGS):
+ for meth in self._overloadings:
+ # check if one of the overloadings has the correct signature
+ # TODO: this algorithm is quite naive, it doesn't handle
+ # automatic conversions
+ METH = meth._TYPE
+ if METH.ARGS == ARGS:
+ return meth
+ raise TypeError, 'No suitable overloading found for method'
+
+ def _get_desc(self, name, ARGS):
+ meth = self._resolve_overloading(ARGS)
+ return _overloaded_meth_desc(name, meth._TYPE)
class _builtin_type(object):
@@ -1210,6 +1274,9 @@
def meth(METHOD, **attrs):
return _meth(METHOD, **attrs)
+def overload(*overloadings, **attrs):
+ return _overloaded_meth(*overloadings, **attrs)
+
def null(INSTANCE_OR_FUNCTION):
return INSTANCE_OR_FUNCTION._null
Modified: pypy/dist/pypy/rpython/ootypesystem/rootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rootype.py (original)
+++ pypy/dist/pypy/rpython/ootypesystem/rootype.py Fri Oct 20 14:44:55 2006
@@ -75,15 +75,21 @@
v = rpair.rtype_eq(hop)
return hop.genop("bool_not", [v], resulttype=ootype.Bool)
-
class OOBoundMethRepr(Repr):
def __init__(self, ootype, name):
self.lowleveltype = ootype
self.name = name
def rtype_simple_call(self, hop):
+ TYPE = hop.args_r[0].lowleveltype
+ _, meth = TYPE._lookup(self.name)
+ if isinstance(meth, ootype._overloaded_meth):
+ ARGS = tuple([repr.lowleveltype for repr in hop.args_r[1:]])
+ desc = meth._get_desc(self.name, ARGS)
+ cname = hop.inputconst(Void, desc)
+ else:
+ cname = hop.inputconst(Void, self.name)
vlist = hop.inputargs(self, *hop.args_r[1:])
- cname = hop.inputconst(Void, self.name)
hop.exception_is_here()
return hop.genop("oosend", [cname]+vlist,
resulttype = hop.r_result.lowleveltype)
Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py (original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py Fri Oct 20 14:44:55 2006
@@ -1,3 +1,4 @@
+import py
from pypy.rpython.ootypesystem.ootype import *
from pypy.annotation import model as annmodel
from pypy.objspace.flow import FlowObjSpace
@@ -235,3 +236,39 @@
a = RPythonAnnotator()
s = a.build_types(oof, [int, int])
assert isinstance(s, annmodel.SomeInteger)
+
+def test_overloaded_meth():
+ C = Instance("test", ROOT, {},
+ {'foo': overload(meth(Meth([Float], Void)),
+ meth(Meth([Signed], Signed)),
+ meth(Meth([], Float)))})
+ def fn1():
+ return new(C).foo(42.5)
+ def fn2():
+ return new(C).foo(42)
+ def fn3():
+ return new(C).foo()
+ a = RPythonAnnotator()
+ assert a.build_types(fn1, []) is annmodel.s_None
+ assert isinstance(a.build_types(fn2, []), annmodel.SomeInteger)
+ assert isinstance(a.build_types(fn3, []), annmodel.SomeFloat)
+
+def test_overloaded_meth_string():
+ C = Instance("test", ROOT, {},
+ {'foo': overload(meth(Meth([Char], Signed)),
+ meth(Meth([String], Float)))})
+ def fn1():
+ return new(C).foo('a')
+ def fn2():
+ return new(C).foo('aa')
+ a = RPythonAnnotator()
+ assert isinstance(a.build_types(fn1, []), annmodel.SomeInteger)
+ assert isinstance(a.build_types(fn2, []), annmodel.SomeFloat)
+
+def test_bad_overload():
+ def fn():
+ C = Instance("test", ROOT, {},
+ {'foo': overload(meth(Meth([Signed], Void)),
+ meth(Meth([Signed], Signed)))})
+ py.test.raises(TypeError, fn)
+
Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_ootype.py (original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_ootype.py Fri Oct 20 14:44:55 2006
@@ -174,6 +174,23 @@
assert c.m(c) == 6
+def test_overloaded_method():
+ C = Instance("test", ROOT, {'a': (Signed, 3)})
+ def m1(self, x):
+ return self.a+x
+ def m2(self, x, y):
+ return self.a+x+y
+ def m3(self, x):
+ return self.a*x
+ m = overload(meth(Meth([Signed], Signed), _callable=m1, _name='m'),
+ meth(Meth([Signed, Signed], Signed), _callable=m2, _name='m'),
+ meth(Meth([Float], Float), _callable=m3, _name='m'))
+ addMethods(C, {"m": m})
+ c = new(C)
+ assert c.m(1) == 4
+ assert c.m(2, 3) == 8
+ assert c.m(2.0) == 6
+
def test_explicit_name_clash():
C = Instance("test", ROOT, {})
More information about the Pypy-commit
mailing list