summaryrefslogtreecommitdiff
path: root/Brainfuck/Interpreter.hs
diff options
context:
space:
mode:
authorJed Barber <jjbarber@y7mail.com>2014-03-26 16:18:57 +1100
committerJed Barber <jjbarber@y7mail.com>2014-03-26 16:18:57 +1100
commit4885bc81e3716841723b585572ff157b4e324198 (patch)
tree7f72999e6d353a1ad88868e5c4239dcaf0ebbceb /Brainfuck/Interpreter.hs
parentd52939715e33a40b2c59ccfadf417b2752d3229e (diff)
The interpreter looks suspiciously like a turing machine
Diffstat (limited to 'Brainfuck/Interpreter.hs')
-rw-r--r--Brainfuck/Interpreter.hs70
1 files changed, 70 insertions, 0 deletions
diff --git a/Brainfuck/Interpreter.hs b/Brainfuck/Interpreter.hs
new file mode 100644
index 0000000..1085a30
--- /dev/null
+++ b/Brainfuck/Interpreter.hs
@@ -0,0 +1,70 @@
+module Brainfuck.Interpreter (
+ brainfuck
+ ) where
+
+
+import Data.Char
+import Data.Maybe
+import Brainfuck.Parser
+import Brainfuck.Tape
+
+
+
+
+brainfuck :: BrainfuckProgram -> IO (Tape Int)
+brainfuck program =
+ let dataTape = (repeat 0, Just 0, repeat 0)
+ commandTape = shiftRight ([], Nothing, program)
+ in process commandTape dataTape
+
+
+
+endLoop :: Tape BrainCom -> Tape BrainCom
+endLoop tape =
+ let f t c = case (currentCell t, c) of
+ (Just CloseLoop, 0) -> shiftRight t
+ (Just OpenLoop, x) -> f (shiftRight t) (x + 1)
+ (Just CloseLoop, x) -> f (shiftRight t) (x - 1)
+ (Just com, x) -> f (shiftRight t) x
+ in f (shiftRight tape) 0
+
+
+
+doLoop :: Tape BrainCom -> Tape BrainCom
+doLoop tape =
+ let f t c = case (currentCell t, c) of
+ (Just OpenLoop, 0) -> shiftRight t
+ (Just OpenLoop, x) -> f (shiftLeft t) (x - 1)
+ (Just CloseLoop, x) -> f (shiftLeft t) (x + 1)
+ (Just com, x) -> f (shiftLeft t) x
+ in f (shiftLeft tape) 0
+
+
+
+process :: Tape BrainCom -> Tape Int -> IO (Tape Int)
+process commandTape dataTape =
+ case (currentCell commandTape) of
+ Nothing -> return dataTape
+
+ Just R -> process (shiftRight commandTape) (shiftRight dataTape)
+
+ Just L -> process (shiftRight commandTape) (shiftLeft dataTape)
+
+ Just Inc -> process (shiftRight commandTape) (applyToCurrentCell ((`mod` 256) . (+1)) dataTape)
+
+ Just Dec -> process (shiftRight commandTape) (applyToCurrentCell ((`mod` 256) . (subtract 1)) dataTape)
+
+ Just Out -> (putChar . chr . fromJust . currentCell $ dataTape) >> process (shiftRight commandTape) dataTape
+
+ Just In -> do { c <- getChar; process (shiftRight commandTape) (applyToCurrentCell (\_ -> ord c) dataTape) }
+
+ Just OpenLoop ->
+ if (currentCell dataTape == Just 0)
+ then process (endLoop commandTape) dataTape
+ else process (shiftRight commandTape) dataTape
+
+ Just CloseLoop ->
+ if (currentCell dataTape /= Just 0)
+ then process (doLoop commandTape) dataTape
+ else process (shiftRight commandTape) dataTape
+