[SML 7561] Re: 第8回Smalltalk勉強会@京都

AOKI Atsushi atsushi @ cc.kyoto-su.ac.jp
2009年 6月 4日 (木) 09:40:12 JST


青木@京都上賀茂です。

昨夜に行った京都駅前でのSmalltalk勉強会の簡単な報告をします。

3.5 メッセージ(p.88)から始めて、3.6 文(p.95)のカスケード
までゆきました。8ページしか進んでいない!のですが、7.2 本格的
な文法を併せて行いましたので、こちらが15ページ分あります。合
計して23ページ分になります。ちょうど良いペースでしょう。:-)

デバッカによる逐次実行で、メッセージの種類や優先順位(どの順
番でメッセージが発信されるか)などを、より深く理解していただ
けたのではないかと思います。

#初学者ほどデバッカを使うのが望ましい。

以下に単項メッセージセレクタ・二項メッセージセレクタ・キーワ
ードメッセージセレクタを求めるプログラムを記載しておきます。
ウィンドウのラベルに個数をつけておきました。

------------------------------------------------------------

"メッセージセレクタを種類別に求めてウィンドウにリストする"
| aSet aPoint |
aSet := Set new: 50000.
Smalltalk allBehaviorsDo: [:each | aSet addAll: each selectors].
aPoint := nil.
(Array
    with: 'Unary Message Selectors'
            -> [:each | each numArgs = 0 and: [each isKeyword not]]
    with: 'Binary Message Selectors'
            -> [:each | each numArgs = 1 and: [each isKeyword not]]
    with: 'Keyword Message Selectors'
            -> [:each | each numArgs >= 1 and: [each isKeyword]])
        do: [:anAssociation |
            | aString aBlock aStream aCollection aModel |
            aString := anAssociation key.
            aBlock := anAssociation value.
            aStream := WriteStream on: String new.
            aCollection := (aSet select: aBlock) asSortedCollection.
            aCollection do: [:each |
                    aStream
                        nextPutAll: each asString;
                        cr].
            aModel := ValueHolder with: aStream contents.
            TextEditorView
                open: aModel
                label: aString , ' : ' , aCollection size printString
                extent: 400 @ 300.
            (aModel dependents detect: [:each | each isKindOf: ScheduledWindow]
                ifNone: [nil])
                    ifNotNil: [:aWindow |
                        | aBox |
                        aPoint
                            ifNil: [aPoint := aWindow displayBox origin]
                            ifNotNil: [aPoint := aPoint translatedBy: 40 @ 30.
                                aBox := aPoint extent: aWindow displayBox extent.
                                aWindow displayBox: aBox]]].
^aSet

------------------------------------------------------------

また、構文木(JunParseTreeもしくはFooProgramScanner)を援用し
ました。構文木を深さ優先でたどれば、それが実行順序になること
も得心していただけたと思います。

プログラムコードを文字列として構文木に渡し、出せ!というだけ。

(JunParseTree code: '3 + 4 * 5') show

(JunParseTree code: '3 + (4 * 5)') show

次のような単項メッセージ・二項メッセージ・キーワードメッセー
ジが混ざったものでも、コンパイラの気持ちを知ることができます。

(JunParseTree code: 'Rectangle origin: 1 asPoint + 2 asPoint extent: 3 asPoint + 4 asPoint') show

また、クラスとメッセージセレクタを指定して構文木を出したり、
コンパイルドメソッドを指定して構文木を出したりできます。

(JunParseTree class: Integer selector: #factorial) show

(JunParseTree method: (Integer compiledMethodAt: #factorial)) show

------------------------------------------------------------

さらに、なぜカスケードが有用であるのかを、バイトコードから証
を立てることも行いましたので、そのプログラムを記しておきます。

------------------------------------------------------------

"カスケードを使わない場合"
[Transcript clear.
Transcript nextPutAll: 'ASAOKA Hiroko'.
Transcript cr.
Transcript nextPutAll: 'SAWAMOTO Eri'.
Transcript cr.
Transcript nextPutAll: 'AOKI Atsushi'.
Transcript cr.
Transcript flush]
    method symbolic

"以下のようなバイトコード列(30バイト)になります”
normal CompiledBlock numArgs=0 numTemps=0 frameSize=12

literals: ({Transcript} #clear 'ASAOKA Hiroko' 'SAWAMOTO Eri' 'AOKI Atsushi' #flush )

1 <34> push Transcript
2 <71> send clear
3 <66> pop
4 <34> push Transcript
5 <1E> push 'ASAOKA Hiroko'
6 <B5> send nextPutAll:
7 <66> pop
8 <34> push Transcript
9 <F0 21> send cr
11 <66> pop
12 <34> push Transcript
13 <1F> push 'SAWAMOTO Eri'
14 <B5> send nextPutAll:
15 <66> pop
16 <34> push Transcript
17 <F0 21> send cr
19 <66> pop
20 <34> push Transcript
21 <20> push 'AOKI Atsushi'
22 <B5> send nextPutAll:
23 <66> pop
24 <34> push Transcript
25 <F0 21> send cr
27 <66> pop
28 <34> push Transcript
29 <75> send flush
30 <65> return

------------------------------------------------------------

"カスケードを使った場合"
[Transcript
    clear;
    nextPutAll: 'ASAOKA Hiroko';
    cr;
    nextPutAll: 'SAWAMOTO Eri';
    cr;
    nextPutAll: 'AOKI Atsushi';
    cr;
    flush]
    method symbolic

"以下のようなバイトコード列(24バイト)になります”
normal CompiledBlock numArgs=0 numTemps=0 frameSize=12

literals: ({Transcript} #clear 'ASAOKA Hiroko' 'SAWAMOTO Eri' 'AOKI Atsushi' #flush )

1 <34> push Transcript
2 <68> dup first
3 <71> send clear
4 <69> dup
5 <1E> push 'ASAOKA Hiroko'
6 <B5> send nextPutAll:
7 <69> dup
8 <F0 21> send cr
10 <69> dup
11 <1F> push 'SAWAMOTO Eri'
12 <B5> send nextPutAll:
13 <69> dup
14 <F0 21> send cr
16 <69> dup
17 <20> push 'AOKI Atsushi'
18 <B5> send nextPutAll:
19 <69> dup
20 <F0 21> send cr
22 <6A> dup last
23 <75> send flush
24 <65> return

------------------------------------------------------------

以上、簡単ですが、昨日の勉強の報告でした。不足や他に思うとこ
ろなどがありましたら、ご参加いただいた皆さん、フォローをお願
いします。

#きっと浅岡さんが差し入れの報告をしてくれるにちがいない。

------------------------------------------------------------
AOKI Atsushi          http://www.cc.kyoto-su.ac.jp/~atsushi/


SML メーリングリストの案内