@@ -2389,6 +2389,14 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
23892389 }
23902390 YARVINSN_pop => { state. stack_pop ( ) ?; }
23912391 YARVINSN_dup => { state. stack_push ( state. stack_top ( ) ?) ; }
2392+ YARVINSN_dupn => {
2393+ // Duplicate the top N element of the stack. As we push, n-1 naturally
2394+ // points higher in the original stack.
2395+ let n = get_arg ( pc, 0 ) . as_usize ( ) ;
2396+ for _ in 0 ..n {
2397+ state. stack_push ( state. stack_topn ( n-1 ) ?) ;
2398+ }
2399+ }
23922400 YARVINSN_swap => {
23932401 let right = state. stack_pop ( ) ?;
23942402 let left = state. stack_pop ( ) ?;
@@ -4180,6 +4188,29 @@ mod tests {
41804188 Return v10
41814189 "# ] ] ) ;
41824190 }
4191+
4192+ #[ test]
4193+ fn dupn ( ) {
4194+ eval ( "
4195+ def test(x) = (x[0, 1] ||= 2)
4196+ " ) ;
4197+ assert_method_hir_with_opcode ( "test" , YARVINSN_dupn , expect ! [ [ r#"
4198+ fn test:
4199+ bb0(v0:BasicObject, v1:BasicObject):
4200+ v3:NilClassExact = Const Value(nil)
4201+ v4:Fixnum[0] = Const Value(0)
4202+ v5:Fixnum[1] = Const Value(1)
4203+ v7:BasicObject = SendWithoutBlock v1, :[], v4, v5
4204+ v8:CBool = Test v7
4205+ IfTrue v8, bb1(v0, v1, v3, v1, v4, v5, v7)
4206+ v10:Fixnum[2] = Const Value(2)
4207+ v12:BasicObject = SendWithoutBlock v1, :[]=, v4, v5, v10
4208+ Return v10
4209+ bb1(v14:BasicObject, v15:BasicObject, v16:NilClassExact, v17:BasicObject, v18:Fixnum[0], v19:Fixnum[1], v20:BasicObject):
4210+ Return v20
4211+ "# ] ] ) ;
4212+
4213+ }
41834214}
41844215
41854216#[ cfg( test) ]
0 commit comments