Search code examples
forth

Create a new word from string on stack in Forth


I need to use create on a string that I got from parse-name. Possible? Perhaps using the word evaluate?


Solution

  • To create a named definition programmatically, you have the following options:

    1. allow a defining word to take the name from the input stream;
    2. use the well-known word execute-parsing;
    3. compose a string and pass it to evaluate.

    1. Using a defining word

    If you need to create a word with a name that parse-name returns, just use a usual defining word instead of parse-name.

    : foo ( "name" -- ) create  123 , ;
    foo bar \ it creates "bar"
    bar @ . \ it prints "123"
    

    2. Using execute-parsing

    There is a well-known word execute-parsing ( i*x c-addr u xt -- j*x ), which is provided by some systems, or can be loaded from a standard-compliant library, such as execute-parsing.fs.

    This word executes given xt providing the given string as the input buffer. This word can be useful when you compose a name programmatically.

    : foo ( "name" -- )
      parse-name
      ['] create execute-parsing
      123 ,
    ;
    

    3. Composing a string

    The standard means to compose a string are too low-level: you allocate a memory region and place sub-strings using move ( addr.src addr.dest u.length -- ). Therefore, a better way is to use some library (for example, ffl/str.fs).

    Another way to compose a short string is to use the pictured numeric output mechanism and the word holds ( c-addr u -- ):

    : foo ( "name" -- )
      <#  parse-name holds  s" create " holds   0 0 #>
      evaluate
      123 ,
    ;
    

    In this mechanism, the new sub-string prepends the previous one (i.e., they are placed into the buffer from right to left).

    The available buffer size can be obtained by:

    s" /HOLD" environment? 0= throw .
    

    The string returned by #> ( xd -- c-addr u ) is transient.

    When you use evaluate, you must be sure that all names will be resolved correctly (due to late binding).