Meadow3でjdeeを使えるようにする

久しぶりに家の環境でjavaを使おうとMeadow3にjdeeをセットアップしようとするとちゃんと動かないご様子。
プアなマシンなのでeclipseを入れるのもなぁ、ということでエラーを追いかけて修正してみることにしました。

入れたもの
Meadow 3.02-r4261-3
apel 10.701
cedet 1.0pre6-1
elib 1.0-1
elscreen 1.4.5-1
imagemagick 6.2.8-0-Q16-1
info-ja-emacs 21.3.50-2
jdee 2.3.5.1-1
misc 0.7-1
psvn 16070-2

以上をnetinstallでインストールしました。


meadow起動後、(require 'jde) してみると*Backtrace*バッファにエラーが表示されちゃんとjdeが読み込まれません。
エラーは wrong-number-of-arguments ということでどこかの関数呼び出しの引数の個数がおかしいようです。


backtraceログのエラー箇所から近いところはcompiler-macroexpandやらbyte-optimize-*、byte-compile-*ばかりなのでとりあえずは関係なさそうなので適当に読み飛ばしていくと・・・


require(efc) としているところが見つかりました。
とりあえずここから追いかけていくことにして見ます。
emacs lispのrequireはfeature名に.elc(なければ.el)をつけたファイルをloadしてくれるようなのでefc.el、またはefc.elcというファイルがあるはずです。
探してみると $(MEADOW_INSTALL_DIR)/packages/lisp/jde/lisp/efc.el というファイルが見つかりました。
ほかの拡張子がelのファイルは拡張子elcのバイトコンパイルされたファイルが見つかりますが
efc-xemacs.el、efc.el、jde-xemacs.elの三つだけバイトコンパイルファイルがないようです。
efc-xemacs.elとjde-xemacs.elは名前からしてxemacs用でしょうから関係なさそうです。
というわけでefc.elをバイトコンパイルしてみます。


するとefc.el:646:42 でWrong number of argumentsでエラーが発生してとまりました。
該当行を見てみると efc-coll-addというメソッドを第一引数をefc-listで特殊化して宣言しています。

C-x C-e (eval-last-sexp) で (defmethod efc-coll-add ...) を評価しようとしても同様のエラーが起こりました。こいつがクロのようです。

*Backtrace*をよくみてみるとエラー箇所の近い呼び出しに compiler-macroexpand( (typep item) ) がありました。同様の呼び出しがefc-coll-add のerror関数呼び出しの第二引数にあります。


さて、common-lispではtypep関数は引数を二つとって第一引数が第二引数で指定した型と等しいかどうかを調べる関数のはずです。common-lispemacs-lispの違いはあれど普通は同じような関数のはず。


describe-functionでしらべてみると・・・

typep is a compiled Lisp function in `cl-macs.el'.
(typep object type)

Check that object is of type type.
type is a Common Lisp-style type specifier.

[back]

ということでどうもcommon-lispと同様の関数のようです。とするとこの部分の呼び出しがおかしいということになります。error関数のエラーメッセージのプレースホルダからみてどうもtypepで判定するのが必要ではなく、type-ofと書くべきところのようですので(typep item) を (type-of item) に書き換えました。

書き換えて保存し、再度byte-compile-fileすると別の箇所でエラーになりました。
(defmethod initialize-instance ((this efc-hash-table) &rest fields) ...)のなかでのエラーのようです。


エラーをみても該当箇所がわかりません。eval-last-sexp してもそのまま通ってしまいます。調べてみるとdefmethod自体はlisp macroなのでどうも展開された形を評価したときにエラーがあるように思われます。というわけでmacroexpandしてみます。

(macroexpand '(defmethod initialize-instance ((this efc-hash-table) &rest fields)
  "Hash table constructor."
  (call-next-method)
  (oset table (make-hash-table))))

(eieio-defmethod (quote initialize-instance) (quote ((... &rest fields) "Hash table constructor." (call-next-method) (oset table ...))))

ありゃ、省略されてしまいました。
たしかこの辺制御する変数が・・・ありました。eval-expression-print-levelです。4になっているのでnilにセットしてからmacroexpandしてみます。

(setq eval-expression-print-level nil)

(macroexpand 
 '(defmethod initialize-instance ((this efc-hash-table) &rest fields)
    "Hash table constructor."
    (call-next-method)
    (oset table (make-hash-table))))

(eieio-defmethod (quote initialize-instance) (quote (((this efc-hash-table) &rest fields) "Hash table constructor." (call-next-method) (oset table (make-hash-table)))))

出ました。
整形すると以下のようになります。

(eieio-defmethod 'initialize-instance
		 '(((this efc-hash-table) &rest fields)
		   "Hash table constructor."
		   (call-next-method)
		   (oset table (make-hash-table))))

バイトコンパイルのエラー出力をもう一度見てみると・・・

efc.el:760:61:Error: Wrong number of arguments: #[(obj slot value) "\303\304	D
F\207" [obj slot value eieio-oset quote] 4 ("g:/Emacsen/Meadow3/packages/lisp/cedet/eieio/eieio.elc" . 41185)], 2

eieio-osetというシンボルが見えます。もしかして・・・とosetをdescribe-functionしてみると・・・

oset is a Lisp macro in `eieio.el'.
(oset obj slot value)

Set the value in obj for slot slot to value.
slot is the slot name as specified in `defclass' or the tag created
with in the :initarg slot.  value can be any Lisp object.

[back]

で、というわけでマクロでした。
macroexpandしてみましょう。

(macroexpand '(oset table (make-hash-table)))

でました。どうもこいつがクロのようです。

上のosetの定義をよく見てみると・・・
(oset obj slot value) となっています。ですが 呼び出しは(oset table (make-hash-table))となっています。引数の個数が足りません。どうもobjがないようです。


文脈からみてobjは関数の第一引数のthisのようですからthisを付け足します。
(oset table (make-hash-table)) を (oset this table (make-hash-table)) に変更してもう一度バイトコンパイルします。


またエラー・・・えーかげんにせーよとか思いつつもみていきます。
今度はefc-coll-putという関数でwrong-number-of-argumentsです。
またtypepのようなので最初のエラーと同じように修正します。そしてバイトコンパイル・・・やっとうまくいったようです。


そして(require 'jde)してみると・・・
いきました。やっと動くようになったようです。


最後に変更部分のdiffをつけときます。

diff -u "g:/Meadow3/packages/lisp/jde/lisp/efc.el.orig" "g:/Meadow3/packages/lisp/jde/lisp/efc.el"
--- g:/Meadow3/packages/lisp/jde/lisp/efc.el.orig	2009-09-27 05:32:14.710375000 +0900
+++ g:/Meadow3/packages/lisp/jde/lisp/efc.el	2009-09-27 05:56:20.272875000 +0900
@@ -648,7 +648,7 @@
   (if (efc-coll-type-compatible-p this item)
       (oset this items (append (oref this items) (list item)))
     (error "Tried to add an item of type %s to a list of items of type %s"
-	   (typep item) (oref this elem-type))))
+	   (type-of item) (oref this elem-type))))
 
 (defmethod efc-coll-iterator ((this efc-list))
   "Return an iterator for this list."
@@ -760,14 +760,14 @@
 (defmethod initialize-instance ((this efc-hash-table) &rest fields)
   "Hash table constructor."
   (call-next-method)
-  (oset table (make-hash-table)))
+  (oset this table (make-hash-table)))
 
 (defmethod efc-coll-put ((this efc-hash-table) key value)
   "Put an item into the table."
   (if (efc-coll-type-compatible-p this value)
       (puthash key value (oref this table))      
     (error "Tried to add an item of type %s to a hash table of items of type %s"
-	   (typep value) (oref this elem-type))))
+	   (type-of value) (oref this elem-type))))
 
 (defmethod efc-coll-get ((this efc-hash-table) key)
   "Get an item from the table."

Diff finished.  Sun Sep 27 05:58:26 2009