Proposal: New words: latest-name and latest-name-in

Formal

This page is dedicated to discussing this specific proposal

ContributeContributions

ruvavatar of ruv [311] New words: latest-name and latest-name-inProposal2023-10-23 01:13:22

Author

Ruv

Change Log

  • 2023-10-22 Initial revision

Problem

In some applications, mainly in libraries and extensions, the capability to obtain the most recently added definition is very useful and demanded.

For example, if we are creating a library for decoration, tracing, support for OOP, simple DSLs (e.g., to describe Final State Machines), etc — it is always useful to have an accessor to the recent definition, instead of redefining a lot of words to define such an access method yourself, or juggling with the input buffer and search.

However, many Forth systems have such internal methods to access the recently added word. Among them: latest ( -- nt|0 ), last @ ( -- nt|0 ), latestxt ( -- xt|0 ), etc.

And additionally, there has been much discussions regarding standardization of such a method in recent decades. For example, Elizabeth D. Rather wrote on 2011-12-09 in comp.lang.forth:

AFAIK most if not all Forths have some method for knowing the latest definition, it's kinda necessary. The problem is, that they all do it differently (at different times, in different forms, etc.), which is why it hasn't been possible to standardize it.

Although it's a system necessity, I haven't found this of much value in application programming.

Elizabeth D. Rather

It's true: depending on the system, an internal method can return the recent word regardless of the compilation word list, or depending on the compilation word list, a completed definition, or not yet completed definition, also unnamed definition, or only named definition, etc.

Nevertheless, the author convinced that we can standardize a consistent method that solves the problem.

Solution

Let's introduce the following words:

  • LATEST-NAME-IN ( wid -- nt|0 )
  • LATEST-NAME ( -- nt )

The former word returns the name token for the definition name that was placed most recently into given word list, or zero if this word list is empty.

The latter word returns the name token for the definition name that was placed most recently into the compilation word list, or throws an exception if such a definition is absent.

It seems, the best place for these words is the section 15.6.2 Programming-Tools extension words), where TRAVERSE-WORDLIST is also placed.

Rationale

Connection with word lists

By considering definitions in the frame of a word list only, we solve several problems, namely:

  1. A word list contains only completed definitions (see the accepted proposal #153 Traverse-wordlist does not find unnamed/unfinished definitions). This eliminates the question of whether the word of returned nt is finished — yes, it is always finished (completed).

  2. Unnamed definitions are not considered since they are not placed into the compilation word list (regardless of whether the system creates a name token for them, or places them into an internal system-specific word list).

  3. An extension or library can create definitions in its internal word list for internal purposes. And it will not affect the compilation word list or other user-defined word lists. Thus, the user of such library always gets the expected result from latest-name (regardless of what words are created by this library for internal purposes on the fly).

Return values

As a matter of practice, almost all the use cases for the word LATEST-NAME imply that the requested definition exists, and if it doesn't exist, only an error can be reported. So the option to return 0 by this word only burdens users with having to analyze this zero, or redefine this word as:

: latest-name ( -- nt ) latest-name dup 0= -80 and throw ;

If the user needs to handle the case where the compilation word list is empty, they can use the word latest-name-in as:

get-current latest-name-in dup if ( nt ) ... else ( 0 ) drop ... then

Implementation options

In some plausible Forth systems, the word list structure doesn't contain any information about the definition that was placed into this word list most recently. Such systems might not provide the proposed words, or they are changed to keep the mentioned information in the word list structure. It seems, in most systems the word list structure contains this information.

If a system does not implement The optional Search-Order word set, it might not provide the word LATEST-NAME-IN.

Naming

The names for these words LATEST-NAME-IN and LATEST-NAME are similar to FIND-NAME-IN and FIND-NAME. Ditto for stack effects.

Typical use

: STRUCT: ( "name" -- wid.current.old u.offset )
  GET-CURRENT  VOCABULARY
  ALSO  LATEST-NAME NAME> EXECUTE  DEFINITIONS
  0
;

Proposal

Add the following line into the Table 9.1: THROW code assignments:

-80 compilation word list is empty

Add the following sections into 15.6.2 Programming-Tools extension words:

15.6.2.2541 LATEST-NAME-IN

( wid -- nt|0 )
Remove the word list identifier wid from the stack. If this word list is empty, then return 0, otherwise return the name token nt for the definition that was placed most recently into this word list.

15.6.2.2542 LATEST-NAME

( -- nt )
Return the name token nt for the definition that was placed most recently into the compilation word list, if such definition exists. Otherwise throw exception code -80.

Reference implementation

In this implementation we assume that wid is an address that contains nt of the most recently placed definition name into the word list wid.

: LATEST-NAME-IN ( wid -- nt|0 ) @ ;

: LATEST-NAME ( -- nt )
  GET-CURRENT LATEST-NAME-IN  DUP IF EXIT THEN  -80 THROW
;

ruvavatar of ruvNew Version: New words: latest-name and latest-name-in

Hide differences

Author

Ruv

Change Log

  • 2023-10-22 Initial revision
  • 2023-10-23 Add testing, examples, a question to discuss, change the throw code description

Problem

In some applications, mainly in libraries and extensions, the capability to obtain the most recently added definition is very useful and demanded.

For example, if we are creating a library for decoration, tracing, support for OOP, simple DSLs (e.g., to describe Final State Machines), etc — it is always useful to have an accessor to the recent definition, instead of redefining a lot of words to define such an access method yourself, or juggling with the input buffer and search.

However, many Forth systems have such internal methods to access the recently added word. Among them: latest ( -- nt|0 ), last @ ( -- nt|0 ), latestxt ( -- xt|0 ), etc.

And additionally, there has been much discussions regarding standardization of such a method in recent decades. For example, Elizabeth D. Rather wrote on 2011-12-09 in comp.lang.forth:

AFAIK most if not all Forths have some method for knowing the latest definition, it's kinda necessary. The problem is, that they all do it differently (at different times, in different forms, etc.), which is why it hasn't been possible to standardize it.

Although it's a system necessity, I haven't found this of much value in application programming.

Elizabeth D. Rather

It's true: depending on the system, an internal method can return the recent word regardless of the compilation word list, or depending on the compilation word list, a completed definition, or not yet completed definition, also unnamed definition, or only named definition, etc.

Nevertheless, the author convinced that we can standardize a consistent method that solves the problem.

Solution

Let's introduce the following words:

  • LATEST-NAME-IN ( wid -- nt|0 )
  • LATEST-NAME ( -- nt )

The former word returns the name token for the definition name that was placed most recently into given word list, or zero if this word list is empty.

The latter word returns the name token for the definition name that was placed most recently into the compilation word list, or throws an exception if such a definition is absent.

It seems, the best place for these words is the section 15.6.2 Programming-Tools extension words), where TRAVERSE-WORDLIST is also placed.

Rationale

Connection with word lists

