module Yabi.Engine ( run , initWorld ) where import Control.Monad.Trans import Data.ByteString import Control.Lens import System.IO (stdin, stdout) import Prelude hiding (null, head) import qualified Data.IntMap as IM import Yabi.Types initWorld :: World initWorld = World IM.empty 0 run :: [Inst] -> VM () run [] = return () run (x:xs) = inst x >> run xs inst :: Inst -> VM () inst Next = pos += 1 inst Prev = pos -= 1 inst Incr = use pos >>= \p -> array . at p %= Just . maybe 1 (+1) inst Decr = use pos >>= \p -> array . at p %= Just . maybe (-1) (+ (-1)) inst GetC = do bs <- liftIO $ hGet stdin 1 p <- use pos array . at p ?= if null bs then -1 else head bs inst PutC = do p <- use pos c <- uses (array . at p) (maybe 0 id) liftIO $ hPut stdout (pack [c]) inst (Loop blk) = do p <- use pos c <- uses (array . at p) (maybe 0 id) if c == 0 then return () else run blk >> inst (Loop blk)