Re: Fun with the CS stack - Portable Control Structures (for Ed)
  Home FAQ Contact Sign in
comp.lang.forth only
 
Advanced search
POPULAR GROUPS

more...

 Up
Re: Fun with the CS stack - Portable Control Structures (for Ed)         

Group: comp.lang.forth · Group Profile
Author: Jenny Brien
Date: Jul 16, 2008 05:02

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?
no comments
diggit! del.icio.us! reddit!