doc: out-of-system documentation
I've changed my mind about having documentation in-system. It doesn't serve much of a purpose and make blkfs significantly heavier. This commit is the first step in writing a documentation outside of the blkfs.
This commit is contained in:
parent
c4db9d4420
commit
ffcd93699e
33
doc/intro.txt
Normal file
33
doc/intro.txt
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Introduction to Collapse OS
|
||||||
|
|
||||||
|
Collapse OS is a minimal operating system created to preserve
|
||||||
|
the ability to program microcontrollers through civilizational
|
||||||
|
collapse. Its author expect the collapse of the global supply
|
||||||
|
chain means the loss of our computer production capability. Many
|
||||||
|
microcontrollers require a computer to program them.
|
||||||
|
|
||||||
|
Collapse OS innovates by self-hosting on extremely tight resour-
|
||||||
|
ces and is thus (theoretically thus far) able to operate and be
|
||||||
|
improved in a world without modern computers.
|
||||||
|
|
||||||
|
# Forth
|
||||||
|
|
||||||
|
This OS is a Forth. It doesn't adhere to any pre-collapse stand-
|
||||||
|
ard, but is pretty close to the Forth described by Starting
|
||||||
|
Forth by Leo Brodie. It is therefore the recommended introduct-
|
||||||
|
ory material to learn Forth in the context of Collapse OS.
|
||||||
|
|
||||||
|
If you don't have access to this book and don't know anything
|
||||||
|
about Forth, learning Collapse OS could be a rough ride, but
|
||||||
|
don't despair. There's a Forth primer in primer.txt.
|
||||||
|
|
||||||
|
# Documentation and self-hosting
|
||||||
|
|
||||||
|
Collapse OS is self-hosting, its documentation is not, that is,
|
||||||
|
Collapse OS cannot read this document you're reading. Text
|
||||||
|
blocks could, of course, be part of Collapse OS' blocks, but
|
||||||
|
doing so needlessly uses blocks and make the system heavier than
|
||||||
|
it should.
|
||||||
|
|
||||||
|
This documentation is expected to be printed before the last
|
||||||
|
modern computer of your community dies.
|
201
doc/primer.txt
Normal file
201
doc/primer.txt
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
# Forth Primer
|
||||||
|
|
||||||
|
# First steps
|
||||||
|
|
||||||
|
Before you read this primer, let's try a few commands, just for
|
||||||
|
fun.
|
||||||
|
|
||||||
|
42 .
|
||||||
|
|
||||||
|
This will push the number 42 to the stack, then print the number
|
||||||
|
at the top of the stack.
|
||||||
|
|
||||||
|
4 2 + .
|
||||||
|
|
||||||
|
This pushes 4, then 2 to the stack, then adds the 2 numbers on
|
||||||
|
the top of the stack, then prints the result.
|
||||||
|
|
||||||
|
42 0x8000 C! 0x8000 C@ .
|
||||||
|
|
||||||
|
This writes the byte "42" at address 0x8000, and then reads
|
||||||
|
back that bytes from the same address and print it.
|
||||||
|
|
||||||
|
# Interpreter loop
|
||||||
|
|
||||||
|
Forth's main interpeter loop is very simple:
|
||||||
|
|
||||||
|
1. Read a word from input
|
||||||
|
2. Look it up in the dictionary
|
||||||
|
3. Found? Execute.
|
||||||
|
4. Not found?
|
||||||
|
4.1. Is it a number?
|
||||||
|
4.2. Yes? Parse and push on the Parameter Stack.
|
||||||
|
4.3. No? Error.
|
||||||
|
5. Repeat
|
||||||
|
|
||||||
|
# Word
|
||||||
|
|
||||||
|
A word is a string of non-whitepace characters. We consider that
|
||||||
|
we're finished reading a word when we encounter a whitespace
|
||||||
|
after having read at least one non-whitespace character
|
||||||
|
|
||||||
|
# Character encoding
|
||||||
|
|
||||||
|
Collapse OS doesn't support any other encoding than 7bit ASCII.
|
||||||
|
A character smaller than 0x21 is considered a whitespace,
|
||||||
|
others are considered non-whitespace.
|
||||||
|
|
||||||
|
Characters above 0x7f have no special meaning and can be used in
|
||||||
|
words (if your system has glyphs for them).
|
||||||
|
|
||||||
|
# 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),
|
||||||
|
but you can define new words with the ":" word. For example:
|
||||||
|
|
||||||
|
: FOO 42 . ;
|
||||||
|
|
||||||
|
defines a new word "FOO" with the code "42 ." linked to it. The
|
||||||
|
word ";" closes the definition. Once defined, a word can be
|
||||||
|
executed like any other word.
|
||||||
|
|
||||||
|
You can define a word that already exists. In that case, the new
|
||||||
|
definition will overshadow the old one. However, any word def-
|
||||||
|
ined *before* the overshadowing took place will still use the
|
||||||
|
old word.
|
||||||
|
|
||||||
|
# Cell size
|
||||||
|
|
||||||
|
The cell size in Collapse OS is 16 bit, that is, each item in
|
||||||
|
stacks is 16 bit, @ and ! read and write 16 bit numbers.
|
||||||
|
Whenever we refer to a number, a pointer, we speak of 16 bit.
|
||||||
|
|
||||||
|
To read and write bytes, use C@ and C!.
|
||||||
|
|
||||||
|
# Number literals
|
||||||
|
|
||||||
|
Traditional Forth often uses HEX/DEC switches to go from deci-
|
||||||
|
mal to hexadecimal parsing. Collapse OS parses literals in a
|
||||||
|
way that is closer to C.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
# Parameter Stack
|
||||||
|
|
||||||
|
Unlike most programming languages, Forth execute words directly,
|
||||||
|
without arguments. The Parameter Stack (PS) replaces them. There
|
||||||
|
is only one, and we're constantly pushing to and popping from
|
||||||
|
it. All the time.
|
||||||
|
|
||||||
|
For example, the word "+" pops the 2 number on the Top Of Stack
|
||||||
|
(TOS), adds them, then pushes back the result on the same stack.
|
||||||
|
It thus has the "stack signature" of "a b -- n". Every word in
|
||||||
|
a dictionary specifies that signature because stack balance, as
|
||||||
|
you can guess, is paramount. It's easy to get confused so you
|
||||||
|
need to know the stack signature of words you use very well.
|
||||||
|
|
||||||
|
# Return Stack
|
||||||
|
|
||||||
|
There's a second stack, the Return Stack (RS), which is used to
|
||||||
|
keep track of execution, that is, to know where to go back after
|
||||||
|
we've executed a word. It is also used in other contexts, but
|
||||||
|
this is outside of the scope of this primer.
|
||||||
|
|
||||||
|
# Conditional execution
|
||||||
|
|
||||||
|
Code can be executed conditionally with IF/ELSE/THEN. IF pops
|
||||||
|
PS and checks whether its nonzero. If it is, it does nothing.
|
||||||
|
If it's zero, it jumps to the following ELSE or the following
|
||||||
|
THEN. Similarly, when ELSE is encountered in the context of a
|
||||||
|
nonzero IF, we jump to the following THEN.
|
||||||
|
|
||||||
|
Because IFs involve jumping, they only work inside word defin-
|
||||||
|
itions. You can't use IF directly in the interpreter loop.
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
|
||||||
|
: FOO IF 42 ELSE 43 THEN . ;
|
||||||
|
0 FOO --> 42
|
||||||
|
1 FOO --> 43
|
||||||
|
|
||||||
|
# Loops
|
||||||
|
|
||||||
|
Loops work a bit like conditionals, and there's 3 forms:
|
||||||
|
|
||||||
|
BEGIN..AGAIN --> Loop forever
|
||||||
|
BEGIN..UNTIL --> Loop conditionally
|
||||||
|
DO..LOOP --> Loop X times
|
||||||
|
|
||||||
|
UNTIL works exactly like IF, but instead of jumping forward to
|
||||||
|
THEN, it jumps backward to BEGIN.
|
||||||
|
|
||||||
|
DO pops the lower, then the higher bounds of the loop to be
|
||||||
|
executed, then pushes them on RS. Then, each time LOOP is
|
||||||
|
encountered, RS' TOS is increased. As long as the 2 numbers at
|
||||||
|
RS' TOS aren't equal, we jump back to DO.
|
||||||
|
|
||||||
|
The word "I" copies RS' TOS to PS, which can be used to get our
|
||||||
|
"loop counter".
|
||||||
|
|
||||||
|
Beware: the bounds arguments for DO are unintuitive. We begin
|
||||||
|
with the upper bound. Example:
|
||||||
|
|
||||||
|
42 0 DO I . SPC LOOP
|
||||||
|
|
||||||
|
Will print numbers 0 to 41, separated by a space.
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
|
||||||
|
We can read and write to arbitrary memory address with @ and !
|
||||||
|
(C@ and C! for bytes). For example, "1234 0x8000 !" writes the
|
||||||
|
word 1234 to address 0x8000.
|
||||||
|
|
||||||
|
The word "VARIABLE" link a name to an address. For example,
|
||||||
|
"VARIABLE FOO" defines the word "FOO" and "reserves" 2 bytes of
|
||||||
|
memory. Then, when FOO is executed, it pushes the address of the
|
||||||
|
"reserved" area to PS.
|
||||||
|
|
||||||
|
For example, "1234 FOO !" writes 1234 to memory address reserved
|
||||||
|
for FOO.
|
||||||
|
|
||||||
|
# IMMEDIATE
|
||||||
|
|
||||||
|
We approach the end of our primer. So far, we've covered the
|
||||||
|
"cute and cuddly" parts of the language. However, that's not
|
||||||
|
what makes Forth powerful. Forth becomes mind-bending when we
|
||||||
|
throw IMMEDIATE into the mix.
|
||||||
|
|
||||||
|
A word can be declared immediate thus:
|
||||||
|
|
||||||
|
: FOO ; IMMEDIATE
|
||||||
|
|
||||||
|
That is, when the IMMEDIATE word is executed, it makes the
|
||||||
|
latest defined word immediate.
|
||||||
|
|
||||||
|
An immediate word, when used in a definition, is executed
|
||||||
|
immediately instead of being compiled. This seemingly simple
|
||||||
|
mechanism (and it *is* simple) has very wide implications.
|
||||||
|
|
||||||
|
For example, The words "(" and ")" are comment indicators. In
|
||||||
|
the definition:
|
||||||
|
|
||||||
|
: FOO 42 ( this is a comment ) . ;
|
||||||
|
|
||||||
|
The word "(" is read like any other word. What prevents us from
|
||||||
|
trying to compile "this" and generate an error because the word
|
||||||
|
doesn't exist? Because "(" is immediate. Then, that word reads
|
||||||
|
from input stream until a ")" is met, and then returns to word
|
||||||
|
compilation.
|
||||||
|
|
||||||
|
Words like "IF", "DO", ";" are all regular Forth words, but
|
||||||
|
their "power" come from the fact that they're immediate.
|
||||||
|
|
||||||
|
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
|
||||||
|
a while, browse the dictionary (B30) and try to understand why
|
||||||
|
this or that word is immediate. Good luck!
|
Loading…
Reference in New Issue
Block a user