pi

pi は scheme インタプリタである。

起動方法
pi [file] [arguments]

引数なしで起動した場合、pi は通常の read-eval-print ループを実行する。 式 (exit) を評価することで終了する。
起動時に引数を与えた場合、それが "--" でなければ第一引数をファイル名 として解釈し、read-eval-print ループの実行に先だってそのファイルを ロードする。 第二引数以降はアプリケーションにパラメータを与えるために利用できる。 プログラムからコマンドラインの引数を知るには大域変数 *invocation-arg* または手続き rp:command-line-arguments を使用する。 pi に引数を与えるがファイルのロードは行わない場合は第一引数として "--" を指定する。pi が引数なし、あるいは "--" を第一引数として起動された場合、 環境変数 RHIZOME_PI_RC がセットされていればその内容が read-eval-print ループの実行に先だって評価される。
pi の動作は標準ライブラリに含まれるモジュール rp_pi が行なっている。pisl の最後の引数として rp_pi: を指定することで他のモジュールに含まれる手続きが コンパイル済みで追加されたインタプリタを作成できる。特にコマンド "pisl rp_pi:" を実行することで pi そのものと同じ実行プログラムが作られる。 モジュール rp_pi の動作の詳細は以下のとおりである。

  1. 実行前に *invocation-arg* にはコマンドラインがセットされている。
  2. 第一引数が "--" であればそれを *invocation-arg* から取り除く。 それ以外の第一引数が指定されていれば第ゼロ引数(コマンド名)を *invocation-arg* から取り除く。 引数がなければ *invocation-arg* はそのままにしておく。
    1. 引数が無いか第一引数が "--" であったなら環境変数 RHIZOME_PI_RC を調べ、セットされていればその値を評価する。
    2. "--" 以外の第一引数が指定されていればそれをロードする。
  3. ステップ2が終了し pi の実行が続いていれば、手続き break (即ち read-eval-print ループ)がプロンプトを *invocation-arg* の car から取って呼ばれる。この動作自体はモジュール rp_pi が行なうものではなく、モジュール rp_pi がリンクされているかどうかにかかわらず常に行なわれる。

*invocation-arg* 大域変数
初期状態では起動時のコマンドラインをリストとして保持している。これは インタプリタ pi では第一引数(ロードするファイル)以降の文字列からなる リストであり、コンパイルされたプログラムでは実行ファイル名を含む コマンドライン全体からなるリストである。いずれの場合でもリストの第二 要素以降をプログラムに対する引数として扱えばよいので、プログラムを インタプリタで実行する場合でもコンパイルされている場合でも引数の取得 は同様に行えばよい。
なお、これは単なる変数なのでいつでも代入して値を変えることができる。

(rp:command-line-arguments) 手続き
起動時のコマンドラインをベクタとして返す。これは常にコマンドライン 全体となる。この手続きの返す値を変更する手段はない(定義自体を上書き する場合を除いて。)

$ cat arg.scm
(display "*invocation-arg* is               ")
(write *invocation-arg*)
(newline)
(display "rp:command-line-arguments returns ")
(write (rp:command-line-arguments))
(newline)
(exit)
$ pi arg.scm foo bar baz
*invocation-arg* is               ("arg.scm" "foo" "bar" "baz")
rp:command-line-arguments returns #("pi" "arg.scm" "foo" "bar" "baz")
$ pisc arg.scm
$ pisl arg
gcc -O2 -m486 -I/u/qfwfq/lib/rhizome -c arg.c
gcc -O2 -m486 -I/u/qfwfq/lib/rhizome -c a.c
gcc -L/u/qfwfq/lib/rhizome a.o arg.o -lrhzscm -lrhzpi -lrhizome -lm
$ ./a.out foo bar baz
*invocation-arg* is               ("./a.out" "foo" "bar" "baz")
rp:command-line-arguments returns #("./a.out" "foo" "bar" "baz")

piw

piw はWin32版にのみ存在する。pi と同様 scheme インタプリタであり、 起動方法に違いはない。pi と piw の違いは以下に述べる点のみである。

