Thursday, June 19, 2008

Adding New Word Classes

In my previous post I discussed the concept of word classes. In this post I'll show how to define and add a word class to Retro. This assumes that you know Forth, and have some experience with Retro. Consult the documentation if you have questions on the words used.

For this example, we'll create a class for strings with the following behaviour:

  • If interpreting, display the string
  • If compiling, compile the code needed to display the string

Retro has a convention of using a . as the first character of a class name. We'll call our new class .string

On entry to a class handler, the address (xt) of the word or data element is on the stack. The compiler state (often important to class handlers) is stored in a variable named compiler. With this in mind, we'll define our class:

  : .string ( xt -- )
    compiler @ 0 =if type ;; then
    1 , , ['] type compile ;

The compile-time portion is a bit trickier than the interpret time since it has to lay down the proper code in the target definition. In this case a LIT instruction (opcode 1) is laid down, followed by the xt of the string. This is followed by code to lay down a call to type.

We now need a creator word to attach this class to a value. For this example we'll define displayString: to take a form like the one shown below.

  string-addr displayString: name

New dictionary entries are made using create, so we'll use that and change the class to our new .string handler.

  : displayString: ( string-addr -- )
    create ['] .string last @ d->class !
    keepString last @ d->xt ! ;

This uses create to make a new word, then sets the class to .string and the xt of the word to the string. It also makes the string permanent using keepString. last is a variable pointing to the most recently created dictionary entry. The words d->class and d->xt are dictionary field accessors and are used to provide portable access to fields in the dictionary.

We can now test our new class:

  " hello, world!" displayString: hello
  hello
  : foo hello cr ;   foo

No comments: