Author: Lars Wassermann <lars.wasserm...@gmail.com>
Branch: 
Changeset: r239:d1a240901b6d
Date: 2013-03-26 13:41 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/d1a240901b6d/

Log:    added positive_32bit_integer wrapping functions to space the result
        is that we can now do primitive bitAnd:, bitOr: and bitXor: with
        LargePositive1WordIntegers also, wrap_int cant wrap to
        PositiveLargeInts anymore, because in wrap_int, we cant be sure that
        the result needs be positive.

diff --git a/spyvm/objspace.py b/spyvm/objspace.py
--- a/spyvm/objspace.py
+++ b/spyvm/objspace.py
@@ -167,10 +167,11 @@
 
     def wrap_int(self, val):
         from spyvm import constants
-        if int_between(constants.TAGGED_MININT, val, constants.TAGGED_MAXINT + 
1):
+        if int_between(constants.TAGGED_MININT, val,
+                        constants.TAGGED_MAXINT + 1):
             return model.W_SmallInteger(val)
-        elif val > 0:
-            return model.W_LargePositiveInteger1Word(val)
+        # We can't build large integers here, because we don't know what to do
+        # with negativ vals: raise an error or interpret them as 4-byte 
positive?
         raise WrappingError("integer too large to fit into a tagged pointer")
 
     def wrap_uint(self, val):
@@ -178,7 +179,7 @@
             raise WrappingError("negative integer")
         if intmask(val) >= 0:
             try:
-                return self.wrap_int(intmask(val))
+                return self.wrap_positive_32bit_int(intmask(val))
             except WrappingError:
                 pass
         # XXX this code sucks
@@ -190,6 +191,15 @@
             w_result.setchar(i, chr(intmask((val >> i*8) & 255)))
         return w_result
 
+    def wrap_positive_32bit_int(self, val):
+        # This will always return a positive value.
+        # XXX: For now, we assume that val is at most 32bit, i.e. overflows are
+        # checked for before wrapping.
+        if int_between(0, val, constants.TAGGED_MAXINT + 1):
+            return model.W_SmallInteger(val)
+        else:
+            return model.W_LargePositiveInteger1Word(val)
+
     def wrap_float(self, i):
         return model.W_Float(i)
 
@@ -225,6 +235,8 @@
         elif isinstance(w_value, model.W_LargePositiveInteger1Word):
             if w_value.value > 0:
                 return w_value.value
+            else:
+                raise UnwrappingError("The value is negative when interpreted 
as 32bit value.")
         raise UnwrappingError("expected a W_SmallInteger or 
W_LargePositiveInteger1Word, got %s" % (w_value,))
 
     def unwrap_uint(self, w_value):
@@ -247,6 +259,14 @@
         else:
             raise UnwrappingError("Got unexpected class in unwrap_uint")
 
+    def unwrap_positive_32bit_int(self, w_value):
+        if isinstance(w_value, model.W_SmallInteger):
+            if w_value.value >= 0:
+                return w_value.value
+        elif isinstance(w_value, model.W_LargePositiveInteger1Word):
+            return w_value.value
+        raise UnwrappingError("Wrong types or negative SmallInteger.")
+
     def unwrap_char(self, w_char):
         from spyvm import constants
         w_class = w_char.getclass(self)
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -50,6 +50,7 @@
 # converted to an index0 
 index1_0 = object()
 char = object()
+pos_32bit_int = object()
 
 def expose_primitive(code, unwrap_spec=None, no_result=False, 
result_is_new_frame=False):
     # some serious magic, don't look
@@ -96,6 +97,8 @@
                     w_arg = s_frame.peek(index)
                     if spec is int:
                         args += (interp.space.unwrap_int(w_arg), )
+                    elif spec is pos_32bit_int:
+                        args += 
(interp.space.unwrap_positive_32bit_int(w_arg),)
                     elif spec is index1_0:
                         args += (interp.space.unwrap_int(w_arg)-1, )
                     elif spec is float:
@@ -174,10 +177,11 @@
     }
 for (code,op) in bitwise_binary_ops.items():
     def make_func(op):
-        @expose_primitive(code, unwrap_spec=[int, int])
+        @expose_primitive(code, unwrap_spec=[pos_32bit_int, pos_32bit_int])
         def func(interp, s_frame, receiver, argument):
+            from spyvm.model import W_LargePositiveInteger1Word
             res = op(receiver, argument)
-            return interp.space.wrap_int(res)
+            return interp.space.wrap_positive_32bit_int(res)
     make_func(op)
 
 # #/ -- return the result of a division, only succeed if the division is exact
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
@@ -67,10 +67,10 @@
     assert prim(primitives.ADD, [3,4]).value == 7
 
 def test_small_int_add_fail():
-    w_result = prim(primitives.ADD, [constants.TAGGED_MAXINT, 2])
-    assert isinstance(w_result, model.W_LargePositiveInteger1Word)
-    assert w_result.value == constants.TAGGED_MAXINT + 2
-    prim_fails(primitives.ADD, [constants.TAGGED_MAXINT, 
constants.TAGGED_MAXINT * 2])
+    w_result = prim_fails(primitives.ADD, [constants.TAGGED_MAXINT, 2])
+    # assert isinstance(w_result, model.W_LargePositiveInteger1Word)
+    # assert w_result.value == constants.TAGGED_MAXINT + 2
+    # prim_fails(primitives.ADD, [constants.TAGGED_MAXINT, 
constants.TAGGED_MAXINT * 2])
 
 def test_small_int_minus():
     assert prim(primitives.SUBTRACT, [5,9]).value == -4
@@ -84,9 +84,9 @@
     assert prim(primitives.MULTIPLY, [6,3]).value == 18
 
 def test_small_int_multiply_overflow():
-    w_result = prim(primitives.MULTIPLY, [constants.TAGGED_MAXINT, 2])
-    assert isinstance(w_result, model.W_LargePositiveInteger1Word)
-    assert w_result.value == constants.TAGGED_MAXINT * 2
+    w_result = prim_fails(primitives.MULTIPLY, [constants.TAGGED_MAXINT, 2])
+    #assert isinstance(w_result, model.W_LargePositiveInteger1Word)
+    #assert w_result.value == constants.TAGGED_MAXINT * 2
     prim_fails(primitives.MULTIPLY, [constants.TAGGED_MAXINT, 
constants.TAGGED_MAXINT])
     prim_fails(primitives.MULTIPLY, [constants.TAGGED_MAXINT, -4])
     prim_fails(primitives.MULTIPLY, [constants.TAGGED_MININT, 
constants.TAGGED_MAXINT])
@@ -171,9 +171,9 @@
     prim_fails(primitives.BIT_SHIFT, [4, 31])
     prim_fails(primitives.BIT_SHIFT, [4, 30])
     prim_fails(primitives.BIT_SHIFT, [4, 29])
-    w_result = prim(primitives.BIT_SHIFT, [4, 28])
-    assert isinstance(w_result, model.W_LargePositiveInteger1Word)
-    assert w_result.value == 4 << 28
+    w_result = prim_fails(primitives.BIT_SHIFT, [4, 28])
+    # assert isinstance(w_result, model.W_LargePositiveInteger1Word)
+    # assert w_result.value == 4 << 28
 
 def test_smallint_as_float():
     assert prim(primitives.SMALLINT_AS_FLOAT, [12]).value == 12.0
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to