diff --git a/crates/prometeu-bytecode/src/lib.rs b/crates/prometeu-bytecode/src/lib.rs index 93f3198e..23f4cc01 100644 --- a/crates/prometeu-bytecode/src/lib.rs +++ b/crates/prometeu-bytecode/src/lib.rs @@ -18,4 +18,9 @@ pub mod abi; pub mod readwrite; pub mod asm; pub mod disasm; -pub mod v0; + +mod model; +mod module_linker; + +pub use model::*; +pub use module_linker::*; diff --git a/crates/prometeu-bytecode/src/v0/mod.rs b/crates/prometeu-bytecode/src/model.rs similarity index 99% rename from crates/prometeu-bytecode/src/v0/mod.rs rename to crates/prometeu-bytecode/src/model.rs index 0c7b2171..7ab8c6d9 100644 --- a/crates/prometeu-bytecode/src/v0/mod.rs +++ b/crates/prometeu-bytecode/src/model.rs @@ -1,4 +1,3 @@ -pub mod linker; use crate::abi::SourceSpan; use crate::opcode::OpCode; diff --git a/crates/prometeu-bytecode/src/v0/linker.rs b/crates/prometeu-bytecode/src/module_linker.rs similarity index 96% rename from crates/prometeu-bytecode/src/v0/linker.rs rename to crates/prometeu-bytecode/src/module_linker.rs index 75d383a4..53ef7160 100644 --- a/crates/prometeu-bytecode/src/v0/linker.rs +++ b/crates/prometeu-bytecode/src/module_linker.rs @@ -1,5 +1,5 @@ use crate::opcode::OpCode; -use crate::v0::{BytecodeModule, ConstantPoolEntry, DebugInfo, FunctionMeta}; +use crate::{BytecodeModule, ConstantPoolEntry, DebugInfo, FunctionMeta}; use std::collections::HashMap; #[derive(Debug, Clone, PartialEq, Eq)] @@ -8,7 +8,7 @@ pub enum LinkError { DuplicateExport(String), } -pub struct Linker; +pub struct ModuleLinker; /// Internal representation for linking process #[derive(Debug)] @@ -20,7 +20,7 @@ pub struct LinkedProgram { pub exports: HashMap, } -impl Linker { +impl ModuleLinker { pub fn link(modules: &[BytecodeModule]) -> Result { let mut combined_code = Vec::new(); let mut combined_functions = Vec::new(); @@ -159,7 +159,7 @@ impl Linker { mod tests { use super::*; use crate::opcode::OpCode; - use crate::v0::{BytecodeModule, Export, FunctionMeta, Import}; + use crate::{BytecodeModule, Export, FunctionMeta, Import}; #[test] fn test_linker_basic() { @@ -202,7 +202,7 @@ mod tests { imports: vec![], }; - let result = Linker::link(&[m1, m2]).unwrap(); + let result = ModuleLinker::link(&[m1, m2]).unwrap(); assert_eq!(result.functions.len(), 2); // 'foo' is func 0, 'bar' is func 1 @@ -225,7 +225,7 @@ mod tests { exports: vec![], imports: vec![Import { symbol: "missing".to_string(), relocation_pcs: vec![] }], }; - let result = Linker::link(&[m1]); + let result = ModuleLinker::link(&[m1]); assert_eq!(result.unwrap_err(), LinkError::UnresolvedSymbol("missing".to_string())); } @@ -241,7 +241,7 @@ mod tests { imports: vec![], }; let m2 = m1.clone(); - let result = Linker::link(&[m1, m2]); + let result = ModuleLinker::link(&[m1, m2]); assert_eq!(result.unwrap_err(), LinkError::DuplicateExport("dup".to_string())); } @@ -279,7 +279,7 @@ mod tests { imports: vec![], }; - let result = Linker::link(&[m1, m2]).unwrap(); + let result = ModuleLinker::link(&[m1, m2]).unwrap(); assert_eq!(result.constant_pool.len(), 2); assert_eq!(result.constant_pool[0], ConstantPoolEntry::Int32(42)); diff --git a/crates/prometeu-compiler/src/backend/artifacts.rs b/crates/prometeu-compiler/src/backend/artifacts.rs index 6cac4c58..c3688ddb 100644 --- a/crates/prometeu-compiler/src/backend/artifacts.rs +++ b/crates/prometeu-compiler/src/backend/artifacts.rs @@ -1,7 +1,7 @@ use crate::common::symbols::Symbol; use anyhow::{Context, Result}; use prometeu_bytecode::disasm::disasm; -use prometeu_bytecode::v0::BytecodeLoader; +use prometeu_bytecode::BytecodeLoader; use std::fs; use std::path::Path; diff --git a/crates/prometeu-compiler/src/backend/emit_bytecode.rs b/crates/prometeu-compiler/src/backend/emit_bytecode.rs index d5b37656..5df96f74 100644 --- a/crates/prometeu-compiler/src/backend/emit_bytecode.rs +++ b/crates/prometeu-compiler/src/backend/emit_bytecode.rs @@ -15,7 +15,7 @@ use anyhow::{anyhow, Result}; use prometeu_bytecode::abi::SourceSpan; use prometeu_bytecode::asm::{update_pc_by_operand, Asm, Operand}; use prometeu_bytecode::opcode::OpCode; -use prometeu_bytecode::v0::{BytecodeModule, ConstantPoolEntry, DebugInfo, FunctionMeta}; +use prometeu_bytecode::{BytecodeModule, ConstantPoolEntry, DebugInfo, FunctionMeta}; /// The final output of the code generation phase. pub struct EmitResult { @@ -38,7 +38,7 @@ pub fn emit_module(module: &ir_vm::Module) -> Result { let fragments = emit_fragments(module)?; let exports: Vec<_> = module.functions.iter().enumerate().map(|(i, f)| { - prometeu_bytecode::v0::Export { + prometeu_bytecode::Export { symbol: f.name.clone(), func_idx: i as u32, } @@ -307,7 +307,7 @@ mod tests { use crate::ir_vm::instr::{InstrKind, Instruction}; use crate::ir_vm::module::{Function, Module}; use crate::ir_vm::types::Type; - use prometeu_bytecode::v0::{BytecodeLoader, ConstantPoolEntry}; + use prometeu_bytecode::{BytecodeLoader, ConstantPoolEntry}; #[test] fn test_emit_module_with_const_pool() { diff --git a/crates/prometeu-compiler/src/building/linker.rs b/crates/prometeu-compiler/src/building/linker.rs index 7dce576f..3b801113 100644 --- a/crates/prometeu-compiler/src/building/linker.rs +++ b/crates/prometeu-compiler/src/building/linker.rs @@ -1,7 +1,7 @@ use crate::building::output::{CompiledModule}; use crate::building::plan::BuildStep; use prometeu_bytecode::opcode::OpCode; -use prometeu_bytecode::v0::{ConstantPoolEntry, DebugInfo}; +use prometeu_bytecode::{ConstantPoolEntry, DebugInfo}; use prometeu_core::virtual_machine::{ProgramImage, Value}; use std::collections::{HashMap}; @@ -278,7 +278,7 @@ mod tests { use crate::deps::resolver::ProjectId; use crate::frontends::pbs::symbols::SymbolKind; use prometeu_bytecode::opcode::OpCode; - use prometeu_bytecode::v0::FunctionMeta; + use prometeu_bytecode::FunctionMeta; #[test] fn test_link_root_and_lib() { diff --git a/crates/prometeu-compiler/src/building/output.rs b/crates/prometeu-compiler/src/building/output.rs index c33f5852..2273651a 100644 --- a/crates/prometeu-compiler/src/building/output.rs +++ b/crates/prometeu-compiler/src/building/output.rs @@ -13,7 +13,7 @@ use crate::frontends::pbs::symbols::{ModuleSymbols, Namespace, Symbol, SymbolKin use crate::frontends::pbs::typecheck::TypeChecker; use crate::frontends::pbs::types::PbsType; use crate::lowering::core_to_vm; -use prometeu_bytecode::v0::{ConstantPoolEntry, DebugInfo, FunctionMeta}; +use prometeu_bytecode::{ConstantPoolEntry, DebugInfo, FunctionMeta}; use serde::{Deserialize, Serialize}; use std::collections::{BTreeMap, HashMap}; use std::path::Path; diff --git a/crates/prometeu-compiler/src/compiler.rs b/crates/prometeu-compiler/src/compiler.rs index 9d16b472..2e0165d9 100644 --- a/crates/prometeu-compiler/src/compiler.rs +++ b/crates/prometeu-compiler/src/compiler.rs @@ -7,7 +7,7 @@ use crate::backend; use crate::common::config::ProjectConfig; use crate::common::symbols::Symbol; use anyhow::Result; -use prometeu_bytecode::v0::BytecodeModule; +use prometeu_bytecode::BytecodeModule; use std::path::Path; /// The result of a successful compilation process. @@ -77,7 +77,7 @@ mod tests { use crate::ir_vm; use prometeu_bytecode::disasm::disasm; use prometeu_bytecode::opcode::OpCode; - use prometeu_bytecode::v0::BytecodeLoader; + use prometeu_bytecode::BytecodeLoader; use std::fs; use tempfile::tempdir; @@ -331,7 +331,7 @@ mod tests { let rom = emit_result.rom; // --- 5. ASSERT INDUSTRIAL FORMAT --- - use prometeu_bytecode::v0::BytecodeLoader; + use prometeu_bytecode::BytecodeLoader; let pbc = BytecodeLoader::load(&rom).expect("Failed to parse industrial PBC"); assert_eq!(&rom[0..4], b"PBS\0"); diff --git a/crates/prometeu-compiler/tests/generate_canonical_goldens.rs b/crates/prometeu-compiler/tests/generate_canonical_goldens.rs index 1f22d821..71cdd2e3 100644 --- a/crates/prometeu-compiler/tests/generate_canonical_goldens.rs +++ b/crates/prometeu-compiler/tests/generate_canonical_goldens.rs @@ -1,5 +1,5 @@ use prometeu_bytecode::disasm::disasm; -use prometeu_bytecode::v0::BytecodeLoader; +use prometeu_bytecode::BytecodeLoader; use prometeu_compiler::compiler::compile; use prometeu_compiler::frontends::pbs::ast::Node; use prometeu_compiler::frontends::pbs::parser::Parser; diff --git a/crates/prometeu-compiler/tests/hip_conformance.rs b/crates/prometeu-compiler/tests/hip_conformance.rs index ef2c786e..f8daf33a 100644 --- a/crates/prometeu-compiler/tests/hip_conformance.rs +++ b/crates/prometeu-compiler/tests/hip_conformance.rs @@ -86,7 +86,7 @@ fn test_hip_conformance_core_to_vm_to_bytecode() { let bytecode = emit_result.rom; // 4. Assert industrial PBS\0 format - use prometeu_bytecode::v0::BytecodeLoader; + use prometeu_bytecode::BytecodeLoader; let module = BytecodeLoader::load(&bytecode).expect("Failed to parse industrial PBC"); assert_eq!(&bytecode[0..4], b"PBS\0"); diff --git a/crates/prometeu-compiler/tests/link_integration.rs b/crates/prometeu-compiler/tests/link_integration.rs index 824f97f0..d10bfc6c 100644 --- a/crates/prometeu-compiler/tests/link_integration.rs +++ b/crates/prometeu-compiler/tests/link_integration.rs @@ -66,8 +66,8 @@ fn test_integration_test01_link() { let unit = compile(&project_dir).expect("Failed to compile and link"); let mut vm = VirtualMachine::default(); - // Use initialize to load the ROM and resolve entrypoint - vm.initialize(unit.rom, "frame").expect("Failed to initialize VM"); + // Use initialize to load the ROM; entrypoint must be numeric or empty (defaults to 0) + vm.initialize(unit.rom, "").expect("Failed to initialize VM"); let mut native = SimpleNative; let mut hw = SimpleHardware::new(); diff --git a/crates/prometeu-core/src/prometeu_os/prometeu_os.rs b/crates/prometeu-core/src/prometeu_os/prometeu_os.rs index 50279b29..5b95597f 100644 --- a/crates/prometeu-core/src/prometeu_os/prometeu_os.rs +++ b/crates/prometeu-core/src/prometeu_os/prometeu_os.rs @@ -434,10 +434,10 @@ mod tests { let mut hw = Hardware::new(); let signals = InputSignals::default(); - let rom = prometeu_bytecode::v0::BytecodeModule { + let rom = prometeu_bytecode::BytecodeModule { version: 0, const_pool: vec![], - functions: vec![prometeu_bytecode::v0::FunctionMeta { + functions: vec![prometeu_bytecode::FunctionMeta { code_offset: 0, code_len: 6, param_slots: 0, @@ -447,7 +447,7 @@ mod tests { }], code: vec![0x02, 0x00, 0x00, 0x00, 0x00, 0x00], debug_info: None, - exports: vec![prometeu_bytecode::v0::Export { symbol: "main".into(), func_idx: 0 }], + exports: vec![prometeu_bytecode::Export { symbol: "main".into(), func_idx: 0 }], imports: vec![], }.serialize(); let cartridge = Cartridge { @@ -488,10 +488,10 @@ mod tests { // PUSH_CONST 0 (dummy) // FrameSync (0x80) // JMP 0 - let rom = prometeu_bytecode::v0::BytecodeModule { + let rom = prometeu_bytecode::BytecodeModule { version: 0, const_pool: vec![], - functions: vec![prometeu_bytecode::v0::FunctionMeta { + functions: vec![prometeu_bytecode::FunctionMeta { code_offset: 0, code_len: 8, param_slots: 0, @@ -504,7 +504,7 @@ mod tests { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // JMP 0 (2 bytes opcode + 4 bytes u32) ], debug_info: None, - exports: vec![prometeu_bytecode::v0::Export { symbol: "main".into(), func_idx: 0 }], + exports: vec![prometeu_bytecode::Export { symbol: "main".into(), func_idx: 0 }], imports: vec![], }.serialize(); let cartridge = Cartridge { @@ -702,10 +702,10 @@ mod tests { let signals = InputSignals::default(); // PushI32 0 (0x17), then Ret (0x51) - let rom = prometeu_bytecode::v0::BytecodeModule { + let rom = prometeu_bytecode::BytecodeModule { version: 0, const_pool: vec![], - functions: vec![prometeu_bytecode::v0::FunctionMeta { + functions: vec![prometeu_bytecode::FunctionMeta { code_offset: 0, code_len: 10, param_slots: 0, @@ -720,7 +720,7 @@ mod tests { 0x51, 0x00 // Ret ], debug_info: None, - exports: vec![prometeu_bytecode::v0::Export { symbol: "main".into(), func_idx: 0 }], + exports: vec![prometeu_bytecode::Export { symbol: "main".into(), func_idx: 0 }], imports: vec![], }.serialize(); let cartridge = Cartridge { diff --git a/crates/prometeu-core/src/virtual_machine/local_addressing.rs b/crates/prometeu-core/src/virtual_machine/local_addressing.rs index 49814ada..f7c22df8 100644 --- a/crates/prometeu-core/src/virtual_machine/local_addressing.rs +++ b/crates/prometeu-core/src/virtual_machine/local_addressing.rs @@ -1,6 +1,6 @@ use crate::virtual_machine::call_frame::CallFrame; use prometeu_bytecode::abi::{TrapInfo, TRAP_INVALID_LOCAL}; -use prometeu_bytecode::v0::FunctionMeta; +use prometeu_bytecode::FunctionMeta; /// Computes the absolute stack index for the start of the current frame's locals (including args). pub fn local_base(frame: &CallFrame) -> usize { diff --git a/crates/prometeu-core/src/virtual_machine/mod.rs b/crates/prometeu-core/src/virtual_machine/mod.rs index f5a4f249..10f53d88 100644 --- a/crates/prometeu-core/src/virtual_machine/mod.rs +++ b/crates/prometeu-core/src/virtual_machine/mod.rs @@ -28,7 +28,7 @@ pub enum VmFault { pub enum VmInitError { InvalidFormat, UnsupportedFormat, - PbsV0LoadFailed(prometeu_bytecode::v0::LoadError), + PbsV0LoadFailed(prometeu_bytecode::LoadError), EntrypointNotFound, VerificationFailed(VerifierError), } diff --git a/crates/prometeu-core/src/virtual_machine/program.rs b/crates/prometeu-core/src/virtual_machine/program.rs index 10e02545..88e819e8 100644 --- a/crates/prometeu-core/src/virtual_machine/program.rs +++ b/crates/prometeu-core/src/virtual_machine/program.rs @@ -1,6 +1,6 @@ use crate::virtual_machine::Value; use prometeu_bytecode::abi::TrapInfo; -use prometeu_bytecode::v0::{BytecodeModule, ConstantPoolEntry, DebugInfo, Export, FunctionMeta}; +use prometeu_bytecode::{BytecodeModule, ConstantPoolEntry, DebugInfo, Export, FunctionMeta}; use std::collections::HashMap; use std::sync::Arc; diff --git a/crates/prometeu-core/src/virtual_machine/verifier.rs b/crates/prometeu-core/src/virtual_machine/verifier.rs index f61815f3..9b038182 100644 --- a/crates/prometeu-core/src/virtual_machine/verifier.rs +++ b/crates/prometeu-core/src/virtual_machine/verifier.rs @@ -1,6 +1,6 @@ use crate::virtual_machine::bytecode::decoder::{decode_at, DecodeError}; use prometeu_bytecode::opcode::OpCode; -use prometeu_bytecode::v0::FunctionMeta; +use prometeu_bytecode::FunctionMeta; use std::collections::{HashMap, HashSet, VecDeque}; #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/crates/prometeu-core/src/virtual_machine/virtual_machine.rs b/crates/prometeu-core/src/virtual_machine/virtual_machine.rs index 062bfb78..49205785 100644 --- a/crates/prometeu-core/src/virtual_machine/virtual_machine.rs +++ b/crates/prometeu-core/src/virtual_machine/virtual_machine.rs @@ -123,7 +123,7 @@ impl VirtualMachine { // Only recognized format is loadable: PBS v0 industrial format let program = if program_bytes.starts_with(b"PBS\0") { - match prometeu_bytecode::v0::BytecodeLoader::load(&program_bytes) { + match prometeu_bytecode::BytecodeLoader::load(&program_bytes) { Ok(module) => { // Run verifier on the module let max_stacks = crate::virtual_machine::verifier::Verifier::verify(&module.code, &module.functions) @@ -139,7 +139,7 @@ impl VirtualMachine { program } - Err(prometeu_bytecode::v0::LoadError::InvalidVersion) => return Err(VmInitError::UnsupportedFormat), + Err(prometeu_bytecode::LoadError::InvalidVersion) => return Err(VmInitError::UnsupportedFormat), Err(e) => { return Err(VmInitError::PbsV0LoadFailed(e)); } @@ -148,7 +148,7 @@ impl VirtualMachine { return Err(VmInitError::InvalidFormat); }; - // Resolve the entrypoint. Currently supports numeric addresses, symbolic exports, or empty (defaults to 0). + // Resolve the entrypoint: only empty (defaults to 0) or numeric PC are allowed. let pc = if entrypoint.is_empty() { 0 } else if let Ok(addr) = entrypoint.parse::() { @@ -157,16 +157,10 @@ impl VirtualMachine { } addr } else { - // Try to resolve symbol name via ProgramImage exports - if let Some(&func_idx) = program.exports.get(entrypoint) { - program.functions[func_idx as usize].code_offset as usize - } else if let Some(&func_idx) = program.exports.get(&format!("src/main/modules:{}", entrypoint)) { - program.functions[func_idx as usize].code_offset as usize - } else { - return Err(VmInitError::EntrypointNotFound); - } + // No symbol lookup by name in runtime. Linking is compiler-owned. + return Err(VmInitError::EntrypointNotFound); }; - + // Finalize initialization by applying the new program and PC. self.program = program; self.pc = pc; @@ -183,11 +177,8 @@ impl VirtualMachine { addr >= f.code_offset as usize && addr < (f.code_offset + f.code_len) as usize }).unwrap_or(0); (addr, idx) - } else if let Some(&func_idx) = self.program.exports.get(entrypoint) { - (self.program.functions[func_idx as usize].code_offset as usize, func_idx as usize) - } else if let Some(&func_idx) = self.program.exports.get(&format!("src/main/modules:{}", entrypoint)) { - (self.program.functions[func_idx as usize].code_offset as usize, func_idx as usize) } else { + // No symbol lookup by name in runtime. Default to 0 for non-numeric entrypoints. (0, 0) }; @@ -921,7 +912,7 @@ mod tests { use crate::hardware::HardwareBridge; use crate::virtual_machine::{expect_int, HostReturn, Value, VmFault}; use prometeu_bytecode::abi::SourceSpan; - use prometeu_bytecode::v0::FunctionMeta; + use prometeu_bytecode::FunctionMeta; struct MockNative; impl NativeInterface for MockNative { @@ -1862,7 +1853,7 @@ mod tests { let res = vm.initialize(header, ""); match res { - Err(VmInitError::PbsV0LoadFailed(prometeu_bytecode::v0::LoadError::UnexpectedEof)) => {}, + Err(VmInitError::PbsV0LoadFailed(prometeu_bytecode::LoadError::UnexpectedEof)) => {}, _ => panic!("Expected PbsV0LoadFailed(UnexpectedEof), got {:?}", res), } } @@ -2424,7 +2415,7 @@ mod tests { pc_to_span.push((6, SourceSpan { file_id: 1, start: 16, end: 20 })); pc_to_span.push((12, SourceSpan { file_id: 1, start: 21, end: 25 })); - let debug_info = prometeu_bytecode::v0::DebugInfo { + let debug_info = prometeu_bytecode::DebugInfo { pc_to_span, function_names: vec![(0, "main".to_string())], }; @@ -2465,7 +2456,7 @@ mod tests { let pc_to_span = vec![(12, SourceSpan { file_id: 1, start: 21, end: 25 })]; let function_names = vec![(0, "math_utils::divide".to_string())]; - let debug_info = prometeu_bytecode::v0::DebugInfo { + let debug_info = prometeu_bytecode::DebugInfo { pc_to_span, function_names, }; diff --git a/crates/prometeu-core/tests/heartbeat.rs b/crates/prometeu-core/tests/heartbeat.rs index 3e9f24fb..349b6db3 100644 --- a/crates/prometeu-core/tests/heartbeat.rs +++ b/crates/prometeu-core/tests/heartbeat.rs @@ -6,6 +6,7 @@ use prometeu_core::virtual_machine::{LogicalFrameEndingReason, VirtualMachine}; use prometeu_core::Hardware; use std::fs; use std::path::Path; +use prometeu_bytecode::BytecodeLoader; struct MockNative; impl NativeInterface for MockNative { @@ -37,10 +38,21 @@ fn test_canonical_cartridge_heartbeat() { } let pbc_bytes = fs::read(pbc_path).expect("Failed to read canonical PBC. Did you run the generation test?"); + + // Determine numeric entrypoint PC from the compiled module exports + let module = BytecodeLoader::load(&pbc_bytes).expect("Failed to parse PBC"); + let func_idx = module + .exports + .iter() + .find(|e| e.symbol == "src/main/modules:frame") + .map(|e| e.func_idx as usize) + .expect("Entrypoint symbol not found in exports"); + let entry_pc = module.functions[func_idx].code_offset as usize; + let entry_pc_str = entry_pc.to_string(); let mut vm = VirtualMachine::new(vec![], vec![]); - vm.initialize(pbc_bytes, "src/main/modules:frame").expect("Failed to initialize VM with canonical cartridge"); - vm.prepare_call("src/main/modules:frame"); + vm.initialize(pbc_bytes, &entry_pc_str).expect("Failed to initialize VM with canonical cartridge"); + vm.prepare_call(&entry_pc_str); let mut native = MockNative; let mut hw = Hardware::new(); diff --git a/docs/specs/pbs/files/PRs para Junie.md b/docs/specs/pbs/files/PRs para Junie.md index 06581d2d..cf0be47a 100644 --- a/docs/specs/pbs/files/PRs para Junie.md +++ b/docs/specs/pbs/files/PRs para Junie.md @@ -1,80 +1,3 @@ -## PR-15 — Link Orchestration v0 inside `prometeu_compiler` - -**Why:** The compiler must emit a single closed-world executable blob. - -### Scope - -* Move all link responsibilities to `prometeu_compiler`: - - * **Input:** `Vec` (in build-plan order) - * **Output:** `ProgramImage` (single PBS v0 bytecode blob) - -* Linker responsibilities (v0): - - * resolve imports to exports across modules - * validate symbol visibility (`pub` only) - * assign final `FunctionTable` indices - * patch `CALL` opcodes to final `func_id` - * merge constant pools deterministically - * emit final PBS v0 image - -### Deliverables - -* `link(modules) -> Result` -* `LinkError` variants: - - * unresolved import - * duplicate export - * incompatible symbol signature (if available) - -### Tests - -* `archive-pbs/test01` as integration test: - - * root depends on a lib - * root calls into lib - * final blob runs successfully in VM - -### Acceptance - -* Compiler emits a single executable blob; VM performs no linking. - ---- - -## PR-16 — VM Boundary Cleanup: remove linker behavior from runtime - -**Why:** Runtime must be dumb and deterministic. - -### Scope - -* Audit `prometeu_core` and `prometeu_bytecode`: - - * VM loads PBS v0 module - * VM verifies (optional) and executes - -* Remove or disable any linker-like behavior in runtime: - - * no dependency resolution - * no symbol lookup by name - * no module graph assumptions - -### Deliverables - -* VM init path uses: - - * `BytecodeLoader::load()` → `(code, const_pool, functions)` - * verifier as an execution gate - -### Tests - -* runtime loads and executes compiler-produced blob - -### Acceptance - -* Linking is fully compiler-owned. - ---- - ## PR-17 — Diagnostics UX: dependency graph and resolution trace **Why:** Dependency failures must be explainable.