Saturday, May 30, 2026

Update to the matrix multiplication example.

 Wow!  It's been 16 years since I did that and I haven't done much with ColorForth since. But some new developments have peaked my interest again.  One is the explosion of artificial intelligence and it's enormous energy requirements.  The GA144 has long been touted for its efficiency.  The other is that GreenArrays recently announced a new partnership with AI startup Volatco which has developed its own 2 GA144 board with 2 MB of SRAM and 32 MB SPI flash.  By contrast the GreenArrays eval board comes with 1 MB of SRAM and 1 MB flash.  The GA board has USB build in which the Voltaco board lacks and is considerably larger.  Hopefully the Voltaco will come in as a lower price point.

 


 GreenArrays Inc has ended support for ColorForth and is now using a version of polyForth for development. However ColorForth is available for download.  The latest version of ColorForth doesn't work with my original code as some of the default boot code for the F18 cores changed.  After having Claude.ai help me work through the documentation, I got the code working again.  In the process I better learned how this all worked.  Here is the updated code which I put in blocks 798 to 804.  Note that block 200 is the "loader" block used to tell softsim to load which blocks into which nodes and block 216 is the "config" block that sets the initial states for each node. By default the program counter is set to xA9 which does a multi-port read.  For this example all three nodes start at address 0 and that is set by 0 /p.

 

 


multicore matrix multiplication example,
a 2 row by 8 col matrix is multiplied by,
a 2 col by 8 row matrix cr
resulting in a vector r1*c1 r1*c2 r2*c1 r2*c2,
cr
r1out send vector r1 to right node cr
r2out sent vector r2 to down node cr
c1,c2out send vectors c1,c2 to right indent
  
and down nodes cr
getres get results from rt and dwn nodes cr
note 0 org means the code is compiled to that
address                                       

   798 list
0 org r2out right b! 7 for @p !b unext cr
1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , cr
r2out down b! 7 for @p !b unext cr
9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , cr
rd-- b! 0 !b c1,c2out 15 for @p !b unext cr
17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , cr
25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , cr
getres right b! @b @b down b! @b @b r---      


helper functions for worker nodes
getvector
gets vector from manager node
*
ab-a*b 17 bit multiply
.prod
a-n get vector and do dotproduct with,
vector stored at a
r*c1,c2
p- read r from port p then read c1 and
c2 and do dot products with r. return results
to port p                                     

   800 list
getrow a! 7 for @b !+ unext ;
*
a! dup dup or 17 push . begin +* unext drop
drop a ;

.prod
a! dup dup or 7 for @b @+ a push * + pop
a! next ;

r*c1,c2
b! 60 getrow @b drop 60 .prod 60 .prod
!b !b ;                                       


code for right worker node                    

   802 list
4 org 800 load 0 org left r*c1,c2 r---        


code for down worker node                     

   804 list
4 org 800 load 0 org up r*c1,c2 r---          


use this load block to compile your code cr
for the f18 computers. br

as delivered, sample code loaded here is pro-
vided to facilitate working with examples
cr
presented in the user's guide. it may be cr
deleted if you no longer have use for it.     

   200 list
user f18 code reclaim 716 node 798 load 717 no
de
802 load 616 node 804 load br

softsim example reclaim 0 node 1342 load cr
practical example pwm code reclaim 842 load br

sha256 reclaim 900 5 loads,
greg n1 object 950 load,
mangpo test 894 load,
an012 sensortag 960 load,
,
hardsim pwr verify 882 load,
random 884 load                               


this block is loaded by softsim to set the,
configuration for a given simulation. edit it
as needed to set up testbeds, load application
code and initialize it for running, and set
,
breakpoints.,
,
see arrayforth user's manual for information,
about these options.                          

   216 list
softsim configuration,
,
spi boot testbed 1244 2 loads,
sync boot testbed 'addr,len' 1230 load,
,
smtm 0 +node 0 /ram 0 /p,
/command test 400 +node 0 /ram 25 /a 12 /b,
9 8 7 6 5 4 3 2 1 12345 10 /stack A9 /p,
,
rom write test 200 +node 13 /p,
,
0 32 103 break,
0 BE 300 break,
616 +node 0 /p 716 +node 0 /p 717 +node 0 /p  

