Unify simple instruction actions
This commit is contained in:
@@ -27,7 +27,6 @@ executable MVM
|
|||||||
other-modules:
|
other-modules:
|
||||||
VirtualMachine
|
VirtualMachine
|
||||||
Instruction
|
Instruction
|
||||||
Command
|
|
||||||
Parser
|
Parser
|
||||||
Interpreter
|
Interpreter
|
||||||
Util
|
Util
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
module Command (
|
|
||||||
Command(..)
|
|
||||||
) where
|
|
||||||
|
|
||||||
import qualified Instruction as I
|
|
||||||
|
|
||||||
data Command = Command { instr :: I.Instruction
|
|
||||||
, args :: [Int]
|
|
||||||
} deriving (Eq, Show)
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
module Instruction (
|
module Instruction (
|
||||||
Op(..),
|
Op(..),
|
||||||
Instruction(..),
|
Instruction(..),
|
||||||
|
Command(..),
|
||||||
instructions,
|
instructions,
|
||||||
instructionByOp,
|
instructionByOp,
|
||||||
toOp
|
toOp
|
||||||
@@ -8,6 +9,9 @@ module Instruction (
|
|||||||
|
|
||||||
import qualified Data.Char as Char
|
import qualified Data.Char as Char
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
import qualified Data.Sequence as S
|
||||||
|
|
||||||
|
import qualified VirtualMachine as VM
|
||||||
|
|
||||||
data Op = Nop -- 0x00
|
data Op = Nop -- 0x00
|
||||||
| Halt -- 0x01
|
| Halt -- 0x01
|
||||||
@@ -33,24 +37,33 @@ data Op = Nop -- 0x00
|
|||||||
| Ld -- 0x15
|
| Ld -- 0x15
|
||||||
deriving (Eq, Ord, Enum, Show, Read, Bounded)
|
deriving (Eq, Ord, Enum, Show, Read, Bounded)
|
||||||
|
|
||||||
|
type Args = [Int]
|
||||||
|
type Pops = [Int]
|
||||||
|
type Pushes = S.Seq Int
|
||||||
|
|
||||||
data Instruction = Simple { op :: Op
|
data Instruction = Simple { op :: Op
|
||||||
, noParams :: Int
|
, noParams :: Int
|
||||||
, noPops :: Int }
|
, noPops :: Int
|
||||||
| Complex { op :: Op
|
, sAction :: Args -> Pops -> Pushes
|
||||||
|
}
|
||||||
|
| Complex { op :: Op
|
||||||
|
, cAction :: VM.VM -> Command -> Either String VM.VM
|
||||||
|
}
|
||||||
|
|
||||||
|
data Command = Command { instr :: Instruction
|
||||||
|
, args :: [Int]
|
||||||
}
|
}
|
||||||
deriving (Eq, Show)
|
|
||||||
|
|
||||||
instructions :: [Instruction]
|
instructions :: [Instruction]
|
||||||
instructions = [ Simple { op = Nop, noParams = 0, noPops = 0 }
|
instructions = [ Simple { op = Nop, noParams = 0, noPops = 0, sAction = (\_ _ -> S.empty) }
|
||||||
, Simple { op = Halt, noParams = 0, noPops = 0 }
|
, Simple { op = Halt, noParams = 0, noPops = 0, sAction = (\_ _ -> S.empty) }
|
||||||
, Simple { op = Push, noParams = 1, noPops = 0 }
|
, Simple { op = Push, noParams = 1, noPops = 0, sAction = (\args _ -> S.fromList args) }
|
||||||
, Simple { op = Pop, noParams = 0, noPops = 1 }
|
, Simple { op = Pop, noParams = 0, noPops = 1, sAction = (\_ _ -> S.empty) }
|
||||||
]
|
]
|
||||||
|
|
||||||
instructionByOp :: Map.Map Op Instruction
|
instructionByOp :: Map.Map Op Instruction
|
||||||
instructionByOp = Map.fromList $ map (\i -> (op i, i)) instructions
|
instructionByOp = Map.fromList $ map (\i -> (op i, i)) instructions
|
||||||
|
|
||||||
|
|
||||||
toOp :: String -> Op
|
toOp :: String -> Op
|
||||||
toOp = read . capitalize
|
toOp = read . capitalize
|
||||||
where capitalize :: String -> String
|
where capitalize :: String -> String
|
||||||
|
|||||||
@@ -4,46 +4,36 @@ module Interpreter (
|
|||||||
|
|
||||||
import Data.Word
|
import Data.Word
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
|
import Data.Foldable
|
||||||
import qualified Data.Sequence as S
|
import qualified Data.Sequence as S
|
||||||
|
|
||||||
import qualified Command as C
|
|
||||||
import qualified Instruction as I
|
import qualified Instruction as I
|
||||||
import qualified VirtualMachine as VM
|
import qualified VirtualMachine as VM
|
||||||
|
|
||||||
interpret :: [C.Command] -> VM.VM -> Either String VM.VM
|
interpret :: [I.Command] -> VM.VM -> Either String VM.VM
|
||||||
interpret _ vm@(VM.VM _ _ _ True) = Right $ vm
|
interpret _ vm@(VM.VM _ _ _ True) = Right $ vm
|
||||||
interpret cmds vm = do
|
interpret cmds vm = do
|
||||||
vm' <- interpretCommand cmds vm
|
vm' <- interpretCommand cmds vm
|
||||||
interpret cmds vm'
|
interpret cmds vm'
|
||||||
|
|
||||||
interpretCommand :: [C.Command] -> VM.VM -> Either String VM.VM
|
interpretCommand :: [I.Command] -> VM.VM -> Either String VM.VM
|
||||||
interpretCommand [] _ = Left $ "Empty code"
|
interpretCommand [] _ = Left $ "Empty code"
|
||||||
interpretCommand cmds vm@(VM.VM pc _ _ _)
|
interpretCommand cmds vm@(VM.VM pc _ _ _)
|
||||||
| pc >= length cmds = Right $ vm { VM.halt = True }
|
| pc >= length cmds = Right $ vm { VM.halt = True }
|
||||||
| otherwise = case instr of
|
| otherwise = case instr of
|
||||||
(I.Simple _ _ _) -> interpretSimple vm cmd
|
(I.Simple _ _ _ _) -> interpretSimple vm cmd
|
||||||
(I.Complex _) -> interpretComplex vm cmd
|
(I.Complex _ _) -> interpretComplex vm cmd
|
||||||
where cmd@(C.Command instr _) = cmds !! pc
|
where cmd@(I.Command instr _) = cmds !! pc
|
||||||
|
|
||||||
interpretSimple :: VM.VM -> C.Command -> Either String VM.VM
|
interpretSimple :: VM.VM -> I.Command -> Either String VM.VM
|
||||||
interpretSimple vm (C.Command (I.Simple op _ noPops) args) = vm'
|
interpretSimple vm (I.Command (I.Simple op _ noPops operation) args) = vm'
|
||||||
where
|
where
|
||||||
pops = [1, 2, 3]
|
pops = toList . S.take noPops . VM.stack $ vm
|
||||||
stack' = case op of
|
stack' = Right $ operation args pops
|
||||||
I.Nop -> Right $ nop vm args pops
|
|
||||||
I.Halt -> Right $ nop vm args pops
|
|
||||||
I.Push -> Right $ push vm args pops
|
|
||||||
_ -> Left $ "Unknown operator"
|
|
||||||
vm' = stack' >>= (\s -> Right $ vm { VM.pc = VM.pc vm + 1
|
vm' = stack' >>= (\s -> Right $ vm { VM.pc = VM.pc vm + 1
|
||||||
, VM.stack = VM.stack vm <> s
|
, VM.stack = (S.drop noPops . VM.stack) vm <> s
|
||||||
})
|
})
|
||||||
interpretSimple _ _ = Left $ "Unknown operation"
|
interpretSimple _ _ = Left $ "Unknown operation"
|
||||||
|
|
||||||
interpretComplex :: VM.VM -> C.Command -> Either String VM.VM
|
interpretComplex :: VM.VM -> I.Command -> Either String VM.VM
|
||||||
interpretComplex _ _ = Left "Not implemented yet"
|
interpretComplex _ _ = Left "Not implemented yet"
|
||||||
|
|
||||||
nop :: VM.VM -> [Int] -> [Int] -> S.Seq Int
|
|
||||||
nop vm _ _ = S.empty
|
|
||||||
|
|
||||||
push :: VM.VM -> [Int] -> [Int] -> S.Seq Int
|
|
||||||
push vm args _ = S.fromList args
|
|
||||||
@@ -6,24 +6,23 @@ import Data.Word
|
|||||||
import qualified Data.ByteString as B
|
import qualified Data.ByteString as B
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
|
||||||
import qualified Command as C
|
|
||||||
import qualified Instruction as I
|
import qualified Instruction as I
|
||||||
import qualified Util as U
|
import qualified Util as U
|
||||||
|
|
||||||
parse :: B.ByteString -> Either String [C.Command]
|
parse :: B.ByteString -> Either String [I.Command]
|
||||||
parse = parseCommands . B.unpack
|
parse = parseCommands . B.unpack
|
||||||
|
|
||||||
parseCommands :: [Word8] -> Either String [C.Command]
|
parseCommands :: [Word8] -> Either String [I.Command]
|
||||||
parseCommands [] = Right []
|
parseCommands [] = Right []
|
||||||
parseCommands code@(x:_) = case parseCommand code of
|
parseCommands code@(x:_) = case parseCommand code of
|
||||||
Just (cmd, rest) -> parseCommands rest >>= (\r -> return $ cmd : r)
|
Just (cmd, rest) -> parseCommands rest >>= (\r -> return $ cmd : r)
|
||||||
Nothing -> Left $ "Unparseable byte: " ++ U.byteStr x ++ "\nIn following sequence:\n" ++ U.bytesStr 16 code
|
Nothing -> Left $ "Unparseable byte: " ++ U.byteStr x ++ "\nIn following sequence:\n" ++ U.bytesStr 16 code
|
||||||
|
|
||||||
parseCommand :: [Word8] -> Maybe (C.Command, [Word8])
|
parseCommand :: [Word8] -> Maybe (I.Command, [Word8])
|
||||||
parseCommand [] = Nothing
|
parseCommand [] = Nothing
|
||||||
parseCommand (opByte:xs) = do
|
parseCommand (opByte:xs) = do
|
||||||
let op = toEnum . fromIntegral $ opByte :: I.Op
|
let op = toEnum . fromIntegral $ opByte :: I.Op
|
||||||
instruction <- Map.lookup op I.instructionByOp
|
instruction <- Map.lookup op I.instructionByOp
|
||||||
let noParams = I.noParams instruction
|
let noParams = I.noParams instruction
|
||||||
let params = map fromIntegral $ take noParams xs :: [Int]
|
let params = map fromIntegral $ take noParams xs :: [Int]
|
||||||
return (C.Command instruction params, drop noParams xs)
|
return (I.Command instruction params, drop noParams xs)
|
||||||
Reference in New Issue
Block a user