module Ip ( Ip , mkIp , getId , getPos , getDelta , getSs , isAlive , getStorageOffset , getSemantics , testMode , addMode , removeMode , toggleMode , killIp , reverseIp , setPos , setDelta , setSs , setStorageOffset ) where import Control.Monad.State.Strict import Data.Deque import Data.I import Data.Map (Map) import Data.Set (Set) import qualified Data.Set as Set import Data.Stack import Data.Vector import Text.PrettyShow import Mode import Semantics ----------------------------------------------------------- type Instruction env i = StateT (env i) IO data Ip env i = Ip { getId :: i , getPos :: Vector i , getDelta :: Vector i , getSs :: Stack (Deque i) , isAlive :: Bool , getStorageOffset :: !(Vector i) , getSemantics :: Semantics env i , modes :: Set Mode } instance (PrettyShow i) => PrettyShow (Ip env i) where pshow ip = concat [ [] , "(IP" , " " , "id=" ++ pshow (getId ip) , " " , "pos=" ++ pshow (getPos ip) , " " , "delta=" ++ pshow (getDelta ip) , " " , "modes=" ++ pshow (Set.toList $ modes ip) , ")" ] mkIp :: (I i) => Int -> i -> Map i (Instruction env i ()) -> Ip env i mkIp dim ident baseSemantics = Ip { getId = ident , getPos = takeV dim 0 , getDelta = takeV dim (1 `cons` 0) , getSs = mkStack1 mkDeque , isAlive = True , getStorageOffset = takeV dim 0 , getSemantics = mkSemantics baseSemantics , modes = Set.empty } testMode :: Mode -> Ip env i -> Bool testMode mode = Set.member mode . modes addMode :: Mode -> Ip env i -> Ip env i addMode mode ip = ip { modes = Set.insert mode $ modes ip } removeMode :: Mode -> Ip env i -> Ip env i removeMode mode ip = ip { modes = Set.delete mode $ modes ip } toggleMode :: Mode -> Ip env i -> Ip env i toggleMode mode ip = if testMode mode ip then removeMode mode ip else addMode mode ip killIp :: Ip env i -> Ip env i killIp ip = ip { isAlive = False } reverseIp :: (Num i) => Ip env i -> Ip env i reverseIp ip = ip { getDelta = negate . getDelta $ ip } setPos :: (Num i) => Vector i -> Ip env i -> Ip env i setPos pos ip = ip { getPos = pos } setDelta :: (Num i) => Vector i -> Ip env i -> Ip env i setDelta delta ip = ip { getDelta = delta } setSs :: Stack (Deque i) -> Ip env i -> Ip env i setSs s ip = ip { getSs = s } setStorageOffset :: Vector i -> Ip env i -> Ip env i setStorageOffset v ip = ip { getStorageOffset = v }