GitHub

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

44104410

}

44114411

break;

441244124413+

case NODE_PAT_ARRAY:

4414+

{

4415+

struct mrb_ast_pat_array_node *pat_arr = pat_array_node(pattern);

4416+

int pre_len = 0, post_len = 0;

4417+

int arr_reg = cursp();

4418+

node *elem;

4419+

int i;

4420+4421+

/* Count pre and post elements */

4422+

for (elem = pat_arr->pre; elem; elem = elem->cdr) pre_len++;

4423+

for (elem = pat_arr->post; elem; elem = elem->cdr) post_len++;

4424+4425+

/* Call deconstruct on target */

4426+

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

4427+

push();

4428+

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

4429+4430+

/* Check length constraints */

4431+

if (pat_arr->rest == 0) {

4432+

/* No rest: exact length match */

4433+

/* Generate: arr.size == pre_len */

4434+

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

4435+

push();

4436+

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

4437+

gen_int(s, cursp(), pre_len);

4438+

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

4439+

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

4440+

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

4441+

*fail_pos = tmp;

4442+

}

4443+

else {

4444+

/* Has rest: minimum length check */

4445+

int min_len = pre_len + post_len;

4446+

if (min_len > 0) {

4447+

/* Generate: arr.size >= min_len */

4448+

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

4449+

push();

4450+

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

4451+

gen_int(s, cursp(), min_len);

4452+

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

4453+

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

4454+

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

4455+

*fail_pos = tmp;

4456+

}

4457+

}

4458+4459+

/* Match pre-rest elements */

4460+

i = 0;

4461+

for (elem = pat_arr->pre; elem; elem = elem->cdr, i++) {

4462+

/* Get arr[i] */

4463+

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

4464+

push();

4465+

gen_int(s, cursp(), i);

4466+

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

4467+

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

4468+

/* Match element pattern */

4469+

codegen_pattern(s, elem->car, cursp(), fail_pos);

4470+

}

4471+4472+

/* Bind rest elements if rest is a variable */

4473+

if (pat_arr->rest && pat_arr->rest != (node*)-1) {

4474+

struct mrb_ast_pat_var_node *rest_var = pat_var_node(pat_arr->rest);

4475+

if (rest_var->name) {

4476+

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

4477+

/* Generate: arr[pre_len..-(post_len+1)] or arr[pre_len..-1] if no post */

4478+

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

4479+

push();

4480+

gen_int(s, cursp(), pre_len); /* start at cursp */

4481+

push();

4482+

if (post_len > 0) {

4483+

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

4484+

}

4485+

else {

4486+

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

4487+

}

4488+

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

4489+

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

4490+

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

4491+

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

4492+

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

4493+

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

4494+

if (var_idx > 0) {

4495+

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

4496+

}

4497+

}

4498+

}

4499+4500+

/* Match post-rest elements */

4501+

i = -post_len;

4502+

for (elem = pat_arr->post; elem; elem = elem->cdr, i++) {

4503+

/* Get arr[i] (negative index from end) */

4504+

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

4505+

push();

4506+

gen_int(s, cursp(), i);

4507+

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

4508+

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

4509+

/* Match element pattern */

4510+

codegen_pattern(s, elem->car, cursp(), fail_pos);

4511+

}

4512+4513+

pop(); /* Pop arr_reg */

4514+

}

4515+

break;

4516+44134517

default:

44144518

raise_error(s, "unsupported pattern type");

44154519

break;

Read the original on github.com ↗