Brainf*ck系言語を作る一番簡単な方法【個人開発】

**Brainf*ck**という言語はご存知でしょうか。これはいわゆる難解プログラミング言語 (Esolang) の一種で、たった8種類という少なくシンプルな命令セット[^lazy_k]でチューリング完全になっていることが知られています。1文字1命令で、手続き型で比較的分かりやすいという特徴から、難解プログラミング言語の代表格ともいえる言語です。

[^lazy_k]: 命令の少なさで言えばもっと少ない言語はありますが。Lazy Kとか。

Brainf*ckは30,000バイトのメモリと1つのポインタを持ち、`+`, `-`, `<`, `>`, `[`, `]`, `.`, `,`の8命令からなる言語です。例えば、以下のプログラムは"Hello, world!"を出力するBrainf*ckプログラムです。

```
+++++++++[
>++++++++>+++++++++++
>++++++++++++>+++++<<<<-
]>.>++.>..+++.
>-.------------.<
++++++++.--------.
+++.------.<-.>>+.
```

Brainf*ckは極めて簡単な言語仕様ながら、奥の深いプログラミングが可能なたいへん興味深く面白い言語です。

さて、その一方で、Brainf*ckのこのような特徴が、**Brainf*ck系言語**という存在を生みました。これは私がそう呼んでいるだけで一般的な呼び方なのかは分かりませんが、Brainf*ck系言語というのは、Brainf*ckの8種類の命令を別の文字列に変えることで作られる
<font color="#aaaaaa">新規性も面白さも全く無い</font>
プログラミング言語です。Brainf*ckの言語仕様が簡単なのでこのようなプログラミング言語の実装はあまり難しくありませんが、「プログラミング言語を作った」というと
<font color="#aaaaaa">実際はなんも凄くないのに</font>
何となく凄そうな響きがすることや、Brainf*ckプログラムの性質上同じ文言が大量に並ぶという
<font color="#aaaaaa">小学生くらいなら喜びそうな</font>
見た目の面白さがあることから、[そのような言語がねとらぼで取り上げられてみたり](http://nlab.itmedia.co.jp/nl/articles/1204/19/news112.html)、果てはエンジニアが集まるはずのここQiitaですら[Brainf*ck系言語を](https://qiita.com/benisho_ga/items/50e674fded183a9e12f1)[作る人やそれをもてはやす人がいる状態です](https://qiita.com/segur/items/eaca10475d7a9f7dda78#_reference-5c2a2aaf0d3b8dd33b8d)。ここで紹介した3つの事例から分かる通り、ファン活動としてこのような言語が作られることが多いようです。

また、そのような人を支援するライブラリもいくつか存在するようです。Qiitaで人気なのは[r-fxxk](https://github.com/masarakki/r-fxxk)で、独自のBrainf*ck系言語のインタプリタを簡単に作れるようになっています。

現在のところ、Brainf*ck系言語を作成するには、自分でインタプリタを作成するか、あるいは最低でもr-fxxkなどのライブラリを使用できる素養が必要で
<font color="#aaaaaa">あり、これが本来1ミリも無いはずのBrainf*ck系言語の価値をわずかながらに高める要因となっていま</font>
す。

前置きが長くなりましたが、この記事ではBrainf*ck系言語をさらに簡単に作れる方法を紹介し
<font color="#aaaaaa">、Brainf*ck系言語の価値をさらにゼロに近づけることを目論んでい</font>
ます。なお、記事名に【個人開発】とあることから分かる通り、今回紹介するのは筆者が制作したちょっとしたWebサービスです。では、さっそく今回作ったサービスを宣伝します。

- [Brainf*ck系言語を作るやつ](https://bf-gen.uhyohyo.net/)

このサービスは、命令の文字列を8種類決めて名前と説明文を入力するだけで簡単にBrainf*ck系言語の公式ページを作ることができるものです。もはや自分で1行たりともプログラムを書く必要はありません。このサービスで作られた言語は、言語の説明文に加えてブラウザ上で動作するWebインタプリタと、ダウンロード可能なコマンドライン向けインタプリタ（node.js製）が備えられています。また、サンプルプログラムが4種類ついており、その場で
<font color="#aaaaaa">小学生が喜びそうな</font>
プログラムの見た目を楽しむことができます。

---

以上でお伝えしたかった内容は終わりですが、Qiitaの記事の質がどうのと騒がれる昨今に記事の内容が宣伝だけというのは申し訳ないので、ここからはあのサービスの技術的な側面に触れようと思います。

# Brainf*ckインタプリタ

まあ、サーバー側は普通にnode.jsでクライアント側は普通にReactですが、注目すべき点があるとすれば**Brainf*ckインタプリタがWebAssemblyで動いている**という点かと思います。これはRustで書いたインタプリタがWebAssemblyにコンパイルされています。このインタプリタは以下の独立したリポジトリに置いてあり、一応npmにも公開してあります。

- https://github.com/uhyo/bf-wasm

ちょっとずるいですが、Brainf*ck系言語のソースが入力として与えられると、まずそれを普通のBrainf*ckに変換してからこの`bf-wasm`に渡すようになっています。

## RustからWebAssemblyへのコンパイル
RustはWebAssemblyを出力できる有力な言語の一つですが、実際どうやってWebAssemblyにコンパイルするのかは諸説あるかと思います。ここでは素直に`cargo`を用いてコンパイルするようになっています。実際、package.jsonを見ると以下のコマンドでコンパイルしていることが分かります。

```sh
cargo build --target wasm32-unknown-unknown --release
```

`bf-wasm`にはRustで書かれたコア部分とJavaScriptで書かれたラッパー部分があり、それらをwebpackで1つにまとめる構成をとっています。webpack.config.jsを見ると[rust-native-wasm-loader](https://github.com/dflemstr/rust-native-wasm-loader)を使おうとした形跡が見えたりしますが、確か結局うまくいきませんでした。その代わりに、生成された`wasm`ファイルをJavaScriptから直にimportして、[wasm-loader](https://github.com/ballercat/wasm-loader)に処理してもらっています。

ただ、webpackにより生成されたJavaScriptファイルを見るとwasmファイルのバイナリデータがJavaScriptコードに埋め込まれているため何だかファイルサイズの面で無駄があるように思えます。別のファイルにするとかそういう最適化は今後の課題でしょうか。

## Rust側とJavaScript側の連携
WebAssemblyはモジュールという形で読みこまれ、JavaScriptからはモジュールからエクスポートされた関数を呼び出すことができます。また、逆にJavaScriptから提供された関数をWebAssembly側から呼び出すことができます。今回は簡単のために、WebAssembly側から関数をエクスポートしてJavaScript側から呼び出す形のみ使うことにします。

[lib.rs](https://github.com/uhyo/bf-wasm/blob/master/src/lib.rs)を見ると`pub fn`で関数がエクスポートされています。このようにエクスポートされた関数はJavaScript側から呼び出すことができます。ただし、`#[no_mangle]`が必要な点に注意してください。

また、データをJavaScriptとRust間でどう受け渡すのかにも工夫が必要です。というのも、WebAssemblyのデータ型は整数とか浮動小数点数とかだけで、文字列のような複雑なデータを関数の引数などで受け渡すことができません。その代わり、同じメモリをJavaScript側とWebAssembly側の両方から読み書きできることを利用して、データをポインタで受け渡しします。このとき、メモリレイアウトはWebAssembly（というかRust）側によって制御されていますから、データを置くためのメモリ領域はRust側のコードで確保することになります。実際、[lib.rs](https://github.com/uhyo/bf-wasm/blob/master/src/lib.rs)はallocとfreeという2つの関数をエクスポートしており、これらを用いてJavaScript側からメモリの確保や解放を行うようになっています。`free`のコードを見ると`unsafe`などと書いており見るからに危ないですが、まあそういうものでしょう。

例えば、インタプリタに入力としてソースファイルを渡すには、まず`alloc`でソース用のメモリ領域を確保し、JavaScript側からその領域に書き込むという流れになります。Brainf*ckプログラムの出力についても、それ用の領域にRust側から書き込んでおいて、あとでJavaScript側からその領域を読むことになります。

また、もう1つ厄介な点として、Brainf*ckプログラムは入力を受け付ける可能性がある点が上げられます。Rust（WebAssembly）側から直にユーザーの入力を待ったりすることはできませんから、入力待ちの際にはJavaScript側に制御を返す必要があります。このことから、Rust側がエクスポートしている`run`関数はプログラムを全部実行するのではなく、次の入力待ちが発生するまで（またはプログラムが終了するまで）実行するようになっています。JavaScript側はユーザーから入力を得たらそれを入力バッファに書き込み、再び`run`を呼び出します。

以上のことが分かればソースコードを読めばだいたい何をやっているのか分かるのではないかと思います。

# まとめ
この記事ではまずBrainf*ckとBrainf*ck系言語について解説し、サービスを宣伝しました。このサービスを用いることで余計な手間を書けずにBrainf*ck系言語
<font color="#aaaaaa">などという何の価値もないおもちゃ</font>
を作ることができます。皆さんもこのサービスを使ってどんどんBrainf*ck系言語を生みだ
<font color="#aaaaaa">すことでBrainf*ck系言語の価値をゼロに</font>
しましょう。

ぶっちゃけ、サービスを宣伝したかっただけと言われると否定できませんが、実装に興味がある人向けに、JavaScriptとWebAssemblyの提携についても少し解説しました。