Author: Lars Wassermann <[email protected]>
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
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit