module VM.Instruction.Variable
( instLoadLocal
, instStoreLocal
, instLoadCapture
, instStoreCapture
, instLoadGlobal
, instStoreGlobal
) where
import Control.Monad.State.Strict (get, put)
import qualified Data.Vector as V
import VM.VMValue (VMValue)
import VM.VMState (VirtualMachine, VMState(..))
import VM.Bytecode.Reader (readInt32)
import VM.VMStack (stackPush, stackPop)
instLoadLocal :: VirtualMachine ()
instLoadLocal :: VirtualMachine ()
instLoadLocal = do
idx <- VirtualMachine Int
readInt32
vm <- get
let baseIdx = VMState -> Int
baseVStackIndex VMState
vm Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
idx
let stack = VMState -> Vector VMValue
vStack VMState
vm
case baseIdx >= 0 && baseIdx < V.length stack of
Bool
False -> [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error ([Char] -> VirtualMachine ()) -> [Char] -> VirtualMachine ()
forall a b. (a -> b) -> a -> b
$ [Char]
"VM Error: LOAD_LOCAL out of bounds (Index: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
Int -> [Char]
forall a. Show a => a -> [Char]
show Int
baseIdx [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
", Size: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (Vector VMValue -> Int
forall a. Vector a -> Int
V.length Vector VMValue
stack) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
Bool
True -> VMValue -> VirtualMachine ()
stackPush (Vector VMValue
stack Vector VMValue -> Int -> VMValue
forall a. Vector a -> Int -> a
V.! Int
baseIdx)
throwStoreError :: Int -> Int -> VirtualMachine ()
throwStoreError :: Int -> Int -> VirtualMachine ()
throwStoreError Int
idx Int
size = [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error ([Char] -> VirtualMachine ()) -> [Char] -> VirtualMachine ()
forall a b. (a -> b) -> a -> b
$
[Char]
"VM Error: STORE_LOCAL out of bounds (Idx: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
idx [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
[Char]
", Size: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
size [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
updateLocalVar :: VMState -> Int -> VMValue -> VirtualMachine ()
updateLocalVar :: VMState -> Int -> VMValue -> VirtualMachine ()
updateLocalVar VMState
vm Int
idx VMValue
val
| Int
idx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = Int -> Int -> VirtualMachine ()
throwStoreError Int
idx (Vector VMValue -> Int
forall a. Vector a -> Int
V.length (VMState -> Vector VMValue
vStack VMState
vm))
| Int
idx Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Vector VMValue -> Int
forall a. Vector a -> Int
V.length (VMState -> Vector VMValue
vStack VMState
vm) =
VMState -> VirtualMachine ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put (VMState -> VirtualMachine ()) -> VMState -> VirtualMachine ()
forall a b. (a -> b) -> a -> b
$ VMState
vm { vStack = V.snoc (vStack vm) val }
| Int
idx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Vector VMValue -> Int
forall a. Vector a -> Int
V.length (VMState -> Vector VMValue
vStack VMState
vm) =
VMState -> VirtualMachine ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put (VMState -> VirtualMachine ()) -> VMState -> VirtualMachine ()
forall a b. (a -> b) -> a -> b
$ VMState
vm { vStack = (vStack vm) V.// [(idx, val)] }
| Bool
otherwise = Int -> Int -> VirtualMachine ()
throwStoreError Int
idx (Vector VMValue -> Int
forall a. Vector a -> Int
V.length (VMState -> Vector VMValue
vStack VMState
vm))
instStoreLocal :: VirtualMachine ()
instStoreLocal :: VirtualMachine ()
instStoreLocal = do
idx <- VirtualMachine Int
readInt32
v <- stackPop
vm <- get
let absIdx = VMState -> Int
baseVStackIndex VMState
vm Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
idx
updateLocalVar vm absIdx v
instLoadCapture :: VirtualMachine ()
instLoadCapture :: VirtualMachine ()
instLoadCapture = do
idx <- VirtualMachine Int
readInt32
vm <- get
let currEnv = VMState -> Vector VMValue
env VMState
vm
case idx >= 0 && idx < V.length currEnv of
Bool
False -> [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error ([Char] -> VirtualMachine ()) -> [Char] -> VirtualMachine ()
forall a b. (a -> b) -> a -> b
$ [Char]
"VM Error: LOAD_CAPTURE out of bounds (" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
Int -> [Char]
forall a. Show a => a -> [Char]
show Int
idx [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
Bool
True -> VMValue -> VirtualMachine ()
stackPush (Vector VMValue
currEnv Vector VMValue -> Int -> VMValue
forall a. Vector a -> Int -> a
V.! Int
idx)
instStoreCapture :: VirtualMachine ()
instStoreCapture :: VirtualMachine ()
instStoreCapture = do
idx <- VirtualMachine Int
readInt32
val <- stackPop
vm <- get
let currEnv = VMState -> Vector VMValue
env VMState
vm
case idx >= 0 && idx < V.length currEnv of
Bool
False -> [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error ([Char] -> VirtualMachine ()) -> [Char] -> VirtualMachine ()
forall a b. (a -> b) -> a -> b
$ [Char]
"VM Error: STORE_CAPTURE out of bounds (" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
Int -> [Char]
forall a. Show a => a -> [Char]
show Int
idx [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
Bool
True -> VMState -> VirtualMachine ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put (VMState -> VirtualMachine ()) -> VMState -> VirtualMachine ()
forall a b. (a -> b) -> a -> b
$ VMState
vm { env = currEnv V.// [(idx, val)] }
instLoadGlobal :: VirtualMachine ()
instLoadGlobal :: VirtualMachine ()
instLoadGlobal = do
idx <- VirtualMachine Int
readInt32
vm <- get
let gEnv = VMState -> Vector VMValue
globalEnv VMState
vm
case idx >= 0 && idx < V.length gEnv of
Bool
False -> [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error ([Char] -> VirtualMachine ()) -> [Char] -> VirtualMachine ()
forall a b. (a -> b) -> a -> b
$ [Char]
"VM Error: LOAD_GLOBAL out of bounds (" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
Int -> [Char]
forall a. Show a => a -> [Char]
show Int
idx [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
Bool
True -> VMValue -> VirtualMachine ()
stackPush (Vector VMValue
gEnv Vector VMValue -> Int -> VMValue
forall a. Vector a -> Int -> a
V.! Int
idx)
instStoreGlobal :: VirtualMachine ()
instStoreGlobal :: VirtualMachine ()
instStoreGlobal = do
idx <- VirtualMachine Int
readInt32
v <- stackPop
vm <- get
let gEnv = VMState -> Vector VMValue
globalEnv VMState
vm
case idx >= 0 && idx < V.length gEnv of
Bool
False -> [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error ([Char] -> VirtualMachine ()) -> [Char] -> VirtualMachine ()
forall a b. (a -> b) -> a -> b
$ [Char]
"VM Error: STORE_GLOBAL out of bounds (" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
Int -> [Char]
forall a. Show a => a -> [Char]
show Int
idx [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
Bool
True -> VMState -> VirtualMachine ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put (VMState -> VirtualMachine ()) -> VMState -> VirtualMachine ()
forall a b. (a -> b) -> a -> b
$ VMState
vm { globalEnv = gEnv V.// [(idx, v)] }