94 lines
3.9 KiB
Plaintext
94 lines
3.9 KiB
Plaintext
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.
|
|
|
|
DOES>: Used inside a colon definition that itself uses CREATE, DOES> transforms
|
|
that newly created word into a "does cell", that is, a regular cell ( when
|
|
called, puts the cell's addr on PS), but right after that, it executes words
|
|
that appear after the DOES>.
|
|
|
|
"does cells" always allocate 4 bytes (2 for the cell, 2 for the DOES> link) and
|
|
there is no need for ALLOT in colon definition.
|
|
|
|
At compile time, colon definition stops processing words when reaching the
|
|
DOES>.
|
|
|
|
Example: ": CONSTANT CREATE HERE @ ! DOES> @ ;"
|
|
|
|
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.
|
|
|
|
*** Defining words ***
|
|
: x ... -- Define a new word
|
|
; R:I -- Exit a colon definition
|
|
ALLOT n -- Move HERE by n bytes
|
|
CREATE x -- Create cell named x. Doesn't allocate a PF.
|
|
CONSTANT x n -- Creates cell x that when called pushes its value
|
|
DOES> -- See description at top of file
|
|
IMMEDIATE -- Flag the latest defined word as immediate.
|
|
LITERAL n -- Inserts number from TOS as a literal
|
|
VARIABLE c -- Creates cell x with 2 bytes allocation.
|
|
|
|
*** Flow ***
|
|
ELSE -- Branch to THEN
|
|
EXECUTE a -- Execute wordref at addr a
|
|
IF n -- Branch to ELSE or THEN if n is zero
|
|
INTERPRET -- Get a line from stdin, compile it in tmp memory,
|
|
then execute the compiled contents.
|
|
QUIT R:drop -- Return to interpreter promp immediately
|
|
RECURSE R:I -- R:I-2 Run the current word again.
|
|
THEN -- Does nothing. Serves as a branching merker for IF
|
|
and ELSE.
|
|
|
|
*** Stack ***
|
|
DUP a -- a a
|
|
OVER a b -- a b a
|
|
SWAP a b -- b 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
|
|
|
|
*** 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 -- n Set n to wordref of last added entry.
|
|
HERE -- a Push HERE's address
|
|
|
|
*** Arithmetic ***
|
|
|
|
+ a b -- c a + b -> c
|
|
- a b -- c a - b -> c
|
|
* a b -- c a * b -> c
|
|
/ 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@ x -- a Read folloing LIT and push its addr to a
|
|
S= a1 a2 -- n Compare strings a1 and a2. See CMP
|
|
|
|
*** I/O ***
|
|
. n -- Print n in its decimal form
|
|
EMIT c -- Spit char c to stdout
|
|
KEY -- c Get char c from stdin
|
|
PC! c a -- Spit c to port a
|
|
PC@ a -- c Fetch c from port a
|
|
|