GitHub

@@ -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 */

4252440342534404

static void

@@ -5725,6 +5876,10 @@ codegen(codegen_scope *s, node *tree, int val)

57255876

codegen_case(s, tree, val);

57265877

break;

572758785879+

case NODE_CASE_MATCH:

5880+

codegen_case_match(s, tree, val);

5881+

break;

5882+57285883

case NODE_DEF:

57295884

codegen_def(s, tree, val);

57305885

break;

Read the original on github.com ↗