@@ -378,6 +378,154 @@ impl<'a> VM<'a> {
378378 self . push ( Val :: int ( n) ) ;
379379 Ok ( ( ) )
380380 }
381+ ListSort => {
382+ if !positional. is_empty ( ) {
383+ return Err ( VmErr :: Type ( "sort() takes no arguments" ) ) ;
384+ }
385+ let items = match self . heap . get ( recv) {
386+ HeapObj :: List ( rc) => rc. borrow ( ) . clone ( ) ,
387+ _ => return Err ( VmErr :: Type ( "sort: receiver is not a list" ) ) ,
388+ } ;
389+ let mut sorted = items;
390+ let mut sort_err: Option < VmErr > = None ;
391+ sorted. sort_by ( |& a, & b| {
392+ if sort_err. is_some ( ) { return core:: cmp:: Ordering :: Equal ; }
393+ match self . lt_vals ( a, b) {
394+ Ok ( true ) => core:: cmp:: Ordering :: Less ,
395+ Ok ( false ) => match self . lt_vals ( b, a) {
396+ Ok ( true ) => core:: cmp:: Ordering :: Greater ,
397+ Ok ( false ) => core:: cmp:: Ordering :: Equal ,
398+ Err ( e) => { sort_err = Some ( e) ; core:: cmp:: Ordering :: Equal }
399+ } ,
400+ Err ( e) => { sort_err = Some ( e) ; core:: cmp:: Ordering :: Equal }
401+ }
402+ } ) ;
403+ if let Some ( e) = sort_err { return Err ( e) ; }
404+ match self . heap . get_mut ( recv) {
405+ HeapObj :: List ( rc) => * rc. borrow_mut ( ) = sorted,
406+ _ => return Err ( VmErr :: Type ( "sort: receiver is not a list" ) ) ,
407+ }
408+ self . mark_impure ( ) ;
409+ self . push ( Val :: none ( ) ) ;
410+ Ok ( ( ) )
411+ }
412+ ListReverse => {
413+ if !positional. is_empty ( ) {
414+ return Err ( VmErr :: Type ( "reverse() takes no arguments" ) ) ;
415+ }
416+ match self . heap . get_mut ( recv) {
417+ HeapObj :: List ( rc) => rc. borrow_mut ( ) . reverse ( ) ,
418+ _ => return Err ( VmErr :: Type ( "reverse: receiver is not a list" ) ) ,
419+ }
420+ self . mark_impure ( ) ;
421+ self . push ( Val :: none ( ) ) ;
422+ Ok ( ( ) )
423+ }
424+ ListPop => {
425+ if positional. len ( ) > 1 {
426+ return Err ( VmErr :: Type ( "pop() takes at most one argument" ) ) ;
427+ }
428+ let popped = match self . heap . get_mut ( recv) {
429+ HeapObj :: List ( rc) => {
430+ let mut b = rc. borrow_mut ( ) ;
431+ if b. is_empty ( ) {
432+ return Err ( VmErr :: Value ( "pop from empty list" ) ) ;
433+ }
434+ if positional. is_empty ( ) {
435+ b. pop ( ) . unwrap ( )
436+ } else {
437+ if !positional[ 0 ] . is_int ( ) {
438+ return Err ( VmErr :: Type ( "list indices must be integers" ) ) ;
439+ }
440+ let i = positional[ 0 ] . as_int ( ) ;
441+ let ui = if i < 0 { ( b. len ( ) as i64 + i) as usize } else { i as usize } ;
442+ if ui >= b. len ( ) {
443+ return Err ( VmErr :: Value ( "pop index out of range" ) ) ;
444+ }
445+ b. remove ( ui)
446+ }
447+ }
448+ _ => return Err ( VmErr :: Type ( "pop: receiver is not a list" ) ) ,
449+ } ;
450+ self . mark_impure ( ) ;
451+ self . push ( popped) ;
452+ Ok ( ( ) )
453+ }
454+ ListInsert => {
455+ if positional. len ( ) != 2 {
456+ return Err ( VmErr :: Type ( "insert() takes exactly 2 arguments" ) ) ;
457+ }
458+ if !positional[ 0 ] . is_int ( ) {
459+ return Err ( VmErr :: Type ( "list indices must be integers" ) ) ;
460+ }
461+ let item = positional[ 1 ] ;
462+ match self . heap . get_mut ( recv) {
463+ HeapObj :: List ( rc) => {
464+ let mut b = rc. borrow_mut ( ) ;
465+ let i = positional[ 0 ] . as_int ( ) ;
466+ let ui = if i < 0 {
467+ ( b. len ( ) as i64 + i) . max ( 0 ) as usize
468+ } else {
469+ ( i as usize ) . min ( b. len ( ) )
470+ } ;
471+ b. insert ( ui, item) ;
472+ }
473+ _ => return Err ( VmErr :: Type ( "insert: receiver is not a list" ) ) ,
474+ }
475+ self . mark_impure ( ) ;
476+ self . push ( Val :: none ( ) ) ;
477+ Ok ( ( ) )
478+ }
479+ ListRemove => {
480+ if positional. len ( ) != 1 {
481+ return Err ( VmErr :: Type ( "remove() takes exactly one argument" ) ) ;
482+ }
483+ let target = positional[ 0 ] ;
484+ let items = match self . heap . get ( recv) {
485+ HeapObj :: List ( rc) => rc. borrow ( ) . clone ( ) ,
486+ _ => return Err ( VmErr :: Type ( "remove: receiver is not a list" ) ) ,
487+ } ;
488+ let pos = items. iter ( )
489+ . position ( |& v| eq_vals_with_heap ( v, target, & self . heap ) )
490+ . ok_or ( VmErr :: Value ( "list.remove: value not found" ) ) ?;
491+ match self . heap . get_mut ( recv) {
492+ HeapObj :: List ( rc) => { rc. borrow_mut ( ) . remove ( pos) ; }
493+ _ => return Err ( VmErr :: Type ( "remove: receiver is not a list" ) ) ,
494+ }
495+ self . mark_impure ( ) ;
496+ self . push ( Val :: none ( ) ) ;
497+ Ok ( ( ) )
498+ }
499+ ListIndex => {
500+ if positional. len ( ) != 1 {
501+ return Err ( VmErr :: Type ( "index() takes exactly one argument" ) ) ;
502+ }
503+ let target = positional[ 0 ] ;
504+ let idx = match self . heap . get ( recv) {
505+ HeapObj :: List ( rc) => {
506+ rc. borrow ( ) . iter ( ) . position ( |& v| eq_vals_with_heap ( v, target, & self . heap ) )
507+ . map ( |i| i as i64 )
508+ . ok_or ( VmErr :: Value ( "value not found in list" ) ) ?
509+ }
510+ _ => return Err ( VmErr :: Type ( "index: receiver is not a list" ) ) ,
511+ } ;
512+ self . push ( Val :: int ( idx) ) ;
513+ Ok ( ( ) )
514+ }
515+ ListCount => {
516+ if positional. len ( ) != 1 {
517+ return Err ( VmErr :: Type ( "count() takes exactly one argument" ) ) ;
518+ }
519+ let target = positional[ 0 ] ;
520+ let n = match self . heap . get ( recv) {
521+ HeapObj :: List ( rc) => {
522+ rc. borrow ( ) . iter ( ) . filter ( |& & v| eq_vals_with_heap ( v, target, & self . heap ) ) . count ( ) as i64
523+ }
524+ _ => return Err ( VmErr :: Type ( "count: receiver is not a list" ) ) ,
525+ } ;
526+ self . push ( Val :: int ( n) ) ;
527+ Ok ( ( ) )
528+ }
381529 }
382530 }
383531
0 commit comments