integer_primitives.py 7.2 KB
Newer Older
1
from rpython.rlib.rarithmetic import ovfcheck, LONG_BIT
Stefan Marr's avatar
Stefan Marr committed
2
from rpython.rlib.rbigint import rbigint
Stefan Marr's avatar
Stefan Marr committed
3
from som.primitives.primitives import Primitives
Stefan Marr's avatar
Stefan Marr committed
4
from som.vmobjects.integer import Integer
Stefan Marr's avatar
Stefan Marr committed
5 6
from som.vmobjects.primitive   import Primitive
from som.vmobjects.double      import Double
Stefan Marr's avatar
Stefan Marr committed
7
from som.vmobjects.string      import String
8
from som.vmobjects.block       import block_evaluate
Stefan Marr's avatar
Stefan Marr committed
9 10 11

import math

Stefan Marr's avatar
Stefan Marr committed
12

13 14
def _asString(ivkbl, frame, interpreter):
    rcvr = frame.pop()
Stefan Marr's avatar
Stefan Marr committed
15
    frame.push(rcvr.prim_as_string(interpreter.get_universe()))
16

Stefan Marr's avatar
Stefan Marr committed
17

18 19
def _sqrt(ivkbl, frame, interpreter):
    rcvr = frame.pop()
20 21 22 23 24
    res = math.sqrt(rcvr.get_embedded_integer())
    if res == float(int(res)):
        frame.push(interpreter.get_universe().new_integer(int(res)))
    else:
        frame.push(interpreter.get_universe().new_double(res))
25

Stefan Marr's avatar
Stefan Marr committed
26

27 28
def _atRandom(ivkbl, frame, interpreter):
    rcvr = frame.pop()
Tobias Pape's avatar
Tobias Pape committed
29 30
    frame.push(interpreter.get_universe().new_integer(int(
        rcvr.get_embedded_integer() * interpreter.get_universe().random.random())))
31

Stefan Marr's avatar
Stefan Marr committed
32

33 34 35
def _plus(ivkbl, frame, interpreter):
    right_obj = frame.pop()
    left      = frame.pop()
Stefan Marr's avatar
Stefan Marr committed
36
    frame.push(left.prim_add(right_obj, interpreter.get_universe()))
37

Stefan Marr's avatar
Stefan Marr committed
38

39 40 41
def _minus(ivkbl, frame, interpreter):
    right_obj = frame.pop()
    left      = frame.pop()
Stefan Marr's avatar
Stefan Marr committed
42
    frame.push(left.prim_subtract(right_obj, interpreter.get_universe()))
43

Stefan Marr's avatar
Stefan Marr committed
44

45 46 47
def _mult(ivkbl, frame, interpreter):
    right_obj = frame.pop()
    left      = frame.pop()
Stefan Marr's avatar
Stefan Marr committed
48
    frame.push(left.prim_multiply(right_obj, interpreter.get_universe()))
49

Stefan Marr's avatar
Stefan Marr committed
50

51 52 53
def _doubleDiv(ivkbl, frame, interpreter):
    right_obj = frame.pop()
    left      = frame.pop()
Stefan Marr's avatar
Stefan Marr committed
54
    frame.push(left.prim_double_div(right_obj, interpreter.get_universe()))
55

Stefan Marr's avatar
Stefan Marr committed
56

57 58 59
def _intDiv(ivkbl, frame, interpreter):
    right_obj = frame.pop()
    left      = frame.pop()
Stefan Marr's avatar
Stefan Marr committed
60
    frame.push(left.prim_int_div(right_obj, interpreter.get_universe()))
61

Stefan Marr's avatar
Stefan Marr committed
62

63 64 65
def _mod(ivkbl, frame, interpreter):
    right_obj = frame.pop()
    left      = frame.pop()
Stefan Marr's avatar
Stefan Marr committed
66
    frame.push(left.prim_modulo(right_obj, interpreter.get_universe()))
67

Stefan Marr's avatar
Stefan Marr committed
68

69 70 71
def _and(ivkbl, frame, interpreter):
    right_obj = frame.pop()
    left      = frame.pop()
Stefan Marr's avatar
Stefan Marr committed
72
    frame.push(left.prim_and(right_obj, interpreter.get_universe()))
73 74 75 76 77


def _equals(ivkbl, frame, interpreter):
    right_obj = frame.pop()
    left      = frame.pop()
Stefan Marr's avatar
Stefan Marr committed
78
    frame.push(left.prim_equals(right_obj, interpreter.get_universe()))
79

Stefan Marr's avatar
Stefan Marr committed
80

81 82 83
def _lessThan(ivkbl, frame, interpreter):
    right_obj = frame.pop()
    left      = frame.pop()
Stefan Marr's avatar
Stefan Marr committed
84
    frame.push(left.prim_less_than(right_obj, interpreter.get_universe()))
Stefan Marr's avatar
Stefan Marr committed
85

Stefan Marr's avatar
Stefan Marr committed
86

Stefan Marr's avatar
Stefan Marr committed
87 88 89 90 91 92 93 94 95 96 97
def _fromString(ivkbl, frame, interpreter):
    param = frame.pop()
    frame.pop()
    
    if not isinstance(param, String):
        frame.push(interpreter.get_universe().nilObject)
        return
    
    int_value = int(param.get_embedded_string())
    frame.push(interpreter.get_universe().new_integer(int_value))

Stefan Marr's avatar
Stefan Marr committed
98

99 100 101
def _leftShift(ivkbl, frame, interpreter):
    right = frame.pop()
    left  = frame.pop()
