This commit is contained in:
bQUARKz 2026-02-20 17:52:12 +00:00
parent 1a782cbb5c
commit a199857280
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
32 changed files with 118 additions and 463 deletions

View File

@ -98,6 +98,7 @@ impl Value {
} }
} }
#[allow(clippy::inherent_to_string)]
pub fn to_string(&self) -> String { pub fn to_string(&self) -> String {
match self { match self {
Value::Int32(i) => i.to_string(), Value::Int32(i) => i.to_string(),

View File

@ -1,3 +1,4 @@
#![allow(clippy::collapsible_if)]
use crate::memory_banks::{SoundBankPoolInstaller, TileBankPoolInstaller}; use crate::memory_banks::{SoundBankPoolInstaller, TileBankPoolInstaller};
use prometeu_hal::AssetBridge; use prometeu_hal::AssetBridge;
use prometeu_hal::asset::{ use prometeu_hal::asset::{
@ -486,12 +487,12 @@ impl AssetManager {
let palette_data = &buffer[pixel_data_size..pixel_data_size + 2048]; let palette_data = &buffer[pixel_data_size..pixel_data_size + 2048];
let mut palettes = [[Color::BLACK; 16]; 64]; let mut palettes = [[Color::BLACK; 16]; 64];
for p in 0..64 { for (p, pal) in palettes.iter_mut().enumerate() {
for c in 0..16 { for (c, slot) in pal.iter_mut().enumerate() {
let offset = (p * 16 + c) * 2; let offset = (p * 16 + c) * 2;
let color_raw = let color_raw =
u16::from_le_bytes([palette_data[offset], palette_data[offset + 1]]); u16::from_le_bytes([palette_data[offset], palette_data[offset + 1]]);
palettes[p][c] = Color(color_raw); *slot = Color(color_raw);
} }
} }
@ -687,7 +688,7 @@ impl AssetManager {
match slot.asset_type { match slot.asset_type {
BankType::TILES => { BankType::TILES => {
let slots = self.gfx_slots.read().unwrap(); let slots = self.gfx_slots.read().unwrap();
let asset_id = slots.get(slot.index).and_then(|s| s.clone()); let asset_id = slots.get(slot.index).and_then(|s| *s);
let (bytes, asset_name) = if let Some(id) = &asset_id { let (bytes, asset_name) = if let Some(id) = &asset_id {
let bytes = self let bytes = self
@ -708,7 +709,7 @@ impl AssetManager {
} }
BankType::SOUNDS => { BankType::SOUNDS => {
let slots = self.sound_slots.read().unwrap(); let slots = self.sound_slots.read().unwrap();
let asset_id = slots.get(slot.index).and_then(|s| s.clone()); let asset_id = slots.get(slot.index).and_then(|s| *s);
let (bytes, asset_name) = if let Some(id) = &asset_id { let (bytes, asset_name) = if let Some(id) = &asset_id {
let bytes = self let bytes = self

View File

@ -8,6 +8,7 @@ pub enum LoopMode {
} }
pub trait AudioBridge { pub trait AudioBridge {
#[allow(clippy::too_many_arguments)]
fn play( fn play(
&mut self, &mut self,
bank_id: u8, bank_id: u8,
@ -19,6 +20,7 @@ pub trait AudioBridge {
priority: u8, priority: u8,
loop_mode: LoopMode, loop_mode: LoopMode,
); );
#[allow(clippy::too_many_arguments)]
fn play_sample( fn play_sample(
&mut self, &mut self,
sample: Arc<Sample>, sample: Arc<Sample>,

View File

@ -27,7 +27,7 @@ pub struct Button {
impl Button { impl Button {
pub fn begin_frame(&mut self, is_down_now: bool) { pub fn begin_frame(&mut self, is_down_now: bool) {
let was_down = self.down; let was_down = self.down;
self.down = is_down_now.clone(); self.down = is_down_now;
self.pressed = !was_down && self.down; self.pressed = !was_down && self.down;
self.released = was_down && !self.down; self.released = was_down && !self.down;

View File

@ -50,55 +50,55 @@ impl Certifier {
let mut violations = 0; let mut violations = 0;
if let Some(budget) = self.config.cycles_budget_per_frame { if let Some(budget) = self.config.cycles_budget_per_frame
if telemetry.cycles_used > budget { && telemetry.cycles_used > budget
log_service.log( {
ts_ms, log_service.log(
telemetry.frame_index, ts_ms,
LogLevel::Warn, telemetry.frame_index,
LogSource::Pos, LogLevel::Warn,
0xCA01, LogSource::Pos,
format!( 0xCA01,
"Cert: cycles_used exceeded budget ({} > {})", format!(
telemetry.cycles_used, budget "Cert: cycles_used exceeded budget ({} > {})",
), telemetry.cycles_used, budget
); ),
violations += 1; );
} violations += 1;
} }
if let Some(limit) = self.config.max_syscalls_per_frame { if let Some(limit) = self.config.max_syscalls_per_frame
if telemetry.syscalls > limit { && telemetry.syscalls > limit
log_service.log( {
ts_ms, log_service.log(
telemetry.frame_index, ts_ms,
LogLevel::Warn, telemetry.frame_index,
LogSource::Pos, LogLevel::Warn,
0xCA02, LogSource::Pos,
format!( 0xCA02,
"Cert: syscalls per frame exceeded limit ({} > {})", format!(
telemetry.syscalls, limit "Cert: syscalls per frame exceeded limit ({} > {})",
), telemetry.syscalls, limit
); ),
violations += 1; );
} violations += 1;
} }
if let Some(limit) = self.config.max_host_cpu_us_per_frame { if let Some(limit) = self.config.max_host_cpu_us_per_frame
if telemetry.host_cpu_time_us > limit { && telemetry.host_cpu_time_us > limit
log_service.log( {
ts_ms, log_service.log(
telemetry.frame_index, ts_ms,
LogLevel::Warn, telemetry.frame_index,
LogSource::Pos, LogLevel::Warn,
0xCA03, LogSource::Pos,
format!( 0xCA03,
"Cert: host_cpu_time_us exceeded limit ({} > {})", format!(
telemetry.host_cpu_time_us, limit "Cert: host_cpu_time_us exceeded limit ({} > {})",
), telemetry.host_cpu_time_us, limit
); ),
violations += 1; );
} violations += 1;
} }
violations violations

View File

@ -54,6 +54,7 @@ impl Heap {
/// Allocate a new object with the given kind and raw payload bytes. /// Allocate a new object with the given kind and raw payload bytes.
/// Returns an opaque `HeapRef` handle. /// Returns an opaque `HeapRef` handle.
#[cfg(test)]
pub fn allocate_object(&mut self, kind: ObjectKind, payload: &[u8]) -> HeapRef { pub fn allocate_object(&mut self, kind: ObjectKind, payload: &[u8]) -> HeapRef {
let header = ObjectHeader::new(kind, payload.len() as u32); let header = ObjectHeader::new(kind, payload.len() as u32);
let obj = StoredObject { header, payload: payload.to_vec(), array_elems: None, closure_env: None, coroutine: None }; let obj = StoredObject { header, payload: payload.to_vec(), array_elems: None, closure_env: None, coroutine: None };
@ -65,6 +66,7 @@ impl Heap {
/// Allocate a new `Array` object with the given `Value` elements. /// Allocate a new `Array` object with the given `Value` elements.
/// `payload_len` stores the element count; raw `payload` bytes are empty. /// `payload_len` stores the element count; raw `payload` bytes are empty.
#[cfg(test)]
pub fn allocate_array(&mut self, elements: Vec<Value>) -> HeapRef { pub fn allocate_array(&mut self, elements: Vec<Value>) -> HeapRef {
let header = ObjectHeader::new(ObjectKind::Array, elements.len() as u32); let header = ObjectHeader::new(ObjectKind::Array, elements.len() as u32);
let obj = StoredObject { header, payload: Vec::new(), array_elems: Some(elements), closure_env: None, coroutine: None }; let obj = StoredObject { header, payload: Vec::new(), array_elems: Some(elements), closure_env: None, coroutine: None };
@ -128,6 +130,7 @@ impl Heap {
} }
/// Returns a shared reference to the coroutine data for the given handle, if it is a Coroutine. /// Returns a shared reference to the coroutine data for the given handle, if it is a Coroutine.
#[cfg(test)]
pub fn coroutine_data(&self, r: HeapRef) -> Option<&CoroutineData> { pub fn coroutine_data(&self, r: HeapRef) -> Option<&CoroutineData> {
let idx = r.0 as usize; let idx = r.0 as usize;
self.objects.get(idx).and_then(|slot| slot.as_ref()).and_then(|obj| obj.coroutine.as_ref()) self.objects.get(idx).and_then(|slot| slot.as_ref()).and_then(|obj| obj.coroutine.as_ref())
@ -158,8 +161,8 @@ impl Heap {
.map(|o| &mut o.header) .map(|o| &mut o.header)
} }
/// Internal: list inner `HeapRef` children of an object without allocating. // Internal: list inner `HeapRef` children of an object without allocating.
/// Note: GC mark no longer uses this helper; kept for potential diagnostics. // Note: GC mark no longer uses this helper; kept for potential diagnostics.
// fn children_of(&self, r: HeapRef) -> Box<dyn Iterator<Item = HeapRef> + '_> { // fn children_of(&self, r: HeapRef) -> Box<dyn Iterator<Item = HeapRef> + '_> {
// let idx = r.0 as usize; // let idx = r.0 as usize;
// if let Some(Some(o)) = self.objects.get(idx) { // if let Some(Some(o)) = self.objects.get(idx) {
@ -221,6 +224,7 @@ impl Heap {
} }
/// Get the captured environment slice of a closure. Returns None if kind mismatch or invalid ref. /// Get the captured environment slice of a closure. Returns None if kind mismatch or invalid ref.
#[cfg(test)]
pub fn closure_env_slice(&self, r: HeapRef) -> Option<&[Value]> { pub fn closure_env_slice(&self, r: HeapRef) -> Option<&[Value]> {
let idx = r.0 as usize; let idx = r.0 as usize;
let slot = self.objects.get(idx)?.as_ref()?; let slot = self.objects.get(idx)?.as_ref()?;
@ -261,14 +265,14 @@ impl Heap {
ObjectKind::Array => { ObjectKind::Array => {
if let Some(elems) = obj.array_elems.as_ref() { if let Some(elems) = obj.array_elems.as_ref() {
for val in elems.iter() { for val in elems.iter() {
if let Value::HeapRef(child) = val { if let Value::HeapRef(child) = val
if self.is_valid(*child) { && self.is_valid(*child)
let marked = self {
.header(*child) let marked = self
.map(|h: &ObjectHeader| h.is_marked()) .header(*child)
.unwrap_or(false); .map(|h: &ObjectHeader| h.is_marked())
if !marked { stack.push(*child); } .unwrap_or(false);
} if !marked { stack.push(*child); }
} }
} }
} }
@ -281,14 +285,14 @@ impl Heap {
if let Some(env) = obj.closure_env.as_ref() { if let Some(env) = obj.closure_env.as_ref() {
debug_assert_eq!(env.len(), env_len, "closure env len must match encoded env_len"); debug_assert_eq!(env.len(), env_len, "closure env len must match encoded env_len");
for val in env[..env_len].iter() { for val in env[..env_len].iter() {
if let Value::HeapRef(child) = val { if let Value::HeapRef(child) = val
if self.is_valid(*child) { && self.is_valid(*child)
let marked = self {
.header(*child) let marked = self
.map(|h: &ObjectHeader| h.is_marked()) .header(*child)
.unwrap_or(false); .map(|h: &ObjectHeader| h.is_marked())
if !marked { stack.push(*child); } .unwrap_or(false);
} if !marked { stack.push(*child); }
} }
} }
} }
@ -296,14 +300,14 @@ impl Heap {
ObjectKind::Coroutine => { ObjectKind::Coroutine => {
if let Some(co) = obj.coroutine.as_ref() { if let Some(co) = obj.coroutine.as_ref() {
for val in co.stack.iter() { for val in co.stack.iter() {
if let Value::HeapRef(child) = val { if let Value::HeapRef(child) = val
if self.is_valid(*child) { && self.is_valid(*child)
let marked = self {
.header(*child) let marked = self
.map(|h: &ObjectHeader| h.is_marked()) .header(*child)
.unwrap_or(false); .map(|h: &ObjectHeader| h.is_marked())
if !marked { stack.push(*child); } .unwrap_or(false);
} if !marked { stack.push(*child); }
} }
} }
} }
@ -333,7 +337,6 @@ impl Heap {
/// Current number of allocated (live) objects. /// Current number of allocated (live) objects.
pub fn len(&self) -> usize { self.objects.iter().filter(|s| s.is_some()).count() } pub fn len(&self) -> usize { self.objects.iter().filter(|s| s.is_some()).count() }
pub fn is_empty(&self) -> bool { self.len() == 0 }
/// Enumerate handles of coroutines that are currently suspended (i.e., not running): /// Enumerate handles of coroutines that are currently suspended (i.e., not running):
/// Ready or Sleeping. These must be treated as GC roots by the runtime so their /// Ready or Sleeping. These must be treated as GC roots by the runtime so their
@ -341,14 +344,12 @@ impl Heap {
pub fn suspended_coroutine_handles(&self) -> Vec<HeapRef> { pub fn suspended_coroutine_handles(&self) -> Vec<HeapRef> {
let mut out = Vec::new(); let mut out = Vec::new();
for (idx, slot) in self.objects.iter().enumerate() { for (idx, slot) in self.objects.iter().enumerate() {
if let Some(obj) = slot { if let Some(obj) = slot
if obj.header.kind == ObjectKind::Coroutine { && obj.header.kind == ObjectKind::Coroutine
if let Some(co) = &obj.coroutine { && let Some(co) = &obj.coroutine
if matches!(co.state, CoroutineState::Ready | CoroutineState::Sleeping) { && matches!(co.state, CoroutineState::Ready | CoroutineState::Sleeping)
out.push(HeapRef(idx as u32)); {
} out.push(HeapRef(idx as u32));
}
}
} }
} }
out out

View File

@ -51,12 +51,15 @@
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum ObjectKind { pub enum ObjectKind {
/// Reserved/unknown kind. Should not appear in valid allocations. /// Reserved/unknown kind. Should not appear in valid allocations.
#[allow(dead_code)] // Kept for stable tag layout and persisted images, even if not constructed in this crate yet
Unknown = 0, Unknown = 0,
/// UTF-8 string. `payload_len` is the number of bytes. /// UTF-8 string. `payload_len` is the number of bytes.
#[allow(dead_code)] // Public/stable tag retained; construction may live in higher layers
String = 1, String = 1,
/// Homogeneous array of VM values/handles. `payload_len` is element count. /// Homogeneous array of VM values/handles. `payload_len` is element count.
#[allow(dead_code)] // Public/stable tag retained; constructed via Heap helpers in tests
Array = 2, Array = 2,
/// Compiled closure/function value. /// Compiled closure/function value.
@ -69,9 +72,11 @@ pub enum ObjectKind {
Closure = 3, Closure = 3,
/// Byte buffer / blob. `payload_len` is the number of bytes. /// Byte buffer / blob. `payload_len` is the number of bytes.
#[allow(dead_code)] // Public/stable tag retained for future/host APIs
Bytes = 4, Bytes = 4,
/// User-defined/native host object. Payload shape is host-defined. /// User-defined/native host object. Payload shape is host-defined.
#[allow(dead_code)] // Reserved for host/native integrations
UserData = 5, UserData = 5,
/// Coroutine object: suspended execution context with its own stack/frames. /// Coroutine object: suspended execution context with its own stack/frames.

View File

@ -42,11 +42,14 @@ impl Scheduler {
self.ready_queue.pop_front() self.ready_queue.pop_front()
} }
#[cfg(test)]
pub fn is_ready_empty(&self) -> bool { self.ready_queue.is_empty() } pub fn is_ready_empty(&self) -> bool { self.ready_queue.is_empty() }
#[cfg(test)]
pub fn ready_len(&self) -> usize { self.ready_queue.len() } pub fn ready_len(&self) -> usize { self.ready_queue.len() }
// ---------- Current tracking (no switching here) ---------- // ---------- Current tracking (no switching here) ----------
pub fn set_current(&mut self, coro: Option<HeapRef>) { self.current = coro; } pub fn set_current(&mut self, coro: Option<HeapRef>) { self.current = coro; }
#[cfg(test)]
pub fn current(&self) -> Option<HeapRef> { self.current } pub fn current(&self) -> Option<HeapRef> { self.current }
pub fn clear_current(&mut self) { self.current = None; } pub fn clear_current(&mut self) { self.current = None; }

View File

@ -208,10 +208,8 @@ impl Verifier {
} }
// Coroutine safety: forbid YIELD when operand stack is not empty (minimal rule) // Coroutine safety: forbid YIELD when operand stack is not empty (minimal rule)
if let OpCode::Yield = instr.opcode { if let OpCode::Yield = instr.opcode && in_height != 0 {
if in_height != 0 { return Err(VerifierError::InvalidYieldContext { pc: func_start + pc, height: in_height });
return Err(VerifierError::InvalidYieldContext { pc: func_start + pc, height: in_height });
}
} }
// Compute out types vector with closure-aware rules // Compute out types vector with closure-aware rules
@ -317,7 +315,7 @@ impl Verifier {
} }
} }
let _pushes_final = dynamic_pushes.unwrap_or_else(|| match instr.opcode { let _pushes_final = dynamic_pushes.unwrap_or(match instr.opcode {
OpCode::MakeClosure => 1, OpCode::MakeClosure => 1,
OpCode::CallClosure => { OpCode::CallClosure => {
// If we reached here, we handled it above and set dynamic_pushes // If we reached here, we handled it above and set dynamic_pushes
@ -340,14 +338,12 @@ impl Verifier {
}); });
} }
if instr.opcode == OpCode::Ret { if instr.opcode == OpCode::Ret && in_height != func.return_slots {
if in_height != func.return_slots { return Err(VerifierError::BadRetStackHeight {
return Err(VerifierError::BadRetStackHeight { pc: func_start + pc,
pc: func_start + pc, height: in_height,
height: in_height, expected: func.return_slots,
expected: func.return_slots, });
});
}
} }
// Propagate to successors // Propagate to successors

View File

@ -228,7 +228,7 @@ impl VirtualMachine {
// Resolve the entrypoint: empty (defaults to func 0), numeric func_idx, or symbol name. // Resolve the entrypoint: empty (defaults to func 0), numeric func_idx, or symbol name.
let pc = if entrypoint.is_empty() { let pc = if entrypoint.is_empty() {
program.functions.get(0).map(|f| f.code_offset as usize).unwrap_or(0) program.functions.first().map(|f| f.code_offset as usize).unwrap_or(0)
} else if let Ok(func_idx) = entrypoint.parse::<usize>() { } else if let Ok(func_idx) = entrypoint.parse::<usize>() {
program program
.functions .functions
@ -525,7 +525,7 @@ impl VirtualMachine {
.imm_u32() .imm_u32()
.map_err(|e| LogicalFrameEndingReason::Panic(format!("{:?}", e)))? .map_err(|e| LogicalFrameEndingReason::Panic(format!("{:?}", e)))?
as usize; as usize;
let val = self.pop().map_err(|e| LogicalFrameEndingReason::Panic(e))?; let val = self.pop().map_err(LogicalFrameEndingReason::Panic)?;
match val { match val {
Value::Boolean(false) => { Value::Boolean(false) => {
let func_start = self let func_start = self
@ -551,7 +551,7 @@ impl VirtualMachine {
.imm_u32() .imm_u32()
.map_err(|e| LogicalFrameEndingReason::Panic(format!("{:?}", e)))? .map_err(|e| LogicalFrameEndingReason::Panic(format!("{:?}", e)))?
as usize; as usize;
let val = self.pop().map_err(|e| LogicalFrameEndingReason::Panic(e))?; let val = self.pop().map_err(LogicalFrameEndingReason::Panic)?;
match val { match val {
Value::Boolean(true) => { Value::Boolean(true) => {
let func_start = self let func_start = self
@ -622,7 +622,7 @@ impl VirtualMachine {
// Pop args top-first, then reverse to logical order arg1..argN // Pop args top-first, then reverse to logical order arg1..argN
let mut args: Vec<Value> = Vec::with_capacity(arg_count); let mut args: Vec<Value> = Vec::with_capacity(arg_count);
for _ in 0..arg_count { for _ in 0..arg_count {
args.push(self.pop().map_err(|e| LogicalFrameEndingReason::Panic(e))?); args.push(self.pop().map_err(LogicalFrameEndingReason::Panic)?);
} }
args.reverse(); args.reverse();
@ -1040,7 +1040,7 @@ impl VirtualMachine {
_ => Err(OpError::Panic("Invalid types for MOD".into())), _ => Err(OpError::Panic("Invalid types for MOD".into())),
})?, })?,
OpCode::BoundToInt => { OpCode::BoundToInt => {
let val = self.pop().map_err(|e| LogicalFrameEndingReason::Panic(e))?; let val = self.pop().map_err(LogicalFrameEndingReason::Panic)?;
if let Value::Bounded(b) = val { if let Value::Bounded(b) = val {
self.push(Value::Int64(b as i64)); self.push(Value::Int64(b as i64));
} else { } else {
@ -1050,13 +1050,13 @@ impl VirtualMachine {
} }
} }
OpCode::IntToBoundChecked => { OpCode::IntToBoundChecked => {
let val = self.pop().map_err(|e| LogicalFrameEndingReason::Panic(e))?; let val = self.pop().map_err(LogicalFrameEndingReason::Panic)?;
let int_val = val.as_integer().ok_or_else(|| { let int_val = val.as_integer().ok_or_else(|| {
LogicalFrameEndingReason::Panic( LogicalFrameEndingReason::Panic(
"Expected integer for INT_TO_BOUND_CHECKED".into(), "Expected integer for INT_TO_BOUND_CHECKED".into(),
) )
})?; })?;
if int_val < 0 || int_val > 0xFFFF { if !(0..=0xFFFF).contains(&int_val) {
return Err(self.trap( return Err(self.trap(
TRAP_OOB, TRAP_OOB,
OpCode::IntToBoundChecked as u16, OpCode::IntToBoundChecked as u16,
@ -1101,7 +1101,7 @@ impl VirtualMachine {
_ => Err(OpError::Panic("Invalid types for OR".into())), _ => Err(OpError::Panic("Invalid types for OR".into())),
})?, })?,
OpCode::Not => { OpCode::Not => {
let val = self.pop().map_err(|e| LogicalFrameEndingReason::Panic(e))?; let val = self.pop().map_err(LogicalFrameEndingReason::Panic)?;
if let Value::Boolean(b) = val { if let Value::Boolean(b) = val {
self.push(Value::Boolean(!b)); self.push(Value::Boolean(!b));
} else { } else {
@ -1148,7 +1148,7 @@ impl VirtualMachine {
_ => Err(OpError::Panic("Invalid types for Shr".into())), _ => Err(OpError::Panic("Invalid types for Shr".into())),
})?, })?,
OpCode::Neg => { OpCode::Neg => {
let val = self.pop().map_err(|e| LogicalFrameEndingReason::Panic(e))?; let val = self.pop().map_err(LogicalFrameEndingReason::Panic)?;
match val { match val {
Value::Int32(a) => self.push(Value::Int32(a.wrapping_neg())), Value::Int32(a) => self.push(Value::Int32(a.wrapping_neg())),
Value::Int64(a) => self.push(Value::Int64(a.wrapping_neg())), Value::Int64(a) => self.push(Value::Int64(a.wrapping_neg())),

View File

@ -22,7 +22,7 @@ pub fn rng_from_seed(seed: u64) -> StdRng {
/// Convenience helper that returns a RNG with a fixed well-known seed. /// Convenience helper that returns a RNG with a fixed well-known seed.
pub fn deterministic_rng() -> StdRng { pub fn deterministic_rng() -> StdRng {
rng_from_seed(0xC0FFEE_5EED) rng_from_seed(0x00C0_FFEE_5EED)
} }
/// Returns the next u64 from the provided RNG. /// Returns the next u64 from the provided RNG.

View File

@ -1,56 +0,0 @@
# PR-9.4 — Final Cleanup & Quality Sweep
## Briefing
This PR performs the final cleanup pass.
Goal: Zero warnings. No dead code. No outdated examples.
## Target
1. Remove dead modules/files.
2. Remove unused imports and code.
3. Eliminate compiler warnings.
4. Update outdated examples.
5. Remove stale TODOs referencing removed architecture.
Optional (if present):
* Enforce `cargo clippy` clean baseline.
* Ensure `rustfmt` compliance.
## Acceptance Checklist
* [ ] No dead code.
* [ ] Zero compiler warnings.
* [ ] Clippy clean (if configured).
* [ ] Examples reflect new baseline.
* [ ] No TODO referencing RC/HIP.
## Tests
* Full test suite passes.
* Clean build with warnings denied (if configured).
## Junie Instructions
You MAY:
* Remove unused code.
* Refactor minor clarity issues.
You MUST NOT:
* Introduce new features.
* Change runtime semantics.
If cleanup requires semantic change, STOP and split into new PR.
---
## Final Definition of Done
* Architecture documented clearly.
* Public API minimal and controlled.
* No temporary flags remain.
* Codebase clean, warning-free, and aligned with the new VM baseline.

View File

@ -1,26 +0,0 @@
# PROMETEU Test Cartridges
This directory contains example cartridges and test suites to validate the behavior of the PROMETEU runtime and development tools.
## Available Cartridges
### 🟩 [color-square-ts](color-square-ts)
A simple cartridge that demonstrates:
- System initialization.
- Rendering a colored square in the framebuffer.
- Basic execution loop.
## Cartridge Structure
A PROMETEU cartridge (in its unpacked form) generally consists of:
- `manifest.json`: Application metadata (ID, title, version, mode).
- `program.pbc`: Compiled bytecode for the PROMETEU VM.
- `assets/`: Resources such as tiles, sprites, and audio samples.
## How to use
You can run any of these cartridges using the main CLI:
```bash
prometeu run test-cartridges/<cartridge_name>
```

View File

@ -1,8 +0,0 @@
{
"kind": "File",
"imports": [],
"decls": [
30,
40
]
}

View File

@ -1,20 +0,0 @@
0000 PushConst U32(1)
0006 SetLocal U32(0)
000C GetLocal U32(0)
0012 GetLocal U32(0)
0018 SetLocal U32(1)
001E SetLocal U32(0)
0024 GetLocal U32(0)
002A GetLocal U32(1)
0030 Call U32(1)
0036 SetLocal U32(2)
003C FrameSync
003E Ret
0040 GetLocal U32(0)
0046 GetLocal U32(0)
004C GetLocal U32(1)
0052 Add
0054 Mul
0056 GetLocal U32(1)
005C Mul
005E Ret

View File

@ -1,6 +0,0 @@
{
"name": "canonical",
"version": "0.1.0",
"script_fe": "pbs",
"entry": "src/main/modules/main.pbs"
}

View File

@ -1,18 +0,0 @@
declare struct Vec2(x: int, y: int)
[
(x: int, y: int): (x, y) as default
(s: int): (s, s) as square
]
[[
ZERO: square(0)
]]
{
pub fn len(self: this): int {
return x * x + y * y;
}
}
fn frame(): void {
let zero = Vec2.ZERO;
let zz = zero.len();
}

View File

@ -1,6 +0,0 @@
{
"name": "sdk",
"version": "0.1.0",
"script_fe": "pbs",
"kind": "lib"
}

View File

@ -1,8 +0,0 @@
pub declare struct Color(raw: bounded)
[[
BLACK: Color(0b),
WHITE: Color(65535b),
RED: Color(63488b),
GREEN: Color(2016b),
BLUE: Color(31b)
]]

View File

@ -1,3 +0,0 @@
pub declare contract Gfx host {
fn clear(color: Color): void;
}

View File

@ -1,6 +0,0 @@
pub declare struct Button(
pressed: bool,
released: bool,
down: bool,
hold_frames: bounded
)

View File

@ -1,20 +0,0 @@
pub declare contract Pad host {
fn up(): Button;
fn down(): Button;
fn left(): Button;
fn right(): Button;
fn a(): Button;
fn b(): Button;
fn x(): Button;
fn y(): Button;
fn l(): Button;
fn r(): Button;
fn start(): Button;
fn select(): Button;
}
pub declare contract Touch host {
fn screen_x(): int;
fn screen_y(): int;
fn finger(): Button;
}

View File

@ -1,48 +0,0 @@
// Injeção pelo hardware
declare contract LogHost host {
fn write(level: int, msg: string): void;
fn writeTag(level: int, tag: int, msg: string): void;
}
// exposicao do modulo, com sugar sintatico, nada injetado aqui
pub service Log {
fn trace(msg: string): void {
LogHost.write(0, msg);
}
fn trace(tag: int, msg: string): void {
LogHost.writeTag(0, tag, msg);
}
fn debug(msg: string): void {
LogHost.write(1, msg);
}
fn debug(tag: int, msg: string): void {
LogHost.writeTag(1, tag, msg);
}
fn info(msg: string): void {
LogHost.write(2, msg);
}
fn info(tag: int, msg: string): void {
LogHost.writeTag(2, tag, msg);
}
fn warn(msg: string): void {
LogHost.write(3, msg);
}
fn warn(tag: int, msg: string): void {
LogHost.writeTag(3, tag, msg);
}
fn err(msg: string): void {
LogHost.write(4, msg);
}
fn err(tag: int, msg: string): void {
LogHost.writeTag(4, tag, msg);
}
}

View File

@ -1,41 +0,0 @@
{
"magic": "PMTU",
"cartridge_version": 1,
"app_id": 1,
"title": "Test 1",
"app_version": "0.1.0",
"app_mode": "Game",
"entrypoint": "frame",
"asset_table": [
{
"asset_id": 0,
"asset_name": "bgm_music",
"bank_type": "SOUNDS",
"offset": 0,
"size": 88200,
"decoded_size": 88200,
"codec": "RAW",
"metadata": {
"sample_rate": 44100
}
},
{
"asset_id": 1,
"asset_name": "mouse_cursor",
"bank_type": "TILES",
"offset": 88200,
"size": 2304,
"decoded_size": 2304,
"codec": "RAW",
"metadata": {
"tile_size": 16,
"width": 16,
"height": 16
}
}
],
"preload": [
{ "asset_name": "bgm_music", "slot": 0 },
{ "asset_name": "mouse_cursor", "slot": 1 }
]
}

View File

@ -1,11 +0,0 @@
{
"name": "test01",
"version": "0.1.0",
"script_fe": "pbs",
"kind": "app",
"entry": "src/main/modules/main.pbs",
"out": "build/program.pbc",
"dependencies": {
"sdk": "../sdk"
}
}

View File

@ -1,7 +0,0 @@
#!/bin/zsh
set -e
sdk/prometeu build .
cp build/program.pbc cartridge/program.pbc
sdk/prometeu run cartridge

View File

@ -1 +0,0 @@
../../dist-staging/stable/prometeu-aarch64-apple-darwin

View File

@ -1,3 +0,0 @@
{
"prometeuPbs.serverPath": "/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/target/debug/prometeu-lsp --studio"
}

View File

@ -1,66 +0,0 @@
import { Color, Gfx } from "@sdk:gfx";
import { Pad, Touch } from "@sdk:input";
import { Log } from "@sdk:log";
declare struct Vec2(x: int, y: int)
[
(x: int, y: int): (x, y) as default { }
(s: int): (s, s) as square { }
]
[[
ZERO: square(0)
]]
{
fn getX(self: this): int {
return x;
}
fn getY(self: this): int {
return y;
}
}
fn add(a: int, b: int): int {
return a + b;
}
fn is_higher(a: int, b: int): bool {
let c: int = a + b;
return c >= 30;
}
fn add2(a: int, b: int): int {
let c = add(a, b);
return c;
}
fn frame(): void {
let zero = Vec2.ZERO;
let zz = add2(zero.getX(), zero.getY());
// 1. Locals & Arithmetic
let x = 10;
let y = 20;
let z = add(x, y);
// 2. Control Flow (if)
if z == 30 {
// 3. Syscall Clear
Gfx.clear(Color.GREEN);
} else {
Gfx.clear(Color.RED);
}
// 4. Input Snapshot & Nested Member Access
let pad_a = Pad.a();
let touch_f = Touch.finger();
let is_pressed = pad_a.down || touch_f.down;
if is_pressed {
Gfx.clear(Color.BLUE);
}
if Pad.b().pressed {
Log.debug("B Pressed");
Gfx.clear(Color.RED);
}
}