Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Posting-Version: version B 2.10.1 6/24/83; site utah-cs.UUCP
Path: utzoo!linus!philabs!cmcl2!seismo!utah-cs!carr
From: carr@utah-cs.UUCP (Harold Carr)
Newsgroups: net.lang.forth
Subject: CREATE 
Date: Fri, 12-Oct-84 14:10:42 EDT
Article-I.D.: utah-cs.3068
Posted: Fri Oct 12 14:10:42 1984
Date-Received: Sat, 13-Oct-84 06:44:13 EDT
Organization: Univ of Utah CS Dept
Lines: 106



Could someone enlighten me on why one would use CREATE ... DOES> in
some instances and  in others?  Also, I am very interested
in Forth's meta-defining words and would appreciate examples of interesting
and powerful ways of using them.

Here are a couple of examples of using 	( index -- )
		( DOES> alters the code field and first parameter of )
		( word defined by .  When the DOES> part executes )
		( it begins with the address of the first parameter of )
		( the new word on the stack. )
   swap 2* 2* + @ execute ; ( Execute the function in the indexed slot. )

 is run.  In this case, the
code allocates space in the new word for a vector initialized to zeros.
The DOES> part defines the run-time words for the newly created word.
When the new word is run its parameter field address is pushed on Forth's
parameter stack (the user has already pushed an index before it).  The
parameter address is the base of the vector.  It swaps these two items,
leaving the index on top, which is then multiplied by four to create
a thirty-two bit word index.  This index is then added to the base.
The @ operator gets the contents of the indexed slot and leaves it
on the stack.  The contents should be the address of another executable
word.  Execute simply executes the word whose address is on the top
of the stack.

By defining the following auxilary words (shown without comment):

: put
   [compile] ' ;

: offset-in
   2* 2* [compile] ' + ! ;

We can create a key-stroke dispatch table:

26 xeq-array control-keys
...
put backward  2 offset-in control-keys
put forward   6 offset-in control-keys
put next     14 offset-in control-keys
put previous 21 offset-in control-keys
...

This creates an execution array for control keys.  Then we install
the functions associated with each key.  Note, that by using the
execution array rather than a case statement, we can dynamically
redefine the keys.  To run any of the functions in the array we simply
do:

14 control-keys

Control-keys takes its index from the stack, fetches the function and
executes it.  A simple loop will now listen to the keyboard:

: keys
   begin
    key
    dup 27 <=
    if
     control-keys
    else
     regular-keys
    then
   again ;


A second example (sent to me by Mitch Bradley) uses CREATE to create
an automatically indexed byte array:

: carray    ( array-size --name)
   create   ( Create a dictionary entry for the next word in
              the input stream, without allocating any parameter
              field memory. )
   allot    ( Add array-size bytes to the parameter field of the
              most recently defined word. )
   does>    ( index -- byte-address )
            ( Marks the termination of the defining part of a high-level
              defining word and begins the definition of the run-time
              actions.  On execution of words defined with CARRAY, the
              sequence of words between DOES> and ; will be executed,
              with the address of the word's parameter field on the stack. )
   + ;      ( Add index to base. )

I am still not sure why one would use CREATE rather than DOES> here.

I'll be waiting to hear from you.

Forth programmers remind me of Lisp
hackers: fearless, creative and free - The environment is so open
and powerful (no secret black boxes called compilers), we just can't
wait to get our hands on it an change it!

Harold Carr      arpa: CARR@UTAH-20  uucp: harpo!utah-cs!carr