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:
co-authored by
Claude Sonnet 5
parent
3426d6a4a7
commit
dfdabcc2d7
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user