home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 5 / DATAFILE_PDCD5.iso / utilities / f / forthmac / !Forthmacs / docs / html / tutorial < prev    next >
Encoding:
Text File  |  1997-05-01  |  34.6 KB  |  766 lines

  1. <!-- Forthmacs Formatter generated HTML V.2 output -->
  2. <html>
  3. <head>
  4. <title>Forth Tutorial</title>
  5. </head>
  6. <body>
  7. <h1>Forth Tutorial</h1>
  8. <hr>
  9. <p>
  10. <p>
  11. This chapter is a brief tutorial about the Forth language.  It will get you 
  12. started with Forth, but you should probably buy a Forth book to learn more.  
  13. <p>
  14. If you already know how to program in Forth, you may skip this chapter.  You may 
  15. want to look at the chapter "Glossary Functional Index".  
  16. <p>
  17. <p>
  18. Forth is a complete programming language with some unique features.  In fact, it 
  19. is probably unlike any other language you have ever used.  Please don't let it's 
  20. "strangeness" cause you to immediately reject it --- once you get used to it, 
  21. you may find that you can use Forth to write working programs faster than you 
  22. ever dreamed possible.  
  23. <p>
  24. Forth is often described as an assembler, compiler, operating system, editor, 
  25. and command language all rolled into one.  In addition, most of the Forth system 
  26. is written in Forth.  
  27. <p>
  28. To find out more about your RISC OS Forthmacs system try 
  29. <p><pre>  words</pre><p>
  30. <p><pre>  see words</pre><p>
  31. <p><pre>  whatis words</pre><p>
  32. or others.  
  33. <p>
  34. <p>
  35. <h2>Getting Started</h2>
  36. <p>
  37. If you sit down to a computer running Forth, you'll probably see the word <code><A href="_smal_AU#284">ok</A></code> 
  38. right before the cursor.  <code><A href="_smal_AU#284">ok</A></code> is the 
  39. "prompt".  It means that Forth is ready for you to type something.  Suppose you 
  40. type 
  41. <p>
  42. <p><pre>1 2 + .</pre><p>
  43. <p>
  44. Always type the cr, Return, lf, Linefeed, or whatever equivalent key your 
  45. terminal has, at the end of the line.  Forth will respond with 
  46. <p>
  47. <p><pre>3</pre><p>
  48. <p>
  49. You have just added 1 and 2, and printed the result.  
  50. <p>
  51. I am going to assume at this point that you understand the concept of a stack.  
  52. Forth uses stacks heavily.  In fact, the consistent stack orientation is the key 
  53. to Forth's ability to pack a lot of capability in a small amount of memory.  
  54. <p>
  55. Going back to our example, typing "1" caused the number 1 to be pushed onto 
  56. Forth's main stack, which is called the data stack.  Typing "2" caused the 
  57. number 2 to be pushed onto the same stack, on top of the 1.  The "+" caused two 
  58. numbers to be popped off the stack, in this case 1 and 2.  The numbers were 
  59. added together and the result was put back on the stack.  The <code>"<A href="_smal_AO#CE">."</A></code> 
  60. caused a number to be popped off the stack, in this case 3, and printed on the 
  61. terminal.  
  62. <p>
  63. If you have an HP calculator, no doubt this sounds very familiar to you.  An 
  64. important differences is that HP calculators have a stack that is 4 numbers 
  65. deep, whereas Forth's stack is much larger, typically more than 64 numbers.  In 
  66. RISC OS Forthmacs this is <code><A href="_smal_BU#29C">ps-size</A></code> 
  67. divided by the cell size.  
  68. <p>
  69. Other arithmetic operators that Forth knows about are - (minus), * (times), and 
  70. / (divide), as well a some others that we'll worry about later.  The arithmetic 
  71. is performed as 32-bit integer arithmetic, although there are operators which 
  72. will cope with other kinds of numbers.  
  73. <p>
  74. <p>
  75. <h2>Defining your own words</h2>
  76. <p>
  77. A Forth system understands a number of "words", each of which causes something 
  78. to happen, usually to the stack.  In our example, "+" and <code>"<A href="_smal_AO#CE">."</A></code> 
  79. were both words.  You can define your own words in terms of words the system 
  80. already knows.  Once defined, your words may be used just as though they they 
  81. were system words.  Another example: 
  82. <p>
  83. <p><pre>: addprint   + .   ;</pre><p>
  84. <p>
  85. Here, the ":", which is a system word, causes a new word to be defined, in this 
  86. case addprint.  The definition of addprint is (B + .  ), which means that when 
  87. you execute addprint, two numbers will be taken from the stack and the sum 
  88. printed.  The ;, another system word, terminates the definition.  If you were to 
  89. later type 
  90. <p>
  91. <p><pre>23 45 addprint</pre><p>
  92. <p>
  93. Forth would respond with 
  94. <p>
  95. <p><pre>68</pre><p>
  96. <p>
  97. A definition of this sort is called a "colon definition".  A distinguishing 
  98. characteristic is that the new word is defined in terms of other Forth words.  
  99. It is also possible to define a word in terms of the assembly language of the 
  100. machine you are actually running on.  This kind of definition is called a "code 
  101. definition", and is not used nearly as often as colon definitions.  
  102. <p>
  103. If you wished to later use addprint in the definition of another word, you could 
  104. do so just as though addprint were a system-supplied word.  
  105. <p>
  106. <p><pre>: addprint2 addprint addprint ;</pre><p>
  107. <p><pre>1 2 3 4  addprint2</pre><p>
  108. <p>
  109. would result in 
  110. <p>
  111. <p><pre>7 3</pre><p>
  112. <p>
  113. Note the order in which the numbers were added.  The reason is that, when 
  114. addprint2 is executed, 4 is on top of the stack, with 3 underneath it.  The 
  115. first addition will thus be 3+4.  
  116. <p>
  117. It is important to keep track of what is on the stack when you are writing Forth 
  118. programs.  An essential part of the documentation of a Forth word is a stack 
  119. diagram.  A stack diagram shows what the word expects to be on the stack when it 
  120. starts executing, and what it leaves on the stack after it is finished.  The 
  121. stack diagram for addprint would be 
  122. <p>
  123. <p><pre>( n1 n2 -- sum )</pre><p>
  124. <p>
  125. showing that two numbers ( n1 and n2 ) are expected to be on the stack at the 
  126. start, and that addprint leaves one number on the stack ( sum ) when it is 
  127. finished.  The "--" shows where the word executes, or, in other words, it 
  128. separates the input parameters from the output parameters.  
  129. <p>
  130. Stack diagrams are enclosed in parentheses, because parentheses are used in 
  131. Forth to enclose comments.  The Forth system will ignore everything between "(" 
  132. and the next ")".  The space between "(" and "n1" is necessary.  The space 
  133. between "sum" and ")" is optional in most Forth's, but it is a good idea to 
  134. include it anyway.  
  135. <p>
  136. By convention, the rightmost number (n2) is the one that is on top of the stack.  
  137. Thus ( a b c -- d e f ) would signify a word which expected c on top of the 
  138. stack, b under c, and a under b.  After execution, f would be on top, with e 
  139. under f, and d under e.  
  140. <p>
  141. <p>
  142. <h2>Variables, @, !</h2>
  143. <p>
  144. <p>
  145. <p><pre>variable  john ( -- adr )</pre><p>
  146. <p>
  147. defines a variable called john and allocates one 32-bit machines word for it.  
  148. The stack diagram shows that when john is executed, an address will be left on 
  149. the stack.  The address is the address of the word that was allocated for john.  
  150. Right now we don't know what value is contained in the variable, so let's put 
  151. something in it.  
  152. <p>
  153. <p><pre>123 john !</pre><p>
  154. <p>
  155. will put the number 123 in the variable.  <strong>!</strong> , pronounced <em>store</em> 
  156. , is the store operator.  Its stack diagram looks like ( value adr -- ), meaning 
  157. that it expects an address on the top of the stack and a value underneath the 
  158. address.  The value will be put in the machine word at the indicated address, 
  159. and both arguments will be removed from the stack.  
  160. <p>
  161. Note in this example that the address was left by the word john.  It is an 
  162. important point that variables leave their addresses, rather than their values.  
  163. If the value of a variable is needed, the <strong>@</strong> (fetch) operator is 
  164. used.  
  165. <p>
  166. <p><pre>john @</pre><p>
  167. <p>
  168. will leave the value contained in the variable, in this case 123, on the stack.  
  169. The stack diagram for <strong>@</strong> is ( adr -- value ).  
  170. <p>
  171. It is reasonable to ask why it works this way, rather than having a variable 
  172. return its value.  In fact, a scheme to do this was discussed in the Forth 
  173. community for awhile, and the final consensus was that the the consistency and 
  174. regularity of the <strong>@</strong> and <strong>!</strong> operators was too 
  175. powerful to give up.  Forth is not the only language to do it is this way.  
  176. BLISS is another language which requires an explicit operator to return the 
  177. value of a variable.  
  178. <p>
  179. Similar operators, <code><A href="_smal_BB#169">c!</A></code> and <code><A href="_smal_BE#16C">c@</A>,</code> 
  180. are provided for storing and fetching bytes instead of 32-bit quantities.  The 
  181. stack only holds 32-bit quantities, so the bytes are stored in the 
  182. least-significant part of the 32-bit number on the stack.  
  183. <p>
  184. <p><pre>
  185. w!  ( w adr -- )        stores the least-significant 16 bits of the number
  186.                         on the stack into the 16-bit memory location at addr
  187. w@  ( adr -- w )        fetches the 16-bit word at addr, leaving it on the
  188.                         stack.  The high-order bits of the stack item are
  189.                         zeroed.
  190. c!  ( byte adr -- )     stores the least-significant byte of the stack
  191.                         item into the 8-bit memory location at adr 
  192. c@  ( adr -- byte )     fetches the byte at addr
  193. +!  ( n adr -- )        adds n to the contents of the 32-bit word at addr
  194. </pre><p>
  195. <p>
  196. <p>
  197. <h2>Constants</h2>
  198. <p>
  199. <p>
  200. <p><pre>32 constant buflen</pre><p>
  201. <p>
  202. defines a constant whose value is 32.  When buflen is executed, it leaves its 
  203. value, in contrast to a variable, which leaves its address.  There is no 
  204. explicit mechanism provided for changing the value of a constant.  Many Forth 
  205. systems may be tricked into telling you the address where the value of a 
  206. constant is actually stored, so it may be possible to change the value.  
  207. However, this is non-standard and implementation dependent.  Use a variable if 
  208. you want to change the value.  
  209. <p>
  210. <p><pre>buflen buflen + .</pre><p>
  211. <p>
  212. results in 
  213. <p>
  214. <p><pre>64</pre><p>
  215. <p>
  216. <p><pre>buflen john @ + .</pre><p>
  217. <p>
  218. results in 
  219. <p>
  220. <p><pre>155</pre><p>
  221. <p>
  222. assuming that john was defined and initialised as before to 123.  you should 
  223. make sure you understand why the <strong>@</strong> is needed after john but not 
  224. after buflen.  
  225. <p>
  226. The stack diagram for a constant is ( -- value ).  Remember that this is what 
  227. happens to the stack when the constant is executed, not when it is defined.  
  228. <p>
  229. More generally, the word <code><A href="_smal_AP#18F">constant</A></code> need 
  230. not be explicitly preceded by a number.  <code><A href="_smal_AP#18F">constant</A></code> 
  231. takes the initial value off of the stack.  The stack diagram is 
  232. <p>
  233. <p><pre>constant  \ name  ( initial_value -- )</pre><p>
  234. <p>
  235. "\ name" means that when the defining word constant executes, it takes a name ( 
  236. a sequence of non-blank characters ) out of the input stream and uses that name 
  237. for something.  In this case, the name is used as the name of the new constant.  
  238. Notice that distinction between arguments that are taken from the stack and 
  239. names that are taken from the input stream ( the input stream is what you type 
  240. at the terminal ).  
  241. <p>
  242. Since typing a number puts that number on the stack, our example works fine.  It 
  243. is also possible to use Forth to calculate the value of the constant, as in 
  244. <p>
  245. <p><pre>buflen 10 * constant bigbufsize</pre><p>
  246. <p>
  247. which defines a constant whose value is 10 times buflen, or 320.  This is 
  248. completely general; if you can get a number on the stack by any means 
  249. whatsoever, you can define a constant which returns that value.  
  250. <p>
  251. <p>
  252. <h2>Stack Manipulation</h2>
  253. <p>
  254. The following words rearrange numbers on the stack.  
  255. <p>
  256. <p><pre>
  257. dup  ( n -- n n )   duplicates the number on top of the stack.  This is a
  258.                     real workhorse - dup is used a lot when you want to
  259.                     make a copy because you want to remember a number but
  260.                     the word you want to use next will "eat" it.
  261. drop  ( n -- )      discards the number on top of the stack.
  262. swap  ( n1 n2 -- n2 n1 )    exchanges the positions of the number on top
  263.                             of the stack and the number underneath it.  
  264.                             Suppose you had 3 4 on the stack and you
  265.                             wanted to compute 4-3.  You could do SWAP -
  266.                             and you would get what you wanted.
  267. over ( n1 n2 -- n1 n2 n1 )  copies the number which is directly
  268.                             underneath the top of the stack so that a copy
  269.                             of it on top.
  270. rot ( n1 n2 n3 -- n2 n3 n1 ) pulls the third stack element to the top
  271.                             and moves the two which were above it
  272.                             down to fill its vacancy.
  273. pick  (  np np-1 np-2 ... n0 p -- np np-1 np-2 np-2 ... n0 np )
  274.                       copies the p-th stack element to the top of the
  275.                       stack; 0 pick is equivalent to dup
  276.                              1 pick is equivalent to over
  277. roll  ( np np-1 np-2 ... n0 p -- np-1 np-2 ... n0 np )
  278.                       moves the p-th stack element to the top and moves
  279.                       the others down to fill the vacancy.  3 roll is
  280.                       equivalent to rot
  281. depth  ( -- n )       leaves the number of items that were on the stack
  282.                       before depth executed.  The number that depth leaves
  283.                       on the stack is not included in the count.
  284. </pre><p>
  285. <p>
  286. <p>
  287. <h2>Conditionals</h2>
  288. <p>
  289. Of course Forth lets you make tests and do different things based on the results 
  290. of those tests.  
  291. <p>
  292. Here are some words which are useful for comparisons.  
  293. <p>
  294. <p><pre>
  295. <     ( n1 n2 -- flag )   Flag is true if n1 < n2
  296. =     ( n1 n2 -- flag )   Flag is true if n1 = n2
  297. >     ( n1 n2 -- flag )   Flag is true if n1 > n2
  298. 0<    ( n1 -- flag )      Flag is true if n1 < 0
  299. 0=    ( n1 -- flag )      Flag is true if n1 = 0
  300. <>    ( n1 n2 --  flag )  Flag is true if n1 not equal to n2
  301. 0>    ( n1 -- flag )      Flag is true if n1 > 0
  302. u<    ( un1 un2 -- flag)  "<" for unsigned integers, such as addresses
  303. ?dup  (n-- [n] n )        duplicate the top of the stack only if it is not
  304.                           zero
  305. </pre><p>
  306. <p>
  307. The brackets mean that the number in brackets is present only if the number on 
  308. top of it is nonzero.  This convention is useful because some words leave a flag 
  309. on top of the stack to indicate whether or not a particular operation succeeded.  
  310. If it did succeed, the flag is true and the word has left some results on the 
  311. stack underneath the flag.  If the operation failed, the flag is false (zero) 
  312. and the results were not put on the stack.  
  313. <p>
  314. The basic conditional in Forth is <code><A href="_smal_AW#226">if</A></code> .  
  315. It's stack diagram is ( n -- ), and it is used like: 
  316. <p>
  317. <p><pre>if  stuff_to_do_if_n_was_not_0  else  stuff_to_do_if_n_was_0  then</pre><p>
  318. <p>
  319. The <code><A href="_smal_BP#1D7">else</A></code> part is optional.  The use of 
  320. the English word "then" to terminate the conditional is misleading, but that is 
  321. the way it is.  
  322. <p>
  323. <p><pre>: absval  ( n -- absolute_value_of_n )  dup 0 < if 0 swap - then  ;</pre><p>
  324. <p>
  325. Let's analyze this definition carefully.  First of all, when this word executes, 
  326. it expects a number to be on top of the stack.  Call the number n.  The first 
  327. thing that happens is that <code><A href="_smal_BN#1D5">dup</A></code> is 
  328. executed, putting another copy of n on top of the stack.  The stack now looks 
  329. like ( n n ).  Next we have "0", which puts a zero on top of the stack, so that 
  330. stack looks like ( n n 0 ).  Then we execute "<", which compares to see 
  331. whether or not n is less than 0.  The two numbers that "<" compares are 
  332. removed from the stack and a flag is left instead.  
  333. <p>
  334. Suppose that n was -5, so that n really was less than 0.  "<" would then 
  335. leave a -1 on top of the stack.  Any nonzero number is considered to mean <code><A href="_smal_AE#304">true</A>,</code> 
  336. whereas zero means <code><A href="_smal_AR#1F1">false</A>.</code> So the stack 
  337. is ( n 1 ).  <code><A href="_smal_AW#226">if</A></code> takes the number off the 
  338. top of the stack, sees that it is -1, and proceeds to execute <strong>0 swap -</strong> 
  339. .  This has the effect of negating n.  The complete sequence of stack states is 
  340. <p>
  341. <p><pre>( n )  dup  ( n n )  0  ( n n 0 )  <  ( n 1 )  if  ( n )</pre><p>
  342. <p><pre> 0  ( n 0 )  swap  ( 0 n )  -  ( -n )  then  ( -n )</pre><p>
  343. <p>
  344. The <code><A href="_smal_BK#2F2">then</A></code> terminates the conditional.  
  345. <p>
  346. If n had been positive, "<" would have left a zero, because 0 is not greater 
  347. than a positive number.  <code><A href="_smal_AW#226">if</A></code> would have 
  348. taken the zero off of the stack and then skipped the stuff between <code><A href="_smal_AW#226">if</A></code> 
  349. and <code><A href="_smal_BK#2F2">then</A>.</code> If there had been an <code><A href="_smal_BP#1D7">else</A></code> 
  350. clause, it would have been executed.  
  351. <p>
  352. Instead of <strong>dup 0 <</strong> , we could have used <strong>dup 0<</strong> 
  353. .  
  354. <p>
  355. As a matter of fact there is an easier way to negate a number than <strong>0 swap -</strong> 
  356. .  You can just use <code><A href="_smal_AE#274">negate</A></code> ( n -- n ).  
  357. In fact, absval duplicates the function provided by system-supplied Forth word <code><A href="_smal_BE#13C">abs</A></code> 
  358. ( n -- |n| ).  
  359. <p>
  360. <code><A href="_smal_AW#226">if</A></code> ...  <code><A href="_smal_BP#1D7">else</A></code> 
  361. ...  <code><A href="_smal_BK#2F2">then</A></code> may be nested to any depth, 
  362. provided of course that there is a <code><A href="_smal_BK#2F2">then</A></code> 
  363. for every <code><A href="_smal_AW#226">if</A>.</code> <code><A href="_smal_AW#226">if</A></code> 
  364. may only be used within colon definitions, which means that you can't just type 
  365. in <code><A href="_smal_AW#226">if</A></code> blah-blah-blah <code><A href="_smal_BK#2F2">then</A></code> 
  366. unless you are in the middle of defining some other word.  
  367. <p>
  368. <p>
  369. <h2>Loops</h2>
  370. <p>
  371. The basic looping construct is the <code><A href="_smal_AP#1BF">do</A></code> <code><A href="_smal_AW#256">loop</A>.</code> 
  372. The stack diagram is (end+1 start -- ).  Examples are necessary.  
  373. <p>
  374. <p><pre>: printlots ( n9 n8 ... n1 n0 -- ) 10 0 do . loop ;</pre><p>
  375. <p>
  376. will print ten numbers from off of the stack.  The loop will start at 0 and end 
  377. after 9.  
  378. <p>
  379. You can get at the loop index by using <strong>i</strong> .  It leaves the loop 
  380. index on the stack (where else?).  
  381. <p>
  382. <p><pre>: sumit010 ( -- sum ) 0 11 1 do i + loop ;</pre><p>
  383. <p>
  384. will add up the numbers from 1 to 10 inclusive.  The "0" is there because the 
  385. current running sum is kept on the stack, and the sum needs to be initialised to 
  386. 0.  
  387. <p>
  388. <code><A href="_smal_AW#256">loop</A></code> limits don't have to be positive.  
  389. Try out various limits and see what happens.  
  390. <p>
  391. <p><pre>: bigjumps ( -- n ) 0   1000 0 do i +  10  +loop ;</pre><p>
  392. <p>
  393. will sum the multiples of 10 less than 1000.  <code><A href="_smal_AG#C6">+loop</A></code> 
  394. increments the loop index by a number that it takes from the stack, in this case 
  395. 10.  You can run loops backwards if you wish, by using <code><A href="_smal_AG#C6">+loop</A></code> 
  396. with a negative increment.  
  397. <p>
  398. You may prematurely exit from a <code><A href="_smal_AP#1BF">do</A></code> <code><A href="_smal_AW#256">loop</A></code> 
  399. by executing <code><A href="_smal_AE#244">leave</A></code> within the loop.  You 
  400. probably want to enclose the <code><A href="_smal_AE#244">leave</A></code> in an <code><A href="_smal_AW#226">if</A></code> 
  401. ...  <code><A href="_smal_BK#2F2">then</A></code> structure, because it doesn't 
  402. make sense to construct a loop which always exits after the first times through.  
  403. <p>
  404. More general loops may be constructed with 
  405. <p>
  406. <p><pre>begin ... until       or</pre><p>
  407. <p><pre>begin ... while ... repeat</pre><p>
  408. <p>
  409. In the case of <code><A href="_smal_AF#155">begin</A></code> ...  <code><A href="_smal_BC#31A">until</A>,</code> 
  410. the stack is checked by <code><A href="_smal_BC#31A">until</A>.</code> If if is 
  411. zero, looping continues at <code><A href="_smal_AF#155">begin</A>.</code> If it 
  412. is one, execution continues after <code><A href="_smal_BC#31A">until</A>.</code> 
  413. <p>
  414. For <code><A href="_smal_AF#155">begin</A></code> ...  <code><A href="_smal_AC#332">while</A></code> 
  415. ...  <code><A href="_smal_AK#2AA">repeat</A>,</code> <code><A href="_smal_AC#332">while</A></code> 
  416. checks the stack.  If it is 1, looping proceeds, first executing the stuff 
  417. between <code><A href="_smal_AC#332">while</A></code> and <code><A href="_smal_AK#2AA">repeat</A>,</code> 
  418. then starting over at <code><A href="_smal_AF#155">begin</A>.</code> If <code><A href="_smal_AC#332">while</A></code> 
  419. found a zero on the stack, the stuff between <code><A href="_smal_AC#332">while</A></code> 
  420. and <code><A href="_smal_AK#2AA">repeat</A></code> is skipped and execution 
  421. continues after "repeat".  
  422. <p>
  423. Well, campers, it's example time again.  This time we'll assume that there is a 
  424. table somewhere in memory.  This table consists of 8-word entries, and the end 
  425. of the table is flagged by a -1 in the first word of the last entry.  We would 
  426. like to scan through the table and add a number to the third word in each entry.  
  427. This third word represents the age of an employee, so we'll call it <strong>age</strong> 
  428. .  Our operation will make everybody older.  Study this example carefully.  It 
  429. shows how Forth programs should be constructed with simple words.  
  430. <p>
  431. <p><pre>
  432. : age  ( entry_adr -- age_adr )  \ converts entry adr to age adr
  433.    12 +
  434. ;
  435. : addin  ( n adr -- n adr )  \ adds n to the number at adr
  436.    over over                   \ copy both n and adr
  437.    age +!                      \ increase age by n
  438. ;
  439. : more?  ( adr -- adr flag )  \ flag is false iff adr points to a -1
  440.    dup @ -1 <>
  441. ;
  442. : +entry  ( adr1 -- adr2 )  \ advances to the next entry
  443.    32 +
  444. ;
  445. : older  ( n adr -- )  \ adds n to each age in table at adr
  446.    begin  more?  while  addin +entry  repeat  drop drop
  447. ;
  448. </pre><p>
  449. <p>
  450. <p>
  451. Supposing that there is a word <strong>employees</strong> which returns the 
  452. address of such a table, we could make a everybody 100 years older by typing 
  453. <p>
  454. <p><pre>100 employees older</pre><p>
  455. <p>
  456. Notice that I was careful to define each word before I used it inside another 
  457. word.  This is a requirement with typical Forth systems.  There is no "forward 
  458. referencing", so everything must be defined before it is used.  This may seem 
  459. archaic, but in fact it is seldom ever missed.  The payoff is great, in terms of 
  460. reduced compiler complexity and conceptual simplicity.  There are Forth 
  461. "cross-compiler" and "meta-compiler" programs which allow forward references to 
  462. varying degree, but they are generally used to build entire Forth kernels from 
  463. scratch.  
  464. <p>
  465. Now suppose we want to print out multiples of 2 until the user types a key on 
  466. his keyboard, at which time we want to stop.  There is a word <code><A href="_smal_BS#23A">key?</A></code> 
  467. which returns true if the user has typed something since the last time we 
  468. checked, 0 otherwise.  
  469. <p>
  470. <p><pre>: mults-of-2  ( -- )  0  begin  dup . 2 +  key?  until  drop  ;</pre><p>
  471. <p>
  472. Of course, this could have been done as 
  473. <p>
  474. <p><pre>: mults-of-2  ( -- )  32766 0  do  i .  key?  if leave then  2 +loop  ;</pre><p>
  475. <p>
  476. but the real point here was to illustrate the <code><A href="_smal_AF#155">begin</A></code> 
  477. ...  <code><A href="_smal_BC#31A">until</A></code> .  
  478. <p>
  479. <p><pre>
  480. key?  ( -- flag )      input and output
  481.                        flag is true if a key has been typed.
  482. key  ( -- char )       key waits until the user types a character, then
  483.                        returns the character
  484. emit  ( char -- )      emit displays the char on the terminal
  485. space  ( -- )          displays a space character.
  486. cr  ( -- )             displays a carriage return, line feed
  487. spaces  ( n -- )       displays n spaces
  488. type  ( adr n -- )     displays n characters, beginning at adr
  489. ." string of characters to display"
  490.                        here you actually have to type the
  491.                        double-quote characters.  The string starts 
  492.                        after the space following the first quote, 
  493.                        and continues up to but not including the 
  494.                        last quote.
  495. expect  ( adr n -- )   accepts n characters from the terminal,
  496.                        storing them at addr.  If a carriage return is
  497.                        typed before n characters have been
  498.                        accumulated, expect fills out the rest of the
  499.                        n locations with nulls
  500. -trailing  ( adr nl -- adr n2 )
  501.                        reduces the character count n1 so that
  502.                        trailing blanks are omitted 
  503. count  ( adr -- adr+1 n )
  504.                        converts a packed string to an address and
  505.                        character count
  506. </pre><p>
  507. <p>
  508. A word about <code><A href="_smal_AU#194">count</A></code> is in order.  Forth 
  509. stores strings as a length byte followed by a number of characters.  The length 
  510. byte contains the number of characters in the string, not including the length 
  511. byte.  <code><A href="_smal_AU#194">count</A></code> takes the address of a 
  512. packed string, which is the address of its length byte, and returns the address 
  513. of the actual characters in the string, which is 1 more than the address of the 
  514. length byte.  On top of that, it returns the value of the length byte.  
  515. <p>
  516. Note that Forth addresses are byte addresses.  If you add 1 to a Forth address, 
  517. you get the next byte.  To get the next word, you have to add 2.  
  518. <p>
  519. Normally, when you are typing Forth words for it to execute, they are being 
  520. stored in a buffer called the "terminal input buffer".  To execute the next 
  521. word, it first has to be fetched from the terminal input buffer.  To do this, a 
  522. word called <code><A href="_smal_AG#336">word</A></code> is executed.  <code><A href="_smal_AG#336">word</A></code> 
  523. takes the next word from the terminal input buffer and stores it as a packed 
  524. string, then returns the address of the packed string.  The boundary between one 
  525. word and the next is denoted by a space character.  Actually, <code><A href="_smal_AG#336">word</A></code> 
  526. accepts an argument which tells it what to use as the separator character.  
  527. Normally, space is used, but if you want to use <code><A href="_smal_AG#336">word</A></code> 
  528. yourself, you are free to chose your own delimiter.  
  529. <p>
  530. <p><pre>word  \ word  ( delimiter_char -- adr )</pre><p>
  531. <p><pre>                accepts the next word, or sequence of characters not</pre><p>
  532. <p><pre>                including the delimiter_char, from the input stream.</pre><p>
  533. <p><pre>                Stores it as a packed string and returns its address</pre><p>
  534. <p><pre>                (the address of the length byte).</pre><p>
  535. <p>
  536. <p>
  537. <h2>Numeric I/O</h2>
  538. <p>
  539. We have already seen how to use <code>"<A href="_smal_AO#CE">."</A></code> Also, 
  540. we have seen that numbers may be put on the stack simply by typing the number.  
  541. More options are available, such as accepting or typing hexadecimal numbers.  
  542. <p>
  543. <p><pre>
  544. base  ( -- adr )     a variable which contains the value of the current
  545.                      numeric input and output base.
  546. hex  ( -- )          sets base to 16 ( default when running stand alone )
  547. decimal  ( -- )      sets base to 10 ( the default when running under unix )
  548. .  ( n -- )          displays n according to the current BASE
  549. u.  ( u -- )         displays u as an unsigned number
  550. .r  ( n r -- )       displays n right-justified in a field of width r
  551. u.r  ( u r -- )      like ".r", but unsigned
  552. ?  ( adr -- )        displays the contents of the memory location at address
  553.                      adr. Equivalent to "@ ."
  554. .s  ( -- )           displays the entire stack contents without removing
  555.                      anything from the stack
  556. </pre><p>
  557. <p>
  558. <p>
  559. Note that executing <strong>base @ .</strong> is useless as a way to find out 
  560. what the current value of <code><A href="_smal_AD#153">base</A></code> is.  You 
  561. will always get 10 as the answer because whatever <code><A href="_smal_AD#153">base</A></code> 
  562. is, it will be typed as "10" according to its own base.  If you want to find out 
  563. what the base is according to the decimal numbering system, this will work: 
  564. <p>
  565. <p><pre>: decbase  ( -- )  base @ dup decimal .  base !  ;</pre><p>
  566. <p>
  567. Can you figure out why this works? 
  568. <p>
  569. <p>
  570. <h2>Arrays</h2>
  571. <p>
  572. Forth doesn't have very many explicit data structures, but it provides good 
  573. primitives for efficiently creating whatever kind of data structures you want.  
  574. Let's build an array.  
  575. <p>
  576. We need to know a couple more words first.  
  577. <p>
  578. <p><pre>
  579. create  \ name ( -- adr )  defines a new word which will return its address
  580.                            when executed.  The name of the new word is taken
  581.                            from the input stream.
  582. allot  ( n -- )            allocates n bytes of storage for the most recently
  583.                            defined word.
  584. </pre><p>
  585. <p>
  586. <code><A href="_smal_AX#197">create</A></code> is the like <code><A href="_smal_BN#325">variable</A>,</code> 
  587. except that variable automatically allocates /N bytes of storage.  variable xxx 
  588. is like the <strong>create</strong> xxx /cell allot).  Okay, here we go.  
  589. <p>
  590. <p><pre>
  591. : arrayvar  \ name  ( size-in-words -- )
  592.    cells create allot
  593. ;
  594. : a@  ( index adr -- value )  swap cells + @  ;
  595. : a!  ( value index adr -- )  swap cells + !  ;
  596. </pre><p>
  597. <p>
  598. <strong>arrayvar</strong> will allow us to create an array to hold size words.  
  599. a@ and a! will allow us to fetch and store elements of an array we have created.  
  600. Let's make an array and initialise it to all zeroes.  
  601. <p>
  602. <p><pre>
  603. 50 arrayvar ourarray
  604. : init  ( n adr -- )  swap   0 do  0 over i a!  loop  ;
  605. 50 ourarray init
  606. </pre><p>
  607. <p>
  608. <p>
  609. Now let's put a 5 in the 23rd element.  
  610. <p>
  611. \d 5 23 ourarray a! 
  612. <p>
  613. Is it there? 
  614. <p>
  615. <p><pre>23 ourarray a@  .</pre><p>
  616. <p>
  617. Of course it is.  Would I lie to you? Data structures in Forth can be as 
  618. sophisticated as you can imagine.  It's up to you; the primitives are all 
  619. present.  
  620. <p>
  621. <p>
  622. <h2>Vocabularies</h2>
  623. <p>
  624. Note: This section is incomplete.  The stuff that is here is correct, but there 
  625. are some words that I don't list.  Read the "Vocabularies and Search Order" 
  626. chapter in the manual for more information.  
  627. <p>
  628. Forth words may be grouped together in sets called <strong>vocabularies</strong> 
  629. .  This is somewhat analogous to directories in other operating systems, whereby 
  630. files are grouped together in different places.  
  631. <p>
  632. When Forth is looking for a word, it may search several vocabularies.  The 
  633. vocabulary where Forth looks first is called the "context" vocabulary, and there 
  634. is a system variable called <code><A href="_smal_AQ#190">context</A></code> 
  635. which keeps track of which vocabulary is the "context".  All Forth systems have 
  636. a vocabulary whose name is <code><A href="_smal_BT#20B">forth</A>.</code> If the 
  637. word that is sought is not found in "context", a list of other vocabularies is 
  638. searched.  
  639. <p>
  640. The "context" vocabulary specifies where to look for words.  It is also 
  641. necessary to know where to put the new words created by the user.  This 
  642. vocabulary is called the "current" vocabulary (also known as the "compilation 
  643. vocabulary), and again there is a system word <code><A href="_smal_BG#19E">current</A></code> 
  644. to keep track of which vocabulary is selected as the "current" one.  
  645. <p>
  646. Typical vocabularies present in most systems include <code><A href="_smal_BT#20B">forth</A>,</code> 
  647. and <code><A href="_smal_BV#14D">assembler</A>.</code> Others may be present, 
  648. and you can create your own if you wish.  After you have created a vocabulary, 
  649. you make make it the "context" vocabulary by typing the vocabulary's name.  The 
  650. only way to make a vocabulary "current" is to first make it "context" (by typing 
  651. its name).  Then you may use the word "definitions" which sets the "current" 
  652. vocabulary to be the same as the "context" vocabulary.  
  653. <p>
  654. <p><pre>
  655. vocabulary  \ name ( -- )    creates a new vocabulary whose name is taken
  656.                              from the input stream.  Executing that
  657.                              name later will cause the new vocabulary
  658. definitions  ( -- )          makes the "CURRENT" vocabulary the same as
  659.                              "the "CONTEXT" one
  660. order  ( -- )                displays the list of vocabularies to be
  661.                              searched 
  662. </pre><p>
  663. <p>
  664. <p>
  665. So, if you want to make a new vocabulary named "myvoc", execute 
  666. <p>
  667. <p><pre>vocabulary myvoc</pre><p>
  668. <p>
  669. If you want your new vocabulary to be the one that is searched first (i.e.  the 
  670. "context"), just type its name.  
  671. <p>
  672. <p><pre>myvoc</pre><p>
  673. <p>
  674. If you wished new word definitions to go into your new vocabulary (i.e.  make it 
  675. "current"), all you have to do is type 
  676. <p>
  677. <p><pre>definitions</pre><p>
  678. <p>
  679. assuming that you have already made "myvoc" the "context" by typing "myvoc".  If 
  680. not, just execute 
  681. <p>
  682. <p><pre>myvoc definitions</pre><p>
  683. <p>
  684. It is possible to create vocabularies within vocabularies, but it is most of the 
  685. time you should create new vocabularies only within the "forth" vocabulary.  To 
  686. insure that this is the case, type 
  687. <p>
  688. <p><pre>forth definitions</pre><p>
  689. <p>
  690. before creating new vocabularies.  This way, you always know how to find your 
  691. vocabularies ( just type Forth then the vocabulary name).  
  692. <p>
  693. <p>
  694. <h2>Forgetting</h2>
  695. <p>
  696. <p><pre>
  697. forget  \ name  ( -- )  forgets the named word from the dictionary.
  698.                         All words which have been defined after the
  699.                         named word are forgotten too.  This is necessary
  700.                         because the subsequent words may depend on the
  701.                         word you are forgetting.
  702. words  ( -- )           tells you what words the system knows
  703. </pre><p>
  704. <p>
  705. <p>
  706. <h2>Arithmetic Summary</h2>
  707. <p>
  708. <p><pre>
  709. +  ( n1 n2 -- sum )           integer addition
  710. -  ( n1 n2 -- difference )    integer subtraction, n1-n2 
  711. 1+  ( n -- n+1 )              add 1.  This is provided as an alternative
  712.                               to "1 +" because it is such a frequent
  713.                               operation and should be optimized
  714. 1-  ( n -- n-1 )              subtract 1
  715. 2+  ( n -- n+2 )              add 2.
  716. 2-  ( n -- n-2 )              subtract 2
  717. *  ( n1 n2 -- product )       integer multiply
  718. 2*  ( n -- n*2 )              times 2.  Usually implemented by shifting
  719. /  ( n1 n2 -- quotient )      integer portion of quotient
  720. 2/  ( n -- n/2 )              halve.  Usually implemented by shifting
  721. mod  ( n1 n2 -- remainder )   integer remainder
  722. /mod  ( n1 n2 -- quotient remainder )
  723.                               quotient and remainder
  724. u*  ( un1 un2 -- ud )         like "*" but unsigned
  725. u/mod  ( u1 u2 -- uremainder uquotient )
  726.                               unsigned /mod
  727.  
  728. max  ( n1 n2 -- max )         maximum
  729. min  ( n1 n2 -- min )         minimum
  730. abs  ( n -- |n| )             absolute value 
  731. negate  ( n -- -n )           arithmetic negation 
  732. and  ( n1 n2 -- and )         bitwise logical and
  733. or  ( n1 n2 -- or )           bitwise logical or
  734. xor  ( n1 n2 -- xor )         bitwise logical exclusive-or
  735. not  ( n1 -- complement )     bitwise logical complement
  736. </pre><p>
  737. <p>
  738. <p>
  739. <h2>Further Topics and books</h2>
  740. <p>
  741. There is a lot more to Forth than I have described here.  However, this should 
  742. be sufficient to get you a long way.  For a complete introduction to the 
  743. complete Forth language, I recommend the following books: 
  744. <p>
  745. <p><pre>
  746. Mastering Forth
  747. Anita Anderson and Martin Tracy
  748. Mountain View Press,
  749. P.O. Box 4656,
  750. Mountain  View, CA 94040
  751.     
  752. Starting Forth
  753. Leo Brodie of Forth,Inc.
  754. Prentice-Hall,Inc.
  755. Englewood Cliffs, NJ 07632
  756.    
  757. Thinking Forth
  758. Leo Brodie
  759. Prentice-Hall,Inc.
  760.    
  761. Dr. Dobbs Toolbook of Forth, Parts I+II
  762. </pre><p>
  763. <p>
  764. </body>
  765. </html>
  766.