packages feed

Fungi-1.0.6: src/Ip.hs

module Ip (
    Ip
  , mkIp

  , getId
  , getPos
  , getDelta
  , getSs
  , isAlive
  , getStorageOffset
  , getSemantics
  , hrtiMark


  , testMode
  , addMode
  , removeMode
  , toggleMode

  , record
  , clearRecordings
  , getRecordings
  , getRecordLength
  , setRecordLength

  , killIp
  , reverseIp
  , setPos
  , setDelta
  , setSs
  , setStorageOffset

  ) where

import Control.Monad.State.Strict

import Data.Deque
import Data.I
import Data.Map (Map)
import Data.StackSet (StackSet)
import qualified Data.StackSet as StackSet
import Data.Sequence
import qualified Data.Sequence as Seq
import Data.Stack
import Data.Vector

import System.Time (ClockTime)

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 :: StackSet Mode
  , hrtiMark :: Maybe ClockTime
  , getRecordings :: Seq (Instruction env i ())
  , getRecordLength :: i
  }

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 (StackSet.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 = StackSet.empty
  , hrtiMark = Nothing
  , getRecordings = Seq.empty
  , getRecordLength = 0
  }

testMode :: Mode -> Ip env i -> Bool
testMode mode = StackSet.member mode . modes

addMode :: Mode -> Ip env i -> Ip env i
addMode mode ip = ip { modes = StackSet.insert mode $ modes ip }

removeMode :: Mode -> Ip env i -> Ip env i
removeMode mode ip = ip { modes = StackSet.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 }

setRecordLength :: i -> Ip env i -> Ip env i
setRecordLength n ip = ip { getRecordLength = n }

clearRecordings :: Ip env i -> Ip env i
clearRecordings ip = ip { getRecordings = Seq.empty }

record :: Instruction env i () -> Ip env i -> Ip env i
record instr ip = ip { getRecordings = getRecordings ip |> instr }