@@ -4248,6 +4248,157 @@ codegen_case(codegen_scope *s, node *varnode, int val)
42484248 }
42494249}
425042504251+/* Forward declaration for pattern matching code generation */
4252+static void codegen_pattern(codegen_scope *s, node *pattern, int target, uint32_t *fail_pos);
4253+4254+/* Pattern matching case/in expression */
4255+static void
4256+codegen_case_match(codegen_scope *s, node *varnode, int val)
4257+{
4258+struct mrb_ast_case_match_node *case_match_n = case_match_node(varnode);
4259+node *value = case_match_n->value;
4260+node *in_clauses = case_match_n->in_clauses;
4261+4262+int head = cursp();
4263+uint32_t case_end_jumps = JMPLINK_START;
4264+uint32_t tmp;
4265+4266+/* Generate code for the case value */
4267+codegen(s, value, VAL);
4268+4269+/* Iterate through in clauses */
4270+node *current_in = in_clauses;
4271+while (current_in) {
4272+struct mrb_ast_in_node *in_n = in_node(current_in->car);
4273+node *pattern = in_n->pattern;
4274+node *body = in_n->body;
4275+4276+uint32_t fail_pos = JMPLINK_START;
4277+4278+if (pattern) {
4279+/* Generate pattern matching code */
4280+codegen_pattern(s, pattern, head, &fail_pos);
4281+ }
4282+4283+/* Generate in-clause body */
4284+codegen(s, body, val);
4285+if (val) pop();
4286+4287+/* Jump to end of case/in */
4288+tmp = genjmp(s, OP_JMP, case_end_jumps);
4289+case_end_jumps = tmp;
4290+4291+/* Dispatch fail jumps to next in-clause */
4292+if (fail_pos != JMPLINK_START) {
4293+dispatch_linked(s, fail_pos);
4294+ }
4295+4296+current_in = current_in->cdr;
4297+ }
4298+4299+/* No pattern matched - generate nil or error */
4300+if (val) {
4301+genop_1(s, OP_LOADNIL, cursp());
4302+ }
4303+4304+/* Dispatch all end jumps */
4305+if (case_end_jumps != JMPLINK_START) {
4306+dispatch_linked(s, case_end_jumps);
4307+ }
4308+4309+if (val) {
4310+/* Move result to original case value position */
4311+gen_move(s, head, cursp(), 0);
4312+pop();
4313+push();
4314+ }
4315+else {
4316+pop(); /* pop the case value */
4317+ }
4318+}
4319+4320+/* Generate pattern matching code for a single pattern.
4321+ * target: stack position of the value being matched
4322+ * fail_pos: linked list of jump positions for pattern match failure
4323+ */
4324+static void
4325+codegen_pattern(codegen_scope *s, node *pattern, int target, uint32_t *fail_pos)
4326+{
4327+uint32_t tmp;
4328+4329+switch (get_node_type(pattern)) {
4330+case NODE_PAT_VALUE:
4331+ {
4332+struct mrb_ast_pat_value_node *pat_val = pat_value_node(pattern);
4333+/* Generate: pattern_value === target */
4334+codegen(s, pat_val->value, VAL);
4335+gen_move(s, cursp(), target, 0);
4336+push(); push(); pop(); pop(); pop();
4337+genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_OPSYM_2(s->mrb, eqq)), 1);
4338+/* Jump to fail if not matched */
4339+tmp = genjmp2(s, OP_JMPNOT, cursp(), *fail_pos, 1);
4340+*fail_pos = tmp;
4341+ }
4342+break;
4343+4344+case NODE_PAT_VAR:
4345+ {
4346+struct mrb_ast_pat_var_node *pat_var = pat_var_node(pattern);
4347+if (pat_var->name) {
4348+/* Bind the matched value to the variable */
4349+int idx = lv_idx(s, pat_var->name);
4350+if (idx > 0) {
4351+gen_move(s, idx, target, 0);
4352+ }
4353+ }
4354+/* Variable pattern always matches (wildcard if name is 0) */
4355+ }
4356+break;
4357+4358+case NODE_PAT_ALT:
4359+ {
4360+struct mrb_ast_pat_alt_node *pat_alt = pat_alt_node(pattern);
4361+uint32_t left_fail = JMPLINK_START;
4362+uint32_t success_pos = JMPLINK_START;
4363+4364+/* Try left pattern */
4365+codegen_pattern(s, pat_alt->left, target, &left_fail);
4366+/* Left succeeded - jump to success */
4367+tmp = genjmp(s, OP_JMP, success_pos);
4368+success_pos = tmp;
4369+4370+/* Left failed - try right pattern */
4371+if (left_fail != JMPLINK_START) {
4372+dispatch_linked(s, left_fail);
4373+ }
4374+codegen_pattern(s, pat_alt->right, target, fail_pos);
4375+4376+/* Dispatch success jumps */
4377+if (success_pos != JMPLINK_START) {
4378+dispatch_linked(s, success_pos);
4379+ }
4380+ }
4381+break;
4382+4383+case NODE_PAT_AS:
4384+ {
4385+struct mrb_ast_pat_as_node *pat_as = pat_as_node(pattern);
4386+/* First match the pattern */
4387+codegen_pattern(s, pat_as->pattern, target, fail_pos);
4388+/* Then bind the value to the variable */
4389+int idx = lv_idx(s, pat_as->name);
4390+if (idx > 0) {
4391+gen_move(s, idx, target, 0);
4392+ }
4393+ }
4394+break;
4395+4396+default:
4397+raise_error(s, "unsupported pattern type");
4398+break;
4399+ }
4400+}
4401+42514402/* Definition node codegen functions */
4252440342534404static void
@@ -5725,6 +5876,10 @@ codegen(codegen_scope *s, node *tree, int val)
57255876codegen_case(s, tree, val);
57265877break;
572758785879+case NODE_CASE_MATCH:
5880+codegen_case_match(s, tree, val);
5881+break;
5882+57285883case NODE_DEF:
57295884codegen_def(s, tree, val);
57305885break;