石原 博の覚書

電子工作に関する日々の覚書を記載します

Forthの制御構造(CASEの場合)

2021-05-03 21:23:19 | 日記
今度は逆に CASEを作ってみよう

FORTH DIMENSIONS II/3 の CASE Contest (Dr. Charles E. Eaker) を参考に

このような定義の場合、
: TEST
CASE
1 OF ." ONE" ENDOF
2 OF ." TWO" ENDOF
." OTHER"
ENDCASE ;

以下のようになってほしい
: TEST 1 OVER = ?BRANCH x1 DROP (.") ONE BRANCH x3
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^
CASE OF ENDOF

2 OVER = ?BRANCH x2 DROP (.") TWO BRANCH x3 (.") OTHER DROP ;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^
OF ENDOF ENDCASE

こうするためには、
CASE =>
OF => COMPILE OVER COMPILE = COMPILE ?BRANCH HERE 0 , COMPILE DROP
ENDOF => COMPILE BRANCH HERE 0 , SWAP HERE !
ENDCASE => HERE SWAP ! をすべてのOFに対して繰り返す
すべてのOFに対して繰り返すのは、回数が未定のためCASEで
フラグ(TRUE)を積んで置くことにする。

これらを考慮すると
: CASE TRUE ; IMMEDIATE
: OF COMPILE OVER COMPILE = COMPILE ?BRANCH HERE 0 , COMPILE DROP ; IMMEDIATE
: ENDOF COMPILE BRANCH HERE 0 , SWAP HERE SWAP ! ; IMMEDIATE
: ENDCASE COMPILE DROP BEGIN DUP TRUE <> WHILE
HERE SWAP ! REPEAT DROP ; IMMEDIATE

: TEST CASE 1 OF ." ONE" ENDOF 2 OF ." TWO" ENDOF ." OTHER" ENDCASE ;

確認すると、
SEE TEST
: TEST 1 OVER = ?BRANCH 14 DROP (.") ONE BRANCH 34 2 OVER = ?BRANCH 14
DROP (.") TWO BRANCH 12 (.") OTHER DROP ;

このままでも使えるが、F83らしく
HERE 0 , => >MARK
HERE SWAP ! => >RESOLVE
とすると、
: CASE TRUE ; IMMEDIATE
: OF COMPILE OVER COMPILE = COMPILE ?BRANCH >MARK COMPILE DROP ; IMMEDIATE
: ENDOF COMPILE BRANCH >MARK SWAP >RESOLVE ; IMMEDIATE
: ENDCASE COMPILE DROP BEGIN DUP TRUE <> WHILE
>RESOLVE REPEAT DROP ; IMMEDIATE

さらにチェック用のフラグを入れると
: CASE TRUE ; IMMEDIATE
: OF COMPILE OVER COMPILE = COMPILE ?BRANCH ?>MARK COMPILE DROP ; IMMEDIATE
: ENDOF COMPILE BRANCH ?>MARK 2SWAP ?>RESOLVE ; IMMEDIATE
: ENDCASE COMPILE DROP BEGIN DUP TRUE <> WHILE
?>RESOLVE REPEAT DROP ; IMMEDIATE


https://forth-standard.org/standard/core/CASE にある
テストで動くことが確認出来た。

: cs1 CASE 1 OF 111 ENDOF
2 OF 222 ENDOF
3 OF 333 ENDOF
>R 999 R>
ENDCASE
;

1 cs1 . 111 ok
2 cs1 . 222 ok
3 cs1 . 333 ok
4 cs1 . 999 ok

: cs2 >R CASE
-1 OF CASE R@ 1 OF 100 ENDOF
2 OF 200 ENDOF
>R -300 R>
ENDCASE
ENDOF
-2 OF CASE R@ 1 OF -99 ENDOF
>R -199 R>
ENDCASE
ENDOF
>R 299 R>
ENDCASE R> DROP ;

-1 1 cs2 . 100 ok
-1 2 cs2 . 200 ok
-1 3 cs2 . -300 ok
-2 1 cs2 . -99 ok
-2 2 cs2 . -199 ok
0 2 cs2 . 299 ok

注意
 CASEワードを自分で書くまで気づかなかったが、ForthのCASEには微妙な点がある。
 CASE 条件1 OF ワード1 ENDOF
条件2 OF ワード2 ENDOF
ワード3
ENDCASE
条件1、条件2に合致しない場合は、ワード3が実行される。ところがスタックトップの値は残ったままになり、
 ENDCASE で DROP される。このためワード3でスタックに値を積んで残すには工夫が必要になる。

cs1の定義の以下の部分がそれに相当する。
>R 999 R>


最新の画像もっと見る

コメントを投稿