[pypy-svn] r18388 - in pypy/dist/pypy/rpython/ootype: . test
boria at codespeak.net
boria at codespeak.net
Tue Oct 11 13:13:52 CEST 2005
Author: boria
Date: Tue Oct 11 13:13:51 2005
New Revision: 18388
Modified:
pypy/dist/pypy/rpython/ootype/ootype.py
pypy/dist/pypy/rpython/ootype/test/test_ootype.py
Log:
(Samuele, Arre, Bert, Boris, Aurelien)
* Functions, methods
Modified: pypy/dist/pypy/rpython/ootype/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootype/ootype.py (original)
+++ pypy/dist/pypy/rpython/ootype/ootype.py Tue Oct 11 13:13:51 2005
@@ -131,12 +131,16 @@
class Class(OOType):
- def __init__(self, name, superclass, fields):
+ def __init__(self, name, superclass, fields, methods=None):
self._superclass = superclass
self._fields = {}
self._add_fields(fields)
+ if methods is None:
+ methods = {}
+ self._methods = methods
+
self._null = _null_instance(self)
def _defl(self):
@@ -150,10 +154,16 @@
raise TypeError("Field %r exists in superclass" % name)
if type(defn) is not tuple:
+ if isinstance(defn, Meth):
+ raise TypeError("Attempting to store method in field")
+
fields[name] = (defn, defn._defl())
else:
ootype, default = defn
+ if isinstance(ootype, Meth):
+ raise TypeError("Attempting to store method in field")
+
if ootype != typeOf(default):
raise TypeError("Expected type %r for default" % ootype)
@@ -180,6 +190,23 @@
if not self._has_field(name):
raise TypeError("No field named %r" % name)
+ def _lookup(self, meth_name):
+ meth = self._methods.get(meth_name)
+
+ # XXX superclass
+
+ return meth
+
+class Func(OOType):
+
+ def __init__(self, args, result):
+ self.ARGS = tuple(args)
+ self.RESULT = result
+
+class Meth(Func):
+
+ def __init__(self, args, result):
+ Func.__init__(self, args, result)
# ____________________________________________________________
class _instance(object):
@@ -190,6 +217,10 @@
CLASS._init_instance(self)
def __getattr__(self, name):
+ meth = self._TYPE._lookup(name)
+ if meth is not None:
+ return meth._bound(self)
+
self._TYPE._check_field(name)
return self.__dict__[name]
@@ -220,9 +251,62 @@
raise RuntimeError("Assignment to field in null object")
+class _callable(object):
+
+ def __init__(self, TYPE, **attrs):
+ self._TYPE = TYPE
+ self._name = "?"
+ self._callable = None
+ self.__dict__.update(attrs)
+
+ def _checkargs(self, args):
+ if len(args) != len(self._TYPE.ARGS):
+ raise TypeError,"calling %r with wrong argument number: %r" % (self._TYPE, args)
+
+ for a, ARG in zip(args, self._TYPE.ARGS):
+ if typeOf(a) != ARG:
+ raise TypeError,"calling %r with wrong argument types: %r" % (self._TYPE, args)
+ callb = self._callable
+ if callb is None:
+ raise RuntimeError,"calling undefined function"
+ return callb
+
+class _func(_callable):
+
+ def __init__(self, FUNCTION, **attrs):
+ assert isinstance(FUNCTION, Func)
+ _callable.__init__(self, FUNCTION, **attrs)
+
+ def __call__(self, *args):
+ return self._checkargs(args)(*args)
+
+class _meth(_callable):
+
+ def __init__(self, METHOD, **attrs):
+ assert isinstance(METHOD, Meth)
+ _callable.__init__(self, METHOD, **attrs)
+
+ def _bound(self, inst):
+ return _bound_meth(inst, self)
+
+class _bound_meth(object):
+
+ def __init__(self, inst, meth):
+ self.inst = inst
+ self.meth = meth
+
+ def __call__(self, *args):
+ return self.meth._checkargs(args)(self.inst, *args)
+
def new(CLASS):
return _instance(CLASS)
+def func(FUNCTION, **attrs):
+ return _func(FUNCTION, **attrs)
+
+def meth(METHOD, **attrs):
+ return _meth(METHOD, **attrs)
+
def null(CLASS):
return CLASS._null
Modified: pypy/dist/pypy/rpython/ootype/test/test_ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootype/test/test_ootype.py (original)
+++ pypy/dist/pypy/rpython/ootype/test/test_ootype.py Tue Oct 11 13:13:51 2005
@@ -61,3 +61,49 @@
C = Class("test", None, {"a": (Signed, 3)})
py.test.raises(TypeError, """D = Class("test2", C, {"a": (Signed, 3)})""")
+
+def test_simple_function():
+ F = Func([Signed, Signed], Signed)
+ def f_(a, b):
+ return a+b
+ f = func(F, _name="f", _callable=f_)
+ assert typeOf(f) == F
+
+ result = f(2, 3)
+ assert typeOf(result) == Signed
+ assert result == 5
+
+def test_function_args():
+ F = Func([Signed, Signed], Signed)
+ def f_(a, b):
+ return a+b
+ f = func(F, _name="f", _callable=f_)
+
+ py.test.raises(TypeError, "f(2.0, 3.0)")
+ py.test.raises(TypeError, "f()")
+ py.test.raises(TypeError, "f(1, 2, 3)")
+
+def test_class_method():
+ M = Meth([Signed], Signed)
+ def m_(self, b):
+ return self.a + b
+ m = meth(M, _name="m", _callable=m_)
+
+ C = Class("test", None, {"a": (Signed, 2)}, {"m": m})
+ c = new(C)
+
+ assert c.m(3) == 5
+
+ py.test.raises(TypeError, "c.m(3.0)")
+ py.test.raises(TypeError, "c.m()")
+ py.test.raises(TypeError, "c.m(1, 2, 3)")
+
+def test_class_method_field_clash():
+ M = Meth([Signed], Signed)
+ def m_(self, b):
+ return self.a + b
+ m = meth(M, _name="m", _callable=m_)
+
+ py.test.raises(TypeError, """Class("test", None, {"a": M})""")
+
+ py.test.raises(TypeError, """Class("test", None, {"m": Signed}, {"m":m})""")
More information about the Pypy-commit
mailing list