Proposal: Tighten the specification of SYNONYM (version 1)

Informal

This proposal has been moved into this section. Its former address was: /standard/tools/SYNONYM

This page is dedicated to discussing this specific proposal

ContributeContributions

GerryJacksonavatar of GerryJackson Tighten the specification of SYNONYM (version 1)Proposal2018-06-08 10:09:18

Problem

Since SYNONYM has been incorporated into the Forth 2012 standard a number of use cases have been discussed that can result in different Forth 2012 systems giving different results. Therefore the specification for SYNONYM needs to be tightened to either specify the results of those cases or to make them ambiguous conditions. This RfD addresses those use cases and proposes solutions.

Terminology: in this RfD given this definition: SYNONYM BAR FOO FOO will be referred to as the original word, BAR as the synonym.

The guiding principle in this RfD is one of 'least surprise to the user'. Following use of SYNONYM a reasonable user expectation is that the synonym can be used in exactly the same way as the original word: the functionality and usage of them should be identical, the same operations should be applicable to them and they should have the same restrictions on usage.

Six aspects of the use of SYNONYM have identified that need to be clarified in the standard.

1) Restrictions (ambiguous conditions).

Given SYNONYM NEW-TO TO then ' NEW-TO is not designated an ambiguous condition by the standard whereas ' TO is

This particular example demonstrates that a synonym should inherit all the restrictions placed on the original word.

2) Values (VALUE, 2VALUE and FVALUE)

Given 123 VALUE FOO SYNONYM BAR FOO The view of the current Forth 2012 committee is that: 456 TO BAR is not permitted by the standard. but of course 456 TO FOO is permitted which may or may not result in FOO and BAR containing the same value.

Contrast this with synonyms of variables where storing a new value in a variable can be done on either the original word or the synonym and, in either case, their contents remain identical.

Therefore the guiding principle indicates that it should be legal for TO to be applied to the synonym of a value and that the values of the original word and its synonym should remain in step whichever word is updated using TO.

3) Deferred Words

Given DEFER FOO SYNONYM BAR FOO

As with TO above, writing ( xt ) IS BAR is not allowed whereas ( xt ) IS FOO is permitted and executing FOO is not guaranteed to give the same result as executing BAR

Similarly there are problems with DEFER!, DEFER@ and ACTION-OF ' some-word ' BAR DEFER! ' BAR DEFER@ and ACTION-OF BAR are invalid as BAR was not defined by DEFER

After ' some-word ' FOO DEFER! FOO and BAR are not guaranteed to hold the same xt

The guiding principle indicates it should be legal for IS, DEFER@, DEFER! and ACTION-OF to be applied to the synonym of a deferred word and for the XTs held by the synonym and original deferred word to be kept in step following the use of IS or DEFER! on either the synonym or original deferred word.

4) CREATE and >BODY

Given CREATE FOO SYNONYM BAR FOO should ' FOO >BODY and ' BAR >BODY give the same result?

At present ' BAR >BODY is an ambiguous condition since BAR was not defined directly via CREATE

This violates the guiding principle. Therefore >BODY should work on the synonym and the result should be the same address as for >BODY on the original word.

5) CREATE and DOES>

Given : DOESER DOES> ... ; CREATE FOO (zero or more definitions) SYNONYM BAR FOO DOESER should the use of DOESER be valid and, if so, should it operate on both FOO and BAR?

The current position in the standard is that it is invalid as it violates the rule that DOES> operates on the previous definition which has to have been CREATE'd.

If there are no definitions between CREATE FOO and SYNONYM BAR FOO then in some systems it is possible for DOES> to change the behaviour of both FOO AND BAR. But, in the general case if not impossible, that would cause severe implementation difficulties.

Therefore the guiding principle should be ignored in this case and applying DOES> to a synonym should be an ambiguous condition.

6) NAME>STRING

Given : FOO ... ; SYNONYM BAR FOO

TRAVERSE-WORDLIST will produce a name token for FOO and BAR. What result should NAME>STRING give for the name tokens of FOO and BAR?

