Files
LithosAnanake/capsules/v4/rom/in.f18
T
rajamesandClaude Opus 5.5 a28b5f2230 fix(v4): the final review's six minors in the ROM boot
- Text after start is refused, as text.c refuses it: before it jumps, the
  ROM reads on to the end of the source; blanks, comments and the ends of
  blobs may follow, a token is ERR-AFTER (26), "text after start".
- A token too long where a name, a target or a value is wanted is "name
  too long", as text.c says: (MISSING) reports "missing" only when no error
  came first.  `", keeps "missing", which is text.c's word for both.
- text.c's "address out of range" names the address, not the value.
- The system's source files are one list, v4/sys_files.h: boot.c, the
  harness and the nucleus test are made from it.
- The ROM's error codes and words are one list, v4/rom_errors.h: boot.c's
  messages, host_map.h's ROM_ERR_* and mkmap's ERR-* are made from it.
- node.h says what v4_node_store does with a ROM address (nothing, as for
  any address outside RAM, D-14); test_host_rom_range pins it.

ROM: 2095 words, rom_hash 0x06d0dcb7a0cb41a1.  dict_hash unchanged,
0xe5a57f3eb72ff94a.  make -C v4 test test-32 hosted-check pass.  QEMU:
amd64, aarch64, riscv64 to ok>, POST 538/538, POST: PASSED.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 17:10:45 -04:00

126 lines
4.1 KiB
Plaintext

\ in.f18 -- the ROM's input: characters from the console, and tokens.
\
\ The text the ROM assembles arrives at the console's receive registers,
\ a character at a time. Each blob of it ends with a new line and FS (28,
\ V4_ROM_BLOB_END), where a file ends for text.c: a comment still open there
\ is an error, and (TOKEN) gives 0 there as at the end. The end of all of
\ it is EOT (4), which the loader sends after the last blob. A token is what v4/src/text.c's next_token makes
\ of the same text: blanks are space, tab, CR and LF; a token is at most 63
\ characters; `\` as a whole token skips to the end of the line, and `(` as a
\ whole token to the next `)`.
\
\ State, in the ROM's area of the memory map (MACHINE.md 2.1):
\ (TOK) the token, as a counted string: its count byte, then its
\ characters, four to a cell, low byte first, zero-padded --
\ the form `",` lays down and (FIND) compares; 16 cells
\ (TOKN) its length
\ (PEEK) a character put back, plus one; 0: none
\ (LINE) how many new lines have been read
\ (EOF) non-zero once EOT has been read
\ (FAILED) 0, or the code of the error that stopped the ROM
\ (ERRLINE) (LINE) when it failed
\ (RAW) 1 while a token is read raw: ( and \ are then names
\ Every routine here uses A.
\ ( -- c ) wait for a character, then take it
: (KEY)
W: CONSOLE-STATUS a! @ if Z drop CONSOLE-RX a! @ ;
Z: drop jump W
\ ( -- c ) the character put back, if there is one; else the next
: (GETC)
(PEEK) a! @ if NONE 0 ! -1 + ;
NONE: drop jump (KEY)
\ ( c -- ) put a character back, to be the next one read
: (BACK) 1 + (PEEK) a! ! ;
\ ( -- ) one more new line
: (LF+) (LINE) a! @ 1 + ! ;
\ ( code -- ) stop with an error, noting the line
: (FAIL) (FAILED) a! ! (LINE) a! @ (ERRLINE) a! ! ;
\ ( -- ) "missing": a name, a target or a value was wanted and there is
\ none -- unless an error came first, a token too long or a comment not
\ closed, which stands, as text.c's first error does
: (MISSING)
(FAILED) a! @ if M drop ;
M: drop ERR-MISSING jump (FAIL)
\ ( c -- ) one more character of the token: byte (TOKN)+1 of (TOK), into
\ a cell whose byte there is still zero
: (PUT)
(TOKN) a! @ 1 +
dup 2/ 2/ (TOK) + push
3 and
S: if SD push 2* 2* 2* 2* 2* 2* 2* 2* pop -1 + jump S
SD: drop pop a! @ xor !
(TOKN) a! @ 1 + ! ;
\ ( i -- c ) character i of the token, from 0
: (CHAR@)
1 + dup 2/ 2/ (TOK) + a! @
push 3 and
S: if SD -1 + pop 2/ 2/ 2/ 2/ 2/ 2/ 2/ 2/ push jump S
SD: drop pop 255 and ;
\ ( -- len ) the next token into (TOK), its length into (TOKN). 0: the end
\ of a blob, the end of all ((EOF) set), or an error, which is in (FAILED).
: (TOKEN)
(EOF) a! @ if GO drop 0 ;
GO: drop
SKIP: (GETC)
dup 4 xor if END
drop dup 28 xor if BLOB
drop dup 10 xor if NL
drop dup 32 xor if SP
drop dup 9 xor if SP
drop dup 13 xor if SP
drop 0 (TOKN) a! !
(TOK) a! 15 FOR 0 !+ NEXT
READ: (TOKN) a! @ 63 xor if LONG
drop (PUT) (GETC)
dup 4 xor if TEND
drop dup 28 xor if TEND
drop dup 10 xor if TEND
drop dup 32 xor if TEND
drop dup 9 xor if TEND
drop dup 13 xor if TEND
drop jump READ
TEND: drop (BACK)
(TOKN) a! @ (TOK) a! @ xor !
(RAW) a! @ if COOKED drop (TOKN) a! @ ;
COOKED: drop
(TOKN) a! @ 1 xor if ONE
drop (TOKN) a! @ ;
ONE: drop 0 (CHAR@)
dup 92 xor if BSL
drop dup 40 xor if PAREN
drop drop 1 ;
BSL: drop drop
B1: (GETC)
dup 10 xor if BEND
drop dup 28 xor if BEND
drop dup 4 xor if BEND
drop drop jump B1
BEND: drop (BACK) jump SKIP
PAREN: drop drop
P1: (GETC)
dup 41 xor if PCLOSE
drop dup 10 xor if PNL
drop dup 28 xor if PEOF
drop dup 4 xor if PEOF
drop drop jump P1
PNL: drop drop (LF+) jump P1
PCLOSE: drop drop jump SKIP
PEOF: drop drop ERR-COMMENT (FAIL) 0 ;
END: drop drop 1 (EOF) a! ! 0 ;
BLOB: drop drop 0 ;
NL: drop drop (LF+) jump SKIP
SP: drop drop jump SKIP
LONG: drop drop ERR-TOO-LONG (FAIL) 0 ;
\ ( -- len ) the next token, raw: ( and \ are names, not comments
: (RAW-TOKEN) 1 (RAW) a! ! (TOKEN) 0 (RAW) a! ! ;