[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15. Lispプログラムのデバッグ

Emacs Lispのプログラムに問題がおきたとき、 プログラムで何をしていたかによって、 問題を調べるための方法が三つあります。

そのほかに便利なデバッグ用ツールとしてドリブル・ファイルがあります。 ドリブル・ファイルを開けると、 キーボードからの入力文字はすべてそのファイルにコピーされます。 後々そのファイルを調べてどんな入力があったか、 確かめることができます。See section 端末入力

端末記述の問題のデバッグには、 open-termscript関数が便利です。See section 端末出力


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.1 Lispのデバッガ

Lispデバッガ(Lisp debugger)は、 形式の評価を途中で止めることができるようにします。 (ブレーク(break)という)評価が止められている状況では、 実行時スタックを調べたり、 ローカルもしくはグローバル変数の値を調べたり、 その値を変更したりできます。 ブレークは再帰編集であるため、 通常のEmacsの編集機能が有効です。 再帰的にデバッガにはいるプログラムを実行することさえ可能です。See section 再帰編集


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.1.1 エラーでデバッガにはいる

デバッガにはいる一番重要な場合はLispエラーのおきたときです。 これでエラーによる直接的な結果を調べることができます。

普段はエラーの結果としてデバッガにはいることはありません。 多くのコマンドは、 不適切なところで実行されると (バッファの最後でのC-f) よくLispエラーになるので、 通常の編集の最中にデバッガを呼び出すのは非常に困ります。 エラーのたびにデバッガにはいらせるには、 debug-on-errorを非nilにします。

User Option: debug-on-error

この変数は、ハンドルされないエラーが通知された場合、デバッガを呼 ぶべきか否かを定めます。 もしdebug-on-errortなら、 すべてのエラーでデバッガを呼びます。 nilの場合、デバッガは呼びません。

値はデバッガを呼ぶエラー・コンディションのリストでもかまいません。 たとえば、これをリスト(void-variable)に設定すると、 値のない変数についてのエラーだけがデバッガを呼びます。

この変数が非nilのとき、 プロセス・フィルターと見張りの処理で発生したエラーをEmacsが捕捉することはありません。 したがって、 このようなエラーでもデバッガを起動します。See section プロセス

`.emacs'ファイルのロード中におきるエラーをデバッグするには、 これは`.emacs'をロードしている間debug-on-errortに束縛し、 condition-caseで初期化ファイルのエラーをとらまえるのを禁止します。

もし`.emacs'ファイルでdebug-on-errorを設定しても、 その効果は`.emacs'のロードが終わるまでしかありません (これは`-debug-init'コマンド行オプションを実装する際に生じた 望ましくない副産物です)。 `.emacs'ファイルにdebug-on-errorを永久的に設定させるには、 次のようにafter-init-hookを使います。

 
(add-hook 'after-init-hook
          '(lambda () (setq debug-on-error t)))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.1.2 無限ループのデバッグ

プログラムが無限にループして、 戻れなくなっているとき、 最初の問題はループを止めることです。 ほとんどのオペレーティング・システムでは、 とりやめをするC-gでこれができます。

とりやめでは通常、 なぜプログラムがループしたのかについての情報を教えてはくれません。 より詳しい情報を得るには、 変数debug-on-quitを非nilに設定します。 C-gによるとりやめはエラーとはみなしません。 debug-on-errorC-gのハンドリングについての効果がありません。 同様にdebug-on-quitはエラーについての効果がありません。

無限ループの途中でデバッガを動かすと、 ステップ・コマンドを使ってデバッガからの続行が可能です。 ループ全体をステップすれば、 おそらく問題を解くのに十分な情報が得らえるでしょう。

User Option: debug-on-quit

この変数は、quitが通知されハンドルされなかった場合、 デバッガを呼ぶべきか否かを定めます。 debug-on-quitが非nilの場合、 とりやめる (つまりC-gを押下する) ごとにデバッガを呼びます。 debug-on-quitnilの場合、 とりやめてもデバッガは呼ばれません。See section とりやめ


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.1.3 関数呼出しでデバッガにはいる

プログラムの途中でおきる問題を調べるときに便利な手法として、 特定の関数を呼び出したときには必ずデバッガにはいる、 というのがあります。 問題のおきる関数や問題のおきるところより前の関数をこう設定しておいて、 その関数を呼ぶまでは素速くステップしたり、 呼出し元に戻るまでステップしたりできます。

Command: debug-on-entry function-name

この関数は、 function-nameが呼ばれるたびにデバッガを起動するようにします。 これは形式(debug 'debug)を関数定義の最初の形式として挿入すること で行ないます。

Lispコードで定義された関数は、 解釈されるコードであれコンパイルされたコードであれ、 どれでも(訳注:関数に)はいるときのブレークを設定できます。 関数がコマンドなら、 Lispから呼ばれた場合も、 対話的に呼ばれた場合も (引数を読み込んだ後) デバッガにはいります。 プリミティブ関数 (すなわちCで書かれた関数) はこの方法でのデバッグはできません。

debug-on-entryが対話的に呼ばれた場合、 function-nameを求めミニバッファにプロ ンプトを出します。

すでに関数へはいるときにデバッガを起動するよう設定してある場合、 debug-on-entryは何も行ないません。

注意!: debug-on-entryの後で関数を再定義すると、 デバッガにはいるコードはなくなります。

debug-on-entryfunction-nameを返します。

 
(defun fact (n)
  (if (zerop n) 1
      (* n (fact (1- n)))))
     ⇒ fact
(debug-on-entry 'fact)
     ⇒ fact
(fact 3)

------ Buffer: *Backtrace* ------
Entering:
* fact(3)
  eval-region(4870 4878 t)
  byte-code("...")
  eval-last-sexp(nil)
  (let ...)
  eval-insert-last-sexp(nil)
* call-interactively(eval-insert-last-sexp)
------ Buffer: *Backtrace* ------

(symbol-function 'fact)
     ⇒ (lambda (n)
          (debug (quote debug))
          (if (zerop n) 1 (* n (fact (1- n)))))
Command: cancel-debug-on-entry function-name

この関数は、function-nameにたいするdebug-on-entryを取り消します。 対話的に呼ばれた場合、function-nameを求めミニバッファにプロ ンプトを出します。 もしfunction-namenilや空文字列の場合は、 全関数のデバッグを取り消します。

同じ関数にたいしdebug-on-entryを複数回呼んだ場 合、2回目の呼出しは何も行ないません。 cancel-debug-on-entryfunction-nameを返します。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.1.4 陽にデバッガへはいる

プログラムに式(debug)を書いてデバッガを呼ぶこともできます。 そうするにはソース・ファイルを読み込み、 テキスト`(debug)'を挿入しC-M-xを押下します。 セーブする前に挿入を取り消すのを忘れないでください!

`(debug)'を入れるのは、 付加的な形式が評価されかつその値が無視されるような場所でなければなりません。 ((debug)の値が無視されなければ、 プログラムの実行を変えることになります!) 適切で、 ありがちな場所はprognや暗黙prognの内側です(see section 順次実行)。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.1.5 デバッガを使う

デバッガにはいると、 以前に選択していたバッファを片方のウィンドウに表示し、 そして`*Backtrace*'という名前のバッファを別のウィンドウに表示します。 バックトレース・バッファには、 1行ごとに現在のLisp関数実行の各レベルが示されます。 このバッファの最初に、 デバッガが呼び出された理由を示したメッセージがあります (たとえば、エラーによって呼び出された場合は、 エラー・メッセージとそれに関連するデータです)。

バックトレース・バッファは読出し専用で、 Debuggerモードという特別の主モードになっています。 そこでは、文字がデバッガ・コマンドとして定義されています。 普通のEmacs編集コマンドも使えます。 エラーの際に編集していたバッファを調べるためにウィンドウを切替えたり、 バッファを切替えたり、 ファイルを読み込んだりなどの編集もできます。 しかし、デバッガは再帰編集レベルにあります(see section 再帰編集)。 デバッガを使う必要がなくなったときは、 バックトレース・バッファに戻って (qコマンドで) 正式にデバッガを抜けなければなりません。 デバッガから抜けると、 再帰編集を終わらせてバックトレース・バッファをkillします。

バックトレース・バッファには、 実行している関数とそれに与えられた引数の値が表示されます。 また、ポイントを動かして、 その行が示しているスタック・フレームを指定する目的にも使えます (スタック・フレームとは、 Lispインタプリタが関数の実行についての情報を記録しておく場所です)。 ポイントがある行のフレームを現在のフレーム(current frame)とみなします。 デバッガ・コマンドのいくつかは現在のフレームに作用します。

デバッガ自身にスタック・フレームをいくつ作るかという仮定をするため、 デバッガ自身はバイトコンパイルした上で動作させる必要があります。 解釈されて動作しているときにはこの仮定がくずれてしまいます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.1.6 デバッガ・コマンド

デバッガ(Debuggerモード)の中では、 通常のカーソル移動コマンドのほかに特殊なコマンドが有効です (Emacsの普通の機能、 たとえば、ウィンドウやバッファを切替えたりすることは、 ずっと有効なことを忘れないでください)。

