On 2022-10-07 03:01, Krishna Myneni wrote:
> On 10/6/22 15:40, Ruvim wrote:
>> On 2022-10-05 09:26, Krishna Myneni wrote:
[...]
>
> In contrast, in dual-xt systems, there is no need for the term
> "execution semantics".
Even if some standard dual-xt system doesn't need the term "execution
semantics" under the hood, it shall map the standard notions of
"execution semantics" and "identifier of execution semantics" to its
internal notions.
Have a look:
:noname 123 . ; ( xt )
For a standard program it does not matter what this xt means in your
system under the hood, and how you call it internally.
For a standard program this xt is an identifier of execution semantics,
namely of the execution semantics that are defined in the body of this
unnamed definition.
[...]
>>> Your points above about execution token not always representing the
>>> interpretation semantics are valid for a traditional Forth system,
>>> but when you tick a word name, how do you know which semantics are
>>> being returned?
>>
>> Actually, I may tick only ordinary or immediate word.
>> Anyway, when I Tick a word, it returns an identifier of the execution
>> semantics for the word.
>>
>
> In a dual-xt system, which xt do you expect tick or ['] to return?
> xt-interp or xt-comp? It should return xt-interp for backward
> compatibility with single-xt systems.
The standard does not specify a notion of xt-interp or xt-comp.
On any standard system Tick shall return an xt that identifies the
execution semantics of a word.
When a user defines a word via Colon, he defines the execution semantics
for this word.
For example, see 6.1.0450 : (colon)
| The execution semantics of /name/ will be determined
| by the words compiled into the body of the definition.
For the most standard words the execution semantics are specified.
When execution semantics are not specified for a standard word, the
system may provide implementation-dependent execution semantics for the
word. But it's ambiguous to perform these execution semantics in the
general case, and it's ambiguous even to apply Tick to such a standard word.
In a dual-xt system I would make the first xt identify the execution
semantics for the word. The second xt — identifies the execution
semantics of a definition that is used to perform the special
compilation semantics for a word (if any).
I would not provide the "name>interpret" and "name>compile" words since
they are flawed by design and insufficiently specified to be usable on
any standard system.
I would provide "find", "find-name", and words as:
find-semantics (
sd.name -- xt1 xt2 ) \ stateless
compile-name ( i*x nt -- j*x )
interpret-name ( i*x nt -- j*x )
Well, having internal words like
name>xt ( nt -- xt true | nt false )
name>xt2 ( nt -- xt true | nt false )
The words of an public API can be defined as follows:
: compilation ( -- flag ) state @ 0<> ;
: leave-compilation ( -- ) ] ;
: enter-compilation ( -- ) postpone [ ;
: execute-interpretively ( i*x xt -- j*x )
compilation 0= if execute exit then
leave-compilation execute enter-compilation
;
: execute-compilatively ( i*x xt -- j*x )
compilation if execute exit then
enter-compilation execute leave-compilation
;
: interpret-name ( i*x nt -- j*x )
name>xt 0= -14 and throw execute-interpretively
;
: compile-name ( i*x nt -- j*x )
name>xt2 if execute-compilatively exit then
name>xt 0= -14 and throw compile,
;
: postpone-name ( nt -- )
\ portable implementation
lit, ['] compile-name compile,
;
: postpone-name ( nt -- )
\ system-specific implementation, which is slightly more efficient
name>xt2 if lit, ['] execute-compilatively compile, exit then
name>xt 0= -32 and throw lit, ['] compile, compile,
;
: postpone ( "name" -- )
parse-name find-name dup 0= -32 and throw postpone-name
; immediate
: find-semantics (
sd.name -- xt.word|0 xt.special-com|0 )
\ stateless
find-name dup 0= if 0 exit then
dup name>xt and swap name>xt2 and
;
: find-word? (
sd.name -- xt flag.special true | false )
\ stateful
find-semantics compilation if
dup if nip true true exit then drop
dup if false true exit then ( false )
exit
then
over 0= if 2drop false exit then 0<> true
;
: find-word (
sd.name -- xt flag.special true |
sd.name false )
\ stateful
2dup 2>r find-word? dup if 2rdrop exit then drop 2r> false
;
: find ( c-addr -- c-addr 0 | xt 1 | xt -1 )
\ stateful
dup >r count find-word? 0= if r> 0 exit then rdrop
if 1 else -1 then
;
: immediate ( -- )
latest-name name>xt -32 ?throw name-xt2!
;
: compile: ( "name" -- ) ( C: -- colon-sys )
parse-name find-name dup -13 ?throw >r
['] :noname execute-balance 1- pick r> name-xt2!
;
Where
\ latest-name ( -- nt )
\ Return the name token nt for the definition
\ whose name was placed into the compilation word list most recently,
\ or throw an exception if there is no such a definition.
: execute-balance ( i*x xt -- j*x n )
\ Take xt, execute it and place on the stack
\ the stack depth difference
depth 1- >r execute depth r> -
;
--
Ruvim