Lab · Playground
Forth playground
A small Forth that runs in your browser — the data stack, defining new words, loops, and memory, in the language that fits in 8 KB.
Forth is the language Chuck Moore built in the late 1960s to control radio telescopes, and it still turns up wherever memory is tiny: boot firmware (Open Firmware on old Macs and Suns), spacecraft, and hobby microcontrollers. There is almost no syntax. A program is a stream of words separated by spaces; numbers go onto a stack, and every word takes its arguments from the stack and leaves its results there. You grow the language by defining new words, until the problem reads like its own little vocabulary.
These blocks run a small ANS-style Forth written for this site — it is part of the playground
script, so there is nothing to download. Each run starts a fresh system, and whatever is left on
the stack at the end is shown after it, like <2> 30 20 ok (the depth, then the items, top last). Comments are ( like this ) or \ to the end
of the line; the stack comments such as ( a b — sum ) are the Forth convention for "takes a
and b, leaves sum".
2 3 + . \ 5 — "." pops the top of the stack and prints it
2 3 4 * + . \ 14 — no precedence rules: it is just the order words run in
cr
10 20 30 .s \ show the stack without changing it
cr
swap .s cr \ exchange the top two
rot .s cr \ bring the third item to the top
over .s cr \ copy the second item over the top
drop drop \ leave two items: you will see them after "ok"
: square ( n -- n*n ) dup * ;
: cube ( n -- n^3 ) dup square * ;
: hyp2 ( a b -- a²+b² ) square swap square + ;
7 square . cr
3 cube . cr
3 4 hyp2 . cr
\ Fixed-point maths, Forth style: */ multiplies then divides with no overflow in between
: c>f ( celsius -- fahrenheit ) 9 5 */ 32 + ;
-40 c>f . 0 c>f . 37 c>f . 100 c>f . cr
: row ( n -- ) 11 1 do dup i * 4 .r loop drop ;
: table ( -- ) 11 1 do i row cr loop ;
table
: fizz? ( n -- flag ) 3 mod 0= ;
: buzz? ( n -- flag ) 5 mod 0= ;
: fizzbuzz ( n -- )
dup fizz? over buzz? and if drop ." FizzBuzz" else
dup fizz? if drop ." Fizz" else
dup buzz? if drop ." Buzz" else
. then then then ;
: run 21 1 do i fizzbuzz space loop ;
run
\ Euclid's greatest common divisor, as a loop
: gcd ( a b -- g ) begin dup while tuck mod repeat drop ;
1071 462 gcd . cr
\ The same idea recursively: RECURSE calls the word being defined
: gcd-r ( a b -- g ) ?dup if tuck mod recurse then ;
1071 462 gcd-r . cr
\ Collatz: how many steps from n down to 1?
: step ( n -- n' ) dup 2 mod if 3 * 1+ else 2/ then ;
: collatz ( n -- steps ) 0 swap begin dup 1 > while step swap 1+ swap repeat drop ;
27 collatz . cr
variable total
0 total ! \ ! stores: value address !
5 total +! 12 total +! \ +! adds into memory
total @ . cr \ @ fetches: 17
8 constant #samples
create samples 3 , 9 , 4 , 1 , 7 , 2 , 8 , 6 , \ , compiles a cell into memory
: sample ( i -- n ) cells samples + @ ;
: sum ( -- n ) 0 #samples 0 do i sample + loop ;
: biggest ( -- n ) 0 sample #samples 1 do i sample max loop ;
." sum " sum . ." max " biggest . cr
255 dup hex . decimal . cr \ BASE changes how numbers print (and parse): FF 255
\ ' (tick) gives a word's execution token; EXECUTE runs it — Forth's function pointers
: twice ( xt n -- n' ) over execute swap execute ;
: double 2* ;
: inc 1+ ;
' double 5 twice . cr \ 20
' inc 5 twice . cr \ 7
variable op ' double op ! \ keep an xt in a variable…
9 op @ execute . cr \ …and call through it: 18
Things to try: define : cube-root by searching with a loop, change table to print squares
only, or type words to list every word the system knows.