# 8 Variables, Constants, and Arrays

As we have seen throughout the previous seven chapters, Forth programmers use the stack to store numbers temporarily while they perform calculations or to pass arguments from one word to another. When programmers need to store numbers more permanently, they use variables and constants.

In this chapter, we'll learn how Forth treats variables and constants, and in the process we'll see how to directly access locations in memory.

## Variables

Let's start with an example of a situation in which you'd want to use a variable--to store the day's date. First we'll create a variable called `DATE`. We do this by saying

    	VARIABLE DATE

If today is the twelfth, we now say

    	12 DATE !

that is, we put twelve on the stack, then give the name of the variable, then finally execute the word !, which is pronounced store. This phrase stores the number twelve into the variable `DATE`.

Conversely, we can say

    	DATE @

that is, we can name the variable, then execute the word @, which is pronounced fetch. This phrase fetches the twelve and puts it on the stack. Thus the phrase

    	DATE @ . 12 ok

prints the date.

To make matters even easier, there is a Forth word whose definition is this:

    	: ?   @ . ;

So instead of "DATE-fetch-dot," we can simply type

    	DATE ? 12 ok

The value of `DATE` will be twelve until we change it. To change it, we simply store a new number

    	13 DATE ! ok
    	DATE ? 13 ok

Conceivably we could define additional variables for the month and year:

    	VARIABLE DATE   VARIABLE MONTH   VARIABLE YEAR

then define a word called `!DATE` (for "store-the-date") like this:

    	: !DATE  YEAR !  DATE !  MONTH ! ;

to be used like this:

    	7 31 03 !DATE ok

then define a word called `.DATE` (for "print-the-date") like this:

    	: .DATE  MONTH ?  DATE ?  YEAR ? ;

Your Forth system already has a number of variables defined; one is called BASE. BASE contains the number base that you're currently working in. In fact, the definition of HEX and DECIMAL (and OCTAL, if your system has it) are simply

    	: DECIMAL  10 BASE ! ;
    	: HEX      16 BASE ! ;
    	: OCTAL     8 BASE ! ;

You can work in any number base by simply storing it into BASE.

> For Experts
> A three-letter code such as an airport terminal name, can be stored as a single-length unsigned number in base 36. For example:

>     	: ALPHA  36 BASE ! ; ok
>     	ALPHA ok
>     	ZAP U. ZAP ok

Somewhere in the definitions of the system words which perform input and output number conversions, you will find the phrase

    	BASE @

because the current value of BASE is used in the conversion process. Thus a single routine can convert numbers in any base. This leads us to make a formal statement about the use of variables:

In Forth, variables are appropriate for any value that is used inside a definition which may need to change at any time after the definition has already been compiled.

## A Closer Look at Variables

When you create a variable such as `DATE` by using the phrase

    	VARIABLE DATE

you are really compiling a new word, called `DATE`, into the dictionary. A simplified view would look like the view below.

4 | D | A | T | E
instruction code appropriate for variables
space for the actual value to be stored

`DATE` is like any other word in your dictionary except that you defined it with the word VARIABLE instead of the word :. As a result, you didn't have to define what your definition would do, the word VARIABLE itself spells out what is supposed to happen. And here is what happens:

When you say

    	12 DATE !

Twelve goes onto the stack, after which the text interpreter looks up `DATE` in the dictionary and, finding it, points it out to EXECUTE.

EXECUTE executes a variable by copying the address of the variable's "empty" cell (where the value will go) onto the stack.

The word ! takes the address (on top) and the value (underneath), and stores the value into that location. Whatever number used to be at that address is replaced by the new number.

(To remember what order the arguments belong in, think of setting down your parcel, then sticking the address label on top.)

The word @ expects one argument only: an address, which in this case is supplied by the name of the variable, as in

    	DATE @

Using the value on the stack as an address, the word @ pushes the contents of that location onto the stack, "dropping" the address. (The contents of the location remain intact.)

## Using a Variable as a Counter

In Forth, a variable is ideal for keeping a count of something. To reuse our egg-packer example, we might keep track of how many eggs go down the conveyor belt in a single day. (This example will work at your terminal, so enter it as we go.)

First we can define

    	VARIABLE EGGS

