Skip to content

Instantly share code, notes, and snippets.

@AndrasKovacs
Last active December 24, 2015 20:19
Show Gist options
  • Save AndrasKovacs/6856911 to your computer and use it in GitHub Desktop.
Save AndrasKovacs/6856911 to your computer and use it in GitHub Desktop.
Brainfuck interpreter. Usage: just run script or executable with Brainfuck source file as commandline argument.It has bidirectionally "infinite" memory and one-byte cells.
import System.Environment
import Data.Word
import Data.Char
import Control.Arrow
import Data.Function
infixr 5 :>
data Mem = {- UNPACK -} !Word8 :> Mem
eval :: Mem -> Mem -> String -> IO (Mem, Mem)
eval ml@(l:>ls) mr@(r:>rs) (x:xs) = case x of
'>' -> eval (r:>ml) rs xs
'<' -> eval ls (l:>mr) xs
'+' -> eval ml (r + 1:>rs) xs
'-' -> eval ml (r - 1:>rs) xs
'.' -> putChar (chr $ fromIntegral r) >> eval ml mr xs
',' -> do {c <- getChar; eval ml (fromIntegral (ord c):>rs) xs}
'[' -> let (block, rest) = getBlock xs
in ($(ml, mr)) $ fix $ \loop (ml, r:>rs) ->
case r of
0 -> eval ml (r:>rs) rest
_ -> eval ml (r:>rs) block >>= loop
']' -> error "Unexpected bracket"
eval ml mr [] = return (ml, mr)
getBlock = go 1 where
go n ('[':xs) = first ('[':) $ go (n + 1) xs
go 1 (']':xs) = ("", xs)
go n (']':xs) = first (']':) $ go (n - 1) xs
go n (x:xs) = first (x:) $ go n xs
go n [] = error "Unmatched bracket"
runBF :: String -> IO ()
runBF = fmap (const ()) . eval (fix (0:>)) (fix (0:>)) . filter (`elem` "+-<>,.[]")
main = do
as <- getArgs
case as of
f:[] -> runBF =<< readFile f
_ -> putStrLn "usage: bfuck [source file]"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment