Smalltalk (3)
SMAPの慎吾ちゃんが昔宣伝してた体重計が壊れた。どうも、液晶が壊れたみたいでもう諦めるしか。 そんな訳なんで、ホームセンターへ出動命令が下りましたよ。
体重だけ測れる2000円台のやつと、体脂肪も測れる6000円台と、マーケットが綺麗に分かれて いるのね。女房のお目あては、勿論6000円台のやつ。メーカーはオムロンとタニタの2択。 前に使ってた、手に取って測るやつは面倒なので、今回はただ乗るだけってやつにした。
メーカーは、どっちにしようか迷ったけど、タニタの食堂のおばちゃんに敬意を払って、タニタに した。どちらのメーカーでも、ほぼ機能は一緒みたい。機能が豊富すぎて、機能がアイコン表示 してあったぞ。
家に帰って、早速個人情報の登録。その前に、お使いの地域を次の3択から選べですって。 曰く、北海道/本州、四国、九州/沖縄。そんな事初めて知ったよ。地域で選ぶなら、50/60Hz かなあ。電源周波数の誘導のキャンセルって事なら腑に落ちるんだけど。
これ、雑学クイズに出そうだな。正解は 地域による補正みたい。なるほどね。 一つ利口になったよ。
そして、測定原理はと言うと、、足を乗せる部分が4つの電極になってるんで、4端子網に よるインピーダンスを測定します。インピーダンスと言っても、抵抗と誘導成分らしい、そうか、 インピーダンスを測れば、足の長さと太さが分かる訳か。これは女性必携な機能だな。 タニタ独自の言い回しで、説明書には、体組成計 って書いてあったぞ。脂肪は電気を通さない事に着目して、体内脂肪量を計測してますってさ。
個人情報は、身長、男女、アスリートか否、年齢を入力して、試し測りをして登録と言うか機械学習。 後は、乗るだけで、体脂肪率とか表示しますだってさ。BMIも勿論自動表示。こういう事だな。
gosh> (define (bmi w h)(/. w h h)) bmi gosh> (define (foo-bmi w)(bmi w 1.75)) foo-bmi gosh> (define (hoge-bmi w)(bmi w 1.56)) hoge-bmi gosh> (hoge-bmi 50.0) 20.5456936226167 gosh> (foo-bmi 67.0) 21.877551020408163
BMIの計算は、体重(Kg)を身長(m)の2乗で割ったものです。今回は、2回身長で割ると言うズルを しました。fooさんの身長を登録しておいて、体重だけを入力すれば、BMIを計算してくれるように しました。hogeさんも同様にしました。 こんな事が、タニタの体組成計に埋め込まれているんだな。後は、筋肉量とか脂肪量とかあるけど、 表を引いているみたいだ。実に旨く、数値化してくれているもんだ。むにゃむにゃな説明しか、 読み取れなかったぞ。
ArchLinuxでもsqueak
ArchLinuxでもsqueakしたいぞ。提供されてんのかな?
community/squeak-vm 4.10.2.2602-1 A full-featured implementation of the Smalltalk programming language
一応、有名なアプリらしいんで、パッケージになってる事は分かった。素直に入れろってか。 まてまて、以前落とした、一粒で3度おいしいやつはどうだ? Linuxでも動きますって謳ってた から、きっと動くんだろう。今回はへそを曲げて、そっち方面でやってみる。
[sakae@arch squeak]$ ls -F image/ linux_run* vm_cog/ [sakae@arch squeak]$ cat linux_run #! /bin/sh ./vm_cog/linux/squeak.sh -vm-display-X11 -compositioninput ./image/Squeak4.3-ja.image &
Linux関係者だけを収監したよ。起動は、linux_run だけで良さそう。なんだけど、/bin/fgrepが 無いと言って起動しない。なんか、sqeak.shで特殊な事をやってるな。調べてみるか。
おいらの所のfgrepは、/usr/binの下に有るんよ。で、そこをクリアしても、今度は、
can't infer base LD_LIBRARY_PATH. Aborting.
とか言われる始末。おいらの所のlibcは、ArchLinuxの大改革を経て、/usr/libの下に大移動をし たんよ。そんなこんなで、ちょいとsqueak.shを書き換え。
: case `/usr/bin/ldd "$BIN/squeak" | /usr/bin/fgrep /libc. | sed 's/^.*=> //'` in /usr/lib/libc*) SVMLLP="/lib:/usr/lib";; /lib32/libc*) SVMLLP="/lib32:/usr/lib32";; : LD_LIBRARY_PATH=$PLUGINS:$SVMLLP:${LD_LIBRARY_PATH} exec "$BIN/squeak" "$@"
全ては、LD_LIBRARY_PATH を設定して、squeak様(最近は、患者様とか生徒様とか、異様な言葉使いが 流行ってて気持ち悪い)が、快適に働いて頂く為の下準備だったのね。まあ、こういう変更を施して 無事に動くようになりましたとさ。
FreeBSDではPharo
Linuxにsqueakをいれたんなら、FreeBSDではPharoで行ってみよう。portsになってるんで、Pharoは 一発で入った。けど、squeakも一緒についてきた。portsの説明書によれば、VMはsqueakのやつを 借用してるとか。へぇー、そうなんだ。CPUはどうであれ、Disk相当のイメージで勝負って事か。
何とかイメージだけじゃなくて、何とかチェンジと何とかソースもセットなんだな。チェンジの方は 、差分を保持してんのか、そして、そのソースも元にイメージが出来上がっているんだな。
[sakae@secd /usr/local/lib/squeak]$ file P* Pharo-1.4.changes: ASCII text, with very long lines, with CR line terminators Pharo-1.4.image: data PharoV10.sources: ASCII text, with very long lines, with CR line terminators
CRでターミネートされてるって事は、MAC屋さんが製造・メンテナンスしてるのかな。 ソースからイメージは、どうやって作るのだろう?
分からない事は、selfに聞けってのがSmalltalkでは鉄則らしい。どうやって聞けばいいの? Pharoの参考書には、MethodFinder なんてのがあるって書いてあったけど。。。 そうそう、Pharo by Example のはじめ方 なんてのがあるんで、この際、それに合わせてみよう。
そしてVMの方も例によってgdbで探検出来るようにしておこう。squaekのportsのMakefileを ちょいと眺めてみて、改変しとく。
# Plugin image must be writable, because of it copy to user's ~/.npsqueak/ and # be updated. SHAREMODE= 644 CONFIGURE_SCRIPT= ../unix/cmake/configure --CFLAGS=-g
コンパイルにはcmakeが使われている。mrubyみたいに、どこでも動いて欲しいってSmalltakerの 願いが込められているな。この所、Smalltalkを母に、Lispを父にPerlを姉にRailsを兄にした rubyが世界的に猛威を振るっているからなあ。
尤も、rubyが有名になったのはレールのおかげだけど。Smalltalkもそれに肖ろうとしたかどうか は良く知らないけど、海辺へGO なんてのが有るようだし、スモールトーク合宿 なんてのも行われいますからね。
余談はさておき、どんなVMが出来上がったかみると、
[sakae@secd /usr/local/lib/squeak/4.10.2-2602]$ ./squeakvm -version 4.10.2-2602 #1 XShm 2013年 3月 27日 水曜日 10時49分27秒 JST /usr/bin/cc FreeBSD secd 9.1-RELEASE FreeBSD 9.1-RELEASE #0 r243826: Tue Dec 4 06:55:39 UTC 2012 root@obrian.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386 plugin path: /usr/local/lib/squeak/4.10.2-2602/ [default: /usr/local/lib/squeak/4.10.2-2602/]
その成分は
[sakae@secd /usr/local/lib/squeak/4.10.2-2602]$ ldd squeakvm squeakvm: libm.so.5 => /lib/libm.so.5 (0x28133000) libiconv.so.3 => /usr/local/lib/libiconv.so.3 (0x2814d000) libfreetype.so.9 => /usr/local/lib/libfreetype.so.9 (0x28245000) libc.so.7 => /lib/libc.so.7 (0x282bd000) libz.so.6 => /lib/libz.so.6 (0x283e7000) libbz2.so.4 => /usr/lib/libbz2.so.4 (0x283fb000)
もっといろいろなライブラリーを抱えこんでいるかと思ったら、そうじゃないのね。代わりは プラグインに任せているのかな。
[sakae@secd /usr/local/lib/squeak/4.10.2-2602]$ ldd so.vm-display-X11 so.vm-display-X11: ldd: so.vm-display-X11: Shared object "so.vm-display-X11" not found, required by "ldd" so.vm-display-X11: exit status 1
lddだと気分を害されてしまったようなので、readelfあたりを使ってみると
Dynamic section at offset 0x17380 contains 29 entries: Tag Type Name/Value 0x00000001 (NEEDED) Shared library: [libXrender.so.1] 0x00000001 (NEEDED) Shared library: [libSM.so.6] 0x00000001 (NEEDED) Shared library: [libICE.so.6] 0x00000001 (NEEDED) Shared library: [libX11.so.6] 0x00000001 (NEEDED) Shared library: [libXext.so.6] 0x00000001 (NEEDED) Shared library: [libGLU.so.1] 0x00000001 (NEEDED) Shared library: [libGL.so.1] 0x00000001 (NEEDED) Shared library: [libc.so.7] 0x0000000e (SONAME) Library soname: [so.vm-display-X11] 0x0000000f (RPATH) Library rpath: [/usr/local/lib]
ふーん、オブジェクト嗜好だけあって、リソースも委譲してんだな。徹底してる事!
ここまでは良いとして、 gdbを使おうとすると、環境を整えているsqueak.shが邪魔になる。必要最低限の環境を 持って行って起動してみよう。
./squeakvm -plugins . -display unix:0 pharo.image
必要そうな、squeakvmとso.vm-display-X11を持ってきたんだけど、何か音のするものも欲しいって 言って、ゲロ吐いちゃったよ。どんな事VMが考えてたか調べてみる。
[sakae@secd ~/.npsqueak]$ gdb squeakvm squeakvm.core : (gdb) bt #0 0x283b73f7 in kill () from /lib/libc.so.7 #1 0x283b7316 in raise () from /lib/libc.so.7 #2 0x283b5d9a in abort () from /lib/libc.so.7 #3 0x08084556 in loadModules () at /usr/ports/lang/squeak/work/Squeak-4.10.2.2602-src/unix/vm/sqUnixMain.c:930 #4 0x0808590b in main (argc=6, argv=0xbfbfe84c, envp=0xbfbfe868) at /usr/ports/lang/squeak/work/Squeak-4.10.2.2602-src/unix/vm/sqUnixMain.c:1399 (gdb) f 3 #3 0x08084556 in loadModules () at /usr/ports/lang/squeak/work/Squeak-4.10.2.2602-src/unix/vm/sqUnixMain.c:930 930 abort(); (gdb) l 925 abort(); 926 } 927 if (!soundModule) 928 { 929 fprintf(stderr, "squeak: could not find any sound driver\n"); 930 abort(); 931 } 932 933 dpy= (struct SqDisplay *)displayModule->makeInterface(); 934 snd= (struct SqSound *)soundModule ->makeInterface();
先ほど見たメッセージをオブジェクトのおいらは受け取りましたよ。で、おいらの挙動は、 適当なドライバーを用意しました。今の環境をインスペクトしてみます。
[sakae@secd ~/.npsqueak]$ ls PharoV10.sources pharo.image so.vm-sound-OSS* pharo.changes so.vm-display-X11* squeakvm*
これで、特製debug環境が用意できましたよ。ちゃんと動いたしね。ここらで、恒例の観察会をします。
(gdb) run Starting program: /usr/home/sakae/.npsqueak/squeakvm -plugins . -display unix:0 pharo.image Breakpoint 1, main (argc=6, argv=0xbfbfe794, envp=0xbfbfe7b0) at /usr/ports/lang/squeak/work/Squeak-4.10.2.2602-src/unix/vm/sqUnixMain.c:1346 1346 fldcw(0x12bf); /* signed infinity, round to nearest, REAL8, disable intrs, disable signals */ (gdb) n ;; 以下、nを乱打、gdbからのプロンプトは省略した 1351 argCnt= argc; 1352 argVec= argv; 1353 envVec= envp; 1367 if ((vmArgVec= calloc(argc + 1, sizeof(char *))) == 0) 1370 if ((squeakArgVec= calloc(argc + 1, sizeof(char *))) == 0) 1373 signal(SIGSEGV, sigsegv); 1387 tzset(); /* should _not_ be necessary! */ 1390 recordFullPathForVmName(argv[0]); /* full vm path */ 1391 squeakPlugins= vmPath; /* default plugin location is VM directory */ 1393 sqIgnorePluginErrors= 1; 1394 if (!modules) 1395 modules= &vm_Module; 1396 vm_Module.parseEnvironment(); 1397 parseArguments(argc, argv); 1398 if ((!dpy) || (!snd)) 1399 loadModules(); 1400 sqIgnorePluginErrors= 0; 1408 if (!realpath(argv[0], vmName)) 1417 initTimers(); 1418 aioInit(); 1419 dpy->winInit(); 1420 imgInit(); 1421 dpy->winOpen(); 1424 if (useJit) 1454 if (runInterpreter) 1455 interpret();
ここまでて、立ち上げてあるX画面に、world(と呼ばれる箱庭、若しくは監獄)が出現しましたよ。 後は、どこら辺で回ってるかだな。
^C Program received signal SIGINT, Interrupt. 0x283b8e23 in select () from /lib/libc.so.7 (gdb) bt #0 0x283b8e23 in select () from /lib/libc.so.7 #1 0x08081936 in aioPoll (microSeconds=1000) at /usr/ports/lang/squeak/work/Squeak-4.10.2.2602-src/unix/vm/aio.c:225 #2 0x08081bb1 in aioSleep (microSeconds=1000) at /usr/ports/lang/squeak/work/Squeak-4.10.2.2602-src/unix/vm/aio.c:277 #3 0x284307d5 in display_ioRelinquishProcessorForMicroseconds (microSeconds=1000) at /usr/ports/lang/squeak/work/Squeak-4.10.2.2602-src/unix/vm-display-X11/sqUnixX11.c:3720 #4 0x08083776 in ioRelinquishProcessorForMicroseconds (us=1000) at /usr/ports/lang/squeak/work/Squeak-4.10.2.2602-src/unix/vm/sqUnixMain.c:502 #5 0x08076c0c in primitiveRelinquishProcessor () at /usr/ports/lang/squeak/work/Squeak-4.10.2.2602-src/build/gnu-interp.c:22600 #6 0x0805a2fb in dispatchFunctionPointer (aFunctionPointer=0x8076bb0) at /usr/ports/lang/squeak/work/Squeak-4.10.2.2602-src/build/gnu-interp.c:3809 #7 0x08062776 in interpret () at /usr/ports/lang/squeak/work/Squeak-4.10.2.2602-src/build/gnu-interp.c:9339 #8 0x08085a16 in main (argc=6, argv=0xbfbfe794, envp=0xbfbfe7b0) at /usr/ports/lang/squeak/work/Squeak-4.10.2.2602-src/unix/vm/sqUnixMain.c:1455
ざっとこれを見る限り、監獄内の見回りは1ミリ秒間隔かな。後は、これたの道標を頼りに 興味の赴くまま道草してけばいいんだな。
リンク
毎度々、gdbによる観察会じゃ、あれなんで。。。
ちゃんとSmalltalkしようと思ったら、中身を知らなあかんな。何かないかと探してみたよ。 そしたら、 Squeakによるオブジェクト指向プログラミング入門 で、本質を掴んで、 チートシートを参照して、rubyのそれと比べてみるって コースが良さそうと思えたぞ。
実際に手を動かそうと思ったら、 探検会の記録を 読んで、雰囲気に慣れるか、 モサ伝:SqueakではじめるSmalltalk入門・アーカイブ とか言う、メルマガのアーカイブあたりが良さそうです。
チートシートのおかげで、鍵括弧は、(lambda ....)を表している事が明確になりました。ルビーだと、 do ... end とか、 {} か。 これだけ分かれば、後は、膨大なクラスの理解で事が足りる、、かな?
正統派の説明書は、
Squeak Smalltalk: Language Reference