Iter: flatten any iterable into a List for guest GetItem/Len access. */
(recv_h: u32)
| 168 | |
| 169 | /* Iter: flatten any iterable into a List for guest GetItem/Len access. */ |
| 170 | fn dispatch_iter(recv_h: u32) -> Result<Val, VmErr> { |
| 171 | with_recv("edge_op iter: invalid receiver handle", recv_h, |vm, recv| { |
| 172 | let items: Vec<Val> = match vm.heap.get(recv) { |
| 173 | HeapObj::List(rc) => rc.borrow().clone(), |
| 174 | HeapObj::Tuple(t) => t.clone(), |
| 175 | HeapObj::Set(rc) => rc.borrow().iter().copied().collect(), |
| 176 | HeapObj::Dict(rc) => rc.borrow().keys().collect(), |
| 177 | HeapObj::Range(s, e, st) => { |
| 178 | let mut out = Vec::new(); |
| 179 | let (mut cur, end, step) = (*s, *e, *st); |
| 180 | if step > 0 { |
| 181 | while cur < end { out.push(Val::int(cur)); cur += step; } |
| 182 | } else if step < 0 { |
| 183 | while cur > end { out.push(Val::int(cur)); cur += step; } |
| 184 | } |
| 185 | out |
| 186 | } |
| 187 | HeapObj::Str(s) => { |
| 188 | let chars: Vec<String> = s.chars().map(|c| c.to_string()).collect(); |
| 189 | chars.into_iter() |
| 190 | .map(|cs| vm.heap.alloc(HeapObj::Str(cs))) |
| 191 | .collect::<Result<Vec<_>, _>>()? |
| 192 | } |
| 193 | _ => return Err(VmErr::TypeMsg(s!("object of type '", str vm.type_name(recv), "' is not iterable"))), |
| 194 | }; |
| 195 | vm.heap.alloc(HeapObj::List(Rc::new(RefCell::new(items)))) |
| 196 | }) |
| 197 | } |
| 198 | |
| 199 | /* IterNext: pops list head; raises StopIteration when empty. */ |
| 200 | fn dispatch_iter_next(recv_h: u32) -> Result<Val, VmErr> { |