Depth-tracked `<`; past the cap surface RecursionError instead of overflowing the stack. */
(&self, a: Val, b: Val, depth: usize)
| 354 | |
| 355 | /* Depth-tracked `<`; past the cap surface RecursionError instead of overflowing the stack. */ |
| 356 | fn lt_vals_d(&self, a: Val, b: Val, depth: usize) -> Result<bool, VmErr> { |
| 357 | if depth > CMP_DEPTH_MAX { return Err(cold_depth()); } |
| 358 | let a = if a.is_bool() { Val::int(a.as_bool() as i64) } else { a }; |
| 359 | let b = if b.is_bool() { Val::int(b.as_bool() as i64) } else { b }; |
| 360 | if a.is_int() && b.is_int() { return Ok(a.as_int() < b.as_int()); } |
| 361 | if let Some((af, bf)) = coerce_floats(a, b, &self.heap) { return Ok(af < bf); } |
| 362 | // Wide-int compare in i128; falls through when either side isn't int-like. |
| 363 | if let (Some(ai), Some(bi)) = (as_i128(a, &self.heap), as_i128(b, &self.heap)) { return Ok(ai < bi); } |
| 364 | if a.is_heap() && b.is_heap() { |
| 365 | match (self.heap.get(a), self.heap.get(b)) { |
| 366 | (HeapObj::Str(x), HeapObj::Str(y)) => return Ok(x < y), |
| 367 | (HeapObj::Bytes(x), HeapObj::Bytes(y)) => return Ok(x < y), |
| 368 | // Sequences compare lexicographically; clone to drop the heap borrow before recursing. |
| 369 | (HeapObj::List(x), HeapObj::List(y)) => { |
| 370 | let (x, y) = (x.borrow().clone(), y.borrow().clone()); |
| 371 | return self.seq_lt_d(&x, &y, depth + 1); |
| 372 | } |
| 373 | (HeapObj::Tuple(x), HeapObj::Tuple(y)) => { |
| 374 | let (x, y) = (x.clone(), y.clone()); |
| 375 | return self.seq_lt_d(&x, &y, depth + 1); |
| 376 | } |
| 377 | _ => {} |
| 378 | } |
| 379 | } |
| 380 | Err(VmErr::TypeMsg(s!("'<' not supported between instances of '", str self.type_name(a), "' and '", str self.type_name(b), "'"))) |
| 381 | } |
| 382 | |
| 383 | /* Lexicographic `<` for sequences: first differing element decides; otherwise the shorter is less. Recurses through `lt_vals`, so nested sequences and mixed element types are handled (and rejected) consistently. */ |
| 384 | pub fn seq_lt(&self, xs: &[Val], ys: &[Val]) -> Result<bool, VmErr> { |