[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