Monday, January 18, 2021

Primary ColorForth Chapter 1

As mentioned in the intro, Primary ColorForth is loosely based on Starting Forth. You can follow along in it for this tutorial series either with a hardcopy version or online. Starting Forth chapter 1 starts by describing a way of organizing work by defining useful tasks and giving them a name, then grouping tasks together into larger tasks and naming them. It gives the example of an embedded washing machine program which we will explore. 

Washing Machine Example 

 Here is the top level washing machine program in ColorForth. 

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. Green words are ones that have already been defined and are compiled into the new definition. Note that 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, to define new words in block 22 you would use 22 edit, then to compile then you would use 22 load. Let's look at the definition of rinse

rinse fill agitate drain ; 

 And now the definition of fill

fill 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". Every word must be defined before it can be compiled into a definition, so fill must be compiled before rinse and rinse must be compiled before washer

fill faucets open till-full faucets close ; 
rinse fill agitate drain ; 
washer wash spin rinse spin ; 

 This system is just an example. For a real system the definitions for open, close, faucets, till-full, agitate, drain and spin would all have to be defined. At some point it would be direct machine code to activate stepper motors, read sensors etc. 

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 trickier 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 93 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 character set is different from ASCII. You can look up the characters in a code map, or you can use the command icons. 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 character using "ASCII art". Here is a walkthrough of that example using colorForth. First we need to define the word spaces which is built into traditional Forth. 

spaces for space next ; 

Note ColorForth uses for...next for its counted loop structure. Using spaces with what we learned earlier we can code the following: 

(Also note that when this blog post was first published in 2009, the word "space" was built into ColorForth.  But the latest version of ColorForth from GreenArrays called "arrayForth" does not have that word built it.  It is defined:
space 0 emit ; )

space 0 emit ; 
spaces for space next ; 
ok show text 15 spaces 93 emit ; 

Notice when we run this, the word spaces doesn't erase the text already on the screen, but just moves the star over. That's another example of how graphical CF is different from TTY TF. Now let's define star as it's own word. spaces for space next ; star 93 emit ; go show text 15 spaces star ; Moving sections of code into their own definitions is called factoring. Factoring is used to increase readability and/or code density. 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. 

stars for star next ; 
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. 

Hello World from ColorForth 

 The next Starting Forth example is a variation on the venerable "Hello World" program. This particular program has cause some needless controvery and confusion over the years. Sure you emit each character one at a time, but that's not the most readable solution nor the most flexible. ColorForth can type blocks of text just like traditional Forth. And since ColorForth is extensible, just like traditional Forth is extensible, you extend it to where you can do a program like "Hello World" in just two lines. First you have to understand how text is stored in the ColorForth editor. ColorForth doesn't store ASCII characters in bytes. Instead it packs several characters in one 32 bit word using Shannon encoding, eabling it to store 5 to 7 characters plus a color token in one word. ColorForth includes a word unpack for decompressing such words. We have already discussed red and green words. ColorForth uses white words for comments. Comments can be as all lowercase, all upper case, or mixed case. So one way to display a block of text is to store it as comments in a Forth block, put that address on the stack, and then unpack and properly display the words until a non comment word is reached. Here is the code to set this up: 

+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 @ 
tag dup 15 and select .s ; 

That may look like a lot, but realize that you can load this block whenever you need it or you can even have it load automatically when ColorForth boots. Here is an example of its usage (assuming the code was stored in block 126). 

126 load s 0 Hello world, I speak ColorForth 
ok show text s .s ; 

 Note that magenta words like s define variables. Variables in ColorForth point to the blocks where they are defined as opposed to the dictionary. So s is being used here to point to the comment block of text we want to type. 

Run-time Versus Compile-time Versus Edit Time 

 Starting Forth then goes into a discussion about "run time versus compile time". This is a good time (no pun intended) to go into the other color states in ColorForth. We've already gone over how red defines a new word and how green compiles a previously defined word into a new definition. Green words are executed at run time. There are also yellow words that are executed at compile time. Consider the "hello world" example given earlier. 

