Files
LithosAnanake/v4/include/v4/post.h
T
rajamesandClaude Opus 5.5 18adf59091 fix(v4.0.0): POST leaves nothing, as v3 really does; and what the review of step 6b found
Captain Bob was told that v3 leaves the words POST's cases define in the
dictionary, and ruled that v4 should.  That was false: v3's run_test_suite
puts the dictionary back after each word's cases (test_common.c:333,
:365).  Shown that, he ruled that POST leaves nothing.  The boot now
seals the system, runs POST, and has the node do COLD, whose printing is
not shown; PARITY:V4_SYSTEM is the system as sealed.

A case the node does not come back from ends POST there, named, with how
many were not run: it would have stalled the boot for hours, where the
capsule had ended it.  The runner's test of it now uses a word that
really never ends.

hosted-check also requires that RS1 and T{ are unknown after boot, and
boots a program whose POST has failing cases (tests/post_cases_fail.c):
PARITY:FAIL, POST: FAILED, no prompt, none of a case's printing shown.

Comments and documents that still named the POST capsule or its two
hooks are brought up to date; NUCLEUS.md 6.3 says what v3 does, with the
lines, and how the wrong ruling came about.

make -C v4 test, sanitize and hosted-check pass; amd64, aarch64 and
riscv64 boot, POST 538 of 538, word_count=314, dict_hash
0x220ab283a504a3b3 on all six: logs/20261007-112638, -112901, -113220.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 11:40:20 -04:00

69 lines
3.4 KiB
C

/* post.h -- POST, which is the kernel's. docs/v4.0.0/NUCLEUS.md section 6.
*
* As in v3, the kernel holds the cases and runs them on the node: nothing
* of POST is in the node's dictionary. A case is a name, its lines of
* FORTH, and what it must do. The table is generated from v3's own cases
* (v4/tools/mkpost.py -> v4/system/post_cases.c).
*/
#ifndef V4_POST_H
#define V4_POST_H
#include "v4/node.h"
#define V4_POST_STACK 0 /* its data stack and what it prints are compared */
#define V4_POST_DEPTH 1 /* only how many values it leaves; what it prints is not compared */
#define V4_POST_DEPTH_OUTPUT 2 /* how many values it leaves, and what it prints */
#define V4_POST_ERROR 3 /* it must end in an error; nothing else is compared */
typedef struct {
const char *name;
const char *const *lines; /* line_count of them, sent one at a time */
unsigned line_count;
int expect; /* V4_POST_* */
const long long *stack; /* V4_POST_STACK: depth values, the deepest first; else 0 */
unsigned depth;
const char *output; /* output_len characters */
unsigned output_len;
} v4_post_case;
extern const v4_post_case v4_post_cases[];
extern const unsigned v4_post_case_count;
/* THE RUNNER (v4/system/post.c). Whoever runs POST on a node supplies how a
* line is sent to it and where the console is. For each case the runner
* empties the node's data stack from outside; sends DECIMAL FORTH
* DEFINITIONS, the state every expected result was taken from; sends the
* case's lines one at a time, keeping what the node prints and showing none
* of it; and judges. A case passes when it ended in an error exactly if
* one was expected and, if none was, its stack and its printing are what
* the table has. It has ended in an error if any of its lines did. What
* the cases define is still in the node's dictionary when the runner
* returns: whoever runs POST puts the dictionary back afterwards, as v3
* does after each of its suites (v3/src/test_runner/test_common.c,
* run_test_suite: "to remove test-created words").
*
* If the node does not come back from a line -- it has stopped, or runs for
* ever -- that case fails and POST ends there: the runner says which case
* it was and how many were not run. */
#define V4_POST_OUT 1024u /* the most of a case's printing that is kept */
typedef struct {
void *self;
v4_node *n; /* the node: its data stack is read and emptied */
/* Send the node a line and run it to its end. What it prints is put at
* `out`, at most `cap` characters, and *len is how many it printed in
* all. Returns V4_TEXT_QUIT, V4_TEXT_COMPLETED or V4_TEXT_ERROR
* (message.h); or a negative number if the line did not come back. */
int (*line)(void *self, const char *text, unsigned text_len, char *out, unsigned cap, unsigned *len);
void (*say)(void *self, const char *text, unsigned len); /* the console */
} v4_post_host;
typedef struct { unsigned tests, pass, fail; } v4_post_tally;
/* Run the cases. Prints "POST FAIL: name out<...> stack<...>" for each
* failing case and then "PARITY:V4_POST tests=N pass=N fail=N", where tests
* is how many were run. Returns 1 if every case was run and none failed. */
int v4_post_run(const v4_post_host *h, const v4_post_case *cases, unsigned count, v4_post_tally *tally);
#endif /* V4_POST_H */