Go to the first, previous, next, last section, table of contents.


Interpretation and Compilation Semantics

The interpretation semantics of a word are what the text interpreter does when it encounters the word in interpret state. It also appears in some other contexts, e.g., the execution token returned by ' word identifies the interpretation semantics of word (in other words, ' word execute is equivalent to interpret-state text interpretation of word).

The compilation semantics of a word are what the text interpreter does when it encounters the word in compile state. It also appears in other contexts, e.g, POSTPONE word compiles(3) the compilation semantics of word.

The standard also talks about execution semantics. They are used only for defining the interpretation and compilation semantics of many words. By default, the interpretation semantics of a word are to execute its execution semantics, and the compilation semantics of a word are to compile, its execution semantics.(4)

You can change the compilation semantics into executeing the execution semantics with

immediate       --         core       ``immediate''

You can remove the interpretation semantics of a word with

compile-only       --         gforth       ``compile-only''

restrict       --         gforth       ``restrict''

Note that ticking (') compile-only words gives an error ("Interpreting a compile-only word").

Gforth also allows you to define words with arbitrary combinations of interpretation and compilation semantics.

interpret/compile:       interp-xt comp-xt "name" --         gforth       ``interpret/compile:''

This feature was introduced for implementing TO and S". I recommend that you do not define such words, as cute as they may be: they make it hard to get at both parts of the word in some contexts. E.g., assume you want to get an execution token for the compilation part. Instead, define two words, one that embodies the interpretation part, and one that embodies the compilation part. Once you have done that, you can define a combined word with interpret/compile: for the convenience of your users.

You also might try to provide an optimizing implementation of the default compilation semantics with this feature, like this:

:noname
   foo bar ;
:noname
   POSTPONE foo POSTPONE bar ;
interpret/compile: foobar

as an optimizing version of

: foobar
    foo bar ;

Unfortunately, this does not work correctly with [compile], because [compile] assumes that the compilation semantics of all interpret/compile: words are non-default. I.e., [compile] foobar would compile the compilation semantics for the optimizing foobar, whereas it would compile the interpretation semantics for the non-optimizing foobar.

Some people try to use state-smart words to emulate the feature provided by interpret/compile: (words are state-smart if they check STATE during execution). E.g., they would try to code foobar like this:

: foobar
  STATE @
  IF ( compilation state )
    POSTPONE foo POSTPONE bar
  ELSE
    foo bar
  ENDIF ; immediate

While this works if foobar is processed only by the text interpreter, it does not work in other contexts (like ' or POSTPONE). E.g., ' foobar will produce an execution token for a state-smart word, not for the interpretation semantics of the original foobar; when you execute this execution token (directly with EXECUTE or indirectly through COMPILE,) in compile state, the result will not be what you expected (i.e., it will not perform foo bar). State-smart words are a bad idea. Simply don't write them!

It is also possible to write defining words that define words with arbitrary combinations of interpretation and compilation semantics. In general, this looks like:

: def-word
    create-interpret/compile
    code1
interpretation>
    code2
<interpretation
compilation>
    code3
<compilation ;

For a word defined with def-word, the interpretation semantics are to push the address of the body of word and perform code2, and the compilation semantics are to push the address of the body of word and perform code3. E.g., constant can also be defined like this (except that the defined constants don't behave correctly when [compile]d):

: constant ( n "name" -- )
    create-interpret/compile
    ,
interpretation> ( -- n )
    @
<interpretation
compilation> ( compilation. -- ; run-time. -- n )
    @ postpone literal
<compilation ;

create-interpret/compile       "name" --         gforth       ``create-interpret/compile''

interpretation>       compilation. -- orig colon-sys         gforth       ``interpretation>''

<interpretation       compilation. orig colon-sys --         gforth       ``<interpretation''

compilation>       compilation. -- orig colon-sys         gforth       ``compilation>''

<compilation       compilation. orig colon-sys --         gforth       ``<compilation''

Note that words defined with interpret/compile: and create-interpret/compile have an extended header structure that differs from other words; however, unless you try to access them with plain address arithmetic, you should not notice this. Words for accessing the header structure usually know how to deal with this; e.g., ' word >body also gives you the body of a word created with create-interpret/compile.


Go to the first, previous, next, last section, table of contents.