126 load s 0 Hello world, I speak ColorForth 
ok show text s .s ; 

 Note the phrase 126 load. This will load the text display code in block 126 as soon as the current block is loaded. You don't have to wait until ok is run. Also note that the acess to the variable s is in yellow too. A variable is really just a name for an address. Why wait until run time to look up the address? Why not look it up at compile time and compile the address directly into the code? Accessing variables as yellow words instead of green ones accomplishes that. In fact that is the preferred way. Another way to use yellow words are with constants. When a constant is coded in yellow its value is compiled into the code on the yellow to green transition. This is also true for calculations that are done in yellow. Using the earlier "big F" exampe: 

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 ; 

Yellow words can also be used to do calculations that can be determined at compile time such as calculations based on a constant. Cyan words are used to create inline macros. 

The Dictionary 

 ColorForth, like traditional Forth, stores definitions in a dictionary. One difference is the way ColorForth handles numbers. In traditional Forth the interpreter first looks in the dictionary find a word and if it's not found it checks to see if it is a number. The ColorForth editor handles numbers differently. So the compiler never has to check to see if something is really a number. 

The Stack: Forth's Worksite for Arithmetic 

 If you are already familiar with Forth (or with HP scientific calculators) you know you to use the stack. If not here's a brief overview. Everytime a number is entered it is pushed on the stack. Forth arithmetic words will take numbers off the stack, do some operation with them, and return the results to the stack. To do 3 + 4 you must first push the 3 and the 4 to the stack then execute the "+" word. 3 4 + Note that the current state of the stack is shown on the bottom left of the screen. If you use the dot command . by itself all you will notice is that one number drops off. In traditional Forth . displays the top number on the stack. If you use . inside of a show word you get the traditional result. go show 3 4 + . ; Problems Problem 1-1: Define a word called gift that, when executed, will type out the name of some .gift, a word .giver that prints out a person's name, and a word .thanks that prints out something like this: 

 Dear Stephanie, Thanks for the bookends. 

 Solution: 

gift 0 bookends. giver 0 Stephanie, dear 0 Dear thank 0 Thanks for the 
.gift gift .s ; 
.giver giver .s ; 
.thank thank .s ; 
.dear dear .s ; 
thanks show black screen text .dear .giver .thank .gift ; 

Alternatively: 

gift 0 bookends. giver 0 Stephanie, dear 0 Dear thank 0 Thanks for the
thanks show black screen text dear .s giver .s thank .s gift .s ; 

 Problem 1-2: Define a word tenless that takes a number on the stack, substracts 10, and returns the answer on the stack. (Hint: You can use +.) 

Be sure to include stack effects. 

 Solution tenless n-n' -10 + ; 

 Problem 1-3: After entering the words in Problems 1-1, enter a new definition for .giver to print someone else's name, then without redefining thanks, execute thanks again. Can you explain why thanks still prints out the first giver's name?

 Solution 

gift 0 bookends. giver 0 Stephanie, dear 0 Dear thank 0 Thanks for the 
.gift gift .s ; 
.giver giver .s ; 
.thank thank .s ; 
.dear dear .s ;
thanks .dear .giver .thank .gift ; giver 0 Jill
.giver giver .s ; 
go show black screen text thanks .giver ; 

 Alternatively: 

gift 0 bookends. giver 0 Stephanie, dear 0 Dear thank 0 Thanks for the
thanks dear .s giver .s thank .s .gift .s ; giver 0 Jill 
go show black screen text thanks giver .s ; 

Whenever a new word is compiled it is appended to the end of the dictionary. The old definition isn't overwritten, but the interpreter starts at the newest definition and searches backwards so it doesn't find the older definition. However words that were defined using the old definition still work the same.

Labels:

Tuesday, March 30, 2010

Matrix Multiplication example ported to arrayForth

I'm going to put up a better description later. Right now I just want to get this up on the web. It works! (Took a while). The source HTML was generated by the built in arrayForth HTML generator.

To run the code put the following at the top of block 1302:

0 node 200 load 1 node 204 load 2 node 206 node 3 node 210 load exit

