Be sure to read "usage.txt" for a guide to Collapse OS' Forth.

*** Glossary ***
Stack notation: "<stack before> -- <stack after>". Rightmost is top of stack
(TOS). For example, in "a b -- c d", b is TOS before, d is TOS after. "R:" means
that the Return Stack is modified. "I:" prefix means "IMMEDIATE", that is, that
this stack transformation is made at compile time.

Word references (wordref): When we say we have a "word reference", it's a
pointer to a words *code link*. For example, the label "PLUS:" in this unit is a
word reference. Why not refer to the beginning of the word struct? Because we
actually seldom refer to the name and prev link, except during compilation, so
defining "word reference" this way makes the code easier to understand.

Atom: A word of the type compiledWord contains, in its PF, a list of what we
call "atoms". Those atoms are most of the time word references, but they can
also be references to NUMBER and LIT.

Words between "()" are "support words" that aren't really meant to be used
directly, but as part of another word.

"*I*" in description indicates an IMMEDIATE word.

*** Symbols ***

Throughout words, different symbols are used in different contexts, but we try
to been consistent in their use. Here's their definitions:

! - Store
@ - Fetch
$ - Initialize
^ - Arguments in their opposite order
< - Input
> - 1. Pointer in a buffer 2. Opposite of "<".
( - Lower boundary
) - Upper boundary
* - Word indirection (pointer to word)
~ - Container for native code. Usually not an executable word.
? - Is it ...? (example: IMMED?)

*** Entry management ***
(find)      a -- a f        Read at a and find it in dict. If found, f=1 and
                            a = wordref. If not found, f=0 and a = string addr.
