Imported Upstream version 1.46.0
[platform/upstream/nghttp2.git] / third-party / mruby / src / array.c
index 707820a..dae2fbf 100644 (file)
@@ -9,6 +9,8 @@
 #include <mruby/class.h>
 #include <mruby/string.h>
 #include <mruby/range.h>
+#include <mruby/proc.h>
+#include <mruby/opcode.h>
 #include "value_array.h"
 
 #define ARY_DEFAULT_LEN   4
@@ -120,9 +122,7 @@ ary_fill_with_nil(mrb_value *ptr, mrb_int size)
 static void
 ary_modify_check(mrb_state *mrb, struct RArray *a)
 {
-  if (MRB_FROZEN_P(a)) {
-    mrb_raise(mrb, E_FROZEN_ERROR, "can't modify frozen array");
-  }
+  mrb_check_frozen(mrb, a);
 }
 
 static void
@@ -388,7 +388,7 @@ ary_replace(mrb_state *mrb, struct RArray *a, struct RArray *b)
     mrb_write_barrier(mrb, (struct RBasic*)a);
     return;
   }
-  if (!MRB_FROZEN_P(b) && len > ARY_REPLACE_SHARED_MIN) {
+  if (!mrb_frozen_p(b) && len > ARY_REPLACE_SHARED_MIN) {
     ary_make_shared(mrb, b);
     goto shared_b;
   }
@@ -631,11 +631,13 @@ mrb_ary_unshift_m(mrb_state *mrb, mrb_value self)
     ptr = a->as.heap.ptr;
   }
   else {
+    mrb_bool same = vals == ARY_PTR(a);
     ary_modify(mrb, a);
     if (ARY_CAPA(a) < len + alen)
       ary_expand_capa(mrb, a, len + alen);
     ptr = ARY_PTR(a);
     value_move(ptr + alen, ptr, len);
+    if (same) vals = ptr;
   }
   array_copy(ptr, vals, alen);
   ARY_SET_LEN(a, len+alen);
@@ -670,7 +672,7 @@ mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val)
   if (n < 0) {
     n += len;
     if (n < 0) {
-      mrb_raisef(mrb, E_INDEX_ERROR, "index %S out of array", mrb_fixnum_value(n - len));
+      mrb_raisef(mrb, E_INDEX_ERROR, "index %i out of array", n - len);
     }
   }
   if (len <= n) {
@@ -702,7 +704,7 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val
   ary_modify(mrb, a);
 
   /* len check */
-  if (len < 0) mrb_raisef(mrb, E_INDEX_ERROR, "negative length (%S)", mrb_fixnum_value(len));
+  if (len < 0) mrb_raisef(mrb, E_INDEX_ERROR, "negative length (%i)", len);
 
   /* range check */
   if (head < 0) {
@@ -730,13 +732,17 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val
       argv = ARY_PTR(r);
     }
   }
