|
- # Collapse OS usage guide
-
- If you already know Forth, start here. Otherwise, read primer
- first.
-
- We begin with a few oddities in Collapse OS compared to tradi-
- tional forths, then cover higher level operations.
-
- # Signed-ness
-
- For simplicity purposes, numbers are generally considered
- unsigned. For convenience, decimal parsing and formatting
- support the "-" prefix, but under the hood, it's all unsigned.
-
- This leads to some oddities. For example, "-1 0 <" is false.
- To compare whether something is negative, use the "0<" word
- which is the equivalent to "0x7fff >".
-
- # Branching
-
- Branching in Collapse OS is limited to 8-bit. This represents
- 64 word references forward or backward. While this might seem
- a bit tight at first, having this limit saves us a non-
- negligible amount of resource usage.
-
- The reasoning behind this intentional limit is that huge
- branches are generally an indicator that a logic ought to be
- simplified. So here's one more constraint for you to help you
- towards simplicity.
-
- # Interpreter 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.
-
- 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 a time.
-
- Both C< and KEY can be overridden by setting an alternate
- routine at the proper RAM offset (see impl.txt). For example,
- C< overrides are used during LOAD so that input comes from disk
- blocks instead of keyboard.
-
- KEY overrides can be used to, for example, temporarily give
- prompt control to a RS-232 device instead of the keyboard.
-
- 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.
-
- # Aliases
-
- A common pattern in Forth is to add an indirection layer with
- a pointer word. For example, if you have a word "FOO" for
- which you would like to add an indirection layer, you would
- rename "FOO" to "_FOO", add a variable "FOO*" pointing to
- "_FOO" and re-defining "FOO" as ": FOO FOO* @ EXECUTE".
-
- This is all well and good, but it is resource intensive and
- verbose, which make us want to avoid this pattern for words
- that are often used.
-
- For this purpose, Collapse OS has two special word types:
- alias and ialiases (indirect alias).
-
- An alias is a variable that contains a pointer to another word.
- When invoked, we invoke the specified pointer with minimal over-
- head. Using our FOO example above, we would create an alias
- with "' _FOO :* FOO". Invoking FOO will then invoke "_FOO". You
- can change the alias' pointer with "*!" like this:
- "' BAR ' FOO *!". FOO now invokes BAR.
-
- A ialias is like an alias, but with a second level of indi-
- rection. The variable points to a cell pointing to our word.
- It works like an alias, except you have to use ":**" and "**!".
- Ialiases are used by core code which point to hardcoded
- addresses in RAM (because the core code is designed to run from
- ROM, we can't have regular variables). You are unlikely to
- need ialiases in regular code.
-
- # Disk blocks
-
- Disk blocks are Collapse OS' main access to permanent storage.
- The system is exceedingly simple: blocks are contiguous
- chunks of 1024 bytes each living on some permanent media such
- as floppy disks or SD cards. They are mostly used for text,
- either informational or source code, which is organized into
- 16 lines of 64 characters each.
-
- Blocks are referred to by number, 0-indexed. They are read
- through BLK@ and written through BLK!. When a block is read,
- its 1024 bytes content is copied to an in-memory buffer
- starting at BLK( and ending at BLK). Those read/write
- operations are often implicit. For example, LIST calls BLK@.
-
- When a word modifies the buffer, it sets the buffer as dirty
- by calling BLK!!. BLK@ checks, before it reads its buffer,
- whether the current buffer is dirty and implicitly calls BLK!
- when it is.
-
- The index of the block currently in memory is kept in BLK>.
-
- Many blocks contain code. That code can be interpreted through
- LOAD. Programs stored in blocks frequently have "loader blocks"
- that take care of loading all blocks relevant to the program.
-
- # Spanning multiple disks
-
- Blocks spanning multiple disks are tricky. If your media isn't
- large enough to hold all Collapse OS blocks in one unit, you'll
- have to make it span multiple disks. Block reference in
- informational texts aren't a problem: When you swap your disk,
- you mentally adjust the block number you fetch.
-
- However, absolute LOAD operations in Collapse OS aren't aware
- of disk spanning and will not work properly in your spanned
- system.
-
- Although the usage of absolute LOAD calls are minimally used
- (relative LOADs are preferred), they are sometimes unavoidable.
- When you span Collapse OS over multiple disks, don't forget to
- adjust those absolute LOADs.
-
- When you work with multiple disks, you have to remember to FLUSH
- before swapping the disk. This will write current block if it's
- dirty and also invalidate the cache. This way, you're not at
- risk of either overwriting a block on your other disk or LOADing
- cached contents without noticing.
-
- # How blocks are organized
-
- Organization of contiguous blocks is an ongoing challenge and
- Collapse OS' blocks are never as tidy as they should, but we
- try to strive towards a few goals:
-
- 1. Block 0 contains documentation discovery core keys to the
- uninitiated.
- 2. B1-B4 are for a master index of blocks.
- 3. B5-B259 are for programs loaded at runtime.
- 4. B260-B599 are for bootstrapping a new core.
- 5. B600-B650 are for recipes.
-
- Recipes blocks do not live in the main blkfs, but each recipe
- has its own blkfs overlay, with blocks beginning at 600.
|