Note that the multicore matrix example is in blocks 200 to 208 and uses nodes 0, 1 and 2.  Block 210 does the same thing with a singlecore (node 3).  The multicore example finishes in 1479 cycles and the singlecore example takes 3040 cycles.  I verified that the multiplications are correct using the statistical language R.  At some point I plan to make a video explaining how this all works, but again right now I just want to get the results up.


































multicore matrix multiplication example cr
a 2 row by 8 col matrix is multiplied by cr
a 2 col by 8 row matrix cr
resuting in vector r1*c1 r1*c2 r2*c1 r2*c2 cr
cr
r1out send vector r1 to right node cr
r2out send vector r2 to down node cr
rtdwn set port to right and down cr
synch dummy write to synchronize nodes cr
c1c2out send vectors c1 and c2 to right indent
    
and down nodes cr
getres get results from right and down vectors

  200 list

0 org r1out right b! 7 for @p !b unext cr
1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , cr
r2out down b! 7 for @p !b unext cr
9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , cr
rtdwn B5 b! cr
synch 0 !b cr
c1c2out 15 for @p !b unext cr
17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , cr
25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , cr
getres right b! @b @b down b! @b @b r---      


invect a- read in vector and store at a
*
ab-a*b 17 bit multiply
.prod
a-n read in vector and do dot product wi
th vector stored at a

r*c1,c2
p- read r from port p then read c1 and
c2 and do dot products with r. return results
to port p                                     

  202 list

invect a! 7 for @b !+ unext ;
*
a! dup dup or 17 push . begin +* unext drop
drop a ;

.prod
a! dup dup or 7 for @b @+ a push * + pop
a! next ;

r*c1,c2
b! 60 invect cr
synch @b drop cr
60 .prod 60 .prod !b !b ;                     


                                              

  204 list

0 org 202 load 69 org right r*c1,c2 r---      


                                              

  206 list

0 org 202 load 69 org down r*c1,c2 r---       


                                              

  208 list

0 org
*
a! dup dup or 17 push . begin +* unext drop
drop a ;
cr
69 org 3 3 * r---                             


singlecore matrix multiplication example cr
* ab-a*b 17 bit multiplication
*sum
v2ofs-n vector v1 is stored in a and cr
v2ofs is the offset to vector v2. sum the cr
products of v1 and v2.                        

  210 list

0 org
*
a push a! dup dup or 17 push . begin +* unex
t drop drop a pop a! ;

*sum
dup dup or 7 for over a + b! @+ @b * + ne
xt push drop pop ;
69 org cr
40 a! 10 *sum 8 *sum 40 a! 18 *sum 10 *sum r--
-
40 org cr
1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , cr
9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , cr
17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , cr
25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , cr
                                              

Sunday, June 14, 2009

Primary ColorForth Chapter 2

First some housekeeping:

Since Starting Forth is based on traditional Forth, there are some examples that won't work out of the box on ColorForth. Most of the required words can be easily implemented such as spaces back in chapter 1. Some words already exist but are not available in interactive mode because they have only been defined in the macro wordlist. I will define definitions needed for the Starting Forth examples as we go along. Alternatively here are the new definitions together.

/mod ab-qr /mod ;
mod ab-r mod ;
swap ab-ba swap ;
over ab-aba over ;
rot abc-bca push swap pop swap ;
2swap abcd-cdab push rot rot pop rot rot ;
2dup ab-abab over over ;
2over abcd-abcdab push push 2dup pop pop 2swap ;
2drop ab- drop drop ;

Forth Arithmetic -- Calculator Style

Starting Forth identifies the four fundamental arithmetic instructions in traditional Forth are +, -, *, and /. ColorForth has +, * and /. You might be wondering what happened to -. It is a macro that returns the one's complement (the same as invert in ANS Forth). This corresponds to the way - is used in Charles Moore's MISC processors since MuP21. You can still subtract by adding the negative. For constants just use the negative value. For variables or calculated results you can get the negative using NEGATE.

Starting Forth then gives several examples of postfix math. Note as mentioned in chapter 2, in ColorForth you don't need to use
. in interactive mode except as a shortcut for drop. You can also clear the entire stack using c. ColorForth continuously displays the parameter stack in the lower left of the screen. Try the following:

