Container constructors: list / tuple / dict / set / slice / string. */
(&mut self, op: OpCode, operand: u16)
| 12 | |
| 13 | /* Container constructors: list / tuple / dict / set / slice / string. */ |
| 14 | pub(crate) fn handle_build(&mut self, op: OpCode, operand: u16) -> Result<(), VmErr> { |
| 15 | match op { |
| 16 | OpCode::BuildList => { |
| 17 | let v = self.pop_n(operand as usize)?; |
| 18 | let val = self.heap.alloc(HeapObj::List(Rc::new(RefCell::new(v))))?; |
| 19 | self.push(val); |
| 20 | } |
| 21 | OpCode::BuildTuple => { |
| 22 | let v = self.pop_n(operand as usize)?; |
| 23 | let val = self.heap.alloc(HeapObj::Tuple(v))?; |
| 24 | self.push(val); |
| 25 | } |
| 26 | OpCode::BuildDict => { |
| 27 | let flat = self.pop_n(operand as usize * 2)?; |
| 28 | for pair in flat.chunks(2) { self.require_hashable(pair[0])?; } |
| 29 | let dm = DictMap::from_pairs(flat.chunks(2).map(|c| (c[0], c[1])).collect(), &self.heap); |
| 30 | let val = self.heap.alloc(HeapObj::Dict(Rc::new(RefCell::new(dm))))?; |
| 31 | self.push(val); |
| 32 | } |
| 33 | OpCode::BuildString => { |
| 34 | let parts = self.pop_n(operand as usize)?; |
| 35 | let s: String = parts.iter().map(|v| self.display(*v)).collect(); |
| 36 | let val = self.heap.alloc(HeapObj::Str(s))?; |
| 37 | self.push(val); |
| 38 | } |
| 39 | OpCode::BuildSet => self.build_set(operand)?, |
| 40 | OpCode::BuildSlice => self.build_slice(operand)?, |
| 41 | _ => return Err(cold_runtime("non-build opcode in handle_build")), |
| 42 | } |
| 43 | Ok(()) |
| 44 | } |
| 45 | |
| 46 | /* Indexed access/store, unpacking, and `{value!s:spec}` formatting. `GetItem`/`StoreItem`/`DelItem` are dispatched directly from the hot loop; the arms below cover legacy callers that may route through here. */ |
| 47 | pub(crate) fn handle_container(&mut self, op: OpCode, operand: u16, chunk: &SSAChunk, slots: &mut [Val]) -> Result<(), VmErr> { |
no test coverage detected