Common Lisp の実装: インタプリタとコンパイラ
Common Lisp では、コード実行のタイプは、Lisp システムが実装するものと、それをどのように使用するかによって異なります。多くの場合、Common Lisp の実装には、コードを実行する複数の方法があります。インタープリターと 1 つまたは複数のコンパイラーです。単一の実行中の実装でさえそれを持っている可能性があり、ユーザーはそれらを切り替えることができます。
インタプリタ: Lisp データ構造から直接実行します。JVM のような仮想マシン コードのインタープリターではありません。実行中にインタープリターが完全なコード ツリー/グラフを検証するとは思わないでしょう。インタプリタは通常、実行する現在の最上位フォームのみを調べます。
コンパイラ: Lisp コードを C、一部のバイト コードまたはマシン コードにコンパイルします。コンパイラはコードを実行する前にコードを生成するため、すべてのコードの構文チェックを行います (例外の可能性については、下部のコメントを参照してください)。
トップレベルの評価: インタープリター、コンパイラー、または両方の組み合わせを使用できます。
GNU CLISP にはインタープリターとコンパイラーの両方があります
GNU CLISP での例:
通常、テキスト ファイルの LOAD はインタープリターを使用します。
[1]> (load "test.lisp")
;; Loading file test.lisp ...
;; Loaded file test.lisp
T
インタープリターは式全体の構文の正確性をチェックしないため、エラーを検出しません。構文エラーのある else 句は使用されないため、Interpreter はそれを確認しません。
CLISP にはコンパイラもあります。
[2]> (compile-file "test.lisp")
;; Compiling file /tmp/test.lisp ...
** - Continuable Error
in #:|1 1 (IF T 1 ...)-1| in line 1 : Form too short, too few arguments: (IF)
If you continue (by typing 'continue'): Ignore the error and proceed
The following restarts are also available:
ABORT :R1 Abort main loop
ご覧のとおり、CLISP コンパイラは構文エラーを検出し、明確なエラー メッセージを表示します。
SBCL はコンパイラーを使用しますが、インタープリターも備えています
SBCL はデフォルトで、エラーを検出するコンパイラを使用します。トップレベルのフォームでは、一部のフォームではより単純な評価メカニズムを使用します。通訳に切り替えることもできます。
SBCL で単純な IF フォームを記述した場合、エバリュエーターは完全なコンパイルを使用せず、エラーをキャッチしません。
CL-USER> (if t 1 (if))
1
関数定義内に同じコードを記述すると、関数定義はデフォルトでコンパイルされるため、エラーが検出されます。
CL-USER> (defun foo () (if t 1 (if)))
; in: DEFUN FOO
; (IF)
;
; caught ERROR:
; error while parsing arguments to special operator IF:
; too few elements in
; ()
; to satisfy lambda list
; (SB-C::TEST SB-C::THEN &OPTIONAL SB-C::ELSE):
; between 2 and 3 expected, but got 0
;
; compilation unit finished
; caught 1 ERROR condition
WARNING: redefining COMMON-LISP-USER::FOO in DEFUN
FOO
完全な SBCL インタープリターに切り替えると、定義時にエラーが検出されません。
CL-USER> (setf *evaluator-mode* :interpret)
:INTERPRET
CL-USER> (defun foo () (if t 1 (if)))
WARNING: redefining COMMON-LISP-USER::FOO in DEFUN
FOO
最適化と構文チェック
一部の最適化コンパイラは、到達不能コードの構文をチェックしない場合があることに注意してください。
概要
ほとんどの Common Lisp 実装では、コンパイラを使用して完全な構文の警告/エラーを取得する必要があります。