On May 9, 1:42 pm, Bernd Paysan <
bernd.pay...@gmx.de> wrote:
> Problem: LEAVE and UNLOOP are defined to have no interpretation
> semantics, but an execution semantics. This implies that ['] LEAVE
> EXECUTE is equivalent to LEAVE within a loop body.
I do not believe that this premise is valid.
(1) ['] clearly specifies that it gives the same result as ' does when
interpreting.
(2) ' clearly specifies that *when interpreting*
' foo EXECUTE
... is the same as interpreting "foo".
(3) Thus ['] foo EXECUTE while compiling should give the
interpretation semantics of a word.
(4) LEAVE and UNLOOP are specified to have undefined interpreter
semantics, and so ['] LEAVE EXECUTE which while compiling is *not*
required to be equivalent to LEAVE within a loop body.
*However* my view is that there is still merit to one part of this
proposal. This is based on a point regarding which there is no
consensus, and upon which I appear to differ for Bernd, who has
suggested in another forum that this may be because his perspective is
too abstract for my humble mental capacities. And that may very well
be the case, so if I am wrong on this point, I'll need the assistance
of a somewhat less than lofty explanation why.
This goes to the heart of the notion of what "execution semantics" are
and what it implies for a word to be specified with special
compilation semantics. I have always had a tendency to view the first
clause in the specification of the term "execution" as the primary
clause. This clause is highlighted in the quote of relevant section
with * marks:
"3.4.3.1 Execution semantics"
"The execution semantics of each Forth definition are specified in
an Execution: section of its glossary entry. When a definition has
only one specified behavior, the label is omitted."
"*Execution may occur implicitly, when the definition into which it
has been compiled is executed*, or explicitly, when its execution
token is passed to EXECUTE. The execution semantics of a syntactically
correct definition under conditions other than those specified in this
Standard are implementation dependent."
"Glossary entries for defining words include the execution
semantics for the new definition in a name Execution: section."
What is not mentioned in the first paragraph of the specification is
that not all definitions have an "Execution:" section.
In my view, the special cases are implied by the highlighted section:
"Execution may occur implicitly, when the definition into which it has
been compiled is executed."
In most cases, the execution semantics are atomic. They occur at
execution time of the word into which the execution semantics have
been compiled, and all that is required to get that is for the system
to be in compilation state when encountering the word in the source.
However, in some cases, the execution semantics are not atomic. [CHAR]
must parse the following token at compile time to obtain the
character, which is placed on the stack at execution time, so correct
execution is contingent on both a compile-time and a run-time action.
THEN must find a valid orig on the compilation structures stack at
compile time, in order to be the position at which execution resumes
following, eg, the run-time of IF consuming a zero.
In scanning through the Standard, every instance where there is no
"Execution:" section, the situation involves this kind of non-atomic
execution semantics.
While the UNLOOP semantics are atomic, and properly specified, the
LEAVE semantics are not *necessarily* atomic, *unless* one provides an
implementation such as pushing the target leave address onto the
return stack. If one implements LEAVE as an unconditional branch,
tracking the LEAVE origins in some way outside of the compilation
structures stack, then the semantics are not in fact atomic.
This may have been overlooked because the former was the most common
LEAVE implementation in the early 90's, or because the record keeping
for the branch version of LEAVE is explicitly somewhere other than the
compilation structures stack, but in any event, LEAVE is, in my view,
properly defined as having special compilation semantics, as the other
structure words are.
I view UNLOOP as having atomic execution semantics similar to RDROP
and EXIT, and so I do not support the proposal with respect to UNLOOP.
> Solution: Remove "Execution:" from the definition of LEAVE.
> Insert instead
> Compilation: ( -- )
> Append the run-time semantics given below to the current
> definition.
>
> Run-Time:
> Rationale:
> This change is to allow alternative implementations of LEAVE with special
> compilation semantics. This is common practice.