(&mut self, expected: usize)
| 167 | } |
| 168 | |
| 169 | pub(crate) fn exec_unpack_seq(&mut self, expected: usize) -> Result<(), VmErr> { |
| 170 | let obj = self.pop()?; |
| 171 | if !obj.is_heap() { return Err(cold_type("cannot unpack non-sequence")); } |
| 172 | let items: Vec<Val> = match self.heap.get(obj) { |
| 173 | HeapObj::List(v) => v.borrow().clone(), |
| 174 | HeapObj::Tuple(v) => v.clone(), |
| 175 | HeapObj::Set(v) => v.borrow().iter().cloned().collect(), |
| 176 | HeapObj::FrozenSet(v) => v.iter().cloned().collect(), |
| 177 | // Range materialises to its ints, with the same budget cap as `*` spread. |
| 178 | HeapObj::Range(..) => self.iter_to_vec_for_spread(obj)?, |
| 179 | HeapObj::Str(s) => { |
| 180 | let s = s.clone(); |
| 181 | let out = self.str_to_char_vals(&s)?; |
| 182 | if out.len() > expected { |
| 183 | return Err(cold_value("too many values to unpack")); |
| 184 | } else if out.len() < expected { |
| 185 | return Err(cold_value("not enough values to unpack")); |
| 186 | } |
| 187 | out |
| 188 | }, |
| 189 | _ => return Err(cold_type("cannot unpack non-sequence")), |
| 190 | }; |
| 191 | if items.len() > expected { |
| 192 | return Err(cold_value("too many values to unpack")); |
| 193 | } else if items.len() < expected { |
| 194 | return Err(cold_value("not enough values to unpack")); |
| 195 | } |
| 196 | for item in items.into_iter().rev() { self.push(item); } |
| 197 | Ok(()) |
| 198 | } |
| 199 | |
| 200 | /* Pick the first defined Phi source; if both are undef fall back to None. */ |
| 201 | pub(crate) fn exec_phi(op: u16, rip: usize, phi_map: &[usize], slots: &mut [Val], phi_sources: &[(u16, u16)]) { |
no test coverage detected