17 5 +
7 8 *
3 4 +
500 -300 +
5 6 *
20 4 /
c


An example of adding multiple numbers:

17 20 + 132 + 3 + 9 + .

Converting infix expressions to postfix (quizzie 2-a)

Here is a little trick I learned as a computer science undergraduate. Fully parenthesize your expression and move all operators to the end of the corresponding parenthesis. Examples:

c(a + b) => (c*(a+b)) => (c(a b)+)* => c a b + *

a*b/100 => ((a * b)/100) => ((a b)*100)/ => a b * 100 /

Try the following on your own:

(3a - b)/4 + c

(a + 1)/4

x(7x + 5)

Forth Arithmetic -- Definition Style

The next examples are for converting from yards or feet to inches. We know 1 yard = 36 inches and 1 foot = 12 inches. Here is the conversion code:

yards-inches 36 * ;
feet-inches 12 * ;

Usage example:

10 yards-inches
2 feet-inches

If we always want results to be in inches, we can define:

yards 36 * ;
feet 12 * ;
inches ;

to get the phrase

10 yards 2 feet + 9 inches +

Now perhaps you want to be able to use singular or plural words for better readability. Starting Forth used the following code:

: yard yards ;
: foot feet ;
: inch ;

That has the undesiable effect of adding an extra word call just for the sake of readability. ColorForth can do the same without the overhead using fall through factoring. The same definition can have multiple entry points. So in ColorForth you can define:

yard
yards 36 * ;
foot
feet 12 * ;
inch
inches ;

Note that yard and yards, foot and feet, inch and inches all point to the same memory location.

Now let's consider the earlier example of adding 5 numbers together.

17 20 + 132 + 3 + 9 +

The same thing could be accomplished by moving the
+'s to the end.

17 20 132 3 9 + + + +


Changing this to a definition we get:

5sum + + + + ;

Now say if in the same program sometimes we needed to add 5 numbers together and sometimes we needed to add 3? We could use fall through factoring here.

5sum + +
3sum + + ;

This time
5sum and 3sum point to different locations in memory. If you call 5sum it does the first 2 additions and then "falls through" to the remaining 2 additions in 3sum. If you call 3sum it just does the required 2 additions and returns.

An equation for another definition:

(a + b) * c

In postfix:

a b + c *

Alternatively we could say:

c * (a + b)

In postfix:

c a b + *

from which we can write the definition:

solution + * ;

It's a good time to point out that in Forth it's sometimes better to re-write an equation to make it easier to manipulate on the parameter stack. Here is the same code as a word problem:

If a jet plane flies at an average air speed of 600 mph and if it flies with a tail wind of 25 mph, how far will it travel in five hours?

If we define:

flight-dist + * ;

we could enter
5 600 25 flight-dist and get 3125 on the top of the stack.

Try it with different values, including head winds (negative values).


The Division Operators

The basic division in ColorForth (and traditional Forth as well) is /. This is an interger operator which discards the remainder.

22 5 /

This leaves 4 on the stack. There are two other division operators,
mod and /mod. By default they are in the macro wordset and only available during compilation. However they can be compiled to the Forth wordset.

mod ab-r mod ; returns the remainder
/mod ab-qr /mod ; returns quotient and remainder

Testing
/mod interactively: 22 4 /mod leaves 2 5 on the stack.

We can define a word quarters that takes a number of quarters and calculates the dollars and leftover quarters.

126 load q 0 quarters ones 0 ones
quarters 4 /mod . q .s . ones .s ;
go show blank text 22 quarters ;

Test
mod interactively: 22 4 mod leaves 2 on the stack.

Stack Manipulation

Swap

As the name suggests, this word takes the top too numbers on the stack and swaps them. Again this word is only in the macro wordlist. To use it interactively:

swap swap ;

Testing this interactively:
1 2 swap leaves 2 1 on the stack.

Dup

Dup takes the top number on the stack and duplicates it.
2 dup leaves 2 2 on the stack.

You can use dup to square a number.
4 dup * leaves 16 on the stack.

Over

Over is defined only in the macro wordlist. To use it interactively define:

over over ;

Over takes the second item on the stack and copies it to the top of the stack.

