## Simple Forth

### Rudiments of a Programming Language

2 January 2004 +

Lesson:
0. What is Simple Forth ?
1. The Forth Programmer Interface
2. Forth in One Sentence
3. "The Stack" `.S DROP`
4. The Dictionary `WORDS SEE`
5. Adding to the Dictionary `: ; \`
6. Forth Arithmetic 1 `+ - * /`
7. Forth Arithmetic 2 `/MOD MOD .`
8. Forth Arithmetic 3 ` 1+ 1- ABS NEGATE MAX MIN */ */MOD`
9. Managing the Stack 1 `DEPTH`
10. Managing the Stack 2 `DUP ?DUP SWAP OVER ROT PICK ROLL NIP TUCK 2DROP 2DUP 2OVER 2SWAP`
11. Programming by Teaching and Learning
12. Thoroughly Modern Forth
13. Comparisons `TRUE FALSE = < > 0= 0<`
14. Conditional Execution `IF ELSE THEN`
15. Repeated Execution `EXIT BEGIN AGAIN UNTIL WHILE REPEAT`
16. Counted Loops `?DO DO I J LEAVE UNLOOP LOOP +LOOP`
17. Source Files `S" INCLUDED`
18. Game of Sticks `CR SPACE SPACES ." .(`
19. More to Display `PAGE AT-XY .R MS`
20. Data on the Return Stack `>R R@ R> 2>R 2R@ 2R>`
21. Named Storage `CONSTANT VARIABLE U. U.R ! @ +! ?`
22. Accessing Memory 1 `UNUSED CELLS`
23. Accessing Memory 2 `CREATE HERE ALLOT ERASE CELL+`
24. Accessing Memory 3 `,`
25. Decimal Hexadecimal Binary `BASE DECIMAL HEX DUMP`
26. Booleans and Bits `AND OR XOR 0<> INVERT 2* 2/ LSHIFT RSHIFT`
27. A Software Stack `2@ 2!`
28. Characters A ` EMIT CHAR BL`
29. Characters B ` [CHAR] KEY`
30. Characters C ` C, C@ C! CHARS CHAR+ ALIGN`
31. Strings 1 `S" TYPE`
32. Strings 2 `COUNT MOVE`
33. Strings 3 `/STRING FILL BLANK -TRAILING`
34. Strings 4 `SEARCH COMPARE`
35. Values `VALUE TO`
36. Locals `LOCALS| TO`

'Tis the gift to be simple, 'tis the gift to be free,
'Tis the gift to come down where we ought to be,
And when we find ourselves in the place just right,
'Twill be in the valley of love and delight.

When true simplicity is gain'd
To bow and to bend we shan't be asham'd,
To turn, turn will be our delight
'Till by turning, turning we come round right.

"Simple Gifts," a Shaker song by Joseph Brackett (1848)

Ground 0 What is Simple Forth ?

Forth is, among other things, a programming language whose ideals are freedom and simplicity. Freedom requires knowledge and responsibility, and simplicity is yet more demanding. But "simple" can also mean rudimentary. Simple Forth attempts to teach the rudiments of Forth.

How to try the examples.

Forth is inherently interactive. Programming in Forth is carried on as a dialog between you and a machine that understands Forth. You send the machine some code. Depending on the circumstances, the machine responds by trying either to perform ("execute") or to remember ("compile") the code. If the machine then says something like "ok", that's good. If it doesn't say ok, it might still be ok. Try sending more code until the machine explicitly objects (or pretends to be dead).

A machine that knows Forth is: a Forth Machine. Sometimes I don't distinguish between Forth and the machine. If this is confusing, let me know.

1. Start up a Forth system, and type in the examples. Most Forths accept source from disk, but you'll get a better feeling for Forth by entering into a give-and-take with the computer. Where you see a space, press the spacebar. At the end of a line, press the key on your keyboard that means "Enter".

2. If the machine doesn't understand something you entered it may respond by repeating what it didn't understand and adding an error message or maybe just: ?. Check to see if you typed in the example correctly. If not, type it in again. If you and your machine continue to be baffled, write to me at hello@albany.net.

3. In Forth named procedures are called words. Some frequently used words are very short. For example, the word `.` displays a signed (plus/minus) integer. In general, what is punctuation in other languages are procedures in Forth.

4. Many Forths are case sensitive. All the examples will work in uppercase. If you try lowercase and the machine says ok, use whatever case you wish.

Start up a Forth and try:

```1 .
```

Forth reads from left to right:

```1 . 2 . 3 .
```

Spaces are separators:

```12 .  3 .  123 .
```

Your machine probably won't understand this:

```aieee!
```

It should understand when it's time to go:

```BYE
```

Lesson 1 The Forth Programmer Interface

According to Leo Brodie's book Thinking Forth, the three characteristics of the Forth Programmer Interface are implicit calls, implicit data passing, and direct access to memory. None of these characteristics is unique to Forth, but they form quite a combination.

The following examples use Forth words that will be explained later. For now just type each line exactly as you see it and observe how your Forth responds.

1. Implicit calls. The word `.S` is called by entering its name, `.S`.

Try:

```.S
```

2. Implicit data passing. The word `1+` takes a number and returns another without specifying either. The word `DROP` takes a number without returning one.

Try:

```.S
7
.S
1+
.S
1+
.S
DROP
.S

```

An address of memory identifies an "address unit". The size of an address unit is often 8 bits - too small to hold a number greater than 255. Forth typically works with "cells". The size of a cell is usually two, four, or more address units. Numbers considerably larger than 255 fit comfortably in a cell.

To name a memory address `MINE` and reserve a cell of memory at `MINE` try:
```CREATE MINE  1 CELLS ALLOT
```

To put a number in the cell of memory at `MINE` try:

