Skip to content

Commit 96ca604

Browse files
refactor(vm): unify iterable extractors into single extract_iter helper.
1 parent f13d136 commit 96ca604

1 file changed

Lines changed: 17 additions & 38 deletions

File tree

compiler/src/modules/vm/builtins.rs

Lines changed: 17 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ impl<'a> VM<'a> {
230230
let args = self.pop_n(op as usize)?;
231231
if args.is_empty() { return Err(cold_type("sum() requires at least 1 argument")); }
232232
let start = if args.len() > 1 { args[1] } else { Val::int(0) };
233-
let items = self.extract_iterable(args[0])?;
233+
let items = self.extract_iter(args[0], false)?;
234234
let mut acc = start;
235235
for item in items { acc = self.add_vals(acc, item)?; }
236236
self.push(acc); Ok(())
@@ -240,7 +240,7 @@ impl<'a> VM<'a> {
240240

241241
pub fn call_sorted(&mut self) -> Result<(), VmErr> {
242242
let o = self.pop()?;
243-
let mut items = self.extract_iterable(o)?;
243+
let mut items = self.extract_iter(o, false)?;
244244
let mut sort_err: Option<VmErr> = None;
245245
items.sort_by(|&a, &b| {
246246
if sort_err.is_some() { return core::cmp::Ordering::Equal; }
@@ -271,7 +271,7 @@ impl<'a> VM<'a> {
271271
self.push(val);
272272
return Ok(());
273273
}
274-
let items = self.extract_iterable_full(o)?;
274+
let items = self.extract_iter(o, true)?;
275275
let val = self.heap.alloc(HeapObj::List(Rc::new(RefCell::new(items))))?;
276276
self.push(val); Ok(())
277277
}
@@ -291,7 +291,7 @@ impl<'a> VM<'a> {
291291

292292
pub fn call_enumerate(&mut self) -> Result<(), VmErr> {
293293
let o = self.pop()?;
294-
let src = self.extract_iterable(o)?;
294+
let src = self.extract_iter(o, false)?;
295295
let mut pairs: Vec<Val> = Vec::with_capacity(src.len());
296296
for (i, x) in src.into_iter().enumerate() {
297297
let t = self.heap.alloc(HeapObj::Tuple(vec![Val::int(i as i64), x]))?;
@@ -308,7 +308,7 @@ impl<'a> VM<'a> {
308308
let mut vals = Vec::with_capacity(op as usize);
309309
for _ in 0..op { vals.push(self.pop()?); }
310310
vals.reverse();
311-
for v in vals { iters.push(self.extract_iterable(v)?); }
311+
for v in vals { iters.push(self.extract_iter(v, false)?); }
312312
let len = iters.iter().map(|v| v.len()).min().unwrap_or(0);
313313
let mut pairs: Vec<Val> = Vec::with_capacity(len);
314314
for i in 0..len {
@@ -370,50 +370,29 @@ impl<'a> VM<'a> {
370370
match self.heap.get(args[0]) {
371371
HeapObj::List(v) => return Ok(v.borrow().clone()),
372372
HeapObj::Tuple(v) => return Ok(v.clone()),
373-
HeapObj::Set(v) => return Ok(v.borrow().iter().cloned().collect::<Vec<Val>>()),
373+
HeapObj::Set(v) => return Ok(v.borrow().iter().cloned().collect()),
374374
_ => {}
375375
}
376376
}
377377
Ok(args)
378378
}
379379

380-
/* Extracts Vec<Val> from list, tuple, or set heap objects. */
381-
382-
fn extract_iterable(&self, o: Val) -> Result<Vec<Val>, VmErr> {
380+
/// Extracts Vec<Val> from list/tuple/set; optionally materializes Range.
381+
/// Str is handled at callsite (it needs heap-allocated chars, not ints).
382+
fn extract_iter(&self, o: Val, include_range: bool) -> Result<Vec<Val>, VmErr> {
383383
if !o.is_heap() { return Err(cold_type("object is not iterable")); }
384384
Ok(match self.heap.get(o) {
385-
HeapObj::List(v) => v.borrow().clone(),
386-
HeapObj::Tuple(v) => v.clone(),
387-
HeapObj::Set(v) => v.borrow().iter().cloned().collect::<Vec<Val>>(),
388-
_ => return Err(cold_type("object is not iterable")),
389-
})
390-
}
391-
392-
/* Like extract_iterable but also materializes Range objects. */
393-
394-
fn extract_iterable_full(&self, o: Val) -> Result<Vec<Val>, VmErr> {
395-
if !o.is_heap() { return Err(VmErr::Type("list() argument must be iterable")); }
396-
Ok(match self.heap.get(o) {
397-
HeapObj::List(v) => v.borrow().clone(),
385+
HeapObj::List(v) => v.borrow().clone(),
398386
HeapObj::Tuple(v) => v.clone(),
399-
HeapObj::Set(v) => v.borrow().iter().cloned().collect::<Vec<Val>>(),
400-
HeapObj::Range(s, e, st) => {
387+
HeapObj::Set(v) => v.borrow().iter().cloned().collect(),
388+
HeapObj::Range(s, e, st) if include_range => {
401389
let (mut cur, end, step) = (*s, *e, *st);
402-
let mut v = Vec::new();
403-
if step > 0 { while cur < end { v.push(Val::int(cur)); cur += step; } }
404-
else { while cur > end { v.push(Val::int(cur)); cur += step; } }
405-
v
390+
let mut out = Vec::new();
391+
if step > 0 { while cur < end { out.push(Val::int(cur)); cur += step; } }
392+
else { while cur > end { out.push(Val::int(cur)); cur += step; } }
393+
out
406394
}
407-
HeapObj::Str(s) => {
408-
let s = s.clone();
409-
drop(s);
410-
let s = match self.heap.get(o) { HeapObj::Str(s) => s.clone(), _ => unreachable!() };
411-
s.chars().map(|c| {
412-
// Can't alloc here (caller must handle).
413-
Val::int(c as i64)
414-
}).collect()
415-
}
416-
_ => return Err(VmErr::Type("list() argument must be iterable")),
395+
_ => return Err(cold_type("object is not iterable")),
417396
})
418397
}
419398

0 commit comments

Comments
 (0)