pisc

pisc は scheme コンパイラである。scheme プログラムをC言語のプログラムに 変換する。

起動方法
pisc -help
コマンドラインの書式の簡単な説明を出力する。
pisc [options] file
file をC言語のプログラムに変換する。

オプション:

-module module-identifier
モジュール名を module-identifier とする。 モジュール名は pisl で実行ファイルを生成する時に指定する名前である。 これはC言語の識別子として正当なものでなければならない。 デフォルトではソースファイルの名前から末尾の ".scm" を (もしあれば)除いたものとなる。
-output filename
出力するファイルの名前を指定する。デフォルトではモジュール 名の末尾に ".c" を加えたものとなる。
-mpath dir
dirrp:use-macro-package のサーチパスに加える。このオプションは複数指定できる。
-load filename
ソースの読み込みの前に指定されたファイルをコンパイラの実行 環境にロードする。コンパイル時にマクロの組み込みを行う目的 に使用できる。このオプションは複数指定できる。

pisf

pisf は scheme プログラムを(多くのケースで)ロードしやすい表現に変換する。 生成されるファイルはソースファイルと同様に load 手続きによってロード できるが人が読むには適さない。通常はソースファイルより小さなファイルを 出力するが、変換過程でマクロの展開を行うため逆に巨大なファイルを出力する 可能性もある。(マクロ展開後の)プログラムのサイズが大きいと pisf の実行 自体にかなりの時間がかかることがある。オプションによってロード可能なファイル ではなくC言語のプログラムを出力することも可能である。この場合通常は pisc で生成するよりもかなり小さなプログラムが得られるが、ソースファイルの内容は インタプリタによって実行されることになる。

起動方法
pisf -help
コマンドラインの書式の簡単な説明を出力する。
pisf [options] file
file を変換する。

オプション:

-exec interpreter
実行可能なスクリプトを出力する(unix 系のOSでのみ意味を持つ)。 interpreter にはプログラムを実行すべき実行ファイルのフルパスを指定する。 出力されるファイルの一行目は "#!interpreter" の形になる。
-module module-identifier
C言語のプログラムを出力する。 module-identifierは pisc で指定するのと同様の意味を持ち、生成されたファイルは pisc の出力と同様に pisl にモジュールとして指定する。
-output filename
-mpath dir
-load filename
これらのオプションの意味は pisc と同じ。

pisl

pisl は pisc によって生成されたC言語のプログラムをコンパイルし、ランタイム ライブラリとリンクして実行ファイルを生成する。

起動方法
pisl -help
コマンドラインの書式の簡単な説明を出力する。
pisl [options] module-specifier ...
module-specifier で指定されるモジュールを 結合して実行ファイルを生成する。

オプション:

