Stage D batch 5: mama_forth_words.c group 3 -- cross-VM execution/dispatch, both flagged special cases resolved (FABRIC-3.md §XXXII.6)
VM-STEP/VM-EXEC/VM-CALL (5 sites) gained console_println() diagnostics
matching their own existing sibling guards.
SWITCH-MARK-WORK and VM-HEAT (3 sites) resolved per §XXXII.3's own
recommendation: dropped vm->error entirely rather than diagnosing it,
matching each function's own doc comment ("must never error or spam
the console" / "does not print/error"). SWITCH-MARK-WORK is the same
function §XXVIII.3 already fixed once for an off-by-one that fired
silently on every MSG-SEND in the system -- the guard now genuinely
cannot repeat that by contract, not just by the threshold being right.
VM-HEAT's guards now push 0 and return, matching its own
always-returns-a-value stack effect.
Three-arch clean qemu acceptance passed. Zuse's own WIREBIND attach
(every boot) drives MSG-SEND -> SWITCH-MARK-WORK, so this batch's most
safety-critical fix is exercised by standard acceptance, not just
compiled.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BWpNjdwPtFLuVLaAq44L9K
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
b42c3b195c
commit
8b5300fc4f
+20
@@ -4634,3 +4634,23 @@ gold-standard default for a function with nothing else to match against.
|
|||||||
`BIRTH` itself is exercised heavily by every boot (Hermes/Artemis birth), a real regression check
|
`BIRTH` itself is exercised heavily by every boot (Hermes/Artemis birth), a real regression check
|
||||||
beyond compile-cleanliness for this specific batch.
|
beyond compile-cleanliness for this specific batch.
|
||||||
|
|
||||||
|
**Batch 5 -- DONE, 2026-09-15: group 3, cross-VM execution/dispatch (`VM-STEP`/`VM-EXEC`/
|
||||||
|
`VM-CALL`/`SWITCH-MARK-WORK`/`VM-HEAT`) -- 11 sites, including both flagged special cases.**
|
||||||
|
`VM-STEP` (1 site), `VM-EXEC` (2), `VM-CALL` (2) gained `console_println()` diagnostics matching
|
||||||
|
their own existing sibling guards, same shape as batch 4.
|
||||||
|
|
||||||
|
**The two flagged special cases resolved per §XXXII.3's own recommendation -- dropped the error
|
||||||
|
entirely, not diagnosed.** `SWITCH-MARK-WORK`'s underflow guard (`dsp < 1`) now bare-returns,
|
||||||
|
matching its own doc comment's "must never error or spam the console" contract exactly -- this
|
||||||
|
is the same function §XXVIII.3 already fixed once for an off-by-one that fired on every
|
||||||
|
`MSG-SEND` in the system; the guard now genuinely cannot do that again, by contract rather than
|
||||||
|
by accident of the threshold being right. `VM-HEAT`'s two guards (`dsp < 1`, bad address) now
|
||||||
|
push `0` and return, matching the word's own "unknown name -> push 0, never error" contract and
|
||||||
|
its own always-returns-a-value stack effect -- previously these two specific guards were the
|
||||||
|
only ways to make this word violate its own documented promise.
|
||||||
|
|
||||||
|
**Verified:** three-architecture `clean qemu` acceptance (amd64/aarch64/riscv64) passed. Zuse's
|
||||||
|
own WIREBIND attach (every boot) drives `HERA-BLK-ATTACH-REQ`'s `MSG-SEND`, which tail-calls
|
||||||
|
`SWITCH-MARK-WORK` -- so this fix's own most safety-critical path is exercised by the standard
|
||||||
|
acceptance boot itself, not just compiled.
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Capsule Block Manifest — Auto-generated
|
# Capsule Block Manifest — Auto-generated
|
||||||
<!-- Generated by mkcapsule --manifest 2026-09-15T22:41:56Z -->
|
<!-- Generated by mkcapsule --manifest 2026-09-15T23:13:32Z -->
|
||||||
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
|
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
|
||||||
<!-- Hand-written justifications and immutability notes live -->
|
<!-- Hand-written justifications and immutability notes live -->
|
||||||
<!-- in MANIFEST.md alongside this auto-generated index. -->
|
<!-- in MANIFEST.md alongside this auto-generated index. -->
|
||||||
|
|||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -680,7 +680,11 @@ static void mama_word_vm_step(VM *vm)
|
|||||||
VM *target;
|
VM *target;
|
||||||
char saved_name[VM_NAME_MAX];
|
char saved_name[VM_NAME_MAX];
|
||||||
|
|
||||||
if (vm->dsp < 1) { vm->error = 1; return; }
|
if (vm->dsp < 1) {
|
||||||
|
console_println("VM-STEP: expects S\" name\" VM-STEP -- nothing on the stack");
|
||||||
|
vm->error = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
u = vm_pop(vm);
|
u = vm_pop(vm);
|
||||||
caddr = vm_pop(vm);
|
caddr = vm_pop(vm);
|
||||||
@@ -692,7 +696,11 @@ static void mama_word_vm_step(VM *vm)
|
|||||||
|
|
||||||
{
|
{
|
||||||
const uint8_t *p = vm_ptr(vm, (vaddr_t)caddr);
|
const uint8_t *p = vm_ptr(vm, (vaddr_t)caddr);
|
||||||
if (!p) { vm->error = 1; return; }
|
if (!p) {
|
||||||
|
console_println("VM-STEP: invalid address on the stack");
|
||||||
|
vm->error = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
src = (const char *)p;
|
src = (const char *)p;
|
||||||
}
|
}
|
||||||
for (i = 0; i < (uint32_t)u; i++) name_buf[i] = src[i];
|
for (i = 0; i < (uint32_t)u; i++) name_buf[i] = src[i];
|
||||||
@@ -741,7 +749,11 @@ static void mama_word_vm_exec(VM *vm)
|
|||||||
VM *target;
|
VM *target;
|
||||||
char saved_name[VM_NAME_MAX];
|
char saved_name[VM_NAME_MAX];
|
||||||
|
|
||||||
if (vm->dsp < 3) { vm->error = 1; return; }
|
if (vm->dsp < 3) {
|
||||||
|
console_println("VM-EXEC: expects S\" cmd\" S\" name\" VM-EXEC -- too few items on the stack");
|
||||||
|
vm->error = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* TOS: vm-name-u, vm-name-caddr, cmd-u, cmd-caddr */
|
/* TOS: vm-name-u, vm-name-caddr, cmd-u, cmd-caddr */
|
||||||
vm_u = vm_pop(vm);
|
vm_u = vm_pop(vm);
|
||||||
@@ -760,7 +772,11 @@ static void mama_word_vm_exec(VM *vm)
|
|||||||
|
|
||||||
{
|
{
|
||||||
const uint8_t *p = vm_ptr(vm, (vaddr_t)vm_caddr);
|
const uint8_t *p = vm_ptr(vm, (vaddr_t)vm_caddr);
|
||||||
if (!p) { vm->error = 1; return; }
|
if (!p) {
|
||||||
|
console_println("VM-EXEC: invalid VM-name address on the stack");
|
||||||
|
vm->error = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
src = (const char *)p;
|
src = (const char *)p;
|
||||||
}
|
}
|
||||||
for (i = 0; i < (uint32_t)vm_u; i++) vm_name[i] = src[i];
|
for (i = 0; i < (uint32_t)vm_u; i++) vm_name[i] = src[i];
|
||||||
@@ -768,7 +784,11 @@ static void mama_word_vm_exec(VM *vm)
|
|||||||
|
|
||||||
{
|
{
|
||||||
const uint8_t *p = vm_ptr(vm, (vaddr_t)cmd_caddr);
|
const uint8_t *p = vm_ptr(vm, (vaddr_t)cmd_caddr);
|
||||||
if (!p) { vm->error = 1; return; }
|
if (!p) {
|
||||||
|
console_println("VM-EXEC: invalid command address on the stack");
|
||||||
|
vm->error = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
src = (const char *)p;
|
src = (const char *)p;
|
||||||
}
|
}
|
||||||
for (i = 0; i < (uint32_t)cmd_u; i++) cmd_buf[i] = src[i];
|
for (i = 0; i < (uint32_t)cmd_u; i++) cmd_buf[i] = src[i];
|
||||||
@@ -823,7 +843,12 @@ static void mama_word_switch_mark_work(VM *vm)
|
|||||||
uint32_t i;
|
uint32_t i;
|
||||||
VMRegistryEntry entry;
|
VMRegistryEntry entry;
|
||||||
|
|
||||||
if (vm->dsp < 1) { vm->error = 1; return; }
|
/* FABRIC-3.md §XXXII.6, 2026-09-15: this guard used to set vm->error on
|
||||||
|
* underflow, contradicting this function's own doc comment above ("must
|
||||||
|
* never error or spam the console") -- flagged as a special case in
|
||||||
|
* §XXXII.3's triage, not just a missing diagnostic. Silently ignored,
|
||||||
|
* matching every other malformed-input case in this same function. */
|
||||||
|
if (vm->dsp < 1) return;
|
||||||
|
|
||||||
u = vm_pop(vm);
|
u = vm_pop(vm);
|
||||||
caddr = vm_pop(vm);
|
caddr = vm_pop(vm);
|
||||||
@@ -860,7 +885,11 @@ static void mama_word_vm_call(VM *vm)
|
|||||||
VM *target;
|
VM *target;
|
||||||
char saved_name[VM_NAME_MAX];
|
char saved_name[VM_NAME_MAX];
|
||||||
|
|
||||||
if (vm->dsp < 3) { vm->error = 1; return; }
|
if (vm->dsp < 3) {
|
||||||
|
console_println("VM-CALL: expects S\" cmd\" S\" name\" VM-CALL -- too few items on the stack");
|
||||||
|
vm->error = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
vm_u = vm_pop(vm);
|
vm_u = vm_pop(vm);
|
||||||
vm_caddr = vm_pop(vm);
|
vm_caddr = vm_pop(vm);
|
||||||
@@ -878,7 +907,11 @@ static void mama_word_vm_call(VM *vm)
|
|||||||
|
|
||||||
{
|
{
|
||||||
const uint8_t *p = vm_ptr(vm, (vaddr_t)vm_caddr);
|
const uint8_t *p = vm_ptr(vm, (vaddr_t)vm_caddr);
|
||||||
if (!p) { vm->error = 1; return; }
|
if (!p) {
|
||||||
|
console_println("VM-CALL: invalid VM-name address on the stack");
|
||||||
|
vm->error = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
src = (const char *)p;
|
src = (const char *)p;
|
||||||
}
|
}
|
||||||
for (i = 0; i < (uint32_t)vm_u; i++) vm_name[i] = src[i];
|
for (i = 0; i < (uint32_t)vm_u; i++) vm_name[i] = src[i];
|
||||||
@@ -886,7 +919,11 @@ static void mama_word_vm_call(VM *vm)
|
|||||||
|
|
||||||
{
|
{
|
||||||
const uint8_t *p = vm_ptr(vm, (vaddr_t)cmd_caddr);
|
const uint8_t *p = vm_ptr(vm, (vaddr_t)cmd_caddr);
|
||||||
if (!p) { vm->error = 1; return; }
|
if (!p) {
|
||||||
|
console_println("VM-CALL: invalid command address on the stack");
|
||||||
|
vm->error = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
src = (const char *)p;
|
src = (const char *)p;
|
||||||
}
|
}
|
||||||
for (i = 0; i < (uint32_t)cmd_u; i++) cmd_buf[i] = src[i];
|
for (i = 0; i < (uint32_t)cmd_u; i++) cmd_buf[i] = src[i];
|
||||||
@@ -952,7 +989,13 @@ static void mama_word_vm_heat(VM *vm)
|
|||||||
const char *src;
|
const char *src;
|
||||||
VMRegistryEntry entry;
|
VMRegistryEntry entry;
|
||||||
|
|
||||||
if (vm->dsp < 1) { vm->error = 1; return; }
|
/* FABRIC-3.md §XXXII.6, 2026-09-15: both guards below used to set
|
||||||
|
* vm->error, contradicting this function's own doc comment above
|
||||||
|
* ("does not print/error") -- flagged as a special case in §XXXII.3's
|
||||||
|
* triage. Push the same 0 the "unknown name" case already returns,
|
||||||
|
* matching this word's own always-returns-a-value contract, instead
|
||||||
|
* of erroring. */
|
||||||
|
if (vm->dsp < 1) { vm_push(vm, 0); return; }
|
||||||
|
|
||||||
vm_u = vm_pop(vm);
|
vm_u = vm_pop(vm);
|
||||||
vm_caddr = vm_pop(vm);
|
vm_caddr = vm_pop(vm);
|
||||||
@@ -964,7 +1007,7 @@ static void mama_word_vm_heat(VM *vm)
|
|||||||
|
|
||||||
{
|
{
|
||||||
const uint8_t *p = vm_ptr(vm, (vaddr_t)vm_caddr);
|
const uint8_t *p = vm_ptr(vm, (vaddr_t)vm_caddr);
|
||||||
if (!p) { vm->error = 1; return; }
|
if (!p) { vm_push(vm, 0); return; }
|
||||||
src = (const char *)p;
|
src = (const char *)p;
|
||||||
}
|
}
|
||||||
for (i = 0; i < (uint32_t)vm_u; i++) vm_name[i] = src[i];
|
for (i = 0; i < (uint32_t)vm_u; i++) vm_name[i] = src[i];
|
||||||
|
|||||||
Reference in New Issue
Block a user