module VM.Instruction.Struct
( instBuildStruct
, instGetStructField
, instAttrUpdate
, pushStruct
) where
import qualified Data.Vector as V
import Control.Monad.State.Strict (get, put)
import VM.VMState (VMState(..), VirtualMachine)
import VM.VMValue (VMValue(..))
import VM.VMStack (stackPush, stackPop)
import VM.Bytecode.Reader (readInt32)
import Common.Type.Integer (intValueToInt)
pushStruct :: VMState -> Int -> VirtualMachine ()
pushStruct :: VMState -> Int -> VirtualMachine ()
pushStruct VMState
vm Int
count =
let start :: Int
start = Vector VMValue -> Int
forall a. Vector a -> Int
V.length (VMState -> Vector VMValue
vStack VMState
vm) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
count
fields :: Vector VMValue
fields = Int -> Int -> Vector VMValue -> Vector VMValue
forall a. Int -> Int -> Vector a -> Vector a
V.slice Int
start Int
count (VMState -> Vector VMValue
vStack VMState
vm) in
VMState -> VirtualMachine ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put (VMState
vm { vStack = V.take start (vStack vm) }) VirtualMachine () -> VirtualMachine () -> VirtualMachine ()
forall a b.
StateT VMState IO a -> StateT VMState IO b -> StateT VMState IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
VMValue -> VirtualMachine ()
stackPush (Vector VMValue -> VMValue
VStruct Vector VMValue
fields)
instBuildStruct :: VirtualMachine ()
instBuildStruct :: VirtualMachine ()
instBuildStruct = do
count <- VirtualMachine Int
readInt32
vm <- get
case V.length (vStack vm) >= count of
Bool
False -> [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error [Char]
"VM Error: BUILD_STRUCT Stack Underflow"
Bool
True -> VMState -> Int -> VirtualMachine ()
pushStruct VMState
vm Int
count
instGetStructField :: VirtualMachine ()
instGetStructField :: VirtualMachine ()
instGetStructField = do
idx <- VirtualMachine Int
readInt32
v <- stackPop
case v of
VStruct Vector VMValue
fields -> case Int
idx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
idx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Vector VMValue -> Int
forall a. Vector a -> Int
V.length Vector VMValue
fields of
Bool
True -> VMValue -> VirtualMachine ()
stackPush (Vector VMValue
fields Vector VMValue -> Int -> VMValue
forall a. Vector a -> Int -> a
V.! Int
idx)
Bool
False -> [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error ([Char] -> VirtualMachine ()) -> [Char] -> VirtualMachine ()
forall a b. (a -> b) -> a -> b
$ [Char]
"VM Error: Struct Field Access Out of Bounds " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
[Char]
"(" [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]
")"
VMValue
_ -> [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error [Char]
"VM Error: GET_STRUCT_FIELD expects a Struct"
instAttrUpdate :: VirtualMachine ()
instAttrUpdate :: VirtualMachine ()
instAttrUpdate = do
v <- VirtualMachine VMValue
stackPop
idx <- stackPop
struct <- stackPop
case (struct, idx) of
(VStruct Vector VMValue
vec, VInt IntValue
vi) -> let i :: Int
i = IntValue -> Int
intValueToInt IntValue
vi in
case Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Vector VMValue -> Int
forall a. Vector a -> Int
V.length Vector VMValue
vec of
Bool
True -> VMValue -> VirtualMachine ()
stackPush (Vector VMValue -> VMValue
VStruct (Vector VMValue
vec Vector VMValue -> [(Int, VMValue)] -> Vector VMValue
forall a. Vector a -> [(Int, a)] -> Vector a
V.// [(Int
i, VMValue
v)]))
Bool
False -> [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error ([Char] -> VirtualMachine ()) -> [Char] -> VirtualMachine ()
forall a b. (a -> b) -> a -> b
$ [Char]
"VM Error: attr_update OOB (" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
i [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
(VMValue
other, VMValue
_) -> [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error ([Char] -> VirtualMachine ()) -> [Char] -> VirtualMachine ()
forall a b. (a -> b) -> a -> b
$ [Char]
"VM Error: attr_update not struct " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ VMValue -> [Char]
forall a. Show a => a -> [Char]
show VMValue
other