[pypy-svn] rev 1053 - in pypy/trunk/src/pypy: interpreter objspace/stdobjspace/std/test

arigo at codespeak.net arigo at codespeak.net
Tue Jun 24 15:50:58 CEST 2003


Author: arigo
Date: Tue Jun 24 15:50:57 2003
New Revision: 1053

Modified:
   pypy/trunk/src/pypy/interpreter/baseobjspace.py
   pypy/trunk/src/pypy/objspace/std/dictobject.py
   pypy/trunk/src/pypy/objspace/std/dicttype.py
   pypy/trunk/src/pypy/objspace/std/floattype.py
   pypy/trunk/src/pypy/objspace/std/inttype.py
   pypy/trunk/src/pypy/objspace/std/listobject.py
   pypy/trunk/src/pypy/objspace/std/listtype.py
   pypy/trunk/src/pypy/objspace/std/objectobject.py
   pypy/trunk/src/pypy/objspace/std/objecttype.py
   pypy/trunk/src/pypy/objspace/std/objspace.py
   pypy/trunk/src/pypy/objspace/std/register_all.py
   pypy/trunk/src/pypy/objspace/std/slicetype.py
   pypy/trunk/src/pypy/objspace/std/stringtype.py
   pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py
   pypy/trunk/src/pypy/objspace/std/tupletype.py
   pypy/trunk/src/pypy/objspace/std/typeobject.py
   pypy/trunk/src/pypy/objspace/std/typetype.py
   pypy/trunk/src/pypy/objspace/std/userobject.py
   pypy/trunk/src/pypy/objspace/std/usertype.py
Log:
Got the __new__ and __init__ methods (probably) right.
Reorganized constructors of all object types accordingly.


Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/trunk/src/pypy/interpreter/baseobjspace.py	Tue Jun 24 15:50:57 2003
@@ -226,8 +226,6 @@
     ('get',             'get',       3, ['__get__']),
     ('set',             'set',       2, ['__set__']),
     ('delete',          'delete',    2, ['__delete__']),