to keep the count in. To start with a clean slate every morning, we could store a zero into `EGGS` by executing a word whose definition looks like this:

    	: RESET  0 EGGS ! ;

Then somewhere in our egg-packing application, we would define a word which executes the following phrase every time an egg passes an electric eye on the conveyor:

    	1 EGGS +!

The word +! adds the given value to the contents of the given address. (It doesn't bother to tell you what the contents are.) Thus the phrase

    	1 EGGS +!

increments the count of eggs by one. For purposes of illustration, let's put this phrase inside a definition like this:

    	: EGG  1 EGGS +! ;

At the end of the day, we would say

    	EGGS ?

to find out how many eggs went by since morning.

Let's try it:

    	RESET ok
    	EGG ok
    	EGG ok
    	EGG ok
    	EGGS ? 3 ok

Here's a review of the words we've covered in the chapter so far:

`VARIABLE xxx` | ( -- ) xxx: ( -- addr ) | Creates a variable named xxx; the word xxx returns its address when executed. |
`!` | ( n addr -- ) | Stores a single-length number into the address. |
`@` | ( addr -- n ) | Replaces the address with its contents. |
`?` | ( addr -- ) | Prints the contents of the address, followed by one space. |
`+!` | ( n addr -- ) | Adds a single-length number to the contents of the address. |

## Constants

5 | L | I | M | I | T
instruction code appropriate for constants
220

While variables are normally used for values that may change, constants are used for values that won't change. In Forth, we create a constant and set its value at the same time, like this:

    	220 CONSTANT LIMIT

Here we have defined a constant named `LIMIT`, and given it the value 220. Now we can use the word `LIMIT` in place of the value, like this:

    	: ?TOO-HOT  LIMIT > IF  ." Danger -- reduce heat "  THEN ;

If the number on the stack is greater than 220, then the warning message will be printed.

Notice that when we say

    	LIMIT

we get the value, not the address. We don't need the "fetch."

This is an important difference between variables and constants. The reason for the difference is that with variables, we need the address to have the option of fetching or storing. With constants we always want the value; we absolutely never store. (If you really need to store a new value into a "constant", you should use a VALUE.)

One use for constants is to name a hardware address. For example, a microprocessor-controlled portable camera application might contain this definition:

    	: PHOTOGRAPH   SHUTTER OPEN  TIME EXPOSE  SHUTTER CLOSE ;

Here the word `SHUTTER` has been defined as a constant so that execution of `SHUTTER` returns the hardware address of the camera's shutter. It might, for example, be defined:

    	HEX
    	FFFF3E27 CONSTANT SHUTTER
    	DECIMAL

The words `OPEN` and `CLOSE` might be defined simply as

    	: OPEN  1 SWAP ! ;
    	: CLOSE 0 SWAP ! ;

so that the phrase

    	SHUTTER OPEN

writes a "1" to the shutter address, causing the shutter to open.

Here are some situations when it's good to define numbers as constants:

1. When it's important that you make your application more readable. One of the elements of Forth style is that definitions should be self-documenting, as is the definition of `PHOTOGRAPH` above.
2. When it's more convenient to use a name instead of the number. For example, if you think you may have to change the value (because, for instance, the hardware might get changed) you will only have to change the value once--in the file where the constant is defined--then recompile your application.
3. (Only true for less sophisticated Forth compilers) When you are using the same value many times in your application. In the compiled form of a definition, reference to a constant requires less memory space.

`CONSTANT xxx` | ( n -- ) xxx: ( -- n ) | Creates a constant named xxx with the value n; the word xxx returns n when executed.

## Double-length Variables and Constants

You can define a double-length variable by using the word 2VARIABLE. For example,

    	2VARIABLE DATE

Now you can use the Forth words 2! (pronounced two-store) and 2@ (pronounced two-fetch) to access this double-length variable. You can store a double-length number into it by simply saying

    	800,000 DATE 2!

and fetch it back with

    	DATE 2@ D. 800000 ok

Or you can store the full month/date/year into it, like this:

    	7/17/03 DATE 2!

and fetch it back with

    	DATE 2@ .DATE 7/17/03 ok

assuming that you've loaded the version of `.DATE` we gave in the last chapter.

You can define a double-length constant by using the Forth word 2CONSTANT, like this:

    	200,000 2CONSTANT APPLES

Now the word `APPLES` will place the double-length number on the stack.

    	APPLES D. 200000 ok

Of course, we can do:

    	400,000 2CONSTANT MUCH
    	: MUCH-MORE  200,000 D+  MUCH D+ ;

in order to be able to say

    	APPLES MUCH-MORE D. 800000 ok

As the prefix "2" reminds us, we can also use 2CONSTANT to define a pair of single-length numbers. The reason for putting two numbers under the same name is a matter of convenience and of saving space in the dictionary.

As an example, recall (from Chap. 5) that we can use the phrase

    	355 113 */

to multiply a number by a crude approximation of p. We could store these two integers as a 2CONSTANT as follows:

    	355 113 2CONSTANT PI

then simply use the phrase

    	PI */

as in

    	10000 PI */ . 31415 ok

Here is a review of the double-length data-structure words:

`2CONSTANT xxx` | ( d -- ) xxx: ( -- d ) | Creates a double-length constant named xxx with the value d; the word xxx returns d when executed. |
`2VARIABLE xxx` | ( -- ) xxx: ( -- addr ) | Creates a double-length variable named xxx; the word xxx returns its address when executed. |
`2!` | ( d addr -- ) | Stores a double-length number into the address. |
`2@` | ( addr -- d ) | Returns the double-length contents of the address. |

## Arrays

4 | D | A | T | E
code
room for a single-length value

As you know, the phrase

    	VARIABLE DATE

creates a definition which conceptually looks like that at the right.

Now if you say

    	1 CELLS ALLOT

an additional cell is allotted in the definition, like this:

4 | D | A | T | E
code
room for a single-length value
ditto

The result is the same as if you had used 2VARIABLE. By changing the argument to ALLOT, however, you can define any number of variables under the same name. Such a group of variables is called an "array."

For example, let's say that in our laboratory, we have not just one, but five burners that heat various kinds of liquids.

We can make our word `?TOO-HOT` check that all five burners have not exceeded their individual limit if we define `LIMIT` using an array rather than a constant.

Let's give the array the name `LIMITS`, like this:

    	VARIABLE LIMITS 4 CELLS ALLOT

The phrase "4 CELLS ALLOT" gives the array an extra four cells (five cells in all).

6 | L | I | M | I | T | S
code
room for burner-0's limit
room for burner-1's limit
room for burner-2's limit
room for burner-3's limit
room for burner-4's limit
address
3160
3164
3168
316C
3170

Suppose we want the limit for burner 0 to be 220. We can store this value by simply saying

    	220 LIMITS !

because `LIMITS` returns the address of the first cell in the array. Suppose we want the limit for burner 1 to be 340. We can store this value by adding 1 CELLS to the address of the original cell, like this:

    	340 LIMITS 1 CELLS + !

We can store limits for burners 2, 3, and 4 by adding the "offsets" 2 CELLS, 3 CELLS, and 4 CELLS, respectively, to the original address. We can define the convenient word

    	: LIMIT  ( burner# -- addr ) CELLS LIMITS + ;

to take a burner number on the stack and compute an address that reflects the appropriate offset.

Now if we want the value 170 to be the limit for burner 2, we simply say

    	170 2 LIMIT !

or similarly, we can fetch the limit for burner 2 with the phrase

    	2 LIMIT ? 170 ok

This technique increases the usefulness of the word `LIMIT`, so that we can redefine `?TOO-HOT` as follows:

    	: ?TOO-HOT ( temp burner# -- )
    	LIMIT @ > IF  ." Danger -- reduce heat "  THEN ;

which works like this:

    	210 0 ?TOO-HOT ok
    	230 0 ?TOO-HOT Danger -- reduce heat ok
    	300 1 ?TOO-HOT ok
    	350 1 ?TOO-HOT Danger -- reduce heat ok

etc.

## Another Example -- Using an Array for Counting

Meanwhile, back at the egg ranch:

Here's another example of an array. In this example, each element of the array is used as a separate counter. Thus we can keep track of how many cartons of "extra large" eggs the machine has packed, how many "large," and so forth.

Recall from our previous definition of `EGGSIZE` (in Chap. 4) that we used four categories of acceptable eggs, plus two categories of "bad eggs."

    	0 CONSTANT REJECT
    	1 CONSTANT SMALL
    	2 CONSTANT MEDIUM
    	3 CONSTANT LARGE
    	4 CONSTANT EXTRA-LARGE
    	5 CONSTANT ERROR

So let's create an array that is six cells long:

    	VARIABLE COUNTS 5 CELLS ALLOT

The counts will be incremented using the word +!, so we must be able to set all the elements of the array to zero before we begin counting. The phrase

    	COUNTS 6 CELLS 0 FILL

will fill 6 cells , starting at the address of `COUNTS`, with zeros. If your Forth system includes the word ERASE, it's better to use it in this situation. ERASE fills the given number of bytes with zeroes. Use it like this:

    	COUNTS 6 CELLS ERASE

`FILL` | ( addr n b -- ) | Fills n bytes of memory, beginning at the address, with value b.
`ERASE` | ( addr n -- ) | Stores zeroes into n bytes of memory, beginning at the address.

For convenience, we can put the phrase inside a definition, like this:

    	: RESET  COUNTS 6 CELLS ERASE ;

Now let's define a word which will give us the address of one of the counters, depending on the category number it is given (0 through 5), like this:

    	: COUNTER   CELLS COUNTS + ;

and another word which will add one to the counter whose number is given, like this:

    	: TALLY  COUNTER 1 SWAP +! ;

The "1" serves as the increment for +!, and SWAP puts the arguments for +! in the order they belong, i.e., ( n addr -- ).

Now, for instance, the phrase

    	LARGE TALLY

will increment the counter that corresponds to large eggs.

Now let's define a word which converts the weight per dozen into a category number:

    	: CATEGORY ( weight -- category )
    	  DUP 18 < IF   REJECT      ELSE
    	  DUP 21 < IF   SMALL       ELSE
    	  DUP 24 < IF   MEDIUM      ELSE
    	  DUP 27 < IF   LARGE       ELSE
    	  DUP 30 < IF   EXTRA-LARGE ELSE
    			ERROR
    	THEN THEN THEN THEN THEN  NIP ;

(By the time we'll get to the NIP, we will have two values on the stack: the weight which we have been DUPping and the category number, which will be on top. We want only the category number; "NIP" eliminates the weight.)

For instance, the phrase

    	25 CATEGORY

will leave the number 3 (`LARGE`) on the stack. The above definition of `CATEGORY` resembles our old definition of `EGGSIZE`, but, in the true Forth style of keeping words as short as possible, we have removed the output messages from the definition. Instead, we'll define an additional word which expects a category number and prints an output message, like this:

    	: LABEL ( category -- )
    	  CASE
    	    REJECT      OF ." reject "      ENDOF
    	    SMALL       OF ." small "       ENDOF
    	    MEDIUM      OF ." medium "      ENDOF
    	    LARGE       OF ." large "       ENDOF
    	    EXTRA-LARGE OF ." extra large " ENDOF
    	    ERROR       OF ." error "       ENDOF
    	  ENDCASE ;

For example:

    	SMALL LABEL small ok

Now we can define `EGGSIZE` using three of our own words:

    	: EGGSIZE  CATEGORY  DUP LABEL  TALLY ;

Thus the phrase

    	23 EGGSIZE

will print

    	medium ok

at your terminal and update the counter for medium eggs.

How will we read the counters at the end of the day? We could check each cell in the array separately with a phrase such as

    	LARGE COUNTER ?

(which would tell us how many "large" cartons were packed). But let's get a little fancier and define our own word to print a table of the day's results in this format:

    	QUANTITY		SIZE
    	    1			reject
    	  112			small
    	  132			medium
    	  143			large
    	  159			extra large
    	    0			error

Since we have already devised category numbers, we can simply use a DO and index on the category number, like this:

    	: REPORT ( -- )
    		PAGE ." QUANTITY       SIZE" CR CR
    		6 0 DO	 I COUNTER @ 5 U.R
    			 7 SPACES
    			 I LABEL CR
    		  LOOP ;

(The phrase `"I COUNTER @ 5 U.R"` takes the category number given by I, indexes into the array, and prints the contents of the proper element in a five-column field.)

## Factoring Definitions

This is a good time to talk about factoring as it applies to Forth definitions. We've just seen an example in which factoring simplified our problem.

Our first definition of `EGGSIZE` from Chap. 4, categorized eggs by weight and printed the name of the categories at the terminal. In our present version we factored out the "categorizing" and the "printing" into two separate words. We can use the word `CATEGORY` to provide the argument either for the printing word or the counter-tallying word (or both). And we can use the printing word, `LABEL`, in both `EGGSIZE` and `REPORT`.

As Charles Moore, the inventor of Forth, has written:

> A good Forth vocabulary contains a large number of small words. It is not enough to break a problem into small pieces. The object is to isolate words that can be reused.

For example, in the recipe:

> Get a can of tomato sauce.
> Open can of tomato sauce.
> Pour tomato sauce into pan.
> Get can of mushrooms.
> Open can of mushrooms.
> Pour mushrooms into pan.

you can "factor out" the getting, opening, and pouring, since they are common to both cans. Then you can give the factored-out process a name and simply write:

    	TOMATOES ADD
    	MUSHROOMS ADD

and any chef who's graduated from the Postfix School of Cookery will know exactly what you mean.

Not only does factoring make a program easier to write (and fix!), it saves memory space, too. A reusable word such as `ADD` gets defined only once. The more complicated the application, the greater the savings.

Here is another thought about Forth style before we leave the egg ranch. Recall our definition of `EGGSIZE`

    	: EGGSIZE  CATEGORY  DUP LABEL  TALLY ;

`CATEGORY` gave us a value which we wanted to pas on to both `LABEL` and `TALLY`, so we included the DUP. To make the definition "cleaner," we might have been tempted to take the DUP out and put it inside the definition of `LABEL`, at the beginning. Thus we might have written:

    	: EGGSIZE  CATEGORY  LABEL TALLY ;

where `CATEGORY` passes the value to `LABEL`, and `LABEL` passes it on to `TALLY`. Certainly this approach would have worked. But then, when we defined `REPORT`, we would have had to say

    	I LABEL DROP

instead of simply

    	I LABEL

Forth programmers tend to follow this convention: when possible, words should destroy their own parameters. In general, it's better to put the DUP inside the "calling definition" (`EGGSIZE`, here) than in the "called" definition (`LABEL`, here).

## Another Example -- "Looping" through an Array

We'd like to introduce a little technique that is relevant to arrays. We can best illustrate this technique by writing our own definition of a Forth word called DUMP. DUMP is used to print out the contents of a series of memory addresses. The usage is

    	addr count DUMP

For instance, we could enter

    	COUNTS 6 DUMP

to print the contents of our egg-counting array called `COUNTS`. Since DUMP is primarily designed as a programming tool to print out the contents of memory locations, it prints either byte-by-byte or cell-by-cell, depending on the type of addressing our computer uses. Our version of DUMP will print cell-by-cell.

Obviously DUMP will involve a DO loop. The question is: what should we use for an index? Although we might use the count itself (0 - 6) as the loop index, it's better to use the address as the index.

The address of `COUNTS` will be the starting index for the loop, while the address plus the count will serve as the limit, like this:

    	: DUMP ( addr cell-count -- )
    		CELLS OVER + SWAP
    		           DO   CR I @ 5 U.R
    		1 CELLS +LOOP ;

The key phrase here is

    	CELLS OVER + SWAP

which immediately precedes the DO.

The ending and starting addresses are now on the stack, ready to serve as the limit and index for the DO loop. Since we are "indexing on the addresses," once we are inside the loop we merely have to say

    	I @  5 U.R

to print the contents of each element of the array. Since we are examining cells (@ fetches a single-length, single cell value), we increment the index by one cell each time, by using

    	1 CELLS +LOOP

## Byte Arrays

Forth lets you create an array in which each element consists of a single byte rather than a full cell. This is useful any time you are storing a series of numbers whose range fits into that which can be expressed within eight bits.

The range of an unsigned 8-bit number is 0 to 255. Byte arrays are also used to store ASCII character strings. The benefit of using a byte array instead of a cell array is that you can get the same amount of data in 25% (32-bit Forth) of the memory space.

The mechanics of using a byte array are the same as using a cell array except that

1. you don't have to use CELLS to manipulate the offset, since each element corresponds to one address unit, and
2. you must use the words C! and C@ instead of ! and @. These words, which operate on byte values only, have the prefix "C" because their typical use is accepting ASCII characters.

`C!` | ( b addr -- ) | Stores an 8-bit value into the address. |
`C@` | ( addr -- b ) | Fetches an 8-bit value from the address. |

## Initializing an Array

Many situations call for an array whose values never change during the operation of the application and which may as well be stored into the array at the same time that the array is created, just as CONSTANTs are. Forth provides the means to accomplish this through the two words CREATE and , (pronounced create and comma).

Suppose we want permanent values in our `LIMITS` array. Instead of saying

    	VARIABLE LIMITS 4 CELLS ALLOT

we can say

    	CREATE LIMITS  220 , 340 , 170 , 100 , 190 ,

Usually the above line would be included from a disk file, but it also works interactively.

Like the word VARIABLE, CREATE puts a new name in the dictionary at compile time and returns the address of that definition when it is executed. But it does not "allot" any bytes for a value.

The word , takes a number off the stack and stores it into the array. So each time you express a number and follow it with ,, you add one cell to the array.

> For Newcomers
> Ingrained habits, learned from English writing, lead some newcomers to forget to type the final , in the line. Remember that , does not separate the numbers, it compiles them.

You can access the elements in a CREATE array just as you would the elements in a VARIABLE array. For example:

    	LIMITS CELL+ @ . 340 ok

You can even store new values into the array, just as you would into a VARIABLE array.

To initialize a byte-array that has been defined with CREATE, you can use the word C, (c-comma). For instance, we could store each of the values used in our egg-sorting definition `CATEGORY` as follows:

    	CREATE SIZES 18 C, 21 C, 24 C, 27 C, 30 C, 255 C,

This would allow us to redefine `CATEGORY` using a DO loop rather than as a series of nested IF...THEN statements, as follows

    	: CATEGORY  6 0 DO  DUP SIZES I + C@  < IF  DROP I LEAVE THEN  LOOP ;

Note that we have added a maximum (255) to the array to simplify our definition regarding category 5.

Including the initialization of the `SIZES` array, this version takes only three lines of source text as opposed to six and takes less space in the dictionary, too.

> For People Who Don't Like Guessing How It Works
> The idea here is this: since there are five possible categories, we can use the category numbers as our loop index. Each time around, we compare the number on the stack against the element in `SIZES`, offset by the current loop index. As soon as the weight on the stack is greater than one of the elements in the array, we leave the loop and use I to tell us how many times we had looped before we "left." Since this number is our offset into the array, it will also be our category number.

Here's a list of the Forth words we've covered in this chapter:

`CONSTANT xxx` | ( n -- ) xxx: ( -- n ) | Creates a constant named xxx with the value n; the word xxx returns n when executed.
`VARIABLE xxx` | ( -- ) xxx: ( -- addr ) | Creates a variable named xxx; the word xxx returns its address when executed.
`CREATE xxx` | ( -- ) xxx: ( -- addr ) | Creates a dictionary entry (head and code pointer only) named xxx; the word xxx returns its address when executed.
`!` | ( n addr -- ) | Stores a single-length number into the address.
`@` | ( addr -- n ) | Replaces the address with its contents.
`?` | ( addr -- ) | Prints the contents of the address, followed by one space.
`+!` | ( n addr -- ) | Adds a single-length number to the contents of the address.
`ALLOT` | ( n -- ) | Adds n bytes to the body of the most recently defined word.
`,` | ( n -- ) | Compiles n into the next available cell in the dictionary.
`C!` | ( b addr -- ) | Stores an 8-bit value into the address.
`C@` | ( addr -- b ) | Fetches an 8-bit value from the address.
`FILL` | ( addr n b -- ) | Fills n bytes of memory, beginning at the address, with value b.
`BASE` | ( n -- ) | A variable which contains the value of the number base being used by the system.
`2CONSTANT xxx` | ( d -- ) xxx: ( -- d ) | Creates a double-length constant named xxx with the value d; the word xxx returns d when executed.
`2VARIABLE xxx` | ( -- ) xxx: ( -- addr ) | Creates a double-length variable named xxx; the word xxx returns its address when executed.
`2!` | ( d addr -- ) | Stores a double-length number into the address.
`2@` | ( addr -- d ) | Returns the double-length contents of the address.
`C,` | ( b -- ) | Compiles b into the next available byte in the dictionary.
`DUMP` | ( addr u -- ) | Displays u bytes of memory, starting at the address.
`ERASE` | ( addr n -- ) | Stores zeroes into n bytes of memory, beginning at the address.

KEY
n, n1, ... | single-length signed
d, d1, ... | double-length signed
u, u1, ... | single-length unsigned
ud, ud1, ... | double-length unsigned
addr | address
c | ASCII character value
b | 8-bit byte
f | Boolean flag

Review of Terms
Array | a series of memory locations with a single name. Values can be stored and fetched into the individual locations by giving the name of the array and adding an offset to the address.
Constant | a value which has a name. The value is stored in memory and usually never changes.
Factoring | as it applies to programming in Forth, simplifying a large job by extracting those elements which might be reused and defining those elements as operations.
Fetch | to retrieve a value from a given memory location.
Initialize | to give a variable (or array) its initial value(s) before the rest of the program begins.
Offset | a number which can be added to the address of the beginning of an array to produce the address of the desired location within the array.
Store | to place a value in a given memory location.
Variable | a location in memory which has a name and in which values are frequently stored and fetched.

## Problems -- Chapter 8

1. 1. Write two words called `BAKE-PIE` and `EAT-PIE`. The first word increases the number of available `PIES` by one. The second decreases the number by one and thanks you for the pie. But if there are no pies, it types "What pie?" (make sure you start out with no pies.)

          	EAT-PIE What pie?
          	BAKE-PIE ok
          	EAT-PIE Thank you! ok

   2. Write a word called `FREEZE-PIES` which takes all the available pies and adds them to the number of pies in the freezer. Remember that frozen pies cannot be eaten.

          	BAKE-PIE BAKE-PIE FREEZE-PIES ok
          	PIES ? 0 ok
          	FROZEN-PIES ? 2 ok

   [answer]
2. Define a word called `.BASE` which prints the current value of the variable BASE in decimal. Test it by first changing BASE to some value other than ten. (This one is trickier than it may seem.)

       	DECIMAL .BASE 10 ok
       	HEX .BASE 16 ok

   [answer]
3. Define a number-formatting word called `M.` which prints a double-length number with a decimal point. The position of the decimal point witin the number is movable and depends on the value of a variable that you will define as `PLACES`. For example, if you store a "1" into `PLACES`, you will get

       	200,000 M. 20000.0 ok

   that is, with the decimal point one place from the right. A zero in `PLACES` should produce no decimal point at all. [answer]
4. In order to keep track of the inventory of colored pencils in your office, create an array, each cell of which contains the count of a different colored pencil. Define a set of words so that, for example, the phrase

       	RED PENCILS

   returns the address of the cell that contains the count of red pencils, etc. Then set these variables to indicate the following counts:

       	23 red pencils
       	15 blue pencils
       	12 green pencils
       	0 orange pencils

   [answer]
5. A histogram is a graphic representation of a series of values. Each value is shown by the height or length of a bar. In this exercise you will create an array of values and print a histogram which displays a line of "*"s for each value. First create an array with about ten cells. Initialize each element of the array with a value in the range of zero to seventy. Then define a word `PLOT` which will print a line for each value. On each line print the number of the cell followed by a number of "*"s equal to the contents of that cell.

   For example, if the array has four cells and contains the values 1, 2, 3 and 4, then `PLOT` would produce:

       	1 *
       	2 **
       	3 ***
       	4 ****

   [answer]
6. Create an application that displays a tic-tac-toe board, so that two human players can make their moves by entering them from the keyboard. For example, the phrase

       	4 X!

   puts an "X" in box 4 (counting starts with 1) and produces this display:

       	  |   |
       	---------
       	X |   |
       	---------
       	  |   |

   Then the phrase

       	3 O!

   puts an "O" in box 3 and prints the display:

       	  |   | O
       	---------
       	X |   |
       	---------
       	  |   |

   Use a byte array to remember the contents of the board, with the value 1 to signify "X," a -1 to signify a "O," and a 0 to signify an empty box. [answer]