6.2.0945 COMPILE, compile-comma CORE EXT

Interpretation:

Interpretation semantics for this word are undefined.

Execution:

( xt -- )

Append the execution semantics of the definition represented by xt to the execution semantics of the current definition.

See:

Rationale:

COMPILE, is the compilation equivalent of EXECUTE.

In traditional threaded-code implementations, compilation is performed by , (comma). This usage is not portable; it doesn't work for subroutine-threaded, native code, or relocatable implementations. Use of COMPILE, is portable.

In most systems it is possible to implement COMPILE, so it will generate code that is optimized to the same extent as code that is generated by the normal compilation process. However, in some implementations there are two different "tokens" corresponding to a particular definition name: the normal "execution token" that is used while interpreting or with EXECUTE, and another "compilation token" that is used while compiling. It is not always possible to obtain the compilation token from the execution token. In these implementations, COMPILE, might not generate code that is as efficient as normally compiled code.

The intention is that COMPILE, can be used as follows to write the classic interpreter/compiler loop:

...                                                 ( c-addr )
FIND ?DUP IF                                     ( xt +-1 )
   STATE @ IF                                     ( xt +-1 )
     0> IF EXECUTE ELSE COMPILE, THEN   ( ??? )
   ELSE                                            ( xt +-1 )
     DROP EXECUTE                                ( ??? )
   THEN
ELSE                                              ( c-addr )
   ( whatever you do for an undefined word )
THEN
...

Thus the interpretation semantics are left undefined, as COMPILE, will not be executed during interpretation.

Testing:

:NONAME DUP + ; CONSTANT dup+
T{ : q dup+ COMPILE, ; -> }T
T{ : as [ q ] ; -> }T
T{ 123 as -> 246 }T

ContributeContributions

ruvavatar of ruv [87] Interpretation semanticsComment2019-06-26 12:50:14

According to "4.1.2 Ambiguous conditions", a standard programme can't obtain the execution token of a definition with undefined interpretation semantics. So, it can't obtain xt of COMPILE, word by any means (according to the current specification for this word).

And the following code is not standard — without any solid reason:

