Digest #134 2021-01-24
Contributions
I'm confused. Is ' an immediate word or not?
If I do:
: test ' DUP ;
1 test SWAP
Do I get:
( xtD 1 )
where xtD is the execution token of DUP that got swapped with the 1, or do I get:
( 1 xtS xtS )
where xtS is the execution token of SWAP that got duplicated?
The existence of ['] certainly implies that ' is not immediate, and that if you want to have an immediate effect, you should use [']. Maybe that's what the documentation is trying to imply by not having separate "Compilation:" and "Runtime:" sections for this word? Many of the simpler words don't have such sections. Still, it may be better to explicitly state when the parsing and finding occurs... just for the sake of clarity. Maybe add another test to the "Testing:" section?
Under the "Run-time:" section it says:
1. names are initialized ...
2. names are uninitialized.
I suspect it might mean to say:
1. \<arg\> names are initialized...
2. \<val\> names are unitialized.
[In typing this response, I've noticed that the markdown format seems to eliminate things in greater/less brackets unless explicit care is given. That may be the reason -- that it just isn't rendering properly.]
Replies
referenceImplementation - Suggested reference implementation
What about this:
: TYPE ( c-addr u -- ) 0 ?DO COUNT EMIT LOOP DROP ;
It's kind of crazy, and still no XCHAR support, but COUNT is very (overly?) specific about what it does.
Thanks for catching my mistake - I think that clarification should be added in the text above, because this is two VERY different behaviors, i.e. in
: ENDIF POSTPONE THEN ; IMMEDIATE
: AGAIN POSTPONE branch <RESOLVE ; IMMEDIATE
: foo ....ENDIF .... AGAIN ;
The first POSTPONE
causes THEN
to be compiled into ENDIF
, while the second causes branch
to be compiled into foo,
i.e. not only does the programmer still have to be very cognisant of the immediateness or otherwise of THEN
and branch
, but the implementer of POSTPONE
(me in this case) has to write a definition that checks if THEN
or branch
are immediate and behave differently for the two cases.
While it could be argued that this is precisely explained by the standard as written above, to anyone coming from a eForth or similar environment, familiar with COMPILE
and [COMPILE]
, I think it is highly ambiguous, and would strongly suggest some explanation in the standard.
You are correct (verified by looking at the PDF). There must have been a conversion error when converting from LaTeX to HTML or Markdown.
You get ( 1 xtS xtS ).
' has default compilation semantics, i.e., is not immediate, as you noted from the absence of a "Compilation:" section.
Maybe we should add a caveat like you suggest to the Rationale for '. While a common argument is that the standard is not intended as an introduction to Standard Forth, this comment demonstrates that adding to the rationale could be useful; in particular, ' in fig-Forth works differently from ' in Standard Forth, so it's not just inexperienced users that might be confused.
Both cause the compilation semantics of the POSTPONEd word to be performed during the compilation of FOO.
The programmer does not have to know the immediacy of the POSTPONEd word at all, but has to know the compilation semantics (admittedly, if you think about words in terms of "immediate" or not, you need to know the immediacy in order to know the compilation semantics, but that's a result of framing the whole issue in these terms, not something innate in POSTPONE). The whole reason for POSTPONE's standardization is that systems like cmForth have, e.g., "immediate" implementations of, e.g., +, and classical COMPILE would not work for them (here "immediate" is used in an implementation-specific way; in the standard sense + is not immediate).
The system implementor does not need to check for immediacy, either. E.g., here's a definition of POSTPONE that does not check:
: ?parse-name ( "name" -- c-addr u )
parse-name dup 0= -16 and throw ;
: ?find-name ( c-addr u -- nt )
find-name dup 0= -13 and throw ;
: postpone ( "name" -- )
?parse-name ?find-name name>compile
( xt1 xt2 ) swap postpone literal compile, ;
Sure, if your system uses a header flag for "immediate", NAME>COMPILE will check that flag, but other systems are possible. E.g., in Gforth NAME>COMPILE is equivalent to
: NAME>COMPILE ( nt -- x xt ) dup cell- @ >vt>comp @ execute ;
I made two attempts to explain semantics: one in 2000 (slight revision in 2004) and one in 2010. But there is no consensus on the Forth200x committee about adding such explanations, so nothing in this direction has been added to the standards document yet.