Author: Philip Jenvey <pjen...@underboss.org>
Branch: py3.3
Changeset: r74191:3820173e81e3
Date: 2014-10-24 13:48 -0700
http://bitbucket.org/pypy/pypy/changeset/3820173e81e3/

Log:    merge py3k

diff too long, truncating to 2000 out of 5270 lines

diff --git a/lib_pypy/_tkinter/app.py b/lib_pypy/_tkinter/app.py
--- a/lib_pypy/_tkinter/app.py
+++ b/lib_pypy/_tkinter/app.py
@@ -439,7 +439,7 @@
         if isinstance(s, int):
             return s
         s = s.encode('utf-8')
-        if '\x00' in s:
+        if b'\x00' in s:
             raise TypeError
         v = tkffi.new("int*")
         res = tklib.Tcl_GetBoolean(self.interp, s, v)
@@ -451,7 +451,7 @@
         if isinstance(s, int):
             return s
         s = s.encode('utf-8')
-        if '\x00' in s:
+        if b'\x00' in s:
             raise TypeError
         v = tkffi.new("int*")
         res = tklib.Tcl_GetInt(self.interp, s, v)
@@ -463,7 +463,7 @@
         if isinstance(s, float):
             return s
         s = s.encode('utf-8')
-        if '\x00' in s:
+        if b'\x00' in s:
             raise TypeError
         v = tkffi.new("double*")
         res = tklib.Tcl_GetDouble(self.interp, s, v)
@@ -472,7 +472,7 @@
         return v[0]
 
     def exprboolean(self, s):
-        if '\x00' in s:
+        if b'\x00' in s:
             raise TypeError
         v = tkffi.new("int*")
         res = tklib.Tcl_ExprBoolean(self.interp, s, v)
@@ -481,7 +481,7 @@
         return v[0]
 
     def exprlong(self, s):
-        if '\x00' in s:
+        if b'\x00' in s:
             raise TypeError
         v = tkffi.new("long*")
         res = tklib.Tcl_ExprLong(self.interp, s, v)
@@ -490,7 +490,7 @@
         return v[0]
 
     def exprdouble(self, s):
-        if '\x00' in s:
+        if b'\x00' in s:
             raise TypeError
         v = tkffi.new("double*")
         res = tklib.Tcl_ExprDouble(self.interp, s, v)
@@ -499,7 +499,7 @@
         return v[0]
 
     def exprstring(self, s):
-        if '\x00' in s:
+        if b'\x00' in s:
             raise TypeError
         res = tklib.Tcl_ExprString(self.interp, s)
         if res == tklib.TCL_ERROR:
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -22,3 +22,6 @@
 
 .. branch: ClassRepr
 Refactor ClassRepr and make normalizecalls independent of the rtyper.
+
+.. branch: remove-remaining-smm
+Remove all remaining multimethods.
diff --git a/pypy/goal/targetpypystandalone.py 
b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -310,7 +310,8 @@
         return self.get_entry_point(config)
 
     def jitpolicy(self, driver):
-        from pypy.module.pypyjit.policy import PyPyJitPolicy, pypy_hooks
+        from pypy.module.pypyjit.policy import PyPyJitPolicy
+        from pypy.module.pypyjit.hooks import pypy_hooks
         return PyPyJitPolicy(pypy_hooks)
 
     def get_entry_point(self, config):
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1902,5 +1902,4 @@
     'newdict',
     'newslice',
     'call_args',
-    'marshal_w',
 ]
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -644,6 +644,17 @@
                 elif unwrap_spec == [ObjSpace, W_Root, Arguments]:
                     self.__class__ = BuiltinCodePassThroughArguments1
                     self.func__args__ = func
+                elif unwrap_spec == [self_type, ObjSpace, Arguments]:
+                    self.__class__ = BuiltinCodePassThroughArguments1
+                    miniglobals = {'func': func, 'self_type': self_type}
+                    d = {}
+                    source = """if 1:
+                        def _call(space, w_obj, args):
+                            self = space.descr_self_interp_w(self_type, w_obj)
+                            return func(self, space, args)
+                        \n"""
+                    exec compile2(source) in miniglobals, d
+                    self.func__args__ = d['_call']
             else:
                 self.__class__ = globals()['BuiltinCode%d' % arity]
                 setattr(self, 'fastfunc_%d' % arity, fastfunc)
diff --git a/pypy/interpreter/test/test_gateway.py 
b/pypy/interpreter/test/test_gateway.py
--- a/pypy/interpreter/test/test_gateway.py
+++ b/pypy/interpreter/test/test_gateway.py
@@ -906,11 +906,33 @@
         assert len(called) == 1
         assert isinstance(called[0], argument.Arguments)
 
+    def test_pass_trough_arguments_method(self):
+        space = self.space
+
+        called = []
+
+        class W_Something(W_Root):
+            def f(self, space, __args__):
+                called.append(__args__)
+                a_w, _ = __args__.unpack()
+                return space.newtuple([space.wrap('f')]+a_w)
+
+        w_f = space.wrap(gateway.interp2app_temp(W_Something.f))
+
+        w_self = space.wrap(W_Something())
+        args = argument.Arguments(space, [space.wrap(7)])
+
+        w_res = space.call_obj_args(w_f, w_self, args)
+        assert space.is_true(space.eq(w_res, space.wrap(('f', 7))))
+
+        # white-box check for opt
+        assert called[0] is args
+
 
 class AppTestKeywordsToBuiltinSanity(object):
     def test_type(self):
         class X(object):
-            def __init__(self, **kw):
+            def __init__(myself, **kw):
                 pass
         clash = type.__call__.__code__.co_varnames[0]
 
@@ -926,7 +948,6 @@
         X(**{clash: 33})
         object.__new__(X, **{clash: 33})
 
-
     def test_dict_new(self):
         clash = dict.__new__.__code__.co_varnames[0]
 
diff --git a/pypy/module/marshal/interp_marshal.py 
b/pypy/module/marshal/interp_marshal.py
--- a/pypy/module/marshal/interp_marshal.py
+++ b/pypy/module/marshal/interp_marshal.py
@@ -2,6 +2,7 @@
 from pypy.interpreter.gateway import WrappedDefault, unwrap_spec
 from rpython.rlib.rarithmetic import intmask
 from rpython.rlib import rstackovf
+from pypy.objspace.std.marshal_impl import marshal, get_unmarshallers
 
 
 Py_MARSHAL_VERSION = 2
@@ -139,6 +140,26 @@
         raise OperationError(space.w_ValueError, space.wrap(msg))
 
 class Marshaller(_Base):
+    """
+    atomic types including typecode:
+
+    atom(tc)                    puts single typecode
+    atom_int(tc, int)           puts code and int
+    atom_int64(tc, int64)       puts code and int64
+    atom_str(tc, str)           puts code, len and string
+    atom_strlist(tc, strlist)   puts code, len and list of strings
+
+    building blocks for compound types:
+
+    start(typecode)             sets the type character
+    put(s)                      puts a string with fixed length
+    put_short(int)              puts a short integer
+    put_int(int)                puts an integer
+    put_pascal(s)               puts a short string
+    put_w_obj(w_obj)            puts a wrapped object
+    put_tuple_w(TYPE, tuple_w)  puts tuple_w, an unwrapped list of wrapped 
objects
+    """
+
     # _annspecialcase_ = "specialize:ctr_location" # polymorphic
     # does not work with subclassing
 
@@ -217,7 +238,7 @@
         self.put(x)
 
     def put_w_obj(self, w_obj):
-        self.space.marshal_w(w_obj, self)
+        marshal(self.space, w_obj, self)
 
     def dump_w_obj(self, w_obj):
         space = self.space
@@ -243,7 +264,7 @@
         idx = 0
         while idx < lng:
             w_obj = lst_w[idx]
-            self.space.marshal_w(w_obj, self)
+            marshal(self.space, w_obj, self)
             idx += 1
 
     def _overflow(self):
@@ -333,14 +354,11 @@
     u.raise_exc("bad marshal data (unknown type code)")
 
 
-def register(codes, func):
-    """NOT_RPYTHON"""
-    for code in codes:
-        Unmarshaller._dispatch[ord(code)] = func
-
 
 class Unmarshaller(_Base):
     _dispatch = [invalid_typecode] * 256
+    for tc, func in get_unmarshallers():
+        _dispatch[ord(tc)] = func
 
     def __init__(self, space, reader):
         self.space = space
diff --git a/pypy/module/marshal/test/test_marshalimpl.py 
b/pypy/module/marshal/test/test_marshalimpl.py
--- a/pypy/module/marshal/test/test_marshalimpl.py
+++ b/pypy/module/marshal/test/test_marshalimpl.py
@@ -72,7 +72,7 @@
         expected = marshal.dumps(long(x))
         w_obj = space.wraplong(x)
         m = FakeM()
-        space.marshal_w(w_obj, m)
+        interp_marshal.marshal(space, w_obj, m)
         assert ''.join(m.seen) == expected
         #
         u = interp_marshal.StringUnmarshaller(space, space.wrapbytes(expected))
diff --git a/pypy/module/micronumpy/boxes.py b/pypy/module/micronumpy/boxes.py
--- a/pypy/module/micronumpy/boxes.py
+++ b/pypy/module/micronumpy/boxes.py
@@ -3,8 +3,8 @@
 from pypy.interpreter.mixedmodule import MixedModule
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.objspace.std.bytesobject import W_BytesObject
-from pypy.objspace.std.complextype import complex_typedef
-from pypy.objspace.std.floattype import float_typedef
+from pypy.objspace.std.complexobject import W_ComplexObject
+from pypy.objspace.std.floatobject import W_FloatObject
 from pypy.objspace.std.intobject import W_IntObject
 from pypy.objspace.std.unicodeobject import W_UnicodeObject
 from rpython.rlib.rarithmetic import LONG_BIT
@@ -784,7 +784,7 @@
     __reduce__ = interp2app(W_Float32Box.descr_reduce),
 )
 
