[comp.lang.forth] A word on my Forth wishlist

D_FELDMA@UNHH.BITNET (01/22/90)

For me, the most tedious aspect of programming in Forth is getting items
on the data stack in the desired order.  It would be nice to have a word, say,
REORGANIZE that would lift this burden.

I can think of two ways that this might work:

RUNTIME version:

a_1 a_2 ... a_n str1 str2 REORGANIZE ====> a_j_1 ... a_j_m

where the a_i are arbitrary data elements, and str1 and str2 are (addresses of)
strings, so that for example:

a_1 a_2 a_3 (abc) (cbbac) REORGANIZE ===> a_3 a_2 a_2 a_1 a_3

This would be easy enough to write, but slow.

COMPILETIME version:  str1 str2 REORGANIZE as a string of Forth words to
accomplish the desired rearrangement.  For example:

(a) (aa)     REORGANIZE   would compile as    dup
(ab) (ba)    REORGANIZE   would compile as    swap
(ab) (aba)   REORGANIZE   would compile as    over
(ba) (baaba) REORGANIZE   might compile as    over over swap over
                                          or  dup dup 4 pick swap
                                          or  ???
             (I hope I have the numbering convention for  pick  correct;
              I've been writing a lot of PostScript lately.)
The point is that to write such a word, one must solve a (possibly
implementation dependent) optimization problem.  The reason for the dependency
on implementation is that on any given system, e.g. pick might be more or
less expensive than  swap.  So problem: given the relative cost of Forth's
stack primitives in a given implementation, generate the cheapest sequence
for rearranging the stack in a given way.  Or easier, just find one way to
implement REORGANIZE that's presumably close to optimal.  If the word generated
different code on different systems, but all with the same runtime behavior,
would it still be considered portable?

Having such a word would make Forth programs more readable (because a series
of stack manipulations is seldom transparent at first glance), and possibly
more efficient (if REORGANIZE could be optimized.)  In particular, it would
allow one to do on the stack what one might do less efficiently with reads
and writes to memory while not compromising the readability of one's code.

Any thoughts on how this might be done?  On on why one would or wouldn't
want to, if it could?

                                David Feldman
                                d_feldman@UNHH

ir230@sdcc6.ucsd.edu (john wavrik) (01/23/90)

David Feldman writes:

# For me, the most tedious aspect of programming in Forth is getting items
# on the data stack in the desired order.  It would be nice to have a word
# say, REORGANIZE that would lift this burden.
                                                                             
# Having such a word would make Forth programs more readable (because a series 
# of stack manipulations is seldom transparent at first glance), and possibly  
# more efficient (if REORGANIZE could be optimized.)  In particular, it would  
# allow one to do on the stack what one might do less efficiently with reads   
# and writes to memory while not compromising the readability of one's code.   

The following word was found in FIFTH. It allows a desired stack change 
to be produced by a diagram.  It does not satisfy David Feldman's desire 
to act as a macro during compilation -- but it is relatively fast (it is 
written in F83 assembly language for the 8086).  The desired stack 
configuration is produced on top of the existing stack, and the stack is 
then shifted to eliminate the input arguments. 

==================================
\     Stack diagram word
variable sscnt
code (stack)  ( old $ --  new )
      di pop  0 # cx mov  0 [di] cl mov
      cx sscnt #) mov  di inc   ascii | # ax mov
      repnz byte scas   cx sscnt #) sub  0 # dx mov
      -2 [di] dl mov    sp bx mov
      here  0 # ah mov 0 [di] al mov   dx ax sub  ax ax add
            ax neg  bx ax add  ax bx xchg  0 [bx] push
            ax bx xchg  di inc
      loop  sscnt #) dx mov  dx dec  dx dx add  bx si xchg
      si cx mov  sp cx sub  si dec  si dec
      si di mov  dx di add  std  rep byte movs  cld
      dx sp add  bx si xchg  next c;

                                                           -->
\     Stack diagram word

: ($)  r> dup count + >r  ;
: stack  state @ if  compile ($)  bl word c@ 1+ allot
                     compile (stack)
                 else  bl word (stack) then  ;  immediate
\s
The word STACK is followed by a diagram. On the left of | is a
sequence of *consecutive* ascii characters indicating the stack
before rearrangement -- on the right is the desired result
e.g.
     1 2 3  stack  ab|abab   gives  1 2 3 2 3
     "stack abc|bca"  is equivalent to ROT

NOTE:  the words do not do not check the diagram for correct
       syntax.
========================================
This mechanism is reasonably efficient. "STACK abc|bca" is only about 
five times slower than ROT. It is slightly faster than some of the 
abundantly available schemes for local or stack variables (which, 
however, have an advantage in clarity and flexibility). 

DISCLAIMER:  I do not use this word! It was written as part of my
book "101 Ways Not to Interest Others in Forth".

   Way #47  -- Try to satisfy the perverse and devious
               ways others would like Forth to function.

Does anyone else have a colleague who periodically says "I think I'd like 
Forth if only it worked like <this>"?  You show him how easy it is to add 
what he wants. A few weeks later you find (1) he continues to program in 
his favorite language and (2) you feel like a pander (one who ministers 
to the baser passions of others). 

Horrendous stack manipulations can usually be avoided without resort to 
this mechanism. Factoring decreases the need immensely. Variables can 
also be used judiciously. Both lead to clearer code. Any non-obvious
sequence of stack manipulations should be broken up into separate lines 
of obvious manipulations each accompanied by a "declaration of intent"
(a "state of the stack" comment).



                                                  John J Wavrik 
             jjwavrik@ucsd.edu                    Dept of Math  C-012 
                                                  Univ of Calif - San Diego 
                                                  La Jolla, CA  92093