[pypy-svn] rev 671 - in pypy/trunk/src/pypy: . interpreter interpreter/test module/test objspace/std objspace/std/test

arigo at codespeak.net arigo at codespeak.net
Thu May 29 15:31:37 CEST 2003


Author: arigo
Date: Thu May 29 15:31:36 2003
New Revision: 671

Added:
   pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py   (contents, props changed)
   pypy/trunk/src/pypy/objspace/std/typeobject.py   (contents, props changed)
   pypy/trunk/src/pypy/objspace/std/userobject.py
      - copied, changed from rev 620, pypy/trunk/src/pypy/objspace/std/usertype.py
Removed:
   pypy/trunk/src/pypy/objspace/std/usertype.py
Modified:
   pypy/trunk/src/pypy/interpreter/baseobjspace.py
   pypy/trunk/src/pypy/interpreter/test/s1.py   (props changed)
   pypy/trunk/src/pypy/interpreter/testsupport.py   (props changed)
   pypy/trunk/src/pypy/module/test/test_apply.py   (props changed)
   pypy/trunk/src/pypy/objspace/std/boolobject.py
   pypy/trunk/src/pypy/objspace/std/cpythonobject.py
   pypy/trunk/src/pypy/objspace/std/default.py   (contents, props changed)
   pypy/trunk/src/pypy/objspace/std/floatobject.py
   pypy/trunk/src/pypy/objspace/std/intobject.py
   pypy/trunk/src/pypy/objspace/std/multimethod.py
   pypy/trunk/src/pypy/objspace/std/noneobject.py
   pypy/trunk/src/pypy/objspace/std/objspace.py
   pypy/trunk/src/pypy/objspace/std/rarray.py   (props changed)
   pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py
   pypy/trunk/src/pypy/objspace/std/test/test_stdobjspace.py   (props changed)
   pypy/trunk/src/pypy/objspace/std/test/test_stringobject.py   (props changed)
   pypy/trunk/src/pypy/testwice.py   (props changed)
