4: 2009-12-20 (日) 08:30:58 HOSINO[6] [7] | 現: 2024-01-08 (月) 12:58:43 lina[8] [9] | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | *efg01上で動くプログラムの作り方講座(1) [#ab5c428e] | ||
**この講座について [#jb0faaac] | **この講座について [#jb0faaac] | ||
星野が作ったインタプリタ(ip.g01)の上で動くプログラムを作る事を目標とします。~ | 星野が作ったインタプリタ(ip.g01)の上で動くプログラムを作る事を目標とします。~ | ||
Line 10: | Line 9: | ||
ip.g01はhttp://osask.net/w/513.htmlから入手できます。~ | ip.g01はhttp://osask.net/w/513.htmlから入手できます。~ | ||
後はip.g01とefg01を同じフォルダに入れておいてください。~ | 後はip.g01とefg01を同じフォルダに入れておいてください。~ | ||
+ | *efg01上で動くプログラムの作り方講座(1) [#ab5c428e] | ||
**HQ9+でプログラミング [#h9d2d97d] | **HQ9+でプログラミング [#h9d2d97d] | ||
まずはじめに、初心者向けのHQ9+という言語でのプログラミングをやってみましょう。~ | まずはじめに、初心者向けのHQ9+という言語でのプログラミングをやってみましょう。~ | ||
Line 18: | Line 18: | ||
上のような内容にしたテキストファイルをhello.txtという名前で保存します。~ | 上のような内容にしたテキストファイルをhello.txtという名前で保存します。~ | ||
このプログラムを実行したいときは、コンソールを開いて次のように打ち込みます。~ | このプログラムを実行したいときは、コンソールを開いて次のように打ち込みます。~ | ||
- | プロンプト>efg01 ip01 file:hello.txt type:10 | + | プロンプト>efg01 ip02 file:hello.txt type:10 |
これで無事にHello, world!プログラムを作ることが出来ました。~ | これで無事にHello, world!プログラムを作ることが出来ました。~ | ||
もし、上のように打ち込んでもHello, world!と表示されなければ、それまでのところで何か失敗をしているはずです。~ | もし、上のように打ち込んでもHello, world!と表示されなければ、それまでのところで何か失敗をしているはずです。~ | ||
Line 26: | Line 26: | ||
HH | HH | ||
という内容のファイルを実行させます。~ | という内容のファイルを実行させます。~ | ||
+ | |||
***プログラムが書いてあるファイルの中身を表示させる! [#id73c46d] | ***プログラムが書いてあるファイルの中身を表示させる! [#id73c46d] | ||
Hello, world!と表示するだけでは飽きてしまったと思いますので、今回はファイル出入力の一環としてHQ9+プログラムが書かれたファイルの中身を表示させてみようと思います。~ | Hello, world!と表示するだけでは飽きてしまったと思いますので、今回はファイル出入力の一環としてHQ9+プログラムが書かれたファイルの中身を表示させてみようと思います。~ | ||
Line 86: | Line 87: | ||
この命令は、変数に2を足し、さらにオブジェクトのインスタンスを生成します。~ | この命令は、変数に2を足し、さらにオブジェクトのインスタンスを生成します。~ | ||
HQ9++で書かれたプログラムをip01.g01で実行するときは、~ | HQ9++で書かれたプログラムをip01.g01で実行するときは、~ | ||
- | プロンプト>efg01 ip01 file:ファイル名 type:11 | + | プロンプト>efg01 ip02 file:ファイル名 type:11 |
とコマンドプロンプトに打ち込みます。 | とコマンドプロンプトに打ち込みます。 | ||
HQ9++ | HQ9++ | ||
Line 99: | Line 100: | ||
と表示され、プログラム終了時の変数の値は2で、オブジェクトのインスタンスが生成されています。~ | と表示され、プログラム終了時の変数の値は2で、オブジェクトのインスタンスが生成されています。~ | ||
ただし、情報隠蔽の原理に従って、このオブジェクトへのアクセスはできない様になっているようです。~ | ただし、情報隠蔽の原理に従って、このオブジェクトへのアクセスはできない様になっているようです。~ | ||
+ | |||
**HQ9F+でプログラミング [#ae1e7dc1] | **HQ9F+でプログラミング [#ae1e7dc1] | ||
HQ9F+も、HQ9+と互換性のある言語のひとつです。~ | HQ9F+も、HQ9+と互換性のある言語のひとつです。~ | ||
- | HQ9F+で書かれたプログラムをip01.g01で実行するときは、~ | + | HQ9F+で書かれたプログラムをip02.g01で実行するときは、~ |
- | プロンプト>efg01 ip01 file:ファイル名 type:12 | + | プロンプト>efg01 ip02 file:ファイル名 type:12 |
とコマンドプロンプトに打ち込みます。~ | とコマンドプロンプトに打ち込みます。~ | ||
新たにFという命令が加えられています。~ | 新たにFという命令が加えられています。~ | ||
Line 125: | Line 127: | ||
と表示されます。~ | と表示されます。~ | ||
また、お分かりだと思いますが、HQ9F+では、Fもコメントではなく命令として扱われるのでご注意ください。~ | また、お分かりだと思いますが、HQ9F+では、Fもコメントではなく命令として扱われるのでご注意ください。~ | ||
+ | |||
*efg01上で動くプログラムの作り方講座(2) [#qed0b097] | *efg01上で動くプログラムの作り方講座(2) [#qed0b097] | ||
前回はHQ9+系統のプログラミング言語を使ってプログラムを作りました。~ | 前回はHQ9+系統のプログラミング言語を使ってプログラムを作りました。~ | ||
Line 132: | Line 135: | ||
**Brainf*ckでプログラミング [#uf970460] | **Brainf*ckでプログラミング [#uf970460] | ||
Brainf*ckのプログラムをip02.g01で実行する際は、~ | Brainf*ckのプログラムをip02.g01で実行する際は、~ | ||
- | プロンプト>efg01 ip02.g01 file:ファイル名 type:0 | + | プロンプト>efg01 ip02 file:ファイル名 type:0 |
と打ち込みます。~ | と打ち込みます。~ | ||
- | HQ9+よりも早くインタプリタを製作していたため、typeの番号がHQ9+よりも小さいですが、ip01.g01ではBrainf*ckの派生言語は対応していません。~ | + | |
- | なるべくip02.g01をお使いになる事をお勧めします。~ | + | |
***まずはHello, world! [#j45975eb] | ***まずはHello, world! [#j45975eb] | ||
伝統は大切にするべきなので、いきなりですがHello, world!と表示するプログラムを以下に示します。~ | 伝統は大切にするべきなので、いきなりですがHello, world!と表示するプログラムを以下に示します。~ | ||
Line 235: | Line 237: | ||
+[>,.<] | +[>,.<] | ||
これさえあれば、一時的にコンソールにメモをすることが出来ます。~ | これさえあれば、一時的にコンソールにメモをすることが出来ます。~ | ||
- | |||
***charsプログラムを作る! [#r0398d88] | ***charsプログラムを作る! [#r0398d88] | ||
同じくabcdwでおなじみのcharsプログラムです。~ | 同じくabcdwでおなじみのcharsプログラムです。~ | ||
Line 246: | Line 247: | ||
[>.+<-] | [>.+<-] | ||
色々と最適化の余地があるので、考えてみてください。~ | 色々と最適化の余地があるので、考えてみてください。~ | ||
+ | ***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] | ||
+ | BrainCrashはBrainf*ckを拡張した言語です。~ | ||
+ | 新たにビット演算を行う命令が加えられました。~ | ||
+ | また、0バイトでHello, world!プログラムが書ける言語としても有名です。~ | ||
+ | ip02.g01でBrainCrashで書かれたプログラムを実行するには、~ | ||
+ | プロンプト>efg01 ip02 file:ファイル名 type:2 | ||
+ | と入力します。~ | ||
+ | 以下に、BrainCrashの追加機能を示します。~ | ||
+ | 追加命令~ | ||
+ | | レジスタが指しているメモリのアドレスにある値と、その次のアドレスにある値をOR計算し、 | ||
+ | レジスタが指しているアドレスの次のアドレスに値を入れます。 | ||
+ | また、レジスタの値は一つ進められます。 | ||
+ | & レジスタが指しているメモリのアドレスにある値と、その次のアドレスにある値をAND計算し、 | ||
+ | レジスタが指しているアドレスの次のアドレスに値を入れます。 | ||
+ | また、レジスタの値は一つ進められます。 | ||
+ | ~ レジスタが指しているメモリのアドレスにある値をビット反転(NOT計算)させます。 | ||
+ | レジスタの値は変化しません。 | ||
+ | ^ レジスタが指しているメモリのアドレスにある値と、その次のアドレスにある値をXOR計算し、 | ||
+ | レジスタが指しているアドレスの次のアドレスに値を入れます。 | ||
+ | また、レジスタの値は一つ進められます。 | ||
+ | 開始、終了時の挙動~ | ||
+ | 処理開始時、メモリにはHello, world!に相当する72,101,108,108,111,44,32,119,111,114,108,100,33が0番地よりこの順で積まれます。 | ||
+ | 終了時、現在レジスタが指し示すアドレスの値が0になるまでレジスタを1づつ進めて出力します。 | ||
+ | よって、BrainCrashでHello, worldを書くと、以下のようになります。~ | ||
+ | Let us write Hello world ! | ||
+ | 何かしら英文が書かれていますが、全部コメントなので無視されます。~ | ||
+ | これを実行すると、まずメモリにHello, world!に当たる文字コードが0番地から順に積まれ、レジスタは0番地を示しています。~ | ||
+ | そして、プログラムが何も書かれていないので、このまま終了処理に移行し、Hから順に文字が出力されつつレジスタの値が増加していきます。~ | ||
+ | !に当たる33を出力し、レジスタの値が1増加すると、レジスタが指し示すアドレスの値が0になるので、そこで処理が終了します。~ | ||
+ | BrainCrashのインタプリタでBrainf*ckのプログラムを動かす際には、~ | ||
+ | [>] | ||
+ | Brainf*ckのプログラム | ||
+ | [>] | ||
+ | とします。~ | ||
+ | ただし、ip.g01ではtypeの値を0にすればBrainf*ckのプログラムとして実行できるので、通常は使う事のないテクニックです。~ | ||
+ | *efg01上で動くプログラムの作り方講座(3) [#b5f36808] | ||
+ | 前回までは、難解プログラミング言語と呼ばれる言語でプログラミングを行っていました。~ | ||
+ | やはりそれらの言語では実用性が高いとは言えません。~ | ||
+ | 今回扱うeasy Forthは立派な実用言語であるForthを少し変更を加えた実用言語です。~ | ||
+ | これでip.g01でのプログラミングもかなり楽になるはずです。~ | ||
+ | ちなみに、easy Forthの「easy」は処理系にとって処理しやすいという意味で、初心者向け、という意味ではありません。~ | ||
+ | Forth自体が十分簡単な言語ですので、お間違えの無いように。~ | ||
+ | |||
+ | **easy Forthでプログラミング [#qb5d8096] | ||
+ | ip02.g01でeasy Forthのプログラムを実行するには~ | ||
+ | プロンプト>efg01 ip02 file:ファイル名 type:20 | ||
+ | と入力します。~ | ||
+ | ***基本はHello, world!! [#pb448222] | ||
+ | 今回もHello, world!と表示するプログラムから解説していきます。~ | ||
+ | : main | ||
+ | "!" "d" "l" "r" "o" "w" " " "," "o" "l" "l" "e" "H" | ||
+ | PUT PUT PUT PUT PUT PUT PUT PUT PUT PUT PUT PUT PUT | ||
+ | ; | ||
+ | 以上を実行すると、Hello, world!と表示されます。~ | ||
+ | easy Forthでは、プログラムはワードと呼ばれる物の集まりで出来ています。~ | ||
+ | このプログラムでは「:」「main」「"!"」「PUT」「;」などがワードです。~ | ||
+ | ワードとワードの間は一つ以上のスペースか改行で区切られている必要が有ります。~ | ||
+ | 最初の「:」というワードは新たに自分でワードを定義することを宣言するワードです。~ | ||
+ | このように、easy Forthでは、最初から定義されているワード以外に自分でワードを定義することが出来ます。~ | ||
+ | 「:」の次にワードが新たに定義するワードの名前となり、「;」までがワードの内容となります。~ | ||
+ | ここでは、mainというワードを定義していますが、インタプリタは実行を開始すると、このmainという名前のワードを探し、そこから処理を始めます。~ | ||
+ | そのため、easy Forthでは、必ずmainというワードを定義することが必要になります。~ | ||
+ | さて、ワードの中身ですが、二行目に"!"、"d"、"l"…というワードが有ります。~ | ||
+ | easy Forthでは、スタックと呼ばれる靴下のような物を使って色々な処理をするのですが、この"と"で文字が囲まれたワードはその文字のデータをスタックの中に放り込みます。~ | ||
+ | つまり、二行目が終わった段階で靴下の中身は以下のようになります。~ | ||
+ | (左側が靴下の口です。)~ | ||
+ | ------------------------------+ | ||
+ | H e l l o , w o r l d ! | | ||
+ | ------------------------------+ | ||
+ | Hello, world!を逆の順番でスタックに入れていったので、スタックの奥に!がきます。~ | ||
+ | 三行目のPUTというワードは、スタックから一つデータを取り出して、文字として出力するワードです。~ | ||
+ | 勿論靴下は物を入れたり出したりする穴は一つしかないので、最後に入れたHから、順番に出力されていきます。~ | ||
+ | このようにして、mainはHello, world!を出力するワードとして定義され、それがインタプリタによって実行されて、Hello, world!が表示されたわけです。~ | ||
+ | しかし、いちいちこんな書き方をしていたのでは、めんどくさいです。~ | ||
+ | 以下に、ちょっとめんどくさくなくなったHello, world!を示します。~ | ||
+ | : main "!dlrow ,olleH" PUT PUT PUT PUT PUT PUT PUT PUT PUT PUT PUT PUT PUT ; | ||
+ | PUTの連続がカッコ悪いのは変わりませんが、だいぶんまともに見えます。~ | ||
+ | easy Forthでは、もし"と"の間の文字が二つ以上なら、一つ一つに分解して一つずつスタックに入れてくれます。~ | ||
+ | そのため、最初の"!dlrow ,olleH"は"!" "d" "l" "r" "o" "w" " " "," "o" "l" "l" "e" "H"と解釈されるわけです。~ | ||
+ | つぎに、PUTの連続を何とかしたいと思います。~ | ||
+ | : main 0 "!dlrow ,olleH" print ; | ||
+ | : print BGN DUP WHL PUT RPT DRP ; | ||
+ | mainの次に、0というワードが有ります。~ | ||
+ | これは、スタックに0を積むワードです。~ | ||
+ | また、"!dlrow ,olleH"の次にprintというワードが有ります。~ | ||
+ | これは、最初から定義されているワードではなく、二行目で定義しているワードです。~ | ||
+ | ここで、処理が二行目に移ります。~ | ||
+ | 二行目では、C言語で言うところのwhile文が使われています。~ | ||
+ | easy Forthでの繰り返し処理は、以下のように書きます。~ | ||
+ | BGN ワード列(1) WHL ワード列(2) RPT | ||
+ | まず、ワード列(1)が実行されて、WHLに到達した時点でスタックから一つデータが取り出されます。~ | ||
+ | そのデータが0ならRPTの次まで処理をジャンプします。~ | ||
+ | そのデータが0以外ならばワード列(2)を実行し、BGNに戻り、以上の処理を繰り返し行います。~ | ||
+ | 今回ワード列(1)のところにあるのはDUPだけです。~ | ||
+ | このDUPはスタックから一つデータを取り出し、それを二回スタックに入れます。~ | ||
+ | つまり、スタックの一番上のデータを複製します。~ | ||
+ | 最後のDRPは、スタックから一つデータを取り出し、それを捨てるワードです。~ | ||
+ | では、print全体の処理を見てみます。~ | ||
+ | まず最初にワード列(1)のDUPで、スタックの一番上にあるHが複製されます。~ | ||
+ | 次にWHLで複製されたHが取り出されます。~ | ||
+ | Hの文字コードは72なので、0以外である為、ワード列(2)のPUTが実行されます。~ | ||
+ | PUTは、スタックからHを取り出し、表示します。~ | ||
+ | もう一度BGNの次のDUPが行われてeが複製され、0以外なので、表示されます。~ | ||
+ | これを繰り返して、!まで無事表示されます。~ | ||
+ | !を表示してBGNに戻ると、DUPで今度は0が複製されます。~ | ||
+ | そして、WHLで0が取り出され、0なのでPUTを行わずにRPTの次へ処理が移ります。~ | ||
+ | スタックの中に残った0をDRPで掃除します。~ | ||
+ | 次は、ワードの定義が終了した事を示す;が有るので、printワードを呼び出したmainワードに処理が戻る、という流れです。~ | ||
+ | これでだいぶんカッコ良くなりましたが、Hello, world!が逆向きなのが気に食わないので、これを何とかします。~ | ||
+ | : main 0 "Hello, world!" print ; | ||
+ | : print invert BGN DUP WHL PUT RPT DRP ; | ||
+ | : invert | ||
+ | VAR pointer VAR256 words | ||
+ | 0 pointer ! | ||
+ | 256 BGN DUP WHL | ||
+ | 1 - DUP words + 0 SWP ! | ||
+ | RPT DRP | ||
+ | BGN DUP WHL | ||
+ | words pointer @ + ! | ||
+ | pointer @ 1 + pointer ! | ||
+ | RPT | ||
+ | 0 words pointer @ + ! | ||
+ | 0 pointer ! | ||
+ | BGN words pointer @ + @ WHL | ||
+ | words pointer @ + @ | ||
+ | pointer @ 1 + pointer ! | ||
+ | RPT | ||
+ | ; | ||
+ | とりあえず、Hello, world!は正しい向きになりました。~ | ||
+ | 色々と新しいワードが出ていますが、これを今説明するのは難しいので、後回しにさせてください。~ | ||
+ | とりあえずこれで、printとinvertをきちんと定義すれば、0 "文字列" print とするだけで文字列が表示できるようになりました。~ | ||
+ | |||
+ | ***計算をする! [#j2b87d24] | ||
+ | いきなりですが、easy Forthを使って計算をさせて見たいと思います。~ | ||
+ | : main | ||
+ | 0 "11 + 3 = " print 11 3 + . "\n" PUT | ||
+ | 0 "11 - 3 = " print 11 3 - . "\n" PUT | ||
+ | 0 "11 * 3 = " print 11 3 * . "\n" PUT | ||
+ | 0 "11 / 3 = " print 11 3 / . "\n" PUT | ||
+ | 0 "11 % 3 = " print 11 3 % . "\n" PUT | ||
+ | ; | ||
+ | : print invert BGN DUP WHL PUT RPT DRP ; | ||
+ | : invert VAR pointer VAR256 words 0 pointer ! 256 BGN DUP WHL 1 - DUP words + 0 SWP ! RPT DRP | ||
+ | BGN DUP WHL words pointer @ + ! pointer @ 1 + pointer ! RPT 0 words pointer @ + ! 0 pointer ! | ||
+ | BGN words pointer @ + @ WHL words pointer @ + @ pointer @ 1 + pointer ! RPT ; | ||
+ | これを実行すると、11+3、11-3、11*3、11/3、11%3の結果がそれぞれ表示されます。~ | ||
+ | (*は掛け算、/は小数点以下切り捨ての割り算、%は割り算の余り)~ | ||
+ | まず、0 "11 + 3 = " printのところは前回までの内容なのでいいと思います。~ | ||
+ | invertの中身は今回も説明しません。もう少し待って下さい。~ | ||
+ | 2~6行目の最後の"\n" PUTはちょっと変に思われた方もいるかもしれません。~ | ||
+ | \nというのは改行を表す特別な文字で、この二文字で一文字として扱われます。~ | ||
+ | そのため、PUT一回で出力することが出来、これが出力されると改行されます。~ | ||
+ | さて、最後に残ったprintと"\n"の間の説明です。~ | ||
+ | 代表して、2行目で説明します。~ | ||
+ | まず、11というワードが実行され、スタックに11が積まれます。~ | ||
+ | 次に、3というワードが実行され、スタックに3が積まれます。~ | ||
+ | そして、+というワードでは、スタックから二つデータを取り出し、その二つを足して答えをスタックに積みます。~ | ||
+ | これで、11+3の答えである14がスタックに積まれるわけです。~ | ||
+ | 最後に、.というワードは、スタックから一つデータを取り出し、それを数値として出力します。~ | ||
+ | ここでは、14が出力されます。~ | ||
+ | 3~6行もほぼ同じです。割る方、割られる方、引く方、引かれる方に注意してください。~ | ||
+ | スタックの一番上のデータで(を)、二番目のデータを(から)割る(引く)します。~ | ||
+ | ***if文を使う! [#ac5b9d2b] | ||
+ | easy Forthでは、勿論if文も使う事が出来ます。~ | ||
+ | 以下にサンプルを示します。~ | ||
+ | : main | ||
+ | 100 RND DUP . 0 " + " print 100 RND DUP . 0 " = " print + , "\n" PUT | ||
+ | = IF 0 "That's true !" print ELS 0 "That's false !" print THN | ||
+ | ; | ||
+ | : print invert BGN DUP WHL PUT RPT DRP ; | ||
+ | : invert VAR pointer VAR256 words 0 pointer ! 256 BGN DUP WHL 1 - DUP words + 0 SWP ! RPT DRP | ||
+ | BGN DUP WHL words pointer @ + ! pointer @ 1 + pointer ! RPT 0 words pointer @ + ! 0 pointer ! | ||
+ | BGN words pointer @ + @ WHL words pointer @ + @ pointer @ 1 + pointer ! RPT ; | ||
+ | これを実行すると、足し算の問題が出題されます。~ | ||
+ | これに、正しい答えを入力してEnterを押すとThat's true !と、間違った答えを入力してEnterを押すとThat's false !と表示されます。~ | ||
+ | では、プログラムを見ていきます。~ | ||
+ | 2行目にRNDというワードが二回出ています。~ | ||
+ | このワードは、スタックから一つデータを取り出し、0~取り出したデータ-1までの数で、ランダムに一つ選んでスタックに積みます。~ | ||
+ | 今回はどちらも100が直前に積まれているので、0~99の間で、ランダムに数が積まれます。~ | ||
+ | (ちなみに、このランダムな数の事を乱数と言います。)~ | ||
+ | それらの数はそれぞれDUPで複製され、片方は.でそれぞれ出力されています。~ | ||
+ | " = "が出力された後、二つの乱数は足されています。~ | ||
+ | そして、,というワードがきます。~ | ||
+ | このワードは、このプログラムを実行している人に数字を入力してもらうワードです。~ | ||
+ | Enterで入力を終了します。~ | ||
+ | 数字以外はもちろん入力できず、入力された物は数字として処理されます。~ | ||
+ | 今回はこのワードで、それまでに表示した足し算の式の答えを入力してもらいます。~ | ||
+ | 2行目が終わった時点で、スタックの中には、一番上に入力してもらった数値が、二番目に足し算の答えが入っています。~ | ||
+ | 3行目では、いきなり=というワードが実行されます。~ | ||
+ | このワードはスタックから値を二つ取り出し、その二つの値が等しければ1を、等しくなければ0をスタックに積みます。~ | ||
+ | ここでは、足し算の答えと入力された答えが同じなら1が、違えば0がスタックに積まれます。~ | ||
+ | そしてついにIFです。~ | ||
+ | easy Forthでは、IFというワードは以下のように使います。~ | ||
+ | IF ワード列(1) ELS ワード列(2) THN | ||
+ | IFというワードが実行されるとスタックからデータが一つ取り出され、その値が0以外ならワード列(1)を、0ならワード列(2)を実行します。~ | ||
+ | もし、値が0の時何もしないのであれば、~ | ||
+ | IF ワード列(1) THN | ||
+ | とすることもできます。~ | ||
+ | 今回は、答えが正解ならワード列(1)が、不正解ならワード列(2)が実行されます。~ | ||
+ | 最後に、=と似たような意味を持つワード群を書いておきます。~ | ||
+ | = スタックの1番目のデータが2番目のデータと等しければ1を、そうでなければ0をスタックに積みます | ||
+ | < スタックの1番目のデータが2番目のデータより小さければ1を、そうでなければ0をスタックに積みます | ||
+ | > スタックの1番目のデータが2番目のデータより大きければ1を、そうでなければ0をスタックに積みます | ||
+ | <= スタックの1番目のデータが2番目のデータより小さいか等しければ1を、そうでなければ0をスタックに積みます | ||
+ | >= スタックの1番目のデータが2番目のデータより大きいか等しければ1を、そうでなければ0をスタックに積みます | ||
+ | <> スタックの1番目のデータが2番目のデータと等しくなければ1を、そうでなければ0をスタックに積みます | ||
+ | ***変数を使う! [#u26830eb] | ||
+ | ~ | ||
+ | ~ | ||
+ | ~ | ||
+ | ~ | ||
+ | ''工事中!''~ |
(This host) = http://osask.net