Commit 8e079882 by Stefan Marr

Remove BigInteger from SOM

It is implemented like in RTruffleSOM, BigInteger remains on the VM level to hold rbigint instances.
This also properly parses rbigint.

Signed-off-by: Stefan Marr <git@stefan-marr.de>
1 parent e0d567af
Subproject commit ab97d9c0aad8042e4fffa5e0161a62cd6ca86eae
Subproject commit d47d0965cae605c07ffe10321203e3154dd6e301
from rpython.rlib.rarithmetic import string_to_int
from rpython.rlib.rbigint import rbigint
from .lexer import Lexer
from .bytecode_generator import BytecodeGenerator
from .method_generation_context import MethodGenerationContext
from .symbol import Symbol, symbol_as_str
from ..vmobjects.integer import integer_value_fits
class ParseError(BaseException):
def __init__(self, message, expected_sym, parser):
......@@ -532,20 +532,21 @@ class Parser(object):
def _literal_integer(self, negate_value):
try:
i = int(self._text)
i = string_to_int(self._text)
if negate_value:
i = 0 - i
result = self._universe.new_integer(i)
except OverflowError:
bigint = rbigint.fromstr(self._text)
if negate_value:
bigint.sign = -1
result = self._universe.new_biginteger(bigint)
except ValueError:
raise ParseError("Could not parse integer. "
"Expected a number but got '%s'" % self._text,
Symbol.NONE, self)
self._expect(Symbol.Integer)
if integer_value_fits(i):
return self._universe.new_integer(i)
else:
return self._universe.new_biginteger(i)
return result
def _literal_double(self, negate_value):
try:
......
......@@ -2,7 +2,9 @@ from som.interpreter.bytecodes import bytecode_length, Bytecodes
from som.interpreter.control_flow import ReturnException
from rpython.rlib import jit
from som.vmobjects.integer import Integer, integer_value_fits
from som.vmobjects.biginteger import BigInteger
from som.vmobjects.double import Double
from som.vmobjects.integer import Integer
class Interpreter(object):
......@@ -137,23 +139,16 @@ class Interpreter(object):
raise ReturnException(result, context)
# TODO: this should be done like in the RTruffleSOM variant
def _push_long_result(self, frame, result):
# Check with integer bounds and push:
if integer_value_fits(result):
frame.push(self._universe.new_integer(int(result)))
else:
frame.push(self._universe.new_biginteger(result))
def _do_add(self, bytecode_index, frame, method):
rcvr = frame.get_stack_element(1)
right = frame.get_stack_element(0)
if isinstance(rcvr, Integer) and isinstance(right, Integer):
if (isinstance(rcvr, Integer) or
isinstance(rcvr, BigInteger) or
isinstance(rcvr, Double)):
frame.pop()
frame.pop()
result = rcvr.get_embedded_integer() + right.get_embedded_integer()
self._push_long_result(frame, result)
frame.push(rcvr.prim_add(right, self._universe))
else:
self._send(method, frame, self._add_symbol,
rcvr.get_class(self._universe), bytecode_index)
......
from rpython.rlib.rfloat import (formatd, DTSF_ADD_DOT_0, DTSF_STR_PRECISION,
NAN, INFINITY, isfinite, round_double)
from rpython.rlib.rfloat import round_double
from som.primitives.primitives import Primitives
from som.vmobjects.primitive import Primitive
......@@ -19,90 +18,67 @@ def _coerce_to_double(obj, universe):
def _asString(ivkbl, frame, interpreter):
rcvr = frame.pop()
d = rcvr.get_embedded_double()
s = formatd(d, "g", DTSF_STR_PRECISION, DTSF_ADD_DOT_0)
frame.push(interpreter.get_universe().new_string(s))
frame.push(rcvr.prim_as_string(interpreter.get_universe()))
def _sqrt(ivkbl, frame, interpreter):
rcvr = frame.pop()
frame.push(interpreter.get_universe().new_double(math.sqrt(rcvr.get_embedded_double())))
frame.push(interpreter.get_universe().new_double(math.sqrt(
rcvr.get_embedded_double())))
def _plus(ivkbl, frame, interpreter):
op1 = _coerce_to_double(frame.pop(), interpreter.get_universe())
op2 = frame.pop()
frame.push(interpreter.get_universe().new_double(op1.get_embedded_double()
+ op2.get_embedded_double()))
right = frame.pop()
rcvr = frame.pop()
frame.push(rcvr.prim_add(right, interpreter.get_universe()))
def _minus(ivkbl, frame, interpreter):
op1 = _coerce_to_double(frame.pop(), interpreter.get_universe())
op2 = frame.pop()
frame.push(interpreter.get_universe().new_double(op2.get_embedded_double()
- op1.get_embedded_double()))
right = frame.pop()
rcvr = frame.pop()
frame.push(rcvr.prim_subtract(right, interpreter.get_universe()))
def _mult(ivkbl, frame, interpreter):
op1 = _coerce_to_double(frame.pop(), interpreter.get_universe())
op2 = frame.pop()
frame.push(interpreter.get_universe().new_double(op2.get_embedded_double()
* op1.get_embedded_double()))
right = frame.pop()
rcvr = frame.pop()
frame.push(rcvr.prim_multiply(right, interpreter.get_universe()))
def _doubleDiv(ivkbl, frame, interpreter):
op1 = _coerce_to_double(frame.pop(), interpreter.get_universe())
op2 = frame.pop()
frame.push(interpreter.get_universe().new_double(op2.get_embedded_double()
/ op1.get_embedded_double()))
right = frame.pop()
rcvr = frame.pop()
frame.push(rcvr.prim_double_div(right, interpreter.get_universe()))
def _mod(ivkbl, frame, interpreter):
op1 = _coerce_to_double(frame.pop(), interpreter.get_universe())
op2 = frame.pop()
o1 = op1.get_embedded_double()
o2 = op2.get_embedded_double()
r = math.fmod(o1, o2)
frame.push(interpreter.get_universe().new_double(r))
right = frame.pop()
rcvr = frame.pop()
frame.push(rcvr.prim_modulo(right, interpreter.get_universe()))
def _equals(ivkbl, frame, interpreter):
op1 = _coerce_to_double(frame.pop(), interpreter.get_universe())
op2 = frame.pop()
if op1.get_embedded_double() == op2.get_embedded_double():
frame.push(interpreter.get_universe().trueObject)
else:
frame.push(interpreter.get_universe().falseObject)
right = frame.pop()
rcvr = frame.pop()
frame.push(rcvr.prim_equals(right, interpreter.get_universe()))
def _lessThan(ivkbl, frame, interpreter):
op1 = _coerce_to_double(frame.pop(), interpreter.get_universe())
op2 = frame.pop()
if op2.get_embedded_double() < op1.get_embedded_double():
frame.push(interpreter.get_universe().trueObject)
else:
frame.push(interpreter.get_universe().falseObject)
right = frame.pop()
rcvr = frame.pop()
frame.push(rcvr.prim_less_than(right, interpreter.get_universe()))
def _and(ivkbl, frame, interpreter):
op1 = _coerce_to_double(frame.pop(), interpreter.get_universe())
op2 = frame.pop()
left = int(op2.get_embedded_double())
right = int(op1.get_embedded_double())
result = float(left & right)
frame.push(interpreter.get_universe().new_double(result))
right = frame.pop()
rcvr = frame.pop()
frame.push(rcvr.prim_and(right, interpreter.get_universe()))
def _bitXor(ivkbl, frame, interpreter):
op1 = _coerce_to_double(frame.pop(), interpreter.get_universe())
op2 = frame.pop()
left = int(op2.get_embedded_double())
right = int(op1.get_embedded_double())
result = float(left ^ right)
frame.push(interpreter.get_universe().new_double(result))
right = frame.pop()
rcvr = frame.pop()
frame.push(rcvr.prim_bit_xor(right, interpreter.get_universe()))
def _round(ivkbl, frame, interpreter):
......
from rpython.rlib.rarithmetic import ovfcheck
from rpython.rlib.rbigint import rbigint
from som.primitives.primitives import Primitives
from som.vmobjects.integer import Integer
from som.vmobjects.primitive import Primitive
from som.vmobjects.biginteger import BigInteger
from som.vmobjects.integer import integer_value_fits, Integer
from som.vmobjects.double import Double
from som.vmobjects.string import String
from som.vmobjects.block import block_evaluate
......@@ -9,29 +10,9 @@ from som.vmobjects.block import block_evaluate
import math
def _push_long_result(frame, result, universe):
# Check with integer bounds and push:
if integer_value_fits(result):
frame.push(universe.new_integer(int(result)))
else:
frame.push(universe.new_biginteger(result))
def _resend_as_biginteger(frame, operator, left, right, universe):
left_biginteger = universe.new_biginteger(left.get_embedded_integer())
operands = [right]
left_biginteger.send(frame, operator, operands, universe, universe.get_interpreter())
def _resend_as_double(frame, operator, left, right, universe):
left_double = universe.new_double(float(left.get_embedded_integer()))
operands = [right]
left_double.send(frame, operator, operands, universe, universe.get_interpreter())
def _asString(ivkbl, frame, interpreter):
rcvr = frame.pop()
frame.push(interpreter.get_universe().new_string(str(rcvr.get_embedded_integer())))
frame.push(rcvr.prim_as_string(interpreter.get_universe()))
def _sqrt(ivkbl, frame, interpreter):
......@@ -52,157 +33,55 @@ def _atRandom(ivkbl, frame, interpreter):
def _plus(ivkbl, frame, interpreter):
right_obj = frame.pop()
left = frame.pop()
# Check second parameter type:
if isinstance(right_obj, BigInteger):
# Second operand was BigInteger
_resend_as_biginteger(frame, "+", left, right_obj, interpreter.get_universe())
elif isinstance(right_obj, Double):
_resend_as_double(frame, "+", left, right_obj, interpreter.get_universe())
else:
# Do operation:
right = right_obj
result = left.get_embedded_integer() + right.get_embedded_integer()
_push_long_result(frame, result, interpreter.get_universe())
frame.push(left.prim_add(right_obj, interpreter.get_universe()))
def _minus(ivkbl, frame, interpreter):
right_obj = frame.pop()
left = frame.pop()
# Check second parameter type:
if isinstance(right_obj, BigInteger):
# Second operand was BigInteger
_resend_as_biginteger(frame, "-", left, right_obj, interpreter.get_universe())
elif isinstance(right_obj, Double):
_resend_as_double(frame, "-", left, right_obj, interpreter.get_universe())
else:
# Do operation:
right = right_obj
result = left.get_embedded_integer() - right.get_embedded_integer()
_push_long_result(frame, result, interpreter.get_universe())
frame.push(left.prim_subtract(right_obj, interpreter.get_universe()))
def _mult(ivkbl, frame, interpreter):
right_obj = frame.pop()
left = frame.pop()
# Check second parameter type:
if isinstance(right_obj, BigInteger):
# Second operand was BigInteger
_resend_as_biginteger(frame, "*", left, right_obj, interpreter.get_universe())
elif isinstance(right_obj, Double):
_resend_as_double(frame, "*", left, right_obj, interpreter.get_universe())
else:
# Do operation:
right = right_obj
result = left.get_embedded_integer() * right.get_embedded_integer()
_push_long_result(frame, result, interpreter.get_universe())
frame.push(left.prim_multiply(right_obj, interpreter.get_universe()))
def _doubleDiv(ivkbl, frame, interpreter):
right_obj = frame.pop()
left = frame.pop()
# Check second parameter type:
if isinstance(right_obj, BigInteger):
# Second operand was BigInteger
_resend_as_biginteger(frame, "/", left, right_obj, interpreter.get_universe())
elif isinstance(right_obj, Double):
_resend_as_double(frame, "/", left, right_obj, interpreter.get_universe())
else:
# Do operation:
right = right_obj
result = float(left.get_embedded_integer()) / float(right.get_embedded_integer())
frame.push(interpreter.get_universe().new_double(result))
frame.push(left.prim_double_div(right_obj, interpreter.get_universe()))
def _intDiv(ivkbl, frame, interpreter):
right_obj = frame.pop()
left = frame.pop()
# Check second parameter type:
if isinstance(right_obj, BigInteger):
# Second operand was BigInteger
_resend_as_biginteger(frame, "/", left, right_obj, interpreter.get_universe())
elif isinstance(right_obj, Double):
_resend_as_double(frame, "/", left, right_obj, interpreter.get_universe())
else:
# Do operation:
right = right_obj
result = left.get_embedded_integer() / right.get_embedded_integer()
_push_long_result(frame, result, interpreter.get_universe())
frame.push(left.prim_int_div(right_obj, interpreter.get_universe()))
def _mod(ivkbl, frame, interpreter):
right_obj = frame.pop()
left = frame.pop()
# Check second parameter type:
if isinstance(right_obj, BigInteger):
# Second operand was BigInteger
_resend_as_biginteger(frame, "%", left, right_obj, interpreter.get_universe())
elif isinstance(right_obj, Double):
_resend_as_double(frame, "%", left, right_obj, interpreter.get_universe())
else:
# Do operation:
_push_long_result(frame, left.get_embedded_integer() % right_obj.get_embedded_integer(), interpreter.get_universe())
frame.push(left.prim_modulo(right_obj, interpreter.get_universe()))
def _and(ivkbl, frame, interpreter):
right_obj = frame.pop()
left = frame.pop()
# Check second parameter type:
if isinstance(right_obj, BigInteger):
# Second operand was BigInteger
_resend_as_biginteger(frame, "&", left, right_obj, interpreter.get_universe())
elif isinstance(right_obj, Double):
_resend_as_double(frame, "&", left, right_obj, interpreter.get_universe())
else:
# Do operation:
right = right_obj
result = left.get_embedded_integer() & right.get_embedded_integer()
_push_long_result(frame, result, interpreter.get_universe())
frame.push(left.prim_and(right_obj, interpreter.get_universe()))
def _equals(ivkbl, frame, interpreter):
right_obj = frame.pop()
left = frame.pop()
# Check second parameter type:
if isinstance(right_obj, BigInteger):
# Second operand was BigInteger
_resend_as_biginteger(frame, "=", left, right_obj, interpreter.get_universe())
elif isinstance(right_obj, Integer):
if left.get_embedded_integer() == right_obj.get_embedded_integer():
frame.push(interpreter.get_universe().trueObject)
else:
frame.push(interpreter.get_universe().falseObject)
elif isinstance(right_obj, Double):
if left.get_embedded_integer() == right_obj.get_embedded_double():
frame.push(interpreter.get_universe().trueObject)
else:
frame.push(interpreter.get_universe().falseObject)
else:
frame.push(interpreter.get_universe().falseObject)
frame.push(left.prim_equals(right_obj, interpreter.get_universe()))
def _lessThan(ivkbl, frame, interpreter):
right_obj = frame.pop()
left = frame.pop()
# Check second parameter type:
if isinstance(right_obj, BigInteger):
# Second operand was BigInteger
_resend_as_biginteger(frame, "<", left, right_obj, interpreter.get_universe())
elif isinstance(right_obj, Double):
_resend_as_double(frame, "<", left, right_obj, interpreter.get_universe())
else:
if left.get_embedded_integer() < right_obj.get_embedded_integer():
frame.push(interpreter.get_universe().trueObject)
else:
frame.push(interpreter.get_universe().falseObject)
frame.push(left.prim_less_than(right_obj, interpreter.get_universe()))
def _fromString(ivkbl, frame, interpreter):
......@@ -220,10 +99,17 @@ def _fromString(ivkbl, frame, interpreter):
def _leftShift(ivkbl, frame, interpreter):
right = frame.pop()
left = frame.pop()
universe = interpreter.get_universe()
assert isinstance(right, Integer)
result = left.get_embedded_integer() << right.get_embedded_integer()
_push_long_result(frame, result, interpreter.get_universe())
l = left.get_embedded_integer()
r = right.get_embedded_integer()
try:
result = ovfcheck(l << r)
frame.push(universe.new_integer(result))
except OverflowError:
frame.push(universe.new_biginteger(
rbigint.fromint(l).lshift(r)))
def _bitXor(ivkbl, frame, interpreter):
......@@ -258,7 +144,6 @@ jitdriver_double = jit.JitDriver(
get_printable_location=get_printable_location)
def _toDoInt(i, top, frame, context, interpreter, block_method, universe):
assert isinstance(i, int)
assert isinstance(top, int)
......@@ -293,7 +178,7 @@ def _toDo(ivkbl, frame, interpreter):
universe = interpreter.get_universe()
block = frame.pop()
limit = frame.pop()
self = frame.pop() # we do leave it on there
self = frame.pop() # we do leave it on there
block_method = block.get_method()
context = block.get_context()
......@@ -303,7 +188,7 @@ def _toDo(ivkbl, frame, interpreter):
_toDoDouble(i, limit.get_embedded_double(), frame, context, interpreter,
block_method, universe)
else:
_toDoInt(i, limit.get_embedded_value(), frame, context, interpreter,
_toDoInt(i, limit.get_embedded_integer(), frame, context, interpreter,
block_method, universe)
frame.push(self)
......
from rpython.rlib.debug import make_sure_not_resized
from rpython.rlib.rbigint import rbigint
from rpython.rlib.rrandom import Random
from rpython.rlib import jit
......@@ -60,7 +61,6 @@ class Universe(object):
"metaclassClass",
"nilClass",
"integerClass",
"bigintegerClass",
"arrayClass",
"methodClass",
"symbolClass",
......@@ -87,7 +87,6 @@ class Universe(object):
self.nilClass = None
self.integerClass = None
self.bigintegerClass= None
self.arrayClass = None
self.methodClass = None
self.symbolClass = None
......@@ -252,7 +251,6 @@ class Universe(object):
self.symbolClass = self.new_system_class()
self.methodClass = self.new_system_class()
self.integerClass = self.new_system_class()
self.bigintegerClass = self.new_system_class()
self.primitiveClass = self.new_system_class()
self.stringClass = self.new_system_class()
self.doubleClass = self.new_system_class()
......@@ -269,7 +267,6 @@ class Universe(object):
self._initialize_system_class(self.methodClass, self.arrayClass, "Method")
self._initialize_system_class(self.symbolClass, self.objectClass, "Symbol")
self._initialize_system_class(self.integerClass, self.objectClass, "Integer")
self._initialize_system_class(self.bigintegerClass, self.objectClass, "BigInteger")
self._initialize_system_class(self.primitiveClass, self.objectClass, "Primitive")
self._initialize_system_class(self.stringClass, self.objectClass, "String")
self._initialize_system_class(self.doubleClass, self.objectClass, "Double")
......@@ -283,7 +280,6 @@ class Universe(object):
self._load_system_class(self.methodClass)
self._load_system_class(self.symbolClass)
self._load_system_class(self.integerClass)
self._load_system_class(self.bigintegerClass)
self._load_system_class(self.primitiveClass)
self._load_system_class(self.stringClass)
self._load_system_class(self.doubleClass)
......@@ -389,6 +385,7 @@ class Universe(object):
@staticmethod
def new_biginteger(value):
assert isinstance(value, rbigint)
return BigInteger(value)
@staticmethod
......
from som.vmobjects.abstract_object import AbstractObject
from rpython.rlib.rbigint import rbigint
from .abstract_object import AbstractObject
from .double import Double
class BigInteger(AbstractObject):
......@@ -7,15 +9,127 @@ class BigInteger(AbstractObject):
def __init__(self, value):
AbstractObject.__init__(self)
assert isinstance(value, int)
assert isinstance(value, rbigint)
self._embedded_biginteger = value
def get_embedded_biginteger(self):
return self._embedded_biginteger
def get_embedded_value(self):
"""This Method is polymorphic with Integer"""
return self._embedded_biginteger
def get_class(self, universe):
return universe.bigintegerClass
return universe.integerClass
def _to_double(self, universe):
return universe.new_double(self._embedded_biginteger.tofloat())
def prim_less_than(self, right, universe):
# Check second parameter type:
if isinstance(right, Double):
return self._to_double(universe).prim_less_than(right, universe)
if not isinstance(right, BigInteger):
result = self._embedded_biginteger.lt(
rbigint.fromint(right.get_embedded_integer()))
else:
result = self._embedded_biginteger.lt(
right.get_embedded_biginteger())
if result:
return universe.trueObject
else:
return universe.falseObject
def prim_as_string(self, universe):
return universe.new_string(self._embedded_biginteger.str())
def prim_add(self, right, universe):
if isinstance(right, BigInteger):
return universe.new_biginteger(
right.get_embedded_biginteger().add(self._embedded_biginteger))
elif isinstance(right, Double):
return self._to_double(universe).prim_add(right, universe)
else:
return universe.new_biginteger(
rbigint.fromint(right.get_embedded_integer()).add(
self._embedded_biginteger))
def prim_subtract(self, right, universe):
if isinstance(right, BigInteger):
r = self._embedded_biginteger.sub(right.get_embedded_biginteger())
elif isinstance(right, Double):
return self._to_double(universe).prim_subtract(right, universe)
else:
r = self._embedded_biginteger.sub(rbigint.fromint(
right.get_embedded_integer()))
return universe.new_biginteger(r)
def prim_multiply(self, right, universe):
if isinstance(right, BigInteger):
r = self._embedded_biginteger.mul(right.get_embedded_biginteger())
elif isinstance(right, Double):
return self._to_double(universe).prim_multiply(right, universe)
else:
r = self._embedded_biginteger.mul(rbigint.fromint(
right.get_embedded_integer()))
return universe.new_biginteger(r)
def prim_double_div(self, right, universe):
if isinstance(right, BigInteger):
r = self._embedded_biginteger.truediv(
right.get_embedded_biginteger())
elif isinstance(right, Double):
return self._to_double(universe).prim_double_div(right, universe)
else:
r = self._embedded_biginteger.truediv(rbigint.fromint(
right.get_embedded_integer()))
return universe.new_double(r)
def prim_int_div(self, right, universe):
if isinstance(right, BigInteger):
r = self._embedded_biginteger.floordiv(
right.get_embedded_biginteger())
elif isinstance(right, Double):
return self._to_double(universe).prim_int_div(right, universe)
else:
r = self._embedded_biginteger.floordiv(rbigint.fromint(
right.get_embedded_integer()))
return universe.new_biginteger(r)
def prim_modulo(self, right, universe):
if isinstance(right, BigInteger):
r = self._embedded_biginteger.mod(
right.get_embedded_biginteger())
elif isinstance(right, Double):
return self._to_double(universe).prim_modulo(right, universe)
else:
r = self._embedded_biginteger.mod(rbigint.fromint(
right.get_embedded_integer()))
return universe.new_biginteger(r)
def prim_and(self, right, universe):
if isinstance(right, BigInteger):
r = self._embedded_biginteger.and_(
right.get_embedded_biginteger())
elif isinstance(right, Double):
return self._to_double(universe).prim_modulo(right, universe)
else:
r = self._embedded_biginteger.and_(rbigint.fromint(
right.get_embedded_integer()))
return universe.new_biginteger(r)
def prim_equals(self, right, universe):
from .integer import Integer
if isinstance(right, BigInteger):
result = self._embedded_biginteger.eq(
right.get_embedded_biginteger())
elif isinstance(right, Double):
result = (self._embedded_biginteger.tofloat()
== right.get_embedded_double())
elif isinstance(right, Integer):
r = right.get_embedded_integer()
result = self._embedded_biginteger.eq(rbigint.fromint(r))
else:
return universe.falseObject
if result:
return universe.trueObject
else:
return universe.falseObject
from rpython.rlib.rfloat import formatd, DTSF_ADD_DOT_0, DTSF_STR_PRECISION
from som.vmobjects.abstract_object import AbstractObject
import math
class Double(AbstractObject):
_immutable_fields_ = ["_embedded_double"]
......@@ -14,3 +18,64 @@ class Double(AbstractObject):
def get_class(self, universe):
return universe.doubleClass
@staticmethod
def _get_float(obj):
from .integer import Integer
if isinstance(obj, Double):
return obj.get_embedded_double()
if isinstance(obj, Integer):
return float(obj.get_embedded_integer())
raise ValueError("Cannot coerce %s to Double!" % obj)
def prim_multiply(self, right, universe):
r = self._get_float(right)
return universe.new_double(self._embedded_double * r)
def prim_add(self, right, universe):
r = self._get_float(right)
return universe.new_double(self._embedded_double + r)
def prim_bit_xor(self, right, universe):
l = int(self._embedded_double)
r = int(self._get_float(right))
result = float(l ^ r)
return universe.new_double(result)
def prim_as_string(self, universe):
s = formatd(self._embedded_double, "g", DTSF_STR_PRECISION, DTSF_ADD_DOT_0)
return universe.new_string(s)
def prim_subtract(self, right, universe):
r = self._get_float(right)
return universe.new_double(self._embedded_double - r)
def prim_double_div(self, right, universe):
r = self._get_float(right)
return universe.new_double(self._embedded_double / r)
def prim_int_div(self, right, universe):
r = self._get_float(right)
return universe.new_integer(int(self._embedded_double / r))
def prim_modulo(self, right, universe):
r = self._get_float(right)
return universe.new_double(math.fmod(self._embedded_double, r))
def prim_and(self, right, universe):
r = int(self._get_float(right))
return universe.new_double(float(int(self._embedded_double) & r))
def prim_equals(self, right, universe):
r = self._get_float(right)
if self._embedded_double == r:
return universe.trueObject
else:
return universe.falseObject
def prim_less_than(self, right, universe):
r = self._get_float(right)
if self._embedded_double < r:
return universe.trueObject
else:
return universe.falseObject
from rpython.rlib.rarithmetic import ovfcheck
from rpython.rlib.rbigint import rbigint
from som.vmobjects.abstract_object import AbstractObject
from som.vmobjects.biginteger import BigInteger
from som.vmobjects.double import Double
class Integer(AbstractObject):
......@@ -12,17 +16,147 @@ class Integer(AbstractObject):
def get_embedded_integer(self):
return self._embedded_integer
def get_embedded_value(self):
"""This Method is polymorphic with BigInteger"""
return self._embedded_integer
def __str__(self):
return str(self._embedded_integer)
def get_class(self, universe):
return universe.integerClass
def _to_double(self, universe):
return universe.new_double(float(self._embedded_integer))
def prim_less_than(self, right, universe):
# Check second parameter type:
if isinstance(right, BigInteger):
result = rbigint.fromint(self._embedded_integer).lt(
right.get_embedded_biginteger())
elif isinstance(right, Double):
return self._to_double(universe).prim_less_than(right, universe)
else:
result = self._embedded_integer < right.get_embedded_integer()
if result:
return universe.trueObject
else:
return universe.falseObject
def prim_as_string(self, universe):
return universe.new_string(str(self._embedded_integer))
def prim_add(self, right, universe):
if isinstance(right, BigInteger):
return universe.new_biginteger(
right.get_embedded_biginteger().add(
rbigint.fromint(self._embedded_integer)))
elif isinstance(right, Double):
return self._to_double(universe).prim_add(right, universe)
else:
l = self._embedded_integer
r = right.get_embedded_integer()
try:
result = ovfcheck(l + r)
return universe.new_integer(result)
except OverflowError:
return universe.new_biginteger(
rbigint.fromint(l).add(rbigint.fromint(r)))
def prim_subtract(self, right, universe):
if isinstance(right, BigInteger):
r = rbigint.fromint(self._embedded_integer).sub(
right.get_embedded_biginteger())
return universe.new_biginteger(r)
elif isinstance(right, Double):
return self._to_double(universe).prim_subtract(right, universe)
else:
l = self._embedded_integer
r = right.get_embedded_integer()
try:
result = ovfcheck(l - r)
return universe.new_integer(result)
except OverflowError:
return universe.new_biginteger(
rbigint.fromint(l).sub(rbigint.fromint(r)))
def prim_multiply(self, right, universe):
if isinstance(right, BigInteger):
r = rbigint.fromint(self._embedded_integer).mul(
right.get_embedded_biginteger())
return universe.new_biginteger(r)
elif isinstance(right, Double):
return self._to_double(universe).prim_multiply(right, universe)
else:
l = self._embedded_integer
r = right.get_embedded_integer()
try:
result = ovfcheck(l * r)
return universe.new_integer(result)
except OverflowError:
return universe.new_biginteger(
rbigint.fromint(l).mul(rbigint.fromint(r)))
def prim_double_div(self, right, universe):
if isinstance(right, BigInteger):
r = rbigint.fromint(self._embedded_integer).truediv(
right.get_embedded_biginteger())
return universe.new_double(r)
elif isinstance(right, Double):
return self._to_double(universe).prim_double_div(right, universe)
else:
l = self._embedded_integer
r = right.get_embedded_integer()
return universe.new_double(l / float(r))
def prim_int_div(self, right, universe):
if isinstance(right, BigInteger):
r = rbigint.fromint(self._embedded_integer).floordiv(
right.get_embedded_biginteger())
return universe.new_biginteger(r)
elif isinstance(right, Double):
return self._to_double(universe).prim_int_div(right, universe)