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