Emacs Lispは非ローカル脱出(nonlocal
exits)をサポートしており、これによりプログラムの制御はプログラムのあるポイントから別の離れたポイントに転送されます。非ローカル脱出を参照してください。したがってモジュールから呼び出されたLisp関数はsignal
やthrow
を呼び出して非ローカルにexitするかもしれず、そのような非ローカル脱出をモジュール関数は正しくハンドルしなければなりません。このようなハンドリングはCプログラムがリソースを自動的に解放せず、このような場合には別のクリーンアップを行うために必要になります。モジュールコードは自身でこれを行わなければなりません。そのための機能をモジュールAPIは提供しており、このサブセクションではそれを説明します。これらは一般的にはEmacs
25以降で利用可能です。これ以降のリリースで利用可能になったものについては、APIに含まれるようになった最初のEmacsのバージョンを付記します。
モジュール関数から呼び出されたLispコードがエラーをシグナルしたりthrowを行う際には、非ローカル脱出はtrapされて保留中のexitと関連するデータは環境内に格納されます。環境内で非ローカル脱出が保留中の際には、環境へのポインターで呼び出されたすべてのモジュールAPI関数は何も処理を行わずに即座にリターンします(関数non_local_exit_check
、non_local_exit_get
、non_local_exit_clear
はこのルールの例外)。モジュール関数が何も行わずにEmacsにリターンすれば、保留中の非ローカル脱出にたいしてEmacsがエラーをシグナルしたり、対応するcatch
へのthrowという対処を行うでしょう。
したがって特別なことな何も行わずに、何事もなかったかのようにコードの残りを実行するのが、モジュール関数での非ローカル脱出にけるもっともシンプルな“ハンドリング”です。しかしこれは2つのクラスの問題を引き起こすかもしれません:
したがってモジュール関数は以下に説明する関数を使用して、非ローカル脱出のコンディションのチェックとリカバリングを行うことを推奨します。
enum emacs_funcall_exit
non_local_exit_check (emacs_env *env)
¶この関数はenvに格納された非ローカル脱出のコンディションをリターンする。可能な値は:
enum emacs_funcall_exit
non_local_exit_get (emacs_env *env, emacs_value *symbol, emacs_value *data)
¶この関数はnon_local_exit_check
が行うようにenvに格納された非ローカル脱出の種別をリターンするが、もしあれば非ローカル脱出に関する完全な情報もリターンする。リターン値がemacs_funcall_exit_signal
なら関数は*symbol
にエラーシンボル、*data
にエラーデータを格納する(エラーをシグナルする方法を参照)。リターン値がemacs_funcall_exit_throw
なら関数は*symbol
にcatch
されたたタグシンボル、*data
にthrow
された値を格納する。リターン値がemacs_funcall_exit_return
なら関数はこれらの引数が指すメンモリー内に何も格納しない。
何らかのリソースの割り当て前や解放を要するリソースの割り当て後、あるいは失敗がそれ以上の処理が不可能もしくは実行不能を意味するような場合のように、非ローカル脱出が問題になるようならチェックするべきです。
モジュール関数が保留中の非ローカル脱出を一度検知すれば、(必要なローカルクリーンアップの実施後に)Emacsにリターンしたり、非ローカル脱出からのリカバリーを試みることができます。以下のAPI関数はこれらのタスクの助けとなるでしょう。
void
non_local_exit_clear (emacs_env *env)
¶この関数は保留中の非ローカル脱出のコンディションとenv由来のデータをクリアーする。これの呼び出し後にはモジュールAPI関数は通常どおり機能するだろう。モジュール関数が呼び出したLisp関数の非ローカル脱出からリカバーして継続可能な場合、あるいは以下の2つの関数のいずれか(非ローカル脱出が保留中の際に他のAPI関数に意図した動作を行わせたい場合にはそれらのAPI関数も)を呼び出す前にもこの関数を使用すること
void
non_local_exit_throw (emacs_env *env, emacs_value tag, emacs_value value)
¶この関数はtagで表されるLispのcatch
シンボルにリターン値としてvalueを渡してthrowを行う。モジュール関数は一般的にはこの関数の呼び出し後は即座にリターンすること。この関数は呼び出されたAPI関数やLisp関数のいずれかから非ローカル脱出を再throwしたい際の1つの手段である。
void
non_local_exit_signal (emacs_env *env, emacs_value symbol, emacs_value data)
¶この関数はエラーシンボルsymbolで表されるエラーを、指定したエラーデータdataとともにシグナルする。モジュール関数はこの関数の呼び出し後は即座にリターンすること。この関数はたとえばモジュール関数からEmacsにエラーをシグナルする際に有用かもしれない。