minforth@gmx.net (minforth) writes:
On Tue, 4 Feb 2025 12:26:26 +0000, albert@spenarnc.xs4all.nl wrote:
Remark that is doesn't introduce any unfamiliar syntax,
only does away with "Forth shall not nested definitions"
(Says who?)
>
Given that a Forth system supports quotations and xt-locals,
nested definitions are easy to implement.
You mean:
: foo [: ." xyz" ;] {: xt: bar :} bar ;
Sure, you then get a local that behaves similar to a nested
definition, but I don't think anyone would want to do that.
And it uses proper locals as part of the mechanism, whereas many
contributions in the thread seem to have the goal of doing something
that may require less implementation effort, but also does not do
everything proper locals do (e.g., work with exceptions), and then try
to Jedi away the cases that do not work.
BTW xt-locals exist
f.ex. in gforth. They hold xt's and when called execute the xt
instead of pushing it to the stack as normal locals would do.
We call them defer-flavoured, and the more usual locals
value-flavoured. In the example above the "xt:" means that the next
name is that of a defer-flavoured local.
When Bernd Paysan introduced defer-flavoured locals, I was sceptical,
especially given the experience with variable-flavoured locals which
have been in Gforth since 1994 and are barely used. But it turns out
that when a local contains an xt, using a defer-flavoured local is
often more appropriate than a value-flavoured local. This is: you can
use either (use l EXECUTE when l is value-flavoured and you want to
execute it, or use ACTION-OF l when l is defer-flavoured and you want
its value), but in many cases you want to execute an xt you pass,
sometimes multiple times.
An example is the generation of code for 2-stage division by
constants:
: lit/, {: divisor xt: stage1 xt: stage2 -- :}
next-section staged/-size small-allot previous-section {: addr :}
divisor addr stage1 ]] addr stage2 [[ ;
The first line allocates memory for storing the inverse of the divisor
in ADDR. The second line first converts from the divisor to the
inverse in stage 1 of the division when the division is compiled, and
compiles code for performing stage 2 of the division (multiplying the
dividend (available only at run-time) with the inverse). It also
demonstrates that when using a defer-flavoured local inside ]]...[[,
the xt in the local is COMPILE,d, not EXECUTEd.
With value-flavoured locals that would have been:
: lit/, {: divisor stage1 stage2 -- :}
next-section staged/-size small-allot previous-section {: addr :}
divisor addr stage1 execute ]] addr [[ stage2 compile, ;
While the mechanism is more obvious here, the intent is more obvious
in the version with defer-flavoured locals (at least if you understand
the code). And of course the orthodox traditional Forther would have
written this without locals at all:
: lit/, ( divisor stage1 stage2 -- )
>r >r >r next-section staged/-size small-allot previous-section ( addr )
r> dup r> execute ( addr )
postpone literal r> compile, ;
- anton
-- M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.htmlcomp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html New standard: https://forth-standard.org/EuroForth 2023 proceedings: http://www.euroforth.org/ef23/papers/EuroForth 2024 proceedings:
http://www.euroforth.org/ef24/papers/