```1 MINE !
```
To see the contents (might look rather strange if you're just beginning to learn programming) of the address units in the cell of memory at `MINE` try:
```MINE 1 CELLS DUMP
```

To display the number in the cell of memory at `MINE` try:

```MINE ?
```

To change the number in the cell of memory at `MINE` try:

```1024 MINE !
MINE 1 CELLS DUMP
MINE ?

-1 MINE !
MINE 1 CELLS DUMP
MINE ?

BYE
```

Lesson 2 Forth in One Sentence

The sentence is: "Forth is a programming language that uses two stacks and a dictionary of words that a programmer adds to in writing a program."

Words, dictionary, two stacks: the essence of Forth.

In Lesson 1, I wrote that the Forth programmer interface is characterized by implicit calls, implicit data passing, and direct access to data.

Calls are implicit because when a Forth sees space-delimited text, it thinks "word" and tries to find it in its dictionary. If it finds it, it will immediately do something with it (if Forth doesn't find it in its dictionary it will try to understand it as a number; if that fails, Forth will confess its failure).

Data passing is implicit because Forth words get their input from and return their output to the same stack.

Lesson 3 discusses the Forth data stack. Lesson 4 discusses the Forth dictionary. Addresses will wait until Lesson 21.

Lesson 3 "The Stack" `.S DROP`

All Forths have at least two stacks. The stacks work similarly but serve different purposes.

A stack is a way of managing data. With a stack, data is added to and taken from the "top", as with a stack of dishes. The acronym for this is LIFO: Last In First Out. The top of the stack is called TOS. If there's no TOS, the stack is empty. A stack is such a convenient way of managing data that most (all?) programming languages use it internally.

The stack discussed in this lesson is the Forth data stack: Forth programmers call it "the stack". The second Forth stack, called the return stack, will be discussed later. Some Forths have special-purpose stacks for floating-point numbers or for strings. These special stacks hold data that it may be convenient to keep separate from the data on "the stack".

Words take and return numbers from the stack. When you type in a number its destination is the stack. The following examples use the words `.S` and `DROP`. `.S` displays (at least some of) the numbers on the stack in stack order, TOS (top of stack) on the right. In some Forths, `.S` also tells how many numbers are on the stack. `DROP` removes TOS, reducing the number of numbers on the stack by one.

Try:

```.S
10
```
10 is TOS:
```.S
```
Now try:
```20
```
20 is TOS, and 10 is below 20:
```.S
```
Now try:
```DROP
```
The word `DROP` removed 20 from the stack. TOS is again 10:
```.S
```
Now try:
```DROP
```
The word `DROP` removed 10 from the stack. The stack is now (probably) empty:
```.S

BYE
```

Lesson 4 The Dictionary `WORDS SEE`

About all a Forth system knows is contained in its dictionary. The dictionary contains words - words the system came with and words defined by the programmer. By "word" is meant: the word's name, which Forth uses to look up the word, and the word's action, which is code that Forth either executes or compiles.

The dictionary comes with the Forth system. The programmer writes a program by adding to the dictionary words defined in terms of words in the dictionary.

As a rule, Forth finds a word by starting with the most recently defined word and working backwards. If two or more words in the dictionary have the same name, Forth will find the most recently defined and be satisfied. Re-use of names is allowed but probably isn't Simple Forth.

Most Forths have the words `WORDS` and `SEE`. `WORDS` displays the names of words currently in the dictionary. A "fat" Forth will have lots a words - the names will whizz by unless the display pauses. A "thin" Forth will have far fewer - the names might fit into a single screen. `SEE` followed by a word's name tries to display the word's definition. `SEE` may or may not display definitions of words defined in assembly language. There's no harm in seeing what Forth `SEE`s.

Try:

```WORDS
SEE WORDS
SEE SEE
SEE .S
SEE ?
SEE !
```
Short definitions are ok. Try (exactly as written):
```: HELLO  ." Hi! " ;
HELLO
SEE HELLO

: GOODBYE  ." Bye! " ;
GOODBYE
SEE GOODBYE

: QUICK   HELLO GOODBYE ;
QUICK
SEE QUICK

BYE
```

Lesson 5 Adding to the Dictionary `: ; \`

By far the most common way of adding a word to the dictionary is to write a colon definition. A colon definition starts with the Forth word `:` and ends with the Forth word `;`. After `:` comes the name, then the definition, then `;`.

This is a commonly cited Forth definition:

`: SQUARED  DUP * ;`

Forth reads from left to right. The definition of `SQUARED` tells Forth: when you see `SQUARED`, first do `DUP`, then do `*`.

Because in Forth data is passed implicitly, it is considered insane to define a word without documenting what data (if any) it takes from the stack and what data (if any) it returns to the stack. The canonical way of doing this is to use the Forth word `(` which tells the system to ignore what follows up to and including the next `)`. Expectations ("before") and results ("after") are separated by `--`. The resulting ( before -- after ) is a "stack-effect comment".

So:

`: SQUARED  ( n -- n*n )  DUP * ;`

It's also wise to document what the new word does. For this the Forth word `\` is useful. `\` tells Forth to ignore the rest of the line.

So try:

```\ Return square of n
: SQUARED  ( n -- n*n )  DUP * ;

\ Skip next line if your system doesn't SEE
SEE SQUARED

2 SQUARED
.S
SQUARED
.S
SQUARED
.S
DROP
```

Leo Brodie's Forth Style Guide and Paul Bennett's Forth Coding Rules.

```BYE
```

Lesson 6 Forth Arithmetic 1 `+ - * /`

Most words don't wait before acting. The word `+` doesn't ask "plus what?"; it removes the top two stack numbers and returns their sum. The words `- * / ` also take the top two stack numbers and return a result.

Try:

```1 1 +
.S
1 +
.S
1 1 +
.S
+
.S
DROP
```

`-` subtracts TOS from the number below it. Try:

```1 1 -
.S
1 -
.S
1 1 -
.S
-
.S
DROP
```

`*` multiplies the top two stack numbers. Try:

```2 2 *
.S
2 *
.S
2 2 *
.S
*
.S
DROP
```

`/` takes the number below TOS and divides it by TOS. Try:

```100 2 /
.S
2 /
.S
2 /
.S
2 2 /
.S
/
.S
DROP
```
Forth reads from left to right. There is no "operator precedence." Try:
```\ 1 + (2 * 3)
2 3 * 1 +
.S
DROP
1 2 3 * +
.S
DROP

\ (1 + 2) * 3
1 2 + 3 *
.S
DROP
```

There's a lot to observe in these examples. You might want to repeat them with the same and with different numbers before saying:

```BYE
```

Lesson 7 Forth Arithmetic 2 `/MOD MOD .`

I hope you noticed in Lesson 6 that `100 2 / 2 / 2 /` left `12` on the stack. The words `+ - * /` are integer operators. `/` gives the quotient of `n1` divided by `n2`. To get the remainder, use either `/MOD`, which returns the quotient as TOS and the remainder below TOS, or `MOD`, which just returns the reminder.

Here are the stack effects of `+ - * /MOD / MOD`:

```+  ( n1 n2 -- n1+n2 )
-  ( n1 n2 -- n1-n2 )
*  ( n1 n2 -- n1*n2 )
/MOD  ( n1 n2 -- remainder quotient )
/  ( n1 n2 -- quotient )
MOD  ( n1 n2 -- remainder )
```

`. ( n -- )` displays the signed integer n.

Try:

```1 .
-1 .
0 -1 + .
10 10 /MOD . .
10 11 /MOD . .
10 3 /MOD . .
10 3 / .
10 3 MOD .
10 3 /MOD 3 * + .

BYE
```

Lesson 8 Forth Arithmetic 3 `1+ 1- ABS NEGATE MAX MIN */ */MOD`

Here are some other arithmetic words to try in your free time. The words are categorized by stack effect.

Take one, leave one:

```1+  ( n -- n+1 )  \ Faster 1 +
1-  ( n -- n-1 )  \ Faster 1 -
ABS  ( n -- u )  \ Return absolute value of n
NEGATE  ( +n|-n -- -n|+n ) \ Return arithmetic inverse of n
```

Take two, leave one:

```MAX  ( n1 n2 -- n1|n2 ) \ Return the greater of n1 and n2
MIN  ( n1 n2 -- n1|n2 ) \ Return the lesser of n1 and n2
```

Take three, leave one:

`*/  ( n1 n2 n3 -- quotient ) \ Similar to n1 n2 * n3 / `

Take three, leave two:

```*/MOD  ( n1 n2 n3 -- rem quot ) \ Similar to n1 n2 * n3 /MOD
```

`*/` and `*/MOD` avoid overflow during the multiplication, but the quotient must be within the range of signed integers.

```\ Celsius <-> Fahrenheit
: C  ( Celsius -- Fahrenheit )  9 5 */  32 + ;

100 C .
0 C .

: F  ( Fahrenheit -- Celsius )  32 -  5 9 */ ;

212 F .
32 F .

BYE
```

Lesson 9 Managing the Stack 1 `DEPTH`

`.S`, discussed in Lesson 3, displays the numbers on the stack. `DEPTH ( -- +n )` returns how many of those numbers they are. "Number" can stand for various things: signed integer, unsigned integer, address, count, ASCII code, UNICODE, true/false flag, etc, so I will now refer to stack items. All the items on the stack are the same size: one cell. The size of a cell depends on the implementation. A cell must be at least 16-bits; nowadays 32-bits is probably most common. How many bits there are in a cell determines how much information a cell can hold - more about this in a later lesson.

So in somewhat technical terms, `DEPTH ( -- +n )` returns as TOS the number of one-celled items that were on the stack before `DEPTH` was called. Note that the stack-effect comment doesn't indicate these items, because `DEPTH` doesn't require that there be any items on the stack and doesn't affect the items that may be on the stack, except of course, to push them one item deeper in the stack by making +n TOS.

Try:

```\ Tell how many items are on the stack
:  DEPTH?  ( -- )  DEPTH . ;

DEPTH?
10
DEPTH?
20
DEPTH?
30
DEPTH?
.
DEPTH?
.
DEPTH?
.
DEPTH?
```

Some Forths empty the stack when they encounter a word not in the dictionary; others don't. To find out what your Forth does, try:

```10 20 30
DEPTH?
\ Unlikely word:
Nonce
DEPTH?

BYE
```

Lesson 10 Managing the Stack 2 `DUP ?DUP OVER SWAP ROT PICK ROLL NIP TUCK 2DROP 2DUP 2OVER 2SWAP`

When you said `BYE` in the last lesson, your dictionary forgot `DEPTH?`, the word you so carefully added to it. You could have preserved `DEPTH?` in either of two ways: saving the system before saying `BYE`, or saving the colon definition of `DEPTH?` as source code and having your Forth read the definition again to add it back to the dictionary. So are real programs written. For now you are learning Forth by writing little definitions that you won't miss when they're gone.

With something as strict as a stack (Last In First Out), some legerdemain is necessary, and Forth provides the words for it. If you want a copy of TOS, you `DUP`licate it. If you want a copy of the item below TOS, you bring it `OVER` If you want TOS and the item below it to switch positions, `SWAP` them. If you want the third stack item to be TOS, you `ROT`ate it to the top.

```DUP  ( x -- x x )  Copy TOS
?DUP  ( x|0 -- x x | 0 ) Copy TOS if it isn't zero
OVER  ( x1 x2 -- x1 x2 x1 ) Copy x1 to TOS
SWAP  ( x1 x2 -- x2 x1 )  Switch positions of x1 and x2
ROT  ( x1 x2 x3 -- x2 x3 x1 )  Rotate x1 to TOS
```

These words could be (but likely aren't) defined in terms of the words `PICK` and `ROLL`:

```PICK  ( xu ... x0 u -- xu ... x0 xu )  Copy xu to TOS
ROLL  ( xu ... x0 u -- xu-1 ... x0 xu )  Rotate xu to TOS
: DUP  ( x -- x x )  0 PICK ;
: OVER  ( x1 x2 -- x1 x2 x1 ) 1 PICK ;
: SWAP  ( x1 x2 -- x2 x1 )  1 ROLL ;
: ROT  ( x1 x2 x3 -- x2 x3 x1 ) 2 ROLL ;
```

Forth programmers generally don't use `PICK` and `ROLL` much, preferring specific to general solutions and avoiding the temptation to treat the stack as an array.

On the other hand, these definitions wouldn't be unusual:

```\ Drop the second stack item
: NIP  ( x1 x2 -- x2 ) SWAP DROP ;

: /  ( n1 n2 -- quotient )  /MOD NIP ;
: MOD  ( n1 n2 -- remainder )  /MOD DROP ;
```

`NIP` and `TUCK` are probably `CODE`d in assembly language, but one could define:

```\ Copy TOS below the second stack item
: TUCK  ( x1 x2 -- x2 x1 x2 )  SWAP OVER ;
```

These words that concern pairs of stack elements are probably also in assembly language:

```\ Drop top two stack items
: 2DROP  ( x1 x2 -- )  DROP DROP ;

\ Duplicate top two stack items
: 2DUP  ( x1 x2 -- x1 x2 x1 x2 )  OVER OVER ;

\ Copy lower pair over top pair
: 2OVER  ( x1 x2 x3 x4  -- x1 x2 x3 x4 x1 x2)
3 PICK  3 PICK ;

\ Exchange top two cell pairs
: 2SWAP  ( x1 x2 x3 x4 -- x3 x4 x1 x2 )
3 ROLL  3 ROLL ;

```

Managing the stack well comes with experience. Meanwhile my 7-year-old daughter could use this:

```\ Math Family
\ ." and CR to be discussed later
: "+"  ." + " ;
: "-"  ." - " ;
: "="  ." = " ;

: FAM  ( n1 n2 -- )
2DUP +
DUP 2OVER           CR . "+" . "=" .
DUP 2OVER SWAP      CR . "+" . "=" .
DUP 2OVER SWAP ROT  CR . "-" . "=" .
CR . "-" . "=" . ;

\ Did somebody say 3DUP ?
: 3DUP  ( x y z -- x y z x y z )
2 PICK  2 PICK  2 PICK ;

Homework: redefine `FAM` using `3DUP`.

BYE
```

Lesson 11 Programming by Teaching and Learning

You program in Forth by teaching a machine new actions that you and the machine know by name. Each new action is a novel arrangement of known actions, perhaps mixing in some data. By being added to the dictionary the new action can be used to teach still newer actions. You choose the names, so a good part of the communication between you and machine is in your terms. By your pupil you'll be taught - the machine knows a lot of Forth, probably more than you do - and prefers certain ways of doing things, but it will make your ways its own if you teach it well.

As you saw, among the Forth words the machine knows are `DUP` and `*`. You might therefore teach it:

```: SQUARED  ( n -- n**2 )  DUP * ;
: CUBED  ( n -- n**3 )  DUP SQUARED * ;
: 4TH  ( n -- n**4 )  SQUARED SQUARED ;
```

…and so on until you have taught it all the words your program needs to do.

With Forth you can teach the machine whatever a computer can do. As you teach you learn, because any word you add to the dictionary you can (and should) immediately test.

```\ ." displays text
: ME  ( -- )  ." Leonardo DiCaprio" ;
ME
\ Oops!
: ME  ( -- )  ." Leo Wong" ;
ME

BYE
```

Lesson 12 Thoroughly Modern Forth

In Lesson 9 I talked about stack items the size of a cell, noting that an item could be represent different kinds of data: a signed integer, an unsigned integer, an ASCII code (character), a true/false (or Boolean) flag, etc. It used to be that a cell was 16-bits, period. Then came 32-bit processors and 32-bit Forths, and now there are 64-bit and 128-bit processors. The notion that in every Forth a stack item (and by implication some other kinds of data) is the size of a cell, but that the size of a cell is determined by the implementation allows for easier porting of Forth programs between different kinds of computers.

The number of bits (binary digits) in a cell determines how many different bit patterns the cell can distinguish, which determines how many different values of a particular kind of data a cell can distinguish.

For instance, one bit can distinguish two different patterns:0 1, which could be interpreted as:
the unsigned integers 0 and 1
the signed integers 0 and -1 or (maybe) -0
the Boolean flags false and true
etc.

Two bits can distinguish four patterns: 00 01 10 11, which could be interpreted as:
the unsigned integers 0 1 2 3
the signed integers 0 1 -2 -1
the Boolean flags false(=00) and true(<>false)
etc.

We can generalize and say that n-bits can distinguish 2**n (2 to the power of n) different patterns.

Getting down to cases,
a 16-bit cell can distinguish 65,536 different patterns, each of which could represent:
an unsigned integer between 0 and 65,535
a signed integer between -32,768 and 32,767
the Boolean flags false(=0000000000000000) and true(<>false)
etc.

a 32-bit cell can distinguish 4294967296 patterns, each of which could represent:
an unsigned integer between 0 and 4,294,967,295
a signed integer between -2,147,483,648 and 2,147,483,647
the Boolean flags false(=00000000000000000000000000000000) and true(<>false)
etc.

Try the following:
```-1 U.
```

If 65535 is displayed, your Forth has 16-bit cells. If 4294967295, 32-bit cells. If another number is displayed, then either the size of cell is other than 16 or 32 bits, or your Forth represents numbers atypically.

Forth easily handles data bigger and smaller than the size of one cell: "double" (2-cell) numbers and "floating-point" numbers, "bits", "characters", "strings" of characters, database fields and records, files, "objects", etc.

But for now we still stay with one kind of data - cell-sized signed integers.

Lesson 13 Comparisons `TRUE FALSE = < > 0= 0<`

I lied, because I will now talk about flags. But I lied only a little, because Forth flags are cell-size bit patterns like Forth integers and because Forth integers can be used as Forth flags.

A flag tells whether a condition is true or false, for instance whether TOS is equal to the stack item beneath TOS. Your Forth may already have the words `TRUE` and `FALSE`, which return to TOS "well formed" true and false flags. A well-formed true flag has all bits set (1), while a well-formed false flag as all bits "reset" (0). It is highly likely that in your Forth all bits set has the same bit pattern as the integer -1 and all bits reset has the same pattern as the integer 0.

Try:
```TRUE .
FALSE .
```
If your Forth doesn't have `TRUE` or `FALSE` you can teach it:
```\ CONSTANT defines a word that always returns the same value
0 CONSTANT FALSE
FALSE .

\ = returns a true flag if the top two stack items are equal
FALSE FALSE = CONSTANT TRUE
TRUE .
```

Each of these words returns a well-formed flag:

```=  ( n1 n2 -- flag )  \ Does n1 equal n2 ?
>  ( n1 n2 -- flag )  \ Is n1 greater than n2 ?
<  ( n1 n2 -- flag )  \ Is n1 less than n2 ?
0=  ( n -- flag )     \ Does n equal 0 ?
0<  ( n -- flag )     \ Is n less than 0 ?
```
Try:
```1 2 +  2 1 + = .
1 2 -  2 1 - = .
3 4 *  4 3 * < .
3 4 /  4 3 / < .
5 6 /  6 5 / > .
5 6 MOD  6 5 MOD > .
1 -1 + 0= .
1 -1 - 0= .
-1  0< .
-1 -1 * 0< .
```

Given these comparison words, others are easy to define. Your Forth may already have:

```\ Does n1 not equal n2 ?
: <> ( n1 n2 -- flag )  = 0= ;

\ Does n not equal 0 ?
: 0<> ( n -- flag)  0= 0= ;

\ Frequently seen synonym for 0=
: NOT  ( n -- flag ) 0= ;

\ Is n1 greater than or equal to n2 ?
: >=  ( n1 n2 -- flag ) < NOT ;

\ Is n1 less than or equal to n2 ?
: <=  ( n1 n2 -- flag ) > NOT ;

BYE
```

Lesson 14 Conditional Execution `IF ELSE THEN`

This is how to tell Forth to execute words conditionally:

```true-flag IF do-this THEN
true-flag IF do-this ELSE do-that THEN
```

Use `IF ELSE THEN` only colon definitions ( that is between `:` and `;`). `IF` and `THEN` must be in the same definition. `ELSE` is optional and if used must come between `IF` and `THEN`. Words can come before `IF` and follow `THEN`.

Try writing two inefficient definitions:

```: EVEN?  ( n -- )  2 MOD IF ." odd" ELSE ." even" THEN ;
1 EVEN?
2 EVEN?

\ The stack effect of IF is ( flag -- ),
\ so if TOS is needed after the test
\ make a copy of it before the test.
: ABS  ( n -- +n )  DUP O< IF -1 * THEN ;
1 ABS .
-1 ABS .
```

`IF ELSE THEN` can be "nested". Try:

```: SCORE  ( n -- )
DUP 89 > IF  ." Honors"
ELSE  DUP 69 > IF  ." Pass"
ELSE  ." Fail"
THEN
THEN  DROP ;

100 SCORE
80 SCORE
60 SCORE
```

In Forth the true flag need not be "well formed" - have all bits set. Any flag with at least one bit set is taken to be true. Try:

```       0 CONSTANT FALSE
FALSE 0= CONSTANT TRUE

: TRUE?  ( n -- )
DUP TRUE = IF  ." Well-formed true"  ELSE
DUP        IF  ." Still true"        ELSE
." False"
THEN THEN  DROP ;

TRUE TRUE?
FALSE TRUE?
-1 TRUE?
1 TRUE?
2 TRUE?
0 TRUE?

BYE
```

Lesson 15 Repeated Execution `EXIT BEGIN AGAIN UNTIL WHILE REPEAT`

Much of the computer's power comes from its ability to do something repeatedly. One way to tell Forth to something again is to repeat the word or phrase: Try:

```\ Add five numbers
: SUM5  ( n1 n2 n3 n4 n5 -- sum ) + + + + ;
14 26 33 25 18 SUM5 .

```

Repeating words or phrases is quite legitimate but limiting. In this lesson I'll show you three other ways of repeating execution ("looping"). Each begins with the word `BEGIN`:

```BEGIN ... AGAIN
BEGIN ... UNTIL
BEGIN ... WHILE ... REPEAT
```

`BEGIN AGAIN UNTIL WHILE REPEAT`, like `IF ELSE THEN`, are used colon definitions, with `BEGIN` and `AGAIN` or `UNTIL` or `WHILE ... REPEAT` in the same definition (in Forth, other "control structures" can be developed, but we'll just use these for now). I'll soon use these words in three definitions of a word I'll name `INTEGERS`. But first another word that is also used only in colon definitions: `EXIT`.

`EXIT` says: stop executing the word I'm in.

Try:

```\ Display 1 2 3
: JUST3  ( -- ) 1 . 2 . 3 . EXIT 4 . 5 . ;
JUST3
```

`EXIT` just affects the word it's in. Try:

```\ Display 1 2 3 4 5
: TO5  ( -- )  JUST3  4 . 5 . ;
TO5
```

We need `EXIT` because in my first definition of `INTEGERS`, the words between `BEGIN ... AGAIN` repeat unconditionally.

Try:

```\ Display integers 1 ... +n using BEGIN ... AGAIN
: INTEGERS  ( +n -- )
1 BEGIN  2DUP < IF 2DROP EXIT THEN  DUP . 1+  AGAIN ;
10 INTEGERS
1 INTEGERS
0 INTEGERS
```
`BEGIN ... AGAIN` executes the words between `BEGIN` and `AGAIN` again and again unless Forth executes `EXIT`, which in `INTEGERS` happens when `+n` is less than TOS.

Many published Forth definitions are very short - one or two lines. The best way to understand them (and to go about defining your own words) is to write them out one word or phrase to a line along with stack and other comments. Here is the definition of `INTEGERS` one word to a line, explaining the action of each word and the resulting stack:

```: INTEGERS  ( +n -- )
1            \ Initialize i to 1     ( +n i=1 )
BEGIN        \ Start loop: i is TOS  ( +n i )
2DUP      \ Duplicate 2 items     ( +n i +n i )
<         \ Is +n less than i ?   ( +n i flag )
IF        \ Act on flag           ( +n i )
2DROP  \ True: drop 2 items    (  )
EXIT   \ True: leave word      (  )
THEN      \ End IF ... THEN       (  )
DUP       \ DUPlicate TOS         ( +n i i )
.         \ Display TOS           ( +n i )
1+        \ Increment TOS         ( +n i=i+1 )
AGAIN        \ Loop back             ( +n i )
;            \ End definition
```

`BEGIN ... UNTIL` repeats execution until there's a true flag just before `UNTIL`. The words between `BEGIN` and `UNTIL` execute at least once, since `UNTIL` tests whether to leave the loop. Like `IF`, `UNTIL` swallows the flag, and as with `IF`, a true flag need not be "well formed". Here's the second definition of `INTEGERS`:

Try:

```\ Display integers 1 ... +n using BEGIN ... UNTIL
: INTEGERS ( +n -- )
1 BEGIN 2DUP < 0= IF DUP . THEN 1+ 2DUP < UNTIL 2DROP ;
10 INTEGERS
1 INTEGERS
0 INTEGERS

\ Don't do this:
: INTEGERS  ( +n -- )
1 BEGIN  DUP .  1+ 2DUP < UNTIL  2DROP ;
10 INTEGERS
1 INTEGERS
0 INTEGERS \ Not right

```

Here is the second definition one word to a line:

```: INTEGERS  ( +n -- )
1        \ Initialize i to 1      ( +n i=1 )
BEGIN    \ Start loop: i is TOS   ( +n i )
DUP   \ DUPlicate TOS          ( +n i i )
.     \ Display TOS            ( +n i )
1+    \ Increment TOS          ( +n i=i+1 )
2DUP  \ Duplicate 2 items      ( +n i +n i )
<     \ Is +n less than i ?    ( +n i flag )
UNTIL    \ Loop back unless true  ( +n i )
2DROP    \ Drop two items         (  )
;        \ End definition
```

Notice that an integer ("1") is displayed even when `0 INTEGERS` is called for.

`BEGIN ... WHILE ... REPEAT` executes the words between `BEGIN` and `WHILE`, continues execution to `REPEAT` while there's a true flag just before `WHILE`, then at `REPEAT` loops back to the word just after `BEGIN`. If the flag just before `WHILE` is false, execution skips to after `REPEAT`. The words between `BEGIN` and `WHILE` will execute at least once. If the flag before `WHILE` is false the first time through, the words between `WHILE` and `REPEAT` will not execute at all. `WHILE`, like `UNTIL`, swallows its flag, which need not be well formed. Here's the third definition:

Try:

```\ Display integers 1 ... +n using BEGIN ... WHILE ... REPEAT
: INTEGERS  ( +n -- )
1  BEGIN  2DUP < 0= WHILE  DUP .  1+  REPEAT  2DROP ;
10 INTEGERS
1 INTEGERS
0 INTEGERS
```

The third definition with line comments:

```: INTEGERS  ( +n -- )
1        \ Initialize i to 1        ( +n i=1 )
BEGIN    \ Start loop: i is TOS     ( +n i )
2DUP  \ Duplicate 2 items        ( +n i +n i )
< 0=  \ Is +n not less than i ?  ( +n i flag )
WHILE    \ If true, continue else
DUP   \ DUPlicate TOS            ( +n i i )
.     \ Display TOS              ( +n i )
1+    \ Increment TOS            ( +n i=i+1 )
REPEAT   \ Loop back                ( +n i )
2DROP    \ Drop two items           (  )
;        \ End definition

BYE
```

Lesson 16 Counted Loops `?DO DO I J LEAVE UNLOOP LOOP +LOOP`

Forth understands several kinds of counted loops, in which stack arguments before the loop determine the number of iterations. I recommend that you just use:

```+n 0 ?DO ... LOOP
```

which executes the words between `?DO` and `LOOP` exactly +n times and not at all if +n equals zero. Like `BEGIN`, etc. `?DO`, etc. should only be used in colon definitions.

Try:

```: INTEGERS  ( +n -- )
1 SWAP  0 ?DO  DUP .  1+  LOOP  DROP ;
10 INTEGERS
1 INTEGERS
0 INTEGERS
```

```: INTEGERS  ( +n -- )
1        \ Initialize i        ( +n i=1 )
SWAP     \ Set limit for ?DO   ( i limit=+n )
0        \ Set index for ?DO   ( i limit index=0 )
?DO      \ Start counted loop  ( i )
DUP   \ DUPlicate i         ( i i )
.     \ Display i           ( i )
1+    \ Increment i         ( i=i+1 )
LOOP     \ Increment index.
\ Loop back if
\ index < limit
\ else leave loop     ( i )
DROP     \ Drop i              (  )
;        \ End definition
```

This is all and more than all you need to know about counted loops. Please skip the rest of this lesson.

I recommended that you use `?DO`, use a positive limit, and set the starting index to zero: +n `0 ?DO`. `?DO` actually takes any limit and starting index: limit start `?DO`. You may experiment by writing words that accept various values of limit and start.

We saw when commenting on `INTEGERS` that `?DO` removes the limit and the starting index from the stack and that `LOOP` increments the index and compares it to the limit, leaving the loop then the index equals the limit. It's quite probable that your Forth keeps the limit and the index on Forth's second stack, called the return stack, and drops the limit and index from the return stack on leaving the loop. This likelihood results in rules about using the return stack that I may or may not discuss later.

`?DO` checks if the limit and the starting index are equal, skipping the loop entirely if the are. The word `DO` acts like `?DO` but doesn't check if the limit and the starting index are equal. `DO` may be a tiny bit faster than `?DO`, but a condition like `0 0 DO ... LOOP` will likely give you more than you bargained for.

`I` returns the current loop index. This is sometimes useful. For example one could have defined:

```: INTEGERS ( +n -- )
1+ 1 ?DO I . LOOP ;
```

This program translated from a famous book also uses `I`:

```\ Power
\ after Kernighan and Ritchie,
\ The C Programming Language, 2nd ed., pp. 24-25

\  Raise base to n-th power; n >= 0
: power  ( base n -- base**n )
1 SWAP 0 ?DO OVER * LOOP  NIP ;

\ Test power
: test  ( -- )
10 0 ?DO  CR I .  2 I power .  -3 I power .  LOOP ;
```

`J` returns the index of the next outer loop when counted loops are nested in the same word. This useful for stepping through two-dimensional arrays:

```\ Display indexes of a 2D array
: INDEXES  ( rows columns -- )
SWAP          ( columns rows )
0 ?DO         \ For number of rows
CR         \ CR goes to next line
DUP        \ DUPlicate columns
0 ?DO      \ For number of rows
J .    \ Display row index
I .    \ Display column index
SPACE  \ SPACE displays a space
LOOP        \ End of inner loop
LOOP ;         \ End of outer loop
3 4 INDEXES
```

`LEAVE` and `UNLOOP EXIT` exit a counted loop or counted loops "prematurely". `LEAVE` immediately leaves the loop it is in. `UNLOOP EXIT` exits the word it is in, and can exit a word with nested loops. Here are some phrases to ponder:

```DO ... IF LEAVE THEN ... LOOP
DO ... IF UNLOOP EXIT THEN ... LOOP
DO ... DO ... IF UNLOOP UNLOOP EXIT THEN ... LOOP ... LOOP
```

The phrase n `+LOOP` changes the loop index by n. n can be positive or negative, permitting stepping up or stepping down through the loop. Depending on whether it's up or down, the ending conditions, I think, "equal or greater than" or "less than". Try if you like:

```: LOOPY ( limit start step -- )
ROT ROT ?DO I . DUP +LOOP DROP ;
10 0 1 LOOPY
0 10 -1 LOOPY

10 0 2 LOOPY
0 10 -2 LOOPY

10 0 3 LOOPY
0 10 -3 LOOPY
```
n before `+LOOP` can vary within the loop. Here's a cute definition by Wil Baden:
```: SQRT   ( n1 -- n2 )
0 TUCK  DO  1+  DUP 2* 1+  +LOOP ;
```

```BYE
```

Lesson 17 Source Files `S" INCLUDED`

I think I shall write a little game. Since the game will take a few lines that I will revise as I develop the game I'll put the source code in a file. I'll write the code with a text editor and then load the source into Forth by entering: `S" `filename" `INCLUDED` where filename" is the name of the file followed by a double quotation mark. As I develop and correct my program I will get in and out of Forth and go back to my text editor. This isn't the most efficient way of developing a Forth program - Forth is an "integrated development environment" in which Forth and the source editor can work much more closely together - but it will work regardless of Forth implementation.

Since the game could use a little unpredictability, I'll need a "random number generator". I'll put that in a file too, so you can test `S" `filename" `INCLUDED`.

The random number generator in Leo Brodie's Starting Forth will be more than good enough for our purposes. Either type or copy and paste the following into a file that you name random.f. The code has a few words that I might explain in another lesson. For now just copy the source.

```\ random.f
\ Simple random number generator
\ from Leo Brodie, _Starting Forth_

VARIABLE RND  \ Holds current result

\ Generate a random integer
: RANDOM  ( -- u )  RND @  31421 *  6927 +  DUP RND ! ;

\ Return a random integer between 0 and u-1
: CHOOSE  ( u -- 0...u-1 ) RANDOM UM* NIP ;

\ Initialize
: RANDOMIZE  ( -- )  TIME&DATE + + + + + RND ! ;
```

Now try:

```S" random.f" INCLUDED
100 CHOOSE .
100 CHOOSE .
100 CHOOSE .
100 CHOOSE .
100 CHOOSE .
```

Excuse me while I write the game.

```BYE
```

Lesson 18 Game of Sticks `CR SPACE SPACES ." .( `

I'm back. It didn't take very long because I copied the game from David H. Ahl's BASIC Computer Games. If you can find a copy of that book you might wish to compare the BASIC code for "23 Matches" with my Forth code for "Sticks." Of course, I just didn't sit down and write "Sticks" without changing things and testing words as I went along. I just give the result. However, being a careless coder, I appreciate bug reports: hello@albany.net.

Nor do I particularly recommend my style of "coding". I will say that I value a plain style.

"Sticks" uses a few words that haven't been formally introduced:

`CR ( -- )` sends the display cursor to the next line.
`SPACE ( -- )` displays a space.
`SPACES ( n -- )` displays n spaces (`SPACES` isn't used in sticks.f).
`." ` text`" ( -- )`, used only in definitions, remembers (compiles) text up to but not including `"`. text is displayed when the word being defined is executed.
`.( ` text`) ( -- )` immediately displays text up to but not including `)`. You don't see `.( ` much. I'll use it in the source for "Sticks" to give you an indication of how quickly Forth reads code.

Try:

```.( Four score and seven years ago )

: brought  .( our fathers ) ." Forth on this continent." ;

brought
```

Type or copy and paste the following code into a file called sticks.f:

```\ sticks.f
\ After "23 Matches" in Ahl, _Basic Computer Games_
\ Ahl attributes the original to Bob Albrecht

\ random number generator
s" random.f" INCLUDED

\ Rules of the game
: RULES  ( -- )
CR ." Sticks"
CR
CR ." The game starts with 23 sticks.  "
." By turns, you and Forth take"
CR ." from 1 to 3 sticks.  "
." Whoever takes the last stick loses."
CR
CR ." You take sticks by entering:  n STICKS"
CR ." where n is 1, 2, or 3"
CR ;

\ Display sticks
: .STICKS  ( n -- )  0 ?DO  ." |"  LOOP ;

\ Report remaining sticks
: LEFT  ( sticks taken -- left )
-  DUP CR .STICKS SPACE DUP . ." left." ;

\ The fates of Forth
: YOU-WIN  ( sticks -- )  DROP  ." You win! " ;
: FORTH-WINS  ( sticks -- )
." Forth took "  1- .
CR ." 1 left - sorry!" ;
: 4-PLAY  ( sticks -- left )
." Forth took " 3 CHOOSE 1+ DUP . LEFT ;

\ My esteemed opponent
: COMPUTER  ( sticks -- left| )
CR
DUP 1 = IF  YOU-WIN     ELSE
DUP 5 < IF  FORTH-WINS  ELSE
4-PLAY
THEN THEN ;

\ First play
: COIN  ( 23 -- n )
2 CHOOSE
CR ." A coin has been flipped:  "
IF   ." Heads, Forth is first."  COMPUTER
ELSE ." Tails, you start."
THEN ;

\ Confine n between min and max
: CLAMP  ( n min max -- n )  ROT MIN MAX ;

\ May take between 1 and 3 sticks, leaving at least 1
: LEGAL  ( sticks try -- sticks taken )
OVER 1- 3 MIN  1 SWAP CLAMP ;

\ My play
: PROGRAMMER  ( sticks try - left )  LEGAL LEFT ;

\ 1 Round
: STICKS  ( sticks try -- left| )  PROGRAMMER COMPUTER ;
\ Alias for STICKS
: STICK  ( sticks try -- left| )  STICKS ;

: GAME  ( -- )
RULES  23 DUP CR .STICKS  RANDOMIZE COIN ;

CR .( Ready.  To play, enter: GAME)

```
Now try:
```S" sticks.f" INCLUDED
GAME
```
Homework: write your own version of Sticks or another game.
```BYE
```

Lesson 19 More to Display `PAGE AT-XY .R MS `

Sticks used `CR SPACE SPACES . ." .( ` for displaying on the screen. Here are three other display words:

`PAGE ( -- )` clears the screen and puts the cursor in the top left corner.
`AT-XY ( col row -- )` moves the cursor to col row. Top left is `0 0 `.
`.R ( n u -- )` displays the signed integer n right aligned in a field u spaces wide. `.R` is often used to display numbers in columns.

Not technically a display word but useful in this context is:

`MS ( +n -- )` Wait +n milliseconds.

Try:

```PAGE  30 12 AT-XY .( Simple Forth )
PAGE  CR 1 3 .R  CR 12 3 .R  CR 123 3 .R
PAGE  33 12 2DUP AT-XY  100 5 .R  2000 MS  AT-XY 1 5 .R

```
Homework: Improve Sticks by using words introduced in this lesson.
```BYE
```

Lesson 20 Data on the Return Stack `>R R@ R> 2>R 2R@ 2R>`

You will occasionally find it convenient to be able to put a stack item temporarily in another place. "Another" place is the return stack. Your Forth almost certainly uses the return stack for its own purposes, so your use of the return stack must follow certain rules:

1. Data put on the return stack must be taken back within the same word.
2. Data put on the return stack outside a `?DO (DO) ... LOOP (+LOOP)` cannot be accessed within the loop.
3. Data put on the return stack within a `?DO (DO) ... LOOP (+LOOP)` must be taken back before leaving the loop.
4. Data cannot be on the return stack when executing `I` or `J` in a loop.

In the following descriptions of return stack words, `( S: ... -- ... )` shows the (data) stack effect
`( R: ... -- ... )` shows the return stack effect.

`>R ( S: x -- ) ( R: -- x )` moves x from the stack to the return stack.
`R@ ( R: x -- x ) ( S: -- x )` copies x from the return stack to the stack.
`R> ( R: x -- ) ( S: -- x )` moves x from the return stack to the stack.
`2>R ( S: x1 x2 -- ) ( R: -- x1 x2 )` moves x1 x2 from the stack to the return stack.
`2R@ ( R: x1 x2 -- x1 x2 ) ( S: -- x1 s2 )` copies x1 x2 from the return stack to the stack.
`2R> ( R: x1 x2 -- ) ( S: -- x1 x2)` moves x1 x2 from the return stack to the stack.

I'll use return stack words in future lessons. The uses will simplify coding. You won't find anything like this:

```\ pascal.f
\ Pascal's Triangle
: POSITION  ( row -- )  CR  33 SWAP 2 *  - SPACES ;
: PAS ( 0 ... 0 -- 0 ... 0 )
0 >R
BEGIN  OVER + >R  DUP 0= UNTIL
BEGIN  R> DUP WHILE  DUP 4 .R  REPEAT ;
: PASS  ( -- )
0 1 0
13 0 ?DO  DUP POSITION  >R  PAS  R>  1+  LOOP  DROP ;
: PAX  ( 0 ... 0 -- )  DROP BEGIN 0= UNTIL ;
: PASCAL  ( -- )  PASS PAX ;

BYE
```

Lesson 21 Named Storage `CONSTANT VARIABLE U. U.R ! @ +! ?`

Stack items are anonymous, documented only by the stack effect comments you are urged but not required to write. Forth can also name data. We start with two words:

x `CONSTANT` name defines the word name `( -- x )` that returns x.
`VARIABLE` name defines the word name ` ( -- addr )` that returns the memory address addr where is reserved space for one cell of data (remember that a stack item is the size of one cell).

Your Forth dictionary probably comes with the constants TRUE and FALSE, which return the well-formed flags all bits set and all bit reset respectively. If not, they are easy to define (I think we've defined them twice before).

Try:

```0 CONSTANT FALSE
FALSE FALSE = CONSTANT TRUE
FALSE .
TRUE .

123 CONSTANT EASY
EASY .
```

We defined the variable `RND` in random.f. Let's define another variable and display its address.

Try:

```VARIABLE x
x U.
```

`U.` displays an unsigned integer. Memory addresses are always positive integers.

`U. ( u -- )` displays the unsigned integer u.
`U.R ( u n -- )` displays the unsigned integer u right aligned in a field n spaces wide.

A constant's value doesn't change (in Forth one can change anything, but this is Simple Forth). A variable returns an address at which a value can be "stored" and from which a copy of the stored value can be "fetched". To change what is fetched from a variable's address, store a different value at it. The words for storing and fetching are:

`! ( x addr -- )` stores x at the address addr.
`@ ( addr -- x )` fetches a copy of x from the address addr.
`+! ( x addr -- )` adds x to the value at addr.

Try:
```VARIABLE y
y U.
50 y !
y @ .

100 y !
y @ .

1 y +!
y @ .
```

Most Forths have a word for `@ .`:
`? ( addr -- )` displays the value at addr.

Try:

```VARIABLE z
7 z !
z ?

VARIABLE w
11 w !
w ?

z @ w @ z ! w !
z ?
w ?

\ Exchange values of two variables
: VSWAP  ( addr1 addr2 -- )  2DUP 2>R  @ SWAP @  R> !  R> ! ;

w ?
z ?
w z VSWAP
w ?
z ?

VARIABLE OLD
VARIABLE NEW
VARIABLE INDIRECTION

67 OLD !
70 NEW !

OLD INDIRECTION !

\ EMIT displays a character
INDIRECTION @ @ EMIT

NEW INDIRECTION !
INDIRECTION @ @ EMIT

BYE
```

Lesson 22 Accessing Memory 1 `UNUSED CELLS`

In the last lesson, we learned how to access a cell of data in memory by using `! +! @`. In this and the next few lessons we'll work with groups of cells in memory. Much of the discussion will be applicable when working with data that may be more or less than a cell in size.

Forth systems tend to be small. What the system doesn't use is available to the programmer. Your system may have the word `UNUSED` that tells how many memory addresses are currently available for data.

`UNUSED ( -- u )` returns u, the number of addresses still available.

Try:

```UNUSED U.
```

As you add words and data structures to your program the amount of unused space gets smaller.

Try:

```UNUSED U.
VARIABLE x
UNUSED U.
```

Since we've been working with cell-sized data, we now introduce:

`CELLS ( n1 -- n2 )` returns n2, the number of address units in n1 cells.

It's likely that a cell occupies 2 address units if you have a 16-bit Forth and 4 address units if you have a 32-bit Forth. I say address units, since the address of the cell is the address of the first address unit occupied by the cell.

To see for yourself, try:

```1 CELLS .
2 CELLS .
10 CELLS .
```

To see how many cells could fit in currently unused memory, try:

```UNUSED 1 CELLS / .

BYE
```

Lesson 23 Accessing Memory 2 `CREATE HERE ALLOT ERASE CELL+`

Let us claim some unused memory.

`CREATE` name defines name, which returns a memory address.
`HERE ( -- addr )` returns the next free memory address.
`ALLOT ( n -- )` reserves n address units of memory.

`CREATE` name resembles `VARIABLE` name but doesn't reserve space. To reserve space after `CREATE` name, `ALLOT` it. The first address that is reserved is the address returned by `HERE`.

Try:

```CREATE ITEMS
ITEMS U.
HERE U.
1 CELLS ALLOT
HERE U.
4 CELLS ALLOT
HERE U.
```

A word that combines `CREATE` and `ALLOT` can be defined.

Try:

```\ Reserve n address units starting at name
\ n BUFFER: name
: BUFFER:   ( n -- )  CREATE ALLOT ;

4 20 + CELLS BUFFER: BLACKBIRDS
BLACKBIRDS 24 CELLS DUMP
```

`BUFFER:` could be "enhanced" by making it initialize (typically set to zeroes) the space `ALLOT`ed, but we'll leave it as it is and initialize with in separate step:

`ERASE ( a u -- )` sets the contents u addresses starting from a to zero.

Try:

```BLACKBIRDS 24 CELLS ERASE
BLACKBIRDS 24 CELLS DUMP
```

Once you have `CREATE`d (that is, named) and `ALLOT`ed space in memory, you can `!` (store), `+!` ( add to or "plus" store), @ (fetch), and `?` (question) data from within that space by calculating the particular address needed. The starting address is returned by name. The addresses of the following cells are calculated by adding n `CELLS` to the starting address.

Given 5 cells starting at `ITEMS` try:

```ITEMS U.
50 ITEMS !
ITEMS ?

ITEMS 0 CELLS + U.
ITEMS 0 CELLS + ?

ITEMS 1 CELLS + U.
95 ITEMS 1 CELLS + !
ITEMS 1 CELLS + ?

ITEMS 2 CELLS + U.
77 ITEMS 2 CELLS + !
ITEMS 2 CELLS + ?
23 ITEMS 2 CELLS + +!
ITEMS 2 CELLS + ?
```

There are many ways of not having to repeatedly write n `CELLS` to calculate memory addresses. Here are two simple ways:

Try:

```\ Return address of cell n from addr

ITEMS ?
ITEMS 0 TH ?

ITEMS 3 TH U.
33 ITEMS 3 TH !
ITEMS 3 TH ?

\ Return address of cell n of ITEMS
: ITEM  ( n -- addr )  CELLS ITEMS +

ITEMS ?
0 ITEM ?

25 4 ITEM !
4 ITEM ?
```

The word for going from one cell address to the next is:

`CELL+ ( addr1 -- addr2 )` adds 1 CELLS to addr1.

Try:

```\ Display n cells beginning at addr
: .CELLS  ( addr n -- )
0 ?DO  DUP ?  CELL+  LOOP  DROP ;

ITEMS 5 .CELLS

\ Sum of n cells beginning at addr
: SUM-CELLS  ( addr n -- sum )
0 ROT ROT  0 ?DO  DUP >R  @ +  R> CELL+  LOOP  DROP ;

ITEMS 5 SUM-CELLS
```

For another definition of `SUM-CELLS` try:

```: UNDER+  ( n1 x n2 -- n1+n2 x )  ROT + SWAP ;
: SUM-CELLS  ( addr n -- sum )
0 ROT ROT  0 ?DO  DUP @ UNDER+  CELL+  LOOP  DROP ;

ITEMS 5 SUM-CELLS
```

Homework: write yet another definition of `SUM-CELLS` by using

```: @+  ( addr1 -- addr2 n )  DUP CELL+  SWAP @ ;
```

and any other words you know or care to define.

```BYE
```

Lesson 24 Accessing Memory 3 `,`

After a long lesson a short one on a short word:

`, ( x -- )` reserves a cell of memory and stores x in it.

Try:

```: TH  ( addr1 n -- addr2 )  CELLS + ;
\ Powers of 2 from 2^0 to 2^8
CREATE 2^  1 ,  2 ,  4 ,  8 ,  16 ,  32 ,  64 ,  128 ,  256 ,
2^ ?
2^ CELL+ ?
2^ 2 CELLS + ?

2^ 0 TH ?
2^ 1 TH ?
2^ 2 TH ?
2^ 8 TH ?
```

A word by Wil Baden can make this procedure even nicer.

Try:

```\ "commas" by Wil Baden
: ,S  ( x1 ... xn n -- )
BEGIN ?DUP WHILE  DUP ROLL ,  1-  REPEAT ;

\ Redefine   2^ 0 1 2 3  4  5  6   7   8
CREATE 2^       1 2 4 8 16 32 64 128 256   9 ,S

2^ ?+ ?+ ?+ ?+ ?+ ?+ ?+ ?+ ?

BYE
```

Lesson 25 Decimal Hexadecimal Binary `BASE DECIMAL HEX DUMP`

Mostly we've been using ordinary-looking numbers like `5 12 33`. These are decimal - or base 10 - numbers represented with the 10 digits from 0 to 9. In Forth, numbers can be entered or displayed in any base from 2 to 36 (the computer stores the numbers in binary - base 2). The base in which numbers are input and displayed is stored in a variable:

`BASE ( -- addr)` holds the current base.

Forth has words for making the base decimal or hexadecimal:

`DECIMAL ( -- )` stores 10 (decimal) in `BASE`
`HEX ( -- )` stores 16 (decimal) in `BASE`

Try:

```DECIMAL
16 .
16 HEX .
FF .
FF DECIMAL .
1024 .
1024 HEX .
DECIMAL
```

Usually the base is decimal but hexadecimal - base 16, where digits range from 0 to F - is very convenient in computing because a hexadecimal digit represents 4 bits (0=0001, 1=0001, 2=0010, 3=0011 ... F=1111). That means that 8 bits can be represented by 2 hexadecimal digits, 16 bits by 4 hexadecimal digits, 32 bits by 8 hexadecimal digits, and so on. This grouping of bits makes it easier to understand what's going on inside a computer. The word `DUMP` reports in hexadecimal:

`DUMP ( addr u -- )` displays the contents of u consecutive addresses beginning at addr. The display depends on the implementation. You'll often see on each line an address, then 16 2-digit hexadecimal numbers representing the contents of 16 addresses, then the ASCII equivalents of these contents.

We can write words that restore the current base after displaying in another base.

Try:

```\ Display as an unsigned hexadecimal number
: H.  ( n -- )  BASE @ >R  HEX U.  R> BASE ! ;
\ Display as an unsigned binary number
: B.  ( n -- )  BASE @ >R  2 BASE !  U.  R> BASE ! ;
\ Display as an unsigned decimal number
\ D. is already used in Forth
: D#.  ( n -- )  BASE @ >R  DECIMAL .  R> BASE ! ;

\ Display as decimal, hexadecimal, binary
: DHB.  ( n -- )  DUP D#.  DUP H.  B. ;

DECIMAL
1 DHB.
2 DHB.
3 DHB.
4 DHB.
10 DHB.
15 DHB.
16 DHB.
1023 DHB.
1024 DHB.

HEX
1 DHB.
2 DHB.
A DHB.
F DHB.
10 DHB.
FF DHB.
100 DHB.
1000 DHB.
FFFF DHB.
1000 DHB.

CREATE POTS  3 CELLS ALLOT

10 POTS !
100 POTS CELL+ !
1000 POTS 2 CELLS + !

POTS ?
POTS CELL+ ?
POTS 2 CELLS + ?

DECIMAL
POTS 3 CELLS DUMP
POTS @ DHB.
POTS CELL+ @ DHB.
POTS 2 CELLS + @ DHB.

2 BASE !
1 DHB.
10 DHB.
11 DHB.
100 DHB.

DECIMAL

BYE
```

Lesson 26 Booleans and Bits `AND OR XOR 0<> INVERT 2* 2/ LSHIFT RSHIFT`

Forth's "logical operators" are all bit operators.

`AND ( x1 x2 -- x3 )`
`OR ( x1 x2 -- x3 )`
`XOR ( x1 x2 -- x3 ) `

Try:

```1 1 AND .
1 0 AND .
0 1 AND .
0 0 AND .

1 1 OR .
1 0 OR .
0 1 OR .
0 0 OR .

1 1 XOR .
1 0 XOR .
0 1 XOR .
0 0 XOR .

: B.  ( u -- )  BASE @ >R  2 BASE ! U.  R> BASE ! ;

1 DUP B. 2 DUP B. AND B.
1 DUP B. 2 DUP B. OR B.
1 DUP B. 2 DUP B. XOR B.

1 DUP B. 3 DUP B. AND B.
1 DUP B. 3 DUP B. OR B.
1 DUP B. 3 DUP B. XOR B.
```

Any non-zero flag is treated as true, but `1 2 AND` leaves zero, so it's wise to `AND` only well-formed flags. You can make a flag well formed with `0<>`:

`0<> ( x -- flag )` \ Does x not equal zero?

A definition of `0<>` might be:

```: 0<>  ( x -- flag)  0= 0= ;
```

Try:

```1 2 AND .
1 0<> 2 0<> AND .

\ A year is a leap year if:
\ it's divisible by 4 but not by 100
\ or it's divisible by 400
: LEAP ( year -- flag )  \ nonzero flag means a leap year
DUP 4 MOD 0=  OVER 100 MOD AND
SWAP 400 MOD 0= OR ;

: LEAP?  ( year -- )
DUP .
LEAP IF ." is" ELSE  ." isn't" THEN  ."  a leap year." ;

2000 LEAP?

\ A word can be saved by deciding if a year isn't a leap year
: -LEAP  ( year -- flag )  \ nonzero flag means not a leap year
DUP 100 MOD 0=  OVER 400 MOD AND  SWAP 4 MOD OR ;

\ Using EXIT skips some tests for most years
: LEAPX  ( year -- flag )
DUP 4 MOD IF DROP FALSE EXIT THEN
DUP 100 MOD SWAP 400 MOD 0= OR ;

: -LEAPX  ( year -- flag )
DUP 4 MOD IF EXIT THEN
DUP 100 MOD 0= SWAP 400 MOD AND ;
```

Forth's other bit operators are:

`INVERT ( x1 -- x2 )` toggles bits of x1
`2* ( x1 -- x2 )` shifts bits of x1 one place left, leaving the least significant bit zero. A fast `2 *` on most systems.
`2/ ( x1 -- x2 )` shifts bits of x1 one place right, leaving the most significant bit unchanged. A fast `2 /` on most systems.
`LSHIFT ( x1 u -- x2 )` shifts bits of x1 u places to the left, putting zeros in the empty places on the right.
`RSHIFT ( x1 u -- x2 )` shifts bits of x1 u places to the right, putting zeroes in the into empty places on the left.

Try:

```0 DUP B. INVERT B.
1 DUP B. INVERT B.
-1 DUP B. INVERT B.

1 DUP B. 2* DUP B. .
-1 DUP B. 2* DUP B. .

2 DUP B. 2/ DUP B. .
-2 DUP B. 2/ DUP B. .

1 DUP B. 4 LSHIFT DUP B. .
1 DUP B. 8 LSHIFT DUP B. .

-1 DUP B. 4 LSHIFT DUP B. .
-1 DUP B. 8 LSHIFT DUP B. .

\ 2 to the nth power
: 2^  ( +n -- u )  1 SWAP LSHIFT ;

0 2^ U.
1 2^ U.
2 2^ U.
3 2^ U.
4 2^ U.
10 2^ U.

-1 DUP B. 4 RSHIFT DUP B. .
-1 DUP B. 8 RSHIFT DUP B. .
```

The following code uses several bit operators.

```\ lights.f
\ Usage: S" lights.f" INCLUDED

VARIABLE LIGHTS  \ holds state of lights

\ Set nth bit only
: MASK  ( n1 -- n2 ) 1 SWAP LSHIFT ;

: LAMP  ( -- )  PAGE
26  4 AT-XY  ." LIGHTS"
4  7 AT-XY  0 16 0 ?DO  DUP 3 .R  1+  LOOP  DROP
13  9 AT-XY  ." n ON/OFF/TOGGLE / BRIGHT/DARK/BYE " ;

: ON?  ( n1 -- n2|0 )  MASK LIGHTS @ AND ;

: LIGHT  ( -- )  ."  @ " ;
: .LIGHT?  ( u -- )  ON? IF LIGHT ELSE 3 SPACES THEN ;
: .LIGHTS  ( -- )
5  6 AT-XY  0 16 0 ?DO  DUP .LIGHT?  1+  LOOP  DROP
0 11 AT-XY  80 SPACES  0 10 AT-XY ;

\ Set individual lights
: ON  ( u -- )  MASK LIGHTS @ OR LIGHTS !  .LIGHTS ;
: OFF ( u -- )  MASK INVERT LIGHTS @ AND LIGHTS !  .LIGHTS ;
: TOGGLE ( u -- )  MASK LIGHTS @ XOR LIGHTS !  .LIGHTS ;

\ Set all lights
: DARK  ( -- )  FALSE LIGHTS !  .LIGHTS ;
: BRIGHT  ( -- )  TRUE LIGHTS !  LAMP .LIGHTS ;

BRIGHT
```

Bit data can extend beyond one cell. Try:

```\ highest on-bit in x
: HI-BIT  ( x -- u )
0 SWAP
BEGIN DUP WHILE  1 RSHIFT  1 UNDER+  REPEAT  DROP ;

\ Number of bits in a cell
TRUE HI-BIT CONSTANT BITS/CELL

\ bit is the nth bit of cell
: BIT  ( bit - n cell )  BITS/CELL /MOD ;

\ Number of cells needed to hold bits
: BITS  ( bits - cells )  BIT SWAP IF 1+ THEN ;

\ Create bit array
: BIT-ARRAY  ( bits -- )
CREATE             \ Name of array
DUP ,              \ Size in bits
BITS CELLS ALLOT   \ Reserve space in memory
;

64 BIT-ARRAY LIGHT

\ Set nth bit only
: MASK  ( n1 -- n2 ) 1 SWAP LSHIFT ;

\ Individual bits
: >BIT  ( addr1 bit1 -- bit2 addr2 )  BIT CELLS ROT + CELL+ ;
: ON  ( addr bit -- )  >BIT >R  MASK R@ @ OR  R> ! ;
: OFF ( addr bit -- )  >BIT >R  MASK INVERT R@ @ AND  R> ! ;
: TOGGLE ( addr bit -- )  >BIT >R  MASK R@ @ XOR  R> ! ;
: ON?  ( addr bit -- flag )  >BIT >R  MASK R> @ AND 0<> ;

\ Set cells
: >CELL  ( addr1 cell -- addr2 ) 1+ CELLS + ;
: CELL-ON  ( addr cell -- ) >CELL  TRUE SWAP ! ;
: CELL-OFF  ( addr cell -- ) >CELL  FALSE SWAP ! ;
: CELL-TOGGLE ( addr cell -- ) >CELL DUP @ INVERT  SWAP ! ;

\ Set all bits
: @+  ( addr1 -- addr2 x )  DUP CELL+  SWAP @ ;
: !S  ( x addr1 u -- )  0 ?DO  2DUP !  CELL+  LOOP  2DROP ;

: DARK  ( addr -- )  FALSE SWAP @+ BITS !S ;
: BRIGHT  ( addr -- )  TRUE SWAP @+ BITS !S ;

\ Inspect bit-array in memory
: MEMORY  ( bit-array -- )  @+ BITS CELLS DUMP ;

\ Display bit array
: SHOW  ( addr )  CR
0 OVER @
0 ?DO  2DUP ON? 1 AND 0 .R  1+  LOOP  2DROP ;

LIGHT BRIGHT
LIGHT MEMORY
LIGHT SHOW

LIGHT DARK
LIGHT MEMORY
LIGHT SHOW

LIGHT 0 CELL-ON
LIGHT MEMORY
LIGHT SHOW

LIGHT 0 CELL-OFF
LIGHT MEMORY
LIGHT SHOW

LIGHT 1 CELL-TOGGLE
LIGHT MEMORY
LIGHT SHOW

LIGHT 1 CELL-TOGGLE
LIGHT MEMORY
LIGHT SHOW

LIGHT 32 ON
LIGHT 32 ON? .
LIGHT SHOW

LIGHT 32 OFF
LIGHT SHOW
LIGHT 32 ON? .
LIGHT SHOW

LIGHT 32 TOGGLE
LIGHT 32 ON? .
LIGHT SHOW

LIGHT 32 TOGGLE
LIGHT 32 ON? .
LIGHT SHOW

BYE
```

Lesson 27 A Software Stack `2@ 2!`

For an excursion, here are some words for software stacks. Each stack element occupies a cell; stack depth is checked. To create a stack, specify its maximum depth and its name. The name is used when `PUSH`ing, `POP`ing, displaying, and `EMPTY`ing. For an implementation of stacks with elements of arbitrary size, see Len Zettel's User Stacks in Forth. And for a use of such user stacks see Len's Discrete Event Simulation in Forth.

`2! ( x1 x2 addr -- )` does `SWAP OVER ! CELL+ !`
`2@ ( addr -- x1 x2 )` does `DUP CELL+ @ SWAP @`

`2!` and `2@` are typically used to store and fetch "double numbers", which are integers 2 cells wide. In our software-stack implementation, we'll use `2@` to fetch values from the two addresses starting at addr.

Try:

```\ Software stack implementation

: ++  ( addr -- )   1 SWAP +! ;
: --  ( addr -- )  -1 SWAP +! ;

: @+  ( addr -- addr+ x )  DUP CELL+ SWAP @ ;

\ Make a stack u cells deep
\ Usage:  u STACK <name>
: STACK  ( u -- )
CREATE         \ stack <name>
0 ,            \ initialize depth
DUP ,          \ set maximum depth
CELLS ALLOT ;  \ reserve space

\ If there's room on stack, move x from the Forth stack to it
\ else leave x on the Forth stack
: PUSH  ( x stack -- |x )
DUP 2@ >
IF  DUP ++  @+ CELLS + !
ELSE  DROP ." Stack full"  THEN ;

\ If there's an x, move it from stack to the Forth stack
\ else put nothing on the Forth stack
: POP  ( stack -- x| )
DUP @+ ?DUP
IF  ROT --  CELLS + @
ELSE  DROP ." Empty stack"  THEN ;

\ Display stack items, bottom --> top
: .STACK  ( stack -- )
@+ ?DUP
IF  0 ?DO  CELL+  DUP ?  LOOP
ELSE  ." Empty stack"  THEN
DROP ;

\ Clear stack
: EMPTY  ( stack -- )  0 SWAP ! ;

3 STACK MYSTACK

33 MYSTACK PUSH

-33 MYSTACK PUSH

MYSTACK .STACK

MYSTACK POP .

MYSTACK EMPTY

BYE
```

Lesson 28 Characters A `EMIT CHAR BL`

Characters, like other data in a computer, are bit patterns treated in a particular way. An integer and a character can have the same bit pattern.

`EMIT ( char -- )` displays char.
`CHAR ( -- char )` puts the next char on the stack.
`BL ( -- char )` puts the value for space (decimal 32) on the stack.

Try:

```BL DUP . EMIT
BL DUP EMIT .
65 DUP . EMIT
CHAR A DUP . EMIT
```

Decimal 65 is the ASCII (American Standard Code for Information Interchange) and ISO IRV (International Standards Organization? International Reverence Version) code for 'A'. Both standards have the same character interpretation for codes 32-126 except for 36.

Try:

```36 EMIT
```

If \$ is displayed, it's ASCII.

Codes 0-31 are control codes with generally accepted meanings. Codes beyond 126 exist in other standards. We'll stick to 32-126. Here are characters 32-126 with the implementation-defined character 127 thrown in.

Try:

```\ Display next n characters and their codes
: .CHARS ( c n -- c+n )
0 ?DO  DUP 5 .R  DUP SPACE EMIT  1+  LOOP ;

\ Display characters 32-127 and their codes
: .CHARS32-127 ( -- )
BL 12 0 ?DO  CR 8 .CHARS  LOOP  DROP ;

.CHARS32-127

BYE
```

Lesson 29 Characters B `[CHAR] KEY`

To put a particular character in a definition, use `[CHAR]`. To wait for a character from the keyboard, use `KEY`.

`[CHAR] <char>` in a definition puts char on the stack when the definition is executed.
`KEY ( -- char )` waits for a key press, then puts the character pressed on the stack.

Try:

```\ Is character Y or y?
: Y?  ( char -- flag )
DUP [CHAR] Y =  SWAP [CHAR] y = OR ;

: YES?  ( -- )
." Press Y for yes."  KEY
Y? IF  ." Yes"  ELSE  ." No"  THEN ;

YES?

\ KEY doesn't automatically EMIT
: PRESS  ( -- )
." Please press a key. " KEY
." You pressed " EMIT ;

PRESS

BYE
```

Lesson 30 Characters C `C, C@ C! CHARS CHAR+ ALIGN`

`C, C@ C! CHARS CHAR+` are character versions of `, @ ! CELLS CELL+`. Although on the stack a character occupies a cell, in many Forths a character in memory occupies less space than a cell. Character codes 0-127 fit into 7 bits, and 8 bits (a byte) can hold codes 0-255. A Forth with 8-bit characters can therefore store two characters in 16 bits and 4 characters in 32 bits. Since `, @ ! CELLS CELL+` are intended for cell-size values in memory, character versions are need for character-size values.

`C, ( char -- )` reserves a character of memory and stores character-size value in it.
`C@ ( c-addr -- char )` fetches char from c-addr.
`C! ( char c-addr -- )` stores char at c-addr.
`CHARS ( n1 -- n2 ) ` n1 chars fit into n2 address units.
`CHAR+ ( c-addr1 -- c-addr2 )` advances c-addr1 by one character.

`ALIGN` assures proper placement of cell values. Use after `C,` and `CHARS ALLOT`.

Try:

```CREATE CHARACTER  CHAR A C, CHAR  B C, ALIGN
CHARACTER C@ EMIT
CHARACTER CHAR+ C@ EMIT
CHAR Z CHARACTER C!
CHAR ! CHARACTER CHAR+ C!
CHARACTER C@ EMIT
CHARACTER CHAR+ C@ EMIT
: C!+  ( c-addr char -- c-addr+ )  OVER C! CHAR+ ;
\ C@+ and EMITS we'll meet again as COUNT and TYPE
: C@+  ( c-addr -- c-addr+ char )  DUP CHAR+ SWAP C@ ;
: EMITS  ( c-addr n )  0 MAX  0 ?DO  C@+ EMIT  LOOP  DROP ;
CREATE 5CHARS 5 CHARS ALLOT ALIGN
5CHARS
CHAR F C!+  CHAR o C!+  CHAR r C!+  CHAR t C!+  CHAR h C!+
DROP  \ drop the c-addr remaining after the last C!+

5CHARS 5 EMITS

BYE

```

Lesson 31 Strings 1 `S" TYPE`

A string is an array of characters. We already used `."` and `.(` to display strings. To just define a string one can use:

`S" `text`" ( -- a u )`, used in a definition, compiles text up to but not including the next `"`, returning the character address c-addr and the length of the string u when the definition is executed. Using `S"` in a definition is an easy way to create a string constant.

Try:

```: HI  S" Ni hao!" ;
HI CHARS DUMP
```

If your ANS Forth system has file words, `S"` can also be used outside a definition to put text in a temporary buffer that could be overwritten by the next use of `S"` outside a definition. This `S"` also returns an address and a length. I'll assume that you can use `S"` outside a definition.

Try:

```S" Xiexie."  .S CHARS DUMP
S" Bu keqi." .S CHARS DUMP
```

`TYPE ( c-addr u -- )` displays the first u characters of a string, starting at address c-addr.

Try:

```\ Assumes HI is defined
HI TYPE

\ Equivalent to : GOODBYE  ." Zaijian" ;
: GOOD-BYE  S" Zaijian" TYPE ;

GOOD-BYE

BYE
```

Lesson 32 Strings 2 `COUNT MOVE`

Since most string functions use the starting address of a string and the string's length, it's convenient to store the length along with the string. In Forth, a string that has its length in a character-sized address and the string itself in the following character addresses is called a counted string. For example, the counted string "Leo" is: `3 'L' 'e' 'o'`. The word that takes the address of a counted string and returns the address and length of the string is:

`COUNT ( c-addr1 -- c-addr2 u )` returns the address c-addr2 of the first character and the number of characters u in the counted string at c-addr1.

`COUNT` is effectively `DUP CHAR+ SWAP C@`. It is used for other things besides getting the start and "count" of a counted string and would have been better named `C@+`.

Since the "count" is stored in a character-sized space, the maximum length of a counted string can't be larger than the largest number that space can hold. For a Forth with 8-bit characters, the maximum length of a counted string is 255. However, longer strings are easy to accommodate in Forth.

The easiest way to create a counted string is to `MOVE` a string ( c-addr u ) into data space.

`MOVE ( addr1 u addr2 -- )` copies the contents of u consecutive address units at addr1 to the u consecutive address units at addr2.

Since `MOVE` uses address units, it can be used for any type of data. The two Forth words `CMOVE` and `CMOVE>` specifically copy characters, but we'll just use `MOVE` and specify that we are moving `CHARS`.

I'm getting tired of typing `addr c-addr char` in comments, so from now on I'll just write `a ca c`. Also, I'll continue to write ANS Forth words in uppercase but start writing non-ANS Forth words in lowercase.

`s`

Try:

```CREATE my-string  50 CHARS ALLOT
\ Copy ca1 u as a counted string to ca2
: place  ( ca1 u ca2 -- )
2DUP 2>R  CHAR+ SWAP CHARS MOVE  2R> C! ;

S" The quick brown fox jumped over the lazy dog."
my-string place
my-string COUNT TYPE

\ Illustrating COUNT as C@+
: my-type  ( ca u -- )  0 ?DO COUNT EMIT LOOP DROP ;
my-string COUNT my-type

BYE
```

Lesson 33 Strings 3 `/TRAILING FILL BLANK -TRAILING`

A penknife for strings is:

`/STRING ( ca1 u1 n -- ca2 u2 )` returns ca2 = ca1+nchars, u2 = u1-n. `/STRING` is officially "slash string"; a nicer name would be "cut string". `/STRING` could be defined:
``` : /STRING ( ca1 u1 n -- ca2 us ) TUCK - >R CHARS + R>```

Try:

```\ Three words useful in string processing.
\ Skip leading c's in ca u; return remaining string ca' u'
: skip  ( ca u c -- ca' u' )
>R
BEGIN DUP WHILE OVER C@ R@ = WHILE 1 /STRING REPEAT THEN
R> DROP ;

\ Look for 1st c in ca u; return ca' u' including c
: scan  ( ca u c -- ca' u' )
>R
BEGIN DUP WHILE OVER C@ R@ <> WHILE 1 /STRING REPEAT THEN
R> DROP ;

\ From ca u, return 1st "word" ca2 u2 and remainder ca1 u1
\ WORD is a Forth word, so I'll call this:
: "word"  ( ca u -- ca1 u1 ca2 u2 )
BL skip  2DUP 2>R  BL scan  DUP 2R> ROT - ;

\ Illustration using word
: list-words  ( ca u -- )
BEGIN DUP WHILE "word" CR TYPE REPEAT 2DROP ;

S" To be or not to be" list-words
```

`FILL BLANK` and `-TRAILING` are also handy. I give them and possible Forth definitions.

`FILL ( ca u c -- )` stores c in u consecutive characters of memory beginning at ca.

`: FILL ( ca u c -- ) ROT ROT 0 ?DO 2DUP C! CHAR+ LOOP 2DROP ;`

`BLANK ( ca u -- )` `FILL`s with spaces.
`: BLANK ( ca u -- ) BL FILL ;`

`-TRAILING ( ca u1 -- ca u2 )` returns ca u1 minus any trailing spaces. "Dash trailing".

```: <skip  ( ca u1 c -- ca u2 )
>R
BEGIN DUP WHILE 1- 2DUP CHARS + C@ R@ <> UNTIL 1+ THEN
R> DROP ;
: -TRAILING  ( ca u1 -- ca u2 >  BL <skip ;
```

Try:

```CREATE BUFFER 40 CHARS ALLOT
BUFFER 40 CHAR Y FILL
BUFFER 40 TYPE
BUFFER 20 CHARS + 20 BLANK
BUFFER 40 TYPE
BUFFER 40 -TRAILING TYPE
BUFFER 20 BLANK
BUFFER 40 TYPE
BUFFER 40 -TRAILING TYPE

BYE
```

Lesson 34 Strings 4 `SEARCH COMPARE`

String searches and compares are done with `SEARCH` and `COMPARE`:

`SEARCH ( ca1 u1 ca2 u2 -- ca3|ca1 u3|u1 true|false )` searches ca1 u1 for the string specified by ca2 u2. If found, returns address ca3 of first match, characters remaining u3, and true, else returns ca1 u1 false.

`COMPARE ( ca1 u1 ca2 u2 -- -1|0|1 )` compares ca1 u1 and ca2 u2 and returns -1 if ca1 u1 is less than ca2 u2, 0 if the two strings are the same, and 1 if ca1 u1 is greater than ca2 u2. (See the examples for what is meant by less, same, and greater.)

`SEARCH` and `COMPARE` are case sensitive.

Try:

```: s1  S" Out out out!" ;
s1 s" Out" SEARCH . TYPE
s1 S" out" SEARCH . TYPE
s1 s" out!" SEARCH . TYPE
s1 S" OUT"  SEARCH . TYPE

\ Char is lowercase?
: lower?  ( c -- t|f)  [CHAR] a - 26 U< ;
\ Make char uppercase
: upper  ( c -- c' )  DUP lower? BL AND XOR ;
\ Make string uppercase
: supper  ( a u -- )
0 ?DO DUP C@ upper OVER C! CHAR+ LOOP DROP ;

s1 2DUP supper S" ouT" 2DUP supper SEARCH . TYPE

: outs?  ( a u -- n )
2DUP supper  0 >R
BEGIN S" OUT" SEARCH
WHILE R> 1+ >R  1 /STRING
REPEAT  2DROP
R> ;

S" out spout mouth" outs? .

: ABC?  S" ABC" COMPARE . ;
S" ABC" ABC?
S" abc" ABC?
S" AB" ABC?
S" ABCD" ABC?
S" B" ABC?
S" @ABC" ABC?
S" abc" 2DUP supper ABC?

\ Compare for integers
: sgn  ( n - -1|0|1 )
-1 MAX 1 MIN ;
: ncompare  ( n1 n2 -- -1|0|1 )
- sgn ;

-10 sgn .
0 sgn .
10 sgn .

10 5 ncompare .
5 5 ncompare .
-10 5 ncompare .

BYE
```

Lesson 35 Values `VALUE TO`

In some programs a value is set once or infrequently and used often. For example, many words that have to do with files require a file identifier (fid) that is returned when the file is created or opened. The fid could easily be stored in a variable:

```VARIABLE fid
```
and fetched whenever needed:
```fid @
```
Many Forths provide a cross between a constant and the variable that is called a value. It might be used as follows:
```0 VALUE fid      \ Define fid as a value set to 0
...
( u -- ) TO fid  \ Set fid to u
...
fid ( -- u )     \ Return u
```

x `VALUE` name defines the word name that returns x unless the value to be returned is changed by `TO`.

y `TO` name makes name return y.

y `+TO` name, available in some Forths, increments by y the value returned by name.

Try:

```FALSE VALUE love
love FALSE = .
love love = TO love
love TRUE = .

BYE
```

For a less sappy use of `VALUE` and a preview of file words, see Fans.

Lesson 36 Locals `LOCALS| TO`

A named `VARIABLE` or `VALUE` can appear in several parts of a program: its possible use is "global" within the program. Forths that implement "locals" also provide for value names that apply only within the word they are defined in.

Using locals can prevent the bug in which a change in a variable in one part of the program has unintended consequences in another part. Locals can also make a definition easier to write and to read by making values explicit and reducing stack manipulation. Here are definitions of `vswap` without and with locals:

```\ Exchange values of two variables
\ Without locals
: vswap1  ( addr1 addr2 -- )  2DUP 2>R  @ SWAP @  R> !  R> ! ;

\ Exchange values of two variables
\ With locals
LOCALS| v1 v2 |
v1 @ v2 @ v1 ! v2 ! ;
```

`LOCALS|` allows the creation of up to eight (in some Forths more than eight) names as local identifiers. The list of names ends with `|`. Given `0 1 LOCALS| a b |`, `a` returns `1` and `b` returns `0`. (Some Forths implement a word that allows the values and the names to be placed in the same order.)

y `TO` name makes name return y. The usage is the same as that for `VALUE`s.

y `+TO` name, available in some Forths, increments by y the value returned by name. Again, the usage is the same as that for `VALUE`s.

I wrote the following after trying to explain to my daughter how to find out if a given integer is a prime number.

```\ prime.f LW 10 Jan 02002 +

\ An integer is a prime number if it can be evenly divided
\ only by itself and 1.  Integers that are not prime numbers
\ are composite numbers, divisible without a remainder by
\ numbers (factors) other than itself and 1.
\ We want to find out if a given integer n is prime or
\ composite.

\ Two English words for easier reading code.
: not  ( ? -- ? )  0= ;
: between  ( n1 n2 n3 -- ? )  1+ WITHIN ;

\ If n is evenly divisible by f, then f is a factor of n.
\ Is f a factor of n?
: factor  ( n f -- ? )  MOD 0= ;

\ 2 is a factor of even numbers.
: even  ( n -- ? )  2 factor ;

\ A composite number has at least one factor less than
\ or equal to its square root, so we only try f's whose
\ squares are less than or equal to n.
: square  ( f -- f*f )  DUP * ;

\ Find out if n has a factor between 3 and its square root
: factorable  ( n -- ? )
BEGIN
n f factor not WHILE  \ Continue if f not a factor of
f 2 + TO f            \ make f the next odd number
n f square < not WHILE  \ Continue if f squared <= n
REPEAT THEN
n f factor ;

: prime?  ( +n -- )
LOCALS| n |
n 1 3 between IF ." prime"     \ 1, 2, 3 : prime
ELSE n even IF  ." composite " \ Even & > 2 : composite
ELSE n factorable IF ." composite"  ELSE ." prime" THEN
THEN THEN ;

```
A third example of using locals multiplies complex numbers.
```\ complex multiply by ward mcfarland
: ComplexMultiply ( x1\y1\x2\y2 -- xp\yp )
\ calculate (x1 + j*y1) * (x2 + j*y2)
\            = (x1*x2 - y1*y2) + j(x1*y2 + x2*y1)
locals| y2 x2 y1 x1 |
x1 x2 *
y1 y2 *  -
x1 y2 *
x2 y1 *  +
;
```

Without locals a solution might be:

```: cm  2OVER 2OVER ROT ROT * >R * >R ROT * >R * R> - 2R> + ;
```

[To be continued....]

1999-2002 Leo Wong hello@albany.net