Hello, Forth World!!
はい。今日も新たな言語に挑戦してみます。前回は、s kだけで全部出来ちゃうよ〜という純粋関数型言語Unlambdaでしたが、今回はもうちょっと高級に攻めてみたいと思います。
今日の言語はForth。噂によると相当早い言語らしい。なんか聞いたことがあったけど、どんな言語かは知らなかったので謎を追っていきます。処理系はgforthを使います。
Hello, Forth World!!
とりあえず、Hello, world。
." Hello, Forth World!!" Hello, Forth World!! ok
ドットでprint。文字列の場合は、ドットと文字列の間はスペースは開けちゃダメらしい。
Hello, worldは謎が多いので次へ行きます。
(追記:突っ込みを頂きました。 ." という関数みたい。)
足し算
高級過ぎたので、もうちょっと低レベルに足し算行きます。
1 1 +
なんか見たことあるなぁ。と思ったら正解。.は表示なので、
1 1 + . 2
で、表示出来ます。
Forthは単なるスタック型言語でした。逆ポーランド電卓の高級な奴。
しかし、逆ポーランド電卓に少し毛が生えた感じじゃない。「もっさり」毛が生えてる。順を追って見ていこう。
スタック操作
スタックの中を除きましょう。
1 2 .s <2> 1 2 ok
<2>はスタックの詰まれた数。
取り出すときは、
1 2 3 . . . 3 2 1 ok
1を積んで、2を積んで、3を積んで、3を取り出して表示、2を取り出して表示、1を取り出して表示。
うぅん。簡単!!
スタックを捨てるdrop
1 drop .s <0> ok
スタックのコピーdup
1 .s dup .s <1> 1 <2> 1 1 ok
一個飛び越えてコピーover
1 2 .s over .s <2> 1 2 <3> 1 2 1 ok
おもろい。
入れ替えるswap。
.s swap .s <2> 1 2 <2> 2 1 ok
スタック3つをローテーション
.s rot .s <3> 1 2 3 <3> 2 3 1 ok
楽しい。まだまだいっぱいあるみたい。
さすがスタック型言語です。充実っぷりはリスト並です。
四則演算
計算。
1 2 + . 3 ok 3 4 - . -1 ok 5 6 * . 30 ok 7 8 / . 0 ok 9 10 mod . 9 ok
符合つき整数みたい。
続けて計算。
1 2 + 3 4 + * . 21
いち と に を たして さん と よん を たして かける。 ひょうじ。
Forthは日本語で読めます。スタック思考な日本人的には最適な言語かも。
コメント
プログラムにはコメントを。
1 1 + \ 足し算します。 ( これもコメント )
\と括弧がコメントっす。Forthには括弧が要らないので、コメントに使っちゃうみたい。Lisper的にはありえないっす!!
文字列
文字列は、s" Hello"らしい。
s" Hello" .s <2> 147052888 5
文字長と、ポインタをスタックに積んでる。Java系の文字格納法らしい。JavaVMはForthを参考に作ったらしいので、なんとなく納得した。
表示方法は後ほど・・・。
関数
というかマクロに近い。
: square ( n -- n^2 ) dup * ;
括弧の中はコメントなので、激しく無意味だけど、慣習的にこうするらしい。実体は、
: square dup * ;
こうなって、
2 square . 4
ははぁん。
see
デコンパイル出来る。
see square : square dup * ;
組込みは、
Code + ( $804E346 ) mov dword ptr 805E480 , ebp \ $89 $2D $80 $E4 $5 $8 ( $804E34C ) lea eax , dword ptr 4 [edi] \ $8D $47 $4 ( $804E34F ) mov edx , dword ptr [edi] \ $8B $17 ( $804E351 ) add ebp , # 4 \ $83 $C5 $4 ( $804E354 ) add dword ptr [eax] , edx \ $1 $10 ( $804E356 ) mov edi , eax \ $89 $C7 ( $804E358 ) mov ecx , dword ptr FC [ebp] \ $8B $4D $FC ( $804E35B ) jmp ecx \ $FF $E1 end-code
ほぉぉぉぉぉぉ。
ローカル変数付き関数
{}はかなり高級。「ローカル変数が持てる」凄いっす。
: swap { a b -- b a } b a ;
本物っぽい関数に出来る。どうなってんだ。
: square { a -- a^2 } a dup * ;
後ろのは相変わらずコメント。
どうなってるのかわからん。
seeしてみる。
see square : square >l lp- @local1 dup * lp+ ;
{}にすると。Cのローカル変数みたいな感じになるらしい。アセンブラよりは断然楽。
if
激しく読みづらいけどもちろんifもある。
: abs ( n1 -- +n2 ) dup 0 < if negate endif ;
アセンブラと同じ順。比較して、ジャンプ。アセンブラに毛が生えた程度。
比較はこんな感じ。
1 2 < . -1 ok 2 1 < . 0 ok
trueだと-1,falseだと0。何故-1なのか微妙な所だけど、ダンプしたときにフラグが全部立ってた方が見やすいとか。そんな感じかも。
elseもある。elseifは無いかも。
ガーン
書いたのに、消えてしまったorz
ま、Forthには、構造体やらクラスまであって、ただの逆ポーランド言語じゃない。
gforthのマニュアルは、Gforth Manualにあるので、ガッツリよんでくれぃ〜。