Wednesday, December 27, 2006

Typing ColorForth...version 3.0

Cliche of the day: The third time's a charm

I've now extended my ColorForth text display library to the place where it's as "non-tedious" to use as possible. The first step was to be able to unpack and "type" a word rather than having to look up ColorForth charecter codes and emit them one at a time. The second step was to be able to print multiple words at one shot. That was in version 2.0. But the problem there was that I either had to put the number of words on the stack, or store them in the string variable itself. Now, after some brainstorming on the c4th IRC channel, I've come up with working code that figures out for itself how many words to type. Here it is.

s 0 hello , i speak forth
type fffffff0 and unpack if emit type ; then drop drop ;
nextw dup @ type space 1 + ;
tag f and ;
?ncom tag -9 + drop ;
print 1 +
ploop dup @ ?ncom if drop ; then nextw ploop ;
greet show text s print ;

A few notes here. Due to the way "print" works I couldn't use the old "nxtw" definition. So I modified it and changed the name. Also note, for those obsessing over lines of code (despite the fact that just about everyone knows that's no longer a good measure of program size, complexity or "tediousness") the above can be "compressed" into less lines, though IMO at the cost of readability.

s 0 hello , i speak forth
type fffffff0 and unpack if emit type ; then drop drop ;
print dup @ f and -9 + drop if drop then ; dup @ type space 1 + print ;
greet show text s 1 + print ;

There you have it. Four lines of ColorForth. (Or 3 lines depending upon where you put your variable.)

type fffffff0 and unpack if emit type ; then drop drop ; s 0 hello , i speak forth
print dup @ f and -9 + drop if drop then ; dup @ type space 1 + print ;
greet show text s 1 + print ;

And for the "ultra minimalist" (who doesn't want to bother with the tedium of looking up ColorForth charecter codes) you can do a simple "hello world" in 2 lines.

type fffffff0 and unpack if emit type ; then drop drop ; s 0 hello world
ok show text s dup push 1 + @ type 0 emit pop 2 + @ type ;

But that code isn't very robust. What happens when the string you want to type grows from 2 words to 6 as in "hello world, what a lovely day"? Still, that beats the pants off of emitting each charecter one at a time.

Anyway, this is the last I'm do anything with "hello world" programs for a while. I've got enough now to finish all of the examples in Starting Forth (chapter 1 anyway) with a minimum of tedium. This does remind me of how Chuck Moore answered the question of "hello world" programs on the ColorForth mailing list.
I've noticed the interest people have in getting colorForth to say "Hello
World".

The facility for doing that is extremely simple. Find an empty block. Edit
"Hello World" at the top.

I know that's not quite what they have in mind. But it's the way I'd
generate any sort of display. Format a block with the editor. Fill in
whatever numbers or graphics are required.
Gotta love it! "Hello world" in a single line and no need for tedious charecter code look ups and emits! Honestly though, that's what got me (and others) thinking about the "unpack" method of displaying text. The ColorForth to my understanding works by unpacking and displaying all of the 32 bit words in a block of code. But it's smart enough to understand compile words, macros, comments, numbers ect and choose the correct color and font. Right now the method I'm using only recognizes comments from non comments so it can't properly handle capitalization. But it should be intuitively obvious to the casual observer how to fix that. Perhaps I'll leave that as a "student exercise". :)

Typing ColorForth...ver 2.0

Hello folks. Back fresh from the forever flamewars at comp.lang.forth. :) It's funny how some people want to nitpick ColorForth while posting code that the ANS standard calls "dangerous".

Anyway the current "nitpick" is over my stype code. Small confession. I'm not omniscient. ;) When I posted at c.l.f. I was replying to the usual nonsense while thinking about where I was going with PrimaryForth tutorial as opposed to just answering what's possible now. Once I get finished you will be able to do the following code:

s 0 hello , i speak forth
ok show text s stype ;

And get:

hello, i speak forth

as output. Right now you get:

hello

as output. If you want to get the entire phrase you have to put the number of words you want to type on the stack use the "words" word. For example:

ok show text s 5 words ;

I really don't see that as a big deal. You still don't have to do:

hw
show blue screen text 230 350 at red 2a 10 c 1 3 3f 0 2e 3 c c 4 44 13 for 2emit next ; hw

But don't tell the "haters*" that. :) They still want to believe what they want to believe. Still, I've found a way around this. By storing the number of words in the ColorForth string variable (the same as the way ANS Forth stores the number of charecters in the first byte of an ANS Forth string variable) the computer can put the number of words on the stack for you. For example:

s 5 hello , i speak forth
phrase dup @
words for ntxtw next ;

Now with just one small line of ColorForth:

ok show text s phrase ;

You get:

hello , i speak forth

The next step will be to incorporate testing the token color. Comments use the "white" color. So phrase could be programmed to typing words until it hits a word that's not a comment. (Thanks to "tathi" on the c4th IRC channel for kicking this idea around.)

* Note: By "haters" I don't mean the person who actually wrote the ColorForth code I referenced. I mean those who want to insist on using that as "proof" that it's difficult to do something as simple as "hello world" in ColorForth rather than seeing the obvious. ColorForth, like any other Forth, is extensible.

