nptのドキュメントです。
参照元:ANSI Common Lisp npt
前へ:スタートアップ
Paperオブジェクトは、npt固有のデータ形式です。
vector
のような一次元配列と、byte形式の配列データを同時に保有することができます。
nptの実装に合ったオブジェクトを作成するため、 メモリ空間に対して効率がよいという利点があります。
本オブジェクトは、主にC言語上で使用することを目的としています。
例えば、Common Lispのヒープ上に独自のデータを格納するような場合に便利です。
操作関数はC言語とCommon Lispのどちらのものも用意されています。
nptのオブジェクトは、下記の3つのいずれかの形で表されます。
array形式は一次元simple-vector
と同じです。
body形式は、バイト単位のバッファ領域を保有します。
array-body形式は、array形式とbody形式を組み合わせたものです。
array-body形式には制限があり、arrayとbodyのサイズをどちらも#xFFFF
以下にしなければなりません。
それ以上の長さを使いたい場合は、例えばarray形式とbody形式を分けて確保してください。
全てのオブジェクトには、User値と呼ばれる1byteのデータ領域が用意されています。
User値の使い方は自由ですが、Paperオブジェクトを種類分けするために使うことをお勧めします。
User値のデフォルト値は0
です。
array形式の使い方を説明します。
array形式は、一次元general arrayである、simple-vector
と同じです。
作成は次のようにして行います。
0) (make-paper size
第一引数のsize
は配列の要素数です。
例えば、要素数10のPaperを作成する場合は次のようになります。
10 0) (make-paper
初期値は、全要素がnil
です。
配列の値を取得するには、次のように実行します。
(array-paper paper index)
値を設定するには、次のように実行します。
(array-paper paper index value)
下記の実行をvector
の操作と比較してみます。
setq x (make-paper 10 0))
(3)
(array-paper x 3 "Hello") (array-paper x
vector
では次のようにあらわされます。
setq x (make-array 10))
(aref x 3)
(setf (aref x 3) "Hello") (
次に、同じことをC言語で行います。
オブジェクトの作成は次の関数を使用します。
int lisp_paper_(addr x, size_t array, size_t body);
実行例を示します。
static int main_call_(void)
{
;
addr x
= Lisp_hold();
x if (lisp_paper_(x, 10, 0))
return 1;
return 0;
}
int main_lisp(void *ignore)
{
;
addr control
(&control);
lisp_push_control(void)main_call_();
return lisp_pop_control_(control);
}
正しく実行するには上記のようにする必要があるのですが、 説明するうえでは不要のため、 戻り値の判定を省略して次のようにあらわします。
;
addr x
= Lisp_hold();
x (x, 10, 0); lisp_paper_
配列の取得と設定は下記の関数を使用します。
int lisp_paper_getarray_(addr x, addr pos, size_t index);
int lisp_paper_setarray_(addr x, size_t index, addr value);
次の例文をC言語で表してみます。
setq x (make-paper 10 0))
(3)
(array-paper x 3 "Hello") (array-paper x
, v;
addr x
= Lisp_hold();
x = Lisp_hold();
v (x, 10, 0);
lisp_paper_(v, x, 3);
lisp_paper_getarray_(v, "Hello");
lisp_string8_(x, 3, v); lisp_paper_setarray_
body形式の使い方を説明します。
body形式は、(unsigned-byte 8)
形式の 一次元specialized arrayと同じです。
作成は次のようにして行います。
0 size) (make-paper
第二引数のsize
は確保するバッファのバイト数です。
例えば、10byteのPaperを作成する場合は次のようになります。
0 10) (make-paper
初期値は不定です。
array形式とは違い、body形式は値の内容を初期化しません。
もし初期化が必要な場合は:fill
引数を使用します。
下記の例では、確保したbody部の#x00
で初期化します。
0 10 :fill t) (make-paper
または、次のように初期値を指定できます。
0 10 :fill #xFF) (make-paper
値の範囲は0
~#xFF
の間になります。
配列の値を取得するには、次のように実行します。
(body-paper paper index)
返却される値は、0
~#xFF
の整数です。
値を設定するには、次のように実行します。
(body-paper paper index value)
value
は、0
~#xFF
の整数である必要があります。
バッファの取得と設定は下記の関数を使用します。
int lisp_paper_getbody_(addr x, size_t index, byte *ret);
int lisp_paper_setbody_(addr x, size_t index, byte value);
次の例文をC言語で表してみます。
setq x (make-paper 0 10))
(3)
(body-paper x 3 #xFF) (body-paper x
;
byte value;
addr x
= Lisp_hold();
x (x, 0, 10);
lisp_paper_(x, 3, &value);
lisp_paper_getbody_(x, 3, 0xFF); lisp_paper_setbody_
array-body形式の使い方を説明します。
(make-paper size1 size2)
第一引数のsize1
は、array配列の個数です。
第二引数のsize2
は、bodyバッファのバイト数です。
例えば、arrayが10要素、bodyが20byteのPaperを作成する場合は次のようになります。
10 20) (make-paper
array-body形式を作成する場合は、 size1
, size2
どちらの値も#xFFFF
以下にしてください。
違反した場合はsimple-error
conditionが発生します。
info-array
関数info-array
関数は、Paperオブジェクトに対して、下記の操作を行います。
User値とはオブジェクトが保有する1byteの情報です。
取得はinfo-paper
関数に、type
を指定します。
setq x (make-paper 3 4))
(0 #x801699220>
-> #<PAPER
(info-array paper 'type)0 ->
User値は、make-array
の:type
引数で指定できます。
setq x (make-paper 3 4 :type 123))
(123 #x80169b258>
-> #<PAPER
(info-paper x 'type)123 ->
または、info-array
の引数にて設定できます。
100)
(info-paper x 'type 100
->
(info-paper x 'type)100
->
x100 #x80169b258> -> #<PAPER
C言語では、下記の関数を使用します。
int lisp_paper_gettype_(addr x, byte *ret);
int lisp_paper_settype_(addr x, byte value);
実行例を示します。
;
byte value;
addr x
= Lisp_hold();
x (x, 0, 10);
lisp_paper_(x, 123);
lisp_paper_settype_(x, &value);
lisp_paper_gettype_("%d\n", (int)value); printf
arrayとbodyの内容は、list
かvector
形式で取得できます。
arrayの内容を取得してみます。
取得はinfo-paper
関数に、list
かvector
を指定します。
setq x (make-paper 3 4 :fill 7))
(0 #x80174f258>
-> #<PAPER
(info-paper x 'list)
-> (NIL NIL NIL)
(info-paper x 'vector) -> #(NIL NIL NIL)
bodyの内容を取得する場合は、info-paper
の第三引数にt
を指定します。
setq x (make-paper 3 4 :fill 7))
(0 #x801752c28>
-> #<PAPER
t)
(info-paper x 'list 7 7 7 7)
-> (
t)
(info-paper x 'vector 7 7 7 7) -> #(
なお、body部のvector
は、 (unsigned-byte 8)
のspecialized array形式で返却されます。
arrayとbodyの長さを取得します。
取得はinfo-paper
関数に、length
を指定します。
setq x (make-paper 3 4))
(0 #x801756418>
-> #<PAPER
(info-paper x 'length)3
->
t)
(info-paper x 'length 4 ->
C言語では、下記の関数を使用します。
int lisp_paper_lenarray_(addr x, size_t *ret);
int lisp_paper_lenbody_(addr x, size_t *ret);
実行例を示します。
;
addr xsize_t array, body;
= Lisp_hold();
x (x, 5, 6);
lisp_paper_(x, &array);
lisp_paper_lenarray_(x, &body);
lisp_paper_lenbody_("%d, %d\n", (int)array, (int)body); printf
下記の内容について説明します。
compile-file
の扱いPaperオブジェクトは、npt内においては通常のLispオブジェクトです。
eval
で評価できますし、型も持っています。
型の評価は下記のようにして行います。
typep x 'npt-system::paper) (
built-in-class
のクラスも存在します。
find-class 'npt-system::paper)
( -> #<BUILT-IN-CLASS PAPER>
compile-file
の扱いPaperオブジェクトは、compile-file
で保存できます。
array部分はvector
オブジェクトと同様に扱われます。
body部分は、バッファの内容をそのままfaslファイルに書き込みます。
User値も同様に保存されます。
下記の関数が用意されています。
int lisp_paper_getmemory_(addr x, size_t a, size_t b, void *output, size_t *ret);
int lisp_paper_setmemory_(addr x, size_t a, size_t b, const void *input, size_t *ret);
lisp_paper_getmemory_
は、body部の内容を一括して取得します。
lisp_paper_setmemory_
は、body部の内容を一括して設定します。
引数a
とb
はbody部の位置を表し、a
番目からb
番目直前までの内容を示します。
subseq
関数と同様、b
番目の位置は含まれません。
a
番目から開始し、(- b a)
byte分の内容を処理します。
a
とb
の値は、body部のサイズを超えていてもかまいません。
処理されたバイト数は、引数ret
に格納されます。
引数ret
がNULL
の場合は無視されます。