From da2d652ec983d1045bbbe5713b1be76b63b7bda4 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 29 Dec 2025 19:09:06 +0900 Subject: [PATCH] codegen.c: fix NODE_MATCH_PAT to push result when val is true Pattern matching expressions were not pushing a result value in several code paths when used in value context (e.g., string interpolation). This caused crashes when the result was expected on the stack. Fix all code paths in NODE_MATCH_PAT to push the appropriate value: - 'in' pattern returns true/false - '=>' pattern returns nil (matches CRuby behavior) Co-authored-by: Claude --- mrbgems/mruby-compiler/core/codegen.c | 48 +++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 20c517e53..32b850f84 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -6520,11 +6520,22 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, mp->value, VAL); pop(); gen_move(s, idx, cursp(), 0); /* peephole optimizes LOADI+MOVE */ - break; + goto match_pat_push_result; } } /* Wildcard pattern - just evaluate value for side effects */ codegen(s, mp->value, NOVAL); + match_pat_push_result: + if (val) { + /* 'in' pattern returns true, '=>' pattern returns nil */ + if (mp->raise_on_fail) { + gen_load_nil(s, 1); + } + else { + genop_1(s, OP_LOADT, cursp()); + push(); + } + } break; } @@ -6561,10 +6572,15 @@ codegen(codegen_scope *s, node *tree, int val) if (fail_pos != JMPLINK_START) { goto pattern_fail_handling; } - /* Pattern always matches - for 'in' pattern, return true */ - if (!mp->raise_on_fail && val) { - genop_1(s, OP_LOADT, cursp()); - push(); + /* Pattern always matches - push result if needed */ + if (val) { + if (mp->raise_on_fail) { + gen_load_nil(s, 1); /* '=>' pattern returns nil */ + } + else { + genop_1(s, OP_LOADT, cursp()); /* 'in' pattern returns true */ + push(); + } } break; } @@ -6595,8 +6611,14 @@ codegen(codegen_scope *s, node *tree, int val) uint32_t match_pos; if (val) { - genop_1(s, OP_LOADT, cursp()); - push(); + /* 'in' pattern returns true, '=>' pattern returns nil */ + if (mp->raise_on_fail) { + gen_load_nil(s, 1); + } + else { + genop_1(s, OP_LOADT, cursp()); + push(); + } } /* Optimize: single JMPNOT can be inverted to JMPIF, eliminating JMP */ @@ -6644,6 +6666,18 @@ codegen(codegen_scope *s, node *tree, int val) /* End of pattern matching */ dispatch(s, match_pos); } + else { + /* Pattern always matches - push result if needed */ + if (val) { + if (mp->raise_on_fail) { + gen_load_nil(s, 1); /* '=>' pattern returns nil */ + } + else { + genop_1(s, OP_LOADT, cursp()); /* 'in' pattern returns true */ + push(); + } + } + } } break;