Add POST coverage for physics-freeze words (Module 27), fix two real bugs found in the process
Cluster 4 of the POST-coverage sweep: physics_freeze_words_test.c covers the 6 words proof/StarForth_Physics_Freeze_Words.thy actually gives real lemmas for (FREEZE-WORD, UNFREEZE-WORD, FROZEN?, HEAT!, HEAT@, DECAY-RATE@), correcting an earlier fork summary's wrong "5 words" scope. Writing the tests surfaced two independent, pre-existing bugs in physics_freeze_words.c, both now fixed: - Every address-taking word cast the VM's caddr directly to a host pointer instead of resolving it through vm_ptr() -- caddr is an offset into vm->memory, not a host pointer. Fixed in all 9 call sites (the 5 in-scope words plus SHOW-HEAT, which shares the identical pattern). - Every underflow check used dsp < N (item count) instead of dsp < N-1, since this VM's dsp is a 0-indexed top-of-stack pointer. Fixed in all 6 checks. Together these meant every word in this file taking a stack-supplied name has been broken for any real caller since the file was written. Verified zero build warnings and a clean three-arch QEMU boot (amd64/aarch64/riscv64), 1009 passed / 0 failed / 0 errors identically on all three, dict_hash matching across arches. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
825ab078f1
commit
abb858a300
@@ -82,8 +82,9 @@
|
||||
void forth_FREEZE_WORD(VM *vm) {
|
||||
if (vm->error) return;
|
||||
|
||||
/* Stack: ( caddr u -- ) */
|
||||
if (vm->dsp < 2) {
|
||||
/* Stack: ( caddr u -- ) -- dsp is a 0-indexed top-of-stack pointer,
|
||||
* so 2 items on stack means dsp >= 1, not dsp >= 2. */
|
||||
if (vm->dsp < 1) {
|
||||
vm->error = 1;
|
||||
return;
|
||||
}
|
||||
@@ -95,8 +96,9 @@ void forth_FREEZE_WORD(VM *vm) {
|
||||
return; /* Silently fail on invalid length */
|
||||
}
|
||||
|
||||
/* Convert VM address to C pointer (if using strict pointer mode) */
|
||||
const char *name = (const char *)(uintptr_t)caddr;
|
||||
/* caddr is a VM memory offset, not a host pointer -- resolve via vm_ptr() */
|
||||
const char *name = (const char *)vm_ptr(vm, (vaddr_t)(uint64_t)caddr);
|
||||
if (!name) return;
|
||||
|
||||
/* Look up the word */
|
||||
DictEntry *entry = vm_find_word(vm, name, (size_t)len);
|
||||
@@ -121,8 +123,9 @@ void forth_FREEZE_WORD(VM *vm) {
|
||||
void forth_UNFREEZE_WORD(VM *vm) {
|
||||
if (vm->error) return;
|
||||
|
||||
/* Stack: ( caddr u -- ) */
|
||||
if (vm->dsp < 2) {
|
||||
/* Stack: ( caddr u -- ) -- dsp is a 0-indexed top-of-stack pointer,
|
||||
* so 2 items on stack means dsp >= 1, not dsp >= 2. */
|
||||
if (vm->dsp < 1) {
|
||||
vm->error = 1;
|
||||
return;
|
||||
}
|
||||
@@ -134,7 +137,8 @@ void forth_UNFREEZE_WORD(VM *vm) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *name = (const char *)(uintptr_t)caddr;
|
||||
const char *name = (const char *)vm_ptr(vm, (vaddr_t)(uint64_t)caddr);
|
||||
if (!name) return;
|
||||
DictEntry *entry = vm_find_word(vm, name, (size_t)len);
|
||||
|
||||
if (entry) {
|
||||
@@ -157,8 +161,9 @@ void forth_UNFREEZE_WORD(VM *vm) {
|
||||
void forth_FROZEN_QUERY(VM *vm) {
|
||||
if (vm->error) return;
|
||||
|
||||
/* Stack: ( caddr u -- flag ) */
|
||||
if (vm->dsp < 2) {
|
||||
/* Stack: ( caddr u -- flag ) -- dsp is a 0-indexed top-of-stack pointer,
|
||||
* so 2 items on stack means dsp >= 1, not dsp >= 2. */
|
||||
if (vm->dsp < 1) {
|
||||
vm->error = 1;
|
||||
return;
|
||||
}
|
||||
@@ -171,8 +176,8 @@ void forth_FROZEN_QUERY(VM *vm) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *name = (const char *)(uintptr_t)caddr;
|
||||
DictEntry *entry = vm_find_word(vm, name, (size_t)len);
|
||||
const char *name = (const char *)vm_ptr(vm, (vaddr_t)(uint64_t)caddr);
|
||||
DictEntry *entry = name ? vm_find_word(vm, name, (size_t)len) : NULL;
|
||||
|
||||
if (entry && (entry->flags & WORD_FROZEN)) {
|
||||
vm->data_stack[vm->dsp++] = -1; /* True (frozen) */
|
||||
@@ -196,8 +201,9 @@ void forth_FROZEN_QUERY(VM *vm) {
|
||||
void forth_HEAT_STORE(VM *vm) {
|
||||
if (vm->error) return;
|
||||
|
||||
/* Stack: ( heat caddr u -- ) */
|
||||
if (vm->dsp < 3) {
|
||||
/* Stack: ( heat caddr u -- ) -- dsp is a 0-indexed top-of-stack pointer,
|
||||
* so 3 items on stack means dsp >= 2, not dsp >= 3. */
|
||||
if (vm->dsp < 2) {
|
||||
vm->error = 1;
|
||||
return;
|
||||
}
|
||||
@@ -210,7 +216,8 @@ void forth_HEAT_STORE(VM *vm) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *name = (const char *)(uintptr_t)caddr;
|
||||
const char *name = (const char *)vm_ptr(vm, (vaddr_t)(uint64_t)caddr);
|
||||
if (!name) return;
|
||||
DictEntry *entry = vm_find_word(vm, name, (size_t)len);
|
||||
|
||||
if (entry) {
|
||||
@@ -231,8 +238,9 @@ void forth_HEAT_STORE(VM *vm) {
|
||||
void forth_HEAT_FETCH(VM *vm) {
|
||||
if (vm->error) return;
|
||||
|
||||
/* Stack: ( caddr u -- heat ) */
|
||||
if (vm->dsp < 2) {
|
||||
/* Stack: ( caddr u -- heat ) -- dsp is a 0-indexed top-of-stack pointer,
|
||||
* so 2 items on stack means dsp >= 1, not dsp >= 2. */
|
||||
if (vm->dsp < 1) {
|
||||
vm->error = 1;
|
||||
return;
|
||||
}
|
||||
@@ -245,8 +253,8 @@ void forth_HEAT_FETCH(VM *vm) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *name = (const char *)(uintptr_t)caddr;
|
||||
DictEntry *entry = vm_find_word(vm, name, (size_t)len);
|
||||
const char *name = (const char *)vm_ptr(vm, (vaddr_t)(uint64_t)caddr);
|
||||
DictEntry *entry = name ? vm_find_word(vm, name, (size_t)len) : NULL;
|
||||
|
||||
if (entry) {
|
||||
vm->data_stack[vm->dsp++] = entry->execution_heat;
|
||||
@@ -270,8 +278,9 @@ void forth_HEAT_FETCH(VM *vm) {
|
||||
void forth_SHOW_HEAT(VM *vm) {
|
||||
if (vm->error) return;
|
||||
|
||||
/* Stack: ( caddr u -- ) */
|
||||
if (vm->dsp < 2) {
|
||||
/* Stack: ( caddr u -- ) -- dsp is a 0-indexed top-of-stack pointer,
|
||||
* so 2 items on stack means dsp >= 1, not dsp >= 2. */
|
||||
if (vm->dsp < 1) {
|
||||
vm->error = 1;
|
||||
return;
|
||||
}
|
||||
@@ -283,7 +292,8 @@ void forth_SHOW_HEAT(VM *vm) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *name = (const char *)(uintptr_t)caddr;
|
||||
const char *name = (const char *)vm_ptr(vm, (vaddr_t)(uint64_t)caddr);
|
||||
if (!name) return;
|
||||
DictEntry *entry = vm_find_word(vm, name, (size_t)len);
|
||||
|
||||
if (entry) {
|
||||
|
||||
Reference in New Issue
Block a user