Typing ColorForth

I made the following extensions to ColorForth.

s 0 hello , i speak forth

stype 1 + @
type fffffff0 and unpack if emit type ; then drop drop ;

The word "type" takes a packed word and displays it on the screen. Right now it ignores all color tags and just emits charecters using the current foreground color. Note that s is a string variable. Actually it's just a regular variable, but I'm treating it like a string variable. Variables in ColorForth really point directly to block memory. So by adding 1 to the address of s I can get the address of the text for "hello". The word "stype" adds 1 to the address on the stack and then returns data which is treated by "type" as a packed string. So the code:

greet show text s stype ;

Will display "hello" on the screen. Of course that's only part of the phrase. I added a definition to get a word, display it, and add the address for the next word.

nxtw 1 + dup @ type space ;

The word "space" was defined in a previous posting. I then added a word to unpack and display several words of text.

words for nxtw next ;

So the code:

greet show text s 5 words ;

Will display:

hello , i speak forth

I'm looking for better ways to do this. All comments welcome.

Thursday, December 21, 2006

Starting Forth chapter 1 examples.

Intro to PrimaryColorForth

The goal here is to simply reproduce all of the examples from chapter 1 of Starting Forth in ColorForth.

Washing Machine Example

washer wash spin rinse spin ;

In ColorForth red words signify the start of a new definition. So "washer" is the new procedure. The ";" represents the call return. The green words are procedures that have already been defined. Let's look at the definition of rinse.

rinse faucets open till-full faucets close ;

The definition includes "things" (faucets) and verbs (open and close). The word "till-full" represents a delay loop. After the faucets "open" the word waits "till-full" before they "close".

Note. Unlike traditional Forth words cannot be defined from the command line. All words must be defined in the editor. Then the block containing the source text must be loaded. For example if you defined some new words in block 22 you would type:

22 load

Putting on a show

Forth was originally designed around a TTY display model. But ColorForth uses a GUI display, albeit one that is MUCH simpler than MS Windows, X-Windows or MacIntosh. So getting things displayed on the screen is a bit tricker than traditional Forth, but simpler than raw programming of most GUI operating system. The ColorForth word "show" creates a display task using the words following it.

Consider this definition.

ok show text 45 emit keyboard ;

This creates a new definition "ok" that draws a "*" at the top left corner of the screen. The word "text" moves the cursor to the top left of the screen and sets the drawing color to white. The word "emit" takes a number off the stack and draws the corresponding charecter. It's the same as "emit" in traditional Forth. Note that the charecter set is different from ASCII. The word "keyboard" redraws the keyboard and stack.

Chapter 1 of Starting Forth builds up an example on how to draw the letter "F" as a large charecter using "ASCII art". Here is a walkthrough of that example using colorForth.

The first word "space" draws a blank space on the screen.

space 0 emit ;

The next word "spaces" draws a certain number of spaces. For instance "5 spaces" would draw 5 spaces. Note that the "for..next" loop will be covered in detail later.

spaces for space next ;

The word "star" is similar to "space" but draws a star.

star 45 emit ;

The word "stars is similar to "spaces" but draws a number of stars.

stars for star next ;

The next words define the "F" using combinations of the above defined words. Note that "cr" stands for "carriage return". That simply moves the cursor to the next line.

side star spaces star ;
margin cr 30 spaces ;
blip margin star ;
bar margin 5 stars ;
f bar blip bar blip blip cr ;
ok show text f keyboard ;

After loading the block containing these words and typing "ok" from the command line a large "F" will be displayed on the screen.

Re-starting "Primary Colorforth"

Hello all. Some months ago I announced that I was working on a tutorial for ColorForth called Primary ColorForth. It is a play on words for the Leo Brodie classic Starting Forth. The plan was (and still is) to build a tutorial that follows the "spirit" of Starting Forth while departing from it when necessary to better fit the ColorForth model. I made a little progress. (Actually Jeff Fox made a bigger contribution than I did with his "Editor" chapter.)

However the project got stalled. Part of the problem is that I got waylaid by other projects. But another bigger problem was the classic "chicken and egg" problem. Some of the examples I wanted to do in the first chapter required advanced concepts that I didn't want to cover until other chapters. I was really stuck. Then, in a discussion with Jeff Fox in the USENET group comp.lang.forth about learning VentureForth I got an idea. Jeff suggested that someone learning VentureForth should try to do the examples from Staring Forth in it. I found then (and still find) that a daunting prospect. But I knew I could many of them in ColorForth so I decided to try. Then while reading the first chapter I noticed that Brodie put some advance code in an example and simply said we'll explain how it works in a later chapter. Now why did I think of that?

So I'm restarting my efforts. Things that I need to explain later, I'll just note and explain later. It's good to be back!

I'm going to use the blog to track my progress. While the tutorial will be built here, this won't be the final "polished" version. That will be put at the ColorForth Wiki. I don't want to be slowed down by trying to be "perfect" the first time.