From 24fd8fa26f1714264f4bb730f4ca5449deda27be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Przemys=C5=82aw=20Pluta?= Date: Tue, 9 Nov 2021 15:51:51 +0100 Subject: [PATCH] Improve simple and complex instructions interpreters --- app/VirtualMachine.hs | 58 +++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/app/VirtualMachine.hs b/app/VirtualMachine.hs index 479ce01..81a272c 100644 --- a/app/VirtualMachine.hs +++ b/app/VirtualMachine.hs @@ -134,9 +134,12 @@ output _ _ [] = except $ Left $ "Empty stack - nothing to output" -------------------------------------------------------------------------- push :: [Int] -> State VM () -push numbers = do +push = pushS . S.fromList + +pushS :: S.Seq Int -> State VM () +pushS numbers = do vm <- get - put vm { _stack = S.fromList numbers <> _stack vm } + put vm { _stack = numbers <> _stack vm } return () pop :: Int -> State VM [Int] @@ -146,12 +149,6 @@ pop count = do put vm { _stack = S.drop count $ stack } return $ toList $ S.take count $ stack -popThenPush :: Int -> [Int] -> State VM [Int] -popThenPush count numbers = do - pops <- pop count - push numbers - return pops - getAt :: Int -> String -> ExceptT String (State VM) Int getAt index err = do vm <- get @@ -160,6 +157,15 @@ getAt index err = do (Just i) -> return i Nothing -> except $ Left err +forward :: Int -> State VM () +forward offset = do + vm <- get + put vm { _pc = _pc vm + offset } + return () + +getPc :: State VM Int +getPc = get >>= (return . _pc) + -------------------------------------------------------------------------- instructionByOp :: M.Map Op Instruction @@ -212,32 +218,30 @@ dispatchInstr vm units instr = case instr of Complex {} -> interpretComplex vm units instr interpretSimple :: VM -> [Unit] -> Instruction -> VM -interpretSimple vm units instr = vm' - where - stack = _stack vm - pc = _pc vm - noParams = _noParams instr - noPops = _noPops instr - - paramBytes = take noParams $ drop (pc + 1) $ units :: [Unit] - params = map (fromIntegral . _byte) paramBytes :: [Int] - pops = toList $ S.take noPops $ stack :: [Int] - - action = _sAction instr - pushes = action params pops - vm' = vm { _pc = pc + noParams + 1, _stack = pushes <> (S.drop noPops stack) } +interpretSimple vm units instr = flip execState vm $ do + pc <- getPc + let noParams = _noParams instr + let noPops = _noPops instr + let paramBytes = take noParams $ drop (pc + 1) $ units + let params = map (fromIntegral . _byte) paramBytes + let action = _sAction instr + pops <- pop noPops + let pushes = action params pops + pushS pushes + forward $ noParams + 1 + return () + interpretComplex :: VM -> [Unit] -> Instruction -> ExceptT String IO VM interpretComplex vm units instr = action vm params pops - where - stack = _stack vm + where pc = _pc vm noParams = _noParams instr noPops = _noPops instr - paramBytes = take noParams $ drop (pc + 1) $ units :: [Unit] - params = map (fromIntegral . _byte) paramBytes :: [Int] - pops = toList $ S.take noPops $ stack :: [Int] + paramBytes = take noParams $ drop (pc + 1) $ units + params = map (fromIntegral . _byte) paramBytes + pops = evalState (pop noPops) vm action = _cAction instr