Subsections

評価

評価関数

エラーやシグナル(signal)に関する振る舞いを示すために、 あらかじめそれぞれ特別の変数*error-handler**signal-handler* に適当な関数を設定する。 修正あるいは続行できるエラーはない。 エラーを解析後、現在の実行をresetまたは上位レベルへの適当なthrow によって停止しなければならない。 Euslispの最上位レベルで0と名付けられたcatch frameを作成しているので、 resetは、(throw 0 NIL)と同等である。

エラーハンドラーは、code msg1 form &optional (msg2) という3つあるいは4つの引き数を持つ関数として定義しなければならない。 codeはエラーコードで、システムで定義されたエラーを示す。 例えば、14が'引き数が合わない'、13が'関数が定義されていない'となる。 これらの定義は、"c/eus.h"の中に定義されている。 msg1msg2は、ユーザーに示されるメッセージである。 formは、エラーによって生じたs表現である。

シグナルハンドラーは、sigcodeの2つの引き数を受ける関数として 定義されなければならない。 sigは、1から30までのシグナル番号である。 codeは、シグナル番号の中に定義された補助番号である。

最上位レベルでの^D(end-of-file)は、Euslispの活動を停止させる。 これは、Euslispをフィルターとしてプログラムされているとき 役に立つ。

eval-dynamicは、letやlambda変数として使用されるsymbolに結び付く 動的な変数を捜す関数である。 デバッグするときに役に立つ。



identity obj [関数]

obj自身を返す。 idnetityquoteとの違いに注意すること。 identityが関数であるのに対してquoteは、特殊書式(special form) である。 したがって、(identity 'abc)abcと評価されるが、 (quote 'abc) == (quote (quote abc))'abcと評価される。 identityは、多くの一般列関数の:keyパラメータのデフォルト値 としてしばしば用いられる。


eval form &optional environment [関数]

formを評価して、その値を返す。 もし、*evalhook*formenvironmentを受ける関数を 設定するならば、hook関数を評価に入る前に呼び出すことができる。


apply func &rest args [関数]

