GitHub

@@ -4538,6 +4538,163 @@ codegen_pattern(codegen_scope *s, node *pattern, int target, uint32_t *fail_pos)

45384538

}

45394539

break;

454045404541+

case NODE_PAT_FIND:

4542+

{

4543+

/* Find pattern: [*pre, elem1, elem2, ..., *post]

4544+

* Searches for elems anywhere in the array.

4545+

*

4546+

* Stack layout:

4547+

* arr_reg: deconstructed array (stable)

4548+

* idx_reg: current search index (stable)

4549+

*

4550+

* Loop bound is recomputed each iteration since OP_SEND clobbers registers.

4551+

*/

4552+

struct mrb_ast_pat_find_node *pat_find = pat_find_node(pattern);

4553+

int elems_len = 0;

4554+

node *elem;

4555+

int arr_reg = cursp();

4556+

int idx_reg;

4557+

uint32_t loop_start, match_fail, loop_end;

4558+4559+

/* Count middle elements */

4560+

for (elem = pat_find->elems; elem; elem = elem->cdr) elems_len++;

4561+4562+

/* Call deconstruct on target */

4563+

gen_move(s, cursp(), target, 0);

4564+

push();

4565+

genop_3(s, OP_SEND, arr_reg, new_sym(s, MRB_SYM_2(s->mrb, deconstruct)), 0);

4566+4567+

/* Check minimum length: arr.size >= elems_len */

4568+

gen_move(s, cursp(), arr_reg, 0);

4569+

push();

4570+

genop_3(s, OP_SEND, cursp() - 1, new_sym(s, MRB_SYM_2(s->mrb, size)), 0);

4571+

gen_int(s, cursp(), elems_len);

4572+

push(); push(); pop(); pop(); pop();

4573+

genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_OPSYM_2(s->mrb, ge)), 1);

4574+

tmp = genjmp2(s, OP_JMPNOT, cursp(), *fail_pos, 1);

4575+

*fail_pos = tmp;

4576+4577+

/* Initialize index to 0 */

4578+

idx_reg = cursp();

4579+

gen_int(s, idx_reg, 0);

4580+

push();

4581+4582+

/* Loop: try matching at each position */

4583+

loop_start = s->pc;

4584+

match_fail = JMPLINK_START;

4585+4586+

/* Check if idx <= arr.size - elems_len (i.e., idx < arr.size - elems_len + 1) */

4587+

/* Compute: arr.size - elems_len */

4588+

gen_move(s, cursp(), arr_reg, 0);

4589+

push();

4590+

genop_3(s, OP_SEND, cursp() - 1, new_sym(s, MRB_SYM_2(s->mrb, size)), 0);

4591+

gen_int(s, cursp(), elems_len);

4592+

push(); push(); pop(); pop(); pop();

4593+

genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_OPSYM_2(s->mrb, sub)), 1);

4594+

/* Now cursp() has (size - elems_len), compare: idx <= (size - elems_len) */

4595+

gen_move(s, cursp() + 1, idx_reg, 0);

4596+

push();

4597+

push(); push(); pop(); pop(); pop();

4598+

genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_OPSYM_2(s->mrb, ge)), 1);

4599+

tmp = genjmp2(s, OP_JMPNOT, cursp(), *fail_pos, 1);

4600+

*fail_pos = tmp;

4601+4602+

/* Try to match each middle element at idx+offset */

4603+

int offset = 0;

4604+

for (elem = pat_find->elems; elem; elem = elem->cdr, offset++) {

4605+

/* Get arr[idx + offset] */

4606+

gen_move(s, cursp(), arr_reg, 0);

4607+

push();

4608+

if (offset == 0) {

4609+

gen_move(s, cursp(), idx_reg, 0);

4610+

}

4611+

else {

4612+

gen_move(s, cursp(), idx_reg, 0);

4613+

push();

4614+

gen_int(s, cursp(), offset);

4615+

push(); push(); pop(); pop(); pop();

4616+

genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_OPSYM_2(s->mrb, add)), 1);

4617+

}

4618+

push(); push(); pop(); pop(); pop();

4619+

genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_OPSYM_2(s->mrb, aref)), 1);

