1:
real 0m39.444s
user 0m39.348s
sys 0m0.058s
2:
real 0m39.715s
user 0m39.621s
sys 0m0.056s
3:
real 0m40.055s
user 0m39.964s
sys 0m0.039s
runBrainfuck :: Brainfuck -> IO ()
runBrainfuck bf = do
dataPointer <- newPrimVar (0 :: Word16)
arr <- MV.replicate @_ @Word8 (fromIntegral (maxBound @Word16) + 1) 0
let readRef = fromIntegral <$> readPrimVar dataPointer
modifyRef = modifyPrimVar dataPointer
bf & fix \evalLoop bf' ->
forM_ bf' \case
Op OpInc -> readRef >>= MV.modify arr (+ 1)
Op OpDec -> readRef >>= MV.modify arr (- 1)
Op OpLeft -> modifyRef (- 1)
Op OpRight -> modifyRef (+ 1)
Op OpOutput -> readRef >>= MV.read arr >>= putChar . w2c
Op OpInput -> join $ liftM2 (MV.write arr) readRef (c2w <$> getChar)
Loop bf'' -> fix \recurse -> do
state <- readRef >>= MV.read arr
unless (state == 0) (evalLoop bf'' >> recurse)
putChar '\n'
1:
real 1m27.346s
user 1m27.183s
sys 0m0.096s
2:
real 1m27.948s
user 1m27.702s
sys 0m0.117s
3: TL, didn't wait
runBrainfuck :: Brainfuck -> IO ()
runBrainfuck bf = do
dataPointer <- newIORef (0 :: Word16)
arr <- MV.replicate @_ @Word8 (fromIntegral (maxBound @Word16) + 1) 0
let readRef = fromIntegral <$> readIORef dataPointer
modifyRef = modifyIORef dataPointer
bf & fix \evalLoop bf' ->
forM_ bf' \case
Op OpInc -> readRef >>= MV.modify arr (+ 1)
Op OpDec -> readRef >>= MV.modify arr (- 1)
Op OpLeft -> modifyRef (- 1)
Op OpRight -> modifyRef (+ 1)
Op OpOutput -> readRef >>= MV.read arr >>= putChar . w2c
Op OpInput -> join $ liftM2 (MV.write arr) readRef (c2w <$> getChar)
Loop bf'' -> fix \recurse -> do
state <- readRef >>= MV.read arr
unless (state == 0) (evalLoop bf'' >> recurse)
putChar '\n'
1:
real 0m50.884s
user 0m50.846s
sys 0m0.040s
2:
real 0m52.145s
user 0m52.083s
sys 0m0.048s
3:
real 0m51.155s
user 0m51.108s
sys 0m0.046s
runBrainfuck :: Brainfuck -> IO ()
runBrainfuck bf = do
arr <- MV.replicate @_ @Word8 (fromIntegral (maxBound @Word16) + 1) 0
let dataPointer = (0 :: Word16)
w2i = fromIntegral
evalLoop :: Word16 -> Brainfuck -> IO Word16
evalLoop !dp = \case
[] -> return dp
Op OpInc:xs -> MV.modify arr (+ 1) (w2i dp) >> evalLoop dp xs
Op OpDec:xs -> MV.modify arr (- 1) (w2i dp) >> evalLoop dp xs
Op OpLeft:xs -> evalLoop (dp - 1) xs
Op OpRight:xs -> evalLoop (dp + 1) xs
Op OpOutput:xs -> MV.read arr (w2i dp) >>= putChar . w2c >> evalLoop dp xs
Op OpInput:xs -> (MV.write arr (w2i dp) . c2w =<< getChar) >> evalLoop dp xs
Loop bf'':xs -> let loop !dp' = do
state <- MV.read arr (w2i dp')
if state /= 0 then evalLoop dp' bf'' >>= loop else evalLoop dp' xs
in loop dp
evalLoop dataPointer bf
putChar '\n'