Skip to content

Instantly share code, notes, and snippets.

@neonpixii
Created February 14, 2018 23:55
Show Gist options
  • Save neonpixii/7440cfd70dc6d759d0e9313586f1eb1c to your computer and use it in GitHub Desktop.
Save neonpixii/7440cfd70dc6d759d0e9313586f1eb1c to your computer and use it in GitHub Desktop.
brainfuck interpreter in haskell
import Data.Array
import Data.Char
type Brainfuck = (Int, String, Int, Array Int Int)
-- Contents of a Brainfuck tuple are:
-- * An Int, representing the position in the program
-- * A String, representing the program
-- * An Int, representing the index in memory
-- * An Array, representing the Memory.
findLeftBrack :: Brainfuck -> Brainfuck
findLeftBrack (i, p, j, m)
| p !! i == ']' = findLeftBrack (i'-1, p, j, m)
| p !! i == '[' = (i, p, j, m)
| otherwise = (i', p, j, m)
where (i',_,_,_) = findLeftBrack (i-1, p, j, m)
-- needs to find MATCHING
findRightBrack :: Brainfuck -> Brainfuck
findRightBrack (i, p, j, m)
| p !! i == '[' = findRightBrack (i'+1, p, j, m)
| p !! i == ']' = (i, p, j, m)
| otherwise = (i', p, j, m)
where (i',_,_,_) = findRightBrack (i+1, p, j, m)
handlePlus :: Brainfuck -> Brainfuck
handlePlus (i, p, j, m) = (i + 1, p, j, m // [(j, (m ! j) + 1)])
handleMinus :: Brainfuck -> Brainfuck
handleMinus (i, p, j, m) = (i + 1, p, j, m // [(j, (m ! j) - 1)])
handleGT :: Brainfuck -> Brainfuck
handleGT (i, p, j, m) = (i + 1, p, j + 1, m)
handleLT :: Brainfuck -> Brainfuck
handleLT (i, p, j, m) = (i + 1, p, j - 1, m)
handleLeftBrack :: Brainfuck -> Brainfuck
handleLeftBrack (i, p, j, m)
| m ! j == 0 = findRightBrack (i+1, p, j, m)
| otherwise = (i+1, p, j, m)
handleRightBrack :: Brainfuck -> Brainfuck
handleRightBrack (i, p, j, m)
| m ! j == 0 = (i+1, p, j, m)
| otherwise = findLeftBrack (i-1, p, j, m)
handlePeriod :: Brainfuck -> IO Brainfuck
handlePeriod (i, p, j, m) = do
putChar $ chr $ m ! j
return (i + 1, p, j, m)
handleComma :: Brainfuck -> IO Brainfuck
handleComma (i, p, j, m) = do
x <- ord <$> getChar
return (i + 1, p, j, m // [(j, x)])
-- create brainfuck of size s with program p
brainfuck :: Int -> String -> Brainfuck
brainfuck s p = (0, p, 0, array (0,s) [(i,0) | i <- [0..s]])
interpret :: Brainfuck -> IO Brainfuck
interpret bf@(i, p, j, m) = if i >= length p
then return bf
else
case (p !! i) of
'+' -> return $ handlePlus bf
'-' -> return $ handleMinus bf
'>' -> return $ handleGT bf
'<' -> return $ handleLT bf
'.' -> handlePeriod bf
',' -> handleComma bf
'[' -> return $ handleLeftBrack bf
']' -> return $ handleRightBrack bf
_ -> interpret (i+1, p, j, m)
brainfuckLoop :: Brainfuck -> IO Brainfuck
brainfuckLoop bf@(i, p, j, m)
| i >= length p = return bf
| otherwise = do
bf' <- interpret bf
brainfuckLoop bf'
main = do
bf <- brainfuck 300 <$> getContents
brainfuckLoop bf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment