CL

198. CLPは配列を使えるか?

CLPで配列は使えるか? という問いに対して
AIは次のようなポインタを使うエレガントな手法を
提案してきた。

PGM
    /* 10バイトの要素が15個詰まった 150バイトの連続データ */
    DCL VAR(&LIST)    TYPE(*CHAR) LEN(150)
    /* ポインター変数(&LIST の先頭アドレスを保持) */
    DCL VAR(&PTR)     TYPE(*PTR)  ADDRESS(&LIST)
    /* ポインターが指す現在のアドレスの要素(10バイト) */
    DCL VAR(&ELEM)    TYPE(*CHAR) LEN(10) STG(*BASED) BASPTR(&PTR)
    /* ループカウンター */
    DCL VAR(&IDX)     TYPE(*INT)  LEN(4)

    /* 例: 配列要素を順に処理するループ */
    DOFOR VAR(&IDX) FROM(1) TO(15)
        /* &ELEM を参照または更新 */
        /* 例: CHGVAR VAR(&ELEM) VALUE('ITEM_' *CAT %CHAR(&IDX)) */

        /* 次の要素へポインターを 10バイト進める */
        CHGVAR VAR(%OFS(&PTR)) VALUE(%OFS(&PTR) + 10)
    ENDDO
ENDPGM

[解説]

おわかり頂けるだろうか?
これはAIが提案してきたCLPソースであり一切、手は加えていない。
最初に定義したポインタ: &PTR は

/* ポインター変数(&LIST の先頭アドレスを保持) */
    DCL VAR(&PTR)     TYPE(*PTR)  ADDRESS(&LIST)

と定義されているので150バイトの &LIST の先頭を
示している。
ところで変数: &ELEM はこのポインタ &PTRをベースとして
定義される変数であって

/* ポインターが指す現在のアドレスの要素(10バイト) */
    DCL VAR(&ELEM)    TYPE(*CHAR) LEN(10) STG(*BASED) BASPTR(&PTR)

のように定義されている。

BASPTR(&PTR) としてポインタ : &PTRをベースとしているので
&PTR が変わるとそれに応じて &ELEMの変数も変わるというわけである。

/* 10バイトの要素が15個詰まった 150バイトの連続データ */
    DCL VAR(&LIST)    TYPE(*CHAR) LEN(150)

/* 例: 配列要素を順に処理するループ */
    DOFOR VAR(&IDX) FROM(1) TO(15)
   :
  (この中で &ELEMの値は &LISTの始めから 1バイト目、10バイト目,...と変わる)
      :
    /* 次の要素へポインターを 10バイト進める */
        CHGVAR VAR(%OFS(&PTR)) VALUE(%OFS(&PTR) + 10)
    ENDDO

で15回LOOPするのであるが &ELEMの開始位置は 1, 10, 20, ….と変化していく。
ポインタも加算することができるという事実を使ったテクニックである。
このような手法はC言語では日常的によくある手法でめずらしくはないが
CLPで同じような手法を使っていることに新しさがある。
ひれを提案したAIは自らのこの手法をエレガントと自画自賛していた。