Improve simple and complex instructions interpreters
This commit is contained in:
@@ -134,9 +134,12 @@ output _ _ [] = except $ Left $ "Empty stack - nothing to output"
|
|||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
push :: [Int] -> State VM ()
|
push :: [Int] -> State VM ()
|
||||||
push numbers = do
|
push = pushS . S.fromList
|
||||||
|
|
||||||
|
pushS :: S.Seq Int -> State VM ()
|
||||||
|
pushS numbers = do
|
||||||
vm <- get
|
vm <- get
|
||||||
put vm { _stack = S.fromList numbers <> _stack vm }
|
put vm { _stack = numbers <> _stack vm }
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
pop :: Int -> State VM [Int]
|
pop :: Int -> State VM [Int]
|
||||||
@@ -146,12 +149,6 @@ pop count = do
|
|||||||
put vm { _stack = S.drop count $ stack }
|
put vm { _stack = S.drop count $ stack }
|
||||||
return $ toList $ S.take 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 :: Int -> String -> ExceptT String (State VM) Int
|
||||||
getAt index err = do
|
getAt index err = do
|
||||||
vm <- get
|
vm <- get
|
||||||
@@ -160,6 +157,15 @@ getAt index err = do
|
|||||||
(Just i) -> return i
|
(Just i) -> return i
|
||||||
Nothing -> except $ Left err
|
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
|
instructionByOp :: M.Map Op Instruction
|
||||||
@@ -212,32 +218,30 @@ dispatchInstr vm units instr = case instr of
|
|||||||
Complex {} -> interpretComplex vm units instr
|
Complex {} -> interpretComplex vm units instr
|
||||||
|
|
||||||
interpretSimple :: VM -> [Unit] -> Instruction -> VM
|
interpretSimple :: VM -> [Unit] -> Instruction -> VM
|
||||||
interpretSimple vm units instr = vm'
|
interpretSimple vm units instr = flip execState vm $ do
|
||||||
where
|
pc <- getPc
|
||||||
stack = _stack vm
|
let noParams = _noParams instr
|
||||||
pc = _pc vm
|
let noPops = _noPops instr
|
||||||
noParams = _noParams instr
|
let paramBytes = take noParams $ drop (pc + 1) $ units
|
||||||
noPops = _noPops instr
|
let params = map (fromIntegral . _byte) paramBytes
|
||||||
|
let action = _sAction instr
|
||||||
paramBytes = take noParams $ drop (pc + 1) $ units :: [Unit]
|
pops <- pop noPops
|
||||||
params = map (fromIntegral . _byte) paramBytes :: [Int]
|
let pushes = action params pops
|
||||||
pops = toList $ S.take noPops $ stack :: [Int]
|
pushS pushes
|
||||||
|
forward $ noParams + 1
|
||||||
action = _sAction instr
|
return ()
|
||||||
pushes = action params pops
|
|
||||||
vm' = vm { _pc = pc + noParams + 1, _stack = pushes <> (S.drop noPops stack) }
|
|
||||||
|
|
||||||
interpretComplex :: VM -> [Unit] -> Instruction -> ExceptT String IO VM
|
interpretComplex :: VM -> [Unit] -> Instruction -> ExceptT String IO VM
|
||||||
interpretComplex vm units instr = action vm params pops
|
interpretComplex vm units instr = action vm params pops
|
||||||
where
|
where
|
||||||
stack = _stack vm
|
|
||||||
pc = _pc vm
|
pc = _pc vm
|
||||||
noParams = _noParams instr
|
noParams = _noParams instr
|
||||||
noPops = _noPops instr
|
noPops = _noPops instr
|
||||||
|
|
||||||
paramBytes = take noParams $ drop (pc + 1) $ units :: [Unit]
|
paramBytes = take noParams $ drop (pc + 1) $ units
|
||||||
params = map (fromIntegral . _byte) paramBytes :: [Int]
|
params = map (fromIntegral . _byte) paramBytes
|
||||||
pops = toList $ S.take noPops $ stack :: [Int]
|
pops = evalState (pop noPops) vm
|
||||||
|
|
||||||
action = _cAction instr
|
action = _cAction instr
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user