4620+

/* Match element pattern - on fail, try next index */

4621+

codegen_pattern(s, elem->car, cursp(), &match_fail);

4622+

}

4623+4624+

/* All elements matched - bind pre and post if named */

4625+

if (pat_find->pre && pat_find->pre != (node*)-1) {

4626+

struct mrb_ast_pat_var_node *pre_var = pat_var_node(pat_find->pre);

4627+

if (pre_var->name) {

4628+

int var_idx = lv_idx(s, pre_var->name);

4629+

/* pre = arr[0...idx] (exclusive range) */

4630+

/* Following the NODE_PAT_ARRAY pattern exactly */

4631+

gen_move(s, cursp(), arr_reg, 0); /* arr at cursp */

4632+

push();

4633+

gen_int(s, cursp(), 0); /* start=0 at cursp */

4634+

push();

4635+

gen_move(s, cursp(), idx_reg, 0); /* end=idx at cursp */

4636+

/* start at cursp-1, end at cursp; create exclusive range at cursp-1 */

4637+

genop_1(s, OP_RANGE_EXC, cursp() - 1);

4638+

/* arr at cursp-2, range at cursp-1 */

4639+

pop(); /* cursp now at range position */

4640+

pop(); /* cursp now at arr position */

4641+

genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_OPSYM_2(s->mrb, aref)), 1);

4642+

if (var_idx > 0) {

4643+

gen_move(s, var_idx, cursp(), 1);

4644+

}

4645+

}

4646+

}

4647+4648+

if (pat_find->post && pat_find->post != (node*)-1) {

4649+

struct mrb_ast_pat_var_node *post_var = pat_var_node(pat_find->post);

4650+

if (post_var->name) {

4651+

int var_idx = lv_idx(s, post_var->name);

4652+

/* post = arr[(idx+elems_len)..-1] (inclusive range) */

4653+

/* Following the NODE_PAT_ARRAY pattern exactly */

4654+

gen_move(s, cursp(), arr_reg, 0); /* arr at cursp */

4655+

push();

4656+

/* Compute idx + elems_len for start index */

4657+

gen_move(s, cursp(), idx_reg, 0); /* idx at cursp */

4658+

push();

4659+

gen_int(s, cursp(), elems_len); /* elems_len at cursp */

4660+

push(); push(); pop(); pop(); pop();

4661+

genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_OPSYM_2(s->mrb, add)), 1);

4662+

/* start index (idx+elems_len) now at cursp */

4663+

push();

4664+

gen_int(s, cursp(), -1); /* end=-1 at cursp */

4665+

/* start at cursp-1, end at cursp; create inclusive range at cursp-1 */

4666+

genop_1(s, OP_RANGE_INC, cursp() - 1);

4667+

/* arr at cursp-2, range at cursp-1 */

4668+

pop(); /* cursp now at range position */

4669+

pop(); /* cursp now at arr position */

4670+

genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_OPSYM_2(s->mrb, aref)), 1);

4671+

if (var_idx > 0) {

4672+

gen_move(s, var_idx, cursp(), 1);

4673+

}

4674+

}

4675+

}

4676+4677+

/* Jump to success (end of find pattern) */

4678+

loop_end = genjmp(s, OP_JMP, JMPLINK_START);

4679+4680+

/* Match failed - increment index and try again */

4681+

dispatch_linked(s, match_fail);

4682+

gen_move(s, cursp(), idx_reg, 0);

4683+

push();

4684+

gen_int(s, cursp(), 1);

4685+

push(); push(); pop(); pop(); pop();

4686+

genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_OPSYM_2(s->mrb, add)), 1);

4687+

gen_move(s, idx_reg, cursp(), 0);

4688+

genjmp(s, OP_JMP, loop_start);

4689+4690+

/* Success exit point */

4691+

dispatch(s, loop_end);

4692+4693+

pop(); /* idx_reg */

4694+

pop(); /* arr_reg */

4695+

}

4696+

break;

4697+45414698

case NODE_PAT_HASH:

45424699

{

45434700

struct mrb_ast_pat_hash_node *pat_hash = pat_hash_node(pattern);

Read the original on github.com ↗