argsfuncを適用する。 funcは、関数symbolかlambda書式かclosureでなければならない。 マクロと特殊書式(special form)は適用出来ない。 argsの最後の要素は、他のargsが空の引き数であるなら 引き数のリストでなければならない。 このように、もし、argsの最後がNILであったならば、 applyはほとんどfuncallと同じである。 ただし、applyfuncallより1つ多くの引き数を持つことができる。 (apply #'max 2 5 3 '(8 2)) -> 8.


funcall func &rest args [関数]

argsfuncを適用する。 argsの数は、funcで要求されている引き数の数と一致しなければ ならない。


quote obj [特殊]

obj自身を評価する。


function func [特殊]

closure関数を作る。 もし、funcがsymbolならば、その関数定義が検索される。


evalhook hookfunc form &optional env [関数]

hookfun*evalhook*に結び付けた後、formを一度評価する。


eval-dynamic variable [関数]

スタックにあるvariable(symbol)の値を捜す。


macroexpand form [関数]

もし、formがマクロcallであるなら、それを展開する。 もし、展開したものがまだマクロcallを含んでいるならば、 マクロcallのない結果となるまでくり返し展開する。


eval-when situation &rest forms [特殊]

situationcompile, load, evalのリストである。 formは、現在の実行モードがsituationと一致するときに評価される。 eval-whenは、コンパイラでの動作や環境を制御するために重要なものである。 もし、compileが指定されたならば、formはコンパイラによって 評価されるので、その結果はコンパイル結果に影響を及ぼすことになる。 例えば、defmacroはコンパイル時にマクロcallを展開するためにコンパイラで 評価されなければならない。 もし、loadsituationのリストに与えられたならば、 formはload時にloadまたは評価されるためにコンパイルされる。 すなわち、load時にコンパイルされた関数が定義される。 これは、コンパイラに期待される一般的な機能である。 loadは、コンパイラの環境を制御するために使用される。 もし、evalsituationのリストに含まれているならば、 formはソースコードがloadされるときに評価される。


the type form [特殊]

formtypeとして宣言する。 typeは、:integer, :fixnum, :floatで示されるクラスオブジェクト のどれかである。


declare &rest declarations [特殊]

それぞれdeclarationは、宣言指定や整数あるいは目的のsymbolのリストである。 宣言は、コンパイラが高速なコードを生成するために重要である。
special 特殊変数を宣言する。
type 変数の型を宣言する。; (type integer count); 有効な型指定子はinteger, :integer, fixnum, :floatfloatである。型指定子がここに示したものの1つである ならば、typeキーワードを削除しても良い。そのため、 (integer count)は正しい宣言である。 float-vector,integer-vectorなどのような、その他の型(クラス)では、 (type float-vector vec1)のようにtypeを前に付ける必要がある。
ftype 関数の結果の型を宣言する。
optimize コンパイラの*optimize*パラメータに値(0-3)を設定する。
safety コンパイラの*safety*パラメータに値(0-3)を設定する。
space コンパイラの*space*パラメータに値(0-3)を設定する。
inline 認識しない。
not-inline 認識しない。


proclaim proclamation [関数]

変数やコンパイラオプションをグローバルに宣言する。 同様な宣言は、declare特殊書式によって記述することができる。 しかしながら、proclaimは、1つの引数を持つ関数であり、 宣言を評価する。


warn format-string &rest args [関数]

format-stringargsで与えられる警告メッセージを *error-output*に出力する。


error format-string &rest args [関数]

*error-handler*に結び付く現在のエラーハンドラー関数を呼び出す。 デフォルトのエラーハンドラー'euserror'を*error-output*に最初に出力し format-stringargsformatを用いて出力する。 その後、新しい最上位レベルのセッション(session)に入る。 プロンプトには、エラーセッションの深さを示す。 throwにその番号を与えることにより、低いエラーレベルのセッションへ戻ることができる。


マルチスレッドEuslispにおいて、特殊変数はスレッド間で共有され、 同じ*error-handler*が異なったスレッドから参照される。 この不自由を避けるために、マルチスレッドEuslispはinstall-error-handler 関数を備えている。その関数は、それぞれのスレッドに対して 異なったエラーハンドラーをインストールする。



lisp::install-error-handler handler [関数]

handlerを現在のスレッドのエラーハンドラーとしてインストールする。


最上位レベルの対話

EusLispの標準の最上位レベルの入力−評価−出力のループ(loop)は、eustop により制御されている。 euslispが呼び出されたとき、 eustopは、ホームディレクトリから".eusrc"というファイルを あるいはEUSRC環境変数で指定されたファイルをロードする。 それから、euslispは、引き数リストで指定されたファイルをロードする。 これらのロードが終了後、eustopは、普通の対話セッション(session)に入る。

*standard-input*にユーザーのTTYが接続されたとき、 eustopは、*prompt-string*(デフォルトとして"eus$"が 設定されている)に設定されたプロンプトを出力する。 そして、*terminal-io*ストリームから命令を入力する。 もし、その入力がカッコで括られた行ならば、 evalによってlisp書式として扱われる。 もし、入力行の最初のsymbolに関数定義があった場合、その行に自動的に カッコが入れられ、評価される。 もし、関数定義が見つからなかった場合、その特殊値(special value)が 調査され、その値が出力される。 もし、そのsymbolになにも定義されてないならば、 その行はUNIX命令とみなされ、sh(Bourn's shell)へ渡される。 もし、shが一致するUNIX命令を捜せなかったとき、 "command unrecognized"というメッセージを出力する。 このように、eustopはlispのインタープリタおよびUNIXのシェルとして動作する。 もし、入力をUNIX命令として実行したくないとき、 行の最初にコンマ','を付ければよい。 これは、対話実行(interpretive execution)でエラーが発生したとき、 動的な値を見るときに役に立つ。 Euslispはローカルなスコープ(lexical scope)を採用しているので ローカル変数の値をspecialとして宣言されていない限りスコープの外から 調査することは出来ない。

入力は、それぞれ行番号とともに*history*ベクトルに記憶される。 cshの上と同じ様に!関数を入力することにより入力の詳細を 呼び出すことができる。 cshの履歴との違いは、!が関数であるため!の次に最低1つの スペースが必要である。 また、コントロールキーを用いることによりemacsのように対話的に 行を編集することができる。

通常^D (EOF)でEuslispは終了する。 上位レベル(普通はcsh)に異常終了コードを返すためには、適当な条件コードをつけた exitを使用すること。

eustopは、SIGINTとSIGPIPEのためにシグナルハンドラーを設定する。 そして、他のシグナルはcatchしない。 このため、SIGTERMやSIGQUITのようなシグナルでEuslispを終了できる。 終了を避けたいとき、これらのシグナルをcatchするためには、 unix:signal関数でユーザーで定義したシグナルハンドラーを設定すること。



- [変数]

現在の入力


+ [変数]

直前の入力


++ [変数]

2つ前の入力


+++ [変数]

3つ前の入力


* [変数]

直前の結果


** [変数]

2つ前の結果


*** [変数]

3つ前の結果


*prompt-string* [変数]

eustopで使用されるプロンプト文字列


*program-name* [変数]

このEuslispが呼び出された命令。例えば、eus,eusx,eusxviewやユーザーで作った euslispなど。


eustop &rest argv [関数]

デフォルトの最上位ループ


eussig sig code [関数]

SIGPIPEのデフォルトシグナルハンドラー。 eussigは、SIGPIPEが到着したり他の最上位レベルループに入るとき シグナル番号を出力する。


sigint-handler sig code [関数]

SIGINT(control-C)のデフォルトシグナルハンドラー。 このシグナルで新しい最上位セッションへ入る。


euserror code message &rest arg [関数]

デフォルトのエラーハンドラーで、 messageを出力し、新しいエラーセッションへ入る。


reset [関数]

エラーループから脱出して、最後のeustopセッションへ戻る。


exit &optional termination-code [関数]

Euslispプロセスを終了し、プロセスの状態コードとしてtermination-code (0..255)を返す。


*top-selector* [変数]

複数のストリームによる非同時関数呼び出しを管理するport-selectorオブジェクト。


h [関数]

*history*の中に記憶されている入力履歴を 関連する列番号とともに出力する。


! &optional (seq 0) [関数]

列番号seqに関連する入力行を呼び出す。 seqが0のとき、もっとも最近の命令が呼び出される。 もし、seqが負の場合、現在行から相対的な位置にある行が 呼び出される。 呼び出された行が表示され、その行の最後にカーソルを移動する。 次のコントロールキーが使用出来る。 control-H (backspace)かcontrol-Bで1文字戻る。 control-Fかcontrol-Kで1文字進む。 control-Aで行の最初に移動する。 control-Lで行の最後に移動する。 control-Cで行の修正をキャンセルする。 control-M (carriage-return)かcontrol-J (line-feed)で 行修正を終了して、修正した行を評価する。 もし、seqが番号でなくsymbolまたは文字列の場合、 履歴リストを古い方に向かって検索し、 symbolまたは文字列が含まれている命令行を返す。


new-history depth [関数]

depthの長さを持つように*history*を初期化する。 depth行が記憶される。 現在の*history*に記録された入力行は、すべて消滅する。



コンパイル

Euslispコンパイラは、Lispプログラムの実行を高速化するために使用される。 実行時間の5〜30倍の高速化とマクロ展開によるガーベージコレクション 時間の大幅な減少が期待できる。

euscompは、計算処理とベクトル処理のための最適化を行う。 ときどきコンパイラが最適化を効率良く実行するために、固有の型宣言が必要となる。

compile-functionは、1つずつ関数をコンパイルする。 compile-fileは、すべてのソースファイルをコンパイルする。 compile-fileを実行している間、ファイル内のすべての書式が読み込まれ 評価される。 これは、現在のEuslispの環境を変化させる。 例えば、defparameterはsymbolに新しい値を設定するし、 defunはコンパイルされていない関数をコンパイルされた関数に 置き換える。 これらの予期しない影響を避けるためには、compile指定のないeval-whenを 使用したり、euscompを使用して別プロセスとしてコンパイラを実行したりする。

euscompはUNIXのコマンドで、普通eusにシンボリックリンクされている。 幾つかのオプションを持っている。 -OフラグはCコンパイラの最適化を指示し、 -O1,-O2, -O3 はそれぞれEuslispコンパイラの最適化のレベルを指示する。 これは、(optimize 1 or 2 or 3)と宣言するのと同等である。 -S0, -S1, -S2, -S3は、compiler:*safety*に0,1,2,3を設定する。 もし*safety*が2より小さければ、割り込みチェックのためのコードを発行しない。 もし、プログラムが無限ループに入ったとき、制御を失うことになる。 もし*safety*が0のときは、引き数の数をチェックしない。 -Vフラグは、コンパイルされている関数名を表示する。 -cフラグは、ccの実行やforkを防ぐ。 -Dは、*features*リストに続く引き数を置く。 これは、読み込みマクロ#-#+ を用いた条件付きコンパイルのために使用することができる。

コンパイラは"xxx.l"という名のEuslispソースプログラムを 中間Cプログラムファイル"xxx.c" とヘッダーファイル"xxx.h"に変換する。 それから、Cコンパイラが実行され、"xxx.o"が生成される。 中間ファイル"xxx.c"と"xxx.h"はクロスコンパイルの目的のために残される。 したがって、違うアーキテクチャーの機械の上で使用したいとき、UNIX命令のccで "xxx.c"ファイルをコンパイルするだけでよい。 コンパイルされたコードは、'(load "xxx")'によってEuslispにロードされる。

中間ファイルはそれぞれ、"eus.h"ヘッダーファイルを参照する。 このファイルは、*eusdir*/cディレクトリに置かれていると仮定している。 *eusdir*は、EUSDIR環境変数からコピーされる。 もし設定されてなければ、/usr/local/eus/がデフォルトディレクトリ として扱われる。

コンパイルされたとき、中間のCプログラムは普通元のソースコードよりも かなり大きくなる。例えば、1,161行のlispソースコード"l/common.l"は、 8,194行の"l/common.c"と544行の"l/common.h"に展開される。 1,000行のlispソースをコンパイルするのは、難しい作業ではないが、 10,000行近いCのプログラムを最適コンパイルすることは、長い時間(数分)かかる とともに、たくさんのディスク空間を消費する。 そのため、もし相対的に大きなプログラムのコンパイルをするならば、 /var/tmpに十分なディスクがあるかどうかを確認すること。 そうでなければ、CCは死ぬだろう。 TMPDIR環境変数をもっと大きなディスク部分に設定することが助かる道である。

リンクがロード時または実行時に実行されるので、 eusのカーネルがバージョンアップされても再コンパイルする必要はない。 もう一方で、実行時リンクは不便なことがある。 2つの関数AとBが"x.l"ファイルにありAがBを呼び出していると仮定する。 "x.l"をコンパイル後、"x.o"をロードし内部でBを呼び出しているAを呼び出そうとする。 それから、Bの中でbugを見つけると、たぶんBを再定義しようとするだろう。 ここで、コンパイルされたAとコンパイルされていないBとができる。 再びAを呼び出したとすると、Aはまだ古いコンパイルされているBを呼び出す。 これは、Aが最初にBを呼び出したとき固定的にリンクされるからである。 この問題を避けるためには、Aを再定義しなおすかあるいは"x.o"がロードされた直後で Aを呼び出す前にBを再定義しなければならない。

コンパイルされたコードがロードされるとき、一般的にdefunやdefmethodの 列である最上位コードが実行される。 この最上位コードはロードモジュールのエントリ関数として定義されている。 コンパイラがそのエントリ関数の名前を付け、 ローダがこの関数の名前を正確にわからなければならない。 状況を簡単にするために、コンパイラとローダの両方とも そのエントリ関数の名前としてオブジェクトファイルのbasenameと同一のもの と仮定する。 例えば、もし"fib.l"をコンパイルしたならば、 コンパイラは"fib.c"のエントリ関数として"fib(...)"を生成する。 そして、ローダはオブジェクトファイル"fib.o"の中から"fib"を探す。 最終的にオブジェクトファイルはUnixの"cc"や"ld"で生成されるので、 このエントリ関数名は、C関数の命名ルールを満足しなければならない。 したがって、ファイル名としてCの予約キーワード(例えば、 "int", "struct", "union", "register", "extern"など)や"c/eus.h"に 定義されているプライベート指示語(例えば、"pointer", "cons", "makeint"など)を避けなければならない。 もし、ソースファイルの名前としてこれらの予約語の内の1つを 使用しなければならないならば、コンパイラやローダの :entry引数を別に指定すること。

closureの使用には制限がある。 closureの中のreturn-from特殊書式とunwind-protectの中のclean-up書式は いつも正しくコンパイルされるわけではない。

disassembleは、実現されていない。 コンパイルされたコードを解析するためには中間Cプログラムを見るかあるいは adbを使用する。



euscomp &rest filename [UNIXコマンド]

Euslispコンパイラを呼びだす。



compile-file   [関数] 

srcfile &key (verbose nil)
(optimize 2) (c-optimize 1) (safety 1)
; optimization level
(pic t)
; position independent code
(cc t)
; run c compiler
(entry (pathname-name file))
ファイルをコンパイルする。 ".l"がsrcfileの拡張子として仮定される。 もし、:verboseがTならば、コンパイルされた関数やメソッド名が表示される。 これは、エラーが発生した箇所を簡単に探すのに役立つ。 :optimize, :c-optimize:safetyは、最適化のレベルを 指定する。 モジュールが作成中にEuslispのコアにハードリンクされていないかぎり、 :picは、Tに設定すべきである。


compile funcname [関数]

関数をコンパイルする。compileは、最初に関数定義をテンポラリファイルに 出力する。そのファイルは、compile-fileによってコンパイルされ、 それからloadによってロードされる。 テンポラリファイルは削除される。


compile-file-if-src-newer srcfile &key compiler-options [関数]

srcfileが対応するオブジェクトファイルよりも新しい(最近変更された) ならば、コンパイルする。そのオブジェクトファイルは、".o"拡張子を 持っていると仮定される。


compiler:*optimize* [変数]

コンパイラの最適化レベルを制御する。


compiler:*verbose* [変数]

non-NILが設定されたとき、コンパイルされている関数名やメソッド名そして コンパイルに要した時間を表示する。


compiler:*safety* [変数]

安全性レベルを制御する。


プログラムロード




load   [関数] 

fname &key (verbose *load-verbose*)
(package *package*)
(entry (pathname-name fname))
(symbol-input nil)
(symbol-output "")
(print nil)
(ld-option "")
loadはソースファイルあるいはコンパイルされたオブジェクトファイル をEuslispに読み込むための関数である。 もし、fnameで指定されたファイルが存在するとき、 Euslispはロードする。 そのファイルがソースとバイナリーの内どちらかは、magic numberを見ることにより 自動的にチェックされる。 もし、そのファイルが存在しないが'.o'の型のファイルが存在する場合、 そのファイルをオブジェクトファイルとしてロードする。 その他、'.l'のファイルが見つかったならば、ソースプログラムとしてロードする。 もし、ファイル名の最初に"/"を付ける絶対パスを指定していない場合、 loadは、グローバル変数*load-path*に指定されているディレクトリ の中からファイルを検索する。 例えば、*load-path*("/user/eus/" "/usr/lisp/")であり、 fnameとして"llib/math"が与えられたとき、 load"/user/eus/llib/math.o", "/usr/lisp/llib/math.o", "/user/eus/llib/math.l", "/usr/lisp/llib/math.l"をこの順番に捜す。 適当なファイルが見つからなければ、エラーを返す。

:entryオプションは、ロードモジュールを初期化する入力アドレスを 指定する。 たとえば、:entry "_myfunc"オプションは_myfuncから実行を始める ことを意味する。 デフォルト入力アドレスは、10.3節に記述されているように ロードされたファイル名のbasenameである。 ライブラリモジュール名は:ld-optionオプション文字列の中に指定 することができる。 たとえば、suncoreライブラリを使用するモジュールをリンクするために、 :ld-optionには "-lsuncore -lsunwindow -lpixrect -lm -lc" を与える必要がある。Solarisシステム以外では、 ライブラリがリンクされるときldは2度実行される。 1度はサイズを決定するため、2度目は固有のメモリーに実際にリンクするため。

:symbol-input:symbol-outputオプションはあるオブジェクト モジュールから他のモジュールへの参照を解決するため、あるいは ライブラリーの2重ロードを避けるために使用される。 A,B2つのオブジェクトモジュールがあり,BがAの中で定義されているsymbolを 参照しているとする。 :symbol-output ="a.out"を指定してモジュールAをロードする。 このリンクによって生成されたsymbol情報は、a.outに書き込まれる。 モジュールBをロードするためには、BからAへの参照を解決する :symbol-input = "a.out"を指定しなければならない。



Solaris2 OSにおいて、コンパイルコードのロードは、動的ロードライブラリの中の dlopenを呼び出すことにより実行している。 dlopenの使用は、共有オブジェクトに制限されている。 そのオブジェクトは、位置に依存するようにコンパイルされるために、 "-K pic"オプションを指定する。 また、dlopenは同じファイルを2度オープンすることができないので、 既にロードされているファイルに関しては、dlcloseを最初に 実行する。

load-files &rest files [関数]

:verboseにTを設定し、filesを連続的にロードする。


*modules* [変数]

これまでにロードされたモジュールの名前のリストを持つ。


provide module-name &rest version-info [関数]

module-nameversion-infoのconsを、すでにロードされた モジュールの名前として*modules*の中に加える。 module-nameはsymbolあるいは文字列でなければならない。 requireの呼び出しは、完全なモジュールを構成するファイルの最初に 存在しなければならない。


require module-name &rest load-arg [関数]

*modules*の中にmodule-nameが見つからなかったとき、 module-nameload-argの第一要素によって 示されているファイルをロードする。 providerequireは、モジュールの中の依存を制御し、 基本モジュールの2重ロードを避けるために使用される。 1つの基本モジュール"A"と2つの応用モジュール"B"と"C"があったとし、 "B"と"C"は互いに依存しないが"A"に依存しているとする。 それぞれのファイルの最初にprovideでモジュール名を宣言する。 "A"モジュールがどのモジュールにも依存していないなら、なにもrequire しなくてよい。 "B"や"C"の中のprovide呼び出しに続いて(require "A" "a.o")が 実行される。 もし"B"をロードするとき、*modules*の中に"A"が見つからなければ "a.o"もロードし、*modules*に"A"と"B"のモジュール名を追加する。 その後、もし"C"がロードされるなら、"A"モジュールはロードされず、"C"が *modules*に追加されるのみである。



system:binload   [関数] 

opath qpath &optional (entry (pathname-name opath))
(symfile "/usr/local/bin/eus")
(symout "a.out")
(ldopt "")
バイナリファイルをロードしリンクする。


system::txtload fname [関数]



デバッグ補助



describe obj &optional (stream *standard-output*) [関数]

describeはオブジェクトのslotごとの中身を表示する。


describe-list list &optional (stream *standard-output*) [関数]

list内のそれぞれの要素にdescribeを実行する。


inspect obj [マクロ]

inspectdescribeの対話版である。 オブジェクトのそれぞれのslotを表示するためにサブ命令を受けたとき、 slotの中に深く入ったりあるいは新しい値をslotに設定したりする。 '?'命令でサブ命令のメニューを見ることができる。


more &rest forms [関数]

*standard-output*にテンポラリーファイルを結び付けて formsを評価した後、そのテンポラリーファイルをUNIXの'more'命令 を使用して*standard-output*に出力する。 moredescribeのような関数によって発生した長い出力を 見るときに役に立つ。


break &optional (prompt ":: ") [関数]

breakループに入る。 現在バインドされている環境が実施されている間、入力の前に","を付ける ことによりローカル変数を見ることができる。 breakを終了したいとき、control-Dを入力する。


help topic [関数]

helpは、topicに関して短い説明を表示する。 topicは、ふつう関数symbolである。 文章はKCLのマニュアルから借りているため、説明がEuslisp関数のものといつも 合っているとは限らない。


apropos strng &optional pack [関数]

aproposは、関数や変数の正確な名前を忘れていて、その一部あるいは 不確かな名前しか知らないときに役に立つ。 symbol-nameの中に部分文字列としてstrngを含むすべてのsymbolを表示する。 packが与えられた時、そのパッケージに属するシンボルのみ表示する。


apropos-list strng &optional pack [関数]

aproposと似ているが表示はしない、しかしリストとして結果を返す。


constants &optional (string "") (pkg *package*) [関数]

pkgの中に定数として定義されstringと合うsymbolをすべてリスト 出力する。


variables &optional (string "") (pkg *package*) [関数]

pkgの中にグローバル値として割り当てられstringと合う symbolをすべてリスト出力する。


functions &optional (string "") (pkg *package*) [関数]

pkgの中にグローバル関数として定義されstringと合う symbolをすべてリスト出力する。


btrace &optional (depth 10) [関数]

depthレベルの履歴を呼び出し表示する。


step-hook form env [関数]



step form [関数]

steptraceは関数の上でのみ正確に働く。マクロや特殊書式では 働かない。


trace &rest functions [関数]

functionsのトレースを始める。 functionsが呼び出されたときはいつでも、その引き数と結果を表示する。


untrace &rest functions [関数]

トレースを終了する。


timing count &rest forms [マクロ]

formscount回実行し、formsの1回の実行に要する 時間を計算する。


time function [マクロ]

functionによって経過した時間を測定し始める。


sys:list-all-catchers [関数]

すべてのcatchタグを返す。


sys:list-all-instances aclass &optional scan-sub [関数]

すべてのヒープの中からaclassで指定されるインスタンスをすべて 探し、集める。 もし、scan-subがNILなら、aclassの確実なインスタンスを リストする。そうでなければ、aclassのインスタンスあるいはサブクラス が集められる。


sys:list-all-bindings [関数]

バインドされるスタックを探し、 アクセス可能な値すべてをリストで返す。


sys:list-all-special-bindings [関数]

スタックを捜し、値をすべてリストアップする。


ダンプオブジェクト

EusLispのリーダとプリンタは、どのようなオブジェクトも再読みだし可能な書式 でファイルに出力できるように設計されている。 オブジェクトは相互参照あるいは再帰参照を持っていてもよい。 *print-circle**print-object*にTを設定したとき、この特徴は は可能となる。 次の関数はこれらの変数をTにし、ファイルをオープンし、オブジェクトを表示する。 これらの関数のもっとも重要な用途は、相互参照を持つ3Dモデルの 構造体をダンプすることである。



dump-object file &rest objects [関数]



dump-structure file &rest objects [関数]

再び読み戻しができるような書式でfileobjectsをダンプする。


dump-loadable-structure file &rest symbols [関数]

symbolにバインドされたオブジェクトをfileにダンプする。 そのfileは簡単にロードすることによって読み戻すことができる。


(setq a (make-cube 1 2 3))

;; sample for dump-object
(dump-object "a-cube.l" a)
(with-open-file
  (f "a-cube.l" :direction :input)
  (setq a (read f)))
(print a)

;; sample for dump-structure
(dump-structure "a-cube.l" a)
(with-open-file
  (f "a-cube.l" :direction :input)
  (setq a (read f)))
(print a)

;; sample for dump-loadable-structure
(dump-loadable-structure "a-cube.l" a)
(load "a-cube.l")
(print a)

プロセスイメージ保存

このプロセスイメージ保存は、Solarisの動的ロード機能に深く依存しているため、 Solaris2のEuslispにおいてサポートされていない。 Solarisの動的ロード機能は、共有するオブジェクトをsbrk点の上の 位置に依存した形でロードする。



sys:save path &optional (symbol-file "") starter [関数]

saveは、現在のEuslisp処理の環境をファイルにダンプする。 そのファイルは、後でUNIX命令として呼び出すことができる。 もし関数名がstarterによって指定されているなら、 その関数はその命令の実行が始まるときに評価される。 それぞれの命令行の引き数はEuslispの中で強制的に文字列にされ、 引き数としてstarterに受け渡される。 それで、命令行を解析できる。 *standard-input**standard-output*を除くすべてのストリームを 確実にクローズしていなければならない。 ファイルがオープンされた状態を保存することはできない。 また、mmapを試そうとしてはならない。 mmapはインターネットのソケットストリームを作るとき、見えない所で実行されている。 Sunのネットワークライブラリはhost-by-nameのようなNIS情報をメモリ上に いつも展開し、プロセスの最上位に置くため保存できない。 そのため、保存されたイメージが実行されるても、ネットワークライブラリへの アクセスはどれも失敗し、コアダンプが生じる。 Xwindowもこのライブラリを使用している。 それで、一度Xserverに接続されたプロセスイメージを保存することはできない。


最上位レベルのカスタマイズ

EuslispがUNIXから呼び出されるとき、*toplevel*にバインドされる 最上位関数によって実行が始められる。 この関数は、eusの中のeustopeusxの中のxtopである。 saveの3番目の引き数に独自の関数を指定することによりこの最上位 関数を変更することができる。

この最上位関数は、任意の数の引き数を受け取れるようにプログラムすべきである。 その命令行の上の引き数はそれぞれ、強制的に文字列にされ、最上位関数に渡される。 以下に示すプログラムは、最初の引き数に与えられたファイルからくり返し読み込み、 2番目の引き数のファイルに整形表示する。

(defun pprint-copy (infile outfile)
  (with-open-file (in infile)
     (with-open-file (out outfile :direction :output)
        (let ((eof (cons nil nil)) (exp))
           (while (not (eq (setq exp (read in nil eof)) eof))
              (pprint exp out))))))
(defun pprint-copy-top (&rest argv)
   (when (= (length argv) 2)
      (pprint-copy (first argv) (second argv))))

一度これらの関数をEuslispの中に定義すれば、 (save "ppcopy" "" 'pprint-copy-top)ppcopyという名のUNIXで実行 可能な命令を作る。

Solaris上のEuslispにおいて、saveがないので、 最上位評価関数はこの手法では変更できない。 代わりに、独自の最上位評価関数を定義するためにlib/eusrt.lを 修正し、*toplevel*に設定することができる。 lib/eusrt.lには、Euslispの起動時に評価される初期化手続きを 定義している。

その他の関数



lisp-implementation-type [関数]

"EusLisp"を返す。


lisp-implementation-version [関数]

このEuslispの名前、バージョン、作成日を返す。 この文字列が起動時にも表示される。 "MT-EusLisp 7.50 X 1.2 for Solaris Sat Jan 7 11:13:28 1995"


This document was generated using the LaTeX2HTML translator on Sat Feb 5 14:36:44 JST 2022 from EusLisp version 138fb6ee Merge pull request #482 from k-okada/apply_dfsg_patch