2026-04-17 17:49:18 +01:00

162 lines
4.3 KiB
Rust

mod domains;
mod registry;
mod resolver;
#[cfg(test)]
mod tests;
pub mod caps;
pub use resolver::{
DeclaredLoadError, LoadError, SyscallIdentity, SyscallResolved,
resolve_declared_program_syscalls, resolve_program_syscalls, resolve_syscall,
};
/// Enumeration of all System Calls (Syscalls) available in the Prometeu environment.
///
/// Syscalls are the primary mechanism for a program running in the Virtual Machine
/// to interact with the outside world (Hardware, OS, Filesystem).
///
/// Each Syscall has a unique 32-bit ID. The IDs are grouped by category:
/// - **0x0xxx**: System & OS Control
/// - **0x1xxx**: Graphics (GFX)
/// - **0x11xx**: Frame Composer orchestration
/// - **0x2xxx**: Reserved for legacy input syscalls (disabled for v1 VM-owned input)
/// - **0x3xxx**: Audio (PCM & Mixing)
/// - **0x4xxx**: Filesystem (Sandboxed I/O)
/// - **0x5xxx**: Logging & Debugging
/// - **0x6xxx**: Asset Loading & Memory Banks
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
pub enum Syscall {
SystemHasCart = 0x0001,
SystemRunCart = 0x0002,
GfxClear = 0x1001,
GfxFillRect = 0x1002,
GfxDrawLine = 0x1003,
GfxDrawCircle = 0x1004,
GfxDrawDisc = 0x1005,
GfxDrawSquare = 0x1006,
GfxDrawText = 0x1008,
GfxClear565 = 0x1010,
ComposerBindScene = 0x1101,
ComposerUnbindScene = 0x1102,
ComposerSetCamera = 0x1103,
ComposerEmitSprite = 0x1104,
AudioPlaySample = 0x3001,
AudioPlay = 0x3002,
FsOpen = 0x4001,
FsRead = 0x4002,
FsWrite = 0x4003,
FsClose = 0x4004,
FsListDir = 0x4005,
FsExists = 0x4006,
FsDelete = 0x4007,
MemSlotCount = 0x4201,
MemSlotStat = 0x4202,
MemSlotRead = 0x4203,
MemSlotWrite = 0x4204,
MemSlotCommit = 0x4205,
MemSlotClear = 0x4206,
LogWrite = 0x5001,
LogWriteTag = 0x5002,
AssetLoad = 0x6001,
AssetStatus = 0x6002,
AssetCommit = 0x6003,
AssetCancel = 0x6004,
BankInfo = 0x6101,
BankSlotInfo = 0x6102,
}
/// Canonical metadata describing a syscall using the unified slot-based ABI.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SyscallMeta {
pub id: u32,
pub module: &'static str,
pub name: &'static str,
pub version: u16,
pub arg_slots: u8,
pub ret_slots: u16,
pub caps: CapFlags,
pub determinism: Determinism,
pub may_allocate: bool,
pub cost_hint: u32,
}
/// Bitflags representing capabilities required to invoke a syscall.
pub type CapFlags = u64;
/// Determinism flags for a syscall.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Determinism {
Unknown,
Deterministic,
NonDeterministic,
}
/// Pairing of a strongly-typed syscall and its metadata.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SyscallRegistryEntry {
pub syscall: Syscall,
pub meta: SyscallMeta,
}
impl SyscallRegistryEntry {
/// Starts the builder with mandatory fields and sensible default values.
pub const fn builder(syscall: Syscall, module: &'static str, name: &'static str) -> Self {
Self {
syscall,
meta: SyscallMeta {
id: syscall as u32,
module,
name,
version: 1, // Default for new syscalls
arg_slots: 0,
ret_slots: 0,
caps: 0,
determinism: Determinism::Deterministic,
may_allocate: false,
cost_hint: 1,
},
}
}
pub const fn version(mut self, n: u16) -> Self {
self.meta.version = n;
self
}
pub const fn args(mut self, n: u8) -> Self {
self.meta.arg_slots = n;
self
}
pub const fn rets(mut self, n: u16) -> Self {
self.meta.ret_slots = n;
self
}
pub const fn caps(mut self, caps: CapFlags) -> Self {
self.meta.caps = caps;
self
}
pub const fn non_deterministic(mut self) -> Self {
self.meta.determinism = Determinism::NonDeterministic;
self
}
pub const fn may_allocate(mut self) -> Self {
self.meta.may_allocate = true;
self
}
pub const fn cost(mut self, cost: u32) -> Self {
self.meta.cost_hint = cost;
self
}
}
pub fn meta_for(syscall: Syscall) -> &'static SyscallMeta {
registry::meta_for(syscall)
}