Log:
multimethods and basic type system coexist now

Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/trunk/src/pypy/interpreter/baseobjspace.py	Thu May 29 15:31:36 2003
@@ -163,65 +163,65 @@
 ## as 'space.op.xxx()' instead of directly 'space.xxx()'.
 
 ObjSpace.MethodTable = [
-# method name # symbol # number of arguments
-    ('id',              'id',        1),
-    ('type',            'type',      1),
-    ('issubtype',       'issubtype', 2),  # not for old-style classes
-    ('repr',            'repr',      1),
-    ('str',             'str',       1),
-    ('len',             'len',       1),
-    ('hash',            'hash',      1),
-    ('getattr',         'getattr',   2),
-    ('setattr',         'setattr',   3),
-    ('delattr',         'delattr',   2),
-    ('getitem',         'getitem',   2),
-    ('setitem',         'setitem',   3),
-    ('delitem',         'delitem',   2),
-    ('pos',             'pos',       1),
-    ('neg',             'neg',       1),
-    ('not_',            'not',       1),
-    ('abs' ,            'abs',       1),
-    ('hex',             'hex',       1),
-    ('oct',             'oct',       1),
-    ('ord',             'ord',       1),
-    ('invert',          '~',         1),
-    ('add',             '+',         2),
-    ('sub',             '-',         2),
-    ('mul',             '*',         2),
-    ('truediv',         '/',         2),
-    ('floordiv',        '//',        2),
-    ('div',             'div',       2),
-    ('mod',             '%',         2),
-    ('divmod',          'divmod',    2),
-    ('pow',             '**',        3),
-    ('lshift',          '<<',        2),
-    ('rshift',          '>>',        2),
-    ('and_',            '&',         2),
-    ('or_',             '|',         2),
-    ('xor',             '^',         2),
-    ('inplace_add',     '+=',        2),
-    ('inplace_sub',     '-=',        2),
-    ('inplace_mul',     '*=',        2),
-    ('inplace_truediv', '/=',        2),
-    ('inplace_floordiv','//=',       2),
-    ('inplace_div',     'div=',      2),
-    ('inplace_mod',     '%=',        2),
-    ('inplace_pow',     '**=',       2),
-    ('inplace_lshift',  '<<=',       2),
-    ('inplace_rshift',  '>>=',       2),
-    ('inplace_and',     '&=',        2),
-    ('inplace_or',      '|=',        2),
-    ('inplace_xor',     '^=',        2),
-    ('lt',              '<',         2),
-    ('le',              '<=',        2),
-    ('eq',              '==',        2),
-    ('ne',              '!=',        2),
-    ('gt',              '>',         2),
-    ('ge',              '>=',        2),
-    ('contains',        'contains',  2),
-    ('iter',            'iter',      1),
-    ('next',            'next',      1),  # iterator interface
-    ('call',            'call',      3),
+# method name # symbol # number of arguments # special method name(s)
+    ('id',              'id',        1, []),
+    ('type',            'type',      1, []),
+    ('issubtype',       'issubtype', 2, []),  # not for old-style classes
+    ('repr',            'repr',      1, ['__repr__']),
+    ('str',             'str',       1, ['__str__']),
+    ('len',             'len',       1, ['__len__']),
+    ('hash',            'hash',      1, ['__hash__']),
+    ('getattr',         'getattr',   2, ['__getattribute__']),
+    ('setattr',         'setattr',   3, ['__setattr__']),
+    ('delattr',         'delattr',   2, ['__delattr__']),
+    ('getitem',         'getitem',   2, ['__getitem__']),
+    ('setitem',         'setitem',   3, ['__setitem__']),
+    ('delitem',         'delitem',   2, ['__delitem__']),
+    ('pos',             'pos',       1, ['__pos__']),
+    ('neg',             'neg',       1, ['__neg__']),
+    ('not_',            'not',       1, []),
+    ('abs' ,            'abs',       1, ['__abs__']),
+    ('hex',             'hex',       1, ['__hex__']),
+    ('oct',             'oct',       1, ['__oct__']),
+    ('ord',             'ord',       1, []),
+    ('invert',          '~',         1, ['__invert__']),
+    ('add',             '+',         2, ['__add__', '__radd__']),
+    ('sub',             '-',         2, ['__sub__', '__rsub__']),
+    ('mul',             '*',         2, ['__mul__', '__rmul__']),
+    ('truediv',         '/',         2, ['__truediv__', '__rtruediv__']),
+    ('floordiv',        '//',        2, ['__floordiv__', '__rfloordiv__']),
+    ('div',             'div',       2, ['__div__', '__rdiv__']),
+    ('mod',             '%',         2, ['__mod__', '__rmod__']),
+    ('divmod',          'divmod',    2, ['__divmod__', '__rdivmod__']),
+    ('pow',             '**',        3, ['__pow__', '__rpow__']),
+    ('lshift',          '<<',        2, ['__lshift__', '__rlshift__']),
+    ('rshift',          '>>',        2, ['__rshift__', '__rrshift__']),
+    ('and_',            '&',         2, ['__and__', '__rand__']),
+    ('or_',             '|',         2, ['__or__', '__ror__']),
+    ('xor',             '^',         2, ['__xor__', '__rxor__']),
+    ('inplace_add',     '+=',        2, ['__iadd__']),
+    ('inplace_sub',     '-=',        2, ['__isub__']),
+    ('inplace_mul',     '*=',        2, ['__imul__']),
+    ('inplace_truediv', '/=',        2, ['__itruediv__']),
+    ('inplace_floordiv','//=',       2, ['__ifloordiv__']),
+    ('inplace_div',     'div=',      2, ['__idiv__']),
+    ('inplace_mod',     '%=',        2, ['__imod__']),
+    ('inplace_pow',     '**=',       2, ['__ipow__']),
+    ('inplace_lshift',  '<<=',       2, ['__ilshift__']),
+    ('inplace_rshift',  '>>=',       2, ['__irshift__']),
+    ('inplace_and',     '&=',        2, ['__iand__']),
+    ('inplace_or',      '|=',        2, ['__ior__']),
+    ('inplace_xor',     '^=',        2, ['__ixor__']),
+    ('lt',              '<',         2, ['__lt__', '__gt__']),
+    ('le',              '<=',        2, ['__le__', '__ge__']),
+    ('eq',              '==',        2, ['__eq__', '__eq__']),
+    ('ne',              '!=',        2, ['__ne__', '__ne__']),
+    ('gt',              '>',         2, ['__gt__', '__lt__']),
+    ('ge',              '>=',        2, ['__ge__', '__le__']),
+    ('contains',        'contains',  2, ['__contains__']),
+    ('iter',            'iter',      1, ['__iter__']),
+    ('next',            'next',      1, ['next']),  # iterator interface
+    ('call',            'call',      3, ['__call__']),
     ]
 
 ObjSpace.BuiltinModuleTable = [

Modified: pypy/trunk/src/pypy/objspace/std/boolobject.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/boolobject.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/boolobject.py	Thu May 29 15:31:36 2003
@@ -3,6 +3,7 @@
 
 class W_BoolObject(W_Object):
     delegate_once = {}
+    statictypename = 'bool'
 
     def __init__(w_self, space, boolval):# please pass in a real bool, not an int
         W_Object.__init__(w_self, space)

Modified: pypy/trunk/src/pypy/objspace/std/cpythonobject.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/cpythonobject.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/cpythonobject.py	Thu May 29 15:31:36 2003
@@ -123,7 +123,7 @@
     'iter':               iter,
     }
 
