feat(v4.0.0): division by zero is guarded (D-15); division words in the capsule
Ruled 2026-10-04: guarded, an error shown, back to the prompt.
- capsule/forth.v4: / MOD /MOD */ */MOD M/MOD, M* and S>D join the
vocabulary. Each dividing word tests its divisor first; zero prints
v3's message ("/: Division by zero"), ends an open definition, prints
ERROR and returns to the prompt from however deep.
- SM/REM here has UM/MOD written into it and keeps its signs in memory,
and */MOD has M* written in, so that division can be used inside words
that other words call: / from four words deep, */MOD from three.
- forth.v4 now loads after quit.v4, which the guard leaves through.
- tests: v3 transcripts for each message; /MOD, /, MOD and */MOD against
C on every pair of edge values.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
b3d2d56d11
commit
361dcd1148
@@ -21,6 +21,7 @@
|
||||
* - control words that do not match give ERROR alone; v3 names the word.
|
||||
* - QUERY takes 80 characters (FORTH-79); v3's line is 255.
|
||||
* - an address outside memory says so (D-14); v3 gives ERROR alone.
|
||||
* - M/MOD by zero says so (D-15); v3 gives ERROR alone.
|
||||
*/
|
||||
#include "v4/text.h"
|
||||
#include "v4/testcode.h"
|
||||
@@ -146,7 +147,18 @@ static const transcript script[] = {
|
||||
{ ": P .\" two spaces \" 124 EMIT ; P\n", " two spaces | ok\nok> ", 1 },
|
||||
{ "65 EMIT CR 66 EMIT\n", "A\nB ok\nok> ", 1 },
|
||||
{ ": E .\" \" 65 EMIT ; E\n", "A ok\nok> ", 1 },
|
||||
{ "65 EMIT 1 0 / 66 EMIT\n67 EMIT\n", "A/: Division by zero\n ERROR\nok> C ok\nok> ", 1 },
|
||||
{ "1 0 MOD\n", "MOD: Division by zero\n ERROR\nok> ", 1 },
|
||||
{ "1 0 /MOD\n", "/MOD: Division by zero\n ERROR\nok> ", 1 },
|
||||
{ "1 1 0 */\n", "*/: Division by zero\n ERROR\nok> ", 1 },
|
||||
{ "1 1 0 */MOD\n", "*/MOD: Division by zero\n ERROR\nok> ", 1 },
|
||||
{ ": T 1 0 / 65 EMIT ; T 66 EMIT\n67 EMIT\n", "/: Division by zero\n ERROR\nok> C ok\nok> ", 1 },
|
||||
{ "0 0 /\n7 2 / 48 + EMIT\n", "/: Division by zero\n ERROR\nok> 3 ok\nok> ", 1 },
|
||||
/* v4's own */
|
||||
{ "1 0 0 M/MOD\n", "M/MOD: Division by zero\n ERROR\nok> ", 0 },
|
||||
{ ": Z0 0 / ; : Z1 65 EMIT 9 Z0 66 EMIT ; Z1\n: Z2 1 IF [ 5 0 MOD ]\nZ2\n",
|
||||
"A/: Division by zero\n ERROR\nok> MOD: Division by zero\n ERROR\nok> UNKNOWN WORD: 'Z2'\n ERROR\nok> ", 0 },
|
||||
{ ": Z3 5 0 DO 9 3 I - / DROP LOOP 65 EMIT ; Z3\n66 EMIT\n", "/: Division by zero\n ERROR\nok> B ok\nok> ", 0 },
|
||||
{ ": BAD 1 NOSUCH 2 ;\nBAD\n65 EMIT\n", "UNKNOWN WORD: 'NOSUCH'\n ERROR\nok> UNKNOWN WORD: 'BAD'\n ERROR\nok> A ok\nok> ", 0 },
|
||||
{ "1 ABORT\" now\" 65 EMIT\n66 EMIT\n", "now\n ok\nok> B ok\nok> ", 0 },
|
||||
{ ": B1 IF LOOP ;\n65 EMIT\n", " ERROR\nok> A ok\nok> ", 0 },
|
||||
@@ -172,7 +184,7 @@ 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", "forth.v4", "quit.v4" };
|
||||
static const char *const files[] = { "core.v4", "input.v4", "dict.v4", "codegen.v4", "compile.v4", "quit.v4", "forth.v4" };
|
||||
CHECK(host_load(&tx, &n, files, 7), "the capsule assembles");
|
||||
}
|
||||
CHECK(v4_text_finish(&tx), "everything is defined: %s", v4_text_error(&tx));
|
||||
|
||||
Reference in New Issue
Block a user