Next: , Previous: , Up: Control Structures   [Contents][Index]


6.9.3 Counted Loops

基本のカウント・ループ:

limit start ?DO
  body
LOOP

これは、 start から始まり limit まで(limit 自身は除く)、 各整数値に対して 1 回の反復を実行します。 カウンタ、 つまりインデックスには、 i を使用してアクセスできます。 たとえば、 以下のループをご覧ください:

10 0 ?DO
  i .
LOOP

出力: 0 1 2 3 4 5 6 7 8 9

最も内側のループのインデックスには i を使用してアクセスでき、 その一つ外側のループのインデックスには j を使用してアクセスでき、 さらにもう一つ外側のループのインデックスには k を使用してアクセスできます。

i' を使用すると最も内側のループの limit にアクセスでき、 delta-i を使用すると i' - i にアクセスできます。

: foo 7 5 ?do cr i . i' . delta-i . loop ; 

出力:

5 7 2 
6 7 1

ループ制御データはリターン・スタックに保持されるため、 リターン・スタックへのアクセスとカウント・ループ・ワードの混在にはいくつかの制限があります。 特に、ループの外側のリターン・スタックに値を置いた場合、 ループ内で値を読み取る事はできません12。 ループ内のリターン・スタックに値を置く場合は、 ループの終了前、 およびループのインデックスにアクセスする前に値を削除する必要があります。

カウント・ループにはいくつかのバリエーションがあります:

カウント・ループ・ワード群:

?DO ( compilation – do-sys ; run-time w1 w2 – | loop-sys  ) core-ext “question-do”

See Counted Loops.

+DO ( compilation – do-sys ; run-time n1 n2 – | loop-sys  ) gforth-0.2 “plus-do”

See Counted Loops.

U+DO ( compilation – do-sys ; run-time u1 u2 – | loop-sys  ) gforth-0.2 “u-plus-do”

See Counted Loops.

bounds ( addr u – addr+u addr ) gforth-0.2 “bounds”

開始アドレス addr と長さ u で表されるメモリ・ブロックを指定すると、 u+do または ?do の終了アドレス addr+u と開始アドレス addr を正しい順序で生成します。

-[do ( compilation – do-sys ; run-time n1 n2 – | loop-sys  ) gforth-experimental “minus-bracket-do”

負の方向へカウントされるループを開始します。 n2<n1 の場合、 ループをスキップします。 このようなカウント・ループは、 増分が負である +loop と対になります。 I>=n1 である限り実行されます。

u-[do ( compilation – do-sys ; run-time u1 u2 – | loop-sys  ) gforth-experimental “u-minus-bracket-do”

負の方向へカウントするループを開始します。 u2<u1 の場合、ループをスキップします。 このようなカウント・ループは、 増分が負の +loop と対になります。 I>=u1 である限り実行されます。

-DO ( compilation – do-sys ; run-time n1 n2 – | loop-sys  ) gforth-0.2 “minus-do”

See Counted Loops.

U-DO ( compilation – do-sys ; run-time u1 u2 – | loop-sys  ) gforth-0.2 “u-minus-do”

See Counted Loops.

array>mem ( uelements uelemsize – ubytes uelemsize) \ ubytes は uelements * uelementsize です

mem+do ( compilation – w xt do-sys; run-time addr ubytes +nstride –  ) gforth-experimental “mem-plus-do”

Iaddr から開始し、 I<addr+ubytes である限り、 nstride 幅のステップでメモリ内をアドレスが増える方向にカウント・アップするカウント・ループを開始します。 loop と対にする必要があります。

mem-do ( compilation – w xt do-sys; run-time addr ubytes +nstride –  ) gforth-experimental “mem-minus-do”

Iaddr+ubytes-ustride として開始し、 I>=addr である間 -nstride 幅のステップでメモリをアドレス下位方向(backward)にステップするカウント・ループを開始します。 loop と対にしなければなりません。

DO ( compilation – do-sys ; run-time w1 w2 – loop-sys  ) core “DO”

See Counted Loops.

FOR ( compilation – do-sys ; run-time u – loop-sys  ) gforth-0.2 “FOR”

See Counted Loops.

LOOP ( compilation do-sys – ; run-time loop-sys1 – | loop-sys2  ) core “LOOP”

See Counted Loops.

+LOOP ( compilation do-sys – ; run-time loop-sys1 n – | loop-sys2  ) core “plus-loop”

See Counted Loops.

-LOOP ( compilation do-sys – ; run-time loop-sys1 u – | loop-sys2  ) gforth-0.2 “minus-loop”

See Counted Loops.

NEXT ( compilation do-sys – ; run-time loop-sys1 – | loop-sys2  ) gforth-0.2 “NEXT”

See Counted Loops.

i ( R:n – R:n n ) core “i”

n は、最も内側のカウント・ループのインデックスです。

j ( R:n R:w1 R:w2 – n R:n R:w1 R:w2 ) core “j”

n は、 最も内側から数えて 2 番目のカウント・ループのインデックスです。

k ( R:n R:w1 R:w2 R:w3 R:w4 – n R:n R:w1 R:w2 R:w3 R:w4 ) gforth-0.3 “k”

n は、 最も内側から数えて3番目のカウント・ループのインデックスです。

i' ( R:w R:w2 – R:w R:w2 w ) gforth-0.2 “i-tick”

最も内側のカウント・ループの limit

delta-i ( r:ulimit r:u – r:ulimit r:u u2 ) gforth-1.0 “delta-i”

u2=I'-I (limit とインデックスの差)

LEAVE ( compilation – ; run-time loop-sys –  ) core “LEAVE” 
\ 訳注: LEAVE は、 最も内側のカウンタ付きループを抜け出します。
\       それが関係する LOOP または NEXT の直後から実行を続行します。

See Counted Loops.

?LEAVE ( compilation – ; run-time f | f loop-sys –  ) gforth-0.2 “question-leave” 
\訳注: f が true なら leave します。

See Counted Loops.

unloop ( R:w1 R:w2 – ) core “unloop”
DONE ( compilation do-sys – ; run-time –  ) gforth-0.2 “DONE”

do-sys までのすべての LEAVE を解決します(訳注: loop, +loop , next 等の中で内部的に呼び出されます)。

標準では、 do-sysCS-PICKCS-ROLL を使用することは許可されていません。 MEM+DOMEM-DO によって生成される do-sys を除いて、 Gforth では CS-PICKCS-ROLL の使用を許可しますが、 すべての ?DO などに対して、 定義を介した任意の経路上に UNLOOP が正確に 1 つだけ存在すること(LOOP などの失敗経路上で UNLOOP コンパイルするなど)を確認するのはあなたの仕事です。 また、 すべての LEAVE が(ループ終了ワードの 1 つまたは DONE を使用して)解決されていることを確認する必要があります。


Footnotes

(12)

ええ、まぁ、 移植可能な方法ではできません、 ぐらいな


Next: Begin loops with multiple exits, Previous: Simple Loops, Up: Control Structures   [Contents][Index]