module VM.Instruction.Arithmetic
( instAdd
, instSub
, instMul
, instDiv
, instMod
, binaryInstInt
, binaryInstIntZero
) where
import Common.Type.Integer (IntValue(..), intValueToInt)
import VM.VMState (VirtualMachine)
import VM.VMValue (VMValue(..))
import VM.VMStack (stackPush, stackPop)
binaryInstInt :: (Int -> Int -> Int) -> VirtualMachine ()
binaryInstInt :: (Int -> Int -> Int) -> VirtualMachine ()
binaryInstInt Int -> Int -> Int
fn = do
v2 <- VirtualMachine VMValue
stackPop
v1 <- stackPop
case (v1, v2) of
(VInt IntValue
i1, VInt IntValue
i2) ->
let result :: Int
result = Int -> Int -> Int
fn (IntValue -> Int
intValueToInt IntValue
i1) (IntValue -> Int
intValueToInt IntValue
i2) in
VMValue -> VirtualMachine ()
stackPush (IntValue -> VMValue
VInt (Int64 -> IntValue
I64 (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
result)))
(VMValue, VMValue)
_ -> [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error [Char]
"VM Error: Arithmetic instruction expects Integers"
binaryInstIntZero :: (Int -> Int -> Int) -> VirtualMachine ()
binaryInstIntZero :: (Int -> Int -> Int) -> VirtualMachine ()
binaryInstIntZero Int -> Int -> Int
fn = do
v2 <- VirtualMachine VMValue
stackPop
v1 <- stackPop
case (v1, v2) of
(VInt IntValue
i1, VInt IntValue
i2) -> let a :: Int
a = IntValue -> Int
intValueToInt IntValue
i1
b :: Int
b = IntValue -> Int
intValueToInt IntValue
i2 in
case Int
b Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 of
Bool
True -> [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error [Char]
"VM Error: Division by Zero"
Bool
False -> VMValue -> VirtualMachine ()
stackPush (IntValue -> VMValue
VInt (Int64 -> IntValue
I64 (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Int -> Int
fn Int
a Int
b))))
(VMValue, VMValue)
_ -> [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error [Char]
"VM Error: Arithmetic instruction expects Integers"
instAdd :: VirtualMachine ()
instAdd :: VirtualMachine ()
instAdd = (Int -> Int -> Int) -> VirtualMachine ()
binaryInstInt Int -> Int -> Int
forall a. Num a => a -> a -> a
(+)
instSub :: VirtualMachine ()
instSub :: VirtualMachine ()
instSub = (Int -> Int -> Int) -> VirtualMachine ()
binaryInstInt (-)
instMul :: VirtualMachine ()
instMul :: VirtualMachine ()
instMul = (Int -> Int -> Int) -> VirtualMachine ()
binaryInstInt Int -> Int -> Int
forall a. Num a => a -> a -> a
(*)
instDiv :: VirtualMachine ()
instDiv :: VirtualMachine ()
instDiv = (Int -> Int -> Int) -> VirtualMachine ()
binaryInstIntZero Int -> Int -> Int
forall a. Integral a => a -> a -> a
div
instMod :: VirtualMachine ()
instMod :: VirtualMachine ()
instMod = (Int -> Int -> Int) -> VirtualMachine ()
binaryInstIntZero Int -> Int -> Int
forall a. Integral a => a -> a -> a
mod