そういえば Lightweight Language Day and Night 2005 で、どんなテーマにしたらよいかを皆さんが考えてくださったときに、
Masashi Umezawa wrote: > 今回プログラミングを担当されるのは鷲見さんですが、「応用編」に関しては > いろいろな人のアイデアを集めておいた方が有利かと思います。 > > 例: > - 解を出すまでの過程が視覚的に見える(パースツリー、3Dポリゴン) > - 意味もなく解を読み上げる > - ロボットが動き出し、達筆で答えを書く > > などなど、「応用編」にふさわしい「見せ方」といったものがありましたら、 > このMLにどしどしお寄せください。 > > それではよろしくお願い申し上げます。 ビジュアルではないですが、客層的には 1) 入力を受け取る 2) 解を返す Slang 文を生成する 3) VMMaker で C に変換 4) gcc でコンパイル 5) プラグインとして Squeak から呼び出して答えを表示 と言うのは如何でしょうか。
http://www.smalltalk.jp/pipermail/squeak-ja/2005-July/002532.html
なんてな id:propella さんのアイデアがあったなぁ…とふと思い出したので、遅まきなががらようやく Squeak VM 外部プラグインの作り方も分かったことだしと、さっそく簡単なところで試してみました。
| expression vmMaker newPluginFile pjDir vmDir | expression := FillInTheBlank request: 'expression:' initialAnswer: '3 + 4'. AdhocPlugin compile: ' primitiveCalc | ret | self primitive: ''primitiveCalc''. ret := ', expression,'. ^ ret asOop: SmallInteger' classified: 'primitives'. vmMaker := VMMaker default. vmMaker initializeInternal: #() external: #(AdhocPlugin). vmMaker deleteEntireGeneratedTree. vmMaker generateExternalPlugins. pjDir := 'Mac OS X:Users:yourhome:AdhocPlugin:'. Applescript doIt: ' tell application "Xcode" activate open alias "', pjDir, 'AdhocPlugin.xcode" clean build quit end tell'. newPluginFile := FileStream oldFileNamed: pjDir, 'build:AdhocPlugin.bundle:Contents:MacOS:AdhocPlugin'. vmDir := FileDirectory on: SmalltalkImage current vmPath, 'AdhocPlugin.bundle:Contents:MacOS'. vmDir deleteFileNamed: 'AdhocPlugin'. vmDir putFile: newPluginFile named: 'AdhocPlugin'. Smalltalk unloadModule: #AdhocPlugin. ^ AdhocPluginChecker calc
まず、最初の a FillInTheBlank で入力した式を含む Slang コード(AdhocPlugin >> #primitiveCalc)が a VMMaker により C 言語に(AdhocPlugin.c)。それを Xcode がコンパイル後、Squeak の VM 外部プラグインとしてビルド(AdhocPlugin.bundle)。さらに VM がこれを(機能的に)取り込むことで、スクリプトの最後にある AdhocPluginChecker class >> #calc を介したプリミティブ(原始メソッド。簡単にはネイティブコードで書かれたメソッド)としての評価が可能になる、というカラクリです。途中、Xcode の起動やプラグインのビルド作業には AppleScript を使っています。
なお、このスクリプトを機能させるためには、前のエントリーでとりあげた VM 外部プラグインの生成環境を整えるほかに、次のようなタネをあらかじめ仕込んでおく必要があります。
- AdhocPlugin を SmartSyntaxInterpreterPlugin のサブクラスとして定義
- AdhocPluginChecker と AdhocPluginChecker class >> #calc を定義
AdhocPluginChecker class >> calc <primitive: 'primitiveCalc' module: 'AdhocPlugin'> self primitiveFailed
- Xcode の AdhocPlugin プロジェクトをホームディレクトリに作っておく
- ビルド可能なように必要なファイルの追加や設定を済ませておく
- 一度ビルドに成功した AdhocPlugin.bundle を VM と同じディレクトリに置く
- TestOSAPlugin.bundle を入手し VM と同じディレクトリに置く
- Applescript(AppleScript スクリプトを実行するためのモジュール)のインストール
- AEDesc >> #createFromText: に、次の修正
- (aString class = String) ifFalse: ... → (aString isKindOf: String) ifFalse: ...