Guest User

Untitled

a guest
May 23rd, 2018
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.32 KB | None | 0 0
  1. {-# LANGUAGE OverloadedStrings #-}
  2. import Data.Array.IO
  3. import Data.Array.Base
  4. import Control.Applicative
  5. import Control.Monad.Loops
  6. import Data.Either
  7. import Data.Attoparsec.Char8
  8. import qualified Data.ByteString.Char8 as B
  9. import System.Environment
  10.  
  11. type Tape = IOUArray Int Int
  12.  
  13. main = do
  14. program <- B.readFile =<< head <$> getArgs
  15. tape <- newArray (0,30000) 0 :: IO Tape
  16. unsafeWrite tape 0 1
  17. either error id (parseOnly (bf tape) program)
  18.  
  19. bf :: Tape -> Parser (IO ())
  20. bf tape = (sequence_ <$>) . many $!
  21. (takeWhile1 (== '>') >>= return . next . B.length)
  22. <|> (takeWhile1 (== '<') >>= return . prev . B.length)
  23. <|> (takeWhile1 (== '+') >>= return . incr . B.length)
  24. <|> (takeWhile1 (== '-') >>= return . decr . B.length)
  25. <|> "." .*> return output
  26. <|> "," .*> return input
  27. <|> whileM_ nonzero <$> ("[" .*> bf tape <*. "]")
  28. <|> notChar ']' *> bf tape
  29.  
  30. where
  31. next n = exec $! \i v -> unsafeWrite tape 0 (i + n)
  32. prev n = exec $! \i v -> unsafeWrite tape 0 (i - n)
  33. incr n = exec $! \i v -> unsafeWrite tape i (v + n)
  34. decr n = exec $! \i v -> unsafeWrite tape i (v - n)
  35. output = exec $! \i v -> putChar $! toEnum v
  36. input = exec $! \i v -> getChar >>= unsafeWrite tape i . fromEnum
  37. nonzero = exec $! \i v -> return $! v /= 0
  38.  
  39. exec f = do
  40. i <- unsafeRead tape 0
  41. v <- unsafeRead tape i
  42. f i v
Add Comment
Please, Sign In to add comment