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 とか、 {} か。 これだけ分かれば、後は、膨大なクラスの理解で事が足りる、、かな?

正統派の説明書は、

Terse guide to Squeak

Squeak Smalltalk: Language Reference

Squeak Smalltalk: Classes Reference

Pharo online API reference