-
Notifications
You must be signed in to change notification settings - Fork 2
/
forthin5mins
344 lines (238 loc) · 11.4 KB
/
forthin5mins
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
( The basis of this file came from https://learnxinyminutes.com/docs/forth/ )
( It has been edited,corrected and expanded for ANS/ISO FORTH )
( NOTE: this file is written in Forth and can be read by a compliant system)
\ --------------------------------- Preamble --------------------------------
( This is the original Forth comment. Notice the required 1st space!)
\ This is the full line comment. This file is to get you started with CAMEL99 V2
\ *** All Forth commands are separated by a SPACE ***
\ Forth commands are called WORDS.
\ They are like sub-routines in other languages.
\ WORDs are kept in the Forth Dictionary.
\ In Forth, everything is either a WORD in the dictionary or a number.
\ All programming in Forth is done by using existing WORDs to make new WORDs.
\ FORTH is one of the first "CONCATENTIVE" languages which means you can
\ string words together end to end to make more powerful words.
\ Numbers and math are typically performed on the data stack
( commonly called "the stack")
\ Typing numbers pushes them onto the stack. 1st number is on the bottom.
5 2 3 56 76 23 65 \ ok
( .S prints the stack contents but DOES NOT remove them)
\ 5 2 3 56 76 23 65
.S
\ The `.` word pops the top item from the stack and prints it:
. . . . . . .
\ ------------------------------ Basic Arithmetic ------------------------------
\ set the interpreter to DECIMAL arithmetic with:
DECIMAL \ ok
\ Arithmetic operators (+ - * / etc.) are also just Forth WORDs
\ They operate on numbers sitting on the stack
\ '+' takes two inputs, adds them and leaves the answer on the stack
5 4 + \ ok ( looks like nothing happened but 9 is on the stack)
\ print the answer on the stack with "dot"
.
\ More examples of arithmetic:
6 7 * . \ 42 ok
1360 23 - . \ 1337 ok
12 12 / . \ 1 ok
13 2 MOD . \ 1 ok
99 NEGATE . \ -99 ok
-99 ABS . \ 99 ok
52 23 MAX . \ 52 ok
52 23 MIN . \ 23 ok
\ HEXADECIMAL arithmetic and other BASEs
\ Forth can switch to HEX numbers with the word HEX
\ AND performs a logical AND so we can mask bits like this
HEX
1234 00FF AND . \ 34
DECIMAL ( changes the system back to BASE 10 arithmetic)
\ ----------------------------- Stack Manipulation -----------------------------
\ Naturally, as we work with the stack, we'll need these WORDs:
\ -----
3 DUP \ duplicate the top item (1st now equals 2nd): 3 3
4 0 DROP .S \ remove the top item : 4
1 2 3 NIP .S \ remove the second item (similar to drop): 1 3
2 5 SWAP .S \ swap the top with the second element: 5 2
6 4 5 ROT .S \ rotate the 3rd item to top: 4 5 6
6 4 5 -ROT .S \ rotate top item to 3rd position 5 6 4
\ clean the stack the hard way
DROP DROP DROP DROP DROP DROP DROP DROP DROP DROP DROP DROP DROP
\ ---------------------- More Advanced Stack Manipulation ----------------------
( duplicate the top item below the second slot:)
1 2 3 4 TUCK .S
DROP DROP DROP DROP DROP
\ duplicate the second item to the top:
1 2 3 4 OVER .S
DROP DROP DROP DROP DROP
\ *duplicate* the item from position "2" onto the top:
1 2 3 4 2 PICK
DROP DROP DROP DROP DROP
\ PICK use "0" based indexing. ( ie: 0 PICK = DUP)
\ ------------------------------ Creating Words --------------------------------
\ The `:` word puts Forth into compile mode until it sees the `;` word.
: SQUARE ( n -- n ) DUP * ; \ ok
5 SQUARE . \ 25 ok
\ WORDs that we create are just added to the dictionary
\ WORDs can be combined with other words to any depth
: 2(X^2) ( n -- n) SQUARE 2 * ; \ returns 2(n^2)
\ Printing text is unusual but workable.
\ ANS Forth has ." to print a text string inside a compiled word.
\ There are two unusual things about "dot-quote", as it is called.
\ 1. You must put a space after ."
\ Do you understand why? Because it is a Forth word like all the rest.
\ 2. "dot-quote"is a state-smart word. This means it does one thing in compiling mode
\ and something else in immediate mode (interpreting)
\ In compile mode it has to "compile" strings of text into a new word definition.
\ CR (carriage return) is the word for a new line
: HELLO
CR ." Hello World!"
CR ." uses 'dot-quote' in the word HELLO" ;
HELLO
\ In IMMEDIATE mode "dot-quote" simply has to type a string to the output device.
." Print this now!"
\ You can also print text in the interpret mode ONLY using .(
\ This is called a talking comment.
CR .( This message will print from the interpreter)
CR .( This is also called a "talking comment")
CR .( It is used to inform the programmer while a file is compiling)
\ Remember to put space between ." or .( and the text!
\ -------------------------------- Conditionals ------------------------------
\ TRUE and FALSE are constants in CAMEL99. TRUE returns -1 FALSE returns 0
( However, any non-zero value is also treated as being true)
TRUE . \ -1 ok
FALSE . \ 0 ok
42 42 = . \ -1 ok
12 53 = . \ 0 ok
\ `IF` is a compile-only word that does stuff if top of stack is TRUE
\ Forth's IF/THEN will confuse you if you think it's the same as other languages.
\ It is best understood if we consider the sentence:
\ Looks like rain? IF so, Get your umbrella THEN go outside.
\ Syntax: `IF` <stuff to do when TOS is true> `THEN` <do the rest of program>.
: ?>64 ( n -- n ) DUP 64 > IF ." Greater than 64!" THEN ; \ ok
100 ?>64 \ Greater than 64! ok
\ 'ELSE'
: ?>64 ( n -- n ) DUP 64 > IF ." Greater than 64!" ELSE ." Less than 64!" THEN ;
100 ?>64
20 ?>64
\ ------------------------------------ Loops ------------------------------
\ looping words are compile-only. (must be inside a colon definition)
: MYLOOP ( -- ) 5 0 DO ." Hello! " LOOP ; \ ok
\ Hello! Hello! Hello! Hello! Hello!
MYLOOP
\ `DO` expects two numbers on the stack: the end number and the start number.
\ (the loop limit and the loop index)
\ We can get the value of the index as we loop with `I`:
: ONE-TO-12 ( -- ) 12 0 DO I . LOOP ; \ ok
\ 0 1 2 3 4 5 6 7 8 9 10 11 ok
ONE-TO-12
\ Notice the loop stops when the limit and index are equal.
\ We printed 12 numbers... 0 to 11
\ `?DO` works similarly, except it will skip the LOOP if the end and start
\ numbers are equal on the parameter stack. This is used if there is a chance
\ that limit=index as input arguments and you want to prevent a run-away loop.
( We defined SQUARE earlier so we can use it now)
: SQUARES ( n -- ) 0 ?DO I SQUARE . LOOP ; \ ok
\ 0 1 4 9 16 25 36 49 64 81 ok
10 SQUARES
0 SQUARES
\ Change the looping "step" with `+LOOP`:
: THREES ( n n -- ) 3 ?DO I . 3 +LOOP ; \ ok
\ 3 6 9 12 15 18 ok
20 THREES
\ Indefinite loops with `BEGIN` <stuff to do> `AGAIN`:
( **DONT' RUN THIS. YOU CAN'T STOP IT ***)
: FOREVER ( -- ) BEGIN ." Are we there yet?" AGAIN ;
\ Conditional loops use 'BEGIN' <stuff to do> <condition> 'UNTIL'
: DECREMENTER ( n -- ) BEGIN 1- DUP 0= UNTIL ;
99 DECREMENTER \ OK
\ Breaking out of a loop from the keyboard is possible by testing for a
\ key with KEY? which reads any key and returns 0 if no key is pressed
: KEYLOOP BEGIN ." Press a key to stop me..." KEY? UNTIL ;
\ WHILE loops use 'BEGIN' <condition> 'WHILE' <stuff to do> 'REPEAT'
: UPTO10 ( -- ) 0 BEGIN 1+ DUP 10 < WHILE ." NOT YET! " REPEAT DROP ;
\ ---------------------------- Variables and Memory ----------------------------
\ Use `VARIABLE` to create an integer variable.
VARIABLE AGE \ ok
\ VARIABLEs do not return their value!
\ They simply give us an address in memory where we can store numbers
( like a "pointer" but simpler language)
\ We write 21 to AGE with the word `!` (pronounced "store")
21 AGE ! \ ok
\ We can read the value of our variable using the `@` word called "fetch"
\ '@' just reads the value from an address and puts in the stack
AGE @ \ 21 is sitting on the top of the stack now
\ to print the value on the top of the stack use the '.' command
.
\ A common tool to fetch and print is '?' which combines @ and .
: ? ( addr -- ) @ . ;
AGE ? \ 21 ok
\ We can work in a new RADIX by changing the system variable BASE
\ Binary...
HEX F0 2 BASE ! . \ 11110000 ok
\ Octal...
8 BASE ! 7 1 + . \ 10 ok
DECIMAL
\ Constants work as expected and return their value to the top of stack
100 CONSTANT WATER-BOILING-POINT \ ok
WATER-BOILING-POINT . \ 100 ok
\ ----------------------------------- Arrays -----------------------------------
\ Like Assembly language Forth has no standard way to make arrays.
\ We can create arrays by naming a block of memory with the WORD CREATE
\ and allocating memory space with ALLOT.
\ A CELL in Forth is the memory size of a native integer on the CPU
\ For 16 bit machine, a CELL is 2 bytes
\ For 32 bit computer, it would be 4 bytes etc.
\ 'CELLS' calculates memory size for n CELLS of memory on your computer
CR ." Your computer's CELLs take" 1 CELLS . ." bytes"
\ All together it looks like this:
CREATE MYNUMBERS 10 CELLS ALLOT \ ok
\ Initialize all the values to 0
MYNUMBERS 10 CELLS 0 FILL \ ok
\ If we needed to do this a lot, we would define ERASE
: ERASE ( addr len -- ) 0 FILL ;
\ ... and do this...
MYNUMBERS 10 CELLS ERASE
\ or we can CREATE an array initialized with specific values
\ using the 'comma' number compiler. (puts 1 integer in next available CELL)
CREATE MYNUMBERS 64 , 9001 , 1337 , \ ok (the last `,` is important!)
\ ...which is equivalent to manually writing values to each index:
64 MYNUMBERS 0 CELLS + ! \ ok
9001 MYNUMBERS 1 CELLS + ! \ ok
1337 MYNUMBERS 2 CELLS + ! \ ok
\ Reading values from our array at indexes, the hard way:
MYNUMBERS 0 CELLS + ? \ 64 ok
MYNUMBERS 1 CELLS + ? \ 9001 ok
\ Normally we would extend the language and make a helper word for
\ accessing arrays for example we could create '[]'
( FORTH lets us use any characters except space as identifiers)
: [] ( n array -- addr[n] ) SWAP CELLS + ; \ ok
\ Now we created an array syntax that works like this:
20 1 MYNUMBERS [] ! \ ok
1 MYNUMBERS [] ? \ 20 ok
\ If you don't like this syntax you are free to change it!
\ *Notice there is no index checking. You could add it if you need it.
\ ------------------------------ The Return Stack ------------------------------
\ Just like a sub-routine stack, the Forth return stack holds the address (pointer)
\ of the word that called the currently running word. This lets a Forth Word 'return'
\ to the word that called it. (ie: where it came from)
\ In CAMEL99 the return stack also holds the limit and index of any running DO LOOP.
\ The programmer is free to use the return stack BUT be very careful.
\ You can easily crash the system if you make a mistake.
\ Example: Print 4 numbers starting from the bottom of the DATA stack
: .INORDER ( n1 n2 n3 n4 -- )
>R >R >R \ push 3 #s onto return stack
. \ print n1,
R> . R> . R> . ; \ pop each and print
1 2 3 4 .INORDER
\ NOTE: Because Forth uses the return stack internally, `>R` should
\ always be matched by `R>` inside of your word definitions or expect a crash!
PAGE
\ --------------------------------- Final Notes --------------------------------
\ Typing a non-existent word will empty the stack because it calls the word ABORT
\ which resets the data stack and the return stack
\ Clear the screen:
\ PAGE
\ Loading Forth files into the system:
\ INCLUDE MYFILE.FTH
\ you can list every word that's in Forth's dictionary with WORDS
KEY DROP
WORDS