Stefan Marr's avatar
Stefan Marr committed
102 103
    universe  = interpreter.get_universe()
    assert isinstance(right, Integer)
104

Stefan Marr's avatar
Stefan Marr committed
105 106 107
    l = left.get_embedded_integer()
    r = right.get_embedded_integer()
    try:
108
        if not (l == 0 or 0 <= r < LONG_BIT):
109
            raise OverflowError
Stefan Marr's avatar
Stefan Marr committed
110 111 112 113 114
        result = ovfcheck(l << r)
        frame.push(universe.new_integer(result))
    except OverflowError:
        frame.push(universe.new_biginteger(
            rbigint.fromint(l).lshift(r)))
115 116 117 118 119 120 121 122 123 124


def _bitXor(ivkbl, frame, interpreter):
    right = frame.pop()
    left  = frame.pop()
    
    result = left.get_embedded_integer() ^ right.get_embedded_integer()

    frame.push(interpreter.get_universe().new_integer(result))

Stefan Marr's avatar
Stefan Marr committed
125

Stefan Marr's avatar
Stefan Marr committed
126 127
from rpython.rlib import jit

Stefan Marr's avatar
Stefan Marr committed
128

Stefan Marr's avatar
Stefan Marr committed
129
def get_printable_location(interpreter, block_method):
Stefan Marr's avatar
Stefan Marr committed
130 131
    from som.vmobjects.method import Method
    assert isinstance(block_method, Method)
132 133
    return "to:do: [%s>>%s]" % (block_method.get_holder().get_name().get_string(),
                                block_method.get_signature().get_string())
Stefan Marr's avatar
Stefan Marr committed
134 135


136
jitdriver_int = jit.JitDriver(
Stefan Marr's avatar
Stefan Marr committed
137
    greens=['interpreter', 'block_method'],
Stefan Marr's avatar
Stefan Marr committed
138 139 140 141
    reds='auto',
    # virtualizables=['frame'],
    get_printable_location=get_printable_location)

142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
jitdriver_double = jit.JitDriver(
    greens=['interpreter', 'block_method'],
    reds='auto',
    # virtualizables=['frame'],
    get_printable_location=get_printable_location)


def _toDoInt(i, top, frame, context, interpreter, block_method, universe):
    assert isinstance(i, int)
    assert isinstance(top, int)
    while i <= top:
        jitdriver_int.jit_merge_point(interpreter=interpreter,
                                      block_method=block_method)

        b = universe.new_block(block_method, context)
        frame.push(b)
        frame.push(universe.new_integer(i))
        block_evaluate(b, interpreter, frame)
        frame.pop()
        i += 1


def _toDoDouble(i, top, frame, context, interpreter, block_method, universe):
    assert isinstance(i, int)
    assert isinstance(top, float)
    while i <= top:
        jitdriver_double.jit_merge_point(interpreter=interpreter,
                                         block_method=block_method)

        b = universe.new_block(block_method, context)
        frame.push(b)
        frame.push(universe.new_integer(i))
        block_evaluate(b, interpreter, frame)
        frame.pop()
        i += 1


179 180 181 182
def _toDo(ivkbl, frame, interpreter):
    universe = interpreter.get_universe()
    block = frame.pop()
    limit = frame.pop()
Stefan Marr's avatar
Stefan Marr committed
183
    self  = frame.pop()  # we do leave it on there
184

185 186
    block_method = block.get_method()
    context      = block.get_context()
187 188

    i = self.get_embedded_integer()
189
    if isinstance(limit, Double):
190 191
        _toDoDouble(i, limit.get_embedded_double(), frame, context, interpreter,
                    block_method, universe)
192
    else:
Stefan Marr's avatar
Stefan Marr committed
193
        _toDoInt(i, limit.get_embedded_integer(), frame, context, interpreter,
194
                 block_method, universe)
195

196 197
    frame.push(self)

198

199
class IntegerPrimitives(Primitives):
Stefan Marr's avatar
Stefan Marr committed
200 201 202

    def install_primitives(self):
        self._install_instance_primitive(Primitive("asString", self._universe, _asString))
203
        self._install_instance_primitive(Primitive("sqrt",     self._universe, _sqrt))
Stefan Marr's avatar
Stefan Marr committed
204
        self._install_instance_primitive(Primitive("atRandom", self._universe, _atRandom))
205 206 207
        
        self._install_instance_primitive(Primitive("+",  self._universe, _plus))
        self._install_instance_primitive(Primitive("-",  self._universe, _minus))
Stefan Marr's avatar
Stefan Marr committed
208

209
        self._install_instance_primitive(Primitive("*",  self._universe, _mult))
Stefan Marr's avatar
Stefan Marr committed
210
        self._install_instance_primitive(Primitive("//", self._universe, _doubleDiv))
211 212 213 214 215
        self._install_instance_primitive(Primitive("/",  self._universe, _intDiv))
        self._install_instance_primitive(Primitive("%",  self._universe, _mod))
        self._install_instance_primitive(Primitive("&",  self._universe, _and))
        self._install_instance_primitive(Primitive("=",  self._universe, _equals))
        self._install_instance_primitive(Primitive("<",  self._universe, _lessThan))
216 217 218 219

        self._install_instance_primitive(Primitive("<<", self._universe, _leftShift))
        self._install_instance_primitive(Primitive("bitXor:", self._universe, _bitXor))

220 221
        self._install_instance_primitive(Primitive("to:do:", self._universe, _toDo))
        
Stefan Marr's avatar
Stefan Marr committed
222
        self._install_class_primitive(Primitive("fromString:", self._universe, _fromString))