デバッガ・コマンドはコードにそってステップ実行するのに主に使われます。 これでどのように制御が流れるのかを見ることができます。 デバッガは解釈された関数の制御構造にそってステップできますが、 バイトコンパイルされた関数ではできません。 バイトコンパイルされた関数でそうしたいなら、 同じ関数を解釈されるような再定義に置き換えてください (それには関数のソース・ファイルを読み込み、 その定義のあるところでC-M-xを押下します)。

以下はDebuggerモードのコマンドの一覧です。

c

デバッガを抜けて実行を再開します。 再開が可能ならば、 あたかもデバッガにはいらなかったかのように (デバッガ内で変更した変数やデータ構造の作用は別として) プログラムの実行を続けます。

再開が可能なのは、 関数の入口、出口、陽に(訳注: デバッガを)呼び出したとき、 C-gによるとりやめ、 などがあります。 エラーのせいでデバッガにはいったときは続行ができません。

d

実行を再開しますが、 次にLisp関数が呼び出されるとまたデバッガにはいります。 これによって、一つの式の中の各式をステップ実行することができ、 それらの式が計算する値など実行状況を見ることができます。

このようにしてデバッガにはいった関数呼出しのスタック・フレームには、 そのフレームから抜けるときにもデバッガにはいるように自動的に印がつけられます。 この印を消すにはuコマンドを使います。

b

現在のフレームから抜けるときにデバッガにはいるようフレームに印をつけます。 このように印をつけたフレームには、 バックトレース・バッファで星を表示します。

u

現在のフレームから抜けるときにはデバッガにはいらないようにします。 これはフレームでのbコマンドの取り消しになります

e

Lisp式をミニバッファから読み込んで評価し、 その値をエコー領域に表示します。 デバッガは実行中にある重要な変数群を変更し、 操作の一部分としてカレント・バッファも変更します。 eは一時的にデバッガの外での値に復帰するので、 その変数の値も調べることができます。 これでデバッガがかなり透過的になります。 一方M-:は、デバッガの中でも特殊なことをしません。 デバッガの中での変数の値を表示します。

q

デバッグしているプログラムを終了します。 Emacsのコマンド実行のトップレベルに戻ります。

C-gによってデバッガにはいったが、 デバッグではなく本当にとりやめをしたいときに、 qコマンドを使います。

r

デバッガから値を返します。 その値はミニバッファで式を読み込み、評価して求めます。

rコマンドは (bを指定して) Lispの呼出しフレームから抜けたために呼び出されたデバッガでは便利です。 また、debugを呼んだときの値を使用するというときにも便利です。 それ以外の場合では、 rcは同じで、 指定した値は無視されます。

エラーのせいでデバッガにはいったときrは使えません。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.1.7 デバッガの起動

ここではデバッガを起動するための関数について詳しく述べます。

Function: debug &rest debugger-args

この関数は、デバッガにはいります。 バッファを`*Backtrace*' (2番目の再帰編集の場合`*Backtrace*<2>'など) という名前のバッファに切替え、 Lisp関数呼出しのスタックに関する情報を出力します。 この後、 バックトレース・バッファをDebuggerモードにして、 再帰編集にはいります。

Debuggerモードのcrコマンドは再帰編集を抜けます。 debugは前のバッファに戻し、 debugの呼び出したところに返します。 これは関数debugが呼出し元に返る唯一の方法です。

debugに渡したdebugger-argsの先頭がnilの場合 (またはそれが後述する表にある特殊な値でない場合)、 残りの引数は`*Backtrace*'バッファの先頭に表示されます。 このしくみはユーザへのメッセージを表示するのに使います。

しかし、debugの最初の引数が以下の特殊な値の一つである場合、 特別な意味をもちます。 通常、デバッガとEmacsの内部だけがそれらの値をdebugに渡し、 debugを呼んでいるプログラマが用いることはありません。

特別な値は、

lambda

最初の引数がlambdaの場合は、 debug-on-next-callnilでなかったときに関数を呼んだため、 debugにはいったということを意味します。 デバッガはバッファの先頭行に`Entering:'を表示します。

debug

最初の引数がdebugのときは、 関数にはいったときにデバッグするよう設定した関数に、 はいったことを示します。 lambdaの場合と同様に、 デバッガは`Entering:'を表示します。 この関数のスタック・フレームに印をつけて、 この関数から抜けたときにデバッガを起動するようにします。

t

最初の引数がtの場合は、 debug-on-next-callが非nilのときにリスト形式を評価したために、 debugを呼んだことを意味します。 デバッガはバッファの先頭行に

 
Beginning evaluation of function call form:

を表示します。

exit

最初の引数がexitの場合は、 フレームから抜けるときにデバッガを呼ぶように あらかじめ印をつけておいたスタック・フレームが、 抜けたことを示すのに用います。 この場合のdebugの次の引数は、 フレームの返した値です。 バッファの先頭行に`Return value:'を表示し、 返された値をこれに続けて表 示します。

error

第1引数がerrorの場合、 エラーかquitが通知されハンドルされなかったため、 デバッガにはいったことを示すのに用います。 `Signalling:'を表示し、 通知されたエラーとsignalにたいする引数とを後につけて表示します。 たとえば、

 
(let ((debug-on-error t))
  (/ 1 0))

------ Buffer: *Backtrace* ------
Signaling: (arith-error)
  /(1 0)
...
------ Buffer: *Backtrace* ------

エラーが通知されたのなら、 当然変数debug-on-errorは非nilです。 quitが通知されたのなら、 当然変数debug-on-quitは非nilです。

nil

あなたが陽にデバッガにはいりたいときは、 debugger-argsの最初にnilを使います。 バッファの先頭行にdebugger-argsの残りを表示します。 たとえば、debugを呼んだ条件を思い出すためメッセージを表示するのに、 この機能を使うことができます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.1.8 デバッガの内部

この節ではデバッガ内部で使っている関数と変数について述べます。

Variable: debugger

この変数の値は、デバッガを起動するために呼ぶ関数です。 この値は、 任意個の引数 をもちうる関数(もしくは、より一般的には関数の名前)でなくてはい けません。 この関数は、 何らかのデバッガにはいるものとされます。 この変数のデフォルト値はdebugです。

Lispがこの関数に渡す最初の引数は、 どのように呼ばれたかを示します。 引数に関する慣例の詳細は、 debugの記述で述べられています。

Command: backtrace

この関数は、今現在アクティブになっているLisp関数呼出しのトレースを印字します。 これはdebug`*Backtrace*'バッファを作る際、用いる関 数です。 どの関数呼出しがアクティブなっているかを調べるのにスタックをアクセ スしなくてはいけないため、この関数は、Cで書かれています。 常にnilを返します。

次はLisp式で陽にbacktraceを呼んだ例です。 これはバックトレースをストリームstandard-outputに印字します。 この場合は`backtrace-output'です。 バックトレースの各行が関数の一つの呼出しを表わします。 関数の引数の値がわかっているときは、各行に表示します。 計算中の場合はそのように表わします。 (この例では)特殊形式の引数が省略されています。

 
(with-output-to-temp-buffer "backtrace-output"
  (let ((var 1))
    (save-excursion
      (setq var (eval '(progn
                         (1+ var)
                         (list 'testing (backtrace))))))))

     ⇒ nil

----------- Buffer: backtrace-output ------------
  backtrace()
  (list ...computing arguments...)
  (progn ...)
  eval((progn (1+ var) (list (quote testing) (backtrace))))
  (setq ...)
  (save-excursion ...)
  (let ...)
  (with-output-to-temp-buffer ...)
  eval-region(1973 2142 #<buffer *scratch*>)
  byte-code("...  for eval-print-last-sexp ...")
  eval-print-last-sexp(nil)
* call-interactively(eval-print-last-sexp)
----------- Buffer: backtrace-output ------------

文字`*'は、 フレームのdebug-on-exitフラグが設定されていることを表わします。

Variable: debug-on-next-call

この変数が非nilのとき、 次のevalapplyfuncallの前にデバッガを呼ぶべきであることを示します。 デバッガがnilにします。

デバッガのdコマンドの動きはこの変数の設定によります。

Function: backtrace-debug level flag

この関数は、 levelレベル下のスタック・フレームのdebug-on-exitフラグをflagに設定します。 flagが非nilの場合、 そのフレームを抜ける際、 デバッガにはいるようにします。 フレームから局所的でない抜けかたをしてもデバッガにはいりま す。

この関数は、デバッガからのみ呼ばれます。

Variable: command-debug-status

この変数は、現在の対話的なコマンドのデバッグ状態を記録します。 コマンドが対話的に呼ばれるたびにこの変数は、nilに束縛されます。 デバッガは同じコマンドの実行中にあとで別なデバッガを起動するときのために 情報を残しておくのにこの変数を設定しておくことがあります。

別のグローバル変数でなくこの変数を使うことの、 デバッガにとっての利点は、 ひき続くコマンドの呼出しにデータを渡さないようにすることです。

Function: backtrace-frame frame-number

関数backtrace-frameはLispデバッガが使うことを想定しています。 frame-numberレベル下のスタック・フレームでおきている計算についての情報を返します。

