On Jul 14, 6:43Â am, "Ed" invalid.com> wrote:
> "Jenny Brien" googlemail.com> wrote in message
>> : TEST ( n -- )
>> Â case
>> Â Â Â Â Â 0 Â 20 range else
>> Â Â Â Â Â 7F of either ." Control char " Â Â Â endof
>
>> Â Â Â Â Â cond
>> Â Â Â Â Â 20 2F range else
>> Â Â Â Â Â 3A 40 range else
>> Â Â Â Â Â 5B 60 range else
>> Â Â Â Â Â 7B 7E range whence ." Punctuation " Â endof
>
>>      30 39 range  ." Digit "        endof
>>      41 5A range  ." Upper case letter "  endof
>>      61 7A range  ." Lower case letter "  endof
>> Â Â Â Â Â Â Â ." Not a character "
>> Â endcase ;
>
> This is interesting because it reverses the logic used in Miser.
> The trade-offs are also reversed as a consequence e.g. RANGE
> is efficient when used on its own, but in a COND WHENCE each
> RANGE will require an ELSE which generates another branch.
>
> Miser also generates this redundant branch however it occurs
> once at WHEN. Â This makes COND WHEN efficient for handling
> multiple items. Â
This is a space issue rather than one of speed. Only one ELSE in
encountered on any branch.
I wrote it this way so that WHENCE or EITHER would work with any test:
A? IF A ELSE B? IF ." B, not A" EITHER ." A or B" THEN
COND A? IF A B? IF B ELSE ." not B" WHENCE ." not(A & B) "
ELSE ." A & B" THEN
COND A? IF A B? IF B ELSE WHENCE
C? IF ." C & not(A & B)" EITHER ." (A & B) or C" THEN
>
> In theory redundant unconditional branches could be "optimized out"
> but neither of the native code forth compilers I tried do that.
The rules for that are quite simple:
Record all forward branches in an array while compiling.
At end of definiton, search backwards through array.
For each branch:
If it points to the end of definition, replace with EXIT or ?EXIT
If it points to EXIT or an unconditional branch, with EXIT, ?EXIT or
the branch target
>
>
> I tried reformatting to:
>
> Â COND
> Â Â BEGIN
> Â Â Â producer
> Â Â Â COND .... Â WHENCE Â ." One of the above" Â ELSE
> Â Â Â A OF Â ." A" Â CONTINUE
> Â Â Â B OF Â ." B" Â BREAK
> Â Â C UNTIL
> Â WHENCE Â ." Stopped on C" Â ELSE
> Â Â Â ." Stopped on B"
> Â THEN
>
> But it was still not intuitive (to me) just by looking that BREAK should
> continue where it does. Â Probably, like WHILE, one needs to get used
> to it.
>
>
That's because I got it wrong again, trying to put too many clauses.
Think of BREAK as an ELSE for WHILE, so that the exit action may be
next its test.
Both BREAK and CONTINUE may only be separated from the preceding BEGIN
by a single unresolved condition.
Like WHILE, BREAK continues at then first unresolved THEN (there is
one implicit in REPEAT), ELSE, WHENCE or THENCE.
BEGIN
a? WHILE
b? WHILE
c
REPEAT
." not B" ELSE
." not A"
THEN
becomes
COND
BEGIN
a? 0= IF ." not A" BREAK
b? 0= IF ." not B" BREAK
c
REPEAT
THENCE
and
BEGIN
a? WHILE
b? IF
c? IF
c ELSE
b ELSE
a
THEN
THEN
REPEAT
becomes
BEGIN
a? WHILE
b? 0= IF a CONTINUE
c? IF c CONTINUE
b
REPEAT
I also managed to mess up the definition of DUFF. It's simpler than I
thought, and does not requise BREAK.
: duff ( data port count )
  dup  7 + 8 /
  swap 8 mod
   0  of
   nexttime \ C: dest orig
      send  else
   7  of either  send  else \ C: dest orig
   6  of either  send  else
   5  of either  send  else
   4  of either  send  else
   3  of either  send  else
   2  of either  send  else
   1  of either  send then \ C: orig
      1- dup 0= until
   drop 2drop ;
> In looking over these and previous examples, one notices CS-ROLL
> is relied upon for moving items out of the way. Â That may not always
> be possible or convenient. Â I think I'd still want to see CS-PUSH/POP
> in the toolset. Â e.g. CS-RESOLVE1 could then be eliminated.
There is an ugly bog-Standard way to get out of an arbitrary level of
complication:
0 0 DO (big mess) LEAVE (more mess) LEAVE LOOP
Gforth factors this behaviour out of DO ... LOOP to give the structure
BEGIN ... LEAVE ... DONE
I suspect it is not resorted to very often.
Examples, anyone?