@@ -4410,6 +4410,110 @@ codegen_pattern(codegen_scope *s, node *pattern, int target, uint32_t *fail_pos)
44104410 }
44114411break;
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+44134517default:
44144518raise_error(s, "unsupported pattern type");
44154519break;