そのフレームがまだ引数を評価していない(あるいは、特殊形式である)場合は、 値は(nil function arg-forms…)です。

そのフレームが引数を評価し、すでに関数を呼んでしまっているときは、 値は(t function arg-values…)です。

戻り値におけるfunctionは、 計算中のリストのCARとして与えられているもの、 あるいはマクロ呼出しの場合はlambda式となります。 関数に&rest引数があるときは、 リストarg-valuesの最後になります。

frame-numberが範囲外のとき、 backtrace-framenilを返します。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.2 誤ったLisp構文のデバッグ

Lispリーダは不正な構文について知らせてくれますが、 どこに真の問題があるのかについては、 何も教えてはくれません。 たとえば、エラー"End of file during parsing" (訳注:構文解析中にファイル終了) が式の評価中におこったら、 開き括弧(あるいは角括弧)が多すぎることを示します。 リーダはファイルの最後で不釣合いを検出しますが、 閉じ括弧をどこに置くべきかはわかりません。 同様に"Invalid read syntax: ")""は、 閉じ括弧が多すぎるのか開き括弧が少なすぎることを示しますが、 対応する括弧がどこなのかはわかりません。 このときにどうやって変えるところを見つけるのでしょうか?

問題が単に括弧の不釣合いでないとしても、 各defunの先頭でC-M-eをやってみて、 defunの最後にゆくかどうかを見るのは、 便利な手法です。 もし最後に行かないのなら、 問題はそのdefunにあります。

しかしながら、括弧の不対応はLispでは一番ありがちな構文エラーなので、 これに対処するための助言はさらに続きます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.2.1 余計な開き括弧

最初のステップは不釣合いなdefunを見つけることです。 開き括弧が多いときは、 ファイルの最後に閉じ括弧を置いてC-M-b (backward-sexp)を実行します。 こうすると不釣合いなdefunの先頭に来ることになります (そしてC-SPC C-_ C-u C-SPCで、 マークを設定し閉じ括弧の挿入を取り消し、 マークの場所に戻ることができます)。

次のステップはどこが誤っているのか決定することです。 プログラムから学ぶこと以外には、 これについて確かなことをいうことはできませんが、 往々にして、 既存の字下げが、 括弧がどこにあるべきかについての手がかりになることがあります。 この手がかりを使う一番簡単な方法は、 C-M-qで字下げしてどこが動くかを見ることです。

これをやる前には、 defunに十分な数の閉じ括弧があることを確認しておいてください。 さもないと、 C-M-qはエラーになるか、 ファイルの最後までを全部字下げしてしまうことになります。 ですから、 defunの最後に行って閉じ括弧をいれます。 defunが釣合っていなければだめなので、 ここでC-M-eを使ってはいけません。

さてここでdefunの先頭に行きC-M-qを押下します。 普通はある点以下のすべての行が右にずれるはずです。 多分その点の近くになくなった閉じ括弧か余計な開き括弧があるはずです (しかしながら常にそうとはかぎりません。 コードから学んで確かめてください)。 くいちがいがみつかったらC-M-qC-_で取り消します。 なぜなら前の字下げの方が、 意図していた括弧にたいしておそらく適切なはずだからです。

問題が直ったと考えたら、 ふたたびC-M-qを使います。 前の字下げが意図した括弧のネストと実際に合っていて、 その括弧を戻したのであれば、 C-M-qでは何も変わらないはずです。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.2.2 余計な閉じ括弧

余計な閉じ括弧を扱うには、 まずファイルの先頭に開き括弧を置いて1文字戻り、 C-M-fを押下し、 不釣合いなdefunの最後に行きます (そしてC-SPC C-_ C-u C-SPCで、 マークを設定し開き括弧の挿入を取り消し、 マークの場所に戻ることができます)。

そして実際に対応する閉じ括弧を見つけるには、 defunの先頭でC-M-fを押下します。 defunが終るべき場所より手前に来ることがあるかもしれませんが、 おそらくそのへんで余計な閉じ括弧を見つけることができるでしょう。

そこで問題がみえてこなければ、 次にすべきことはdefunの先頭でC-M-qを押下することです。 何行かは左にずれるはずです。 そのときに、 なくなった開き括弧や余計な閉じ括弧が、 ずれた行の前の方にあるはずです (しかしながら常にそうとはかぎりません。 コードから学んで確かめてください)。 くいちがいがみつかったらC-M-qC-_で取り消します。 なぜなら前の字下げの方が、 意図していた括弧にたいしておそらく適切なはずだからです。

問題が直ったと考えたら、 ふたたびC-M-qを使います。 前の字下げが意図した括弧のネストと実際に合っていて、 その括弧を戻したのであれば、 C-M-qでは何も変わらないはずです。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.3 コンパイル時の問題のデバッグ

バイトコンパイル中にエラーがおきたときは、 通常はコンパイルしているプログラム中の構文エラーが原因です。 コンパイラは適切なエラー・メッセージを`*Compile-Log*'バッファに印字して、 止まります。 メッセージの中にはエラーがみつかった関数名があることもありますが、 ないこともあります。 いずれにせよ、 以下ではファイルのどこでエラーがおきたのかを見つける方法について述べます。

まずすべきことはバッファ` *Compiler Input*'に切替えることです。 (バッファ名がスペースで始まっているため、 M-x list-buffersでは表示されません。) このバッファにはコンパイル中のプログラムがあり、 ポイントはバイトコンパイラがどこまで読み込んだかを示します。

エラーが不正なLisp構文によるものならば、 ポイントは不正な構文を検出したまさにその場所を示します。 エラーの原因はその近くとはかぎりません。 前節の手法を使ってエラーを見つけてください。

もしエラーが、 首尾よく読み込めた形式のコンパイル中に検出されたのなら、 ポイントはその形式の後にあるはずです。 この場合、 今の手法ではエラーを正確に局所化することはできませんが、 どの関数を調べればいいのかはわかります。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4 Edebug

Edebug はEmacs Lispプログラムのソース・レベル・デバッガで、 以下のようなことができます。

最初の三つの節を読めば十分にEdebugを使うことができるようになるでしょう。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.1 Edebug利用入門

EdebugでLispプログラムをデバッグするには、 まずあなたがデバッグしたいLispコードの膳立て(instrument)を しなければなりません。 これを簡単に行なう方法は、 まず、 ポイントをマクロや関数定義の中に移動して、 C-u C-M-x (前置引数をつけたeval-defun) をすることです。 コードの膳立てをするほかの方法についてはEdebugのために膳立てをする

いったん関数が膳立てをされると、 その関数のどのような呼出しもEdebugをアクティブにします。 Edebugをアクティブにすると、 あなたの選択したEdebug実行モードによって、 実行を停止して関数をずっとステップさせたり、 表示を更新しデバッグ用コマンドを調べながら実行を継続させたりすることがで きます。 デフォルトの実行モードはstepで、 これは実行を停止させます。See section Edebug実行モード

Edebugの中にいるときは、 デバッグ中のLispコードのソースを示しているEmacsのバッファを、 通常ながめることになります。 これをソース・コード・バッファ(source code buffer)といいます。 このバッファは一時的に読出し専用です。

左はしの矢印は関数の実行している箇所を示します。 ポイントははじめ関数が行のどこを実行しているのかを示していますが、 あなたが自分でポイントを動かしてしまうとそうでなくなります。

もし(以下に示す)facの定義の膳立てをして(fac 3)を実行すると、 以下のようなものが見られるはずです。 ポイントはifの前の開き括弧にあります。

 
(defun fac (n)
=>∗(if (< 0 n)
      (* n (fac (1- n)))
    1))

Edebugが関数中で実行を止められる 場所をストップ・ポイント(stop point)といいます。 これはリストである部分式の前後と、 変数参照の後に起きます。 以下に関数facのストップ・ポイントを終止符で示します。

 
(defun fac (n)
  .(if .(< 0 n.).
      .(* n. .(fac .(1- n.).).).
    1).)
; (訳注:原文には1-の前にストップ・ポイントがなかった。)

ソース・コード・バッファでは、 Emacs Lispモードのコマンドに加えて、 Edebugの特殊なコマンドが有効です。 たとえば、EdebugコマンドのSPCを押下して、 次のストップ・ポイントまで実行することができます。 facにはいった後、 SPCを1回押下した直後の様子を以下に示します。

 
(defun fac (n)
=>(if ∗(< 0 n)
      (* n (fac (1- n)))
    1))

Edebugが式の後で実行を止めたときは、 その式の値をエコー領域に表示します。

ほかによく使うコマンドとして、 bでストップ・ポイントにブレークポイントを設定したり、 gでブレークポイントまで実行したり、 qでEdebugを抜けて トップレベルのコマンド・ループに戻ったりすることができます。 ?で全Edebugのコマンドの一覧を見ることができます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.2 Edebugのために膳立てをする

LispコードをデバッグするのにEdebugを使うためには、 まずはじめにコードの膳立て(instrument)をすることが必要です。 コードの膳立てをすると適切な場所でEdebugを起動するコードを追加します。

