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