\ 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! ! ;