MCPcopy Create free account
hub / github.com/dylan-sutton-chavez/edge-python / extract_iter

Method extract_iter

compiler/src/modules/vm/builtins/sequence.rs:309–355  ·  view source on GitHub ↗

Vec from any iterable (dict yields keys, str yields one-char strs, bytes yields ints). `include_range = false` lets callers reject Range. */

(&mut self, o: Val, include_range: bool)

Source from the content-addressed store, hash-verified

307
308 /* Vec<Val> from any iterable (dict yields keys, str yields one-char strs, bytes yields ints). `include_range = false` lets callers reject Range. */
309 pub(in crate::modules::vm) fn extract_iter(&mut self, o: Val, include_range: bool) -> Result<Vec<Val>, VmErr> {
310 if !o.is_heap() {
311 return Err(self.not_iterable(o));
312 }
313 // Snapshot the variant out so the &self borrow ends before any allocation.
314 let snapshot = match self.heap.get(o) {
315 HeapObj::List(v) => Some(v.borrow().clone()),
316 HeapObj::Tuple(v) => Some(v.clone()),
317 HeapObj::Set(v) => Some(v.borrow().iter().cloned().collect()),
318 HeapObj::FrozenSet(v) => Some(v.iter().cloned().collect()),
319 HeapObj::Range(s, e, st) if include_range => {
320 let (mut cur, end, step) = (*s, *e, *st);
321 // Materialised length is user-controlled; cap it against the heap budget.
322 let span = (end as i128 - cur as i128).unsigned_abs();
323 let count = if step == 0 { 0 } else { span / (step as i128).unsigned_abs() };
324 if count > self.heap.limit() as u128 { return Err(cold_heap()); }
325 let mut out = Vec::new();
326 if step > 0 {
327 while cur < end {
328 out.push(range_int(&mut self.heap, cur)?);
329 match cur.checked_add(step) { Some(n) => cur = n, None => break }
330 }
331 } else {
332 while cur > end {
333 out.push(range_int(&mut self.heap, cur)?);
334 match cur.checked_add(step) { Some(n) => cur = n, None => break }
335 }
336 }
337 Some(out)
338 }
339 HeapObj::Dict(d) => Some(d.borrow().keys().collect()),
340 HeapObj::Bytes(b) => Some(b.iter().map(|&x| Val::int(x as i64)).collect()),
341 HeapObj::Str(_) => None, // handled below, needs heap allocation
342 _ => return Err(self.not_iterable(o)),
343 };
344 if let Some(v) = snapshot {
345 // Cost scales with element count; charge it so repeated materialisation stays bounded.
346 self.charge_steps(v.len())?;
347 return Ok(v);
348 }
349 // Str path materialises one-char heap strings via the existing helper.
350 if let HeapObj::Str(s) = self.heap.get(o) {
351 let s = s.clone();
352 return self.str_to_char_vals(&s);
353 }
354 unreachable!()
355 }
356
357 /* Flatten any iterable to a fresh `Vec<Val>`, shared input path for iter/map/filter so all three accept the same set of sources. */
358 pub(crate) fn iter_to_vec_general(&mut self, o: Val) -> Result<Vec<Val>, VmErr> {

Callers 15

iter_to_vecFunction · 0.80
fromkeysFunction · 0.80
updateFunction · 0.80
extendFunction · 0.80
dict_from_sourceMethod · 0.80
call_setMethod · 0.80
store_item_builtinMethod · 0.80
call_sortedMethod · 0.80
call_sorted_with_keyMethod · 0.80
call_reversedMethod · 0.80
call_enumerateMethod · 0.80
call_zipMethod · 0.80

Calls 14

cold_heapFunction · 0.85
range_intFunction · 0.85
is_heapMethod · 0.80
not_iterableMethod · 0.80
borrowMethod · 0.80
collectMethod · 0.80
limitMethod · 0.80
pushMethod · 0.80
keysMethod · 0.80
charge_stepsMethod · 0.80
str_to_char_valsMethod · 0.80
getMethod · 0.45

Tested by

no test coverage detected