(&mut self, op: u16)
| 81 | } |
| 82 | |
| 83 | pub fn unpack_ex(&mut self, op: u16) -> Result<(), VmErr> { |
| 84 | let obj = self.pop()?; |
| 85 | if !obj.is_heap() { return Err(cold_type("cannot unpack non-iterable")); } |
| 86 | let items: Vec<Val> = match self.heap.get(obj) { |
| 87 | HeapObj::List(v) => v.borrow().clone(), |
| 88 | HeapObj::Tuple(v) => v.clone(), |
| 89 | // Range materialises to its ints, with the same budget cap as `*` spread. |
| 90 | HeapObj::Range(..) => self.iter_to_vec_for_spread(obj)?, |
| 91 | _ => return Err(cold_type("cannot unpack non-iterable")), |
| 92 | }; |
| 93 | let before = (op >> 8) as usize; |
| 94 | let after = (op & 0xFF) as usize; |
| 95 | if items.len() < before + after { |
| 96 | return Err(cold_value("not enough values to unpack")); |
| 97 | } |
| 98 | let mid = items.len() - after; |
| 99 | for &v in items[mid..].iter().rev() { self.push(v); } |
| 100 | let star = self.alloc_list(items[before..mid].to_vec())?; |
| 101 | self.push(star); |
| 102 | for &v in items[..before].iter().rev() { self.push(v); } |
| 103 | Ok(()) |
| 104 | } |
| 105 | |
| 106 | // Operand packs kw<<8 | pos; keep counts distinct. |
| 107 | pub fn call_dict(&mut self, op: u16) -> Result<(), VmErr> { |
no test coverage detected