module Language.Subleq.Model.Prim (Address, Memory, SubleqState, Machine, getPC, putPC, readMem, writeMem, advancePC, runMachineStep, runMachine, runMachineWithHistory) where
import Language.Subleq.Model.Memory (Address, Memory)
import qualified Language.Subleq.Model.Memory as Mem
import Control.Monad.State
import Control.Arrow
type SubleqState a w m = (a, m)
type Machine a w m = State (SubleqState a w m)
getPC :: Machine a w m a
getPC = get >>= \(pc,_)-> return pc
putPC :: a -> Machine a w m ()
putPC pc = get >>= \(_,mem)-> put (pc,mem)
readMem :: (Memory a w m) => a -> Machine a w m w
readMem addr = get >>= \(_,mem)-> return (Mem.read addr mem)
writeMem :: (Memory a w m) => a -> w -> Machine a w m ()
writeMem addr val = get >>= \(pc,mem)-> put (pc, Mem.write addr val mem)
advancePC :: (Integral a, Memory a w m) => a -> Machine a w m ()
advancePC d = do
pc <- getPC
putPC (pc + fromIntegral d)
runMachineStep :: Machine a w m Bool -> SubleqState a w m -> SubleqState a w m
runMachineStep st m = m'
where
(_, m') = runState st m
runMachineWithHistory :: Machine a w m Bool -> SubleqState a w m -> (SubleqState a w m, [SubleqState a w m])
runMachineWithHistory st m = cont `seq` if cont then second (m:) $ runMachineWithHistory st m' else (m', [m,m'])
where
(cont, m') = runState st m
runMachine :: Machine a w m Bool -> SubleqState a w m -> SubleqState a w m
runMachine st m = cont `seq` if cont then runMachine st m' else m'
where
(cont, m') = runState st m