Forthの面白さは、BEGIN AGAINやIF ELSE THENなどの制御構造のコンパイルもForthで書かれているところだと思う。
F83の場合、SEEでデコンパイル出来るし、VIEW BEGIN や VIEW IF として、制御用のワードの定義を見ることが出来る。
BEGIN AGAINの例 (無限ループ)
: TEST 0 BEGIN 1 + DUP . AGAIN ;
SEE TEST
: TEST 0 1 + DUP . BRANCH -10 ; ok
→コンパイルすると、BEGIN も AGAIN も消えて単純なBRANCHになっていることがわかる。
制御用のワードBEGINを見てみよう。
VIEW BEGIN すると、KERNEL80.BLK 内の BEGIN の定義を見ることが出来る
1 : BEGIN ?
? 10 : ?
TRUEをスタックに積んで 5 :
なんのことはない。結局TRUEと現在のアドレスをスタックに積んでいるだけ。
AGAINは
10 : AGAIN COMPILE BRANCH ?
BRANCHワードを書き込んで、?
11 : ?
SWAPしてTRUEとアドレスを交換し、?CONDITION
1 : ?CONDITION (S f -- )
2 NOT ABORT" Conditionals Wrong" ;
スタックトップがTRUEじゃなければ、アボート
6 :
スタックトップのアドレスを書き込む
これも結局フラグをチェックして、スタックに積まれていたアドレスに分岐(BRANCH)しているだけなことがわかる。
デコンパイルした結果の下線部分がその結果となっている。
: TEST 0 1 + DUP . BRANCH -10 ; ok
^^^^^^^^^^^^
(注意)
SEEでは分岐先が相対アドレス表記になっているが、実際は絶対アドレスが入っている。
FIG-ForthやF79では実際にも相対アドレスであったが、F83から絶対アドレスに変わっているみたい
制御構造には、BEGIN ... UNTIL もある。これは条件が成立するまでループであるが、
BEGIN AGAINとほとんど変わらない。
9 : UNTIL COMPILE ?BRANCH ?
AGAINのBRANCHが、?BRANCHにかわっただけ。 (?BRANCHはスタックトップが0なら分岐というワード)
F83の場合、SEEでデコンパイル出来るし、VIEW BEGIN や VIEW IF として、制御用のワードの定義を見ることが出来る。
BEGIN AGAINの例 (無限ループ)
: TEST 0 BEGIN 1 + DUP . AGAIN ;
SEE TEST
: TEST 0 1 + DUP . BRANCH -10 ; ok
→コンパイルすると、BEGIN も AGAIN も消えて単純なBRANCHになっていることがわかる。
制御用のワードBEGINを見てみよう。
VIEW BEGIN すると、KERNEL80.BLK 内の BEGIN の定義を見ることが出来る
1 : BEGIN ?
? 10 : ?
TRUEをスタックに積んで 5 :
なんのことはない。結局TRUEと現在のアドレスをスタックに積んでいるだけ。
AGAINは
10 : AGAIN COMPILE BRANCH ?
11 : ?
1 : ?CONDITION (S f -- )
2 NOT ABORT" Conditionals Wrong" ;
スタックトップがTRUEじゃなければ、アボート
6 :
これも結局フラグをチェックして、スタックに積まれていたアドレスに分岐(BRANCH)しているだけなことがわかる。
デコンパイルした結果の下線部分がその結果となっている。
: TEST 0 1 + DUP . BRANCH -10 ; ok
^^^^^^^^^^^^
(注意)
SEEでは分岐先が相対アドレス表記になっているが、実際は絶対アドレスが入っている。
FIG-ForthやF79では実際にも相対アドレスであったが、F83から絶対アドレスに変わっているみたい
制御構造には、BEGIN ... UNTIL もある。これは条件が成立するまでループであるが、
BEGIN AGAINとほとんど変わらない。
9 : UNTIL COMPILE ?BRANCH ?
AGAINのBRANCHが、?BRANCHにかわっただけ。 (?BRANCHはスタックトップが0なら分岐というワード)