integer_primitives.py 10.1 KB
Newer Older
Stefan Marr's avatar
Stefan Marr committed
1 2 3
from som.primitives.primitives import Primitives
from som.vmobjects.primitive   import Primitive
from som.vmobjects.biginteger  import BigInteger
4
from som.vmobjects.integer     import integer_value_fits, Integer
Stefan Marr's avatar
Stefan Marr committed
5
from som.vmobjects.double      import Double
Stefan Marr's avatar
Stefan Marr committed
6
from som.vmobjects.string      import String
7
from som.vmobjects.block       import block_evaluate
Stefan Marr's avatar
Stefan Marr committed
8 9 10

import math

11 12 13
def _push_long_result(frame, result, universe):
    # Check with integer bounds and push:
    if integer_value_fits(result):
Tobias Pape's avatar
Tobias Pape committed
14
        frame.push(universe.new_integer(int(result)))
15 16 17
    else:
        frame.push(universe.new_biginteger(result))

18
def _resend_as_biginteger(frame, operator, left, right, universe):
19 20
    left_biginteger = universe.new_biginteger(left.get_embedded_integer())
    operands = [right]
21
    left_biginteger.send(frame, operator, operands, universe, universe.get_interpreter())
22

23
def _resend_as_double(frame, operator, left, right, universe):
24 25
    left_double = universe.new_double(left.get_embedded_integer())
    operands    = [right]
26
    left_double.send(frame, operator, operands, universe, universe.get_interpreter())
27 28 29 30 31 32 33

def _asString(ivkbl, frame, interpreter):
    rcvr = frame.pop()
    frame.push(interpreter.get_universe().new_string(str(rcvr.get_embedded_integer())))

def _sqrt(ivkbl, frame, interpreter):
    rcvr = frame.pop()
34 35 36 37 38
    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))
39 40 41

def _atRandom(ivkbl, frame, interpreter):
    rcvr = frame.pop()
Tobias Pape's avatar
Tobias Pape committed
42 43
    frame.push(interpreter.get_universe().new_integer(int(
        rcvr.get_embedded_integer() * interpreter.get_universe().random.random())))
44 45 46 47 48 49 50 51

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
52
        _resend_as_biginteger(frame, "+", left, right_obj, interpreter.get_universe())
53
    elif isinstance(right_obj, Double):
54
        _resend_as_double(frame, "+", left, right_obj, interpreter.get_universe())
