Stephen Pelc <
ste...@vfxforth.com> writes:
>However NEXT-CASE is very rarely used as once you get to
>needing it, refactoring the code is probably a good idea.
I am not sure that refactoring really helps when you have multiple
exit conditions in a loop.
As for usage frequency:
In Gforth's image there are the following usages:
2 NEXT-CASE
19 CONTOF (another looping word used with CASE)
8 ?OFs (another non-standard word used with CASE)
16 CASE standard word
74 OF standard word
133 WHILE
103 REPEAT
So obviously 30 more WHILE's than REPEATs, so there is quite a bit of
usage of "extended flow control structures".
Almost all uses of non-standard CASE words are in locate1.fs, a
relatively recent part of Gforth (just as we added NEXT-CASE
relatively recently).
The two NEXT-CASE usages are:
: l2 ( -- c-addr u lineno )
located-buffer 1 case ( c-addr u lineno1 )
over 0= ?of endof
dup located-bottom @ >= ?of endof
locate-lines# @ located-diff >= ?of endof
dup located-top @ >= ?of locate-print-line contof
locate-next-line
next-case ;
: .whereline {: view u -- :}
\ print the part of the source line around view that fits in the
\ current line, of which u characters have already been used
view view>buffer
1 case ( c-addr u lineno1 )
over 0= ?of endof
dup view view>line = ?of locate-line view u .wheretype1 endof
locate-next-line
next-case
drop 2drop ;
The three uses of ?OF CONTOF indicate that a WHILE would have been ok
for that case, but note that both loops had a case where WHILE would
have required something beyond adding a THEN after the REPEAT. How
would these word be improved with factoring?
You see one of the CONTOFs in L2 above. The other 18 are in:
: fancy-after-l ( c-addr1 u1 lineno1 -- c-addr2 u2 lineno2 )
\ allow to scroll around right after LOCATE and friends:
case
ekey \ k-winch will only be visible with ekey
ctrl p of 1 prepend-locate-lines contof
ctrl n of 1 append-locate-lines contof
ctrl u of rows 2/ prepend-locate-lines contof
ctrl d of rows 2/ append-locate-lines contof
'k' of 1 prepend-locate-lines contof
'j' of 1 append-locate-lines contof
'l' of located-diff >r index++
r> located-diff - append-locate-lines contof
'h' of located-diff >r index--
r> located-diff - append-locate-lines contof
ctrl b of rows 2 - prepend-locate-lines contof
bl of rows 2 - append-locate-lines contof
ctrl l of 0 append-locate-lines contof
'q' of endof
#esc of endof
ekey>xchar ?of ['] xemit $tmp unkeys endof
k-up of 1 prepend-locate-lines contof
k-down of 1 append-locate-lines contof
k-prior of rows 2/ prepend-locate-lines contof
k-next of rows 2/ append-locate-lines contof
k-winch of 0 append-locate-lines contof
k-right of located-diff >r index++
r> located-diff - append-locate-lines contof
k-left of located-diff >r index--
r> located-diff - append-locate-lines contof
endcase ;
This could obviously done in a more data-driven way, but I think that
this way is more readable, dogma be damned. Here's a similar thing in
a data-driven approach:
Create xchar-ctrlkeys ( -- )
' false , ' xfirst-pos , ' xback , ' false ,
' xeof , ' xend-pos , ' xforw , ' false ,
' ?xdel , ' xtab-expand , ' (xenter) , ' xclear-rest ,
' xreformat , ' (xenter) , ' next-line , ' false ,
' prev-line , ' false , ' false , ' setsel ,
' xtranspose , ' xclear-first , ' xpaste , ' false ,
' <xdel> , ' xpaste , ' xhide , ' xchar-altkey ,
' false , ' false , ' false , ' false ,
Create std-ekeys
' xback , ' xforw , ' prev-line , ' next-line ,
' xfirst-pos , ' xend-pos , ' prev-line , ' next-line ,
' false , ' <xdel> , ' (xenter) , ' false ,
' false , ' false , ' false , ' false ,
' false , ' false , ' false , ' false ,
' false , ' false , ' false , ' xreformat ,
' xhide , ' false , ' prev-line , ' next-line ,
' ?xdel , ' xtab-expand , ' setsel , ' xeof' ,
' xchar-ctrlkeys IS ctrlkeys
' std-ekeys IS ekeys
: bindkey ( xt key -- )
dup bl u>= abort" Ctrl codes only!"
cells ctrlkeys + ! ;
: ebindkey ( xt key -- )
dup keycode-limit keycode-start within abort" Ekeys only!"
keycode-start - cells ekeys + ! ;
Disadvantage of the data-driven approach: It's not obvious which key,
e.g., xclear-first is bound to.