-cc cc-command-line
C コンパイラのコマンドラインを指定する。デフォルトは pisl -help の出力で知ることができる。
-ld ld-command-line
リンカのコマンドラインを指定する。デフォルトは pisl -help の出力で知ることができる。
-nold
リンカの起動を抑制する。
-nolib
デフォルトのランタイムライブラリの指定を抑制する。この指定 が無い時にリンクされるライブラリは pisl -help の出力で知る ことができる。
-loadable
実行ファイルではなく共有オブジェクトを生成する。生成されたオブジェクトは rp:load-compiled-module手続きによりロードする。 環境によってはこのオプションは使用できない。
-static
生成される実行ファイルを特定の共有オブジェクトに依存しないで 実行できるものにする。ファイルサイズは大きくなる。 環境によってはこのオプションは常に有効になる。
-modlib
さらに pisl を実行する時にモジュールが含まれる入力ファイルと して使用できる共有オブジェクトを作成する。 環境によってはこのオプションは使用できない。
-windows
このオプションはWin32でのみ意味を持つ。指定された場合Win32の GUIアプリケーションが生成される。生成された実行ファイルは コンソールから切り離されて起動し、最初にコンソールからの 入出力を行った時に自身のコンソールを持つようになる。
-o filename
出力する実行ファイルの名前を指定する。デフォルトはリンカの 仕様によって決定される。
-s filename
スタートアップコード(リンクされる各モジュールの初期化ルーチン の呼び出しを行うコード)のファイル名を指定する。このファイルが リンクされる最初のモジュールとなる。デフォルトは -o オプション がある場合その値に先頭に "s_", 末尾に ".c" を加えたもの、 -o オプションがない場合 a.c となる。
-base address
出力ファイルのベースアドレスを指定する。 アドレスの書式は使用するリンカによる。 環境によってはベースアドレスを指定することによって 性能が向上すると言われている。
-xm module
module で指定された標準モジュールを 実行ファイルから除く。
module は次のうちのどれか。
expand syntax-case によるhygienicマクロ機能。これが除かれると 一部の構文の振る舞いがわずかに変化するが、その変化は 普通のプログラムに影響を及ぼすようなものではない。
stdmacro 標準のマクロ。rhizome/pi では define, lambda など 基本的な構文キーワードもマクロなのでこれが除かれると 使用できなくなる。アプリケーションが実行時に任意の 式を評価する機能を持たないならこれを除いても安全 である。
debugger デバッグ機能。
stdproc 組み込み手続きのうち rhizome/pi において scheme で 記述されているもの。これを除いた場合何が使用できなく なるかはソースを参照のこと :-) これを除くと expanddebugger も自動的に除かれる。
extcall 共有オブジェクト内の関数へのインターフェースを提供するマクロ。 アプリケーションの実行時に新たに外部手続き、コールバック、 バッファ構造、定数を定義する必要がなければ これを除いても安全である。
saccess extcallに含まれるマクロによって定義されたマクロを 展開するときに使用される手続き。expandが除かれると saccessも自動的に除かれる。またsaccess が除かれるとextcallが自動的に除かれる。

このオプションは複数指定できる。
-aux string
string をリンカのコマンドラインに追加する。 すでにオブジェクトファイルになっているモジュールを指定する目的に使用 できる。
このオプションは複数指定できる。
module-specifier の指定方法

module-specifier には pisc の -module オプションで指定した名前を指定する。
そのモジュールが含まれるファイルがモジュール名に ".c" を追加した名前で ない場合、ファイル名を ':' のあとに指定する。また、ファイルが既に オブジェクトファイルになっている場合は ':' のあとを空文字列にし、 オブジェクトファイルの名前を -aux オプションを使用して指定する。


ソースファイル x.scm, y.scm, z-0.scm をコンパイルして実行ファイルを 作成するとする。以下はコンパイルの手順の一例である。

pisc x.scm				# x.c を生成
pisl -nold x				# x.o を生成
pisc y.scm				# y.c を生成
pisc -module zz -output z-0.c z-0.scm	# z-0.c を生成、モジュール名は zz
pisl -aux x.o x: y zz:z-0.c		# 実行ファイルを生成
生成された実行ファイルを起動すると各ソースファイルをインタプリタ上で pisl に与えたモジュール指定の順にロードした場合と同様の動作をする。 上の例では、a.scm の内容が
	(load "x.scm")
	(load "y.scm")
	(load "z-0.scm")
であったとして
	pi a.scm [arguments]
とした場合と同様の動作となる。
特に、コンパイルしたプログラムが非対話的な一連の動作の後 (exit) するようになっていれば、生成されるものは非対話的なプログラムになる。また、 一連の手続きの定義のみを含むプログラムをコンパイルすれば生成されるものは その手続きがあらかじめ定義された scheme インタプリタとなる。ただしこの 場合起動時の第一引数をロードするといった pi と同じ動作を望むなら、その 動作をプログラムに記述しなければならない(ライブラリに含まれるモジュール rp_pi をリンクすればよい。pi 自身は "pisl -o pi rp_pi:" として作成できる。)
同一のモジュールを2回以上ロードしてはならない。 これに違反した場合プログラムは異常終了する。
インデックス