Execute Brain****/Haskell: Difference between revisions

m
<code>
(unsafePerformIO sounds scary)
m (<code>)
Line 8:
A more efficient implementation could for example only admit well-bracketed brainfuck programs, and parse bracket blocks first, to replace the ''matchLeft'' and ''matchRight'' which need linear time.
 
<code haskell>moveLeft (x:l,r) = (l,x:r)
moveRight (l,x:r) = (x:l,r)
 
matchLeft d@('[':_,_) = d
matchLeft d@(']':_,_) = matchLeft $ moveLeft $ matchLeft $ moveLeft $ d
matchLeft d = matchLeft $ moveLeft $ d
 
matchRight d@(_,']':_) = moveRight $ d
matchRight d@(_,'[':_) = matchRight $ matchRight $ moveRight $ d
matchRight d = matchRight $ moveRight $ d
 
pad ([],[]) = ([0],[0])
pad ([],r) = ([0],r)
pad (l,[]) = (l,[0])
pad d = d
 
modify f (l,x:r) = (l,(f x):r)
 
exec :: (String, String) -> ([Integer], [Integer]) -> [Integer] -> [Integer]
exec (_,[]) _ _ = []
exec p@(_,'>':_) d cs = exec (moveRight p) (pad $ moveRight $ d) cs
exec p@(_,'<':_) d cs = exec (moveRight p) (pad $ moveLeft $ d) cs
exec p@(_,'+':_) d cs = exec (moveRight p) (modify (+ 1) d) cs
exec p@(_,'-':_) d cs = exec (moveRight p) (modify (- 1) d) cs
exec p@(_,',':_) d (c:cs) = exec (moveRight p) (modify (const c) d) cs
exec p@(_,'.':_) d@(_,x:_) cs = x : exec (moveRight p) d cs
exec p@(_,'[':_) d@(_,0:_) cs = exec (matchRight $ moveRight $ p) d cs
exec p@(_,'[':_) d cs = exec (moveRight p) d cs
exec p@(_,']':_) d@(_,0:_) cs = exec (moveRight p) d cs
exec p@(_,']':_) d cs = exec (matchLeft $ moveLeft $ p) d cs
 
run :: String -> [Integer] -> [Integer]
run s = exec ([],s) ([0],[0])
 
dialog :: String -> IO ()
dialog s = mapM_ print . run s . map read . lines =<< getContents</code>
 
Example session:
 
<pre>: *Main> dialog ",[>+<-].>."
: ''5''
: 0
: 5</pre>
Anonymous user