-for _name, _symbol, _arity in ObjSpace.MethodTable:
+for _name, _symbol, _arity, _specialnames in ObjSpace.MethodTable:
     f = MethodImplementation.get(_name)
     if f:
         if _arity == 1:

Modified: pypy/trunk/src/pypy/objspace/std/default.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/default.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/default.py	Thu May 29 15:31:36 2003
@@ -71,7 +71,7 @@
 
 # in-place operators fall back to their non-in-place counterpart
 
-for _name, _symbol, _arity in ObjSpace.MethodTable:
+for _name, _symbol, _arity, _specialnames in ObjSpace.MethodTable:
     if _name.startswith('inplace_'):
         def default_inplace(space, w_1, w_2, baseop=_name[8:]):
             op = getattr(space, baseop)

Modified: pypy/trunk/src/pypy/objspace/std/floatobject.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/floatobject.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/floatobject.py	Thu May 29 15:31:36 2003
@@ -7,25 +7,40 @@
 ##############################################################
 
 import math
+import intobject
 
 applicationfile = StdObjSpace.AppFile(__name__)
 
 class W_FloatObject(W_Object):
     """This is a reimplementation of the CPython "PyFloatObject" 
        it is assumed that the constructor takes a real Python float as
-       an argument""" 
+       an argument"""
+
+    delegate_once = {}
+    statictypename = 'float'
     
     def __init__(w_self, space, floatval):
         W_Object.__init__(w_self, space)
         w_self.floatval = floatval
 
+# int-to-float delegation
+def int_to_float(space, w_intobj):
+    return W_FloatObject(space, float(w_intobj.intval))
+intobject.W_IntObject.delegate_once[W_FloatObject] = int_to_float
+
+
 def float_float(space,w_value):
     if w_value.__class__ == W_FloatObject:
         return w_value
     else:
         return W_FloatObject(space, w_value.floatval)
 
-StdObjSpace.float.register(float_float, W_FloatObject)
+#?StdObjSpace.float.register(float_float, W_FloatObject)
+
+def float_unwrap(space, w_float):
+    return w_float.floatval
+
+StdObjSpace.unwrap.register(float_unwrap, W_FloatObject)
 
 def float_repr(space, w_float):
     ## %reimplement%
@@ -41,17 +56,41 @@
 
 StdObjSpace.str.register(float_str, W_FloatObject)
 
-def float_float_compare(space, w_float1, w_float2):
-    x = w_float1.floatval
-    y = w_float2.floatval
-    if x < y:
-        return space.wrap(-1)
-    elif x > y:
-        return space.wrap(1)
-    else:
-        return space.wrap(0)
-
-StdObjSpace.cmp.register(float_float_compare, W_FloatObject, W_FloatObject)
+def float_float_lt(space, w_float1, w_float2):
+    i = w_float1.floatval
+    j = w_float2.floatval
+    return space.newbool( i < j )
+StdObjSpace.lt.register(float_float_lt, W_FloatObject, W_FloatObject)
+
+def float_float_le(space, w_float1, w_float2):
+    i = w_float1.floatval
+    j = w_float2.floatval
+    return space.newbool( i <= j )
+StdObjSpace.le.register(float_float_le, W_FloatObject, W_FloatObject)
+
+def float_float_eq(space, w_float1, w_float2):
+    i = w_float1.floatval
+    j = w_float2.floatval
+    return space.newbool( i == j )
+StdObjSpace.eq.register(float_float_eq, W_FloatObject, W_FloatObject)
+
+def float_float_ne(space, w_float1, w_float2):
+    i = w_float1.floatval
+    j = w_float2.floatval
+    return space.newbool( i != j )
+StdObjSpace.ne.register(float_float_ne, W_FloatObject, W_FloatObject)
+
+def float_float_gt(space, w_float1, w_float2):
+    i = w_float1.floatval
+    j = w_float2.floatval
+    return space.newbool( i > j )
+StdObjSpace.gt.register(float_float_gt, W_FloatObject, W_FloatObject)
+
+def float_float_ge(space, w_float1, w_float2):
+    i = w_float1.floatval
+    j = w_float2.floatval
+    return space.newbool( i >= j )
+StdObjSpace.ge.register(float_float_ge, W_FloatObject, W_FloatObject)
     
 def float_hash(space,w_value):
     ## %reimplement%
@@ -188,7 +227,7 @@
 def float_nonzero(space, w_float):
     return w_float.floatval != 0.0
 
-StdObjSpace.nonzero.register(float_nonzero, W_FloatObject)
+StdObjSpace.is_true.register(float_nonzero, W_FloatObject)
 
 ######## coersion must be done later
 later = """