55 56 57 58 59 60 61 62 63 64 65 66 67
    else:
        # Do operation:
        right = right_obj
        result = left.get_embedded_integer() + right.get_embedded_integer()
        _push_long_result(frame, result, 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
68
        _resend_as_biginteger(frame, "-", left, right_obj, interpreter.get_universe())
69
    elif isinstance(right_obj, Double):
70
        _resend_as_double(frame, "-", left, right_obj, interpreter.get_universe())
71 72 73 74 75 76 77 78 79 80 81 82 83
    else:
        # Do operation:
        right = right_obj
        result = left.get_embedded_integer() - right.get_embedded_integer()
        _push_long_result(frame, result, 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
84
        _resend_as_biginteger(frame, "*", left, right_obj, interpreter.get_universe())
85
    elif isinstance(right_obj, Double):
86
        _resend_as_double(frame, "*", left, right_obj, interpreter.get_universe())
87 88 89 90 91 92 93 94 95 96 97 98 99
    else:
        # Do operation:
        right = right_obj
        result = left.get_embedded_integer() * right.get_embedded_integer()
        _push_long_result(frame, result, 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
100
        _resend_as_biginteger(frame, "/", left, right_obj, interpreter.get_universe())
101
    elif isinstance(right_obj, Double):
102
        _resend_as_double(frame, "/", left, right_obj, interpreter.get_universe())
103 104 105 106 107 108 109 110 111 112 113 114 115
    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))

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
116
        _resend_as_biginteger(frame, "/", left, right_obj, interpreter.get_universe())
117
    elif isinstance(right_obj, Double):
118
        _resend_as_double(frame, "/", left, right_obj, interpreter.get_universe())
119 120 121 122 123 124 125 126 127 128 129 130 131
    else:
        # Do operation:
        right = right_obj
        result = left.get_embedded_integer() / right.get_embedded_integer()
        _push_long_result(frame, result, 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
132
        _resend_as_biginteger(frame, "%", left, right_obj, interpreter.get_universe())
133
    elif isinstance(right_obj, Double):
134
        _resend_as_double(frame, "%", left, right_obj, interpreter.get_universe())
135 136 137 138 139 140 141 142 143 144 145
    else:
        # Do operation:
        _push_long_result(frame, left.get_embedded_integer() % right_obj.get_embedded_integer(), 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
146
        _resend_as_biginteger(frame, "&", left, right_obj, interpreter.get_universe())
147
    elif isinstance(right_obj, Double):
148
        _resend_as_double(frame, "&", left, right_obj, interpreter.get_universe())
149 150 151 152 153 154 155 156 157 158 159 160 161 162
    else:
        # Do operation:
        right = right_obj
        result = left.get_embedded_integer() & right.get_embedded_integer()
        _push_long_result(frame, result, 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
163
        _resend_as_biginteger(frame, "=", left, right_obj, interpreter.get_universe())
164 165 166
    elif isinstance(right_obj, Integer):
        if left.get_embedded_integer() == right_obj.get_embedded_integer():
            frame.push(interpreter.get_universe().trueObject)
167
        else:
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
            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)

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
184
        _resend_as_biginteger(frame, "<", left, right_obj, interpreter.get_universe())
185
    elif isinstance(right_obj, Double):
186
        _resend_as_double(frame, "<", left, right_obj, interpreter.get_universe())
187 188 189 190 191
    else:
        if left.get_embedded_integer() < right_obj.get_embedded_integer():
            frame.push(interpreter.get_universe().trueObject)
        else:
            frame.push(interpreter.get_universe().falseObject)
Stefan Marr's avatar
Stefan Marr committed
192

Stefan Marr's avatar
Stefan Marr committed
193 194 195 196 197 198 199 200 201 202 203
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
204 205 206

from rpython.rlib import jit

Stefan Marr's avatar
Stefan Marr committed
207
def get_printable_location(interpreter, block_method):
Stefan Marr's avatar
Stefan Marr committed
208 209 210 211 212 213
    from som.vmobjects.method import Method
    assert isinstance(block_method, Method)
    return "TODO"


jitdriver = jit.JitDriver(
Stefan Marr's avatar
Stefan Marr committed
214
    greens=['interpreter', 'block_method'],
Stefan Marr's avatar
Stefan Marr committed
215 216 217 218
    reds='auto',
    # virtualizables=['frame'],
    get_printable_location=get_printable_location)

219 220 221 222 223
def _toDo(ivkbl, frame, interpreter):
    universe = interpreter.get_universe()
    block = frame.pop()
    limit = frame.pop()
    self  = frame.pop() # we do leave it on there
224

225 226
    block_method = block.get_method()
    context      = block.get_context()
227 228 229 230

    i = self.get_embedded_integer()
    top = limit.get_embedded_integer()
    while i <= top:
Stefan Marr's avatar
Stefan Marr committed
231
        jitdriver.jit_merge_point(interpreter=interpreter,
Stefan Marr's avatar
Stefan Marr committed
232
                                  block_method=block_method)
233

234 235 236 237 238
        b = universe.new_block(block_method, context)
        frame.push(b)
        frame.push(universe.new_integer(i))
        block_evaluate(b, interpreter, frame)
        frame.pop()
239 240
        i += 1

241 242
    frame.push(self)

243
class IntegerPrimitives(Primitives):
Stefan Marr's avatar
Stefan Marr committed
244 245 246

    def install_primitives(self):
        self._install_instance_primitive(Primitive("asString", self._universe, _asString))
247
        self._install_instance_primitive(Primitive("sqrt",     self._universe, _sqrt))
Stefan Marr's avatar
Stefan Marr committed
248
        self._install_instance_primitive(Primitive("atRandom", self._universe, _atRandom))
249 250 251
        
        self._install_instance_primitive(Primitive("+",  self._universe, _plus))
        self._install_instance_primitive(Primitive("-",  self._universe, _minus))
Stefan Marr's avatar
Stefan Marr committed
252

253
        self._install_instance_primitive(Primitive("*",  self._universe, _mult))
Stefan Marr's avatar
Stefan Marr committed
254
        self._install_instance_primitive(Primitive("//", self._universe, _doubleDiv))
255 256 257 258 259
        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))
Stefan Marr's avatar
Stefan Marr committed
260
        
261 262
        self._install_instance_primitive(Primitive("to:do:", self._universe, _toDo))
        
Stefan Marr's avatar
Stefan Marr committed
263
        self._install_class_primitive(Primitive("fromString:", self._universe, _fromString))