いったんEdebugをロードすると、 コマンドC-M-x (eval-defun)は再定義されるので、 前置引数をつけて定義上で起動すると、 その定義を評価する前に膳立てをするようになります (ソース・コード自身は修正しません)。 もし変数edebug-all-defsが非nilのとき、 前置引数の意味を反転させます。 このときC-M-xは前置引数がないとき、 定義の膳立てをします。 edebug-all-defsのデフォルト値はnilです。 コマンドM-x edebug-all-defsは、 変数edebug-all-defsの値をトグルします。

edebug-all-defsが非nilのとき、 コマンドeval-regioneval-current-buffereval-bufferも、 評価する定義の膳立てをします。 同様に、edebug-all-formsは、 eval-regionが定義をしない形式も含んだ形式の膳立てをすべきかどうかを制御します。 これはロードや、 ミニバッファでの評価には関係ありません。 コマンドM-x edebug-all-formsは、 このオプションをトグルします。

別なコマンドM-x edebug-top-level-formは、 edebug-all-defsedebug-all-formsの値にかかわらず 全トップレベルの形式の膳立てをします。

Edebugがセッションではじめてのコードの膳立てをしようとするとき、 フックedebug-setup-hookを作動させてから これをnilにします。 使用中のパッケージにまつわるEdebug仕様指定を、 Edebugを使っているときだけロードするのに、 これを使えます。

Edebugがアクティブな間、 コマンドI (edebug-instrument-callee)は、 もしされていなければ ポイントの後のリスト形式に呼ばれているマクロや関数定義の膳立てをします。 これはEdebugがその関数のソースの場所がどこかわかっているときだけ可能です。 Edebugをロードすると、 eval-regionは評価する全定義の位置を記録するようになります (膳立てをしないときでも)。 関数の膳立てをしてからステップするiコマンド (see section ジャンプ)を参照してください。

Edebugは、 標準の特殊形式、 式を引数にもつ対話的形式、 匿名ラムダ式、 ほかの定義形式について知っています。 ユーザが定義したマクロが、 マクロ呼出しの引数をどう処理するかは Edebugにはわからないので、 あなたがEdebugにそれを教えなければなりません。 詳細はSee section マクロ呼出しの膳立て

膳立てを定義から除くには、単に膳立てをしないよう定義を再評価します。 膳立てをしないで形式を評価する二つの方法があります。 loadでファイルから評価する方法と ミニバッファからeval-expression (M-:)で評価する方法です。

Edebugが膳立てをしている間に構文エラーを検出したときは、 誤ったコードにポイントを置き、invalid-read-syntax エラーを通知します。

Edebug内で有効なほかの評価関数については、See section 評価


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.3 Edebug実行モード

Edebugにはあなたがデバッグしているプログラムを作動させているときの実行モー ドがいくつかあります。 これらの選択肢をEdebug実行モード(Edebug execution mode)といいます。 主モードや副モードと勘違いしないでください。現在のEdebug実行モードは、 Edebugが(訳注:実行を)停止させるまでにどれだけ実行を継続させるか、 そして、停止させる前に評価の進行状況をどの程度Edebugに表示させるかを、 決定します。

通常は、どのモードでプログラムを継続させるかというコマンドを押下するこ とで、Edebug実行モードを指定します。これらのコマンドの一覧を示します。S 以外は少なくとも少しの間プログラムの実行を再開します。

S

停止(stop):これ以上プログラムを実行しない。 Edebugのコマンドを待つ(edebug-stop)。

SPC

ステップ(step):次のストップ・ポイントにきたら止める (edebug-step-mode)。

n

次(next):式の後にある次のストップ・ポイントで止める(edebug-next-mode)。 いろいろなEdebugのコマンドedebug-forward-sexpを参照。

t

トレース(trace):各Edebugストップ・ポイントで1秒休む (edebug-trace-mode)。

T

高速トレース(rapid trace):各ストップ・ポイントで表示を更新するが、 休みはしない (edebug-Trace-fast-mode)。

g

進める(go):次のブレークポイントまで作動させる (edebug-go-mode)。See section ブレークポイント

c

続行(continue):各ブレークポイントで1秒休み続行する (edebug-continue-mode)。

C

高速続行(rapid continue):各ブレークポイントへポイントを移動するが、 休まない(edebug-Continue-fast-mode)。

G

ノンストップで進める(go non-stop):ブレークポイントを無視する (edebug-Go-nonstop-mode)。 引き続きSや任意の編集コマンドを押下すると、 プログラムを止めることができます。

一般に上の表の上の方にある実行モードは、 表の下にあるモードよりプログラムをゆっくり動かしたり、 すぐに止めたりします。

実行中やトレース中にEdebugコマンドを押下して実行に割り込むことができます。 次のストップ・ポイントでEdebugはプログラムを止め、 あなたの押下したコマンドを実行します。 たとえば、実行中のtは、 次のストップ・ポイントからtraceモードに切り替えます。 実行を止め何もさせないようにするにはSを使います。

関数がたまたま入力を読み込むものであったとき、 実行を割り込むつもりで押下した文字は、 関数によって代わりに読み込まれます。 プログラムが入力を要求するときについて注意を払っていれば、 そのような予期せぬ結果を避けることができます。

この節のコマンドを含むキーボード・マクロは、うまく働きません。 プログラムに戻ろうとしてEdebugを抜けてもキーボード・マクロの追跡に失敗します。 これを直すのは大変です。 また、Edebugの外で定義したり実行したりするキーボード・マクロは、 Edebugのなかのコマンドには関係ありません。 通常これは長所です。 ですがedebug-continue-kbd-macroオプションを 参照してください(see section Edebugのオプション)。

新しいEdebugレベルにはいったときは最初の実行は、 変数edebug-initial-modeの値となります。 デフォルトではstepモードを指定します。 たとえば、膳立てをされた関数が一つのコマンドから複数回呼ばれた場合、 同じEdebugレベルに複数回はいることもあることに注意してください。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.4 ジャンプ

この節で述べられているコマンドは、 指定した場所に到達するまで実行します。 i以外のすべては、 停止する場所を確立するために一時的なブレークポイントを作り、 そしてgoモードにはいります。 想定したストップ・ポイントの前のブレークポイントも実行を止めます。 ブレークポイントの詳細についてはSee section ブレークポイント

これらのコマンドは非局所脱出のときは期待どおりには働きません。 なぜなら、 非局所脱出はプログラムを止めようと期待した一時的なブレークポイントを、 迂回するからです。

h

ポイントの近くにあるストップ・ポイントまで進める(edebug-goto-here)。

f

前方に式一つ分、すすめる (edebug-forward-sexp)。

o

含んでいる式が終わるまでプログラムを作動させる。

i

ポイントの後の形式で呼ばれる関数やマクロをステップする。

hコマンドは一時的なブレークポイントを使って、 ポイントの現在の位置の近くにあるストップ・ポイントまで続行します。 ブレークポイントの詳細についてはブレークポイントを見てください。

fコマンドは、 プログラムの順方向へ式一つ分だけ実行します。 より正確にいえば、 C-M-fで到達する場所に一時的なブレークポイントを置き、 ブレークポイントで停止するようにgoモードで実行します。

前置引数nをつけると 一時的なブレークポイントはS式n個分向こうに置かれます。 もし含んでいるリストが、 n個の要素の前で終わっている場合、 止まる場所は含んでいる式の後になります。

C-M-fで到達する位置が プログラムが本当に実行をする場所であることを注意してください。 たとえば、condの中では、 これが正しくないこともあります。

fコマンドでは柔軟性のため、ストップ・ポイントからではなくポイントから 始めたforward-sexpを実行します。現在のストップ・ポイントから、 式一つ分を実行したいときは、まずwを押下しポイントを動かしてから、f を押下します。

oコマンドは、 式から「抜け出るまで」続行します。 これはポイントを含むS式の終わりに一時的なブレークポイントを置きます。 含んでいるS式が関数定義自身であるときは、 oは定義中の最後のS式の前まで続行します。 今もしそこにいるなら関数から抜けて止まります。 いいかえると、 最後のS式の後にいなければ、 このコマンドは現在実行中の関数を抜けません。

iコマンドはポイントの後のリスト形式で呼ばれる関数やマクロをステップし、 最初のストップ・ポイントで停止させます。 形式は評価しようとしているものでなくともかまわないことに注意してください。 しかし、形式が評価しようとしている関数呼出しであるなら、 まだ引数の評価が始まらないうちにこのコマンドを使うようにしてください。 評価の始まった後では遅すぎます。

iコマンドはステップしようとしている関数あるいはマクロの膳立てを (してなければ)します。 これは便利ですが、 陽に膳立てをやめるまではずっと膳立てをされたままになっている、 ということに、 気をつけてください。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.5 いろいろなEdebugのコマンド

Edebugのそのほかのいろいろなコマンドについて解説します。

?

Edebugのヘルプ・メッセージを表示します (edebug-help)。

C-]

一つ前のレベルのコマンド・レベルに戻します (abort-recursive-edit)。

q

