自作言語にBrainf*ckを移植した
プログラム
"\0" code
0 $ ptr
512 @ mem
0 $ index
: execute {
index @g code $ inst
inst '\0' = ( [ )
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 ! ( next { index @g code ']' = ( [ ) next } ) ] next ;
: loop index 1 - $ index { index @g code '[' = ( [ ) index 1 - $ index } ] ;
実行例
"\0" code
0 $ ptr
512 @ mem
0 $ index
: execute {
index @g code $ inst
inst '\0' = ( [ )
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 ! ( next { index @g code ']' = ( [ ) next } ) ] next ;
: loop index 1 - $ index { index @g code '[' = ( [ ) index 1 - $ index } ] ;
上記のブログラムをbrainf.nzl
という名前を付けて保存、以下のプログラムを記述し同じディレクトリに入れて実行する。
##> 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
した先で書き換えることもできます。
サブルーチン
サブルーチン名 | 意味 |
---|---|
execute | 実行サブルーチンです。空文字\0 が見つかるまで実行し続けます。 |
next |
index をインクリメントして次の命令の実行をします。 |
incp | ポインタをインクリメントします。 |
decp | ポインタをディクリメントします。 |
incb | ポインタが指し示しているメモリの値をインクリメントします。 |
decb | ポインタが指し示しているメモリの値をディクリメントします。 |
out | ポインタが指し示しているメモリの値を文字として標準出力します。 |
in | 標準入力から1文字を取得し、その値をポインタが指し示しているメモリへ格納します。 |
if | ポインタが指すメモリの値が0だったら直後の] までジャンプします。 |
loop | 直前の[ までジャンプします |
参考文献
こちらのサイトを参考にさせていただきました。
Brainf*ck
The Brainfuck Programming Language
おわりに
これでついに私のプログラミング言語もひとつの壁を突破したわけですが(本当か?)、前々からやりたいと思っていた先祖返り的なことができて良かったです。
それはそれとして、暗号みたいなソースコードからHello World!
と出力されるのは特別なことをしているような気分になるので皆さんもご自身の手でBrainf*ck
を実装してみてはいかがでしょうか?
最後まで読んでくださってありがとうございました。 MLFEでnouzenを実装するのはいつになるんだ…
Author And Source
この問題について(自作言語にBrainf*ckを移植した), 我々は、より多くの情報をここで見つけました https://qiita.com/asana_yui/items/cdb7678f520e736bd4a1著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .