1- use crate :: { runtime:: RawWasmValue , Error , Result } ;
1+ use core:: ops:: Range ;
2+
3+ use crate :: { runtime:: RawWasmValue , Error , ModuleInstance , Result } ;
24use alloc:: vec:: Vec ;
5+ use log:: info;
36use tinywasm_types:: BlockArgs ;
47
58// minimum stack size
@@ -23,26 +26,36 @@ impl Default for ValueStack {
2326}
2427
2528impl ValueStack {
29+ #[ cfg( test) ]
30+ pub ( crate ) fn data ( & self ) -> & [ RawWasmValue ] {
31+ & self . stack
32+ }
33+
2634 #[ inline]
2735 pub ( crate ) fn len ( & self ) -> usize {
2836 assert ! ( self . top <= self . stack. len( ) ) ;
2937 self . top
3038 }
3139
3240 #[ inline]
33- pub ( crate ) fn trim ( & mut self , n : usize ) {
41+ pub ( crate ) fn truncate ( & mut self , n : usize ) {
3442 assert ! ( self . top <= self . stack. len( ) ) ;
3543 self . top -= n;
3644 self . stack . truncate ( self . top ) ;
3745 }
3846
3947 #[ inline]
40- pub ( crate ) fn push_block_args ( & self , args : BlockArgs ) -> Result < ( ) > {
41- match args {
42- BlockArgs :: Empty => Ok ( ( ) ) ,
43- BlockArgs :: Type ( _t ) => todo ! ( "support block args (type)" ) ,
44- BlockArgs :: FuncType ( _t ) => todo ! ( "support block args (func type)" ) ,
48+ // example: [1, 2, 3] n=1, end_keep=1 => [1, 3]
49+ // example: [1] n=1, end_keep=1 => [1]
50+ pub ( crate ) fn truncate_keep ( & mut self , n : usize , end_keep : usize ) {
51+ if n == end_keep || n == 0 {
52+ return ;
4553 }
54+
55+ assert ! ( self . top <= self . stack. len( ) ) ;
56+ info ! ( "removing from {} to {}" , self . top - n, self . top - end_keep) ;
57+ self . stack . drain ( self . top - n..self . top - end_keep) ;
58+ self . top -= n - end_keep;
4659 }
4760
4861 #[ inline]
@@ -98,3 +111,56 @@ impl ValueStack {
98111 Ok ( res)
99112 }
100113}
114+
115+ #[ cfg( test) ]
116+ mod tests {
117+ use super :: * ;
118+ use crate :: std:: panic;
119+
120+ fn crate_stack < T : Into < RawWasmValue > + Copy > ( data : & [ T ] ) -> ValueStack {
121+ let mut stack = ValueStack :: default ( ) ;
122+ stack. extend ( data. iter ( ) . map ( |v| ( * v) . into ( ) ) ) ;
123+ stack
124+ }
125+
126+ fn assert_truncate_keep < T : Into < RawWasmValue > + Copy > ( data : & [ T ] , n : usize , end_keep : usize , expected : & [ T ] ) {
127+ let mut stack = crate_stack ( data) ;
128+ stack. truncate_keep ( n, end_keep) ;
129+ assert_eq ! (
130+ stack. data( ) ,
131+ expected. iter( ) . map( |v| ( * v) . into( ) ) . collect:: <Vec <_>>( ) . as_slice( )
132+ ) ;
133+ }
134+
135+ fn catch_unwind_silent < F : FnOnce ( ) -> R + panic:: UnwindSafe , R > ( f : F ) -> crate :: std:: thread:: Result < R > {
136+ let prev_hook = panic:: take_hook ( ) ;
137+ panic:: set_hook ( alloc:: boxed:: Box :: new ( |_| { } ) ) ;
138+ let result = panic:: catch_unwind ( f) ;
139+ panic:: set_hook ( prev_hook) ;
140+ result
141+ }
142+
143+ #[ test]
144+ fn test_truncate_keep ( ) {
145+ assert_truncate_keep ( & [ 1 , 2 , 3 ] , 1 , 1 , & [ 1 , 2 , 3 ] ) ;
146+ assert_truncate_keep ( & [ 1 ] , 1 , 1 , & [ 1 ] ) ;
147+ assert_truncate_keep ( & [ 1 , 2 , 3 ] , 2 , 1 , & [ 1 , 3 ] ) ;
148+ assert_truncate_keep :: < i32 > ( & [ ] , 0 , 0 , & [ ] ) ;
149+ catch_unwind_silent ( || assert_truncate_keep ( & [ 1 , 2 , 3 ] , 4 , 1 , & [ 1 , 3 ] ) ) . expect_err ( "should panic" ) ;
150+ }
151+
152+ #[ test]
153+ fn test_value_stack ( ) {
154+ let mut stack = ValueStack :: default ( ) ;
155+ stack. push ( 1 . into ( ) ) ;
156+ stack. push ( 2 . into ( ) ) ;
157+ stack. push ( 3 . into ( ) ) ;
158+ assert_eq ! ( stack. len( ) , 3 ) ;
159+ assert_eq ! ( stack. pop_t:: <i32 >( ) . unwrap( ) , 3 ) ;
160+ assert_eq ! ( stack. len( ) , 2 ) ;
161+ assert_eq ! ( stack. pop_t:: <i32 >( ) . unwrap( ) , 2 ) ;
162+ assert_eq ! ( stack. len( ) , 1 ) ;
163+ assert_eq ! ( stack. pop_t:: <i32 >( ) . unwrap( ) , 1 ) ;
164+ assert_eq ! ( stack. len( ) , 0 ) ;
165+ }
166+ }
0 commit comments