Deutsch English Français Italiano |
<2024Sep12.105526@mips.complang.tuwien.ac.at> View for Bookmarking (what is this?) Look up another Usenet article |
Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: anton@mips.complang.tuwien.ac.at (Anton Ertl) Newsgroups: comp.lang.forth Subject: Re: Avoid treating the stack as an array [Re: "Back & Forth" is back!] Date: Thu, 12 Sep 2024 08:55:26 GMT Organization: Institut fuer Computersprachen, Technische Universitaet Wien Lines: 133 Message-ID: <2024Sep12.105526@mips.complang.tuwien.ac.at> References: <nnd$61e0ad9a$48ed61c2@b4d945e456041481> <vasqjd$icjm$1@dont-email.me> <66d26c4b$1@news.ausics.net> <vaubf7$tbke$1@dont-email.me> <nnd$04cff141$0193ba04@301336b8dd8ed69a> <vbfqnd$v4c4$1@dont-email.me> <nnd$26b4d59b$27bdb181@ce638e508b04426e> <87bk0vbvgk.fsf@nightsong.com> <66e0fa58$1@news.ausics.net> <66e11d64$1@news.ausics.net> <877cbh4b6z.fsf@nightsong.com> Injection-Date: Thu, 12 Sep 2024 12:18:17 +0200 (CEST) Injection-Info: dont-email.me; posting-host="b3a05cc3d9bbc2cf43d4db2bfea46e1b"; logging-data="231099"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19Ixo596EtG74nTg0sOdPxW" Cancel-Lock: sha1:QJ2l0zxh5s5vHrJ5Vzpzq3+VpMw= X-newsreader: xrn 10.11 Bytes: 6394 Paul Rubin <no.email@nospam.invalid> writes: >The 100+ occurrences of DUP, DROP, and SWAP are either an abstraction >inversion (with a smart compiler, the data ends up in registers that >could be named by locals) I don't see an inversion here. The programmer-visible stack abstracts (ideally) the registers in one way, the programmer-visible locals abstracts them in a different way. And if we look at the VICHECK example from Nick Nelson's Better Values <http://www.euroforth.org/ef22/papers/nelson-values-slides.pdf> the version with locals, followed by the version that eliminates the locals: : VICHECK {: pindex paddr -- pindex' paddr :} \ Checks for valid index \ paddr is the address of the data, the first cell of which contains \ the array size pindex 0 paddr @ WITHIN IF \ Index is valid pindex paddr ELSE \ Index is invalid Z" Invalid index " pindex ZFORMAT Z+ Z" for " Z+ paddr >NAME 1+ Z+ \ >NAME does not work for separated data Z" length " Z+ paddr @ ZFORMAT Z+ ERROR 0 paddr \ Use zeroth index THEN ; : VICHECK ( pindex paddr -- pindex' paddr ) \ Checks for valid index \ paddr is the address of the data, the first cell of which contains \ the array size over 0 2 pick @ WITHIN 0= IF \ Index is invalid Z" Invalid index " 2 PICK ZFORMAT Z+ Z" for " Z+ OVER CELL- @ Z+ \ Add NFA from extra cell Z" length " Z+ OVER @ ZFORMAT Z+ ERROR NIP 0 SWAP \ Use zeroth index THEN ; So by keeping the values on the stack you not just eliminate their repeated mention, but also eliminate one branch of the IF. With a more capable Forth system a synthesis of the two approaches is possible: : VICHECK ( pindex paddr -- pindex' paddr ) \ Checks for valid index \ paddr is the address of the data, the first cell of which contains \ the array size over 0 2 pick @ WITHIN 0= IF \ Index is invalid {: pindex paddr :} Z" Invalid index " pindex ZFORMAT Z+ Z" for " Z+ paddr >NAME 1+ Z+ \ >NAME does not work for separated data Z" length " Z+ paddr @ ZFORMAT Z+ ERROR 0 paddr \ Use zeroth index THEN ; Or one could factor out the code between IF and THEN and stay within the confines of VFX: : VIERROR {: pindex paddr -- 0 paddr :} Z" Invalid index " pindex ZFORMAT Z+ Z" for " Z+ paddr >NAME 1+ Z+ \ >NAME does not work for separated data Z" length " Z+ paddr @ ZFORMAT Z+ ERROR 0 paddr \ Use zeroth index ; : VICHECK ( pindex paddr -- pindex' paddr ) \ Checks for valid index \ paddr is the address of the data, the first cell of which contains \ the array size over 0 2 pick @ WITHIN 0= IF \ Index is invalid VIERROR THEN ; The check can be simplified, which also simplifies the stack handling: : VICHECK ( pindex paddr -- pindex' paddr ) \ Checks for valid index \ paddr is the address of the data, the first cell of which contains \ the array size 2dup @ u>= IF \ Index is invalid VIERROR THEN ; >or they are stack traffic whose cost has to be >compared with the cost of indexed references to locals in the return >stack. That check often results in the code without locals winning, but that is, for a large part, due to suboptimal implementations of locals. Ideally a perfect compiler will produce the same code for code using locals and for equivalent code using stack manipulation words, because the data flow is the same. This actually works out in the case of lxf processing various implementations of 3DUP, including a locals-based one; see <2024Apr10.090038@mips.complang.tuwien.ac.at>. However, in general Forth systems do not produce perfect results. I have now looked at what happens for the first two variants of VICHECK; I have defined the non-standard words as follows to make it possible to compile the code: defer dummy : z" [char] " parse 2drop postpone dummy ; immediate defer zformat defer z+ defer >name defer error I looked at 3 systems: Gforth (because I work on it); lxf (because it produces the best results in the 3DUP case); VFX (because it's the system Nick Nelson uses). The numbers below are the number of bytes of native code: locals stack 401 336 gforth-fast (AMD64) 179 132 lxf 1.6-982-823 (IA-32) 182 119 VFX FX Forth for Linux IA32 Version: 4.72 (IA-32) 241 159 VFX Forth 64 5.43 (AMD64) >I'd agree that they aren't necessary "juggling" which evokes >permuting stuff in the stack outside the usual FIFO order. That does >happpen a little bit though, with OVER, ROT, etc. In particular, in Starting Forth ROT is illustrated with a juggler (you see the juggling balls right beside her), and the swap dragon comments: "I hate jugglers". https://www.forth.com/wp-content/uploads/2015/03/ch2-rot.gif - anton -- M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html New standard: https://forth-standard.org/ EuroForth 2024: https://euro.theforth.net