14.8 トップレベルの実行
SML#プログラムの実行は, .smlファイルの トップレベルに書かれた val宣言を上から順に評価することで行われます. ひとつのプログラムが複数の .smlファイルからなるとき, どのファイルのトップレベルが どの順番で実行されるかは,自明ではありません. SML#では,各.smlファイルのトップレベルの実行 順序を,以下の規則に従って決定します.
-
1.
リンク時にsmlsharpコマンドに指定した.smiファイルに 対応する.smlファイルのトップレベルは必ず最後に実行されます. この条件は以下のどの条件よりも優先されます. 以下,この条件に合致する.smlファイルのトップレベルを リンクトップレベルと呼びます.
-
2.
A.smlがProvideしている変数を B.smlが使用しているとき, A.smlのトップレベルはB.smlのトップレベルより 先に実行されます.
-
3.
定義-使用関係に無い2つの.smlファイルの トップレベルの実行順序は不定です.
-
4.
A.smlが何もProvideしていないか, あるいはリンクトップレベルから変数の定義-使用関係を辿って A.smlに到達できない場合, A.smlのトップレベルは実行されません (SML#コンパイラはA.oをリンクしません).
トップレベルの実行順序およびリンクされるオブジェクトファイルの 集合は,_requireによって決まるのではなく, ファイル間での変数の定義-使用関係によって決まることに注意してください. たとえA.smiが他の.smiファイルから_require されていたとしても,A.smiがProvideする変数をどの.smlファイル も使用していなければ,A.smlのオブジェクトファイルA.oは リンクされません. 従って, 例えばprintしかしない.smlファイルなど, 副作用のあるトップレベルコードだけからなり何もProvideしない .smlファイルは, リンクも実行もされません.
例外は2つあります. ひとつはリンクトップレベルです. リンクトップレベルは必ず実行されます. もうひとつは,Require宣言を
_require init
と書くことです. .smiに_require ".smi" initと書かれている場合, 変数の定義-参照関係にかかわらず,.smiのトップレベルが.smiの トップレベルより先に実行されます. ただし,この書き方は特殊な用途に使用すべきものであり,常用は 推奨されません. 従って,プログラムの初期化時に必ず実行されなければならない printや配列の破壊的更新は, リンクトップレベルで行うか, リンクトップレベルから呼び出される関数で行うようにしてください.