Modified: pypy/trunk/src/pypy/objspace/std/intobject.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/intobject.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/intobject.py	Thu May 29 15:31:36 2003
@@ -23,6 +23,7 @@
 class W_IntObject(W_Object):
 
     delegate_once = {}
+    statictypename = 'int'
     
     def __init__(w_self, space, intval):
         W_Object.__init__(w_self, space)

Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/multimethod.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/multimethod.py	Thu May 29 15:31:36 2003
@@ -6,15 +6,17 @@
 
 class W_ANY:
     "Placeholder to allow dispatch on any value."
+    statictype = None
 
 
 class MultiMethod(object):
 
-    def __init__(self, operatorsymbol, arity):
+    def __init__(self, operatorsymbol, arity, specialnames):
         "MultiMethod dispatching on the first 'arity' arguments."
         self.arity = arity
         self.operatorsymbol = operatorsymbol
         self.dispatch_table = {}
+        self.specialnames = specialnames  # list like ['__xxx__', '__rxxx__']
 
     def register(self, function, *types):
         # W_ANY can be used as a placeholder to dispatch on any value.
@@ -61,6 +63,16 @@
                                            currentdelegators + (delegator,),
                                            result)
 
+    def slicetable(self, position, statictype):
+        m = MultiMethod(self.operatorsymbol, self.arity, self.specialnames)
+        for key, value in self.dispatch_table.iteritems():
+            if key[position].statictype == statictype:
+                m.dispatch_table[key] = value
+        return m
+
+    def is_empty(self):
+        return not self.dispatch_table
+
 
 class BoundMultiMethod:
 
@@ -73,8 +85,26 @@
             raise TypeError, ("multimethod needs at least %d arguments" %
                               self.multimethod.arity)
         dispatchargs = args[:self.multimethod.arity]
-        extraargs    = args[self.multimethod.arity:]
         initialtypes = tuple([a.__class__ for a in dispatchargs])
