12
27Smalltalk勉強会 - Smalltalkの超能力 2010 Masashi Umezawa

MultilineクラスとMultilineメソッド

Embed Size (px)

DESCRIPTION

クラス名やメソッド名に改行がつかえるようにSmalltalkを拡張するとどうなるかという話。アスキーアートでメッセージ送信

Citation preview

Page 1: MultilineクラスとMultilineメソッド

第27回 Smalltalk勉強会 - Smalltalkの超能力

2010 Masashi Umezawa

Page 2: MultilineクラスとMultilineメソッド

動機

もっとクラス名、メソッド名をわかりやすくできないか? 長い名前とか、読むのが大変

ぱっと見ただけでわかるほうがいい

クラス名やメソッド名で改行つきの文字列を

使えれば、表現力が格段と高まるのではないか?

Page 3: MultilineクラスとMultilineメソッド

いらないクラスということがすぐにわかる

Object subclass: #'/ \

/ ─ ─\/ (●) (●) \ よく考えたら俺いらないな| (__人__) |/ ∩ノ ⊃ /( \ / _ノ | | .\ “ /__| |

\ /___ /'

instanceVariableNames: ''classVariableNames: ''poolDictionaries: ''category: 'Test-Multilines'

Page 4: MultilineクラスとMultilineメソッド

実装にあたって技術的には簡単

もともとクラス名やメソッド名はSymbolのインスタンス

Symbol自体には改行を含めることができる

○ #'改行文字列' のようにシングルクォートでくくればよい

開発環境の制限を外していくだけ

Page 5: MultilineクラスとMultilineメソッド

Multiline class

クラス名の先頭文字と使える文字に改行を追加

Character >> canBeGlobalVarInitialself = Character cr ifTrue: [^true].^ (EncodedCharSet charsetAt: self leadingChar)

canBeGlobalVarInitial: self.

基本これだけ

Page 6: MultilineクラスとMultilineメソッド

Multiline method (1)

開発環境の抵抗がなかなか強かったので、メソッド追加で対処

ClassDescriptiopn >> addAAMethod: aa body: bodyCode| code aaSymbol |code := 'tmp' , String cr , bodyCode.aaSymbol := aa asSymbol.self compile: code classified: ''.self addAndClassifySelector: aaSymbol

withMethod: (self methodDict at: #tmp)inProtocol: 'AA' notifying: nil.

self removeSelector: #tmp

Page 7: MultilineクラスとMultilineメソッド

Multiline Method (2)

各クラスのMethodDictionaryをいじってあげればよい tmpという名前でまずメソッドをコンパイル

コンパイルされたバイトコード(CompiledMethod)をアスキーアート(AA)をキーとして登録しなおす

tempのメソッドは消しておく

これでできた!

Page 8: MultilineクラスとMultilineメソッド

パーサライブラリの拡張 (1)

ワークスペース等で実行しやすいように既存のSmalltalkパーサライブラリを拡張する

DSL系を実装するには常套手段

Smalltalkでは自分をコンパイルするコンパイラクラスをクラス毎に指定できる

○ compilerClassメソッドのオーバーライド

今回は単にデフォルトのスキャナに手を入れるだけ

Page 9: MultilineクラスとMultilineメソッド

パーサライブラリの拡張 (2) スキャナにバッククォートのトークンを加える

AAをバッククォートで囲むと、クラスやメソッドの識別子としてパースされるようにしたいため

Scanner class >> initialize...newTable at: $` asciiValue put: #xBackQuote....

バッククォートを選んだ理由 他で使われていない

存在感が薄いのでアスキーアートを邪魔しない

Page 10: MultilineクラスとMultilineメソッド

パーサライブラリの拡張 (3)Scanner >> xBackQuote

self step.buffer reset.[hereChar = $`

and: [aheadChar = $`ifTrue: [self step. false]ifFalse: [true]]]

whileFalse: [buffer nextPut: self step.(hereChar = 30 asCharacter and: [source atEnd])

ifTrue: [^self offEnd: 'Unmatched string quote']].self step.token := buffer contents asSymbol.tokenType := #word

まじめに読む必要なし

xSingleQuoteメソッドをパクる

tokenTypeを#wordにする => 識別子になる

Page 11: MultilineクラスとMultilineメソッド

デモ AAクラスの定義

AAメソッドの定義

実行`

|┃三 ∩___∩|┃ | ノ ヽ|┃ ≡ / ● ● | きたクマー!

____,|ミ\___| (..●..) ミ|┃=___ |∪| \|┃ ≡ / ヽノ 人 \ ガラッ` new

`/⌒ヽ

∩ ^ω ^) うはwww| ⊂ノ

| _⊃ し ⌒`

Page 12: MultilineクラスとMultilineメソッド

まとめ

Smalltalkで、内部DSLをつくるのは非常に簡単

グラフィカルな表現もお手のもの

まじめな開発ではAAクラスとか使わないでください