-    ('new',             'new',       3, ['__new__']),
-    ('init',            'init',      3, ['__init__']),
     ]
 
 ObjSpace.BuiltinModuleTable = [

Modified: pypy/trunk/src/pypy/objspace/std/dictobject.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/dictobject.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/dictobject.py	Tue Jun 24 15:50:57 2003
@@ -88,6 +88,26 @@
         result[space.unwrap(w_key)] = space.unwrap(cell.get())
     return result
 
+def object_init__Dict_ANY_ANY(space, w_dict, w_args, w_kwds):
+    # w_kwds = w_kwds.copy() w unwrap & rewrap, but that should not be needed
+    dict_clear__Dict(space, w_dict)
+    args = space.unpackiterable(w_args)
+    if len(args) == 0:
+        pass
+    elif len(args) == 1:
+        # XXX do dict({...}) with dict_update__Dict_Dict()
+        list_of_w_pairs = space.unpackiterable(args[0])
+        for w_pair in list_of_w_pairs:
+            pair = space.unpackiterable(w_pair)
+            if len(pair)!=2:
+                raise OperationError(space.w_ValueError,
+                             space.wrap("dict() takes a sequence of pairs"))
+            w_k, w_v = pair
+            setitem__Dict_ANY_ANY(space, w_dict, w_k, w_v)
+    else:
+        raise OperationError(space.w_TypeError,
+                             space.wrap("dict() takes at most 1 argument"))
+
 def getitem__Dict_ANY(space, w_dict, w_lookup):
     data = w_dict.non_empties()
     # XXX shouldn't this use hashing? -- mwh

Modified: pypy/trunk/src/pypy/objspace/std/dicttype.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/dicttype.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/dicttype.py	Tue Jun 24 15:50:57 2003
@@ -28,26 +28,8 @@
 
 registerimplementation(W_DictType)
 
-# XXX we'll worry about the __new__/__init__ distinction later
-def dicttype_new(space, w_listtype, w_args, w_kwds):
-    # w_kwds = w_kwds.copy() w unwrap & rewrap, but that should not be needed
-    args = space.unpackiterable(w_args)
-    if len(args) == 0:
-        pass
-    elif len(args) == 1:
-        list_of_w_pairs = space.unpackiterable(args[0])
-        list_of_w_pairs.reverse()
-        for pair_w in list_of_w_pairs:
-            pair = space.unpackiterable(pair_w)
-            if len(pair)!=2:
-                raise OperationError(space.w_ValueError,
-                             space.wrap("dict() takes a sequence of pairs"))
-            k, v = pair
-            if not space.is_true(space.contains(w_kwds, k)):
-                space.setitem(w_kwds, k, v)
-    else:
-        raise OperationError(space.w_TypeError,
-                             space.wrap("dict() takes at most 1 argument"))
-    return w_kwds
 
-StdObjSpace.new.register(dicttype_new, W_DictType, W_ANY, W_ANY)
+def type_new__DictType_DictType_ANY_ANY(space, w_basetype, w_dicttype, w_args, w_kwds):
+    return space.newdict([]), True
+
+register_all(vars())

Modified: pypy/trunk/src/pypy/objspace/std/floattype.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/floattype.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/floattype.py	Tue Jun 24 15:50:57 2003
@@ -8,24 +8,25 @@
 
 registerimplementation(W_FloatType)
 
-def new__FloatType_ANY_ANY(space, w_inttype, w_args, w_kwds):
+
+def type_new__FloatType_FloatType_ANY_ANY(space, w_basetype, w_floattype, w_args, w_kwds):
     if space.is_true(w_kwds):
         raise OperationError(space.w_TypeError,
                              space.wrap("no keyword arguments expected"))
     args = space.unpackiterable(w_args)
     if len(args) == 0:
-        return space.newint(0)
+        return space.newfloat(0), True
     elif len(args) == 1:
         arg = args[0]
         if space.is_true(space.issubtype(space.type(arg),
                                          space.w_str)):
             try:
-                return space.newfloat(float(space.unwrap(arg)))
+                return space.newfloat(float(space.unwrap(arg))), True
             except TypeError:
                 raise OperationError(space.w_TypeError,
                                      space.wrap("invalid literal for float()"))
         else:
-            return space.float(args[0])
+            return space.float(args[0]), True
     else:
         raise OperationError(space.w_TypeError,
                              space.wrap("float() takes at most 1 argument"))

Modified: pypy/trunk/src/pypy/objspace/std/inttype.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/inttype.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/inttype.py	Tue Jun 24 15:50:57 2003
@@ -9,27 +9,26 @@
 registerimplementation(W_IntType)
 
 
-# XXX we'll worry about the __new__/__init__ distinction later
-def inttype_new(space, w_inttype, w_args, w_kwds):
+def type_new__IntType_IntType_ANY_ANY(space, w_basetype, w_inttype, w_args, w_kwds):
     if space.is_true(w_kwds):
         raise OperationError(space.w_TypeError,
                              space.wrap("no keyword arguments expected"))
     args = space.unpackiterable(w_args)
     if len(args) == 0:
-        return space.newint(0)
+        return space.newint(0), True
     elif len(args) == 1:
         arg = args[0]
         if space.is_true(space.issubtype(space.type(arg),
                                          space.w_str)):
             try:
-                return space.newint(int(space.unwrap(arg)))
+                return space.newint(int(space.unwrap(arg))), True
             except TypeError:
                 raise OperationError(space.w_TypeError,
                                      space.wrap("invalid literal for int()"))
         else:
-            return space.int(args[0])
+            return space.int(args[0]), True
     else:
         raise OperationError(space.w_TypeError,
                              space.wrap("int() takes at most 1 argument"))
 
-StdObjSpace.new.register(inttype_new, W_IntType, W_ANY, W_ANY)
+register_all(vars())

Modified: pypy/trunk/src/pypy/objspace/std/listobject.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/listobject.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/listobject.py	Tue Jun 24 15:50:57 2003
@@ -35,6 +35,27 @@
     items = [space.unwrap(w_item) for w_item in w_list.ob_item[:w_list.ob_size]]
     return list(items)
 
+def object_init__List_ANY_ANY(space, w_list, w_args, w_kwds):
+    if space.is_true(w_kwds):
+        raise OperationError(space.w_TypeError,
+                             space.wrap("no keyword arguments expected"))
+    w_list.ob_size = 0  # XXX think about it later
+    args = space.unpackiterable(w_args)
+    if len(args) == 0:
+        pass   # empty list
+    elif len(args) == 1:
+        w_iterable = args[0]
+        w_iterator = space.iter(w_iterable)
+        while True:
+            try:
+                w_item = space.next(w_iterator)
+            except NoValue:
+                break  # done
+            _ins1(w_list, w_list.ob_size, w_item)
+    else:
+        raise OperationError(space.w_TypeError,
+                             space.wrap("list() takes at most 1 argument"))
+
 def len__List(space, w_list):
     result = w_list.ob_size
     return W_IntObject(space, result)
@@ -158,23 +179,24 @@
     items[idx] = w_any
     return space.w_None
 
-# not trivial!
+# XXX not trivial!
 def setitem__List_Slice_List(space, w_list, w_slice, w_list2):
-    items = w_list.ob_item
-    w_length = space.wrap(w_list.ob_size)
-    w_start, w_stop, w_step, w_slicelength = w_slice.indices(w_length)
-    start       = space.unwrap(w_start)
-    step        = space.unwrap(w_step)
-    slicelength = space.unwrap(w_slicelength)
-    assert slicelength >= 0
-    w_res = W_ListObject(space, [])
-    _list_resize(w_res, slicelength)
-    subitems = w_res.ob_item
-    for i in range(slicelength):
-        subitems[i] = items[start]
-        start += step
-    w_res.ob_size = slicelength
-    return w_res
+    raise Exception, "not done!"
+##    items = w_list.ob_item
+##    w_length = space.wrap(w_list.ob_size)
+##    w_start, w_stop, w_step, w_slicelength = w_slice.indices(w_length)
+##    start       = space.unwrap(w_start)
+##    step        = space.unwrap(w_step)
+##    slicelength = space.unwrap(w_slicelength)
+##    assert slicelength >= 0
+##    w_res = W_ListObject(space, [])
+##    _list_resize(w_res, slicelength)
+##    subitems = w_res.ob_item
+##    for i in range(slicelength):
+##        subitems[i] = items[start]
+##        start += step
+##    w_res.ob_size = slicelength
+##    return w_res
 
 def repr__List(space, w_list):
     w = space.wrap

Modified: pypy/trunk/src/pypy/objspace/std/listtype.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/listtype.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/listtype.py	Tue Jun 24 15:50:57 2003
@@ -19,20 +19,7 @@
 registerimplementation(W_ListType)
 
 
-# XXX right now, this is responsible for building a whole new list
-# XXX we'll worry about the __new__/__init__ distinction later
-def listtype_new(space, w_listtype, w_args, w_kwds):
-    if space.is_true(w_kwds):
-        raise OperationError(space.w_TypeError,
-                             space.wrap("no keyword arguments expected"))
-    args = space.unpackiterable(w_args)
-    if len(args) == 0:
-        list_w = []
-    elif len(args) == 1:
-        list_w = space.unpackiterable(args[0])
-    else:
-        raise OperationError(space.w_TypeError,
-                             space.wrap("list() takes at most 1 argument"))
-    return space.newlist(list_w)
+def type_new__ListType_ListType_ANY_ANY(space, w_basetype, w_listtype, w_args, w_kwds):
+    return space.newlist([]), True
 
-StdObjSpace.new.register(listtype_new, W_ListType, W_ANY, W_ANY)
+register_all(vars())

Modified: pypy/trunk/src/pypy/objspace/std/objectobject.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/objectobject.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/objectobject.py	Tue Jun 24 15:50:57 2003
@@ -17,5 +17,8 @@
     return W_ObjectObject(space)
 delegate__ANY.priority = PRIORITY_PARENT_TYPE
 
+def object_init__Object_ANY_ANY(space, w_object, w_args, w_kwds):
+    pass
+
 
 register_all(vars())

Modified: pypy/trunk/src/pypy/objspace/std/objecttype.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/objecttype.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/objecttype.py	Tue Jun 24 15:50:57 2003
@@ -20,14 +20,16 @@
     object_str     = StdObjSpace.str
     object_hash    = StdObjSpace.hash
 
+    # this is a method in 'object' because it is not an object space operation
+    object_init    = MultiMethod('__init__', 3, varargs=True, keywords=True)
+
 registerimplementation(W_ObjectType)
 
 
-# XXX we'll worry about the __new__/__init__ distinction later
-def new__ObjectType_ANY_ANY(space, w_objecttype, w_args, w_kwds):
+def type_new__ObjectType_ObjectType_ANY_ANY(space, w_basetype, w_objecttype, w_args, w_kwds):
     # XXX 2.2 behavior: ignoring all arguments
     from objectobject import W_ObjectObject
-    return W_ObjectObject(space)
+    return W_ObjectObject(space), True
 
 
 ### The following implementations are registered to the

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	Tue Jun 24 15:50:57 2003
@@ -302,5 +302,6 @@
 # import the common base W_ObjectObject as well as
 # default implementations of some multimethods for all objects
 # that don't explicitely override them or that raise FailedToImplement
+from pypy.objspace.std.register_all import register_all
 import pypy.objspace.std.objectobject
 import pypy.objspace.std.default

Modified: pypy/trunk/src/pypy/objspace/std/register_all.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/register_all.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/register_all.py	Tue Jun 24 15:50:57 2003
@@ -14,6 +14,9 @@
     for registration. 
     """
     from pypy.objspace.std.objspace import StdObjSpace, W_ANY
+    namespaces = [StdObjSpace]
+    if alt_ns:
+        namespaces.insert(0, alt_ns)
 
     for name, obj in module_dict.items():
         if name.find('__')<1:
@@ -32,23 +35,40 @@
                              i, i, name)
             l.append(icls)
 
-        if len(l) != obj.func_code.co_argcount-1:
-            raise ValueError, \
-                  "function name %s doesn't specify exactly %d arguments" % (
-                     repr(name), obj.func_code.co_argcount-1)
+        #XXX trying to be too clever at the moment for userobject.SpecialMethod
+        #if len(l) != obj.func_code.co_argcount-1:
+        #    raise ValueError, \
+        #          "function name %s doesn't specify exactly %d arguments" % (
+        #             repr(name), obj.func_code.co_argcount-1)
 
         funcname =  _name_mappings.get(funcname, funcname)
 
-        if hasattr(alt_ns, funcname):
-            getattr(alt_ns, funcname).register(obj, *l)
-        else:
-            getattr(StdObjSpace, funcname).register(obj, *l)
+        func = hack_func_by_name(funcname, namespaces)
+        func.register(obj, *l)
     add_extra_comparisons()
 
+def hack_func_by_name(funcname, namespaces):
+    for ns in namespaces:
+        if hasattr(ns, funcname):
+            return getattr(ns, funcname)
+    import typetype
+    try:
+        return getattr(typetype.W_TypeType, funcname)
+    except AttributeError:
+        pass  # catches not only the getattr() but the typetype.W_TypeType
+              # in case it is not fully imported yet :-((((
+    import objecttype
+    try:
+        return getattr(objecttype.W_ObjectType, funcname)
+    except AttributeError:
+        pass  # same comment
+    raise NameError, ("trying hard but not finding a multimethod named %s" %
+                      funcname)
+
 class Curry:
     def __init__(self, fun, arg):
         self.fun = fun
-        self.pending = [arg]
+        self.pending = (arg,)
 
     def __call__(self, *args):
         return self.fun(*(self.pending + args))

Modified: pypy/trunk/src/pypy/objspace/std/slicetype.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/slicetype.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/slicetype.py	Tue Jun 24 15:50:57 2003
@@ -8,7 +8,8 @@
 
 registerimplementation(W_SliceType)
 
-def slicetype_new(space, w_slicetype, w_args, w_kwds):
+
+def type_new__SliceType_SliceType_ANY_ANY(space, w_basetype, w_slicetype, w_args, w_kwds):
     if space.is_true(w_kwds):
         raise OperationError(space.w_TypeError,
                              space.wrap("no keyword arguments expected"))
@@ -28,6 +29,6 @@
     else:
         raise OperationError(space.w_TypeError,
                              space.wrap("slice() takes at least 1 argument"))
-    return space.newslice(start, stop, step)
+    return space.newslice(start, stop, step), True
 
-StdObjSpace.new.register(slicetype_new, W_SliceType, W_ANY, W_ANY)
+register_all(vars())

Modified: pypy/trunk/src/pypy/objspace/std/stringtype.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/stringtype.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/stringtype.py	Tue Jun 24 15:50:57 2003
@@ -41,16 +41,15 @@
 registerimplementation(W_StringType)
 
 
-# XXX we'll worry about the __new__/__init__ distinction later
-def new__StringType_ANY_ANY(space, w_stringtype, w_args, w_kwds):
+def type_new__StringType_StringType_ANY_ANY(space, w_basetype, w_stringtype, w_args, w_kwds):
     if space.is_true(w_kwds):
         raise OperationError(space.w_TypeError,
                              space.wrap("no keyword arguments expected"))
     args = space.unpackiterable(w_args)
     if len(args) == 0:
-        return space.newstring([])
+        return space.newstring([]), True
     elif len(args) == 1:
-        return space.str(args[0])
+        return space.str(args[0]), True
     else:
         raise OperationError(space.w_TypeError,
                              space.wrap("str() takes at most 1 argument"))

Modified: pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/test/test_dictobject.py	Tue Jun 24 15:50:57 2003
@@ -84,7 +84,7 @@
         w = space.wrap
         wd = space.newdict
         def mydict(w_args=w(()), w_kwds=w({})):
-            return space.new(space.w_dict, w_args, w_kwds)
+            return space.call(space.w_dict, w_args, w_kwds)
         def deepwrap(lp):
             return [[w(a),w(b)] for a,b in lp]
         d = mydict()
@@ -104,7 +104,7 @@
         w = space.wrap
         wd = space.newdict
         def mydict(w_args=w(()), w_kwds=w({})):
-            return space.new(space.w_dict, w_args, w_kwds)
+            return space.call(space.w_dict, w_args, w_kwds)
         def deepwrap(lp):
             return [[w(a),w(b)] for a,b in lp]
         d = mydict(w_kwds=w({1:2, 3:4}))
@@ -129,7 +129,7 @@
         space = self.space
         w = space.wrap
         def mydict(w_args=w(()), w_kwds=w({})):
-            return space.new(space.w_dict, w_args, w_kwds)
+            return space.call(space.w_dict, w_args, w_kwds)
         d = mydict(w_kwds=w({1:2, 3:4}))
         get = space.getattr(d, w("get"))
         self.assertEqual_w(space.call_function(get, w(1)), w(2))

Modified: pypy/trunk/src/pypy/objspace/std/tupletype.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/tupletype.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/tupletype.py	Tue Jun 24 15:50:57 2003
@@ -9,8 +9,7 @@
 registerimplementation(W_TupleType)
 
 
-# XXX we'll worry about the __new__/__init__ distinction later
-def tupletype_new(space, w_tupletype, w_args, w_kwds):
+def type_new__TupleType_TupleType_ANY_ANY(space, w_basetype, w_tupletype, w_args, w_kwds):
     if space.is_true(w_kwds):
         raise OperationError(space.w_TypeError,
                              space.wrap("no keyword arguments expected"))
@@ -22,6 +21,6 @@
     else:
         raise OperationError(space.w_TypeError,
                              space.wrap("tuple() takes at most 1 argument"))
-    return space.newtuple(tuple_w)
+    return space.newtuple(tuple_w), True
 
-StdObjSpace.new.register(tupletype_new, W_TupleType, W_ANY, W_ANY)
+register_all(vars())

Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/typeobject.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/typeobject.py	Tue Jun 24 15:50:57 2003
@@ -94,11 +94,13 @@
                     code = multimethods[name]
                     if code.bound_position < i:
                         continue
-                if len(multimethod.specialnames) > 1:
-                    mmcls = SpecialMultimethodCode
-                else:
-                    mmcls = PyMultimethodCode
-                code = mmcls(multimethod, typeclass, i)
+                pycodeclass = multimethod.extras.get('pycodeclass')
+                if pycodeclass is None:
+                    if len(multimethod.specialnames) > 1:
+                        pycodeclass = SpecialMultimethodCode
+                    else:
+                        pycodeclass = PyMultimethodCode
+                code = pycodeclass(multimethod, typeclass, i)
                 multimethods[name] = code
         # add some more multimethods with a special interface
         code = NextMultimethodCode(spaceclass.next, typeclass)
@@ -182,10 +184,21 @@
         result = self.do_call(space, w_globals, w_locals)
         return space.newbool(result)
 
+class NewMultimethodCode(PyMultimethodCode):
+
+    def eval_code(self, space, w_globals, w_locals):
+        "Call the __new__() method of typetype.py."
+        w_result, callinit = self.do_call(space, w_globals, w_locals)
+        return w_result
+
 
 def call__Type_ANY_ANY(space, w_type, w_args, w_kwds):
-    w_newobject = space.new(w_type, w_args, w_kwds)
-    # XXX call __init__() later
+    type_new = typetype.W_TypeType.type_new.get(space)
+    w_newobject, callinit = type_new(w_type, w_type, w_args, w_kwds)
+    if callinit:
+        import objecttype
+        object_init = objecttype.W_ObjectType.object_init.get(space)
+        object_init(w_newobject, w_args, w_kwds)
     return w_newobject
 
 def issubtype__Type_Type(space, w_type1, w_type2):

Modified: pypy/trunk/src/pypy/objspace/std/typetype.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/typetype.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/typetype.py	Tue Jun 24 15:50:57 2003
@@ -1,5 +1,12 @@
 from pypy.objspace.std.objspace import *
-from typeobject import W_TypeObject # , NewMultimethodCode
+from pypy.objspace.std.register_all import register_all
+from typeobject import W_TypeObject
+
+
+def NewMultimethodCode_builder(*args):
+    from typeobject import NewMultimethodCode  # sadly necessary late import hack
+    return NewMultimethodCode(*args)
+
 
 class W_TypeType(W_TypeObject):
     """The single instance of this class is the object the user sees as
@@ -7,22 +14,31 @@
 
     typename = 'type'
 
-registerimplementation(W_TypeType)
+    # XXX this is worth tons of comments.
+    # the four arguments are (T, S, args, kw) for the expression
+    # T.__new__(S, *args, **kw).  There is no (known?) way to get it as
+    # an unbound method, because 'type.__new__' means reading from the
+    # instance 'type' of the class 'type', as opposed to reading from
+    # the class 'type'.
+    # Attention, this internally returns a tuple (w_result, flag),
+    # where 'flag' specifies whether we would like __init__() to be called.
+    type_new = MultiMethod('__new__', 4, varargs=True, keywords=True,
+                                         pycodeclass=NewMultimethodCode_builder)
 
+registerimplementation(W_TypeType)
 
-# XXX we'll worry about the __new__/__init__ distinction later
-def new__TypeType_ANY_ANY(space, w_typetype, w_args, w_kwds):
+def type_new__TypeType_TypeType_ANY_ANY(space, w_basetype, w_typetype, w_args, w_kwds):
     if space.is_true(w_kwds):
         raise OperationError(space.w_TypeError,
                              space.wrap("no keyword arguments expected"))
     args = space.unpackiterable(w_args)
     if len(args) == 1:
-        return space.type(args[0])
+        return space.type(args[0]), False   # don't call __init__() on that
     elif len(args) == 3:
         from usertype import W_UserType
         w_name, w_bases, w_dict = args
         w_usertype = W_UserType(space, w_name, w_bases, w_dict)
-        return w_usertype
+        return w_usertype, True
     else:
         raise OperationError(space.w_TypeError,
                              space.wrap("type() takes 1 or 3 arguments"))

Modified: pypy/trunk/src/pypy/objspace/std/userobject.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/userobject.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/userobject.py	Tue Jun 24 15:50:57 2003
@@ -42,10 +42,11 @@
     try:
         return _bltin_subclass_cache[cls]
     except:
-        _bltin_subclass_cache[cls] = subcls = type(W_Object)("%s_sub" % cls.__name__,(cls,),
-                                                       {'statictype': W_UserType,
-                                                        'bltbase': cls,
-                                                        'dispatchtype': W_UserObject})
+        subcls = type(W_Object)("%s_sub" % cls.__name__, (cls,),
+                                {'statictype'   : W_UserType,
+                                 'bltbase'      : cls,
+                                 'dispatchclass': W_UserObject})
+        _bltin_subclass_cache[cls] = subcls
         return subcls
 
 def morph_into_user_object(space,w_type,newobj):
@@ -109,12 +110,7 @@
         self.method_name = method_name
         self.bound_position = bound_position
 
-    def do_call(self, space, args_w):
-        # args_w is in the standard multimethod order
-        # we need it in the Python-friendly order (i.e. swapped for __rxxx__)
-        args_w = list(args_w)
-        w_userobj = args_w.pop(self.bound_position)
-        w_args = space.newtuple(args_w)
+    def internal_do_call(self, space, w_userobj, w_args, w_kwds):
         w_key = space.wrap(self.method_name)
         w_mro = space.getattr(w_userobj.w_type, space.wrap('__mro__'))
         mro = space.unpacktuple(w_mro)
@@ -126,9 +122,17 @@
             except KeyError:
                 continue
             w_method = space.get(w_function, w_userobj, w_base)
-            return space.call(w_method, w_args, space.newdict([]))
+            return space.call(w_method, w_args, w_kwds)
         raise FailedToImplement
 
+    def do_call(self, space, args_w):
+        # args_w is in the standard multimethod order
+        # we need it in the Python-friendly order (i.e. swapped for __rxxx__)
+        args_w = list(args_w)
+        w_userobj = args_w.pop(self.bound_position)
+        w_args = space.newtuple(args_w)
+        return self.internal_do_call(space, w_userobj, w_args, space.newdict([]))
+
     def normal_call(self, space, *args_w):
         "Call a user-defined __xxx__ method and convert the result back."
         w_result = self.do_call(space, args_w)
@@ -155,6 +159,10 @@
         w_result = self.do_call(space, args_w)
         return space.is_true(w_result)
 
+    def argskwds_call(self, space, w_userobj, w_args, w_kwds):
+        "For __init__()."
+        return self.internal_do_call(space, w_userobj, w_args, w_kwds)
+
 
 import new
 for multimethod in typeobject.hack_out_multimethods(StdObjSpace):
@@ -166,6 +174,6 @@
 
 next__User    = SpecialMethod('next').next_call
 is_true__User = SpecialMethod('nonzero').nonzero_call
-
+object_init__User_ANY_ANY = SpecialMethod('__init__').argskwds_call
 
 register_all(vars())

Modified: pypy/trunk/src/pypy/objspace/std/usertype.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/usertype.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/usertype.py	Tue Jun 24 15:50:57 2003
@@ -53,17 +53,35 @@
 #   but we're documenting it here as there seems no better place!!!
 #   The problem is actually that, currently, several types such as
 #   int and float just cannot be CALLED -- this needs to be fixed soon.
-def new__UserType_ANY_ANY(space, w_usertype, w_args, w_kwds):
-    from userobject import make_user_object
-    newobj = make_user_object(space, w_usertype, w_args, w_kwds)
-    try:
-        init = space.getattr(newobj, space.wrap('__init__'))
-    except OperationError, err:
-        if not err.match(space, space.w_AttributeError):
-            raise
-    else:
-        space.call(init, w_args, w_kwds)
-    return newobj
+def type_new__UserType_UserType_ANY_ANY(space, w_basetype, w_usertype, w_args, w_kwds):
+    import typetype
+    # XXX this uses the following algorithm:
+    #     walk the __mro__ of the user type
+    #     for each *user* type t in there, just look for a __new__ in t.__dict__
+    #     if we get to a *built-in* type t, we use t.__new__, which is a
+    #       bound method from the type 'type'.
+    for w_looktype in w_basetype.getmro():
+        if not isinstance(w_looktype, W_UserType):
+            # no user-defined __new__ found
+            type_new = typetype.W_TypeType.type_new.get(space)
+            return type_new(w_looktype, w_usertype, w_args, w_kwds)
+        try:
+            w_new = w_looktype.lookup_exactly_here(space.wrap('__new__'))
+        except KeyError:
+            pass
+        else:
+            w_newobj = space.call_function(w_new, [w_usertype, w_args, w_kwds])
+            return w_newobj, True
+    raise AssertionError, "execution should not get here"
+
+def type_new__ANY_UserType_ANY_ANY(space, w_basetype, w_usertype, w_args, w_kwds):
+    import typetype
+    from userobject import morph_into_user_object, getsinglebuiltintype
+    assert w_basetype is getsinglebuiltintype(space, w_usertype)
+    type_new = typetype.W_TypeType.type_new.get(space)
+    w_newobject, callinit = type_new(w_basetype, w_basetype, w_args, w_kwds)
+    morph_into_user_object(space, w_usertype, w_newobject)
+    return w_newobject, True
 
 def getdict__UserType(space, w_usertype):
     return w_usertype.w_dict


More information about the Pypy-commit mailing list