Krishna Myneni <
krishna...@ccreweb.org> writes:
>On 10/3/20 9:23 AM, Anton Ertl wrote:
>> Krishna Myneni <
krishna...@ccreweb.org> writes:
>>> Imagine for the moment that the standard explicitly requires a dual-xt
>>> implementation, and disallows the traditional single xt + immediate
>>> flag.
>>
>> You mean, for all words? With, e.g.,
>>
>> ' s"int ' s"comp interpret/compile: s"
>>
>
>Yes. I don't recall the meanings of the above words, but all words have
>an xt1 for interpretation state and an xt2 for compilation state.
S"INT is a word with an xt that performs the interpretation semantics
of S". S"COMP is a word with an xt that performs the compilation
semantics of S". The implementation may be:
: s"int '"' parse save-mem ;
: s"comp '"' parse postpone sliteral ;
INTERPRET/COMPILE: ( xt-int xt-comp "name" -- ) is a word that defines
"name" with the interpretation semantics being to perform xt-int, and
the compilation semantics being to perform xt-comp.
Your description and INTEPRET/COMPILE: suggest an implementation where
the compilation semantics are always represented by a single xt.
E.g., you might have a separated-header design, where the header of S"
above looks like:
link field: address of the previously defined header
name field: string 'S"'
int field: xt of S"INT
comp field: xt of S"COMP
An immediate word like '(' is easy to define with this header
structure:
:noname ')' parse 2drop ; dup interpret/compile: (
link field: address of the previously defined header
name field: string '('
int field: xt of the :noname-defined word above
comp field: xt of the :noname-defined word above
A normal word like 2DUP is slightly harder to define; for each such
word you have to define an xt that implements the compilation
semantics:
: 2dup-int over over ;
: 2dup-comp ['] 2dup-int compile, ;
' 2dup-int ' 2dup-comp interpret/compile: 2dup
(The names 2DUP-INT and 2DUP-COMP are used here for clarity. In
practice, one would use :NONAME definitions, because they do not
introduce more headers that would need additional compilation
semantics definitions, which would lead to endless recursion.).
Because normal words are so frequent, AFAIK no system has taken this
pure dual-xt approach. This is also catered for in the stack effect
of
NAME>COMPILE ( nt -- xt1 xt2 )
For normal words, you can pass the content of the int field as xt1 and
the xt of COMPILE, as xt2, avoiding the need to have a separate compilation semantics implementation.
For immediate words, you can again pass the content of the int field
as xt1, but you pass the xt of EXECUTE as xt2.
For dual words, you can pass the xt in the comp field as xt1, and the
xt of EXECUTE as xt2.
So how do you know which of these cases you have? A straighforward
way is to design the header so you do not need to know:
link field
name field
int field
comp-xt1 field
comp-xt2 field
A normal definition stores the same xt in the int field and in
comp-xt1, and stores the xt of COMPILE, in comp-xt2. IMMEDIATE writes
the xt of EXECUTE into the comp-xt2 field. A word defined with
INTERPRET/COMPILE: stores xt-int in the int field, xt-comp in the
comp-xt1 field, and the xt of EXECUTE in the comp-xt2 field.
The new Gforth header [paysan19] takes a different approach, though.
It has fields that contain the xts for performing NAME>INTERPRET and
NAME>COMPILE on this particular header; e.g., NAME>COMPILE is
implemented like
: name>compile ( nt -- xt1 xt2 ) dup name>compile-field @ execute ;
This allows to implement them very flexibly. For normal words, the
NAME>INTERPRET field contains ' NOOP (the nt and the xt point to the
same place for normal words in the new header), and the NAME>COMPILE
field contains
: default-name>comp ( nt -- xt1 xt2 ) ['] compile, ;
i.e., xt1=nt, nt2=COMPILE,
For immediate words, the NAME>INTERPRET field contains ' NOOP, and the
NAME>COMPILE field contains the xt of
: imm>comp ( nt -- xt1 xt2 ) name>int ['] execute ;
For a word defined with INTERPRET/COMPILE:, such as S", the body
contains an int field and a comp field (similar to the straightforward
header above), and the NAME>INTERPRET field contains the xt of
: a>int ( nt -- xt-int ) >body @ ;
and the NAME>COMPILE field contains the xt of
: i/c>comp ( nt -- xt1 xt2 )
>body cell+ @ ['] execute ;
The new Gforth header is very flexible, also supporting standard features
like "to name" semantics, synonyms and a number of non-standard
features like per-task deferred words (defined with udefer) without
needing to add flag after flag to the header and corresponding ifs to
the code dealing with headers. Read all about it in:
@InProceedings{paysan19,
author = {Bernd Paysan and M. Anton Ertl},
title = {The new {Gforth} Header},
crossref = {euroforth19},
pages = {5--20},
url = {
http://www.euroforth.org/ef19/papers/paysan.pdf},
url-slides = {
http://www.euroforth.org/ef19/papers/paysan-slides.pdf},
video = {
https://wiki.forth-ev.de/doku.php/events:ef2019:header},
OPTnote = {refereed},
abstract = {The new Gforth header is designed to directly
implement the requirements of Forth-94 and
Forth-2012. Every header is an object with a fixed
set of fields (code, parameter, count, name, link)
and methods (\texttt{execute}, \texttt{compile,},
\texttt{(to)}, \texttt{defer@}, \texttt{does},
\texttt{name>interpret}, \texttt{name>compile},
\texttt{name>string}, \texttt{name>link}). The
implementation of each method can be changed
per-word (prototype-based object-oriented
programming). We demonstrate how to use these
features to implement optimization of constants,
\texttt{fvalue}, \texttt{defer}, \texttt{immediate},
\texttt{to} and other dual-semantics words, and
\texttt{synonym}.}
}
>>> Does it then follow that
>>>
>>> 1) The word IMMEDIATE may be removed from the standard,
>>
>> You still want to be able to load existing programs, so that probably
>> will not happen.
>>
>
>Under the hypothetical standard, IMMEDIATE should be definable as word
>which retrieves the last named definition's interpretation semantics and
>sets the word's compilation semantics to the same xt. So that's not
>really an issue for backwards compatibility.
So the question is "Can IMMEDIATE be defined on such a dual-xt
system?" Yes, it can. In the straightforward dual-xt system that
would be
: immediate latest dup int-field @ swap comp-field ! ;
In the variant with comp-xt1 and comp-xt2 it would be
: immediate ['] execute latest comp-xt2-field ! ;
In development Gforth, it is
: imm>comp name>int ['] execute ;
: immediate ( -- ) \ core
['] imm>comp set->comp ;
>>> 2) All ambiguous conditions for use of ' (tick), ['], and POSTPONE with
>>> any standard word or user-defined colon definitions, in either
>>> compilation or interpretation state, may be eliminated,
>>
>> Those that come to my mind at the moment, yes.
>>
>
>Good. It is possible that some words have one or the other xt set to
>NOOP (no-operation), but that's fine.
NOOP does not make much sense as the interpretation semantics or
compilation semantics of all words but NOOP. If the interpretation
semantics are undefined (e.g., for IF), you can put
: no-intsem -14 throw ;
in the int field. However, our experience is that a number of users
expect that these words have an interpretation semantics that's the
same as the defined compilation semantics, i.e., that these words are
defined like
: if postpone ?branch >mark? ; immediate
so in the current development version that is what we do.