1use serde::{Deserialize, Serialize};
29use std::fmt;
30
31#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
33pub struct Confidence(pub f32);
34
35impl Confidence {
36 pub const ZERO: Confidence = Confidence(0.0);
37 pub const CERTAIN: Confidence = Confidence(1.0);
38 pub const HIGH: Confidence = Confidence(0.95);
39 pub const MEDIUM: Confidence = Confidence(0.5);
40 pub const LOW: Confidence = Confidence(0.1);
41
42 pub fn new(v: f32) -> Self {
43 Confidence(v.clamp(0.0, 1.0))
44 }
45
46 pub fn fuse(a: Confidence, b: Confidence) -> Confidence {
48 if a.0 <= 0.0 && b.0 <= 0.0 { return Confidence::ZERO; }
49 if a.0 <= 0.0 { return b; }
50 if b.0 <= 0.0 { return a; }
51 Confidence::new(1.0 / (1.0 / a.0 + 1.0 / b.0))
52 }
53
54 pub fn chain(a: Confidence, b: Confidence) -> Confidence {
56 Confidence::new(a.0 * b.0)
57 }
58}
59
60#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
62pub enum OpCategory {
63 Control, ArithConf, Logic, Compare, Stack,
64 Perception, A2A, Memory, Type, SIMD,
65 Instinct, Energy, System,
66}
67
68#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
70#[repr(u8)]
71pub enum Opcode {
72 Nop = 0x00,
74 Mov = 0x01,
75 MovI = 0x02,
76 Jmp = 0x03,
77 Jz = 0x04,
78 Jnz = 0x05,
79 Call = 0x06,
80 Ret = 0x07,
81
82 CAdd = 0x08,
84 CSub = 0x09,
85 CMul = 0x0A,
86 CDiv = 0x0B,
87 CMod = 0x0C,
88 CNeg = 0x0D,
89 CInc = 0x0E,
90 CDec = 0x0F,
91 CMin = 0x10,
92 CMax = 0x11,
93 CAbs = 0x12,
94 CLerp = 0x13,
95 ConfSet = 0x14,
96 ConfFuse = 0x15,
97 ConfChain = 0x16,
98 ConfThreshold = 0x17,
99
100 And = 0x18,
102 Or = 0x19,
103 Xor = 0x1A,
104 Not = 0x1B,
105 Shl = 0x1C,
106 Shr = 0x1D,
107 RotL = 0x1E,
108 RotR = 0x1F,
109
110 Cmp = 0x20,
112 Eq = 0x21,
113 Lt = 0x22,
114 Gt = 0x23,
115 Le = 0x24,
116 Ge = 0x25,
117 ConfEq = 0x26,
118 Test = 0x27,
119
120 Push = 0x28,
122 Pop = 0x29,
123 Dup = 0x2A,
124 Swap = 0x2B,
125 Rot3 = 0x2C,
126 Enter = 0x2D,
127 Leave = 0x2E,
128 Pick = 0x2F,
129
130 IoRead = 0x30,
132 IoWrite = 0x31,
133 SensorAcquire = 0x32,
134 FuseConf = 0x33,
135 Perceive = 0x34,
136 Sense = 0x35,
137 Load8 = 0x36,
138 Store8 = 0x37,
139
140 Tell = 0x38,
142 Ask = 0x39,
143 Delegate = 0x3A,
144 DelegResult = 0x3B,
145 Broadcast = 0x3C,
146 Reduce = 0x3D,
147 TrustCheck = 0x3E,
148 TrustUpdate = 0x3F,
149 TrustQuery = 0x40,
150 TrustRevoke = 0x41,
151 CapRequire = 0x42,
152 CapGrant = 0x43,
153 CapRevoke = 0x44,
154 DeclareIntent = 0x45,
155 AssertGoal = 0x46,
156 VerifyOutcome = 0x47,
157 Barrier = 0x48,
158 Formation = 0x49,
159 SyncClock = 0x4A,
160 ReportStatus = 0x4B,
161 ExplainFail = 0x4C,
162 SetPriority = 0x4D,
163 RequestOverride = 0x4E,
164 EmergencyStop = 0x4F,
165
166 RegionCreate = 0x50,
168 RegionDestroy = 0x51,
169 RegionTransfer = 0x52,
170 MemCopy = 0x53,
171 MemSet = 0x54,
172 MemCmp = 0x55,
173 Load = 0x56,
174 Store = 0x57,
175
176 Cast = 0x58,
178 Box = 0x59,
179 Unbox = 0x5A,
180 CheckType = 0x5B,
181 CheckBounds = 0x5C,
182 Tag = 0x5D,
183 Untag = 0x5E,
184 IsNil = 0x5F,
185
186 VLoad = 0x60,
188 VStore = 0x61,
189 VAdd = 0x62,
190 VSub = 0x63,
191 VMul = 0x64,
192 VDiv = 0x65,
193 VFma = 0x66,
194 VConfFuse = 0x67,
195
196 InstinctActivate = 0x68,
198 InstinctQuery = 0x69,
199 GeneExpress = 0x6A,
200 EnzymeBind = 0x6B,
201 RnaTranslate = 0x6C,
202 ProteinFold = 0x6D,
203 MembraneCheck = 0x6E,
204 Quarantine = 0x6F,
205
206 AtpGenerate = 0x70,
208 AtpConsume = 0x71,
209 AtpQuery = 0x72,
210 AtpTransfer = 0x73,
211 ApoptosisCheck = 0x74,
212 ApoptosisTrigger = 0x75,
213 CircadianSet = 0x76,
214 CircadianGet = 0x77,
215
216 Halt = 0x78,
218 Yield = 0x79,
219 ResourceAcquire = 0x7A,
220 ResourceRelease = 0x7B,
221 Debug = 0x7C,
222 DumpState = 0x7D,
223 Trap = 0x7E,
224 NopSys = 0x7F,
225}
226
227impl Opcode {
228 pub fn from_byte(b: u8) -> Option<Self> {
229 if b <= 0x7F { Some(unsafe { std::mem::transmute(b) }) } else { None }
231 }
232
233 pub fn to_byte(self) -> u8 { self as u8 }
234
235 pub fn category(self) -> OpCategory {
236 match self as u8 {
237 0x00..=0x07 => OpCategory::Control,
238 0x08..=0x17 => OpCategory::ArithConf,
239 0x18..=0x1F => OpCategory::Logic,
240 0x20..=0x27 => OpCategory::Compare,
241 0x28..=0x2F => OpCategory::Stack,
242 0x30..=0x37 => OpCategory::Perception,
243 0x38..=0x4F => OpCategory::A2A,
244 0x50..=0x57 => OpCategory::Memory,
245 0x58..=0x5F => OpCategory::Type,
246 0x60..=0x67 => OpCategory::SIMD,
247 0x68..=0x6F => OpCategory::Instinct,
248 0x70..=0x77 => OpCategory::Energy,
249 0x78..=0x7F => OpCategory::System,
250 _ => OpCategory::Control,
251 }
252 }
253
254 pub fn name(self) -> &'static str {
255 match self {
256 Opcode::Nop => "NOP", Opcode::Mov => "MOV", Opcode::MovI => "MOVI",
257 Opcode::Jmp => "JMP", Opcode::Jz => "JZ", Opcode::Jnz => "JNZ",
258 Opcode::Call => "CALL", Opcode::Ret => "RET",
259 Opcode::CAdd => "CADD", Opcode::CSub => "CSUB", Opcode::CMul => "CMUL",
260 Opcode::CDiv => "CDIV", Opcode::CMod => "CMOD", Opcode::CNeg => "CNEG",
261 Opcode::CInc => "CINC", Opcode::CDec => "CDEC", Opcode::CMin => "CMIN",
262 Opcode::CMax => "CMAX", Opcode::CAbs => "CABS", Opcode::CLerp => "CLERP",
263 Opcode::ConfSet => "CONF_SET", Opcode::ConfFuse => "CONF_FUSE",
264 Opcode::ConfChain => "CONF_CHAIN", Opcode::ConfThreshold => "CONF_THRESH",
265 Opcode::And => "AND", Opcode::Or => "OR", Opcode::Xor => "XOR",
266 Opcode::Not => "NOT", Opcode::Shl => "SHL", Opcode::Shr => "SHR",
267 Opcode::RotL => "ROTL", Opcode::RotR => "ROTR",
268 Opcode::Cmp => "CMP", Opcode::Eq => "EQ", Opcode::Lt => "LT",
269 Opcode::Gt => "GT", Opcode::Le => "LE", Opcode::Ge => "GE",
270 Opcode::ConfEq => "CONF_EQ", Opcode::Test => "TEST",
271 Opcode::Push => "PUSH", Opcode::Pop => "POP", Opcode::Dup => "DUP",
272 Opcode::Swap => "SWAP", Opcode::Rot3 => "ROT3", Opcode::Enter => "ENTER",
273 Opcode::Leave => "LEAVE", Opcode::Pick => "PICK",
274 Opcode::IoRead => "IO_READ", Opcode::IoWrite => "IO_WRITE",
275 Opcode::SensorAcquire => "SENSOR_ACQ", Opcode::FuseConf => "FUSE_CONF",
276 Opcode::Perceive => "PERCEIVE", Opcode::Sense => "SENSE",
277 Opcode::Load8 => "LOAD8", Opcode::Store8 => "STORE8",
278 Opcode::Tell => "TELL", Opcode::Ask => "ASK", Opcode::Delegate => "DELEGATE",
279 Opcode::DelegResult => "DELEG_RESULT", Opcode::Broadcast => "BROADCAST",
280 Opcode::Reduce => "REDUCE", Opcode::TrustCheck => "TRUST_CHECK",
281 Opcode::TrustUpdate => "TRUST_UPDATE", Opcode::TrustQuery => "TRUST_QUERY",
282 Opcode::TrustRevoke => "TRUST_REVOKE", Opcode::CapRequire => "CAP_REQ",
283 Opcode::CapGrant => "CAP_GRANT", Opcode::CapRevoke => "CAP_REVOKE",
284 Opcode::DeclareIntent => "DECLARE_INTENT", Opcode::AssertGoal => "ASSERT_GOAL",
285 Opcode::VerifyOutcome => "VERIFY_OUTCOME", Opcode::Barrier => "BARRIER",
286 Opcode::Formation => "FORMATION", Opcode::SyncClock => "SYNC_CLOCK",
287 Opcode::ReportStatus => "REPORT_STATUS", Opcode::ExplainFail => "EXPLAIN_FAIL",
288 Opcode::SetPriority => "SET_PRIORITY", Opcode::RequestOverride => "REQ_OVERRIDE",
289 Opcode::EmergencyStop => "EMERGENCY_STOP",
290 Opcode::RegionCreate => "REGION_CREATE", Opcode::RegionDestroy => "REGION_DESTROY",
291 Opcode::RegionTransfer => "REGION_TRANSFER", Opcode::MemCopy => "MEMCOPY",
292 Opcode::MemSet => "MEMSET", Opcode::MemCmp => "MEMCMP",
293 Opcode::Load => "LOAD", Opcode::Store => "STORE",
294 Opcode::Cast => "CAST", Opcode::Box => "BOX", Opcode::Unbox => "UNBOX",
295 Opcode::CheckType => "CHECK_TYPE", Opcode::CheckBounds => "CHECK_BOUNDS",
296 Opcode::Tag => "TAG", Opcode::Untag => "UNTAG", Opcode::IsNil => "IS_NIL",
297 Opcode::VLoad => "VLOAD", Opcode::VStore => "VSTORE",
298 Opcode::VAdd => "VADD", Opcode::VSub => "VSUB",
299 Opcode::VMul => "VMUL", Opcode::VDiv => "VDIV",
300 Opcode::VFma => "VFMA", Opcode::VConfFuse => "VCONF_FUSE",
301 Opcode::InstinctActivate => "INSTINCT_ACT", Opcode::InstinctQuery => "INSTINCT_Q",
302 Opcode::GeneExpress => "GENE_EXPR", Opcode::EnzymeBind => "ENZYME_BIND",
303 Opcode::RnaTranslate => "RNA_TRANS", Opcode::ProteinFold => "PROTEIN_FOLD",
304 Opcode::MembraneCheck => "MEMBRANE_CHK", Opcode::Quarantine => "QUARANTINE",
305 Opcode::AtpGenerate => "ATP_GEN", Opcode::AtpConsume => "ATP_CONSUME",
306 Opcode::AtpQuery => "ATP_Q", Opcode::AtpTransfer => "ATP_TRANSFER",
307 Opcode::ApoptosisCheck => "APOPTOSIS_CHK", Opcode::ApoptosisTrigger => "APOPTOSIS_TRIGGER",
308 Opcode::CircadianSet => "CIRCADIAN_SET", Opcode::CircadianGet => "CIRCADIAN_GET",
309 Opcode::Halt => "HALT", Opcode::Yield => "YIELD",
310 Opcode::ResourceAcquire => "RES_ACQ", Opcode::ResourceRelease => "RES_REL",
311 Opcode::Debug => "DEBUG", Opcode::DumpState => "DUMP",
312 Opcode::Trap => "TRAP", Opcode::NopSys => "NOP_SYS",
313 }
314 }
315}
316
317impl fmt::Display for Opcode {
318 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.name()) }
319}
320
321#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
323pub struct ConfValue {
324 pub value: i64,
325 pub confidence: Confidence,
326}
327
328impl ConfValue {
329 pub fn certain(v: i64) -> Self { ConfValue { value: v, confidence: Confidence::CERTAIN } }
330 pub fn uncertain(v: i64, c: f32) -> Self { ConfValue { value: v, confidence: Confidence::new(c) } }
331 pub fn zero() -> Self { ConfValue { value: 0, confidence: Confidence::CERTAIN } }
332}
333
334#[derive(Clone, Debug, Serialize, Deserialize)]
336pub struct Instruction {
337 pub opcode: Opcode,
338 pub operands: Vec<u8>,
339}
340
341impl Instruction {
342 pub fn new(op: Opcode, ops: Vec<u8>) -> Self { Instruction { opcode: op, operands: ops } }
343 pub fn simple(op: Opcode) -> Self { Instruction { opcode: op, operands: vec![] } }
344 pub fn reg(op: Opcode, rd: u8) -> Self { Instruction { opcode: op, operands: vec![rd] } }
345 pub fn reg2(op: Opcode, rd: u8, rs: u8) -> Self { Instruction { opcode: op, operands: vec![rd, rs] } }
346 pub fn reg_imm(op: Opcode, rd: u8, imm: i16) -> Self {
347 Instruction { opcode: op, operands: vec![rd, (imm & 0xFF) as u8, ((imm >> 8) & 0xFF) as u8] }
348 }
349
350 pub fn encode(&self) -> Vec<u8> {
352 let mut bytes = vec![self.opcode.to_byte()];
353 match self.opcode.category() {
355 OpCategory::A2A | OpCategory::Memory | OpCategory::Type => {
356 let len = self.operands.len() as u16;
357 bytes.push((len & 0xFF) as u8);
358 bytes.push(((len >> 8) & 0xFF) as u8);
359 bytes.extend(&self.operands);
360 }
361 _ => { bytes.extend(&self.operands); }
362 }
363 bytes
364 }
365
366 pub fn decode(data: &[u8]) -> Option<(Self, usize)> {
368 if data.is_empty() { return None; }
369 let op = Opcode::from_byte(data[0])?;
370 let (operands, consumed) = match op.category() {
371 OpCategory::A2A | OpCategory::Memory | OpCategory::Type => {
372 if data.len() < 3 { return None; }
373 let len = (data[1] as u16) | ((data[2] as u16) << 8);
374 let end = 3 + len as usize;
375 if data.len() < end { return None; }
376 (data[3..end].to_vec(), end)
377 }
378 OpCategory::Control | OpCategory::ArithConf | OpCategory::Logic
379 | OpCategory::Compare | OpCategory::Stack | OpCategory::SIMD => {
380 let op_len = match op {
382 Opcode::MovI | Opcode::Jmp | Opcode::Jz | Opcode::Jnz
383 | Opcode::Call => 4, Opcode::Nop | Opcode::Ret | Opcode::Halt | Opcode::Yield
385 | Opcode::Dup | Opcode::NopSys => 1,
386 Opcode::Enter | Opcode::Leave => 2, _ => 3, };
389 let ops = if data.len() >= op_len { data[1..op_len].to_vec() } else { vec![] };
390 (ops, op_len)
391 }
392 _ => (vec![], 1),
393 };
394 Some((Instruction { opcode: op, operands }, consumed))
395 }
396}
397
398pub struct Assembler {
400 pub instructions: Vec<Instruction>,
401 pub labels: std::collections::HashMap<String, usize>,
402 pub unresolved: Vec<(String, usize)>,
403}
404
405impl Assembler {
406 pub fn new() -> Self { Assembler { instructions: vec![], labels: std::collections::HashMap::new(), unresolved: vec![] } }
407
408 pub fn emit(&mut self, insn: Instruction) { self.instructions.push(insn); }
409
410 pub fn label(&mut self, name: &str) { self.labels.insert(name.to_string(), self.instructions.len()); }
411
412 pub fn emit_jmp(&mut self, label: &str) {
413 self.unresolved.push((label.to_string(), self.instructions.len()));
414 self.emit(Instruction::new(Opcode::Jmp, vec![0, 0, 0])); }
416
417 pub fn assemble(&mut self) -> Result<Vec<u8>, String> {
418 for (label, idx) in &self.unresolved {
420 if let Some(&target) = self.labels.get(label) {
421 let offset = target as i16 - *idx as i16;
422 if let Some(ref mut insn) = self.instructions.get_mut(*idx) {
423 insn.operands = vec![0, (offset & 0xFF) as u8, ((offset >> 8) & 0xFF) as u8];
424 }
425 } else { return Err(format!("Unresolved label: {}", label)); }
426 }
427 let mut bytecode = vec![];
429 for insn in &self.instructions { bytecode.extend(insn.encode()); }
430 Ok(bytecode)
431 }
432}
433
434pub struct Disassembler;
436
437impl Disassembler {
438 pub fn disassemble(data: &[u8]) -> Vec<String> {
439 let mut lines = vec![];
440 let mut pc = 0;
441 while pc < data.len() {
442 if let Some((insn, consumed)) = Instruction::decode(&data[pc..]) {
443 let ops_str = insn.operands.iter().map(|b| format!("{}", b)).collect::<Vec<_>>().join(" ");
444 if ops_str.is_empty() { lines.push(format!("{:04X}: {}", pc, insn.opcode.name())); }
445 else { lines.push(format!("{:04X}: {} {}", pc, insn.opcode.name(), ops_str)); }
446 pc += consumed;
447 } else { lines.push(format!("{:04X}: ???", pc)); pc += 1; }
448 }
449 lines
450 }
451}
452
453#[derive(Clone, Debug, Serialize, Deserialize)]
455pub struct A2AMessage {
456 pub sender_id: u32,
457 pub intent: String,
458 pub confidence: Confidence,
459 pub payload_hash: u64,
460 pub trust_level: f32,
461 pub priority: u8,
462}
463
464impl A2AMessage {
465 pub fn encode(&self) -> Vec<u8> {
466 let intent_bytes = self.intent.as_bytes();
467 let mut out = vec![];
468 out.extend(&self.sender_id.to_le_bytes());
469 out.push(intent_bytes.len() as u8);
470 out.extend(intent_bytes);
471 out.extend(&self.confidence.0.to_le_bytes());
472 out.extend(&self.payload_hash.to_le_bytes());
473 out.extend(&self.trust_level.to_le_bytes());
474 out.push(self.priority);
475 out
476 }
477
478 pub fn decode(data: &[u8]) -> Option<Self> {
479 if data.len() < 4 + 1 + 4 + 8 + 4 + 1 { return None; }
480 let sender_id = u32::from_le_bytes([data[0], data[1], data[2], data[3]]);
481 let intent_len = data[4] as usize;
482 if data.len() < 5 + intent_len + 4 + 8 + 4 + 1 { return None; }
483 let intent = String::from_utf8_lossy(&data[5..5 + intent_len]).to_string();
484 let mut offset = 5 + intent_len;
485 let confidence = f32::from_le_bytes([data[offset], data[offset+1], data[offset+2], data[offset+3]]);
486 offset += 4;
487 let payload_hash = u64::from_le_bytes(data[offset..offset+8].try_into().ok()?);
488 offset += 8;
489 let trust_level = f32::from_le_bytes([data[offset], data[offset+1], data[offset+2], data[offset+3]]);
490 offset += 4;
491 let priority = data[offset];
492 Some(A2AMessage { sender_id, intent, confidence: Confidence::new(confidence), payload_hash, trust_level, priority })
493 }
494}
495
496#[cfg(test)]
497mod tests {
498 use super::*;
499
500 #[test]
501 fn test_opcode_roundtrip() {
502 for b in 0..=0x7F {
503 let op = Opcode::from_byte(b).unwrap();
504 assert_eq!(op.to_byte(), b);
505 if b == 0 { assert_eq!(op.category(), Opcode::Nop.category()); }
506 }
507 assert!(Opcode::from_byte(0x80).is_none());
508 }
509
510 #[test]
511 fn test_confidence_fusion() {
512 let a = Confidence::new(0.8);
513 let b = Confidence::new(0.5);
514 let fused = Confidence::fuse(a, b);
515 assert!((fused.0 - 0.308).abs() < 0.01);
517 }
518
519 #[test]
520 fn test_confidence_chain() {
521 let a = Confidence::new(0.9);
522 let b = Confidence::new(0.8);
523 let chained = Confidence::chain(a, b);
524 assert!((chained.0 - 0.72).abs() < 0.01);
525 }
526
527 #[test]
528 fn test_instruction_encode_decode() {
529 let insn = Instruction::reg2(Opcode::CAdd, 0, 1);
530 let bytes = insn.encode();
531 assert_eq!(bytes, vec![0x08, 0, 1]);
532 let (decoded, consumed) = Instruction::decode(&bytes).unwrap();
533 assert_eq!(decoded.opcode, Opcode::CAdd);
534 assert_eq!(decoded.operands, vec![0, 1]);
535 assert_eq!(consumed, 3);
536 }
537
538 #[test]
539 fn test_movi_encode_decode() {
540 let insn = Instruction::reg_imm(Opcode::MovI, 0, -42);
541 let bytes = insn.encode();
542 let (decoded, _) = Instruction::decode(&bytes).unwrap();
543 assert_eq!(decoded.opcode, Opcode::MovI);
544 assert_eq!(decoded.operands[0], 0);
545 assert_eq!(decoded.operands[1], 0xD6);
547 assert_eq!(decoded.operands[2], 0xFF);
548 }
549
550 #[test]
551 fn test_a2a_message_roundtrip() {
552 let msg = A2AMessage {
553 sender_id: 42,
554 intent: "investigate_anomaly".to_string(),
555 confidence: Confidence::new(0.85),
556 payload_hash: 12345,
557 trust_level: 0.9,
558 priority: 3,
559 };
560 let encoded = msg.encode();
561 let decoded = A2AMessage::decode(&encoded).unwrap();
562 assert_eq!(decoded.sender_id, 42);
563 assert_eq!(decoded.intent, "investigate_anomaly");
564 assert!((decoded.confidence.0 - 0.85).abs() < 0.01);
565 }
566
567 #[test]
568 fn test_assembler_basic() {
569 let mut asm = Assembler::new();
570 asm.emit(Instruction::reg_imm(Opcode::MovI, 0, 10));
571 asm.emit(Instruction::reg_imm(Opcode::MovI, 1, 25));
572 asm.emit(Instruction::reg2(Opcode::CAdd, 0, 1));
573 asm.emit(Instruction::simple(Opcode::Halt));
574 let bytecode = asm.assemble().unwrap();
575 assert_eq!(bytecode[0], 0x02); assert_eq!(bytecode[bytecode.len()-1], 0x78); }
578
579 #[test]
580 fn test_assembler_with_labels() {
581 let mut asm = Assembler::new();
582 asm.emit(Instruction::reg_imm(Opcode::MovI, 0, 1));
583 asm.label("loop");
584 asm.emit(Instruction::simple(Opcode::Nop));
585 asm.emit(Instruction::new(Opcode::Jz, vec![0, 3, 0]));
586 asm.emit_jmp("loop");
587 let bytecode = asm.assemble().unwrap();
588 assert!(!bytecode.is_empty());
589 }
590
591 #[test]
592 fn test_disassembler() {
593 let bytecode = vec![0x00, 0x78, 0x02, 0, 10, 0];
594 let lines = Disassembler::disassemble(&bytecode);
595 assert_eq!(lines[0], "0000: NOP");
596 assert_eq!(lines[1], "0001: HALT");
597 assert!(lines[2].starts_with("0002: MOVI"));
598 }
599
600 #[test]
601 fn test_opcode_names() {
602 assert_eq!(Opcode::Halt.name(), "HALT");
603 assert_eq!(Opcode::CAdd.name(), "CADD");
604 assert_eq!(Opcode::InstinctActivate.name(), "INSTINCT_ACT");
605 assert_eq!(Opcode::AtpGenerate.name(), "ATP_GEN");
606 }
607
608 #[test]
609 fn test_confidence_clamping() {
610 assert_eq!(Confidence::new(1.5).0, 1.0);
611 assert_eq!(Confidence::new(-0.5).0, 0.0);
612 }
613
614 #[test]
615 fn test_all_categories_covered() {
616 let cats = [
617 OpCategory::Control, OpCategory::ArithConf, OpCategory::Logic,
618 OpCategory::Compare, OpCategory::Stack, OpCategory::Perception,
619 OpCategory::A2A, OpCategory::Memory, OpCategory::Type,
620 OpCategory::SIMD, OpCategory::Instinct, OpCategory::Energy,
621 OpCategory::System,
622 ];
623 for cat in &cats {
624 let found = (0..=0x7Fu8).any(|b| Opcode::from_byte(b).map(|o| o.category() == *cat).unwrap_or(false));
625 assert!(found, "Category {:?} has no opcodes", cat);
626 }
627 }
628
629 #[test]
630 fn test_instinct_opcodes() {
631 assert_eq!(Opcode::InstinctActivate as u8, 0x68);
632 assert_eq!(Opcode::GeneExpress as u8, 0x6A);
633 assert_eq!(Opcode::EnzymeBind as u8, 0x6B);
634 assert_eq!(Opcode::ApoptosisCheck as u8, 0x74);
635 assert_eq!(Opcode::AtpGenerate as u8, 0x70);
636 }
637}