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]) |
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. |