ghc bf.hs
cat hello | ./a.out
| import Data.Char | |
| class Mem a where | |
| empty :: a | |
| instance Mem Int where empty = 0 | |
| instance Mem Char where empty = ' ' | |
| data (Mem a) => Tape a = Tape Int [a] deriving (Show) | |
| get (Tape 0 (x:_)) = x | |
| get (Tape i (x:xs)) = get $ Tape (i - 1) xs | |
| set (Tape i xs) n = Tape i $ a ++ (n:b) | |
| where a = fst tape | |
| b = tail $ snd tape | |
| tape = splitAt i xs | |
| next (Tape i xs) | |
| | i < length xs - 1 = Tape (i + 1) xs | |
| | otherwise = Tape (i + 1) (xs ++ [empty]) | |
| prev (Tape i xs) | |
| | i < 1 = Tape i (empty:xs) | |
| | otherwise = Tape (i - 1) xs | |
| incr tape = set tape $ (get tape) + 1 | |
| decr tape = set tape $ (get tape) - 1 | |
| exec instruction memory | |
| | command == '>' = exec (next instruction) (next memory) | |
| | command == '<' = exec (next instruction) (prev memory) | |
| | command == '+' = exec (next instruction) (incr memory) | |
| | command == '-' = exec (next instruction) (decr memory) | |
| | command == '.' = do | |
| putChar $ (chr value) | |
| exec (next instruction) memory | |
| | command == ',' = do | |
| c <- getChar | |
| exec (next instruction) (set memory $ ord c) | |
| | command == '[' && value == 0 = exec (jumpTo instruction) memory | |
| | command == '[' && value /= 0 = exec (next instruction) memory | |
| | command == ']' && value /= 0 = exec (jumpBack instruction) memory | |
| | command == ']' && value == 0 = exec (next instruction) memory | |
| | otherwise = return () | |
| where command = get instruction | |
| value = get memory | |
| jumpTo tape | |
| | get tape == ']' = next tape | |
| | otherwise = jumpTo $ next tape | |
| jumpBack tape | |
| | get tape == '[' = next tape | |
| | otherwise = jumpBack $ prev tape | |
| main = do | |
| inst <- getLine | |
| exec (Tape 0 inst) (Tape 0 [0]) |
| ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. |