キー入力エラー

Squeakにもだいぶ慣れてきて、ワークスペースへの入力が段々加速してくる。打鍵速度がどんどん高速になって行って、ほとんど同時押しくらいになってくると、なんか "subscript is out of bounds: 0"とかいうエラーがたくさん出てきて、かなりうっとーしい。環境は前の通り

VM
4.1.1beta2U
Image/Changeファイル
3.10.2-7179-basic-J
OS
Linux 2.6.24-23-generic #1 SMP Wed Apr 1 21:47:28 UTC 2009 i686 GNU/Linux

何なんだろう? エラー表示からしてまんま配列の0アクセスなんだけど(smalltalkの配列は 1はじまり)、、、

強力なデバック機能

Squeakでこういう例外事象が起こると、Errorウィンドウが出てトレースが表示される。

Array(Object)>>error:
Array(Object)>>errorSubscriptBounds:
Array(Object)>>at:
Character class>>value:
  :
  :

呼ばれたオブジェクト&メソッドが示されている。まあここまでは普通なんだけど、ここからが凄くてたとえばポチッと 一行目をクリックすると

error: aString 
	"Throw a generic Error exception."

	^Error new signal: aString

という表示と共にデバッカが立ち上がる。実際に呼ばれた式がハイライトされた状態で開くので、その部分だけを追っていくと簡単に実行トレースがわかる。そのときのオブジェクトの状態とか、ローカル変数なども(わざわざステップして絞り込まなくても)トレースとして好きな時に参照出来る。例外としてキャッチしてくれてさえいれば、これを地道に順に見ていくだけで、入出力を追いかけ、システム構造を理解し、問題の根幹を掌握することができる。すべてがオブジェクな一貫性の高い環境とあいまって非常にわかりやすい。
で、更にスゴイのが、このウィンドウの中の記述を変更して Alt-s すると、それが即座にシステムに反映されるということ。うひぃゃあ。一瞬でシステムを破壊してしまう脅威の神の手*1。コードを気軽に変更して試してみることができ、ロールバックも簡単、という真にオープンな環境になっている。

キーボードイベントルーチンのバグ?

と、言うわけで順にこれを見ていくと、どうやらキーボードイベントを生成しているのは HandMorphというオブジェクトらしい。これが生成している evtBufがいわゆるイベント構造体。その内訳はこんな感じなんだけど、

		["simulate keyboard event"
		array at: 1 put: EventTypeKeyboard. "evt type"
		array at: 2 put: Time millisecondClockValue. "time stamp"
		array at: 3 put: (kbd bitAnd: 255). "char code"
		array at: 4 put: EventKeyChar. "key press/release"
		array at: 5 put: (kbd bitShift: -8). "modifier keys"
		^ array].

この3番目がどういうわけか -1 になってしまうのが原因らしい。このため、その先のCharacter class >> value: で

value: anInteger 
	"Answer the Character whose value is anInteger."

	anInteger > 255 ifTrue: [^self basicNew setValue: anInteger].
	^ CharacterTable at: anInteger + 1.

の at:が 0になってしまう、というのがエラーの直接の理由だった。
今回はイベントの生成元を追うのが面倒くさくて、根元じゃなく安直に葉のほうで対処療法してしまった。

	(anInteger < 0) |(anInteger > 255) ifTrue: [^self basicNew setValue: anInteger].

とりあえず、エラーは出なくなったんだけど、こんなことでよいのかな。気が向いたらevent回りも調べてみようかなと思うけど・・・

*1:いやいや、ポジティブにポジティブに