@@ -2405,6 +2405,14 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
2405
2405
}
2406
2406
YARVINSN_pop => { state. stack_pop ( ) ?; }
2407
2407
YARVINSN_dup => { state. stack_push ( state. stack_top ( ) ?) ; }
2408
+ YARVINSN_dupn => {
2409
+ // Duplicate the top N element of the stack. As we push, n-1 naturally
2410
+ // points higher in the original stack.
2411
+ let n = get_arg ( pc, 0 ) . as_usize ( ) ;
2412
+ for _ in 0 ..n {
2413
+ state. stack_push ( state. stack_topn ( n-1 ) ?) ;
2414
+ }
2415
+ }
2408
2416
YARVINSN_swap => {
2409
2417
let right = state. stack_pop ( ) ?;
2410
2418
let left = state. stack_pop ( ) ?;
@@ -4314,6 +4322,28 @@ mod tests {
4314
4322
Return v8
4315
4323
"# ] ] ) ;
4316
4324
}
4325
+
4326
+ #[ test]
4327
+ fn dupn ( ) {
4328
+ eval ( "
4329
+ def test(x) = (x[0, 1] ||= 2)
4330
+ " ) ;
4331
+ assert_method_hir_with_opcode ( "test" , YARVINSN_dupn , expect ! [ [ r#"
4332
+ fn test:
4333
+ bb0(v0:BasicObject, v1:BasicObject):
4334
+ v3:NilClassExact = Const Value(nil)
4335
+ v4:Fixnum[0] = Const Value(0)
4336
+ v5:Fixnum[1] = Const Value(1)
4337
+ v7:BasicObject = SendWithoutBlock v1, :[], v4, v5
4338
+ v8:CBool = Test v7
4339
+ IfTrue v8, bb1(v0, v1, v3, v1, v4, v5, v7)
4340
+ v10:Fixnum[2] = Const Value(2)
4341
+ v12:BasicObject = SendWithoutBlock v1, :[]=, v4, v5, v10
4342
+ Return v10
4343
+ bb1(v14:BasicObject, v15:BasicObject, v16:NilClassExact, v17:BasicObject, v18:Fixnum[0], v19:Fixnum[1], v20:BasicObject):
4344
+ Return v20
4345
+ "# ] ] ) ;
4346
+ }
4317
4347
}
4318
4348
4319
4349
#[ cfg( test) ]
0 commit comments