トップレベルのエディタ・コマンド・ループに戻ります(top-level)。 これはEdebugの全レベルも含めすべての再帰編集レベルを抜けます。 しかしながら、 膳立てをしたコードでunwind-protectcondition-case形式で 保護されたもののせいで、 デバッグに戻されることがあります。

Q

qに似ていますが、 保護されたコードがあっても止めません (top-level-nonstop)。

r

わかっている一番最後の式の結果をエコー領域に再表示します (edebug-previous-result)。

d

Edebug自身の関数のそれを明確さのためにのぞいて、 バックトレースを表示します (edebug-backtrace)。

標準のデバッガのときとは違って、 Edebugのバックトレース・バッファの中では、 デバッガのコマンドは使えません。

実行を継続すると、バックトレース・バッファは自動的にkillされます。

Edebugの再帰編集からEdebugを再帰的にアクティブにするコマンドを 起動してもかまいません。 Edebugがアクティブなとき、 qでトップレベルまでとりやめたり、 C-]で再帰編集レベルを一つ中断したりできます。 dで評価を保留しているすべてのバックトレースを表示できます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.6 ブレークポイント

Edebugのstepモードでは次のストップポイントに到達すると実行を止めます。 いったん動き始めたらEdebugが実行を止める方法は三つあります。 それはブレークポイント、 グローバル・ブレーク条件、 ソースのブレークポイントです。

Edebugを使っている間は、 テスト中のプログラムにブレークポイント(breakpoint)、 実行を止めるべき点を、 指定できます。Edebug利用入門で定義された任意のストップ・ポイントで ブレークポイントを設定できます。 ブレークポイントを設定したり解除したりする際、 影響をうけるストップ・ポイントは最初のものかあるいは ソース・コード・バッファのポイントの後にあるものです。 ブレークポイントにまつわるEdebugコマンドは以下のものがあります。

b

ストップ・ポイント、あるいはポイントの後に、 ブレークポイントを置く(edebug-set-breakpoint)。 前置引数を与えるとブレークポイントは一時的になります (最初にそこでプログラムを止めたときに消えます)。

u

ストップ・ポイントあるいはポイントの後にあるブレークポイント(もしあれば)を 解除します(edebug-unset-breakpoint)。

x condition RET

conditionが非nilの値に評価したときにかぎって止める、 条件つきのブレークポイントを設定します (edebug-set-condition-breakpoint)。 前置引数を与えると、 ブレークポイントは一時的になります。

B

定義中の次のブレークポイントにポイントを動かします (edebug-next-breakpoint)。

Edebugにいる間ブレークポイントをbで設定したり、 uで解除したりすることができます。 まずポイントをあなたの好きなEdebugのストップ・ポイントに動かし、 buを押下して設定あるいは解除します。 ブレークポイントのないところで解除しても何の効果もありません。

定義の膳立てをしたり再評価をしたりすると、 その定義内のすべてのブレークポイントはなくなります。

条件つきブレークポイント(conditional breakpoint)は、 プログラムがそこにくるたびに条件を検査します。 条件の評価の結果起きたエラーはすべて無視し、 結果はnilとみなします。 条件つきブレークポイントを設定するには、 xを使ってミニバッファから条件式を指定します。 以前に確立した条件つきブレークポイントのあるストップ・ポイントに 条件つきブレークポイントを確立すると、 編集ができるようにミニバッファに前の条件式を置きます。

条件つきや無条件のブレークポイントを一時的(temporary)にするには、 設定するコマンドに前置引数を与えます。 一時的なブレークポイントがプログラムを止めたとき、 自動的に解除されます。

EdebugモードがGo-nonstopのとき以外は、 Edebugはブレークポイントで休んだり止まったりします。 Go-nonstopモードのときはすべて無視します。

ブレークポイントの場所を見つけるには、 Bコマンドを使います。 これはポイントを、 同じ関数でポイントの後ろにある次のブレークポイントか、 もしそれがなければ最初のブレークポイントに動かします。 このコマンドは実行の継続はしません。 バッファのポイントを動かすだけです。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.6.1 グローバル・ブレーク条件

グローバル・ブレーク条件(global break condition)は、 どこを実行していても、 指定した条件が成立したときに実行を止めます。 Edebugは各ストップ・ポイントでグローバル・ブレーク条件を評価します。 もしこれが非nilの値に評価したら、 ブレークポイントがあったかのように 実行モードにしたがって止まったり休んだりします。 評価でエラーが起きても実行を止めません。

Xコマンド(edebug-set-global-break-condition)を使って、 edebug-global-break-conditionに格納した条件式を、 設定したり編集したりできます。

グローバル・ブレーク条件は、 あるイベントがコードのどこで起こったかをさがすための最も単純な方法ですが、 これによりコードの実行は非常に遅くなります。 ですから使わないときは条件をnilにするべきです。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.6.2 ソースのブレークポイント

定義中の全ブレークポイントは、 あなたが再び膳立てをするたびに、 なくなります。 ブレークポイントがなくならないようにするには、 単にソース・コードから関数edebugを呼ぶだけの ソースのブレークポイント(source breakpoint)を書くことができます。 もちろん条件をつけることもできます。 たとえば、 fac関数では、 以下に示すように1行目に引数が0になったときに止まるようにしています。

 
(defun fac (n)
  (if (= n 0) (edebug))
  (if (< 0 n)
      (* n (fac (1- n)))
    1))

facの定義が膳立てをされ関数が呼び出されると、 edebugの呼出しはブレークポイントのように作用します。 実行モードによってEdebugはそこで止まったり休んだりします。

膳立てをされた関数を実行していないときにedebugを呼び出すと、 その関数はdebugを呼び出します。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.7 エラーのトラップ

通常Emacsはcondition-caseでハンドルされないエラーが通知されると、 エラー・メッセージを表示します。 通常Edebugがアクティブな間はハンドルされていないすべてのエラーに反応します。 あなたはオプションedebug-on-erroredebug-on-quitで、 これをカスタマイズすることができます。Edebugのオプションを参照してください。

Edebugがエラーに反応するとき、 エラーの前にあった最後のストップ・ポイントを表示します。 この場所は実際にエラーが起きたのとは別の、 膳立てをされていない関数を呼び出している箇所であることがあります。 束縛されていない変数のエラーの場合、 前のブレークポイントは変数を参照しているところからは、 とても離れているかもしれません。 この場合は全バックトレース(see section いろいろなEdebugのコマンド)を表示したくなるでしょう。

Edebugがアクティブなとき debug-on-errordebug-on-quitを変更しても、 Edebugがアクティブでなくなると変更は失われます。 さらにEdebugの再帰編集の間、 これらの変数は、 Edebugの外の値に束縛します。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.8 Edebugでのながめ

以下のEdebugのコマンドは、 Edebugにはいる前に取得したバッファとウィンドウの状態の外観を見せてくれます。 外側のウィンドウ構成は、 Edebugの外側で有効になる ウィンドウと(訳注:その)内容の集まりです。

v

一時的に外側のウィンドウ構成をながめる(edebug-view-outside)。

p

一時的にポイントを外側の位置に移し、 カレント・バッファの外側を表示します(edebug-bounce-point)。 前置引数nをつけると n秒間休止します。

w

ソース・コード・バッファのポイントを、 現在のストップ・ポイントに動かします(edebug-where)。 さらに、 同じバッファを表示している別なウィンドウからこのコマンドを使った場合、 それ以降では、 現在の定義の表示にそのウィンドウを使います。

W

Edebugが外側のウィンドウ構成を保存したり復帰したりするかどうかをトグルします (edebug-toggle-save-windows)。

前置引数を与えると Wは選択されたウィンドウの保存復帰についてだけトグルします。 ソース・コード・バッファを表示していないウィンドウを指定するには、 C-x X Wをグローバル・キーマップから使わなければなりません。

vで外側のウィンドウ構成をながめたり、 また、通常には表示されていない場合にも pでただカレント・バッファのポイントへ跳ね返したりすることができます。 ポイントを動かした後は、 ソース・コード・バッファからwでストップ・ポイントへ戻りたくなるでしょう。

Wで保存をやめるときはいつでも、 Edebugは保存した外側のウィンドウ構成を忘れます。 したがって、 保存を再開した場合でも、 次に(プログラムを継続して)Edebugを抜けたときに、 現在のウィンドウ構成は変わりません。 しかしながら、 ウィンドウを十分オープンしていないときは、 `*edebug*'`*edebug-trace*'の自動再表示が、 あなたの見たいバッファとかちあうことがあります。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.9 評価

Edebugの中で、 「あたかも」Edebugが走っていないかのように式を評価できます。 Edebugは式の評価と印字にたいして透過的になるようにしています。 副作用を起こす式の評価は Edebugが陽に保存復帰したものをのぞいて 期待どおりに働きます。 この過程についての詳細は、See section 外側の文脈

e exp RET

expをEdebugの外側の文脈で評価します(edebug-eval-expression)。 つまりEdebugは評価への影響を最少化しようとします。

M-: exp RET

expをEdebug自身の文脈で評価します。

C-x C-e

ポイントの前の式をEdebugの外側の文脈で評価します (edebug-eval-last-sexp)。

