mirror of
https://github.com/hsoft/collapseos.git
synced 2024-12-26 16:48:05 +11:00
doc: take dictionary out of blkfs
This commit is contained in:
parent
d03d93668f
commit
fd69195799
2
blk/001
2
blk/001
@ -1,6 +1,6 @@
|
|||||||
MASTER INDEX
|
MASTER INDEX
|
||||||
|
|
||||||
30 Dictionary 100 Block editor
|
100 Block editor
|
||||||
120 Visual Editor 150 Extra words
|
120 Visual Editor 150 Extra words
|
||||||
200 Z80 assembler 260 Cross compilation
|
200 Z80 assembler 260 Cross compilation
|
||||||
280 Z80 boot code 350 Core words
|
280 Z80 boot code 350 Core words
|
||||||
|
12
blk/030
12
blk/030
@ -1,12 +0,0 @@
|
|||||||
Dictionary
|
|
||||||
|
|
||||||
List of words defined in Inner core (B390), Core words (B420)
|
|
||||||
and Extra words (B150).
|
|
||||||
|
|
||||||
31 Glossary 34 Symbols
|
|
||||||
37 Entry management 40 Defining words
|
|
||||||
42 Flow 46 Parameter stack
|
|
||||||
48 Return stack 50 Memory
|
|
||||||
52 Addressed devices 54 Arithmetic / Bits
|
|
||||||
56 Logic 58 Strings
|
|
||||||
60 I/O 64 Disk
|
|
16
blk/031
16
blk/031
@ -1,16 +0,0 @@
|
|||||||
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 word's *code link*. For example,
|
|
||||||
the address that "' DUP" puts on the stack is a wordref, that
|
|
||||||
is, a reference to the code link of the word DUP.
|
|
||||||
|
|
||||||
PF: Parameter field. The area following the code link of a
|
|
||||||
word. For example, "' H@ 1+" points to the PF of the word H@.
|
|
||||||
(cont.)
|
|
9
blk/032
9
blk/032
@ -1,9 +0,0 @@
|
|||||||
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.
|
|
16
blk/034
16
blk/034
@ -1,16 +0,0 @@
|
|||||||
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)
|
|
||||||
(cont.)
|
|
3
blk/035
3
blk/035
@ -1,3 +0,0 @@
|
|||||||
(cont.)
|
|
||||||
~ - Container for native code. Usually not an executable word.
|
|
||||||
? - Is it ...? (example: IMMED?)
|
|
16
blk/037
16
blk/037
@ -1,16 +0,0 @@
|
|||||||
Entry management
|
|
||||||
|
|
||||||
'? x -- a f Find x 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.
|
|
||||||
FIND w -- a f Like '?, but for w.
|
|
||||||
EMPTY -- Rewind HERE and CURRENT where they were at
|
|
||||||
system initialization.
|
|
||||||
(cont.)
|
|
5
blk/038
5
blk/038
@ -1,5 +0,0 @@
|
|||||||
(cont.)
|
|
||||||
FORGET x -- Rewind the dictionary (both CURRENT and HERE)
|
|
||||||
up to x's previous entry.
|
|
||||||
PREV a -- a Return a wordref's previous entry.
|
|
||||||
WORD( a -- a Get wordref's beginning addr.
|
|
15
blk/040
15
blk/040
@ -1,15 +0,0 @@
|
|||||||
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. See B6.
|
|
||||||
CONSTANT x n -- Creates cell x that when called pushes its
|
|
||||||
value.
|
|
||||||
DOES> -- See B17.
|
|
||||||
IMMED? a -- f Checks whether wordref at a is immediate.
|
|
||||||
IMMEDIATE -- Flag the latest defined word as immediate.
|
|
||||||
LITN n -- Write number n as a literal.
|
|
||||||
VARIABLE c -- Creates cell x with 2 bytes allocation.
|
|
16
blk/042
16
blk/042
@ -1,16 +0,0 @@
|
|||||||
Flow
|
|
||||||
|
|
||||||
Note that 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.
|
|
||||||
|
|
||||||
f IF A ELSE B THEN: if f is true, execute A, if false, execute
|
|
||||||
B. ELSE is optional.
|
|
||||||
[IF] .. [THEN]: Meta-IF. Works outside definitions. No [ELSE].
|
|
||||||
BEGIN .. f UNTIL: if f is false, branch to BEGIN.
|
|
||||||
BEGIN .. AGAIN: Always branch to BEGIN.
|
|
||||||
x y DO .. LOOP: LOOP increments y. if y != x, branch to DO.
|
|
||||||
|
|
||||||
|
|
||||||
(cont.)
|
|
16
blk/043
16
blk/043
@ -1,16 +0,0 @@
|
|||||||
x CASE y OF A ENDOF z OF B ENDOF C ENDCASE: If x == y, execute
|
|
||||||
A, if x == z, execute B. Otherwise, execute C. x is dropped
|
|
||||||
in case of an OF match, *but it is kept if it reaches C*. You
|
|
||||||
have to consume it to avoid PSP leak.
|
|
||||||
|
|
||||||
(br) -- Branches by the number specified in the 2
|
|
||||||
following bytes. Can be negative.
|
|
||||||
(?br) f -- Branch if f is false.
|
|
||||||
( -- *I* Comment. Ignore input until ")" is read.
|
|
||||||
[ -- Begin interpretative mode. In a definition,
|
|
||||||
execute words instead of compiling them.
|
|
||||||
] -- End interpretative mode.
|
|
||||||
ABORT -- Resets PS and RS and returns to interpreter.
|
|
||||||
ABORT" x" -- *I* Compiles a ." followed by a ABORT.
|
|
||||||
ERR a -- Prints a and ABORT. Defined early and used by
|
|
||||||
drivers. (cont.)
|
|
5
blk/044
5
blk/044
@ -1,5 +0,0 @@
|
|||||||
EXECUTE a -- Execute wordref at addr a
|
|
||||||
INTERPRET -- Get a line from stdin, compile it in tmp memory,
|
|
||||||
then execute the compiled contents.
|
|
||||||
LEAVE -- In a DO..LOOP, exit at the next LOOP call.
|
|
||||||
QUIT -- Return to interpreter prompt immediately
|
|
16
blk/046
16
blk/046
@ -1,16 +0,0 @@
|
|||||||
Parameter Stack
|
|
||||||
|
|
||||||
DROP a --
|
|
||||||
DUP a -- a a
|
|
||||||
?DUP DUP if a is nonzero
|
|
||||||
NIP a b -- b
|
|
||||||
OVER a b -- a b a
|
|
||||||
ROT a b c -- b c a
|
|
||||||
SWAP a b -- b a
|
|
||||||
TUCK a b -- b a b
|
|
||||||
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
|
|
||||||
'S Returns current stack pointer, not counting the
|
|
||||||
push it's making right now. (cont.)
|
|
6
blk/047
6
blk/047
@ -1,6 +0,0 @@
|
|||||||
S0 Returns address of PSP TOS. When PSP is empty,
|
|
||||||
'S == S0
|
|
||||||
PICK Pick nth item from stack. "0 PICK" = DUP,
|
|
||||||
"1 PICK" = OVER.
|
|
||||||
ROLL Rotate PSP over n items. "1 ROLL" = SWAP,
|
|
||||||
"2 ROLL" = ROT. 0 is noop.
|
|
9
blk/048
9
blk/048
@ -1,9 +0,0 @@
|
|||||||
Return Stack
|
|
||||||
|
|
||||||
>R n -- R:n Pops PS and push to RS
|
|
||||||
2>R x y -- R:x y Equivalent to SWAP >R >R
|
|
||||||
R> R:n -- n Pops RS and push to PS
|
|
||||||
2R> R:x y -- x y Equivalent to R> R> SWAP
|
|
||||||
I -- n Copy RS TOS to PS
|
|
||||||
I' -- n Copy RS second item to PS
|
|
||||||
J -- n Copy RS third item to PS
|
|
16
blk/050
16
blk/050
@ -1,16 +0,0 @@
|
|||||||
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
|
|
||||||
BIT@ b a -- f Get bit b from addr a.
|
|
||||||
BIT! f b a -- Set bit b to f in addr a.
|
|
||||||
C@ a -- c Set c to byte at address a
|
|
||||||
C@+ a -- a+1 c Fetch c from a and inc a.
|
|
||||||
C@- a -- a-1 c Fetch c from a and dec a.
|
|
||||||
C! c a -- Store byte c in address a
|
|
||||||
C!+ c a -- a+1 Store byte c in a and inc a.
|
|
||||||
C!- c a -- a-1 Store byte c in a and dec a.
|
|
||||||
CURRENT -- a Set a to wordref of last added entry.
|
|
||||||
(cont.)
|
|
10
blk/051
10
blk/051
@ -1,10 +0,0 @@
|
|||||||
CURRENT* -- a A pointer to active CURRENT*. Useful
|
|
||||||
when we have multiple active dicts.
|
|
||||||
FILL a n b -- Fill n bytes at addr a with val b.
|
|
||||||
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.
|
|
||||||
MOVE- a1 a2 u -- Copy u bytes from a1 to a2, starting
|
|
||||||
with a1+u, going down.
|
|
||||||
MOVE, a u -- Copy u bytes from a to HERE.
|
|
10
blk/052
10
blk/052
@ -1,10 +0,0 @@
|
|||||||
Addressed devices
|
|
||||||
|
|
||||||
See B14 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!
|
|
16
blk/054
16
blk/054
@ -1,16 +0,0 @@
|
|||||||
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
|
|
||||||
LSHIFT a u -- c a << u -> c
|
|
||||||
RSHIFT a u -- c a >> u -> c
|
|
||||||
|
|
||||||
Shortcuts: 1+ 2+ 1- 2-
|
|
12
blk/056
12
blk/056
@ -1,12 +0,0 @@
|
|||||||
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
|
|
||||||
>< n l h -- f Push true if l < n < h
|
|
||||||
=><= n l h -- f Push true if l <= n <= h
|
|
||||||
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.
|
|
||||||
MIN a b -- n Returns the lowest of a and b
|
|
||||||
MAX a b -- n Returns the highest of a and b
|
|
||||||
NOT f -- f Push the logical opposite of f
|
|
7
blk/058
7
blk/058
@ -1,7 +0,0 @@
|
|||||||
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.
|
|
||||||
S= a1 a2 -- f Returns whether string a1 == a2.
|
|
16
blk/060
16
blk/060
@ -1,16 +0,0 @@
|
|||||||
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)
|
|
||||||
(print) a -- Print string at addr a. Stops at 0x0 or 0xd.
|
|
||||||
. 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
|
|
||||||
|
|
||||||
|
|
||||||
(cont.)
|
|
16
blk/061
16
blk/061
@ -1,16 +0,0 @@
|
|||||||
," xxx" -- Write xxx to HERE
|
|
||||||
." xxx" -- *I* Compiles string literal xxx followed by a
|
|
||||||
call to (print).
|
|
||||||
C<? -- f Returns whether there's a char waiting in buf.
|
|
||||||
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
|
|
||||||
|
|
||||||
(cont.)
|
|
9
blk/062
9
blk/062
@ -1,9 +0,0 @@
|
|||||||
WORD -- a Read one word from buffered input and push its
|
|
||||||
addr. Always null terminated. If ASCII EOT is
|
|
||||||
encountered, a will point to it (it is cons-
|
|
||||||
idered a word).
|
|
||||||
There are also ascii const emitters:
|
|
||||||
BS CR LF SPC CRLF
|
|
||||||
NL is an indirect word (see B80) that aliases to CRLF by
|
|
||||||
default and that should generally be used when we want to emit
|
|
||||||
a newline.
|
|
16
blk/064
16
blk/064
@ -1,16 +0,0 @@
|
|||||||
Disk
|
|
||||||
|
|
||||||
BLK> -- a Address of the current block variable.
|
|
||||||
BLK( -- a Beginning addr of blk buf.
|
|
||||||
BLK) -- a Ending addr of blk buf.
|
|
||||||
COPY s d -- Copy contents of s block to d block.
|
|
||||||
FLUSH -- Write current block to disk if dirty.
|
|
||||||
FREEBLKS? a b -- List free blocks between blocks a and b.
|
|
||||||
LIST n -- Prints the contents of the block n on screen
|
|
||||||
in the form of 16 lines of 64 columns.
|
|
||||||
LOAD n -- Interprets Forth code from block n
|
|
||||||
LOAD+ n -- Relative load. Loads active block + n.
|
|
||||||
LOADR n1 n2 -- Load block range between n1 and n2, inclusive.
|
|
||||||
LOADR+ n1 n2 -- Relative ranged load.
|
|
||||||
WIPE -- Empties current block
|
|
||||||
WIPED? -- f Whether current block is empty
|
|
3
blk/150
3
blk/150
@ -6,8 +6,7 @@ disk blocks access running. The goal here is to minimize the
|
|||||||
binary size of a minimum Collapse OS install.
|
binary size of a minimum Collapse OS install.
|
||||||
|
|
||||||
Extra words are words you will most likely want because they
|
Extra words are words you will most likely want because they
|
||||||
are generally useful. They are so useful that they are part
|
are generally useful.
|
||||||
of the Dictionary (B30).
|
|
||||||
|
|
||||||
Some programs need them, so they will automatically LOAD them.
|
Some programs need them, so they will automatically LOAD them.
|
||||||
Because more than one program can use the same extra words,
|
Because more than one program can use the same extra words,
|
||||||
|
2
cvm/vm.c
2
cvm/vm.c
@ -108,7 +108,7 @@ static void pushRS(word val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The functions below directly map to native forth words defined in the
|
// The functions below directly map to native forth words defined in the
|
||||||
// dictionary (B30)
|
// dictionary (doc/dict.txt)
|
||||||
static void execute(word wordref) {
|
static void execute(word wordref) {
|
||||||
byte wtype = vm.mem[wordref];
|
byte wtype = vm.mem[wordref];
|
||||||
if (wtype == 0) { // native
|
if (wtype == 0) { // native
|
||||||
|
281
doc/dict.txt
Normal file
281
doc/dict.txt
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
# Dictionary
|
||||||
|
|
||||||
|
List of words defined in Inner core (B390), Core words (B420)
|
||||||
|
and Extra words (B150).
|
||||||
|
|
||||||
|
# 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 word's *code link*. For example,
|
||||||
|
the address that "' DUP" puts on the stack is a wordref, that
|
||||||
|
is, a reference to the code link of the word DUP.
|
||||||
|
|
||||||
|
PF: Parameter field. The area following the code link of a
|
||||||
|
word. For example, "' H@ 1+" points to the PF of the word H@.
|
||||||
|
|
||||||
|
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)
|
||||||
|
? - Is it ...? (example: IMMED?)
|
||||||
|
|
||||||
|
# Entry management
|
||||||
|
|
||||||
|
'? x -- a f Find x 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.
|
||||||
|
FIND w -- a f Like '?, but for w.
|
||||||
|
EMPTY -- Rewind HERE and CURRENT where they were at
|
||||||
|
system initialization.
|
||||||
|
FORGET x -- Rewind the dictionary (both CURRENT and HERE)
|
||||||
|
up to x's previous entry.
|
||||||
|
PREV a -- a Return a wordref's previous entry.
|
||||||
|
WORD( a -- a Get wordref's beginning addr.
|
||||||
|
|
||||||
|
# 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. See B6.
|
||||||
|
CONSTANT x n -- Creates cell x that when called pushes its
|
||||||
|
value.
|
||||||
|
DOES> -- See primer.txt
|
||||||
|
IMMED? a -- f Checks whether wordref at a is immediate.
|
||||||
|
IMMEDIATE -- Flag the latest defined word as immediate.
|
||||||
|
LITN n -- Write number n as a literal.
|
||||||
|
VARIABLE c -- Creates cell x with 2 bytes allocation.
|
||||||
|
|
||||||
|
# Flow
|
||||||
|
|
||||||
|
Note that 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.
|
||||||
|
|
||||||
|
f IF A ELSE B THEN: if f is true, execute A, if false, execute
|
||||||
|
B. ELSE is optional.
|
||||||
|
[IF] .. [THEN]: Meta-IF. Works outside definitions. No [ELSE].
|
||||||
|
BEGIN .. f UNTIL: if f is false, branch to BEGIN.
|
||||||
|
BEGIN .. AGAIN: Always branch to BEGIN.
|
||||||
|
x y DO .. LOOP: LOOP increments y. if y != x, branch to DO.
|
||||||
|
|
||||||
|
x CASE y OF A ENDOF z OF B ENDOF C ENDCASE: If x == y, execute
|
||||||
|
A, if x == z, execute B. Otherwise, execute C. x is dropped
|
||||||
|
in case of an OF match, *but it is kept if it reaches C*. You
|
||||||
|
have to consume it to avoid PSP leak.
|
||||||
|
|
||||||
|
(br) -- Branches by the number specified in the 2
|
||||||
|
following bytes. Can be negative.
|
||||||
|
(?br) f -- Branch if f is false.
|
||||||
|
( -- *I* Comment. Ignore input until ")" is read.
|
||||||
|
[ -- Begin interpretative mode. In a definition,
|
||||||
|
execute words instead of compiling them.
|
||||||
|
] -- End interpretative mode.
|
||||||
|
ABORT -- Resets PS and RS and returns to interpreter.
|
||||||
|
ABORT" x" -- *I* Compiles a ." followed by a ABORT.
|
||||||
|
ERR a -- Prints a and ABORT. Defined early and used by
|
||||||
|
drivers.
|
||||||
|
EXECUTE a -- Execute wordref at addr a
|
||||||
|
INTERPRET -- Get a line from stdin, compile it in tmp memory,
|
||||||
|
then execute the compiled contents.
|
||||||
|
LEAVE -- In a DO..LOOP, exit at the next LOOP call.
|
||||||
|
QUIT -- Return to interpreter prompt immediately
|
||||||
|
|
||||||
|
# Parameter Stack
|
||||||
|
|
||||||
|
DROP a --
|
||||||
|
DUP a -- a a
|
||||||
|
?DUP DUP if a is nonzero
|
||||||
|
NIP a b -- b
|
||||||
|
OVER a b -- a b a
|
||||||
|
ROT a b c -- b c a
|
||||||
|
SWAP a b -- b a
|
||||||
|
TUCK a b -- b a b
|
||||||
|
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
|
||||||
|
'S Returns current stack pointer, not counting the
|
||||||
|
push it's making right now.
|
||||||
|
S0 Returns address of PSP TOS. When PSP is empty,
|
||||||
|
'S == S0
|
||||||
|
PICK Pick nth item from stack. "0 PICK" = DUP,
|
||||||
|
"1 PICK" = OVER.
|
||||||
|
ROLL Rotate PSP over n items. "1 ROLL" = SWAP,
|
||||||
|
"2 ROLL" = ROT. 0 is noop.
|
||||||
|
|
||||||
|
# Return Stack
|
||||||
|
|
||||||
|
>R n -- R:n Pops PS and push to RS
|
||||||
|
2>R x y -- R:x y Equivalent to SWAP >R >R
|
||||||
|
R> R:n -- n Pops RS and push to PS
|
||||||
|
2R> R:x y -- x y Equivalent to R> R> SWAP
|
||||||
|
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
|
||||||
|
BIT@ b a -- f Get bit b from addr a.
|
||||||
|
BIT! f b a -- Set bit b to f in addr a.
|
||||||
|
C@ a -- c Set c to byte at address a
|
||||||
|
C@+ a -- a+1 c Fetch c from a and inc a.
|
||||||
|
C@- a -- a-1 c Fetch c from a and dec a.
|
||||||
|
C! c a -- Store byte c in address a
|
||||||
|
C!+ c a -- a+1 Store byte c in a and inc a.
|
||||||
|
C!- c a -- a-1 Store byte c in a and dec 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.
|
||||||
|
FILL a n b -- Fill n bytes at addr a with val b.
|
||||||
|
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.
|
||||||
|
MOVE- a1 a2 u -- Copy u bytes from a1 to a2, starting
|
||||||
|
with a1+u, going down.
|
||||||
|
MOVE, a u -- Copy u bytes from a to HERE.
|
||||||
|
|
||||||
|
# Addressed devices
|
||||||
|
|
||||||
|
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
|
||||||
|
LSHIFT a u -- c a << u -> c
|
||||||
|
RSHIFT a u -- c a >> u -> c
|
||||||
|
|
||||||
|
Shortcuts: 1+ 2+ 1- 2-
|
||||||
|
|
||||||
|
# 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
|
||||||
|
>< n l h -- f Push true if l < n < h
|
||||||
|
=><= n l h -- f Push true if l <= n <= h
|
||||||
|
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.
|
||||||
|
MIN a b -- n Returns the lowest of a and b
|
||||||
|
MAX a b -- n Returns the highest of a and b
|
||||||
|
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.
|
||||||
|
S= a1 a2 -- f Returns whether string a1 == a2.
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
(print) a -- Print string at addr a. Stops at 0x0 or 0xd.
|
||||||
|
. 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" -- Write xxx to HERE
|
||||||
|
." xxx" -- *I* Compiles string literal xxx followed by a
|
||||||
|
call to (print).
|
||||||
|
C<? -- f Returns whether there's a char waiting in buf.
|
||||||
|
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. Always null terminated. If ASCII EOT is
|
||||||
|
encountered, a will point to it (it is cons-
|
||||||
|
idered a word).
|
||||||
|
|
||||||
|
There are also ascii const emitters:
|
||||||
|
BS CR LF SPC CRLF
|
||||||
|
|
||||||
|
NL is an indirect word (see SYSVARS in impl.txt) that aliases to
|
||||||
|
CRLF by default and that should generally be used when we want
|
||||||
|
to emit a newline.
|
||||||
|
|
||||||
|
# Disk
|
||||||
|
|
||||||
|
BLK> -- a Address of the current block variable.
|
||||||
|
BLK( -- a Beginning addr of blk buf.
|
||||||
|
BLK) -- a Ending addr of blk buf.
|
||||||
|
COPY s d -- Copy contents of s block to d block.
|
||||||
|
FLUSH -- Write current block to disk if dirty.
|
||||||
|
FREEBLKS? a b -- List free blocks between blocks a and b.
|
||||||
|
LIST n -- Prints the contents of the block n on screen
|
||||||
|
in the form of 16 lines of 64 columns.
|
||||||
|
LOAD n -- Interprets Forth code from block n
|
||||||
|
LOAD+ n -- Relative load. Loads active block + n.
|
||||||
|
LOADR n1 n2 -- Load block range between n1 and n2, inclusive.
|
||||||
|
LOADR+ n1 n2 -- Relative ranged load.
|
||||||
|
WIPE -- Empties current block
|
||||||
|
WIPED? -- f Whether current block is empty
|
@ -51,8 +51,9 @@ words (if your system has glyphs for them).
|
|||||||
# Dictionary
|
# Dictionary
|
||||||
|
|
||||||
Forth's dictionary link words to code. On boot, this dictionary
|
Forth's dictionary link words to code. On boot, this dictionary
|
||||||
contains the system's words (look in B30 for a list of them),
|
contains the system's words (look in dict.txt for a list of
|
||||||
but you can define new words with the ":" word. For example:
|
them), but you can define new words with the ":" word. For
|
||||||
|
example:
|
||||||
|
|
||||||
: FOO 42 . ;
|
: FOO 42 . ;
|
||||||
|
|
||||||
@ -245,5 +246,5 @@ their "power" come from the fact that they're immediate.
|
|||||||
|
|
||||||
Starting Forth by Leo Brodie explain all of this in details.
|
Starting Forth by Leo Brodie explain all of this in details.
|
||||||
Read this if you can. If you can't, well, let this sink in for
|
Read this if you can. If you can't, well, let this sink in for
|
||||||
a while, browse the dictionary (B30) and try to understand why
|
a while, browse the dictionary (dict.txt) and try to understand
|
||||||
this or that word is immediate. Good luck!
|
why this or that word is immediate. Good luck!
|
||||||
|
Loading…
Reference in New Issue
Block a user