+        try:
+            return self.perform_call(args, initialtypes)
+        except FailedToImplement, e:
+            if e.args:
+                raise OperationError(*e.args)
+            else:
+                if len(initialtypes) <= 1:
+                    plural = ""
+                else:
+                    plural = "s"
+                typenames = [t.__name__ for t in initialtypes]
+                message = "unsupported operand type%s for %s: %s" % (
+                    plural, self.multimethod.operatorsymbol,
+                    ', '.join(typenames))
+                w_value = self.space.wrap(message)
+                raise OperationError(self.space.w_TypeError, w_value)
+
+    def perform_call(self, args, initialtypes):
+        extraargs = args[self.multimethod.arity:]
         choicelist = self.multimethod.buildchoices(initialtypes)
         firstfailure = None
         for delegators, function in choicelist:
@@ -90,19 +120,14 @@
                 # we got FailedToImplement, record the first such error
                 if firstfailure is None:
                     firstfailure = e
-        if firstfailure is None:
-            if len(initialtypes) <= 1:
-                plural = ""
-            else:
-                plural = "s"
-            typenames = [t.__name__ for t in initialtypes]
-            message = "unsupported operand type%s for %s: %s" % (
-                plural, self.multimethod.operatorsymbol,
-                ', '.join(typenames))
-            w_value = self.space.wrap(message)
-            raise OperationError(self.space.w_TypeError, w_value)
-        else:
-            raise OperationError(*e.args)
+        raise firstfailure or FailedToImplement()
+
+    def slicetable(self, position, statictype):
+        return BoundMultiMethod(self.space,
+            self.multimethod.slicetable(position, statictype))
+
+    def is_empty(self):
+        return self.multimethod.is_empty()
 
 
 class error(Exception):

Modified: pypy/trunk/src/pypy/objspace/std/noneobject.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/noneobject.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/noneobject.py	Thu May 29 15:31:36 2003
@@ -3,6 +3,7 @@
 
 class W_NoneObject(W_Object):
     delegate_once = {}
+    statictypename = 'NoneType'
 
 
 def none_unwrap(space, w_none):

Modified: pypy/trunk/src/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/objspace.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/objspace.py	Thu May 29 15:31:36 2003
@@ -10,9 +10,14 @@
 
 class W_Object:
     "Parent base class for wrapped objects."
+    statictype = None
+    
     def __init__(w_self, space):
         w_self.space = space
 
+    def get_builtin_impl_class(w_self):
+        return w_self.__class__
+
 
 ##################################################################
 
@@ -26,24 +31,45 @@
         pass
     AppFile.LOCAL_PATH = [PACKAGE_PATH]
 
+    BUILTIN_TYPES = {
+        'W_NoneObject':  'noneobject',
+        'W_BoolObject':  'boolobject',
+        'W_IntObject':   'intobject',
+        'W_FloatObject': 'floatobject',
+        #'W_ListObject': 'listobject',
+        }
+    TYPE_CACHE = {}
+
     def initialize(self):
         from noneobject    import W_NoneObject
         from boolobject    import W_BoolObject
         from cpythonobject import W_CPythonObject
+        from typeobject    import W_TypeObject, make_type_by_name
         self.w_None  = W_NoneObject(self)
         self.w_False = W_BoolObject(self, False)
         self.w_True  = W_BoolObject(self, True)
+        self.w_NotImplemented = self.wrap(NotImplemented)  # XXX do me
         # hack in the exception classes
         import __builtin__, types
         newstuff = {"False": self.w_False,
                     "True" : self.w_True,
                     "None" : self.w_None,
+                    "NotImplemented": self.w_NotImplemented,
                     }
         for n, c in __builtin__.__dict__.iteritems():
             if isinstance(c, types.ClassType) and issubclass(c, Exception):
                 w_c = W_CPythonObject(self, c)
                 setattr(self, 'w_' + c.__name__, w_c)
                 newstuff[c.__name__] = w_c
+        # make the types
+        for classname, modulename in self.BUILTIN_TYPES.iteritems():
+            mod = __import__(modulename, globals(), locals(), [classname])
+            cls = getattr(mod, classname)
+            w_type = make_type_by_name(self, cls.statictypename)
+            w_type.setup_builtin_type(cls)
+            setattr(self, 'w_' + cls.statictypename, w_type)
+            newstuff[cls.statictypename] = w_type
+        
         self.make_builtins()
         self.make_sys()
         # insert these into the newly-made builtins
