JVM関連でforthに触ってみる
タイトル通りなんですが、いきなりJVMの動きを追うのも、ちときついかと思いまして
JVMの元になった、forthにでも触ってみようと思います。
forthの源流を追っていくと、バローズのマシンまで行き着いてしまうらしいのですが
それは、ご勘弁と言う事で。
どこからか、forthを調達してこなければなりません。DebianでやるかFreeBSDで
やるか? 悩む程の事は無いのですが、2chを読むために、たまたまFreeBSDが
立ち上がっていたので、今回は、FreeBSDで行きます。
どんなものがあるやら?
[sakae@fb /usr/ports/lang]$ cd /usr/ports/
[sakae@fb /usr/ports]$ make search key=forth|more
Port: ficl-4.0.31_1
Path: /usr/ports/lang/ficl-devel
Info: Forth Inspired Command Language
Maint: bms@FreeBSD.org
B-deps: gettext-0.14.5_2 gmake-3.81_1 libiconv-1.9.2_2
R-deps:
WWW: http://ficl.sourceforge.net/
Port: pfe-0.29.1_1
Path: /usr/ports/lang/forth
Info: Implementation of ANSI Forth
Maint: andrew.nau.ua@gmail.com
B-deps: gettext-0.14.5_2 gmake-3.81_1 libiconv-1.9.2_2
R-deps:
WWW: http://pfe.sourceforge.net/
Port: gforth-0.6.1_2
Path: /usr/ports/lang/gforth
Info: Fast and portable Forth system
Maint: ports@FreeBSD.org
B-deps: gettext-0.14.5_2 gmake-3.81_1 libiconv-1.9.2_2
R-deps:
WWW: http://www.gnu.org/software/gforth/gforth.html
Port: pfe-0.32.94_1
Path: /usr/ports/lang/pfe-devel
Info: Implementation of ANSI Forth
Maint: andrew.nau.ua@gmail.com
B-deps: gettext-0.14.5_2 gmake-3.81_1 libiconv-1.9.2_2 perl-5.8.8
R-deps:
WWW: http://pfe.sourceforge.net/
いろいろありますなあ!
今回は、gforthで行ってみます。
[sakae@fb /usr/ports/lang/gforth]$ sudo make
===> gforth-0.6.2_2 is marked as broken: Does not compile on ports build cluster.
*** Error code 1
たまに、こういう事ってあるんですよ。めげないで、Makefileを眺めます。
.if ${OSVERSION} < 700000
BROKEN= Does not compile on ports build cluster
.endif
事故責任で、これをコメントアウトしたら、コンパイル、インストールまで出来ちゃい
ましたよ。
早速、起動してみます。
[sakae@fb ~]$ gforth
Gforth 0.6.2, Copyright (C) 1995-2003 Free Software Foundation, Inc.
Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license'
Type `bye' to exit
1 2 3 + ok
ok って言われたってねぇ。この先どうしたらいいん? マニュアルを探してきました。
. 5 ok
. 1 ok
.
*the terminal*:4: Stack underflow
.
^
Backtrace:
$33D8ED44 dup
$33D8F9E0 s>d
2足す3は5で、それがスタックに積まれる。(この時点で、2と3はスタックから
消えている) . は、スタックから、データを取り出して表示するって訳だ。
1 2 3 4 ok
.s <4> 1 2 3 4 ok
は、データを4つスタックに積んで 取り合えず ok。.s は、スタックを調査
するコマンドだ。現在、4個のデータがスタックにあり、一番最後(上)にある
データは、4.
: foo compiled
dup * compiled
; ok
今度は、foo と言うコマンドを定義してみた。(定義の終了は、; だ)
スタックの一番上のデータを複製してから掛け算せよ。結局、スタックのTOPに
あるデータを、2乗した事になる。
foo cr .
16 ok
.s <3> 1 2 3 ok
2乗してから、カーソルを改行(cr)、そして、結果を表示。この時点で、スタック
上のデータは、一つ無くなっている。
see foo
: foo
dup * ; ok
先ほど定義した foo を、確認してみた。
gforth に、あらかじめ定義されているコマンドも、see で、確認出来る。
see *
Code *
( $804C0AE ) mov dword ptr 8062094 , ebp \ $89 $2D $94 $20 $6 $8
( $804C0B4 ) mov ebx , dword ptr 4 [esp] \ $8B $5C $24 $4
( $804C0B8 ) mov edx , dword ptr [ebx] \ $8B $13
( $804C0BA ) mov eax , dword ptr 4 [ebx] \ $8B $43 $4
( $804C0BD ) imul eax , edx \ $F $AF $C2
( $804C0C0 ) add ebx , # 4 \ $83 $C3 $4
( $804C0C3 ) mov dword ptr 4 [esp] , ebx \ $89 $5C $24 $4
( $804C0C7 ) add ebp , # 4 \ $83 $C5 $4
( $804C0CA ) mov dword ptr [ebx] , eax \ $89 $3
( $804C0CC ) mov eax , dword ptr FC [ebp] \ $8B $45 $FC
( $804C0CF ) jmp 804B470 \ $E9 $9C $F3 $FF $FF
end-code
ok
おお、いきなり、インテルと出会ってしまったわい。¥以降は、マシン語ね。
やっぱり、インテルは避けて通れないか。
と、まあ、恣意的な事を書いてきました。まとめとして、マニュアルを見ると
5.6.1 Data stack
drop w - core “drop”
nip w1 w2 - w2 core-ext “nip”
dup w - w w core “dupe”
over w1 w2 - w1 w2 w1 core “over”
tuck w1 w2 - w2 w1 w2 core-ext “tuck”
swap w1 w2 - w2 w1 core “swap”
pick S:... u ? S:... w core-ext “pick”
等と、かかれています。何か判じものみたいですね。でも、dupの所にある
w - w w と言うのは、- を、境に左側が演算前、右側が結果ですと読みます。
演算前にTopに w と言うデータがあり、それを取り出して、2回stackにpush
すると言う具合。nipだと、TOPから2番目のデータを消し去る、ですね。
と、まあ、gforthを見てきたけど、余り参考にならんなー。
何かないものかと探してみると、笹田先生のYARVがあるじゃないですか。
YARVの命令表と解説も、ばっちりまとめてありますね。更に、YARVを解析された方もおられる。
嬉しくなって、Ruby-1.9.2devを思わず入れてしまいました。
sakae@debian:~$ ruby -v
ruby 1.9.2dev (2009-04-03 trunk 23129) [i686-linux]
ruby-1.9Xって、コンパイルにめちゃ時間がかかるようになりました。特にGB-XXXの
コード変換(?)に時間がかかってます。中国4000年の文化の凝縮ですから、我慢我慢。
先ほど、Sunから、javaがUpdateしましたって、案内があったけど、JVMより先にYARVだな。