The ANSI Standard On Forth has ensured that words are usually not state-smart, since it can be a problem when trying to postpone execution in self-constructed compiling words. Only two compile-only words exist that have an extra execution-semantics, one is s-quote (for use with included, the other is to. A note in the standard says (near TO, 13.6.1.2295 )
This note can be seen as a big red warning for anything that is state-smart - state-smart words are one of the widely used implementation tactics to make life easier for the usage of words. It is escpially a bit cumbersone while learning the forth language. In general, a forth user can test a little series of words on the command line in interpret mode, and when the things work as expected, just surround it with ":" and ";" to memorize the word-sequence for further reference. It makes one of the strengths of forth that one can easily factor out command-sequences and attach a nice and readable name to it.
The ANS Forth describes a few pairs of words to handle the problems with postpone - one is an immediate compile-only word, the other is just the execution that is done by that word before compiling it into the dictionary - usually to leave a value on the stack. The words are:
` [char] `
is compile-only - it will get the
(ascii-) value of the next char, and compile it as
a `literal`. It's interpret-semantics are undefined,
and the word `char` must be used outside of your
colon-definitions. The `char` word is more or less the
implementation used by `[char]`, as in
: [char] ?comp char postpone literal ; immediate
In pfe, the `[char]` is state-smart - in interpret-mode, it will only do `char` and it will not call `literal`. The char-value is left on the stack just as it is done in a compiled word that has used `[char]`.
: [char] char state @ if literal then ; immediate
` ['] `
is compile-only - it will get the
execution-token of the next word, and compile it as
a `literal`. It's interpret-semantics are undefined,
and the word `'` must be used outside of your
colon-definitions. The `'` word is more or less the
implementation used by `[']`, as in
: ['] ?comp ' postpone literal ; immediate
In pfe, the `[']` is state-smart - in interpret-mode, it will only do `'` and it will not call `literal`. The tick-value is left on the stack just as it is done in a compiled word that has used `[']`.
: ['] ' state @ if postpone literal then ; immediate
` ." string" `
is compile-only - it will parse
the string, compile it, and when the compiled word is executed,
it will print the string to the terminal. The usage of
` .( string) `
will run immediatly, to show
the string to the terminal in both compile- or interpret-mode, which
is good for notifications during compiling of a forth script.
The non-immediate word would be `type` that needs to be
passed a string which could be compiled with `sliteral`.
In PFE, the `."` is made state-smart, therefore in interpret-mode, it will instantly print the string to the terminal, just like `.(` would do. In compile-mode it parses and compiles the string (`sliteral`) and postpones a `type`-execution.
: .( postpone " type ; immediate : ." postpone " state @ 0= if type else postpone sliteral postpone type fi ; immediate
` C" string" `
is compile-only - it will
parse the string, compile it, and when the compiled word is
executed, the string-address will be avaiable for further usage
in the word. There is originally no interpret-semantics for
the strings, but ANS Forth has defined one only for the
usage with `included`. You will find that the ANS Forth
standard has two descriptions of `S"`, where one is in
CORE, the other is in FILE-EXT - only the latter is
more or less state-smart.
The problem with interpreted string constants is the question where the string is stored. In traditional systems, the stringconstant is put into a temporary location called the `pocket`. Many systems (including the PFE) have more than one pocket that are used in a round-robin fashion, but the user should be aware that interpret string-constants are only temporary - they will be overwritten in the pocket by some other call later on.
The usage of `included` from the FILE-EXT wordset however suggests that one does need stringconstants in interpret-mode, and ANS Forth has therefore defined that `S"` should be extended with an interpret-semantics if `included` is available in a forth system. However, `S"` is easier for temporary strings than `C"` - an implementation can choose to return the address and length of the charstring in the TIB - the terminal input buffer. In such a system, the use of such an intepret-mode string construct would only last for a single line entered - the following `included` call must be on the same line as the `S"`-quoted string-constant.
PFE however is very traditional (it's one of the features of PFE) and in interpret-mode, all these stringconst quote-words will actually parse the string into a pocket whose address is returned. Usually, PFE is configured to have eight pockets, and a maintainer is asked to never configure with less than two pockets to enable move-file and rename-file operations from the commandline. And always remember - interpret-mode stringconstants are temporary, and their number is limited.
( To postpone these words can again be a problem, just as it is with state-smart words. Be sure to use `sliteral` to add a string-constant to a meta-compiled definition, and look into the documentation of the nonstandard word `parse,` to add just the chars of the stringconstant to the dictionary. )
All these words are compile-only - they are used to compile a value on the (cs-)stack into the dictionary and to return their value/address during execution of the compiled word.
It is easy to add a bit of state-smartness to these words - compilation is only done in compile-mode, while in interpret-mode it will do as if it is already running. `literal` will leave the value on stack, actually a `noop` in pfe. The same for `2literal` that leaves the 2value on stack, and for `fliteral` and the f-stack. `sliteral` will effectivly do nothing either, leaving you with the pocket-string. In compile-mode, it would `allot` and copy the string to the defined word leave that address later.
If you are interested about the whole topic of postpone, state-smart words and ANS Forth descriptions with differing compile-mode and interpret-mode semantics ("combined words"), then have a look at gforth which uses a truly different approach about compile-only/interpret-only/combined/self-parsing and other immediate/non-immediate words.
Anton Ertl (the gforth author) has some more indepth documentation about the topic availabl on the Vienna university server, see
also, there was a discussion about this topic on comp.lang.forth during 6.March.2001 to 7.March.2001, that may give you some hints
As far as I can see, state-smart implementations of the string-contant words and literal-words are very very common in the forth systems around, the state-smart variants of char/[char] and '/['] pair is not so widespread. Be sure to postpone only `char` or `'`. There is a configure-time default for PFE-compilation that can make all these statesmart words non-smart - if these compile-only words are interpeted on the command-line then a `?comp` exception is thrown - something like "trying to execute a compile-only word". The compile-default for PFE is however to make them statesmart instead of compile-only-immediate.