@@ -125,7 +125,7 @@ impl<'a> VM<'a> {
125125 Merges two SSA branches into target slot and back-propagates through prev_slots chain.
126126 */
127127
128- fn exec_phi ( op : u16 , rip : usize , phi_map : & [ usize ] , slots : & mut Vec < Option < Val > > , prev_slots : & [ Option < u16 > ] , phi_sources : & [ ( u16 , u16 ) ] ) {
128+ fn exec_phi ( op : u16 , rip : usize , phi_map : & [ usize ] , slots : & mut [ Option < Val > ] , prev_slots : & [ Option < u16 > ] , phi_sources : & [ ( u16 , u16 ) ] ) {
129129 let target = op as usize ;
130130 let ( ia, ib) = phi_sources[ phi_map[ rip] ] ;
131131 let val = slots[ ia as usize ] . or ( slots[ ib as usize ] ) . unwrap_or ( Val :: none ( ) ) ;
@@ -193,14 +193,14 @@ impl<'a> VM<'a> {
193193 #[ inline] pub ( crate ) fn push ( & mut self , v : Val ) { self . stack . push ( v) ; }
194194
195195 #[ inline] pub ( crate ) fn pop ( & mut self ) -> Result < Val , VmErr > {
196- self . stack . pop ( ) . ok_or_else ( || VmErr :: Runtime ( "stack underflow" ) )
196+ self . stack . pop ( ) . ok_or ( VmErr :: Runtime ( "stack underflow" ) )
197197 }
198198 #[ inline] pub ( crate ) fn pop2 ( & mut self ) -> Result < ( Val , Val ) , VmErr > {
199199 let b = self . pop ( ) ?; let a = self . pop ( ) ?; Ok ( ( a, b) )
200200 }
201201 #[ inline] pub ( crate ) fn pop_n ( & mut self , n : usize ) -> Result < Vec < Val > , VmErr > {
202- let at = self . stack . len ( ) . checked_sub ( n)
203- . ok_or_else ( || VmErr :: Runtime ( "stack underflow" ) ) ?;
202+ let at = self . stack . len ( ) . checked_sub ( n)
203+ . ok_or ( VmErr :: Runtime ( "stack underflow" ) ) ?;
204204 Ok ( self . stack . split_off ( at) )
205205 }
206206
@@ -209,7 +209,7 @@ impl<'a> VM<'a> {
209209 Converts a parser-level Value into a runtime Val, allocating heap for strings.
210210 */
211211
212- pub ( crate ) fn to_val ( & mut self , v : & Value ) -> Result < Val , VmErr > {
212+ pub ( crate ) fn val_from ( & mut self , v : & Value ) -> Result < Val , VmErr > {
213213 Ok ( match v {
214214 Value :: Int ( i) => {
215215 if * i >= Val :: INT_MIN && * i <= Val :: INT_MAX {
@@ -278,7 +278,7 @@ impl<'a> VM<'a> {
278278 Fetches instructions by IP, routes each opcode to its handler arm.
279279 */
280280
281- pub ( crate ) fn exec ( & mut self , chunk : & SSAChunk , slots : & mut Vec < Option < Val > > ) -> Result < Val , VmErr > {
281+ pub ( crate ) fn exec ( & mut self , chunk : & SSAChunk , slots : & mut [ Option < Val > ] ) -> Result < Val , VmErr > {
282282 let slots_base = self . live_slots . len ( ) ;
283283 let n = chunk. instructions . len ( ) ;
284284
@@ -320,7 +320,7 @@ impl<'a> VM<'a> {
320320 match ins. opcode {
321321
322322 // Loads
323- OpCode :: LoadConst => { let v = self . to_val ( & chunk. constants [ op as usize ] ) ?; self . push ( v) ; }
323+ OpCode :: LoadConst => { let v = self . val_from ( & chunk. constants [ op as usize ] ) ?; self . push ( v) ; }
324324 OpCode :: LoadName => { let slot = op as usize ; self . push ( slots[ slot] . ok_or_else ( || VmErr :: Name ( chunk. names [ slot] . clone ( ) ) ) ?) ; }
325325 OpCode :: StoreName => {
326326 let v = self . pop ( ) ?;
@@ -355,8 +355,8 @@ impl<'a> VM<'a> {
355355 }
356356 OpCode :: Pow => {
357357 let ( a, b) = self . pop2 ( ) ?;
358- if let Some ( ba) = self . to_bigint ( a) {
359- if b. is_int ( ) {
358+ if let Some ( ba) = self . to_bigint ( a)
359+ && b. is_int ( ) {
360360 let exp = b. as_int ( ) ;
361361 if exp >= 0 {
362362 let result = ba. pow_u32 ( exp as u32 ) ;
@@ -366,7 +366,6 @@ impl<'a> VM<'a> {
366366 }
367367 self . push ( Val :: float ( fpowi ( ba. to_f64 ( ) , exp as i32 ) ) ) ;
368368 continue ;
369- }
370369 }
371370 let fa = if a. is_int ( ) { a. as_int ( ) as f64 } else if a. is_float ( ) { a. as_float ( ) }
372371 else { return Err ( VmErr :: Type ( "** requires numeric operands" ) ) ; } ;
@@ -517,7 +516,7 @@ impl<'a> VM<'a> {
517516
518517 OpCode :: ListAppend => {
519518 let v = self . pop ( ) ?;
520- let acc = * self . stack . last ( ) . ok_or_else ( || VmErr :: Runtime ( "stack underflow" ) ) ?;
519+ let acc = * self . stack . last ( ) . ok_or ( VmErr :: Runtime ( "stack underflow" ) ) ?;
521520 if !acc. is_heap ( ) { return Err ( VmErr :: Runtime ( "list accumulator corrupted" ) ) ; }
522521 match self . heap . get ( acc) {
523522 HeapObj :: List ( rc) => rc. borrow_mut ( ) . push ( v) ,
@@ -526,20 +525,18 @@ impl<'a> VM<'a> {
526525 }
527526 OpCode :: SetAdd => {
528527 let v = self . pop ( ) ?;
529- let acc = * self . stack . last ( ) . ok_or_else ( || VmErr :: Runtime ( "stack underflow" ) ) ?;
528+ let acc = * self . stack . last ( ) . ok_or ( VmErr :: Runtime ( "stack underflow" ) ) ?;
530529 if !acc. is_heap ( ) { return Err ( VmErr :: Runtime ( "set accumulator corrupted" ) ) ; }
531530 let already = match self . heap . get ( acc) {
532531 HeapObj :: Set ( rc) => rc. borrow ( ) . iter ( ) . any ( |& x| eq_vals_with_heap ( x, v, & self . heap ) ) ,
533532 _ => return Err ( VmErr :: Runtime ( "set accumulator corrupted" ) ) ,
534533 } ;
535- if !already {
536- if let HeapObj :: Set ( rc) = self . heap . get ( acc) { rc. borrow_mut ( ) . push ( v) ; }
537- }
534+ if !already && let HeapObj :: Set ( rc) = self . heap . get ( acc) { rc. borrow_mut ( ) . push ( v) ; }
538535 }
539536 OpCode :: MapAdd => {
540537 let value = self . pop ( ) ?;
541538 let key = self . pop ( ) ?;
542- let acc = * self . stack . last ( ) . ok_or_else ( || VmErr :: Runtime ( "stack underflow" ) ) ?;
539+ let acc = * self . stack . last ( ) . ok_or ( VmErr :: Runtime ( "stack underflow" ) ) ?;
543540 if !acc. is_heap ( ) { return Err ( VmErr :: Runtime ( "dict accumulator corrupted" ) ) ; }
544541 match self . heap . get ( acc) {
545542 HeapObj :: Dict ( rc) => { rc. borrow_mut ( ) . insert ( key, value) ; }
@@ -580,21 +577,22 @@ impl<'a> VM<'a> {
580577 for ( i, n) in body. names . iter ( ) . enumerate ( ) { body_map. insert ( n. as_str ( ) , i) ; }
581578 // Bind args to params: detects keyword args (HeapObj::Str matching a param name) and consumes key+value pairs
582579 let mut pi = 0usize ;
583- for ( _, p) in params. iter ( ) . enumerate ( ) {
584- if pi >= args. len ( ) { break ; }
585- if args[ pi] . is_heap ( ) {
586- if let HeapObj :: Str ( k) = self . heap . get ( args[ pi] ) {
587- if params. iter ( ) . any ( |p| p. trim_start_matches ( '*' ) == k. as_str ( ) ) && pi + 1 < args. len ( ) {
588- let pname = format ! ( "{}_0" , k) ;
589- if let Some ( & s) = body_map. get ( pname. as_str ( ) ) { fn_slots[ s] = Some ( args[ pi + 1 ] ) ; }
590- pi += 2 ;
591- continue ;
592- }
593- }
580+ for p in params. iter ( ) {
581+ if pi < args. len ( )
582+ && args[ pi] . is_heap ( )
583+ && let HeapObj :: Str ( k) = self . heap . get ( args[ pi] )
584+ && params. iter ( ) . any ( |p| p. trim_start_matches ( '*' ) == k. as_str ( ) )
585+ && pi + 1 < args. len ( ) {
586+ let pname = format ! ( "{}_0" , k) ;
587+ if let Some ( & s) = body_map. get ( pname. as_str ( ) ) { fn_slots[ s] = Some ( args[ pi + 1 ] ) ; }
588+ pi += 2 ;
589+ continue ;
590+ }
591+ if pi < args. len ( ) {
592+ let pname = format ! ( "{}_0" , p. trim_start_matches( '*' ) ) ;
593+ if let Some ( & s) = body_map. get ( pname. as_str ( ) ) { fn_slots[ s] = Some ( args[ pi] ) ; }
594+ pi += 1 ;
594595 }
595- let pname = format ! ( "{}_0" , p. trim_start_matches( '*' ) ) ;
596- if let Some ( & s) = body_map. get ( pname. as_str ( ) ) { fn_slots[ s] = Some ( args[ pi] ) ; }
597- pi += 1 ;
598596 }
599597 if pi < params. len ( ) && !captured_defaults. is_empty ( ) {
600598 let d_start = captured_defaults. len ( ) . saturating_sub ( params. len ( ) - pi) ;
0 commit comments