diff --git a/crates/console/prometeu-system/src/virtual_machine_runtime.rs b/crates/console/prometeu-system/src/virtual_machine_runtime.rs index 1b2d665c..6df8768e 100644 --- a/crates/console/prometeu-system/src/virtual_machine_runtime.rs +++ b/crates/console/prometeu-system/src/virtual_machine_runtime.rs @@ -498,7 +498,7 @@ impl NativeInterface for VirtualMachineRuntime { return Ok(()); } Syscall::SystemRunCart => { - ret.push_null(); + // ret_slots = 0 (void). Must return exactly 0 values per SyscallMeta. return Ok(()); } _ => {} @@ -513,15 +513,14 @@ impl NativeInterface for VirtualMachineRuntime { // --- GFX Syscalls --- - // gfx.clear(color_index) -> null + // gfx.clear(color_index) -> void (ret_slots = 0) Syscall::GfxClear => { let color_val = expect_int(args, 0)?; let color = self.get_color(color_val); hw.gfx_mut().clear(color); - ret.push_null(); Ok(()) } - // gfx.draw_rect(x, y, w, h, color_index) -> null + // gfx.draw_rect(x, y, w, h, color_index) -> void (ret_slots = 0) Syscall::GfxFillRect => { let x = expect_int(args, 0)? as i32; let y = expect_int(args, 1)? as i32; @@ -530,10 +529,9 @@ impl NativeInterface for VirtualMachineRuntime { let color_val = expect_int(args, 4)?; let color = self.get_color(color_val); hw.gfx_mut().fill_rect(x, y, w, h, color); - ret.push_null(); Ok(()) } - // gfx.draw_line(x1, y1, x2, y2, color_index) -> null + // gfx.draw_line(x1, y1, x2, y2, color_index) -> void (ret_slots = 0) Syscall::GfxDrawLine => { let x1 = expect_int(args, 0)? as i32; let y1 = expect_int(args, 1)? as i32; @@ -542,10 +540,9 @@ impl NativeInterface for VirtualMachineRuntime { let color_val = expect_int(args, 4)?; let color = self.get_color(color_val); hw.gfx_mut().draw_line(x1, y1, x2, y2, color); - ret.push_null(); Ok(()) } - // gfx.draw_circle(x, y, r, color_index) -> null + // gfx.draw_circle(x, y, r, color_index) -> void (ret_slots = 0) Syscall::GfxDrawCircle => { let x = expect_int(args, 0)? as i32; let y = expect_int(args, 1)? as i32; @@ -553,10 +550,9 @@ impl NativeInterface for VirtualMachineRuntime { let color_val = expect_int(args, 3)?; let color = self.get_color(color_val); hw.gfx_mut().draw_circle(x, y, r, color); - ret.push_null(); Ok(()) } - // gfx.draw_disc(x, y, r, border_color_idx, fill_color_idx) -> null + // gfx.draw_disc(x, y, r, border_color_idx, fill_color_idx) -> void (ret_slots = 0) Syscall::GfxDrawDisc => { let x = expect_int(args, 0)? as i32; let y = expect_int(args, 1)? as i32; @@ -566,10 +562,9 @@ impl NativeInterface for VirtualMachineRuntime { let fill_color = self.get_color(fill_color_val); let border_color = self.get_color(border_color_val); hw.gfx_mut().draw_disc(x, y, r, border_color, fill_color); - ret.push_null(); Ok(()) } - // gfx.draw_square(x, y, w, h, border_color_idx, fill_color_idx) -> null + // gfx.draw_square(x, y, w, h, border_color_idx, fill_color_idx) -> void (ret_slots = 0) Syscall::GfxDrawSquare => { let x = expect_int(args, 0)? as i32; let y = expect_int(args, 1)? as i32; @@ -580,7 +575,6 @@ impl NativeInterface for VirtualMachineRuntime { let fill_color = self.get_color(fill_color_val); let border_color = self.get_color(border_color_val); hw.gfx_mut().draw_square(x, y, w, h, border_color, fill_color); - ret.push_null(); Ok(()) } // gfx.set_sprite(asset_name, id, x, y, tile_id, palette_id, active, flip_x, flip_y, priority) @@ -617,7 +611,7 @@ impl NativeInterface for VirtualMachineRuntime { priority, }; } - ret.push_null(); + // ret_slots = 0 (void). Must return exactly 0 values per SyscallMeta. Ok(()) } Syscall::GfxDrawText => { @@ -633,7 +627,7 @@ impl NativeInterface for VirtualMachineRuntime { let color_val = expect_int(args, 3)?; let color = self.get_color(color_val); hw.gfx_mut().draw_text(x, y, &msg, color); - ret.push_null(); + // ret_slots = 0 (void). Must return exactly 0 values per SyscallMeta. Ok(()) } // gfx.clear565(color_u16) -> void @@ -873,7 +867,7 @@ impl NativeInterface for VirtualMachineRuntime { 0, prometeu_hal::LoopMode::Off, ); - ret.push_null(); + // ret_slots = 0 (void). Must return exactly 0 values per SyscallMeta. Ok(()) } @@ -909,7 +903,7 @@ impl NativeInterface for VirtualMachineRuntime { hw.assets().find_slot_by_name(&asset_name, BankType::SOUNDS).unwrap_or(0); hw.audio_mut().play(bank_id, sample_id, voice_id, volume, pan, pitch, 0, loop_mode); - ret.push_null(); + // ret_slots = 0 (void). Must return exactly 0 values per SyscallMeta. Ok(()) } @@ -971,7 +965,7 @@ impl NativeInterface for VirtualMachineRuntime { Syscall::FsClose => { let handle = expect_int(args, 0)? as u32; self.open_files.remove(&handle); - ret.push_null(); + // ret_slots = 0 (void). Must return exactly 0 values per SyscallMeta. Ok(()) } // FS_LIST_DIR(path) @@ -1087,13 +1081,13 @@ impl NativeInterface for VirtualMachineRuntime { Syscall::AssetCommit => { let handle = expect_int(args, 0)? as u32; hw.assets().commit(handle); - ret.push_null(); + // ret_slots = 0 (void). Must return exactly 0 values per SyscallMeta. Ok(()) } Syscall::AssetCancel => { let handle = expect_int(args, 0)? as u32; hw.assets().cancel(handle); - ret.push_null(); + // ret_slots = 0 (void). Must return exactly 0 values per SyscallMeta. Ok(()) } Syscall::BankInfo => { diff --git a/crates/console/prometeu-vm/src/virtual_machine.rs b/crates/console/prometeu-vm/src/virtual_machine.rs index 87c94202..7e8c5ba6 100644 --- a/crates/console/prometeu-vm/src/virtual_machine.rs +++ b/crates/console/prometeu-vm/src/virtual_machine.rs @@ -1732,11 +1732,17 @@ mod tests { let mut ctx = HostContext::new(None); vm.prepare_call("0"); - vm.run_budget(100, &mut native, &mut ctx).unwrap(); - - assert_eq!(vm.pop().unwrap(), Value::Bounded(255)); - assert_eq!(vm.pop().unwrap(), Value::Int64(42)); - assert_eq!(vm.pop().unwrap(), Value::Boolean(true)); + // Ensure we have SYSTEM capability so we pass capability gate + vm.set_capabilities(prometeu_hal::syscalls::caps::SYSTEM); + let report = vm.run_budget(100, &mut native, &mut ctx).unwrap(); + // Under PR5, VM enforces return-slot count based on SyscallMeta during syscall + // execution. A mismatch yields a Panic with a descriptive message. + match report.reason { + LogicalFrameEndingReason::Panic(msg) => { + assert!(msg.contains("results mismatch")); + } + _ => panic!("Expected Panic with results mismatch, got {:?}", report.reason), + } } #[test] @@ -1810,6 +1816,8 @@ mod tests { let mut ctx = HostContext::new(None); vm.prepare_call("0"); + // Ensure we have GFX capability so we reach type checking inside native handler + vm.set_capabilities(prometeu_hal::syscalls::caps::GFX); let report = vm.run_budget(100, &mut native, &mut ctx).unwrap(); match report.reason { @@ -1832,6 +1840,8 @@ mod tests { let mut ctx = HostContext::new(None); vm.prepare_call("0"); + // Grant GFX capability so arg underflow is checked (capability gate is first) + vm.set_capabilities(prometeu_hal::syscalls::caps::GFX); let report = vm.run_budget(100, &mut native, &mut ctx).unwrap(); match report.reason { @@ -1857,6 +1867,8 @@ mod tests { let mut ctx = HostContext::new(None); vm.prepare_call("0"); + // Grant GFX capability so arg underflow is checked (capability gate is first) + vm.set_capabilities(prometeu_hal::syscalls::caps::GFX); let report = vm.run_budget(100, &mut native, &mut ctx).unwrap(); match report.reason { @@ -1949,6 +1961,8 @@ mod tests { } let mut vm = new_test_vm(rom.clone(), vec![]); + // Grant GFX capability so results mismatch path is exercised + vm.set_capabilities(prometeu_hal::syscalls::caps::GFX); let mut native = BadNative; let mut ctx = HostContext::new(None); diff --git a/crates/console/prometeu-vm/tests/syscall_multi_return.rs b/crates/console/prometeu-vm/tests/syscall_multi_return.rs index a2200b07..d361218b 100644 --- a/crates/console/prometeu-vm/tests/syscall_multi_return.rs +++ b/crates/console/prometeu-vm/tests/syscall_multi_return.rs @@ -44,6 +44,8 @@ fn vm_syscall_multi_return_stack_contents() { let mut native = TestNative; let mut ctx = HostContext::new(None); vm.prepare_call("0"); + // Grant INPUT capability to pass capability gate for PadGetUp + vm.set_capabilities(prometeu_hal::syscalls::caps::INPUT); let _ = vm.run_budget(100, &mut native, &mut ctx).expect("VM run failed"); // Verify stack order: last pushed is on top diff --git a/files/VM RESET.md b/files/VM RESET.md new file mode 100644 index 00000000..a8fa4440 --- /dev/null +++ b/files/VM RESET.md @@ -0,0 +1,34 @@ +6 — Closures (first-class user functions) + +6.1. Definir objeto Closure no heap: fn_id + env (captures) + metadata mínima. +6.2. Definir como capturas são materializadas (layout do env e como o bytecode cria closures). +6.3. Implementar instruções/semântica para criar closure e para CALL_CLOSURE. +6.4. Atualizar GC traversal: closure → env → heap refs internos. +6.5. Atualizar verifier: tipo “closure value”, validação de call sites, ret_slots. +6.6. Testes: closure simples, closure capturando, closure retornando outra closure. + +7 — Coroutines (único modelo de concorrência, cooperativo) + +7.1. Definir objeto Coroutine no heap: stack/frames próprios, status, wake time, mailbox/queue se existir. +7.2. Definir scheduler determinístico: fila pronta, fila dormindo, política estável. +7.3. Implementar SPAWN: criar coroutine + capturar entry + agendar. +7.4. Implementar YIELD: ceder controle de forma cooperativa (somente em locais válidos). +7.5. Implementar SLEEP: mover para fila dormindo até tick/time. +7.6. Integrar execução/switch apenas em safepoints (FRAME_SYNC). +7.7. Integrar GC roots: stacks suspensas e frames de todas as coroutines. +7.8. Verifier: invariantes (ex.: proibir yield em contextos ilegais, validar spawn args/ret). +7.9. Testes: determinismo (mesma ordem), sleep/wake, stress com GC + muitas coroutines. + +8 — Tooling & test harness (para manter “JVM-grade”) + +8.1. Disasm atualizado e confiável (roundtrip + snapshots). +8.2. Harness de execução determinística para testes (seed fixo, time controlado). +8.3. Suite de testes por camadas: bytecode (encode/decode), verifier, VM, GC, scheduler. +8.4. “No legacy artifacts” check: busca por símbolos/nomes (retain/release/hip/gate/scope), módulos mortos removidos. + +9 — Hardening final e documentação do novo baseline + +9.1. Consolidar documentação de arquitetura (curta, objetiva, em inglês). +9.2. Garantir que o “surface area” público está minimalista (APIs internas escondidas). +9.3. Remover qualquer feature flag temporária que tenha sobrado. +9.4. Rodar limpeza final: dead code, warnings, docs desatualizadas, exemplos antigos. \ No newline at end of file