+<HTML>\r
+<HEAD>\r
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">\r
+ <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (Win95; I) [Netscape]">\r
+ <META NAME="Author" CONTENT="Phil Burk">\r
+ <META NAME="Description" CONTENT="Tutorial for pForth language.">\r
+ <META NAME="KeyWords" CONTENT="Forth, tutorial, pForth">\r
+ <TITLE>pForth Tutorial</TITLE>\r
+</HEAD>\r
+<BODY BACKGROUND="r2harch.gif">\r
+\r
+<HR size=4>\r
+<CENTER>\r
+<H1>\r
+Forth Tutorial</H1></CENTER>\r
+\r
+<HR WIDTH="100%">\r
+\r
+<P>by <A HREF="http://www.softsynth.com/philburk.html">Phil Burk</A>\r
+\r
+<P>To <A HREF="pforth.html">pForth Home Page</A>\r
+<H2>\r
+Table of Contents</H2>\r
+\r
+<UL>\r
+<LI>\r
+<A HREF="#Forth Syntax">Forth Syntax</A></LI>\r
+\r
+<LI>\r
+<A HREF="#The Stack">Stack Manipulation</A></LI>\r
+\r
+<LI>\r
+<A HREF="#Arithmetic">Arithmetic</A></LI>\r
+\r
+<LI>\r
+<A HREF="#Defining a New Word">Defining a New Word</A></LI>\r
+\r
+<LI>\r
+<A HREF="#More Arithmetic">More Arithmetic</A></LI>\r
+\r
+<UL>\r
+<LI>\r
+<A HREF="#Arithmetic Overflow">Arithmetic Overflow</A></LI>\r
+\r
+<LI>\r
+<A HREF="#Convert Algebraic Expressions to Forth">Convert Algebraic Expressions\r
+to Forth</A></LI>\r
+</UL>\r
+\r
+<LI>\r
+<A HREF="#Character Input and Output">Character Input and Output</A></LI>\r
+\r
+<LI>\r
+<A HREF="#Compiling from Files">Compiling from Files</A></LI>\r
+\r
+<LI>\r
+<A HREF="#Variables">Variables</A></LI>\r
+\r
+<LI>\r
+<A HREF="#Constants">Constants</A></LI>\r
+\r
+<LI>\r
+<A HREF="#Logical Operators">Logical Operators</A></LI>\r
+\r
+<LI>\r
+<A HREF="#Conditionals - IF ELSE THEN CASE">Conditionals - IF ELSE THEN\r
+CASE</A></LI>\r
+\r
+<LI>\r
+<A HREF="#Loops">Loops</A></LI>\r
+\r
+<LI>\r
+<A HREF="#Text Input and Output">Text Input and Output</A></LI>\r
+\r
+<LI>\r
+<A HREF="#Changing Numeric Base">Changing Numeric Base</A></LI>\r
+\r
+<LI>\r
+<A HREF="#Answers to Problems">Answers to Problems</A></LI>\r
+</UL>\r
+The intent of this tutorial is to provide a series of experiments that\r
+will introduce you to the major concepts of Forth. It is only a starting\r
+point. Feel free to deviate from the sequences I provide. A free form investigation\r
+that is based on your curiosity is probably the best way to learn any language.\r
+Forth is especially well adapted to this type of learning.\r
+\r
+<P>This tutorial is written for the PForth implementation of the ANS Forth\r
+standard. I have tried to restrict this tutorial to words that are part\r
+of the ANS standard but some PForth specific words may have crept in.\r
+\r
+<P>In the tutorials, I will print the things you need to type in upper\r
+case, and indent them. You can enter them in upper or lower case. At the\r
+end of each line, press the RETURN (or ENTER) key; this causes Forth to\r
+interpret what you've entered.\r
+<H2>\r
+<A NAME="Forth Syntax"></A>Forth Syntax</H2>\r
+Forth has one of the simplest syntaxes of any computer language. The syntax\r
+can be stated as follows, "<B>Forth code is a bunch of words with spaces\r
+between them.</B>" This is even simpler than English! Each <I>word</I>\r
+is equivalent to a function or subroutine in a language like 'C'. They\r
+are executed in the order they appear in the code. The following statement,\r
+for example, could appear in a Forth program:\r
+<UL>\r
+<PRE> <TT>WAKE.UP EAT.BREAKFAST WORK EAT.DINNER PLAY SLEEP</TT></PRE>\r
+</UL>\r
+Notice that WAKE.UP has a dot between the WAKE and UP. The dot has no particular\r
+meaning to the Forth compiler. I simply used a dot to connect the two words\r
+together to make one word. Forth word names can have any combination of\r
+letters, numbers, or punctuation. We will encounter words with names like:\r
+<UL>\r
+<PRE> ." #S SWAP ! @ ACCEPT . *</PRE>\r
+</UL>\r
+They are all called <I>words</I>. The word <B>$%%-GL7OP</B> is a legal\r
+Forth name, although not a very good one. It is up to the programmer to\r
+name words in a sensible manner.\r
+\r
+<P>Now it is time to run your Forth and begin experimenting. Please consult\r
+the manual for your Forth for instructions on how to run it.\r
+<H2>\r
+<A NAME="The Stack"></A>Stack Manipulation</H2>\r
+The Forth language is based on the concept of a <I>stack</I>. Imagine a\r
+stack of blocks with numbers on them. You can add or remove numbers from\r
+the top of the stack. You can also rearrange the order of the numbers.\r
+Forth uses several stacks. The <I>DataStack </I>is the one used for passing\r
+data between Forth words so we will concentrate our attention there. The\r
+<I>Return Stack</I> is another Forth stack that is primarily for internal\r
+system use. In this tutorial, when we refer to the "stack," we will be\r
+referring to the Data Stack.\r
+\r
+<P>The stack is initially empty. To put some numbers on the stack, enter:\r
+<UL>\r
+<PRE><TT>23 7 9182</TT></PRE>\r
+</UL>\r
+Let's now print the number on top of the stack using the Forth word ' <B>.</B>\r
+', which is pronounced " dot ". This is a hard word to write about in a\r
+manual because it is a single period.\r
+\r
+<P>Enter: <B>. </B>\r
+\r
+<P>You should see the last number you entered, 9182 , printed. Forth has\r
+a very handy word for showing you what's on the stack. It is <B>.S</B>\r
+, which is pronounced "dot S". The name was constructed from "dot" for\r
+print, and "S" for stack. (PForth will automatically print the stack after\r
+every line if the TRACE-STACK variable is set to TRUE.) If you enter:\r
+<UL>\r
+<PRE><TT>.S</TT></PRE>\r
+</UL>\r
+you will see your numbers in a list. The number at the far right is the\r
+one on top of the stack.\r
+\r
+<P>You will notice that the 9182 is not on the stack. The word ' . ' removes\r
+the number on top of the stack before printing it. In contrast, ' .S '\r
+leaves the stack untouched.\r
+\r
+<P>We have a way of documenting the effect of words on the stack with a\r
+<I>stack diagram</I>. A stack diagram is contained in parentheses. In Forth,\r
+the parentheses indicate a comment. In the examples that follow, you do\r
+not need to type in the comments. When you are programming, of course,\r
+we encourage the use of comments and stack diagrams to make your code more\r
+readable. In this manual, we often indicate stack diagrams in <B>bold text</B>\r
+like the one that follows. Do not type these in. The stack diagram for\r
+a word like ' . ' would be:\r
+<PRE><B><TT>. ( N -- , print number on top of stack )</TT></B></PRE>\r
+The symbols to the left of -- describe the parameters that a word expects\r
+to process. In this example, N stands for any integer number. To the right\r
+of --, up to the comma, is a description of the stack parameters when the\r
+word is finished, in this case there are none because 'dot' "eats" the\r
+N that was passed in. (Note that the stack descriptions are not necessary,\r
+but they are a great help when learning other peoples programs.)\r
+\r
+<P>The text following the comma is an English description of the word.\r
+You will note that after the -- , N is gone. You may be concerned about\r
+the fact that there were other numbers on the stack, namely 23 and 7 .\r
+The stack diagram, however, only describes the portion of the stack that\r
+is affected by the word. For a more detailed description of the stack diagrams,\r
+there is a special section on them in this manual right before the main\r
+glossary section.\r
+\r
+<P>Between examples, you will probably want to clear the stack. If you\r
+enter <B>0SP</B>, pronounced "zero S P", then the stack will be cleared.\r
+\r
+<P>Since the stack is central to Forth, it is important to be able to alter\r
+the stack easily. Let's look at some more words that manipulate the stack.\r
+Enter:\r
+<UL>\r
+<PRE><TT>0SP .S \ That's a 'zero' 0, not an 'oh' O.\r
+777 DUP .S</TT></PRE>\r
+</UL>\r
+You will notice that there are two copies of 777 on the stack. The word\r
+<B>DUP</B> duplicates the top item on the stack. This is useful when you\r
+want to use the number on top of the stack and still have a copy. The stack\r
+diagram for DUP would be:\r
+<PRE><B><TT>DUP ( n -- n n , DUPlicate top of stack )</TT></B></PRE>\r
+Another useful word, is <B>SWAP</B>. Enter:\r
+<UL>\r
+<PRE><TT>0SP \r
+23 7 .S \r
+SWAP .S \r
+SWAP .S</TT></PRE>\r
+</UL>\r
+The stack diagram for SWAP would be:\r
+<PRE><B><TT>SWAP ( a b -- b a , swap top two items on stack )</TT></B></PRE>\r
+Now enter:\r
+<UL>\r
+<PRE><TT>OVER .S\r
+OVER .S</TT></PRE>\r
+</UL>\r
+The word <B>OVER</B> causes a copy of the second item on the stack to leapfrog\r
+over the first. It's stack diagram would be:\r
+\r
+<P><B><TT>OVER ( a b -- a b a , copy second item on stack )</TT></B>\r
+\r
+<P>Here is another commonly used Forth word:\r
+\r
+<P><B><TT>DROP ( a -- , remove item from the stack )</TT></B>\r
+\r
+<P>Can you guess what we will see if we enter:\r
+<UL>\r
+<PRE><TT>0SP 11 22 .S\r
+DROP .S</TT></PRE>\r
+</UL>\r
+Another handy word for manipulating the stack is <B>ROT</B>. Enter:\r
+<UL>\r
+<PRE><TT>0SP\r
+11 22 33 44 .S\r
+ROT .S</TT></PRE>\r
+</UL>\r
+The stack diagram for ROT is, therefore:\r
+\r
+<P><B><TT>ROT ( a b c -- b c a , ROTate third item to top ) </TT></B>\r
+\r
+<P>You have now learned the more important stack manipulation words. You\r
+will see these in almost every Forth program. I should caution you that\r
+if you see too many stack manipulation words being used in your code then\r
+you may want to reexamine and perhaps reorganize your code. You will often\r
+find that you can avoid excessive stack manipulations by using <I>local\r
+or global VARIABLES</I> which will be discussed later.\r
+\r
+<P>If you want to grab any arbitrary item on the stack, use <B>PICK</B>\r
+. Try entering:\r
+<UL>\r
+<PRE><TT>0SP\r
+14 13 12 11 10\r
+3 PICK . ( prints 13 )\r
+0 PICK . ( prints 10 )\r
+4 PICK .</TT></PRE>\r
+</UL>\r
+PICK makes a copy of the Nth item on the stack. The numbering starts with\r
+zero, therefore:\r
+<UL><TT>0 PICK is equivalent to DUP</TT>\r
+<BR><TT>1 PICK is equivalent to OVER </TT></UL>\r
+<B><TT>PICK ( ... v3 v2 v1 v0 N -- ... v3 v2 v1 v0 vN ) </TT></B>\r
+\r
+<P>(Warning. The Forth-79 and FIG Forth standards differ from the ANS and\r
+Forth '83 standard in that their PICK numbering starts with one, not zero.)\r
+\r
+<P>I have included the stack diagrams for some other useful stack manipulation\r
+words. Try experimenting with them by putting numbers on the stack and\r
+calling them to get a feel for what they do. Again, the text in parentheses\r
+is just a comment and need not be entered.\r
+\r
+<P><B><TT>DROP ( n -- , remove top of stack ) </TT></B>\r
+\r
+<P><B><TT>?DUP ( n -- n n | 0 , duplicate only if non-zero, '|' means OR\r
+) </TT></B>\r
+\r
+<P><B><TT>-ROT ( a b c -- c a b , rotate top to third position ) </TT></B>\r
+\r
+<P><B><TT>2SWAP ( a b c d -- c d a b , swap pairs ) </TT></B>\r
+\r
+<P><B><TT>2OVER ( a b c d -- a b c d a b , leapfrog pair ) </TT></B>\r
+\r
+<P><B><TT>2DUP ( a b -- a b a b , duplicate pair ) </TT></B>\r
+\r
+<P><B><TT>2DROP ( a b -- , remove pair ) </TT></B>\r
+\r
+<P><B><TT>NIP ( a b -- b , remove second item from stack ) </TT></B>\r
+\r
+<P><B><TT>TUCK ( a b -- b a b , copy top item to third position ) </TT></B>\r
+<H3>\r
+<A NAME="Problems - Stack"></A>Problems:</H3>\r
+Start each problem by entering:\r
+<UL>\r
+<PRE><TT>0SP 11 22 33</TT></PRE>\r
+</UL>\r
+Then use the stack manipulation words you have learned to end up with the\r
+following numbers on the stack:\r
+<UL>\r
+<PRE><TT>1) 11 33 22 22</TT></PRE>\r
+\r
+<PRE><TT>2) 22 33</TT></PRE>\r
+\r
+<PRE><TT>3) 22 33 11 11 22</TT></PRE>\r
+\r
+<PRE><TT>4) 11 33 22 33 11</TT></PRE>\r
+\r
+<PRE><TT>5) 33 11 22 11 22</TT></PRE>\r
+</UL>\r
+<A HREF="#Answers to Problems">Answers to the problems</A> can be found\r
+at the end of this tutorial.\r
+<H2>\r
+<A NAME="Arithmetic"></A>Arithmetic</H2>\r
+Great joy can be derived from simply moving numbers around on a stack.\r
+Eventually, however, you'll want to do something useful with them. This\r
+section describes how to perform arithmetic operations in Forth.\r
+\r
+<P>The Forth arithmetic operators work on the numbers currently on top\r
+of the stack. If you want to add the top two numbers together, use the\r
+Forth word <B>+</B> , pronounced "plus". Enter:\r
+<UL>\r
+<PRE><TT>2 3 + .\r
+2 3 + 10 + .</TT></PRE>\r
+</UL>\r
+This style of expressing arithmetic operations is called <I>Reverse Polish\r
+Notation,</I> or<I> RPN</I>. It will already be familiar to those of you\r
+with HP calculators. In the following examples, I have put the algebraic\r
+equivalent representation in a comment.\r
+\r
+<P>Some other arithmetic operators are <B>- * /</B> . Enter:\r
+<UL>\r
+<PRE><TT>30 5 - . ( 25=30-5 )\r
+30 5 / . ( 6=30/5 )\r
+30 5 * . ( 150=30*5 )\r
+30 5 + 7 / . \ 5=(30+5)/7</TT></PRE>\r
+</UL>\r
+Some combinations of operations are very common and have been coded in\r
+assembly language for speed. For example, <B>2*</B> is short for 2 * .\r
+You should use these whenever possible to increase the speed of your program.\r
+These include:\r
+<UL>\r
+<PRE><TT>1+ 1- 2+ 2- 2* 2/</TT></PRE>\r
+</UL>\r
+Try entering:\r
+<UL>\r
+<PRE><TT>10 1- .\r
+7 2* 1+ . ( 15=7*2+1 )</TT></PRE>\r
+</UL>\r
+One thing that you should be aware of is that when you are doing division\r
+with integers using / , the remainder is lost. Enter:\r
+<UL>\r
+<PRE><TT>15 5 / .\r
+17 5 / .</TT></PRE>\r
+</UL>\r
+This is true in all languages on all computers. Later we will examine <B>/MOD</B>\r
+and <B>MOD</B> which do give the remainder.\r
+<H2>\r
+<A NAME="Defining a New Word"></A>Defining a New Word</H2>\r
+It's now time to write a <I>small program</I> in Forth. You can do this\r
+by defining a new word that is a combination of words we have already learned.\r
+Let's define and test a new word that takes the average of two numbers.\r
+<DT>\r
+We will make use of two new words, <B>:</B> ( "colon"), and <B>;</B> (\r
+"semicolon") . These words start and end a typical <I>Forth definition</I>.\r
+Enter:</DT>\r
+\r
+<UL>\r
+<PRE><TT>: AVERAGE ( a b -- avg ) + 2/ ;</TT></PRE>\r
+</UL>\r
+Congratulations. You have just written a Forth program. Let's look more\r
+closely at what just happened. The colon told Forth to add a new word to\r
+its list of words. This list is called the Forth dictionary. The name of\r
+the new word will be whatever name follows the colon. Any Forth words entered\r
+after the name will be compiled into the new word. This continues until\r
+the semicolon is reached which finishes the definition.\r
+\r
+<P>Let's test this word by entering:\r
+<UL>\r
+<PRE><TT>10 20 AVERAGE . ( should print 15 )</TT></PRE>\r
+</UL>\r
+Once a word has been defined, it can be used to define more words. Let's\r
+write a word that tests our word.. Enter:\r
+<UL>\r
+<PRE><TT>: TEST ( --) 50 60 AVERAGE . ;\r
+TEST</TT></PRE>\r
+</UL>\r
+Try combining some of the words you have learned into new Forth definitions\r
+of your choice. If you promise not to be overwhelmed, you can get a list\r
+of the words that are available for programming by entering:\r
+<UL>\r
+<PRE><TT>WORDS</TT></PRE>\r
+</UL>\r
+Don't worry, only a small fraction of these will be used directly in your\r
+programs.\r
+<H2>\r
+<A NAME="More Arithmetic"></A>More Arithmetic</H2>\r
+When you need to know the remainder of a divide operation. /MOD will return\r
+the remainder as well as the quotient. the word MOD will only return the\r
+remainder. Enter:\r
+<UL>\r
+<PRE><TT>0SP\r
+53 10 /MOD .S\r
+0SP\r
+7 5 MOD .S</TT></PRE>\r
+</UL>\r
+Two other handy words are <B>MIN</B> and <B>MAX</B> . They accept two numbers\r
+and return the MINimum or MAXimum value respectively. Try entering the\r
+following:\r
+<UL>\r
+<PRE><TT>56 34 MAX .\r
+56 34 MIN .\r
+-17 0 MIN .</TT></PRE>\r
+</UL>\r
+Some other useful words are:\r
+\r
+<P><B><TT>ABS ( n -- abs(n) , absolute value of n ) </TT></B>\r
+\r
+<P><B><TT>NEGATE ( n -- -n , negate value, faster then -1 * ) </TT></B>\r
+\r
+<P><B><TT>LSHIFT ( n c -- n<<c , left shift of n ) </TT></B>\r
+\r
+<P><B><TT>RSHIFT ( n c -- n>>c , logical right shift of n ) </TT></B>\r
+\r
+<P><B><TT>ARSHIFT ( n c -- n>>c ) , arithmetic right shift of n ) </TT></B>\r
+\r
+<P>ARSHIFT or LSHIFT can be used if you have to multiply quickly by a power\r
+of 2 . A right shift is like doing a divide by 2. This is often faster\r
+than doing a regular multiply or divide. Try entering:\r
+<UL>\r
+<PRE><TT>: 256* 8 LSHIFT ;\r
+3 256* .</TT></PRE>\r
+</UL>\r
+\r
+<H3>\r
+<A NAME="Arithmetic Overflow"></A>Arithmetic Overflow</H3>\r
+If you are having problems with your calculation overflowing the 32-bit\r
+precision of the stack, then you can use <B>*/</B> . This produces an intermediate\r
+result that is 64 bits long. Try the following three methods of doing the\r
+same calculation. Only the one using */ will yield the correct answer,\r
+5197799.\r
+<UL>\r
+<PRE><TT>34867312 99154 * 665134 / .\r
+34867312 665134 / 99154 * .\r
+34867312 99154 665134 */ .</TT></PRE>\r
+</UL>\r
+\r
+<H4>\r
+<A NAME="Convert Algebraic Expressions to Forth"></A>Convert Algebraic\r
+Expressions to Forth</H4>\r
+How do we express complex algebraic expressions in Forth? For example:\r
+20 + (3 * 4)\r
+\r
+<P>To convert this to Forth you must order the operations in the order\r
+of evaluation. In Forth, therefore, this would look like:\r
+<UL>\r
+<PRE><TT>3 4 * 20 +</TT></PRE>\r
+</UL>\r
+Evaluation proceeds from left to right in Forth so there is no ambiguity.\r
+Compare the following algebraic expressions and their Forth equivalents:\r
+(Do <B>not</B> enter these!)\r
+<UL>\r
+<PRE>(100+50)/2 ==> 100 50 + 2/\r
+((2*7) + (13*5)) ==> 2 7 * 13 5 * +</PRE>\r
+</UL>\r
+If any of these expressions puzzle you, try entering them one word at a\r
+time, while viewing the stack with .S .\r
+<H3>\r
+<A NAME="Problems - Square"></A>Problems:</H3>\r
+Convert the following algebraic expressions to their equivalent Forth expressions.\r
+(Do <B>not</B> enter these because they are not Forth code!)\r
+<UL>\r
+<PRE>(12 * ( 20 - 17 ))</PRE>\r
+\r
+<PRE>(1 - ( 4 * (-18) / 6) )</PRE>\r
+\r
+<PRE>( 6 * 13 ) - ( 4 * 2 * 7 )</PRE>\r
+</UL>\r
+Use the words you have learned to write these new words:\r
+<UL>\r
+<PRE><TT>SQUARE ( N -- N*N , calculate square )</TT></PRE>\r
+\r
+<PRE><TT>DIFF.SQUARES ( A B -- A*A-B*B , difference of squares )</TT></PRE>\r
+\r
+<PRE><TT>AVERAGE4 ( A B C D -- [A+B+C+D]/4 )</TT></PRE>\r
+\r
+<PRE>HMS>SECONDS ( HOURS MINUTES SECONDS -- TOTAL-SECONDS , convert )</PRE>\r
+</UL>\r
+<A HREF="#Answers to Problems">Answers to the problems</A> can be found\r
+at the end of this tutorial.\r
+<H2>\r
+<A NAME="Character Input and Output"></A>Character Input and Output</H2>\r
+The numbers on top of the stack can represent anything. The top number\r
+might be how many blue whales are left on Earth or your weight in kilograms.\r
+It can also be an ASCII character. Try entering the following:\r
+<UL>\r
+<PRE><TT>72 EMIT 105 EMIT</TT></PRE>\r
+</UL>\r
+You should see the word "Hi" appear before the OK. The 72 is an ASCII 'H'\r
+and 105 is an 'i'. EMIT takes the number on the stack and outputs it as\r
+a character. If you want to find the ASCII value for any character, you\r
+can use the word ASCII . Enter:\r
+<UL>\r
+<PRE><TT>CHAR W .\r
+CHAR % DUP . EMIT\r
+CHAR A DUP .\r
+32 + EMIT</TT></PRE>\r
+</UL>\r
+There is an ASCII chart in the back of this manual for a complete character\r
+list.\r
+\r
+<P>Notice that the word CHAR is a bit unusual because its input comes not\r
+from the stack, but from the following text. In a stack diagram, we represent\r
+that by putting the input in angle brackets, <input>. Here is the stack\r
+diagram for CHAR.\r
+\r
+<P><B><TT>CHAR ( <char> -- char , get ASCII value of a character ) </TT></B>\r
+\r
+<P>Using EMIT to output character strings would be very tedious. Luckily\r
+there is a better way. Enter:\r
+<UL>\r
+<PRE><TT>: TOFU ." Yummy bean curd!" ;\r
+TOFU</TT></PRE>\r
+</UL>\r
+The word <B>."</B> , pronounced "dot quote", will take everything up to\r
+the next quotation mark and print it to the screen. Make sure you leave\r
+a space after the first quotation mark. When you want to have text begin\r
+on a new line, you can issue a carriage return using the word <B>CR</B>\r
+. Enter:\r
+<UL>\r
+<PRE><TT>: SPROUTS ." Miniature vegetables." ;\r
+: MENU\r
+ CR TOFU CR SPROUTS CR\r
+;\r
+MENU</TT></PRE>\r
+</UL>\r
+You can emit a blank space with <B>SPACE</B> . A number of spaces can be\r
+output with SPACES . Enter:\r
+<UL>\r
+<PRE><TT>CR TOFU SPROUTS\r
+CR TOFU SPACE SPROUTS\r
+CR 10 SPACES TOFU CR 20 SPACES SPROUTS</TT></PRE>\r
+</UL>\r
+For character input, Forth uses the word <B>KEY</B> which corresponds to\r
+the word EMIT for output. KEY waits for the user to press a key then leaves\r
+its value on the stack. Try the following.\r
+<UL>\r
+<PRE><TT>: TESTKEY ( -- )\r
+ ." Hit a key: " KEY CR\r
+ ." That = " . CR\r
+;\r
+TESTKEY</TT></PRE>\r
+</UL>\r
+[Note: On some computers, the input if buffered so you will need to hit\r
+the ENTER key after typing your character.]\r
+\r
+<P><B><TT>EMIT ( char -- , output character ) </TT></B>\r
+\r
+<P><B><TT>KEY ( -- char , input character ) </TT></B>\r
+\r
+<P><B><TT>SPACE ( -- , output a space ) </TT></B>\r
+\r
+<P><B><TT>SPACES ( n -- , output n spaces ) </TT></B>\r
+\r
+<P><B><TT>CHAR ( <char> -- char , convert to ASCII ) </TT></B>\r
+\r
+<P><B><TT>CR ( -- , start new line , carriage return ) </TT></B>\r
+\r
+<P><B><TT>." ( -- , output " delimited text ) </TT></B>\r
+<H2>\r
+<BR>\r
+<BR>\r
+<A NAME="Compiling from Files"></A>Compiling from Files</H2>\r
+PForth can read read from ordinary text files so you can use any editor\r
+that you wish to write your programs.\r
+<H3>\r
+Sample Program</H3>\r
+Enter into your file, the following code.\r
+<UL>\r
+<PRE><TT>\ Sample Forth Code\r
+\ Author: <I>your name</I></TT></PRE>\r
+\r
+<PRE><TT>: SQUARE ( n -- n*n , square number )\r
+ DUP *\r
+;</TT></PRE>\r
+\r
+<PRE><TT>: TEST.SQUARE ( -- )\r
+ CR ." 7 squared = "\r
+ 7 SQUARE . CR\r
+;</TT></PRE>\r
+</UL>\r
+Now save the file to disk.\r
+\r
+<P>The text following the <B>\</B> character is treated as a comment. This\r
+would be a REM statement in BASIC or a /*---*/ in 'C'. The text in parentheses\r
+is also a comment.\r
+<H3>\r
+Using INCLUDE</H3>\r
+"INCLUDE" in Forth means to compile from a file.\r
+\r
+<P>You can compile this file using the INCLUDE command. If you saved your\r
+file as WORK:SAMPLE, then compile it by entering:\r
+<UL>\r
+<PRE><TT>INCLUDE SAMPLE.FTH</TT></PRE>\r
+</UL>\r
+Forth will compile your file and tell you how many bytes it has added to\r
+the dictionary. To test your word, enter:\r
+<UL>\r
+<PRE><TT>TEST.SQUARE</TT></PRE>\r
+</UL>\r
+Your two words, SQUARE and TEST.SQUARE are now in the Forth dictionary.\r
+We can now do something that is very unusual in a programming language.\r
+We can "uncompile" the code by telling Forth to <B>FORGET</B> it. Enter:\r
+<UL>\r
+<PRE><TT>FORGET SQUARE</TT></PRE>\r
+</UL>\r
+This removes SQUARE and everything that follows it, ie. TEST.SQUARE, from\r
+the dictionary. If you now try to execute TEST.SQUARE it won't be found.\r
+\r
+<P>Now let's make some changes to our file and reload it. Go back into\r
+the editor and make the following changes: (1) Change TEST.SQUARE to use\r
+15 instead of 7 then (2) Add this line right before the definition of SQUARE:\r
+<UL>\r
+<PRE><TT>ANEW TASK-SAMPLE.FTH</TT></PRE>\r
+</UL>\r
+Now Save your changes and go back to the Forth window.\r
+\r
+<P>You're probably wondering what the line starting with <B>ANEW</B> was\r
+for. ANEW is always used at the beginning of a file. It defines a special\r
+marker word in the dictionary before the code. The word typically has "TASK-"\r
+as a prefix followed by the name of the file. When you ReInclude a file,\r
+ANEW will automatically FORGET the old code starting after the ANEW statement.\r
+This allows you to Include a file over and over again without having to\r
+manually FORGET the first word. If the code was not forgotten, the dictionary\r
+would eventually fill up.\r
+\r
+<P>If you have a big project that needs lots of files, you can have a file\r
+that will load all the files you need. Sometimes you need some code to\r
+be loaded that may already be loaded. The word <B>INCLUDE?</B> will only\r
+load code if it isn't already in the dictionary. In this next example,\r
+I assume the file is on the volume WORK: and called SAMPLE. If not, please\r
+substitute the actual name. Enter:\r
+<UL>\r
+<PRE><TT>FORGET TASK-SAMPLE.FTH\r
+INCLUDE? SQUARE WORK:SAMPLE\r
+INCLUDE? SQUARE WORK:SAMPLE</TT></PRE>\r
+</UL>\r
+Only the first INCLUDE? will result in the file being loaded.\r
+<H2>\r
+<A NAME="Variables"></A>Variables</H2>\r
+Forth does not rely as heavily on the use of variables as other compiled\r
+languages. This is because values normally reside on the stack. There are\r
+situations, of course, where variables are required. To create a variable,\r
+use the word <B>VARIABLE</B> as follows:\r
+<UL>\r
+<PRE><TT>VARIABLE MY-VAR</TT></PRE>\r
+</UL>\r
+This created a variable named MY-VAR . A space in memory is now reserved\r
+to hold its 32-bit value. The word VARIABLE is what's known as a "defining\r
+word" since it creates new words in the dictionary. Now enter:\r
+<UL>\r
+<PRE><TT>MY-VAR .</TT></PRE>\r
+</UL>\r
+The number you see is the address, or location, of the memory that was\r
+reserved for MY-VAR. To store data into memory you use the word <B>!</B>\r
+, pronounced "store". It looks like an exclamation point, but to a Forth\r
+programmer it is the way to write 32-bit data to memory. To read the value\r
+contained in memory at a given address, use the Forth word <B>@</B> , pronounced\r
+"fetch". Try entering the following:\r
+<UL>\r
+<PRE><TT>513 MY-VAR !\r
+MY-VAR @ .</TT></PRE>\r
+</UL>\r
+This sets the variable MY-VAR to 513 , then reads the value back and prints\r
+it. The stack diagrams for these words follows:\r
+\r
+<P><B><TT>@ ( address -- value , FETCH value FROM address in memory ) </TT></B>\r
+\r
+<P><B><TT>! ( value address -- , STORE value TO address in memory )</TT></B>\r
+\r
+<P><B><TT>VARIABLE ( <name> -- , define a 4 byte memory storage location)</TT></B>\r
+\r
+<P>A handy word for checking the value of a variable is <B>? </B>, pronounced\r
+"question". Try entering:\r
+<UL>\r
+<PRE><TT>MY-VAR ?</TT></PRE>\r
+</UL>\r
+If ? wasn't defined, we could define it as:\r
+<UL>\r
+<PRE><TT>: ? ( address -- , look at variable )\r
+ @ .\r
+;</TT></PRE>\r
+</UL>\r
+Imagine you are writing a game and you want to keep track of the highest\r
+score. You could keep the highest score in a variable. When you reported\r
+a new score, you could check it aginst the highest score. Try entering\r
+this code in a file as described in the previous section:\r
+<UL>\r
+<PRE><TT>VARIABLE HIGH-SCORE</TT></PRE>\r
+\r
+<PRE><TT>: REPORT.SCORE ( score -- , print out score )\r
+ DUP CR ." Your Score = " . CR\r
+ HIGH-SCORE @ MAX ( calculate new high )\r
+ DUP ." Highest Score = " . CR\r
+ HIGH-SCORE ! ( update variable )\r
+;</TT></PRE>\r
+</UL>\r
+Save the file to disk, then compile this code using the INCLUDE word. Test\r
+your word as follows:\r
+<UL>\r
+<PRE><TT>123 REPORT.SCORE\r
+9845 REPORT.SCORE\r
+534 REPORT.SCORE</TT></PRE>\r
+</UL>\r
+The Forth words @ and ! work on 32-bit quantities. Some Forths are "16-bit"\r
+Forths. They fetch and store 16-bit quantities. Forth has some words that\r
+will work on 8 and 16-bit values. C@ and C! work characters which are usually\r
+for 8-bit bytes. The 'C' stands for "Character" since ASCII characters\r
+are 8-bit numbers. Use W@ and W! for 16-bit "Words."\r
+\r
+<P>Another useful word is <B>+!</B> , pronounced "plus store." It adds\r
+a value to a 32-bit value in memory. Try:\r
+<UL>\r
+<PRE><TT>20 MY-VAR !\r
+5 MY-VAR +!\r
+MY-VAR @ .</TT></PRE>\r
+</UL>\r
+Forth also provides some other words that are similar to VARIABLE. Look\r
+in the glossary for VALUE and ARRAY. Also look at the section on "<A HREF="pf_ref.htm#Local Variables { foo --}?">local\r
+variables</A>" which are variables which only exist on the stack while\r
+a Forth word is executing.\r
+\r
+<P><I>A word of warning about fetching and storing to memory</I>: You have\r
+now learned enough about Forth to be dangerous. The operation of a computer\r
+is based on having the right numbers in the right place in memory. You\r
+now know how to write new numbers to any place in memory. Since an address\r
+is just a number, you could, but shouldn't, enter:\r
+<UL>\r
+<PRE><TT>73 253000 ! ( Do NOT do this. )</TT></PRE>\r
+</UL>\r
+The 253000 would be treated as an address and you would set that memory\r
+location to 73. I have no idea what will happen after that, maybe nothing.\r
+This would be like firing a rifle through the walls of your apartment building.\r
+You don't know who or what you are going to hit. Since you share memory\r
+with other programs including the operating system, you could easily cause\r
+the computer to behave strangely, even crash. Don't let this bother you\r
+too much, however. Crashing a computer, unlike crashing a car, does not\r
+hurt the computer. You just have to reboot. The worst that could happen\r
+is that if you crash while the computer is writing to a disk, you could\r
+lose a file. That's why we make backups. This same potential problem exists\r
+in any powerful language, not just Forth. This might be less likely in\r
+BASIC, however, because BASIC protects you from a lot of things, including\r
+the danger of writing powerful programs.\r
+\r
+<P>Another way to get into trouble is to do what's called an "odd address\r
+memory access." The 68000 processor arranges words and longwords, 16 and\r
+32 bit numbers, on even addresses. If you do a <B>@</B> or <B>!</B> , or\r
+<B>W@</B> or <B>W!</B> , to an odd address, the 68000 processor will take\r
+exception to this and try to abort.\r
+\r
+<P>Forth gives you some protection from this by trapping this exception\r
+and returning you to the OK prompt. If you really need to access data on\r
+an odd address, check out the words <B>ODD@</B> and <B>ODD!</B> in the\r
+glossary. <B>C@</B> and <B>C!</B> work fine on both odd and even addresses.\r
+<H2>\r
+<A NAME="Constants"></A>Constants</H2>\r
+If you have a number that is appearing often in your program, we recommend\r
+that you define it as a "constant." Enter:\r
+<UL>\r
+<PRE><TT>128 CONSTANT MAX_CHARS\r
+MAX_CHARS .</TT></PRE>\r
+</UL>\r
+We just defined a word called MAX_CHARS that returns the value on the stack\r
+when it was defined. It cannot be changed unless you edit the program and\r
+recompile. Using <B>CONSTANT</B> can improve the readability of your programs\r
+and reduce some bugs. Imagine if you refer to the number 128 very often\r
+in your program, say 8 times. Then you decide to change this number to\r
+256. If you globally change 128 to 256 you might change something you didn't\r
+intend to. If you change it by hand you might miss one, especially if your\r
+program occupies more than one file. Using CONSTANT will make it easy to\r
+change. The code that results is equally as fast and small as putting the\r
+numbers in directly. I recommend defining a constant for almost any number.\r
+<H2>\r
+<A NAME="Logical Operators"></A>Logical Operators</H2>\r
+These next two sections are concerned with decision making. This first\r
+section deals with answering questions like "Is this value too large?"\r
+or "Does the guess match the answer?". The answers to questions like these\r
+are either TRUE or FALSE. Forth uses a 0 to represent <B>FALSE</B> and\r
+a -1 to represent <B>TRUE</B>. TRUE and FALSE have been capitalized because\r
+they have been defined as Forth constants. Try entering:\r
+<UL>\r
+<PRE><TT>23 71 = .\r
+18 18 = .</TT></PRE>\r
+</UL>\r
+You will notice that the first line printed a 0, or FALSE, and the second\r
+line a -1, or TRUE. The equal sign in Forth is used as a question, not\r
+a statement. It asks whether the top two items on the stack are equal.\r
+It does not set them equal. There are other questions that you can ask.\r
+Enter:\r
+<UL>\r
+<PRE><TT>23 198 < .\r
+23 198 > .\r
+254 15 > .</TT></PRE>\r
+</UL>\r
+In California, the drinking age for alcohol is 21. You could write a simple\r
+word now to help bartenders. Enter:\r
+<UL>\r
+<PRE><TT>: DRINK? ( age -- flag , can this person drink? )\r
+ 20 >\r
+;</TT></PRE>\r
+\r
+<PRE><TT>20 DRINK? .\r
+21 DRINK? .\r
+43 DRINK? .</TT></PRE>\r
+</UL>\r
+The word FLAG in the stack diagram above refers to a logical value.\r
+\r
+<P>Forth provides special words for comparing a number to 0. They are <B>0=</B>\r
+<B>0></B> and <B>0<</B> . Using 0> is faster than calling 0 and > separately.\r
+Enter:\r
+<UL><TT>23 0> . ( print -1 )</TT>\r
+<BR><TT>-23 0> . ( print 0 )</TT>\r
+<BR><TT>23 0= . ( print 0 )</TT></UL>\r
+For more complex decisions, you can use the <I>Boolean</I> operators <B>OR</B>\r
+, <B>AND</B> , and <B>NOT</B> . OR returns a TRUE if either one or both\r
+of the top two stack items are true.\r
+<UL>\r
+<PRE><TT>TRUE TRUE OR .\r
+TRUE FALSE OR .\r
+FALSE FALSE OR .</TT></PRE>\r
+</UL>\r
+AND only returns a TRUE if both of them are true.\r
+<UL>\r
+<PRE><TT>TRUE TRUE AND .\r
+TRUE FALSE AND .</TT></PRE>\r
+</UL>\r
+NOT reverses the value of the flag on the stack. Enter:\r
+<UL>\r
+<PRE><TT>TRUE .\r
+TRUE NOT .</TT></PRE>\r
+</UL>\r
+Logical operators can be combined.\r
+<UL>\r
+<PRE><TT>56 3 > 56 123 < AND .\r
+23 45 = 23 23 = OR .</TT></PRE>\r
+</UL>\r
+Here are stack diagrams for some of these words. See the glossary for a\r
+more complete list.\r
+\r
+<P><B><TT>< ( a b -- flag , flag is true if A is less than B )</TT></B>\r
+\r
+<P><B><TT>> ( a b -- flag , flag is true if A is greater than B )</TT></B>\r
+\r
+<P><B><TT>= ( a b -- flag , flag is true if A is equal to B )</TT></B>\r
+\r
+<P><B><TT>0= ( a -- flag , true if a equals zero )</TT></B>\r
+\r
+<P><B><TT>OR ( a b -- a||b , perform logical OR of bits in A and B )</TT></B>\r
+\r
+<P><B><TT>AND ( a b -- a&b , perform logical AND of bits in A and B\r
+)</TT></B>\r
+\r
+<P><B><TT>NOT ( flag -- opposite-flag , true if false, false if true )</TT></B>\r
+<H3>\r
+<A NAME="Problems - Logical"></A>Problems:</H3>\r
+1) Write a word called LOWERCASE? that returns TRUE if the number on top\r
+of the stack is an ASCII lowercase character. An ASCII 'a' is 97 . An ASCII\r
+'z' is 122 . Test using the characters " A ` a q z { ".\r
+<UL>\r
+<PRE><TT>CHAR A LOWERCASE? . ( should print 0 )\r
+CHAR a LOWERCASE? . ( should print -1 )</TT></PRE>\r
+</UL>\r
+<A HREF="#Answers to Problems">Answers to the problems</A> can be found\r
+at the end of this tutorial.\r
+<H2>\r
+<A NAME="Conditionals - IF ELSE THEN CASE"></A>Conditionals - IF ELSE THEN\r
+CASE</H2>\r
+You will now use the TRUE and FALSE flags you learned to generate in the\r
+last section. The "flow of control" words accept flags from the stack,\r
+and then possibly "branch" depending on the value. Enter the following\r
+code.\r
+<UL>\r
+<PRE><TT>: .L ( flag -- , print logical value )\r
+ IF ." True value on stack!"\r
+ ELSE ." False value on stack!"\r
+ THEN\r
+;</TT></PRE>\r
+\r
+<PRE><TT>0 .L\r
+FALSE .L\r
+TRUE .L\r
+23 7 < .L</TT></PRE>\r
+</UL>\r
+You can see that when a TRUE was on the stack, the first part got executed.\r
+If a FALSE was on the stack, then the first part was skipped, and the second\r
+part was executed. One thing you will find interesting is that if you enter:\r
+<UL>\r
+<PRE><TT>23 .L</TT></PRE>\r
+</UL>\r
+the value on the stack will be treated as true. The flow of control words\r
+consider any value that does not equal zero to be TRUE.\r
+\r
+<P>The <B>ELSE</B> word is optional in the <B>IF...THEN</B> construct.\r
+Try the following:\r
+<UL>\r
+<PRE><TT>: BIGBUCKS? ( ammount -- )\r
+ 1000 >\r
+ IF ." That's TOO expensive!"\r
+ THEN\r
+;</TT></PRE>\r
+\r
+<PRE><TT>531 BIGBUCKS?\r
+1021 BIGBUCKS?</TT></PRE>\r
+</UL>\r
+Many Forths also support a <B>CASE</B> statement similar to switch() in\r
+'C'. Enter:\r
+<UL>\r
+<PRE><TT>: TESTCASE ( N -- , respond appropriately )\r
+ CASE\r
+ 0 OF ." Just a zero!" ENDOF\r
+ 1 OF ." All is ONE!" ENDOF\r
+ 2 OF WORDS ENDOF\r
+ DUP . ." Invalid Input!"\r
+ ENDCASE CR\r
+;</TT></PRE>\r
+\r
+<PRE><TT>0 TESTCASE\r
+1 TESTCASE\r
+</TT>5 TESTCASE</PRE>\r
+</UL>\r
+See CASE in the glossary for more information.\r
+<H3>\r
+<A NAME="Problems - Conditionals"></A>Problems:</H3>\r
+1) Write a word called DEDUCT that subtracts a value from a variable containing\r
+your checking account balance. Assume the balance is in dollars. Print\r
+the balance. Print a warning if the balance is negative.\r
+<UL>\r
+<PRE><TT>VARIABLE ACCOUNT</TT></PRE>\r
+\r
+<PRE><TT>: DEDUCT ( n -- , subtract N from balance )\r
+ ????????????????????????????????? ( you fill this in )\r
+;</TT></PRE>\r
+\r
+<PRE><TT>300 ACCOUNT ! ( initial funds )\r
+40 DEDUCT ( prints 260 )\r
+200 DEDUCT ( print 60 )\r
+100 DEDUCT ( print -40 and give warning! )</TT></PRE>\r
+</UL>\r
+<A HREF="#Answers to Problems">Answers to the problems</A> can be found\r
+at the end of this tutorial.\r
+<H2>\r
+<A NAME="Loops"></A>Loops</H2>\r
+Another useful pair of words is <B>BEGIN...UNTIL</B> . These are used to\r
+loop until a given condition is true. Try this:\r
+<UL>\r
+<PRE><TT>: COUNTDOWN ( N -- )\r
+ BEGIN\r
+ DUP . CR ( print number on top of stack )\r
+ 1- DUP 0< ( loop until we go negative )\r
+ UNTIL\r
+;</TT></PRE>\r
+\r
+<PRE><TT>16 COUNTDOWN</TT></PRE>\r
+</UL>\r
+This word will count down from N to zero.\r
+\r
+<P>If you know how many times you want a loop to execute, you can use the\r
+<B>DO...LOOP</B> construct. Enter:\r
+<UL>\r
+<PRE><TT>: SPELL\r
+ ." ba"\r
+ 4 0 DO\r
+ ." na"\r
+ LOOP\r
+;</TT></PRE>\r
+</UL>\r
+This will print "ba" followed by four occurrences of "na". The ending value\r
+is placed on the stack before the beginning value. Be careful that you\r
+don't pass the values in reverse. Forth will go "the long way around" which\r
+could take awhile. The reason for this order is to make it easier to pass\r
+the loop count into a word on the stack. Consider the following word for\r
+doing character graphics. Enter:\r
+<UL>\r
+<PRE><TT>: PLOT# ( n -- )\r
+ 0 DO\r
+ [CHAR] - EMIT\r
+ LOOP CR\r
+;</TT></PRE>\r
+\r
+<PRE><TT>CR 9 PLOT# 37 PLOT#</TT></PRE>\r
+</UL>\r
+If you want to access the loop counter you can use the word I . Here is\r
+a simple word that dumps numbers and their associated ASCII characters.\r
+<UL>\r
+<PRE><TT>: .ASCII ( end start -- , dump characters )\r
+ DO\r
+ CR I . I EMIT\r
+ LOOP CR\r
+;</TT></PRE>\r
+\r
+<PRE><TT>80 64 .ASCII</TT></PRE>\r
+</UL>\r
+If you want to leave a DO LOOP before it finishes, you can use the word\r
+<B>LEAVE</B>. Enter:\r
+<UL>\r
+<PRE><TT>: TEST.LEAVE ( -- , show use of leave )\r
+ 100 0\r
+ DO\r
+ I . CR \ print loop index\r
+ I 20 > \ is I over 20\r
+ IF\r
+ LEAVE\r
+ THEN\r
+ LOOP\r
+;\r
+TEST.LEAVE \ will print 0 to 20</TT></PRE>\r
+</UL>\r
+Please consult the manual to learn about the following words <B>+LOOP</B>\r
+and <B>RETURN</B> . FIXME\r
+\r
+<P>Another useful looping construct is the <B>BEGIN WHILE REPEAT</B> loop.\r
+This allows you to make a test each time through the loop before you actually\r
+do something. The word WHILE will continue looping if the flag on the stack\r
+is True. Enter:\r
+<UL>\r
+<PRE><TT>: SUM.OF.N ( N -- SUM[N] , calculate sum of N integers )\r
+ 0 \ starting value of SUM\r
+ BEGIN\r
+ OVER 0> \ Is N greater than zero?\r
+ WHILE\r
+ OVER + \ add N to sum\r
+ SWAP 1- SWAP \ decrement N\r
+ REPEAT\r
+ SWAP DROP \ get rid on N\r
+;</TT></PRE>\r
+\r
+<PRE><TT>4 SUM.OF.N \ prints 10 ( 1+2+3+4 )</TT></PRE>\r
+</UL>\r
+\r
+<H3>\r
+<A NAME="Problems - Loops"></A>Problems:</H3>\r
+1) Rewrite SUM.OF.N using a DO LOOP.\r
+\r
+<P>2) Rewrite SUM.OF.N using BEGIN UNTIL.\r
+\r
+<P>3) For bonus points, write SUM.OF.N without using any looping or conditional\r
+construct!\r
+\r
+<P><A HREF="#Answers to Problems">Answers to the problems</A> can be found\r
+at the end of this tutorial.\r
+<H2>\r
+<A NAME="Text Input and Output"></A>Text Input and Output</H2>\r
+You learned earlier how to do single character I/O. This section concentrates\r
+on using strings of characters. You can embed a text string in your program\r
+using S". Note that you must follow the S" by one space. The text string\r
+is terminated by an ending " .Enter:\r
+<UL>\r
+<PRE>: TEST S" Hello world!" ;\r
+TEST .S</PRE>\r
+</UL>\r
+Note that TEST leaves two numbers on the stack. The first number is the\r
+address of the first character. The second number is the number of characters\r
+in the string. You can print the characters of the string as follows.\r
+<UL>\r
+<PRE>TEST DROP \ get rid of number of characters\r
+DUP C@ EMIT \ prints first character, 'H'\r
+CHAR+ DUP C@ EMIT \ prints second character, 'e'\r
+\ and so on</PRE>\r
+</UL>\r
+CHAR+ advances the address to the next character. You can print the entire\r
+string using TYPE.\r
+<UL>\r
+<PRE>TEST TYPE\r
+TEST 2/ TYPE \ print half of string</PRE>\r
+</UL>\r
+It would be nice if we could simply use a single address to describe a\r
+string and not have to pass the number of characters around. 'C' does this\r
+by putting a zero at the end of the string to show when it ends. Forth\r
+has a different solution. A text string in Forth consists of a character\r
+count in the first byte, followed immediately by the characters themselves.\r
+This type of character string can be created using the Forth word C" ,\r
+pronounced 'c quote'. Enter:\r
+<UL>\r
+<PRE><TT>: T2 C" Greetings Fred" ;\r
+T2 .</TT></PRE>\r
+</UL>\r
+The number that was printed was the address of the start of the string.\r
+It should be a byte that contains the number of characters. Now enter:\r
+<UL>\r
+<PRE><TT>T2 C@ .</TT></PRE>\r
+</UL>\r
+You should see a 14 printed. Remember that C@ fetches one character/byte\r
+at the address on the stack. You can convert a counted Forth string to\r
+an address and count using COUNT.\r
+<UL>\r
+<PRE><TT>T2 COUNT .S\r
+TYPE</TT></PRE>\r
+</UL>\r
+The word <B>COUNT</B> extracts the number of characters and their starting\r
+address. COUNT will only work with strings of less than 256 characters,\r
+since 255 is the largest number that can be stored in the count byte. TYPE\r
+will, however, work with longer strings since the length is on the stack.\r
+Their stack diagrams follow:\r
+\r
+<P><B><TT>CHAR+ ( address -- address' , add the size of one character )</TT></B>\r
+\r
+<P><B><TT>COUNT ( $addr -- addr #bytes , extract string information ) </TT></B>\r
+\r
+<P><B><TT>TYPE ( addr #bytes -- , output characters at addr )</TT></B>\r
+\r
+<P>The $addr is the address of a count byte. The dollar sign is often used\r
+to mark words that relate to strings.\r
+\r
+<P>You can easily input a string using the word <B>ACCEPT</B>. (You may\r
+want to put these upcoming examples in a file since they are very handy.)\r
+The word <B>ACCEPT </B>receives characters from the keyboard and places\r
+them at any specified address. <B>ACCEPT </B>takes input characters until\r
+a maximum is reached or an end of line character is entered. <B>ACCEPT\r
+</B>returns the number of characters entered. You can write a word for\r
+entering text. Enter:\r
+<UL>\r
+<PRE><TT>: INPUT$ ( -- $addr )\r
+ PAD 1+ ( leave room for byte count )\r
+ 127 ACCEPT ( recieve a maximum of 127 chars )\r
+ PAD C! ( set byte count )\r
+ PAD ( return address of string )\r
+;</TT></PRE>\r
+\r
+<PRE><TT>INPUT$ COUNT TYPE</TT></PRE>\r
+</UL>\r
+Enter a string which should then be echoed. You could use this in a program\r
+that writes form letters.\r
+<UL>\r
+<PRE><TT>: FORM.LETTER ( -- )\r
+ ." Enter customer's name." CR\r
+ INPUT$\r
+ CR ." Dear " DUP COUNT TYPE CR\r
+ ." Your cup that says " COUNT TYPE\r
+ ." is in the mail!" CR\r
+;</TT></PRE>\r
+</UL>\r
+<B><TT>ACCEPT ( addr maxbytes -- numbytes , input text, save at address\r
+) </TT></B>\r
+\r
+<P>You can use your word INPUT$ to write a word that will read a number\r
+from the keyboard. Enter:\r
+<UL>\r
+<PRE><TT>: INPUT# ( -- N true | false )\r
+ INPUT$ ( get string )\r
+ NUMBER? ( convert to a string if valid )\r
+ IF DROP TRUE ( get rid of high cell )\r
+ ELSE FALSE\r
+ THEN\r
+;</TT></PRE>\r
+</UL>\r
+This word will return a single-precision number and a TRUE, or it will\r
+just return FALSE. The word <B>NUMBER?</B> returns a double precision number\r
+if the input string contains a valid number. Double precision numbers are\r
+64-bit so we DROP the top 32 bits to get a single-precision 32 bit number.\r
+<H2>\r
+<A NAME="Changing Numeric Base"></A>Changing Numeric Base</H2>\r
+Our numbering system is decimal, or "base 10." This means that a number\r
+like 527 is equal to (5*100 + 2*10 + 7*1). The use of 10 for the numeric\r
+base is a completely arbitrary decision. It no doubt has something to do\r
+with the fact that most people have 10 fingers (including thumbs). The\r
+Babylonians used base 60, which is where we got saddled with the concept\r
+of 60 minutes in an hour. Computer hardware uses base 2, or "binary". A\r
+computer number like 1101 is equal to (1*8 + 1*4 + 0*2 + 1*1). If you add\r
+these up, you get 8+4+1=13 . A 10 in binary is (1*2 + 0*1), or 2. Likewise\r
+10 in any base N is N .\r
+\r
+<P>Forth makes it very easy to explore different numeric bases because\r
+it can work in any base. Try entering the following:\r
+<UL>\r
+<PRE><TT>DECIMAL 6 BINARY .\r
+1 1 + .\r
+1101 DECIMAL .</TT></PRE>\r
+</UL>\r
+Another useful numeric base is <I>hexadecimal</I>. which is base 16. One\r
+problem with bases over 10 is that our normal numbering system only has\r
+digits 0 to 9. For hex numbers we use the letters A to F for the digits\r
+10 to 15. Thus the hex number 3E7 is equal to (3*256 + 14*16 + 7*1). Try\r
+entering:\r
+<UL>\r
+<PRE><TT>DECIMAL 12 HEX . \ print C\r
+DECIMAL 12 256 * 7 16 * + 10 + .S\r
+DUP BINARY .\r
+HEX .</TT></PRE>\r
+</UL>\r
+A variable called <B>BASE</B> is used to keep track of the current numeric\r
+base. The words HEX , <B>DECIMAL</B> , and <B>BINARY</B> work by changing\r
+this variable. You can change the base to anything you want. Try:\r
+<UL>\r
+<PRE><TT>7 BASE !\r
+6 1 + .\r
+BASE @ . \ surprise!</TT></PRE>\r
+</UL>\r
+You are now in base 7 . When you fetched and printed the value of BASE,\r
+it said 10 because 7, in base 7, is 10.\r
+\r
+<P>PForth defines a word called .HEX that prints a number as hexadecimal\r
+regardless of the current base.\r
+<UL>\r
+<PRE>DECIMAL 14 .HEX</PRE>\r
+</UL>\r
+You could define a word like .HEX for any base. What is needed is a way\r
+to temporarily set the base while a number is printed, then restore it\r
+when we are through. Try the following word:\r
+<UL>\r
+<PRE><TT>: .BIN ( N -- , print N in Binary )\r
+ BASE @ ( save current base )\r
+ 2 BASE ! ( set to binary )\r
+ SWAP . ( print number )\r
+ BASE ! ( restore base )\r
+;</TT></PRE>\r
+\r
+<PRE><TT>DECIMAL\r
+22 .BIN\r
+22 .</TT></PRE>\r
+</UL>\r
+\r
+<H2>\r
+<A NAME="Answers to Problems"></A>Answers to Problems</H2>\r
+If your answer doesn't exactly match these but it works, don't fret. In\r
+Forth, there are usually many ways to the same thing.\r
+<H3>\r
+<A HREF="#Problems - Stack">Stack Manipulations</A></H3>\r
+\r
+<UL>\r
+<PRE><TT>1) SWAP DUP\r
+2) ROT DROP\r
+3) ROT DUP 3 PICK\r
+4) SWAP OVER 3 PICK\r
+5) -ROT 2DUP</TT></PRE>\r
+</UL>\r
+\r
+<H3>\r
+<A HREF="#Problems - Square">Arithmetic</A></H3>\r
+\r
+<UL>\r
+<PRE>(12 * (20 - 17)) ==> <TT>20 17 - 12 *\r
+</TT>(1 - (4 * (-18) / 6)) ==> <TT>1 4 -18 * 6 / -\r
+</TT>(6 * 13) - (4 * 2 * 7) ==> <TT>6 13 * 4 2 * 7 * -</TT></PRE>\r
+\r
+<PRE><TT>: SQUARE ( N -- N*N ) \r
+ DUP *\r
+;</TT></PRE>\r
+\r
+<PRE><TT>: DIFF.SQUARES ( A B -- A*A-B*B )\r
+SWAP SQUARE \r
+SWAP SQUARE - \r
+;</TT></PRE>\r
+\r
+<PRE><TT>: AVERAGE4 ( A B C D -- [A+B+C+D]/4 )\r
+ + + + ( add'em up )\r
+ -2 ashift ( divide by four the fast way, or 4 / )\r
+;</TT></PRE>\r
+\r
+<DT>\r
+<TT>: HMS>SECONDS ( HOURS MINUTES SECONDS -- TOTAL-SECONDS )</TT></DT>\r
+\r
+<BR><TT> -ROT SWAP ( -- seconds minutes hours )</TT>\r
+<BR><TT> 60 * + ( -- seconds total-minutes )</TT>\r
+<BR><TT> 60 * + ( -- seconds )</TT>\r
+<BR><TT>; </TT></UL>\r
+\r
+<H3>\r
+<A HREF="#Problems - Logical">Logical Operators</A></H3>\r
+\r
+<UL>\r
+<PRE><TT>: LOWERCASE? ( CHAR -- FLAG , true if lowercase )\r
+ DUP 123 <\r
+ SWAP 96 > AND\r
+;</TT></PRE>\r
+</UL>\r
+\r
+<H3>\r
+<A HREF="#Problems - Conditionals">Conditionals</A></H3>\r
+\r
+<UL>\r
+<PRE><TT>: DEDUCT ( n -- , subtract from account )\r
+ ACCOUNT @ ( -- n acc \r
+ SWAP - DUP ACCOUNT ! ( -- acc' , update variable )\r
+ ." Balance = $" DUP . CR ( -- acc' )\r
+ 0< ( are we broke? )\r
+ IF ." Warning!! Your account is overdrawn!" CR\r
+ THEN\r
+;</TT></PRE>\r
+</UL>\r
+\r
+<H3>\r
+<TT><A HREF="#Problems - Loops">Loops</A></TT></H3>\r
+\r
+<UL>\r
+<PRE><TT>: SUM.OF.N.1 ( N -- SUM[N] )\r
+ 0 SWAP \ starting value of SUM\r
+ 1+ 0 \ set indices for DO LOOP\r
+ ?DO \ safer than DO if N=0\r
+ I +\r
+ LOOP\r
+;</TT></PRE>\r
+\r
+<PRE><TT>: SUM.OF.N.2 ( N -- SUM[N] )\r
+ 0 \ starting value of SUM\r
+ BEGIN ( -- N' SUM )\r
+ OVER +\r
+ SWAP 1- SWAP\r
+ OVER 0<\r
+ UNTIL\r
+ SWAP DROP\r
+;</TT></PRE>\r
+\r
+<PRE><TT>: SUM.OF.N.3 ( NUM -- SUM[N] , Gauss' method )\r
+ DUP 1+ \ SUM(N) = N*(N+1)/2\r
+ * 2/\r
+;</TT></PRE>\r
+</UL>\r
+Back to <A HREF="pforth.html">pForth Home Page</A>\r
+</BODY>\r
+</HTML>\r