-W_Float64Box.typedef = TypeDef("numpy.float64", (W_FloatingBox.typedef, 
float_typedef),
+W_Float64Box.typedef = TypeDef("numpy.float64", (W_FloatingBox.typedef, 
W_FloatObject.typedef),
     __new__ = interp2app(W_Float64Box.descr__new__.im_func),
     __reduce__ = interp2app(W_Float64Box.descr_reduce),
     as_integer_ratio = interp2app(W_Float64Box.descr_as_integer_ratio),
@@ -799,7 +799,7 @@
     __complex__ = interp2app(W_GenericBox.item),
 )
 
-W_Complex128Box.typedef = TypeDef("numpy.complex128", 
(W_ComplexFloatingBox.typedef, complex_typedef),
+W_Complex128Box.typedef = TypeDef("numpy.complex128", 
(W_ComplexFloatingBox.typedef, W_ComplexObject.typedef),
     __new__ = interp2app(W_Complex128Box.descr__new__.im_func),
     __reduce__ = interp2app(W_Complex128Box.descr_reduce),
 )
@@ -810,7 +810,7 @@
         __reduce__ = interp2app(W_FloatLongBox.descr_reduce),
     )
 
-    W_ComplexLongBox.typedef = TypeDef("numpy.complex%d" % (long_double_size * 
16), (W_ComplexFloatingBox.typedef, complex_typedef),
+    W_ComplexLongBox.typedef = TypeDef("numpy.complex%d" % (long_double_size * 
16), (W_ComplexFloatingBox.typedef, W_ComplexObject.typedef),
         __new__ = interp2app(W_ComplexLongBox.descr__new__.im_func),
         __reduce__ = interp2app(W_ComplexLongBox.descr_reduce),
         __complex__ = interp2app(W_GenericBox.item),
diff --git a/pypy/module/posix/interp_nt.py b/pypy/module/posix/interp_nt.py
--- a/pypy/module/posix/interp_nt.py
+++ b/pypy/module/posix/interp_nt.py
@@ -21,6 +21,9 @@
 """
 eci = ExternalCompilationInfo(
     includes=['windows.h'],
+    post_include_bits=[
+        "DWORD "
+        "pypy_GetFinalPathNameByHandle(FARPROC, HANDLE, LPTSTR, DWORD, 
DWORD);"],
     separate_module_sources=[separate_module_source],
     export_symbols=['pypy_GetFinalPathNameByHandle']
     )
diff --git a/pypy/module/pypyjit/__init__.py b/pypy/module/pypyjit/__init__.py
--- a/pypy/module/pypyjit/__init__.py
+++ b/pypy/module/pypyjit/__init__.py
@@ -24,7 +24,7 @@
     def setup_after_space_initialization(self):
         # force the __extend__ hacks to occur early
         from pypy.module.pypyjit.interp_jit import pypyjitdriver
-        from pypy.module.pypyjit.policy import pypy_hooks
+        from pypy.module.pypyjit.hooks import pypy_hooks
         # add the 'defaults' attribute
         from rpython.rlib.jit import PARAMETERS
         space = self.space
diff --git a/pypy/module/pypyjit/hooks.py b/pypy/module/pypyjit/hooks.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pypyjit/hooks.py
@@ -0,0 +1,89 @@
+
+from rpython.rlib import jit_hooks
+from rpython.rlib.jit import JitHookInterface, Counters
+
+from pypy.interpreter.error import OperationError
+from pypy.module.pypyjit.interp_resop import (Cache, wrap_greenkey,
+    WrappedOp, W_JitLoopInfo, wrap_oplist)
+
+class PyPyJitIface(JitHookInterface):
+    def on_abort(self, reason, jitdriver, greenkey, greenkey_repr, logops, 
operations):
+        space = self.space
+        cache = space.fromcache(Cache)
+        if cache.in_recursion:
+            return
+        if space.is_true(cache.w_abort_hook):
+            cache.in_recursion = True
+            oplist_w = wrap_oplist(space, logops, operations)
+            try:
+                try:
+                    space.call_function(cache.w_abort_hook,
+                        space.wrap(jitdriver.name),
+                        wrap_greenkey(space, jitdriver, greenkey, 
greenkey_repr),
+                        space.wrap(Counters.counter_names[reason]),
+                        space.newlist(oplist_w)
+                    )
+                except OperationError, e:
+                    e.write_unraisable(space, "jit hook ", cache.w_abort_hook)
+            finally:
+                cache.in_recursion = False
+
+    def after_compile(self, debug_info):
+        self._compile_hook(debug_info, is_bridge=False)
+
+    def after_compile_bridge(self, debug_info):
+        self._compile_hook(debug_info, is_bridge=True)
+
+    def before_compile(self, debug_info):
+        self._optimize_hook(debug_info, is_bridge=False)
+
+    def before_compile_bridge(self, debug_info):
+        self._optimize_hook(debug_info, is_bridge=True)
+
+    def _compile_hook(self, debug_info, is_bridge):
+        space = self.space
+        cache = space.fromcache(Cache)
+        if cache.in_recursion:
+            return
+        if space.is_true(cache.w_compile_hook):
+            w_debug_info = W_JitLoopInfo(space, debug_info, is_bridge)
+            cache.in_recursion = True
+            try:
+                try:
+                    space.call_function(cache.w_compile_hook,
+                                        space.wrap(w_debug_info))
+                except OperationError, e:
+                    e.write_unraisable(space, "jit hook ", 
cache.w_compile_hook)
+            finally:
+                cache.in_recursion = False
+
+    def _optimize_hook(self, debug_info, is_bridge=False):
+        space = self.space
+        cache = space.fromcache(Cache)
+        if cache.in_recursion:
+            return
+        if space.is_true(cache.w_optimize_hook):
+            w_debug_info = W_JitLoopInfo(space, debug_info, is_bridge)
+            cache.in_recursion = True
+            try:
+                try:
+                    w_res = space.call_function(cache.w_optimize_hook,
+                                                space.wrap(w_debug_info))
+                    if space.is_w(w_res, space.w_None):
+                        return
+                    l = []
+                    for w_item in space.listview(w_res):
+                        item = space.interp_w(WrappedOp, w_item)
+                        l.append(jit_hooks._cast_to_resop(item.op))
+                    del debug_info.operations[:] # modifying operations above 
is
+                    # probably not a great idea since types may not work
+                    # and we'll end up with half-working list and
+                    # a segfault/fatal RPython error
+                    for elem in l:
+                        debug_info.operations.append(elem)
+                except OperationError, e:
+                    e.write_unraisable(space, "jit hook ", 
cache.w_compile_hook)
+            finally:
+                cache.in_recursion = False
+
+pypy_hooks = PyPyJitIface()
diff --git a/pypy/module/pypyjit/policy.py b/pypy/module/pypyjit/policy.py
--- a/pypy/module/pypyjit/policy.py
+++ b/pypy/module/pypyjit/policy.py
@@ -1,93 +1,4 @@
 from rpython.jit.codewriter.policy import JitPolicy
-from rpython.rlib import jit_hooks
-from rpython.rlib.jit import JitHookInterface, Counters
-
-from pypy.interpreter.error import OperationError
-from pypy.module.pypyjit.interp_resop import (Cache, wrap_greenkey,
-    WrappedOp, W_JitLoopInfo, wrap_oplist)
-
-
-class PyPyJitIface(JitHookInterface):
-    def on_abort(self, reason, jitdriver, greenkey, greenkey_repr, logops, 
operations):
-        space = self.space
-        cache = space.fromcache(Cache)
-        if cache.in_recursion:
-            return
-        if space.is_true(cache.w_abort_hook):
-            cache.in_recursion = True
-            oplist_w = wrap_oplist(space, logops, operations)
-            try:
-                try:
-                    space.call_function(cache.w_abort_hook,
-                        space.wrap(jitdriver.name),
-                        wrap_greenkey(space, jitdriver, greenkey, 
greenkey_repr),
-                        space.wrap(Counters.counter_names[reason]),
-                        space.newlist(oplist_w)
-                    )
-                except OperationError, e:
-                    e.write_unraisable(space, "jit hook ", cache.w_abort_hook)
-            finally:
-                cache.in_recursion = False
-
-    def after_compile(self, debug_info):
-        self._compile_hook(debug_info, is_bridge=False)
-
-    def after_compile_bridge(self, debug_info):
-        self._compile_hook(debug_info, is_bridge=True)
-
-    def before_compile(self, debug_info):
-        self._optimize_hook(debug_info, is_bridge=False)
-
-    def before_compile_bridge(self, debug_info):
-        self._optimize_hook(debug_info, is_bridge=True)
-
-    def _compile_hook(self, debug_info, is_bridge):
-        space = self.space
-        cache = space.fromcache(Cache)
-        if cache.in_recursion:
-            return
-        if space.is_true(cache.w_compile_hook):
-            w_debug_info = W_JitLoopInfo(space, debug_info, is_bridge)
-            cache.in_recursion = True
-            try:
-                try:
-                    space.call_function(cache.w_compile_hook,
-                                        space.wrap(w_debug_info))
-                except OperationError, e:
-                    e.write_unraisable(space, "jit hook ", 
cache.w_compile_hook)
-            finally:
-                cache.in_recursion = False
-
-    def _optimize_hook(self, debug_info, is_bridge=False):
-        space = self.space
-        cache = space.fromcache(Cache)
-        if cache.in_recursion:
-            return
-        if space.is_true(cache.w_optimize_hook):
-            w_debug_info = W_JitLoopInfo(space, debug_info, is_bridge)
-            cache.in_recursion = True
-            try:
-                try:
-                    w_res = space.call_function(cache.w_optimize_hook,
-                                                space.wrap(w_debug_info))
-                    if space.is_w(w_res, space.w_None):
-                        return
-                    l = []
-                    for w_item in space.listview(w_res):
-                        item = space.interp_w(WrappedOp, w_item)
-                        l.append(jit_hooks._cast_to_resop(item.op))
-                    del debug_info.operations[:] # modifying operations above 
is
-                    # probably not a great idea since types may not work
-                    # and we'll end up with half-working list and
-                    # a segfault/fatal RPython error
-                    for elem in l:
-                        debug_info.operations.append(elem)
-                except OperationError, e:
-                    e.write_unraisable(space, "jit hook ", 
cache.w_compile_hook)
-            finally:
-                cache.in_recursion = False
-
-pypy_hooks = PyPyJitIface()
 
 class PyPyJitPolicy(JitPolicy):
 
@@ -103,19 +14,13 @@
             return True
         if '.' in modname:
             modname, rest = modname.split('.', 1)
+            if modname in ['unicodedata', 'gc', '_minimal_curses', 'cpyext']:
+                return False
         else:
             rest = ''
-        if modname in ['pypyjit', 'signal', 'micronumpy', 'math', 'exceptions',
-                       'imp', 'sys', 'array', 'itertools', 'operator',
-                       'posix', '_socket', '_sre', '_lsprof', '_weakref',
-                       '__pypy__', 'cStringIO', '_collections', 'struct',
-                       'mmap', 'marshal', '_codecs', 'rctime', 'cppyy',
-                       '_cffi_backend', 'pyexpat', '_continuation', '_io',
-                       'thread', 'select', '_random']:
-            if modname == 'pypyjit' and 'interp_resop' in rest:
-                return False
-            return True
-        return False
+        if modname == 'pypyjit' and 'interp_resop' in rest:
+            return False
+        return True
 
     def look_inside_function(self, func):
         mod = func.__module__ or '?'
diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py 
b/pypy/module/pypyjit/test_pypy_c/test_string.py
--- a/pypy/module/pypyjit/test_pypy_c/test_string.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_string.py
@@ -85,7 +85,7 @@
             i95 = getfield_gc_pure(p93, descr=<FieldS 
rpython.rlib.rbigint.rbigint.inst_size .*>)
             i96 = int_gt(i95, .*)
             guard_false(i96, descr=...)
-            i94 = call(ConstClass(rbigint._toint_helper), p93, descr=<Calli 8 
r EF=3>)
+            i94 = call(ConstClass(rbigint._toint_helper), p93, descr=<Calli . 
r EF=3>)
             guard_no_exception(descr=...)
             i95 = int_add_ovf(i6, i94)
             guard_no_overflow(descr=...)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_thread.py 
b/pypy/module/pypyjit/test_pypy_c/test_thread.py
--- a/pypy/module/pypyjit/test_pypy_c/test_thread.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_thread.py
@@ -70,7 +70,6 @@
         i59 = int_is_true(i58)
         guard_true(i59, descr=...)
         i60 = int_sub(i44, 1)
-        guard_not_invalidated(descr=...)
         p62 = force_token()
         setfield_gc(p0, p62, descr=<FieldP 
pypy.interpreter.pyframe.PyFrame.vable_token 8>)
         i63 = call_release_gil(..., i37, 0, descr=<Calli 4 ii EF=6>)
diff --git a/pypy/objspace/std/complexobject.py 
b/pypy/objspace/std/complexobject.py
--- a/pypy/objspace/std/complexobject.py
+++ b/pypy/objspace/std/complexobject.py
@@ -1,57 +1,181 @@
 import math
 
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.baseobjspace import W_Root
+from pypy.interpreter.error import OperationError, oefmt
+from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
 from pypy.objspace.std import newformat
-from pypy.objspace.std.intobject import W_IntObject
-from pypy.objspace.std.model import registerimplementation, W_Object
-from pypy.objspace.std.register_all import register_all
-from pypy.objspace.std.floatobject import W_FloatObject, _hash_float
-from pypy.objspace.std.longobject import W_LongObject
+from pypy.objspace.std.floatobject import _hash_float
+from pypy.objspace.std.stdtypedef import GetSetProperty, StdTypeDef
+from pypy.objspace.std.unicodeobject import unicode_to_decimal_w
+from rpython.rlib import jit, rcomplex
+from rpython.rlib.rarithmetic import intmask, r_ulonglong
 from rpython.rlib.rbigint import rbigint
 from rpython.rlib.rfloat import (
-    formatd, DTSF_STR_PRECISION, isinf, isnan, copysign)
-from rpython.rlib import jit, rcomplex
-from rpython.rlib.rarithmetic import intmask, r_ulonglong
+    formatd, DTSF_STR_PRECISION, isinf, isnan, copysign, string_to_float)
+from rpython.rlib.rstring import ParseStringError
+from rpython.tool.sourcetools import func_with_new_name
 
 HASH_IMAG = 1000003
 
 
-class W_AbstractComplexObject(W_Object):
-    __slots__ = ()
+def _split_complex(s):
+    slen = len(s)
+    if slen == 0:
+        raise ValueError
+    realstart = 0
+    realstop = 0
+    imagstart = 0
+    imagstop = 0
+    imagsign = ' '
+    i = 0
+    # ignore whitespace at beginning and end
+    while i < slen and s[i] == ' ':
+        i += 1
+    while slen > 0 and s[slen-1] == ' ':
+        slen -= 1
 
-    def is_w(self, space, w_other):
-        from rpython.rlib.longlong2float import float2longlong
-        if not isinstance(w_other, W_AbstractComplexObject):
-            return False
-        if self.user_overridden_class or w_other.user_overridden_class:
-            return self is w_other
-        real1 = space.float_w(space.getattr(self,    space.wrap("real")))
-        real2 = space.float_w(space.getattr(w_other, space.wrap("real")))
-        imag1 = space.float_w(space.getattr(self,    space.wrap("imag")))
-        imag2 = space.float_w(space.getattr(w_other, space.wrap("imag")))
-        real1 = float2longlong(real1)
-        real2 = float2longlong(real2)
-        imag1 = float2longlong(imag1)
-        imag2 = float2longlong(imag2)
-        return real1 == real2 and imag1 == imag2
+    if s[i] == '(' and s[slen-1] == ')':
+        i += 1
+        slen -= 1
+        # ignore whitespace after bracket
+        while i < slen and s[i] == ' ':
+            i += 1
+        while slen > 0 and s[slen-1] == ' ':
+            slen -= 1
 
-    def immutable_unique_id(self, space):
-        if self.user_overridden_class:
-            return None
-        from rpython.rlib.longlong2float import float2longlong
-        from pypy.objspace.std.model import IDTAG_COMPLEX as tag
-        real = space.float_w(space.getattr(self, space.wrap("real")))
-        imag = space.float_w(space.getattr(self, space.wrap("imag")))
-        real_b = rbigint.fromrarith_int(float2longlong(real))
-        imag_b = rbigint.fromrarith_int(r_ulonglong(float2longlong(imag)))
-        val = real_b.lshift(64).or_(imag_b).lshift(3).or_(rbigint.fromint(tag))
-        return space.newlong_from_rbigint(val)
+    # extract first number
+    realstart = i
+    pc = s[i]
+    while i < slen and s[i] != ' ':
+        if s[i] in ('+', '-') and pc not in ('e', 'E') and i != realstart:
+            break
+        pc = s[i]
+        i += 1
 
+    realstop = i
 
-class W_ComplexObject(W_AbstractComplexObject):
-    """This is a reimplementation of the CPython "PyComplexObject"
+    # return appropriate strings is only one number is there
+    if i >= slen:
+        newstop = realstop - 1
+        if newstop < 0:
+            raise ValueError
+        if s[newstop] in ('j', 'J'):
+            if realstart == newstop:
+                imagpart = '1.0'
+            elif realstart == newstop-1 and s[realstart] == '+':
+                imagpart = '1.0'
+            elif realstart == newstop-1 and s[realstart] == '-':
+                imagpart = '-1.0'
+            else:
+                imagpart = s[realstart:newstop]
+            return '0.0', imagpart
+        else:
+            return s[realstart:realstop], '0.0'
+
+    # find sign for imaginary part
+    if s[i] == '-' or s[i] == '+':
+        imagsign = s[i]
+    else:
+        raise ValueError
+
+    i += 1
+    if i >= slen:
+        raise ValueError
+
+    imagstart = i
+    pc = s[i]
+    while i < slen and s[i] != ' ':
+        if s[i] in ('+', '-') and pc not in ('e', 'E'):
+            break
+        pc = s[i]
+        i += 1
+
+    imagstop = i - 1
+    if imagstop < 0:
+        raise ValueError
+    if s[imagstop] not in ('j', 'J'):
+        raise ValueError
+    if imagstop < imagstart:
+        raise ValueError
+
+    if i < slen:
+        raise ValueError
+
+    realpart = s[realstart:realstop]
+    if imagstart == imagstop:
+        imagpart = '1.0'
+    else:
+        imagpart = s[imagstart:imagstop]
+    if imagsign == '-':
+        imagpart = imagsign + imagpart
+
+    return realpart, imagpart
+
+
+def format_float(x, code, precision):
+    # like float2string, except that the ".0" is not necessary
+    if isinf(x):
+        if x > 0.0:
+            return "inf"
+        else:
+            return "-inf"
+    elif isnan(x):
+        return "nan"
+    else:
+        return formatd(x, code, precision)
+
+def repr_format(x):
+    return format_float(x, 'r', 0)
+
+def str_format(x):
+    return format_float(x, 'g', DTSF_STR_PRECISION)
+
+
+def unpackcomplex(space, w_complex, strict_typing=True):
     """
-    from pypy.objspace.std.complextype import complex_typedef as typedef
+    convert w_complex into a complex and return the unwrapped (real, imag)
+    tuple. If strict_typing==True, we also typecheck the value returned by
+    __complex__ to actually be a complex (and not e.g. a float).
+    See test___complex___returning_non_complex.
+    """
+    if type(w_complex) is W_ComplexObject:
+        return (w_complex.realval, w_complex.imagval)
+    #
+    # test for a '__complex__' method, and call it if found.
+    w_z = None
+    w_method = space.lookup(w_complex, '__complex__')
+    if w_method is not None:
+        w_z = space.get_and_call_function(w_method, w_complex)
+    #
+    if w_z is not None:
+        # __complex__() must return a complex or (float,int,long) object
+        # (XXX should not use isinstance here)
+        if not strict_typing and (space.isinstance_w(w_z, space.w_int) or
+                                  space.isinstance_w(w_z, space.w_float)):
+            return (space.float_w(w_z), 0.0)
+        elif isinstance(w_z, W_ComplexObject):
+            return (w_z.realval, w_z.imagval)
+        raise oefmt(space.w_TypeError,
+                    "__complex__() must return a complex number")
+
+    #
+    # no '__complex__' method, so we assume it is a float,
+    # unless it is an instance of some subclass of complex.
+    if space.isinstance_w(w_complex, space.gettypefor(W_ComplexObject)):
+        real = space.float(space.getattr(w_complex, space.wrap("real")))
+        imag = space.float(space.getattr(w_complex, space.wrap("imag")))
+        return (space.float_w(real), space.float_w(imag))
+    #
+    # Check that it is not a string (on which space.float() would succeed).
+    if (space.isinstance_w(w_complex, space.w_str) or
+        space.isinstance_w(w_complex, space.w_unicode)):
+        raise oefmt(space.w_TypeError,
+                    "complex number expected, got '%T'", w_complex)
+    #
+    return (space.float_w(space.float(w_complex)), 0.0)
+
+
+class W_ComplexObject(W_Root):
     _immutable_fields_ = ['realval', 'imagval']
 
     def __init__(self, realval=0.0, imgval=0.0):
@@ -63,7 +187,7 @@
 
     def __repr__(self):
         """ representation for debugging purposes """
-        return "<W_ComplexObject(%f,%f)>" % (self.realval, self.imagval)
+        return "<W_ComplexObject(%f, %f)>" % (self.realval, self.imagval)
 
     def as_tuple(self):
         return (self.realval, self.imagval)
@@ -104,162 +228,331 @@
 
         return w_result
 
+    def is_w(self, space, w_other):
+        from rpython.rlib.longlong2float import float2longlong
+        if not isinstance(w_other, W_ComplexObject):
+            return False
+        if self.user_overridden_class or w_other.user_overridden_class:
+            return self is w_other
+        real1 = space.float_w(space.getattr(self, space.wrap("real")))
+        real2 = space.float_w(space.getattr(w_other, space.wrap("real")))
+        imag1 = space.float_w(space.getattr(self, space.wrap("imag")))
+        imag2 = space.float_w(space.getattr(w_other, space.wrap("imag")))
+        real1 = float2longlong(real1)
+        real2 = float2longlong(real2)
+        imag1 = float2longlong(imag1)
+        imag2 = float2longlong(imag2)
+        return real1 == real2 and imag1 == imag2
+
+    def immutable_unique_id(self, space):
+        if self.user_overridden_class:
+            return None
+        from rpython.rlib.longlong2float import float2longlong
+        from pypy.objspace.std.model import IDTAG_COMPLEX as tag
+        real = space.float_w(space.getattr(self, space.wrap("real")))
+        imag = space.float_w(space.getattr(self, space.wrap("imag")))
+        real_b = rbigint.fromrarith_int(float2longlong(real))
+        imag_b = rbigint.fromrarith_int(r_ulonglong(float2longlong(imag)))
+        val = real_b.lshift(64).or_(imag_b).lshift(3).or_(rbigint.fromint(tag))
+        return space.newlong_from_rbigint(val)
+
     def int(self, space):
-        raise OperationError(space.w_TypeError, space.wrap("can't convert 
complex to int; use int(abs(z))"))
+        raise oefmt(space.w_TypeError,
+                    "can't convert complex to int; use int(abs(z))")
 
-registerimplementation(W_ComplexObject)
+    def _to_complex(self, space, w_obj):
+        if isinstance(w_obj, W_ComplexObject):
+            return w_obj
+        if space.isinstance_w(w_obj, space.w_int):
+            w_float = space.float_w(w_obj)
+            return W_ComplexObject(w_float, 0.0)
+        if space.isinstance_w(w_obj, space.w_float):
+            return W_ComplexObject(space.float_w(w_obj), 0.0)
+
+    @staticmethod
+    @unwrap_spec(w_real=WrappedDefault(0.0))
+    def descr__new__(space, w_complextype, w_real, w_imag=None):
+        # if w_real is already a complex number and there is no second
+        # argument, return it.  Note that we cannot return w_real if
+        # it is an instance of a *subclass* of complex, or if w_complextype
+        # is itself a subclass of complex.
+        noarg2 = w_imag is None
+        if (noarg2 and space.is_w(w_complextype, space.w_complex)
+            and space.is_w(space.type(w_real), space.w_complex)):
+            return w_real
+
+        if space.isinstance_w(w_real, space.w_unicode):
+            # a string argument
+            if not noarg2:
+                raise oefmt(space.w_TypeError, "complex() can't take second"
+                                               " arg if first is a string")
+            unistr = unicode_to_decimal_w(space, w_real)
+            try:
+                realstr, imagstr = _split_complex(unistr)
+            except ValueError:
+                raise oefmt(space.w_ValueError,
+                            "complex() arg is a malformed string")
+            try:
+                realval = string_to_float(realstr)
+                imagval = string_to_float(imagstr)
+            except ParseStringError:
+                raise oefmt(space.w_ValueError,
+                            "complex() arg is a malformed string")
+
+        else:
+            # non-string arguments
+            realval, imagval = unpackcomplex(space, w_real,
+                                             strict_typing=False)
+
+            # now take w_imag into account
+            if not noarg2:
+                # complex(x, y) == x+y*j, even if 'y' is already a complex.
+                realval2, imagval2 = unpackcomplex(space, w_imag,
+                                                   strict_typing=False)
+
+                # try to preserve the signs of zeroes of realval and realval2
+                if imagval2 != 0.0:
+                    realval -= imagval2
+
+                if imagval != 0.0:
+                    imagval += realval2
+                else:
+                    imagval = realval2
+        # done
+        w_obj = space.allocate_instance(W_ComplexObject, w_complextype)
+        W_ComplexObject.__init__(w_obj, realval, imagval)
+        return w_obj
+
+    def descr___getnewargs__(self, space):
+        return space.newtuple([space.newfloat(self.realval),
+                               space.newfloat(self.imagval)])
+
+    def descr_repr(self, space):
+        if self.realval == 0 and copysign(1., self.realval) == 1.:
+            return space.wrap(repr_format(self.imagval) + 'j')
+        sign = (copysign(1., self.imagval) == 1. or
+                isnan(self.imagval)) and '+' or ''
+        return space.wrap('(' + repr_format(self.realval)
+                          + sign + repr_format(self.imagval) + 'j)')
+
+    def descr_str(self, space):
+        if self.realval == 0 and copysign(1., self.realval) == 1.:
+            return space.wrap(str_format(self.imagval) + 'j')
+        sign = (copysign(1., self.imagval) == 1. or
+                isnan(self.imagval)) and '+' or ''
+        return space.wrap('(' + str_format(self.realval)
+                          + sign + str_format(self.imagval) + 'j)')
+
+    def descr_hash(self, space):
+        hashreal = _hash_float(space, self.realval)
+        hashimg = _hash_float(space, self.imagval)
+        combined = intmask(hashreal + HASH_IMAG * hashimg)
+        return space.newint(-2 if combined == -1 else combined)
+
+    def descr_format(self, space, w_format_spec):
+        return newformat.run_formatter(space, w_format_spec, "format_complex",
+                                       self)
+
+    def descr_bool(self, space):
+        return space.newbool((self.realval != 0.0) or (self.imagval != 0.0))
+
+    def descr_float(self, space):
+        raise oefmt(space.w_TypeError,
+                    "can't convert complex to float; use abs(z)")
+
+    def descr_neg(self, space):
+        return W_ComplexObject(-self.realval, -self.imagval)
+
+    def descr_pos(self, space):
+        return W_ComplexObject(self.realval, self.imagval)
+
+    def descr_abs(self, space):
+        try:
+            return space.newfloat(math.hypot(self.realval, self.imagval))
+        except OverflowError, e:
+            raise OperationError(space.w_OverflowError, space.wrap(str(e)))
+
+    def descr_eq(self, space, w_other):
+        if isinstance(w_other, W_ComplexObject):
+            return space.newbool((self.realval == w_other.realval) and
+                                 (self.imagval == w_other.imagval))
+        if (space.isinstance_w(w_other, space.w_int) or
+            space.isinstance_w(w_other, space.w_float)):
+            if self.imagval:
+                return space.w_False
+            return space.eq(space.newfloat(self.realval), w_other)
+        return space.w_NotImplemented
+
+    def descr_ne(self, space, w_other):
+        if isinstance(w_other, W_ComplexObject):
+            return space.newbool((self.realval != w_other.realval) or
+                                 (self.imagval != w_other.imagval))
+        if (space.isinstance_w(w_other, space.w_int)):
+            if self.imagval:
+                return space.w_True
+            return space.ne(space.newfloat(self.realval), w_other)
+        return space.w_NotImplemented
+
+    def _fail_cmp(self, space, w_other):
+        return space.w_NotImplemented
+
+    def descr_add(self, space, w_rhs):
+        w_rhs = self._to_complex(space, w_rhs)
+        if w_rhs is None:
+            return space.w_NotImplemented
+        return W_ComplexObject(self.realval + w_rhs.realval,
+                               self.imagval + w_rhs.imagval)
+
+    def descr_radd(self, space, w_lhs):
+        w_lhs = self._to_complex(space, w_lhs)
+        if w_lhs is None:
+            return space.w_NotImplemented
+        return W_ComplexObject(w_lhs.realval + self.realval,
+                               w_lhs.imagval + self.imagval)
+
+    def descr_sub(self, space, w_rhs):
+        w_rhs = self._to_complex(space, w_rhs)
+        if w_rhs is None:
+            return space.w_NotImplemented
+        return W_ComplexObject(self.realval - w_rhs.realval,
+                               self.imagval - w_rhs.imagval)
+
+    def descr_rsub(self, space, w_lhs):
+        w_lhs = self._to_complex(space, w_lhs)
+        if w_lhs is None:
+            return space.w_NotImplemented
+        return W_ComplexObject(w_lhs.realval - self.realval,
+                               w_lhs.imagval - self.imagval)
+
+    def descr_mul(self, space, w_rhs):
+        w_rhs = self._to_complex(space, w_rhs)
+        if w_rhs is None:
+            return space.w_NotImplemented
+        return self.mul(w_rhs)
+
+    def descr_rmul(self, space, w_lhs):
+        w_lhs = self._to_complex(space, w_lhs)
+        if w_lhs is None:
+            return space.w_NotImplemented
+        return w_lhs.mul(self)
+
+    def descr_truediv(self, space, w_rhs):
+        w_rhs = self._to_complex(space, w_rhs)
+        if w_rhs is None:
+            return space.w_NotImplemented
+        try:
+            return self.div(w_rhs)
+        except ZeroDivisionError, e:
+            raise OperationError(space.w_ZeroDivisionError, space.wrap(str(e)))
+
+    def descr_rtruediv(self, space, w_lhs):
+        w_lhs = self._to_complex(space, w_lhs)
+        if w_lhs is None:
+            return space.w_NotImplemented
+        try:
+            return w_lhs.div(self)
+        except ZeroDivisionError, e:
+            raise OperationError(space.w_ZeroDivisionError, space.wrap(str(e)))
+
+    def descr_floordiv(self, space, w_rhs):
+        raise oefmt(space.w_TypeError, "can't take floor of complex number.")
+    descr_rfloordiv = func_with_new_name(descr_floordiv, 'descr_rfloordiv')
+
+    def descr_mod(self, space, w_rhs):
+        raise oefmt(space.w_TypeError, "can't mod complex numbers.")
+    descr_rmod = func_with_new_name(descr_mod, 'descr_rmod')
+
+    def descr_divmod(self, space, w_rhs):
+        raise oefmt(space.w_TypeError,
+                    "can't take floor or mod of complex number.")
+    descr_rdivmod = func_with_new_name(descr_divmod, 'descr_rdivmod')
+
+    @unwrap_spec(w_third_arg=WrappedDefault(None))
+    def descr_pow(self, space, w_exponent, w_third_arg):
+        w_exponent = self._to_complex(space, w_exponent)
+        if w_exponent is None:
+            return space.w_NotImplemented
+        if not space.is_w(w_third_arg, space.w_None):
+            raise oefmt(space.w_ValueError, 'complex modulo')
+        try:
+            r = w_exponent.realval
+            if (w_exponent.imagval == 0.0 and -100.0 <= r <= 100.0 and
+                r == int(r)):
+                w_p = self.pow_small_int(int(r))
+            else:
+                w_p = self.pow(w_exponent)
+        except ZeroDivisionError:
+            raise oefmt(space.w_ZeroDivisionError,
+                        "0.0 to a negative or complex power")
+        except OverflowError:
+            raise oefmt(space.w_OverflowError, "complex exponentiation")
+        return w_p
+
+    @unwrap_spec(w_third_arg=WrappedDefault(None))
+    def descr_rpow(self, space, w_lhs, w_third_arg):
+        w_lhs = self._to_complex(space, w_lhs)
+        if w_lhs is None:
+            return space.w_NotImplemented
+        return w_lhs.descr_pow(space, self, w_third_arg)
+
+    def descr_conjugate(self, space):
+        """(A+Bj).conjugate() -> A-Bj"""
+        return space.newcomplex(self.realval, -self.imagval)
+
 
 w_one = W_ComplexObject(1, 0)
 
 
-def delegate_Bool2Complex(space, w_bool):
-    return W_ComplexObject(w_bool.intval, 0.0)
+def complexwprop(name, doc):
+    def fget(space, w_obj):
+        if not isinstance(w_obj, W_ComplexObject):
+            raise oefmt(space.w_TypeError, "descriptor is for 'complex'")
+        return space.newfloat(getattr(w_obj, name))
+    return GetSetProperty(fget, doc=doc)
 
-def delegate_Int2Complex(space, w_int):
-    return W_ComplexObject(w_int.intval, 0.0)
+W_ComplexObject.typedef = StdTypeDef("complex",
+    __doc__ = """complex(real[, imag]) -> complex number
 
-def delegate_Long2Complex(space, w_long):
-    dval = w_long.tofloat(space)
-    return W_ComplexObject(dval, 0.0)
+Create a complex number from a real part and an optional imaginary part.
+This is equivalent to (real + imag*1j) where imag defaults to 0.""",
+    __new__ = interp2app(W_ComplexObject.descr__new__),
+    __getnewargs__ = interp2app(W_ComplexObject.descr___getnewargs__),
+    real = complexwprop('realval', doc="the real part of a complex number"),
+    imag = complexwprop('imagval',
+                        doc="the imaginary part of a complex number"),
+    __repr__ = interp2app(W_ComplexObject.descr_repr),
+    __str__ = interp2app(W_ComplexObject.descr_str),
+    __hash__ = interp2app(W_ComplexObject.descr_hash),
+    __format__ = interp2app(W_ComplexObject.descr_format),
+    __bool__ = interp2app(W_ComplexObject.descr_bool),
+    __float__ = interp2app(W_ComplexObject.descr_float),
+    __neg__ = interp2app(W_ComplexObject.descr_neg),
+    __pos__ = interp2app(W_ComplexObject.descr_pos),
+    __abs__ = interp2app(W_ComplexObject.descr_abs),
 
-def delegate_Float2Complex(space, w_float):
-    return W_ComplexObject(w_float.floatval, 0.0)
+    __eq__ = interp2app(W_ComplexObject.descr_eq),
+    __ne__ = interp2app(W_ComplexObject.descr_ne),
+    __lt__ = interp2app(W_ComplexObject._fail_cmp),
+    __le__ = interp2app(W_ComplexObject._fail_cmp),
+    __gt__ = interp2app(W_ComplexObject._fail_cmp),
+    __ge__ = interp2app(W_ComplexObject._fail_cmp),
 
-def hash__Complex(space, w_value):
-    hashreal = _hash_float(space, w_value.realval)
-    hashimg = _hash_float(space, w_value.imagval)
-    combined = intmask(hashreal + HASH_IMAG * hashimg)
-    return space.newint(-2 if combined == -1 else combined)
+    __add__ = interp2app(W_ComplexObject.descr_add),
+    __radd__ = interp2app(W_ComplexObject.descr_radd),
+    __sub__ = interp2app(W_ComplexObject.descr_sub),
+    __rsub__ = interp2app(W_ComplexObject.descr_rsub),
+    __mul__ = interp2app(W_ComplexObject.descr_mul),
+    __rmul__ = interp2app(W_ComplexObject.descr_rmul),
+    __truediv__ = interp2app(W_ComplexObject.descr_truediv),
+    __rtruediv__ = interp2app(W_ComplexObject.descr_rtruediv),
+    __floordiv__ = interp2app(W_ComplexObject.descr_floordiv),
+    __rfloordiv__ = interp2app(W_ComplexObject.descr_rfloordiv),
+    __mod__ = interp2app(W_ComplexObject.descr_mod),
+    __rmod__ = interp2app(W_ComplexObject.descr_rmod),
+    __divmod__ = interp2app(W_ComplexObject.descr_divmod),
+    __rdivmod__ = interp2app(W_ComplexObject.descr_rdivmod),
+    __pow__ = interp2app(W_ComplexObject.descr_pow),
+    __rpow__ = interp2app(W_ComplexObject.descr_rpow),
 
-def add__Complex_Complex(space, w_complex1, w_complex2):
-    return W_ComplexObject(w_complex1.realval + w_complex2.realval,
-                           w_complex1.imagval + w_complex2.imagval)
-
-def sub__Complex_Complex(space, w_complex1, w_complex2):
-    return W_ComplexObject(w_complex1.realval - w_complex2.realval,
-                           w_complex1.imagval - w_complex2.imagval)
-
-def mul__Complex_Complex(space, w_complex1, w_complex2):
-    return w_complex1.mul(w_complex2)
-
-def div__Complex_Complex(space, w_complex1, w_complex2):
-    try:
-        return w_complex1.div(w_complex2)
-    except ZeroDivisionError, e:
-        raise OperationError(space.w_ZeroDivisionError, space.wrap(str(e)))
-
-truediv__Complex_Complex = div__Complex_Complex
-
-def pow__Complex_Complex_ANY(space, w_complex, w_exponent, thirdArg):
-    if not space.is_w(thirdArg, space.w_None):
-        raise OperationError(space.w_ValueError, space.wrap('complex modulo'))
-    try:
-        r = w_exponent.realval
-        if w_exponent.imagval == 0.0 and -100.0 <= r <= 100.0 and r == int(r):
-            w_p = w_complex.pow_small_int(int(r))
-        else:
-            w_p = w_complex.pow(w_exponent)
-    except ZeroDivisionError:
-        raise OperationError(space.w_ZeroDivisionError, space.wrap("0.0 to a 
negative or complex power"))
-    except OverflowError:
-        raise OperationError(space.w_OverflowError, space.wrap("complex 
exponentiation"))
-    return w_p
-
-def neg__Complex(space, w_complex):
-    return W_ComplexObject(-w_complex.realval, -w_complex.imagval)
-
-def pos__Complex(space, w_complex):
-    return W_ComplexObject(w_complex.realval, w_complex.imagval)
-
-def abs__Complex(space, w_complex):
-    try:
-        return space.newfloat(math.hypot(w_complex.realval, w_complex.imagval))
-    except OverflowError, e:
-        raise OperationError(space.w_OverflowError, space.wrap(str(e)))
-
-def eq__Complex_Complex(space, w_complex1, w_complex2):
-    return space.newbool((w_complex1.realval == w_complex2.realval) and
-            (w_complex1.imagval == w_complex2.imagval))
-
-def ne__Complex_Complex(space, w_complex1, w_complex2):
-    return space.newbool((w_complex1.realval != w_complex2.realval) or
-            (w_complex1.imagval != w_complex2.imagval))
-
-def eq__Complex_Long(space, w_complex1, w_long2):
-    if w_complex1.imagval:
-        return space.w_False
-    return space.eq(space.newfloat(w_complex1.realval), w_long2)
-eq__Complex_Int = eq__Complex_Long
-
-def eq__Long_Complex(space, w_long1, w_complex2):
-    return eq__Complex_Long(space, w_complex2, w_long1)
-eq__Int_Complex = eq__Long_Complex
-
-def ne__Complex_Long(space, w_complex1, w_long2):
-    if w_complex1.imagval:
-        return space.w_True
-    return space.ne(space.newfloat(w_complex1.realval), w_long2)
-ne__Complex_Int = ne__Complex_Long
-
-def ne__Long_Complex(space, w_long1, w_complex2):
-    return ne__Complex_Long(space, w_complex2, w_long1)
-ne__Int_Complex = ne__Long_Complex
-
-def lt__Complex_Complex(space, w_complex1, w_complex2):
-    from pypy.objspace.std.model import FailedToImplement
-    raise FailedToImplement
-
-gt__Complex_Complex = lt__Complex_Complex
-ge__Complex_Complex = lt__Complex_Complex
-le__Complex_Complex = lt__Complex_Complex
-
-def nonzero__Complex(space, w_complex):
-    return space.newbool((w_complex.realval != 0.0) or
-                         (w_complex.imagval != 0.0))
-
-def float__Complex(space, w_complex):
-    raise OperationError(space.w_TypeError, space.wrap("can't convert complex 
to float; use abs(z)"))
-
-def complex_conjugate__Complex(space, w_self):
-    #w_real = space.call_function(space.w_float,space.wrap(w_self.realval))
-    #w_imag = space.call_function(space.w_float,space.wrap(-w_self.imagval))
-    return space.newcomplex(w_self.realval,-w_self.imagval)
-
-def format_float(x, code, precision):
-    # like float2string, except that the ".0" is not necessary
-    if isinf(x):
-        if x > 0.0:
-            return "inf"
-        else:
-            return "-inf"
-    elif isnan(x):
-        return "nan"
-    else:
-        return formatd(x, code, precision)
-
-def repr_format(x):
-    return format_float(x, 'r', 0)
-def str_format(x):
-    return format_float(x, 'g', DTSF_STR_PRECISION)
-
-def repr__Complex(space, w_complex):
-    if w_complex.realval == 0 and copysign(1., w_complex.realval) == 1.:
-        return space.wrap(repr_format(w_complex.imagval) + 'j')
-    sign = (copysign(1., w_complex.imagval) == 1. or
-            isnan(w_complex.imagval)) and '+' or ''
-    return space.wrap('(' + repr_format(w_complex.realval)
-                      + sign + repr_format(w_complex.imagval) + 'j)')
-
-def str__Complex(space, w_complex):
-    if w_complex.realval == 0 and copysign(1., w_complex.realval) == 1.:
-        return space.wrap(str_format(w_complex.imagval) + 'j')
-    sign = (copysign(1., w_complex.imagval) == 1. or
-            isnan(w_complex.imagval)) and '+' or ''
-    return space.wrap('(' + str_format(w_complex.realval)
-                      + sign + str_format(w_complex.imagval) + 'j)')
-
-def format__Complex_ANY(space, w_complex, w_format_spec):
-    return newformat.run_formatter(space, w_format_spec, "format_complex", 
w_complex)
-
-from pypy.objspace.std import complextype
-register_all(vars(), complextype)
+    conjugate = interp2app(W_ComplexObject.descr_conjugate),
+)
diff --git a/pypy/objspace/std/complextype.py b/pypy/objspace/std/complextype.py
deleted file mode 100644
--- a/pypy/objspace/std/complextype.py
+++ /dev/null
@@ -1,240 +0,0 @@
-from pypy.interpreter.error import OperationError, oefmt
-from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
-from pypy.objspace.std.register_all import register_all
-from pypy.objspace.std.stdtypedef import GetSetProperty, StdTypeDef
-from pypy.objspace.std.stdtypedef import StdObjSpaceMultiMethod
-from pypy.objspace.std.unicodeobject import unicode_to_decimal_w
-from rpython.rlib.rfloat import string_to_float
-from rpython.rlib.rstring import ParseStringError
-
-# ERRORCODES
-
-ERR_WRONG_SECOND = "complex() can't take second arg if first is a string"
-ERR_MALFORMED = "complex() arg is a malformed string"
-
-complex_conjugate = StdObjSpaceMultiMethod('conjugate', 1,
-                                           doc="(A+Bj).conjugate() -> A-Bj")
-
-register_all(vars(),globals())
-
-def _split_complex(s):
-    slen = len(s)
-    if slen == 0:
-        raise ValueError
-    realstart = 0
-    realstop = 0
-    imagstart = 0
-    imagstop = 0
-    imagsign = ' '
-    i = 0
-    # ignore whitespace at beginning and end
-    while i < slen and s[i] == ' ':
-        i += 1
-    while slen > 0 and s[slen-1] == ' ':
-        slen -= 1
-
-    if s[i] == '(' and s[slen-1] == ')':
-        i += 1
-        slen -= 1
-        # ignore whitespace after bracket
-        while i < slen and s[i] == ' ':
-            i += 1
-        while slen > 0 and s[slen-1] == ' ':
-            slen -= 1
-
-    # extract first number
-    realstart = i
-    pc = s[i]
-    while i < slen and s[i] != ' ':
-        if s[i] in ('+', '-') and pc not in ('e', 'E') and i != realstart:
-            break
-        pc = s[i]
-        i += 1
-
-    realstop = i
-
-    # return appropriate strings is only one number is there
-    if i >= slen:
-        newstop = realstop - 1
-        if newstop < 0:
-            raise ValueError
-        if s[newstop] in ('j', 'J'):
-            if realstart == newstop:
-                imagpart = '1.0'
-            elif realstart == newstop-1 and s[realstart] == '+':
-                imagpart = '1.0'
-            elif realstart == newstop-1 and s[realstart] == '-':
-                imagpart = '-1.0'
-            else:
-                imagpart = s[realstart:newstop]
-            return '0.0', imagpart
-        else:
-            return s[realstart:realstop], '0.0'
-
-    # find sign for imaginary part
-    if s[i] == '-' or s[i] == '+':
-        imagsign = s[i]
-    else:
-        raise ValueError
-
-    i += 1
-    if i >= slen:
-        raise ValueError
-
-    imagstart = i
-    pc = s[i]
-    while i < slen and s[i] != ' ':
-        if s[i] in ('+', '-') and pc not in ('e', 'E'):
-            break
-        pc = s[i]
-        i += 1
-
-    imagstop = i - 1
-    if imagstop < 0:
-        raise ValueError
-    if s[imagstop] not in ('j', 'J'):
-        raise ValueError
-    if imagstop < imagstart:
-        raise ValueError
-
-    if i < slen:
-        raise ValueError
-
-    realpart = s[realstart:realstop]
-    if imagstart == imagstop:
-        imagpart = '1.0'
-    else:
-        imagpart = s[imagstart:imagstop]
-    if imagsign == '-':
-        imagpart = imagsign + imagpart
-
-    return realpart, imagpart
-
-
-@unwrap_spec(w_real = WrappedDefault(0.0))
-def descr__new__(space, w_complextype, w_real, w_imag=None):
-    from pypy.objspace.std.complexobject import W_ComplexObject
-
-    # if w_real is already a complex number and there is no second
-    # argument, return it.  Note that we cannot return w_real if
-    # it is an instance of a *subclass* of complex, or if w_complextype
-    # is itself a subclass of complex.
-    noarg2 = w_imag is None
-    if (noarg2 and space.is_w(w_complextype, space.w_complex)
-               and space.is_w(space.type(w_real), space.w_complex)):
-        return w_real
-
-    if space.isinstance_w(w_real, space.w_unicode):
-        # a string argument
-        if not noarg2:
-            raise OperationError(space.w_TypeError,
-                                 space.wrap("complex() can't take second arg"
-                                            " if first is a string"))
-        unistr = unicode_to_decimal_w(space, w_real)
-        try:
-            realstr, imagstr = _split_complex(unistr)
-        except ValueError:
-            raise OperationError(space.w_ValueError, space.wrap(ERR_MALFORMED))
-        try:
-            realval = string_to_float(realstr)
-            imagval = string_to_float(imagstr)
-        except ParseStringError:
-            raise OperationError(space.w_ValueError, space.wrap(ERR_MALFORMED))
-
-    else:
-        # non-string arguments
-        realval, imagval = unpackcomplex(space, w_real, strict_typing=False)
-
-        # now take w_imag into account
-        if not noarg2:
-            # complex(x, y) == x+y*j, even if 'y' is already a complex.
-            realval2, imagval2 = unpackcomplex(space, w_imag, 
strict_typing=False)
-
-            # try to preserve the signs of zeroes of realval and realval2
-            if imagval2 != 0.0:
-                realval -= imagval2
-
-            if imagval != 0.0:
-                imagval += realval2
-            else:
-                imagval = realval2
-    # done
-    w_obj = space.allocate_instance(W_ComplexObject, w_complextype)
-    W_ComplexObject.__init__(w_obj, realval, imagval)
-    return w_obj
-
-
-def unpackcomplex(space, w_complex, strict_typing=True):
-    """
-    convert w_complex into a complex and return the unwrapped (real, imag)
-    tuple. If strict_typing==True, we also typecheck the value returned by
-    __complex__ to actually be a complex (and not e.g. a float).
-    See test___complex___returning_non_complex.
-    """
-    from pypy.objspace.std.complexobject import W_ComplexObject
-    if type(w_complex) is W_ComplexObject:
-        return (w_complex.realval, w_complex.imagval)
-    #
-    # test for a '__complex__' method, and call it if found.
-    w_z = None
-    w_method = space.lookup(w_complex, '__complex__')
-    if w_method is not None:
-        w_z = space.get_and_call_function(w_method, w_complex)
-    #
-    if w_z is not None:
-        # __complex__() must return a complex or (float,int,long) object
-        # (XXX should not use isinstance here)
-        if not strict_typing and (space.isinstance_w(w_z, space.w_int) or
-                                  space.isinstance_w(w_z, space.w_float)):
-            return (space.float_w(w_z), 0.0)
-        elif isinstance(w_z, W_ComplexObject):
-            return (w_z.realval, w_z.imagval)
-        raise OperationError(space.w_TypeError,
-                             space.wrap("__complex__() must return"
-                                        " a complex number"))
-
-    #
-    # no '__complex__' method, so we assume it is a float,
-    # unless it is an instance of some subclass of complex.
-    if space.isinstance_w(w_complex, space.gettypefor(W_ComplexObject)):
-        real = space.float(space.getattr(w_complex, space.wrap("real")))
-        imag = space.float(space.getattr(w_complex, space.wrap("imag")))
-        return (space.float_w(real), space.float_w(imag))
-    #
-    # Check that it is not a string (on which space.float() would succeed).
-    if (space.isinstance_w(w_complex, space.w_str) or
-        space.isinstance_w(w_complex, space.w_unicode)):
-        raise oefmt(space.w_TypeError,
-                    "complex number expected, got '%T'", w_complex)
-    #
-    return (space.float_w(space.float(w_complex)), 0.0)
-
-
-def complexwprop(name, doc):
-    def fget(space, w_obj):
-        from pypy.objspace.std.complexobject import W_ComplexObject
-        if not isinstance(w_obj, W_ComplexObject):
-            raise OperationError(space.w_TypeError,
-                                 space.wrap("descriptor is for 'complex'"))
-        return space.newfloat(getattr(w_obj, name))
-    return GetSetProperty(fget, doc=doc)
-
-def descr___getnewargs__(space,  w_self):
-    from pypy.objspace.std.complexobject import W_ComplexObject
-    assert isinstance(w_self, W_ComplexObject)
-    return space.newtuple([space.newfloat(w_self.realval),
-                           space.newfloat(w_self.imagval)])
-
-complex_typedef = StdTypeDef("complex",
-    __doc__ = """complex(real[, imag]) -> complex number
-
-Create a complex number from a real part and an optional imaginary part.
-This is equivalent to (real + imag*1j) where imag defaults to 0.""",
-    __new__ = interp2app(descr__new__),
-    __getnewargs__ = interp2app(descr___getnewargs__),
-    real = complexwprop('realval', doc="the real part of a complex number"),
-    imag = complexwprop('imagval',
-                        doc="the imaginary part of a complex number"),
-    )
-
-complex_typedef.registermethods(globals())
diff --git a/pypy/objspace/std/default.py b/pypy/objspace/std/default.py
deleted file mode 100644
--- a/pypy/objspace/std/default.py
+++ /dev/null
@@ -1,11 +0,0 @@
-"""Default implementation for some operation."""
-
-from pypy.objspace.std.register_all import register_all
-
-
-# __init__ should succeed if called internally as a multimethod
-
-def init__ANY(space, w_obj, __args__):
-    pass
-
-register_all(vars())
diff --git a/pypy/objspace/std/dictproxyobject.py 
b/pypy/objspace/std/dictproxyobject.py
--- a/pypy/objspace/std/dictproxyobject.py
+++ b/pypy/objspace/std/dictproxyobject.py
@@ -1,5 +1,3 @@
-#from pypy.objspace.std.model import registerimplementation, W_Object
-#from pypy.objspace.std.register_all import register_all
 from pypy.objspace.std.dictmultiobject import DictStrategy, 
create_iterator_classes
 from pypy.objspace.std.typeobject import unwrap_cell
 from pypy.interpreter.error import OperationError, oefmt
diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -1,139 +1,35 @@
 import math
 import operator
+import sys
 
+from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.error import OperationError, oefmt
+from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
+from pypy.interpreter.typedef import GetSetProperty
 from pypy.objspace.std import newformat
-from pypy.objspace.std.floattype import float_typedef, W_AbstractFloatObject
-from pypy.objspace.std.intobject import HASH_BITS, HASH_MODULUS
-from pypy.objspace.std.multimethod import FailedToImplementArgs
-from pypy.objspace.std.model import registerimplementation, W_Object
-from pypy.objspace.std.register_all import register_all
-from pypy.objspace.std.longobject import W_LongObject, newlong_from_float
-from pypy.objspace.std.noneobject import W_NoneObject
+from pypy.objspace.std.intobject import HASH_BITS, HASH_MODULUS, W_IntObject
+from pypy.objspace.std.longobject import (
+    W_AbstractLongObject, newlong_from_float)
 from rpython.rlib.rarithmetic import (
     LONG_BIT, intmask, ovfcheck_float_to_int, r_uint)
+from pypy.objspace.std.stdtypedef import StdTypeDef
+from pypy.objspace.std.util import wrap_parsestringerror
+from rpython.rlib import rarithmetic, rfloat
+from rpython.rlib.rbigint import rbigint
 from rpython.rlib.rfloat import (
     isinf, isnan, isfinite, INFINITY, NAN, copysign, formatd,
     DTSF_ADD_DOT_0, float_as_rbigint_ratio)
-from rpython.rlib.rbigint import rbigint
-from rpython.rlib import rfloat
+from rpython.rlib.rstring import ParseStringError
 from rpython.tool.sourcetools import func_with_new_name
+from rpython.rlib.unroll import unrolling_iterable
 from rpython.rtyper.lltypesystem.module.ll_math import math_fmod
 
-from pypy.objspace.std.intobject import W_IntObject
-
 HASH_INF  = 314159
 HASH_NAN  = 0
 
-class W_FloatObject(W_AbstractFloatObject):
-    """This is a implementation of the app-level 'float' type.
-    The constructor takes an RPython float as an argument."""
-    _immutable_fields_ = ['floatval']
-
-    typedef = float_typedef
-
-    def __init__(self, floatval):
-        self.floatval = floatval
-
-    def unwrap(self, space):
-        return self.floatval
-
-    def int_w(self, space, allow_conversion=True):
-        self._typed_unwrap_error(space, "integer")
-
-    def bigint_w(self, space, allow_conversion=True):
-        self._typed_unwrap_error(space, "integer")
-
-    def float_w(self, space, allow_conversion=True):
-        return self.floatval
-
-    def _float_w(self, space):
-        return self.floatval
-
-    def int(self, space):
-        if (type(self) is not W_FloatObject and
-            space.is_overloaded(self, space.w_float, '__int__')):
-            return W_Object.int(self, space)
-        try:
-            value = ovfcheck_float_to_int(self.floatval)
-        except OverflowError:
-            return newlong_from_float(space, self.floatval)
-        else:
-            return space.newint(value)
-
-    def __repr__(self):
-        return "<W_FloatObject(%f)>" % self.floatval
-
-registerimplementation(W_FloatObject)
-
-# bool-to-float delegation
-def delegate_Bool2Float(space, w_bool):
-    return W_FloatObject(float(w_bool.intval))
-
-# int-to-float delegation
-def delegate_Int2Float(space, w_intobj):
-    return W_FloatObject(float(w_intobj.intval))
-
-# long-to-float delegation
-def delegate_Long2Float(space, w_longobj):
-    return W_FloatObject(w_longobj.tofloat(space))
-
-
-# float__Float is supposed to do nothing, unless it has
-# a derived float object, where it should return
-# an exact one.
-def float__Float(space, w_float1):
-    if space.is_w(space.type(w_float1), space.w_float):
-        return w_float1
-    a = w_float1.floatval
-    return W_FloatObject(a)
-
-def trunc__Float(space, w_floatobj):
-    whole = math.modf(w_floatobj.floatval)[1]
-    try:
-        value = ovfcheck_float_to_int(whole)
-    except OverflowError:
-        return newlong_from_float(space, whole)
-    else:
-        return space.newint(value)
-
-def _char_from_hex(number):
-    return "0123456789abcdef"[number]
-
-TOHEX_NBITS = rfloat.DBL_MANT_DIG + 3 - (rfloat.DBL_MANT_DIG + 2) % 4
-
-def float_hex__Float(space, w_float):
-    value = w_float.floatval
-    if not isfinite(value):
-        return str__Float(space, w_float)
-    if value == 0.0:
-        if copysign(1., value) == -1.:
-            return space.wrap("-0x0.0p+0")
-        else:
-            return space.wrap("0x0.0p+0")
-    mant, exp = math.frexp(value)
-    shift = 1 - max(rfloat.DBL_MIN_EXP - exp, 0)
-    mant = math.ldexp(mant, shift)
-    mant = abs(mant)
-    exp -= shift
-    result = ['\0'] * ((TOHEX_NBITS - 1) // 4 + 2)
-    result[0] = _char_from_hex(int(mant))
-    mant -= int(mant)
-    result[1] = "."
-    for i in range((TOHEX_NBITS - 1) // 4):
-        mant *= 16.0
-        result[i + 2] = _char_from_hex(int(mant))
-        mant -= int(mant)
-    if exp < 0:
-        sign = "-"
-    else:
-        sign = "+"
-    exp = abs(exp)
-    s = ''.join(result)
-    if value < 0.0:
-        return space.wrap("-0x%sp%s%d" % (s, sign, exp))
-    else:
-        return space.wrap("0x%sp%s%d" % (s, sign, exp))
+# Here 0.30103 is an upper bound for log10(2)
+NDIGITS_MAX = int((rfloat.DBL_MANT_DIG - rfloat.DBL_MIN_EXP) * 0.30103)
+NDIGITS_MIN = -int((rfloat.DBL_MAX_EXP + 1) * 0.30103)
 
 def float2string(x, code, precision):
     # we special-case explicitly inf and nan here
@@ -148,34 +44,60 @@
         s = "nan"
     return s
 
-def repr__Float(space, w_float):
-    return space.wrap(float2string(w_float.floatval, 'r', 0))
 
-str__Float = repr__Float
+def detect_floatformat():
+    from rpython.rtyper.lltypesystem import rffi, lltype
+    buf = lltype.malloc(rffi.CCHARP.TO, 8, flavor='raw')
+    rffi.cast(rffi.DOUBLEP, buf)[0] = 9006104071832581.0
+    packed = rffi.charpsize2str(buf, 8)
+    if packed == "\x43\x3f\xff\x01\x02\x03\x04\x05":
+        double_format = 'IEEE, big-endian'
+    elif packed == "\x05\x04\x03\x02\x01\xff\x3f\x43":
+        double_format = 'IEEE, little-endian'
+    else:
+        double_format = 'unknown'
+    lltype.free(buf, flavor='raw')
+    #
+    buf = lltype.malloc(rffi.CCHARP.TO, 4, flavor='raw')
+    rffi.cast(rffi.FLOATP, buf)[0] = rarithmetic.r_singlefloat(16711938.0)
+    packed = rffi.charpsize2str(buf, 4)
+    if packed == "\x4b\x7f\x01\x02":
+        float_format = 'IEEE, big-endian'
+    elif packed == "\x02\x01\x7f\x4b":
+        float_format = 'IEEE, little-endian'
+    else:
+        float_format = 'unknown'
+    lltype.free(buf, flavor='raw')
 
-def format__Float_ANY(space, w_float, w_spec):
-    return newformat.run_formatter(space, w_spec, "format_float", w_float)
+    return double_format, float_format
 
-# ____________________________________________________________
-# A mess to handle all cases of float comparison without relying
-# on delegation, which can unfortunately loose precision when
-# casting an int or a long to a float.
+_double_format, _float_format = detect_floatformat()
 
-def list_compare_funcs(declarator):
-    for op in ['lt', 'le', 'eq', 'ne', 'gt', 'ge']:
-        func, name = declarator(op)
-        globals()[name] = func_with_new_name(func, name)
 
-def _reverse(opname):
-    if opname[0] == 'l': return 'g' + opname[1:]
-    elif opname[0] == 'g': return 'l' + opname[1:]
-    else: return opname
+_alpha = zip("abcdef", range(10, 16)) + zip("ABCDEF", range(10, 16))
+_hex_to_int = zip("0123456789", range(10)) + _alpha
+_hex_to_int_iterable = unrolling_iterable(_hex_to_int)
 
+def _hex_from_char(c):
+    for h, v in _hex_to_int_iterable:
+        if h == c:
+            return v
+    return -1
 
-def declare_compare_bigint(opname):
-    """Return a helper function that implements a float-bigint comparison."""
+def _hex_digit(s, j, co_end, float_digits):
+    if j < float_digits:
+        i = co_end - j
+    else:
+        i = co_end - 1 - j
+    return _hex_from_char(s[i])
+
+def _char_from_hex(number):
+    return "0123456789abcdef"[number]
+
+
+def make_compare_func(opname):
     op = getattr(operator, opname)
-    #
+
     if opname == 'eq' or opname == 'ne':
         def do_compare_bigint(f1, b2):
             """f1 is a float.  b2 is a bigint."""
@@ -201,73 +123,578 @@
                 f1 = math.floor(f1)
             b1 = rbigint.fromfloat(f1)
             return getattr(b1, opname)(b2)
-    #
-    return do_compare_bigint, 'compare_bigint_' + opname
-list_compare_funcs(declare_compare_bigint)
 
+    def _compare(self, space, w_other):
+        if isinstance(w_other, W_FloatObject):
+            return space.newbool(op(self.floatval, w_other.floatval))
+        if isinstance(w_other, W_IntObject):
+            f1 = self.floatval
+            i2 = space.int_w(w_other)
+            f2 = float(i2)
+            if LONG_BIT > 32 and int(f2) != i2:
+                res = do_compare_bigint(f1, rbigint.fromint(i2))
+            else:
+                res = op(f1, f2)
+            return space.newbool(res)
+        if isinstance(w_other, W_AbstractLongObject):
+            return space.newbool(do_compare_bigint(self.floatval,
+                                                   space.bigint_w(w_other)))
+        return space.w_NotImplemented
+    return func_with_new_name(_compare, 'descr_' + opname)
 
-def declare_cmp_float_float(opname):
-    op = getattr(operator, opname)
-    def f(space, w_float1, w_float2):
-        f1 = w_float1.floatval
-        f2 = w_float2.floatval
-        return space.newbool(op(f1, f2))
-    return f, opname + "__Float_Float"
-list_compare_funcs(declare_cmp_float_float)
 
-def declare_cmp_float_int(opname):
-    op = getattr(operator, opname)
-    compare = globals()['compare_bigint_' + opname]
-    def f(space, w_float1, w_int2):
-        f1 = w_float1.floatval
-        i2 = w_int2.intval
-        f2 = float(i2)
-        if LONG_BIT > 32 and int(f2) != i2:
-            res = compare(f1, rbigint.fromint(i2))
+class W_FloatObject(W_Root):
+    """This is a implementation of the app-level 'float' type.
+    The constructor takes an RPython float as an argument."""
+    _immutable_fields_ = ['floatval']
+
+    def __init__(self, floatval):
+        self.floatval = floatval
+
+    def unwrap(self, space):
+        return self.floatval
+
+    def int_w(self, space, allow_conversion=True):
+        self._typed_unwrap_error(space, "integer")
+
+    def bigint_w(self, space, allow_conversion=True):
+        self._typed_unwrap_error(space, "integer")
+
+    def float_w(self, space, allow_conversion=True):
+        return self.floatval
+
+    def _float_w(self, space):
+        return self.floatval
+
+    def int(self, space):
+        if (type(self) is not W_FloatObject and
+            space.is_overloaded(self, space.w_float, '__int__')):
+            return W_Root.int(self, space)
+        try:
+            value = ovfcheck_float_to_int(self.floatval)
+        except OverflowError:
+            return newlong_from_float(space, self.floatval)
         else:
-            res = op(f1, f2)
-        return space.newbool(res)
-    return f, opname + "__Float_Int"
-list_compare_funcs(declare_cmp_float_int)
+            return space.newint(value)
 
-def declare_cmp_float_long(opname):
-    compare = globals()['compare_bigint_' + opname]
-    def f(space, w_float1, w_long2):
-        f1 = w_float1.floatval
-        b2 = w_long2.num
-        return space.newbool(compare(f1, b2))
-    return f, opname + "__Float_Long"
-list_compare_funcs(declare_cmp_float_long)
+    def is_w(self, space, w_other):
+        from rpython.rlib.longlong2float import float2longlong
+        if not isinstance(w_other, W_FloatObject):
+            return False
+        if self.user_overridden_class or w_other.user_overridden_class:
+            return self is w_other
+        one = float2longlong(space.float_w(self))
+        two = float2longlong(space.float_w(w_other))
+        return one == two
 
-def declare_cmp_int_float(opname):
-    op = getattr(operator, opname)
-    revcompare = globals()['compare_bigint_' + _reverse(opname)]
-    def f(space, w_int1, w_float2):
-        f2 = w_float2.floatval
-        i1 = w_int1.intval
-        f1 = float(i1)
-        if LONG_BIT > 32 and int(f1) != i1:
-            res = revcompare(f2, rbigint.fromint(i1))
+    def immutable_unique_id(self, space):
+        if self.user_overridden_class:
+            return None
+        from rpython.rlib.longlong2float import float2longlong
+        from pypy.objspace.std.model import IDTAG_FLOAT as tag
+        val = float2longlong(space.float_w(self))
+        b = rbigint.fromrarith_int(val)
+        b = b.lshift(3).or_(rbigint.fromint(tag))
+        return space.newlong_from_rbigint(b)
+
+    def __repr__(self):
+        return "<W_FloatObject(%f)>" % self.floatval
+
+    @staticmethod
+    @unwrap_spec(w_x=WrappedDefault(0.0))
+    def descr__new__(space, w_floattype, w_x):
+        def _string_to_float(space, w_source, string):
+            try:
+                return rfloat.string_to_float(string)
+            except ParseStringError as e:
+                raise wrap_parsestringerror(space, e, w_source)
+
+        w_value = w_x     # 'x' is the keyword argument name in CPython
+        if space.lookup(w_value, "__float__") is not None:
+            w_obj = space.float(w_value)
+            if space.is_w(w_floattype, space.w_float):
+                return w_obj
+            value = space.float_w(w_obj)
+        elif space.isinstance_w(w_value, space.w_unicode):
+            from unicodeobject import unicode_to_decimal_w
+            value = _string_to_float(space, w_value,
+                                     unicode_to_decimal_w(space, w_value))
         else:
-            res = op(f1, f2)
-        return space.newbool(res)
-    return f, opname + "__Int_Float"
-list_compare_funcs(declare_cmp_int_float)
+            try:
+                value = space.charbuf_w(w_value)
+            except OperationError as e:
+                if e.match(space, space.w_TypeError):
+                    raise oefmt(
+                        space.w_TypeError,
+                        "float() argument must be a string or a number")
+                raise
+            value = _string_to_float(space, w_value, value)
+        w_obj = space.allocate_instance(W_FloatObject, w_floattype)
+        W_FloatObject.__init__(w_obj, value)
+        return w_obj
 
-def declare_cmp_long_float(opname):
-    revcompare = globals()['compare_bigint_' + _reverse(opname)]
-    def f(space, w_long1, w_float2):
-        f2 = w_float2.floatval
-        b1 = w_long1.num
-        return space.newbool(revcompare(f2, b1))
-    return f, opname + "__Long_Float"
-list_compare_funcs(declare_cmp_long_float)
+    @staticmethod
+    @unwrap_spec(kind=str)
+    def descr___getformat__(space, w_cls, kind):
+        if kind == "float":
+            return space.wrap(_float_format)
+        elif kind == "double":
+            return space.wrap(_double_format)
+        raise oefmt(space.w_ValueError, "only float and double are valid")
 
+    @staticmethod
+    @unwrap_spec(s=str)
+    def descr_fromhex(space, w_cls, s):
+        length = len(s)
+        i = 0
+        value = 0.0
+        while i < length and s[i].isspace():
+            i += 1
+        if i == length:
+            raise oefmt(space.w_ValueError, "invalid hex string")
+        sign = 1
+        if s[i] == "-":
+            sign = -1
+            i += 1
+        elif s[i] == "+":
+            i += 1
+        if length == i:
+            raise oefmt(space.w_ValueError, "invalid hex string")
+        if s[i] == "i" or s[i] == "I":
+            i += 1
+            if length - i >= 2 and s[i:i + 2].lower() == "nf":
+                i += 2
+                value = rfloat.INFINITY
+                if length - i >= 5 and s[i:i + 5].lower() == "inity":
+                    i += 5
+        elif s[i] == "n" or s[i] == "N":
+            i += 1
+            if length - i >= 2 and s[i:i + 2].lower() == "an":
+                i += 2
+                value = rfloat.NAN
+        else:
+            if (s[i] == "0" and length - i > 1 and
+                (s[i + 1] == "x" or s[i + 1] == "X")):
+                i += 2
+            co_start = i
+            while i < length and _hex_from_char(s[i]) >= 0:
+                i += 1
+            whole_end = i
+            if i < length and s[i] == ".":
+                i += 1
+                while i < length and _hex_from_char(s[i]) >= 0:
+                    i += 1
+                co_end = i - 1
+            else:
+                co_end = i
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to