1pub mod bet;
2
3use crate::trit::Trit;
4use crate::vm::bet::{unpack_trits, BetFault};
5
6use std::fmt;
7use std::sync::Arc;
8
9pub trait RemoteTransport: Send + Sync {
12 fn remote_send(&self, node_addr: &str, agent_id: usize, trit: i8) -> std::io::Result<()>;
13 fn remote_await(&self, node_addr: &str, agent_id: usize) -> std::io::Result<i8>;
14}
15
16#[derive(Debug, PartialEq, Eq)]
17pub enum VmError {
18 StackUnderflow,
19 BetFault(BetFault),
20 Halt,
21 InvalidOpcode(u8),
22 InvalidRegister(u8),
23 PcOutOfBounds(usize),
24 TypeMismatch { expected: String, found: String },
25 TensorIndexOutOfBounds { tensor_id: usize, index: usize, size: usize },
27 TensorNotAllocated(usize),
28 AgentTypeNotRegistered(u16),
30 AgentIdInvalid(usize),
31 RuntimeError(String),
32}
33
34impl fmt::Display for VmError {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 match self {
37 VmError::StackUnderflow =>
38 write!(f, "[BET-001] Stack underflow — you tried to pop a truth that wasn't there.\n → details: stdlib/errors/BET-001.tern | ternlang errors BET-001"),
39 VmError::BetFault(fault) =>
40 write!(f, "[BET-002] BET encoding fault: {fault:?}. The 0b00 state is forbidden — only 01/10/11 are valid trit bits.\n → details: stdlib/errors/BET-002.tern | ternlang errors BET-002"),
41 VmError::Halt =>
42 write!(f, "[BET-003] VM halted cleanly. Execution reached the end. This is not an error — this is peace.\n → details: stdlib/errors/BET-003.tern | ternlang errors BET-003"),
43 VmError::InvalidOpcode(op) =>
44 write!(f, "[BET-004] Unknown opcode 0x{op:02x} — the machine has never seen this instruction. Delete cached .ternbc files and recompile.\n → details: stdlib/errors/BET-004.tern | ternlang errors BET-004"),
45 VmError::InvalidRegister(reg) =>
46 write!(f, "[BET-005] Register {reg} is out of range. The BET has exactly 27 registers (0–26). That's 3³. No more.\n → details: stdlib/errors/BET-005.tern | ternlang errors BET-005"),
47 VmError::PcOutOfBounds(pc) =>
48 write!(f, "[BET-006] PC {pc} is out of bounds — you jumped outside the known universe. Recompile from source.\n → details: stdlib/errors/BET-006.tern | ternlang errors BET-006"),
49 VmError::TypeMismatch { expected, found } =>
50 write!(f, "[BET-007] Runtime type mismatch — expected {expected} but found {found}. Square peg, round hole.\n → details: stdlib/errors/BET-007.tern | ternlang errors BET-007"),
51 VmError::TensorIndexOutOfBounds { tensor_id, index, size } =>
52 write!(f, "[BET-008] Tensor[{tensor_id}]: index {index} is out of bounds — tensor only has {size} element(s). Trittensors don't grow on access.\n → details: stdlib/errors/BET-008.tern | ternlang errors BET-008"),
53 VmError::TensorNotAllocated(idx) =>
54 write!(f, "[BET-009] TensorRef({idx}) doesn't exist — you never allocated it. TALLOC first, then TIDX.\n → details: stdlib/errors/BET-009.tern | ternlang errors BET-009"),
55 VmError::AgentTypeNotRegistered(type_id) =>
56 write!(f, "[BET-010] Agent type_id 0x{type_id:04x} was never registered. You can't spawn what was never declared.\n → details: stdlib/errors/BET-010.tern | ternlang errors BET-010"),
57 VmError::AgentIdInvalid(id) =>
58 write!(f, "[BET-011] Agent #{id} doesn't exist — no agent was spawned at this ID. TSEND and TAWAIT require a live agent.\n → details: stdlib/errors/BET-011.tern | ternlang errors BET-011"),
59 VmError::RuntimeError(msg) =>
60 write!(f, "[BET-012] Runtime error: {msg}"),
61 }
62 }
63}
64
65#[derive(Debug, Clone, PartialEq)]
66pub enum Value {
67 Trit(Trit),
68 Int(i64),
69 Float(f64),
70 String(String),
71 TensorRef(usize),
72 AgentRef(usize, Option<String>),
73}
74
75impl Default for Value {
76 fn default() -> Self {
77 Value::Trit(Trit::Tend)
78 }
79}
80
81struct TensorInstance {
82 data: Vec<Trit>,
83 rows: usize,
84 cols: usize,
85}
86
87struct AgentInstance {
88 handler_addr: usize,
89 mailbox: std::collections::VecDeque<Value>,
90}
91
92pub struct BetVm {
93 registers: [Value; 27],
94 register_stack: Vec<[Value; 27]>,
95 carry_reg: Trit,
96 stack: Vec<Value>,
97 call_stack: Vec<usize>,
98 tensors: Vec<TensorInstance>,
99 agents: Vec<AgentInstance>,
100 agent_types: std::collections::HashMap<u16, usize>,
101 pc: usize,
102 code: Vec<u8>,
103 node_id: String,
104 remote: Option<Arc<dyn RemoteTransport>>,
105 _instructions_count: u64,
106 pub print_log: Vec<String>,
107}
108
109impl BetVm {
110 pub fn new(code: Vec<u8>) -> Self {
111 Self {
112 registers: std::array::from_fn(|_| Value::default()),
113 register_stack: Vec::new(),
114 carry_reg: Trit::Tend,
115 stack: Vec::new(),
116 call_stack: Vec::new(),
117 tensors: Vec::new(),
118 agents: Vec::new(),
119 agent_types: std::collections::HashMap::new(),
120 pc: 0,
121 code,
122 node_id: "127.0.0.1".into(),
123 remote: None,
124 _instructions_count: 0,
125 print_log: Vec::new(),
126 }
127 }
128
129
130 pub fn take_output(&mut self) -> Vec<String> {
132 std::mem::take(&mut self.print_log)
133 }
134
135 pub fn set_node_id(&mut self, node_id: String) {
136 self.node_id = node_id;
137 }
138
139 pub fn set_remote(&mut self, transport: Arc<dyn RemoteTransport>) {
140 self.remote = Some(transport);
141 }
142
143 pub fn register_agent_type(&mut self, type_id: u16, handler_addr: usize) {
144 self.agent_types.insert(type_id, handler_addr);
145 }
146
147 pub fn peek_stack(&self) -> Option<Value> {
148 self.stack.last().cloned()
149 }
150
151 pub fn get_register(&self, reg: u8) -> Value {
152 if reg < 27 { self.registers[reg as usize].clone() } else { Value::default() }
153 }
154
155 pub fn run(&mut self) -> Result<(), VmError> {
156 loop {
157 if self.pc >= self.code.len() { break; }
158 let opcode = self.code[self.pc];
159 self.pc += 1;
160
161 match opcode {
162 0x01 => { let packed = self.read_u8()?;
164 let trits = unpack_trits(&[packed], 1).map_err(VmError::BetFault)?;
165 self.stack.push(Value::Trit(trits[0]));
166 }
167 0x02 => { let b = self.stack.pop().ok_or(VmError::StackUnderflow)?;
169 let a = self.stack.pop().ok_or(VmError::StackUnderflow)?;
170 match (a.clone(), b.clone()) {
171 (Value::Trit(av), Value::Trit(bv)) => {
172 let (sum, carry) = av + bv;
173 self.stack.push(Value::Trit(sum));
174 self.carry_reg = carry;
175 }
176 (Value::Int(av), Value::Int(bv)) => self.stack.push(Value::Int(av + bv)),
177 (Value::Float(av), Value::Float(bv)) => self.stack.push(Value::Float(av + bv)),
178 (Value::Int(av), Value::Trit(bv)) => self.stack.push(Value::Int(av + bv as i64)),
179 (Value::Trit(av), Value::Int(bv)) => self.stack.push(Value::Int(av as i64 + bv)),
180 (Value::Float(av), Value::Trit(bv)) => self.stack.push(Value::Float(av + (bv as i8 as f64))),
181 (Value::Trit(av), Value::Float(bv)) => self.stack.push(Value::Float((av as i8 as f64) + bv)),
182 (Value::Float(av), Value::Int(bv)) => self.stack.push(Value::Float(av + (bv as f64))),
183 (Value::Int(av), Value::Float(bv)) => self.stack.push(Value::Float((av as f64) + bv)),
184 _ => return Err(VmError::TypeMismatch { expected: "Numeric".into(), found: format!("{:?}", (a, b)) }),
185 }
186 }
187 0x03 => { let b = self.stack.pop().ok_or(VmError::StackUnderflow)?;
189 let a = self.stack.pop().ok_or(VmError::StackUnderflow)?;
190 match (a.clone(), b.clone()) {
191 (Value::Trit(av), Value::Trit(bv)) => self.stack.push(Value::Trit(av * bv)),
192 (Value::Int(av), Value::Int(bv)) => self.stack.push(Value::Int(av * bv)),
193 (Value::Float(av), Value::Float(bv)) => self.stack.push(Value::Float(av * bv)),
194 (Value::Int(av), Value::Trit(bv)) => self.stack.push(Value::Int(av * bv as i64)),
195 (Value::Trit(av), Value::Int(bv)) => self.stack.push(Value::Int(av as i64 * bv)),
196 (Value::Float(av), Value::Trit(bv)) => self.stack.push(Value::Float(av * (bv as i8 as f64))),
197 (Value::Trit(av), Value::Float(bv)) => self.stack.push(Value::Float((av as i8 as f64) * bv)),
198 (Value::Float(av), Value::Int(bv)) => self.stack.push(Value::Float(av * (bv as f64))),
199 (Value::Int(av), Value::Float(bv)) => self.stack.push(Value::Float((av as f64) * bv)),
200 _ => return Err(VmError::TypeMismatch { expected: "Numeric".into(), found: format!("{:?}", (a, b)) }),
201 }
202 }
203 0x04 => { let a = self.stack.pop().ok_or(VmError::StackUnderflow)?;
205 match a.clone() {
206 Value::Trit(av) => self.stack.push(Value::Trit(-av)),
207 Value::Int(av) => self.stack.push(Value::Int(-av)),
208 Value::Float(av) => self.stack.push(Value::Float(-av)),
209 _ => return Err(VmError::TypeMismatch { expected: "Numeric".into(), found: format!("{:?}", a) }),
210 }
211 }
212 0x05 => { let addr = self.read_u16()?;
214 let val = self.stack.last().ok_or(VmError::StackUnderflow)?;
215 let is_pos = match val {
216 Value::Trit(Trit::Affirm) => true,
217 Value::Int(1) => true,
218 _ => false,
219 };
220 if is_pos { self.pc = addr as usize; }
221 }
222 0x06 => { let addr = self.read_u16()?;
224 let val = self.stack.last().ok_or(VmError::StackUnderflow)?;
225 let is_zero = match val {
226 Value::Trit(Trit::Tend) => true,
227 Value::Int(0) => true,
228 _ => false,
229 };
230 if is_zero { self.pc = addr as usize; }
231 }
232 0x07 => { let addr = self.read_u16()?;
234 let val = self.stack.last().ok_or(VmError::StackUnderflow)?;
235 let is_neg = match val {
236 Value::Trit(Trit::Reject) => true,
237 Value::Int(-1) => true,
238 _ => false,
239 };
240 if is_neg { self.pc = addr as usize; }
241 }
242 0x08 => { let reg = self.read_u8()?;
244 let val = self.stack.pop().ok_or(VmError::StackUnderflow)?;
245 if reg < 27 { self.registers[reg as usize] = val; }
246 }
247 0x09 => { let reg = self.read_u8()?;
249 if reg < 27 { self.stack.push(self.registers[reg as usize].clone()); }
250 else { self.stack.push(Value::default()); }
251 }
252 0x0a => { let val = self.stack.last().ok_or(VmError::StackUnderflow)?;
254 self.stack.push(val.clone());
255 }
256 0x0b => { let addr = self.read_u16()?;
258 self.pc = addr as usize;
259 }
260 0x0c => { self.stack.pop().ok_or(VmError::StackUnderflow)?;
262 }
263 0x0e => { let b_val = self.stack.pop().ok_or(VmError::StackUnderflow)?;
265 let a_val = self.stack.pop().ok_or(VmError::StackUnderflow)?;
266
267 let a = match a_val {
268 Value::Trit(t) => t,
269 Value::Int(v) if v == 1 => Trit::Affirm,
270 Value::Int(v) if v == 0 => Trit::Tend,
271 Value::Int(v) if v == -1 => Trit::Reject,
272 _ => return Err(VmError::TypeMismatch { expected: "Trit or Int(-1..1)".into(), found: format!("{:?}", a_val) }),
273 };
274 let b = match b_val {
275 Value::Trit(t) => t,
276 Value::Int(v) if v == 1 => Trit::Affirm,
277 Value::Int(v) if v == 0 => Trit::Tend,
278 Value::Int(v) if v == -1 => Trit::Reject,
279 _ => return Err(VmError::TypeMismatch { expected: "Trit or Int(-1..1)".into(), found: format!("{:?}", b_val) }),
280 };
281
282 let result = match (a, b) {
283 (Trit::Affirm, Trit::Affirm) => Trit::Affirm,
284 (Trit::Reject, Trit::Reject) => Trit::Reject,
285 (Trit::Tend, x) => x,
286 (x, Trit::Tend) => x,
287 _ => Trit::Tend,
288 };
289 self.stack.push(Value::Trit(result));
290 }
291 0x0f => { let rows = self.read_u16()? as usize;
293 let cols = self.read_u16()? as usize;
294 let size = rows * cols;
295 let idx = self.tensors.len();
296 self.tensors.push(TensorInstance {
297 data: vec![Trit::Tend; size],
298 rows,
299 cols,
300 });
301 self.stack.push(Value::TensorRef(idx));
302 }
303 0x10 => { let addr = self.read_u16()? as usize;
305 self.register_stack.push(self.registers.clone());
306 self.call_stack.push(self.pc);
307 self.pc = addr;
308 }
309 0x11 => { if let Some(prev) = self.register_stack.pop() {
311 self.registers = prev;
312 }
313 match self.call_stack.pop() {
314 Some(ret) => self.pc = ret,
315 None => return Ok(()),
316 }
317 }
318 0x14 => { let b = self.stack.pop().ok_or(VmError::StackUnderflow)?;
320 let a = self.stack.pop().ok_or(VmError::StackUnderflow)?;
321 match (a.clone(), b.clone()) {
322 (Value::Int(x), Value::Int(y)) => {
323 let r = if x < y { Trit::Affirm } else if x == y { Trit::Tend } else { Trit::Reject };
324 self.stack.push(Value::Trit(r));
325 }
326 (Value::Float(x), Value::Float(y)) => {
327 let r = if x < y { Trit::Affirm } else if (x - y).abs() < f64::EPSILON { Trit::Tend } else { Trit::Reject };
328 self.stack.push(Value::Trit(r));
329 }
330 (Value::Int(x), Value::Trit(y)) => {
331 let bv = y as i64;
332 let r = if x < bv { Trit::Affirm } else if x == bv { Trit::Tend } else { Trit::Reject };
333 self.stack.push(Value::Trit(r));
334 }
335 (Value::Trit(x), Value::Int(y)) => {
336 let av = x as i64;
337 let r = if av < y { Trit::Affirm } else if av == y { Trit::Tend } else { Trit::Reject };
338 self.stack.push(Value::Trit(r));
339 }
340 (Value::Int(av), Value::Float(bv)) => {
341 let a_val = av as f64;
342 let r = if a_val < bv { Trit::Affirm } else if (a_val - bv).abs() < f64::EPSILON { Trit::Tend } else { Trit::Reject };
343 self.stack.push(Value::Trit(r));
344 }
345 (Value::Float(av), Value::Int(bv)) => {
346 let b_val = bv as f64;
347 let r = if av < b_val { Trit::Affirm } else if (av - b_val).abs() < f64::EPSILON { Trit::Tend } else { Trit::Reject };
348 self.stack.push(Value::Trit(r));
349 }
350 (Value::Trit(av), Value::Float(bv)) => {
351 let a_val = av as i8 as f64;
352 let r = if a_val < bv { Trit::Affirm } else if (a_val - bv).abs() < f64::EPSILON { Trit::Tend } else { Trit::Reject };
353 self.stack.push(Value::Trit(r));
354 }
355 (Value::Float(av), Value::Trit(bv)) => {
356 let b_val = bv as i8 as f64;
357 let r = if av < b_val { Trit::Affirm } else if (av - b_val).abs() < f64::EPSILON { Trit::Tend } else { Trit::Reject };
358 self.stack.push(Value::Trit(r));
359 }
360 (Value::Trit(x), Value::Trit(y)) => {
361 let av = x as i64;
362 let bv = y as i64;
363 let r = if av < bv { Trit::Affirm } else if av == bv { Trit::Tend } else { Trit::Reject };
364 self.stack.push(Value::Trit(r));
365 }
366 _ => return Err(VmError::TypeMismatch { expected: "Numeric".into(), found: format!("{:?}", (a, b)) }),
367 }
368 }
369 0x15 => { let b = self.stack.pop().ok_or(VmError::StackUnderflow)?;
371 let a = self.stack.pop().ok_or(VmError::StackUnderflow)?;
372 match (a.clone(), b.clone()) {
373 (Value::Int(x), Value::Int(y)) => {
374 let r = if x > y { Trit::Affirm } else if x == y { Trit::Tend } else { Trit::Reject };
375 self.stack.push(Value::Trit(r));
376 }
377 (Value::Float(x), Value::Float(y)) => {
378 let r = if x > y { Trit::Affirm } else if (x - y).abs() < f64::EPSILON { Trit::Tend } else { Trit::Reject };
379 self.stack.push(Value::Trit(r));
380 }
381 (Value::Int(x), Value::Trit(y)) => {
382 let bv = y as i64;
383 let r = if x > bv { Trit::Affirm } else if x == bv { Trit::Tend } else { Trit::Reject };
384 self.stack.push(Value::Trit(r));
385 }
386 (Value::Trit(x), Value::Int(y)) => {
387 let av = x as i64;
388 let r = if av > y { Trit::Affirm } else if av == y { Trit::Tend } else { Trit::Reject };
389 self.stack.push(Value::Trit(r));
390 }
391 (Value::Int(av), Value::Float(bv)) => {
392 let a_val = av as f64;
393 let r = if a_val > bv { Trit::Affirm } else if (a_val - bv).abs() < f64::EPSILON { Trit::Tend } else { Trit::Reject };
394 self.stack.push(Value::Trit(r));
395 }
396 (Value::Float(av), Value::Int(bv)) => {
397 let b_val = bv as f64;
398 let r = if av > b_val { Trit::Affirm } else if (av - b_val).abs() < f64::EPSILON { Trit::Tend } else { Trit::Reject };
399 self.stack.push(Value::Trit(r));
400 }
401 (Value::Trit(av), Value::Float(bv)) => {
402 let a_val = av as i8 as f64;
403 let r = if a_val > bv { Trit::Affirm } else if (a_val - bv).abs() < f64::EPSILON { Trit::Tend } else { Trit::Reject };
404 self.stack.push(Value::Trit(r));
405 }
406 (Value::Float(av), Value::Trit(bv)) => {
407 let b_val = bv as i8 as f64;
408 let r = if av > b_val { Trit::Affirm } else if (av - b_val).abs() < f64::EPSILON { Trit::Tend } else { Trit::Reject };
409 self.stack.push(Value::Trit(r));
410 }
411 (Value::Trit(x), Value::Trit(y)) => {
412 let av = x as i64;
413 let bv = y as i64;
414 let r = if av > bv { Trit::Affirm } else if av == bv { Trit::Tend } else { Trit::Reject };
415 self.stack.push(Value::Trit(r));
416 }
417 _ => return Err(VmError::TypeMismatch { expected: "Numeric".into(), found: format!("{:?}", (a, b)) }),
418 }
419 }
420 0x16 => { let b = self.stack.pop().ok_or(VmError::StackUnderflow)?;
422 let a = self.stack.pop().ok_or(VmError::StackUnderflow)?;
423 let is_eq = match (a.clone(), b.clone()) {
424 (Value::Int(av), Value::Trit(bv)) => av == bv as i64,
425 (Value::Trit(av), Value::Int(bv)) => av as i64 == bv,
426 (Value::Float(av), Value::Float(bv)) => (av - bv).abs() < f64::EPSILON,
427 (Value::Float(av), Value::Trit(bv)) => (av - (bv as i8 as f64)).abs() < f64::EPSILON,
428 (Value::Trit(av), Value::Float(bv)) => ((av as i8 as f64) - bv).abs() < f64::EPSILON,
429 (Value::Float(av), Value::Int(bv)) => (av - (bv as f64)).abs() < f64::EPSILON,
430 (Value::Int(av), Value::Float(bv)) => ((av as f64) - bv).abs() < f64::EPSILON,
431 _ => a == b,
432 };
433 let r = if is_eq { Trit::Affirm } else { Trit::Reject };
434 self.stack.push(Value::Trit(r));
435 }
436 0x17 => { let mut b = [0u8; 8];
438 for i in 0..8 { b[i] = self.read_u8()?; }
439 self.stack.push(Value::Int(i64::from_le_bytes(b)));
440 }
441 0x18 => { let b = self.stack.pop().ok_or(VmError::StackUnderflow)?;
443 let a = self.stack.pop().ok_or(VmError::StackUnderflow)?;
444 match (a.clone(), b.clone()) {
445 (Value::Int(x), Value::Int(y)) => self.stack.push(Value::Int(x + y)),
446 _ => return Err(VmError::TypeMismatch { expected: "Int".into(), found: format!("{:?}", (a, b)) }),
447 }
448 }
449 0x19 => { let mut b = [0u8; 8];
451 for i in 0..8 { b[i] = self.read_u8()?; }
452 self.stack.push(Value::Float(f64::from_le_bytes(b)));
453 }
454 0x1e => { let b_val = self.stack.pop().ok_or(VmError::StackUnderflow)?;
456 let a_val = self.stack.pop().ok_or(VmError::StackUnderflow)?;
457 match (a_val.clone(), b_val.clone()) {
458 (Value::Int(av), Value::Int(bv)) => {
459 if bv == 0 { return Err(VmError::RuntimeError("Division by zero".into())); }
460 self.stack.push(Value::Int(av / bv));
461 }
462 (Value::Float(av), Value::Float(bv)) => {
463 if bv == 0.0 { return Err(VmError::RuntimeError("Division by zero".into())); }
464 self.stack.push(Value::Float(av / bv));
465 }
466 (Value::Int(av), Value::Trit(bv)) => {
467 let b = bv as i64;
468 if b == 0 { return Err(VmError::RuntimeError("Division by zero".into())); }
469 self.stack.push(Value::Int(av / b));
470 }
471 (Value::Trit(av), Value::Int(bv)) => {
472 if bv == 0 { return Err(VmError::RuntimeError("Division by zero".into())); }
473 self.stack.push(Value::Int(av as i64 / bv));
474 }
475 (Value::Float(av), Value::Trit(bv)) => {
476 let b = bv as i8 as f64;
477 if b == 0.0 { return Err(VmError::RuntimeError("Division by zero".into())); }
478 self.stack.push(Value::Float(av / b));
479 }
480 (Value::Trit(av), Value::Float(bv)) => {
481 if bv == 0.0 { return Err(VmError::RuntimeError("Division by zero".into())); }
482 self.stack.push(Value::Float(av as i8 as f64 / bv));
483 }
484 (Value::Float(av), Value::Int(bv)) => {
485 let b = bv as f64;
486 if b == 0.0 { return Err(VmError::RuntimeError("Division by zero".into())); }
487 self.stack.push(Value::Float(av / b));
488 }
489 (Value::Int(av), Value::Float(bv)) => {
490 if bv == 0.0 { return Err(VmError::RuntimeError("Division by zero".into())); }
491 self.stack.push(Value::Float(av as f64 / bv));
492 }
493 _ => return Err(VmError::TypeMismatch { expected: "Numeric".into(), found: format!("{:?}", (a_val, b_val)) }),
494 }
495 }
496 0x1f => { let b_val = self.stack.pop().ok_or(VmError::StackUnderflow)?;
498 let a_val = self.stack.pop().ok_or(VmError::StackUnderflow)?;
499 match (a_val.clone(), b_val.clone()) {
500 (Value::Int(av), Value::Int(bv)) => {
501 if bv == 0 { return Err(VmError::RuntimeError("Modulo by zero".into())); }
502 self.stack.push(Value::Int(av % bv));
503 }
504 (Value::Int(av), Value::Trit(bv)) => {
505 let b = bv as i64;
506 if b == 0 { return Err(VmError::RuntimeError("Modulo by zero".into())); }
507 self.stack.push(Value::Int(av % b));
508 }
509 (Value::Trit(av), Value::Int(bv)) => {
510 if bv == 0 { return Err(VmError::RuntimeError("Modulo by zero".into())); }
511 self.stack.push(Value::Int(av as i64 % bv));
512 }
513 (Value::Float(av), Value::Float(bv)) => {
514 if bv == 0.0 { return Err(VmError::RuntimeError("Modulo by zero".into())); }
515 self.stack.push(Value::Float(av % bv));
516 }
517 (Value::Float(av), Value::Trit(bv)) => {
518 let b = bv as i8 as f64;
519 if b == 0.0 { return Err(VmError::RuntimeError("Modulo by zero".into())); }
520 self.stack.push(Value::Float(av % b));
521 }
522 (Value::Trit(av), Value::Float(bv)) => {
523 if bv == 0.0 { return Err(VmError::RuntimeError("Modulo by zero".into())); }
524 self.stack.push(Value::Float(av as i8 as f64 % bv));
525 }
526 (Value::Float(av), Value::Int(bv)) => {
527 let b = bv as f64;
528 if b == 0.0 { return Err(VmError::RuntimeError("Modulo by zero".into())); }
529 self.stack.push(Value::Float(av % b));
530 }
531 (Value::Int(av), Value::Float(bv)) => {
532 if bv == 0.0 { return Err(VmError::RuntimeError("Modulo by zero".into())); }
533 self.stack.push(Value::Float(av as f64 % bv));
534 }
535 _ => return Err(VmError::TypeMismatch { expected: "Int or Trit".into(), found: format!("{:?}", (a_val, b_val)) }),
536 }
537 }
538 0x20 => { let val = self.stack.pop().ok_or(VmError::StackUnderflow)?;
540 let line = match &val {
541 Value::Trit(t) => format!("{:?}", t),
542 Value::Int(i) => format!("{}", i),
543 Value::Float(f) => format!("{}", f),
544 Value::String(s) => s.clone(),
545 Value::TensorRef(idx) => format!("TensorRef({})", idx),
546 Value::AgentRef(idx, addr) => format!("AgentRef({}, {:?})", idx, addr),
547 };
548 println!("{}", line);
549 self.print_log.push(line);
550 }
551 0x21 => { let len = self.read_u16()? as usize;
553 let mut bytes = vec![0u8; len];
554 for i in 0..len { bytes[i] = self.read_u8()?; }
555 let s = String::from_utf8(bytes).map_err(|_| VmError::RuntimeError("Invalid UTF-8 string".into()))?;
556 self.stack.push(Value::String(s));
557 }
558 0x22 => { let col = self.stack.pop().ok_or(VmError::StackUnderflow)?;
560 let row = self.stack.pop().ok_or(VmError::StackUnderflow)?;
561 let rf = self.stack.pop().ok_or(VmError::StackUnderflow)?;
562 let r = match row { Value::Int(v) => v, Value::Trit(t) => t as i64, _ => return Err(VmError::TypeMismatch { expected: "Int or Trit".into(), found: format!("{:?}", row) }) };
563 let c = match col { Value::Int(v) => v, Value::Trit(t) => t as i64, _ => return Err(VmError::TypeMismatch { expected: "Int or Trit".into(), found: format!("{:?}", col) }) };
564 match rf {
565 Value::TensorRef(idx) => {
566 if idx >= self.tensors.len() {
567 return Err(VmError::TensorNotAllocated(idx));
568 }
569 let tensor = &self.tensors[idx];
570 let pos = if tensor.cols > 1 { r as usize * tensor.cols + c as usize } else { r as usize };
571 if pos >= tensor.data.len() {
572 return Err(VmError::TensorIndexOutOfBounds { tensor_id: idx, index: pos, size: tensor.data.len() });
573 }
574 self.stack.push(Value::Trit(tensor.data[pos]));
575 }
576 _ => return Err(VmError::TypeMismatch { expected: "TensorRef".into(), found: format!("{:?}", rf) }),
577 }
578 }
579 0x23 => { let val = self.stack.pop().ok_or(VmError::StackUnderflow)?;
581 let col = self.stack.pop().ok_or(VmError::StackUnderflow)?;
582 let row = self.stack.pop().ok_or(VmError::StackUnderflow)?;
583 let rf = self.stack.pop().ok_or(VmError::StackUnderflow)?;
584 let r = match row { Value::Int(v) => v, Value::Trit(t) => t as i64, _ => return Err(VmError::TypeMismatch { expected: "Int or Trit".into(), found: format!("{:?}", row) }) };
585 let c = match col { Value::Int(v) => v, Value::Trit(t) => t as i64, _ => return Err(VmError::TypeMismatch { expected: "Int or Trit".into(), found: format!("{:?}", col) }) };
586 match (rf.clone(), val.clone()) {
587 (Value::TensorRef(idx), Value::Trit(t)) => {
588 if idx >= self.tensors.len() { return Err(VmError::TensorNotAllocated(idx)); }
589 let tensor = &mut self.tensors[idx];
590 let pos = if tensor.cols > 1 { r as usize * tensor.cols + c as usize } else { r as usize };
591 if pos >= tensor.data.len() { return Err(VmError::TensorIndexOutOfBounds { tensor_id: idx, index: pos, size: tensor.data.len() }); }
592 tensor.data[pos] = t;
593 }
594 (Value::TensorRef(idx), Value::Int(v)) => {
595 if idx >= self.tensors.len() { return Err(VmError::TensorNotAllocated(idx)); }
596 let tensor = &mut self.tensors[idx];
597 let pos = if tensor.cols > 1 { r as usize * tensor.cols + c as usize } else { r as usize };
598 if pos >= tensor.data.len() { return Err(VmError::TensorIndexOutOfBounds { tensor_id: idx, index: pos, size: tensor.data.len() }); }
599 tensor.data[pos] = Trit::from(v as i8);
600 }
601 _ => return Err(VmError::TypeMismatch { expected: "TensorRef, Trit".into(), found: format!("{:?}", (rf, val)) }),
602 }
603 }
604 0x24 => { let rf = self.stack.pop().ok_or(VmError::StackUnderflow)?;
606 if let Value::TensorRef(idx) = rf {
607 if idx >= self.tensors.len() {
608 return Err(VmError::TensorNotAllocated(idx));
609 }
610 let tensor = &self.tensors[idx];
611 self.stack.push(Value::Int(tensor.rows as i64));
612 self.stack.push(Value::Int(tensor.cols as i64));
613 } else { return Err(VmError::TypeMismatch { expected: "TensorRef".into(), found: format!("{:?}", rf) }); }
614 }
615 0x30 => { let type_id = self.read_u16()?;
617 if let Some(&handler_addr) = self.agent_types.get(&type_id) {
618 let id = self.agents.len();
619 self.agents.push(AgentInstance { handler_addr, mailbox: Default::default() });
620 self.stack.push(Value::AgentRef(id, None));
621 } else {
622 return Err(VmError::AgentTypeNotRegistered(type_id));
623 }
624 }
625 0x31 => { let msg = self.stack.pop().ok_or(VmError::StackUnderflow)?;
627 let target = self.stack.pop().ok_or(VmError::StackUnderflow)?;
628 if let Value::AgentRef(id, None) = target {
629 if id < self.agents.len() {
630 self.agents[id].mailbox.push_back(msg);
631 } else {
632 return Err(VmError::AgentIdInvalid(id));
633 }
634 } else {
635 return Err(VmError::TypeMismatch { expected: "Local AgentRef".into(), found: format!("{:?}", target) });
636 }
637 }
638 0x32 => { let target = self.stack.pop().ok_or(VmError::StackUnderflow)?;
640 if let Value::AgentRef(id, None) = target {
641 if id < self.agents.len() {
642 let handler_addr = self.agents[id].handler_addr;
643 let msg = self.agents[id].mailbox.pop_front().unwrap_or(Value::default());
644 self.register_stack.push(self.registers.clone());
646 self.call_stack.push(self.pc);
647 self.pc = handler_addr;
648 self.stack.push(msg);
649 } else {
650 return Err(VmError::AgentIdInvalid(id));
651 }
652 } else {
653 return Err(VmError::TypeMismatch { expected: "Local AgentRef".into(), found: format!("{:?}", target) });
654 }
655 }
656 0x25 => { let mut b = [0u8; 8];
658 for i in 0..8 { b[i] = self.read_u8()?; }
659 let target_val = i64::from_le_bytes(b);
660 let addr = self.read_u16()?;
661 let val = self.stack.last().ok_or(VmError::StackUnderflow)?;
662 let is_eq = match val {
663 Value::Int(v) => *v == target_val,
664 Value::Trit(t) => (*t as i8) as i64 == target_val,
665 _ => false,
666 };
667 if is_eq { self.pc = addr as usize; }
668 }
669 0x26 => { let b = self.stack.pop().ok_or(VmError::StackUnderflow)?;
671 let a = self.stack.pop().ok_or(VmError::StackUnderflow)?;
672 let is_le = match (a.clone(), b.clone()) {
673 (Value::Int(x), Value::Int(y)) => x <= y,
674 (Value::Float(x), Value::Float(y)) => x <= y || (x - y).abs() < f64::EPSILON,
675 (Value::Int(x), Value::Trit(y)) => x <= y as i64,
676 (Value::Trit(x), Value::Int(y)) => (x as i64) <= y,
677 (Value::Trit(x), Value::Trit(y)) => (x as i64) <= (y as i64),
678 _ => false,
679 };
680 self.stack.push(Value::Trit(if is_le { Trit::Affirm } else { Trit::Reject }));
681 }
682 0x27 => { let b = self.stack.pop().ok_or(VmError::StackUnderflow)?;
684 let a = self.stack.pop().ok_or(VmError::StackUnderflow)?;
685 let is_ge = match (a.clone(), b.clone()) {
686 (Value::Int(x), Value::Int(y)) => x >= y,
687 (Value::Float(x), Value::Float(y)) => x >= y || (x - y).abs() < f64::EPSILON,
688 (Value::Int(x), Value::Trit(y)) => x >= y as i64,
689 (Value::Trit(x), Value::Int(y)) => (x as i64) >= y,
690 (Value::Trit(x), Value::Trit(y)) => (x as i64) >= (y as i64),
691 _ => false,
692 };
693 self.stack.push(Value::Trit(if is_ge { Trit::Affirm } else { Trit::Reject }));
694 }
695 0x28 => { let b = self.stack.pop().ok_or(VmError::StackUnderflow)?;
697 let a = self.stack.pop().ok_or(VmError::StackUnderflow)?;
698 let to_trit = |v: Value| -> Result<Trit, VmError> {
699 match v {
700 Value::Trit(t) => Ok(t),
701 Value::Int(n) if n > 0 => Ok(Trit::Affirm),
702 Value::Int(0) => Ok(Trit::Tend),
703 Value::Int(_) => Ok(Trit::Reject),
704 other => Err(VmError::TypeMismatch { expected: "Trit or Int".into(), found: format!("{:?}", other) }),
705 }
706 };
707 let ta = to_trit(a)?;
708 let tb = to_trit(b)?;
709 let result = if (ta as i8) <= (tb as i8) { ta } else { tb };
710 self.stack.push(Value::Trit(result));
711 }
712 0x29 => { let b = self.stack.pop().ok_or(VmError::StackUnderflow)?;
714 let a = self.stack.pop().ok_or(VmError::StackUnderflow)?;
715 let to_trit = |v: Value| -> Result<Trit, VmError> {
716 match v {
717 Value::Trit(t) => Ok(t),
718 Value::Int(n) if n > 0 => Ok(Trit::Affirm),
719 Value::Int(0) => Ok(Trit::Tend),
720 Value::Int(_) => Ok(Trit::Reject),
721 other => Err(VmError::TypeMismatch { expected: "Trit or Int".into(), found: format!("{:?}", other) }),
722 }
723 };
724 let ta = to_trit(a)?;
725 let tb = to_trit(b)?;
726 let result = if (ta as i8) >= (tb as i8) { ta } else { tb };
727 self.stack.push(Value::Trit(result));
728 }
729 0x00 => return Ok(()),
730 _ => return Err(VmError::InvalidOpcode(opcode)),
731 }
732 }
733 Ok(())
734 }
735
736 fn read_u8(&mut self) -> Result<u8, VmError> {
737 if self.pc >= self.code.len() { return Err(VmError::PcOutOfBounds(self.pc)); }
738 let val = self.code[self.pc];
739 self.pc += 1;
740 Ok(val)
741 }
742
743 fn read_u16(&mut self) -> Result<u16, VmError> {
744 if self.pc + 1 >= self.code.len() { return Err(VmError::PcOutOfBounds(self.pc)); }
745 let val = u16::from_le_bytes([self.code[self.pc], self.code[self.pc + 1]]);
746 self.pc += 2;
747 Ok(val)
748 }
749}