fix(v4): the final review's six minors in the ROM boot
- Text after start is refused, as text.c refuses it: before it jumps, the ROM reads on to the end of the source; blanks, comments and the ends of blobs may follow, a token is ERR-AFTER (26), "text after start". - A token too long where a name, a target or a value is wanted is "name too long", as text.c says: (MISSING) reports "missing" only when no error came first. `", keeps "missing", which is text.c's word for both. - text.c's "address out of range" names the address, not the value. - The system's source files are one list, v4/sys_files.h: boot.c, the harness and the nucleus test are made from it. - The ROM's error codes and words are one list, v4/rom_errors.h: boot.c's messages, host_map.h's ROM_ERR_* and mkmap's ERR-* are made from it. - node.h says what v4_node_store does with a ROM address (nothing, as for any address outside RAM, D-14); test_host_rom_range pins it. ROM: 2095 words, rom_hash 0x06d0dcb7a0cb41a1. dict_hash unchanged, 0xe5a57f3eb72ff94a. make -C v4 test test-32 hosted-check pass. QEMU: amd64, aarch64, riscv64 to ok>, POST 538/538, POST: PASSED. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
ff75e69e91
commit
a28b5f2230
@@ -60,7 +60,9 @@
|
||||
/* THE ROM (docs/v4.0.0/MACHINE.md section 2, DATASHEET-F18.md section 5).
|
||||
* A read-only range of V4_ROM_WORDS words at V4_ROM_BASE, just above RAM.
|
||||
* An instruction fetch, an @p literal and a data fetch there read the ROM; a
|
||||
* running programme's store there is an address fault. In the model it is
|
||||
* running programme's store there is an address fault. C code's
|
||||
* v4_node_store there does nothing and counts no fault, as for any address
|
||||
* outside RAM (D-14, at v4_node_store below). In the model it is
|
||||
* attached, as every device is, and v4_node_reset detaches it: the owner
|
||||
* attaches it again after a reset. The range's size is a build parameter,
|
||||
* as RAM's is; 0 (the default) is a machine with no ROM. */
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/* rom_errors.h -- the ROM's error codes and what they mean.
|
||||
*
|
||||
* The ROM (capsules/v4/rom) stops at (ROM-FAILED) with one of these codes in
|
||||
* (FAILED); the loader, which owns the console, prints its words
|
||||
* (v4/system/boot.c). This is the one list: the map's constants ERR-* the
|
||||
* ROM is assembled with (v4/tools/mkmap.c, through v4/tests/host_map.h's
|
||||
* ROM_ERR_*) and the boot's messages are both made from it. The codes run
|
||||
* 1, 2, 3 ... in order; a new one goes at the end.
|
||||
*
|
||||
* X(NAME, CODE, WORDS)
|
||||
*/
|
||||
#ifndef V4_ROM_ERRORS_H
|
||||
#define V4_ROM_ERRORS_H
|
||||
|
||||
#define V4_ROM_ERRORS(X) \
|
||||
X(TOO_LONG, 1, "name too long") /* a token longer than 63 characters */ \
|
||||
X(COMMENT, 2, "comment not closed") /* a ( with no ) before the end of its blob */ \
|
||||
X(BAD_NAME, 3, "cannot be used as a name") /* an opcode, a reserved word, a label, a number or &... */ \
|
||||
X(DEFINED, 4, "already defined") \
|
||||
X(NAMES, 5, "too many names") /* the symbol table is full */ \
|
||||
X(FIT, 6, "does not fit: memory is full, or a branch cannot reach") \
|
||||
X(OPCODE, 7, "not an opcode the packer takes there") \
|
||||
X(IN_MACRO, 8, "not allowed in a macro") \
|
||||
X(MACRO, 9, "macro without endmacro, or endmacro without macro") \
|
||||
X(LABEL_DUP, 10, "label already defined in this word") \
|
||||
X(LABELS, 11, "too many labels in one word") \
|
||||
X(FOR, 12, "FOR nested too deep, NEXT or UNEXT without FOR, or FOR without NEXT") \
|
||||
X(UNEXT, 13, "FOR ... UNEXT must fit one instruction word and hold no literal") \
|
||||
X(TARGET, 14, "not something to branch to") \
|
||||
X(UNDEFINED, 15, "never defined") \
|
||||
X(BIG, 16, "number does not fit a cell") \
|
||||
X(AMP, 17, "& needs a word that is already defined") \
|
||||
X(FETCH_P, 18, "write the number, not @p") \
|
||||
X(MISSING, 19, "a name, a target, a value or a string is missing") \
|
||||
X(DEEP, 20, "macros nested too deep") \
|
||||
X(REFS, 21, "too many unresolved branches") \
|
||||
X(VALUE, 22, "not a value") \
|
||||
X(NO_START, 23, "the source ended with no start") \
|
||||
X(START, 24, "start of something not a word") \
|
||||
X(RANGE, 25, "address out of range") /* store outside RAM */ \
|
||||
X(AFTER, 26, "text after start")
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
/* sys_files.h -- the system's source, in the order the ROM reads it.
|
||||
*
|
||||
* capsules/v4/sys: the memory map (map-<cell bits>.f18) first, then these,
|
||||
* then end.f18 -- the state the system is switched on in, and `start`. The
|
||||
* one list: the boot feeds these blobs (v4/system/boot.c), and the tests
|
||||
* that build the system read these files (v4/tests/rom_harness.h).
|
||||
*
|
||||
* X(FILE): capsules/v4/sys/FILE.f18
|
||||
*/
|
||||
#ifndef V4_SYS_FILES_H
|
||||
#define V4_SYS_FILES_H
|
||||
|
||||
#define V4_SYS_FILES(X) \
|
||||
X(core) X(input) X(dict) X(codegen) X(compile) X(quit) X(forth) \
|
||||
X(numout) X(words) X(system) X(qmath) X(blocks) X(log) X(acl)
|
||||
|
||||
#endif
|
||||
+4
-4
@@ -450,15 +450,15 @@ static void set_directive(v4_text *t, reader *r)
|
||||
/* `store ADDR VALUE`: a word of RAM is given VALUE. */
|
||||
static void store_directive(v4_text *t, reader *r)
|
||||
{
|
||||
char tok[V4_TEXT_MAX_TOKEN + 1u];
|
||||
char at[V4_TEXT_MAX_TOKEN + 1u], tok[V4_TEXT_MAX_TOKEN + 1u];
|
||||
v4_cell addr, v;
|
||||
|
||||
if (r->depth != 1) { fail(t, "not allowed in a macro", "store"); return; }
|
||||
if (!next_token(t, r, tok)) { if (!t->failed) fail(t, "store without an address", NULL); return; }
|
||||
if (!value_of(t, tok, &addr)) return;
|
||||
if (!next_token(t, r, at)) { if (!t->failed) fail(t, "store without an address", NULL); return; }
|
||||
if (!value_of(t, at, &addr)) return;
|
||||
if (!next_token(t, r, tok)) { if (!t->failed) fail(t, "store without a value", NULL); return; }
|
||||
if (!value_of(t, tok, &v)) return;
|
||||
if (addr < 0 || (v4_ucell)addr >= V4_NODE_WORDS) { fail(t, "address out of range", tok); return; }
|
||||
if (addr < 0 || (v4_ucell)addr >= V4_NODE_WORDS) { fail(t, "address out of range", at); return; }
|
||||
v4_node_store(t->as.n, addr, v);
|
||||
}
|
||||
|
||||
|
||||
+12
-18
@@ -8,6 +8,8 @@
|
||||
#include "v4/post.h"
|
||||
#include "v4/blocks.h"
|
||||
#include "v4/boot.h"
|
||||
#include "v4/rom_errors.h"
|
||||
#include "v4/sys_files.h"
|
||||
#include "v4/message.h"
|
||||
#include "v4/wire.h"
|
||||
#include "starkernel/capsule.h"
|
||||
@@ -430,32 +432,24 @@ extern const unsigned v4_rom_32_words;
|
||||
#define EOT 4 /* the end of the source: the ROM's (KEY) sees no more */
|
||||
|
||||
/* The system's source, in the order the ROM reads it: the memory map, then
|
||||
* the system, then its end -- the state it is switched on in, and `start`.
|
||||
* capsules/v4/sys; each blob is a capsule like any other. */
|
||||
* the system (v4/sys_files.h), then its end -- the state it is switched on
|
||||
* in, and `start`. capsules/v4/sys; each blob is a capsule like any other. */
|
||||
#define MAP_NAME_(bits) "v4:sys:map-" #bits ".f18"
|
||||
#define MAP_NAME__(bits) MAP_NAME_(bits)
|
||||
static const char *const system_blobs[] = {
|
||||
#define SYS_BLOB(file) "v4:sys:" #file ".f18",
|
||||
MAP_NAME__(V4_CELL_BITS),
|
||||
"v4:sys:core.f18", "v4:sys:input.f18", "v4:sys:dict.f18", "v4:sys:codegen.f18", "v4:sys:compile.f18",
|
||||
"v4:sys:quit.f18", "v4:sys:forth.f18", "v4:sys:numout.f18", "v4:sys:words.f18", "v4:sys:system.f18",
|
||||
"v4:sys:qmath.f18", "v4:sys:blocks.f18", "v4:sys:log.f18", "v4:sys:acl.f18",
|
||||
V4_SYS_FILES(SYS_BLOB)
|
||||
"v4:sys:end.f18",
|
||||
#undef SYS_BLOB
|
||||
};
|
||||
#define SYSTEM_BLOBS (sizeof system_blobs / sizeof system_blobs[0])
|
||||
|
||||
/* What the ROM's error codes mean (v4/tests/host_map.h, ROM_ERR_*): the ROM
|
||||
* stops with the code, and the loader, which owns the console, says it. */
|
||||
static const char *const rom_errors[] = {
|
||||
"", "name too long", "comment not closed", "cannot be used as a name", "already defined",
|
||||
"too many names", "does not fit: memory is full, or a branch cannot reach", "not an opcode the packer takes there",
|
||||
"not allowed in a macro", "macro without endmacro, or endmacro without macro",
|
||||
"label already defined in this word", "too many labels in one word",
|
||||
"FOR nested too deep, NEXT or UNEXT without FOR, or FOR without NEXT",
|
||||
"FOR ... UNEXT must fit one instruction word and hold no literal", "not something to branch to",
|
||||
"never defined", "number does not fit a cell", "& needs a word that is already defined",
|
||||
"write the number, not @p", "a name, a target, a value or a string is missing", "macros nested too deep",
|
||||
"too many unresolved branches", "not a value", "the source ended with no start", "start of something not a word", "address out of range",
|
||||
};
|
||||
/* What the ROM's error codes mean (v4/rom_errors.h): the ROM stops with the
|
||||
* code, and the loader, which owns the console, says it. Code c is entry c. */
|
||||
#define ROM_ERROR_TEXT(name, code, text) text,
|
||||
static const char *const rom_errors[] = { "", V4_ROM_ERRORS(ROM_ERROR_TEXT) };
|
||||
#undef ROM_ERROR_TEXT
|
||||
#define ROM_ERRORS (sizeof rom_errors / sizeof rom_errors[0])
|
||||
|
||||
/* FNV-1a over the ROM, a cell at a time, low byte first, as the dictionary
|
||||
|
||||
+4
-26
@@ -12,6 +12,7 @@
|
||||
#ifndef V4_TESTS_HOST_MAP_H
|
||||
#define V4_TESTS_HOST_MAP_H
|
||||
|
||||
#include "v4/rom_errors.h"
|
||||
#include "v4/blocks.h"
|
||||
#include "v4/text.h"
|
||||
#include <stdio.h>
|
||||
@@ -197,32 +198,9 @@
|
||||
#define ROM_KIND_CONST 2
|
||||
#define ROM_KIND_MACRO 3
|
||||
#define ROM_KIND_SET 4
|
||||
/* the ROM's error codes */
|
||||
#define ROM_ERR_TOO_LONG 1 /* a token longer than 63 characters: "name too long" */
|
||||
#define ROM_ERR_COMMENT 2 /* a ( with no ) before the end: "comment not closed" */
|
||||
#define ROM_ERR_BAD_NAME 3 /* an opcode, a reserved word, a label, a number or &...: "cannot be used as a name" */
|
||||
#define ROM_ERR_DEFINED 4 /* "already defined" */
|
||||
#define ROM_ERR_NAMES 5 /* the symbol table is full: "too many names" */
|
||||
#define ROM_ERR_FIT 6 /* memory is full, or a branch cannot reach: "does not fit" */
|
||||
#define ROM_ERR_OPCODE 7 /* not an opcode the packer takes there */
|
||||
#define ROM_ERR_IN_MACRO 8 /* "not allowed in a macro" */
|
||||
#define ROM_ERR_MACRO 9 /* "macro without endmacro", "endmacro without macro" */
|
||||
#define ROM_ERR_LABEL_DUP 10 /* "label already defined in this word" */
|
||||
#define ROM_ERR_LABELS 11 /* "too many labels in one word" */
|
||||
#define ROM_ERR_FOR 12 /* FOR nested too deep, NEXT or UNEXT without FOR, FOR without NEXT */
|
||||
#define ROM_ERR_UNEXT 13 /* "FOR ... UNEXT must fit one instruction word and hold no literal" */
|
||||
#define ROM_ERR_TARGET 14 /* "not something to branch to" */
|
||||
#define ROM_ERR_UNDEFINED 15 /* "never defined" */
|
||||
#define ROM_ERR_BIG 16 /* "number does not fit a cell" */
|
||||
#define ROM_ERR_AMP 17 /* "& needs a word that is already defined" */
|
||||
#define ROM_ERR_FETCH_P 18 /* "write the number, not @p" */
|
||||
#define ROM_ERR_MISSING 19 /* a name, a target, a value or a string missing at the end */
|
||||
#define ROM_ERR_DEEP 20 /* "macros nested too deep" */
|
||||
#define ROM_ERR_REFS 21 /* "too many unresolved branches" */
|
||||
#define ROM_ERR_VALUE 22 /* "not a value", "not a number" */
|
||||
#define ROM_ERR_NO_START 23 /* the input ended with no start */
|
||||
#define ROM_ERR_START 24 /* start: not a word */
|
||||
#define ROM_ERR_RANGE 25 /* "address out of range": store outside RAM */
|
||||
/* the ROM's error codes: ROM_ERR_TOO_LONG, ROM_ERR_COMMENT ... (v4/rom_errors.h) */
|
||||
#define ROM_ERR_ENUM_(name, code, text) ROM_ERR_##name = code,
|
||||
enum { V4_ROM_ERRORS(ROM_ERR_ENUM_) ROM_ERR_END_ };
|
||||
#define ROM_ADDR_TOP ((v4_cell)(V4_NODE_WORDS + V4_ROM_WORDS - 1u)) /* the top of the address space */
|
||||
#define WORD_DEFINED (BUF0_W - 11) /* the xt of the word that is told of each new entry, or 0 */
|
||||
#define WORD_FORGOTTEN (BUF0_W - 12) /* the xt of the word that is told when entries go, or 0 */
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "v4/testcode.h"
|
||||
#include "host_map.h"
|
||||
#include "v4/sys_files.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -105,13 +106,15 @@ static void rom_boot(v4_node *n)
|
||||
}
|
||||
|
||||
/* THE SYSTEM, AS THE MACHINE BUILDS IT (MACHINE.md section 6, step 1). The
|
||||
* system's source, capsules/v4/sys (V4_SYS_DIR): the map, the fourteen and
|
||||
* system's source, capsules/v4/sys (V4_SYS_DIR): the map, v4/sys_files.h and
|
||||
* the end, each followed by a new line and V4_ROM_BLOB_END, then EOT -- what v4/system/boot.c
|
||||
* feeds the console. rom_system_text gives it whole, *len its length;
|
||||
* rom_build_system has `n`, booted with its ROM, assemble it, and runs it to
|
||||
* its start: 1 if it started, with *words the instruction words it took. */
|
||||
static const char *const rom_system_files[] = { "core", "input", "dict", "codegen", "compile", "quit", "forth",
|
||||
"numout", "words", "system", "qmath", "blocks", "log", "acl" };
|
||||
#define ROM_SYS_FILE(file) #file,
|
||||
static const char *const rom_system_files[] = { V4_SYS_FILES(ROM_SYS_FILE) };
|
||||
#undef ROM_SYS_FILE
|
||||
#define ROM_SYS_FILES ((unsigned)(sizeof rom_system_files / sizeof rom_system_files[0]))
|
||||
|
||||
static char *rom_system_text(size_t *len)
|
||||
{
|
||||
@@ -119,12 +122,12 @@ static char *rom_system_text(size_t *len)
|
||||
char *text = malloc(cap);
|
||||
unsigned i;
|
||||
if (!text) return NULL;
|
||||
for (i = 0; i < 16; i++) {
|
||||
for (i = 0; i < ROM_SYS_FILES + 2u; i++) {
|
||||
char path[512];
|
||||
FILE *f;
|
||||
long n;
|
||||
if (i == 0) snprintf(path, sizeof path, "%s/map-%d.f18", V4_SYS_DIR, V4_CELL_BITS);
|
||||
else if (i <= 14) snprintf(path, sizeof path, "%s/%s.f18", V4_SYS_DIR, rom_system_files[i - 1]);
|
||||
else if (i <= ROM_SYS_FILES) snprintf(path, sizeof path, "%s/%s.f18", V4_SYS_DIR, rom_system_files[i - 1]);
|
||||
else snprintf(path, sizeof path, "%s/end.f18", V4_SYS_DIR);
|
||||
f = fopen(path, "rb");
|
||||
if (!f) { printf(" cannot read %s\n", path); free(text); return NULL; }
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "rom_harness.h"
|
||||
#include "v4/text.h"
|
||||
#include "rom_asm_cases.h"
|
||||
#include "v4/rom_errors.h"
|
||||
|
||||
static int failures = 0, checks = 0;
|
||||
#define CHECK(c,...) do{checks++; if(!(c)){failures++; printf("FAIL %s:%d: ",__FILE__,__LINE__); printf(__VA_ARGS__); printf("\n");}}while(0)
|
||||
@@ -38,7 +39,7 @@ static v4_cell code_of(const char *m)
|
||||
{ "write the number", ROM_ERR_FETCH_P }, { "too many unresolved", ROM_ERR_REFS },
|
||||
{ "not a value", ROM_ERR_VALUE }, { "not a number", ROM_ERR_VALUE },
|
||||
{ "too many names", ROM_ERR_NAMES }, { "out of name space", ROM_ERR_NAMES },
|
||||
{ "address out of range", ROM_ERR_RANGE }, { "without", ROM_ERR_MISSING },
|
||||
{ "address out of range", ROM_ERR_RANGE }, { "text after start", ROM_ERR_AFTER }, { "without", ROM_ERR_MISSING },
|
||||
};
|
||||
unsigned i;
|
||||
for (i = 0; i < sizeof map / sizeof map[0]; i++) if (strstr(m, map[i].s)) return map[i].c;
|
||||
@@ -246,6 +247,43 @@ int main(void)
|
||||
snprintf(t, sizeof t, "store %ld 5", (long)V4_NODE_WORDS - 1); same(t);
|
||||
}
|
||||
|
||||
/* a token too long where a name or a value is wanted: "name too long", as
|
||||
* text.c says, not "missing" -- the first error stands */
|
||||
{
|
||||
static const char *const forms[] = { "constant %s 5", "constant K %s", "set %s 5", "set S %s", ": %s",
|
||||
"store %s 5", "store 300 %s", "#, %s", "jump %s", "if %s", "\", %s" };
|
||||
static char t[160], long_tok[65];
|
||||
memset(long_tok, 'X', 64); long_tok[64] = 0;
|
||||
for (i = 0; i < sizeof forms / sizeof forms[0]; i++) { snprintf(t, sizeof t, forms[i], long_tok); same(t); }
|
||||
}
|
||||
|
||||
/* text after start: refused, as text.c refuses it; blanks, comments and
|
||||
* the blob's end after it are not text */
|
||||
CHECK(rom_run(": Z ;\nstart Z\n1\n\x04") == 0 && b.mem[ROM_FAILED] == ROM_ERR_AFTER, "text after start: refused (code %ld)",
|
||||
(long)b.mem[ROM_FAILED]);
|
||||
CHECK(rom_run(": Z ;\nstart Z \\ a comment\n( and another )\n\x1c\x04") == 1, "comments and a blob's end after start: started (code %ld)",
|
||||
(long)b.mem[ROM_FAILED]);
|
||||
{
|
||||
v4_node_reset(&a);
|
||||
v4_text_begin(&tx, &a, ROM_ORIGIN);
|
||||
CHECK(!v4_text_assemble(&tx, ": Z ;\nstart Z\n1\n") && code_of(v4_text_error(&tx)) == ROM_ERR_AFTER,
|
||||
"text.c refuses text after start too: %s", v4_text_error(&tx));
|
||||
}
|
||||
|
||||
/* the ROM's error messages, as the boot prints them: one list
|
||||
* (v4/rom_errors.h), its codes 1, 2, 3 ... in order */
|
||||
{
|
||||
static const struct { int code; const char *text; } list[] = {
|
||||
#define E(name, code, text) { code, text },
|
||||
V4_ROM_ERRORS(E)
|
||||
#undef E
|
||||
};
|
||||
for (i = 0; i < sizeof list / sizeof list[0]; i++) if (list[i].code != (int)i + 1) break;
|
||||
CHECK(i == sizeof list / sizeof list[0], "the ROM's error codes run 1, 2, 3 ... : entry %u is %d", i, list[i].code);
|
||||
CHECK(ROM_ERR_RANGE == 25 && strcmp(list[ROM_ERR_RANGE - 1].text, "address out of range") == 0, "ROM_ERR_RANGE's message");
|
||||
CHECK(strcmp(list[ROM_ERR_AFTER - 1].text, "text after start") == 0, "ROM_ERR_AFTER's message");
|
||||
}
|
||||
|
||||
printf("test_host_rom_asm: %d checks, %d failures\n", checks, failures);
|
||||
return failures != 0;
|
||||
}
|
||||
|
||||
@@ -28,9 +28,9 @@ static int build_a(void)
|
||||
unsigned i;
|
||||
v4_node_reset(&a);
|
||||
v4_text_begin(&tx, &a, ROM_ORIGIN);
|
||||
for (i = 0; i < 16; i++) {
|
||||
for (i = 0; i < ROM_SYS_FILES + 2u; i++) {
|
||||
if (i == 0) snprintf(path, sizeof path, "%s/map-%d.f18", V4_SYS_DIR, V4_CELL_BITS);
|
||||
else if (i <= 14) snprintf(path, sizeof path, "%s/%s.f18", V4_SYS_DIR, rom_system_files[i - 1]);
|
||||
else if (i <= ROM_SYS_FILES) snprintf(path, sizeof path, "%s/%s.f18", V4_SYS_DIR, rom_system_files[i - 1]);
|
||||
else snprintf(path, sizeof path, "%s/end.f18", V4_SYS_DIR);
|
||||
if (!v4_text_assemble_file(&tx, path)) return 0;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ int main(void)
|
||||
v4_node_rom_attach(&n, rom, 16);
|
||||
CHECK(v4_node_load(&n, V4_ROM_BASE) == rom[0], "the ROM reads");
|
||||
CHECK(v4_node_load(&n, V4_ROM_BASE + 16) == 0, "past the ROM's words: nothing");
|
||||
v4_node_store(&n, V4_ROM_BASE, 12345);
|
||||
CHECK(v4_node_load(&n, V4_ROM_BASE) == rom[0] && n.faults == 0, "C code's store into the ROM does nothing and counts no fault (node.h)");
|
||||
|
||||
/* RAM 16: call the ROM's word, then return */
|
||||
v4_asm_begin(&as, &n, 16);
|
||||
|
||||
@@ -540,6 +540,7 @@ int main(void)
|
||||
CHECK(ok(": T ; constant A 300 store A 5 store A+1 &T") && nb.mem[300] == 5 && nb.mem[301] == ORIGIN,
|
||||
"store puts a VALUE anywhere in RAM");
|
||||
CHECK(refused("store -1 5", "address out of range", 1), "store outside RAM is refused");
|
||||
CHECK(refused("store 99999 5", "address out of range: 99999", 1), "store outside RAM names the address, not the value");
|
||||
CHECK(refused("store 5", "store without a value", 1), "store needs a value");
|
||||
CHECK(ok(": A ; : B ; start B") && v4_text_start(&tx) == ORIGIN + 1, "start names the word the system starts at");
|
||||
CHECK(ok(": A ;") && v4_text_start(&tx) == -1, "no start: -1");
|
||||
|
||||
+15
-25
@@ -83,9 +83,21 @@ int main(int argc, char **argv)
|
||||
constant("(SYMH)", (long)ROM_SYMH);
|
||||
constant("SYMREC", (long)ROM_SYMREC);
|
||||
constant("POOLTOP", (long)ROM_POOLTOP);
|
||||
constant("ERR-BAD-NAME", (long)ROM_ERR_BAD_NAME);
|
||||
constant("ERR-DEFINED", (long)ROM_ERR_DEFINED);
|
||||
constant("ERR-NAMES", (long)ROM_ERR_NAMES);
|
||||
{
|
||||
/* the ROM's error codes, ERR-TOO-LONG ... (v4/rom_errors.h) */
|
||||
static const struct { const char *name; long code; } errs[] = {
|
||||
#define ROM_ERR_CONST_(name, code, text) { #name, code },
|
||||
V4_ROM_ERRORS(ROM_ERR_CONST_)
|
||||
#undef ROM_ERR_CONST_
|
||||
};
|
||||
unsigned e, c;
|
||||
for (e = 0; e < sizeof errs / sizeof errs[0]; e++) {
|
||||
char n[40] = "ERR-";
|
||||
for (c = 0; errs[e].name[c] && c < sizeof n - 5u; c++) n[4 + c] = errs[e].name[c] == '_' ? '-' : errs[e].name[c];
|
||||
n[4 + c] = 0;
|
||||
constant(n, errs[e].code);
|
||||
}
|
||||
}
|
||||
constant("(HERE)", (long)ROM_HERE);
|
||||
constant("(CUR)", (long)ROM_CUR);
|
||||
constant("(SLOT)", (long)ROM_SLOT);
|
||||
@@ -96,8 +108,6 @@ int main(int argc, char **argv)
|
||||
constant("(RN)", (long)ROM_RN);
|
||||
constant("RAM-WORDS", (long)V4_NODE_WORDS);
|
||||
constant("ADDR-TOP", (long)ROM_ADDR_TOP);
|
||||
constant("ERR-FIT", (long)ROM_ERR_FIT);
|
||||
constant("ERR-OPCODE", (long)ROM_ERR_OPCODE);
|
||||
constant("(NREF)", (long)ROM_NREF);
|
||||
constant("(NLAB)", (long)ROM_NLAB);
|
||||
constant("(WNP)", (long)ROM_WNP);
|
||||
@@ -130,24 +140,6 @@ int main(int argc, char **argv)
|
||||
constant("DICT-END", (long)DICT_END_W);
|
||||
constant("BUF0", (long)BUF0_W);
|
||||
constant("TIB-W", (long)TIB_W);
|
||||
constant("ERR-IN-MACRO", (long)ROM_ERR_IN_MACRO);
|
||||
constant("ERR-MACRO", (long)ROM_ERR_MACRO);
|
||||
constant("ERR-LABEL-DUP", (long)ROM_ERR_LABEL_DUP);
|
||||
constant("ERR-LABELS", (long)ROM_ERR_LABELS);
|
||||
constant("ERR-FOR", (long)ROM_ERR_FOR);
|
||||
constant("ERR-UNEXT", (long)ROM_ERR_UNEXT);
|
||||
constant("ERR-TARGET", (long)ROM_ERR_TARGET);
|
||||
constant("ERR-UNDEFINED", (long)ROM_ERR_UNDEFINED);
|
||||
constant("ERR-BIG", (long)ROM_ERR_BIG);
|
||||
constant("ERR-AMP", (long)ROM_ERR_AMP);
|
||||
constant("ERR-FETCH-P", (long)ROM_ERR_FETCH_P);
|
||||
constant("ERR-MISSING", (long)ROM_ERR_MISSING);
|
||||
constant("ERR-DEEP", (long)ROM_ERR_DEEP);
|
||||
constant("ERR-REFS", (long)ROM_ERR_REFS);
|
||||
constant("ERR-VALUE", (long)ROM_ERR_VALUE);
|
||||
constant("ERR-NO-START", (long)ROM_ERR_NO_START);
|
||||
constant("ERR-START", (long)ROM_ERR_START);
|
||||
constant("ERR-RANGE", (long)ROM_ERR_RANGE);
|
||||
constant("DSTACK-REG", (long)DSTACK_REG);
|
||||
constant("RSTACK-REG", (long)RSTACK_REG);
|
||||
/* the cell width's constants (NUMBER) needs, written as signed cells */
|
||||
@@ -155,7 +147,5 @@ int main(int argc, char **argv)
|
||||
constant("DEC-LIMIT", (long)(v4_cell)(~(v4_ucell)0 / 10u));
|
||||
constant("DEC-NLAST", -(long)(~(v4_ucell)0 % 10u) - 1);
|
||||
constant("HEX-HIGH", (long)(v4_cell)~(~(v4_ucell)0 >> 4));
|
||||
constant("ERR-TOO-LONG", (long)ROM_ERR_TOO_LONG);
|
||||
constant("ERR-COMMENT", (long)ROM_ERR_COMMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user