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);
|
||||
}
|
||||
|
||||
@@ -111,35 +111,6 @@ static char *traverse_name_field(char *name_addr, int direction) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief FORTH word [ - Enter interpretation mode
|
||||
* @param vm Pointer to VM instance
|
||||
* @stack ( -- )
|
||||
*/
|
||||
void dictionary_m_word_left_bracket(VM *vm) {
|
||||
vm->mode = MODE_INTERPRET;
|
||||
state_variable = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief FORTH word ] - Enter compilation mode
|
||||
* @param vm Pointer to VM instance
|
||||
* @stack ( -- )
|
||||
*/
|
||||
void dictionary_m_word_right_bracket(VM *vm) {
|
||||
vm->mode = MODE_COMPILE;
|
||||
state_variable = -1; /* FORTH-79 uses -1 for true */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief FORTH word STATE - Get compilation state variable address
|
||||
* @param vm Pointer to VM instance
|
||||
* @stack ( -- addr )
|
||||
*/
|
||||
void dictionary_m_word_state(VM *vm) {
|
||||
vm_push(vm, (cell_t)(uintptr_t) & state_variable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief FORTH word SMUDGE - Toggle smudge bit of latest word
|
||||
* @param vm Pointer to VM instance
|
||||
@@ -473,9 +444,13 @@ static void dictionary_m_word_hidden(VM *vm) {
|
||||
void register_dictionary_manipulation_words(VM *vm) {
|
||||
|
||||
/* Register all dictionary manipulation words */
|
||||
register_word(vm, "[", dictionary_m_word_left_bracket);
|
||||
register_word(vm, "]", dictionary_m_word_right_bracket);
|
||||
register_word(vm, "STATE", dictionary_m_word_state);
|
||||
/* [, ], STATE are NOT registered here: defining_words.c registers the
|
||||
* same three names later in boot order (word_registry.c Module 17 vs
|
||||
* this file's Module 13), and FORTH's newest-first dictionary lookup
|
||||
* means defining_words.c's versions are the only ones ever reachable.
|
||||
* The versions formerly here also wrote a dead file-scope static
|
||||
* instead of vm->state_addr -- see proof/StarForth_Defining_Words.thy
|
||||
* and proof/FINDINGS.md §1. */
|
||||
register_word(vm, "SMUDGE", dictionary_m_word_smudge);
|
||||
register_word(vm, "HIDDEN", dictionary_m_word_hidden);
|
||||
register_word(vm, ">BODY", dictionary_m_word_to_body);
|
||||
|
||||
@@ -370,11 +370,16 @@ void forth_ALL_HEATS(VM *vm) {
|
||||
*
|
||||
* Stack effect: ( -- rate )
|
||||
*
|
||||
* @param vm Active VM; no-op if @c vm->error is set
|
||||
* @param vm Active VM; sets @c vm->error = 1 on stack overflow
|
||||
*/
|
||||
void forth_DECAY_RATE_FETCH(VM *vm) {
|
||||
if (vm->error) return;
|
||||
|
||||
if (vm->dsp >= STACK_SIZE) {
|
||||
vm->error = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Stack: ( -- rate ) */
|
||||
vm->data_stack[vm->dsp++] = (cell_t)DECAY_RATE_PER_US_Q16;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user