Brainfuck インタプリタ
寝る前に OCaml でなんか書いてみるか、と思って書いてみた。
exception Unexpected_char let interpret str = (* バッファ *) let buf = Array.create 3000 0 in (* 対応する右括弧(])を探しに行く *) let rec rp idx n = match String.get str idx with | '[' -> rp (idx+1) (n+1) | ']' -> if n=0 then idx else rp (idx+1) (n-1) | _ -> rp (idx+1) n (* 対応する左括弧([)を探しに行く *) and lp idx n = match String.get str idx with | '[' -> if n=0 then idx else lp (idx-1) (n-1) | ']' -> lp (idx-1) (n+1) | _ -> lp (idx-1) n (* 1文字ずつ読み込んで処理 *) and loop idx p = match String.get str idx with | '>' -> loop (idx+1) (p+1) | '<' -> loop (idx+1) (p-1) | '+' -> buf.(p) <- buf.(p)+1; loop (idx+1) p | '-' -> buf.(p) <- buf.(p)-1; loop (idx+1) p | '.' -> print_char(char_of_int(buf.(p))); loop (idx+1) p | ',' -> buf.(p) <- int_of_char (input_char stdin); loop (idx+1) p | '[' -> loop (if buf.(p)=0 then (rp (idx+1) 0)+1 else idx+1) p | ']' -> loop (if buf.(p)<>0 then (lp (idx-1) 0)+1 else idx+1) p | '\n' -> () | _ -> raise Unexpected_char in loop 0 0 let _ = interpret (read_line()^"\n")
$ ocaml bf.ml +++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.------------.<++++++++.--------.+++.------.--------.>+. Hello, world!$
ゴルフを経験した後だと、 loop を ($) にすれば括弧が消せる!とか、if 式を消したい!とか、while 使った方がいいかも!とか、例外は無視してよくね!とか思ってしまう。