Guest User

brainfunc

a guest
Jun 15th, 2012
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import qualified Control.Exception as E
  2. import Control.Monad
  3. import Data.Array.IO
  4. import Data.Char
  5. import Data.IORef
  6. import qualified Data.Map as M
  7. import Data.Word
  8. import System.Environment
  9.  
  10. data Exp = Back | Forward | Minus | Plus | In | Out | Loop [Exp]
  11. data State = State (IORef Int) (IOArray Int Word8)
  12.  
  13. modifyArray :: (Ix i) => IOArray i e -> i -> (e -> e) -> IO ()
  14. modifyArray array index f = do
  15.   old <- readArray array index
  16.   writeArray array index (f old)
  17.  
  18. eval :: Exp -> State -> IO ()
  19.  
  20. eval Back (State ptr _) = modifyIORef ptr (subtract 1)
  21. eval Forward (State ptr _) = modifyIORef ptr (+1)
  22.  
  23. eval Minus (State ptr tape) = do
  24.   curptr <- readIORef ptr
  25.   modifyArray tape curptr (subtract 1)
  26.  
  27. eval Plus (State ptr tape) = do
  28.   curptr <- readIORef ptr
  29.   modifyArray tape curptr (+1)
  30.  
  31. eval In (State ptr tape) = do
  32.   curptr <- readIORef ptr
  33.   char <- getChar `E.catch` ((\_ -> return '\xFF') :: E.IOException -> IO Char)
  34.   writeArray tape curptr $ fromIntegral $ ord char
  35.  
  36. eval Out (State ptr tape) = do
  37.   curptr <- readIORef ptr
  38.   char <- readArray tape curptr
  39.   putChar $ chr $ fromIntegral char
  40.  
  41. eval exp@(Loop body) st@(State ptr tape) = do
  42.   curptr <- readIORef ptr
  43.   val <- readArray tape curptr
  44.   when (val /= 0) $ do
  45.     sequence $ map (flip eval st) body
  46.     eval exp st
  47.  
  48. simpleOps = M.fromList [
  49.   ('<', Back),
  50.   ('>', Forward),
  51.   ('-', Minus),
  52.   ('+', Plus),
  53.   (',', In),
  54.   ('.', Out)]
  55.  
  56. parse :: String -> ([Exp], String)
  57.  
  58. parse "" = ([], "")
  59. parse (x:xs) = case M.lookup x simpleOps of
  60.     Just exp -> let (restExp, restCode) = parse xs in (exp:restExp, restCode)
  61.     Nothing -> case x of
  62.       '[' ->
  63.         let
  64.           (body, next) = parse xs
  65.           (restExp, restCode) = parse next
  66.         in ((Loop body):restExp, restCode)
  67.       ']' -> ([], xs)
  68.       _ -> parse xs
  69.  
  70. main :: IO ()
  71.  
  72. main = do
  73.   [pfile] <- getArgs
  74.   code <- readFile pfile
  75.   let (exps, _) = parse code
  76.   ptr <- newIORef 0
  77.   tape <- newArray (0, 4096) 0
  78.   sequence_ $ map (flip eval (State ptr tape)) exps
Advertisement
Add Comment
Please, Sign In to add comment