rcシェル内部の実行制御
This content is a draft and will not be included in production builds.
命令列の管理
Section titled “命令列の管理”rc シェルは内部にスタックマシンのような実行環境を持っている。これは codebuf という変数で表現されていて、例えば
$strをスタックマシンで表現すると次のような命令列になる。
block-beta block columns 1 s1[".f = Xmark"] s2[".f = Xword"] s3(".s = str") s4[".f = Xdol"] end %% style simple fill:none,stroke-width:0px他にも
ls /devこれは以下のような命令列として扱われる。
block-beta block columns 1 s1[".f = Xmark"] s2[".f = Xword"] s3(".s = /dev") s4[".f = Xword"] s5(".s = ls") s6[".f = Xsimple"] endcodebuf は compile のたびに新しく生成される。compile は Xrdcmds 命令から呼ばれるが、この命令は組み込みの . と finit 1からのみ生成されるので、おそらくだがファイル単位で codebuf が切り替わるのだろう。
それぞれの codebuf は先頭に参照カウントを持っている。codecopy すると先頭の参照カウントが増加する。
命令列の操作
Section titled “命令列の操作”emitf や emits で、それぞれの型に応じた命令を生成する。
評価結果の管理
Section titled “評価結果の管理”命令とは別に、argv というコマンド文字列を管理する領域も持っている。
ls $homeという命令は codebuf 上に命令列として展開されるが、命令を評価した結果は命令列では扱えない。そこで Xdol 命令などでは評価した結果を argv に格納しておき、Xsimple 等の引数が必要な命令でそれを利用する。
1つの argv は Xmark 命令で開始し、新しい評価結果は末尾に追加する。
評価結果の操作
Section titled “評価結果の操作”新しいリストは newlist で作る。リスト中の値は pushlist や poplist で末尾の値を操作する。
runq という名前で実行状態を管理する。この状態は
- 命令列(codebuf)
- 次の実行位置(pc)
- コマンドライン引数(argv)
- ローカル変数(local)
などを持っている。
実行キューの操作
Section titled “実行キューの操作”start 関数で新しく実行キューが作られる。start は codebuf と実行を開始するインデックスを受け取る。
Xsubshell, Xasync, Xbackq など平行実行が必要な場面で start が呼ばれているので、実行キューも並列実行毎に作られる。このとき codebuf の参照カウントを増加させるので、全ての参照がなくなるまでは runq が参照する codebuf も残る。
初期化コード
Section titled “初期化コード”bootstrap命令列は以下のようなコードを生成する。
. /rc/lib/main $*命令列に並べると以下のようになる。
block-beta block columns 1 s1([".i = 1"]) s2[".f = Xmark"] s3[".f = Xword"] s4(".s = *") s5[".f = Xassign"] s6[".f = Xmark"] s7[".f = Xmark"] s8[".f = Xword"] s9(".s = *") s10[".f = Xdol"] s11[".f = Xword"] s12(".s = /rc/lib/rcmain") s13[".f = Xword"] s14(".s = .") s15[".f = Xsimple"] s16[".f = Xexit"] s17([".i = 0"]) end %% style simple fill:none,stroke-width:0pxFootnotes
Section titled “Footnotes”-
このコマンドはマニュアルに載ってないので詳細が分からないが関数ファイルを読んでそう ↩