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