Edebugは、 `cl.el' (バージョン 2.03 かそれ以降) の lexical-let macrolet symbol-macrolet 構文要素で生成された、 辞書的に束縛されたシンボルへの参照を含む、 式の評価をサポートします。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.10 評価リスト・バッファ

`*edebug*'という評価リスト・バッファ(evaluation list buffer)を使って 対話的に式を評価することができます。 また、Edebugが表示を更新するたびに自動的に評価される 式の評価リスト(evaluation list)も使えます。

E

評価リスト・バッファ`*edebug*'に 切り替えます(edebug-visit-eval-list)。

`*edebug*'バッファでは Lisp Interactionモード (see (emacs)Lisp Interaction section `Lisp Interaction' in The GNU Emacs Manual) のコマンドのほかに以下の特殊なコマンドが使えます。

LFD

外側の文脈でポイントの前の式を評価し、 バッファに値を挿入します (edebug-eval-print-last-sexp)。

C-x C-e

ポイントの前の式をEdebugの外側の文脈で評価します (edebug-eval-last-sexp)。

C-c C-u

バッファの内容から新しい評価リストを作ります (edebug-update-eval-list)。

C-c C-d

ポイントがある評価リスト群を消去します(edebug-delete-eval-item)。

C-c C-w

現在のストップ・ポイントのソース・コード・バッファに 戻ります(edebug-where)。

LFDC-x C-eで、 `*scratch*'でのように、 評価リスト・ウィンドウの式を評価することができますが、 これらはEdebugの外側の文脈で評価されます。

あなたが対話的に入力した式(とその結果)は実行を継続したときに失われます。 しかし、 実行が止まるたびに評価をする式を含む評価リスト(evaluation list)を 設定することができます。

こうするには評価リスト・バッファの中に 単数または複数の評価リスト群(evaluation list group)を書きます。 評価リスト群には単数または複数のLisp式があります。 各群はコメント行で分割されます。

コマンドC-c C-u (edebug-update-eval-list)は、 バッファをスキャンして各群の1番目の式を用い評価リストを再構築します (なぜこうするかというと群の2番目の式は前に計算され表示された値だからです)。

無限ループになるので、 膳立てをしたコードを実行する式をつけ加えないように注意してください。

Edebugへの各呼出しは、 後ろに現在の値をつけた各式をバッファに挿入して、 評価リストの再表示を行ないます。 コメント行も挿入するので各式はそれぞれに群をなします。 したがってバッファ・テキストを変えずにC-c C-uをまた押下した場合、 評価リストは実質的には変化しません。

評価リストの評価でエラーが起きたとき、 それが結果であるかのように、 エラー・メッセージが文字列として表示されます。 したがって現在無効な変数を使用する式も、 デバッグに割り込むことはありません。

以下は、 式をいくつか追加した後の評価リスト・ウィンドウの例です。

 
(current-buffer)
#<buffer *scratch*>
;---------------------------------------------------------------
(selected-window)
#<window 16 on *scratch*>
;---------------------------------------------------------------
(point)
196
;---------------------------------------------------------------
bad-var
"Symbol's value as variable is void: bad-var"
;---------------------------------------------------------------
(recursion-depth)
0
;---------------------------------------------------------------
this-command
eval-last-sexp
;---------------------------------------------------------------

群を消去するにはポイントを中にもってきてC-c C-dを押下するか、 単に群のテキストを消去してからC-c C-uで評価リストを更新するかします。 新しい式を評価リストに追加するには、 適切な場所に式と新しいコメント行を挿入します (コメント行にダッシュを挿入する必要はありません--内容は関係ありません)。 そしてC-c C-uを押下します。

`*edebug*'を選択した後、 C-c C-wでソース・コード・バッファに戻ることができます。 `*edebug*'バッファは実行を継続したときに抹消され、 次に必要になったとき再生成されます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.11 Edebugでの印字

もしプログラムの中の式が環状リスト構造を含む値を生成したら、 Edebugがそれを印字しようとしたときにエラーになることがありえます。

環状構造を処理する一つの方法は、 印字の切り捨てをするprint-lengthprint-levelを設定することです。 これはEdebugの方でやってくれます。 もしnilならprint-lengthprint-levelを50に束縛します (実際はedebug-print-lengthedebug-print-levelの値にします)。See section 出力に影響を与える変数

環状構造や要素を共有している構造をよりはっきりと印字するのに、 `cust-print'パッケージを利用してもかまいません。

`cust-print'をロードしてEdebug専用にカスタム印字をアクティブにするには、 単にコマンドM-x edebug-install-custom-printを使います。 標準の印字関数を復帰するには、 M-x edebug-uninstall-custom-printを使います。

以下に環状構造を生成するコードの例をあげます。

 
(setq a '(x y))
(setcar a a))

カスタム印字はこれを`Result: #1=(#1# y)'のように印字します。 `#1='という表記は、 それ以降に続く構造に`1'というラベルをつけて、 `#1#'という表記は以前につけたラベルの構造を参照します。 この表記はリストやベクタの共有要素を表わすのに使います。

ほかのプログラムもカスタム印字を利用可能です。 詳しくは`cust-print.el'を見てください。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.12 トレース・バッファ

Edebugは、 実行トレースを`*edebug-trace*'という名前のバッファに格納して、 記録しておくことができます。 これは関数の呼出しと戻りのログで、 関数名、引数、値を示すものです。 トレース記録を有効にするには、 edebug-traceを非nilの値に設定します。

トレース・バッファを作ることは、 trace実行モードを使うこととは違います(see section Edebug実行モード)。

トレース記録を有効にしてあるとき、 各関数の呼出しと終了はトレース・バッファに行を追加します。 関数の呼出し記録は`::::{'に関数名と引数値が ついたような形になっています。 関数の終了記録は`::::}'に関数名と関数の結果が ついたような形になっています。

項目の中の`:'の数は再帰の深さを示します。 トレース・バッファで、対応する関数呼出しの最初や最後を探すのに、 波括弧を使うことができます。

関数edebug-print-trace-beforeと、 edebug-print-trace-afterを再定義して、 関数の呼出しと終了のトレース記録をカスタマイズすることができます。

Macro: edebug-tracing string body…

このマクロはbody形式の実行の前後で追加のトレース情報を要求します。 引数stringはトレース・バッファに置くテキストを指定します。 全引数を評価します。 edebug-tracingbodyの最後の形式の値を返します。

Function: edebug-trace format-string &rest format-args

この関数は、トレース・バッファにテキストを挿入します。 テキストは(apply 'format format-string format-args)で 算出します。 項目をわけるため改行を追加します。

edebug-tracingedebug-traceは、 Edebugがアクティブでないときでもトレース・バッファに行を追加します。

トレース・バッファへのテキストの追加では、 最後に挿入した行が見えるようにウィンドウのスクロールもします。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.13 網羅率検査

Edebugにはおおざっぱな網羅率検査と実行頻度の表示ができます。 膳立てをされた式の評価の前後では、 実行モードがGo-nonstopのときでも、 みな頻度計数を累積してゆきます。 網羅率検査はかなり高くつくので、 edebug-test-coverageが非nilのときにだけ行ないます。 コマンドM-x edebug-display-freq-countは頻度データと網羅率データを (記録していれば)表示します。

Command: edebug-display-freq-count

このコマンドは頻度計数データを、現在の定義の中の各行に表示します。

頻度計数は各行の後ろにコメントとして現われます。 これはundoコマンドで取り消すことができます。 計数は式の前の(、 式の後の)、 シンボルの最後の文字の下に現われます。 同じ行の中では前の計数と同じ値の表示はしません。

文字`='に式の計数がついたものは、 式が評価されるたびにいつも同じ値を返していることを示します。 これはEdebugが記録する唯一の網羅率情報です。

定義の頻度計数と網羅率情報を消すには、再び膳立てをします。

たとえば、ソースにブレークポイントをつけて(fac 5)を評価し、 edebug-test-coveragetにした後で、 ブレークポイントに到達すると、 計数データは次のようになります。

 
(defun fac (n)
  (if (= n 0) (edebug))
;#6           1      0 =5 
  (if (< 0 n)
;#5         = 
      (* n (fac (1- n)))
;#    5               0  
    1))
;#   0 

コメント行はfacが6回呼ばれたことを示しています。 最初のifステートメントは同じ結果を5回返しています。 2番目のifの条件についても同じことがいえます。 facの再帰呼びだしはまったく返っていません。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.14 外側の文脈

Edebugはデバッグ中のプログラムにたいして透過的になるように努めていますが、 そうすることに完全には成功してません。 Edebugはeや評価リスト・バッファで式を評価するとき、 一時的に外側の文脈を復帰して、 透過的になるように努めています。 この節ではEdebugが復帰する文脈と、 Edebugが完全に透過的とはなりきれていないのはどういうところなのかを、 正確に説明します。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.14.1 いつ止めるかのチェック

トレース情報を作ったりプログラムを止めたりするかどうかを決める前であっても、 Edebugにはいるときは常に、 あるデータを保存、復帰する必要があります。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.14.2 Edebugの表示更新

