Sujet : Re: single-xt approach in the standard
De : ruvim.pinka (at) *nospam* gmail.com (Ruvim)
Groupes : comp.lang.forthDate : 18. Sep 2024, 11:34:47
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <vceac8$3unj9$5@dont-email.me>
References : 1 2
User-Agent : Mozilla Thunderbird
On 2024-09-17 23:12, Anthony Howe wrote:
On 2024-09-17 06:54, Ruvim wrote:
Do you think that the Forth standard should recognize the classic single-xt approach as possible for implementing a standard Forth system?
>
The classic single-xt approach implies that only one execution token (xt) is associated with a name token (nt), and only one name token is associated with a word (a named Forth definition). And words whose compilation semantics differ form default compilation semantics are implemented as immediate words.
Given I prefer single-xt (currently),
Me too.
Actually, most Forth systems are classic single-xt systems. And most educational materials on how to implement Forth explain the classic single-xt approach.
One example:
https://github.com/uho/minimalsee:
https://github.com/uho/minimal/blob/master/compiling-words.fswhat I don't get is how for a dual-xt system you define a single word with two actions for interpret and compile. I don't see a word to distinguish between the two, except maybe IMMEDIATE.
: s" ( "ccc" -- sd | )
[char] " parse
state @ if postpone sliteral exit then
dup >r allocate throw tuck r@ move r>
; immediate
Do you define the same word twice, once for compile (immediate) and again for interpret (order of definitions should not be important). Example:
: s" ( "ccc" -- sd | ) postpone sliteral ; immediate
: s" ( "ccc" -- sd | ) dup >r allocate throw tuck r@ move r> ;
Namely this cannot be standard compliant. But yes, something similar. There are different ways in different systems.
For example, it might look like this:
: s" ( "ccc<quot>" -- ) postpone sliteral ; immediate
interpret: s" ( "ccc<quot>" -- sd )
dup >r allocate throw tuck r@ move r>
;
or
interp: s" ( "ccc<quot>" -- sd )
dup >r allocate throw tuck r@ move r>
;interp
Where (in a classic single-xt system):
: interpret: ( "<spaces>name" -- colon-sys )
parse-name get-current search-wordlist
dup 0 = abort" (not found; comp semantics must be defined first)"
-1 = abort" (the found word is not immediate)"
( xt.compilation ) build-interpretation-slot ( a-addr )
>r depth >r :noname ( xt colon-sys ) r> 1- roll r> !
;
: obtain-interpretation ( xt1 -- xt1 | xt2 )
dup lookup-interpretation-slot dup if nip @ exit then drop
;
: find ( c-addr -- c-addr 0 | xt 1 | xt -1 )
find dup if dup 1 = if state @ 0= if
>r obtain-interpretation r>
then then then
;
: name>interpret ( nt -- xt|0 )
name>interpret obtain-interpretation
;
And this makes a classic single-xt system a dual-xt system.
But we still have to execute the result of "name>interpret" *only* in interpretation state if we want to perform the interpretation semantics of the word. Because we don't know whether the execution semantics identified by the returned xt depend on STATE. And if they depend, we must execute them in interpretation state to perform the interpretation semantics.
Therefore, having a second xt gives us little benefit.
NB: when we want to perform the interpretation semantics for a word, we want to perform *exactly* the behavior that the system exhibits when the name of that word is encountered by the Forth text interpreter in interpretation state. There are no examples yet where we need anything else.
-- Ruvim