Forums before death by AOL, social media and spammers... "We can't have nice things"
|    comp.lang.forth    |    Forth programmers eat a lot of Bratwurst    |    117,951 messages    |
[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]
|    Message 116,319 of 117,951    |
|    Anton Ertl to Anton Ertl    |
|    Re: Jensen's Device    |
|    17 Mar 24 08:59:17    |
   
   From: anton@mips.complang.tuwien.ac.at   
      
   anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:   
   >The C entry points out that macros are close to call-by-name   
   >semantics. Let's see how that works out in Gforth:   
   >   
   >: ]sum ( compile-time: ) {: xt: i1 xt: term -- :}   
   > \ run-time: ( lo hi -- r )   
   > ] ]] 0e 1+ swap +do   
   > i i1 ! term f+   
   > loop [[ ; immediate   
   >   
   >variable i1   
   >: term1 i1 @ s>f 1/f ;   
   >: main2 ( -- )   
   > [ ' i1 ] 1 100 [ ' term1 ]sum f. ;   
   >   
   >main2 cr   
   >   
   >Here main2 is decompiled as:   
   >   
   >: main2 #1 #100   
   > 0.00000000000000E0 1+ swap   
   > +do i i1 ! term1 f+   
   > loop   
   > f. ; ok   
   >   
   >This variant reverts to using a global variable I1, because the macro   
   >is expanded at compile-time and dealing with run-time locals in macros   
   >is an unsolved problem in Gforth. It uses a named definition TERM1   
   >rather than a quotation for better readability of the decompiler   
   >output. The code of the macro is remarkably similar to the code of   
   >the Gforth SUM above, thanks to ]] ... [[, and also the way   
   >POSTPONE/]] treats defer-flavoured locals (it COMPILE,s them).   
      
   A more idiomatic macro-based approach is as follows:   
      
   : sum< ( run-time: hi+1 lo -- 0e )   
    0e postpone ?do ; immediate   
      
   : >sum ( run-time: r1 r2 -- r3 )   
    postpone f+ postpone loop ; immediate   
      
   : main3 ( -- )   
    101 1 sum< 1e i s>f f/ >sum f. ;   
   main3 cr   
      
   Here SUM is split into two parts, and the TERM parameter is included   
   as compiled code between these two parts, satisfying call-by-name's   
   intent of textual replacement semantics.   
      
   The parameter i in the Algol 60 variant is an artifact of Algol 60's   
   way of working with variables; you also have to provide it to the for   
   loop in Algol 60 and, e.g., Pascal. Forth produces the loop index of   
   the inner counted loop with I, and so does SUM<...>SUM; an alternative   
   would have been to provide the loop index on the data stack.   
      
   The loop bounds are provided in the Forth-idiomatic form with the   
   limit (hi+1) given first and not being included.   
      
   The solution can be written slightly shorter using ]]...[[, but I   
   decided to stick to Forth-2012 here.   
      
   The Wikipedia page gives Sum(i, l, m, Sum(j, l, n, A[i,j])) as another   
   usage example; this would become:   
      
   : main4 ( -- r )   
    m 1+ l sum< n 1+ l sum< A{{ j i }} f@ >sum >sum ;   
      
   Here I used the FSL array syntax. One notable difference from the   
   Algol code is that the outer loop index is J, while Algol uses the   
   variable given (in this case i). That's the same as for other counted   
   loops in Forth.   
      
   - 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 2023: https://euro.theforth.net/2023   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|
[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]
(c) 1994, bbs@darkrealms.ca