' x         -- a            Push addr of word x to a. If not found, aborts
['] x       --              *I* Like "'", but spits the addr as a number
                            literal. If not found, aborts.
,           n --            Write n in HERE and advance it.
ALLOT       n --            Move HERE by n bytes
C,          b --            Write byte b in HERE and advance it.
DELW        a --            Delete wordref at a. If it shadows another
                            definition, that definition is unshadowed.
FORGET x    --              Rewind the dictionary (both CURRENT and HERE) up to
                            x's previous entry.
PREV        a -- a          Return a wordref's previous entry.
WHLEN       a -- n          Get word header length from wordref. That is, name
                            length + 3. a is a wordref

*** Defining words ***
: x ...     --              Define a new word
;           R:I --          Exit a colon definition
CREATE x    --              Create cell named x. Doesn't allocate a PF.
[COMPILE] x --              Compile word x and write it to HERE. IMMEDIATE
                            words are *not* executed.
COMPILE x   --              Meta compiles. Kind of blows the mind. See below.
CONSTANT x  n --            Creates cell x that when called pushes its value
DOES>       --              See description in usage.txt
IMMED?      a -- f          Checks whether wordref at a is immediate.
IMMEDIATE   --              Flag the latest defined word as immediate.
LITA        n --            Write address n as a literal.
LITN        n --            Write number n as a literal.
VARIABLE c  --              Creates cell x with 2 bytes allocation.

*** Flow ***
Note about flow words: flow words can only be used in definitions. In the
INTERPRET loop, they don't have the desired effect because each word from the
input stream is executed immediately. In this context, branching doesn't work.

(br)        --              Branches by the number specified in the 2 following
                            bytes. Can be negative.
(?br)       f --            Branch if f is false.
(           --              *I* Comment. Ignore rest of line until ")" is read.
[           --              Begin interetative mode. In a definition, words
                            between here and "]" will be executed instead of
                            compiled.
]           --              End interpretative mode.
ABORT       --              Resets PS and RS and returns to interpreter
ABORT" x"   --              *I* Compiles a ." followed by a ABORT.
AGAIN       I:a --          *I* Jump backwards to preceeding BEGIN.
BEGIN       -- I:a          *I* Marker for backward branching with AGAIN.
ELSE        I:a --          *I* Compiles a (fbr) and set branching cell at a.
EXECUTE     a --            Execute wordref at addr a
IF          -- I:a          *I* Compiles a (fbr?) and pushes its cell's addr
INTERPRET   --              Get a line from stdin, compile it in tmp memory,
                            then execute the compiled contents.
QUIT        R:drop --       Return to interpreter prompt immediately
RECURSE     R:I -- R:I-2    Run the current word again.
THEN        I:a --          *I* Set branching cell at a.
UNTIL       f --            *I* Jump backwards to BEGIN if f is *false*.

*** Parameter Stack ***
DROP        a --
DUP         a -- a a
OVER        a b -- a b a
ROT         a b c -- b c a
SWAP        a b -- b a
2DROP       a a --
2DUP        a b -- a b a b
2OVER       a b c d -- a b c d a b
2SWAP       a b c d -- c d a b

*** Return Stack ***
>R          n -- R:n        Pops PS and push to RS
R>          R:n -- n        Pops RS and push to PS
I           -- n            Copy RS TOS to PS
I'          -- n            Copy RS second item to PS
J           -- n            Copy RS third item to PS

*** Memory ***
@           a -- n          Set n to value at address a
!           n a --          Store n in address a
?           a --            Print value of addr a
+!          n a --          Increase value of addr a by n
C@          a -- c          Set c to byte at address a
C!          c a --          Store byte c in address a
CURRENT     -- a            Set a to wordref of last added entry.
CURRENT*    -- a            A pointer to active CURRENT*. Useful when we have
                            multiple active dicts.
HERE        -- a            Push HERE's address
H@          -- a            HERE @
MOVE        a1 a2 u --      Copy u bytes from a1 to a2, starting with a1, going
                            up.
*** Addressed devices ***

See usage.txt for details.

ADEV$       --              Initialize adev subsystem
A@          a -- c          Indirect C@
A!          c a --          Indirect C!
A@*         -- a            Address for A@ word
A!*         -- a            Address for A! word
AMOVE       src dst u --    Same as MOVE, but with A@ and A!

*** Arithmetic / Bits ***

+           a b -- c        a + b -> c
-           a b -- c        a - b -> c
-^          a b -- c        b - a -> c
*           a b -- c        a * b -> c
/           a b -- c        a / b -> c
MOD         a b -- c        a % b -> c
/MOD        a b -- r q      r:remainder q:quotient
AND         a b -- c        a & b -> c
OR          a b -- c        a | b -> c
XOR         a b -- c        a ^ b -> c

*** Logic ***
=           n1 n2 -- f      Push true if n1 == n2
<           n1 n2 -- f      Push true if n1 < n2
>           n1 n2 -- f      Push true if n1 > n2
CMP         n1 n2 -- n      Compare n1 and n2 and set n to -1, 0, or 1.
                            n=0: a1=a2. n=1: a1>a2. n=-1: a1<a2.
NOT         f -- f          Push the logical opposite of f

*** Strings ***
LIT         --              Write a LIT entry. You're expected to write actual
                            string to HERE right afterwards.
LIT< x      --              Read following word and write to HERE as a string
                            literal.
LITS        a --            Write word at addr a as a atring literal.
SCMP        a1 a2 -- n      Compare strings a1 and a2. See CMP
SCPY        a --            Copy string at addr a into HERE.
SLEN        a -- n          Push length of str at a.

*** I/O ***

(parse)     a -- n          Parses string at a as a number and push the result
                            in n as well as whether parsing was a success in f
                            (false = failure, true = success)
(parse.)    a -- n f        Sub-parsing words. They all have the same signature.
                            Parses string at a as a number and push the result
                            in n as well as whether parsing was a success in f
                            (0 = failure, 1 = success)
(parse*)    -- a            Variable holding the current pointer for system
                            number parsing. By default, (parse).
(print)     a --            Print string at addr a.
.           n --            Print n in its decimal form
.x          n --            Print n's LSB in hex form. Always 2 characters.
.X          n --            Print n in hex form. Always 4 characters. Numbers
                            are never considered negative. "-1 .X" --> ffff
." xxx"     --              *I* Compiles string literal xxx followed by a call
                            to (print)
C<          -- c            Read one char from buffered input.
DUMP        n a --          Prints n bytes at addr a in a hexdump format.
                            Prints in chunks of 8 bytes. Doesn't do partial
                            lines. Output is designed to fit in 32 columns.
EMIT        c --            Spit char c to output stream
IN>         -- a            Address of variable containing current pos in input
                            buffer.
KEY         -- c            Get char c from direct input
PC!         c a --          Spit c to port a
PC@         a -- c          Fetch c from port a
WORD        -- a            Read one word from buffered input and push its addr

There are also ascii const emitters:
BS
CR
LF
SPC

