word_source: repair DECAY-RATE@ overflow guard and remove dead shadowed registrations

DECAY-RATE@ (physics_freeze_words.c) pushed to the data stack with no
capacity check and no prior pop to make room, unlike its neighbors in
the same file -- the one live, unconditional missing-guard bug the
Isabelle sweep's ~15 candidate findings reduced to once checked against
vm_push()'s real internal bounds check (see proof/FINDINGS.md SS2).

Removed dictionary_manipulation_words.c's [ ] STATE and defining_words.c's
DEFER IS DEFER@ (plus the now-orphaned defining_runtime_defer helper) --
all confirmed permanently shadowed by later dictionary registrations
(defining_words.c and defer_words.c respectively), per FORTH's
newest-first lookup. No behavior change: the removed code was already
unreachable.

Verified: hosted `make` builds clean under -Wall -Werror; the hosted
self-test suite passes 965/965 implemented tests with no regressions.
Three-architecture QEMU acceptance boot, all clean to ok> with an
identical dict_hash=0x24b4279f0670aa3a across amd64/aarch64/riscv64 and
identical 1003/965/0/0 test totals -- logs attached.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-08-14 21:33:17 -04:00
co-authored by Claude Sonnet 5
parent 3426d6a4a7
commit dfdabcc2d7
13 changed files with 25773 additions and 170 deletions
+8 -98
View File
@@ -711,100 +711,14 @@ static void defining_word_immediate(VM *vm) {
}
/* ───────────────────────────── DEFER / IS ─────────────────────────── */
/* DEFER runtime: execute the XT stored in this word's data field */
static void defining_runtime_defer(VM *vm) {
if (!vm) return;
DictEntry *self = vm->current_executing_entry;
if (!self) { vm->error = 1; return; }
cell_t *df = vm_dictionary_get_data_field(self);
if (!df) { vm->error = 1; return; }
DictEntry *target = (DictEntry *)(uintptr_t)(*df);
if (!target || !target->func) {
log_message(LOG_ERROR, "DEFER %.*s: uninitialized — use IS to set",
(int)self->name_len, self->name);
vm->error = 1;
return;
}
vm->current_executing_entry = target;
target->func(vm);
}
/* DEFER ( "name" -- ) create a deferred word with an empty XT slot */
static void defining_word_defer(VM *vm) {
if (!vm) return;
char namebuf[WORD_NAME_MAX + 1];
int nlen = vm_parse_word(vm, namebuf, sizeof(namebuf));
if (nlen <= 0) { vm->error = 1; return; }
DictEntry *entry = vm_create_word(vm, namebuf, (size_t)nlen, defining_runtime_defer);
if (!entry) { vm->error = 1; return; }
cell_t *df = vm_dictionary_get_data_field(entry);
if (!df) { vm->error = 1; return; }
*df = 0;
log_message(LOG_DEBUG, "DEFER: '%.*s'", nlen, namebuf);
}
/* IS ( xt "name" -- ) store xt into the deferred word's slot */
static void defining_word_is(VM *vm) {
if (!vm) return;
if (vm->dsp < 0) {
log_message(LOG_ERROR, "IS: stack underflow");
vm->error = 1;
return;
}
cell_t xt = vm_pop(vm);
char namebuf[WORD_NAME_MAX + 1];
int nlen = vm_parse_word(vm, namebuf, sizeof(namebuf));
if (nlen <= 0) { vm->error = 1; return; }
DictEntry *entry = vm_find_word(vm, namebuf, (size_t)nlen);
if (!entry) {
log_message(LOG_ERROR, "IS: '%.*s' not found", nlen, namebuf);
vm->error = 1;
return;
}
if (entry->func != defining_runtime_defer) {
log_message(LOG_ERROR, "IS: '%.*s' is not a DEFER word", nlen, namebuf);
vm->error = 1;
return;
}
cell_t *df = vm_dictionary_get_data_field(entry);
if (!df) { vm->error = 1; return; }
*df = xt;
log_message(LOG_DEBUG, "IS: '%.*s' <- XT %p", nlen, namebuf, (void *)(uintptr_t)xt);
}
/* DEFER@ ( "name" -- xt ) fetch the XT stored in a deferred word */
static void defining_word_defer_fetch(VM *vm) {
if (!vm) return;
char namebuf[WORD_NAME_MAX + 1];
int nlen = vm_parse_word(vm, namebuf, sizeof(namebuf));
if (nlen <= 0) { vm->error = 1; return; }
DictEntry *entry = vm_find_word(vm, namebuf, (size_t)nlen);
if (!entry) {
log_message(LOG_ERROR, "DEFER@: '%.*s' not found", nlen, namebuf);
vm->error = 1;
return;
}
cell_t *df = vm_dictionary_get_data_field(entry);
if (!df) { vm->error = 1; return; }
vm_push(vm, *df);
log_message(LOG_DEBUG, "DEFER@: '%.*s' -> XT %p", nlen, namebuf, (void *)(uintptr_t)(*df));
}
/* DEFER/IS/DEFER@ are NOT defined here: defer_words.c registers the same
* three names later in boot order (word_registry.c Module 27 vs this
* file's Module 17), and it has no __STARKERNEL__ guard, so it shadows
* this file's versions in both hosted and kernel builds. FORTH's
* newest-first dictionary lookup means defer_words.c's versions (a
* self-contained implementation, unrelated to this file's former
* defining_runtime_defer) are the only ones ever reachable. See
* proof/StarForth_Defer_Words.thy and proof/FINDINGS.md §3. */
/* ───────────────────────────── Registration ───────────────────────── */
@@ -858,8 +772,4 @@ void register_defining_words(VM *vm) {
register_word(vm, "DOES>", defining_word_does);
vm_make_immediate(vm);
/* DEFER / IS / DEFER@ */
register_word(vm, "DEFER", defining_word_defer);
register_word(vm, "IS", defining_word_is);
register_word(vm, "DEFER@", defining_word_defer_fetch);
}