@@ -71,9 +97,9 @@
             items_w = [(self.wrap(k), self.wrap(v)) for (k, v) in x.iteritems()]
             import dictobject
             return dictobject.W_DictObject(self, items_w)
-        #if isinstance(x, float):
-        #    import floatobject
-        #    return floatobject.W_FloatObject(self, x)
+        if isinstance(x, float):
+            import floatobject
+            return floatobject.W_FloatObject(self, x)
         if isinstance(x, tuple):
             wrappeditems = [self.wrap(item) for item in x]
             import tupleobject
@@ -124,8 +150,9 @@
         return stringobject.W_StringObject(self, ''.join(chars))
 
     # special multimethods
-    unwrap  = MultiMethod('unwrap', 1)   # returns an unwrapped object
-    is_true = MultiMethod('nonzero', 1)  # returns an unwrapped bool
+    unwrap  = MultiMethod('unwrap', 1, [])   # returns an unwrapped object
+    is_true = MultiMethod('nonzero', 1, [])  # returns an unwrapped bool
+    # XXX do something about __nonzero__ !
 
 ##    # handling of the common fall-back cases
 ##    def compare_any_any(self, w_1, w_2, operation):
@@ -141,8 +168,8 @@
 
 
 # add all regular multimethods to StdObjSpace
-for _name, _symbol, _arity in ObjSpace.MethodTable:
-    setattr(StdObjSpace, _name, MultiMethod(_symbol, _arity))
+for _name, _symbol, _arity, _specialnames in ObjSpace.MethodTable:
+    setattr(StdObjSpace, _name, MultiMethod(_symbol, _arity, _specialnames))
 
 # default implementations of some multimethods for all objects
 # that don't explicitely override them or that raise FailedToImplement

Modified: pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/test/test_multimethod.py	Thu May 29 15:31:36 2003
@@ -44,7 +44,7 @@
     return "add_int_any", y1, o2
 
 class FakeObjSpace:
-    add = MultiMethod('+', 2)
+    add = MultiMethod('+', 2, [])
     add.register(add_x_x,           X,   X)
     add.register(add_x_y,           X,   Y)
     add.register(add_y_y,           Y,   Y)

Added: pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/objspace/std/test/test_typeobject.py	Thu May 29 15:31:36 2003
@@ -0,0 +1,59 @@
+import unittest, sys
+import testsupport
+from pypy.interpreter import unittest_w
+from pypy.objspace.std import typeobject as tobj
+from pypy.objspace.std.objspace import *
+
+
+class TestPyMultimethodCode(unittest_w.TestCase_w):
+
+    def setUp(self):
+        self.space = StdObjSpace()
+
+    def tearDown(self):
+        pass
+
+    def test_int_sub(self):
+        w = self.space.wrap
+        for i in range(2):
+            meth = tobj.PyMultimethodCode(self.space.sub, i, self.space.w_int)
+            self.assertEqual(meth.multimethod.is_empty(), False)
+            # test int.__sub__ and int.__rsub__
+            self.assertEqual_w(meth.eval_code(self.space, None,
+                                              w({'x1': 5, 'x2': 7})),
+                               w(-2))
+            self.assertEqual_w(meth.eval_code(self.space, None,
+                                              w({'x1': 5, 'x2': 7.1})),
+                               self.space.w_NotImplemented)
+            self.assertEqual_w(meth.eval_code(self.space, None,
+                                              w({'x1': 5.5, 'x2': 7})),
+                               self.space.w_NotImplemented)
+
+    def test_empty_inplace_add(self):
+        for i in range(2):
+            meth = tobj.PyMultimethodCode(self.space.inplace_add, i,
+                                          self.space.w_int)
+            self.assertEqual(meth.multimethod.is_empty(), True)
+
+    def test_float_sub(self):
+        w = self.space.wrap
+        for i in range(2):
+            meth = tobj.PyMultimethodCode(self.space.sub, i, self.space.w_float)
+            self.assertEqual(meth.multimethod.is_empty(), False)
+            # test float.__sub__ and float.__rsub__
+
+            # some of these tests are pointless for Python because
+            # float.__(r)sub__ should not accept an int as first argument
+            self.assertEqual_w(meth.eval_code(self.space, None,
+                                              w({'x1': 5, 'x2': 7})),
+                               w(-2.0))
+            self.assertEqual_w(meth.eval_code(self.space, None,
+                                              w({'x1': 5, 'x2': 7.5})),
+                               w(-2.5))
+            self.assertEqual_w(meth.eval_code(self.space, None,
+                                              w({'x1': 5.5, 'x2': 7})),
+                               w(-1.5))
+
+
+if __name__ == '__main__':
+    unittest.main()

