module VM.Instruction.Function
( instCall
, instTailCall
, instCallIndirect
, instRet
, instMakeClosure
, instGetFuncAddr
) where
import Control.Monad.State.Strict (get, put)
import qualified Data.Vector as V
import VM.VMState (VirtualMachine, VMState(..), doSnapshot)
import VM.VMValue (VMValue(..))
import VM.CallSnapshot (CallSnapshot(..))
import VM.Bytecode.Reader (readInt32)
import VM.VMStack (stackPop, stackPush)
instCall :: VirtualMachine ()
instCall :: VirtualMachine ()
instCall = do
offset <- VirtualMachine Int
readInt32
vm <- get
doSnapshot (bytecodeIndex vm + offset) V.empty
instTailCall :: VirtualMachine ()
instTailCall :: VirtualMachine ()
instTailCall = do
offset <- VirtualMachine Int
readInt32
vm <- get
put $ vm { baseVStackIndex = V.length (vStack vm),
bytecodeIndex = bytecodeIndex vm + offset, env = V.empty }
dispatchIndirectCall :: VMValue -> VirtualMachine ()
dispatchIndirectCall :: VMValue -> VirtualMachine ()
dispatchIndirectCall (VClosure Int
addr Vector VMValue
caps) = Int -> Vector VMValue -> VirtualMachine ()
doSnapshot Int
addr Vector VMValue
caps
dispatchIndirectCall (VFuncPtr Int
addr) = Int -> Vector VMValue -> VirtualMachine ()
doSnapshot Int
addr Vector VMValue
forall a. Vector a
V.empty
dispatchIndirectCall VMValue
x = [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error ([Char] -> VirtualMachine ()) -> [Char] -> VirtualMachine ()
forall a b. (a -> b) -> a -> b
$ [Char]
"VM Error: Not callable: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ VMValue -> [Char]
forall a. Show a => a -> [Char]
show VMValue
x
instCallIndirect :: VirtualMachine ()
instCallIndirect :: VirtualMachine ()
instCallIndirect = do
callee <- VirtualMachine VMValue
stackPop
dispatchIndirectCall callee
pushClosure :: VMState -> Int -> Int -> VirtualMachine ()
pushClosure :: VMState -> Int -> Int -> VirtualMachine ()
pushClosure VMState
vm Int
addr Int
count =
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 (Int -> Vector VMValue -> VMValue
VClosure Int
addr (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)))
where 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
instMakeClosure :: VirtualMachine ()
instMakeClosure :: VirtualMachine ()
instMakeClosure = do
offset <- VirtualMachine Int
readInt32
count <- readInt32
vm <- get
let absAddr = VMState -> Int
bytecodeIndex VMState
vm Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
offset
case V.length (vStack vm) >= count of
Bool
False -> [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error [Char]
"VM Error: MAKE_CLOSURE Stack Underflow"
Bool
True -> VMState -> Int -> Int -> VirtualMachine ()
pushClosure VMState
vm Int
absAddr Int
count
execReturn :: VMState -> CallSnapshot -> [CallSnapshot] -> VMValue -> Int ->
VirtualMachine ()
execReturn :: VMState
-> CallSnapshot
-> [CallSnapshot]
-> VMValue
-> Int
-> VirtualMachine ()
execReturn VMState
vm CallSnapshot
snap [CallSnapshot]
rest VMValue
v Int
nArgs = VMState -> VirtualMachine ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put (VMState
vm { bytecodeIndex = callbackIndex snap,
baseVStackIndex = vStackIndex snap, env = vEnv snap, snapshotStack = rest,
vStack = V.take (baseVStackIndex vm - nArgs) (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 VMValue
v
instRet :: VirtualMachine ()
instRet :: VirtualMachine ()
instRet = do
nArgs <- VirtualMachine Int
readInt32
retVal <- stackPop
vm <- get
case snapshotStack vm of
[] -> [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error [Char]
"VM Error: Return called with empty call stack"
(CallSnapshot
snap:[CallSnapshot]
rest) -> VMState
-> CallSnapshot
-> [CallSnapshot]
-> VMValue
-> Int
-> VirtualMachine ()
execReturn VMState
vm CallSnapshot
snap [CallSnapshot]
rest VMValue
retVal Int
nArgs
instGetFuncAddr :: VirtualMachine ()
instGetFuncAddr :: VirtualMachine ()
instGetFuncAddr = do
addr <- VirtualMachine Int
readInt32
stackPush (VFuncPtr addr)