Commits

Philip Jenvey committed e677ccd

fully handle int overflowing to smalllong and much cleanup/progress

Comments (0)

Files changed (10)

pypy/objspace/std/boolobject.py

 from rpython.rlib.rbigint import rbigint
 
 from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec
-from pypy.objspace.std.intobject import W_AbstractIntObject, W_IntObject
+from pypy.objspace.std.intobject import W_AbstractIntObject
 from pypy.objspace.std.stdtypedef import StdTypeDef
 
 
 
     def descr_repr(self, space):
         return space.wrap('True' if self.boolval else 'False')
-
     descr_str = descr_repr
 
     def descr_nonzero(self, space):
 @unwrap_spec(w_obj=WrappedDefault(False))
 def descr__new__(space, w_booltype, w_obj):
     space.w_bool.check_user_subclass(w_booltype)
-    return space.newbool(space.is_true(w_obj)) # XXX: method call?
+    return space.newbool(space.is_true(w_obj))
 
 # ____________________________________________________________
 
-W_BoolObject.typedef = StdTypeDef("bool", W_IntObject.typedef,
+W_BoolObject.typedef = StdTypeDef("bool", W_AbstractIntObject.typedef,
     __doc__ = """bool(x) -> bool
 
 Returns True when the argument x is true, False otherwise.
     __new__ = interp2app(descr__new__),
     __repr__ = interp2app(W_BoolObject.descr_repr),
     __str__ = interp2app(W_BoolObject.descr_str),
-                                  # XXX: might as well declare interp2app directly here for nonzero/and/etc
+    __nonzero__ = interp2app(W_BoolObject.descr_nonzero),
+    # XXX: rsides
+    __and__ = interp2app(W_BoolObject.descr_and),
+    #__rand__ = interp2app(W_BoolObject.descr_rand),
+    __or__ = interp2app(W_BoolObject.descr_or),
+    #__ror__ = interp2app(W_BoolObject.descr_ror),
+    __xor__ = interp2app(W_BoolObject.descr_xor),
+    #__rxor__ = interp2app(W_BoolObject.descr_rxor),
     )
 W_BoolObject.typedef.acceptable_as_base_class = False

pypy/objspace/std/floatobject.py

 
 # long-to-float delegation
 def delegate_Long2Float(space, w_longobj):
-    # XXX: tofloat is not abstract (SmallLongs)
     return W_FloatObject(w_longobj.tofloat(space))
 
 
 
 from pypy.objspace.std import floattype
 register_all(vars(), floattype)
-
-# pow delegation for negative 2nd arg
-def pow_neg__Long_Long_None(space, w_int1, w_int2, thirdarg):
-    w_float1 = delegate_Long2Float(space, w_int1)
-    w_float2 = delegate_Long2Float(space, w_int2)
-    return pow__Float_Float_ANY(space, w_float1, w_float2, thirdarg)
-
-model.MM.pow.register(pow_neg__Long_Long_None, W_LongObject, W_LongObject,
-                      W_NoneObject, order=1)
-
-def pow_neg__Int_Int_None(space, w_int1, w_int2, thirdarg):
-    w_float1 = delegate_Int2Float(space, w_int1)
-    w_float2 = delegate_Int2Float(space, w_int2)
-    return pow__Float_Float_ANY(space, w_float1, w_float2, thirdarg)
-
-model.MM.pow.register(pow_neg__Int_Int_None, W_IntObject, W_IntObject,
-                      W_NoneObject, order=2)

pypy/objspace/std/intobject.py

 """
 
 import operator
+import sys
 
 from rpython.rlib import jit
+from rpython.rlib.objectmodel import instantiate, specialize
 from rpython.rlib.rarithmetic import (
-    LONG_BIT, is_valid_int, ovfcheck, string_to_int, r_uint)
-from rpython.rlib.objectmodel import instantiate
+    LONG_BIT, is_valid_int, ovfcheck, r_uint, string_to_int)
 from rpython.rlib.rbigint import rbigint
 from rpython.rlib.rstring import ParseStringError, ParseStringOverflowError
-from rpython.tool.sourcetools import func_with_new_name
+from rpython.tool.sourcetools import func_renamer, func_with_new_name
 
 from pypy.interpreter import typedef
+from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.buffer import Buffer
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.gateway import (
     WrappedDefault, interp2app, interpindirect2app, unwrap_spec)
 from pypy.objspace.std import newformat
-from pypy.objspace.std.model import W_Object
 from pypy.objspace.std.stdtypedef import StdTypeDef
 
 
-class W_AbstractIntObject(W_Object):
+class W_AbstractIntObject(W_Root):
+
     __slots__ = ()
 
     def int(self, space):
         raise NotImplementedError
 
+    def _make_descr_cmp(opname):
+        op = getattr(operator, opname)
+        @func_renamer('descr_' + opname)
+        def descr_cmp(self, space, w_other):
+            if not isinstance(w_other, W_AbstractIntObject):
+                return space.w_NotImplemented
+            i = space.int_w(self)
+            j = space.int_w(w_other)
+            return space.newbool(op(i, j))
+        return descr_cmp
+
+    descr_lt = _make_descr_cmp('lt')
+    descr_le = _make_descr_cmp('le')
+    descr_eq = _make_descr_cmp('eq')
+    descr_ne = _make_descr_cmp('ne')
+    descr_gt = _make_descr_cmp('gt')
+    descr_ge = _make_descr_cmp('ge')
+
+    def _make_generic_descr_binop(opname, ovf=True):
+        op = getattr(operator,
+                     opname + '_' if opname in ('and', 'or') else opname)
+        commutative = opname in ('add', 'mul', 'and', 'or', 'xor')
+
+        @func_renamer('descr_' + opname)
+        def descr_binop(self, space, w_other):
+            if not isinstance(w_other, W_AbstractIntObject):
+                return space.w_NotImplemented
+
+            x = space.int_w(self)
+            y = space.int_w(w_other)
+            if ovf:
+                try:
+                    z = ovfcheck(op(x, y))
+                except OverflowError:
+                    return ovf2long(space, opname, self, w_other)
+            else:
+                z = op(x, y)
+            return wrapint(space, z)
+
+        if commutative:
+            return descr_binop, func_with_new_name(descr_binop,
+                                                   'descr_r' + opname)
+
+        @func_renamer('descr_r' + opname)
+        def descr_rbinop(self, space, w_other):
+            if not isinstance(w_other, W_AbstractIntObject):
+                return space.w_NotImplemented
+
+            x = space.int_w(self)
+            y = space.int_w(w_other)
+            if ovf:
+                try:
+                    z = ovfcheck(op(y, x))
+                except OverflowError:
+                    return ovf2long(space, opname, w_other, self)
+            else:
+                z = op(y, x)
+            return wrapint(space, z)
+
+        return descr_binop, descr_rbinop
+
+    descr_add, descr_radd = _make_generic_descr_binop('add')
+    descr_sub, descr_rsub = _make_generic_descr_binop('sub')
+    descr_mul, descr_rmul = _make_generic_descr_binop('mul')
+
+    descr_and, descr_rand = _make_generic_descr_binop('and', ovf=False)
+    descr_or, descr_ror = _make_generic_descr_binop('or', ovf=False)
+    descr_xor, descr_rxor = _make_generic_descr_binop('xor', ovf=False)
+
+    def _make_descr_binop(func):
+        opname = func.__name__[1:]
+
+        @func_renamer('descr_' + opname)
+        def descr_binop(self, space, w_other):
+            if not isinstance(w_other, W_AbstractIntObject):
+                return space.w_NotImplemented
+            try:
+                return func(self, space, w_other)
+            except OverflowError:
+                return ovf2long(space, opname, self, w_other)
+
+        @func_renamer('descr_r' + opname)
+        def descr_rbinop(self, space, w_other):
+            if not isinstance(w_other, W_AbstractIntObject):
+                return space.w_NotImplemented
+            try:
+                return func(w_other, space, self)
+            except OverflowError:
+                return ovf2long(space, opname, w_other, self)
+
+        return descr_binop, descr_rbinop
+
+    def _floordiv(self, space, w_other):
+        x = space.int_w(self)
+        y = space.int_w(w_other)
+        try:
+            z = ovfcheck(x // y)
+        except ZeroDivisionError:
+            raise operationerrfmt(space.w_ZeroDivisionError,
+                                  "integer division by zero")
+        return wrapint(space, z)
+    descr_floordiv, descr_rfloordiv = _make_descr_binop(_floordiv)
+
+    _div = func_with_new_name(_floordiv, '_div')
+    descr_div, descr_rdiv = _make_descr_binop(_div)
+
+    def _truediv(self, space, w_other):
+        x = float(space.int_w(self))
+        y = float(space.int_w(w_other))
+        if y == 0.0:
+            raise operationerrfmt(space.w_ZeroDivisionError,
+                                  "division by zero")
+        return space.wrap(x / y)
+    descr_truediv, descr_rtruediv = _make_descr_binop(_truediv)
+
+    def _mod(self, space, w_other):
+        x = space.int_w(self)
+        y = space.int_w(w_other)
+        try:
+            z = ovfcheck(x % y)
+        except ZeroDivisionError:
+            raise operationerrfmt(space.w_ZeroDivisionError,
+                                  "integer modulo by zero")
+        return wrapint(space, z)
+    descr_mod, descr_rmod = _make_descr_binop(_mod)
+
+    def _divmod(self, space, w_other):
+        x = space.int_w(self)
+        y = space.int_w(w_other)
+        try:
+            z = ovfcheck(x // y)
+        except ZeroDivisionError:
+            raise operationerrfmt(space.w_ZeroDivisionError,
+                                  "integer divmod by zero")
+        # no overflow possible
+        m = x % y
+        w = space.wrap
+        return space.newtuple([w(z), w(m)])
+    descr_divmod, descr_rdivmod = _make_descr_binop(_divmod)
+
+    def _lshift(self, space, w_other):
+        a = space.int_w(self)
+        b = space.int_w(w_other)
+        if r_uint(b) < LONG_BIT: # 0 <= b < LONG_BIT
+            c = ovfcheck(a << b)
+            return wrapint(space, c)
+        if b < 0:
+            raise operationerrfmt(space.w_ValueError, "negative shift count")
+        else: # b >= LONG_BIT
+            if a == 0:
+                return self.int(space)
+            raise OverflowError
+    descr_lshift, descr_rlshift = _make_descr_binop(_lshift)
+
+    def _rshift(self, space, w_other):
+        a = space.int_w(self)
+        b = space.int_w(w_other)
+        if r_uint(b) >= LONG_BIT: # not (0 <= b < LONG_BIT)
+            if b < 0:
+                raise operationerrfmt(space.w_ValueError,
+                                      "negative shift count")
+            # b >= LONG_BIT
+            if a == 0:
+                return self.int(space)
+            a = -1 if a < 0 else 0
+        else:
+            a = a >> b
+        return wrapint(space, a)
+    descr_rshift, descr_rrshift = _make_descr_binop(_rshift)
+
+    @unwrap_spec(w_modulus=WrappedDefault(None))
+    def descr_pow(self, space, w_exponent, w_modulus=None):
+        if not isinstance(w_exponent, W_AbstractIntObject):
+            return space.w_NotImplemented
+
+        if space.is_none(w_modulus):
+            z = 0
+        elif isinstance(w_modulus, W_AbstractIntObject):
+            z = space.int_w(w_modulus)
+            if z == 0:
+                raise operationerrfmt(space.w_ValueError,
+                                      "pow() 3rd argument cannot be 0")
+        else:
+            # can't return NotImplemented (space.pow doesn't do full
+            # ternary, i.e. w_modulus.__zpow__(self, w_exponent)), so
+            # handle it ourselves
+            return self._ovfpow2long(space, w_exponent, w_modulus)
+
+        x = space.int_w(self)
+        y = space.int_w(w_exponent)
+        try:
+            result = _pow_impl(space, x, y, z)
+        except (OverflowError, ValueError):
+            return self._ovfpow2long(space, w_exponent, w_modulus)
+        return space.wrap(result)
+
+    @unwrap_spec(w_modulus=WrappedDefault(None))
+    def descr_rpow(self, space, w_base, w_modulus=None):
+        if not isinstance(w_base, W_AbstractIntObject):
+            return space.w_NotImplemented
+        return w_base.descr_pow(space, self, w_modulus)
+
+    def _ovfpow2long(self, space, w_exponent, w_modulus):
+        if space.is_none(w_modulus) and recover_with_smalllong(space):
+            from pypy.objspace.std.smalllongobject import pow_ovr
+            return pow_ovr(space, self, w_exponent)
+        self = self.descr_long(space)
+        return self.descr_pow(space, w_exponent, w_modulus)
+
+    def descr_coerce(self, space, w_other):
+        if not isinstance(w_other, W_AbstractIntObject):
+            return space.w_NotImplemented
+        return space.newtuple([self, w_other])
+
     def descr_long(self, space):
         from pypy.objspace.std.longobject import W_LongObject
         return W_LongObject.fromint(space, self.int_w(space))
 
-    def descr_format(self, space, w_format_spec):
-        return newformat.run_formatter(space, w_format_spec,
-                                       "format_int_or_long", self,
-                                       newformat.INT_KIND)
-
     def descr_hash(self, space):
         # unlike CPython, we don't special-case the value -1 in most of
         # our hash functions, so there is not much sense special-casing
         # floats and longs.
         return self.int(space)
 
-    def descr_coerce(self, space, w_other):
-        if not space.isinstance_w(w_other, space.w_int):
-            return space.w_NotImplemented
-        return space.newtuple([self, w_other])
+    def descr_nonzero(self, space):
+        return space.newbool(space.int_w(self) != 0)
 
-    def _make_descr_binop(opname):
-        # XXX: func_renamer or func_with_new_name?
-        from rpython.tool.sourcetools import func_renamer
-        op = getattr(operator, opname)
+    def descr_invert(self, space):
+        return wrapint(space, ~space.int_w(self))
 
-        @func_renamer('descr_' + opname)
-        def descr_binop(self, space, w_other):
-            if not space.isinstance_w(w_other, space.w_int):
-                return space.w_NotImplemented
-
-            x = space.int_w(self)
-            y = space.int_w(w_other)
-            try:
-                z = ovfcheck(op(x, y))
-            except OverflowError:
-                w_long1 = _delegate_Int2Long(space, self)
-                # XXX: this needs to be _delegate_Int2Long(space,
-                # space.int(w_other)) to support bools. so maybe delegation
-                # should work against space.int_w(w_other)
-                w_long2 = _delegate_Int2Long(space, w_other)
-                return getattr(space, opname)(w_long1, w_long2)
-            return wrapint(space, z)
-
-        @func_renamer('descr_r' + opname)
-        def descr_rbinop(self, space, w_other):
-            if not space.isinstance_w(w_other, space.w_int):
-                return space.w_NotImplemented
-
-            x = space.int_w(self)
-            y = space.int_w(w_other)
-            try:
-                z = ovfcheck(op(y, x))
-            except OverflowError:
-                w_long1 = _delegate_Int2Long(space, self)
-                # XXX: this needs to be _delegate_Int2Long(space,
-                # space.int(w_other)) to support bools. so maybe delegation
-                # should work against space.int_w(w_other)
-                w_long2 = _delegate_Int2Long(space, w_other)
-                return getattr(space, opname)(w_long2, w_long1)
-            return wrapint(space, z)
-
-        return descr_binop, descr_rbinop
-
-    descr_add, descr_radd = _make_descr_binop('add')
-    descr_sub, descr_rsub = _make_descr_binop('sub')
-    descr_mul, descr_rmul = _make_descr_binop('mul')
-
-    def _make_descr_cmp(opname):
-        op = getattr(operator, opname)
-        def f(self, space, w_other):
-            # XXX: this doesn't belong here, regardless of how we originally set this up. blargh
-            #if isinstance(w_other, W_SmallLongObject):
-            #    return space.newbool(op(space.int_w(self), w_other.longlong))
-            if not space.isinstance_w(w_other, space.w_int):
-                return space.w_NotImplemented
-
-            i = space.int_w(self)
-            j = space.int_w(w_other)
-            return space.newbool(op(i, j))
-        return func_with_new_name(f, "descr_" + opname)
-
-    descr_lt = _make_descr_cmp('lt')
-    descr_le = _make_descr_cmp('le')
-    descr_eq = _make_descr_cmp('eq')
-    descr_ne = _make_descr_cmp('ne')
-    descr_gt = _make_descr_cmp('gt')
-    descr_ge = _make_descr_cmp('ge')
-
-    def descr_floordiv(self, space, w_other):
-        if not space.isinstance_w(w_other, space.w_int):
-            return space.w_NotImplemented
-
-        x = space.int_w(self)
-        y = space.int_w(w_other)
-        try:
-            z = ovfcheck(x // y)
-        except ZeroDivisionError:
-            raise operationerrfmt(space.w_ZeroDivisionError,
-                                  "integer division by zero")
-        except OverflowError:
-            w_long1 = _delegate_Int2Long(space, self)
-            w_long2 = _delegate_Int2Long(space, w_other)
-            return space.floordiv(w_long1, w_long2)
-        return wrapint(space, z)
-
-    descr_div = func_with_new_name(descr_floordiv, 'descr_div')
-
-    def descr_truediv(self, space, w_other):
-        if not space.isinstance_w(w_other, space.w_int):
-            return space.w_NotImplemented
-
-        x = float(space.int_w(self))
-        y = float(space.int_w(w_other))
-        if y == 0.0:
-            raise operationerrfmt(space.w_ZeroDivisionError,
-                                  "division by zero")
-        return space.wrap(x / y)
-
-    def descr_mod(self, space, w_other):
-        if not space.isinstance_w(w_other, space.w_int):
-            return space.w_NotImplemented
-
-        x = space.int_w(self)
-        y = space.int_w(w_other)
-        try:
-            z = ovfcheck(x % y)
-        except ZeroDivisionError:
-            raise operationerrfmt(space.w_ZeroDivisionError,
-                                  "integer modulo by zero")
-        except OverflowError:
-            w_long1 = _delegate_Int2Long(space, self)
-            w_long2 = _delegate_Int2Long(space, w_other)
-            return space.mod(w_long1, w_long2)
-        return wrapint(space, z)
-
-    def descr_divmod(self, space, w_other):
-        if not space.isinstance_w(w_other, space.w_int):
-            return space.w_NotImplemented
-
-        x = space.int_w(self)
-        y = space.int_w(w_other)
-        try:
-            z = ovfcheck(x // y)
-        except ZeroDivisionError:
-            raise operationerrfmt(space.w_ZeroDivisionError,
-                                  "integer divmod by zero")
-        except OverflowError:
-            w_long1 = _delegate_Int2Long(space, self)
-            w_long2 = _delegate_Int2Long(space, w_other)
-            return space.divmod(w_long1, w_long2)
-
-        # no overflow possible
-        m = x % y
-        w = space.wrap
-        return space.newtuple([w(z), w(m)])
-
-    @unwrap_spec(w_modulus=WrappedDefault(None))
-    def descr_pow(self, space, w_exponent, w_modulus=None):
-        if not space.isinstance_w(w_exponent, space.w_int):
-            return space.w_NotImplemented
-        if space.is_none(w_modulus):
-            z = 0
-        elif space.isinstance_w(w_modulus, space.w_int):
-            # XXX: handle long... overflow?
-            z = space.int_w(w_modulus)
-            if z == 0:
-                raise operationerrfmt(space.w_ValueError,
-                                      "pow() 3rd argument cannot be 0")
-        else:
-            return self._delegate2longpow(space, w_exponent, w_modulus)
-            #return space.w_NotImplemented
-
-        x = space.int_w(self)
-        y = space.int_w(w_exponent)
-        try:
-            return space.wrap(_pow_impl(space, x, y, z))
-        except ValueError:
-            return self._delegate2longpow(space, w_exponent, w_modulus)
-
-    def _delegate2longpow(self, space, w_exponent, w_modulus):
-        # XXX: gross
-        w_long1 = _delegate_Int2Long(space, self)
-        w_exponent = _delegate_Int2Long(space, w_exponent)
-        if not space.is_none(w_modulus):
-            w_modulus = _delegate_Int2Long(space, w_modulus)
-        return space.pow(w_long1, w_exponent, w_modulus)
-
-    @unwrap_spec(w_modulus=WrappedDefault(None))
-    def descr_rpow(self, space, w_base, w_modulus=None):
-        if not space.isinstance_w(w_base, space.w_int):
-            return space.w_NotImplemented
-        # XXX: this seems like trouble?  very likely trouble with int
-        # subclasses implementing __pow__
-        return space.pow(w_base, self, w_modulus)
+    def descr_pos(self, space):
+        return self.int(space)
+    descr_trunc = func_with_new_name(descr_pos, 'descr_trunc')
 
     def descr_neg(self, space):
         a = space.int_w(self)
         try:
             x = ovfcheck(-a)
         except OverflowError:
-            w_long1 = _delegate_Int2Long(space, self)
-            return space.neg(w_long1)
+            if recover_with_smalllong(space):
+                from pypy.objspace.std.smalllongobject import neg_ovr
+                return neg_ovr(space, self)
+            return self.descr_long(space).descr_neg(space)
         return wrapint(space, x)
 
     def descr_abs(self, space):
-        return self.int(space) if space.int_w(self) >= 0 else self.descr_neg(space)
-
-    def descr_nonzero(self, space):
-        return space.newbool(space.int_w(self) != 0)
-
-    def descr_invert(self, space):
-        return wrapint(space, ~space.int_w(self))
-
-    def descr_lshift(self, space, w_other):
-        if not space.isinstance_w(w_other, space.w_int):
-            return space.w_NotImplemented
-
-        a = space.int_w(self)
-        b = space.int_w(w_other)
-        if r_uint(b) < LONG_BIT: # 0 <= b < LONG_BIT
-            try:
-                c = ovfcheck(a << b)
-            except OverflowError:
-                w_long1 = _delegate_Int2Long(space, self)
-                w_long2 = _delegate_Int2Long(space, w_other)
-                return space.lshift(w_long1, w_long2)
-            return wrapint(space, c)
-        if b < 0:
-            raise operationerrfmt(space.w_ValueError, "negative shift count")
-        else: # b >= LONG_BIT
-            if a == 0:
-                return self.int(space)
-            w_long1 = _delegate_Int2Long(space, self)
-            w_long2 = _delegate_Int2Long(space, w_other)
-            return space.lshift(w_long1, w_long2)
-
-    def descr_rshift(self, space, w_other):
-        if not space.isinstance_w(w_other, space.w_int):
-            return space.w_NotImplemented
-
-        a = space.int_w(self)
-        b = space.int_w(w_other)
-        if r_uint(b) >= LONG_BIT: # not (0 <= b < LONG_BIT)
-            if b < 0:
-                raise operationerrfmt(space.w_ValueError,
-                                      "negative shift count")
-            else: # b >= LONG_BIT
-                if a == 0:
-                    return self.int(space)
-                if a < 0:
-                    a = -1
-                else:
-                    a = 0
-        else:
-            a = a >> b
-        return wrapint(space, a)
-
-    def descr_and(self, space, w_other):
-        if not space.isinstance_w(w_other, space.w_int):
-            return space.w_NotImplemented
-
-        a = space.int_w(self)
-        b = space.int_w(w_other)
-        res = a & b
-        return wrapint(space, res)
-
-    def descr_or(self, space, w_other):
-        if not space.isinstance_w(w_other, space.w_int):
-            return space.w_NotImplemented
-
-        a = space.int_w(self)
-        b = space.int_w(w_other)
-        res = a | b
-        return wrapint(space, res)
-
-    def descr_xor(self, space, w_other):
-        if not space.isinstance_w(w_other, space.w_int):
-            return space.w_NotImplemented
-
-        a = space.int_w(self)
-        b = space.int_w(w_other)
-        res = a ^ b
-        return wrapint(space, res)
-
-    descr_rand = func_with_new_name(descr_and, 'descr_rand')
-    descr_ror = func_with_new_name(descr_or, 'descr_ror')
-    descr_rxor = func_with_new_name(descr_xor, 'descr_rxor')
-
-    def descr_pos(self, space):
-        return self.int(space)
-
-    descr_trunc = func_with_new_name(descr_pos, 'descr_trunc')
+        pos = space.int_w(self) >= 0
+        return self.int(space) if pos else self.descr_neg(space)
 
     def descr_index(self, space):
         return self.int(space)
     def descr_getnewargs(self, space):
         return space.newtuple([wrapint(space, space.int_w(self))])
 
-    def descr_repr(self, space):
-        res = str(self.int_w(space))
-        return space.wrap(res)
-    descr_str = func_with_new_name(descr_repr, 'descr_str')
-
     def descr_conjugate(self, space):
-        "Returns self, the complex conjugate of any int."
+        """Returns self, the complex conjugate of any int."""
         return space.int(self)
 
     def descr_bit_length(self, space):
             val >>= 1
         return space.wrap(bits)
 
-    def descr_get_numerator(self, space):
-        return space.int(self)
-    descr_get_real = func_with_new_name(descr_get_numerator, 'descr_get_real')
+    def descr_repr(self, space):
+        res = str(self.int_w(space))
+        return space.wrap(res)
+    descr_str = descr_repr
+
+    def descr_format(self, space, w_format_spec):
+        return newformat.run_formatter(space, w_format_spec,
+                                       "format_int_or_long", self,
+                                       newformat.INT_KIND)
 
     def descr_get_denominator(self, space):
         return space.wrap(1)
     def descr_get_imag(self, space):
         return space.wrap(0)
 
+    descr_get_numerator = descr_get_real = descr_conjugate
+
 
 class W_IntObject(W_AbstractIntObject):
+
     __slots__ = 'intval'
     _immutable_fields_ = ['intval']
 
         return "%s(%d)" % (self.__class__.__name__, self.intval)
 
     def is_w(self, space, w_other):
-        if not isinstance(w_other, W_AbstractIntObject):
+        if not isinstance(w_other, W_IntObject):
             return False
         if self.user_overridden_class or w_other.user_overridden_class:
             return self is w_other
     def uint_w(self, space):
         intval = self.intval
         if intval < 0:
-            raise OperationError(
-                space.w_ValueError,
-                space.wrap("cannot convert negative integer to unsigned"))
-        else:
-            return r_uint(intval)
+            raise operationerrfmt(space.w_ValueError,
+                                  "cannot convert negative integer to "
+                                  "unsigned")
+        return r_uint(intval)
 
     def bigint_w(self, space):
         return rbigint.fromint(self.intval)
     def int(self, space):
         if (type(self) is not W_IntObject and
             space.is_overloaded(self, space.w_int, '__int__')):
-            return W_Object.int(self, space)
+            return W_Root.int(self, space)
         if space.is_w(space.type(self), space.w_int):
             return self
         a = self.intval
         return space.newint(a)
 
-def _delegate_Int2Long(space, w_intobj):
-    from pypy.objspace.std.longobject import W_LongObject
-    return W_LongObject.fromint(space, w_intobj.int_w(space))
+
+def recover_with_smalllong(space):
+    # True if there is a chance that a SmallLong would fit when an Int
+    # does not
+    return (space.config.objspace.std.withsmalllong and
+            sys.maxint == 2147483647)
+
+
+@specialize.arg(1)
+def ovf2long(space, opname, self, w_other):
+    if recover_with_smalllong(space) and opname != 'truediv':
+        from pypy.objspace.std import smalllongobject
+        op = getattr(smalllongobject, opname + '_ovr')
+        return op(space, self, w_other)
+    self = self.descr_long(space)
+    w_other = w_other.descr_long(space)
+    return getattr(self, 'descr_' + opname)(space, w_other)
 
 
 # helper for pow()
 def _pow_impl(space, iv, iw, iz):
     if iw < 0:
         if iz != 0:
-            msg = ("pow() 2nd argument cannot be negative when 3rd argument "
-                   "specified")
-            raise operationerrfmt(space.w_TypeError, msg)
-        ## bounce it, since it always returns float
+            raise operationerrfmt(space.w_TypeError,
+                                  "pow() 2nd argument cannot be negative when "
+                                  "3rd argument specified")
+        # bounce it, since it always returns float
         raise ValueError
     temp = iv
     ix = 1
-    try:
-        while iw > 0:
-            if iw & 1:
-                ix = ovfcheck(ix*temp)
-            iw >>= 1   #/* Shift exponent down by 1 bit */
-            if iw==0:
-                break
-            temp = ovfcheck(temp*temp) #/* Square the value of temp */
-            if iz:
-                #/* If we did a multiplication, perform a modulo */
-                ix = ix % iz;
-                temp = temp % iz;
+    while iw > 0:
+        if iw & 1:
+            ix = ovfcheck(ix * temp)
+        iw >>= 1   # Shift exponent down by 1 bit
+        if iw == 0:
+            break
+        temp = ovfcheck(temp * temp) # Square the value of temp
         if iz:
-            ix = ix % iz
-    except OverflowError:
-        raise ValueError
+            # If we did a multiplication, perform a modulo
+            ix %= iz
+            temp %= iz
+    if iz:
+        ix %= iz
     return ix
 
 # ____________________________________________________________
 
 def wrapint(space, x):
-    if space.config.objspace.std.withprebuiltint:
-        lower = space.config.objspace.std.prebuiltintfrom
-        upper =  space.config.objspace.std.prebuiltintto
-        # use r_uint to perform a single comparison (this whole function
-        # is getting inlined into every caller so keeping the branching
-        # to a minimum is a good idea)
-        index = r_uint(x - lower)
-        if index >= r_uint(upper - lower):
-            w_res = instantiate(W_IntObject)
-        else:
-            w_res = W_IntObject.PREBUILT[index]
-        # obscure hack to help the CPU cache: we store 'x' even into
-        # a prebuilt integer's intval.  This makes sure that the intval
-        # field is present in the cache in the common case where it is
-        # quickly reused.  (we could use a prefetch hint if we had that)
-        w_res.intval = x
-        return w_res
+    if not space.config.objspace.std.withprebuiltint:
+        return W_IntObject(x)
+    lower = space.config.objspace.std.prebuiltintfrom
+    upper = space.config.objspace.std.prebuiltintto
+    # use r_uint to perform a single comparison (this whole function is
+    # getting inlined into every caller so keeping the branching to a
+    # minimum is a good idea)
+    index = r_uint(x - lower)
+    if index >= r_uint(upper - lower):
+        w_res = instantiate(W_IntObject)
     else:
-        return W_IntObject(x)
+        w_res = W_IntObject.PREBUILT[index]
+    # obscure hack to help the CPU cache: we store 'x' even into a
+    # prebuilt integer's intval.  This makes sure that the intval field
+    # is present in the cache in the common case where it is quickly
+    # reused.  (we could use a prefetch hint if we had that)
+    w_res.intval = x
+    return w_res
 
 # ____________________________________________________________
 
     value = 0
     try:
         value = string_to_int(string, base)
-    except ParseStringError, e:
-        raise OperationError(space.w_ValueError,
-                             space.wrap(e.msg))
-    except ParseStringOverflowError, e:
+    except ParseStringError as e:
+        raise OperationError(space.w_ValueError, space.wrap(e.msg))
+    except ParseStringOverflowError as e:
         w_longval = retry_to_w_long(space, e.parser)
     return value, w_longval
 
     parser.rewind()
     try:
         bigint = rbigint._from_numberstring_parser(parser)
-    except ParseStringError, e:
-        raise OperationError(space.w_ValueError,
-                             space.wrap(e.msg))
+    except ParseStringError as e:
+        raise OperationError(space.w_ValueError, space.wrap(e.msg))
     return space.newlong_from_rbigint(bigint)
 
 @unwrap_spec(w_x=WrappedDefault(0))
             # an overflowing long
             value = space.int_w(w_obj)
         elif space.isinstance_w(w_value, space.w_str):
-            value, w_longval = string_to_int_or_long(space, space.str_w(w_value))
+            value, w_longval = string_to_int_or_long(space,
+                                                     space.str_w(w_value))
         elif space.isinstance_w(w_value, space.w_unicode):
             from pypy.objspace.std.unicodeobject import unicode_to_decimal_w
             string = unicode_to_decimal_w(space, w_value)
             # If object supports the buffer interface
             try:
                 w_buffer = space.buffer(w_value)
-            except OperationError, e:
+            except OperationError as e:
                 if not e.match(space, space.w_TypeError):
                     raise
                 raise operationerrfmt(space.w_TypeError,
         else:
             try:
                 s = space.str_w(w_value)
-            except OperationError, e:
-                raise OperationError(space.w_TypeError,
-                                     space.wrap("int() can't convert non-string "
-                                                "with explicit base"))
+            except OperationError as e:
+                raise operationerrfmt(space.w_TypeError,
+                                      "int() can't convert non-string with "
+                                      "explicit base")
 
         value, w_longval = string_to_int_or_long(space, s, base)
 
     if w_longval is not None:
         if not space.is_w(w_inttype, space.w_int):
-            raise OperationError(space.w_OverflowError,
-                                 space.wrap(
-                "long int too large to convert to int"))
+            raise operationerrfmt(space.w_OverflowError,
+                                  "long int too large to convert to int")
         return w_longval
     elif space.is_w(w_inttype, space.w_int):
         # common case
 
 
 W_AbstractIntObject.typedef = StdTypeDef("int",
-    __doc__ = '''int(x[, base]) -> integer
+    __doc__ = """int(x[, base]) -> integer
 
 Convert a string or number to an integer, if possible.  A floating point
 argument will be truncated towards zero (this does not include a string
 representation of a floating point number!)  When converting a string, use
 the optional base.  It is an error to supply a base when converting a
 non-string. If the argument is outside the integer range a long object
-will be returned instead.''',
+will be returned instead.""",
     __new__ = interp2app(descr__new__),
 
     numerator = typedef.GetSetProperty(
     __gt__ = interpindirect2app(W_AbstractIntObject.descr_gt),
     __ge__ = interpindirect2app(W_AbstractIntObject.descr_ge),
 
-    # XXX: rtruediv
     __floordiv__ = interpindirect2app(W_AbstractIntObject.descr_floordiv),
+    __rfloordiv__ = interpindirect2app(W_AbstractIntObject.descr_rfloordiv),
     __div__ = interpindirect2app(W_AbstractIntObject.descr_div),
+    __rdiv__ = interpindirect2app(W_AbstractIntObject.descr_rdiv),
     __truediv__ = interpindirect2app(W_AbstractIntObject.descr_truediv),
+    __rtruediv__ = interpindirect2app(W_AbstractIntObject.descr_rtruediv),
     __mod__ = interpindirect2app(W_AbstractIntObject.descr_mod),
+    __rmod__ = interpindirect2app(W_AbstractIntObject.descr_rmod),
     __divmod__ = interpindirect2app(W_AbstractIntObject.descr_divmod),
+    __rdivmod__ = interpindirect2app(W_AbstractIntObject.descr_rdivmod),
+
+    __lshift__ = interpindirect2app(W_AbstractIntObject.descr_lshift),
+    __rlshift__ = interpindirect2app(W_AbstractIntObject.descr_rlshift),
+    __rshift__ = interpindirect2app(W_AbstractIntObject.descr_rshift),
+    __rrshift__ = interpindirect2app(W_AbstractIntObject.descr_rrshift),
 
     __pow__ = interpindirect2app(W_AbstractIntObject.descr_pow),
     __rpow__ = interpindirect2app(W_AbstractIntObject.descr_rpow),
     __abs__ = interpindirect2app(W_AbstractIntObject.descr_abs),
     __nonzero__ = interpindirect2app(W_AbstractIntObject.descr_nonzero),
     __invert__ = interpindirect2app(W_AbstractIntObject.descr_invert),
-    __lshift__ = interpindirect2app(W_AbstractIntObject.descr_lshift),
-    __rshift__ = interpindirect2app(W_AbstractIntObject.descr_rshift),
     __and__ = interpindirect2app(W_AbstractIntObject.descr_and),
     __rand__ = interpindirect2app(W_AbstractIntObject.descr_rand),
     __xor__ = interpindirect2app(W_AbstractIntObject.descr_xor),
     __rxor__ = interpindirect2app(W_AbstractIntObject.descr_rxor),
     __or__ = interpindirect2app(W_AbstractIntObject.descr_or),
     __ror__ = interpindirect2app(W_AbstractIntObject.descr_ror),
+
     __pos__ = interpindirect2app(W_AbstractIntObject.descr_pos),
     __trunc__ = interpindirect2app(W_AbstractIntObject.descr_trunc),
     __index__ = interpindirect2app(W_AbstractIntObject.descr_index),

pypy/objspace/std/longobject.py

 """The builtin long implementation"""
 
-import sys
+import functools
 
 from rpython.rlib.rbigint import rbigint
 from rpython.rlib.rstring import ParseStringError
 from rpython.tool.sourcetools import func_renamer, func_with_new_name
 
 from pypy.interpreter import typedef
+from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.buffer import Buffer
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.gateway import (
     WrappedDefault, interp2app, interpindirect2app, unwrap_spec)
-from pypy.objspace.std import model, newformat
-from pypy.objspace.std.intobject import W_IntObject
-from pypy.objspace.std.model import W_Object
-from pypy.objspace.std.noneobject import W_NoneObject
+from pypy.objspace.std import newformat
+from pypy.objspace.std.intobject import W_AbstractIntObject
 from pypy.objspace.std.stdtypedef import StdTypeDef
 
 
 def delegate_other(func):
-    @func_renamer(func.__name__)
+    @functools.wraps(func)
     def delegated(self, space, w_other):
-        if space.isinstance_w(w_other, space.w_int):
-            w_other = _delegate_Int2Long(space, w_other)
-        elif not space.isinstance_w(w_other, space.w_long):
+        if isinstance(w_other, W_AbstractIntObject):
+            w_other = w_other.descr_long(space)
+        elif not isinstance(w_other, W_AbstractLongObject):
             return space.w_NotImplemented
-        # XXX: if a smalllong, delegate to Long?
-        assert isinstance(w_other, W_AbstractLongObject)
         return func(self, space, w_other)
     return delegated
 
-def _delegate_Int2Long(space, w_intobj):
-    """int-to-long delegation"""
-    return W_LongObject.fromint(space, w_intobj.int_w(space))
 
+class W_AbstractLongObject(W_Root):
 
-class W_AbstractLongObject(W_Object):
     __slots__ = ()
 
     def is_w(self, space, w_other):
         b = b.lshift(3).or_(rbigint.fromint(tag))
         return space.newlong_from_rbigint(b)
 
-    def unwrap(w_self, space): #YYYYYY
-        return w_self.longval()
+    def unwrap(self, space):
+        return self.longval()
 
     def int(self, space):
         raise NotImplementedError
     def asbigint(self):
         raise NotImplementedError
 
+    # XXX: cleanup, docstrings etc
     def descr_long(self, space):
         raise NotImplementedError
     descr_index = func_with_new_name(descr_long, 'descr_index')
     descr_trunc = func_with_new_name(descr_long, 'descr_trunc')
     descr_pos = func_with_new_name(descr_long, 'descr_pos')
 
-    # XXX:
-    def descr_float(self, space):
-        raise NotImplementedError
+    descr_float = func_with_new_name(descr_long, 'descr_float')
     descr_neg = func_with_new_name(descr_long, 'descr_neg')
     descr_pos = func_with_new_name(descr_long, 'descr_pos')
     descr_abs = func_with_new_name(descr_long, 'descr_abs')
     descr_rxor = func_with_new_name(descr_lt, 'descr_rxor')
 
     descr_lshift = func_with_new_name(descr_lt, 'descr_lshift')
+    descr_rlshift = func_with_new_name(descr_lt, 'descr_rlshift')
     descr_rshift = func_with_new_name(descr_lt, 'descr_rshift')
+    descr_rrshift = func_with_new_name(descr_lt, 'descr_rrshift')
 
     descr_floordiv = func_with_new_name(descr_lt, 'descr_floordiv')
     descr_rfloordiv = func_with_new_name(descr_lt, 'descr_rfloordiv')
         return newformat.run_formatter(space, w_format_spec,
                                        "format_int_or_long", self,
                                        newformat.LONG_KIND)
-    def descr_repr(self, space):
-        return space.wrap(self.asbigint().repr())
 
-    def descr_str(self, space):
-        return space.wrap(self.asbigint().str())
+    def _make_descr_unaryop(opname):
+        op = getattr(rbigint, opname)
+        @func_renamer('descr_' + opname)
+        def descr_unaryop(self, space):
+            return space.wrap(op(self.asbigint()))
+        return descr_unaryop
 
-    def descr_hash(self, space):
-        return space.wrap(self.asbigint().hash())
-
-    def descr_oct(self, space):
-        return space.wrap(self.asbigint().oct())
-
-    def descr_hex(self, space):
-        return space.wrap(self.asbigint().hex())
+    descr_repr = _make_descr_unaryop('repr')
+    descr_str = _make_descr_unaryop('str')
+    descr_hash = _make_descr_unaryop('hash')
+    descr_oct = _make_descr_unaryop('oct')
+    descr_hex = _make_descr_unaryop('hex')
 
     def descr_getnewargs(self, space):
         return space.newtuple([W_LongObject(self.asbigint())])
         try:
             return space.wrap(bigint.bit_length())
         except OverflowError:
-            raise OperationError(space.w_OverflowError,
-                                 space.wrap("too many digits in integer"))
+            raise operationerrfmt(space.w_OverflowError,
+                                  "too many digits in integer")
 
-    # XXX: need rtruediv
-    @delegate_other
-    def descr_truediv(self, space, w_other):
+    def _truediv(self, space, w_other):
         try:
-            #f = self.num.truediv(w_other.num)
             f = self.asbigint().truediv(w_other.asbigint())
         except ZeroDivisionError:
             raise operationerrfmt(space.w_ZeroDivisionError,
         return space.newfloat(f)
 
     @delegate_other
+    def descr_truediv(self, space, w_other):
+        return W_AbstractLongObject._truediv(self, space, w_other)
+
+    @delegate_other
+    def descr_rtruediv(self, space, w_other):
+        return W_AbstractLongObject._truediv(w_other, space, self)
+
+    @delegate_other
     def descr_coerce(self, space, w_other):
-        # XXX: consider stian's branch where he optimizes long + ints
         return space.newtuple([self, w_other])
 
     def descr_get_numerator(self, space):
 
 class W_LongObject(W_AbstractLongObject):
     """This is a wrapper of rbigint."""
+
     _immutable_fields_ = ['num']
 
-    def __init__(self, l):
-        self.num = l # instance of rbigint
+    def __init__(self, num):
+        self.num = num # instance of rbigint
 
     def fromint(space, intval):
         return W_LongObject(rbigint.fromint(intval))
         try:
             return self.num.toint()
         except OverflowError:
-            raise OperationError(space.w_OverflowError, space.wrap(
-                "long int too large to convert to int"))
+            raise operationerrfmt(space.w_OverflowError,
+                                  "long int too large to convert to int")
 
     def uint_w(self, space):
         try:
             return self.num.touint()
         except ValueError:
-            raise OperationError(space.w_ValueError, space.wrap(
-                "cannot convert negative integer to unsigned int"))
+            raise operationerrfmt(space.w_ValueError,
+                                  "cannot convert negative integer to "
+                                  "unsigned int")
         except OverflowError:
-            raise OperationError(space.w_OverflowError, space.wrap(
-                "long int too large to convert to unsigned int"))
+            raise operationerrfmt(space.w_OverflowError,
+                                  "long int too large to convert to unsigned "
+                                  "int")
 
     def bigint_w(self, space):
         return self.num
     def int(self, space):
         if (type(self) is not W_LongObject and
             space.is_overloaded(self, space.w_long, '__int__')):
-            return W_Object.int(self, space)
+            return W_Root.int(self, space)
         try:
             return space.newint(self.num.toint())
         except OverflowError:
         return '<W_LongObject(%d)>' % self.num.tolong()
 
     def descr_long(self, space):
-        # long__Long is supposed to do nothing, unless it has a derived
+        # __long__ is supposed to do nothing, unless it has a derived
         # long object, where it should return an exact one.
         if space.is_w(space.type(self), space.w_long):
             return self
-        l = self.num
-        return W_LongObject(l)
-    descr_index = func_with_new_name(descr_long, 'descr_index')
-    descr_trunc = func_with_new_name(descr_long, 'descr_trunc')
-    descr_pos = func_with_new_name(descr_long, 'descr_pos')
+        return W_LongObject(self.num)
+    descr_index = descr_trunc = descr_pos = descr_long
 
     def descr_float(self, space):
         return space.newfloat(self.tofloat(space))
 
     def _make_descr_cmp(opname):
-        #from pypy.objspace.std.smalllongobject import W_SmallLongObject
         op = getattr(rbigint, opname)
         @delegate_other
         def descr_impl(self, space, w_other):
-            ## XXX: these only need explicit SmallLong support whereas
-            ## everything else would delegate2Long. blah blah
-            #if isinstance(w_other, W_SmallLongObject):
-            #    result = op(self.num, w_other.asbigint())
-            #else:
-            #    result = op(self.num, w_other.num)
-            #return space.newbool(result)
-
-            # XXX: if we use self.asbigint then can this live on
-            # AbstractLong? eek not really, a '_cmp' (_lt) could live on
-            # it that just did this (without the checks..)
+            # XXX: previous impl had all kinds of shortcuts between
+            # smalllong and int/long
             return space.newbool(op(self.num, w_other.asbigint()))
         return func_with_new_name(descr_impl, "descr_" + opname)
 
     descr_gt = _make_descr_cmp('gt')
     descr_ge = _make_descr_cmp('ge')
 
-    def _make_descr_binop(opname):
-        from rpython.tool.sourcetools import func_renamer
+    def _make_generic_descr_binop(opname):
         methname = opname + '_' if opname in ('and', 'or') else opname
         op = getattr(rbigint, methname)
 
         @func_renamer('descr_r' + opname)
         @delegate_other
         def descr_rbinop(self, space, w_other):
+            # XXX: delegate, for --objspace-std-withsmalllong
             return W_LongObject(op(w_other.asbigint(), self.num))
 
         return descr_binop, descr_rbinop
 
-    descr_add, descr_radd = _make_descr_binop('add')
-    descr_sub, descr_rsub = _make_descr_binop('sub')
-    descr_mul, descr_rmul = _make_descr_binop('mul')
-    descr_and, descr_rand = _make_descr_binop('and')
-    descr_or, descr_ror = _make_descr_binop('or')
-    descr_xor, descr_rxor = _make_descr_binop('xor')
+    descr_add, descr_radd = _make_generic_descr_binop('add')
+    descr_sub, descr_rsub = _make_generic_descr_binop('sub')
+    descr_mul, descr_rmul = _make_generic_descr_binop('mul')
+    descr_and, descr_rand = _make_generic_descr_binop('and')
+    descr_or, descr_ror = _make_generic_descr_binop('or')
+    descr_xor, descr_rxor = _make_generic_descr_binop('xor')
 
     def _make_descr_unaryop(opname):
-        from rpython.tool.sourcetools import func_renamer
         op = getattr(rbigint, opname)
         @func_renamer('descr_' + opname)
         def descr_unaryop(self, space):
     def descr_nonzero(self, space):
         return space.newbool(self.num.tobool())
 
-    @delegate_other
-    def descr_lshift(self, space, w_other):
-        # XXX need to replicate some of the logic, to get the errors right
+    def _make_descr_binop(func):
+        opname = func.__name__[1:]
+
+        @delegate_other
+        @func_renamer('descr_' + opname)
+        def descr_binop(self, space, w_other):
+            return func(self, space, w_other)
+
+        @delegate_other
+        @func_renamer('descr_r' + opname)
+        def descr_rbinop(self, space, w_other):
+            if not isinstance(w_other, W_LongObject):
+                # coerce other W_AbstractLongObjects
+                w_other = W_LongObject(w_other.asbigint())
+            return func(w_other, space, self)
+
+        return descr_binop, descr_rbinop
+
+    def _lshift(self, space, w_other):
         if w_other.asbigint().sign < 0:
             raise operationerrfmt(space.w_ValueError, "negative shift count")
         try:
             raise operationerrfmt(space.w_OverflowError,
                                   "shift count too large")
         return W_LongObject(self.num.lshift(shift))
+    descr_lshift, descr_rlshift = _make_descr_binop(_lshift)
 
-    @delegate_other
-    def descr_rshift(self, space, w_other):
-        # XXX need to replicate some of the logic, to get the errors right
+    def _rshift(self, space, w_other):
         if w_other.asbigint().sign < 0:
             raise operationerrfmt(space.w_ValueError, "negative shift count")
         try:
             raise operationerrfmt(space.w_OverflowError,
                                   "shift count too large")
         return newlong(space, self.num.rshift(shift))
+    descr_rshift, descr_rrshift = _make_descr_binop(_rshift)
 
-    @delegate_other
-    def descr_floordiv(self, space, w_other):
+    def _floordiv(self, space, w_other):
         try:
             z = self.num.floordiv(w_other.asbigint())
         except ZeroDivisionError:
             raise operationerrfmt(space.w_ZeroDivisionError,
                                   "long division or modulo by zero")
         return newlong(space, z)
-    descr_div = func_with_new_name(descr_floordiv, 'descr_div')
+    descr_floordiv, descr_rfloordiv = _make_descr_binop(_floordiv)
 
-    @delegate_other
-    def descr_mod(self, space, w_other):
+    _div = func_with_new_name(_floordiv, '_div')
+    descr_div, descr_rdiv = _make_descr_binop(_div)
+
+    def _mod(self, space, w_other):
         try:
             z = self.num.mod(w_other.asbigint())
         except ZeroDivisionError:
             raise operationerrfmt(space.w_ZeroDivisionError,
                                   "long division or modulo by zero")
         return newlong(space, z)
+    descr_mod, descr_rmod = _make_descr_binop(_mod)
 
-    @delegate_other
-    def descr_divmod(self, space, w_other):
+    def _divmod(self, space, w_other):
         try:
             div, mod = self.num.divmod(w_other.asbigint())
         except ZeroDivisionError:
             raise operationerrfmt(space.w_ZeroDivisionError,
                                   "long division or modulo by zero")
         return space.newtuple([newlong(space, div), newlong(space, mod)])
+    descr_divmod, descr_rdivmod = _make_descr_binop(_divmod)
 
-    #@delegate_other # XXX:
     @unwrap_spec(w_modulus=WrappedDefault(None))
     def descr_pow(self, space, w_exponent, w_modulus=None):
-        if space.isinstance_w(w_exponent, space.w_int):
-            w_exponent = _delegate_Int2Long(space, w_exponent)
-        elif not space.isinstance_w(w_exponent, space.w_long):
+        if isinstance(w_exponent, W_AbstractIntObject):
+            w_exponent = w_exponent.descr_long(space)
+        elif not isinstance(w_exponent, W_AbstractLongObject):
             return space.w_NotImplemented
-        assert isinstance(w_exponent, W_AbstractLongObject)
 
-        #if space.is_none(w_modulus):
-        #    from pypy.objspace.std.floatobject import delegate_Long2Float
-        #    self = delegate_Long2Float(space, self)
-        #    w_exponent = delegate_Long2Float(space, w_exponent)
-        #    return space.pow(self, w_exponent, w_modulus)
-        #elif space.isinstance_w(w_modulus, space.w_int):
         if space.is_none(w_modulus):
-            # XXX need to replicate some of the logic, to get the errors right
             if w_exponent.asbigint().sign < 0:
-                from pypy.objspace.std.floatobject import delegate_Long2Float
-                w_exponent = delegate_Long2Float(space, w_exponent)
-                # XXX: hack around multimethod annoyances for now (when
-                # w_modulus=None)
-                return space.pow(self.descr_float(space), w_exponent, space.w_None if w_modulus is None else w_modulus)
-            return W_LongObject(self.num.pow(w_exponent.asbigint(), None))
-        elif space.isinstance_w(w_modulus, space.w_int):
-            w_modulus = _delegate_Int2Long(space, w_modulus)
-        #elif space.is_none(w_modulus):
-        #    # XXX need to replicate some of the logic, to get the errors right
-        #    if w_exponent.num.sign < 0:
-        #        return space.pow(self.descr_float(space), w_exponent, w_modulus)
-        #    return W_LongObject(self.num.pow(w_exponent.num, None))
-        elif not space.isinstance_w(w_modulus, space.w_long):
+                self = self.descr_float(space)
+                w_exponent = w_exponent.descr_float(space)
+                return space.pow(self, w_exponent, space.w_None)
+            return W_LongObject(self.num.pow(w_exponent.asbigint()))
+        elif isinstance(w_modulus, W_AbstractIntObject):
+            w_modulus = w_modulus.descr_long(space)
+        elif not isinstance(w_modulus, W_AbstractLongObject):
             return space.w_NotImplemented
-        assert isinstance(w_modulus, W_AbstractLongObject)
 
         if w_exponent.asbigint().sign < 0:
-            raise OperationError(
-                space.w_TypeError,
-                space.wrap(
-                    "pow() 2nd argument "
-                    "cannot be negative when 3rd argument specified"))
+            raise operationerrfmt(space.w_TypeError,
+                                  "pow() 2nd argument cannot be negative when "
+                                  "3rd argument specified")
         try:
-            return W_LongObject(self.num.pow(w_exponent.asbigint(),
-                                             w_modulus.asbigint()))
+            result = self.num.pow(w_exponent.asbigint(), w_modulus.asbigint())
         except ValueError:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap("pow 3rd argument cannot be 0"))
+            raise operationerrfmt(space.w_ValueError,
+                                  "pow 3rd argument cannot be 0")
+        return W_LongObject(result)
 
     @unwrap_spec(w_modulus=WrappedDefault(None))
-    def descr_rpow(self, space, w_exponent, w_modulus=None):
-        if space.isinstance_w(w_exponent, space.w_int):
-            w_exponent = _delegate_Int2Long(space, w_exponent)
-        elif not space.isinstance_w(w_exponent, space.w_long):
+    def descr_rpow(self, space, w_base, w_modulus=None):
+        if isinstance(w_base, W_AbstractIntObject):
+            w_base = w_base.descr_long(space)
+        elif not isinstance(w_base, W_AbstractLongObject):
             return space.w_NotImplemented
-        ### XXX: these may needs all the checks above has. annoying
-        #if not space.isinstance_w(w_exponent, space.w_long):
-        #    return space.w_NotImplemented
-        # XXX:
-        return space.pow(w_exponent, self, w_modulus)
-
-    def descr_getnewargs(self, space):
-        return space.newtuple([W_LongObject(self.num)])
+        return w_base.descr_pow(space, self, w_modulus)
 
 
 def newlong(space, bigint):
-    """Turn the bigint into a W_LongObject.  If withsmalllong is enabled,
-    check if the bigint would fit in a smalllong, and return a
+    """Turn the bigint into a W_LongObject.  If withsmalllong is
+    enabled, check if the bigint would fit in a smalllong, and return a
     W_SmallLongObject instead if it does.
     """
     if space.config.objspace.std.withsmalllong:
     return W_LongObject(bigint)
 
 
-# register implementations of ops that recover int op overflows
-def recover_with_smalllong(space):
-    # True if there is a chance that a SmallLong would fit when an Int does not
-    return (space.config.objspace.std.withsmalllong and
-            sys.maxint == 2147483647)
-
-# XXX:
-# binary ops
-for opname in ['add', 'sub', 'mul', 'div', 'floordiv', 'truediv', 'mod',
-               'divmod', 'lshift']:
-    exec compile("""
-def %(opname)s_ovr__Int_Int(space, w_int1, w_int2):
-    if recover_with_smalllong(space) and %(opname)r != 'truediv':
-        from pypy.objspace.std.smalllongobject import %(opname)s_ovr
-        return %(opname)s_ovr(space, w_int1, w_int2)
-    w_long1 = _delegate_Int2Long(space, w_int1)
-    w_long2 = _delegate_Int2Long(space, w_int2)
-    #return %(opname)s__Long_Long(space, w_long1, w_long2)
-    return w_long1.descr_%(opname)s(space, w_long2)
-""" % {'opname': opname}, '', 'exec')
-
-    getattr(model.MM, opname).register(globals()['%s_ovr__Int_Int' % opname],
-                                       W_IntObject, W_IntObject, order=1)
-
-# unary ops
-for opname in ['neg', 'abs']:
-    exec """
-def %(opname)s_ovr__Int(space, w_int1):
-    if recover_with_smalllong(space):
-        from pypy.objspace.std.smalllongobject import %(opname)s_ovr
-        return %(opname)s_ovr(space, w_int1)
-    w_long1 = _delegate_Int2Long(space, w_int1)
-    #return %(opname)s__Long(space, w_long1)
-    return w_long1.descr_%(opname)s(space)
-""" % {'opname': opname}
-
-    getattr(model.MM, opname).register(globals()['%s_ovr__Int' % opname],
-                                       W_IntObject, order=1)
-
-# pow
-def pow_ovr__Int_Int_None(space, w_int1, w_int2, w_none3):
-    if recover_with_smalllong(space):
-        from pypy.objspace.std.smalllongobject import pow_ovr
-        return pow_ovr(space, w_int1, w_int2)
-    w_long1 = _delegate_Int2Long(space, w_int1)
-    w_long2 = _delegate_Int2Long(space, w_int2)
-    #return pow__Long_Long_None(space, w_long1, w_long2, w_none3)
-    return w_long1.descr_pow(space, w_long2, w_none3)
-
-def pow_ovr__Int_Int_Long(space, w_int1, w_int2, w_long3):
-    w_long1 = _delegate_Int2Long(space, w_int1)
-    w_long2 = _delegate_Int2Long(space, w_int2)
-    #return pow__Long_Long_Long(space, w_long1, w_long2, w_long3)
-    return w_long1.descr_pow(space, w_long2, w_long3)
-
-model.MM.pow.register(pow_ovr__Int_Int_None, W_IntObject, W_IntObject,
-                      W_NoneObject, order=1)
-model.MM.pow.register(pow_ovr__Int_Int_Long, W_IntObject, W_IntObject,
-                      W_LongObject, order=1)
-
-
 @unwrap_spec(w_x=WrappedDefault(0))
 def descr__new__(space, w_longtype, w_x, w_base=None):
     if space.config.objspace.std.withsmalllong:
             try:
                 s = space.str_w(w_value)
             except OperationError:
-                msg = "long() can't convert non-string with explicit base"
-                raise operationerrfmt(space.w_TypeError, msg)
+                raise operationerrfmt(space.w_TypeError,
+                                      "long() can't convert non-string with "
+                                      "explicit base")
         return string_to_w_long(space, w_longtype, s, base)
 
 
     conjugate = interp2app(W_AbstractLongObject.descr_conjugate),
     bit_length = interp2app(W_AbstractLongObject.descr_bit_length),
 
-    # XXX: likely need indirect everything for SmallLong
     __int__ = interpindirect2app(W_AbstractLongObject.int),
     __long__ = interpindirect2app(W_AbstractLongObject.descr_long),
     __index__ = interpindirect2app(W_AbstractLongObject.descr_index),
     __hex__ = interp2app(W_AbstractLongObject.descr_hex),
 
     __lshift__ = interpindirect2app(W_AbstractLongObject.descr_lshift),
+    __rlshift__ = interpindirect2app(W_AbstractLongObject.descr_rlshift),
     __rshift__ = interpindirect2app(W_AbstractLongObject.descr_rshift),
+    __rrshift__ = interpindirect2app(W_AbstractLongObject.descr_rrshift),
 
-    # XXX: all these need r sides
     __truediv__ = interp2app(W_AbstractLongObject.descr_truediv),
+    __rtruediv__ = interp2app(W_AbstractLongObject.descr_rtruediv),
     __floordiv__ = interpindirect2app(W_AbstractLongObject.descr_floordiv),
+    __rfloordiv__ = interpindirect2app(W_AbstractLongObject.descr_rfloordiv),
     __div__ = interpindirect2app(W_AbstractLongObject.descr_div),
+    __rdiv__ = interpindirect2app(W_AbstractLongObject.descr_rdiv),
     __mod__ = interpindirect2app(W_AbstractLongObject.descr_mod),
+    __rmod__ = interpindirect2app(W_AbstractLongObject.descr_rmod),
     __divmod__ = interpindirect2app(W_AbstractLongObject.descr_divmod),
+    __rdivmod__ = interpindirect2app(W_AbstractLongObject.descr_rdivmod),
 
     __pow__ = interpindirect2app(W_AbstractLongObject.descr_pow),
     __rpow__ = interpindirect2app(W_AbstractLongObject.descr_rpow),

pypy/objspace/std/marshal_impl.py

 from pypy.objspace.std.stringobject  import W_StringObject
 from pypy.objspace.std.typeobject    import W_TypeObject
 from pypy.objspace.std.longobject    import W_LongObject, newlong
+from pypy.objspace.std.smalllongobject    import W_SmallLongObject
 from pypy.objspace.std.noneobject    import W_NoneObject
 from pypy.objspace.std.unicodeobject import W_UnicodeObject
 
     m.start(TYPE_LONG)
     SHIFT = 15
     MASK = (1 << SHIFT) - 1
-    num = w_long.num
+    num = w_long.asbigint()
     sign = num.sign
     num = num.abs()
     total_length = (num.bit_length() + (SHIFT - 1)) / SHIFT
         next = num.abs_rshift_and_mask(bigshiftcount, MASK)
         m.put_short(next)
         bigshiftcount += SHIFT
+marshal_w__SmallLong = marshal_w__Long
 
 def unmarshal_Long(space, u, tc):
     from rpython.rlib.rbigint import rbigint

pypy/objspace/std/model.py

             from pypy.objspace.std.bytearraytype import bytearray_typedef
             from pypy.objspace.std.typeobject   import type_typedef
             from pypy.objspace.std.slicetype  import slice_typedef
-            #from pypy.objspace.std.longtype   import long_typedef
             from pypy.objspace.std.unicodetype import unicode_typedef
             from pypy.objspace.std.nonetype import none_typedef
         self.pythontypes = [value for key, value in result.__dict__.items()
         # the set of implementation types
         self.typeorder = {
             objectobject.W_ObjectObject: [],
+            # XXX: Bool/Int/Long are pythontypes but still included here
+            # for delegation to Float/Complex
             boolobject.W_BoolObject: [],
-            intobject.W_IntObject: [], # XXX: (And self.typeorder[intobject] below)
+            intobject.W_IntObject: [],
             floatobject.W_FloatObject: [],
             stringobject.W_StringObject: [],
             bytearrayobject.W_BytearrayObject: [],
             if option.startswith("with") and option in option_to_typename:
                 for classname in option_to_typename[option]:
                     modname = classname[:classname.index('.')]
-                    if modname == 'smalllongobject': continue # XXX:
                     classname = classname[classname.index('.')+1:]
                     d = {}
                     exec "from pypy.objspace.std.%s import %s" % (
         # XXX build these lists a bit more automatically later
 
         self.typeorder[boolobject.W_BoolObject] += [
-#            (intobject.W_IntObject,     boolobject.delegate_Bool2IntObject),
             (floatobject.W_FloatObject, floatobject.delegate_Bool2Float),
-#            (longobject.W_LongObject,   longobject.delegate_Bool2Long),
             (complexobject.W_ComplexObject, complexobject.delegate_Bool2Complex),
             ]
         self.typeorder[intobject.W_IntObject] += [
             (floatobject.W_FloatObject, floatobject.delegate_Int2Float),
-#            (longobject.W_LongObject,   longobject.delegate_Int2Long),
             (complexobject.W_ComplexObject, complexobject.delegate_Int2Complex),
             ]
-        if False and config.objspace.std.withsmalllong:
+        if config.objspace.std.withsmalllong:
             from pypy.objspace.std import smalllongobject
-            self.typeorder[boolobject.W_BoolObject] += [
-                (smalllongobject.W_SmallLongObject, smalllongobject.delegate_Bool2SmallLong),
-                ]
-            self.typeorder[intobject.W_IntObject] += [
-                (smalllongobject.W_SmallLongObject, smalllongobject.delegate_Int2SmallLong),
-                ]
             self.typeorder[smalllongobject.W_SmallLongObject] += [
-                (longobject.W_LongObject, smalllongobject.delegate_SmallLong2Long),
                 (floatobject.W_FloatObject, smalllongobject.delegate_SmallLong2Float),
                 (complexobject.W_ComplexObject, smalllongobject.delegate_SmallLong2Complex),
                 ]

pypy/objspace/std/smalllongobject.py

 
 from rpython.rlib.rarithmetic import LONGLONG_BIT, intmask, r_longlong, r_uint
 from rpython.rlib.rbigint import rbigint
-from rpython.tool.sourcetools import func_with_new_name
+from rpython.tool.sourcetools import func_renamer, func_with_new_name
 
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.error import operationerrfmt
 from pypy.interpreter.gateway import WrappedDefault, unwrap_spec
-from pypy.objspace.std.multimethod import FailedToImplementArgs
+from pypy.objspace.std.intobject import W_AbstractIntObject
 from pypy.objspace.std.longobject import W_AbstractLongObject, W_LongObject
-from pypy.objspace.std.intobject import _delegate_Int2Long
 
-LONGLONG_MIN = r_longlong((-1) << (LONGLONG_BIT-1))
+LONGLONG_MIN = r_longlong(-1 << (LONGLONG_BIT - 1))
 
 
 class W_SmallLongObject(W_AbstractLongObject):
         b = intmask(a)
         if b == a:
             return b
-        else:
-            raise OperationError(space.w_OverflowError, space.wrap(
-                "long int too large to convert to int"))
+        raise operationerrfmt(space.w_OverflowError,
+                              "long int too large to convert to int")
 
     def uint_w(self, space):
         a = self.longlong
         if a < 0:
-            raise OperationError(space.w_ValueError, space.wrap(
-                "cannot convert negative integer to unsigned int"))
+            raise operationerrfmt(space.w_ValueError,
+                                  "cannot convert negative integer to "
+                                  "unsigned int")
         b = r_uint(a)
         if r_longlong(b) == a:
             return b
-        else:
-            raise OperationError(space.w_OverflowError, space.wrap(
-                "long int too large to convert to unsigned int"))
+        raise operationerrfmt(space.w_OverflowError,
+                              "long int too large to convert to unsigned int")
 
     def bigint_w(self, space):
         return self.asbigint()
     def int(self, space):
         a = self.longlong
         b = intmask(a)
-        if b == a:
-            return space.newint(b)
-        else:
-            return self
+        return space.newint(b) if b == a else self
 
     def descr_long(self, space):
-        # XXX: do subclasses never apply here?
-        return self
-    descr_index = func_with_new_name(descr_long, 'descr_index')
-    descr_trunc = func_with_new_name(descr_long, 'descr_trunc')
-    descr_pos = func_with_new_name(descr_long, 'descr_pos')
-
-    def descr_index(self, space):
-        return self
+        if space.is_w(space.type(self), space.w_long):
+            return self
+        return W_SmallLongObject(self.longlong)
+    descr_index = descr_trunc = descr_pos = descr_long
 
     def descr_float(self, space):
         return space.newfloat(float(self.longlong))
 
     def _make_descr_cmp(opname):
         op = getattr(operator, opname)
-        def descr_impl(self, space, w_other):
-            if space.isinstance_w(w_other, space.w_int):
+        bigint_op = getattr(rbigint, opname)
+        @func_renamer('descr_' + opname)
+        def descr_cmp(self, space, w_other):
+            if isinstance(w_other, W_AbstractIntObject):
                 result = op(self.longlong, w_other.int_w(space))
-            elif not space.isinstance_w(w_other, space.w_long):
+            elif not isinstance(w_other, W_AbstractLongObject):
                 return space.w_NotImplemented
             elif isinstance(w_other, W_SmallLongObject):
                 result = op(self.longlong, w_other.longlong)
             else:
-                result = getattr(self.asbigint(), opname)(w_other.num)
+                result = bigint_op(self.asbigint(), w_other.asbigint())
             return space.newbool(result)
-        return func_with_new_name(descr_impl, "descr_" + opname)
+        return descr_cmp
 
     descr_lt = _make_descr_cmp('lt')
     descr_le = _make_descr_cmp('le')
     descr_ge = _make_descr_cmp('ge')
 
     def _make_descr_binop(func):
-        # XXX: so if w_other is Long, what do we do? sigh
-        # how to handle delegation with descr_add on longobject?
         opname = func.__name__[1:]
-        methname = opname + '_' if opname in ('and', 'or') else opname
+        descr_name = 'descr_' + opname
+        descr_rname = 'descr_r' + opname
 
-        def descr_impl(self, space, w_other):
-            if space.isinstance_w(w_other, space.w_int):
+        @func_renamer(descr_name)
+        def descr_binop(self, space, w_other):
+            if isinstance(w_other, W_AbstractIntObject):
                 w_other = delegate_Int2SmallLong(space, w_other)
-            elif not space.isinstance_w(w_other, space.w_long):
+            elif not isinstance(w_other, W_AbstractLongObject):
                 return space.w_NotImplemented
             elif not isinstance(w_other, W_SmallLongObject):
                 self = delegate_SmallLong2Long(space, self)
-                return getattr(space, methname)(self, w_other)
+                return getattr(self, descr_name)(space, w_other)
 
             try:
                 return func(self, space, w_other)
             except OverflowError:
                 self = delegate_SmallLong2Long(space, self)
                 w_other = delegate_SmallLong2Long(space, w_other)
-                return getattr(space, methname)(self, w_other)
+                return getattr(self, descr_name)(space, w_other)
 
-        def descr_rimpl(self, space, w_other):
-            if space.isinstance_w(w_other, space.w_int):
+        @func_renamer(descr_rname)
+        def descr_rbinop(self, space, w_other):
+            if isinstance(w_other, W_AbstractIntObject):
                 w_other = delegate_Int2SmallLong(space, w_other)
-            elif not space.isinstance_w(w_other, space.w_long):
+            elif not isinstance(w_other, W_AbstractLongObject):
                 return space.w_NotImplemented
             elif not isinstance(w_other, W_SmallLongObject):
                 self = delegate_SmallLong2Long(space, self)
-                return getattr(space, methname)(w_other, self)
+                return getattr(self, descr_rname)(space, w_other)
 
             try:
                 return func(w_other, space, self)
             except OverflowError:
                 self = delegate_SmallLong2Long(space, self)
                 w_other = delegate_SmallLong2Long(space, w_other)
-                return getattr(space, methname)(w_other, self)
+                return getattr(self, descr_rname)(space, w_other)
 
-        return descr_impl, descr_rimpl
+        return descr_binop, descr_rbinop
 
     def _add(self, space, w_other):
         x = self.longlong
         y = w_other.longlong
         z = x + y
-        if ((z^x)&(z^y)) < 0:
+        if ((z ^ x) & (z ^ y)) < 0:
             raise OverflowError
         return W_SmallLongObject(z)
     descr_add, descr_radd = _make_descr_binop(_add)
         x = self.longlong
         y = w_other.longlong
         z = x - y
-        if ((z^x)&(z^~y)) < 0:
+        if ((z ^ x) & (z ^ ~y)) < 0:
             raise OverflowError
         return W_SmallLongObject(z)
     descr_sub, descr_rsub = _make_descr_binop(_sub)
                 raise OverflowError
             z = x // y
         except ZeroDivisionError:
-            raise OperationError(space.w_ZeroDivisionError,
-                                 space.wrap("integer division by zero"))
-        #except OverflowError:
-        #    raise FailedToImplementArgs(space.w_OverflowError,
-        #                            space.wrap("integer division"))
+            raise operationerrfmt(space.w_ZeroDivisionError,
+                                  "integer division by zero")
         return W_SmallLongObject(z)
     descr_floordiv, descr_rfloordiv = _make_descr_binop(_floordiv)
 
                 raise OverflowError
             z = x % y
         except ZeroDivisionError:
-            raise OperationError(space.w_ZeroDivisionError,
-                                 space.wrap("integer modulo by zero"))
-        #except OverflowError:
-        #    raise FailedToImplementArgs(space.w_OverflowError,
-        #                            space.wrap("integer modulo"))
+            raise operationerrfmt(space.w_ZeroDivisionError,
+                                  "integer modulo by zero")
         return W_SmallLongObject(z)
     descr_mod, descr_rmod = _make_descr_binop(_mod)
 
                 raise OverflowError
             z = x // y
         except ZeroDivisionError:
-            raise OperationError(space.w_ZeroDivisionError,
-                                 space.wrap("integer divmod by zero"))
-        #except OverflowError:
-        #    raise FailedToImplementArgs(space.w_OverflowError,
-        #                            space.wrap("integer modulo"))
+            raise operationerrfmt(space.w_ZeroDivisionError,
+                                  "integer divmod by zero")
         # no overflow possible
         m = x % y
         return space.newtuple([W_SmallLongObject(z), W_SmallLongObject(m)])
     descr_divmod, descr_rdivmod = _make_descr_binop(_divmod)
 
-    # XXX:
     @unwrap_spec(w_modulus=WrappedDefault(None))
-    #def descr_pow__SmallLong_Int_SmallLong(self, space, w_exponent,
     def descr_pow(self, space, w_exponent, w_modulus=None):
-        if space.isinstance_w(w_exponent, space.w_long):
+        if isinstance(w_exponent, W_AbstractLongObject):
             self = delegate_SmallLong2Long(space, self)
-            return space.pow(self, w_exponent, w_modulus)
-        elif not space.isinstance_w(w_exponent, space.w_int):
+            return self.descr_pow(space, w_exponent, w_modulus)
+        elif not isinstance(w_exponent, W_AbstractIntObject):
             return space.w_NotImplemented
-        
-        # XXX: this expects w_exponent as an int o_O
-        """
-        if space.isinstance_w(w_exponent, space.w_int):
-            w_exponent = delegate_Int2SmallLong(space, w_exponent)
-        elif not space.isinstance_w(w_exponent, space.w_long):
-            return space.w_NotImplemented
-        elif not isinstance(w_exponent, W_SmallLongObject):
-            self = delegate_SmallLong2Long(space, self)
-            return space.pow(self, w_exponent, w_modulus)
-            """
 
         if space.is_none(w_modulus):
-            #return _impl_pow(space, self.longlong, w_exponent)
             try:
-                return _impl_pow(space, self.longlong, w_exponent)
+                return _pow_impl(space, self.longlong, w_exponent)
             except ValueError:
-                self = delegate_SmallLong2Float(space, self)
+                self = self.descr_float(space)
+                return space.pow(self, w_exponent, space.w_None)
             except OverflowError:
                 self = delegate_SmallLong2Long(space, self)
-            return space.pow(self, w_exponent, w_modulus)
-        elif space.isinstance_w(w_modulus, space.w_int):
+                return self.descr_pow(space, w_exponent, w_modulus)
+        elif isinstance(w_modulus, W_AbstractIntObject):
             w_modulus = delegate_Int2SmallLong(space, w_modulus)
-        elif not space.isinstance_w(w_modulus, space.w_long):
+        elif not isinstance(w_modulus, W_AbstractLongObject):
             return space.w_NotImplemented
         elif not isinstance(w_modulus, W_SmallLongObject):
             self = delegate_SmallLong2Long(space, self)
-            #return space.pow(self, w_modulus, w_modulus)
-            return space.pow(self, w_exponent, w_modulus)
+            return self.descr_pow(space, w_exponent, w_modulus)
 
         z = w_modulus.longlong
         if z == 0:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap("pow() 3rd argument cannot be 0"))
+            raise operationerrfmt(space.w_ValueError,
+                                  "pow() 3rd argument cannot be 0")
         try:
-            return _impl_pow(space, self.longlong, w_exponent, z)
+            return _pow_impl(space, self.longlong, w_exponent, z)
         except ValueError:
-            self = delegate_SmallLong2Float(space, self)
+            self = self.descr_float(space)
+            return space.pow(self, w_exponent, w_modulus)
         except OverflowError:
             self = delegate_SmallLong2Long(space, self)
-        return space.pow(self, w_exponent, w_modulus)
+            return self.descr_pow(space, w_exponent, w_modulus)
 
-    # XXX:
     @unwrap_spec(w_modulus=WrappedDefault(None))
-    def descr_rpow(self, space, w_exponent, w_modulus=None):
-        # XXX: blargh
-        if space.isinstance_w(w_exponent, space.w_int):
-            w_exponent = _delegate_Int2Long(space, w_exponent)
-        elif not space.isinstance_w(w_exponent, space.w_long):
+    def descr_rpow(self, space, w_base, w_modulus=None):
+        if isinstance(w_base, W_AbstractIntObject):
+            # Defer to w_base<W_SmallLongObject>.descr_pow
+            # XXX: W_AbstractIntObject.descr_long could return
+            # SmallLongs then it could used instead of
+            # delegate_Int2SmallLong
+            w_base = delegate_Int2SmallLong(space, w_base)
+        elif not isinstance(w_base, W_AbstractLongObject):
             return space.w_NotImplemented
-        return space.pow(w_exponent, self, w_modulus)
+        return w_base.descr_pow(space, self, w_modulus)
 
-    #def descr_lshift__SmallLong_Int(space, w_small1, w_int2):
-    def descr_lshift(self, space, w_other):
-        if space.isinstance_w(w_other, space.w_long):
-            self = delegate_SmallLong2Long(space, self)
-            w_other = delegate_SmallLong2Long(space, w_other)
-            return space.lshift(self, w_other)
-        elif not space.isinstance_w(w_other, space.w_int):
-            return space.w_NotImplemented
-
+    def _lshift(self, space, w_other):
         a = self.longlong
-        b = w_other.intval
+        # May overflow
+        b = space.int_w(w_other)
         if r_uint(b) < LONGLONG_BIT: # 0 <= b < LONGLONG_BIT
-            try:
-                c = a << b
-                if a != (c >> b):
-                    raise OverflowError
-            except OverflowError:
-                #raise FailedToImplementArgs(space.w_OverflowError,
-                #                        space.wrap("integer left shift"))
-                self = delegate_SmallLong2Long(space, self)
-                w_other = _delegate_Int2Long(space, w_other)
-                return space.lshift(self, w_other)
+            c = a << b
+            if a != (c >> b):
+                raise OverflowError
             return W_SmallLongObject(c)
         if b < 0:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap("negative shift count"))
-        else: #b >= LONGLONG_BIT
+            raise operationerrfmt(space.w_ValueError, "negative shift count")
+        # b >= LONGLONG_BIT
+        if a == 0:
+            return self
+        raise OverflowError
+    descr_lshift, descr_rlshift = _make_descr_binop(_lshift)
+
+    def _rshift(self, space, w_other):
+        a = self.longlong
+        # May overflow
+        b = space.int_w(w_other)
+        if r_uint(b) >= LONGLONG_BIT: # not (0 <= b < LONGLONG_BIT)
+            if b < 0:
+                raise operationerrfmt(space.w_ValueError,
+                                      "negative shift count")
+            # b >= LONGLONG_BIT
             if a == 0:
                 return self
-            #raise FailedToImplementArgs(space.w_OverflowError,
-            #                        space.wrap("integer left shift"))
-            self = delegate_SmallLong2Long(space, self)
-            w_other = _delegate_Int2Long(space, w_other)
-            return space.lshift(self, w_other)
-
-    def descr_rshift(self, space, w_other):
-        if space.isinstance_w(w_other, space.w_long):
-            self = delegate_SmallLong2Long(space, self)
-            w_other = delegate_SmallLong2Long(space, w_other)
-            return space.rshift(self, w_other)
-        elif not space.isinstance_w(w_other, space.w_int):
-            return space.w_NotImplemented
-
-        a = self.longlong
-        b = w_other.intval
-        if r_uint(b) >= LONGLONG_BIT: # not (0 <= b < LONGLONG_BIT)
-            if b < 0:
-                raise OperationError(space.w_ValueError,
-                                     space.wrap("negative shift count"))
-            else: # b >= LONGLONG_BIT
-                if a == 0:
-                    return self
-                if a < 0:
-                    a = -1
-                else:
-                    a = 0
+            a = -1 if a < 0 else 0
         else:
             a = a >> b
         return W_SmallLongObject(a)
+    descr_rshift, descr_rrshift = _make_descr_binop(_rshift)
 
     def _and(self, space, w_other):
         a = self.longlong
                 raise OverflowError
             x = -a
         except OverflowError:
-            return space.neg(delegate_SmallLong2Long(self))
-            #raise FailedToImplementArgs(space.w_OverflowError,
-            #                        space.wrap("integer negation"))
+            self = delegate_SmallLong2Long(space, self)
+            return self.descr_neg(space)
         return W_SmallLongObject(x)
-    #get_negint = neg__SmallLong
-
-    #def descr_pos(self, space):
-    #    return self
 
     def descr_abs(self, space):