When a word is compiled, it behaves differently from being interpreted.
1 2 + . : foo + ;
These two behaviours are known as compilation and interpretation
semantics. For normal words (e.g.,
+), the compilation semantics
is to append the interpretation semantics to the currently defined word
foo in the example above). I.e., when
foo is executed
later, the interpretation semantics of
+ (i.e., adding two
numbers) will be performed.
However, there are words with non-default compilation semantics, e.g.,
the control-flow words like
if. You can use
change the compilation semantics of the last defined word to be equal to
the interpretation semantics:
: [FOO] ( -- ) 5 . ; immediate [FOO] : bar ( -- ) [FOO] ; bar see bar
Two conventions to mark words with non-default compilation semantics are names with brackets (more frequently used) and to write them all in upper case (less frequently used).
For some words, such as
if, using their interpretation
semantics is usually a mistake, so we mark them as
compile-only, and you get a warning when you interpret them.
: flip ( -- ) 6 . ; compile-only \ but not immediate flip : flop ( -- ) flip ; flop
In this example, first the interpretation semantics of
used (and you get a warning); the second use of
flip uses the
compilation semantics (and you get no warning). You can also see in
this example that compile-only is a property that is evaluated at text
interpretation time, not at run-time.
The text interpreter has two states: in interpret state, it performs the interpretation semantics of words it encounters; in compile state, it performs the compilation semantics of these words.
Among other things,
: switches into compile state, and
switches back to interpret state. They contain the factors
(switch to compile state) and
[ (switch to interpret state), that
do nothing but switch the state.
: xxx ( -- ) [ 5 . ] ; xxx see xxx
These brackets are also the source of the naming convention mentioned above.
Reference: Interpretation and Compilation Semantics.