feat(v4.0.0): the POST runner -- the kernel feeds a case and judges it from outside

v4/system/post.c: for each case it empties the node's data stack, sends
DECIMAL FORTH DEFINITIONS, sends the case's lines keeping what the node
prints, reads the stack, and judges: an error exactly if one is expected,
and otherwise the stack and every character printed.  A failing case is
named with what it printed and left.  Nothing of it is on the node.

Its tests are in test_host_quit.c, on that test's node: 29 checks of cases
that must pass and cases that must fail -- a wrong value, depth, order or
output, an error wanted or unwanted, a case of two lines, depth-only
cases, the starting state, more printing than is kept, and a line that
never comes back.  Both widths and the sanitizers.

The boot still runs the capsule; that is the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-07 10:36:36 -04:00
co-authored by Claude Opus 5.5
parent c2f4b9808a
commit 2bf958ce3a
4 changed files with 241 additions and 1 deletions
+29
View File
@@ -29,4 +29,33 @@ typedef struct {
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 stays in the node's dictionary, as in v3. */
#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". Returns 1
* if 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 */