Compare commits
3 Commits
4b499288e2
...
f50a3f127f
| Author | SHA1 | Date | |
|---|---|---|---|
| f50a3f127f | |||
| f0f3f972ce | |||
| b2d2533acb |
@ -19,6 +19,6 @@ pub use assembler::{assemble, AsmError};
|
|||||||
pub use decoder::{decode_next, DecodeError};
|
pub use decoder::{decode_next, DecodeError};
|
||||||
pub use disassembler::disassemble;
|
pub use disassembler::disassemble;
|
||||||
pub use layout::{compute_function_layouts, FunctionLayout};
|
pub use layout::{compute_function_layouts, FunctionLayout};
|
||||||
pub use model::{BytecodeLoader, FunctionMeta, LoadError, SyscallDecl};
|
pub use model::{BytecodeLoader, FunctionMeta, LoadError, SyscallDecl, PBX_MAGIC};
|
||||||
pub use program_image::ProgramImage;
|
pub use program_image::ProgramImage;
|
||||||
pub use value::{string_materialization_count, HeapRef, Value};
|
pub use value::{string_materialization_count, HeapRef, Value};
|
||||||
|
|||||||
@ -80,9 +80,11 @@ const SECTION_KIND_DEBUG: u32 = 3;
|
|||||||
const SECTION_KIND_EXPORTS: u32 = 4;
|
const SECTION_KIND_EXPORTS: u32 = 4;
|
||||||
const SECTION_KIND_SYSCALLS: u32 = 5;
|
const SECTION_KIND_SYSCALLS: u32 = 5;
|
||||||
|
|
||||||
/// Represents the final serialized format of a PBS v0 module.
|
pub const PBX_MAGIC: [u8; 4] = *b"PBX\0";
|
||||||
|
|
||||||
|
/// Represents the final serialized format of a PBX v0 module.
|
||||||
///
|
///
|
||||||
/// This structure is a pure data container for the PBS format. It does NOT
|
/// This structure is a pure data container for the PBX format. It does NOT
|
||||||
/// contain any linker-like logic (symbol resolution, patching, etc.).
|
/// contain any linker-like logic (symbol resolution, patching, etc.).
|
||||||
/// All multi-module programs must be flattened and linked by the compiler
|
/// All multi-module programs must be flattened and linked by the compiler
|
||||||
/// before being serialized into this format.
|
/// before being serialized into this format.
|
||||||
@ -126,8 +128,8 @@ impl BytecodeModule {
|
|||||||
final_sections.push((SECTION_KIND_SYSCALLS, syscall_data));
|
final_sections.push((SECTION_KIND_SYSCALLS, syscall_data));
|
||||||
|
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
// Magic "PBS\0"
|
// Magic "PBX\0"
|
||||||
out.extend_from_slice(b"PBS\0");
|
out.extend_from_slice(&PBX_MAGIC);
|
||||||
// Version 0
|
// Version 0
|
||||||
out.extend_from_slice(&0u16.to_le_bytes());
|
out.extend_from_slice(&0u16.to_le_bytes());
|
||||||
// Endianness 0 (Little Endian), Reserved
|
// Endianness 0 (Little Endian), Reserved
|
||||||
@ -272,8 +274,8 @@ impl BytecodeLoader {
|
|||||||
return Err(LoadError::UnexpectedEof);
|
return Err(LoadError::UnexpectedEof);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Magic "PBS\0"
|
// Magic "PBX\0"
|
||||||
if &bytes[0..4] != b"PBS\0" {
|
if bytes[0..4] != PBX_MAGIC[..] {
|
||||||
return Err(LoadError::InvalidMagic);
|
return Err(LoadError::InvalidMagic);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,7 +710,7 @@ mod tests {
|
|||||||
|
|
||||||
fn create_header(section_count: u32) -> Vec<u8> {
|
fn create_header(section_count: u32) -> Vec<u8> {
|
||||||
let mut h = vec![0u8; 32];
|
let mut h = vec![0u8; 32];
|
||||||
h[0..4].copy_from_slice(b"PBS\0");
|
h[0..4].copy_from_slice(&PBX_MAGIC);
|
||||||
h[4..6].copy_from_slice(&0u16.to_le_bytes()); // version
|
h[4..6].copy_from_slice(&0u16.to_le_bytes()); // version
|
||||||
h[6] = 0; // endianness
|
h[6] = 0; // endianness
|
||||||
h[8..12].copy_from_slice(§ion_count.to_le_bytes());
|
h[8..12].copy_from_slice(§ion_count.to_le_bytes());
|
||||||
@ -727,7 +729,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_pbs_with_sections(sections: Vec<(u32, Vec<u8>)>) -> Vec<u8> {
|
fn build_pbx_with_sections(sections: Vec<(u32, Vec<u8>)>) -> Vec<u8> {
|
||||||
let mut data = create_header(sections.len() as u32);
|
let mut data = create_header(sections.len() as u32);
|
||||||
let mut offset = 32 + (sections.len() as u32 * 12);
|
let mut offset = 32 + (sections.len() as u32 * 12);
|
||||||
|
|
||||||
@ -897,7 +899,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_malformed_sysc_section_is_rejected() {
|
fn test_malformed_sysc_section_is_rejected() {
|
||||||
let data = build_pbs_with_sections(vec![(SECTION_KIND_SYSCALLS, vec![1, 0, 0])]);
|
let data = build_pbx_with_sections(vec![(SECTION_KIND_SYSCALLS, vec![1, 0, 0])]);
|
||||||
|
|
||||||
assert_eq!(BytecodeLoader::load(&data), Err(LoadError::MalformedSection));
|
assert_eq!(BytecodeLoader::load(&data), Err(LoadError::MalformedSection));
|
||||||
}
|
}
|
||||||
@ -914,7 +916,7 @@ mod tests {
|
|||||||
sysc.extend_from_slice(&0u16.to_le_bytes());
|
sysc.extend_from_slice(&0u16.to_le_bytes());
|
||||||
sysc.extend_from_slice(&0u16.to_le_bytes());
|
sysc.extend_from_slice(&0u16.to_le_bytes());
|
||||||
|
|
||||||
let data = build_pbs_with_sections(vec![(SECTION_KIND_SYSCALLS, sysc)]);
|
let data = build_pbx_with_sections(vec![(SECTION_KIND_SYSCALLS, sysc)]);
|
||||||
|
|
||||||
assert_eq!(BytecodeLoader::load(&data), Err(LoadError::InvalidUtf8));
|
assert_eq!(BytecodeLoader::load(&data), Err(LoadError::InvalidUtf8));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ use crate::value::Value;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// Represents a fully linked, executable PBS program image.
|
/// Represents a fully linked, executable PBX program image.
|
||||||
///
|
///
|
||||||
/// Under the Prometeu architecture, the ProgramImage is a "closed-world" artifact
|
/// Under the Prometeu architecture, the ProgramImage is a "closed-world" artifact
|
||||||
/// produced by the compiler. All linking, relocation, and symbol resolution
|
/// produced by the compiler. All linking, relocation, and symbol resolution
|
||||||
|
|||||||
@ -2627,7 +2627,7 @@ mod tests {
|
|||||||
fn test_loader_hardening_unsupported_version() {
|
fn test_loader_hardening_unsupported_version() {
|
||||||
let mut vm = VirtualMachine::default();
|
let mut vm = VirtualMachine::default();
|
||||||
let mut header = vec![0u8; 32];
|
let mut header = vec![0u8; 32];
|
||||||
header[0..4].copy_from_slice(b"PBS\0");
|
header[0..4].copy_from_slice(&prometeu_bytecode::PBX_MAGIC);
|
||||||
header[4..6].copy_from_slice(&1u16.to_le_bytes()); // version 1 (unsupported)
|
header[4..6].copy_from_slice(&1u16.to_le_bytes()); // version 1 (unsupported)
|
||||||
|
|
||||||
let res = vm.initialize(header);
|
let res = vm.initialize(header);
|
||||||
@ -2635,16 +2635,16 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_loader_hardening_malformed_pbs_v0() {
|
fn test_loader_hardening_malformed_pbx_v0() {
|
||||||
let mut vm = VirtualMachine::default();
|
let mut vm = VirtualMachine::default();
|
||||||
let mut header = vec![0u8; 32];
|
let mut header = vec![0u8; 32];
|
||||||
header[0..4].copy_from_slice(b"PBS\0");
|
header[0..4].copy_from_slice(&prometeu_bytecode::PBX_MAGIC);
|
||||||
header[8..12].copy_from_slice(&1u32.to_le_bytes()); // 1 section claimed but none provided
|
header[8..12].copy_from_slice(&1u32.to_le_bytes()); // 1 section claimed but none provided
|
||||||
|
|
||||||
let res = vm.initialize(header);
|
let res = vm.initialize(header);
|
||||||
match res {
|
match res {
|
||||||
Err(VmInitError::ImageLoadFailed(prometeu_bytecode::LoadError::UnexpectedEof)) => {}
|
Err(VmInitError::ImageLoadFailed(prometeu_bytecode::LoadError::UnexpectedEof)) => {}
|
||||||
_ => panic!("Expected PbsV0LoadFailed(UnexpectedEof), got {:?}", res),
|
_ => panic!("Expected PBX v0 load failure UnexpectedEof, got {:?}", res),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3084,7 +3084,7 @@ mod tests {
|
|||||||
fn test_loader_hardening_missing_sysc_section() {
|
fn test_loader_hardening_missing_sysc_section() {
|
||||||
let mut vm = VirtualMachine::default();
|
let mut vm = VirtualMachine::default();
|
||||||
let mut header = vec![0u8; 32];
|
let mut header = vec![0u8; 32];
|
||||||
header[0..4].copy_from_slice(b"PBS\0");
|
header[0..4].copy_from_slice(&prometeu_bytecode::PBX_MAGIC);
|
||||||
|
|
||||||
let res = vm.initialize(header);
|
let res = vm.initialize(header);
|
||||||
|
|
||||||
|
|||||||
@ -83,8 +83,7 @@ impl VirtualMachine {
|
|||||||
self.scheduler = Scheduler::new();
|
self.scheduler = Scheduler::new();
|
||||||
self.current_coro = None;
|
self.current_coro = None;
|
||||||
|
|
||||||
let program = if program_bytes.starts_with(b"PBS\0") {
|
let program = match prometeu_bytecode::BytecodeLoader::load(&program_bytes) {
|
||||||
match prometeu_bytecode::BytecodeLoader::load(&program_bytes) {
|
|
||||||
Ok(mut module) => {
|
Ok(mut module) => {
|
||||||
patch_module_hostcalls(&mut module, self.capabilities)
|
patch_module_hostcalls(&mut module, self.capabilities)
|
||||||
.map_err(VmInitError::LoaderPatchFailed)?;
|
.map_err(VmInitError::LoaderPatchFailed)?;
|
||||||
@ -103,10 +102,13 @@ impl VirtualMachine {
|
|||||||
Err(prometeu_bytecode::LoadError::InvalidVersion) => {
|
Err(prometeu_bytecode::LoadError::InvalidVersion) => {
|
||||||
return Err(VmInitError::UnsupportedFormat);
|
return Err(VmInitError::UnsupportedFormat);
|
||||||
}
|
}
|
||||||
Err(e) => return Err(VmInitError::ImageLoadFailed(e)),
|
Err(prometeu_bytecode::LoadError::InvalidMagic) => {
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Err(VmInitError::InvalidFormat);
|
return Err(VmInitError::InvalidFormat);
|
||||||
|
}
|
||||||
|
Err(prometeu_bytecode::LoadError::UnexpectedEof) if program_bytes.len() < 32 => {
|
||||||
|
return Err(VmInitError::InvalidFormat);
|
||||||
|
}
|
||||||
|
Err(e) => return Err(VmInitError::ImageLoadFailed(e)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let pc = program
|
let pc = program
|
||||||
|
|||||||
@ -2,8 +2,8 @@ use prometeu_vm::{VirtualMachine, VmInitError};
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn invalid_image_format_is_rejected_before_execution() {
|
fn invalid_image_format_is_rejected_before_execution() {
|
||||||
// Provide bytes that are not a valid PBS image. The VM must reject it with InvalidFormat.
|
// Provide bytes that are not a valid PBX image. The VM must reject it with InvalidFormat.
|
||||||
let program_bytes = b"NOT_PBS_IMAGE".to_vec();
|
let program_bytes = b"NOT_PBX_IMAGE".to_vec();
|
||||||
let mut vm = VirtualMachine::default();
|
let mut vm = VirtualMachine::default();
|
||||||
let result = vm.initialize(program_bytes);
|
let result = vm.initialize(program_bytes);
|
||||||
assert!(matches!(result, Err(VmInitError::InvalidFormat)));
|
assert!(matches!(result, Err(VmInitError::InvalidFormat)));
|
||||||
|
|||||||
@ -130,7 +130,7 @@ mod tests {
|
|||||||
fn generated_program_is_pbx_module_with_expected_syscalls() {
|
fn generated_program_is_pbx_module_with_expected_syscalls() {
|
||||||
let bytes = build_program();
|
let bytes = build_program();
|
||||||
|
|
||||||
assert!(bytes.starts_with(b"PBS\0"));
|
assert!(bytes.starts_with(&prometeu_bytecode::PBX_MAGIC));
|
||||||
assert!(bytes.len() > 64);
|
assert!(bytes.len() > 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
{"type":"meta","next_id":{"DSC":48,"AGD":51,"DEC":42,"PLN":173,"LSN":56,"CLSN":1}}
|
{"type":"meta","next_id":{"DSC":49,"AGD":52,"DEC":43,"PLN":174,"LSN":57,"CLSN":1}}
|
||||||
{"type":"discussion","id":"DSC-0044","status":"done","ticket":"hub-suspended-game-kill-affordance","title":"Hub Suspended Game Kill Affordance","created_at":"2026-07-05","updated_at":"2026-07-05","tags":["hub","lifecycle","game","ui"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0054","file":"discussion/lessons/DSC-0044-hub-suspended-game-kill-affordance/LSN-0054-manual-hub-kill-must-share-game-termination-cleanup.md","status":"done","created_at":"2026-07-05","updated_at":"2026-07-05"}]}
|
{"type":"discussion","id":"DSC-0044","status":"done","ticket":"hub-suspended-game-kill-affordance","title":"Hub Suspended Game Kill Affordance","created_at":"2026-07-05","updated_at":"2026-07-05","tags":["hub","lifecycle","game","ui"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0054","file":"discussion/lessons/DSC-0044-hub-suspended-game-kill-affordance/LSN-0054-manual-hub-kill-must-share-game-termination-cleanup.md","status":"done","created_at":"2026-07-05","updated_at":"2026-07-05"}]}
|
||||||
{"type":"discussion","id":"DSC-0043","status":"done","ticket":"system-os-cartridge-switch-orchestrator","title":"SystemOS Cartridge Switch Orchestrator","created_at":"2026-07-03","updated_at":"2026-07-05","tags":["runtime","os","lifecycle","game","cartridge","architecture"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0053","file":"discussion/lessons/DSC-0043-system-os-cartridge-switch-orchestrator/LSN-0053-game-switching-is-lifecycle-replacement-not-loader-work.md","status":"done","created_at":"2026-07-05","updated_at":"2026-07-05"}]}
|
{"type":"discussion","id":"DSC-0043","status":"done","ticket":"system-os-cartridge-switch-orchestrator","title":"SystemOS Cartridge Switch Orchestrator","created_at":"2026-07-03","updated_at":"2026-07-05","tags":["runtime","os","lifecycle","game","cartridge","architecture"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0053","file":"discussion/lessons/DSC-0043-system-os-cartridge-switch-orchestrator/LSN-0053-game-switching-is-lifecycle-replacement-not-loader-work.md","status":"done","created_at":"2026-07-05","updated_at":"2026-07-05"}]}
|
||||||
{"type":"discussion","id":"DSC-0039","status":"abandoned","ticket":"render-pipeline-family-and-future-3d","title":"Render Pipeline Family and Future 3D","created_at":"2026-06-04","updated_at":"2026-06-04","tags":["gfx","renderer","runtime","architecture","pipeline"],"agendas":[{"id":"AGD-0039","file":"AGD-0039-render-pipeline-family-and-future-3d.md","status":"abandoned","created_at":"2026-06-04","updated_at":"2026-06-04","_override_reason":"User explicitly chose to close this agenda without a new decision because DSC-0038 already established enough architecture for future extension, and 3D is intentionally deferred."}],"decisions":[],"plans":[],"lessons":[],"_override_reason":"User explicitly chose to close this agenda without a new decision because DSC-0038 already established enough architecture for future extension, and 3D is intentionally deferred."}
|
{"type":"discussion","id":"DSC-0039","status":"abandoned","ticket":"render-pipeline-family-and-future-3d","title":"Render Pipeline Family and Future 3D","created_at":"2026-06-04","updated_at":"2026-06-04","tags":["gfx","renderer","runtime","architecture","pipeline"],"agendas":[{"id":"AGD-0039","file":"AGD-0039-render-pipeline-family-and-future-3d.md","status":"abandoned","created_at":"2026-06-04","updated_at":"2026-06-04","_override_reason":"User explicitly chose to close this agenda without a new decision because DSC-0038 already established enough architecture for future extension, and 3D is intentionally deferred."}],"decisions":[],"plans":[],"lessons":[],"_override_reason":"User explicitly chose to close this agenda without a new decision because DSC-0038 already established enough architecture for future extension, and 3D is intentionally deferred."}
|
||||||
@ -46,3 +46,4 @@
|
|||||||
{"type":"discussion","id":"DSC-0037","status":"done","ticket":"rgba8888-framebuffer-and-pixel-format-direction","title":"Agenda - RGBA8888 Framebuffer and Pixel Format Direction","created_at":"2026-05-22","updated_at":"2026-05-23","tags":["gfx","framebuffer","rgb565","rgba8888","renderer","assets","host","backend"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0037-rgba8888-framebuffer-and-pixel-format-direction/LSN-0046-pixel-format-contracts-must-move-as-one-surface.md","status":"done","created_at":"2026-05-23","updated_at":"2026-05-23"}]}
|
{"type":"discussion","id":"DSC-0037","status":"done","ticket":"rgba8888-framebuffer-and-pixel-format-direction","title":"Agenda - RGBA8888 Framebuffer and Pixel Format Direction","created_at":"2026-05-22","updated_at":"2026-05-23","tags":["gfx","framebuffer","rgb565","rgba8888","renderer","assets","host","backend"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0037-rgba8888-framebuffer-and-pixel-format-direction/LSN-0046-pixel-format-contracts-must-move-as-one-surface.md","status":"done","created_at":"2026-05-23","updated_at":"2026-05-23"}]}
|
||||||
{"type":"discussion","id":"DSC-0046","status":"done","ticket":"runtime-owned-variable-glyph-bank-palette-protocol","title":"Runtime-Owned Variable Glyph Bank Palette Protocol","created_at":"2026-07-14","updated_at":"2026-07-14","tags":["runtime","gfx","assets","glyph-bank","palette-serialization","protocol"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0055","file":"discussion/lessons/DSC-0046-runtime-owned-variable-glyph-bank-palette-protocol/LSN-0055-runtime-owned-asset-protocols-must-align-payload-residency-and-lookup.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14"}]}
|
{"type":"discussion","id":"DSC-0046","status":"done","ticket":"runtime-owned-variable-glyph-bank-palette-protocol","title":"Runtime-Owned Variable Glyph Bank Palette Protocol","created_at":"2026-07-14","updated_at":"2026-07-14","tags":["runtime","gfx","assets","glyph-bank","palette-serialization","protocol"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0055","file":"discussion/lessons/DSC-0046-runtime-owned-variable-glyph-bank-palette-protocol/LSN-0055-runtime-owned-asset-protocols-must-align-payload-residency-and-lookup.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14"}]}
|
||||||
{"type":"discussion","id":"DSC-0047","status":"open","ticket":"portable-host-backend-strategy","title":"Portable Host Backend Strategy","created_at":"2026-07-14","updated_at":"2026-07-14","tags":["host","desktop","portable","sdl","backend","rendering","input","audio","linux","android","handheld"],"agendas":[{"id":"AGD-0050","file":"AGD-0050-portable-host-backend-strategy.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14"}],"decisions":[],"plans":[],"lessons":[]}
|
{"type":"discussion","id":"DSC-0047","status":"open","ticket":"portable-host-backend-strategy","title":"Portable Host Backend Strategy","created_at":"2026-07-14","updated_at":"2026-07-14","tags":["host","desktop","portable","sdl","backend","rendering","input","audio","linux","android","handheld"],"agendas":[{"id":"AGD-0050","file":"AGD-0050-portable-host-backend-strategy.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14"}],"decisions":[],"plans":[],"lessons":[]}
|
||||||
|
{"type":"discussion","id":"DSC-0048","status":"done","ticket":"corrigir-identificacao-formato-pbx","title":"Corrigir Identificacao do Formato PBX","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["runtime","bytecode","pbx","loader","format","architecture"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0056","file":"discussion/lessons/DSC-0048-corrigir-identificacao-formato-pbx/LSN-0056-runtime-artifact-identity-must-not-borrow-frontend-names.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15"}]}
|
||||||
|
|||||||
@ -0,0 +1,61 @@
|
|||||||
|
---
|
||||||
|
id: LSN-0056
|
||||||
|
ticket: corrigir-identificacao-formato-pbx
|
||||||
|
title: Runtime Artifact Identity Must Not Borrow Frontend Names
|
||||||
|
created: 2026-07-15
|
||||||
|
tags: [runtime, bytecode, pbx, frontend, format-boundary]
|
||||||
|
---
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
Prometeu accepts bytecode produced by multiple frontends. PBS is the base
|
||||||
|
frontend language, while PBX is the executable bytecode artifact consumed by the
|
||||||
|
runtime.
|
||||||
|
|
||||||
|
The runtime had inherited PBS terminology in the executable bytecode path,
|
||||||
|
including the serialized magic number, comments, tests, and VM loader checks.
|
||||||
|
That made one frontend appear to own the runtime executable format.
|
||||||
|
|
||||||
|
## Key Decisions
|
||||||
|
|
||||||
|
### PBX Executable Format Identity
|
||||||
|
|
||||||
|
**What:** PBX is the runtime executable bytecode format, and `PBX\0` is its only
|
||||||
|
valid magic number.
|
||||||
|
|
||||||
|
**Why:** Runtime artifact identity must be independent from any frontend that can
|
||||||
|
produce the artifact. Naming the executable format after PBS would make the
|
||||||
|
runtime boundary look language-specific.
|
||||||
|
|
||||||
|
**Trade-offs:** The correction intentionally rejects old PBS-prefixed executable
|
||||||
|
artifacts instead of carrying a compatibility alias. This keeps the format
|
||||||
|
contract singular, but requires stale generated fixtures to be regenerated or
|
||||||
|
updated.
|
||||||
|
|
||||||
|
## Patterns and Algorithms
|
||||||
|
|
||||||
|
Put file-format identity in the module that serializes and deserializes the
|
||||||
|
format. Loaders and higher-level runtime code should call that boundary instead
|
||||||
|
of duplicating magic-number checks.
|
||||||
|
|
||||||
|
When renaming an artifact identity, update all fixture construction and generator
|
||||||
|
assertions in the same pass as production serialization. Mixed fixture identity
|
||||||
|
usually means tests are asserting historical spelling rather than current
|
||||||
|
contract.
|
||||||
|
|
||||||
|
## Pitfalls
|
||||||
|
|
||||||
|
Do not globally erase frontend names. PBS remains correct when the subject is
|
||||||
|
the PBS language, stdlib, or frontend-facing API. It is wrong only when it names
|
||||||
|
the executable bytecode artifact.
|
||||||
|
|
||||||
|
Do not preserve old magic values just to make a rename feel less disruptive. If
|
||||||
|
there is no compatibility requirement for old artifacts, aliases keep the
|
||||||
|
incorrect model alive.
|
||||||
|
|
||||||
|
## Takeaways
|
||||||
|
|
||||||
|
- Runtime artifact names should describe the runtime contract, not the compiler
|
||||||
|
or frontend that produced the artifact.
|
||||||
|
- Magic numbers are normative format identity, not cosmetic labels.
|
||||||
|
- Loader code should delegate file-format validation to the format owner.
|
||||||
@ -65,6 +65,12 @@ dedicated `System` profile ABI and stdlib/framework.
|
|||||||
|
|
||||||
## 3 Syscall Resolution
|
## 3 Syscall Resolution
|
||||||
|
|
||||||
|
PBX, Prometeu Bytecode Executable, is the runtime executable bytecode format.
|
||||||
|
Its canonical file magic is `PBX\0`. The former PBS-prefixed magic is not valid
|
||||||
|
for PBX artifacts: PBS names a frontend language, while PBX names the executable
|
||||||
|
artifact accepted by the runtime. This distinction is required because Prometeu
|
||||||
|
bytecode can be produced by multiple frontends.
|
||||||
|
|
||||||
The host maintains a registry:
|
The host maintains a registry:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user