Transcript Forth
Forth
A stack language
Free implementations
For our purposes, pforth seems to be best
http://www.softsynth.com/pforth/
Another alternative is SwiftForth
http://www.forth.com/swiftforth/dl.html
Both are ANS compliant
2
Forth syntax
A word consists of a sequence of printable (nonwhitespace) characters
A program consists of a sequence of words, separated
by whitespace
Any questions?
3
Basic execution
Forth uses a dictionary to hold function definitions, and
a stack to hold data
Words are evaluated left to right, top to bottom, in the
usual order
Forth is case insensitive
Most documentation uses words in all caps, but lowercase is also ok
If a word is in the dictionary,
then the function is looked up and executed
else Forth converts the word to a number, if it can, and
places it on the stack
4
Defining and calling functions
A function is defined with
: functionName ( old -- new , words ) body ;
For example, addition might be documented as
( n1 n2 -- n3 , adds top two items )
A function is called by mentioning its name
The function expects to find its parameters on the stack
The function places its return values on the stack
The ( old -- new , words ) tells how the stack is changed
Parameters, if any, are taken from the stack
Return values, if any, are placed on the stack
Example:
: add3 ( n1 n2 n3 -- n4 , add 3 items) + + ;
1 2 3 4 5 add3 .s
1 2 12 <-Top ok
ok
5
Displaying the stack
. ( N -- , print number on top of stack )
Removes (“pops”) the top number from the stack and prints it
2 2 + . 4 ok
.s ( -- , print the entire stack )
This does not modify the stack contents
1 2 3 4 5 .s
1 2 3 4 5 <-Top ok
+ . 9 ok
.s
1 2 3 <-Top ok
The top of the stack is on the right
The above examples are from SwiftForth, which prints <- Top
Most other Forth implementations just take this for granted
6
Manipulating the stack
0sp ( clears the stack ) (pforth only)
dup ( n -- n n , duplicate top of stack )
ok
1 2 3 4 5 swap .s
1 2 3 5 4 <-Top ok
over ( a b -- a b a , copy second item on stack )
1 2 3 4 5 dup .s
1 2 3 4 5 5 <-Top
swap ( a b -- b a , swap top two items on stack )
0sp 0sp ?
.s
<-Top ok
1 2 3 4 5 over .s
1 2 3 4 5 4 <-Top
ok
pick ( ... v3 v2 v1 v0 N -- ... v3 v2 v1 v0 vN )
Makes a copy of the Nth stack item; 0 PICK is equivalent to DUP
7
More stack manipulations
DROP ( a -- , remove top item from the stack )
ROT ( a b c -- b c a , ROTate third item to top )
?DUP ( n -- n n | 0 , duplicate only if non-zero, '|'
means OR )
-ROT ( a b c -- c a b , rotate top to third position )
2SWAP ( a b c d -- c d a b , swap pairs )
2OVER ( a b c d -- a b c d a b , leapfrog pair )
2DUP ( a b -- a b a b , duplicate pair )
2DROP ( a b -- , remove pair )
NIP ( a b -- b , remove second item from stack )
TUCK ( a b -- b a b , copy top item to third position )
8
Arithmetic
Arithmetic is integer
+ - * / mod are add, subtract, multiply, integer divide,
modulus, all ( n1 n2 -- n3 )
Some “shorthand” operators are 1+ 1- 2+ 2- 2* 2/
10 2/ . 5
ok
/MOD ( n1 n2 -- rem quot , remainder and quotient of n1/n2 )
MIN ( n1 n2 -- n3 , minimum of n1 and n2 )
MAX ( n1 n2 -- n3 , maximum of n1 and n2 )
ABS ( n -- abs(n) , absolute value of n )
NEGATE ( n -- -n , negate value, faster then -1 * )
LSHIFT ( n c -- n<<c , left shift of n )
RSHIFT ( n c -- n>>c , logical right shift of n )
ARSHIFT ( n c -- n>>c ) , arithmetic right shift of n )
9
Output
EMIT ( n -- , display character with ASCII value n )
CHAR ( <char> -- char , get ASCII value of a character )
Unusual: Uses the following text, not the stack!
111 108 dup 101 72 emit emit emit emit emit Hello ok
char A . 65 ok
." ( -- , print string up to next " )
." Hello from pforth!" Hello from pforth!
ok
Works in SwiftForth when in a function, but not by itself in REPL (?)
SPACE ( -- , output a space )
SPACES ( n -- , output n spaces )
CR ( -- , start new line , carriage return )
10
Strings
." will output a string, up to a "
ok
S" will put a string on the stack
." hello" hello
Stack<10>
Format: Character count on top, machine address below that
s" Hello from Forth!"
ok
Stack<10> 140255546192593 17
TYPE will remove a print a string from the stack
type Hello from Forth!
Stack<10>
ok
11
Strings, character by character
Given the machine address of a string, C@ will return the first
character
CHAR+ will advance to the next character
s" ABCDE"
ok
Stack<10> 140354489823953 5
drop dup
ok
Stack<10> 140354489823953 140354489823953
c@ emit A
ok
Stack<10> 140354489823953
char+ dup c@ emit B
ok
Stack<10> 140354489823954
char+ char+ char+ dup c@ emit E
ok
Stack<10> 140354489823957
12
Input
KEY ( -- char , input character )
: testkey ( -- ) ." Hit a key: " key cr ."
That was " . cr ; ok
testkey Hit a key: A
That was 65
13
Loading from a file
In file sample.fth, in same directory as sf:
\ Sample Forth Code
\ Author: Phil Burk
ANEW \ forget what was loaded before
: SQUARE ( n -- n*n , square number )
DUP *
;
: TEST.SQUARE ( -- )
CR ." 7 squared = "
7 SQUARE . CR
;
In SwiftForth:
include sample.fth ok
test.square
7 squared = 49
ok
Very similar in pforth
forget square – forgets everything from square on down (pforth only)
14
More about loading
FORGET definition is supposed to forget the named
definition and everything that follows
This works in pforth, but I don’t think it does in SwiftForth
ANEW should forget what was loaded before
INCLUDE? filename will only load code if it isn’t
already in the dictionary
15
Constants and variables
Constants can be defined as value CONSTANT name
42 constant theAnswer
theAnswer . 42 ok
ok
Variables can be defined with VARIABLE name
VARIABLE ( <name> -- , define a 4 byte memory storage
location )
@ ( address -- value , FETCH value FROM address in
memory )
! ( value address -- , STORE value TO address in
memory )
variable ans ok
42 ans ! ok
ans ? 42 ok
ans @ . 42
16
Logic
true and false are constants -1 and 0
Comparisons are < <= = >= >
2
2
2
2
3
3
3
3
0> 0<
< . -1 ok
> . 0 ok
<= . -1 ok
>= . 0 ok
Logical operators are and
0=
true -1 and . -1 ok
true true and not . 0
or
not
ok
17
IF-ELSE-THEN statements
Forth has an “if” statement
: showIf ( flag -- , print logical value )
if ." true" else ." false" then ; ok
true showIf true ok
false showIf false ok
55 showIf true ok
The “else” part is optional
It helps to think of then as “end if
18
BEGIN … END Loops
BEGIN … END will loop until a given condition is
true
5 begin 1- dup . dup not until 4 3 2 1 0
Stack<10> 0
0 begin dup . 1+ dup 3 = until 0 1 2
ok
Stack<10> 3
ok
19
DO … LOOP Loop
end start DO … LOOP will loop a fixed number of times
5 1 do ." hi! " loop hi! hi! hi! hi!
Stack<10>
ok
You can access the loop counter with I
5 1 do ." hi#" i 48 + emit loop hi#1 hi#2 hi#3 hi#4
ok
Stack<10>
70 65 do i . i emit space loop 65 A 66 B 67 C 68 D 69 E
ok
You can leave the loop with LEAVE
50 1 do ." hi " i 5 > if leave then loop hi hi hi hi hi hi ok
Stack<10>
20
BEGIN … WHILE … REPEAT Loop
BEGIN test WHILE body REPEAT acts like a while loop
in more traditional languages
2 begin dup 1000 < while dup . 2* repeat
2 4 8 16 32 64 128 256 512
ok
Stack<10> 1024
21
“Case” statements
On file sample.fth:
: day-of-week ( n -- str , return day of week, Sunday = 1 )
case
1 of s" Sunday" endof
2 of s" Monday" endof
3 of s" Tuesday" endof
4 of s" Wednesday" endof
5 of s" Thursday" endof
6 of s" Friday" endof
7 of s" Saturday" endof
endcase ;
include sample.fth
Include sample.fth
include added 768 bytes,39236 left.
ok
Stack<10>
4 day-of-week type Wednesday
ok
Stack<10>
22
References
Most of this lecture based on (or shamelessly stolen from)
the excellent Forth Tutorial by Phil Burk:
http://www.softsynth.com/pforth/pf_tut.php
23
The End
The first time I combined the ideas I had been developing
into a single entity, I was working on an IBM 1130, a “thirdgeneration” computer. The result seemed so powerful that I
considered it a “fourth generation computer language.” I
would have called it Fourth, except that the 1130 permitted
only five-character identifiers. So Fourth became Forth, a
nicer play on words anyway.
--Charles “Chuck” Moore
24