OpenBoot 3.x コマンド・リファレンスマニュアル

制御コマンド

以降の各項では、Forth プログラム内の実行フローの制御用のワードについて説明します。

if...else...then 構造

ifelsethen の 各コマンドは組み合わされて単純な制御構造を作ります。

表 4-28に条件付き実行フロー制御用のコマンドを示します。

表 4-28 if...else...then コマンド

コマンド 

スタックダイアグラム 

説明 

if

( flag -- ) 

flag が true の場合、このコマンドの後のコードを実行します。

else

( -- ) 

flag が false の場合、このコマンドの後のコードを実行します。

then

( -- ) 

ifelsethen を終了します。

これらのコマンドの書式は次のとおりです。


flag if
	(true の場合これを実行)
then	
(通常どおりに実行を継続

または


flag if
	(true の場合これを実行)
else
	(false の場合これを実行)
then	
(通常どおりに実行を継続)

if コマンドはスタックからフラグを 1 つ「消費」します。そのフラグが true (ゼロ以外) であれば、if の後のコマンドが実行されます。true でなければ、(存在する場合) else の後のコマンドが実行されます。


ok : testit  (n -- ) 
] 5 >  if  ." good enough " 
] else  ." too small " 
] then 
] ." Done. "  ; 
ok
ok 8 testit
good enough Done. 
ok 2 testit 
too small Done. 
ok 


注 -

] プロンプトは、それが現れる間は、新しいコロン定義の作成の途中であることをユーザーに示します。このプロンプトはセミコロンを入力して定義を終了すると ok に戻ります。


case

高水準の case コマンドが、複数の候補のなかから代替実行フローを選択するために用意されています。このコマンドの方が、深く入れ子になった ifthen コマンドよりも読みやすいという利点があります。

表 4-29に条件付き case コマンドを示します。

表 4-29 case 文コマンド

コマンド 

スタックダイアグラム 

説明 

case

( selector -- selector )  

caseendcase 条件付き構造を開始します。

endcase

( selector -- ) 

caseendcase 条件付き構造を終了します。

endof

( -- ) 

caseendcase 条件付き構造内の ofendof 句を終了します。

of

( selector test-value -- selector | {empty} ) 

case 条件付き構造内の ofendof 句を開始します。

次に case コマンドの使用例を示します。


ok : testit  (testvalue -- )
]	case
]		0  of  ." It was zero "     endof 
]		1  of  ." It was one "	     endof 
]		ff of  ." Correct "     endof 
]		-2 of  ." It was minus-two "	     endof 
]		(default )  ." It was this value: "  dup . 
]	endcase   ." All done."  ; 
ok
ok 1 testit
It was one All done.
ok ff testit
Correct All done.
ok 4 testit
It was this value: 4 All done.
ok 


注 -

(省略可能な) default 句はまだスタックにあるテスト値を使用できますが、その値を削除してはなりません (.でなくdup . を使用してください)。of 句が正常に実行されれば、テスト値はスタックから自動的に削除されます。


begin ループ

begin ループは、特定の条件が満たされるまで、同じコマンドの実行を繰り返します。そのようなループのことを条件付きループといいます。

表 4-30に条件付きループの実行制御用のコマンドを示します。

表 4-30 begin (条件付き) ループコマンド

コマンド  

スタックダイアグラム 

説明 

again

( -- ) 

beginagain 無限ループを終了します。

begin

( -- ) 

Begin a beginwhilerepeatbeginuntil、または beginagain ループを開始します。

repeat

( -- ) 

beginwhilerepeat ループを終了します。

until

( flag -- ) 

flag が true である間、 beginuntil ループの実行を続けます。

while

( flag -- ) 

flag が true の間、 beginwhilerepeat ループの実行を続けます。

次に 2 つの一般的な形式を示します。


begin any commands flag until

および


begin any commands flagwhile
more commands	 repeat

上の両方の場合とも、所定のフラグ値によってループが終了させられるまで、ループ内のコマンドが繰り返し実行されます。ループが終了すると、通常、実行はループを閉じているワード (until または repeat) の後のコマンドに継続されます。

beginuntil の場合は、until がスタックの一番上からフラグを削除してそれを調べます。フラグが false の場合は、実行は begin のすぐ後に引き継がれて、ループが繰り返されます。フラグが true の場合は、実行はループから抜け出ます。

beginwhilerepeat の場合は、whileがスタックの一番上からフラグを削除して調べます。フラグが true の場合は、while のすぐ後のコマンドが実行されてループが繰り返されます。repeat コマンドは制御を自動的に begin に戻してループを継続させます。while が現れたときにフラグが false であった場合は、実行はただちにループから抜け出し、制御がループを閉じている repeat の後の最初のコマンドに移ります。

これらのループのいずれについても、「true ならば通り過ぎる」と覚えると忘れないでしょう。

次に簡単な例を示します。


ok begin 4000 c@ . key? until     (任意のキーが押されるまで繰り返す)
43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43
ok 

この例では、ループはまずメモリー位置 4000 から 1 バイトを取り出して表示します。次に、key? コマンドが呼び出され、これが、ユーザーがそれまでにどれかのキーを押していれば true をスタックに残し、そうでない場合は false を残します。このフラグは until によって「消費」され、その値が false であった場合は、ループが繰り返されます。キーを押せば、次に呼び出されたとき、key?true を返し、したがってループは終了します。

