feat(v4.0.0): logging, as v3
- capsule/log.v4: the level constants LOG-ERROR .. LOG-DEBUG, LOG-LEVEL! and LOG-LEVEL@, LOG-ERROR" .. LOG-DEBUG" and LOG-ERROR-STR .. LOG-DEBUG-STR. A message is printed if its level is at or below LOG-LEVEL, as v3's line -- colour, level, text -- without the time of day, which a node has not got. - LOG-xxx" compiles like ." : the level, a call to (LOG"), the text. SEE shows it as text. COLD puts LOG-LEVEL back to LOG-INFO. - tests/test_host_quit.c: ten transcripts of the v3 binary, every level at every setting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
8c540b0305
commit
384a6c1cd2
@@ -760,7 +760,7 @@ call would bury what it works on. A **compile-only** word may not be executed by
|
||||
`v4/capsule/forth.v4` holds the first words of the vocabulary flagged this way (`DUP`, `+`, `>R`, `I`,
|
||||
`LEAVE`, `@`, the in-line variables and so on).
|
||||
|
||||
**The vocabulary at the prompt.** The host node's capsule is `v4/capsule/`, loaded in this order: `core.v4` (bytes, console, strings the rest rest on), `input.v4`, `dict.v4`, `codegen.v4`, `compile.v4`, `quit.v4` (the prompt, faults and errors), `forth.v4` (stack, arithmetic, division, `DEPTH` `PICK` `ROLL`), `numout.v4` (number output, `.S`), `system.v4` (vocabularies, `WORDS`, `FORGET`, `COLD`, `DEFER`), then the two files of FORTH source the node compiles itself, `editor.fth` and `tools.fth` (`SEE`); `blocks.v4` (mass storage and `LOAD`), `qmath.v4` (the Q48.16 words of §5.26: `Q.FROM-INT Q.TO-INT Q.1 Q.0 Q.SCALE Q.+ Q.- Q.* Q./ Q.ABS Q.NEG Q.= Q.< Q.> Q.0= Q.MAX Q.MIN Q.EXP Q.SQRT Q.LOG Q.SIN Q.COS Q.PRINT`; `DUMP` is in `numout.v4`) and `words.v4` (the stack, comparison, shift, double, mixed and string words of §5.1–5.9: `2SWAP 2OVER 2ROT 2>R 2R> 2R@ 2@ 2! -! 0<> 0> <> <= >= U< U> ABS MAX MIN WITHIN LSHIFT RSHIFT D- DABS D0= D0< D= D2* D2/ D< DMAX DMIN M+ M- CMOVE> MOVE FILL ERASE BLANK -TRAILING COMPARE SEARCH SCAN SKIP ?TERMINAL TRUE FALSE INVERT NOP`). Each is the definition this document gives; `tests/test_host_quit.c` runs them from the prompt against transcripts of the v3 binary. From the prompt, 122 results of the Q words printed by `Q.PRINT` — which shows all sixteen bits of a fraction — are digit for digit v3's, at both cell widths. Under D-18, `Q./` by zero and `Q.SQRT` and `Q.LOG` outside their domain leave the result D-11 and D-12 give and then raise an error (codes 11 `Division by zero` and 12 `Argument out of range`); v3 returns 0 and says nothing. As v3, `LSHIFT` and `RSHIFT` with a count that is negative or as large as the cell is wide are an error (D-18, code 9, `Shift count out of range`). `M+`, like `M-` and `M/MOD`, takes its double in the standard order, low cell first; v3 takes it low cell on top.
|
||||
**The vocabulary at the prompt.** The host node's capsule is `v4/capsule/`, loaded in this order: `core.v4` (bytes, console, strings the rest rest on), `input.v4`, `dict.v4`, `codegen.v4`, `compile.v4`, `quit.v4` (the prompt, faults and errors), `forth.v4` (stack, arithmetic, division, `DEPTH` `PICK` `ROLL`), `numout.v4` (number output, `.S`), `system.v4` (vocabularies, `WORDS`, `FORGET`, `COLD`, `DEFER`), then the two files of FORTH source the node compiles itself, `editor.fth` and `tools.fth` (`SEE`); `blocks.v4` (mass storage and `LOAD`), `log.v4` (logging), `qmath.v4` (the Q48.16 words of §5.26: `Q.FROM-INT Q.TO-INT Q.1 Q.0 Q.SCALE Q.+ Q.- Q.* Q./ Q.ABS Q.NEG Q.= Q.< Q.> Q.0= Q.MAX Q.MIN Q.EXP Q.SQRT Q.LOG Q.SIN Q.COS Q.PRINT`; `DUMP` is in `numout.v4`) and `words.v4` (the stack, comparison, shift, double, mixed and string words of §5.1–5.9: `2SWAP 2OVER 2ROT 2>R 2R> 2R@ 2@ 2! -! 0<> 0> <> <= >= U< U> ABS MAX MIN WITHIN LSHIFT RSHIFT D- DABS D0= D0< D= D2* D2/ D< DMAX DMIN M+ M- CMOVE> MOVE FILL ERASE BLANK -TRAILING COMPARE SEARCH SCAN SKIP ?TERMINAL TRUE FALSE INVERT NOP`). Each is the definition this document gives; `tests/test_host_quit.c` runs them from the prompt against transcripts of the v3 binary. From the prompt, 122 results of the Q words printed by `Q.PRINT` — which shows all sixteen bits of a fraction — are digit for digit v3's, at both cell widths. Under D-18, `Q./` by zero and `Q.SQRT` and `Q.LOG` outside their domain leave the result D-11 and D-12 give and then raise an error (codes 11 `Division by zero` and 12 `Argument out of range`); v3 returns 0 and says nothing. As v3, `LSHIFT` and `RSHIFT` with a count that is negative or as large as the cell is wide are an error (D-18, code 9, `Shift count out of range`). `M+`, like `M-` and `M/MOD`, takes its double in the standard order, low cell first; v3 takes it low cell on top.
|
||||
|
||||
**The stacks and the compiler.** The interpreter and compiler run on the same stacks as the user's
|
||||
words, with the user's values beneath them. The capsule was written for stacks of ten cells and nine
|
||||
@@ -914,15 +914,25 @@ index should use them; they cost one instruction per iteration.
|
||||
|
||||
### 5.25 Logging
|
||||
|
||||
A message has a level, and is printed if its level is at or below `LOG-LEVEL`. Source in
|
||||
`v4/capsule/log.v4`; executed on the golden model's host node (2026-10-05) against transcripts of the v3
|
||||
binary.
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `LOG-ERROR` … `LOG-DEBUG` (levels) | IN | Constants. |
|
||||
| `LOG-LEVEL!` `LOG-LEVEL@` | CAP | Variable. |
|
||||
| `LOG-ERROR"` … `LOG-DEBUG"` | CC | |
|
||||
| `LOG-*-STR` | DEV | Log-ring service on the recorder (the ARM). |
|
||||
| `(do-log-*)` | CC | |
|
||||
| `LOG-ERROR` … `LOG-DEBUG` (levels) | IN | Constants, as v3: `LOG-ERROR` 0, `LOG-WARN` 1, `LOG-INFO` 2, `LOG-TEST` 3, `LOG-DEBUG` 4. |
|
||||
| `LOG-LEVEL!` `LOG-LEVEL@` | CAP | A variable, 2 (`LOG-INFO`) at switch-on and after `COLD`. As v3, `LOG-LEVEL!` takes a level below 0 as 0 and one above 4 as 4. |
|
||||
| `LOG-ERROR"` … `LOG-DEBUG"` | CC | `LOG-xxx" text"` logs the text now, if interpreting, or when the word it is compiled into runs. Compiled as `."` is: the level as a literal, a call to `(LOG")`, and the text after it. |
|
||||
| `LOG-*-STR` | DEV | `( baddr u -- )`: log a string at that level. On the mesh this is the log-ring service on the recorder (the ARM); until then it goes to the console. |
|
||||
| `(LOG")` | CC | The run-time word of `LOG-xxx"`, compile-only. It stands for v3's five `(do-log-*)`. |
|
||||
| `(LOG-APPEND-RAW)` | DEV | |
|
||||
|
||||
**What is printed** is v3's line without its time of day, which a node has not got: the level's colour, its
|
||||
name and a colon, the colour off, the text, a new line — `ESC[32mINFO: ESC[0mtext` — with red for `ERROR`,
|
||||
yellow `WARN`, green `INFO`, magenta `TEST`, blue `DEBUG`. v3's `LOG-DEBUG` level also turns on the
|
||||
interpreter's own trace of every word; v4 has no such trace. A string logged with a negative length is
|
||||
D-18's `Negative count` when its level is shown, and is ignored when it is not.
|
||||
|
||||
### 5.26 Q48.16 fixed-point math
|
||||
|
||||
A Q48.16 value is 64 bits, so on a 32-bit node it occupies **two cells** and every Q word is a double
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
\ log.v4 -- logging, as v3: a message has a level, and is printed if the
|
||||
\ level is at or below LOG-LEVEL.
|
||||
\
|
||||
\ DECOMPOSITION.md 5.25: the level constants LOG-ERROR LOG-WARN LOG-INFO
|
||||
\ LOG-TEST LOG-DEBUG (0 .. 4), LOG-LEVEL! LOG-LEVEL@, LOG-ERROR" ... LOG-DEBUG"
|
||||
\ and LOG-ERROR-STR ... LOG-DEBUG-STR. Part of the compiler capsule; rests
|
||||
\ on core.v4, codegen.v4 and quit.v4.
|
||||
\
|
||||
\ WHAT IS PRINTED is v3's line without its time of day, which a node has
|
||||
\ not got: the level's colour, the level's name and a colon, the colour off,
|
||||
\ the text, a new line --
|
||||
\ ESC [32m INFO: ESC [0m text
|
||||
\ On the mesh a message will go to the recorder's log ring (5.25); until
|
||||
\ then it goes to the console.
|
||||
\
|
||||
\ Constants the loader supplies:
|
||||
\ (LOG-LEVEL) word address of the variable: 2, LOG-INFO, at switch-on
|
||||
|
||||
header LOG-ERROR inline : LOG-ERROR 0 ;
|
||||
header LOG-WARN inline : LOG-WARN 1 ;
|
||||
header LOG-INFO inline : LOG-INFO 2 ;
|
||||
header LOG-TEST inline : LOG-TEST 3 ;
|
||||
header LOG-DEBUG inline : LOG-DEBUG 4 ;
|
||||
|
||||
header LOG-LEVEL@
|
||||
: LOG-LEVEL@ ( -- n ) (LOG-LEVEL) a! @ ;
|
||||
\ ( n -- ) as v3: a level below 0 is 0, one above 4 is 4
|
||||
header LOG-LEVEL!
|
||||
: LOG-LEVEL!
|
||||
-if POS drop 0 jump SET
|
||||
POS: dup -5 + -if BIG drop jump SET
|
||||
BIG: drop drop 4
|
||||
SET: (LOG-LEVEL) a! ! ;
|
||||
|
||||
\ ( baddr u level -- ) the message, if the level is at or below LOG-LEVEL
|
||||
: (LOG)
|
||||
dup inv (LOG-LEVEL) a! @ + 1 + -if SHOW drop drop drop drop ; \ LOG-LEVEL - level
|
||||
SHOW: drop
|
||||
if P0 -1 + if P1 -1 + if P2 -1 + if P3 -1 + if P4
|
||||
drop jump OUT
|
||||
P0: drop $31335B1B (EMIT4) $6D (EMIT4) $4F525245 (EMIT4) $203A52 (EMIT4) $6D305B1B (EMIT4) jump OUT
|
||||
P1: drop $33335B1B (EMIT4) $6D (EMIT4) $4E524157 (EMIT4) $203A (EMIT4) $6D305B1B (EMIT4) jump OUT
|
||||
P2: drop $32335B1B (EMIT4) $6D (EMIT4) $4F464E49 (EMIT4) $203A (EMIT4) $6D305B1B (EMIT4) jump OUT
|
||||
P3: drop $35335B1B (EMIT4) $6D (EMIT4) $54534554 (EMIT4) $203A (EMIT4) $6D305B1B (EMIT4) jump OUT
|
||||
P4: drop $34335B1B (EMIT4) $6D (EMIT4) $55424544 (EMIT4) $203A47 (EMIT4) $6D305B1B (EMIT4) jump OUT
|
||||
OUT: TYPE jump CR
|
||||
|
||||
header LOG-ERROR-STR : LOG-ERROR-STR ( baddr u -- ) 0 jump (LOG)
|
||||
header LOG-WARN-STR : LOG-WARN-STR ( baddr u -- ) 1 jump (LOG)
|
||||
header LOG-INFO-STR : LOG-INFO-STR ( baddr u -- ) 2 jump (LOG)
|
||||
header LOG-TEST-STR : LOG-TEST-STR ( baddr u -- ) 3 jump (LOG)
|
||||
header LOG-DEBUG-STR : LOG-DEBUG-STR ( baddr u -- ) 4 jump (LOG)
|
||||
|
||||
\ ( level -- ) the run time of LOG-xxx" : the text is after the call, as
|
||||
\ for ." ; log it at that level and go on after it.
|
||||
header (LOG") compile-only
|
||||
: (LOG")
|
||||
pop 4* dup C@ over + 4/ 1 + push \ level baddr R: the cell after the text
|
||||
COUNT ROT jump (LOG)
|
||||
|
||||
\ ( level -- ) LOG-xxx" text" logs the text -- now, if interpreting; when
|
||||
\ the word it is compiled into runs, if compiling. (Q)+3 holds the level.
|
||||
: (LOG-QUOTE)
|
||||
(Q)+3 a! ! 34 (PARSE) drop
|
||||
STATE a! @ if NOW
|
||||
drop (Q)+3 a! @ (LIT,) &(LOG") (CALL,) jump (STRING,)
|
||||
NOW: drop WBUF COUNT (Q)+3 a! @ jump (LOG)
|
||||
header LOG-ERROR" immediate : LOG-ERROR-QUOTE 0 jump (LOG-QUOTE)
|
||||
header LOG-WARN" immediate : LOG-WARN-QUOTE 1 jump (LOG-QUOTE)
|
||||
header LOG-INFO" immediate : LOG-INFO-QUOTE 2 jump (LOG-QUOTE)
|
||||
header LOG-TEST" immediate : LOG-TEST-QUOTE 3 jump (LOG-QUOTE)
|
||||
header LOG-DEBUG" immediate : LOG-DEBUG-QUOTE 4 jump (LOG-QUOTE)
|
||||
@@ -141,7 +141,7 @@ header COLD
|
||||
(BOOT)+1 a! @ (LATEST) a! !
|
||||
(BOOT) a! @ 2/ 2/ FENCE a! !
|
||||
(LATEST) CONTEXT a! ! (LATEST) CURRENT a! ! 0 VOC-LINK a! !
|
||||
10 BASE a! ! 0 SCR a! ! EMPTY-BUFFERS
|
||||
10 BASE a! ! 0 SCR a! ! 2 (LOG-LEVEL) a! ! EMPTY-BUFFERS
|
||||
$54524F46 (EMIT4) $39372D48 (EMIT4) $6C6F4320 (EMIT4) $74532064 (EMIT4) $747261 (EMIT4) CR
|
||||
$74737953 (EMIT4) $69206D65 (EMIT4) $6974696E (EMIT4) $7A696C61 (EMIT4) $2E6465 (EMIT4) CR
|
||||
jump ABORT
|
||||
|
||||
@@ -46,7 +46,8 @@ VARIABLE (SN) \ how many lines
|
||||
\ ( addr -- ) after a call to addr: if it is one of the words that are
|
||||
\ followed by text, show the text and count its cells with the literals
|
||||
: (TEXT?)
|
||||
DUP ['] (.") = OVER ['] (ABORT") = OR SWAP ['] (S") = OR IF
|
||||
DUP ['] (.") = OVER ['] (ABORT") = OR OVER ['] (LOG") = OR
|
||||
SWAP ['] (S") = OR IF
|
||||
(SP) @ (SLITS) @ + 4 * COUNT 34 EMIT 2DUP TYPE 34 EMIT SPACE
|
||||
SWAP DROP 4 + 4 / (SLITS) +!
|
||||
THEN ;
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
#define SRC (BVARS + 8)
|
||||
#define SRC_HOOK (BVARS + 9)
|
||||
#define STORAGE_REG (BVARS + 10)
|
||||
#define LOG_LEVEL (BUF0_W - 5) /* the level at or below which a message is printed */
|
||||
#define BOOT_CELLS (BVARS + 14) /* (BOOT): DP and LATEST as the loader left them, 2 cells */
|
||||
#define BUF0_W (BVARS - 2 * 256) /* the two block buffers, 256 cells each */
|
||||
#define BUF1_W (BUF0_W + 256)
|
||||
@@ -130,6 +131,7 @@ static int host_load(v4_text *tx, v4_node *n, const char *const *files, unsigned
|
||||
v4_text_constant(tx, "(X)", XVARS);
|
||||
v4_text_constant(tx, "(B)", BVARS);
|
||||
v4_text_constant(tx, "(BOOT)", BOOT_CELLS);
|
||||
v4_text_constant(tx, "(LOG-LEVEL)", LOG_LEVEL);
|
||||
v4_text_constant(tx, "SCR", SCR);
|
||||
v4_text_constant(tx, "BLK", BLK);
|
||||
v4_text_constant(tx, "(SRC)", SRC);
|
||||
|
||||
@@ -101,6 +101,7 @@ static void boot_with(unsigned depth)
|
||||
n.mem[BOOT_CELLS] = n.mem[DP];
|
||||
n.mem[BOOT_CELLS + 1] = capsule_latest;
|
||||
n.mem[FENCE] = DICT_W;
|
||||
n.mem[LOG_LEVEL] = 2;
|
||||
n.mem[CONTEXT] = LATEST;
|
||||
n.mem[CURRENT] = LATEST;
|
||||
n.mem[VOC_LINK] = 0;
|
||||
@@ -380,6 +381,36 @@ static const transcript script[] = {
|
||||
{ "Q.0 Q.LOG 65 EMIT\n-1 Q.FROM-INT Q.LOG\n", "Argument out of range\n ERROR\nok> Argument out of range\n ERROR\nok> ", 0 },
|
||||
{ "7 PAD -1 DUMP 65 EMIT\n.S\n", "Negative count\n ERROR\nok> <1> 7 \n ok\nok> ", 0 },
|
||||
{ "PAD 0 DUMP\n", " ok\nok> ", 1 },
|
||||
/* log.v4: v3's lines, colours and all, without its time of day */
|
||||
{ "LOG-LEVEL@ . LOG-ERROR . LOG-WARN . LOG-INFO . LOG-TEST . LOG-DEBUG .\n",
|
||||
"2 0 1 2 3 4 ok\nok> ", 1 },
|
||||
{ "LOG-INFO\" hello info\"\nLOG-WARN\" careful\"\nLOG-ERROR\" bad\"\nLOG-DEBUG\" dbg\"\nLOG-TEST\" tst\"\n",
|
||||
"\033[32mINFO: \033[0mhello info\n ok\nok> \033[33mWARN: \033[0mcareful\n ok\nok> \033[31mERROR: \033[0mbad\n ok\nok> ok\nok> ok\nok> ", 1 },
|
||||
{ ": T LOG-INFO\" from a word\" 65 EMIT ; T\n",
|
||||
"\033[32mINFO: \033[0mfrom a word\nA ok\nok> ", 1 },
|
||||
{ "S\" a string\" LOG-INFO-STR\nS\" w\" LOG-WARN-STR S\" e\" LOG-ERROR-STR\nS\" d\" LOG-DEBUG-STR S\" t\" LOG-TEST-STR\n",
|
||||
"\033[32mINFO: \033[0ma string\n ok\nok> \033[33mWARN: \033[0mw\n\033[31mERROR: \033[0me\n ok\nok> ok\nok> ", 1 },
|
||||
{ "0 LOG-LEVEL! LOG-LEVEL@ . LOG-ERROR\" e0\" LOG-WARN\" w0\"\n",
|
||||
/* v3 prints the 0 after the message: its log goes to stderr at once and its numbers to stdout when the line ends */
|
||||
"0 \033[31mERROR: \033[0me0\n ok\nok> ", 0 },
|
||||
{ "99 LOG-LEVEL! LOG-LEVEL@ . 4 LOG-LEVEL! LOG-DEBUG\" d\" 5 LOG-LEVEL! LOG-LEVEL@ .\n", "4 \033[34mDEBUG: \033[0md\n4 ok\nok> ", 0 },
|
||||
{ "7 S\" abc\" LOG-DEBUG-STR 8 PAD -1 LOG-DEBUG-STR .S\n", "<2> 7 8 \n ok\nok> ", 0 },
|
||||
{ "7 PAD -1 LOG-ERROR-STR 65 EMIT\n.S\n", "\033[31mERROR: \033[0mNegative count\n ERROR\nok> <1> 7 \n ok\nok> ", 0 },
|
||||
{ "LOG-WARN\" no closing quote\n", "\033[33mWARN: \033[0mno closing quote\n ok\nok> ", 0 },
|
||||
{ ": L3 LOG-INFO\" abcd\" 65 EMIT LOG-DEBUG\" hidden\" 66 EMIT ; L3 .S\n", "\033[32mINFO: \033[0mabcd\nAB<0> \n ok\nok> ", 0 },
|
||||
{ "(LOG\")\n", "(LOG\"): compile-only\n ERROR\nok> ", 0 },
|
||||
{ "1 LOG-LEVEL! LOG-ERROR\" e1\" LOG-WARN\" w1\" LOG-INFO\" i1\"\n",
|
||||
"\033[31mERROR: \033[0me1\n\033[33mWARN: \033[0mw1\n ok\nok> ", 1 },
|
||||
{ "2 LOG-LEVEL! LOG-ERROR\" e2\" LOG-WARN\" w2\" LOG-INFO\" i2\" LOG-TEST\" t2\"\n",
|
||||
"\033[31mERROR: \033[0me2\n\033[33mWARN: \033[0mw2\n\033[32mINFO: \033[0mi2\n ok\nok> ", 1 },
|
||||
{ "3 LOG-LEVEL! LOG-INFO\" i3\" LOG-TEST\" t3\" LOG-DEBUG\" d3\"\n",
|
||||
"\033[32mINFO: \033[0mi3\n\033[35mTEST: \033[0mt3\n ok\nok> ", 1 },
|
||||
{ "-1 LOG-LEVEL! LOG-LEVEL@ .\n",
|
||||
"0 ok\nok> ", 1 },
|
||||
{ "LOG-INFO\" \"\n",
|
||||
"\033[32mINFO: \033[0m\n ok\nok> ", 1 },
|
||||
{ ": W LOG-ERROR\" e\" LOG-WARN\" w\" LOG-TEST\" t\" ; W 3 LOG-LEVEL! W\n",
|
||||
"\033[31mERROR: \033[0me\n\033[33mWARN: \033[0mw\n\033[31mERROR: \033[0me\n\033[33mWARN: \033[0mw\n\033[35mTEST: \033[0mt\n ok\nok> ", 1 },
|
||||
/* blocks.v4 */
|
||||
{ "20 BLOCK 1024 BLANK 65 20 BLOCK C! UPDATE SAVE-BUFFERS 20 BLOCK C@ .\n",
|
||||
"65 ok\nok> ", 1 },
|
||||
@@ -547,8 +578,8 @@ int main(void)
|
||||
printf("v4 host prompt tests: V4_CELL_BITS=%d, V4_NODE_WORDS=%u\n", V4_CELL_BITS, (unsigned)V4_NODE_WORDS);
|
||||
|
||||
{
|
||||
static const char *const files[] = { "core.v4", "input.v4", "dict.v4", "codegen.v4", "compile.v4", "quit.v4", "forth.v4", "numout.v4", "words.v4", "system.v4", "qmath.v4", "blocks.v4" };
|
||||
CHECK(host_load(&tx, &n, files, 12), "the capsule assembles");
|
||||
static const char *const files[] = { "core.v4", "input.v4", "dict.v4", "codegen.v4", "compile.v4", "quit.v4", "forth.v4", "numout.v4", "words.v4", "system.v4", "qmath.v4", "blocks.v4", "log.v4" };
|
||||
CHECK(host_load(&tx, &n, files, 13), "the capsule assembles");
|
||||
}
|
||||
CHECK(v4_text_finish(&tx), "everything is defined: %s", v4_text_error(&tx));
|
||||
CHECK(v4_text_here(&tx) < DICT_W, "code stays below the dictionary space");
|
||||
@@ -1065,6 +1096,7 @@ int main(void)
|
||||
}
|
||||
CHECK(is(say(": S4 .\" abcd\" 65 EMIT ; SEE S4\n"), ": S4\n call (.\") \"abcd\" \n @p 65 call EMIT \n ; \n ok\nok> "), "text that fills its last cell but for the count");
|
||||
CHECK(is(say("SEE *\n"), out) && strstr(out, " +* unext drop drop a ; \n"), "the longest opcode name, in the capsule's multiply");
|
||||
CHECK(is(say(": LG LOG-WARN\" look\" 65 EMIT ; SEE LG\n"), ": LG\n @p 1 call (LOG\") \"look\" \n @p 65 call EMIT \n ; \n ok\nok> "), "a logged message is shown as text, after its level");
|
||||
CHECK(is(say("SEE NOSUCH\n"), "SEE: not found\n ok\nok> ") && is(say("SEE\n"), "SEE: not found\n ok\nok> "), "a word that is not there");
|
||||
CHECK(is(say("(.\")\n"), "(.\"): compile-only\n ERROR\nok> ") && is(say("(S\")\n"), "(S\"): compile-only\n ERROR\nok> "), "the string run-time words have names but cannot be run from the prompt");
|
||||
|
||||
@@ -1080,10 +1112,11 @@ int main(void)
|
||||
CHECK(is(say(": KEEPME 1 ; 1 2 3 WARM 65 EMIT\n.S KEEPME .\n"), "FORTH-79 Warm Start\nSystem restarted.\n ok\nok> <0> \n1 ok\nok> "), "WARM empties the stacks and keeps the dictionary");
|
||||
{
|
||||
v4_cell dp = n.mem[BOOT_CELLS];
|
||||
CHECK(is(say("VOCABULARY VV VV DEFINITIONS : INVV 1 ; HEX 20 BLOCK DROP UPDATE 5 SCR !\n"), " ok\nok> "), "a vocabulary, a base, a block, a screen");
|
||||
CHECK(is(say("VOCABULARY VV VV DEFINITIONS : INVV 1 ; HEX 20 BLOCK DROP UPDATE 5 SCR !\n"), " ok\nok> ")
|
||||
&& is(say("4 LOG-LEVEL!\n"), " ok\nok> "), "a vocabulary, a base, a block, a screen, a log level");
|
||||
CHECK(is(say("1 2 COLD 65 EMIT\n"), "FORTH-79 Cold Start\nSystem initialized.\n ok\nok> "), "COLD says so");
|
||||
CHECK(n.mem[DP] == dp && n.mem[LATEST] == capsule_latest && n.mem[CONTEXT] == LATEST && n.mem[CURRENT] == LATEST && n.mem[VOC_LINK] == 0
|
||||
&& n.mem[BASE] == 10 && n.mem[SCR] == 0 && n.mem[BVARS] == 0 && n.mem[FENCE] == dp / 4, "and everything is as the loader left it");
|
||||
&& n.mem[BASE] == 10 && n.mem[SCR] == 0 && n.mem[BVARS] == 0 && n.mem[FENCE] == dp / 4 && n.mem[LOG_LEVEL] == 2, "and everything is as the loader left it");
|
||||
CHECK(is(say("KEEPME\n"), "UNKNOWN WORD: 'KEEPME'\n ERROR\nok> ") && is(say("VV\n"), "UNKNOWN WORD: 'VV'\n ERROR\nok> ")
|
||||
&& is(say(".S : NEW 16 . ; NEW\n"), "<0> \n16 ok\nok> "), "what was defined is gone, and the system works");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user