@@ -6,7 +6,24 @@ use super::VM;
66use super :: types:: * ;
77
88use core:: cell:: RefCell ;
9- use alloc:: { string:: String , vec:: Vec , vec, rc:: Rc } ;
9+ use alloc:: { string:: { String , ToString } , vec:: Vec , vec, rc:: Rc } ;
10+ use crate :: modules:: fx:: FxHashSet as HashSet ;
11+
12+ fn normalize_index ( i : i64 , len : usize ) -> usize {
13+ ( if i < 0 { len as i64 + i } else { i } ) as usize
14+ }
15+
16+ enum SliceSource { List ( Vec < Val > ) , Tuple ( Vec < Val > ) , Str ( Vec < char > ) }
17+
18+ impl SliceSource {
19+ fn len ( & self ) -> i64 {
20+ match self {
21+ Self :: List ( v) => v. len ( ) as i64 ,
22+ Self :: Tuple ( v) => v. len ( ) as i64 ,
23+ Self :: Str ( v) => v. len ( ) as i64 ,
24+ }
25+ }
26+ }
1027
1128impl < ' a > VM < ' a > {
1229
@@ -399,4 +416,205 @@ impl<'a> VM<'a> {
399416 _ => return Err ( VmErr :: Type ( "list() argument must be iterable" ) ) ,
400417 } )
401418 }
419+
420+ fn alloc_set ( & mut self , items : Vec < Val > ) -> Result < Val , VmErr > {
421+ let mut set = HashSet :: with_capacity_and_hasher ( items. len ( ) , Default :: default ( ) ) ;
422+ for v in items { set. insert ( v) ; }
423+ self . heap . alloc ( HeapObj :: Set ( Rc :: new ( RefCell :: new ( set) ) ) )
424+ }
425+
426+ pub fn build_set ( & mut self , op : u16 ) -> Result < ( ) , VmErr > {
427+ let items = self . pop_n ( op as usize ) ?;
428+ let val = self . alloc_set ( items) ?;
429+ self . push ( val) ; Ok ( ( ) )
430+ }
431+
432+ pub fn build_slice ( & mut self , op : u16 ) -> Result < ( ) , VmErr > {
433+ let step = if op == 3 { self . pop ( ) ? } else { Val :: none ( ) } ;
434+ let stop = self . pop ( ) ?;
435+ let start = self . pop ( ) ?;
436+ let val = self . heap . alloc ( HeapObj :: Slice ( start, stop, step) ) ?;
437+ self . push ( val) ; Ok ( ( ) )
438+ }
439+
440+ pub fn unpack_ex ( & mut self , op : u16 ) -> Result < ( ) , VmErr > {
441+ let obj = self . pop ( ) ?;
442+ if !obj. is_heap ( ) { return Err ( cold_type ( "cannot unpack non-iterable" ) ) ; }
443+ let items: Vec < Val > = match self . heap . get ( obj) {
444+ HeapObj :: List ( v) => v. borrow ( ) . clone ( ) ,
445+ HeapObj :: Tuple ( v) => v. clone ( ) ,
446+ _ => return Err ( cold_type ( "cannot unpack non-iterable" ) ) ,
447+ } ;
448+ let before = ( op >> 8 ) as usize ;
449+ let after = ( op & 0xFF ) as usize ;
450+ if items. len ( ) < before + after {
451+ return Err ( cold_value ( "not enough values to unpack" ) ) ;
452+ }
453+ let mid = items. len ( ) - after;
454+ for & v in items[ mid..] . iter ( ) . rev ( ) { self . push ( v) ; }
455+ let star = self . heap . alloc ( HeapObj :: List ( Rc :: new ( RefCell :: new (
456+ items[ before..mid] . to_vec ( )
457+ ) ) ) ) ?;
458+ self . push ( star) ;
459+ for & v in items[ ..before] . iter ( ) . rev ( ) { self . push ( v) ; }
460+ Ok ( ( ) )
461+ }
462+
463+ pub fn call_dict ( & mut self , op : u16 ) -> Result < ( ) , VmErr > {
464+ if op == 0 {
465+ let val = self . heap . alloc ( HeapObj :: Dict ( Rc :: new ( RefCell :: new ( DictMap :: new ( ) ) ) ) ) ?;
466+ self . push ( val) ;
467+ } else {
468+ let args = self . pop_n ( ( op as usize ) * 2 ) ?;
469+ let mut dm = DictMap :: with_capacity ( op as usize ) ;
470+ for pair in args. chunks ( 2 ) { dm. insert ( pair[ 0 ] , pair[ 1 ] ) ; }
471+ let val = self . heap . alloc ( HeapObj :: Dict ( Rc :: new ( RefCell :: new ( dm) ) ) ) ?;
472+ self . push ( val) ;
473+ }
474+ Ok ( ( ) )
475+ }
476+
477+ pub fn call_set ( & mut self , op : u16 ) -> Result < ( ) , VmErr > {
478+ if op == 0 {
479+ let val = self . alloc_set ( Vec :: new ( ) ) ?;
480+ self . push ( val) ;
481+ } else {
482+ let o = self . pop ( ) ?;
483+ let src: Vec < Val > = if o. is_heap ( ) {
484+ match self . heap . get ( o) {
485+ HeapObj :: List ( v) => v. borrow ( ) . clone ( ) ,
486+ HeapObj :: Tuple ( v) => v. clone ( ) ,
487+ HeapObj :: Set ( v) => v. borrow ( ) . iter ( ) . cloned ( ) . collect ( ) ,
488+ HeapObj :: Str ( s) => {
489+ let s = s. clone ( ) ;
490+ self . str_to_char_vals ( & s) ?
491+ } ,
492+ _ => return Err ( cold_type ( "set() argument must be iterable" ) ) ,
493+ }
494+ } else {
495+ return Err ( cold_type ( "set() argument must be iterable" ) ) ;
496+ } ;
497+ let val = self . alloc_set ( src) ?;
498+ self . push ( val) ;
499+ }
500+ Ok ( ( ) )
501+ }
502+
503+ pub fn get_item ( & mut self ) -> Result < bool , VmErr > {
504+ let idx = self . pop ( ) ?;
505+ let obj = self . pop ( ) ?;
506+
507+ if idx. is_heap ( )
508+ && let HeapObj :: Slice ( start, stop, step) = self . heap . get ( idx) . clone ( ) {
509+ let v = self . slice_val ( obj, start, stop, step) ?;
510+ self . push ( v) ;
511+ return Ok ( true ) ;
512+ }
513+
514+ if obj. is_heap ( ) && idx. is_int ( )
515+ && let HeapObj :: Str ( s) = self . heap . get ( obj) {
516+ let chars: Vec < char > = s. chars ( ) . collect ( ) ;
517+ let i = idx. as_int ( ) ;
518+ let ui = normalize_index ( i, chars. len ( ) ) ;
519+ let c = chars. get ( ui) . copied ( ) . ok_or ( cold_value ( "string index out of range" ) ) ?;
520+ let val = self . heap . alloc ( HeapObj :: Str ( c. to_string ( ) ) ) ?;
521+ self . push ( val) ;
522+ return Ok ( true ) ;
523+ }
524+
525+ let v = self . getitem_val ( obj, idx) ?;
526+ self . push ( v) ;
527+ Ok ( false )
528+ }
529+
530+ fn slice_val ( & mut self , obj : Val , start : Val , stop : Val , step : Val ) -> Result < Val , VmErr > {
531+ if !obj. is_heap ( ) { return Err ( cold_type ( "slice requires a sequence" ) ) ; }
532+ let st = if step. is_none ( ) { 1 } else if step. is_int ( ) { step. as_int ( ) } else {
533+ return Err ( cold_type ( "slice step must be an integer" ) ) ;
534+ } ;
535+ if st == 0 { return Err ( cold_value ( "slice step cannot be zero" ) ) ; }
536+
537+ let source = match self . heap . get ( obj) {
538+ HeapObj :: List ( v) => SliceSource :: List ( v. borrow ( ) . clone ( ) ) ,
539+ HeapObj :: Tuple ( v) => SliceSource :: Tuple ( v. clone ( ) ) ,
540+ HeapObj :: Str ( s) => SliceSource :: Str ( s. chars ( ) . collect ( ) ) ,
541+ _ => return Err ( cold_type ( "object is not sliceable" ) ) ,
542+ } ;
543+
544+ let len = source. len ( ) ;
545+
546+ let clamp = |v : Val , def : i64 | -> i64 {
547+ if v. is_none ( ) { def }
548+ else if v. is_int ( ) { let i = v. as_int ( ) ; if i < 0 { ( len+i) . max ( 0 ) } else { i. min ( len) } }
549+ else { def }
550+ } ;
551+
552+ let ( s, e) = if st > 0 {
553+ ( clamp ( start, 0 ) , clamp ( stop, len) )
554+ } else {
555+ ( clamp ( start, len - 1 ) , clamp ( stop, -1 ) )
556+ } ;
557+
558+ let mut indices = Vec :: new ( ) ;
559+ let mut cur = s;
560+ if st > 0 { while cur < e { indices. push ( cur as usize ) ; cur += st; } }
561+ else { while cur > e { indices. push ( cur as usize ) ; cur += st; } }
562+
563+ let pick = |v : & [ Val ] | -> Vec < Val > {
564+ indices. iter ( ) . filter_map ( |& i| v. get ( i) . copied ( ) ) . collect ( )
565+ } ;
566+
567+ match source {
568+ SliceSource :: List ( v) => self . heap . alloc ( HeapObj :: List ( Rc :: new ( RefCell :: new ( pick ( & v) ) ) ) ) ,
569+ SliceSource :: Tuple ( v) => self . heap . alloc ( HeapObj :: Tuple ( pick ( & v) ) ) ,
570+ SliceSource :: Str ( chars) => {
571+ let sliced: String = indices. iter ( ) . filter_map ( |& i| chars. get ( i) ) . collect ( ) ;
572+ self . heap . alloc ( HeapObj :: Str ( sliced) )
573+ }
574+ }
575+ }
576+
577+ pub fn getitem_val ( & self , obj : Val , idx : Val ) -> Result < Val , VmErr > {
578+ if !obj. is_heap ( ) { return Err ( cold_type ( "object is not subscriptable" ) ) ; }
579+ match self . heap . get ( obj) {
580+ HeapObj :: List ( v) => {
581+ if !idx. is_int ( ) { return Err ( cold_type ( "list indices must be integers" ) ) ; }
582+ let b = v. borrow ( ) ; let i = idx. as_int ( ) ;
583+ let ui = normalize_index ( i, b. len ( ) ) ;
584+ b. get ( ui) . copied ( ) . ok_or ( cold_value ( "list index out of range" ) )
585+ }
586+ HeapObj :: Tuple ( v) => {
587+ if !idx. is_int ( ) { return Err ( cold_type ( "tuple indices must be integers" ) ) ; }
588+ let i = idx. as_int ( ) ;
589+ let ui = normalize_index ( i, v. len ( ) ) ;
590+ v. get ( ui) . copied ( ) . ok_or ( cold_value ( "tuple index out of range" ) )
591+ }
592+ HeapObj :: Dict ( p) => {
593+ p. borrow ( ) . get ( & idx) . copied ( )
594+ . ok_or ( cold_value ( "key not found" ) )
595+ }
596+ _ => Err ( cold_type ( "object is not subscriptable" ) ) ,
597+ }
598+ }
599+
600+ pub fn store_item ( & mut self ) -> Result < ( ) , VmErr > {
601+ let value = self . pop ( ) ?;
602+ let idx_val = self . pop ( ) ?;
603+ let cont = self . pop ( ) ?;
604+ if !cont. is_heap ( ) { return Err ( cold_type ( "object does not support item assignment" ) ) ; }
605+ match self . heap . get_mut ( cont) {
606+ HeapObj :: List ( v) => {
607+ if !idx_val. is_int ( ) { return Err ( cold_type ( "list indices must be integers" ) ) ; }
608+ let mut b = v. borrow_mut ( ) ;
609+ let i = idx_val. as_int ( ) ;
610+ let ui = normalize_index ( i, b. len ( ) ) ;
611+ if ui >= b. len ( ) { return Err ( cold_value ( "list assignment index out of range" ) ) ; }
612+ b[ ui] = value;
613+ }
614+ HeapObj :: Dict ( p) => { p. borrow_mut ( ) . insert ( idx_val, value) ; }
615+ HeapObj :: Tuple ( _) => return Err ( cold_type ( "tuple does not support item assignment" ) ) ,
616+ _ => return Err ( cold_type ( "object does not support item assignment" ) ) ,
617+ }
618+ Ok ( ( ) )
619+ }
402620}
0 commit comments