: foo [ ' DUP COMPILE, ] ; 

But the following code is standard:

: bar COMPILE, ;
: foo [ ' DUP bar ] ; 

So, COMPILE, should be a regular word with single semantics (the execution semantics). But executing of this word when current definition was not started (by :NONAME or :, or other similar words if any) should be an ambiguous condition.

AntonErtlavatar of AntonErtl

I agree.

Appending something to the current definition when there is no current definition is obviously not a well-defined operation. Explicitly making it an ambiguous condition would be a good idea.

StephenPelcavatar of StephenPelc

An ambiguous condition is not an error - it just indicates that different systems do different things. GForth is very strict. VFX is very tolerant - all words with names have FINDable XTs. This does not mean that executing the XT is useful or safe. It just means that an XT exists. We (MPE) use XTs for all sorts of functions like LOCATE and XREF tools. As a result of this ambiguity, words such as ' and ['] usually inherit their system's view of the world. For me, Forth is a dangerous language and should stay that way.

ruvavatar of ruv

I could say that it is a mistake if a standard program contains an ambiguous condition (or unspecified behavior). The program just becomes non standard thereby. Standard programs cannot contain the ambiguous conditions — by definition (recently proposed by me). Therefore, whatever a Forth system does in an ambiguous condition — it does not matter, a standard program shall never reach this condition.

In other words, the ambiguous conditions describe the things that standard programs should never do.

Regarding COMPILE, word, — a standard program shall not execute this word if there is no current definition (assuming that we will have added the corresponding clause into the specification).

ruvavatar of ruvNew Version: [87] Interpretation semantics

Hide differences

According to "4.1.2 Ambiguous conditions", a standard programme can't obtain the execution token of a definition with undefined interpretation semantics. So, it can't obtain xt of COMPILE, word by any means (according to the current specification for this word).

A basis for the following statement is unclear:

And the following code is not standard — without any solid reason:

: foo [ ' DUP COMPILE, ] ; 

Thus the interpretation semantics are left undefined, as COMPILE, will not be executed during interpretation.

But the following code is standard:

: bar COMPILE, ;
: foo [ ' DUP bar ] ; 

Why will not COMPILE, be executed during interpretation?

So, COMPILE, should be a regular word with single semantics (the execution semantics). But executing of this word when current definition was not started (by :NONAME or :, or other similar words if any) should be an ambiguous condition.

A possible explanation is that the author of this statement (and perhaps some other members of the X3J14 Technical Committee) believed that appending semantics to the current definition may take place in compilation state only [1]. In such case COMPILE, is allowed to be executed in compilation state only, and therefore both executing in interpretation state and the interpretation semantics are ambiguous for this word. (And in such case even the second example above would be a non standard code)

It seems this reason is also why we have special LITERAL in place of ordinary LIT, (and the same for other literals).

Eventually this requirement (appending semantics in compilation state only) was not included into the normative part of the standard, but some shadows remained.

I think, now we can remove "Interpretation:" section of this glossary entry and the statement quoted above. Perhaps "Interpretation:" section can be also removed for CS-PICK, CS-ROLL, (LOCAL) and Left-bracket.

[1] See: RFI 9, Bernd Paysan on 04 Jun 1996 (txt)

ruvavatar of ruv

Eventually this requirement (appending semantics in compilation state only) was not included into the normative part of the standard, but some shadows remained.

It should be noted that an official clarification was made in this regard, see TC reply to RFI Q99-027 (the request was prepared by Philip Preston on 1998-10-17).

According to this clarification:

  1. It is an ambiguous condition for a program to perform compilation semantics in the interpretation state.
  2. It is an ambiguous condition for a program to append semantics to the current definition in the interpretation state.

I have started the new discussion on this in comp.lang.forth.

Reply New Version

ruvavatar of ruv [248] Implementing COMPILE, via EXECUTESuggested reference implementation2022-08-12 10:21:25

compile, can be implemented in the following way:

: compile, ( xt -- )  postpone literal  postpone execute ;

It's not an efficient implementation, but a correct and portable one.

lmravatar of lmr

: compile, ( xt -- ) postpone literal postpone execute ; It's not an efficient implementation, but a correct and portable one.

The postpone execute part above needs to append execute's XT to the current definition, i.e. a COMPILE, itself

ruvavatar of ruv

In general, reference implementations do not need to avoid recursive dependencies (when several words uses each other, directly or indirectly), since they actually are not connected with each other. «They are supplied solely for the purpose of providing a detailed understanding of a definitions requirement» (E.1). See also my another comment.

Reply New Version

lmravatar of lmr [328] throw code for compiling outside a definitionRequest for clarification2024-01-05 08:52:21

Based on previous comments it's quite clear that both LITERAL and COMPILE, should to check at runtime whether they are appending to an existing definition, or (as GForth puts it) "compiling outside a definition". Merely disallowing their usage in @ STATE zero is not enough. But I'm wondering, if the system detects an attempt to append to a non-existing definition, what would be the most appropriate error code? -14 (interpreting a compile-only word)? -9 (invalid address)?

AntonErtlavatar of AntonErtl

There is no established throw code for compiling outside a colon definition, so you can choose a system-specific one, if you want to throw an error (most systems don't).

Concerning state, the existence of '[' and ']' means that state @ does not tell you at all whether you are inside a colon definition. E.g.

: myliteral postpone literal ; immediate \ myliteral has interpretation semantics
: mycompile, compile, ; \ mycompile, has interpretation semantics
: test
  [ 1 myliteral ] \ compiling inside a colon definition in interpret state
  [ ' + mycompile, ] \ compiling inside a colon definition in interpret state
;
] + [ \ compiling outside a colon definition in compile state

Everything but the last line is a standard program, the last line is non-standard.

Closed
Reply New Version