module VM.Bytecode.Runner
( runBytecode
, executeInstruction
) where
import Control.Monad.State.Strict (get, liftIO)
import Data.Word (Word8)
import qualified Data.Vector as V
import VM.VMState (VMState(..), VirtualMachine)
import VM.Bytecode.Reader (readByte)
import VM.Instruction.Index
import VM.Instruction.Stack
import VM.Instruction.Arithmetic
import VM.Instruction.Logic
import VM.Instruction.Struct
import VM.Instruction.List
import VM.Instruction.Function
import VM.Instruction.Variable
import VM.Instruction.System
import VM.Instruction.Io
executeInstruction :: Word8 -> VirtualMachine ()
executeInstruction :: Word8 -> VirtualMachine ()
executeInstruction Word8
0x01 = VirtualMachine ()
instPush
executeInstruction Word8
0x02 = VirtualMachine ()
instPop
executeInstruction Word8
0x03 = VirtualMachine ()
instDup
executeInstruction Word8
0x04 = VirtualMachine ()
instSwap
executeInstruction Word8
0x10 = VirtualMachine ()
instAdd
executeInstruction Word8
0x11 = VirtualMachine ()
instSub
executeInstruction Word8
0x12 = VirtualMachine ()
instMul
executeInstruction Word8
0x13 = VirtualMachine ()
instDiv
executeInstruction Word8
0x14 = VirtualMachine ()
instMod
executeInstruction Word8
0x20 = VirtualMachine ()
instEq
executeInstruction Word8
0x21 = VirtualMachine ()
instLt
executeInstruction Word8
0x22 = VirtualMachine ()
instNot
executeInstruction Word8
0x23 = VirtualMachine ()
instAnd
executeInstruction Word8
0x24 = VirtualMachine ()
instOr
executeInstruction Word8
0x25 = VirtualMachine ()
instLe
executeInstruction Word8
0x26 = VirtualMachine ()
instTEq
executeInstruction Word8
0x30 = VirtualMachine ()
instJump
executeInstruction Word8
0x31 = VirtualMachine ()
instJumpIfFalse
executeInstruction Word8
0x32 = VirtualMachine ()
instJumpIfTrue
executeInstruction Word8
0x40 = VirtualMachine ()
instCall
executeInstruction Word8
0x41 = VirtualMachine ()
instTailCall
executeInstruction Word8
0x42 = VirtualMachine ()
instCallIndirect
executeInstruction Word8
0x43 = VirtualMachine ()
instRet
executeInstruction Word8
0x50 = VirtualMachine ()
instLoadLocal
executeInstruction Word8
0x51 = VirtualMachine ()
instStoreLocal
executeInstruction Word8
0x52 = VirtualMachine ()
instLoadGlobal
executeInstruction Word8
0x53 = VirtualMachine ()
instStoreGlobal
executeInstruction Word8
0x54 = VirtualMachine ()
instLoadCapture
executeInstruction Word8
0x55 = VirtualMachine ()
instStoreCapture
executeInstruction Word8
0x60 = VirtualMachine ()
instMakeClosure
executeInstruction Word8
0x61 = VirtualMachine ()
instGetFuncAddr
executeInstruction Word8
0x62 = VirtualMachine ()
instBuildStruct
executeInstruction Word8
0x63 = VirtualMachine ()
instGetStructField
executeInstruction Word8
0x64 = VirtualMachine ()
instAttrUpdate
executeInstruction Word8
0x70 = VirtualMachine ()
instPrint
executeInstruction Word8
0x71 = VirtualMachine ()
instHalt
executeInstruction Word8
0x72 = VirtualMachine ()
instExit
executeInstruction Word8
0x80 = VirtualMachine ()
instCast
executeInstruction Word8
0x81 = VirtualMachine ()
instTypeOf
executeInstruction Word8
0x82 = VirtualMachine ()
instSizeOf
executeInstruction Word8
0x90 = VirtualMachine ()
instCons
executeInstruction Word8
0x91 = VirtualMachine ()
instHead
executeInstruction Word8
0x92 = VirtualMachine ()
instTail
executeInstruction Word8
0x93 = VirtualMachine ()
instNth
executeInstruction Word8
0x94 = VirtualMachine ()
instBuildList
executeInstruction Word8
0x95 = VirtualMachine ()
instNthUpdate
executeInstruction Word8
0xA0 = VirtualMachine ()
instOpen
executeInstruction Word8
0xA1 = VirtualMachine ()
instRead
executeInstruction Word8
0xA2 = VirtualMachine ()
instWrite
executeInstruction Word8
0xA3 = VirtualMachine ()
instClose
executeInstruction Word8
0xA4 = VirtualMachine ()
instInput
executeInstruction Word8
0xFE = VirtualMachine ()
instCheckStack
executeInstruction Word8
0xFF = () -> VirtualMachine ()
forall a. a -> StateT VMState IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
executeInstruction Word8
op = [Char] -> VirtualMachine ()
forall a. HasCallStack => [Char] -> a
error ([Char] -> VirtualMachine ()) -> [Char] -> VirtualMachine ()
forall a b. (a -> b) -> a -> b
$ [Char]
"VM Error: Unknown Opcode 0x" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Word8 -> [Char]
forall a. Show a => a -> [Char]
show Word8
op
debugTrace :: VMState -> IO ()
debugTrace :: VMState -> IO ()
debugTrace VMState
vm = let ip :: Int
ip = VMState -> Int
bytecodeIndex VMState
vm
stack :: Vector VMValue
stack = VMState -> Vector VMValue
vStack VMState
vm in
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"IP: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
ip [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" | Stack: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [VMValue] -> [Char]
forall a. Show a => a -> [Char]
show (Vector VMValue -> [VMValue]
forall a. Vector a -> [a]
V.toList Vector VMValue
stack)
runBytecode :: VirtualMachine ()
runBytecode :: VirtualMachine ()
runBytecode = do
vm <- StateT VMState IO VMState
forall s (m :: * -> *). MonadState s m => m s
get
case isRunning vm of
Bool
False -> () -> VirtualMachine ()
forall a. a -> StateT VMState IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Bool
True -> do
if VMState -> Bool
isDebug VMState
vm then IO () -> VirtualMachine ()
forall a. IO a -> StateT VMState IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> VirtualMachine ()) -> IO () -> VirtualMachine ()
forall a b. (a -> b) -> a -> b
$ VMState -> IO ()
debugTrace VMState
vm else () -> VirtualMachine ()
forall a. a -> StateT VMState IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
opcode <- VirtualMachine Word8
readByte
executeInstruction opcode
runBytecode