自作言語にBrainf*ckを移植した

# プログラム

```
"\0" code
0 $ ptr
512 @ mem

0 $ index

: execute makeJumptable {
    index @g code , 3 = ( [ ) $ inst
    inst '>' = ( incp [ )
    inst '<' = ( decp [ )
    inst '+' = ( incb [ )
    inst '-' = ( decb [ )
    inst '.' = ( out [ )
    inst ',' = ( in [ )
    inst '[' = ( if [ )
    inst ']' = ( loop [ )
    ] ] ] ] ] ] ] ]
} ] ;

: next index 1 + $ index ;

: incp ptr 1 + $ ptr next ;
: decp ptr 1 - $ ptr next ;
: incb ptr @g mem 1 + ptr @s mem next ;
: decb ptr @g mem 1 - ptr @s mem next ;
: out ptr @g mem . next ;
: in ? ptr @s mem next ;
: if ptr @g mem ! ( index getJumpIf $ index ) next ;
: loop index getJumpLoop $ index ;

: makeJumptable
    256 @ _stack
    0 $ _sp
    countOpenBracket 2 * @ jmptable
    0 $ _jmpindex 
    0 $ _lpindex
    {
        _lpindex @g code
        , 3 = ( ` [ )
        _ '[' = ( _lpindex _sp 1 + $ _sp _sp @s _stack )
        _ ']' = ( _sp _sp @g _stack _sp 1 - $ _sp
            _jmpindex @s jmptable
            _lpindex _jmpindex 1 + @s jmptable
            _jmpindex 2 + $ _jmpindex
        )
        _lpindex 1 + $ _lpindex 
    }
] ;

: countOpenBracket 0 $ _index 0 $ _count {
    _index @g code , 3 = ( [ )
    '[' = ( _count 1 + $ _count )
    _index 1 + $ _index

} ] _count ;

: getJumpIf $ ifindex 0 $ _j {
    _j @g jmptable ifindex = (
        _j 1 + @g jmptable [ 
    ) _j 2 + $ _j
} ] ;

: getJumpLoop $ lpindex 1 $ _j {
    _j @g jmptable lpindex = (
        _j 1 - @g jmptable [
    ) _j 2 + $ _j
} ] ;
```

# 実行例

上記のブログラムを`brainf.nzl`という名前を付けて保存、以下のプログラムを記述し`hellobf.nz`と名前を付け同じディレクトリに入れて実行する。

```
##> brainf.nzl

"++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."

code execute
```
`##>`で`brainf.nzl`を`import`します。
ダブルコーテーションで`Brainf*ck`ソースコードを文字列として埋め込み、`code`という変数に格納し、`execute`サブルーチンを呼び出すことで実行できます。

```
> python nouzen.py hellobf.nz
Hello World!
```

# 解説

変数とサブルーチンの解説です。

## 変数

変数として以下のものが実装されています。

|変数名|意味|記述|
|:-:|:-|:-:|
|code|ソースコードを格納する文字配列。|`"\0" code`|
|ptr|メモリ上を指すポインタ。|`0 $ ptr`|
|mem|データを格納するメモリ配列。|`512 @ mem`|
|index|ソースコードの次の命令を指し示すための変数。|`0 $ index`|

これらの値は変更可能なので、例えばメモリをもっと増やしたいと思えば`1024 @ mem`とすれば良いです。`execute`を実行する前なら、`import`した先で書き換えることもできます。

## サブルーチン

|サブルーチン名|意味|
|:-:|:-|
|incp|ポインタをインクリメントします。|
|decp|ポインタをディクリメントします。|
|incb|ポインタが指し示しているメモリの値をインクリメントします。|
|decb|ポインタが指し示しているメモリの値をディクリメントします。|
|out|ポインタが指し示しているメモリの値を文字として標準出力します。|
|in|標準入力から1文字を取得し、その値をポインタが指し示しているメモリへ格納します。|
|if|ポインタが指すメモリの値が0だったら対応する`]`までジャンプします。|
|loop|対応する`[`までジャンプします|
|||
|execute|実行サブルーチンです。|
|next|`index`をインクリメントして次の命令の実行をします。|
|makeJumpTable|`if`や`loop`で使うジャンプ表を作ります。|
|countOpenBracket|`[`の数を数えてジャンプ表のサイズを確認します。|
|getJumpIf|ジャンプ表を使って`if`のジャンプ先を返します。|
|getJumpLoop|ジャンプ表を使って`loop`のジャンプ先を返します。|


# 参考文献

こちらのサイトを参考にさせていただきました。
[Brainf*ck](http://www.kmonos.net/alang/etc/brainfuck.php)
[The Brainfuck Programming Language](http://www.muppetlabs.com/~breadbox/bf/)

nouzenについては[私の過去の記事](https://qiita.com/asana_yui/items/c3b48707584f9cb738f5)をどうぞ。

# おわりに
これでついに私のプログラミング言語もひとつの壁を突破したわけですが（本当か？）、前々からやりたいと思っていた先祖返り的なことができて良かったです。
それはそれとして、暗号みたいなソースコードから`Hello World!`と出力されるのは特別なことをしているような気分になるので皆さんもご自身の手で`Brainf*ck`を実装してみてはいかがでしょうか？
最後まで読んでくださってありがとうございました。 ~~MLFEでnouzenを実装するのはいつになるんだ…~~