carr@utah-cs.UUCP (Harold Carr) (10/12/84)
Could someone enlighten me on why one would use CREATE ... DOES> in some instances and <BUILDS .. DOES> 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 <BUILDS and CREATE. They are both written in Bill's VAXFORTH. This first example creates an "execution array" to contain words to be executed when accessed: : xeq-array ( number-of-slots -- ) <builds ( Executing xeq-array in the form: ) ( 10 xeq-array keys ) ( uses <BUILDS to create a dictionary entry for KEYS. ) 2* 2* dup here swap 0 fill allot ( Make a vector initialized to zero) does> ( index -- ) ( DOES> alters the code field and first parameter of ) ( word defined by <BUILDS to execute the sequence of ) ( words following DOES>. 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. ) <BUILDS will take a word from the input stream and create a dictionary header for it. Then the code up to DOES> 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
wmb@sun.uucp (Mitch Bradley) (10/14/84)
> Could someone enlighten me on why one would use CREATE ... DOES> in > some instances and <BUILDS .. DOES> in others? <BUILDS is an anachronism. The name was changed from <BUILDS to CREATE in the 79 standard. There might have been some subtle difference between the semantics of the old <BUILDS and the new CREATE, but I can't remember what it was. In any case, <BUILDS is no longer part of the current standard, having been replaced by CREATE. CREATE ought to work fine in place of <BUILDS in your example. Your example of an execution array to dispatch control keys is a good one. Instead of initializing the array with zero, it would have been better to initialize it with the address of a word that prints an "unitialized vector" message. There is a spiffier way to do the control key handling, to wit: Instead of making an array indexed by the control key typed, you convert each control character into a string of the form "^P", for instance, and then search the dictionary for a word with that name. If one is found, execute it. This scheme make it very easy to define and modify the behavior of various control keys. For instance, if you want to define control-H to erase the previous character, all you have to do is : ^H erase-previous-character ; assuming you already have a word "erase-previous-character" which does the work. It is also easy to handle escape sequences with this scheme. You define ^[ ( which is ESCAPE ) to append the next key to the current string, then search the dictionary again. For example, : ^[ key append-char-to-string search-and-execute ; : ^[H erase-previous-word ; again assuming you already have the words that do the work. I wrote a paper describing this scheme and its use to implement an Emacs-style command-line editor with command-completion. It is being published in the Proceedings of the 1984 Rochester Forth Conference. Code is included. The Proceedings are being published now and should be out pretty soon. The code will require some hacking for use with Bill's VAX Forth, because it is written for Forth-83, whereas Bill's Forth is Forth-79. Shouldn't be too difficult, though. The command completion may be difficult, due to the highly-encoded 5-character + count names that Bill uses. The line editing should be easy to port. I will mail the code to anybody that wants it, but it would be a nice gesture to buy the Proceedings anyway (Support your Institute for Applied Forth Research!). Mitch Bradley