\ 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. The end 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 \ 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! ! ; \ ( 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, \ 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 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 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 ! (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 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 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 ; NL: drop drop (LF+) jump SKIP SP: drop drop jump SKIP LONG: drop drop ERR-TOO-LONG (FAIL) 0 ;