wvogel日記

自分用の技術備忘録が多めです.

brainf*ck

試験勉強の合間、Haskellでちょっと遊んでみようと思い、40分ほど遊んでみよう。
というわけで、簡便なbrainf*ckを組んでみた。
[]の複数仕様には対応していないし、
外部からの入力も一桁の数値だけですが。


解析と実行が同時並行なので、
タプル形式で読み込み済みと未読み込み部分を保持しました。

import Data.Char
import Foreign.Marshal

main = getLine >>= brainf_ck

brainf_ck :: String -> IO()
brainf_ck str = putStr $ stream ([],[0,0..]) ([],str)

stream :: ([Int],[Int]) -> (String,String) -> String
stream _ (_,[]) = []
stream (n1,n2) str
 = do case head (snd str) of
        '>' -> stream (n1++[head n2],tail n2) str'
        '<' -> stream (init n1,last n1:n2) str'
        '+' -> stream (n1,(head n2+1):tail n2) str'
        '-' -> stream (n1,(head n2-1):tail n2) str'
        '.' -> (chr $ head n2) : stream (n1,n2) str'
        ',' -> stream (n1,unsafeLocalState input:n2) str'
        '[' -> stream (n1,n2) str'
        ']' -> judgeIF (n1,n2) str
  where
    str' = (fst str ++ [head $ snd str] , tail $ snd str)
    input :: IO Int
    input = getChar >>= return.ord

judgeIF :: ([Int],[Int]) -> (String,String) -> String
judgeIF (n1,n2) str@(cs1,cs2)
  = if head n2 == 0
    then stream (n1,n2) (cs1++[head cs2],tail cs2)
    else stream (n1,n2) (cs1',cs2')
  where
    cs1' = takeWhile (/= '[') cs1
    cs2' = dropWhile (/= '[') cs1 ++ cs2

実行結果

++++++++++[>++++++++++++<-]>-.-.-------.--------.--.+++++++.
wvogel

とな。