@@ -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