Author: Lars Wassermann <[email protected]>
Branch: 
Changeset: r249:413ad48ead1f
Date: 2013-04-09 21:00 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/413ad48ead1f/

Log:    fixed drawing error by implementing shift using polymorphism. The
        main problem was rightshift for 'negative' large integers shifting
        in ones instead of zeros

diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -32,7 +32,7 @@
         virtualizables=['s_context'],
         get_printable_location=get_printable_location
     )
-    
+
     def __init__(self, space, image=None, image_name="", trace=False,
                 max_stack_depth=constants.MAX_LOOP_DEPTH):
         self.space = space
@@ -380,6 +380,8 @@
         try:
             s_method = 
s_class.lookup(self.space.objtable["w_doesNotUnderstand"])
         except MethodNotFound:
+            from spyvm.shadow import ClassShadow
+            assert isinstance(s_class, ClassShadow)
             print "Missing doesDoesNotUnderstand in hierarchy of %s" % 
s_class.getname()
             raise
         s_frame = s_method.create_frame(self.space, receiver, [w_message], 
self)
diff --git a/spyvm/model.py b/spyvm/model.py
--- a/spyvm/model.py
+++ b/spyvm/model.py
@@ -121,6 +121,12 @@
     def as_repr_string(self):
         return "%r" % self
 
+    def lshift(self, space, shift):
+        raise error.PrimitiveFailedError()
+
+    def rshift(self, space, shift):
+        raise error.PrimitiveFailedError()
+
 class W_SmallInteger(W_Object):
     """Boxed integer value"""
     # TODO can we tell pypy that its never larger then 31-bit?
@@ -140,6 +146,25 @@
     def invariant(self):
         return isinstance(self.value, int) and self.value < 0x8000
 
+    def lshift(self, space, shift):
+        from rpython.rlib.rarithmetic import ovfcheck, intmask, r_uint
+        # shift > 0, therefore the highest bit of upperbound is not set,
+        # i.e. upperbound is positive
+        upperbound = intmask(r_uint(-1) >> shift)
+        if 0 <= self.value <= upperbound:
+            shifted = intmask(self.value << shift)
+            return space.wrap_positive_32bit_int(shifted)
+        else:
+            try:
+                shifted = ovfcheck(self.value << shift)
+            except OverflowError:
+                raise error.PrimitiveFailedError()
+            return space.wrap_int(shifted)
+        raise PrimitiveFailedError
+
+    def rshift(self, space, shift):
+        return space.wrap_int(self.value >> shift)
+
     @jit.elidable
     def as_repr_string(self):
         return "W_SmallInteger(%d)" % self.value
@@ -217,6 +242,26 @@
     def __repr__(self):
         return "W_LargePositiveInteger1Word(%d)" % r_uint(self.value)
 
+    def lshift(self, space, shift):
+        from rpython.rlib.rarithmetic import intmask, r_uint
+        # shift > 0, therefore the highest bit of upperbound is not set,
+        # i.e. upperbound is positive
+        upperbound = intmask(r_uint(-1) >> shift)
+        if 0 <= self.value <= upperbound:
+            shifted = intmask(self.value << shift)
+            return space.wrap_positive_32bit_int(shifted)
+        else:
+            raise error.PrimitiveFailedError()
+
+    def rshift(self, space, shift):
+        if shift == 0:
+            return self
+        # a problem might arrise, because we may shift in ones from left
+        mask = (1 << (32 - shift))- 1
+        # the mask is only valid if the highest bit of self.value is set
+        # and only in this case we do need such a mask
+        return space.wrap_int((self.value >> shift) & mask)
+
     def clone(self, space):
         return W_LargePositiveInteger1Word(self.value)
 
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -217,33 +217,14 @@
     return interp.space.wrap_int(receiver // argument)
     
 # #bitShift: -- return the shifted value
-@expose_primitive(BIT_SHIFT, unwrap_spec=[pos_32bit_int, int])
+@expose_primitive(BIT_SHIFT, unwrap_spec=[object, int])
 def func(interp, s_frame, receiver, argument):
-
-    # TODO: 1 << 100 will overflow to 0. Catch this gracefully by Primitive
     # Failing! Use ovfcheck_lfshift
     # (http://codespeak.net/pypy/dist/pypy/doc/coding-guide.html#integer-types)
-
-    # left shift, must fail if we lose bits beyond 32
-    from rpython.rlib.rarithmetic import intmask, r_uint, ovfcheck, int_between
     if argument > 0:
-        # argument > 0, therefore the highest bit of upperbound is not set,
-        # i.e. upperbound is positive
-        upperbound = intmask(r_uint(-1) >> argument)
-        if 0 <= receiver <= upperbound:
-            shifted = intmask(receiver << argument)
-            return interp.space.wrap_positive_32bit_int(shifted)
-        else:
-            try:
-                shifted = ovfcheck(receiver << argument)
-            except OverflowError:
-                raise PrimitiveFailedError()
-            return interp.space.wrap_int(shifted)
-
-    # right shift, ok to lose bits
+        return receiver.lshift(interp.space, argument)
     else:
-        return interp.space.wrap_int(receiver >> -argument)
-   
+        return receiver.rshift(interp.space, -argument)
 
 # ___________________________________________________________________________
 # Float Primitives
@@ -578,7 +559,6 @@
     except Return:
         w_dest_form = w_rcvr.fetch(space, 0)
         if w_dest_form.is_same_object(space.objtable['w_display']):
-            #import pdb; pdb.set_trace()
             w_bitmap = w_dest_form.fetch(space, 0)
             assert isinstance(w_bitmap, model.W_DisplayBitmap)
             w_bitmap.flush_to_screen()
diff --git a/spyvm/test/test_primitives.py b/spyvm/test/test_primitives.py
--- a/spyvm/test/test_primitives.py
+++ b/spyvm/test/test_primitives.py
@@ -157,7 +157,6 @@
     assert prim(primitives.BIT_SHIFT, [4, 27]).value == 536870912
     
 def test_small_int_bit_shift_negative():
-    py.test.skip("While this would make sense, because of the specification, 
we dont shift negative numbers")
     assert prim(primitives.BIT_SHIFT, [-4, -3]).value == -1
     assert prim(primitives.BIT_SHIFT, [-4, -2]).value == -1
     assert prim(primitives.BIT_SHIFT, [-4, -1]).value == -2
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to