Added: pypy/trunk/src/pypy/objspace/std/typeobject.py
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/objspace/std/typeobject.py	Thu May 29 15:31:36 2003
@@ -0,0 +1,62 @@
+from pypy.interpreter import pycode
+from pypy.objspace.std.objspace import *
+
+
+class W_TypeObject(W_Object):
+    delegate_once = {}
+    statictypename = 'type'
+
+    def __init__(w_self, space, w_tpname):
+        W_Object.__init__(w_self, space)
+        w_self.w_tpname = w_tpname
+        w_self.builtin_implementations = []
+        w_self.multimethods = [value for key, value in space.__dict__.iteritems()
+                                     if isinstance(value, MultiMethod)]
+
+    def setup_builtin_type(w_self, implementation):
+        implementation.statictype = w_self
+        w_self.builtin_implementations.append(implementation)
+
+
+def make_type_by_name(space, tpname):
+    try:
+        w_type = space.TYPE_CACHE[tpname]
+    except KeyError:
+        w_type = space.TYPE_CACHE[tpname] = W_TypeObject(space,
+                                                         space.wrap(tpname))
+    return w_type
+
+
+class PyMultimethodCode(pycode.PyBaseCode):
+    
+    def __init__(self, multimethod, bound_position=None, w_type=None):
+        pycode.PyBaseCode.__init__(self)
+        argnames = ['x%d'%(i+1) for i in range(multimethod.multimethod.arity)]
+        if w_type is not None:
+            multimethod = multimethod.slicetable(bound_position, w_type)
+            argnames.insert(0, argnames.pop(bound_position))
+        self.multimethod = multimethod
+        self.co_name = multimethod.multimethod.operatorsymbol
+        self.co_flags = 0
+        self.co_varnames = tuple(argnames)
+        self.co_argcount = multimethod.multimethod.arity
+
+    def eval_code(self, space, w_globals, w_locals):
+        """Call the multimethod, ignoring all implementations that do not
+        have exactly the expected type at the bound_position."""
+        multimethod = self.multimethod
+        dispatchargs = []
+        initialtypes = []
+        for i in range(multimethod.multimethod.arity):
+            w_arg = space.getitem(w_locals, space.wrap('x%d'%(i+1)))
+            dispatchargs.append(w_arg)
+            initialtypes.append(w_arg.get_builtin_impl_class())
+        dispatchargs = tuple(dispatchargs)
+        initialtypes = tuple(initialtypes)
+        try:
+            return multimethod.perform_call(dispatchargs, initialtypes)
+        except FailedToImplement, e:
+            if e.args:
+                raise OperationError(*e.args)
+            else:
+                return space.w_NotImplemented

Copied: pypy/trunk/src/pypy/objspace/std/userobject.py (from rev 620, pypy/trunk/src/pypy/objspace/std/usertype.py)
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/usertype.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/userobject.py	Thu May 29 15:31:36 2003
@@ -1,5 +1,6 @@
+from pypy.objspace.std.objspace import *
 
 
-class W_UserType:
-    def __init__(self):
-        pass
+class W_UserObject(W_Object):
+    pass
+

Deleted: pypy/trunk/src/pypy/objspace/std/usertype.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/usertype.py	Thu May 29 15:31:36 2003
+++ (empty file)
@@ -1,5 +0,0 @@
-
-
-class W_UserType:
-    def __init__(self):
-        pass


More information about the Pypy-commit mailing list