(&mut self, chunk: &crate::modules::parser::SSAChunk, slots: &mut [Val])
| 237 | } |
| 238 | |
| 239 | pub fn del_item(&mut self, chunk: &crate::modules::parser::SSAChunk, slots: &mut [Val]) -> Result<(), VmErr> { |
| 240 | let idx_val = self.pop()?; |
| 241 | let cont = self.pop()?; |
| 242 | if !cont.is_heap() { return Err(cold_type("object does not support item deletion")); } |
| 243 | // instance `__delitem__(idx)` short-circuits the built-in dispatch. |
| 244 | if self.try_call_dunder(cont, "__delitem__", &[idx_val], chunk, slots)?.is_some() { |
| 245 | return Ok(()); |
| 246 | } |
| 247 | // Slice deletion: `del xs[a:b]`, same step=1 restriction as `store_slice`. Reuses `store_slice` with an empty replacement vec. |
| 248 | if idx_val.is_heap() |
| 249 | && let HeapObj::Slice(start, stop, step) = self.heap.get(idx_val).clone() |
| 250 | { |
| 251 | return self.store_slice(cont, start, stop, step, Vec::new()); |
| 252 | } |
| 253 | match self.heap.get(cont) { |
| 254 | HeapObj::List(v) => { |
| 255 | if !idx_val.is_int() { return Err(cold_type("list indices must be integers")); } |
| 256 | let mut b = v.borrow_mut(); |
| 257 | let ui = normalize_index(idx_val.as_int(), b.len()); |
| 258 | if ui >= b.len() { return Err(cold_index("list index out of range")); } |
| 259 | b.remove(ui); |
| 260 | } |
| 261 | HeapObj::Dict(p) => { |
| 262 | if p.borrow_mut().remove(&idx_val, &self.heap).is_none() { |
| 263 | return Err(cold_key("key not found")); |
| 264 | } |
| 265 | } |
| 266 | HeapObj::Tuple(_) => return Err(cold_type("tuple does not support item deletion")), |
| 267 | _ => return Err(cold_type("object does not support item deletion")), |
| 268 | } |
| 269 | Ok(()) |
| 270 | } |
| 271 | |
| 272 | /* Splice for `xs[a:b] = items` and `del xs[a:b]`. step=1 resizes; step≠1 demands exact-length RHS. Lists only, tuples/strings are immutable. */ |
| 273 | fn store_slice(&mut self, cont: Val,start: Val, stop: Val, step: Val, new_items: Vec<Val>) -> Result<(), VmErr> { |
no test coverage detected