BrainF*ckインタプリタを作る

Wkikipediaの記事を読んだり,ダウンロードしたインタプリタをいじってるうちに,なんかちょっとできそうな気がしてきた。
目標は Hello world プログラムの実行だ。


まず,データを格納する配列(レジスタと呼ぶことにしよう)とポインタが必要だな。

 data BrainF_ck = BF { bfPointer :: Int, bfRegister :: [Int] }

操作する命令をそれぞれ関数にする。こんな感じか。

 命令   関数名 
+  bfIncrement
-  bfDencrement
>  bfShift
<  bfUnshift
.  bfPrint
,  bfInput
[  bfGoto
]  bfBack

とりあえず簡単そうな「+」,「-」,「>」,「<」だけにしよう。
それから,BrainF_ck の初期値を設定する関数も要るな。レジスタがいくつ要るかわからないけど,10個あればいいか。

 data BrainF_ck = BF { bfPointer :: Int, bfRegister :: [Int] } deriving (Show)
 
 
 bfInitial :: BrainF_ck
 bfInitial = BF { bfPointer = 0, bfRegister = [0,0,0,0,0,0,0,0,0,0] }
 
 
 bfValue :: BrainF_ck -> Int
 bfValue bf = (bfRegister bf) !! (bfPointer bf)
 
 
 bfIncrement :: BrainF_ck -> BrainF_ck
 bfIncrement (BF p v) = BF p ((take p v) ++ [(v !! p) + 1] ++ (tail $ drop p v))
 
 
 bfDecrement :: BrainF_ck -> BrainF_ck
 bfDecrement (BF p v) = BF p ((take p v) ++ [(v !! p) - 1] ++ (tail $ drop p v))
 
 
 bfShift :: BrainF_ck -> BrainF_ck
 bfShift (BF p v) = BF (p+1) v
 
 
 bfUnshift :: BrainF_ck -> BrainF_ck
 bfUnshift (BF p v) = BF (p-1) v
 


まずはここまででどうだ。

 Prelude> :load hbf.hs
 Compiling Main             ( hbf.hs, interpreted )
 Ok, modules loaded: Main.
 *Main> bfInitial
 Loading package haskell98-1.0 ... linking ... done.
 BF {bfPointer = 0, bfRegister = [0,0,0,0,0,0,0,0,0,0]}
 *Main> bfIncrement $ bfInitial
 BF {bfPointer = 0, bfRegister = [1,0,0,0,0,0,0,0,0,0]}
 *Main> bfIncrement $ bfShift $ bfInitial
 BF {bfPointer = 1, bfRegister = [0,1,0,0,0,0,0,0,0,0]}
 *Main> bfUnshift $ bfIncrement $ bfShift $ bfInitial
 BF {bfPointer = 0, bfRegister = [0,1,0,0,0,0,0,0,0,0]}

おお,なんだかうまくいってるみたい。