Data objectに関してはinclude/klic/gdobject.h, include/klic/gd_macro.h 中に定義されたマクロを用いて記述する。
struct {
struct data_object_method_table *method_table;
double value;
};
という型である。これを定義するのに、
GD_OBJ_TYPE {
struct data_object_method_table *method_table;
double value;
};
とする。各々、メソッド表ポインタ、浮動小数点の値、である。
以下でメソッドの説明をする。データオブジェクトのメソッドは``GDDEF_'' で開始されるマクロにより行われている。
をメソッドの返り値としている。
Float型では、まず、メソッドテーブル同士を同じかどうか比較し、 その後、value部分を比較している。
PRINTメソッドはGD_RETURN_FROM_PRINTにてreturnする必要がある。
なお、KLICのGCは幅優先ではなく、深さ優先の順で データのコピーを行う。よっていわゆる``scan''は行わず、 ジェネリック・オブジェクト内部で保持しているタグのないデータも 上手く扱うことができる。
メソッドでは、コピー先ヒープのヒープ割付点へのポインタを引数に持つ。 自分のサイズに従って、コピー先ヒープ上に領域を確保し(ヒープ割付点を進める)、 その自分をそこへコピーする。 メソッドの返り値はコピー後のヒープ割付点へのポインタを返す。
gfloatでは、value部が8byte alignされている必要がある場合が多いため、 alignを合せるためヒープを進めている。
これらのメソッド の他に、ユーザが自由に定義し、ジェネリック・オブジェクトを任意の時 点で任意に操作するための様々なメソッドが定義できる。 例えば、floatでは、各種の演算が行えなければ、 floatを実装する意味はあまりない。 このような、オブジェクトに依存するようなメソッドをジェネリック・メソッドと 呼ぶ。
ジェネリック・メソッドにはガード用とボディ用があり、 2 つ (1 つのジェネリック・オブジェクトクラス当たり 2 つ) のメソッドとして 実装される。 ジェネリック・メソッドを呼ぶ時には、そのメソッド群の中の 1 メソッド を指定するメソッド記述子を引数として呼ぶことで、 実行したいメソッドを指定する。
Body generic メソッドは、以下の2種より構成される。
前者はGDDEF_METHOD(メソッド名_アリティ)として定義される。 後者は、GDDEF_GENERICにより定義される。floatの場合を例にして基本的な処理を 以下で説明する。
その結果、case 1(アリティが1)、 case 2(アリティが2)の場合で各々 GD_SWITCH_ON_METHOD により再度dispatchしている。 その結果行うべき処理を GD_METHOD_CASE_DIRECTで記述する。別にGDDEF_METHODに より定義せずに、直接記述する(単順な処理の場合にはそのような 記述が適当であろう)場合にはこの記述が便利である。
引数は、メソッド記述子およびジェネリック・メソッド引数である。 このメソッドはガードゴールに相当する。 メソッドを実行した結果は成功/失敗/中断のいずれかになるが、 それは戻り値により表現する(GENERIC_SUCCEEDED 成功、 GENERIC_FAILED: 失敗、それ以外: 中断の原因となった変数への参照)。 詳細はinclude/klic/generic.h のguard_genericマクロを参照のこと。
new ルーチンは、ジェネリック・メソッドと同様に、コンパイルされた実行 時ルーチンから呼ばれ得るルーチンである。 また、newルーチンに引数としてデータを渡すことも可能である。 これを new ルーチン引数と呼ぶことにする。
このルーチンは引数として、newルーチン引数とそのサイズおよび ヒープ割付点へのポインタを取る。 ヒープ上に領域を取り、そこにジェネリック・オブジェクトを生成する。 新たなヒープ割付点をルーチンの返り値として返す。