Proposal: Non parsing CREATE

Informal

This page is dedicated to discussing this specific proposal

ContributeContributions

GeraldWodniavatar of GeraldWodni [413] Non parsing CREATEProposal2025-09-16 11:19:01

Author:

Gerald Wodni

Change Log:

Problem:

There is no standard way to set the name of a word defined by create via a string. However, each Forth system has such a word as a factor of create. Given that this functionality is exposed and documented, it is requested by some users. Personally I need it to create multiple words with a common prefix.

Solution:

Expose the underlying word(s) using a standard name.

  • In VFXForth it is called ($create)
  • In Gforth its equivalent is nextname create

This gives the rationale for specific decisions you have taken in the proposal (often in response to comments), or discusses specific issues that have not been decided yet.

Typical use:

Create a store and fetch word pair for a register

32 buffer: next-name
: register: ( addr "prefix" -- )
\ *G create 2 words, with a common prefix
    dup \ save address for both definitions
    parse-name >r next-name r@ cmove    \ save prefix

    '!' r@ next-name + c!             \ add '!' suffix

    \ create store-word
    next-name r@ 1+
    [: ($create) , does> @ ! ;] execute

    '@' r@ next-name + c!             \ replace with '@' suffix

    \ create fetch-word
    next-name r> 1+
    [: ($create) , does> @ @ ;] execute
;

variable uart-addr \ pretend to be a hardware register
uart-addr register: uart
'h' uart!
uart@ emit

Proposal:

Add a new word non-parsing-create with references to create. The behavior is like create except that the name is taken as a string ( caddr len -- ) form the stack instead of being parsed from the input stream.

Reference implementation:

System specific, hence standardization is required.

EricBlakeavatar of EricBlake

Possible reference implementation, shown here with a dependency on the memory word set (a BUFFER: version would also be possible):

: NON-PARSING-CREATE ( c-addr u -- )
  DUP 7 + ALLOCATE THROW
  DUP S" CREATE " ROT SWAP CMOVE
  DUP >R 7 + SWAP DUP 7 + >R CMOVE
  2R> OVER SWAP EVALUATE
  FREE THROW ;

Obviously, this reference implementation is probably less efficient than reusing an implementation's existing factor of create. Also, this implementation leaks an allocated buffer if the evaluate fails (such as if create throws because the dictionary has run out of space).

AntonErtlavatar of AntonErtl

Out of 8 uses of nextname in Gforth's image, only one is with create. So it might be better to have nextname. Even more general: execute-parsing (Implementation in standard Forth; take a look at the example in that file).

BerndPaysanavatar of BerndPaysan

What's used even more frequently in Gforth is noname, which allows to create unnamed words (using latestxt afterwards to access the xt). And a lot of words with nextname or noname are users of create, that exist anyways. That's why Gforth uses this one-shot modified header creation instead of a variant of create.

execute-parsing works for the named part, but noname won't, unless we e.g. would allow that s" " ['] create execute-parsing would create an unnamed word instead of complaining about the missing name.

AntonErtlavatar of AntonErtl

Execute-parsing cannot work for parsing an empty name to create because regular create produces an error when it tries to parse a name and there is none there. This is a difference to nextname: nextname replaces the parsing, so you can give to it an empty name or a name containing spaces. OTOH, execute-parsing works for all parsing words (also for multiple invocations of parse-name or other basic parsing words), not just defining words, whereas nextname only works for defining words.

A possible generalization of both is to let a nextname-like word precharge the next invocation of parse-name or parse, and maybe allow to precharge several invocations of these words in some way.

Reply New Version