1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2022-04-02

プログラム

"\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.nzlimportします。
ダブルコーテーションで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 ifloopで使うジャンプ表を作ります。
countOpenBracket [の数を数えてジャンプ表のサイズを確認します。
getJumpIf ジャンプ表を使ってifのジャンプ先を返します。
getJumpLoop ジャンプ表を使ってloopのジャンプ先を返します。

参考文献

こちらのサイトを参考にさせていただきました。
Brainf*ck
The Brainfuck Programming Language

nouzenについては私の過去の記事をどうぞ。

おわりに

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

1
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?