CallExtern: operand packs `(extern_idx<<8)|(kw<<4)|pos`. Pop kw `name,val` pairs then `pos` positional vals, pack pairs into a heap dict via `pack_kw_dict` and hand it off as the explicit `Option ` kwargs slot. Pure externs leave the impurity flag alone, bodies whose only side-effects are pure externs stay memoizable. */
(&mut self, operand: u16, chunk: &SSAChunk)
| 685 | |
| 686 | /* CallExtern: operand packs `(extern_idx<<8)|(kw<<4)|pos`. Pop kw `name,val` pairs then `pos` positional vals, pack pairs into a heap dict via `pack_kw_dict` and hand it off as the explicit `Option<Val>` kwargs slot. Pure externs leave the impurity flag alone, bodies whose only side-effects are pure externs stay memoizable. */ |
| 687 | pub(crate) fn call_extern(&mut self, operand: u16, chunk: &SSAChunk) -> Result<(), VmErr> { |
| 688 | let extern_idx = (operand >> 8) as usize; |
| 689 | let kw = ((operand >> 4) & 0xF) as usize; |
| 690 | let pos = (operand & 0xF) as usize; |
| 691 | let extern_fn = chunk.extern_table.get(extern_idx).ok_or(cold_runtime("CallExtern: extern index out of bounds"))?; |
| 692 | let func = extern_fn.func.clone(); // Arc clone, refcount bump only |
| 693 | let pure = extern_fn.pure; |
| 694 | let kw_flat = if kw > 0 { self.pop_n(kw * 2)? } else { Vec::new() }; |
| 695 | let positional = self.pop_n(pos)?; |
| 696 | let kwargs = Self::pack_kw_dict(&mut self.heap, &kw_flat)?; |
| 697 | if !pure { self.mark_impure(); } |
| 698 | match func(&mut self.heap, &positional, kwargs) { |
| 699 | Ok(result) => { self.push(result); Ok(()) } |
| 700 | Err(VmErr::HostCallDeferred) => { self.park_host_call(); Ok(()) } |
| 701 | Err(e) => Err(e), |
| 702 | } |
| 703 | } |
| 704 | |
| 705 | /* Park a native that deferred to the host: `None` placeholder (overwritten by `set_host_result_by_id`), correlation id, yield. */ |
| 706 | fn park_host_call(&mut self) { |
no test coverage detected