§ 8.2. 分割コンパイル例
前節のシナリオに従い,乱数を使うおみくじプログラムを例に,分割コ ンパイルをして実行形式ファイルを作ってみましょう. システムを
-
random:乱数発生器
-
main:メインパート
に分割することにします. まず,このインターフェイスファイルを以下のように設計します.
-
random.smiの定義.
structure Random =
struct
val intit : int * int -> unit
val genrand : unit -> int
endこのインターフェイスファイルは,このインターフェイスファイルを実 装するソースファイルが,他のファイルは参照せずにRandom structureを提 供することを表しています.
-
main.smiの定義.
_require "basis.smi"
_require "./random.smi"このインターフェイスファイルは,SML#の基本ライブラリ"basis.smi"(The Standard ML Basis Library)とこのディレクトリにある random.smiを利用し,外部には何も提供しないことを意味しています.
このインターフェイスを使えば,main.smlとrandom.smlを独 立に開発できます. main.smlは図8.1のように定義できます. このファイルは,random.smiを実装するソースファイルが存在し なくても,コンパイルしエラーがないか確認することができます.
$ smlsharp -c main.sml
-cはSML#コンパイラにコンパイルしオブジェクトファイ
ルを生成を指示します.
対話型での使用と同様に型チェックをした後,エラーがなければ,
オブジェクトファイルmain.oを作ります.
インターフェイスファイルは,ファイル名の.smlを.smiに変
えたものが自動的に使用されます.
ソースコード冒頭に_interface
次に,random.smlを開発します. 高品質の乱数発生関数の開発は,数学的な知識と注意深いコーディング が要求されます. ここでは,これはスクラッチから開発するのではなく,既存のCでの実 装を使うことにします. 種々ある乱数発生アルゴリズムの中で,その品質と速度の両方の点から Mersenne Twisterが信頼できます. このアルゴリズムはCのソースファイルmt19937ar.cとして提供されています.
そこでこのファイルをダウンロードしましょう. インターネットでMersenne Twisterあるいはmt19937ar.cをサーチすれば簡単に見つけることができます. このファイルには以下の関数が定義されています.
void init_genrand(unsigned long s)
void init_by_array(unsigned long init_key[], int key_length)
unsigned long genrand_int32(void)
long genrand_int31(void)
double genrand_real1(void)
double genrand_real2(void)
double genrand_real3(void)
double genrand_res53(void)
int main(void)
この中のmainは,このアルゴリズムをテストするためのメイン関 数です. 我々は新たな実行形式プログラムを作成するので,main関数は, 我々のトップレベルファイルmain.smlをコンパイルしたオブジェクトファ イルに含まれているはずです. そこで,mt19937ar.cファイルの関数int main(void)の定 義をコメントアウトする必要があります. その他の関数は,SML#から利用できるライブラリ関数です. ここでは以下の2つを使うことにします.
-
void init_genrand(unsigned long s). シーズの長さを受け取りアルゴリズムを初期化する関数です. シーズsは非負な整数ならなんでも構いません.
-
long genrand_int31(void).初期化された後は,呼ばれる毎に31ビッ トの符号なし整数(32ビット非負整数)のランダムな列を返します.
そこで,これを利用して,random.smlを以下のように定義します.
structure Random =
struct
val init = _import "init_genrand" : int -> unit
val genrand = _import "genrand_int31" : unit -> int
end
このソースファイルも,以下のコマンドにより,このファイルだけで単 独にコンパイルできます.
$ smlsharp -c random.sml
このソースファイルの定義と並行して,(main関数をコメントア ウトした)Mersenne Twisterをコンパイルし,オブジェクトファイルを生 成しておきます.
$ gcc -c -o mt.o mt19937ar.c
以上ですべてのソースファイルがそれぞれコンパイルされ,オブジェク トファイルが作られたはずです. それらオブジェクトファイルは,トップレベルのインターフェイスファ イルと必要なオブジェクトファイルを指定することによって,実行形式ファイル が作成されます.
$ smlsharp main.smi mt.o
SML#コンパイラは,smiファイルを解析し,このファイル から参照されているsmiファイルを再帰的にたどり,対応するオブジェク トファイルのリストを作り,コマンドラインに指定されたC言語のオブジェクト ファイルと共に,システムのリンカーを起動し,実行形式ファイルを作成します.
fun main() = |