Edebugが何かを表示する必要のあるとき(たとえば、traceモード中)、 現在のウィンドウ構成(see section ウィンドウ構成)をEdebugの「外側」から保存します。 (プログラムを継続して)Edebugから抜けたとき、 前のウィンドウ構成を復帰します。

Emacsは休んでいるときだけ再表示を行ないます。 通常、実行を継続したときに、 ブレークポイントにおいてか、または、 休まずにステップをした後か、または、 途中で入力を読み込もうとして、 プログラムはEdebugに戻ってきます。 このような場合、Emacsは「外側」の構成を再表示する機会を失います。 割り込みがなければ、 最後にEdebugがアクティブなときと同じウィンドウ構成が見えます。

何かを表示するためEdebugにはいると以下のデータの保存と復帰を生じますが、 このうちいくつかはあえて、 エラーやとりやめのシグナルが起きても復帰しません。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.15 Edebugの再帰編集

Edebugにはいってユーザからコマンドを実際に読み込んだとき、 以下のデータも保存を(そして後で復帰を)します。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.16 マクロ呼出しの膳立て

EdebugがLispマクロを呼び出す式の膳立てをするとき、 処理を正しく行なうために付加的な情報が必要です。 これは、マクロ呼出しのどの部分式が評価すべき形式なのかを、 決めることができないためです (評価はマクロ本体の中に明示されているときや、 結果の式が評価されるときあるいはそれ以降に起こることがあります)。 Edebugがこれを正しく処理できるよう、 各マクロの呼出し形式を指定しなければなりません。 それには、 def-edebug-specを使い、 与えたマクロへの呼出し形式を定義する必要があります。

Macro: def-edebug-spec macro specification

マクロmacroの呼出しのどの式が評価すべき形式なのかを指定します。 単純なマクロにたいして、 specificationはいつもマクロ引数の仮引数とよく似ていますが、 指定方法はもっとマクロ引数よりもさらに一般的です。

macro引数はマクロ名だけでなく実際には任意のシンボルでかまいません。

以下の例では、 このEmacs Lispリファレンス・マニュアル中に登場するマクロforの仕様を、 2とおりの等価な仕様指定で定義しています。

 
(def-edebug-spec for
  (symbolp "from" form "to" form "do" &rest form))

