ページへ戻る

− Links

 印刷 

HOSINO​/efg01上で動くプログラムの作り方 のバックアップソース(No.6) :: OSASK計画

osaskwiki:HOSINO/efg01上で動くプログラムの作り方 のバックアップソース(No.6)

« Prev[4]  Next »[5]
**この講座について [#jb0faaac]
星野が作ったインタプリタ(ip.g01)の上で動くプログラムを作る事を目標とします。~
そのインタプリタはefg01で動くので、結局作ったアプリも(間接的に)efg01の上で動くことになります。~
ちゃんとしたチュートリアルはそのうちhideyosiさんが作られるようです。~
また、K-tanさんも以前にGUIGUI01/memoシリーズでC言語やアセンブリでのg01アプリの作り方を書かれています。~
インタプリタ上で動くプログラムなんか興味無い!という方はぜひそちらをご覧ください。~
**開発環境の作り方 [#r4e8d055]
efg01とip.g01を手に入れてください。~
ip.g01はhttp://osask.net/w/513.htmlから入手できます。~
後はip.g01とefg01を同じフォルダに入れておいてください。~
*efg01上で動くプログラムの作り方講座(1) [#ab5c428e]
**HQ9+でプログラミング [#h9d2d97d]
まずはじめに、初心者向けのHQ9+という言語でのプログラミングをやってみましょう。~
***Hello, world!プログラムを作る! [#d9f1c40b]
古今東西、いかなるプログラミング言語であっても伝統的に入門時はHello, world!と表示するプログラムを書くことになっています。~
この講座でもその伝統に従って、最初はHello, world!と表示するプログラムをHQ9+で書きたいと思います。~
 H
上のような内容にしたテキストファイルをhello.txtという名前で保存します。~
このプログラムを実行したいときは、コンソールを開いて次のように打ち込みます。~
 プロンプト>efg01 ip02 file:hello.txt type:10
これで無事にHello, world!プログラムを作ることが出来ました。~
もし、上のように打ち込んでもHello, world!と表示されなければ、それまでのところで何か失敗をしているはずです。~
もうお分かりかもしれませんが、HQ9+でHello, world!と表示するには、Hという命令を実行させます。~
このように初心者に非常に分かりやすく、覚えやすい文法を採用しているのがHQ9+の特徴です。~
なお、もしHello, world!と二回表示するプログラムを作りたければ、~
 HH
という内容のファイルを実行させます。~

***プログラムが書いてあるファイルの中身を表示させる! [#id73c46d]
Hello, world!と表示するだけでは飽きてしまったと思いますので、今回はファイル出入力の一環としてHQ9+プログラムが書かれたファイルの中身を表示させてみようと思います。~
まずは、プログラムを以下に示します。~
 Q
これを実行させると、確かにQと表示されます。~
HQ9+では、自分自身のファイルをオープンして内容を読み込み、それを表示する命令が用意されています。~
これがQという命令で、もし仮に二回HQ9+のプログラムが書かれたファイルの内容を表示させたければ、~
 QQ
と書かれたファイルを実行します。~
これでは、「QQ」というファイルの中身を二回表示するので、~
 QQ
 QQ
と表示されます。~
***英語の歌の歌詞を表示させる! [#s2d221db]
これまで作ってきたプログラムはどれも実用的とは言えませんでした。~
そこで、今回は99 Bottles of Beerという英語の歌の歌詞を表示させるプログラムを作りたいと思います。~
これが有れば、何かの機会に99 Bottles of Beerを歌わないといけなくなったときに、すぐに歌詞を思い出すことが出来ます。~
では、今回のプログラムです。~
 9
これを実行すると、かなり長い歌詞が表示されます。~
このように、HQ9+では9という命令を実行させることで、99 Bottles of Beerの歌詞を表示させることが出来ます。~
***変数を使ってみる! [#a567093a]
これまで見てきたように、HQ9+は非常にシンプルで覚えやすいプログラミング言語です。~
この言語の特徴は変数、という物の扱いにも現れています。~
変数とは、簡単にいえば色々な物を入れておく箱の事ですが、HQ9+では特に宣言をしなくても変数を使う事が出来ます。~
つまり、最初から0で初期化された変数が一つ用意されているわけです。~
この変数の値を1増加させるときには、+という命令を使います。~
 +++
上のようなHQ9+プログラムは、最初から用意されている変数に1を3回足すので、変数の中身が3になります。~
***色々なHQ9+プログラムを書く! [#g7e44970]
まずは、次のようなプログラムを実行させてみます。~
 This is HQ9+ program !
これを実行すると、~
 Hello, world!
 This is HQ9+ program !
 99 bottles of beer on the wall, 99 bottles of beer.
 Take one down and pass it around, 98 bottles of beer on the wall.
 (中略)
 No more bottles of beer on the wall, no more bottles of beer.
 Go to the store and buy some more, 99 bottles of beer on the wall.
と表示されます。(もしかしたら長すぎて上のほうがこうンソールからはみ出すかもしれません。)~
HQ9+では、H、Q、9、+、以外の全ての文字がコメントとして無視されます。~
よって、上のプログラムは~
 HQ9+
という内容とみなされて実行されます。~
勿論、HQ9+でも一つのプログラムの中で複数の種類の命令を使う事が出来るので、上記のような結果となるわけです。~
最後に、もうひとつプログラムを紹介します。~
 #include<stdio.h>
 void main(void){
   printf("Hello,world!");
   return;
 }
このプログラムも、コメントの部分を無視すると以下のようになります。~
 H
よって、このプログラムはHello, world!と表示します。~
**HQ9++でプログラミング [#c7c8c817]
HQ9++とは、C言語に対するC++のように、HQ9+と互換性を保ちながら、オブジェクト指向を取り入れた言語です。~
新たに++という命令が追加されています。~
この命令は、変数に2を足し、さらにオブジェクトのインスタンスを生成します。~
HQ9++で書かれたプログラムをip01.g01で実行するときは、~
 プロンプト>efg01 ip02 file:ファイル名 type:11
とコマンドプロンプトに打ち込みます。
 HQ9++
というプログラムを実行すると、~
 Hello, world!
 HQ9++
 99 bottles of beer on the wall, 99 bottles of beer.
 Take one down and pass it around, 98 bottles of beer on the wall.
 (中略)
 No more bottles of beer on the wall, no more bottles of beer.
 Go to the store and buy some more, 99 bottles of beer on the wall.
と表示され、プログラム終了時の変数の値は2で、オブジェクトのインスタンスが生成されています。~
ただし、情報隠蔽の原理に従って、このオブジェクトへのアクセスはできない様になっているようです。~

**HQ9F+でプログラミング [#ae1e7dc1]
HQ9F+も、HQ9+と互換性のある言語のひとつです。~
HQ9F+で書かれたプログラムをip02.g01で実行するときは、~
 プロンプト>efg01 ip02 file:ファイル名 type:12
とコマンドプロンプトに打ち込みます。~
新たにFという命令が加えられています。~
この命令は、0から命令が実行された時の変数の値の数まで、一つずつ数を数えていき、その数が3で割れればFizzを、5で割れればBuzzを、3でも5でも割れればFizz Buzzを、3でも5でも割れなければその数自身を表示させます。~
具体的には、~
 ++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++
 ++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++
 F
というプログラムは、~
 Fizz Buzz
 1
 2
 Fizz
 4
 Buzz
 (中略)
 Fizz
 97
 98
 Fizz
 Buzz
と表示されます。~
また、お分かりだと思いますが、HQ9F+では、Fもコメントではなく命令として扱われるのでご注意ください。~

*efg01上で動くプログラムの作り方講座(2) [#qed0b097]
前回はHQ9+系統のプログラミング言語を使ってプログラムを作りました。~
しかし、HQ9+は初心者用の言語なので、コンピュータが本来処理できる計算の、ほんの一部しか実行できません。~
これに対して、今回扱うBrainf*ck系統のプログラミング言語はコンピュータが行える全ての計算が可能である、とされています。~
最初のうちはちょっと難しく感じるかもしれませんが、頑張ってください。~
**Brainf*ckでプログラミング [#uf970460]
Brainf*ckのプログラムをip02.g01で実行する際は、~
 プロンプト>efg01 ip02 file:ファイル名 type:0
と打ち込みます。~

***まずはHello, world! [#j45975eb]
伝統は大切にするべきなので、いきなりですがHello, world!と表示するプログラムを以下に示します。~
 ++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++
 ++++++++++ ++++++++++ ++.        ++++++++++ ++++++++++
 +++++++++. +++++++.   .          +++.       ----------
 ---------- ---------- ---------- ---------- ----------
 -------.   ---------- --.        ++++++++++ ++++++++++
 ++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++
 ++++++++++ +++++++.   --------.  +++.       ------.
 --------.  ---------- ---------- ---------- ----------
 ---------- ---------- -------.
かなり意味不明だと思いますが、これから少しずつ説明しますのでご安心を。~
***Brainf*ckの基本仕様を知る! [#a51535fc]
Brainf*ckは仮想的なコンピュータの機械語、ととらえることが出来ます。~
しかも、機械語としては非常に高い可読性を持っています。~
その仮想機械は一つのレジスタと、1024バイトのメモリを持っています。~
(この1024という数字は星野が勝手に決めた物であり、処理系によって変化します。)~
レジスタもメモリも最初は0で初期化されています。~
機械語は全部で8種類あります。~
 +  レジスタが指しているメモリのアドレスにある値を1増加させます。
 -  レジスタが指しているメモリのアドレスにある値を1減少させます。
 >  レジスタの値を1増加させます。
 <  レジスタの値を1減少させます。
 [  レジスタが指しているメモリのアドレスにある値が0なら、対応する]の直後にジャンプします。
 ]  レジスタが指しているメモリのアドレスにある値が0以外なら、対応する[にジャンプします。
 .  レジスタが指しているメモリのアドレスにある値を、文字コードとみなして出力します。
 ,  レジスタが指しているメモリのアドレスに、入力された文字のコードを代入します。
上記以外の文字はコメントとみなされて全て無視されます。~
***Hello, world!を読み解く! [#hff35431]
まず、先にあげたソースの解説をしようと思います。~
 ++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++
 ++++++++++ ++++++++++ ++.        ++++++++++ ++++++++++
 +++++++++. +++++++.   .          +++.       ----------
 ---------- ---------- ---------- ---------- ----------
 -------.   ---------- --.        ++++++++++ ++++++++++
 ++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++
 ++++++++++ +++++++.   --------.  +++.       ------.
 --------.  ---------- ---------- ---------- ----------
 ---------- ---------- -------.
1~2行目の3番目のブロックまででメモリの0番地の値を72にして、出力させています。~
この72はHの文字コードです。~
3行目の1番目のブロックまでで、メモリの0番地の値にさらに29を足して、eの文字コードである101を作り、出力しています。~
(中略)~
9行目の3番目のブロックまでで、メモリの0番地の値から67を引いて!の文字コードである33を作り、出力しています。~
ただ、このやり方はかなりカッコ悪いので、もう少し短いソースでHello, world!と表示させてみます。~
 ++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++
 ++++++++++ ++++++++++ ++.        ++++++++++ ++++++++++
 +++++++++. +++++++.   .          +++.>      ++++++++++
 ++++++++++ ++++++++++ ++++++++++ ++++.      ----------
 --.<       ++++++++.  --------.  +++.       ------.
 --------.> +.
前のソースが373文字(スペース、改行を除く)だったのに対して、今回は217文字にまで減らせました。~
(それでもHQ9+の1文字には全然届きませんが…)~
3行目の4番目のブロックまでは前回と同じです。~
ここで、>命令が実行されています。~
これによって、レジスタはメモリの1番地をさすようになります。~
メモリの1番地の値はこのとき0ですが、これを4行目の4番目のブロックまでで,の文字コードである44にして出力します。~
5行目の1番目のブロックでスペースを出力した後、レジスタの値を1減らしています。~
これで再びレジスタはメモリの0番地をさすようになり、そこにはoの文字コードである111が入っています。~
今度はそれをいじって文字を出力していき、最後にもう一回1番地の値をいじって!を出力させて終了です。~
少しはましになりましたが、まだまだカッコイイとは言えないソースです。~
もうちょっと工夫を加えてみます。~
 +++++++ [>++++++++++<-] >++.
 ++++++++++ ++++++++++ +++++++++. +++++++. . +++.>
 ++++ [>++++++++++<-] >++++.
 ---------- --.<<
 ++++++++. --------. +++. ------. --------.>>
 +.
これで152文字にまで減らすことが出来ました。~
ソース自体も、[や]が加わったことでBrainf*ckらしいカッコよさが出てきました。~
今までは72を作るときに、1+1+1+1+(中略)+1=72と考えていました。~
この考えを捨てて、10*7+2=(1+1+1+1+1+1+1+1+1+1)*(1+1+1+1+1+1+1)+1+1=72として計算したのが上のソースです。~
まず最初に、0番地の値を7にします。~
0番地の値は7なので[は素通りして、>でレジスタは1番地をさします。~
1番地の値に10を足した後、<で0番地へもどり、1を引きます。~
それでもまだ値は6なので[へもどり、さらに1番地に10を足します。~
また、0番地の値を1減らしますが、まだ5なので[へもどります。~
これを繰り返すと、1番地の値が70になったときに0番地の値が0になり、ようやく]の次へ進みます。~
それに2を足すので72になり、無事にHが出力されます。~
2行目の最後でoを出力した後も、同じ要領で4回ループさせ、3番地の値を40にします。~
それに4を足して44にし、,を出力します。~
4行目と5行目の最後が<<と>>になっているのは、2回目のループでカウンタとして使った2番地を飛び越えるためです。~
最後に、Brainf*ckのカッコよさが最大限に発揮されたHello, world!を書きます。~
 +++++++++
 [>++++++++>+++++++++++>+++++<<<-]
 >.
 >++.+++++++..+++.
 >-.------------.
 <++++++++.--------.+++.------.--------.
 >+.
119文字、という事は、最初のプログラムの1/3以下という事です。~
簡単に解説すると、最初に0番地をカウンタにして9回ループさせます。~
このループで1番地が72、2番地が99、3番地が45になります。~
後は、1番地を使ってHを、2番地を使って、e、l、l、o、w、o、r、l、dを、3番地を使って,、 、!を出力させるだけです。~
***echoプログラムを作る! [#m858ccb4]
g01アプリをabcdwを使って学んだ人なら誰でも知っているechoプログラムを製作します。~
とはいいつつも、ものすごく簡単なので説明は省きます。~
 +[>,.<]
これさえあれば、一時的にコンソールにメモをすることが出来ます。~
***charsプログラムを作る! [#r0398d88]
同じくabcdwでおなじみのcharsプログラムです。~
0x20~0x7eの文字コードを持つ文字を出力させます。~
これも、最終段階のHello, world!が理解できた人なら難なく理解できると思います。~
 +++++++++
 [>++++++++++>++++<<-]
 >+++++
 >----<
 [>.+<-]
色々と最適化の余地があるので、考えてみてください。~
***1~10の合計を数える! [#x095ab75]
K-tanさんがGUIGUI01/memoシリーズで作ったプログラムの一つである、1~10の合計を数えるプログラムをBrainf*ckで作っていきたいと思います。~
 ++++++++++ +++++++++  ++++++++   +++++++    ++++++
 +++++      ++++       +++        ++         +
 .
これは誰でも思いつくと思います。~
これを実行すると、7と表示されます。7の文字コードは55なので、1~10の合計は55であることが分かります。~
しかし、この方法だと55回+を打ち込まないとこのプログラムは作れないので、実行しなくても何回+を打ち込んだか数えればいい話です。~
それはBrainf*ck的には勿論のこと、一般常識に照らし合わせてみても全然カッコ良くないので、ループを使って数えさせてみます。~
 ++++++++++
 [[>+>+<<-]>-[<+>-]<]
 >>.
ちょっと複雑なループですが、要は1~10の合計を数えさせているだけなので、じっくりと読んでみてください。~
さきほどのプログラムに比べればだいぶ良くなりましたが、答えは55なのに7と表示されるのがあまりカッコよくありません。~
しかし、Brainf*ckで55と表示させるのはかなり難しいので、1~10の合計の数だけ1を表示して、1行ずらして10ごとに0~9の数字を表示させてみます。~
ただ、文字コードを全て暗記している人にとっては、わざわざ1を数えるよりも7と表示されたほうがいいかもしれないので、7と表示する部分も残しておきました。~
 ++++++++++
 [[>+>+<<-]>-[<+>-]<]
 >>.
 >++++++++++.++++++++++++++++++++++.-------------------------
 [>+>+++++++<<-]
 <
 [>>?>.<<<-]
 >++++++++++.
 >>>>+++++
 [>++++++++++>++++++<<-]
 >--
 >++
 >++++++++++
 [><<<.+>>>+++++++++[><<<.>>><-]<-]
かなり汚いプログラムですいません。~
書いているときは全く問題なかったのですが、今改めて見ると書いた自分でも「なんじゃこりゃ?」状態です。~
しかし、それがBrainf*ckの醍醐味だと思うので気にしないことにします。~
なお、プログラム中の?を.に変えれば、一部のOSでは1~10の合計と同じ回数音が鳴ります。~
うるさくしても問題ない環境で試してみてください。~
最後に、これまでの集大成として、1~10の合計を文字コードとみなして表示する前にASCIIcodeと表示させたいと思います。~
これでいきなり7と表示されても戸惑う事が少なくなるはずです。~
 ++++++++++
 [>++++++>++++++++>++++++++++>+++++++++++<<<<-]
 >+++++.>+++.<++.++++++..>>-.>+.<+.+.>>
 ++++++++++
 [[>+>+<<-]>-[<+>-]<]
 >>.
 >++++++++++.++++++++++++++++++++++.-------------------------
 [>+>+++++++<<-]
 <
 [>>?>.<<<-]
 >++++++++++.
 >>>>+++++
 [>++++++++++>++++++<<-]
 >--
 >++
 >++++++++++
 [><<<.+>>>+++++++++[><<<.>>><-]<-]
?を.に変えると音が鳴るのは今回も変わりません。~
このレベルのプログラムが問題なく読めて、作れるようであれば、十分%%変人%%だと思います。~
**MONAmonaでプログラミング [#j9bcfdcd]
MONAmonaはBrainf*ck系統の言語です。~
ip02.g01でMONAmonaで書かれたプログラムを実行するには、~
 プロンプト>efg01 ip02 file:ファイル名 type:1
と入力します。~
MONAmonaでは>、<、+、-、,、.、[、]、がそれぞれM、O、N、A、m、o、n、a、に置き換えられます。~
つまり、~
 M ポインタを1進める
 O ポインタを1戻す
 N ポインタの指す所の値を1増やす
 A ポインタの指す所の値を1減らす
 m ポインタの指す所へ値を入力
 o ポインタの指す所の値を出力
 n ポインタの指す所の値が0だったら対応するaまでジャンプ
 a ポインタの指す所の値が0でなかったら対応するnまでジャンプ
となります。~
MONAmonaでは、M、O、N、A、m、o、n、a、以外の文字は全てコメントとして無視されます。~
以下に、MONAmonaでのHello, world!を示します。~
 NNNNNNNNN                                +++++++++
 nMNNNNNNNNMNNNNNNNNNNNMNNNNNOOOAa        [>++++++++>+++++++++++>+++++<<<-]
 Mo                                       >.
 MNNoNNNNNNNooNNNo                        >++.+++++++..+++.
 MAoAAAAAAAAAAAAo                         >-.------------.
 ONNNNNNNNoAAAAAAAAoNNNoAAAAAAoAAAAAAAAo  <++++++++.--------.+++.------.--------.
 MNo                                      >+.
勿論右側は無視されます。~

**BrainCrashでプログラミング [#i3b6f609]

« Prev[4]  Next »[5]