+  else if (mrb_undef_p(rpl)) {
+    argc = 0;
+    argv = NULL;
+  }
   else {
     argc = 1;
     argv = &rpl;
   }
   if (head >= alen) {
     if (head > ARY_MAX_SIZE - argc) {
-      mrb_raisef(mrb, E_INDEX_ERROR, "index %S too big", mrb_fixnum_value(head));
+      mrb_raisef(mrb, E_INDEX_ERROR, "index %i too big", head);
     }
     len = head + argc;
     if (len > ARY_CAPA(a)) {
@@ -752,7 +758,7 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val
     mrb_int newlen;
 
     if (alen - len > ARY_MAX_SIZE - argc) {
-      mrb_raisef(mrb, E_INDEX_ERROR, "index %S too big", mrb_fixnum_value(alen + argc - len));
+      mrb_raisef(mrb, E_INDEX_ERROR, "index %i too big", alen + argc - len);
     }
     newlen = alen + argc - len;
     if (newlen > ARY_CAPA(a)) {
@@ -802,6 +808,13 @@ ary_subseq(mrb_state *mrb, struct RArray *a, mrb_int beg, mrb_int len)
   return mrb_obj_value(b);
 }
 
+mrb_value
+mrb_ary_subseq(mrb_state *mrb, mrb_value ary, mrb_int beg, mrb_int len)
+{
+  struct RArray *a = mrb_ary_ptr(ary);
+  return ary_subseq(mrb, a, beg, len);
+}
+
 static mrb_int
 aget_index(mrb_state *mrb, mrb_value index)
 {
@@ -853,14 +866,16 @@ static mrb_value
 mrb_ary_aget(mrb_state *mrb, mrb_value self)
 {
   struct RArray *a = mrb_ary_ptr(self);
-  mrb_int i, len, alen;
+  mrb_int i;
+  mrb_int len, alen;
   mrb_value index;
 
-  if (mrb_get_args(mrb, "o|i", &index, &len) == 1) {
+  if (mrb_get_argc(mrb) == 1) {
+    index = mrb_get_arg1(mrb);
     switch (mrb_type(index)) {
       /* a[n..m] */
     case MRB_TT_RANGE:
-      if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == 1) {
+      if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == MRB_RANGE_OK) {
         return ary_subseq(mrb, a, i, len);
       }
       else {
@@ -873,6 +888,7 @@ mrb_ary_aget(mrb_state *mrb, mrb_value self)
     }
   }
 
+  mrb_get_args(mrb, "oi", &index, &len);
   i = aget_index(mrb, index);
   alen = ARY_LEN(a);
   if (i < 0) i += alen;
@@ -926,22 +942,26 @@ mrb_ary_aset(mrb_state *mrb, mrb_value self)
   mrb_int i, len;
 
   mrb_ary_modify(mrb, mrb_ary_ptr(self));
-  if (mrb_get_args(mrb, "oo|o", &v1, &v2, &v3) == 2) {
+  if (mrb_get_argc(mrb) == 2) {
+    mrb_value *vs = mrb_get_argv(mrb);
+    v1 = vs[0]; v2 = vs[1];
+
     /* a[n..m] = v */
     switch (mrb_range_beg_len(mrb, v1, &i, &len, RARRAY_LEN(self), FALSE)) {
-    case 0:                   /* not range */
+    case MRB_RANGE_TYPE_MISMATCH:
       mrb_ary_set(mrb, self, aget_index(mrb, v1), v2);
       break;
-    case 1:                   /* range */
+    case MRB_RANGE_OK:
       mrb_ary_splice(mrb, self, i, len, v2);
       break;
-    case 2:                   /* out of range */
-      mrb_raisef(mrb, E_RANGE_ERROR, "%S out of range", v1);
+    case MRB_RANGE_OUT:
+      mrb_raisef(mrb, E_RANGE_ERROR, "%v out of range", v1);
       break;
     }
     return v2;
   }
 
+  mrb_get_args(mrb, "ooo", &v1, &v2, &v3);
   /* a[n,m] = v */
   mrb_ary_splice(mrb, self, aget_index(mrb, v1), aget_index(mrb, v2), v3);
   return v3;
@@ -1025,10 +1045,9 @@ mrb_ary_last(mrb_state *mrb, mrb_value self)
 static mrb_value
 mrb_ary_index_m(mrb_state *mrb, mrb_value self)
 {
-  mrb_value obj;
+  mrb_value obj = mrb_get_arg1(mrb);
   mrb_int i;
 
-  mrb_get_args(mrb, "o", &obj);
   for (i = 0; i < RARRAY_LEN(self); i++) {
     if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
       return mrb_fixnum_value(i);
@@ -1040,10 +1059,9 @@ mrb_ary_index_m(mrb_state *mrb, mrb_value self)
 static mrb_value
 mrb_ary_rindex_m(mrb_state *mrb, mrb_value self)
 {
-  mrb_value obj;
+  mrb_value obj = mrb_get_arg1(mrb);
   mrb_int i, len;
 
-  mrb_get_args(mrb, "o", &obj);
   for (i = RARRAY_LEN(self) - 1; i >= 0; i--) {
     if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
       return mrb_fixnum_value(i);
@@ -1105,7 +1123,6 @@ mrb_ary_clear(mrb_state *mrb, mrb_value self)
 static mrb_value
 mrb_ary_clear_m(mrb_state *mrb, mrb_value self)
 {
-  mrb_get_args(mrb, "");
   return mrb_ary_clear(mrb, self);
 }
 
@@ -1218,9 +1235,8 @@ mrb_ary_join_m(mrb_state *mrb, mrb_value ary)
 static mrb_value
 mrb_ary_eq(mrb_state *mrb, mrb_value ary1)
 {
-  mrb_value ary2;
+  mrb_value ary2 = mrb_get_arg1(mrb);
 
-  mrb_get_args(mrb, "o", &ary2);
   if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value();
   if (!mrb_array_p(ary2)) {
     return mrb_false_value();
@@ -1233,9 +1249,8 @@ mrb_ary_eq(mrb_state *mrb, mrb_value ary1)
 static mrb_value
 mrb_ary_cmp(mrb_state *mrb, mrb_value ary1)
 {
-  mrb_value ary2;
+  mrb_value ary2 = mrb_get_arg1(mrb);
 
-  mrb_get_args(mrb, "o", &ary2);
   if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_fixnum_value(0);
   if (!mrb_array_p(ary2)) {
     return mrb_nil_value();
@@ -1248,7 +1263,6 @@ mrb_ary_cmp(mrb_state *mrb, mrb_value ary1)
 static mrb_value
 mrb_ary_svalue(mrb_state *mrb, mrb_value ary)
 {
-  mrb_get_args(mrb, "");
   switch (RARRAY_LEN(ary)) {
   case 0:
     return mrb_nil_value();
@@ -1259,46 +1273,96 @@ mrb_ary_svalue(mrb_state *mrb, mrb_value ary)
   }
 }
 
+static const mrb_code each_iseq[] = {
+  OP_ENTER, 0x0, 0x00, 0x1,  /* OP_ENTER     0:0:0:0:0:0:1 */
+  OP_JMPIF, 0x1, 0x0, 19,    /* OP_JMPIF     R1  19 */
+  OP_LOADSELF, 0x3,          /* OP_LOADSELF  R3 */
+  OP_LOADSYM, 0x4, 0x0,      /* OP_LOADSYM   R4  :each*/
+  OP_SEND, 0x3, 0x1, 0x1,    /* OP_SEND      R3  :to_enum   1 */
+  OP_RETURN, 0x3,            /* OP_RETURN    R3 */
+  OP_LOADI_0, 0x2,           /* OP_LOADI_0   R2 */
+  OP_JMP, 0x0, 43,           /* OP_JMP       49 */
+  OP_MOVE, 0x3, 0x1,         /* OP_MOVE      R3  R1 */
+  OP_LOADSELF, 0x4,          /* OP_LOADSELF  R4 */
+  OP_MOVE, 0x5, 0x2,         /* OP_MOVE      R5  R2 */
+  OP_SEND, 0x4, 0x2, 0x1,    /* OP_SEND      R4  :[]        1 */
+  OP_SEND, 0x3, 0x3, 0x1,    /* OP_SEND      R3  :call      1 */
+  OP_ADDI, 0x2, 1,           /* OP_ADDI      R3  1 */
+  OP_MOVE, 0x3, 0x2,         /* OP_MOVE      R3  R2 */
+  OP_LOADSELF, 0x4,          /* OP_LOADSELF  R4 */
+  OP_SEND, 0x4, 0x4, 0x0,    /* OP_SEND      R4  :length    0 */
+  OP_LT, 0x3,                /* OP_LT        R3 */
+  OP_JMPIF, 0x3, 0x0, 24,    /* OP_JMPIF     R3  24 */
+  OP_RETURN, 0x0             /* OP_RETURN    R3 */
+};
+
+static void
+init_ary_each(mrb_state *mrb, struct RClass *ary)
+{
+  struct RProc *p;
+  mrb_method_t m;
+  mrb_irep *each_irep = (mrb_irep*)mrb_malloc(mrb, sizeof(mrb_irep));
+  static const mrb_irep mrb_irep_zero = { 0 };
+
+  *each_irep = mrb_irep_zero;
+  each_irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*5);
+  each_irep->syms[0] = mrb_intern_lit(mrb, "each");
+  each_irep->syms[1] = mrb_intern_lit(mrb, "to_enum");
+  each_irep->syms[2] = mrb_intern_lit(mrb, "[]");
+  each_irep->syms[3] = mrb_intern_lit(mrb, "call");
+  each_irep->syms[4] = mrb_intern_lit(mrb, "length");
+  each_irep->slen = 5;
+  each_irep->flags = MRB_ISEQ_NO_FREE;
+  each_irep->iseq = each_iseq;
+  each_irep->ilen = sizeof(each_iseq);
+  each_irep->nregs = 7;
+  each_irep->nlocals = 3;
+  p = mrb_proc_new(mrb, each_irep);
+  p->flags |= MRB_PROC_SCOPE | MRB_PROC_STRICT;
+  MRB_METHOD_FROM_PROC(m, p);
+  mrb_define_method_raw(mrb, ary, mrb_intern_lit(mrb, "each"), m);
+}
+
 void
 mrb_init_array(mrb_state *mrb)
 {
   struct RClass *a;
 
-  mrb->array_class = a = mrb_define_class(mrb, "Array", mrb->object_class);            /* 15.2.12 */
+  mrb->array_class = a = mrb_define_class(mrb, "Array", mrb->object_class);              /* 15.2.12 */
   MRB_SET_INSTANCE_TT(a, MRB_TT_ARRAY);
 
-  mrb_define_class_method(mrb, a, "[]",        mrb_ary_s_create,     MRB_ARGS_ANY());  /* 15.2.12.4.1 */
-
-  mrb_define_method(mrb, a, "+",               mrb_ary_plus,         MRB_ARGS_REQ(1)); /* 15.2.12.5.1  */
-  mrb_define_method(mrb, a, "*",               mrb_ary_times,        MRB_ARGS_REQ(1)); /* 15.2.12.5.2  */
-  mrb_define_method(mrb, a, "<<",              mrb_ary_push_m,       MRB_ARGS_REQ(1)); /* 15.2.12.5.3  */
-  mrb_define_method(mrb, a, "[]",              mrb_ary_aget,         MRB_ARGS_ANY());  /* 15.2.12.5.4  */
-  mrb_define_method(mrb, a, "[]=",             mrb_ary_aset,         MRB_ARGS_ANY());  /* 15.2.12.5.5  */
-  mrb_define_method(mrb, a, "clear",           mrb_ary_clear_m,      MRB_ARGS_NONE()); /* 15.2.12.5.6  */
-  mrb_define_method(mrb, a, "concat",          mrb_ary_concat_m,     MRB_ARGS_REQ(1)); /* 15.2.12.5.8  */
-  mrb_define_method(mrb, a, "delete_at",       mrb_ary_delete_at,    MRB_ARGS_REQ(1)); /* 15.2.12.5.9  */
-  mrb_define_method(mrb, a, "empty?",          mrb_ary_empty_p,      MRB_ARGS_NONE()); /* 15.2.12.5.12 */
-  mrb_define_method(mrb, a, "first",           mrb_ary_first,        MRB_ARGS_OPT(1)); /* 15.2.12.5.13 */
-  mrb_define_method(mrb, a, "index",           mrb_ary_index_m,      MRB_ARGS_REQ(1)); /* 15.2.12.5.14 */
-  mrb_define_method(mrb, a, "initialize_copy", mrb_ary_replace_m,    MRB_ARGS_REQ(1)); /* 15.2.12.5.16 */
-  mrb_define_method(mrb, a, "join",            mrb_ary_join_m,       MRB_ARGS_ANY());  /* 15.2.12.5.17 */
-  mrb_define_method(mrb, a, "last",            mrb_ary_last,         MRB_ARGS_ANY());  /* 15.2.12.5.18 */
-  mrb_define_method(mrb, a, "length",          mrb_ary_size,         MRB_ARGS_NONE()); /* 15.2.12.5.19 */
-  mrb_define_method(mrb, a, "pop",             mrb_ary_pop,          MRB_ARGS_NONE()); /* 15.2.12.5.21 */
-  mrb_define_method(mrb, a, "push",            mrb_ary_push_m,       MRB_ARGS_ANY());  /* 15.2.12.5.22 */
-  mrb_define_method(mrb, a, "append",          mrb_ary_push_m,       MRB_ARGS_ANY());
-  mrb_define_method(mrb, a, "replace",         mrb_ary_replace_m,    MRB_ARGS_REQ(1)); /* 15.2.12.5.23 */
-  mrb_define_method(mrb, a, "reverse",         mrb_ary_reverse,      MRB_ARGS_NONE()); /* 15.2.12.5.24 */
-  mrb_define_method(mrb, a, "reverse!",        mrb_ary_reverse_bang, MRB_ARGS_NONE()); /* 15.2.12.5.25 */
-  mrb_define_method(mrb, a, "rindex",          mrb_ary_rindex_m,     MRB_ARGS_REQ(1)); /* 15.2.12.5.26 */
-  mrb_define_method(mrb, a, "shift",           mrb_ary_shift,        MRB_ARGS_NONE()); /* 15.2.12.5.27 */
-  mrb_define_method(mrb, a, "size",            mrb_ary_size,         MRB_ARGS_NONE()); /* 15.2.12.5.28 */
-  mrb_define_method(mrb, a, "slice",           mrb_ary_aget,         MRB_ARGS_ANY());  /* 15.2.12.5.29 */
-  mrb_define_method(mrb, a, "unshift",         mrb_ary_unshift_m,    MRB_ARGS_ANY());  /* 15.2.12.5.30 */
-  mrb_define_method(mrb, a, "prepend",         mrb_ary_unshift_m,    MRB_ARGS_ANY());
+  mrb_define_class_method(mrb, a, "[]",        mrb_ary_s_create,     MRB_ARGS_ANY());    /* 15.2.12.4.1 */
+
+  mrb_define_method(mrb, a, "+",               mrb_ary_plus,         MRB_ARGS_REQ(1));   /* 15.2.12.5.1  */
+  mrb_define_method(mrb, a, "*",               mrb_ary_times,        MRB_ARGS_REQ(1));   /* 15.2.12.5.2  */
+  mrb_define_method(mrb, a, "<<",              mrb_ary_push_m,       MRB_ARGS_REQ(1));   /* 15.2.12.5.3  */
+  mrb_define_method(mrb, a, "[]",              mrb_ary_aget,         MRB_ARGS_ARG(1,1)); /* 15.2.12.5.4  */
+  mrb_define_method(mrb, a, "[]=",             mrb_ary_aset,         MRB_ARGS_ARG(2,1)); /* 15.2.12.5.5  */
+  mrb_define_method(mrb, a, "clear",           mrb_ary_clear_m,      MRB_ARGS_NONE());   /* 15.2.12.5.6  */
+  mrb_define_method(mrb, a, "concat",          mrb_ary_concat_m,     MRB_ARGS_REQ(1));   /* 15.2.12.5.8  */
+  mrb_define_method(mrb, a, "delete_at",       mrb_ary_delete_at,    MRB_ARGS_REQ(1));   /* 15.2.12.5.9  */
+  mrb_define_method(mrb, a, "empty?",          mrb_ary_empty_p,      MRB_ARGS_NONE());   /* 15.2.12.5.12 */
+  mrb_define_method(mrb, a, "first",           mrb_ary_first,        MRB_ARGS_OPT(1));   /* 15.2.12.5.13 */
+  mrb_define_method(mrb, a, "index",           mrb_ary_index_m,      MRB_ARGS_REQ(1));   /* 15.2.12.5.14 */
+  mrb_define_method(mrb, a, "initialize_copy", mrb_ary_replace_m,    MRB_ARGS_REQ(1));   /* 15.2.12.5.16 */
+  mrb_define_method(mrb, a, "join",            mrb_ary_join_m,       MRB_ARGS_OPT(1));   /* 15.2.12.5.17 */
+  mrb_define_method(mrb, a, "last",            mrb_ary_last,         MRB_ARGS_OPT(1));   /* 15.2.12.5.18 */
+  mrb_define_method(mrb, a, "length",          mrb_ary_size,         MRB_ARGS_NONE());   /* 15.2.12.5.19 */
+  mrb_define_method(mrb, a, "pop",             mrb_ary_pop,          MRB_ARGS_NONE());   /* 15.2.12.5.21 */
+  mrb_define_method(mrb, a, "push",            mrb_ary_push_m,       MRB_ARGS_ANY());    /* 15.2.12.5.22 */
+  mrb_define_method(mrb, a, "replace",         mrb_ary_replace_m,    MRB_ARGS_REQ(1));   /* 15.2.12.5.23 */
+  mrb_define_method(mrb, a, "reverse",         mrb_ary_reverse,      MRB_ARGS_NONE());   /* 15.2.12.5.24 */
+  mrb_define_method(mrb, a, "reverse!",        mrb_ary_reverse_bang, MRB_ARGS_NONE());   /* 15.2.12.5.25 */
+  mrb_define_method(mrb, a, "rindex",          mrb_ary_rindex_m,     MRB_ARGS_REQ(1));   /* 15.2.12.5.26 */
+  mrb_define_method(mrb, a, "shift",           mrb_ary_shift,        MRB_ARGS_NONE());   /* 15.2.12.5.27 */
+  mrb_define_method(mrb, a, "size",            mrb_ary_size,         MRB_ARGS_NONE());   /* 15.2.12.5.28 */
+  mrb_define_method(mrb, a, "slice",           mrb_ary_aget,         MRB_ARGS_ARG(1,1)); /* 15.2.12.5.29 */
+  mrb_define_method(mrb, a, "unshift",         mrb_ary_unshift_m,    MRB_ARGS_ANY());    /* 15.2.12.5.30 */
 
   mrb_define_method(mrb, a, "__ary_eq",        mrb_ary_eq,           MRB_ARGS_REQ(1));
   mrb_define_method(mrb, a, "__ary_cmp",       mrb_ary_cmp,          MRB_ARGS_REQ(1));
-  mrb_define_method(mrb, a, "__ary_index",     mrb_ary_index_m,      MRB_ARGS_REQ(1)); /* kept for mruby-array-ext */
+  mrb_define_method(mrb, a, "__ary_index",     mrb_ary_index_m,      MRB_ARGS_REQ(1));   /* kept for mruby-array-ext */
   mrb_define_method(mrb, a, "__svalue",        mrb_ary_svalue,       MRB_ARGS_NONE());
+
+  init_ary_each(mrb, a);
 }