Forth の多くのバージョンとは異なり、このユーザーインタフェースの場合は、ループや条件付き制御構造を対話的に使用できます。つまり、まず最初に定義を作成する必要がありません。

do ループ

do ループ (カウント付きループとも呼ばれます) は、ループの繰り返し回数があらかじめ計算できるときに使用します。do ループは、通常、指定した終了値に達する直前に終了します。

表 4-31にカウント付きループの実行制御用コマンドを示します。

表 4-31 do (カウント付き) ループコマンド

コマンド  

スタックダイアグラム 

説明 

+loop

( n -- ) 

do+loop 構造を終了します。ループインデックスに n を加算し、do に戻ります (n < 0 の場合は、インデックスは start から end まで使用されます)。

?do

( end start -- ) 

?doloop の 0 回またはそれ以上の実行を開始します。インデックスは start から end-1 まで使用されます。end = start の場合はループは実行されません。

?leave

( flag -- ) 

flag がゼロ以外の場合、doloop から抜けます。

do

( end start -- ) 

doloop を開始します。インデックスは start から end-1 まで使用されます。

例: 10 0 do i . loop ( 0 1 2...d e f と出力します。)

i

( -- n ) 

ループインデックスをスタックに残します。 

j

( -- n ) 

1 つ外側のループのループインデックスをスタックに残します。 

leave

( -- ) 

doloop から抜けます。

loop

( -- ) 

doloop を終了します。

次の画面で、ループの使用方法をいくつか示します。


ok 10 5 do i .  loop 
5 6 7 8 9 a b c d e f
ok
ok 2000 1000 do i .  i c@ . cr   i c@ ff = if leave then  4 +loop 
1000 23
1004 0
1008 fe
100c 0
1010 78
1014 ff
ok : scan (byte -- ) 
]    6000 5000
     (5000 〜 6000 のメモリー領域を走査して指定のバイト値に
      一致しないバイトを調べる)
]    do dup i c@ <> (byte error? ) 
]     if i . then  (byte ) 
]     loop 
]     drop (the original byte was still on the stack, discard it ) 
]  ; 
ok 55 scan 
5005 5224 5f99 
ok 6000 5000 do i i c! loop
     (メモリー領域にステップパターンを埋め込む)
ok       
ok 500 value testloc 
ok : test16 (-- ) 1.0000 0 (do 0-ffff )
     (指定位置に異なる 16 ビット値を書き込む)
]     do i testloc w! testloc w@ i <> (error? )     (さらに位置をチェック)
]       if ." Error - wrote " i . ." read " testloc w@ . cr 
]        leave (exit after first error found )     (この行は省略可能)
]       then 
]     loop 
]  ; 
ok test16 
ok 6000 to testloc 
ok test16 
Error - wrote 200 read 300 
ok 

ok 10 5 do i .  loop 
5 6 7 8 9 a b c d e f
ok
ok 2000 1000 do i .  i c@ . cr   i c@ ff = if leave then  4 +loop 
1000 23
1004 0
1008 fe
100c 0
1010 78
1014 ff
ok : scan (byte -- ) 
]    6000 5000
     (5000 〜 6000 のメモリー領域を走査して指定のバイト値に
      一致しないバイトを調べる)
]    do dup i c@ <> (byte error? ) 
]      if i . then  (byte ) 
]    loop 
]    drop (the original byte was still on the stack, discard it ) 
]  ; 
ok 55 scan 
5005 5224 5f99 
ok 6000 5000 do i i c! loop
     (メモリー領域にステップパターンを埋め込む)
ok       
ok 500 value testloc 
ok : test16 (-- ) 1.0000 0 (do 0-ffff )
     (指定位置に異なる 16 ビット値を書き込む)
]     do i testloc w! testloc w@ i <> (error? )     (さらに位置をチェック)
]       if ." Error - wrote " i . ." read " testloc w@ . cr 
]        leave (exit after first error found )     (この行は省略可能)
]       then 
]     loop 
]  ; 
ok test16 
ok 6000 to testloc 
ok test16 
Error - wrote 200 read 300 
ok 

その他の制御コマンド

表 4-32に、前記以外のプログラム実行制御用のコマンドについて説明します。

表 4-32 プログラム実行制御コマンド

コマンド 

スタックダイアグラム 

説明 

abort

( -- ) 

現在の実行を終了させ、キーボードコマンドを解釈します。 

abort" ccc"

( abort? -- ) 

abort? が true の場合は、実行を終了させてメッセージを表示します。

eval

( addr len -- ) 

addr len から Forth のソースを解釈します。 

execute

( xt -- ) 

実行トークンがスタックにあるワードを実行します。 

exit

( -- ) 

現在のワードから復帰します (カウント付きループでは使用できません)。 

quit

( -- ) 

スタック内容をまったく変えない点を除いて、 abort と同じです。

abort はプログラムの実行を即時に終了させ、制御をキーボードに返します。abort" は 2 点を除いて abort と同じです。第 1 点は、フラグが true の場合にスタックからフラグを削除し、その後は何もしないで強制終了させることです。もう 1 点は、強制終了が行われたとき、なんらかのメッセージを表示することです。

eval は (アドレスと長さにより指定された) 文字列をスタックから取り出します。次に、キーボードから入力される場合と同様に、その文字列の文字が解釈されます。Forth のテキストファイルをメモリーに読み込んでいる (第 5 章「プログラムの読み込みと実行」を参照) 場合は、eval を使用してそのファイル内の定義をコンパイルできます。