How POSTPONE should work #105
ruv
started this conversation in
Show and tell
Replies: 1 comment 3 replies
-
Why should the edge cases matter? How often are they likely to occur? |
Beta Was this translation helpful? Give feedback.
3 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Preface
The well known words
lit,
andcompile,
are required for illustrations.In a Forth system with direct/indirect threaded code and united code space and data space (so
compile,
is equivalent to,
Comma), these words can be implemented as follows:In any standard Forth system
lit,
can be defined as:For better understanding the terms "compilation semantics", "interpretation semantics", "execution semantics", "current definition", please refer to the section 2.1 Definitions of terms of Forth-2012.
The term "word" is used in the notion of a named Forth definition.
Overview
The behavior of
postpone
word, when it's encountered by the Forth text interpreter in compilation state, is to determine compilation semantics for its parsed argument (immediate argument) and append these semantics to the current definition.Compilation semantics for a word can be either special or ordinary (see the section 3.4.3.3 Compilation semantics of Forth-2012). To work correctly,
postpone
should distinguish these cases and generate code according to the different patterns.Ordinary case
Ordinary compilation semantics for a word are to append the execution semantics of the word to the current definition. The word
compile,
does exactly that.For example, let
foo
is an ordinary word. Then, the quotation[: ['] foo compile, ;]
performs the compilation semantics forfoo
. Hence, the phrasepostpone foo
(in a definition body) is equivalent to the phrase[ [: ['] foo compile, ;] compile, ]
(which appends this quotation behavior to the current definition), which is equivalent to just['] foo compile,
. I.e.,postpone foo
(in the definition body) can be replaced by['] foo compile,
.It means that
postpone foo
should generate the latter phrase immediately during compilation, i.e. the behavior ofpostpone foo
, during compilation, should be equivalent to execution of the phrase['] foo lit, ['] compile, compile,
, which appends['] foo compile,
to the current definition.So the following definitions are equivalent (for an ordinary word
foo
):Special case
Special compilation semantics (if any) are specified individually per a word. And they should not be equivalent to appending execution semantics (the ordinary case).
On the system level they may be implemented in various ways.
Immediate words
In the classic single-xt+immediate-flag Forth systems, special compilation semantics are only implemented via the immediacy mechanism.
The compilation semantics for an immediate word are to perform the execution semantics of this word in compilation state. NB: if they are performed in interpretation state, then the interpretation semantics for this word are performed, that can produce different effects. An example of such a standard word is
s"
(from FILE) in the classic Forth systems.For example, let
bar
is an immediate word. Then, executingbar
(e.g. via['] bar execute
) in compilation state performs the compilation semantics forbar
, and in interpretation state it performs the interpretation semantics forbar
. To perform the compilation semantics forbar
no matter what, we need a helper wordexecute-compiling
, which enters compilation state if it's required.In a classic Forth system the word
execute-compiling
can be implemented as follows:Now the phrase
['] bar execute-compiling
performs the compilation semantics forbar
regardless of the initial value ofstate
. Hence, the phrasepostpone bar
is equivalent to the phrase['] bar execute-compiling
(i.e., the former may be replaced by the latter in a definition body). It means thatpostpone bar
should generate the latter phrase immediately during compilation, i.e. the behavior ofpostpone
during compilation in this case should be equivalent to execution of the phrase['] bar lit, ['] execute-compiling compile,
(which appends['] foo execute-compiling
to the current definition).So the following definitions are equivalent (for an immediate word
bar
):See also About POSTPONE semantics in edge cases to find a proof of this approach correctness in any edge case.
Full implementation
According to the above cases, in a classic single-xt+immediate-flag Forth system,
postpone
can be implemented as follows:Actually, this implementation is valid in any Forth system that provides a compatible implementation for the word
find
.Limited implementation #
Formally, the word
postpone
provides a way to perform the compilation semantics for a word regardless of the initial value ofstate
But before this word was introduced, a standard program might perform special compilation semantics only in compilation state. The Forth-79 and Forth-83 standards explicitly disallowed performing compilation semantics in interpretation state (they use other terminology, certainly).
Taking into account this restriction on programs,
postpone
can be implemented slightly simpler. In a classic single-xt+immediate-flag Forth system it can be implemented as follows:So when
postpone
is applied to an immediate word, it just appends the execution semantics of this word to the current definition — exactly like[compile]
in Forth-83.With this
postpone
, the following definitions are equivalent (for an immediate wordbar
):Having the mentioned restriction on programs by the tradition, and having incorrect behavior only in edge cases, this simpler implementation became popular, unfortunately.
To formally allow such implementation for
postpone
, and hold the letter of the standard in the same time, and avoid incorrect behavior in the edge cases, the Forth-94 technical committee decided to explicitly restrict standard programs and disallowed them to perform compilation semantics in interpretation state — see RFI Q99-027 (copy1,copy2).So, the limited implementation for
postpone
may be provided by a standard Forth system, with the corresponding restriction on programs. But to avoid unexpected effects in edge cases, it's better to provide a complete implementation forpostpone
.Beta Was this translation helpful? Give feedback.
All reactions