(def-edebug-spec for
  (symbolp ['from form] ['to form] ['do body]))

次の表にspecificationのとりうる値と、 それによって引数の処理がどう変わるかをまとめておきます。

t

全引数について評価の膳立てをします。

0

膳立てをする引数はありません。

シンボル

シンボルは、代用するEdebug仕様指定をもたなければなりません。 この間接的な仕様指定は別種の仕様指定が見つかるまで続きます。 別のマクロの仕様指定を継承することができます。

リスト

リストの要素は呼出し形式の引数の型を指定します。 仕様指定リストの要素になりえるものは次の節で解説します。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.16.1 仕様指定リスト

マクロ呼出しの、ある引数は評価され、ある引数は評価されないという場合には、 仕様指定リスト(specification list)がEdebugへの指定として必要です。 仕様指定リスト中のある要素群は、単数あるいは複数の引数と一致し、 別な要素群はそれ以降の要素の処理を修飾します。 後者の方は仕様指定キーワード(specification keyword)といいます。 これは(&optionalのように)`&'で始まるシンボルです。

仕様指定リストは、 それ自身がリストであるような引数に対応する部分リストや、 仲間わけに使うベクタを含んでいることがあります。 このように部分リストやグループは仕様指定リストを レベルの階層構造に分割します。 仕様指定キーワードは、 それを含むグループや部分リストの残りの部分だけに適用します。

仕様指定リストが選択肢や繰り返しになるとき、 実際のマクロ呼出しへの照合にはバックトラックが必要です。 詳しくは、See section バックトラック

Edebug仕様指定は正規表現の照合能力にくわえて、 文脈自由文法としての構文要素をもっています。 すなわち、釣り合いのとれた括弧をもつ部分リスト、形式の再帰的処理、 間接仕様指定を経由した再帰といったものです。

次の表はとりうる仕様指定の要素とその意味です。

sexp

評価されない単一のLispオブジェクト。

form

評価され膳立てをされる単一の式。

place

Common Lispのsetf構文要素のように、 値を格納するところ。

body

&rest formを簡単にしたもの。以下の&restを見てください。

function-form

関数形式。すなわちquoteされた関数シンボル、quoteされたラムダ式、あるいは (関数シンボルやラムダ式へ評価する)形式。 これはラムダ式を渡す引数が、 functionではなくquoteでquoteされることもある場合に、 便利です。 というのはどちらの場合でもラムダ式本体の膳立てをするからです。

lambda-expr

quoteしないラムダ式。

&optional

仕様指定リストでそれ以降の引数が省略可能であることをあらわします。 一つでも一致しなくなるやいなや、Edebugはこのレベルで照合を止めます。

省略不能な要素に続いていくつかの省略可能な要素がある場合、 [&optional specs…]を使います。 いくつかの要素がすべて一致するかまったく一致しないかということを指定するには、 &optional [specs…]を使います。 以下のdefunの例を見てください。

&rest

仕様指定リスト中のそれ以降の要素は0個以上繰り返します。 最後の繰り返しについてはすべてと照合する必要はありません。

いくつかの要素だけを繰り返すには、 [&rest specs…]を使います。 すべての繰り返しで全部が一致する必要のあるときは、 &rest [specs…]を使います。

&or

仕様指定リスト中の後続する全要素が選択肢です。 選択肢の一つが照合する必要があります。 さもなくば&or仕様指定は失敗します。

&orに続く各リスト要素は、単一の選択肢です。 二つ以上のリスト要素を単一の選択肢とするには、 […]でくくります。

&not

後続の各要素は&orを使ったときの選択肢のように照合されますが、 一致するものがあると指定は失敗します。 一致するものがないとき、 照合するものは空ですが、 このときに&not仕様指定は成功します。

&define

仕様指定が定義を行なう形式であることを示します。 定義を行なう形式自身は膳立てをされません (つまりEdebugは定義を行なう形式の前後では止まりません)が、 内側の典型的な形式は膳立てをされます。 &defineキーワードはリスト仕様指定の最初の要素でなければなりません。

nil

これは現在の引数リスト・レベルで 照合すべき引数がないときに成功します。 後述する部分リスト仕様指定と逆引用符の例を見てください。

gate

引数とは対応しませんが、 このレベルでの残った仕様指定の照合でgateをとおったバックトラックを禁止します。 これは主に仕様指定の構文エラー・メッセージの生成に使用されます。 詳しくはバックトラックを見てください。 また、後述のletの例も見てください。

other-symbol

仕様指定リスト中のほかのすべてのシンボルは、 述語または間接的な仕様指定のはずです。

シンボルにEdebug仕様指定があるなら、 この間接的仕様指定(indirect specification)は シンボルの代わりに使われる仕様指定リストであるか、 あるいは引数を処理するために呼び出される関数です。 仕様指定はマクロのようにdef-edebug-specで定義されます。 後述のdefunの例を見てください。

それ以外の場合、シンボルは述語でなければなりません。 述語は引数をともなって呼び出され、 この述語がnilを返すと仕様指定は失敗します。 いずれの場合も、引数の膳立てはされません。

適切な述語には、 symbolpintegerpstringpvectorpatomがあります。

[elements…]

要素のベクタは、 複数の要素を単一のグループ仕様指定(group specification)にまとめます。 この意味はベクタとは関係ありません。

"string"

引数はstringという名前のシンボルでなければなりません。 この仕様指定は、stringという名前のシンボルsymbolを quote した 'symbolというものと等価ですが、 文字列形式の方がお薦めです。

(vector elements…)

引数は、 その要素が仕様指定中のelementsと一致するベクタでなければなりません。 後述の逆引用符の例を見てください。

(elements…)

それ以外のリストは部分リスト仕様指定(sublist specification)です。 この引数はリストで、 その要素が仕様指定elementsと一致していなければなりません。

部分リスト仕様指定がドットつきリストであって、 対応するリスト引数がドットつきリストであってもかまいません。 また、ドットつきリスト仕様指定の最後のCDRが、別な部分リスト仕様指定 (仲間わけや間接仕様指定、すなわち、(spec . [(more specs…)])) で、その要素がドットのないリスト引数と一致するもの であったりしても、かまいません。 これは、後述の逆引用符の例にあるような再帰的仕様指定で、役に立ちます。 このような再帰を終了させるnil仕様指定については、前述しました。

(specs . nil)のように書かれる部分リスト仕様指定は、 (specs)と等価であること、 (specs . (sublist-elements…))は、 (specs sublist-elements…)と等価であることに注意してください。

以下は&defineの後に現われるだけの追加の仕様指定の一覧です。 後述するdefunの例を見てください。

name

引数のシンボルは定義形式中の名前です。

定義形式には名前のフィールドがなくともかまいません。 複数の名前フィールドがあることもあります。

:name

この構文要素は実際の引数とは対応しません。 :nameに続く要素はシンボルでなければなりません。 これは定義にたいして、付加的な名前の成分に使われます。 一意で静的な成分を定義中の名前に追加することができます。 1回以上使うこともできます。

arg

引数のシンボルは定義形式の引数の名前です。 しかし、ラムダ・リスト・キーワード(`&'で始まるシンボル) は許されていません。

lambda-list

これはラムダ・リスト、すなわちラムダ式の引数リストと一致します。

def-body

引数は定義のコードの本体です。 これは前述のbodyに似ていますが、 定義の本体は、 定義にまつわる情報を参照する別なEdebug呼出しで、 膳立てをされていなければなりません。 def-bodyは、定義内の形式の最高位のリストに使用します。

def-form

引数は定義内で最高位の単一の形式です。 def-bodyに似ていますが、 形式のリストではなく、単一の形式と対応します。 特例としてdef-formでは、 形式を実行するとき追跡情報を出力しません。 後述のinteractiveの例を見てください。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.16.2 バックトラック

仕様指定がどこかで照合に失敗しても、 それだけでは構文エラーを通知されるとはかぎりません。 こういう場合、 選択肢がなくなるまでバックトラック(backtracking)を行ないます。 結局のところ、 引数リストの各要素は 仕様指定中のいずれかの要素と一致しなければなりませんし、 仕様指定中で必須と指定した要素にはいずれかの引数と一致しなければなりません。

後述するある条件の成立した場合、 バックトラックは部分リストやグループの余りの部分にたいして禁止されます。 バックトラックは新しい選択肢が&optional&rest&orで確立されたときに、 再び有効になります。 部分リスト、グループ仕様指定、間接仕様指定を処理する前にも有効になります。

Edebugがもっと細かな構文エラー・メッセージを出せるように、 バックトラックを禁止し別な選択肢をえらぶようにしたいかもしれません。 通常、一致する選択肢がないとき、 Edebugは一致したものがなかったということを知らせてきますが、 一つしかない選択肢の場合には、 どうして一致しなかったのかまで知らせることができます。

まず第一に形式の仕様指定のどれか (つまりformbodydef-formdef-body)に照合しているときは、バックトラックが禁止されます。 これらの仕様指定はどんな形式にも一致するため、 どんなエラーも高い水準でではなく形式それ自身の中で起こります。

そして第二にquoteされたシンボルや文字列仕様指定とうまく一致した後にも、 認識された構文要素を示しているということで、 バックトラックは禁止されます。 もし同じシンボルで始まる選択肢の構文要素の集まりがあるなら、 ["foo" &or [first case] [second case] ...] のようにシンボルを選択肢からくくり出すことにより、 この制約をうまく回避することができます。

第三にgate仕様指定を使って陽にバックトラックを禁止することもできます。 これ以上高い選択肢がないとわかっているときには便利です。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.16.3 仕様指定の例

以下の例でEdebug仕様指定について学習すれば、 理解が深まることでしょう。

let特殊形式には束縛の列と本体があります。 各束縛はシンボルであるか、 あるいはシンボルと省略可能な値をともなった部分リストです。 以下の仕様指定でいったん部分リストが見つかると、 部分リストの内側のgateがバックトラックを妨げます。

 
(def-edebug-spec let
  ((&rest
    &or symbolp (gate symbolp &optional form))
   body))

defundefmacro、 そして関連づけられた引数リストとinteractive仕様指定で Edebugが使用する仕様指定は、 以下のとおりです。 対話的な形式は、 実際に関数本体の外側で評価される引数式であるため、 特別扱いすることが必要です。

 
(def-edebug-spec defmacro defun) ; defun仕様指定への間接参照。
(def-edebug-spec defun 
  (&define name lambda-list 
           [&optional stringp]   ; もしあれば、説明文字列と一致する。
           [&optional ("interactive" interactive)]
           def-body))

(def-edebug-spec lambda-list
  (([&rest arg]
    [&optional ["&optional" arg &rest arg]]
    &optional ["&rest" arg]
    )))

(def-edebug-spec interactive
  (&optional &or stringp def-form))    ; 注意: def-form

以下の逆引用符の仕様指定では ドットつきリストや再帰を終結させるnilの使い方が、 説明されています。 また、ベクタの成分と照合させる方法も説明します (再帰が深くなりすぎてだめなので、 Edebugで実際に定義している仕様指定では、 ドットつきリストをサポートしていません)。

 
(def-edebug-spec ` (backquote-form))   ; 簡単のための別名。

(def-edebug-spec backquote-form
  (&or ([&or "," ",@"] &or ("quote" backquote-form) form)
       (backquote-form . [&or nil backquote-form])
       (vector &rest backquote-form)
       sexp))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.4.17 Edebugのオプション

Edebugの振舞いを変えるオプションは以下のとおりです。

User Option: edebug-setup-hook

Edebugを使う前に呼び出される関数群。 新しい値が設定されるたびにEdebugはこれらの諸関数を1回ずつ評価し、 その後edebug-setup-hooknilにします。 使っているパッケージにまつわるEdebug仕様指定を、 Edebugとともに使うときにだけロードするようなときに使います。See section Edebugのために膳立てをする

User Option: edebug-all-defs

もし非nilなら、 defundefmacroのような通常の定義形式の評価で、 Edebugへの膳立てをします。 これはeval-defuneval-regioneval-buffereval-current-bufferに適用されます。

コマンドM-x edebug-all-defsは、 このオプションのトグルを行ないます。See section Edebugのために膳立てをする

User Option: edebug-all-forms

もし非nilなら、 コマンドeval-defuneval-regioneval-buffereval-current-bufferは、 定義をしない場合でも、 全形式の膳立てを行ないます。 ロードとミニバッファでの評価には適用しません。

コマンドM-x edebug-all-formsは、 このオプションのトグルを行ないます。See section Edebugのために膳立てをする

User Option: edebug-save-windows

もし非nilならば、Edebugはウィンドウ構成の保存と復帰をします。 これには時間がかかりますから、 もしウィンドウ構成を無視するようなプログラムでは、 この変数をnilにするとよいでしょう。

値がリストのとき、 リスト中のウィンドウだけが保存復帰されます。

EdebugのWコマンドは、 この変数を対話的に変更します。See section Edebugの表示更新

User Option: edebug-save-displayed-buffer-points

これが非nilのときEdebugは、 表示中の全バッファのポイントの保存と復帰をします。

別なバッファのポイントを保存復帰することは、 選択されていないウィンドウに表示されているバッファの ポイントを変更するコードをデバッグするときに必要になります。 Edebugあるいはユーザがウィンドウを選択すると、 バッファのポイントはウィンドウのポイント値に移動します。

全バッファでポイントの保存と復帰をするのには、 各ウィンドウを2回選択する必要があるので、 高くつきます。 ですから必要なときだけ使うようにしてください。See section Edebugの表示更新

User Option: edebug-initial-mode

この変数が非nilのとき、 Edebugが最初にアクティブになったときの実行モードをとります。 とりうる値は、 stepnextgoGo-nonstoptraceTrace-fastcontinueContinue-fastのいずれかです。

デフォルト値はstepです。

See section Edebug実行モード

User Option: edebug-trace

nilのとき関数の呼出しと終了でトレースを表示します。 に1関数の呼出し終了ごとに1行ずつ、 再帰レベルに応じた字下げをして表示されます。

デフォルト値はnilです。

See section トレース・バッファedebug-tracingも参照してください。

User Option: edebug-test-coverage

もし非nilなら、 Edebugはデバッグ中のすべての式の網羅率検査をします。 各式の結果を前の結果と比較することによります。 二つの異なる値が見つかったとき網羅率は良好とみなされます。 したがってあなたのコードの網羅率を十分に検査するには、 すべての式を(訳注:少なくとも)1回以上は評価するような、 また、各式が異なる結果を生成するような、 条件下で実行するようにしてください。

頻度計数と定義の網羅率情報を表示するには M-x edebug-display-freq-countを使います。See section 網羅率検査

User Option: edebug-continue-kbd-macro

もし非nilなら、 Edebugの外側で実行しているキーボード・マクロの実行や、 定義を続行します。See section Edebug実行モード

User Option: edebug-print-length

もし非nilなら、 Edebugで結果を印字している間print-lengthをこの値に束縛します。 デフォルト値は50です。See section Edebugでの印字

User Option: edebug-print-level

もし非nilなら、 Edebugで結果を印字している間print-levelをこの値に束縛します。 デフォルト値は50です。

User Option: edebug-print-circle

もし非nilなら、 Edebugで結果を印字している間print-circleをこの値に束縛します。 デフォルト値はnilです。

User Option: edebug-on-error

debug-on-errorの値がnilのとき、 Edebugはdebug-on-errorをこの値に束縛します。See section エラーのトラップ

User Option: edebug-on-quit

debug-on-quitの値がnilのとき、 Edebugはdebug-on-quitをこの値に束縛します。See section エラーのトラップ

Edebugがアクティブのときに、 edebug-on-erroredebug-on-quitの値を変えても、 にEdebugが別なコマンドから起動されるまでは無効です。

User Option: edebug-global-break-condition

もし非nilなら各ストップ・ポイントで検査される式です。 結果が非nilならブレークします。 エラーは無視します。See section グローバル・ブレーク条件


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Yasutaka SHINDOH on September, 29 2006 using texi2html 1.76.