In this case it seems clear that applying NAME>STRING on:

  • FOO's name token should be "FOO"
  • BAR's name token should be "BAR" Any other result would be surprising (remember that FOO and BAR may be in different wordlists)

Solution

Follow the recommendations listed in the Problem section above. See the proposal below.

Remarks

NAME>INTERPRET and NAME>COMPILE: if they produce the same values for the synonym as for the original, the DEFER@ DEFER! >BODY, and probably also TO, IS, ACTION-OF issues fall out for free. But identical xts are not required

SYNONYM is already forbidden on locals due to the prohibition on definitions inside a colon definition. But that could usefully be noted in a rationale.

Some of the proposed changes could be regarded as bad practice e.g. changing the synonym of a deferred word also changes the original word could be regarded as a hidden side effect, but this already possible with synonyms of variables and Forth is a sharp knife ...

Banning DOES> on a synonym of a CREATEd word is similar to banning IMMEDIATE in that both alter the characteristics of the preceding definition.

Reference Implementation

Not applicable - requires detailed knowledge of the system

Test Cases

1 VALUE val

T{ SYNONYM synval val -> }T

T{ val synval -> 1 1 }T

2 TO val

T{ synval -> 2 }T

T{ 3 TO synval -> }T

T{ val synval -> 3 3 }T

\ Similarly for 2VALUE and FVALUE

DEFER def :NONAME 4 ; IS def

T{ SYNONYM syndef def -> }T

T{ def syndef -> 4 4 }T

T{ :NONAME 5 ; IS syndef }T

T{ def syndef -> 5 5 }T

:NONAME 6 ; CONSTANT defxt

