Saturday, June 13, 2009

Typing ColorForth 4.1

Well I thought I had done my last post on "typing ColorForth" at version 4.0. That version does everything I want. However it doesn't quite do it the way I wanted it to. I took code I found on the web that types comment text to the screen, modified it to use yellow "immediate" mode for accessing variables, and then factored the word ".s" (stype in the original version) using inline macros. At least I thought I was using inline macros. The reason is that I wanted to make it clear what .s does. Again the code from the original stype.

stype 1 + dup @ dup 15 and select stype ;

Anyone who understands ColorForth's tail recursion feature can tell what
stype ; does. And select is explained in the shadow block comments. But what does 1 + dup @ dup 15 and do? Not obvious is it? 1 + dup @ dup increments then retrieves from the string address. 15 and gets the tag value. You can factor that out those two phrases as "nextw" and "tag", but that doesn't do anything for code density in this case because the words are only used once yet you still have the penalty (albeit small) of the extra call.

So I thought about trying to inline it using
cyan words. My thought was that I could define the words inside the macro wordlist and then use them as cyan words in the normal forth wordlist and everything would be inlined. I'd get the readability improvement from factoring without the overhead.

On retrospect I believe my understanding of cyan words was not right.
Cyan should be used inside macro wordlist and not the forth wordlist. I believe the result of using cyan for a word defined as a macro is that a call was inserted instead of inline code.

Now I'm not sure if this is right either. But there is a better way to get the results I want. One of the key features of ColorForth is fall through factoring. The idea is that you can have multiple entry points to the same word. Using fall through factoring I can rewrite
.s as this:

select jump rest done done done done done done done done norm cap caps done done done done ;
.s
nextw 1 + dup @ dup
tag f and select .s ;

I can now document nextw and tag in the corresponding shadow block. Again, the entire code.

+first 0 +rest 0
type space fffffff0 and unpack +first @ + emit
rest unpack if +rest @ + emit rest ; then drop drop ;
done drop drop pop drop ;
norm 0 +first ! 0 +rest ! type ;
cap 48 +first ! 0 +rest ! type ;
caps 48 +first ! 48 +rest ! type ;
select jump rest done done done done done done done done norm cap caps done done done done ;
.S
nextw 1 + dup @ dup
tag f and select .s ;

And the shadow block:

type w display one 32-bit word of text
rest w finish typing a word
done aw drop addr and word and return from stype
norm normal text
cap text starts with a capital
caps all caps
select wt handle word according to tag
.s a display contiguous white text
nextw a get next word and increment address
tag n get tag field from word. used by select.

The usage remains the same. "Hello World" in 2 lines of ColorForth.

126 load hello 0 Hello World, I speak ColorForth
ok show blank text hello .s ;

Note: This will probably be the last version of Typing ColorForth (at least I hope so). It does (almost*) everything I want it to do as is as efficient and readable as I can make it. To the critics (well meaning I'm sure) who don't understand why I was doing this, please look at the rest of the Primary ColorForth tutorial. Doing all of the examples in Starting Forth by looking up codes and "emitting" them would be an unecessary pain in the butt. And yes, I could just type in "Hello World" on a blank screen, but that would not be flexible enough for what I'm doing.

(* There is one other thing I'd like to do. The current version sticks in an extra space before typing anything. Sometimes this throws the formatting off. But I'm going to quibble about that...for now.)

No comments: