Ruled 2026-10-04, revising D-2: stack overflow and underflow are errors that are shown and return to the prompt, not silent wrap-around. - Each stack counts what it holds. Before every opcode the executor checks that the stacks hold what it takes and have room for what it leaves; otherwise the opcode does nothing and the node faults, as for a bad address, to that kind's handler. Every fault empties both stacks. - The fault handler is now a table of five jumps: address, data overflow, data underflow, return overflow, return underflow. The host node says "Stack overflow", "Stack underflow", "Return stack overflow", "Return stack underflow", then ERROR and the prompt. - Two registers, DSTACK-DEPTH and RSTACK-DEPTH: a fetch reads the depth, a store empties the stack. QUIT, ABORT and the error exits empty the return stack before they call anything; ABORT empties the data stack. - capsule/forth.v4: DEPTH, PICK and ROLL, to FORTH-79 (counting from one). PICK and ROLL set the values above the one wanted aside in memory, and work with the stack full. - Division by zero now takes its operands off the stack, as v3 does. - A colon with no room for its entry abandons the line. - tests: every opcode at every depth of both stacks; the faults, the registers and the three words from the prompt. The sizes are unchanged: ten values, nine return entries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
20 lines
640 B
C
20 lines
640 B
C
/* testcode.c -- run a word on a node, for tests. See testcode.h. */
|
|
#include "v4/testcode.h"
|
|
|
|
long v4_test_call(v4_node *n, v4_exec_state *es, v4_heat *h,
|
|
v4_cell entry, long max_words)
|
|
{
|
|
long words = 0;
|
|
|
|
n->stopped = 0; /* a stop left by an earlier call is over */
|
|
v4_rstack_push(&n->rs, V4_TEST_HALT);
|
|
n->p = entry;
|
|
while (n->p != V4_TEST_HALT) {
|
|
if (words >= max_words) return -1;
|
|
(void)v4_exec_step_word(n, es, h);
|
|
if (n->stopped) return -1; /* an address fault with no handler (D-14) */
|
|
words++;
|
|
}
|
|
return words;
|
|
}
|