Compare commits
No commits in common. "a3c3a2f44a33710ad0b6d49f278d9723a9e5cbab" and "d3dbeb450fe36ee754ff0555bc155c8aa8031cc7" have entirely different histories.
a3c3a2f44a
...
d3dbeb450f
16
blk/003
16
blk/003
@ -2,15 +2,15 @@ Collapse OS usage guide
|
||||
|
||||
This document is not meant to be an introduction to Forth, but
|
||||
to instruct the user about the peculiarities of this Forth
|
||||
implementation. The recommended introductory book is Starting
|
||||
Forth by Leo Brodie. This is the reference that was used to
|
||||
build this implementation and many of the conventions described
|
||||
in this book are followed in Collapse OS. Be sure to refer to
|
||||
the dictionary (B30) for a word reference.
|
||||
implemenation. Be sure to refer to dictionary for a word
|
||||
reference.
|
||||
|
||||
Contents
|
||||
|
||||
4 Number literals 6 Compilation vs meta-comp.
|
||||
8 Interpreter I/O 11 Signed-ness
|
||||
14 Addressed devices 17 DOES>
|
||||
4 DOES> 6 Compilation vs meta-comp.
|
||||
8 I/O 14 Addressed devices
|
||||
18 Signed-ness
|
||||
|
||||
|
||||
|
||||
|
||||
|
23
blk/004
23
blk/004
@ -1,11 +1,16 @@
|
||||
Number literals
|
||||
DOES>
|
||||
|
||||
Traditional Forth often use HEX/DEC switches to go from decimal
|
||||
to hexadecimal parsing. Collapse OS parses literals in a way
|
||||
that is closer to C.
|
||||
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> @ ;"
|
||||
|
||||
Straight numbers are decimals, numbers starting with "0x"
|
||||
are hexadecimals (example "0x12ef"), "0b" prefixes indicate
|
||||
binary (example "0b1010"), char literals are single characters
|
||||
surrounded by ' (example 'X'). Char literals can't be used for
|
||||
whitespaces.
|
||||
|
26
blk/008
26
blk/008
@ -1,16 +1,16 @@
|
||||
Interpreter I/O
|
||||
I/O
|
||||
|
||||
The INTERPRET loop, the heart of Collapse OS, feeds itself
|
||||
from the C< word, which yields a character every time it is
|
||||
called. If no character is available to interpret, it blocks.
|
||||
A little word about inputs. There are two kind of inputs:
|
||||
direct and buffered. As a general rule, we read line in a
|
||||
buffer, then feed words in it to the interpreter. That's what
|
||||
"WORD" does. If it's at the End Of Line, it blocks and wait
|
||||
until another line is entered.
|
||||
|
||||
During normal operations, C< is simply a buffered layer over
|
||||
KEY, which has the same behavior (but unbuffered). Before
|
||||
yielding any character, the C< routine fetches a whole line
|
||||
from KEY, puts it in a buffer, then yields the buffered line,
|
||||
one character at once.
|
||||
KEY input, however, is direct. Regardless of the input buffer's
|
||||
state, KEY will return the next typed key.
|
||||
|
||||
Both C< and KEY can be overridden by setting an alternate
|
||||
routine at the proper RAM offset (see B80). For example, C<
|
||||
overrides are used during LOAD so that input comes from
|
||||
disk blocks instead of keyboard. (cont.)
|
||||
PARSING AND BOOTSTRAP: Parsing number literal is a very "core"
|
||||
activity of Forth, and therefore generally seen as having to be
|
||||
implemented in native code. However, Collapse OS' Forth
|
||||
supports many kinds of literals: decimal, hex, char, binary.
|
||||
This incurs a significant complexity penalty. (cont.)
|
||||
|
20
blk/009
20
blk/009
@ -1,6 +1,16 @@
|
||||
KEY overrides can be used to, for example, temporarily give
|
||||
prompt control to a RS-232 device instead of the keyboard.
|
||||
(cont.) What if we could implement those parsing routines in
|
||||
Forth? "But it's a core routine!" you say. Yes, but here's the
|
||||
deal: at its native core, only decimal parsing is supported. It
|
||||
lives in the "(parsed)" word. The interpreter's main loop is
|
||||
initially set to simply call that word.
|
||||
|
||||
However, in core.fs, "(parsex)", "(parsec)" and "(parseb)" are
|
||||
implemented, in Forth, then "(parse)", which goes through them
|
||||
all is defined. Then, "(parsef)", which is the variable in
|
||||
which the interpreter's word pointer is set, is updated to that
|
||||
new "(parse)" word.
|
||||
|
||||
This way, we have a full-featured (and extensible) parsing with
|
||||
a tiny native core.
|
||||
|
||||
|
||||
Interpreter output is unbuffered and only has EMIT. This
|
||||
word can also be overriden, mostly as a companion to the
|
||||
raison d'etre of your KEY override.
|
||||
|
16
blk/017
16
blk/017
@ -1,16 +0,0 @@
|
||||
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> @ ;"
|
||||
|
12
blk/031
12
blk/031
@ -7,10 +7,10 @@ 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" 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@.
|
||||
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.
|
||||
(cont.)
|
||||
|
1
blk/032
1
blk/032
@ -1,3 +1,4 @@
|
||||
(cont.)
|
||||
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
|
||||
|
6
blk/037
6
blk/037
@ -10,7 +10,7 @@ Entry management
|
||||
, 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.
|
||||
EMPTY -- Rewind HERE and CURRENT where they were at
|
||||
system initialization.
|
||||
|
||||
(cont.)
|
||||
system initialization. (cont.)
|
||||
|
2
blk/040
2
blk/040
@ -8,7 +8,7 @@ CREATE x -- Create cell named x. Doesn't allocate a PF.
|
||||
COMPILE x -- Meta compiles. See B6.
|
||||
CONSTANT x n -- Creates cell x that when called pushes its
|
||||
value.
|
||||
DOES> -- See B17.
|
||||
DOES> -- See B4.
|
||||
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.
|
||||
|
16
blk/129
16
blk/129
@ -1,16 +0,0 @@
|
||||
( Note that the last word is always skipped because it's not
|
||||
possible to reliably detect its end. If you need that last
|
||||
word, define a dummy word before calling RLDICT.
|
||||
|
||||
We first start by copying the affected area to H@+4. This is
|
||||
where the relinking will take place.
|
||||
|
||||
Then we iterate the new dict from the top, keeping track of
|
||||
wr, the current wordref and we, wr's end offset.
|
||||
|
||||
Initially, we get our wr and we, withH@ and CURRENT, which we
|
||||
offset by u+4. +4 before, remember, we're using 4 bytes
|
||||
as variable space.
|
||||
|
||||
At each iteration, we becomes wr-header and wr is fetched from
|
||||
PREV field. )
|
32
blk/130
32
blk/130
@ -1,16 +1,16 @@
|
||||
: RLDICT ( target offset -- )
|
||||
H@ 2+ ! H@ ! ( H@+2 == offset, H@ == target )
|
||||
H@ @ WORD( DUP H@ -^ ( src u )
|
||||
DUP ROT SWAP H@ 4 + ( u src u dst )
|
||||
SWAP MOVE ( u )
|
||||
4 + DUP CURRENT @ WORD( + ( u we )
|
||||
DUP .X CRLF
|
||||
SWAP CURRENT @ PREV + DUP .X CRLF ( we wr )
|
||||
BEGIN ( we wr )
|
||||
DUP ROT ( wr wr we )
|
||||
H@ @ H@ 2+ @ ( wr wr we ol o )
|
||||
2SWAP RLWORD ( wr )
|
||||
DUP PREV SWAP ( wr oldwr )
|
||||
WORD( SWAP ( we wr )
|
||||
DUP 4 - H@ <= ( are we finished? )
|
||||
UNTIL H@ 4 + .X CRLF ;
|
||||
( Note that the last word is always skipped because it's not
|
||||
possible to reliably detect its end. If you need that last
|
||||
word, define a dummy word before calling RLDICT.
|
||||
|
||||
We first start by copying the affected area to H@+4. This is
|
||||
where the relinking will take place.
|
||||
|
||||
Then we iterate the new dict from the top, keeping track of
|
||||
wr, the current wordref and we, wr's end offset.
|
||||
|
||||
Initially, we get our wr and we, withH@ and CURRENT, which we
|
||||
offset by u+4. +4 before, remember, we're using 4 bytes
|
||||
as variable space.
|
||||
|
||||
At each iteration, we becomes wr-header and wr is fetched from
|
||||
PREV field. )
|
||||
|
25
blk/131
25
blk/131
@ -1,9 +1,16 @@
|
||||
( Relink a regular Forth full interpreter. )
|
||||
: RLCORE
|
||||
LIT< H@ (find) DROP ( target )
|
||||
DUP 3 - @ ( t prevoff )
|
||||
( subtract H@ name length )
|
||||
2- ( t o )
|
||||
RLDICT
|
||||
;
|
||||
|
||||
: RLDICT ( target offset -- )
|
||||
H@ 2+ ! H@ ! ( H@+2 == offset, H@ == target )
|
||||
H@ @ WORD( DUP H@ -^ ( src u )
|
||||
DUP ROT SWAP H@ 4 + ( u src u dst )
|
||||
SWAP MOVE ( u )
|
||||
4 + DUP CURRENT @ WORD( + ( u we )
|
||||
DUP .X CRLF
|
||||
SWAP CURRENT @ PREV + DUP .X CRLF ( we wr )
|
||||
BEGIN ( we wr )
|
||||
DUP ROT ( wr wr we )
|
||||
H@ @ H@ 2+ @ ( wr wr we ol o )
|
||||
2SWAP RLWORD ( wr )
|
||||
DUP PREV SWAP ( wr oldwr )
|
||||
WORD( SWAP ( we wr )
|
||||
DUP 4 - H@ <= ( are we finished? )
|
||||
UNTIL H@ 4 + .X CRLF ;
|
||||
|
9
blk/132
Normal file
9
blk/132
Normal file
@ -0,0 +1,9 @@
|
||||
( Relink a regular Forth full interpreter. )
|
||||
: RLCORE
|
||||
LIT< H@ (find) DROP ( target )
|
||||
DUP 3 - @ ( t prevoff )
|
||||
( subtract H@ name length )
|
||||
2- ( t o )
|
||||
RLDICT
|
||||
;
|
||||
|
BIN
emul/forth.bin
BIN
emul/forth.bin
Binary file not shown.
Loading…
Reference in New Issue
Block a user