Testing it interactively,
1 2 over leaves 1 2 1 on the stack.

Thus the expression

a * (a + b)

can be written as:

over * +

Rot

Rot is in traditional Forth but is not by default defined in ColorForth. However defining it is simple. It requires a the words
push and pop. These words manipulate the second stack called the "return stack". Starting Forth doesn't cover this until another chapter. Basically push takes the top number from the parameter stack and moves it to the return stack. pop does the opposite. Using them rot is defined as:

rot push swap pop swap ;

Rot takes the 3rd item on the stack and rotates it to the top.

Testing it interactively:
1 2 3 rot leaves 2 3 1 on the stack.

Say if you wanted to evaluate the expression
ab - bc. First factor out the b's.

b*(a - c)

Now starting with
c b a on the stack we can use rot - *.

Drop

Drop, as its name suggests, drops the top item on the stack. Testing interactively:
1 2 drop leaves 1 on the stack.

Note: Look ma! No .s. Starting Forth mentions at this point that .s can be used to display the stack non destructively. But ColorForth shows the stack in interactive mode at the bottom left of the screen. Thus .s is not needed and not defined. Hence I can use .s is ColorForth for printing strings.

Stack Manipulation and Math Definitions (Quizzie 2-c)

1. Write a phrase which flips three items on the stack, leaving the middle number in the middle; that is:

a b c ==> c b a

Answer:
swap rot

2. Write a phrase that does what
over does, without using over.

Answer:
swap dup rot rot

3. Write a definition called
-rot, which rotates the top three stack items in the opposite direction from rot; that is:

a b c ==> c a b


Answer: -rot rot rot ;

Write definitions for the following:

4. (n+1) / n

Answer: 2c4 dup 1 + swap / ;

5. x(7x + 5)

Answer: 2c5 dup 7 * 5 + * ;

6.
9a2 - ba

a(9a - b)

Answer:
2c6 over 9 * swap - * ;

Playing Doubles

Many early Forths ran on 16 bit computers. As such "double" words, which allowed 32 bit math, were very important. ColorForth was initially written for a 32 bit computer and thus does not implement double words. However double stack manipulation words are not difficult to write.

2swap abcd-cdab push rot rot pop rot rot ;
2dup ab-abab over over ;
2over abcd-abcdab push push 2dup pop pop 2swap ;
2drop ab- drop drop ;

Problems -- Chapter 2

1. What's the difference between DUP DUP and 2DUP?

2. Write a phrase which will reverse the order of the top four items on the stack; that is,

( 1 2 3 4 -- 4 3 2 1 )

Answer:
reverse swap 2swap swap ;

3. Write a definition called 3DUP which will duplicate the top three numbers on the stack; for example,

Answer:
3dup abc-abcabc dup 2over rot ;

Write definitions for the following infix equations, given the stack effects shown:
4. a2 + ab + c ( c a b -- result )

a(a + b) + c

Answer:
prob4 over + * + ;

5. (a-b) / (a+b) ( a b -- result ) [answer]

Answer:
prob5 2dup - -rot + / ;

6. Write a set of words to compute prison sentences for hardened criminals such that the judge can enter:

CONVICTED-OF ARSON HOMICIDE TAX-EVASION ok
WILL-SERVE 35 years ok

or any series of crime beginning with the word CONVICTED-OF and ending with WILL-SERVE. Use these sentences

HOMICIDE 20 years
ARSON 10 years
BOOKMAKING 2 years
TAX-EVASION 5 years

Answer:

126 load years 0 years
convicted-of 0 ;
homicide 20 + ;
arson 10 + ;
bookmaking 2 + ;
tax-evasion 5 + ;
will-serve . years .s ;
ok show blank text convicted-of homicide arson tax-evasion will-serve ;

7. You're the inventory programmer at Maria's Egg Ranch. Define a word called EGG.CARTONS which expects on the stack the total number of eggs laid by the chickens today and prints out the number of cartons that can be filled with a dozen each, as well as the number of left-over eggs.

126 load cartons 0 cartons eggs 0 eggs
egg.cartons e-cr 12 /mod . cartons .s . eggs .s ;
ok show blank text 55 egg.cartons ;