T{ defxt ' syndef DEFER! -> }T

T{ def syndef -> 6 6 }T

T{ ' syndef DEFER@ ' def DEFER@ -> defxt DUP }T

T{ ACTION-OF syndef -> defxt }T

CREATE cre

T{ SYNONYM syncre cre -> }T

T{ ' cre >BODY ' syncre >BODY = -> TRUE }T

\ Testing NAME>STRING is complicated by the facts that:

\ - TRAVERSE-WORDLIST is the only way to get a name token

\ - the order of nt's provided by TRAVERSE-WORDLIST is undefined

\ - names may be stored in the dictionary in upper or lower case

\ If anyone can suggest a simpler test please post it

WORDLIST CONSTANT synwl

GET-ORDER synwl SWAP 1+ SET-ORDER DEFINITIONS

CREATE n>s1

SYNONYM syn-n>s1 n>s1

PREVIOUS DEFINITIONS

: >lower ( ch -- ch' )

DUP 'A' 'Z' 1+ WITHIN IF BL OR THEN ;

\ Case independent string comparison

: i$= ( caddr1 u1 caddr2 u2 -- f ) \ f = TRUE if strings are equal

ROT OVER <> IF DROP 2DROP FALSE EXIT THEN

0 ?DO

    OVER C@ >lower OVER C@ >lower <>

    IF 2DROP FALSE UNLOOP EXIT THEN

    CHAR+ SWAP CHAR+

 LOOP 2DROP TRUE

;

: get-name ( nt -- caddr u true ) NAME>STRING TRUE ;

: check-names ( caddr1 u1 caddr2 u2 -- f1 f2 )

DUP 4 > IF 2SWAP THEN ( -- "syn-n>s1" "n>s1" )

S" n>s1" i$= >R

S" syn-n>s1" i$= R>

;

T{ ' get-name synwl TRAVERSE-WORDLIST check-names -- TRUE TRUE }T

\ Can't test DOES> on a synonym as there is no portable way to test ambiguous conditions`

Experience

GForth 0.7.9_20171101, VFX Forth 4.72, author's personal system run all test cases Win32 Forth 6.15.04 runs the test cases except for NAME>STRING (not implemented) SwiftForth 3.7.2 hasn't implemented SYNONYM Other systems not tried.

Proposal

In the Forth 2012 Standard document make the following amendments:

Section 15.6.2.2264 SYNONYM

If oldname was created by VALUE, 2VALUE, FVALUE or DEFER then the value held by newname shall be identical to that held by oldname at all times even if TO, IS or DEFER! is applied, as appropriate, to oldname or newname.

If oldname was defined using DEFER then DEFER@ and ACTION-OF applied to oldname shall produce the same xt as DEFER@ and AACTION-OF applied to newname

If oldname was created by CREATE then ' newname >BODY shall result in the same address as that given by ' oldname >BODY.

NAME>STRING shall produce the name of newname/oldname when applied to the name token of newname/oldname respectively.

All ambiguous conditions applicable to oldname shall apply to newname.

An ambiguous condition shall exist if DOES> is applied to newname.

Section 6.2.2295 TO

Amend the end of the Interpretation: and Compilation: paragraphs to read ... if name was not defined by a word with "TO name run time" semantics or the synonym of such a word.

Section 6.2.1725 IS

Amend the end of the Interpretation: and Compilation: paragraphs to read ... if name was not defined by DEFER or the synonym of such a word.

Sections 6.2.1175 DEFER! and 6.2.1177 DEFER@

Amend the end of the first paragraph to read ... word defined by DEFER or the synonym of such a word.

Section 6.2.0698

Amend the end of the Interpretation and Compilation paragraphs to read ... not defined by DEFER or the synonym of such a word, or if ...

Section 6.1.0550 >BODY

Amend the end of the description to read ... defined via CREATE or the synonym of such a word.

BerndPaysanavatar of BerndPaysan

For the test cases: Since we have a proposal for FIND-NAME to produce NTs, you can use FIND-NAME as test vehicle.

A reference implementation of FIND-NAME using TRAVERSE-WORDLIST should be available in the FIND-NAME proposal soon (Anton is wrong that FIND-NAME-IN requires carnal knowledge).

JennyBrienavatar of JennyBrien

So either quoting a synonym returns the original xt or >BODY etc. are aware of synonyms and do the necessary adjustment?

What happens when you make a synonym of another synonym?

BerndPaysanavatar of BerndPaysan

This should pass (does so in Gforth):

create foo
synonym bar foo
t{ ' foo -> ' foo }t
synonym baz bar
t{ ' baz -> ' foo }t

No, >body and friends should not know anything about synonyms. The only place where synonym deserve special attention is in name>compile and name>interpret. Since this proposal is to tighten down synonym, it's better to make clear that it mandates where the treatment of synonyms has to happen.

BerndPaysanavatar of BerndPaysan

Can I have an edit button?

First test shall be

t{ ' bar -> ' foo }t

GerryJacksonavatar of GerryJackson

For the test cases: Since we have a proposal for FIND-NAME to produce NTs, you can use FIND-NAME as test vehicle

Yes that certainly simplifies things. The test for FIND-NAME of synonyms then becomes (i$= the case independent compare is still needed):

CREATE n>s1
SYNONYM syn-n>s1 n>s1
T{ S" n>s1" 2DUP FIND-NAME NAME>STRING i$= -> TRUE }T
T{ S" syn-n>s1" 2DUP FIND-NAME NAME>STRING i$= -> TRUE }T

GerryJacksonavatar of GerryJackson

First test shall be: t{ ' bar -> ' foo }t

This requires the xt's to be the same, Anton didn't think that was necessary - I don't mind either way

AntonErtlavatar of AntonErtl

Letting all synonyms have the same xt is certainly a good solution. Should we require it? I don't know a reason for or against (in particular, I don't think that there is a system that has SYNONYM where synonyms of the same word have different xts), so in the spirit of tightening, we probably should require it.

In the proposal, separate the TO cases from the IS/DEFER! to make it watertight.

AACTION-OF should be ACTION-OF

"shall": The style for ambiguous conditions has been: "An ambiguous condition exists if...".

6.2.0698: Mention that this is ACTION-OF

Put the test cases in code style (surround with ``` lines) or in a separate file.

There is no need to test for ambiguous conditions. These are the cases that a standard program should avoid.

JennyBrienavatar of JennyBrien

Anton wrote:

Letting all synonyms have the same xt is certainly a good solution. Should we require it? I don't know a reason for or against (in particular, I don't think that there is a system that has SYNONYM where synonyms of the same word have different xts), so in the spirit of tightening, we probably should require it.

I don't see any objection. I picture SYNONYM as being equivalent to creating an identical header with a possibly different name in a system with detatched headers. I.e. it points to the same code and data space. I think all the restrictions above flow naturally from that.

I think there was, years ago, a proposal for a word ALIAS ( xt name -- ) , that only copied the execution and created a defition with default compiling semantics. Was it suggested that should return the same xt when ticked? I don't think it's possible, under VFX, to have two words with the same xt but different compiling semantics, though I could be wrong.

AntonErtlavatar of AntonErtl

Yes, different systems would behave differently for ALIASes of immediate words, and when applying IMMEDIATE to an alias; and in particular, one passes an xt to ALIAS, and in Gforth, the xt is not associated with immediacy. That's why we standardized SYNONYM, no ALIAS, and why applying IMMEDIATE to a synonym is ambiguous.

JennyBrienavatar of JennyBrien

I see. I was thinking of the twin xt syntax for defining dual word as a factor of SYNONYM

   i-xt c-xt DUAL: *name*  defines a dual word
   0    c-xt DUAL: *name*  defines a  compile-only word 
   xt dup  DUAL: *name*  defines an immediate word
     xt.      ALIAS:  *name* defines a default word

But I don't see how to make it work with VFX

AntonErtlavatar of AntonErtl

Your DUAL: is quite simular to Gforth's INTERPRET/COMPILE:. In a system where the compilation semantics hangs on the i-xt, such a word would either set the compilation semantics of other words with the same i-xt, or would have to introduce a new i-xt (e.g., a deferred word), but then it becomes harder to use this word for defining a synonym. I guess we won't be seeing such a word standardized, though.

ruvavatar of ruv

Some comments.

1. Reference implementation

The current reference implementation is not correct for the new specification, therefore it should be updated or removed.

2. Execution semantics

The same execution semantics should be also mentioned. Otherwise, ticking a synonym is implicitly ambiguous.

3. Synonym of a defining word

It seems, the proposed specification does not take into account the case of a synonym of a defining word, but perhaps it should.

E.g. "defined via CREATE or the synonym of such a word" — i.e. the synonym of a word that was defined via CREATE. But what about the following:

SYNONYM C CREATE
C X 0 ,

Is X defined via CREATE? It is not clear.

OTOH, in the case like : C CREATE ; C X 0 , it is clear that X is defined via CREATE, and therefore >BODY is applicable for the corresponding xt.

Nevertheless, for DOES> the specification says: "if name was not defined with CREATE or a user-defined word that calls CREATE". I wonder why does not it say the same for >BODY.

4. Terminology

The fragment "DOES> is applied to newname" looks not quite correctly. I think it should look like "DOES> run-time semantics is performed when newname is the most recent definition".

But this statement is not needed at all since this ambiguous condition already exists due to: "An ambiguous condition exists if name was not defined with CREATE or a user-defined word that calls CREATE".

5. Absent issue

At least one issue that is mention in "Problem" section (in items 2, 3) is actually absent: the current specification guarantees that a synonym contains the same value, and a synonym always produces the same result as the original word, due to the same interpretation and compilation semantics.

ruvavatar of ruv

DOES> and synonym

But, in the general case if not impossible, that would cause severe implementation difficulties.

If >BODY and IS are work correctly for synonyms, what is a possible problem with DOES> ?

If you know the BODY address of oldname, isn't it enough to know whatever else and change the behavior?

If a synonym (newname) works correctly when you change oldname via IS, why cant newname work in the case of DOES> (i.e. when DOES> changes behavior of oldname)?

Reply New Version