Ruby 版 Brainfuck インタプリタを書いてみました。

brain

以前、C 言語で Brainfuck インタプリタを書きましたが、今度は Ruby で同じものを書いてみました。

クラス Machine を簡単なバーチャルマシンに見立てて、メモリの保持と演算を行なわせています。

C 言語版同様、hello.bf を読み込んで

Hello, world!

と印字します。

演算の内容は C 言語版と変わりありません。大きな違いは Machine オブジェクトごとに独立したメモリ空間・CPUが割り当てられる点と、Brainfuck のコードが読み込まれるメモリ空間と実際に操作可能なメモリ空間が同一配列上に定義されていますので、その気になればコードの実行時に自己書き換えすることが可能な点です。

人工生命シミュレーター Tierra の生物を記述するのに、現実の CPU のアセンブリ言語のような作為的な実装よりも、必要最低限の言語セットだけを持ち、よりシンプルな記述でチューリングマシンが書ける brainfuck で実装し直したら面白いんじゃないかという夏休みの自由研究的な発想から、自己書き換え可能な brainfuck を書いてみています。

オリジナルの Tierra Language の CPU 側にあるレジスタやスタックの概念って世代を重ねるごとに自然形成されるもんなんでしょうかね?

もっと欲を出すと、上の Ruby コードの演算部自体も brainfuck で実装して、さらにそれが書き換えられて進化できるようになると面白そうですが、サルにタイプライターを与えてシェイクスピアを書かせるようなものかもしれません。

Monkey

C による Brainfuck インタプリタ

難解プログラミング言語のひとつ、Brainfuckのインタプリタを書いてみました。命令は8つしかありませんが、立派にチューリング完全です。

言語仕様

処理系の構成要素

  • インストラクションポインタ – プログラム中のある文字を指す。
  • 少なくとも30000個の要素を持つバイトの配列 – 各要素はゼロで初期化される。
  • データポインタ – 前述の配列のどれかの要素を指す。最も左の要素を指すよう初期化される。
  • 入力と出力の2つのバイトストリーム

命令

  1. > ポインタをインクリメントする。ポインタをptrとすると、C言語の「ptr++;」に相当する。
  2. < ポインタをデクリメントする。C言語の「ptr--;」に相当。
  3. + ポインタが指す値をインクリメントする。C言語の「(*ptr)++;」に相当。
  4. - ポインタが指す値をデクリメントする。C言語の「(*ptr)--;」に相当。
  5. . ポインタが指す値を出力に書き出す。C言語の「putchar(*ptr);」に相当。
  6. , 入力から1バイト読み込んで、ポインタが指す先に代入する。C言語の「*ptr=getchar();」に相当。
  7. [ ポインタが指す値が0なら、対応する ] の直後までジャンプする。C言語の「while(*ptr){」に相当。
  8. ] ポインタが指す値が0でないなら、対応する [ にジャンプする。C言語の「}」に相当。

コード

hello.bf を食わせてやると、”Hello, world!” と表示されます。

ビルド

gcc -o bfi bfi.c

実行

./bfi hello.bf
# または
./bfi < hello.bf

注意

実行するスクリプトによっては、危険な振舞いをする可能性があります。十分に注意してください。