By considering definitions in the frame of a word list only, we solve several problems, namely:

  1. A word list contains only completed definitions (see the accepted proposal #153 Traverse-wordlist does not find unnamed/unfinished definitions). This eliminates the question of whether the word of returned nt is finished — yes, it is always finished (completed).

  2. Unnamed definitions are not considered since they are not placed into the compilation word list (regardless of whether the system creates a name token for them, or places them into an internal system-specific word list).

  3. An extension or library can create definitions in its internal word list for internal purposes. And it will not affect the compilation word list or other user-defined word lists. Thus, the user of such library always gets the expected result from latest-name (regardless of what words are created by this library for internal purposes on the fly).

Return values

As a matter of practice, almost all the use cases for the word LATEST-NAME imply that the requested definition exists, and if it doesn't exist, only an error can be reported. So the option to return 0 by this word only burdens users with having to analyze this zero, or redefine this word as:

: latest-name ( -- nt ) latest-name dup 0= -80 and throw ;

If the user needs to handle the case where the compilation word list is empty, they can use the word latest-name-in as:

get-current latest-name-in dup if ( nt ) ... else ( 0 ) drop ... then

Implementation options

In some plausible Forth systems, the word list structure doesn't contain any information about the definition that was placed into this word list most recently. Such systems might not provide the proposed words, or they are changed to keep the mentioned information in the word list structure. It seems, in most systems the word list structure contains this information.

If a system does not implement The optional Search-Order word set, it might not provide the word LATEST-NAME-IN.

Naming

The names for these words LATEST-NAME-IN and LATEST-NAME are similar to FIND-NAME-IN and FIND-NAME. Ditto for stack effects.

Things to discuss

Is it worth introducing the word LATEST-NAME-XT ( -- xt )?

If name>interpret never returns 0 (see my comment), this word can be implemented as:

: latest-name-xt ( -- xt ) latest-name name>interpret ;

The desired (and much discussed) pattern is:

defer bar

: foo ... ; latest-name-xt is bar

Sometimes the name "it" has been suggested for this word, but this name is too short and has more chance for conflicts. Guido Draheim wrote in comp.lang.forth on 2003-03-16:

I think that everyone has been thinking of using IT for something really clever, it's a nice short word - and I'd say that we should leave it for application usage.

I want to support that argument also with real life experience in the telco world where there are a whole lot of abbreviations for various services, signals, connectors around. All too often now I see people making a SYNONYM at the file-start to get a second name for an ANS forth word that is needed in the implemenation but coincides with a common term of the application.

This seems convincing to me.

Typical use

: STRUCT: ( "name" -- wid.current.old u.offset )
  GET-CURRENT  VOCABULARY
  ALSO  LATEST-NAME NAME> EXECUTE  DEFINITIONS
  0
;
  \ In the application's vocabulary
  : IT ( -- xt ) LATEST-NAME NAME>INTERPRET ;

  DEFER FOO

  : BAR ... ; IT IS FOO

Proposal

Add the following line into the Table 9.1: THROW code assignments:

-80 compilation word list is empty

-80 latest name is missing

Add the following sections into 15.6.2 Programming-Tools extension words:

15.6.2.2541 LATEST-NAME-IN

( wid -- nt|0 )
Remove the word list identifier wid from the stack. If this word list is empty, then return 0, otherwise return the name token nt for the definition that was placed most recently into this word list.

15.6.2.2542 LATEST-NAME

( -- nt )
Return the name token nt for the definition that was placed most recently into the compilation word list, if such definition exists. Otherwise throw exception code -80.

Reference implementation

In this implementation we assume that wid is an address that contains nt of the most recently placed definition name into the word list wid.

: LATEST-NAME-IN ( wid -- nt|0 ) @ ;

: LATEST-NAME ( -- nt )
  GET-CURRENT LATEST-NAME-IN  DUP IF EXIT THEN  -80 THROW
;

Testing

: IT ( -- xt ) LATEST-NAME NAME>INTERPRET ;

T{ : LN1 ; IT  ' LN1 =  -> TRUE }T
T{ :NONAME [ IT ] LITERAL ; EXECUTE  ' LN1 =  -> TRUE }T
T{ : LN2 [ IT ] LITERAL ; LN2  ' LN1 =  -> TRUE }T

ruvavatar of ruvNew Version: New words: latest-name and latest-name-in

Hide differences

Author

Ruv

Change Log

  • 2023-10-22 Initial revision
  • 2023-10-23 Add testing, examples, a question to discuss, change the throw code description
  • 2023-10-27 Some rationales and explanations added, the throw code description changed back, better wording in some places

Problem

In some applications, mainly in libraries and extensions, the capability to obtain the most recently added definition is very useful and demanded.

For example, if we are creating a library for decoration, tracing, support for OOP, simple DSLs (e.g., to describe Final State Machines), etc — it is always useful to have an accessor to the recent definition, instead of redefining a lot of words to define such an access method yourself, or juggling with the input buffer and search.

However, many Forth systems have such internal methods to access the recently added word. Among them: latest ( -- nt|0 ), last @ ( -- nt|0 ), latestxt ( -- xt|0 ), etc.

And additionally, there has been much discussions regarding standardization of such a method in recent decades. For example, Elizabeth D. Rather wrote on 2011-12-09 in comp.lang.forth:

AFAIK most if not all Forths have some method for knowing the latest definition, it's kinda necessary. The problem is, that they all do it differently (at different times, in different forms, etc.), which is why it hasn't been possible to standardize it.

Although it's a system necessity, I haven't found this of much value in application programming.

Elizabeth D. Rather

It's true: depending on the system, an internal method can return the recent word regardless of the compilation word list, or depending on the compilation word list, a completed definition, or not yet completed definition, also unnamed definition, or only named definition, etc.

Nevertheless, the author convinced that we can standardize a consistent method that solves the problem.

Thus, although almost every Forth system contains such a method, there is no portable way for programs to obtain the latest definition.

Solution

Let's introduce the following words:

  • LATEST-NAME-IN ( wid -- nt|0 )
  • LATEST-NAME ( -- nt )

The former word returns the name token for the definition name that was placed most recently into given word list, or zero if this word list is empty.

The first word returns the name token for the definition whose name was placed most recently into the given word list, or zero if this word list is empty.

The latter word returns the name token for the definition name that was placed most recently into the compilation word list, or throws an exception if such a definition is absent.

The second word returns the name token for the definition whose name was placed most recently into the compilation word list, or throws an exception if there is no such definition.

These words do not expose or limit any internal mechanism of the compiler. They just provide information about word lists, like the words FIND-NAME-IN, FIND-NAME, and TRAVERSE-WORDLIST do.

This words are intended for programs. The system may use them, but is not required to do so. The system may continue to use its internal LAST, LATEST, or whatever it was using before.

It seems, the best place for these words is the section 15.6.2 Programming-Tools extension words), where TRAVERSE-WORDLIST is also placed.

Rationale

Connection with word lists

By considering definitions in the frame of a word list only, we solve several problems, namely:

  1. A word list contains only completed definitions (see the accepted proposal #153 Traverse-wordlist does not find unnamed/unfinished definitions). This eliminates the question of whether the word of returned nt is finished — yes, it is always finished (completed).
  1. Unnamed definitions are not considered since they are not placed into the compilation word list (regardless of whether the system creates a name token for them, or places them into an internal system-specific word list).
  1. Nameless definitions are not considered since they are not placed into the compilation word list (regardless of whether the system creates a name token for them, or places them into an internal system-specific word list).
  1. An extension or library can create definitions in its internal word list for internal purposes. And it will not affect the compilation word list or other user-defined word lists. Thus, the user of such library always gets the expected result from latest-name (regardless of what words are created by this library for internal purposes on the fly).

Return values

As a matter of practice, almost all the use cases for the word LATEST-NAME imply that the requested definition exists, and if it doesn't exist, only an error can be reported. So the option to return 0 by this word only burdens users with having to analyze this zero, or redefine this word as:

: latest-name ( -- nt ) latest-name dup 0= -80 and throw ;

If the user needs to handle the case where the compilation word list is empty, they can use the word latest-name-in as:

get-current latest-name-in dup if ( nt ) ... else ( 0 ) drop ... then

Implementation options

If the the word list structure in a Forth system contains information about the latest placed definition, the implementations for the proposed words are trivial.

In some plausible Forth systems, the word list structure doesn't contain any information about the definition that was placed into this word list most recently. Such systems might not provide the proposed words, or they are changed to keep the mentioned information in the word list structure. It seems, in most systems the word list structure contains this information.

If a system does not implement The optional Search-Order word set, it might not provide the word LATEST-NAME-IN.

Naming

The names for these words LATEST-NAME-IN and LATEST-NAME are similar to FIND-NAME-IN and FIND-NAME. Ditto for stack effects.

The names LATEST-NAME-IN and LATEST-NAME of new words are similar to FIND-NAME-IN and FIND-NAME by the form. Stack effects are also similar.

The difference is that find is a verb, but latest is an adjective (or sometimes a noun, see Wiktionary). Both are historical in their use in naming words. As well as "NAME".

In Forth-84 "NAME" in word names denoted NFA (name field address), and now it denotes a name token, which is the successor of NFA. In all standard words, e.g. FIND-NAME, NAME>STRING, NAME>COMPILE, etc. (except PARSE-NAME), "NAME" denotes a name token.

NB: the term "token" in "name token" does not mean a character sequence! It's used in a general sense, like "something serving as an expression of something else" (see Wiktionary).

Throw code description

If the throw code description states that there is no latest name, it can be confusing since latest name in some sense probably always exists.

Therefore, it's better to say: "the compilation word list is empty" — it is what actually happens.

Things to discuss

Is it worth introducing the word LATEST-NAME-XT ( -- xt )?

If name>interpret never returns 0 (see my comment), this word can be implemented as:

: latest-name-xt ( -- xt ) latest-name name>interpret ;

The desired (and much discussed) pattern is:

defer bar

: foo ... ; latest-name-xt is bar

Sometimes the name "it" has been suggested for this word, but this name is too short and has more chance for conflicts. Guido Draheim wrote in comp.lang.forth on 2003-03-16:

I think that everyone has been thinking of using IT for something really clever, it's a nice short word - and I'd say that we should leave it for application usage.

I want to support that argument also with real life experience in the telco world where there are a whole lot of abbreviations for various services, signals, connectors around. All too often now I see people making a SYNONYM at the file-start to get a second name for an ANS forth word that is needed in the implemenation but coincides with a common term of the application.

This seems convincing to me.

Typical use

: STRUCT: ( "name" -- wid.current.old u.offset )
  GET-CURRENT  VOCABULARY
  ALSO  LATEST-NAME NAME> EXECUTE  DEFINITIONS
  0
;
  \ In the application's vocabulary
  : IT ( -- xt ) LATEST-NAME NAME>INTERPRET ;

  DEFER FOO

  : BAR ... ; IT IS FOO

Proposal

Add the following line into the Table 9.1: THROW code assignments:

-80 latest name is missing

-80 the compilation word list is empty

Add the following sections into 15.6.2 Programming-Tools extension words:

15.6.2.2541 LATEST-NAME-IN

( wid -- nt|0 )

Remove the word list identifier wid from the stack. If this word list is empty, then return 0, otherwise return the name token nt for the definition that was placed most recently into this word list.

Remove the word list identifier wid from the stack. If the corresponding word list is empty, then return 0; otherwise, return the name token nt for the definition whose name was placed most recently into this word list.

15.6.2.2542 LATEST-NAME

( -- nt )

Return the name token nt for the definition that was placed most recently into the compilation word list, if such definition exists. Otherwise throw exception code -80.

Return the name token nt for the definition whose name was placed most recently into the compilation word list, if such a definition exists. Otherwise, throw exception code -80.

Reference implementation

In this implementation we assume that wid is an address that contains nt of the most recently placed definition name into the word list wid.

: LATEST-NAME-IN ( wid -- nt|0 ) @ ;

: LATEST-NAME ( -- nt )
  GET-CURRENT LATEST-NAME-IN  DUP IF EXIT THEN  -80 THROW
;

Testing

: IT ( -- xt ) LATEST-NAME NAME>INTERPRET ;

T{ : LN1 ; IT  ' LN1 =  -> TRUE }T
T{ :NONAME [ IT ] LITERAL ; EXECUTE  ' LN1 =  -> TRUE }T
T{ : LN2 [ IT ] LITERAL ; LN2  ' LN1 =  -> TRUE }T

ruvavatar of ruv

See also some additional details and usage examples in ForthHub discussion#153

ruvavatar of ruvNew Version: New words: latest-name and latest-name-in

Hide differences

Author

Ruv

Change Log

  • 2023-10-22 Initial revision
  • 2023-10-23 Add testing, examples, a question to discuss, change the throw code description
  • 2023-10-27 Some rationales and explanations added, the throw code description changed back, better wording in some places
  • 2024-06-20 Fix some typos, make some wording and formatting better, add some examples and test cases, add motivation for LATEST-NAME-IN, change the status to "formal".

Problem

In some applications, mainly in libraries and extensions, the capability to obtain the most recently added definition is very useful and demanded.

To make such programs portable, we should introduce a standard method to obtain the most recently added word.

For example, if we are creating a library for decoration, tracing, support for OOP, simple DSLs (e.g., to describe Final State Machines), etc — it is always useful to have an accessor to the recent definition, instead of redefining a lot of words to define such an access method yourself, or juggling with the input buffer and search.

However, many Forth systems have such internal methods to access the recently added word. Among them: latest ( -- nt|0 ), last @ ( -- nt|0 ), latestxt ( -- xt|0 ), etc.

One simple example. If we want to have variables that are initialized by zero, we can use:

: var ( "name" -- )
  variable
  0  latest-name name> execute  !
;

A number of specific examples is provided in my post on ForthHub (those examples are not inserted here so as not to bloat the text).

And additionally, there has been much discussions regarding standardization of such a method in recent decades. For example, Elizabeth D. Rather wrote on 2011-12-09 in comp.lang.forth:

AFAIK most if not all Forths have some method for knowing the latest definition, it's kinda necessary. The problem is, that they all do it differently (at different times, in different forms, etc.), which is why it hasn't been possible to standardize it.

Although it's a system necessity, I haven't found this of much value in application programming.

Elizabeth D. Rather

It's true: depending on the system, an internal method can return the recent word regardless of the compilation word list, or depending on the compilation word list, a completed definition, or not yet completed definition, also unnamed definition, or only named definition, etc.

The value in application programming is shown by me above.

Some known internal methods: latest ( -- nt|0 ), last @ ( -- nt|0 ), latestxt ( -- xt|0 ), etc.

Thus, although almost every Forth system contains such a method, there is no portable way for programs to obtain the latest definition.

But a such portable method is actually very useful, as shown in my examples.

Solution

Let's introduce the following words:

  • LATEST-NAME-IN ( wid -- nt|0 )
  • LATEST-NAME ( -- nt )

The first word returns the name token for the definition whose name was placed most recently into the given word list, or zero if this word list is empty.

The second word returns the name token for the definition whose name was placed most recently into the compilation word list, or throws an exception if there is no such definition.

The second word returns the name token for the definition whose name was placed most recently into the compilation word list, or throws an exception if there is no such definition.

These words do not expose or limit any internal mechanism of the compiler. They just provide information about word lists, like the words FIND-NAME-IN, FIND-NAME, and TRAVERSE-WORDLIST do.

It's a kind of introspection/reflection.

This words are intended for programs. The system may use them, but is not required to do so. The system may continue to use its internal LAST, LATEST, or whatever it was using before.

It seems, the best place for these words is the section 15.6.2 Programming-Tools extension words), where TRAVERSE-WORDLIST is also placed.

It seems, the best place for these words is the section 15.6.2 Programming-Tools extension words, where TRAVERSE-WORDLIST is also placed.

Rationale

Connection with word lists

By considering definitions in the frame of a word list only, we solve several problems, namely:

  1. A word list contains only completed definitions (see the accepted proposal #153 Traverse-wordlist does not find unnamed/unfinished definitions). This eliminates the question of whether the word of returned nt is finished — yes, it is always finished (completed).

  2. Nameless definitions are not considered since they are not placed into the compilation word list (regardless of whether the system creates a name token for them, or places them into an internal system-specific word list).

  1. An extension or library can create definitions in its internal word list for internal purposes. And it will not affect the compilation word list or other user-defined word lists. Thus, the user of such library always gets the expected result from latest-name (regardless of what words are created by this library for internal purposes on the fly).
  1. An extension or library can create definitions in its internal word list for internal purposes. And it will not affect the compilation word list or other user-defined word lists. Thus, the user of such library always gets the expected result from latest-name (regardless of what words are created by this library for internal purposes on the fly). For example, when different dictionary spaces will be introduced, we can implement something like local variables (or local definitions) in portable way, and creating such a definition will not affect the value that latest-name returns.

Return values

As a matter of practice, almost all the use cases for the word LATEST-NAME imply that the requested definition exists, and if it doesn't exist, only an error can be reported. So the option to return 0 by this word only burdens users with having to analyze this zero, or redefine this word as:

: latest-name ( -- nt ) latest-name dup 0= -80 and throw ;

If the user needs to handle the case where the compilation word list is empty, they can use the word latest-name-in as:

get-current latest-name-in dup if ( nt ) ... else ( 0 ) drop ... then

Implementation options

If the the word list structure in a Forth system contains information about the latest placed definition, the implementations for the proposed words are trivial.

In some plausible Forth systems, the word list structure doesn't contain any information about the definition that was placed into this word list most recently. Such systems might not provide the proposed words, or they are changed to keep the mentioned information in the word list structure. It seems, in most systems the word list structure contains this information.

Some checked systems:

  • SwiftForth, VFX, Gforth, minForth, ikForth, SP-Forth — a word list keeps information about the definition that was placed in it most recently;
  • lxf/ntf 2017 — it seems, it doesn't keep this information.

If a system does not implement The optional Search-Order word set, it might not provide the word LATEST-NAME-IN.

Naming

The names LATEST-NAME-IN and LATEST-NAME of new words are similar to FIND-NAME-IN and FIND-NAME by the form. Stack effects are also similar.

The difference is that find is a verb, but latest is an adjective (or sometimes a noun, see Wiktionary). Both are historical in their use in naming words. As well as "NAME".

In Forth-84 "NAME" in word names denoted NFA (name field address), and now it denotes a name token, which is the successor of NFA. In all standard words, e.g. FIND-NAME, NAME>STRING, NAME>COMPILE, etc. (except PARSE-NAME), "NAME" denotes a name token.

NB: the term "token" in "name token" does not mean a character sequence! It's used in a general sense, like "something serving as an expression of something else" (see Wiktionary).

Throw code description

If the throw code description states that there is no latest name, it can be confusing since latest name in some sense probably always exists.

Therefore, it's better to say: "the compilation word list is empty" — it is what actually happens.

Motivation for LATEST-NAME-IN

  1. It's a natural factor for LATEST-NAME. It's always possible to extract this factor from the implementation of LATEST-NAME, because the latter returns nt from the compilation word list, and the system should take wid of the compilation word list and extract most recent nt from this word list.
  2. It's very important to specify the behavior of this word to avoid different behavior in different systems, since in many systems this word will exist (will be implemented as a natural factor).
  3. In some cases a program needs to check if a word list is empty, or obtain the latest word from a particular word list (for example, to use this word as entry point, like main, or as the default exported word from a module).
  4. These both words are optional. And if LATEST-NAME-IN is not provided, it can be implemented in a portable way via LATEST-NAME as:
    : latest-name-in ( wid -- nt|0 )
      get-current >r set-current
     ['] latest-name catch if 0 then
      r> set-current
    ;
    

Things to discuss

Is it worth introducing the word LATEST-NAME-XT ( -- xt )?

If name>interpret never returns 0 (see my comment), this word can be implemented as:

: latest-name-xt ( -- xt ) latest-name name>interpret ;

The desired (and much discussed) pattern is:

defer bar

: foo ... ; latest-name-xt is bar

Sometimes the name "it" has been suggested for this word, but this name is too short and has more chance for conflicts. Guido Draheim wrote in comp.lang.forth on 2003-03-16:

I think that everyone has been thinking of using IT for something really clever, it's a nice short word - and I'd say that we should leave it for application usage.

I want to support that argument also with real life experience in the telco world where there are a whole lot of abbreviations for various services, signals, connectors around. All too often now I see people making a SYNONYM at the file-start to get a second name for an ANS forth word that is needed in the implemenation but coincides with a common term of the application.

This seems convincing to me.

Typical use

: STRUCT: ( "name" -- wid.current.old u.offset )
  GET-CURRENT  VOCABULARY
  ALSO  LATEST-NAME NAME> EXECUTE  DEFINITIONS
  0
;
  \ In the application's vocabulary
  : IT ( -- xt ) LATEST-NAME NAME>INTERPRET ;

  DEFER FOO

  : BAR ... ; IT IS FOO

Proposal

Add the following line into the Table 9.1: THROW code assignments:

-80 the compilation word list is empty

Add the following sections into 15.6.2 Programming-Tools extension words:

15.6.2.2541 LATEST-NAME-IN

( wid -- nt|0 )
Remove the word list identifier wid from the stack. If the corresponding word list is empty, then return 0; otherwise, return the name token nt for the definition whose name was placed most recently into this word list.

15.6.2.2542 LATEST-NAME

( -- nt )

Return the name token nt for the definition whose name was placed most recently into the compilation word list, if such a definition exists. Otherwise, throw exception code -80.

Return the name token nt for the definition whose name was placed most recently into the compilation word list, if such a definition exists. Otherwise, throw the exception code -80.

Reference implementation

In this implementation we assume that wid is an address that contains nt of the most recently placed definition name into the word list wid.

: LATEST-NAME-IN ( wid -- nt|0 ) @ ;

: LATEST-NAME ( -- nt )
  GET-CURRENT LATEST-NAME-IN  DUP IF EXIT THEN  -80 THROW
;

Testing

: IT ( -- xt ) LATEST-NAME NAME>INTERPRET ;

WORDLIST CONSTANT WL1

T{ : LN1 ; IT ' LN1 = -> TRUE }T

T{ GET-CURRENT LATEST-NAME-IN ' LN1 = -> TRUE }T

T{ :NONAME [ IT ] LITERAL ; EXECUTE ' LN1 = -> TRUE }T T{ : LN2 [ IT ] LITERAL ; LN2 ' LN1 = -> TRUE }T

T{ WL1 LATEST-NAME-IN -> 0 }T T{ GET-CURRENT WL1 SET-CURRENT ' LATEST-NAME CATCH SWAP SET-CURRENT -> -80 }T


Formal

ruvavatar of ruvNew Version: New words: latest-name and latest-name-in

Hide differences

Author

Ruv

Change Log

  • 2023-10-22 Initial revision
  • 2023-10-23 Add testing, examples, a question to discuss, change the throw code description
  • 2023-10-27 Some rationales and explanations added, the throw code description changed back, better wording in some places
  • 2024-06-20 Fix some typos, make some wording and formatting better, add some examples and test cases, add motivation for LATEST-NAME-IN, change the status to "formal".
  • 2024-06-20 Add a test case to check that LATEST-NAME returns different value after the compilation word list is switched.

Problem

In some applications, mainly in libraries and extensions, the capability to obtain the most recently added definition is very useful and demanded.

To make such programs portable, we should introduce a standard method to obtain the most recently added word.

For example, if we are creating a library for decoration, tracing, support for OOP, simple DSLs (e.g., to describe Final State Machines), etc — it is always useful to have an accessor to the recent definition, instead of redefining a lot of words to define such an access method yourself, or juggling with the input buffer and search.

One simple example. If we want to have variables that are initialized by zero, we can use:

: var ( "name" -- )
  variable
  0  latest-name name> execute  !
;

A number of specific examples is provided in my post on ForthHub (those examples are not inserted here so as not to bloat the text).

And additionally, there has been much discussions regarding standardization of such a method in recent decades. For example, Elizabeth D. Rather wrote on 2011-12-09 in comp.lang.forth:

AFAIK most if not all Forths have some method for knowing the latest definition, it's kinda necessary. The problem is, that they all do it differently (at different times, in different forms, etc.), which is why it hasn't been possible to standardize it.

Although it's a system necessity, I haven't found this of much value in application programming.

Elizabeth D. Rather

It's true: depending on the system, an internal method can return the recent word regardless of the compilation word list, or depending on the compilation word list, a completed definition, or not yet completed definition, also unnamed definition, or only named definition, etc. The value in application programming is shown by me above.

Some known internal methods: latest ( -- nt|0 ), last @ ( -- nt|0 ), latestxt ( -- xt|0 ), etc.

Thus, although almost every Forth system contains such a method, there is no portable way for programs to obtain the latest definition. But a such portable method is actually very useful, as shown in my examples.

Solution

Let's introduce the following words:

  • LATEST-NAME-IN ( wid -- nt|0 )
  • LATEST-NAME ( -- nt )

The first word returns the name token for the definition whose name was placed most recently into the given word list, or zero if this word list is empty.

The second word returns the name token for the definition whose name was placed most recently into the compilation word list, or throws an exception if there is no such definition.

These words do not expose or limit any internal mechanism of the compiler. They just provide information about word lists, like the words FIND-NAME-IN, FIND-NAME, and TRAVERSE-WORDLIST do. It's a kind of introspection/reflection.

This words are intended for programs. The system may use them, but is not required to do so. The system may continue to use its internal LAST, LATEST, or whatever it was using before.

It seems, the best place for these words is the section 15.6.2 Programming-Tools extension words, where TRAVERSE-WORDLIST is also placed.

Rationale

Connection with word lists

By considering definitions in the frame of a word list only, we solve several problems, namely:

  1. A word list contains only completed definitions (see the accepted proposal #153 Traverse-wordlist does not find unnamed/unfinished definitions). This eliminates the question of whether the word of returned nt is finished — yes, it is always finished (completed).

  2. Nameless definitions are not considered since they are not placed into the compilation word list (regardless of whether the system creates a name token for them, or places them into an internal system-specific word list).

  3. An extension or library can create definitions in its internal word list for internal purposes. And it will not affect the compilation word list or other user-defined word lists. Thus, the user of such library always gets the expected result from latest-name (regardless of what words are created by this library for internal purposes on the fly). For example, when different dictionary spaces will be introduced, we can implement something like local variables (or local definitions) in portable way, and creating such a definition will not affect the value that latest-name returns.

Return values

As a matter of practice, almost all the use cases for the word LATEST-NAME imply that the requested definition exists, and if it doesn't exist, only an error can be reported. So the option to return 0 by this word only burdens users with having to analyze this zero, or redefine this word as:

: latest-name ( -- nt ) latest-name dup 0= -80 and throw ;

If the user needs to handle the case where the compilation word list is empty, they can use the word latest-name-in as:

get-current latest-name-in dup if ( nt ) ... else ( 0 ) drop ... then

Implementation options

If the the word list structure in a Forth system contains information about the latest placed definition, the implementations for the proposed words are trivial.

In some plausible Forth systems, the word list structure doesn't contain any information about the definition that was placed into this word list most recently. Such systems might not provide the proposed words, or they are changed to keep the mentioned information in the word list structure. It seems, in most systems the word list structure contains this information.

Some checked systems:

  • SwiftForth, VFX, Gforth, minForth, ikForth, SP-Forth — a word list keeps information about the definition that was placed in it most recently;
  • lxf/ntf 2017 — it seems, it doesn't keep this information.

If a system does not implement The optional Search-Order word set, it might not provide the word LATEST-NAME-IN.

Naming

The names LATEST-NAME-IN and LATEST-NAME of new words are similar to FIND-NAME-IN and FIND-NAME by the form. Stack effects are also similar.

The difference is that find is a verb, but latest is an adjective (or sometimes a noun, see Wiktionary). Both are historical in their use in naming words. As well as "NAME".

In Forth-84 "NAME" in word names denoted NFA (name field address), and now it denotes a name token, which is the successor of NFA. In all standard words, e.g. FIND-NAME, NAME>STRING, NAME>COMPILE, etc. (except PARSE-NAME), "NAME" denotes a name token.

NB: the term "token" in "name token" does not mean a character sequence! It's used in a general sense, like "something serving as an expression of something else" (see Wiktionary).

Throw code description

If the throw code description states that there is no latest name, it can be confusing since latest name in some sense probably always exists.

Therefore, it's better to say: "the compilation word list is empty" — it is what actually happens.

Motivation for LATEST-NAME-IN

  1. It's a natural factor for LATEST-NAME. It's always possible to extract this factor from the implementation of LATEST-NAME, because the latter returns nt from the compilation word list, and the system should take wid of the compilation word list and extract most recent nt from this word list.
  2. It's very important to specify the behavior of this word to avoid different behavior in different systems, since in many systems this word will exist (will be implemented as a natural factor).
  3. In some cases a program needs to check if a word list is empty, or obtain the latest word from a particular word list (for example, to use this word as entry point, like main, or as the default exported word from a module).
  4. These both words are optional. And if LATEST-NAME-IN is not provided, it can be implemented in a portable way via LATEST-NAME as:
    : latest-name-in ( wid -- nt|0 )
      get-current >r set-current
     ['] latest-name catch if 0 then
      r> set-current
    ;
    

Things to discuss

Is it worth introducing the word LATEST-NAME-XT ( -- xt )?

If name>interpret never returns 0 (see my comment), this word can be implemented as:

: latest-name-xt ( -- xt ) latest-name name>interpret ;

The desired (and much discussed) pattern is:

defer bar

: foo ... ; latest-name-xt is bar

Sometimes the name "it" has been suggested for this word, but this name is too short and has more chance for conflicts. Guido Draheim wrote in comp.lang.forth on 2003-03-16:

I think that everyone has been thinking of using IT for something really clever, it's a nice short word - and I'd say that we should leave it for application usage.

I want to support that argument also with real life experience in the telco world where there are a whole lot of abbreviations for various services, signals, connectors around. All too often now I see people making a SYNONYM at the file-start to get a second name for an ANS forth word that is needed in the implemenation but coincides with a common term of the application.

This seems convincing to me.

Typical use

: STRUCT: ( "name" -- wid.current.old u.offset )
  GET-CURRENT  VOCABULARY
  ALSO  LATEST-NAME NAME> EXECUTE  DEFINITIONS
  0
;
  \ In the application's vocabulary
  : IT ( -- xt ) LATEST-NAME NAME>INTERPRET ;

  DEFER FOO

  : BAR ... ; IT IS FOO

Proposal

Add the following line into the Table 9.1: THROW code assignments:

-80 the compilation word list is empty

Add the following sections into 15.6.2 Programming-Tools extension words:

15.6.2.2541 LATEST-NAME-IN

( wid -- nt|0 )
Remove the word list identifier wid from the stack. If the corresponding word list is empty, then return 0; otherwise, return the name token nt for the definition whose name was placed most recently into this word list.

15.6.2.2542 LATEST-NAME

( -- nt )
Return the name token nt for the definition whose name was placed most recently into the compilation word list, if such a definition exists. Otherwise, throw the exception code -80.

Reference implementation

In this implementation we assume that wid is an address that contains nt of the most recently placed definition name into the word list wid.

: LATEST-NAME-IN ( wid -- nt|0 ) @ ;

: LATEST-NAME ( -- nt )
  GET-CURRENT LATEST-NAME-IN  DUP IF EXIT THEN  -80 THROW
;

Testing

: IT ( -- xt ) LATEST-NAME NAME>INTERPRET ;

WORDLIST CONSTANT WL1

T{ : LN1 ; IT  ' LN1 =  -> TRUE }T
T{ GET-CURRENT LATEST-NAME-IN ' LN1 =  -> TRUE }T
T{ :NONAME [ IT ] LITERAL ; EXECUTE  ' LN1 =  -> TRUE }T
T{ : LN2 [ IT ] LITERAL ; LN2  ' LN1 =  -> TRUE }T
T{ WL1 LATEST-NAME-IN -> 0 }T

T{ GET-CURRENT WL1 SET-CURRENT ' LATEST-NAME CATCH SWAP SET-CURRENT -> -80 }T

GET-CURRENT WL1 SET-CURRENT ( wid.prev ) T{ ' LATEST-NAME CATCH -> -80 }T T{ : LN3 ; -> }T SET-CURRENT T{ IT ' LN2 = -> TRUE }T


ruvavatar of ruvNew Version: New words: latest-name and latest-name-in

Hide differences

Author

Ruv

Change Log

  • 2023-10-22 Initial revision
  • 2023-10-23 Add testing, examples, a question to discuss, change the throw code description
  • 2023-10-27 Some rationales and explanations added, the throw code description changed back, better wording in some places
  • 2024-06-20 Fix some typos, make some wording and formatting better, add some examples and test cases, add motivation for LATEST-NAME-IN, change the status to "formal".
  • 2024-06-20 Add a test case to check that LATEST-NAME returns different value after the compilation word list is switched.
  • 2024-06-20 Simplify the normative text description, and add a rationale for this simplification.

Problem

In some applications, mainly in libraries and extensions, the capability to obtain the most recently added definition is very useful and demanded.

To make such programs portable, we should introduce a standard method to obtain the most recently added word.

For example, if we are creating a library for decoration, tracing, support for OOP, simple DSLs (e.g., to describe Final State Machines), etc — it is always useful to have an accessor to the recent definition, instead of redefining a lot of words to define such an access method yourself, or juggling with the input buffer and search.

One simple example. If we want to have variables that are initialized by zero, we can use:

: var ( "name" -- )
  variable
  0  latest-name name> execute  !
;

A number of specific examples is provided in my post on ForthHub (those examples are not inserted here so as not to bloat the text).

And additionally, there has been much discussions regarding standardization of such a method in recent decades. For example, Elizabeth D. Rather wrote on 2011-12-09 in comp.lang.forth:

AFAIK most if not all Forths have some method for knowing the latest definition, it's kinda necessary. The problem is, that they all do it differently (at different times, in different forms, etc.), which is why it hasn't been possible to standardize it.

Although it's a system necessity, I haven't found this of much value in application programming.

Elizabeth D. Rather

It's true: depending on the system, an internal method can return the recent word regardless of the compilation word list, or depending on the compilation word list, a completed definition, or not yet completed definition, also unnamed definition, or only named definition, etc. The value in application programming is shown by me above.

Some known internal methods: latest ( -- nt|0 ), last @ ( -- nt|0 ), latestxt ( -- xt|0 ), etc.

Thus, although almost every Forth system contains such a method, there is no portable way for programs to obtain the latest definition. But a such portable method is actually very useful, as shown in my examples.

Solution

Let's introduce the following words:

  • LATEST-NAME-IN ( wid -- nt|0 )
  • LATEST-NAME ( -- nt )

The first word returns the name token for the definition whose name was placed most recently into the given word list, or zero if this word list is empty.

The second word returns the name token for the definition whose name was placed most recently into the compilation word list, or throws an exception if there is no such definition.

These words do not expose or limit any internal mechanism of the compiler. They just provide information about word lists, like the words FIND-NAME-IN, FIND-NAME, and TRAVERSE-WORDLIST do. It's a kind of introspection/reflection.

This words are intended for programs. The system may use them, but is not required to do so. The system may continue to use its internal LAST, LATEST, or whatever it was using before.

It seems, the best place for these words is the section 15.6.2 Programming-Tools extension words, where TRAVERSE-WORDLIST is also placed.

Rationale

Connection with word lists

By considering definitions in the frame of a word list only, we solve several problems, namely:

  1. A word list contains only completed definitions (see the accepted proposal #153 Traverse-wordlist does not find unnamed/unfinished definitions). This eliminates the question of whether the word of returned nt is finished — yes, it is always finished (completed).

  2. Nameless definitions are not considered since they are not placed into the compilation word list (regardless of whether the system creates a name token for them, or places them into an internal system-specific word list).

  3. An extension or library can create definitions in its internal word list for internal purposes. And it will not affect the compilation word list or other user-defined word lists. Thus, the user of such library always gets the expected result from latest-name (regardless of what words are created by this library for internal purposes on the fly). For example, when different dictionary spaces will be introduced, we can implement something like local variables (or local definitions) in portable way, and creating such a definition will not affect the value that latest-name returns.

Return values

As a matter of practice, almost all the use cases for the word LATEST-NAME imply that the requested definition exists, and if it doesn't exist, only an error can be reported. So the option to return 0 by this word only burdens users with having to analyze this zero, or redefine this word as:

: latest-name ( -- nt ) latest-name dup 0= -80 and throw ;

If the user needs to handle the case where the compilation word list is empty, they can use the word latest-name-in as:

get-current latest-name-in dup if ( nt ) ... else ( 0 ) drop ... then

Implementation options

If the the word list structure in a Forth system contains information about the latest placed definition, the implementations for the proposed words are trivial.

In some plausible Forth systems, the word list structure doesn't contain any information about the definition that was placed into this word list most recently. Such systems might not provide the proposed words, or they are changed to keep the mentioned information in the word list structure. It seems, in most systems the word list structure contains this information.

Some checked systems:

  • SwiftForth, VFX, Gforth, minForth, ikForth, SP-Forth — a word list keeps information about the definition that was placed in it most recently;
  • lxf/ntf 2017 — it seems, it doesn't keep this information.

If a system does not implement The optional Search-Order word set, it might not provide the word LATEST-NAME-IN.

Naming

The names LATEST-NAME-IN and LATEST-NAME of new words are similar to FIND-NAME-IN and FIND-NAME by the form. Stack effects are also similar.

The difference is that find is a verb, but latest is an adjective (or sometimes a noun, see Wiktionary). Both are historical in their use in naming words. As well as "NAME".

In Forth-84 "NAME" in word names denoted NFA (name field address), and now it denotes a name token, which is the successor of NFA. In all standard words, e.g. FIND-NAME, NAME>STRING, NAME>COMPILE, etc. (except PARSE-NAME), "NAME" denotes a name token.

NB: the term "token" in "name token" does not mean a character sequence! It's used in a general sense, like "something serving as an expression of something else" (see Wiktionary).

Normative text description

The proposed normative text description is based on:

  • 16.2: "compilation word list: The word list into which new definition names are placed",
  • 15.3.1: "A name token is a single-cell value that identifies a named word",
  • 3.4.3: "[Semantics] are largely specified by the stack notation in the glossary entries, which shows what values shall be consumed and produced. The prose in each glossary entry further specifies the definition's behavior" (there is no need to repeat in the text description what is already indicated in the stack diagrams). (emphasis added)

Throw code description

If the throw code description states that there is no latest name, it can be confusing since latest name in some sense probably always exists.

Therefore, it's better to say: "the compilation word list is empty" — it is what actually happens.

Motivation for LATEST-NAME-IN

  1. It's a natural factor for LATEST-NAME. It's always possible to extract this factor from the implementation of LATEST-NAME, because the latter returns nt from the compilation word list, and the system should take wid of the compilation word list and extract most recent nt from this word list.
  2. It's very important to specify the behavior of this word to avoid different behavior in different systems, since in many systems this word will exist (will be implemented as a natural factor).
  3. In some cases a program needs to check if a word list is empty, or obtain the latest word from a particular word list (for example, to use this word as entry point, like main, or as the default exported word from a module).
  4. These both words are optional. And if LATEST-NAME-IN is not provided, it can be implemented in a portable way via LATEST-NAME as:
    : latest-name-in ( wid -- nt|0 )
      get-current >r set-current
     ['] latest-name catch if 0 then
      r> set-current
    ;
    

Things to discuss

Is it worth introducing the word LATEST-NAME-XT ( -- xt )?

If name>interpret never returns 0 (see my comment), this word can be implemented as:

: latest-name-xt ( -- xt ) latest-name name>interpret ;

The desired (and much discussed) pattern is:

defer bar

: foo ... ; latest-name-xt is bar

Sometimes the name "it" has been suggested for this word, but this name is too short and has more chance for conflicts. Guido Draheim wrote in comp.lang.forth on 2003-03-16:

I think that everyone has been thinking of using IT for something really clever, it's a nice short word - and I'd say that we should leave it for application usage.

I want to support that argument also with real life experience in the telco world where there are a whole lot of abbreviations for various services, signals, connectors around. All too often now I see people making a SYNONYM at the file-start to get a second name for an ANS forth word that is needed in the implemenation but coincides with a common term of the application.

This seems convincing to me.

Typical use

: STRUCT: ( "name" -- wid.current.old u.offset )
  GET-CURRENT  VOCABULARY
  ALSO  LATEST-NAME NAME> EXECUTE  DEFINITIONS
  0
;
  \ In the application's vocabulary
  : IT ( -- xt ) LATEST-NAME NAME>INTERPRET ;

  DEFER FOO

  : BAR ... ; IT IS FOO

Proposal

Add the following line into the Table 9.1: THROW code assignments:

-80 the compilation word list is empty

Add the following sections into 15.6.2 Programming-Tools extension words:

15.6.2.2541 LATEST-NAME-IN

15.6.2.xxxx LATEST-NAME-IN TOOLS EXT

( wid -- nt|0 )

Remove the word list identifier wid from the stack. If the corresponding word list is empty, then return 0; otherwise, return the name token nt for the definition whose name was placed most recently into this word list.

If the word list identified by wid is empty, then the returned value is 0; otherwise, the name token nt identifies the definition whose name was placed most recently into the word list wid.

15.6.2.2542 LATEST-NAME

15.6.2.xxxx LATEST-NAME TOOLS EXT

( -- nt )

Return the name token nt for the definition whose name was placed most recently into the compilation word list, if such a definition exists. Otherwise, throw the exception code -80.

If the compilation word list is not empty, the name token nt identifies the definition whose name was placed most recently into this word list. Otherwise, the exception code -80 is thrown.

Reference implementation

In this implementation we assume that wid is an address that contains nt of the most recently placed definition name into the word list wid.

: LATEST-NAME-IN ( wid -- nt|0 ) @ ;

: LATEST-NAME ( -- nt )
  GET-CURRENT LATEST-NAME-IN  DUP IF EXIT THEN  -80 THROW
;

Testing

: IT ( -- xt ) LATEST-NAME NAME>INTERPRET ;

WORDLIST CONSTANT WL1

T{ : LN1 ; IT  ' LN1 =  -> TRUE }T
T{ GET-CURRENT LATEST-NAME-IN ' LN1 =  -> TRUE }T
T{ :NONAME [ IT ] LITERAL ; EXECUTE  ' LN1 =  -> TRUE }T
T{ : LN2 [ IT ] LITERAL ; LN2  ' LN1 =  -> TRUE }T
T{ WL1 LATEST-NAME-IN -> 0 }T
GET-CURRENT WL1 SET-CURRENT ( wid.prev )
T{ ' LATEST-NAME CATCH -> -80 }T
T{ : LN3 ;  -> }T
SET-CURRENT
T{ IT ' LN2 = -> TRUE }T

BerndPaysanavatar of BerndPaysan

One reason to have LATESTNT/LATESTXT in Gforth is that it works even when you switch the current wordlist in between, and that you don't even need to have a definition header (i.e. it also works on :NONAME definitions). The state of them is tied to what RECURSE compiles — RECURSE is an alias to the latest definition.

There's another extension that makes this important: the NONAME word which renders the next definition unnamed, no matter how it is created. This allows to define unnamed definitions that are not colon definitions. To access their xt, you need LATESTXT. I suggest removing the relation from a wordlist, it is an implementation detail that doesn't really help.

ruvavatar of ruv

One reason to have LATESTNT/LATESTXT in Gforth is that it works even when you switch the current wordlist in between, and that you don't even need to have a definition header (i.e. it also works on :NONAME definitions). The state of them is tied to what RECURSE compiles — RECURSE is an alias to the latest definition.

  1. LATESTNT and LATESTXT are Gforth-specific words and may continue to be used by the Gforth core.

  2. LATEST-NAME cannot replace these words, because LATEST-NAME give you nt of a named and completed definition only (i.e., not a definition for which compilation has been started and not yet finished, and not an anonymous definition).


I see a drawback to LATESTXT in that it may return the xt of a definition that is not a current definition. That is, it does not provide useful information about whether a current definition exists. I would like to propose standardizing a word that returns either xt of the current definition or zero (if there is no current definition).

Formal definitios (draft):

GERM ( -- xt|0 )
If the current definition exists, return its xt, otherwise return zero. The returned xt may be processed by COMPILE,. The returned xt shall not be executed (directly or indirectly) while compilation of the corresponding definition is not ended.

The current definition: the definition whose compilation has been started most recently and not yet ended.

End of the formal definitions.

So, GERM returns a correct value even when a quotation is compiled. Using this word, RECURSE can be defined as following:

: recurse  germ dup if compile, exit then  true abort" there is no current definition" ; immediate

(NB: we should introduce a throw code for such a case)

Also, I would like to clarify DOES> to avoid ambiguity concerning what is the current definition after the compilation semantics of DOES> are performed.

For example, replace in 6.1.1250:

Consume colon-sys1 and produce colon-sys2.

With:

End compilation of the current definition, consuming colon-sys1. Start compilation of the new definition, producing colon-sys2.

ruvavatar of ruv

There's another extension that makes this important: the NONAME word which renders the next definition unnamed, no matter how it is created. This allows to define unnamed definitions that are not colon definitions. To access their xt, you need LATESTXT. I suggest removing the relation from a wordlist, it is an implementation detail that doesn't really help.

Why not continue using LATESTXT to access xt of these words?

Anyway, LATESTXT cannot be used instead of the proposed LATEST-NAME.

Usage example for LATEST-NAME (from my post in comp.lang.forth):

: vocabulary>wordlist ( xt.vocabulary -- wid )
  also execute  get-order swap >r 1- set-order r>
;

: exch-current ( wid -- wid )
  get-current swap set-current
;

wordlist constant (labels-for-wordlists)

: wordlist-labeled ( sd.label -- wid )
  (labels-for-wordlists) exch-current >r
  ['] vocabulary execute-parsing
  latest-name name>interpret ( xt.vocabulary )
  vocabulary>wordlist ( wid )
  r> exch-current drop
;

The word wordlist-labeled allows us to create a wordlist with a label (a string without spaces), and this label is indicated by order for this wordlist. For the user of wordlist-labeled it is unexpected, if latest-name returns different values before and after execution of wordlist-labeled.

BerndPaysanavatar of BerndPaysan

The question is: what do you want to solve? The usual problem you have is: you created a word, and want to get a handle to it. One problem here is that while it is still defined, you can't even search for it. Another problem is that you may never search for it, because it doesn't even have a name. And you want to access the last definition even after it was completed, so there's no current definition any longer.

The traditional implementation of the latest name/xt was to go into the current wordlist, take the linked list, and return the last element thereof. That's why the standard says there's an ambiguous condition if you change the current wordlist between : and ;. Don't implement it that way, and that problem goes away.

There's another traditional implementation how to hide the current definition: The smudge bit. The smudge bit is unimplementable in flash-based systems. Gforth doesn't have a smudge bit, it appends the current definition to the corresponding wordlist at ; and not before. So if you use LATEST-NAME-IN in Gforth by looking into the current wordlist, you'd never get the current definition: It`s not there yet. It only gets there once it stops being the current definition.

This proposal standardizes on a traditional implementation which never was a very good idea. The definition you want to access is the one you just defined (it may be incomplete or complete), and that's the last one in time. It always has an xt, it might not have an nt (and if it doesn't have one, that should be 0). Doing all the changes for the new header in Gforth was a bit complicated, because such a transition is fragile, and I think it requires another round of review before 1.0 is ready, especially the naming LATESTNT and LATEST, which both return an unified nt/xt data type, but LATEST returns 0 if the last definition really has no name. It is easy to tell if the current definition is incomplete or completed; that could be helpful. It's also possible to tell which wordlist an incomplete definition is going into when it is completed (it remembers the current wordlist at : and will go there at ;).

So what we could implement is a LATEST-NAME-IN which returns the nt of the latest definition if the wid matches the current incomplete definition's wordlist. If that definition is completed, there will be no non-zero LATEST-NAME-IN anymore. I can't tell you how often we need that functionality, but it looks like that's not quite the right one. The majority of use is after a definition is completed.

The first thing needed here is to really figure out what people actually want: The last element of a wordlist, the last incomplete definition of a wordlist (i.e. the element with the smudge bit set), or the last definition in time, regardless if it is completed or not, and what wordlist it goes into once completed.

ruvavatar of ruv

The question is: what do you want to solve?

I want to solve a problem of obtaining the nt of the definition that was placed into the compilation word list most recently. This is possible in any system in you know the name of this definition, but is unreasonably difficult to do in a standard program.

I have given many examples where this functionality is in demand.

One problem here is that while it is still defined, you can't even search for it.

Concerning xt, this problem is solved with the suggested word germ. Concerning nt — do you have an example when you need nt of the current definition?

Another problem is that you may never search for it, because it doesn't even have a name.

In a standard program such a definition can only be created with :noname, and you have xt of this definition on the stack under colon-sys. It is also possible to obtain this xt with the suggested word germ during compilation of this definition.

And you want to access the last definition even after it was completed, so there's no current definition any longer.

The xt of an anonymous definition is on the stack. What is a problem?

Don't implement it that way, and that problem goes away.

What problem goes away? The way you mentioned is pretty perfect, I think.

So if you use LATEST-NAME-IN in Gforth by looking into the current wordlist, you'd never get the current definition

Yes, it is by design. Because there is no sound meaning what to return.

If you want to return nt for the definition compilation for which was started most recently, then you have to

The definition you want to access is the one you just defined (it may be incomplete or complete), and that's the last one in time. It always has an xt, it might not have an nt (and if it doesn't have one, that should be 0).

The problem is that the last one in time (i.e., the definition whose compilation has been started most recently) is different before and after compilation of a nested definition.

An example:

: foo
  [ ( here the last nt is the nt for "foo" ) ]
  [: bar
    [ ( here the last nt is 0 ) ]
  ;]
  [ ( here the last nt is 0 ) ]
;  ( here the last nt is 0 )

If we will have multiple dictionary sections, a library can create other named definitions in other sections while during compilation of the user's definition. And what definition will be last in time?

The word germ will return values as follows:

: foo
  [ ( here germ returns xt for "foo" ) ]
  [: bar
    [ ( here germ returns xt for the quotation ) ]
  ;]
  [ ( here germ returns xt for "foo" ) ]
;  ( here germ returns 0 )

If we will have multiple dictionary sections, it will not change anything for germ, because germ returns the _xt _of the definition in which compile, would add semantics.


So what we could implement is a LATEST-NAME-IN which returns the nt of the latest definition if the wid matches the current incomplete definition's wordlist.

If you mean to return the nt for the current definition, then implementing LATEST-NAME-IN will require to change Forth systems that create nt by ; (semicolon) only. And what's the use of this?


The first thing needed here is to really figure out what people actually want: The last element of a wordlist, the last incomplete definition of a wordlist (i.e. the element with the smudge bit set), or the last definition in time, regardless if it is completed or not, and what wordlist it goes into once completed.

I have provide a number of examples when the last element of the compilation word list is needed or enough.

Do you have practical examples when you need the nt of the current definition, or 0 if this definition is anonymous?

BerndPaysanavatar of BerndPaysan

Nested definitions require some form of nested dictionary, and in fact, it looks like the easiest way to implement some form of LATEST in that context is to tie it to that nesting.

There are only few cases in Gforth, where the latest nt or 0 is needed, and REVEAL is one of them: it only needs to do something when LATEST is non-zero.

ruvavatar of ruv

There are only few cases in Gforth, where the latest nt or 0 is needed, and REVEAL is one of them: it only needs to do something when LATEST is non-zero.

So, REVEAL in Gforth should only have an observable effect when the current definition exists, is a named definition, and is not already placed into the compilation wordlist. That is, it should not add it into the compilation wordlist twice.

Taking into account that xt is a subtype of nt in Gforth, REVEAL can use the word GERM ( -- xt | 0 ) that returns the xt of the current definition (that is also an nt in Gforth).

: reveal ( -- )
  germ 0= if exit then \ no current definition
  germ string>name nip 0= if exit then \ unnamed definition
  germ get-current latest-name-in = if exit then \ already revealed
  germ ( nt ) ... \ place nt into the compilation word list
;

Note that we rely on the fact that latest-name-in cannot return an nt that is not available to traverse-wordlist (and hence to find-name-in).

Of course, the check if nt is already revealed may be different in Gforth.

Reply New Version