Ignore:
Timestamp:
Jul 9, 2020, 8:51:43 AM (4 years ago)
Author:
coas-nagasima
Message:

mrubyを2.1.1に更新

Location:
EcnlProtoTool/trunk/mruby-2.1.1
Files:
1 deleted
26 edited
1 moved

Legend:

Unmodified
Added
Removed
  • EcnlProtoTool/trunk/mruby-2.1.1/src/array.c

    r331 r439  
    1010#include <mruby/string.h>
    1111#include <mruby/range.h>
     12#include <mruby/proc.h>
     13#include <mruby/opcode.h>
    1214#include "value_array.h"
    1315
     
    1517#define ARY_SHRINK_RATIO  5 /* must be larger than 2 */
    1618#define ARY_C_MAX_SIZE (SIZE_MAX / sizeof(mrb_value))
    17 #define ARY_MAX_SIZE ((ARY_C_MAX_SIZE < (size_t)MRB_INT_MAX) ? (mrb_int)ARY_C_MAX_SIZE : MRB_INT_MAX-1)
     19#define ARY_MAX_SIZE ((mrb_int)((ARY_C_MAX_SIZE < (size_t)MRB_INT_MAX) ? ARY_C_MAX_SIZE : MRB_INT_MAX-1))
    1820
    1921static struct RArray*
     
    2931
    3032  a = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class);
    31   a->ptr = (mrb_value *)mrb_malloc(mrb, blen);
    32   a->aux.capa = capa;
    33   a->len = 0;
     33  if (capa <= MRB_ARY_EMBED_LEN_MAX) {
     34    ARY_SET_EMBED_LEN(a, 0);
     35  }
     36  else {
     37    a->as.heap.ptr = (mrb_value *)mrb_malloc(mrb, blen);
     38    a->as.heap.aux.capa = capa;
     39    a->as.heap.len = 0;
     40  }
    3441
    3542  return a;
     
    7380}
    7481
     82static struct RArray*
     83ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals)
     84{
     85  struct RArray *a = ary_new_capa(mrb, size);
     86
     87  array_copy(ARY_PTR(a), vals, size);
     88  ARY_SET_LEN(a, size);
     89
     90  return a;
     91}
     92
    7593MRB_API mrb_value
    7694mrb_ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals)
    7795{
    78   struct RArray *a = ary_new_capa(mrb, size);
    79 
    80   array_copy(a->ptr, vals, size);
    81   a->len = size;
    82 
     96  struct RArray *a = ary_new_from_values(mrb, size, vals);
    8397  return mrb_obj_value(a);
    8498}
     
    90104
    91105  a = ary_new_capa(mrb, 2);
    92   a->ptr[0] = car;
    93   a->ptr[1] = cdr;
    94   a->len = 2;
     106  ARY_PTR(a)[0] = car;
     107  ARY_PTR(a)[1] = cdr;
     108  ARY_SET_LEN(a, 2);
    95109  return mrb_obj_value(a);
    96110}
     
    107121
    108122static void
     123ary_modify_check(mrb_state *mrb, struct RArray *a)
     124{
     125  mrb_check_frozen(mrb, a);
     126}
     127
     128static void
    109129ary_modify(mrb_state *mrb, struct RArray *a)
    110130{
    111   if (MRB_FROZEN_P(a)) {
    112     mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen array");
    113   }
     131  ary_modify_check(mrb, a);
    114132
    115133  if (ARY_SHARED_P(a)) {
    116     mrb_shared_array *shared = a->aux.shared;
    117 
    118     if (shared->refcnt == 1 && a->ptr == shared->ptr) {
    119       a->ptr = shared->ptr;
    120       a->aux.capa = a->len;
     134    mrb_shared_array *shared = a->as.heap.aux.shared;
     135
     136    if (shared->refcnt == 1 && a->as.heap.ptr == shared->ptr) {
     137      a->as.heap.ptr = shared->ptr;
     138      a->as.heap.aux.capa = a->as.heap.len;
    121139      mrb_free(mrb, shared);
    122140    }
     
    125143      mrb_int len;
    126144
    127       p = a->ptr;
    128       len = a->len * sizeof(mrb_value);
     145      p = a->as.heap.ptr;
     146      len = a->as.heap.len * sizeof(mrb_value);
    129147      ptr = (mrb_value *)mrb_malloc(mrb, len);
    130148      if (p) {
    131         array_copy(ptr, p, a->len);
     149        array_copy(ptr, p, a->as.heap.len);
    132150      }
    133       a->ptr = ptr;
    134       a->aux.capa = a->len;
     151      a->as.heap.ptr = ptr;
     152      a->as.heap.aux.capa = a->as.heap.len;
    135153      mrb_ary_decref(mrb, shared);
    136154    }
     
    149167ary_make_shared(mrb_state *mrb, struct RArray *a)
    150168{
    151   if (!ARY_SHARED_P(a)) {
     169  if (!ARY_SHARED_P(a) && !ARY_EMBED_P(a)) {
    152170    mrb_shared_array *shared = (mrb_shared_array *)mrb_malloc(mrb, sizeof(mrb_shared_array));
     171    mrb_value *ptr = a->as.heap.ptr;
     172    mrb_int len = a->as.heap.len;
    153173
    154174    shared->refcnt = 1;
    155     if (a->aux.capa > a->len) {
    156       a->ptr = shared->ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*a->len+1);
     175    if (a->as.heap.aux.capa > len) {
     176      a->as.heap.ptr = shared->ptr = (mrb_value *)mrb_realloc(mrb, ptr, sizeof(mrb_value)*len+1);
    157177    }
    158178    else {
    159       shared->ptr = a->ptr;
    160     }
    161     shared->len = a->len;
    162     a->aux.shared = shared;
     179      shared->ptr = ptr;
     180    }
     181    shared->len = len;
     182    a->as.heap.aux.shared = shared;
    163183    ARY_SET_SHARED_FLAG(a);
    164184  }
     
    168188ary_expand_capa(mrb_state *mrb, struct RArray *a, mrb_int len)
    169189{
    170   mrb_int capa = a->aux.capa;
    171 
    172   if (len > ARY_MAX_SIZE) {
     190  mrb_int capa = ARY_CAPA(a);
     191
     192  if (len > ARY_MAX_SIZE || len < 0) {
    173193  size_error:
    174194    mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
    175195  }
    176196
    177   if (capa == 0) {
     197  if (capa < ARY_DEFAULT_LEN) {
    178198    capa = ARY_DEFAULT_LEN;
    179199  }
     
    190210  }
    191211
    192   if (capa > a->aux.capa) {
    193     mrb_value *expanded_ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa);
    194 
    195     a->aux.capa = capa;
    196     a->ptr = expanded_ptr;
     212  if (ARY_EMBED_P(a)) {
     213    mrb_value *ptr = ARY_EMBED_PTR(a);
     214    mrb_int len = ARY_EMBED_LEN(a);
     215    mrb_value *expanded_ptr = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*capa);
     216
     217    ARY_UNSET_EMBED_FLAG(a);
     218    array_copy(expanded_ptr, ptr, len);
     219    a->as.heap.len = len;
     220    a->as.heap.aux.capa = capa;
     221    a->as.heap.ptr = expanded_ptr;
     222  }
     223  else if (capa > a->as.heap.aux.capa) {
     224    mrb_value *expanded_ptr = (mrb_value *)mrb_realloc(mrb, a->as.heap.ptr, sizeof(mrb_value)*capa);
     225
     226    a->as.heap.aux.capa = capa;
     227    a->as.heap.ptr = expanded_ptr;
    197228  }
    198229}
     
    201232ary_shrink_capa(mrb_state *mrb, struct RArray *a)
    202233{
    203   mrb_int capa = a->aux.capa;
    204 
     234
     235  mrb_int capa;
     236
     237  if (ARY_EMBED_P(a)) return;
     238
     239  capa = a->as.heap.aux.capa;
    205240  if (capa < ARY_DEFAULT_LEN * 2) return;
    206   if (capa <= a->len * ARY_SHRINK_RATIO) return;
     241  if (capa <= a->as.heap.len * ARY_SHRINK_RATIO) return;
    207242
    208243  do {
     
    212247      break;
    213248    }
    214   } while (capa > a->len * ARY_SHRINK_RATIO);
    215 
    216   if (capa > a->len && capa < a->aux.capa) {
    217     a->aux.capa = capa;
    218     a->ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa);
     249  } while (capa > a->as.heap.len * ARY_SHRINK_RATIO);
     250
     251  if (capa > a->as.heap.len && capa < a->as.heap.aux.capa) {
     252    a->as.heap.aux.capa = capa;
     253    a->as.heap.ptr = (mrb_value *)mrb_realloc(mrb, a->as.heap.ptr, sizeof(mrb_value)*capa);
    219254  }
    220255}
     
    229264  old_len = RARRAY_LEN(ary);
    230265  if (old_len != new_len) {
    231     a->len = new_len;
    232266    if (new_len < old_len) {
    233267      ary_shrink_capa(mrb, a);
     
    235269    else {
    236270      ary_expand_capa(mrb, a, new_len);
    237       ary_fill_with_nil(a->ptr + old_len, new_len - old_len);
    238     }
     271      ary_fill_with_nil(ARY_PTR(a) + old_len, new_len - old_len);
     272    }
     273    ARY_SET_LEN(a, new_len);
    239274  }
    240275
     
    250285  struct RArray *a;
    251286
    252   mrb_get_args(mrb, "*", &vals, &len);
     287  mrb_get_args(mrb, "*!", &vals, &len);
    253288  ary = mrb_ary_new_from_values(mrb, len, vals);
    254289  a = mrb_ary_ptr(ary);
     
    258293}
    259294
     295static void ary_replace(mrb_state*, struct RArray*, struct RArray*);
     296
    260297static void
    261298ary_concat(mrb_state *mrb, struct RArray *a, struct RArray *a2)
     
    263300  mrb_int len;
    264301
    265   if (a2->len > ARY_MAX_SIZE - a->len) {
     302  if (ARY_LEN(a) == 0) {
     303    ary_replace(mrb, a, a2);
     304    return;
     305  }
     306  if (ARY_LEN(a2) > ARY_MAX_SIZE - ARY_LEN(a)) {
    266307    mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
    267308  }
    268   len = a->len + a2->len;
     309  len = ARY_LEN(a) + ARY_LEN(a2);
    269310
    270311  ary_modify(mrb, a);
    271   if (a->aux.capa < len) {
     312  if (ARY_CAPA(a) < len) {
    272313    ary_expand_capa(mrb, a, len);
    273314  }
    274   array_copy(a->ptr+a->len, a2->ptr, a2->len);
     315  array_copy(ARY_PTR(a)+ARY_LEN(a), ARY_PTR(a2), ARY_LEN(a2));
    275316  mrb_write_barrier(mrb, (struct RBasic*)a);
    276   a->len = len;
     317  ARY_SET_LEN(a, len);
    277318}
    278319
     
    301342  struct RArray *a2;
    302343  mrb_value *ptr;
    303   mrb_int blen;
     344  mrb_int blen, len1;
    304345
    305346  mrb_get_args(mrb, "a", &ptr, &blen);
    306   if (ARY_MAX_SIZE - blen < a1->len) {
     347  if (ARY_MAX_SIZE - blen < ARY_LEN(a1)) {
    307348    mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
    308349  }
    309   a2 = ary_new_capa(mrb, a1->len + blen);
    310   array_copy(a2->ptr, a1->ptr, a1->len);
    311   array_copy(a2->ptr + a1->len, ptr, blen);
    312   a2->len = a1->len + blen;
     350  len1 = ARY_LEN(a1);
     351  a2 = ary_new_capa(mrb, len1 + blen);
     352  array_copy(ARY_PTR(a2), ARY_PTR(a1), len1);
     353  array_copy(ARY_PTR(a2) + len1, ptr, blen);
     354  ARY_SET_LEN(a2, len1+blen);
    313355
    314356  return mrb_obj_value(a2);
    315357}
    316358
     359#define ARY_REPLACE_SHARED_MIN 20
     360
    317361static void
    318 ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, mrb_int len)
    319 {
    320   ary_modify(mrb, a);
    321   if (a->aux.capa < len)
     362ary_replace(mrb_state *mrb, struct RArray *a, struct RArray *b)
     363{
     364  mrb_int len = ARY_LEN(b);
     365
     366  ary_modify_check(mrb, a);
     367  if (a == b) return;
     368  if (ARY_SHARED_P(a)) {
     369    mrb_ary_decref(mrb, a->as.heap.aux.shared);
     370    a->as.heap.aux.capa = 0;
     371    a->as.heap.len = 0;
     372    a->as.heap.ptr = NULL;
     373    ARY_UNSET_SHARED_FLAG(a);
     374  }
     375  if (ARY_SHARED_P(b)) {
     376  shared_b:
     377    if (ARY_EMBED_P(a)) {
     378      ARY_UNSET_EMBED_FLAG(a);
     379    }
     380    else {
     381      mrb_free(mrb, a->as.heap.ptr);
     382    }
     383    a->as.heap.ptr = b->as.heap.ptr;
     384    a->as.heap.len = len;
     385    a->as.heap.aux.shared = b->as.heap.aux.shared;
     386    a->as.heap.aux.shared->refcnt++;
     387    ARY_SET_SHARED_FLAG(a);
     388    mrb_write_barrier(mrb, (struct RBasic*)a);
     389    return;
     390  }
     391  if (!mrb_frozen_p(b) && len > ARY_REPLACE_SHARED_MIN) {
     392    ary_make_shared(mrb, b);
     393    goto shared_b;
     394  }
     395  if (ARY_CAPA(a) < len)
    322396    ary_expand_capa(mrb, a, len);
    323   array_copy(a->ptr, argv, len);
     397  array_copy(ARY_PTR(a), ARY_PTR(b), len);
    324398  mrb_write_barrier(mrb, (struct RBasic*)a);
    325   a->len = len;
     399  ARY_SET_LEN(a, len);
    326400}
    327401
     
    333407
    334408  if (a1 != a2) {
    335     ary_replace(mrb, a1, a2->ptr, a2->len);
     409    ary_replace(mrb, a1, a2);
    336410  }
    337411}
     
    354428  struct RArray *a2;
    355429  mrb_value *ptr;
    356   mrb_int times;
     430  mrb_int times, len1;
    357431
    358432  mrb_get_args(mrb, "i", &times);
     
    361435  }
    362436  if (times == 0) return mrb_ary_new(mrb);
    363   if (ARY_MAX_SIZE / times < a1->len) {
     437  if (ARY_MAX_SIZE / times < ARY_LEN(a1)) {
    364438    mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
    365439  }
    366   a2 = ary_new_capa(mrb, a1->len * times);
    367   ptr = a2->ptr;
     440  len1 = ARY_LEN(a1);
     441  a2 = ary_new_capa(mrb, len1 * times);
     442  ARY_SET_LEN(a2, len1 * times);
     443  ptr = ARY_PTR(a2);
    368444  while (times--) {
    369     array_copy(ptr, a1->ptr, a1->len);
    370     ptr += a1->len;
    371     a2->len += a1->len;
     445    array_copy(ptr, ARY_PTR(a1), len1);
     446    ptr += len1;
    372447  }
    373448
     
    379454{
    380455  struct RArray *a = mrb_ary_ptr(self);
    381 
    382   if (a->len > 1) {
     456  mrb_int len = ARY_LEN(a);
     457
     458  if (len > 1) {
    383459    mrb_value *p1, *p2;
    384460
    385461    ary_modify(mrb, a);
    386     p1 = a->ptr;
    387     p2 = a->ptr + a->len - 1;
     462    p1 = ARY_PTR(a);
     463    p2 = p1 + len - 1;
    388464
    389465    while (p1 < p2) {
     
    399475mrb_ary_reverse(mrb_state *mrb, mrb_value self)
    400476{
    401   struct RArray *a = mrb_ary_ptr(self), *b = ary_new_capa(mrb, a->len);
    402 
    403   if (a->len > 0) {
     477  struct RArray *a = mrb_ary_ptr(self), *b = ary_new_capa(mrb, ARY_LEN(a));
     478  mrb_int len = ARY_LEN(a);
     479
     480  if (len > 0) {
    404481    mrb_value *p1, *p2, *e;
    405482
    406     p1 = a->ptr;
    407     e  = p1 + a->len;
    408     p2 = b->ptr + a->len - 1;
     483    p1 = ARY_PTR(a);
     484    e  = p1 + len;
     485    p2 = ARY_PTR(b) + len - 1;
    409486    while (p1 < e) {
    410487      *p2-- = *p1++;
    411488    }
    412     b->len = a->len;
     489    ARY_SET_LEN(b, len);
    413490  }
    414491  return mrb_obj_value(b);
     
    419496{
    420497  struct RArray *a = mrb_ary_ptr(ary);
     498  mrb_int len = ARY_LEN(a);
    421499
    422500  ary_modify(mrb, a);
    423   if (a->len == a->aux.capa)
    424     ary_expand_capa(mrb, a, a->len + 1);
    425   a->ptr[a->len++] = elem;
     501  if (len == ARY_CAPA(a))
     502    ary_expand_capa(mrb, a, len + 1);
     503  ARY_PTR(a)[len] = elem;
     504  ARY_SET_LEN(a, len+1);
    426505  mrb_field_write_barrier_value(mrb, (struct RBasic*)a, elem);
    427506}
     
    431510{
    432511  mrb_value *argv;
    433   mrb_int len;
    434 
    435   mrb_get_args(mrb, "*", &argv, &len);
    436   while (len--) {
    437     mrb_ary_push(mrb, self, *argv++);
    438   }
     512  mrb_int len, len2, alen;
     513  struct RArray *a;
     514
     515  mrb_get_args(mrb, "*!", &argv, &alen);
     516  a = mrb_ary_ptr(self);
     517  ary_modify(mrb, a);
     518  len = ARY_LEN(a);
     519  len2 = len + alen;
     520  if (ARY_CAPA(a) < len2) {
     521    ary_expand_capa(mrb, a, len2);
     522  }
     523  array_copy(ARY_PTR(a)+len, argv, alen);
     524  ARY_SET_LEN(a, len2);
     525  mrb_write_barrier(mrb, (struct RBasic*)a);
    439526
    440527  return self;
     
    445532{
    446533  struct RArray *a = mrb_ary_ptr(ary);
    447 
    448   ary_modify(mrb, a);
    449   if (a->len == 0) return mrb_nil_value();
    450   return a->ptr[--a->len];
     534  mrb_int len = ARY_LEN(a);
     535
     536  ary_modify_check(mrb, a);
     537  if (len == 0) return mrb_nil_value();
     538  ARY_SET_LEN(a, len-1);
     539  return ARY_PTR(a)[len-1];
    451540}
    452541
     
    457546{
    458547  struct RArray *a = mrb_ary_ptr(self);
     548  mrb_int len = ARY_LEN(a);
    459549  mrb_value val;
    460550
    461   ary_modify(mrb, a);
    462   if (a->len == 0) return mrb_nil_value();
     551  ary_modify_check(mrb, a);
     552  if (len == 0) return mrb_nil_value();
    463553  if (ARY_SHARED_P(a)) {
    464554  L_SHIFT:
    465     val = a->ptr[0];
    466     a->ptr++;
    467     a->len--;
     555    val = a->as.heap.ptr[0];
     556    a->as.heap.ptr++;
     557    a->as.heap.len--;
    468558    return val;
    469559  }
    470   if (a->len > ARY_SHIFT_SHARED_MIN) {
     560  if (len > ARY_SHIFT_SHARED_MIN) {
    471561    ary_make_shared(mrb, a);
    472562    goto L_SHIFT;
    473563  }
    474564  else {
    475     mrb_value *ptr = a->ptr;
    476     mrb_int size = a->len;
     565    mrb_value *ptr = ARY_PTR(a);
     566    mrb_int size = len;
    477567
    478568    val = *ptr;
     
    481571      ++ptr;
    482572    }
    483     --a->len;
     573    ARY_SET_LEN(a, len-1);
    484574  }
    485575  return val;
     
    494584{
    495585  struct RArray *a = mrb_ary_ptr(self);
     586  mrb_int len = ARY_LEN(a);
    496587
    497588  if (ARY_SHARED_P(a)
    498       && a->aux.shared->refcnt == 1 /* shared only referenced from this array */
    499       && a->ptr - a->aux.shared->ptr >= 1) /* there's room for unshifted item */ {
    500     a->ptr--;
    501     a->ptr[0] = item;
     589      && a->as.heap.aux.shared->refcnt == 1 /* shared only referenced from this array */
     590      && a->as.heap.ptr - a->as.heap.aux.shared->ptr >= 1) /* there's room for unshifted item */ {
     591    a->as.heap.ptr--;
     592    a->as.heap.ptr[0] = item;
    502593  }
    503594  else {
     595    mrb_value *ptr;
     596
    504597    ary_modify(mrb, a);
    505     if (a->aux.capa < a->len + 1)
    506       ary_expand_capa(mrb, a, a->len + 1);
    507     value_move(a->ptr + 1, a->ptr, a->len);
    508     a->ptr[0] = item;
    509   }
    510   a->len++;
     598    if (ARY_CAPA(a) < len + 1)
     599      ary_expand_capa(mrb, a, len + 1);
     600    ptr = ARY_PTR(a);
     601    value_move(ptr + 1, ptr, len);
     602    ptr[0] = item;
     603  }
     604  ARY_SET_LEN(a, len+1);
    511605  mrb_field_write_barrier_value(mrb, (struct RBasic*)a, item);
    512606
     
    518612{
    519613  struct RArray *a = mrb_ary_ptr(self);
    520   mrb_value *vals;
    521   mrb_int len;
    522 
    523   mrb_get_args(mrb, "*", &vals, &len);
    524   if (len > ARY_MAX_SIZE - a->len) {
     614  mrb_value *vals, *ptr;
     615  mrb_int alen, len;
     616
     617  mrb_get_args(mrb, "*!", &vals, &alen);
     618  if (alen == 0) {
     619    ary_modify_check(mrb, a);
     620    return self;
     621  }
     622  len = ARY_LEN(a);
     623  if (alen > ARY_MAX_SIZE - len) {
    525624    mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
    526625  }
    527626  if (ARY_SHARED_P(a)
    528       && a->aux.shared->refcnt == 1 /* shared only referenced from this array */
    529       && a->ptr - a->aux.shared->ptr >= len) /* there's room for unshifted item */ {
    530     a->ptr -= len;
     627      && a->as.heap.aux.shared->refcnt == 1 /* shared only referenced from this array */
     628      && a->as.heap.ptr - a->as.heap.aux.shared->ptr >= alen) /* there's room for unshifted item */ {
     629    ary_modify_check(mrb, a);
     630    a->as.heap.ptr -= alen;
     631    ptr = a->as.heap.ptr;
    531632  }
    532633  else {
     634    mrb_bool same = vals == ARY_PTR(a);
    533635    ary_modify(mrb, a);
    534     if (len == 0) return self;
    535     if (a->aux.capa < a->len + len)
    536       ary_expand_capa(mrb, a, a->len + len);
    537     value_move(a->ptr + len, a->ptr, a->len);
    538   }
    539   array_copy(a->ptr, vals, len);
    540   a->len += len;
    541   while (len--) {
    542     mrb_field_write_barrier_value(mrb, (struct RBasic*)a, vals[len]);
     636    if (ARY_CAPA(a) < len + alen)
     637      ary_expand_capa(mrb, a, len + alen);
     638    ptr = ARY_PTR(a);
     639    value_move(ptr + alen, ptr, len);
     640    if (same) vals = ptr;
     641  }
     642  array_copy(ptr, vals, alen);
     643  ARY_SET_LEN(a, len+alen);
     644  while (alen--) {
     645    mrb_field_write_barrier_value(mrb, (struct RBasic*)a, vals[alen]);
    543646  }
    544647
     
    550653{
    551654  struct RArray *a = mrb_ary_ptr(ary);
     655  mrb_int len = ARY_LEN(a);
    552656
    553657  /* range check */
    554   if (n < 0) n += a->len;
    555   if (n < 0 || a->len <= n) return mrb_nil_value();
    556 
    557   return a->ptr[n];
     658  if (n < 0) n += len;
     659  if (n < 0 || len <= n) return mrb_nil_value();
     660
     661  return ARY_PTR(a)[n];
    558662}
    559663
     
    562666{
    563667  struct RArray *a = mrb_ary_ptr(ary);
     668  mrb_int len = ARY_LEN(a);
    564669
    565670  ary_modify(mrb, a);
    566671  /* range check */
    567672  if (n < 0) {
    568     n += a->len;
     673    n += len;
    569674    if (n < 0) {
    570       mrb_raisef(mrb, E_INDEX_ERROR, "index %S out of array", mrb_fixnum_value(n - a->len));
    571     }
    572   }
    573   if (a->len <= n) {
    574     if (a->aux.capa <= n)
     675      mrb_raisef(mrb, E_INDEX_ERROR, "index %i out of array", n - len);
     676    }
     677  }
     678  if (len <= n) {
     679    if (ARY_CAPA(a) <= n)
    575680      ary_expand_capa(mrb, a, n + 1);
    576     ary_fill_with_nil(a->ptr + a->len, n + 1 - a->len);
    577     a->len = n + 1;
    578   }
    579 
    580   a->ptr[n] = val;
     681    ary_fill_with_nil(ARY_PTR(a) + len, n + 1 - len);
     682    ARY_SET_LEN(a, n+1);
     683  }
     684
     685  ARY_PTR(a)[n] = val;
    581686  mrb_field_write_barrier_value(mrb, (struct RBasic*)a, val);
    582687}
     
    585690ary_dup(mrb_state *mrb, struct RArray *a)
    586691{
    587   struct RArray *d = ary_new_capa(mrb, a->len);
    588 
    589   ary_replace(mrb, d, a->ptr, a->len);
    590   return d;
     692  return ary_new_from_values(mrb, ARY_LEN(a), ARY_PTR(a));
    591693}
    592694
     
    595697{
    596698  struct RArray *a = mrb_ary_ptr(ary);
     699  mrb_int alen = ARY_LEN(a);
    597700  const mrb_value *argv;
    598701  mrb_int argc;
     
    602705
    603706  /* len check */
    604   if (len < 0) mrb_raisef(mrb, E_INDEX_ERROR, "negative length (%S)", mrb_fixnum_value(len));
     707  if (len < 0) mrb_raisef(mrb, E_INDEX_ERROR, "negative length (%i)", len);
    605708
    606709  /* range check */
    607710  if (head < 0) {
    608     head += a->len;
     711    head += alen;
    609712    if (head < 0) {
    610713      mrb_raise(mrb, E_INDEX_ERROR, "index is out of array");
     
    612715  }
    613716  tail = head + len;
    614   if (a->len < len || a->len < tail) {
    615     len = a->len - head;
     717  if (alen < len || alen < tail) {
     718    len = alen - head;
    616719  }
    617720
     
    620723    argc = RARRAY_LEN(rpl);
    621724    argv = RARRAY_PTR(rpl);
    622     if (argv == a->ptr) {
     725    if (argv == ARY_PTR(a)) {
    623726      struct RArray *r;
    624727
     
    627730      }
    628731      r = ary_dup(mrb, a);
    629       argv = r->ptr;
     732      argv = ARY_PTR(r);
    630733    }
    631734  }
     
    634737    argv = &rpl;
    635738  }
    636   if (head >= a->len) {
     739  if (head >= alen) {
    637740    if (head > ARY_MAX_SIZE - argc) {
    638       mrb_raisef(mrb, E_INDEX_ERROR, "index %S too big", mrb_fixnum_value(head));
     741      mrb_raisef(mrb, E_INDEX_ERROR, "index %i too big", head);
    639742    }
    640743    len = head + argc;
    641     if (len > a->aux.capa) {
     744    if (len > ARY_CAPA(a)) {
    642745      ary_expand_capa(mrb, a, head + argc);
    643746    }
    644     ary_fill_with_nil(a->ptr + a->len, head - a->len);
     747    ary_fill_with_nil(ARY_PTR(a) + alen, head - alen);
    645748    if (argc > 0) {
    646       array_copy(a->ptr + head, argv, argc);
    647     }
    648     a->len = len;
     749      array_copy(ARY_PTR(a) + head, argv, argc);
     750    }
     751    ARY_SET_LEN(a, len);
    649752  }
    650753  else {
    651     mrb_int alen;
    652 
    653     if (a->len - len > ARY_MAX_SIZE - argc) {
    654       mrb_raisef(mrb, E_INDEX_ERROR, "index %S too big", mrb_fixnum_value(a->len + argc - len));
    655     }
    656     alen = a->len + argc - len;
    657     if (alen > a->aux.capa) {
    658       ary_expand_capa(mrb, a, alen);
     754    mrb_int newlen;
     755
     756    if (alen - len > ARY_MAX_SIZE - argc) {
     757      mrb_raisef(mrb, E_INDEX_ERROR, "index %i too big", alen + argc - len);
     758    }
     759    newlen = alen + argc - len;
     760    if (newlen > ARY_CAPA(a)) {
     761      ary_expand_capa(mrb, a, newlen);
    659762    }
    660763
    661764    if (len != argc) {
     765      mrb_value *ptr = ARY_PTR(a);
    662766      tail = head + len;
    663       value_move(a->ptr + head + argc, a->ptr + tail, a->len - tail);
    664       a->len = alen;
     767      value_move(ptr + head + argc, ptr + tail, alen - tail);
     768      ARY_SET_LEN(a, newlen);
    665769    }
    666770    if (argc > 0) {
    667       value_move(a->ptr + head, argv, argc);
     771      value_move(ARY_PTR(a) + head, argv, argc);
    668772    }
    669773  }
     
    687791  struct RArray *b;
    688792
     793  if (!ARY_SHARED_P(a) && len <= ARY_SHIFT_SHARED_MIN) {
     794    return mrb_ary_new_from_values(mrb, len, ARY_PTR(a)+beg);
     795  }
    689796  ary_make_shared(mrb, a);
    690797  b  = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class);
    691   b->ptr = a->ptr + beg;
    692   b->len = len;
    693   b->aux.shared = a->aux.shared;
    694   b->aux.shared->refcnt++;
     798  b->as.heap.ptr = a->as.heap.ptr + beg;
     799  b->as.heap.len = len;
     800  b->as.heap.aux.shared = a->as.heap.aux.shared;
     801  b->as.heap.aux.shared->refcnt++;
    695802  ARY_SET_SHARED_FLAG(b);
    696803
     
    704811    return mrb_fixnum(index);
    705812  }
     813#ifndef MRB_WITHOUT_FLOAT
    706814  else if (mrb_float_p(index)) {
    707815    return (mrb_int)mrb_float(index);
    708816  }
     817#endif
    709818  else {
    710819    mrb_int i, argc;
    711820    mrb_value *argv;
    712821
    713     mrb_get_args(mrb, "i*", &i, &argv, &argc);
     822    mrb_get_args(mrb, "i*!", &i, &argv, &argc);
    714823    return i;
    715824  }
     
    747856{
    748857  struct RArray *a = mrb_ary_ptr(self);
    749   mrb_int i, len;
     858  mrb_int i, len, alen;
    750859  mrb_value index;
    751860
     
    754863      /* a[n..m] */
    755864    case MRB_TT_RANGE:
    756       if (mrb_range_beg_len(mrb, index, &i, &len, a->len, TRUE) == 1) {
     865      if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == MRB_RANGE_OK) {
    757866        return ary_subseq(mrb, a, i, len);
    758867      }
     
    768877
    769878  i = aget_index(mrb, index);
    770   if (i < 0) i += a->len;
    771   if (i < 0 || a->len < i) return mrb_nil_value();
     879  alen = ARY_LEN(a);
     880  if (i < 0) i += alen;
     881  if (i < 0 || alen < i) return mrb_nil_value();
    772882  if (len < 0) return mrb_nil_value();
    773   if (a->len == i) return mrb_ary_new(mrb);
    774   if (len > a->len - i) len = a->len - i;
     883  if (alen == i) return mrb_ary_new(mrb);
     884  if (len > alen - i) len = alen - i;
    775885
    776886  return ary_subseq(mrb, a, i, len);
     
    822932    /* a[n..m] = v */
    823933    switch (mrb_range_beg_len(mrb, v1, &i, &len, RARRAY_LEN(self), FALSE)) {
    824     case 0:                   /* not range */
     934    case MRB_RANGE_TYPE_MISMATCH:
    825935      mrb_ary_set(mrb, self, aget_index(mrb, v1), v2);
    826936      break;
    827     case 1:                   /* range */
     937    case MRB_RANGE_OK:
    828938      mrb_ary_splice(mrb, self, i, len, v2);
    829939      break;
    830     case 2:                   /* out of range */
    831       mrb_raisef(mrb, E_RANGE_ERROR, "%S out of range", v1);
     940    case MRB_RANGE_OUT:
     941      mrb_raisef(mrb, E_RANGE_ERROR, "%v out of range", v1);
    832942      break;
    833943    }
     
    847957  mrb_value val;
    848958  mrb_value *ptr;
    849   mrb_int len;
     959  mrb_int len, alen;
    850960
    851961  mrb_get_args(mrb, "i", &index);
    852   if (index < 0) index += a->len;
    853   if (index < 0 || a->len <= index) return mrb_nil_value();
     962  alen = ARY_LEN(a);
     963  if (index < 0) index += alen;
     964  if (index < 0 || alen <= index) return mrb_nil_value();
    854965
    855966  ary_modify(mrb, a);
    856   val = a->ptr[index];
    857 
    858   ptr = a->ptr + index;
    859   len = a->len - index;
     967  ptr = ARY_PTR(a);
     968  val = ptr[index];
     969
     970  ptr += index;
     971  len = alen - index;
    860972  while (--len) {
    861973    *ptr = *(ptr+1);
    862974    ++ptr;
    863975  }
    864   --a->len;
     976  ARY_SET_LEN(a, alen-1);
    865977
    866978  ary_shrink_capa(mrb, a);
     
    873985{
    874986  struct RArray *a = mrb_ary_ptr(self);
    875   mrb_int size;
    876 
    877   if (mrb_get_args(mrb, "|i", &size) == 0) {
    878     return (a->len > 0)? a->ptr[0]: mrb_nil_value();
    879   }
     987  mrb_int size, alen;
     988
     989  if (mrb_get_argc(mrb) == 0) {
     990    return (ARY_LEN(a) > 0)? ARY_PTR(a)[0]: mrb_nil_value();
     991  }
     992  mrb_get_args(mrb, "|i", &size);
    880993  if (size < 0) {
    881994    mrb_raise(mrb, E_ARGUMENT_ERROR, "negative array size");
    882995  }
    883996
    884   if (size > a->len) size = a->len;
     997  alen = ARY_LEN(a);
     998  if (size > alen) size = alen;
    885999  if (ARY_SHARED_P(a)) {
    8861000    return ary_subseq(mrb, a, 0, size);
    8871001  }
    888   return mrb_ary_new_from_values(mrb, size, a->ptr);
     1002  return mrb_ary_new_from_values(mrb, size, ARY_PTR(a));
    8891003}
    8901004
     
    8931007{
    8941008  struct RArray *a = mrb_ary_ptr(self);
    895   mrb_int size;
    896 
    897   if (mrb_get_args(mrb, "|i", &size) == 0)
    898     return (a->len > 0)? a->ptr[a->len - 1]: mrb_nil_value();
     1009  mrb_int n, size, alen;
     1010
     1011  n = mrb_get_args(mrb, "|i", &size);
     1012  alen = ARY_LEN(a);
     1013  if (n == 0) {
     1014    return (alen > 0) ? ARY_PTR(a)[alen - 1]: mrb_nil_value();
     1015  }
    8991016
    9001017  if (size < 0) {
    9011018    mrb_raise(mrb, E_ARGUMENT_ERROR, "negative array size");
    9021019  }
    903   if (size > a->len) size = a->len;
     1020  if (size > alen) size = alen;
    9041021  if (ARY_SHARED_P(a) || size > ARY_DEFAULT_LEN) {
    905     return ary_subseq(mrb, a, a->len - size, size);
    906   }
    907   return mrb_ary_new_from_values(mrb, size, a->ptr + a->len - size);
     1022    return ary_subseq(mrb, a, alen - size, size);
     1023  }
     1024  return mrb_ary_new_from_values(mrb, size, ARY_PTR(a) + alen - size);
    9081025}
    9091026
     
    9441061mrb_ary_splat(mrb_state *mrb, mrb_value v)
    9451062{
    946   mrb_value a, recv_class;
     1063  mrb_value a;
    9471064
    9481065  if (mrb_array_p(v)) {
     
    9551072
    9561073  a = mrb_funcall(mrb, v, "to_a", 0);
    957   if (mrb_array_p(a)) {
    958     return a;
    959   }
    960   else if (mrb_nil_p(a)) {
     1074  if (mrb_nil_p(a)) {
    9611075    return mrb_ary_new_from_values(mrb, 1, &v);
    9621076  }
    963   else {
    964     recv_class = mrb_obj_value(mrb_obj_class(mrb, v));
    965     mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Array (%S#to_a gives %S)",
    966       recv_class,
    967       recv_class,
    968       mrb_obj_value(mrb_obj_class(mrb, a))
    969     );
    970     /* not reached */
    971     return mrb_undef_value();
    972   }
     1077  mrb_ensure_array_type(mrb, a);
     1078  return a;
    9731079}
    9741080
     
    9781084  struct RArray *a = mrb_ary_ptr(self);
    9791085
    980   return mrb_fixnum_value(a->len);
     1086  return mrb_fixnum_value(ARY_LEN(a));
    9811087}
    9821088
     
    9881094  ary_modify(mrb, a);
    9891095  if (ARY_SHARED_P(a)) {
    990     mrb_ary_decref(mrb, a->aux.shared);
     1096    mrb_ary_decref(mrb, a->as.heap.aux.shared);
    9911097    ARY_UNSET_SHARED_FLAG(a);
    9921098  }
    993   else {
    994     mrb_free(mrb, a->ptr);
    995   }
    996   a->len = 0;
    997   a->aux.capa = 0;
    998   a->ptr = 0;
     1099  else if (!ARY_EMBED_P(a)){
     1100    mrb_free(mrb, a->as.heap.ptr);
     1101  }
     1102  ARY_SET_EMBED_LEN(a, 0);
    9991103
    10001104  return self;
     
    10021106
    10031107static mrb_value
     1108mrb_ary_clear_m(mrb_state *mrb, mrb_value self)
     1109{
     1110  return mrb_ary_clear(mrb, self);
     1111}
     1112
     1113static mrb_value
    10041114mrb_ary_empty_p(mrb_state *mrb, mrb_value self)
    10051115{
    10061116  struct RArray *a = mrb_ary_ptr(self);
    10071117
    1008   return mrb_bool_value(a->len == 0);
    1009 }
    1010 
    1011 MRB_API mrb_value
    1012 mrb_check_array_type(mrb_state *mrb, mrb_value ary)
    1013 {
    1014   return mrb_check_convert_type(mrb, ary, MRB_TT_ARRAY, "Array", "to_ary");
     1118  return mrb_bool_value(ARY_LEN(a) == 0);
    10151119}
    10161120
     
    10211125    offset += RARRAY_LEN(ary);
    10221126  }
    1023   return ary_elt(ary, offset);
     1127  if (offset < 0 || RARRAY_LEN(ary) <= offset) {
     1128    return mrb_nil_value();
     1129  }
     1130  return RARRAY_PTR(ary)[offset];
    10241131}
    10251132
     
    10391146  mrb_ary_push(mrb, list, ary);
    10401147
    1041   result = mrb_str_buf_new(mrb, 64);
     1148  result = mrb_str_new_capa(mrb, 64);
    10421149
    10431150  for (i=0; i<RARRAY_LEN(ary); i++) {
     
    10651172          goto str_join;
    10661173        }
    1067         tmp = mrb_check_convert_type(mrb, val, MRB_TT_ARRAY, "Array", "to_ary");
     1174        tmp = mrb_check_array_type(mrb, val);
    10681175        if (!mrb_nil_p(tmp)) {
    10691176          val = tmp;
     
    11391246}
    11401247
     1248/* internal method to convert multi-value to single value */
     1249static mrb_value
     1250mrb_ary_svalue(mrb_state *mrb, mrb_value ary)
     1251{
     1252  switch (RARRAY_LEN(ary)) {
     1253  case 0:
     1254    return mrb_nil_value();
     1255  case 1:
     1256    return RARRAY_PTR(ary)[0];
     1257  default:
     1258    return ary;
     1259  }
     1260}
     1261
     1262static const mrb_code each_iseq[] = {
     1263  OP_ENTER, 0x0, 0x00, 0x1,  /* OP_ENTER     0:0:0:0:0:0:1 */
     1264  OP_JMPIF, 0x1, 0x0, 19,    /* OP_JMPIF     R1  19 */
     1265  OP_LOADSELF, 0x3,          /* OP_LOADSELF  R3 */
     1266  OP_LOADSYM, 0x4, 0x0,      /* OP_LOADSYM   R4  :each*/
     1267  OP_SEND, 0x3, 0x1, 0x1,    /* OP_SEND      R3  :to_enum   1 */
     1268  OP_RETURN, 0x3,            /* OP_RETURN    R3 */
     1269  OP_LOADI_0, 0x2,           /* OP_LOADI_0   R2 */
     1270  OP_JMP, 0x0, 43,           /* OP_JMP       49 */
     1271  OP_MOVE, 0x3, 0x1,         /* OP_MOVE      R3  R1 */
     1272  OP_LOADSELF, 0x4,          /* OP_LOADSELF  R4 */
     1273  OP_MOVE, 0x5, 0x2,         /* OP_MOVE      R5  R2 */
     1274  OP_SEND, 0x4, 0x2, 0x1,    /* OP_SEND      R4  :[]        1 */
     1275  OP_SEND, 0x3, 0x3, 0x1,    /* OP_SEND      R3  :call      1 */
     1276  OP_ADDI, 0x2, 1,           /* OP_ADDI      R3  1 */
     1277  OP_MOVE, 0x3, 0x2,         /* OP_MOVE      R3  R2 */
     1278  OP_LOADSELF, 0x4,          /* OP_LOADSELF  R4 */
     1279  OP_SEND, 0x4, 0x4, 0x0,    /* OP_SEND      R4  :length    0 */
     1280  OP_LT, 0x3,                /* OP_LT        R3 */
     1281  OP_JMPIF, 0x3, 0x0, 24,    /* OP_JMPIF     R3  24 */
     1282  OP_RETURN, 0x0             /* OP_RETURN    R3 */
     1283};
     1284
     1285static void
     1286init_ary_each(mrb_state *mrb, struct RClass *ary)
     1287{
     1288  struct RProc *p;
     1289  mrb_method_t m;
     1290  mrb_irep *each_irep = (mrb_irep*)mrb_malloc(mrb, sizeof(mrb_irep));
     1291  static const mrb_irep mrb_irep_zero = { 0 };
     1292
     1293  *each_irep = mrb_irep_zero;
     1294  each_irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*5);
     1295  each_irep->syms[0] = mrb_intern_lit(mrb, "each");
     1296  each_irep->syms[1] = mrb_intern_lit(mrb, "to_enum");
     1297  each_irep->syms[2] = mrb_intern_lit(mrb, "[]");
     1298  each_irep->syms[3] = mrb_intern_lit(mrb, "call");
     1299  each_irep->syms[4] = mrb_intern_lit(mrb, "length");
     1300  each_irep->slen = 5;
     1301  each_irep->flags = MRB_ISEQ_NO_FREE;
     1302  each_irep->iseq = each_iseq;
     1303  each_irep->ilen = sizeof(each_iseq);
     1304  each_irep->nregs = 7;
     1305  each_irep->nlocals = 3;
     1306  p = mrb_proc_new(mrb, each_irep);
     1307  p->flags |= MRB_PROC_SCOPE | MRB_PROC_STRICT;
     1308  MRB_METHOD_FROM_PROC(m, p);
     1309  mrb_define_method_raw(mrb, ary, mrb_intern_lit(mrb, "each"), m);
     1310}
     1311
    11411312void
    11421313mrb_init_array(mrb_state *mrb)
     
    11441315  struct RClass *a;
    11451316
    1146   mrb->array_class = a = mrb_define_class(mrb, "Array", mrb->object_class);            /* 15.2.12 */
     1317  mrb->array_class = a = mrb_define_class(mrb, "Array", mrb->object_class);              /* 15.2.12 */
    11471318  MRB_SET_INSTANCE_TT(a, MRB_TT_ARRAY);
    11481319
    1149   mrb_define_class_method(mrb, a, "[]",        mrb_ary_s_create,     MRB_ARGS_ANY());  /* 15.2.12.4.1 */
    1150 
    1151   mrb_define_method(mrb, a, "+",               mrb_ary_plus,         MRB_ARGS_REQ(1)); /* 15.2.12.5.1  */
    1152   mrb_define_method(mrb, a, "*",               mrb_ary_times,        MRB_ARGS_REQ(1)); /* 15.2.12.5.2  */
    1153   mrb_define_method(mrb, a, "<<",              mrb_ary_push_m,       MRB_ARGS_REQ(1)); /* 15.2.12.5.3  */
    1154   mrb_define_method(mrb, a, "[]",              mrb_ary_aget,         MRB_ARGS_ANY());  /* 15.2.12.5.4  */
    1155   mrb_define_method(mrb, a, "[]=",             mrb_ary_aset,         MRB_ARGS_ANY());  /* 15.2.12.5.5  */
    1156   mrb_define_method(mrb, a, "clear",           mrb_ary_clear,        MRB_ARGS_NONE()); /* 15.2.12.5.6  */
    1157   mrb_define_method(mrb, a, "concat",          mrb_ary_concat_m,     MRB_ARGS_REQ(1)); /* 15.2.12.5.8  */
    1158   mrb_define_method(mrb, a, "delete_at",       mrb_ary_delete_at,    MRB_ARGS_REQ(1)); /* 15.2.12.5.9  */
    1159   mrb_define_method(mrb, a, "empty?",          mrb_ary_empty_p,      MRB_ARGS_NONE()); /* 15.2.12.5.12 */
    1160   mrb_define_method(mrb, a, "first",           mrb_ary_first,        MRB_ARGS_OPT(1)); /* 15.2.12.5.13 */
    1161   mrb_define_method(mrb, a, "index",           mrb_ary_index_m,      MRB_ARGS_REQ(1)); /* 15.2.12.5.14 */
    1162   mrb_define_method(mrb, a, "initialize_copy", mrb_ary_replace_m,    MRB_ARGS_REQ(1)); /* 15.2.12.5.16 */
    1163   mrb_define_method(mrb, a, "join",            mrb_ary_join_m,       MRB_ARGS_ANY());  /* 15.2.12.5.17 */
    1164   mrb_define_method(mrb, a, "last",            mrb_ary_last,         MRB_ARGS_ANY());  /* 15.2.12.5.18 */
    1165   mrb_define_method(mrb, a, "length",          mrb_ary_size,         MRB_ARGS_NONE()); /* 15.2.12.5.19 */
    1166   mrb_define_method(mrb, a, "pop",             mrb_ary_pop,          MRB_ARGS_NONE()); /* 15.2.12.5.21 */
    1167   mrb_define_method(mrb, a, "push",            mrb_ary_push_m,       MRB_ARGS_ANY());  /* 15.2.12.5.22 */
    1168   mrb_define_method(mrb, a, "append",          mrb_ary_push_m,       MRB_ARGS_ANY());
    1169   mrb_define_method(mrb, a, "replace",         mrb_ary_replace_m,    MRB_ARGS_REQ(1)); /* 15.2.12.5.23 */
    1170   mrb_define_method(mrb, a, "reverse",         mrb_ary_reverse,      MRB_ARGS_NONE()); /* 15.2.12.5.24 */
    1171   mrb_define_method(mrb, a, "reverse!",        mrb_ary_reverse_bang, MRB_ARGS_NONE()); /* 15.2.12.5.25 */
    1172   mrb_define_method(mrb, a, "rindex",          mrb_ary_rindex_m,     MRB_ARGS_REQ(1)); /* 15.2.12.5.26 */
    1173   mrb_define_method(mrb, a, "shift",           mrb_ary_shift,        MRB_ARGS_NONE()); /* 15.2.12.5.27 */
    1174   mrb_define_method(mrb, a, "size",            mrb_ary_size,         MRB_ARGS_NONE()); /* 15.2.12.5.28 */
    1175   mrb_define_method(mrb, a, "slice",           mrb_ary_aget,         MRB_ARGS_ANY());  /* 15.2.12.5.29 */
    1176   mrb_define_method(mrb, a, "unshift",         mrb_ary_unshift_m,    MRB_ARGS_ANY());  /* 15.2.12.5.30 */
    1177   mrb_define_method(mrb, a, "prepend",         mrb_ary_unshift_m,    MRB_ARGS_ANY());
     1320  mrb_define_class_method(mrb, a, "[]",        mrb_ary_s_create,     MRB_ARGS_ANY());    /* 15.2.12.4.1 */
     1321
     1322  mrb_define_method(mrb, a, "+",               mrb_ary_plus,         MRB_ARGS_REQ(1));   /* 15.2.12.5.1  */
     1323  mrb_define_method(mrb, a, "*",               mrb_ary_times,        MRB_ARGS_REQ(1));   /* 15.2.12.5.2  */
     1324  mrb_define_method(mrb, a, "<<",              mrb_ary_push_m,       MRB_ARGS_REQ(1));   /* 15.2.12.5.3  */
     1325  mrb_define_method(mrb, a, "[]",              mrb_ary_aget,         MRB_ARGS_ARG(1,1)); /* 15.2.12.5.4  */
     1326  mrb_define_method(mrb, a, "[]=",             mrb_ary_aset,         MRB_ARGS_ARG(2,1)); /* 15.2.12.5.5  */
     1327  mrb_define_method(mrb, a, "clear",           mrb_ary_clear_m,      MRB_ARGS_NONE());   /* 15.2.12.5.6  */
     1328  mrb_define_method(mrb, a, "concat",          mrb_ary_concat_m,     MRB_ARGS_REQ(1));   /* 15.2.12.5.8  */
     1329  mrb_define_method(mrb, a, "delete_at",       mrb_ary_delete_at,    MRB_ARGS_REQ(1));   /* 15.2.12.5.9  */
     1330  mrb_define_method(mrb, a, "empty?",          mrb_ary_empty_p,      MRB_ARGS_NONE());   /* 15.2.12.5.12 */
     1331  mrb_define_method(mrb, a, "first",           mrb_ary_first,        MRB_ARGS_OPT(1));   /* 15.2.12.5.13 */
     1332  mrb_define_method(mrb, a, "index",           mrb_ary_index_m,      MRB_ARGS_REQ(1));   /* 15.2.12.5.14 */
     1333  mrb_define_method(mrb, a, "initialize_copy", mrb_ary_replace_m,    MRB_ARGS_REQ(1));   /* 15.2.12.5.16 */
     1334  mrb_define_method(mrb, a, "join",            mrb_ary_join_m,       MRB_ARGS_OPT(1));   /* 15.2.12.5.17 */
     1335  mrb_define_method(mrb, a, "last",            mrb_ary_last,         MRB_ARGS_OPT(1));   /* 15.2.12.5.18 */
     1336  mrb_define_method(mrb, a, "length",          mrb_ary_size,         MRB_ARGS_NONE());   /* 15.2.12.5.19 */
     1337  mrb_define_method(mrb, a, "pop",             mrb_ary_pop,          MRB_ARGS_NONE());   /* 15.2.12.5.21 */
     1338  mrb_define_method(mrb, a, "push",            mrb_ary_push_m,       MRB_ARGS_ANY());    /* 15.2.12.5.22 */
     1339  mrb_define_method(mrb, a, "replace",         mrb_ary_replace_m,    MRB_ARGS_REQ(1));   /* 15.2.12.5.23 */
     1340  mrb_define_method(mrb, a, "reverse",         mrb_ary_reverse,      MRB_ARGS_NONE());   /* 15.2.12.5.24 */
     1341  mrb_define_method(mrb, a, "reverse!",        mrb_ary_reverse_bang, MRB_ARGS_NONE());   /* 15.2.12.5.25 */
     1342  mrb_define_method(mrb, a, "rindex",          mrb_ary_rindex_m,     MRB_ARGS_REQ(1));   /* 15.2.12.5.26 */
     1343  mrb_define_method(mrb, a, "shift",           mrb_ary_shift,        MRB_ARGS_NONE());   /* 15.2.12.5.27 */
     1344  mrb_define_method(mrb, a, "size",            mrb_ary_size,         MRB_ARGS_NONE());   /* 15.2.12.5.28 */
     1345  mrb_define_method(mrb, a, "slice",           mrb_ary_aget,         MRB_ARGS_ARG(1,1)); /* 15.2.12.5.29 */
     1346  mrb_define_method(mrb, a, "unshift",         mrb_ary_unshift_m,    MRB_ARGS_ANY());    /* 15.2.12.5.30 */
    11781347
    11791348  mrb_define_method(mrb, a, "__ary_eq",        mrb_ary_eq,           MRB_ARGS_REQ(1));
    11801349  mrb_define_method(mrb, a, "__ary_cmp",       mrb_ary_cmp,          MRB_ARGS_REQ(1));
    1181   mrb_define_method(mrb, a, "__ary_index",     mrb_ary_index_m,      MRB_ARGS_REQ(1)); /* kept for mruby-array-ext */
    1182 }
     1350  mrb_define_method(mrb, a, "__ary_index",     mrb_ary_index_m,      MRB_ARGS_REQ(1));   /* kept for mruby-array-ext */
     1351  mrb_define_method(mrb, a, "__svalue",        mrb_ary_svalue,       MRB_ARGS_NONE());
     1352
     1353  init_ary_each(mrb, a);
     1354}
  • EcnlProtoTool/trunk/mruby-2.1.1/src/backtrace.c

    r331 r439  
    1717
    1818struct backtrace_location {
    19   int lineno;
     19  int32_t lineno;
     20  mrb_sym method_id;
    2021  const char *filename;
    21   mrb_sym method_id;
    2222};
    2323
    24 typedef void (*each_backtrace_func)(mrb_state*, int i, struct backtrace_location*, void*);
     24typedef void (*each_backtrace_func)(mrb_state*, const struct backtrace_location*, void*);
    2525
    2626static const mrb_data_type bt_type = { "Backtrace", mrb_free };
    2727
    28 static void
    29 each_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, each_backtrace_func func, void *data)
    30 {
    31   int i, j;
     28mrb_value mrb_exc_inspect(mrb_state *mrb, mrb_value exc);
     29mrb_value mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace);
     30
     31static void
     32each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, const mrb_code *pc0, each_backtrace_func func, void *data)
     33{
     34  ptrdiff_t i;
    3235
    3336  if (ciidx >= mrb->c->ciend - mrb->c->cibase)
    3437    ciidx = 10; /* ciidx is broken... */
    3538
    36   for (i=ciidx, j=0; i >= 0; i--,j++) {
     39  for (i=ciidx; i >= 0; i--) {
    3740    struct backtrace_location loc;
    3841    mrb_callinfo *ci;
    3942    mrb_irep *irep;
    40     mrb_code *pc;
     43    const mrb_code *pc;
    4144
    4245    ci = &mrb->c->cibase[i];
     
    5255    }
    5356    else if (i+1 <= ciidx) {
    54       pc = mrb->c->cibase[i+1].pc - 1;
     57      if (!mrb->c->cibase[i + 1].pc) continue;
     58      pc = &mrb->c->cibase[i+1].pc[-1];
    5559    }
    5660    else {
    5761      pc = pc0;
    5862    }
    59     loc.filename = mrb_debug_get_filename(irep, (uint32_t)(pc - irep->iseq));
    60     loc.lineno = mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq));
    61 
     63
     64    loc.lineno = mrb_debug_get_line(mrb, irep, pc - irep->iseq);
    6265    if (loc.lineno == -1) continue;
    6366
     67    loc.filename = mrb_debug_get_filename(mrb, irep, pc - irep->iseq);
    6468    if (!loc.filename) {
    6569      loc.filename = "(unknown)";
     
    6771
    6872    loc.method_id = ci->mid;
    69     func(mrb, j, &loc, data);
     73    func(mrb, &loc, data);
    7074  }
    7175}
     
    7478
    7579static void
    76 print_backtrace(mrb_state *mrb, mrb_value backtrace)
    77 {
    78   int i, n;
     80print_backtrace(mrb_state *mrb, struct RObject *exc, mrb_value backtrace)
     81{
     82  mrb_int i;
     83  mrb_int n = RARRAY_LEN(backtrace);
     84  mrb_value *loc, mesg;
    7985  FILE *stream = stderr;
    8086
    81   if (!mrb_array_p(backtrace)) return;
    82   fprintf(stream, "trace:\n");
    83 
    84   n = RARRAY_LEN(backtrace);
    85   for (i=0; n--; i++) {
    86     mrb_value entry = RARRAY_PTR(backtrace)[n];
    87 
    88     if (mrb_string_p(entry)) {
    89       fprintf(stream, "\t[%d] %.*s\n", i, (int)RSTRING_LEN(entry), RSTRING_PTR(entry));
    90     }
    91   }
    92 }
    93 
    94 static void
    95 print_packed_backtrace(mrb_state *mrb, mrb_value packed)
    96 {
    97   FILE *stream = stderr;
    98   struct backtrace_location *bt;
    99   int n, i;
    100 
    101   bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, packed, &bt_type);
    102   if (bt == NULL) {
    103     mrb_raise(mrb, E_RUNTIME_ERROR, "broken backtrace");
    104   }
    105   n = (mrb_int)RDATA(packed)->flags;
    106 
    107   fprintf(stream, "trace:\n");
    108   for (i = 0; n--; i++) {
    109     int ai = mrb_gc_arena_save(mrb);
    110     struct backtrace_location *entry = &bt[n];
    111     if (entry->filename == NULL) continue;
    112     fprintf(stream, "\t[%d] %s:%d", (int)i, entry->filename, entry->lineno);
    113     if (entry->method_id != 0) {
    114       const char *method_name;
    115 
    116       method_name = mrb_sym2name(mrb, entry->method_id);
    117       fprintf(stream, ":in %s", method_name);
    118       mrb_gc_arena_restore(mrb, ai);
    119     }
    120     fprintf(stream, "\n");
    121   }
     87  if (n != 0) {
     88    fprintf(stream, "trace (most recent call last):\n");
     89    for (i=n-1,loc=&RARRAY_PTR(backtrace)[i]; i>0; i--,loc--) {
     90      if (mrb_string_p(*loc)) {
     91        fprintf(stream, "\t[%d] %.*s\n",
     92                (int)i, (int)RSTRING_LEN(*loc), RSTRING_PTR(*loc));
     93      }
     94    }
     95    if (mrb_string_p(*loc)) {
     96      fprintf(stream, "%.*s: ", (int)RSTRING_LEN(*loc), RSTRING_PTR(*loc));
     97    }
     98  }
     99  mesg = mrb_exc_inspect(mrb, mrb_obj_value(exc));
     100  fprintf(stream, "%.*s\n", (int)RSTRING_LEN(mesg), RSTRING_PTR(mesg));
    122101}
    123102
     
    138117  backtrace = mrb_obj_iv_get(mrb, mrb->exc, mrb_intern_lit(mrb, "backtrace"));
    139118  if (mrb_nil_p(backtrace)) return;
    140   if (mrb_array_p(backtrace)) {
    141     print_backtrace(mrb, backtrace);
    142   }
    143   else {
    144     print_packed_backtrace(mrb, backtrace);
    145   }
     119  if (!mrb_array_p(backtrace)) backtrace = mrb_unpack_backtrace(mrb, backtrace);
     120  print_backtrace(mrb, mrb->exc, backtrace);
    146121}
    147122#else
     
    155130
    156131static void
     132count_backtrace_i(mrb_state *mrb,
     133                 const struct backtrace_location *loc,
     134                 void *data)
     135{
     136  int *lenp = (int*)data;
     137
     138  (*lenp)++;
     139}
     140
     141static void
    157142pack_backtrace_i(mrb_state *mrb,
    158                  int i,
    159                  struct backtrace_location *loc,
     143                 const struct backtrace_location *loc,
    160144                 void *data)
    161145{
    162   struct backtrace_location *entry = (struct backtrace_location*)data;
    163 
    164   entry[i] = *loc;
     146  struct backtrace_location **pptr = (struct backtrace_location**)data;
     147  struct backtrace_location *ptr = *pptr;
     148
     149  *ptr = *loc;
     150  *pptr = ptr+1;
    165151}
    166152
     
    170156  struct RData *backtrace;
    171157  ptrdiff_t ciidx = mrb->c->ci - mrb->c->cibase;
    172   mrb_int len = (ciidx+1)*sizeof(struct backtrace_location);
     158  int len = 0;
     159  int size;
    173160  void *ptr;
    174161
    175   ptr = mrb_malloc(mrb, len);
    176   memset(ptr, 0, len);
     162  each_backtrace(mrb, ciidx, mrb->c->ci->pc, count_backtrace_i, &len);
     163  size = len * sizeof(struct backtrace_location);
     164  ptr = mrb_malloc(mrb, size);
    177165  backtrace = mrb_data_object_alloc(mrb, NULL, ptr, &bt_type);
    178   backtrace->flags = (unsigned int)ciidx+1;
    179   each_backtrace(mrb, ciidx, mrb->c->ci->pc, pack_backtrace_i, ptr);
     166  backtrace->flags = (uint32_t)len;
     167  each_backtrace(mrb, ciidx, mrb->c->ci->pc, pack_backtrace_i, &ptr);
    180168  return mrb_obj_value(backtrace);
    181169}
     
    184172mrb_keep_backtrace(mrb_state *mrb, mrb_value exc)
    185173{
     174  mrb_sym sym = mrb_intern_lit(mrb, "backtrace");
    186175  mrb_value backtrace;
    187   int ai = mrb_gc_arena_save(mrb);
    188 
     176  int ai;
     177
     178  if (mrb_iv_defined(mrb, exc, sym)) return;
     179  ai = mrb_gc_arena_save(mrb);
    189180  backtrace = packed_backtrace(mrb);
    190   mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "backtrace"), backtrace);
     181  mrb_iv_set(mrb, exc, sym, backtrace);
    191182  mrb_gc_arena_restore(mrb, ai);
    192183}
     
    195186mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace)
    196187{
    197   struct backtrace_location *bt;
     188  const struct backtrace_location *bt;
    198189  mrb_int n, i;
    199 
    200   if (mrb_nil_p(backtrace)) return mrb_ary_new_capa(mrb, 0);
     190  int ai;
     191
     192  if (mrb_nil_p(backtrace)) {
     193  empty_backtrace:
     194    return mrb_ary_new_capa(mrb, 0);
     195  }
    201196  if (mrb_array_p(backtrace)) return backtrace;
    202197  bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, backtrace, &bt_type);
    203   if (bt == NULL) {
    204     mrb_raise(mrb, E_RUNTIME_ERROR, "broken backtrace");
    205   }
     198  if (bt == NULL) goto empty_backtrace;
    206199  n = (mrb_int)RDATA(backtrace)->flags;
    207200  backtrace = mrb_ary_new_capa(mrb, n);
     201  ai = mrb_gc_arena_save(mrb);
    208202  for (i = 0; i < n; i++) {
    209     int ai = mrb_gc_arena_save(mrb);
    210     struct backtrace_location *entry = &bt[i];
     203    const struct backtrace_location *entry = &bt[i];
    211204    mrb_value btline;
    212205
    213     if (entry->filename == NULL) continue;
    214     btline = mrb_format(mrb, "%S:%S",
    215                               mrb_str_new_cstr(mrb, entry->filename),
    216                               mrb_fixnum_value(entry->lineno));
     206    btline = mrb_format(mrb, "%s:%d", entry->filename, (int)entry->lineno);
    217207    if (entry->method_id != 0) {
    218208      mrb_str_cat_lit(mrb, btline, ":in ");
    219       mrb_str_cat_cstr(mrb, btline, mrb_sym2name(mrb, entry->method_id));
     209      mrb_str_cat_cstr(mrb, btline, mrb_sym_name(mrb, entry->method_id));
    220210    }
    221211    mrb_ary_push(mrb, backtrace, btline);
  • EcnlProtoTool/trunk/mruby-2.1.1/src/class.c

    r331 r439  
    88#include <mruby.h>
    99#include <mruby/array.h>
     10#include <mruby/hash.h>
    1011#include <mruby/class.h>
    1112#include <mruby/numeric.h>
     
    1617#include <mruby/data.h>
    1718#include <mruby/istruct.h>
    18 
    19 KHASH_DEFINE(mt, mrb_sym, struct RProc*, TRUE, kh_int_hash_func, kh_int_hash_equal)
     19#include <mruby/opcode.h>
     20
     21KHASH_DEFINE(mt, mrb_sym, mrb_method_t, TRUE, kh_int_hash_func, kh_int_hash_equal)
    2022
    2123void
     
    2830  for (k = kh_begin(h); k != kh_end(h); k++) {
    2931    if (kh_exist(h, k)) {
    30       struct RProc *m = kh_value(h, k);
    31       if (m) {
    32         mrb_gc_mark(mrb, (struct RBasic*)m);
     32      mrb_method_t m = kh_value(h, k);
     33
     34      if (MRB_METHOD_PROC_P(m)) {
     35        struct RProc *p = MRB_METHOD_PROC(m);
     36        mrb_gc_mark(mrb, (struct RBasic*)p);
    3337      }
    3438    }
     
    5155}
    5256
    53 static void
    54 name_class(mrb_state *mrb, struct RClass *c, mrb_sym name)
    55 {
    56   mrb_obj_iv_set(mrb, (struct RObject*)c,
    57                  mrb_intern_lit(mrb, "__classid__"), mrb_symbol_value(name));
     57void
     58mrb_class_name_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb_sym id)
     59{
     60  mrb_value name;
     61  mrb_sym nsym = mrb_intern_lit(mrb, "__classname__");
     62
     63  if (mrb_obj_iv_defined(mrb, (struct RObject*)c, nsym)) return;
     64  if (outer == NULL || outer == mrb->object_class) {
     65    name = mrb_symbol_value(id);
     66  }
     67  else {
     68    name = mrb_class_path(mrb, outer);
     69    if (mrb_nil_p(name)) {      /* unnamed outer class */
     70      if (outer != mrb->object_class && outer != c) {
     71        mrb_obj_iv_set_force(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"),
     72                             mrb_obj_value(outer));
     73      }
     74      return;
     75    }
     76    else {
     77      mrb_int len;
     78      const char *n = mrb_sym_name_len(mrb, id, &len);
     79
     80      mrb_str_cat_lit(mrb, name, "::");
     81      mrb_str_cat(mrb, name, n, len);
     82    }
     83  }
     84  mrb_obj_iv_set_force(mrb, (struct RObject*)c, nsym, name);
     85}
     86
     87mrb_bool
     88mrb_const_name_p(mrb_state *mrb, const char *name, mrb_int len)
     89{
     90  return len > 0 && ISUPPER(name[0]) && mrb_ident_p(name+1, len-1);
    5891}
    5992
     
    6194setup_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb_sym id)
    6295{
    63   name_class(mrb, c, id);
     96  mrb_class_name_class(mrb, outer, c, id);
    6497  mrb_obj_iv_set(mrb, (struct RObject*)outer, id, mrb_obj_value(c));
    65   if (outer != mrb->object_class) {
    66     mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"),
    67                    mrb_obj_value(outer));
    68   }
    6998}
    7099
     
    78107  if (o->c->tt == MRB_TT_SCLASS) return;
    79108  sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, mrb->class_class);
     109  sc->flags |= MRB_FL_CLASS_IS_INHERITED;
    80110  sc->mt = kh_init(mt, mrb);
    81111  sc->iv = 0;
     
    104134  mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)o);
    105135  mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern_lit(mrb, "__attached__"), mrb_obj_value(o));
    106 }
    107 
    108 static struct RClass *
     136  sc->flags |= o->flags & MRB_FL_OBJ_IS_FROZEN;
     137}
     138
     139static mrb_value
     140class_name_str(mrb_state *mrb, struct RClass* c)
     141{
     142  mrb_value path = mrb_class_path(mrb, c);
     143  if (mrb_nil_p(path)) {
     144    path = c->tt == MRB_TT_MODULE ? mrb_str_new_lit(mrb, "#<Module:") :
     145                                    mrb_str_new_lit(mrb, "#<Class:");
     146    mrb_str_cat_str(mrb, path, mrb_ptr_to_str(mrb, c));
     147    mrb_str_cat_lit(mrb, path, ">");
     148  }
     149  return path;
     150}
     151
     152static struct RClass*
    109153class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
    110154{
     
    115159}
    116160
    117 static struct RClass *
     161static struct RClass*
    118162module_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
    119163{
     
    137181}
    138182
    139 MRB_API struct RClass*
    140 mrb_class_outer_module(mrb_state *mrb, struct RClass *c)
    141 {
    142   mrb_value outer;
    143   struct RClass *cls;
    144 
    145   outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"));
    146   if (mrb_nil_p(outer)) return NULL;
    147   cls = mrb_class_ptr(outer);
    148   if (cls->tt == MRB_TT_SCLASS)
    149   {
    150     mrb_value klass;
    151     klass = mrb_obj_iv_get(mrb, (struct RObject *)cls,
    152                            mrb_intern_lit(mrb, "__attached__"));
    153     if (class_ptr_p(klass)) {
    154       cls = mrb_class_ptr(klass);
    155     }
    156   }
    157   return cls;
    158 }
    159 
    160183static void
    161184check_if_class_or_module(mrb_state *mrb, mrb_value obj)
    162185{
    163186  if (!class_ptr_p(obj)) {
    164     mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", mrb_inspect(mrb, obj));
     187    mrb_raisef(mrb, E_TYPE_ERROR, "%!v is not a class/module", obj);
    165188  }
    166189}
     
    192215}
    193216
    194 MRB_API struct RClass*
     217struct RClass*
    195218mrb_vm_define_module(mrb_state *mrb, mrb_value outer, mrb_sym id)
    196219{
     
    199222    mrb_value old = mrb_const_get(mrb, outer, id);
    200223
    201     if (mrb_type(old) != MRB_TT_MODULE) {
    202       mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a module", mrb_inspect(mrb, old));
     224    if (!mrb_module_p(old)) {
     225      mrb_raisef(mrb, E_TYPE_ERROR, "%!v is not a module", old);
    203226    }
    204227    return mrb_class_ptr(old);
     
    233256    MRB_CLASS_ORIGIN(c);
    234257    if (super && mrb_class_real(c->super) != super) {
    235       mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for Class %S (%S not %S)",
    236                  mrb_sym2str(mrb, name),
    237                  mrb_obj_value(c->super), mrb_obj_value(super));
     258      mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for Class %n (%C not %C)",
     259                 name, c->super, super);
    238260    }
    239261    return c;
     
    250272{
    251273  if (!super) {
    252     mrb_warn(mrb, "no super class for '%S', Object assumed", mrb_sym2str(mrb, name));
     274    mrb_warn(mrb, "no super class for '%n', Object assumed", name);
    253275  }
    254276  return define_class(mrb, name, super, mrb->object_class);
     
    261283}
    262284
    263 static mrb_value mrb_bob_init(mrb_state *mrb, mrb_value cv);
     285static mrb_value mrb_bob_init(mrb_state *mrb, mrb_value);
     286#ifdef MRB_METHOD_CACHE
     287static void mc_clear_all(mrb_state *mrb);
     288static void mc_clear_by_id(mrb_state *mrb, struct RClass*, mrb_sym);
     289#else
     290#define mc_clear_all(mrb)
     291#define mc_clear_by_id(mrb,c,s)
     292#endif
    264293
    265294static void
     
    271300  if (!super)
    272301    super = mrb->object_class;
     302  super->flags |= MRB_FL_CLASS_IS_INHERITED;
    273303  s = mrb_obj_value(super);
     304  mrb_mc_clear_by_class(mrb, klass);
    274305  mid = mrb_intern_lit(mrb, "inherited");
    275306  if (!mrb_func_basic_p(mrb, s, mid, mrb_bob_init)) {
    276307    mrb_value c = mrb_obj_value(klass);
    277     mrb_funcall_argv(mrb, mrb_obj_value(super), mid, 1, &c);
    278   }
    279 }
    280 
    281 MRB_API struct RClass*
     308    mrb_funcall_argv(mrb, s, mid, 1, &c);
     309  }
     310}
     311
     312struct RClass*
    282313mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id)
    283314{
     
    286317
    287318  if (!mrb_nil_p(super)) {
    288     if (mrb_type(super) != MRB_TT_CLASS) {
    289       mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)",
    290                  mrb_inspect(mrb, super));
     319    if (!mrb_class_p(super)) {
     320      mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%!v given)", super);
    291321    }
    292322    s = mrb_class_ptr(super);
     
    299329    mrb_value old = mrb_const_get(mrb, outer, id);
    300330
    301     if (mrb_type(old) != MRB_TT_CLASS) {
    302       mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class", mrb_inspect(mrb, old));
     331    if (!mrb_class_p(old)) {
     332      mrb_raisef(mrb, E_TYPE_ERROR, "%!v is not a class", old);
    303333    }
    304334    c = mrb_class_ptr(old);
     
    306336      /* check super class */
    307337      if (mrb_class_real(c->super) != s) {
    308         mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %S", old);
     338        mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %v", old);
    309339      }
    310340    }
     
    337367}
    338368
    339 MRB_API struct RClass *
     369MRB_API struct RClass*
    340370mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
    341371{
     
    343373}
    344374
    345 MRB_API struct RClass *
     375MRB_API struct RClass*
    346376mrb_class_get(mrb_state *mrb, const char *name)
    347377{
     
    349379}
    350380
    351 MRB_API struct RClass *
     381MRB_API struct RClass*
    352382mrb_exc_get(mrb_state *mrb, const char *name)
    353383{
     
    356386                              mrb_intern_cstr(mrb, name));
    357387
    358   if (mrb_type(c) != MRB_TT_CLASS) {
     388  if (!mrb_class_p(c)) {
    359389    mrb_raise(mrb, mrb->eException_class, "exception corrupted");
    360390  }
     
    369399}
    370400
    371 MRB_API struct RClass *
     401MRB_API struct RClass*
    372402mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
    373403{
     
    375405}
    376406
    377 MRB_API struct RClass *
     407MRB_API struct RClass*
    378408mrb_module_get(mrb_state *mrb, const char *name)
    379409{
     
    384414 * Defines a class under the namespace of \a outer.
    385415 * \param outer  a class which contains the new class.
    386  * \param id     name of the new class
     416 * \param name     name of the new class
    387417 * \param super  a class from which the new class will derive.
    388418 *               NULL means \c Object class.
     
    397427 *       \a super, the function just returns the defined class.
    398428 */
    399 MRB_API struct RClass *
     429MRB_API struct RClass*
    400430mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super)
    401431{
     
    405435#if 0
    406436  if (!super) {
    407     mrb_warn(mrb, "no super class for '%S::%S', Object assumed",
    408              mrb_obj_value(outer), mrb_sym2str(mrb, id));
     437    mrb_warn(mrb, "no super class for '%C::%n', Object assumed", outer, id);
    409438  }
    410439#endif
     
    415444
    416445MRB_API void
    417 mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RProc *p)
     446mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_method_t m)
    418447{
    419448  khash_t(mt) *h;
     
    422451  h = c->mt;
    423452
    424   if (MRB_FROZEN_P(c)) {
    425     if (c->tt == MRB_TT_MODULE)
    426       mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen module");
    427     else
    428       mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen class");
    429   }
     453  mrb_check_frozen(mrb, c);
    430454  if (!h) h = c->mt = kh_init(mt, mrb);
    431455  k = kh_put(mt, mrb, h, mid);
    432   kh_value(h, k) = p;
    433   if (p) {
     456  kh_value(h, k) = m;
     457  if (MRB_METHOD_PROC_P(m) && !MRB_METHOD_UNDEF_P(m)) {
     458    struct RProc *p = MRB_METHOD_PROC(m);
     459
     460    p->flags |= MRB_PROC_SCOPE;
    434461    p->c = NULL;
    435     mrb_field_write_barrier(mrb, (struct RBasic *)c, (struct RBasic *)p);
    436   }
     462    mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)p);
     463    if (!MRB_PROC_ENV_P(p)) {
     464      MRB_PROC_SET_TARGET_CLASS(p, c);
     465    }
     466  }
     467  mc_clear_by_id(mrb, c, mid);
    437468}
    438469
     
    440471mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec)
    441472{
    442   struct RProc *p;
     473  mrb_method_t m;
    443474  int ai = mrb_gc_arena_save(mrb);
    444475
    445   p = mrb_proc_new_cfunc(mrb, func);
    446   p->target_class = c;
    447   mrb_define_method_raw(mrb, c, mid, p);
     476  MRB_METHOD_FROM_FUNC(m, func);
     477  if (aspec == MRB_ARGS_NONE()) {
     478    MRB_METHOD_NOARG_SET(m);
     479  }
     480  mrb_define_method_raw(mrb, c, mid, m);
    448481  mrb_gc_arena_restore(mrb, ai);
    449482}
     
    459492mrb_notimplement(mrb_state *mrb)
    460493{
    461   const char *str;
    462   mrb_int len;
    463494  mrb_callinfo *ci = mrb->c->ci;
    464495
    465496  if (ci->mid) {
    466     str = mrb_sym2name_len(mrb, ci->mid, &len);
    467     mrb_raisef(mrb, E_NOTIMP_ERROR,
    468       "%S() function is unimplemented on this machine",
    469       mrb_str_new_static(mrb, str, (size_t)len));
     497    mrb_raisef(mrb, E_NOTIMP_ERROR, "%n() function is unimplemented on this machine", ci->mid);
    470498  }
    471499}
     
    481509
    482510static mrb_value
    483 check_type(mrb_state *mrb, mrb_value val, enum mrb_vtype t, const char *c, const char *m)
    484 {
    485   mrb_value tmp;
    486 
    487   tmp = mrb_check_convert_type(mrb, val, t, c, m);
    488   if (mrb_nil_p(tmp)) {
    489     mrb_raisef(mrb, E_TYPE_ERROR, "expected %S", mrb_str_new_cstr(mrb, c));
    490   }
    491   return tmp;
    492 }
    493 
    494 static mrb_value
    495 to_str(mrb_state *mrb, mrb_value val)
    496 {
    497   return check_type(mrb, val, MRB_TT_STRING, "String", "to_str");
    498 }
    499 
    500 static mrb_value
    501511to_ary(mrb_state *mrb, mrb_value val)
    502512{
    503   return check_type(mrb, val, MRB_TT_ARRAY, "Array", "to_ary");
     513  mrb_check_type(mrb, val, MRB_TT_ARRAY);
     514  return val;
    504515}
    505516
     
    507518to_hash(mrb_state *mrb, mrb_value val)
    508519{
    509   return check_type(mrb, val, MRB_TT_HASH, "Hash", "to_hash");
    510 }
    511 
    512 static mrb_sym
    513 to_sym(mrb_state *mrb, mrb_value ss)
    514 {
    515   if (mrb_type(ss) == MRB_TT_SYMBOL) {
    516     return mrb_symbol(ss);
    517   }
    518   else if (mrb_string_p(ss)) {
    519     return mrb_intern_str(mrb, to_str(mrb, ss));
    520   }
    521   else {
    522     mrb_value obj = mrb_funcall(mrb, ss, "inspect", 0);
    523     mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", obj);
    524     /* not reached */
    525     return 0;
    526   }
    527 }
     520  mrb_check_type(mrb, val, MRB_TT_HASH);
     521  return val;
     522}
     523
     524#define to_sym(mrb, ss) mrb_obj_to_sym(mrb, ss)
     525
     526MRB_API mrb_int
     527mrb_get_argc(mrb_state *mrb)
     528{
     529  mrb_int argc = mrb->c->ci->argc;
     530
     531  if (argc < 0) {
     532    struct RArray *a = mrb_ary_ptr(mrb->c->stack[1]);
     533
     534    argc = ARY_LEN(a);
     535  }
     536  return argc;
     537}
     538
     539MRB_API mrb_value*
     540mrb_get_argv(mrb_state *mrb)
     541{
     542  mrb_int argc = mrb->c->ci->argc;
     543  mrb_value *array_argv = mrb->c->stack + 1;
     544  if (argc < 0) {
     545    struct RArray *a = mrb_ary_ptr(*array_argv);
     546
     547    array_argv = ARY_PTR(a);
     548  }
     549  return array_argv;
     550}
     551
     552void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self);
    528553
    529554/*
     
    539564    ----------------------------------------------------------------------------------------------
    540565    o:      Object         [mrb_value]
    541     C:      class/module   [mrb_value]
     566    C:      Class/Module   [mrb_value]
    542567    S:      String         [mrb_value]            when ! follows, the value may be nil
    543568    A:      Array          [mrb_value]            when ! follows, the value may be nil
     
    546571    z:      String         [char*]                NUL terminated string; z! gives NULL for nil
    547572    a:      Array          [mrb_value*,mrb_int]   Receive two arguments; a! gives (NULL,0) for nil
    548     f:      Float          [mrb_float]
    549     i:      Integer        [mrb_int]
    550     b:      Boolean        [mrb_bool]
    551     n:      Symbol         [mrb_sym]
    552     d:      Data           [void*,mrb_data_type const] 2nd argument will be used to check data type so it won't be modified
    553     I:      Inline struct  [void*]
    554     &:      Block          [mrb_value]
    555     *:      rest argument  [mrb_value*,mrb_int]   Receive the rest of the arguments as an array.
    556     |:      optional                              Next argument of '|' and later are optional.
    557     ?:      optional given [mrb_bool]             true if preceding argument (optional) is given.
     573    f:      Fixnum/Float   [mrb_float]
     574    i:      Fixnum/Float   [mrb_int]
     575    b:      boolean        [mrb_bool]
     576    n:      String/Symbol  [mrb_sym]
     577    d:      data           [void*,mrb_data_type const] 2nd argument will be used to check data type so it won't be modified; when ! follows, the value may be nil
     578    I:      inline struct  [void*]
     579    &:      block          [mrb_value]            &! raises exception if no block given
     580    *:      rest argument  [mrb_value*,mrb_int]   The rest of the arguments as an array; *! avoid copy of the stack
     581    |:      optional                              Following arguments are optional
     582    ?:      optional given [mrb_bool]             true if preceding argument (optional) is given
     583    ':':    keyword args   [mrb_kwargs const]     Get keyword arguments
    558584 */
    559585MRB_API mrb_int
    560586mrb_get_args(mrb_state *mrb, const char *format, ...)
    561587{
     588  const char *fmt = format;
    562589  char c;
    563   int i = 0;
     590  mrb_int i = 0;
    564591  va_list ap;
    565   int argc = mrb->c->ci->argc;
    566   int arg_i = 0;
    567   mrb_bool array_argv;
     592  mrb_int argc = mrb->c->ci->argc;
     593  mrb_value *array_argv = mrb->c->stack+1;
     594  mrb_bool argv_on_stack = argc >= 0;
    568595  mrb_bool opt = FALSE;
     596  mrb_bool opt_skip = TRUE;
    569597  mrb_bool given = TRUE;
    570 
     598  mrb_value kdict;
     599  mrb_bool reqkarg = FALSE;
     600  mrb_int needargc = 0;
     601
     602  if (!argv_on_stack) {
     603    struct RArray *a = mrb_ary_ptr(*array_argv);
     604    array_argv = ARY_PTR(a);
     605    argc = ARY_LEN(a);
     606  }
    571607  va_start(ap, format);
    572   if (argc < 0) {
    573     struct RArray *a = mrb_ary_ptr(mrb->c->stack[1]);
    574 
    575     argc = a->len;
    576     array_argv = TRUE;
     608
     609#define ARGV array_argv
     610
     611  while ((c = *fmt++)) {
     612    switch (c) {
     613    case '|':
     614      opt = TRUE;
     615      break;
     616    case '*':
     617      opt_skip = FALSE;
     618      if (!reqkarg) reqkarg = strchr(fmt, ':') ? TRUE : FALSE;
     619      goto check_exit;
     620    case '!':
     621      break;
     622    case ':':
     623      reqkarg = TRUE;
     624      /* fall through */
     625    case '&': case '?':
     626      if (opt) opt_skip = FALSE;
     627      break;
     628    default:
     629      if (!opt) needargc ++;
     630      break;
     631    }
     632  }
     633
     634 check_exit:
     635  if (reqkarg && argc > needargc && mrb_hash_p(kdict = ARGV[argc - 1])) {
     636    mrb_hash_check_kdict(mrb, kdict);
     637    argc --;
    577638  }
    578639  else {
    579     array_argv = FALSE;
    580   }
    581 
    582 #define ARGV \
    583   (array_argv ? mrb_ary_ptr(mrb->c->stack[1])->ptr : (mrb->c->stack + 1))
    584 
     640    kdict = mrb_nil_value();
     641  }
     642
     643  opt = FALSE;
     644  i = 0;
    585645  while ((c = *format++)) {
     646    mrb_value *argv = ARGV;
     647    mrb_bool altmode;
     648
    586649    switch (c) {
    587     case '|': case '*': case '&': case '?':
     650    case '|': case '*': case '&': case '?': case ':':
    588651      break;
    589652    default:
     
    599662    }
    600663
     664    if (*format == '!') {
     665      format ++;
     666      altmode = TRUE;
     667    }
     668    else {
     669      altmode = FALSE;
     670    }
     671
    601672    switch (c) {
    602673    case 'o':
     
    606677        p = va_arg(ap, mrb_value*);
    607678        if (i < argc) {
    608           *p = ARGV[arg_i++];
    609           i++;
     679          *p = argv[i++];
    610680        }
    611681      }
     
    619689          mrb_value ss;
    620690
    621           ss = ARGV[arg_i++];
     691          ss = argv[i++];
    622692          if (!class_ptr_p(ss)) {
    623             mrb_raisef(mrb, E_TYPE_ERROR, "%S is not class/module", ss);
     693            mrb_raisef(mrb, E_TYPE_ERROR, "%v is not class/module", ss);
    624694          }
    625695          *p = ss;
    626           i++;
    627696        }
    628697      }
     
    633702
    634703        p = va_arg(ap, mrb_value*);
    635         if (*format == '!') {
    636           format++;
    637           if (i < argc && mrb_nil_p(ARGV[arg_i])) {
    638             *p = ARGV[arg_i++];
    639             i++;
    640             break;
     704        if (i < argc) {
     705          *p = argv[i++];
     706          if (!(altmode && mrb_nil_p(*p))) {
     707            mrb_to_str(mrb, *p);
    641708          }
    642         }
    643         if (i < argc) {
    644           *p = to_str(mrb, ARGV[arg_i++]);
    645           i++;
    646709        }
    647710      }
     
    652715
    653716        p = va_arg(ap, mrb_value*);
    654         if (*format == '!') {
    655           format++;
    656           if (i < argc && mrb_nil_p(ARGV[arg_i])) {
    657             *p = ARGV[arg_i++];
    658             i++;
    659             break;
     717        if (i < argc) {
     718          *p = argv[i++];
     719          if (!(altmode && mrb_nil_p(*p))) {
     720            *p = to_ary(mrb, *p);
    660721          }
    661         }
    662         if (i < argc) {
    663           *p = to_ary(mrb, ARGV[arg_i++]);
    664           i++;
    665722        }
    666723      }
     
    671728
    672729        p = va_arg(ap, mrb_value*);
    673         if (*format == '!') {
    674           format++;
    675           if (i < argc && mrb_nil_p(ARGV[arg_i])) {
    676             *p = ARGV[arg_i++];
    677             i++;
    678             break;
     730        if (i < argc) {
     731          *p = argv[i++];
     732          if (!(altmode && mrb_nil_p(*p))) {
     733            *p = to_hash(mrb, *p);
    679734          }
    680         }
    681         if (i < argc) {
    682           *p = to_hash(mrb, ARGV[arg_i++]);
    683           i++;
    684735        }
    685736      }
     
    693744        ps = va_arg(ap, char**);
    694745        pl = va_arg(ap, mrb_int*);
    695         if (*format == '!') {
    696           format++;
    697           if (i < argc && mrb_nil_p(ARGV[arg_i])) {
     746        if (i < argc) {
     747          ss = argv[i++];
     748          if (altmode && mrb_nil_p(ss)) {
    698749            *ps = NULL;
    699750            *pl = 0;
    700             i++; arg_i++;
    701             break;
    702751          }
    703         }
    704         if (i < argc) {
    705           ss = to_str(mrb, ARGV[arg_i++]);
    706           *ps = RSTRING_PTR(ss);
    707           *pl = RSTRING_LEN(ss);
    708           i++;
     752          else {
     753            mrb_to_str(mrb, ss);
     754            *ps = RSTRING_PTR(ss);
     755            *pl = RSTRING_LEN(ss);
     756          }
    709757        }
    710758      }
     
    716764
    717765        ps = va_arg(ap, const char**);
    718         if (*format == '!') {
    719           format++;
    720           if (i < argc && mrb_nil_p(ARGV[arg_i])) {
     766        if (i < argc) {
     767          ss = argv[i++];
     768          if (altmode && mrb_nil_p(ss)) {
    721769            *ps = NULL;
    722             i++; arg_i++;
    723             break;
    724770          }
    725         }
    726         if (i < argc) {
    727           ss = to_str(mrb, ARGV[arg_i++]);
    728           *ps = mrb_string_value_cstr(mrb, &ss);
    729           i++;
     771          else {
     772            mrb_to_str(mrb, ss);
     773            *ps = RSTRING_CSTR(mrb, ss);
     774          }
    730775        }
    731776      }
     
    740785        pb = va_arg(ap, mrb_value**);
    741786        pl = va_arg(ap, mrb_int*);
    742         if (*format == '!') {
    743           format++;
    744           if (i < argc && mrb_nil_p(ARGV[arg_i])) {
     787        if (i < argc) {
     788          aa = argv[i++];
     789          if (altmode && mrb_nil_p(aa)) {
    745790            *pb = 0;
    746791            *pl = 0;
    747             i++; arg_i++;
    748             break;
    749792          }
    750         }
    751         if (i < argc) {
    752           aa = to_ary(mrb, ARGV[arg_i++]);
    753           a = mrb_ary_ptr(aa);
    754           *pb = a->ptr;
    755           *pl = a->len;
    756           i++;
     793          else {
     794            aa = to_ary(mrb, aa);
     795            a = mrb_ary_ptr(aa);
     796            *pb = ARY_PTR(a);
     797            *pl = ARY_LEN(a);
     798          }
    757799        }
    758800      }
     
    765807        p = va_arg(ap, void**);
    766808        if (i < argc) {
    767           ss = ARGV[arg_i];
    768           if (mrb_type(ss) != MRB_TT_ISTRUCT)
     809          ss = argv[i++];
     810          if (!mrb_istruct_p(ss))
    769811          {
    770             mrb_raisef(mrb, E_TYPE_ERROR, "%S is not inline struct", ss);
     812            mrb_raisef(mrb, E_TYPE_ERROR, "%v is not inline struct", ss);
    771813          }
    772814          *p = mrb_istruct_ptr(ss);
    773           arg_i++;
    774           i++;
    775         }
    776       }
    777       break;
     815        }
     816      }
     817      break;
     818#ifndef MRB_WITHOUT_FLOAT
    778819    case 'f':
    779820      {
     
    782823        p = va_arg(ap, mrb_float*);
    783824        if (i < argc) {
    784           *p = mrb_to_flo(mrb, ARGV[arg_i]);
    785           arg_i++;
    786           i++;
    787         }
    788       }
    789       break;
     825          *p = mrb_to_flo(mrb, argv[i++]);
     826        }
     827      }
     828      break;
     829#endif
    790830    case 'i':
    791831      {
     
    794834        p = va_arg(ap, mrb_int*);
    795835        if (i < argc) {
    796           switch (mrb_type(ARGV[arg_i])) {
    797             case MRB_TT_FIXNUM:
    798               *p = mrb_fixnum(ARGV[arg_i]);
    799               break;
    800             case MRB_TT_FLOAT:
    801               {
    802                 mrb_float f = mrb_float(ARGV[arg_i]);
    803 
    804                 if (!FIXABLE_FLOAT(f)) {
    805                   mrb_raise(mrb, E_RANGE_ERROR, "float too big for int");
    806                 }
    807                 *p = (mrb_int)f;
    808               }
    809               break;
    810             case MRB_TT_STRING:
    811               mrb_raise(mrb, E_TYPE_ERROR, "no implicit conversion of String into Integer");
    812               break;
    813             default:
    814               *p = mrb_fixnum(mrb_Integer(mrb, ARGV[arg_i]));
    815               break;
    816           }
    817           arg_i++;
    818           i++;
     836          *p = mrb_fixnum(mrb_to_int(mrb, argv[i++]));
    819837        }
    820838      }
     
    825843
    826844        if (i < argc) {
    827           mrb_value b = ARGV[arg_i++];
     845          mrb_value b = argv[i++];
    828846          *boolp = mrb_test(b);
    829           i++;
    830847        }
    831848      }
     
    839856          mrb_value ss;
    840857
    841           ss = ARGV[arg_i++];
     858          ss = argv[i++];
    842859          *symp = to_sym(mrb, ss);
    843           i++;
    844860        }
    845861      }
     
    852868        datap = va_arg(ap, void**);
    853869        type = va_arg(ap, struct mrb_data_type const*);
    854         if (*format == '!') {
    855           format++;
    856           if (i < argc && mrb_nil_p(ARGV[arg_i])) {
     870        if (i < argc) {
     871          mrb_value dd = argv[i++];
     872          if (altmode && mrb_nil_p(dd)) {
    857873            *datap = 0;
    858             i++; arg_i++;
    859             break;
    860874          }
    861         }
    862         if (i < argc) {
    863           *datap = mrb_data_get_ptr(mrb, ARGV[arg_i++], type);
    864           ++i;
     875          else {
     876            *datap = mrb_data_get_ptr(mrb, dd, type);
     877          }
    865878        }
    866879      }
     
    878891          bp = mrb->c->stack + mrb->c->ci->argc + 1;
    879892        }
     893        if (altmode && mrb_nil_p(*bp)) {
     894          mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
     895        }
    880896        *p = *bp;
    881897      }
    882898      break;
    883899    case '|':
     900      if (opt_skip && i == argc) goto finish;
    884901      opt = TRUE;
    885902      break;
     
    897914        mrb_value **var;
    898915        mrb_int *pl;
     916        mrb_bool nocopy = (altmode || !argv_on_stack) ? TRUE : FALSE;
    899917
    900918        var = va_arg(ap, mrb_value**);
     
    903921          *pl = argc-i;
    904922          if (*pl > 0) {
    905             *var = ARGV + arg_i;
     923            if (nocopy) {
     924              *var = argv+i;
     925            }
     926            else {
     927              mrb_value args = mrb_ary_new_from_values(mrb, *pl, argv+i);
     928              RARRAY(args)->c = NULL;
     929              *var = RARRAY_PTR(args);
     930            }
    906931          }
    907932          i = argc;
    908           arg_i += *pl;
    909933        }
    910934        else {
     
    914938      }
    915939      break;
     940
     941    case ':':
     942      {
     943        mrb_value ksrc = mrb_hash_p(kdict) ? mrb_hash_dup(mrb, kdict) : mrb_hash_new(mrb);
     944        const mrb_kwargs *kwargs = va_arg(ap, const mrb_kwargs*);
     945        mrb_value *rest;
     946
     947        if (kwargs == NULL) {
     948          rest = NULL;
     949        }
     950        else {
     951          uint32_t kwnum = kwargs->num;
     952          uint32_t required = kwargs->required;
     953          const char *const *kname = kwargs->table;
     954          mrb_value *values = kwargs->values;
     955          uint32_t j;
     956          const uint32_t keyword_max = 40;
     957
     958          if (kwnum > keyword_max || required > kwnum) {
     959            mrb_raise(mrb, E_ARGUMENT_ERROR, "keyword number is too large");
     960          }
     961
     962          for (j = required; j > 0; j --, kname ++, values ++) {
     963            mrb_value k = mrb_symbol_value(mrb_intern_cstr(mrb, *kname));
     964            if (!mrb_hash_key_p(mrb, ksrc, k)) {
     965              mrb_raisef(mrb, E_ARGUMENT_ERROR, "missing keyword: %s", *kname);
     966            }
     967            *values = mrb_hash_delete_key(mrb, ksrc, k);
     968            mrb_gc_protect(mrb, *values);
     969          }
     970
     971          for (j = kwnum - required; j > 0; j --, kname ++, values ++) {
     972            mrb_value k = mrb_symbol_value(mrb_intern_cstr(mrb, *kname));
     973            if (mrb_hash_key_p(mrb, ksrc, k)) {
     974              *values = mrb_hash_delete_key(mrb, ksrc, k);
     975              mrb_gc_protect(mrb, *values);
     976            }
     977            else {
     978              *values = mrb_undef_value();
     979            }
     980          }
     981
     982          rest = kwargs->rest;
     983        }
     984
     985        if (rest) {
     986          *rest = ksrc;
     987        }
     988        else if (!mrb_hash_empty_p(mrb, ksrc)) {
     989          ksrc = mrb_hash_keys(mrb, ksrc);
     990          ksrc = RARRAY_PTR(ksrc)[0];
     991          mrb_raisef(mrb, E_ARGUMENT_ERROR, "unknown keyword: %v", ksrc);
     992        }
     993      }
     994      break;
     995
    916996    default:
    917       mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid argument specifier %S", mrb_str_new(mrb, &c, 1));
     997      mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid argument specifier %c", c);
    918998      break;
    919999    }
     
    9251005    mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
    9261006  }
     1007
     1008finish:
    9271009  va_end(ap);
    9281010  return i;
     
    9831065    int superclass_seen = 0;
    9841066
    985     if (m->flags & MRB_FLAG_IS_PREPENDED)
     1067    if (m->flags & MRB_FL_CLASS_IS_PREPENDED)
    9861068      goto skip;
    9871069
     
    9901072
    9911073    p = c->super;
    992     while(p) {
     1074    while (p) {
    9931075      if (p->tt == MRB_TT_ICLASS) {
    9941076        if (p->mt == m->mt) {
     
    10061088
    10071089    ic = include_class_new(mrb, m, ins_pos->super);
     1090    m->flags |= MRB_FL_CLASS_IS_INHERITED;
    10081091    ins_pos->super = ic;
    1009     mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ins_pos->super);
     1092    mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ic);
     1093    mrb_mc_clear_by_class(mrb, ins_pos);
    10101094    ins_pos = ic;
    10111095  skip:
    10121096    m = m->super;
    10131097  }
     1098  mc_clear_all(mrb);
    10141099  return 0;
    10151100}
     
    10181103mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
    10191104{
    1020   int changed = include_module_at(mrb, c, find_origin(c), m, 1);
    1021   if (changed < 0) {
     1105  mrb_check_frozen(mrb, c);
     1106  if (include_module_at(mrb, c, find_origin(c), m, 1) < 0) {
    10221107    mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic include detected");
    10231108  }
     
    10301115  int changed = 0;
    10311116
    1032   if (!(c->flags & MRB_FLAG_IS_PREPENDED)) {
     1117  mrb_check_frozen(mrb, c);
     1118  if (!(c->flags & MRB_FL_CLASS_IS_PREPENDED)) {
    10331119    origin = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, c);
    1034     origin->flags |= MRB_FLAG_IS_ORIGIN;
     1120    origin->flags |= MRB_FL_CLASS_IS_ORIGIN | MRB_FL_CLASS_IS_INHERITED;
    10351121    origin->super = c->super;
    10361122    c->super = origin;
     
    10381124    c->mt = kh_init(mt, mrb);
    10391125    mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)origin);
    1040     c->flags |= MRB_FLAG_IS_PREPENDED;
     1126    c->flags |= MRB_FL_CLASS_IS_PREPENDED;
    10411127  }
    10421128  changed = include_module_at(mrb, c, c, m, 0);
     
    11151201      mrb_ary_push(mrb, result, mrb_obj_value(c->c));
    11161202    }
    1117     else if (!(c->flags & MRB_FLAG_IS_PREPENDED)) {
     1203    else if (!(c->flags & MRB_FL_CLASS_IS_PREPENDED)) {
    11181204      mrb_ary_push(mrb, result, mrb_obj_value(c));
    11191205    }
     
    11331219  mrb_include_module(mrb, mrb_class_ptr(mrb_singleton_class(mrb, obj)), mrb_class_ptr(mod));
    11341220  return mod;
    1135 }
    1136 
    1137 static mrb_value
    1138 mrb_mod_included_modules(mrb_state *mrb, mrb_value self)
    1139 {
    1140   mrb_value result;
    1141   struct RClass *c = mrb_class_ptr(self);
    1142   struct RClass *origin = c;
    1143 
    1144   MRB_CLASS_ORIGIN(origin);
    1145   result = mrb_ary_new(mrb);
    1146   while (c) {
    1147     if (c != origin && c->tt == MRB_TT_ICLASS) {
    1148       if (c->c->tt == MRB_TT_MODULE) {
    1149         mrb_ary_push(mrb, result, mrb_obj_value(c->c));
    1150       }
    1151     }
    1152     c = c->super;
    1153   }
    1154 
    1155   return result;
    11561221}
    11571222
     
    11671232  }
    11681233  return mod;
    1169 }
    1170 
    1171 mrb_value mrb_class_instance_method_list(mrb_state*, mrb_bool, struct RClass*, int);
    1172 
    1173 /* 15.2.2.4.33 */
    1174 /*
    1175  *  call-seq:
    1176  *     mod.instance_methods(include_super=true)   -> array
    1177  *
    1178  *  Returns an array containing the names of the public and protected instance
    1179  *  methods in the receiver. For a module, these are the public and protected methods;
    1180  *  for a class, they are the instance (not singleton) methods. With no
    1181  *  argument, or with an argument that is <code>false</code>, the
    1182  *  instance methods in <i>mod</i> are returned, otherwise the methods
    1183  *  in <i>mod</i> and <i>mod</i>'s superclasses are returned.
    1184  *
    1185  *     module A
    1186  *       def method1()  end
    1187  *     end
    1188  *     class B
    1189  *       def method2()  end
    1190  *     end
    1191  *     class C < B
    1192  *       def method3()  end
    1193  *     end
    1194  *
    1195  *     A.instance_methods                #=> [:method1]
    1196  *     B.instance_methods(false)         #=> [:method2]
    1197  *     C.instance_methods(false)         #=> [:method3]
    1198  *     C.instance_methods(true).length   #=> 43
    1199  */
    1200 
    1201 static mrb_value
    1202 mrb_mod_instance_methods(mrb_state *mrb, mrb_value mod)
    1203 {
    1204   struct RClass *c = mrb_class_ptr(mod);
    1205   mrb_bool recur = TRUE;
    1206   mrb_get_args(mrb, "|b", &recur);
    1207   return mrb_class_instance_method_list(mrb, recur, c, 0);
    12081234}
    12091235
     
    12331259  case MRB_TT_SYMBOL:
    12341260  case MRB_TT_FIXNUM:
     1261#ifndef MRB_WITHOUT_FLOAT
    12351262  case MRB_TT_FLOAT:
     1263#endif
    12361264    mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton");
    12371265    return mrb_nil_value();    /* not reached */
     
    12641292}
    12651293
    1266 MRB_API struct RProc*
     1294#ifdef MRB_METHOD_CACHE
     1295static void
     1296mc_clear_all(mrb_state *mrb)
     1297{
     1298  struct mrb_cache_entry *mc = mrb->cache;
     1299  int i;
     1300
     1301  for (i=0; i<MRB_METHOD_CACHE_SIZE; i++) {
     1302    mc[i].c = 0;
     1303  }
     1304}
     1305
     1306void
     1307mrb_mc_clear_by_class(mrb_state *mrb, struct RClass *c)
     1308{
     1309  struct mrb_cache_entry *mc = mrb->cache;
     1310  int i;
     1311
     1312  if (c->flags & MRB_FL_CLASS_IS_INHERITED) {
     1313    mc_clear_all(mrb);
     1314    c->flags &= ~MRB_FL_CLASS_IS_INHERITED;
     1315    return;
     1316  }
     1317  for (i=0; i<MRB_METHOD_CACHE_SIZE; i++) {
     1318    if (mc[i].c == c) mc[i].c = 0;
     1319  }
     1320}
     1321
     1322static void
     1323mc_clear_by_id(mrb_state *mrb, struct RClass *c, mrb_sym mid)
     1324{
     1325  struct mrb_cache_entry *mc = mrb->cache;
     1326  int i;
     1327
     1328  if (c->flags & MRB_FL_CLASS_IS_INHERITED) {
     1329    mc_clear_all(mrb);
     1330    c->flags &= ~MRB_FL_CLASS_IS_INHERITED;
     1331    return;
     1332  }
     1333  for (i=0; i<MRB_METHOD_CACHE_SIZE; i++) {
     1334    if (mc[i].c == c || mc[i].mid == mid)
     1335      mc[i].c = 0;
     1336  }
     1337}
     1338#endif
     1339
     1340MRB_API mrb_method_t
    12671341mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid)
    12681342{
    12691343  khiter_t k;
    1270   struct RProc *m;
     1344  mrb_method_t m;
    12711345  struct RClass *c = *cp;
     1346#ifdef MRB_METHOD_CACHE
     1347  struct RClass *oc = c;
     1348  int h = kh_int_hash_func(mrb, ((intptr_t)oc) ^ mid) & (MRB_METHOD_CACHE_SIZE-1);
     1349  struct mrb_cache_entry *mc = &mrb->cache[h];
     1350
     1351  if (mc->c == c && mc->mid == mid) {
     1352    *cp = mc->c0;
     1353    return mc->m;
     1354  }
     1355#endif
    12721356
    12731357  while (c) {
     
    12781362      if (k != kh_end(h)) {
    12791363        m = kh_value(h, k);
    1280         if (!m) break;
     1364        if (MRB_METHOD_UNDEF_P(m)) break;
    12811365        *cp = c;
     1366#ifdef MRB_METHOD_CACHE
     1367        mc->c = oc;
     1368        mc->c0 = c;
     1369        mc->mid = mid;
     1370        mc->m = m;
     1371#endif
    12821372        return m;
    12831373      }
     
    12851375    c = c->super;
    12861376  }
    1287   return NULL;                  /* no method */
    1288 }
    1289 
    1290 MRB_API struct RProc*
     1377  MRB_METHOD_FROM_PROC(m, NULL);
     1378  return m;                  /* no method */
     1379}
     1380
     1381MRB_API mrb_method_t
    12911382mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid)
    12921383{
    1293   struct RProc *m;
     1384  mrb_method_t m;
    12941385
    12951386  m = mrb_method_search_vm(mrb, &c, mid);
    1296   if (!m) {
    1297     mrb_value inspect = mrb_funcall(mrb, mrb_obj_value(c), "inspect", 0);
    1298     if (mrb_string_p(inspect) && RSTRING_LEN(inspect) > 64) {
    1299       inspect = mrb_any_to_s(mrb, mrb_obj_value(c));
    1300     }
    1301     mrb_name_error(mrb, mid, "undefined method '%S' for class %S",
    1302                mrb_sym2str(mrb, mid), inspect);
     1387  if (MRB_METHOD_UNDEF_P(m)) {
     1388    mrb_name_error(mrb, mid, "undefined method '%n' for class %C", mid, c);
    13031389  }
    13041390  return m;
    13051391}
    13061392
    1307 static mrb_value
    1308 attr_reader(mrb_state *mrb, mrb_value obj)
    1309 {
    1310   mrb_value name = mrb_proc_cfunc_env_get(mrb, 0);
    1311   return mrb_iv_get(mrb, obj, to_sym(mrb, name));
    1312 }
    1313 
    1314 static mrb_value
    1315 mrb_mod_attr_reader(mrb_state *mrb, mrb_value mod)
     1393#define ONSTACK_ALLOC_MAX 32
     1394
     1395static mrb_sym
     1396prepare_name_common(mrb_state *mrb, mrb_sym sym, const char *prefix, const char *suffix)
     1397{
     1398  char onstack[ONSTACK_ALLOC_MAX];
     1399  mrb_int sym_len;
     1400  const char *sym_str = mrb_sym_name_len(mrb, sym, &sym_len);
     1401  size_t prefix_len = prefix ? strlen(prefix) : 0;
     1402  size_t suffix_len = suffix ? strlen(suffix) : 0;
     1403  size_t name_len = sym_len + prefix_len + suffix_len;
     1404  char *buf = name_len > sizeof(onstack) ? (char *)mrb_alloca(mrb, name_len) : onstack;
     1405  char *p = buf;
     1406
     1407  if (prefix_len > 0) {
     1408    memcpy(p, prefix, prefix_len);
     1409    p += prefix_len;
     1410  }
     1411
     1412  memcpy(p, sym_str, sym_len);
     1413  p += sym_len;
     1414
     1415  if (suffix_len > 0) {
     1416    memcpy(p, suffix, suffix_len);
     1417    p += suffix_len;
     1418  }
     1419
     1420  return mrb_intern(mrb, buf, name_len);
     1421}
     1422
     1423static mrb_value
     1424prepare_ivar_name(mrb_state *mrb, mrb_sym sym)
     1425{
     1426  sym = prepare_name_common(mrb, sym, "@", NULL);
     1427  mrb_iv_name_sym_check(mrb, sym);
     1428  return mrb_symbol_value(sym);
     1429}
     1430
     1431static mrb_sym
     1432prepare_writer_name(mrb_state *mrb, mrb_sym sym)
     1433{
     1434  return prepare_name_common(mrb, sym, NULL, "=");
     1435}
     1436
     1437static mrb_value
     1438mod_attr_define(mrb_state *mrb, mrb_value mod, mrb_value (*accessor)(mrb_state *, mrb_value), mrb_sym (*access_name)(mrb_state *, mrb_sym))
    13161439{
    13171440  struct RClass *c = mrb_class_ptr(mod);
     
    13231446  ai = mrb_gc_arena_save(mrb);
    13241447  for (i=0; i<argc; i++) {
    1325     mrb_value name, str;
    1326     mrb_sym method, sym;
     1448    mrb_value name;
     1449    mrb_sym method;
     1450    struct RProc *p;
     1451    mrb_method_t m;
    13271452
    13281453    method = to_sym(mrb, argv[i]);
    1329     name = mrb_sym2str(mrb, method);
    1330     str = mrb_str_buf_new(mrb, RSTRING_LEN(name)+1);
    1331     mrb_str_cat_lit(mrb, str, "@");
    1332     mrb_str_cat_str(mrb, str, name);
    1333     sym = mrb_intern_str(mrb, str);
    1334     mrb_iv_check(mrb, sym);
    1335     name = mrb_symbol_value(sym);
    1336     mrb_define_method_raw(mrb, c, method,
    1337                           mrb_proc_new_cfunc_with_env(mrb, attr_reader, 1, &name));
     1454    name = prepare_ivar_name(mrb, method);
     1455    if (access_name) {
     1456      method = access_name(mrb, method);
     1457    }
     1458
     1459    p = mrb_proc_new_cfunc_with_env(mrb, accessor, 1, &name);
     1460    MRB_METHOD_FROM_PROC(m, p);
     1461    mrb_define_method_raw(mrb, c, method, m);
    13381462    mrb_gc_arena_restore(mrb, ai);
    13391463  }
    13401464  return mrb_nil_value();
     1465}
     1466
     1467static mrb_value
     1468attr_reader(mrb_state *mrb, mrb_value obj)
     1469{
     1470  mrb_value name = mrb_proc_cfunc_env_get(mrb, 0);
     1471  return mrb_iv_get(mrb, obj, to_sym(mrb, name));
     1472}
     1473
     1474static mrb_value
     1475mrb_mod_attr_reader(mrb_state *mrb, mrb_value mod)
     1476{
     1477  return mod_attr_define(mrb, mod, attr_reader, NULL);
    13411478}
    13421479
     
    13551492mrb_mod_attr_writer(mrb_state *mrb, mrb_value mod)
    13561493{
    1357   struct RClass *c = mrb_class_ptr(mod);
    1358   mrb_value *argv;
    1359   mrb_int argc, i;
    1360   int ai;
    1361 
    1362   mrb_get_args(mrb, "*", &argv, &argc);
    1363   ai = mrb_gc_arena_save(mrb);
    1364   for (i=0; i<argc; i++) {
    1365     mrb_value name, str, attr;
    1366     mrb_sym method, sym;
    1367 
    1368     method = to_sym(mrb, argv[i]);
    1369 
    1370     /* prepare iv name (@name) */
    1371     name = mrb_sym2str(mrb, method);
    1372     str = mrb_str_buf_new(mrb, RSTRING_LEN(name)+1);
    1373     mrb_str_cat_lit(mrb, str, "@");
    1374     mrb_str_cat_str(mrb, str, name);
    1375     sym = mrb_intern_str(mrb, str);
    1376     mrb_iv_check(mrb, sym);
    1377     attr = mrb_symbol_value(sym);
    1378 
    1379     /* prepare method name (name=) */
    1380     str = mrb_str_buf_new(mrb, RSTRING_LEN(str));
    1381     mrb_str_cat_str(mrb, str, name);
    1382     mrb_str_cat_lit(mrb, str, "=");
    1383     method = mrb_intern_str(mrb, str);
    1384 
    1385     mrb_define_method_raw(mrb, c, method,
    1386                           mrb_proc_new_cfunc_with_env(mrb, attr_writer, 1, &attr));
    1387     mrb_gc_arena_restore(mrb, ai);
    1388   }
    1389   return mrb_nil_value();
     1494  return mod_attr_define(mrb, mod, attr_writer, prepare_writer_name);
    13901495}
    13911496
     
    14021507  if (ttype == 0) ttype = MRB_TT_OBJECT;
    14031508  if (ttype <= MRB_TT_CPTR) {
    1404     mrb_raisef(mrb, E_TYPE_ERROR, "can't create instance of %S", cv);
     1509    mrb_raisef(mrb, E_TYPE_ERROR, "can't create instance of %v", cv);
    14051510  }
    14061511  o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c);
     
    14201525 */
    14211526
    1422 MRB_API mrb_value
     1527mrb_value
    14231528mrb_instance_new(mrb_state *mrb, mrb_value cv)
    14241529{
     
    14261531  mrb_value *argv;
    14271532  mrb_int argc;
    1428 
    1429   mrb_get_args(mrb, "*&", &argv, &argc, &blk);
     1533  mrb_sym init;
     1534
     1535  mrb_get_args(mrb, "*!&", &argv, &argc, &blk);
    14301536  obj = mrb_instance_alloc(mrb, cv);
    1431   mrb_funcall_with_block(mrb, obj, mrb_intern_lit(mrb, "initialize"), argc, argv, blk);
    1432 
     1537  init = mrb_intern_lit(mrb, "initialize");
     1538  if (!mrb_func_basic_p(mrb, obj, init, mrb_bob_init)) {
     1539    mrb_funcall_with_block(mrb, obj, init, argc, argv, blk);
     1540  }
    14331541  return obj;
    14341542}
     
    14741582  new_class = mrb_obj_value(mrb_class_new(mrb, mrb_class_ptr(super)));
    14751583  mid = mrb_intern_lit(mrb, "initialize");
    1476   if (!mrb_func_basic_p(mrb, new_class, mid, mrb_bob_init)) {
     1584  if (mrb_func_basic_p(mrb, new_class, mid, mrb_class_initialize)) {
     1585    mrb_class_initialize(mrb, new_class);
     1586  }
     1587  else {
    14771588    mrb_funcall_with_block(mrb, new_class, mid, n, &super, blk);
    14781589  }
     
    15591670mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid)
    15601671{
    1561   khiter_t k;
    1562 
    1563   while (c) {
    1564     khash_t(mt) *h = c->mt;
    1565 
    1566     if (h) {
    1567       k = kh_get(mt, mrb, h, mid);
    1568       if (k != kh_end(h)) {
    1569         if (kh_value(h, k)) {
    1570           return TRUE;  /* method exists */
    1571         }
    1572         else {
    1573           return FALSE; /* undefined method */
    1574         }
    1575       }
    1576     }
    1577     c = c->super;
    1578   }
    1579   return FALSE;         /* no method */
     1672  mrb_method_t m;
     1673
     1674  m = mrb_method_search_vm(mrb, &c, mid);
     1675  if (MRB_METHOD_UNDEF_P(m)) {
     1676    return FALSE;
     1677  }
     1678  return TRUE;
    15801679}
    15811680
     
    15901689{
    15911690  mrb_value path;
    1592   const char *name;
    1593   mrb_sym classpath = mrb_intern_lit(mrb, "__classpath__");
    1594 
    1595   path = mrb_obj_iv_get(mrb, (struct RObject*)c, classpath);
     1691  mrb_sym nsym = mrb_intern_lit(mrb, "__classname__");
     1692
     1693  path = mrb_obj_iv_get(mrb, (struct RObject*)c, nsym);
    15961694  if (mrb_nil_p(path)) {
    1597     struct RClass *outer = mrb_class_outer_module(mrb, c);
    1598     mrb_sym sym = mrb_class_sym(mrb, c, outer);
    1599     mrb_int len;
    1600 
    1601     if (sym == 0) {
    1602       return mrb_nil_value();
    1603     }
    1604     else if (outer && outer != c && outer != mrb->object_class) {
    1605       mrb_value base = mrb_class_path(mrb, outer);
    1606       path = mrb_str_buf_new(mrb, 0);
    1607       if (mrb_nil_p(base)) {
    1608         mrb_str_cat_lit(mrb, path, "#<Class:");
    1609         mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, outer));
    1610         mrb_str_cat_lit(mrb, path, ">");
    1611       }
    1612       else {
    1613         mrb_str_concat(mrb, path, base);
    1614       }
    1615       mrb_str_cat_lit(mrb, path, "::");
    1616       name = mrb_sym2name_len(mrb, sym, &len);
    1617       mrb_str_cat(mrb, path, name, len);
    1618     }
    1619     else {
    1620       name = mrb_sym2name_len(mrb, sym, &len);
    1621       path = mrb_str_new(mrb, name, len);
    1622     }
    1623     if (!MRB_FROZEN_P(c)) {
    1624       mrb_obj_iv_set(mrb, (struct RObject*)c, classpath, path);
    1625     }
     1695    /* no name (yet) */
     1696    return mrb_class_find_path(mrb, c);
     1697  }
     1698  else if (mrb_symbol_p(path)) {
     1699    /* toplevel class/module */
     1700    return mrb_sym_str(mrb, mrb_symbol(path));
    16261701  }
    16271702  return mrb_str_dup(mrb, path);
    16281703}
    16291704
    1630 MRB_API struct RClass *
     1705MRB_API struct RClass*
    16311706mrb_class_real(struct RClass* cl)
    16321707{
    1633   if (cl == 0)
    1634     return NULL;
     1708  if (cl == 0) return NULL;
    16351709  while ((cl->tt == MRB_TT_SCLASS) || (cl->tt == MRB_TT_ICLASS)) {
    16361710    cl = cl->super;
     1711    if (cl == 0) return NULL;
    16371712  }
    16381713  return cl;
     
    16421717mrb_class_name(mrb_state *mrb, struct RClass* c)
    16431718{
    1644   mrb_value path = mrb_class_path(mrb, c);
    1645   if (mrb_nil_p(path)) {
    1646     path = mrb_str_new_lit(mrb, "#<Class:");
    1647     mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, c));
    1648     mrb_str_cat_lit(mrb, path, ">");
    1649   }
    1650   return RSTRING_PTR(path);
     1719  mrb_value name = class_name_str(mrb, c);
     1720  return RSTRING_PTR(name);
    16511721}
    16521722
     
    16671737{
    16681738  if (super->tt != MRB_TT_CLASS) {
    1669     mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", mrb_obj_value(super));
     1739    mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%C given)", super);
    16701740  }
    16711741  if (super->tt == MRB_TT_SCLASS) {
     
    17341804mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b)
    17351805{
    1736   struct RProc *m = mrb_method_search(mrb, c, b);
    1737 
     1806  mrb_method_t m = mrb_method_search(mrb, c, b);
     1807
     1808  if (!MRB_METHOD_CFUNC_P(m)) {
     1809    struct RProc *p = MRB_METHOD_PROC(m);
     1810
     1811    if (MRB_PROC_ENV_P(p)) {
     1812      MRB_PROC_ENV(p)->mid = b;
     1813    }
     1814    else {
     1815      struct RClass *tc = MRB_PROC_TARGET_CLASS(p);
     1816      struct REnv *e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, NULL);
     1817
     1818      e->mid = b;
     1819      if (tc) {
     1820        e->c = tc;
     1821        mrb_field_write_barrier(mrb, (struct RBasic*)e, (struct RBasic*)tc);
     1822      }
     1823      p->e.env = e;
     1824      p->flags |= MRB_PROC_ENVSET;
     1825    }
     1826  }
    17381827  mrb_define_method_raw(mrb, c, a, m);
    17391828}
     
    17411830/*!
    17421831 * Defines an alias of a method.
     1832 * \param mrb    the mruby state
    17431833 * \param klass  the class which the original method belongs to
    17441834 * \param name1  a new name for the method
     
    17601850 */
    17611851
    1762 static mrb_value
     1852mrb_value
    17631853mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
    17641854{
    1765   mrb_value str;
    1766 
    1767   if (mrb_type(klass) == MRB_TT_SCLASS) {
     1855
     1856  if (mrb_sclass_p(klass)) {
    17681857    mrb_value v = mrb_iv_get(mrb, klass, mrb_intern_lit(mrb, "__attached__"));
    1769 
    1770     str = mrb_str_new_lit(mrb, "#<Class:");
     1858    mrb_value str = mrb_str_new_lit(mrb, "#<Class:");
    17711859
    17721860    if (class_ptr_p(v)) {
     
    17791867  }
    17801868  else {
    1781     struct RClass *c;
    1782     mrb_value path;
    1783 
    1784     str = mrb_str_buf_new(mrb, 32);
    1785     c = mrb_class_ptr(klass);
    1786     path = mrb_class_path(mrb, c);
    1787 
    1788     if (mrb_nil_p(path)) {
    1789       switch (mrb_type(klass)) {
    1790         case MRB_TT_CLASS:
    1791           mrb_str_cat_lit(mrb, str, "#<Class:");
    1792           break;
    1793 
    1794         case MRB_TT_MODULE:
    1795           mrb_str_cat_lit(mrb, str, "#<Module:");
    1796           break;
    1797 
    1798         default:
    1799           /* Shouldn't be happened? */
    1800           mrb_str_cat_lit(mrb, str, "#<??????:");
    1801           break;
    1802       }
    1803       mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, c));
    1804       return mrb_str_cat_lit(mrb, str, ">");
    1805     }
    1806     else {
    1807       return path;
    1808     }
     1869    return class_name_str(mrb, mrb_class_ptr(klass));
    18091870  }
    18101871}
     
    18181879  mrb_get_args(mrb, "nn", &new_name, &old_name);
    18191880  mrb_alias_method(mrb, c, new_name, old_name);
    1820   return mrb_nil_value();
     1881  return mod;
    18211882}
    18221883
     
    18241885undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a)
    18251886{
     1887  mrb_method_t m;
     1888
     1889  MRB_METHOD_FROM_PROC(m, NULL);
     1890  mrb_define_method_raw(mrb, c, a, m);
     1891}
     1892
     1893void
     1894mrb_undef_method_id(mrb_state *mrb, struct RClass *c, mrb_sym a)
     1895{
    18261896  if (!mrb_obj_respond_to(mrb, c, a)) {
    1827     mrb_name_error(mrb, a, "undefined method '%S' for class '%S'", mrb_sym2str(mrb, a), mrb_obj_value(c));
    1828   }
    1829   else {
    1830     mrb_define_method_raw(mrb, c, a, NULL);
    1831   }
     1897    mrb_name_error(mrb, a, "undefined method '%n' for class '%C'", a, c);
     1898  }
     1899  undef_method(mrb, c, a);
    18321900}
    18331901
     
    18531921  mrb_get_args(mrb, "*", &argv, &argc);
    18541922  while (argc--) {
    1855     undef_method(mrb, c, to_sym(mrb, *argv));
     1923    mrb_undef_method_id(mrb, c, to_sym(mrb, *argv));
    18561924    argv++;
    18571925  }
     
    18591927}
    18601928
    1861 static mrb_value
    1862 mod_define_method(mrb_state *mrb, mrb_value self)
    1863 {
    1864   struct RClass *c = mrb_class_ptr(self);
    1865   struct RProc *p;
    1866   mrb_sym mid;
    1867   mrb_value proc = mrb_undef_value();
    1868   mrb_value blk;
    1869 
    1870   mrb_get_args(mrb, "n|o&", &mid, &proc, &blk);
    1871   switch (mrb_type(proc)) {
    1872     case MRB_TT_PROC:
    1873       blk = proc;
    1874       break;
    1875     case MRB_TT_UNDEF:
    1876       /* ignored */
    1877       break;
    1878     default:
    1879       mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected Proc)", mrb_obj_value(mrb_obj_class(mrb, proc)));
    1880       break;
    1881   }
    1882   if (mrb_nil_p(blk)) {
    1883     mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
    1884   }
    1885   p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
    1886   mrb_proc_copy(p, mrb_proc_ptr(blk));
    1887   p->flags |= MRB_PROC_STRICT;
    1888   mrb_define_method_raw(mrb, c, mid, p);
    1889   return mrb_symbol_value(mid);
    1890 }
    1891 
    18921929static void
    1893 check_cv_name_str(mrb_state *mrb, mrb_value str)
    1894 {
    1895   const char *s = RSTRING_PTR(str);
    1896   mrb_int len = RSTRING_LEN(str);
    1897 
    1898   if (len < 3 || !(s[0] == '@' && s[1] == '@')) {
    1899     mrb_name_error(mrb, mrb_intern_str(mrb, str), "'%S' is not allowed as a class variable name", str);
    1900   }
    1901 }
    1902 
    1903 static void
    1904 check_cv_name_sym(mrb_state *mrb, mrb_sym id)
    1905 {
    1906   check_cv_name_str(mrb, mrb_sym2str(mrb, id));
    1907 }
    1908 
    1909 /* 15.2.2.4.16 */
    1910 /*
    1911  *  call-seq:
    1912  *     obj.class_variable_defined?(symbol)    -> true or false
    1913  *
    1914  *  Returns <code>true</code> if the given class variable is defined
    1915  *  in <i>obj</i>.
    1916  *
    1917  *     class Fred
    1918  *       @@foo = 99
    1919  *     end
    1920  *     Fred.class_variable_defined?(:@@foo)    #=> true
    1921  *     Fred.class_variable_defined?(:@@bar)    #=> false
    1922  */
    1923 
    1924 static mrb_value
    1925 mrb_mod_cvar_defined(mrb_state *mrb, mrb_value mod)
     1930check_const_name_sym(mrb_state *mrb, mrb_sym id)
     1931{
     1932  mrb_int len;
     1933  const char *name = mrb_sym_name_len(mrb, id, &len);
     1934  if (!mrb_const_name_p(mrb, name, len)) {
     1935    mrb_name_error(mrb, id, "wrong constant name %n", id);
     1936  }
     1937}
     1938
     1939static mrb_value
     1940mrb_mod_const_defined(mrb_state *mrb, mrb_value mod)
    19261941{
    19271942  mrb_sym id;
     1943  mrb_bool inherit = TRUE;
     1944
     1945  mrb_get_args(mrb, "n|b", &id, &inherit);
     1946  check_const_name_sym(mrb, id);
     1947  if (inherit) {
     1948    return mrb_bool_value(mrb_const_defined(mrb, mod, id));
     1949  }
     1950  return mrb_bool_value(mrb_const_defined_at(mrb, mod, id));
     1951}
     1952
     1953static mrb_value
     1954mrb_const_get_sym(mrb_state *mrb, mrb_value mod, mrb_sym id)
     1955{
     1956  check_const_name_sym(mrb, id);
     1957  return mrb_const_get(mrb, mod, id);
     1958}
     1959
     1960static mrb_value
     1961mrb_mod_const_get(mrb_state *mrb, mrb_value mod)
     1962{
     1963  mrb_value path;
     1964  mrb_sym id;
     1965  char *ptr;
     1966  mrb_int off, end, len;
     1967
     1968  mrb_get_args(mrb, "o", &path);
     1969
     1970  if (mrb_symbol_p(path)) {
     1971    /* const get with symbol */
     1972    id = mrb_symbol(path);
     1973    return mrb_const_get_sym(mrb, mod, id);
     1974  }
     1975
     1976  /* const get with class path string */
     1977  path = mrb_ensure_string_type(mrb, path);
     1978  ptr = RSTRING_PTR(path);
     1979  len = RSTRING_LEN(path);
     1980  off = 0;
     1981
     1982  while (off < len) {
     1983    end = mrb_str_index_lit(mrb, path, "::", off);
     1984    end = (end == -1) ? len : end;
     1985    id = mrb_intern(mrb, ptr+off, end-off);
     1986    mod = mrb_const_get_sym(mrb, mod, id);
     1987    if (end == len)
     1988      off = end;
     1989    else {
     1990      off = end + 2;
     1991      if (off == len) {         /* trailing "::" */
     1992        mrb_name_error(mrb, id, "wrong constant name '%v'", path);
     1993      }
     1994    }
     1995  }
     1996
     1997  return mod;
     1998}
     1999
     2000static mrb_value
     2001mrb_mod_const_set(mrb_state *mrb, mrb_value mod)
     2002{
     2003  mrb_sym id;
     2004  mrb_value value;
     2005
     2006  mrb_get_args(mrb, "no", &id, &value);
     2007  check_const_name_sym(mrb, id);
     2008  mrb_const_set(mrb, mod, id, value);
     2009  return value;
     2010}
     2011
     2012static mrb_value
     2013mrb_mod_remove_const(mrb_state *mrb, mrb_value mod)
     2014{
     2015  mrb_sym id;
     2016  mrb_value val;
    19282017
    19292018  mrb_get_args(mrb, "n", &id);
    1930   check_cv_name_sym(mrb, id);
    1931   return mrb_bool_value(mrb_cv_defined(mrb, mod, id));
    1932 }
    1933 
    1934 /* 15.2.2.4.17 */
    1935 /*
    1936  *  call-seq:
    1937  *     mod.class_variable_get(symbol)    -> obj
    1938  *
    1939  *  Returns the value of the given class variable (or throws a
    1940  *  <code>NameError</code> exception). The <code>@@</code> part of the
    1941  *  variable name should be included for regular class variables
    1942  *
    1943  *     class Fred
    1944  *       @@foo = 99
    1945  *     end
    1946  *     Fred.class_variable_get(:@@foo)     #=> 99
    1947  */
    1948 
    1949 static mrb_value
    1950 mrb_mod_cvar_get(mrb_state *mrb, mrb_value mod)
    1951 {
    1952   mrb_sym id;
    1953 
    1954   mrb_get_args(mrb, "n", &id);
    1955   check_cv_name_sym(mrb, id);
    1956   return mrb_cv_get(mrb, mod, id);
    1957 }
    1958 
    1959 /* 15.2.2.4.18 */
    1960 /*
    1961  *  call-seq:
    1962  *     obj.class_variable_set(symbol, obj)    -> obj
    1963  *
    1964  *  Sets the class variable names by <i>symbol</i> to
    1965  *  <i>object</i>.
    1966  *
    1967  *     class Fred
    1968  *       @@foo = 99
    1969  *       def foo
    1970  *         @@foo
    1971  *       end
    1972  *     end
    1973  *     Fred.class_variable_set(:@@foo, 101)     #=> 101
    1974  *     Fred.new.foo                             #=> 101
    1975  */
    1976 
    1977 static mrb_value
    1978 mrb_mod_cvar_set(mrb_state *mrb, mrb_value mod)
    1979 {
    1980   mrb_value value;
    1981   mrb_sym id;
    1982 
    1983   mrb_get_args(mrb, "no", &id, &value);
    1984   check_cv_name_sym(mrb, id);
    1985   mrb_cv_set(mrb, mod, id, value);
    1986   return value;
    1987 }
    1988 
    1989 /* 15.2.2.4.39 */
    1990 /*
    1991  *  call-seq:
    1992  *     remove_class_variable(sym)    -> obj
    1993  *
    1994  *  Removes the definition of the <i>sym</i>, returning that
    1995  *  constant's value.
    1996  *
    1997  *     class Dummy
    1998  *       @@var = 99
    1999  *       puts @@var
    2000  *       p class_variables
    2001  *       remove_class_variable(:@@var)
    2002  *       p class_variables
    2003  *     end
    2004  *
    2005  *  <em>produces:</em>
    2006  *
    2007  *     99
    2008  *     [:@@var]
    2009  *     []
    2010  */
    2011 
    2012 static mrb_value
    2013 mrb_mod_remove_cvar(mrb_state *mrb, mrb_value mod)
    2014 {
    2015   mrb_value val;
    2016   mrb_sym id;
    2017 
    2018   mrb_get_args(mrb, "n", &id);
    2019   check_cv_name_sym(mrb, id);
    2020 
     2019  check_const_name_sym(mrb, id);
    20212020  val = mrb_iv_remove(mrb, mod, id);
    2022   if (!mrb_undef_p(val)) return val;
    2023 
    2024   if (mrb_cv_defined(mrb, mod, id)) {
    2025     mrb_name_error(mrb, id, "cannot remove %S for %S",
    2026                    mrb_sym2str(mrb, id), mod);
    2027   }
    2028 
    2029   mrb_name_error(mrb, id, "class variable %S not defined for %S",
    2030                  mrb_sym2str(mrb, id), mod);
    2031 
    2032  /* not reached */
    2033  return mrb_nil_value();
     2021  if (mrb_undef_p(val)) {
     2022    mrb_name_error(mrb, id, "constant %n not defined", id);
     2023  }
     2024  return val;
     2025}
     2026
     2027static mrb_value
     2028mrb_mod_const_missing(mrb_state *mrb, mrb_value mod)
     2029{
     2030  mrb_sym sym;
     2031
     2032  mrb_get_args(mrb, "n", &sym);
     2033
     2034  if (mrb_class_real(mrb_class_ptr(mod)) != mrb->object_class) {
     2035    mrb_name_error(mrb, sym, "uninitialized constant %v::%n", mod, sym);
     2036  }
     2037  else {
     2038    mrb_name_error(mrb, sym, "uninitialized constant %n", sym);
     2039  }
     2040  /* not reached */
     2041  return mrb_nil_value();
    20342042}
    20352043
     
    20702078}
    20712079
    2072 static void
    2073 remove_method(mrb_state *mrb, mrb_value mod, mrb_sym mid)
    2074 {
    2075   struct RClass *c = mrb_class_ptr(mod);
    2076   khash_t(mt) *h = find_origin(c)->mt;
    2077   khiter_t k;
    2078 
    2079   if (h) {
    2080     k = kh_get(mt, mrb, h, mid);
    2081     if (k != kh_end(h)) {
    2082       kh_del(mt, mrb, h, k);
    2083       mrb_funcall(mrb, mod, "method_removed", 1, mrb_symbol_value(mid));
    2084       return;
    2085     }
    2086   }
    2087 
    2088   mrb_name_error(mrb, mid, "method '%S' not defined in %S",
    2089     mrb_sym2str(mrb, mid), mod);
    2090 }
    2091 
    2092 /* 15.2.2.4.41 */
    2093 /*
    2094  *  call-seq:
    2095  *     remove_method(symbol)   -> self
    2096  *
    2097  *  Removes the method identified by _symbol_ from the current
    2098  *  class. For an example, see <code>Module.undef_method</code>.
    2099  */
    2100 
    2101 static mrb_value
    2102 mrb_mod_remove_method(mrb_state *mrb, mrb_value mod)
    2103 {
    2104   mrb_int argc;
    2105   mrb_value *argv;
    2106 
    2107   mrb_get_args(mrb, "*", &argv, &argc);
    2108   while (argc--) {
    2109     remove_method(mrb, mod, to_sym(mrb, *argv));
    2110     argv++;
    2111   }
    2112   return mod;
    2113 }
    2114 
    2115 
    2116 
    2117 static void
    2118 check_const_name_str(mrb_state *mrb, mrb_value str)
    2119 {
    2120   if (RSTRING_LEN(str) < 1 || !ISUPPER(*RSTRING_PTR(str))) {
    2121     mrb_name_error(mrb, mrb_intern_str(mrb, str), "wrong constant name %S", str);
    2122   }
    2123 }
    2124 
    2125 static void
    2126 check_const_name_sym(mrb_state *mrb, mrb_sym id)
    2127 {
    2128   check_const_name_str(mrb, mrb_sym2str(mrb, id));
    2129 }
    2130 
    2131 static mrb_value
    2132 const_defined(mrb_state *mrb, mrb_value mod, mrb_sym id, mrb_bool inherit)
    2133 {
    2134   if (inherit) {
    2135     return mrb_bool_value(mrb_const_defined(mrb, mod, id));
    2136   }
    2137   return mrb_bool_value(mrb_const_defined_at(mrb, mod, id));
    2138 }
    2139 
    2140 static mrb_value
    2141 mrb_mod_const_defined(mrb_state *mrb, mrb_value mod)
    2142 {
    2143   mrb_sym id;
    2144   mrb_bool inherit = TRUE;
    2145 
    2146   mrb_get_args(mrb, "n|b", &id, &inherit);
    2147   check_const_name_sym(mrb, id);
    2148   return const_defined(mrb, mod, id, inherit);
    2149 }
    2150 
    2151 static mrb_value
    2152 mrb_mod_const_get(mrb_state *mrb, mrb_value mod)
    2153 {
    2154   mrb_sym id;
    2155 
    2156   mrb_get_args(mrb, "n", &id);
    2157   check_const_name_sym(mrb, id);
    2158   return mrb_const_get(mrb, mod, id);
    2159 }
    2160 
    2161 static mrb_value
    2162 mrb_mod_const_set(mrb_state *mrb, mrb_value mod)
    2163 {
    2164   mrb_sym id;
    2165   mrb_value value;
    2166 
    2167   mrb_get_args(mrb, "no", &id, &value);
    2168   check_const_name_sym(mrb, id);
    2169   mrb_const_set(mrb, mod, id, value);
    2170   return value;
    2171 }
    2172 
    2173 static mrb_value
    2174 mrb_mod_remove_const(mrb_state *mrb, mrb_value mod)
    2175 {
    2176   mrb_sym id;
    2177   mrb_value val;
    2178 
    2179   mrb_get_args(mrb, "n", &id);
    2180   check_const_name_sym(mrb, id);
    2181   val = mrb_iv_remove(mrb, mod, id);
    2182   if (mrb_undef_p(val)) {
    2183     mrb_name_error(mrb, id, "constant %S not defined", mrb_sym2str(mrb, id));
    2184   }
    2185   return val;
    2186 }
    2187 
    2188 static mrb_value
    2189 mrb_mod_const_missing(mrb_state *mrb, mrb_value mod)
    2190 {
    2191   mrb_sym sym;
    2192 
    2193   mrb_get_args(mrb, "n", &sym);
    2194 
    2195   if (mrb_class_real(mrb_class_ptr(mod)) != mrb->object_class) {
    2196     mrb_name_error(mrb, sym, "uninitialized constant %S::%S",
    2197                    mod,
    2198                    mrb_sym2str(mrb, sym));
    2199   }
    2200   else {
    2201     mrb_name_error(mrb, sym, "uninitialized constant %S",
    2202                    mrb_sym2str(mrb, sym));
    2203   }
    2204   /* not reached */
    2205   return mrb_nil_value();
    2206 }
    2207 
    2208 static mrb_value
    2209 mrb_mod_s_constants(mrb_state *mrb, mrb_value mod)
    2210 {
    2211   mrb_raise(mrb, E_NOTIMP_ERROR, "Module.constants not implemented");
    2212   return mrb_nil_value();       /* not reached */
     2080static mrb_value
     2081mod_define_method(mrb_state *mrb, mrb_value self)
     2082{
     2083  struct RClass *c = mrb_class_ptr(self);
     2084  struct RProc *p;
     2085  mrb_method_t m;
     2086  mrb_sym mid;
     2087  mrb_value proc = mrb_undef_value();
     2088  mrb_value blk;
     2089
     2090  mrb_get_args(mrb, "n|o&", &mid, &proc, &blk);
     2091  switch (mrb_type(proc)) {
     2092    case MRB_TT_PROC:
     2093      blk = proc;
     2094      break;
     2095    case MRB_TT_UNDEF:
     2096      /* ignored */
     2097      break;
     2098    default:
     2099      mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %T (expected Proc)", proc);
     2100      break;
     2101  }
     2102  if (mrb_nil_p(blk)) {
     2103    mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
     2104  }
     2105  p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
     2106  mrb_proc_copy(p, mrb_proc_ptr(blk));
     2107  p->flags |= MRB_PROC_STRICT;
     2108  MRB_METHOD_FROM_PROC(m, p);
     2109  mrb_define_method_raw(mrb, c, mid, m);
     2110  return mrb_symbol_value(mid);
     2111}
     2112
     2113static mrb_value
     2114top_define_method(mrb_state *mrb, mrb_value self)
     2115{
     2116  return mod_define_method(mrb, mrb_obj_value(mrb->object_class));
    22132117}
    22142118
     
    22252129}
    22262130
    2227 MRB_API mrb_value
     2131static mrb_value
     2132mrb_mod_dup(mrb_state *mrb, mrb_value self)
     2133{
     2134  mrb_value mod = mrb_obj_clone(mrb, self);
     2135  MRB_UNSET_FROZEN_FLAG(mrb_obj_ptr(mod));
     2136  return mod;
     2137}
     2138
     2139static mrb_value
    22282140mrb_mod_module_function(mrb_state *mrb, mrb_value mod)
    22292141{
     
    22312143  mrb_int argc, i;
    22322144  mrb_sym mid;
    2233   struct RProc *method_rproc;
     2145  mrb_method_t m;
    22342146  struct RClass *rclass;
    22352147  int ai;
     
    22512163    mid = mrb_symbol(argv[i]);
    22522164    rclass = mrb_class_ptr(mod);
    2253     method_rproc = mrb_method_search(mrb, rclass, mid);
     2165    m = mrb_method_search(mrb, rclass, mid);
    22542166
    22552167    prepare_singleton_class(mrb, (struct RBasic*)rclass);
    22562168    ai = mrb_gc_arena_save(mrb);
    2257     mrb_define_method_raw(mrb, rclass->c, mid, method_rproc);
     2169    mrb_define_method_raw(mrb, rclass->c, mid, m);
    22582170    mrb_gc_arena_restore(mrb, ai);
    22592171  }
     
    22662178/* implementation of instance_eval */
    22672179mrb_value mrb_obj_instance_eval(mrb_state*, mrb_value);
     2180
     2181static mrb_value
     2182inspect_main(mrb_state *mrb, mrb_value mod)
     2183{
     2184  return mrb_str_new_lit(mrb, "main");
     2185}
     2186
     2187static const mrb_code new_iseq[] = {
     2188  OP_ENTER, 0x0, 0x10, 0x1,  /* OP_ENTER     0:0:1:0:0:0:1 */
     2189  OP_LOADSELF, 0x3,          /* OP_LOADSELF  R3 */
     2190  OP_SEND, 0x3, 0x0, 0x0,    /* OP_SEND      R3  :allocate  0 */
     2191  OP_MOVE, 0x0, 0x3,         /* OP_MOVE      R0  R3 */
     2192  OP_MOVE, 0x4, 0x1,         /* OP_MOVE      R4  R1 */
     2193  OP_MOVE, 0x5, 0x2,         /* OP_MOVE      R5  R2 */
     2194  OP_SENDVB, 0x3, 0x1,       /* OP_SENDVB    R4  :initialize */
     2195  OP_RETURN, 0x0             /* OP_RETURN    R0 */
     2196};
     2197
     2198static void
     2199init_class_new(mrb_state *mrb, struct RClass *cls)
     2200{
     2201  struct RProc *p;
     2202  mrb_method_t m;
     2203  mrb_irep *new_irep = (mrb_irep*)mrb_malloc(mrb, sizeof(mrb_irep));
     2204  static const mrb_irep mrb_irep_zero = { 0 };
     2205
     2206  *new_irep = mrb_irep_zero;
     2207  new_irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*2);
     2208  new_irep->syms[0] = mrb_intern_lit(mrb, "allocate");
     2209  new_irep->syms[1] = mrb_intern_lit(mrb, "initialize");
     2210  new_irep->slen = 2;
     2211  new_irep->flags = MRB_ISEQ_NO_FREE;
     2212  new_irep->iseq = new_iseq;
     2213  new_irep->ilen = sizeof(new_iseq);
     2214  new_irep->nregs = 6;
     2215  new_irep->nlocals = 3;
     2216  p = mrb_proc_new(mrb, new_irep);
     2217  MRB_METHOD_FROM_PROC(m, p);
     2218  mrb_define_method_raw(mrb, cls, mrb_intern_lit(mrb, "new"), m);
     2219}
    22682220
    22692221void
     
    22892241  /* name basic classes */
    22902242  mrb_define_const(mrb, bob, "BasicObject", mrb_obj_value(bob));
    2291   mrb_define_const(mrb, obj, "BasicObject", mrb_obj_value(bob));
    22922243  mrb_define_const(mrb, obj, "Object",      mrb_obj_value(obj));
    22932244  mrb_define_const(mrb, obj, "Module",      mrb_obj_value(mod));
     
    22952246
    22962247  /* name each classes */
    2297   name_class(mrb, bob, mrb_intern_lit(mrb, "BasicObject"));
    2298   name_class(mrb, obj, mrb_intern_lit(mrb, "Object"));          /* 15.2.1 */
    2299   name_class(mrb, mod, mrb_intern_lit(mrb, "Module"));          /* 15.2.2 */
    2300   name_class(mrb, cls, mrb_intern_lit(mrb, "Class"));            /* 15.2.3 */
     2248  mrb_class_name_class(mrb, NULL, bob, mrb_intern_lit(mrb, "BasicObject"));
     2249  mrb_class_name_class(mrb, NULL, obj, mrb_intern_lit(mrb, "Object")); /* 15.2.1 */
     2250  mrb_class_name_class(mrb, NULL, mod, mrb_intern_lit(mrb, "Module")); /* 15.2.2 */
     2251  mrb_class_name_class(mrb, NULL, cls, mrb_intern_lit(mrb, "Class"));  /* 15.2.3 */
    23012252
    23022253  mrb->proc_class = mrb_define_class(mrb, "Proc", mrb->object_class);  /* 15.2.17 */
     
    23082259  mrb_define_method(mrb, bob, "==",                      mrb_obj_equal_m,          MRB_ARGS_REQ(1)); /* 15.3.1.3.1  */
    23092260  mrb_define_method(mrb, bob, "!=",                      mrb_obj_not_equal_m,      MRB_ARGS_REQ(1));
    2310   mrb_define_method(mrb, bob, "__id__",                  mrb_obj_id_m,             MRB_ARGS_NONE()); /* 15.3.1.3.3  */
    2311   mrb_define_method(mrb, bob, "__send__",                mrb_f_send,               MRB_ARGS_ANY());  /* 15.3.1.3.4  */
    2312   mrb_define_method(mrb, bob, "instance_eval",           mrb_obj_instance_eval,    MRB_ARGS_ANY());  /* 15.3.1.3.18 */
    2313 
    2314   mrb_define_class_method(mrb, cls, "new",               mrb_class_new_class,      MRB_ARGS_OPT(1));
     2261  mrb_define_method(mrb, bob, "__id__",                  mrb_obj_id_m,             MRB_ARGS_NONE()); /* 15.3.1.3.4  */
     2262  mrb_define_method(mrb, bob, "__send__",                mrb_f_send,               MRB_ARGS_REQ(1)|MRB_ARGS_REST()|MRB_ARGS_BLOCK());  /* 15.3.1.3.5  */
     2263  mrb_define_method(mrb, bob, "equal?",                  mrb_obj_equal_m,          MRB_ARGS_REQ(1)); /* 15.3.1.3.11 */
     2264  mrb_define_method(mrb, bob, "instance_eval",           mrb_obj_instance_eval,    MRB_ARGS_OPT(1)|MRB_ARGS_BLOCK());  /* 15.3.1.3.18 */
     2265
     2266  mrb_define_class_method(mrb, cls, "new",               mrb_class_new_class,      MRB_ARGS_OPT(1)|MRB_ARGS_BLOCK());
     2267  mrb_define_method(mrb, cls, "allocate",                mrb_instance_alloc,       MRB_ARGS_NONE());
    23152268  mrb_define_method(mrb, cls, "superclass",              mrb_class_superclass,     MRB_ARGS_NONE()); /* 15.2.3.3.4 */
    2316   mrb_define_method(mrb, cls, "new",                     mrb_instance_new,         MRB_ARGS_ANY());  /* 15.2.3.3.3 */
    23172269  mrb_define_method(mrb, cls, "initialize",              mrb_class_initialize,     MRB_ARGS_OPT(1)); /* 15.2.3.3.1 */
    23182270  mrb_define_method(mrb, cls, "inherited",               mrb_bob_init,             MRB_ARGS_REQ(1));
    23192271
     2272  init_class_new(mrb, cls);
     2273
    23202274  MRB_SET_INSTANCE_TT(mod, MRB_TT_MODULE);
    2321   mrb_define_method(mrb, mod, "class_variable_defined?", mrb_mod_cvar_defined,     MRB_ARGS_REQ(1)); /* 15.2.2.4.16 */
    2322   mrb_define_method(mrb, mod, "class_variable_get",      mrb_mod_cvar_get,         MRB_ARGS_REQ(1)); /* 15.2.2.4.17 */
    2323   mrb_define_method(mrb, mod, "class_variable_set",      mrb_mod_cvar_set,         MRB_ARGS_REQ(2)); /* 15.2.2.4.18 */
    23242275  mrb_define_method(mrb, mod, "extend_object",           mrb_mod_extend_object,    MRB_ARGS_REQ(1)); /* 15.2.2.4.25 */
    23252276  mrb_define_method(mrb, mod, "extended",                mrb_bob_init,             MRB_ARGS_REQ(1)); /* 15.2.2.4.26 */
     
    23302281  mrb_define_method(mrb, mod, "class_eval",              mrb_mod_module_eval,      MRB_ARGS_ANY());  /* 15.2.2.4.15 */
    23312282  mrb_define_method(mrb, mod, "included",                mrb_bob_init,             MRB_ARGS_REQ(1)); /* 15.2.2.4.29 */
    2332   mrb_define_method(mrb, mod, "included_modules",        mrb_mod_included_modules, MRB_ARGS_NONE()); /* 15.2.2.4.30 */
    23332283  mrb_define_method(mrb, mod, "initialize",              mrb_mod_initialize,       MRB_ARGS_NONE()); /* 15.2.2.4.31 */
    2334   mrb_define_method(mrb, mod, "instance_methods",        mrb_mod_instance_methods, MRB_ARGS_ANY());  /* 15.2.2.4.33 */
    2335   mrb_define_method(mrb, mod, "method_defined?",         mrb_mod_method_defined,   MRB_ARGS_REQ(1)); /* 15.2.2.4.34 */
    23362284  mrb_define_method(mrb, mod, "module_eval",             mrb_mod_module_eval,      MRB_ARGS_ANY());  /* 15.2.2.4.35 */
    23372285  mrb_define_method(mrb, mod, "module_function",         mrb_mod_module_function,  MRB_ARGS_ANY());
     
    23392287  mrb_define_method(mrb, mod, "protected",               mrb_mod_dummy_visibility, MRB_ARGS_ANY());  /* 15.2.2.4.37 */
    23402288  mrb_define_method(mrb, mod, "public",                  mrb_mod_dummy_visibility, MRB_ARGS_ANY());  /* 15.2.2.4.38 */
    2341   mrb_define_method(mrb, mod, "remove_class_variable",   mrb_mod_remove_cvar,      MRB_ARGS_REQ(1)); /* 15.2.2.4.39 */
    2342   mrb_define_method(mrb, mod, "remove_method",           mrb_mod_remove_method,    MRB_ARGS_ANY());  /* 15.2.2.4.41 */
    2343   mrb_define_method(mrb, mod, "method_removed",          mrb_bob_init,             MRB_ARGS_REQ(1));
    23442289  mrb_define_method(mrb, mod, "attr_reader",             mrb_mod_attr_reader,      MRB_ARGS_ANY());  /* 15.2.2.4.13 */
    23452290  mrb_define_method(mrb, mod, "attr_writer",             mrb_mod_attr_writer,      MRB_ARGS_ANY());  /* 15.2.2.4.14 */
     
    23522297  mrb_define_method(mrb, mod, "const_get",               mrb_mod_const_get,        MRB_ARGS_REQ(1)); /* 15.2.2.4.21 */
    23532298  mrb_define_method(mrb, mod, "const_set",               mrb_mod_const_set,        MRB_ARGS_REQ(2)); /* 15.2.2.4.23 */
    2354   mrb_define_method(mrb, mod, "constants",               mrb_mod_constants,        MRB_ARGS_OPT(1)); /* 15.2.2.4.24 */
    23552299  mrb_define_method(mrb, mod, "remove_const",            mrb_mod_remove_const,     MRB_ARGS_REQ(1)); /* 15.2.2.4.40 */
    23562300  mrb_define_method(mrb, mod, "const_missing",           mrb_mod_const_missing,    MRB_ARGS_REQ(1));
     2301  mrb_define_method(mrb, mod, "method_defined?",         mrb_mod_method_defined,   MRB_ARGS_REQ(1)); /* 15.2.2.4.34 */
    23572302  mrb_define_method(mrb, mod, "define_method",           mod_define_method,        MRB_ARGS_ARG(1,1));
    2358   mrb_define_method(mrb, mod, "class_variables",         mrb_mod_class_variables,  MRB_ARGS_NONE()); /* 15.2.2.4.19 */
    2359   mrb_define_method(mrb, mod, "===",                     mrb_mod_eqq,              MRB_ARGS_REQ(1));
    2360   mrb_define_class_method(mrb, mod, "constants",         mrb_mod_s_constants,      MRB_ARGS_ANY());  /* 15.2.2.3.1 */
     2303  mrb_define_method(mrb, mod, "===",                     mrb_mod_eqq,              MRB_ARGS_REQ(1)); /* 15.2.2.4.7 */
     2304  mrb_define_method(mrb, mod, "dup",                     mrb_mod_dup,              MRB_ARGS_NONE());
    23612305
    23622306  mrb_undef_method(mrb, cls, "append_features");
     2307  mrb_undef_method(mrb, cls, "prepend_features");
    23632308  mrb_undef_method(mrb, cls, "extend_object");
    2364 }
     2309  mrb_undef_method(mrb, cls, "module_function");
     2310
     2311  mrb->top_self = (struct RObject*)mrb_obj_alloc(mrb, MRB_TT_OBJECT, mrb->object_class);
     2312  mrb_define_singleton_method(mrb, mrb->top_self, "inspect", inspect_main, MRB_ARGS_NONE());
     2313  mrb_define_singleton_method(mrb, mrb->top_self, "to_s", inspect_main, MRB_ARGS_NONE());
     2314  mrb_define_singleton_method(mrb, mrb->top_self, "define_method", top_define_method, MRB_ARGS_ARG(1,1));
     2315}
  • EcnlProtoTool/trunk/mruby-2.1.1/src/codedump.c

    r331 r439  
    77
    88#ifndef MRB_DISABLE_STDIO
    9 static int
    10 print_r(mrb_state *mrb, mrb_irep *irep, size_t n, int pre)
     9static void
     10print_r(mrb_state *mrb, mrb_irep *irep, size_t n)
    1111{
    1212  size_t i;
    1313
    14   if (n == 0) return 0;
     14  if (n == 0) return;
    1515
    1616  for (i=0; i+1<irep->nlocals; i++) {
    1717    if (irep->lv[i].r == n) {
    1818      mrb_sym sym = irep->lv[i].name;
    19       if (pre) printf(" ");
    20       printf("R%d:%s", (int)n, mrb_sym2name(mrb, sym));
    21       return 1;
     19      printf(" R%d:%s", (int)n, mrb_sym_dump(mrb, sym));
     20      break;
    2221    }
    2322  }
    24   return 0;
    25 }
    26 
    27 #define RA  1
    28 #define RB  2
    29 #define RAB 3
     23}
    3024
    3125static void
    32 print_lv(mrb_state *mrb, mrb_irep *irep, mrb_code c, int r)
    33 {
    34   int pre = 0;
    35 
    36   if (!irep->lv
    37       || ((!(r & RA) || GETARG_A(c) >= irep->nlocals)
    38        && (!(r & RB) || GETARG_B(c) >= irep->nlocals))) {
     26print_lv_a(mrb_state *mrb, mrb_irep *irep, uint16_t a)
     27{
     28  if (!irep->lv || a >= irep->nlocals || a == 0) {
    3929    printf("\n");
    4030    return;
    4131  }
    42   printf("\t; ");
    43   if (r & RA) {
    44     pre = print_r(mrb, irep, GETARG_A(c), 0);
    45   }
    46   if (r & RB) {
    47     print_r(mrb, irep, GETARG_B(c), pre);
    48   }
     32  printf("\t;");
     33  print_r(mrb, irep, a);
    4934  printf("\n");
    5035}
    51 #endif
     36
     37static void
     38print_lv_ab(mrb_state *mrb, mrb_irep *irep, uint16_t a, uint16_t b)
     39{
     40  if (!irep->lv || (a >= irep->nlocals && b >= irep->nlocals) || a+b == 0) {
     41    printf("\n");
     42    return;
     43  }
     44  printf("\t;");
     45  if (a > 0) print_r(mrb, irep, a);
     46  if (b > 0) print_r(mrb, irep, b);
     47  printf("\n");
     48}
     49
     50static void
     51print_header(mrb_state *mrb, mrb_irep *irep, ptrdiff_t i)
     52{
     53  int32_t line;
     54
     55  line = mrb_debug_get_line(mrb, irep, i);
     56  if (line < 0) {
     57    printf("      ");
     58  }
     59  else {
     60    printf("%5d ", line);
     61  }
     62
     63  printf("%03d ", (int)i);
     64}
     65
     66#define CASE(insn,ops) case insn: FETCH_ ## ops (); L_ ## insn
    5267
    5368static void
    5469codedump(mrb_state *mrb, mrb_irep *irep)
    5570{
    56 #ifndef MRB_DISABLE_STDIO
    57   int i;
    5871  int ai;
    59   mrb_code c;
     72  const mrb_code *pc, *pcend;
     73  mrb_code ins;
    6074  const char *file = NULL, *next_file;
    61   int32_t line;
    6275
    6376  if (!irep) return;
    64   printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d\n", (void*)irep,
    65          irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen);
    66 
    67   for (i = 0; i < (int)irep->ilen; i++) {
     77  printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d iseq=%d\n", (void*)irep,
     78         irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen, (int)irep->ilen);
     79
     80  if (irep->lv) {
     81    int i;
     82
     83    printf("local variable names:\n");
     84    for (i = 1; i < irep->nlocals; ++i) {
     85      char const *s = mrb_sym_dump(mrb, irep->lv[i - 1].name);
     86      int n = irep->lv[i - 1].r ? irep->lv[i - 1].r : i;
     87      printf("  R%d:%s\n", n, s ? s : "");
     88    }
     89  }
     90
     91  pc = irep->iseq;
     92  pcend = pc + irep->ilen;
     93  while (pc < pcend) {
     94    ptrdiff_t i;
     95    uint32_t a;
     96    uint16_t b;
     97    uint8_t c;
     98
    6899    ai = mrb_gc_arena_save(mrb);
    69100
    70     next_file = mrb_debug_get_filename(irep, i);
     101    i = pc - irep->iseq;
     102    next_file = mrb_debug_get_filename(mrb, irep, i);
    71103    if (next_file && file != next_file) {
    72104      printf("file: %s\n", next_file);
    73105      file = next_file;
    74106    }
    75     line = mrb_debug_get_line(irep, i);
    76     if (line < 0) {
    77       printf("      ");
    78     }
    79     else {
    80       printf("%5d ", line);
    81     }
    82 
    83     printf("%03d ", i);
    84     c = irep->iseq[i];
    85     switch (GET_OPCODE(c)) {
    86     case OP_NOP:
     107    print_header(mrb, irep, i);
     108    ins = READ_B();
     109    switch (ins) {
     110    CASE(OP_NOP, Z):
    87111      printf("OP_NOP\n");
    88112      break;
    89     case OP_MOVE:
    90       printf("OP_MOVE\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
    91       print_lv(mrb, irep, c, RAB);
    92       break;
    93     case OP_LOADL:
     113    CASE(OP_MOVE, BB):
     114      printf("OP_MOVE\tR%d\tR%d\t", a, b);
     115      print_lv_ab(mrb, irep, a, b);
     116      break;
     117    CASE(OP_LOADL, BB):
    94118      {
    95         mrb_value v = irep->pool[GETARG_Bx(c)];
     119        mrb_value v = irep->pool[b];
    96120        mrb_value s = mrb_inspect(mrb, v);
    97         printf("OP_LOADL\tR%d\tL(%d)\t; %s", GETARG_A(c), GETARG_Bx(c), RSTRING_PTR(s));
     121        printf("OP_LOADL\tR%d\tL(%d)\t; %s", a, b, RSTRING_PTR(s));
    98122      }
    99       print_lv(mrb, irep, c, RA);
    100       break;
    101     case OP_LOADI:
    102       printf("OP_LOADI\tR%d\t%d\t", GETARG_A(c), GETARG_sBx(c));
    103       print_lv(mrb, irep, c, RA);
    104       break;
    105     case OP_LOADSYM:
    106       printf("OP_LOADSYM\tR%d\t:%s", GETARG_A(c),
    107              mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
    108       print_lv(mrb, irep, c, RA);
    109       break;
    110     case OP_LOADNIL:
    111       printf("OP_LOADNIL\tR%d\t\t", GETARG_A(c));
    112       print_lv(mrb, irep, c, RA);
    113       break;
    114     case OP_LOADSELF:
    115       printf("OP_LOADSELF\tR%d\t\t", GETARG_A(c));
    116       print_lv(mrb, irep, c, RA);
    117       break;
    118     case OP_LOADT:
    119       printf("OP_LOADT\tR%d\t\t", GETARG_A(c));
    120       print_lv(mrb, irep, c, RA);
    121       break;
    122     case OP_LOADF:
    123       printf("OP_LOADF\tR%d\t\t", GETARG_A(c));
    124       print_lv(mrb, irep, c, RA);
    125       break;
    126     case OP_GETGLOBAL:
    127       printf("OP_GETGLOBAL\tR%d\t:%s", GETARG_A(c),
    128              mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
    129       print_lv(mrb, irep, c, RA);
    130       break;
    131     case OP_SETGLOBAL:
    132       printf("OP_SETGLOBAL\t:%s\tR%d\t",
    133              mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
    134              GETARG_A(c));
    135       print_lv(mrb, irep, c, RA);
    136       break;
    137     case OP_GETCONST:
    138       printf("OP_GETCONST\tR%d\t:%s", GETARG_A(c),
    139              mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
    140       print_lv(mrb, irep, c, RA);
    141       break;
    142     case OP_SETCONST:
    143       printf("OP_SETCONST\t:%s\tR%d\t",
    144              mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
    145              GETARG_A(c));
    146       print_lv(mrb, irep, c, RA);
    147       break;
    148     case OP_GETMCNST:
    149       printf("OP_GETMCNST\tR%d\tR%d::%s", GETARG_A(c), GETARG_A(c),
    150              mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
    151       print_lv(mrb, irep, c, RAB);
    152       break;
    153     case OP_SETMCNST:
    154       printf("OP_SETMCNST\tR%d::%s\tR%d", GETARG_A(c)+1,
    155              mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
    156              GETARG_A(c));
    157       print_lv(mrb, irep, c, RA);
    158       break;
    159     case OP_GETIV:
    160       printf("OP_GETIV\tR%d\t%s", GETARG_A(c),
    161              mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
    162       print_lv(mrb, irep, c, RA);
    163       break;
    164     case OP_SETIV:
    165       printf("OP_SETIV\t%s\tR%d",
    166              mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
    167              GETARG_A(c));
    168       print_lv(mrb, irep, c, RA);
    169       break;
    170     case OP_GETUPVAR:
    171       printf("OP_GETUPVAR\tR%d\t%d\t%d",
    172              GETARG_A(c), GETARG_B(c), GETARG_C(c));
    173       print_lv(mrb, irep, c, RA);
    174       break;
    175     case OP_SETUPVAR:
    176       printf("OP_SETUPVAR\tR%d\t%d\t%d",
    177              GETARG_A(c), GETARG_B(c), GETARG_C(c));
    178       print_lv(mrb, irep, c, RA);
    179       break;
    180     case OP_GETCV:
    181       printf("OP_GETCV\tR%d\t%s", GETARG_A(c),
    182              mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
    183       print_lv(mrb, irep, c, RA);
    184       break;
    185     case OP_SETCV:
    186       printf("OP_SETCV\t%s\tR%d",
    187              mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
    188              GETARG_A(c));
    189       print_lv(mrb, irep, c, RA);
    190       break;
    191     case OP_JMP:
    192       printf("OP_JMP\t%03d\n", i+GETARG_sBx(c));
    193       break;
    194     case OP_JMPIF:
    195       printf("OP_JMPIF\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c));
    196       break;
    197     case OP_JMPNOT:
    198       printf("OP_JMPNOT\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c));
    199       break;
    200     case OP_SEND:
    201       printf("OP_SEND\tR%d\t:%s\t%d\n", GETARG_A(c),
    202              mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
    203              GETARG_C(c));
    204       break;
    205     case OP_SENDB:
    206       printf("OP_SENDB\tR%d\t:%s\t%d\n", GETARG_A(c),
    207              mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
    208              GETARG_C(c));
    209       break;
    210     case OP_TAILCALL:
    211       printf("OP_TAILCALL\tR%d\t:%s\t%d\n", GETARG_A(c),
    212              mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
    213              GETARG_C(c));
    214       break;
    215     case OP_SUPER:
    216       printf("OP_SUPER\tR%d\t%d\n", GETARG_A(c),
    217              GETARG_C(c));
    218       break;
    219     case OP_ARGARY:
    220       printf("OP_ARGARY\tR%d\t%d:%d:%d:%d", GETARG_A(c),
    221              (GETARG_Bx(c)>>10)&0x3f,
    222              (GETARG_Bx(c)>>9)&0x1,
    223              (GETARG_Bx(c)>>4)&0x1f,
    224              (GETARG_Bx(c)>>0)&0xf);
    225       print_lv(mrb, irep, c, RA);
    226       break;
    227 
    228     case OP_ENTER:
     123      print_lv_a(mrb, irep, a);
     124      break;
     125    CASE(OP_LOADI, BB):
     126      printf("OP_LOADI\tR%d\t%d\t", a, b);
     127      print_lv_a(mrb, irep, a);
     128      break;
     129    CASE(OP_LOADINEG, BB):
     130      printf("OP_LOADI\tR%d\t-%d\t", a, b);
     131      print_lv_a(mrb, irep, a);
     132      break;
     133    CASE(OP_LOADI__1, B):
     134      printf("OP_LOADI__1\tR%d\t\t", a);
     135      print_lv_a(mrb, irep, a);
     136      break;
     137    CASE(OP_LOADI_0, B): goto L_LOADI;
     138    CASE(OP_LOADI_1, B): goto L_LOADI;
     139    CASE(OP_LOADI_2, B): goto L_LOADI;
     140    CASE(OP_LOADI_3, B): goto L_LOADI;
     141    CASE(OP_LOADI_4, B): goto L_LOADI;
     142    CASE(OP_LOADI_5, B): goto L_LOADI;
     143    CASE(OP_LOADI_6, B): goto L_LOADI;
     144    CASE(OP_LOADI_7, B):
     145    L_LOADI:
     146      printf("OP_LOADI_%d\tR%d\t\t", ins-(int)OP_LOADI_0, a);
     147      print_lv_a(mrb, irep, a);
     148      break;
     149    CASE(OP_LOADSYM, BB):
     150      printf("OP_LOADSYM\tR%d\t:%s\t", a, mrb_sym_dump(mrb, irep->syms[b]));
     151      print_lv_a(mrb, irep, a);
     152      break;
     153    CASE(OP_LOADNIL, B):
     154      printf("OP_LOADNIL\tR%d\t\t", a);
     155      print_lv_a(mrb, irep, a);
     156      break;
     157    CASE(OP_LOADSELF, B):
     158      printf("OP_LOADSELF\tR%d\t\t", a);
     159      print_lv_a(mrb, irep, a);
     160      break;
     161    CASE(OP_LOADT, B):
     162      printf("OP_LOADT\tR%d\t\t", a);
     163      print_lv_a(mrb, irep, a);
     164      break;
     165    CASE(OP_LOADF, B):
     166      printf("OP_LOADF\tR%d\t\t", a);
     167      print_lv_a(mrb, irep, a);
     168      break;
     169    CASE(OP_GETGV, BB):
     170      printf("OP_GETGV\tR%d\t:%s", a, mrb_sym_dump(mrb, irep->syms[b]));
     171      print_lv_a(mrb, irep, a);
     172      break;
     173    CASE(OP_SETGV, BB):
     174      printf("OP_SETGV\t:%s\tR%d", mrb_sym_dump(mrb, irep->syms[b]), a);
     175      print_lv_a(mrb, irep, a);
     176      break;
     177    CASE(OP_GETSV, BB):
     178      printf("OP_GETSV\tR%d\t:%s", a, mrb_sym_dump(mrb, irep->syms[b]));
     179      print_lv_a(mrb, irep, a);
     180      break;
     181    CASE(OP_SETSV, BB):
     182      printf("OP_SETSV\t:%s\tR%d", mrb_sym_dump(mrb, irep->syms[b]), a);
     183      print_lv_a(mrb, irep, a);
     184      break;
     185    CASE(OP_GETCONST, BB):
     186      printf("OP_GETCONST\tR%d\t:%s", a, mrb_sym_dump(mrb, irep->syms[b]));
     187      print_lv_a(mrb, irep, a);
     188      break;
     189    CASE(OP_SETCONST, BB):
     190      printf("OP_SETCONST\t:%s\tR%d", mrb_sym_dump(mrb, irep->syms[b]), a);
     191      print_lv_a(mrb, irep, a);
     192      break;
     193    CASE(OP_GETMCNST, BB):
     194      printf("OP_GETMCNST\tR%d\tR%d::%s", a, a, mrb_sym_dump(mrb, irep->syms[b]));
     195      print_lv_a(mrb, irep, a);
     196      break;
     197    CASE(OP_SETMCNST, BB):
     198      printf("OP_SETMCNST\tR%d::%s\tR%d", a+1, mrb_sym_dump(mrb, irep->syms[b]), a);
     199      print_lv_a(mrb, irep, a);
     200      break;
     201    CASE(OP_GETIV, BB):
     202      printf("OP_GETIV\tR%d\t%s", a, mrb_sym_dump(mrb, irep->syms[b]));
     203      print_lv_a(mrb, irep, a);
     204      break;
     205    CASE(OP_SETIV, BB):
     206      printf("OP_SETIV\t%s\tR%d", mrb_sym_dump(mrb, irep->syms[b]), a);
     207      print_lv_a(mrb, irep, a);
     208      break;
     209    CASE(OP_GETUPVAR, BBB):
     210      printf("OP_GETUPVAR\tR%d\t%d\t%d", a, b, c);
     211      print_lv_a(mrb, irep, a);
     212      break;
     213    CASE(OP_SETUPVAR, BBB):
     214      printf("OP_SETUPVAR\tR%d\t%d\t%d", a, b, c);
     215      print_lv_a(mrb, irep, a);
     216      break;
     217    CASE(OP_GETCV, BB):
     218      printf("OP_GETCV\tR%d\t%s", a, mrb_sym_dump(mrb, irep->syms[b]));
     219      print_lv_a(mrb, irep, a);
     220      break;
     221    CASE(OP_SETCV, BB):
     222      printf("OP_SETCV\t%s\tR%d", mrb_sym_dump(mrb, irep->syms[b]), a);
     223      print_lv_a(mrb, irep, a);
     224      break;
     225    CASE(OP_JMP, S):
     226      printf("OP_JMP\t\t%03d\n", a);
     227      break;
     228    CASE(OP_JMPIF, BS):
     229      printf("OP_JMPIF\tR%d\t%03d\t", a, b);
     230      print_lv_a(mrb, irep, a);
     231      break;
     232    CASE(OP_JMPNOT, BS):
     233      printf("OP_JMPNOT\tR%d\t%03d\t", a, b);
     234      print_lv_a(mrb, irep, a);
     235      break;
     236    CASE(OP_JMPNIL, BS):
     237      printf("OP_JMPNIL\tR%d\t%03d\t", a, b);
     238      print_lv_a(mrb, irep, a);
     239      break;
     240    CASE(OP_SENDV, BB):
     241      printf("OP_SENDV\tR%d\t:%s\n", a, mrb_sym_dump(mrb, irep->syms[b]));
     242      break;
     243    CASE(OP_SENDVB, BB):
     244      printf("OP_SENDVB\tR%d\t:%s\n", a, mrb_sym_dump(mrb, irep->syms[b]));
     245      break;
     246    CASE(OP_SEND, BBB):
     247      printf("OP_SEND\tR%d\t:%s\t%d\n", a, mrb_sym_dump(mrb, irep->syms[b]), c);
     248      break;
     249    CASE(OP_SENDB, BBB):
     250      printf("OP_SENDB\tR%d\t:%s\t%d\n", a, mrb_sym_dump(mrb, irep->syms[b]), c);
     251      break;
     252    CASE(OP_CALL, Z):
     253      printf("OP_CALL\n");
     254      break;
     255    CASE(OP_SUPER, BB):
     256      printf("OP_SUPER\tR%d\t%d\n", a, b);
     257      break;
     258    CASE(OP_ARGARY, BS):
     259      printf("OP_ARGARY\tR%d\t%d:%d:%d:%d (%d)", a,
     260             (b>>11)&0x3f,
     261             (b>>10)&0x1,
     262             (b>>5)&0x1f,
     263             (b>>4)&0x1,
     264             (b>>0)&0xf);
     265      print_lv_a(mrb, irep, a);
     266      break;
     267    CASE(OP_ENTER, W):
    229268      printf("OP_ENTER\t%d:%d:%d:%d:%d:%d:%d\n",
    230              (GETARG_Ax(c)>>18)&0x1f,
    231              (GETARG_Ax(c)>>13)&0x1f,
    232              (GETARG_Ax(c)>>12)&0x1,
    233              (GETARG_Ax(c)>>7)&0x1f,
    234              (GETARG_Ax(c)>>2)&0x1f,
    235              (GETARG_Ax(c)>>1)&0x1,
    236              GETARG_Ax(c) & 0x1);
    237       break;
    238     case OP_RETURN:
    239       printf("OP_RETURN\tR%d", GETARG_A(c));
    240       switch (GETARG_B(c)) {
    241       case OP_R_NORMAL:
    242         printf("\tnormal\t"); break;
    243       case OP_R_RETURN:
    244         printf("\treturn\t"); break;
    245       case OP_R_BREAK:
    246         printf("\tbreak\t"); break;
    247       default:
    248         printf("\tbroken\t"); break;
     269             MRB_ASPEC_REQ(a),
     270             MRB_ASPEC_OPT(a),
     271             MRB_ASPEC_REST(a),
     272             MRB_ASPEC_POST(a),
     273             MRB_ASPEC_KEY(a),
     274             MRB_ASPEC_KDICT(a),
     275             MRB_ASPEC_BLOCK(a));
     276      break;
     277    CASE(OP_KEY_P, BB):
     278      printf("OP_KEY_P\tR%d\t:%s\t", a, mrb_sym_dump(mrb, irep->syms[b]));
     279      print_lv_a(mrb, irep, a);
     280      break;
     281    CASE(OP_KEYEND, Z):
     282      printf("OP_KEYEND\n");
     283      break;
     284    CASE(OP_KARG, BB):
     285      printf("OP_KARG\tR%d\t:%s\t", a, mrb_sym_dump(mrb, irep->syms[b]));
     286      print_lv_a(mrb, irep, a);
     287      break;
     288    CASE(OP_RETURN, B):
     289      printf("OP_RETURN\tR%d\t\t", a);
     290      print_lv_a(mrb, irep, a);
     291      break;
     292    CASE(OP_RETURN_BLK, B):
     293      printf("OP_RETURN_BLK\tR%d\t\t", a);
     294      print_lv_a(mrb, irep, a);
     295      break;
     296    CASE(OP_BREAK, B):
     297      printf("OP_BREAK\tR%d\t\t", a);
     298      print_lv_a(mrb, irep, a);
     299      break;
     300    CASE(OP_BLKPUSH, BS):
     301      printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d (%d)", a,
     302             (b>>11)&0x3f,
     303             (b>>10)&0x1,
     304             (b>>5)&0x1f,
     305             (b>>4)&0x1,
     306             (b>>0)&0xf);
     307      print_lv_a(mrb, irep, a);
     308      break;
     309    CASE(OP_LAMBDA, BB):
     310      printf("OP_LAMBDA\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]);
     311      break;
     312    CASE(OP_BLOCK, BB):
     313      printf("OP_BLOCK\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]);
     314      break;
     315    CASE(OP_METHOD, BB):
     316      printf("OP_METHOD\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]);
     317      break;
     318    CASE(OP_RANGE_INC, B):
     319      printf("OP_RANGE_INC\tR%d\n", a);
     320      break;
     321    CASE(OP_RANGE_EXC, B):
     322      printf("OP_RANGE_EXC\tR%d\n", a);
     323      break;
     324    CASE(OP_DEF, BB):
     325      printf("OP_DEF\tR%d\t:%s\n", a, mrb_sym_dump(mrb, irep->syms[b]));
     326      break;
     327    CASE(OP_UNDEF, B):
     328      printf("OP_UNDEF\t:%s\n", mrb_sym_dump(mrb, irep->syms[a]));
     329      break;
     330    CASE(OP_ALIAS, BB):
     331      printf("OP_ALIAS\t:%s\t%s\n", mrb_sym_dump(mrb, irep->syms[a]), mrb_sym_dump(mrb, irep->syms[b]));
     332      break;
     333    CASE(OP_ADD, B):
     334      printf("OP_ADD\tR%d\t\n", a);
     335      break;
     336    CASE(OP_ADDI, BB):
     337      printf("OP_ADDI\tR%d\t%d\n", a, b);
     338      break;
     339    CASE(OP_SUB, B):
     340      printf("OP_SUB\tR%d\t\n", a);
     341      break;
     342    CASE(OP_SUBI, BB):
     343      printf("OP_SUBI\tR%d\t%d\n", a, b);
     344      break;
     345    CASE(OP_MUL, B):
     346      printf("OP_MUL\tR%d\t\n", a);
     347      break;
     348    CASE(OP_DIV, B):
     349      printf("OP_DIV\tR%d\t\n", a);
     350      break;
     351    CASE(OP_LT, B):
     352      printf("OP_LT\t\tR%d\t\n", a);
     353      break;
     354    CASE(OP_LE, B):
     355      printf("OP_LE\t\tR%d\t\n", a);
     356      break;
     357    CASE(OP_GT, B):
     358      printf("OP_GT\t\tR%d\t\n", a);
     359      break;
     360    CASE(OP_GE, B):
     361      printf("OP_GE\t\tR%d\t\n", a);
     362      break;
     363    CASE(OP_EQ, B):
     364      printf("OP_EQ\t\tR%d\t\n", a);
     365      break;
     366    CASE(OP_ARRAY, BB):
     367      printf("OP_ARRAY\tR%d\t%d\t", a, b);
     368      print_lv_a(mrb, irep, a);
     369      break;
     370    CASE(OP_ARRAY2, BBB):
     371      printf("OP_ARRAY\tR%d\tR%d\t%d\t", a, b, c);
     372      print_lv_ab(mrb, irep, a, b);
     373      break;
     374    CASE(OP_ARYCAT, B):
     375      printf("OP_ARYCAT\tR%d\t", a);
     376      print_lv_a(mrb, irep, a);
     377      break;
     378    CASE(OP_ARYPUSH, B):
     379      printf("OP_ARYPUSH\tR%d\t", a);
     380      print_lv_a(mrb, irep, a);
     381      break;
     382    CASE(OP_ARYDUP, B):
     383      printf("OP_ARYDUP\tR%d\t", a);
     384      print_lv_a(mrb, irep, a);
     385      break;
     386    CASE(OP_AREF, BBB):
     387      printf("OP_AREF\tR%d\tR%d\t%d", a, b, c);
     388      print_lv_ab(mrb, irep, a, b);
     389      break;
     390    CASE(OP_ASET, BBB):
     391      printf("OP_ASET\tR%d\tR%d\t%d", a, b, c);
     392      print_lv_ab(mrb, irep, a, b);
     393      break;
     394    CASE(OP_APOST, BBB):
     395      printf("OP_APOST\tR%d\t%d\t%d", a, b, c);
     396      print_lv_a(mrb, irep, a);
     397      break;
     398    CASE(OP_INTERN, B):
     399      printf("OP_INTERN\tR%d", a);
     400      print_lv_a(mrb, irep, a);
     401      break;
     402    CASE(OP_STRING, BB):
     403      {
     404        mrb_value v = irep->pool[b];
     405        mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
     406        printf("OP_STRING\tR%d\tL(%d)\t; %s", a, b, RSTRING_PTR(s));
    249407      }
    250       print_lv(mrb, irep, c, RA);
    251       break;
    252     case OP_BLKPUSH:
    253       printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d", GETARG_A(c),
    254              (GETARG_Bx(c)>>10)&0x3f,
    255              (GETARG_Bx(c)>>9)&0x1,
    256              (GETARG_Bx(c)>>4)&0x1f,
    257              (GETARG_Bx(c)>>0)&0xf);
    258       print_lv(mrb, irep, c, RA);
    259       break;
    260 
    261     case OP_LAMBDA:
    262       printf("OP_LAMBDA\tR%d\tI(%+d)\t", GETARG_A(c), GETARG_b(c)+1);
    263       switch (GETARG_c(c)) {
    264       case OP_L_METHOD:
    265         printf("method"); break;
    266       case OP_L_BLOCK:
    267         printf("block"); break;
    268       case OP_L_LAMBDA:
    269         printf("lambda"); break;
    270       }
    271       print_lv(mrb, irep, c, RA);
    272       break;
    273     case OP_RANGE:
    274       printf("OP_RANGE\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
    275       print_lv(mrb, irep, c, RAB);
    276       break;
    277     case OP_METHOD:
    278       printf("OP_METHOD\tR%d\t:%s", GETARG_A(c),
    279              mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
    280       print_lv(mrb, irep, c, RA);
    281       break;
    282 
    283     case OP_ADD:
    284       printf("OP_ADD\tR%d\t:%s\t%d\n", GETARG_A(c),
    285              mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
    286              GETARG_C(c));
    287       break;
    288     case OP_ADDI:
    289       printf("OP_ADDI\tR%d\t:%s\t%d\n", GETARG_A(c),
    290              mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
    291              GETARG_C(c));
    292       break;
    293     case OP_SUB:
    294       printf("OP_SUB\tR%d\t:%s\t%d\n", GETARG_A(c),
    295              mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
    296              GETARG_C(c));
    297       break;
    298     case OP_SUBI:
    299       printf("OP_SUBI\tR%d\t:%s\t%d\n", GETARG_A(c),
    300              mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
    301              GETARG_C(c));
    302       break;
    303     case OP_MUL:
    304       printf("OP_MUL\tR%d\t:%s\t%d\n", GETARG_A(c),
    305              mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
    306              GETARG_C(c));
    307       break;
    308     case OP_DIV:
    309       printf("OP_DIV\tR%d\t:%s\t%d\n", GETARG_A(c),
    310              mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
    311              GETARG_C(c));
    312       break;
    313     case OP_LT:
    314       printf("OP_LT\tR%d\t:%s\t%d\n", GETARG_A(c),
    315              mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
    316              GETARG_C(c));
    317       break;
    318     case OP_LE:
    319       printf("OP_LE\tR%d\t:%s\t%d\n", GETARG_A(c),
    320              mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
    321              GETARG_C(c));
    322       break;
    323     case OP_GT:
    324       printf("OP_GT\tR%d\t:%s\t%d\n", GETARG_A(c),
    325              mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
    326              GETARG_C(c));
    327       break;
    328     case OP_GE:
    329       printf("OP_GE\tR%d\t:%s\t%d\n", GETARG_A(c),
    330              mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
    331              GETARG_C(c));
    332       break;
    333     case OP_EQ:
    334       printf("OP_EQ\t\tR%d\t:%s\t%d\n", GETARG_A(c),
    335              mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
    336              GETARG_C(c));
    337       break;
    338 
    339     case OP_STOP:
    340       printf("OP_STOP\n");
    341       break;
    342 
    343     case OP_ARRAY:
    344       printf("OP_ARRAY\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
    345       print_lv(mrb, irep, c, RAB);
    346       break;
    347     case OP_ARYCAT:
    348       printf("OP_ARYCAT\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
    349       print_lv(mrb, irep, c, RAB);
    350       break;
    351     case OP_ARYPUSH:
    352       printf("OP_ARYPUSH\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
    353       print_lv(mrb, irep, c, RAB);
    354       break;
    355     case OP_AREF:
    356       printf("OP_AREF\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
    357       print_lv(mrb, irep, c, RAB);
    358       break;
    359     case OP_APOST:
    360       printf("OP_APOST\tR%d\t%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
    361       print_lv(mrb, irep, c, RA);
    362       break;
    363     case OP_STRING:
     408      print_lv_a(mrb, irep, a);
     409      break;
     410    CASE(OP_STRCAT, B):
     411      printf("OP_STRCAT\tR%d\t", a);
     412      print_lv_a(mrb, irep, a);
     413      break;
     414    CASE(OP_HASH, BB):
     415      printf("OP_HASH\tR%d\t%d\t", a, b);
     416      print_lv_a(mrb, irep, a);
     417      break;
     418    CASE(OP_HASHADD, BB):
     419      printf("OP_HASHADD\tR%d\t%d\t", a, b);
     420      print_lv_a(mrb, irep, a);
     421      break;
     422    CASE(OP_HASHCAT, B):
     423      printf("OP_HASHCAT\tR%d\t", a);
     424      print_lv_a(mrb, irep, a);
     425      break;
     426
     427    CASE(OP_OCLASS, B):
     428      printf("OP_OCLASS\tR%d\t\t", a);
     429      print_lv_a(mrb, irep, a);
     430      break;
     431    CASE(OP_CLASS, BB):
     432      printf("OP_CLASS\tR%d\t:%s", a, mrb_sym_dump(mrb, irep->syms[b]));
     433      print_lv_a(mrb, irep, a);
     434      break;
     435    CASE(OP_MODULE, BB):
     436      printf("OP_MODULE\tR%d\t:%s", a, mrb_sym_dump(mrb, irep->syms[b]));
     437      print_lv_a(mrb, irep, a);
     438      break;
     439    CASE(OP_EXEC, BB):
     440      printf("OP_EXEC\tR%d\tI(%d:%p)", a, b, irep->reps[b]);
     441      print_lv_a(mrb, irep, a);
     442      break;
     443    CASE(OP_SCLASS, B):
     444      printf("OP_SCLASS\tR%d\t", a);
     445      print_lv_a(mrb, irep, a);
     446      break;
     447    CASE(OP_TCLASS, B):
     448      printf("OP_TCLASS\tR%d\t\t", a);
     449      print_lv_a(mrb, irep, a);
     450      break;
     451    CASE(OP_ERR, B):
    364452      {
    365         mrb_value v = irep->pool[GETARG_Bx(c)];
    366         mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
    367         printf("OP_STRING\tR%d\tL(%d)\t; %s", GETARG_A(c), GETARG_Bx(c), RSTRING_PTR(s));
    368       }
    369       print_lv(mrb, irep, c, RA);
    370       break;
    371     case OP_STRCAT:
    372       printf("OP_STRCAT\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
    373       print_lv(mrb, irep, c, RAB);
    374       break;
    375     case OP_HASH:
    376       printf("OP_HASH\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
    377       print_lv(mrb, irep, c, RAB);
    378       break;
    379 
    380     case OP_OCLASS:
    381       printf("OP_OCLASS\tR%d\t\t", GETARG_A(c));
    382       print_lv(mrb, irep, c, RA);
    383       break;
    384     case OP_CLASS:
    385       printf("OP_CLASS\tR%d\t:%s", GETARG_A(c),
    386              mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
    387       print_lv(mrb, irep, c, RA);
    388       break;
    389     case OP_MODULE:
    390       printf("OP_MODULE\tR%d\t:%s", GETARG_A(c),
    391              mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
    392       print_lv(mrb, irep, c, RA);
    393       break;
    394     case OP_EXEC:
    395       printf("OP_EXEC\tR%d\tI(%+d)", GETARG_A(c), GETARG_Bx(c)+1);
    396       print_lv(mrb, irep, c, RA);
    397       break;
    398     case OP_SCLASS:
    399       printf("OP_SCLASS\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
    400       print_lv(mrb, irep, c, RAB);
    401       break;
    402     case OP_TCLASS:
    403       printf("OP_TCLASS\tR%d\t\t", GETARG_A(c));
    404       print_lv(mrb, irep, c, RA);
    405       break;
    406     case OP_ERR:
    407       {
    408         mrb_value v = irep->pool[GETARG_Bx(c)];
     453        mrb_value v = irep->pool[a];
    409454        mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
    410455        printf("OP_ERR\t%s\n", RSTRING_PTR(s));
    411456      }
    412457      break;
    413     case OP_EPUSH:
    414       printf("OP_EPUSH\t:I(%+d)\n", GETARG_Bx(c)+1);
    415       break;
    416     case OP_ONERR:
    417       printf("OP_ONERR\t%03d\n", i+GETARG_sBx(c));
    418       break;
    419     case OP_RESCUE:
    420       {
    421         int a = GETARG_A(c);
    422         int b = GETARG_B(c);
    423         int cnt = GETARG_C(c);
    424 
    425         if (b == 0) {
    426           printf("OP_RESCUE\tR%d\t\t%s", a, cnt ? "cont" : "");
    427           print_lv(mrb, irep, c, RA);
    428           break;
    429         }
    430         else {
    431           printf("OP_RESCUE\tR%d\tR%d\t%s", a, b, cnt ? "cont" : "");
    432           print_lv(mrb, irep, c, RAB);
    433           break;
    434         }
     458    CASE(OP_EPUSH, B):
     459      printf("OP_EPUSH\t\t:I(%d:%p)\n", a, irep->reps[a]);
     460      break;
     461    CASE(OP_ONERR, S):
     462      printf("OP_ONERR\t%03d\n", a);
     463      break;
     464    CASE(OP_EXCEPT, B):
     465      printf("OP_EXCEPT\tR%d\t\t", a);
     466      print_lv_a(mrb, irep, a);
     467      break;
     468    CASE(OP_RESCUE, BB):
     469      printf("OP_RESCUE\tR%d\tR%d", a, b);
     470      print_lv_ab(mrb, irep, a, b);
     471      break;
     472    CASE(OP_RAISE, B):
     473      printf("OP_RAISE\tR%d\t\t", a);
     474      print_lv_a(mrb, irep, a);
     475      break;
     476    CASE(OP_POPERR, B):
     477      printf("OP_POPERR\t%d\t\t\n", a);
     478      break;
     479    CASE(OP_EPOP, B):
     480      printf("OP_EPOP\t%d\n", a);
     481      break;
     482
     483    CASE(OP_DEBUG, BBB):
     484      printf("OP_DEBUG\t%d\t%d\t%d\n", a, b, c);
     485      break;
     486
     487    CASE(OP_STOP, Z):
     488      printf("OP_STOP\n");
     489      break;
     490
     491    CASE(OP_EXT1, Z):
     492      ins = READ_B();
     493      printf("OP_EXT1\n");
     494      print_header(mrb, irep, pc-irep->iseq-2);
     495      switch (ins) {
     496#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); goto L_OP_ ## i;
     497#include "mruby/ops.h"
     498#undef OPCODE
    435499      }
    436500      break;
    437     case OP_RAISE:
    438       printf("OP_RAISE\tR%d\t\t", GETARG_A(c));
    439       print_lv(mrb, irep, c, RA);
    440       break;
    441     case OP_POPERR:
    442       printf("OP_POPERR\t%d\t\t\n", GETARG_A(c));
    443       break;
    444     case OP_EPOP:
    445       printf("OP_EPOP\t%d\n", GETARG_A(c));
     501    CASE(OP_EXT2, Z):
     502      ins = READ_B();
     503      printf("OP_EXT2\n");
     504      print_header(mrb, irep, pc-irep->iseq-2);
     505      switch (ins) {
     506#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); goto L_OP_ ## i;
     507#include "mruby/ops.h"
     508#undef OPCODE
     509      }
     510      break;
     511    CASE(OP_EXT3, Z):
     512      ins = READ_B();
     513      printf("OP_EXT3\n");
     514      print_header(mrb, irep, pc-irep->iseq-2);
     515      switch (ins) {
     516#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); goto L_OP_ ## i;
     517#include "mruby/ops.h"
     518#undef OPCODE
     519      }
    446520      break;
    447521
    448522    default:
    449       printf("OP_unknown %d\t%d\t%d\t%d\n", GET_OPCODE(c),
    450              GETARG_A(c), GETARG_B(c), GETARG_C(c));
     523      printf("OP_unknown (0x%x)\n", ins);
    451524      break;
    452525    }
     
    454527  }
    455528  printf("\n");
    456 #endif
    457529}
    458530
     
    460532codedump_recur(mrb_state *mrb, mrb_irep *irep)
    461533{
    462   size_t i;
     534  int i;
    463535
    464536  codedump(mrb, irep);
     
    467539  }
    468540}
     541#endif
    469542
    470543void
    471544mrb_codedump_all(mrb_state *mrb, struct RProc *proc)
    472545{
     546#ifndef MRB_DISABLE_STDIO
    473547  codedump_recur(mrb, proc->body.irep);
    474 }
     548#endif
     549}
  • EcnlProtoTool/trunk/mruby-2.1.1/src/debug.c

    r331 r439  
    44#include <mruby/debug.h>
    55
    6 static mrb_irep_debug_info_file *
     6static mrb_irep_debug_info_file*
    77get_file(mrb_irep_debug_info *info, uint32_t pc)
    88{
     
    5252
    5353MRB_API char const*
    54 mrb_debug_get_filename(mrb_irep *irep, uint32_t pc)
    55 {
    56   if (irep && pc < irep->ilen) {
     54mrb_debug_get_filename(mrb_state *mrb, mrb_irep *irep, ptrdiff_t pc)
     55{
     56  if (irep && pc >= 0 && pc < irep->ilen) {
    5757    mrb_irep_debug_info_file* f = NULL;
    58     if (!irep->debug_info) { return irep->filename; }
    59     else if ((f = get_file(irep->debug_info, pc))) {
    60       return f->filename;
     58    if (!irep->debug_info) return NULL;
     59    else if ((f = get_file(irep->debug_info, (uint32_t)pc))) {
     60      return mrb_sym_name_len(mrb, f->filename_sym, NULL);
    6161    }
    6262  }
     
    6565
    6666MRB_API int32_t
    67 mrb_debug_get_line(mrb_irep *irep, uint32_t pc)
    68 {
    69   if (irep && pc < irep->ilen) {
     67mrb_debug_get_line(mrb_state *mrb, mrb_irep *irep, ptrdiff_t pc)
     68{
     69  if (irep && pc >= 0 && pc < irep->ilen) {
    7070    mrb_irep_debug_info_file* f = NULL;
    7171    if (!irep->debug_info) {
    72       return irep->lines? irep->lines[pc] : -1;
    73     }
    74     else if ((f = get_file(irep->debug_info, pc))) {
     72      return -1;
     73    }
     74    else if ((f = get_file(irep->debug_info, (uint32_t)pc))) {
    7575      switch (f->line_type) {
    7676        case mrb_debug_line_ary:
     
    109109}
    110110
    111 MRB_API mrb_irep_debug_info *
     111MRB_API mrb_irep_debug_info*
    112112mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep)
    113113{
     
    122122}
    123123
    124 MRB_API mrb_irep_debug_info_file *
    125 mrb_debug_info_append_file(mrb_state *mrb, mrb_irep *irep,
     124MRB_API mrb_irep_debug_info_file*
     125mrb_debug_info_append_file(mrb_state *mrb, mrb_irep_debug_info *d,
     126                           const char *filename, uint16_t *lines,
    126127                           uint32_t start_pos, uint32_t end_pos)
    127128{
    128   mrb_irep_debug_info *info;
    129   mrb_irep_debug_info_file *ret;
     129  mrb_irep_debug_info_file *f;
    130130  uint32_t file_pc_count;
    131131  size_t fn_len;
    132   mrb_int len;
    133132  uint32_t i;
    134133
    135   if (!irep->debug_info) { return NULL; }
    136 
    137   mrb_assert(irep->filename);
    138   mrb_assert(irep->lines);
    139 
    140   info = irep->debug_info;
    141 
    142   if (info->flen > 0 && strcmp(irep->filename, info->files[info->flen - 1]->filename) == 0) {
    143     return NULL;
    144   }
    145 
    146   ret = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*ret));
    147   info->files =
    148       (mrb_irep_debug_info_file**)(
    149           info->files
    150           ? mrb_realloc(mrb, info->files, sizeof(mrb_irep_debug_info_file*) * (info->flen + 1))
     134  if (!d) return NULL;
     135  if (start_pos == end_pos) return NULL;
     136
     137  mrb_assert(filename);
     138  mrb_assert(lines);
     139
     140  if (d->flen > 0) {
     141    const char *fn = mrb_sym_name_len(mrb, d->files[d->flen - 1]->filename_sym, NULL);
     142    if (strcmp(filename, fn) == 0)
     143      return NULL;
     144  }
     145
     146  f = (mrb_irep_debug_info_file*)mrb_malloc(mrb, sizeof(*f));
     147  d->files = (mrb_irep_debug_info_file**)(
     148          d->files
     149          ? mrb_realloc(mrb, d->files, sizeof(mrb_irep_debug_info_file*) * (d->flen + 1))
    151150          : mrb_malloc(mrb, sizeof(mrb_irep_debug_info_file*)));
    152   info->files[info->flen++] = ret;
     151  d->files[d->flen++] = f;
    153152
    154153  file_pc_count = end_pos - start_pos;
    155154
    156   ret->start_pos = start_pos;
    157   info->pc_count = end_pos;
    158 
    159   fn_len = strlen(irep->filename);
    160   ret->filename_sym = mrb_intern(mrb, irep->filename, fn_len);
    161   len = 0;
    162   ret->filename = mrb_sym2name_len(mrb, ret->filename_sym, &len);
    163 
    164   ret->line_type = select_line_type(irep->lines + start_pos, end_pos - start_pos);
    165   ret->lines.ptr = NULL;
    166 
    167   switch (ret->line_type) {
     155  f->start_pos = start_pos;
     156  d->pc_count = end_pos;
     157
     158  fn_len = strlen(filename);
     159  f->filename_sym = mrb_intern(mrb, filename, fn_len);
     160
     161  f->line_type = select_line_type(lines + start_pos, end_pos - start_pos);
     162  f->lines.ptr = NULL;
     163
     164  switch (f->line_type) {
    168165    case mrb_debug_line_ary:
    169       ret->line_entry_count = file_pc_count;
    170       ret->lines.ary = (uint16_t*)mrb_malloc(mrb, sizeof(uint16_t) * file_pc_count);
     166      f->line_entry_count = file_pc_count;
     167      f->lines.ary = (uint16_t*)mrb_malloc(mrb, sizeof(uint16_t) * file_pc_count);
    171168      for (i = 0; i < file_pc_count; ++i) {
    172         ret->lines.ary[i] = irep->lines[start_pos + i];
     169        f->lines.ary[i] = lines[start_pos + i];
    173170      }
    174171      break;
     
    177174      uint16_t prev_line = 0;
    178175      mrb_irep_debug_info_line m;
    179       ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * 1);
    180       ret->line_entry_count = 0;
     176      f->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * 1);
     177      f->line_entry_count = 0;
    181178      for (i = 0; i < file_pc_count; ++i) {
    182         if (irep->lines[start_pos + i] == prev_line) { continue; }
    183 
    184         ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_realloc(
    185             mrb, ret->lines.flat_map,
    186             sizeof(mrb_irep_debug_info_line) * (ret->line_entry_count + 1));
     179        if (lines[start_pos + i] == prev_line) { continue; }
     180
     181        f->lines.flat_map = (mrb_irep_debug_info_line*)mrb_realloc(
     182            mrb, f->lines.flat_map,
     183            sizeof(mrb_irep_debug_info_line) * (f->line_entry_count + 1));
    187184        m.start_pos = start_pos + i;
    188         m.line = irep->lines[start_pos + i];
    189         ret->lines.flat_map[ret->line_entry_count] = m;
     185        m.line = lines[start_pos + i];
     186        f->lines.flat_map[f->line_entry_count] = m;
    190187
    191188        /* update */
    192         ++ret->line_entry_count;
    193         prev_line = irep->lines[start_pos + i];
     189        ++f->line_entry_count;
     190        prev_line = lines[start_pos + i];
    194191      }
    195192    } break;
     
    198195  }
    199196
    200   return ret;
     197  return f;
    201198}
    202199
  • EcnlProtoTool/trunk/mruby-2.1.1/src/dump.c

    r331 r439  
    77#include <string.h>
    88#include <limits.h>
     9#include <math.h>
    910#include <mruby/dump.h>
    1011#include <mruby/string.h>
     
    1617#define FLAG_BYTEORDER_NONATIVE 0
    1718
     19#ifndef MRB_WITHOUT_FLOAT
    1820#ifdef MRB_USE_FLOAT
    19 #define MRB_FLOAT_FMT "%.8e"
     21#define MRB_FLOAT_FMT "%.9g"
    2022#else
    21 #define MRB_FLOAT_FMT "%.16e"
     23#define MRB_FLOAT_FMT "%.17g"
     24#endif
    2225#endif
    2326
     
    8083{
    8184  uint8_t *cur = buf;
    82   uint32_t iseq_no;
    8385
    8486  cur += uint32_to_bin(irep->ilen, cur); /* number of opcode */
    8587  cur += write_padding(cur);
    86   switch (flags & DUMP_ENDIAN_NAT) {
    87   case DUMP_ENDIAN_BIG:
    88     if (bigendian_p()) goto native;
    89     for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) {
    90       cur += uint32_to_bin(irep->iseq[iseq_no], cur); /* opcode */
    91     }
    92     break;
    93   case DUMP_ENDIAN_LIL:
    94     if (!bigendian_p()) goto native;
    95     for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) {
    96       cur += uint32l_to_bin(irep->iseq[iseq_no], cur); /* opcode */
    97     }
    98     break;
    99 
    100   native:
    101   case DUMP_ENDIAN_NAT:
    102     memcpy(cur, irep->iseq, irep->ilen * sizeof(mrb_code));
    103     cur += irep->ilen * sizeof(mrb_code);
    104     break;
    105   }
     88  memcpy(cur, irep->iseq, irep->ilen * sizeof(mrb_code));
     89  cur += irep->ilen * sizeof(mrb_code);
    10690
    10791  return cur - buf;
    10892}
    10993
     94#ifndef MRB_WITHOUT_FLOAT
     95static mrb_value
     96float_to_str(mrb_state *mrb, mrb_value flt)
     97{
     98  mrb_float f = mrb_float(flt);
     99
     100  if (isinf(f)) {
     101    return f < 0 ? mrb_str_new_lit(mrb, "I") : mrb_str_new_lit(mrb, "i");
     102  }
     103  return  mrb_float_to_str(mrb, flt, MRB_FLOAT_FMT);
     104}
     105#endif
    110106
    111107static size_t
    112108get_pool_block_size(mrb_state *mrb, mrb_irep *irep)
    113109{
     110  int pool_no;
    114111  size_t size = 0;
    115   size_t pool_no;
    116112  mrb_value str;
    117113
     
    132128      break;
    133129
     130#ifndef MRB_WITHOUT_FLOAT
    134131    case MRB_TT_FLOAT:
    135       str = mrb_float_to_str(mrb, irep->pool[pool_no], MRB_FLOAT_FMT);
     132      str = float_to_str(mrb, irep->pool[pool_no]);
    136133      {
    137134        mrb_int len = RSTRING_LEN(str);
     
    140137      }
    141138      break;
     139#endif
    142140
    143141    case MRB_TT_STRING:
     
    161159write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
    162160{
    163   size_t pool_no;
     161  int pool_no;
    164162  uint8_t *cur = buf;
    165163  uint16_t len;
     
    178176      break;
    179177
     178#ifndef MRB_WITHOUT_FLOAT
    180179    case MRB_TT_FLOAT:
    181180      cur += uint8_to_bin(IREP_TT_FLOAT, cur); /* data type */
    182       str = mrb_float_to_str(mrb, irep->pool[pool_no], MRB_FLOAT_FMT);
     181      str = float_to_str(mrb, irep->pool[pool_no]);
    183182      break;
     183#endif
    184184
    185185    case MRB_TT_STRING:
     
    214214{
    215215  size_t size = 0;
    216   uint32_t sym_no;
     216  int sym_no;
    217217  mrb_int len;
    218218
     
    221221    size += sizeof(uint16_t); /* snl(n) */
    222222    if (irep->syms[sym_no] != 0) {
    223       mrb_sym2name_len(mrb, irep->syms[sym_no], &len);
     223      mrb_sym_name_len(mrb, irep->syms[sym_no], &len);
    224224      size += len + 1; /* sn(n) + null char */
    225225    }
     
    232232write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
    233233{
    234   uint32_t sym_no;
     234  int sym_no;
    235235  uint8_t *cur = buf;
    236236  const char *name;
     
    242242      mrb_int len;
    243243
    244       name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len);
     244      name = mrb_sym_name_len(mrb, irep->syms[sym_no], &len);
    245245
    246246      mrb_assert_int_fit(mrb_int, len, uint16_t, UINT16_MAX);
     
    274274{
    275275  size_t size = 0;
    276   size_t irep_no;
     276  int irep_no;
    277277
    278278  size = get_irep_record_size_1(mrb, irep);
     
    286286write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, size_t *irep_record_size, uint8_t flags)
    287287{
    288   uint32_t i;
     288  int i;
    289289  uint8_t *src = bin;
    290290
     
    367367}
    368368
    369 static int
    370 write_section_lineno_header(mrb_state *mrb, size_t section_size, uint8_t *bin)
    371 {
    372   struct rite_section_lineno_header *header = (struct rite_section_lineno_header*)bin;
    373 
    374   memcpy(header->section_ident, RITE_SECTION_LINENO_IDENT, sizeof(header->section_ident));
    375   uint32_to_bin((uint32_t)section_size, header->section_size);
    376 
    377   return MRB_DUMP_OK;
    378 }
    379 
    380 static size_t
    381 get_lineno_record_size(mrb_state *mrb, mrb_irep *irep)
    382 {
    383   size_t size = 0;
    384 
    385   size += sizeof(uint32_t); /* record size */
    386   size += sizeof(uint16_t); /* filename size */
    387   if (irep->filename) {
    388     size += strlen(irep->filename); /* filename */
    389   }
    390   size += sizeof(uint32_t); /* niseq */
    391   if (irep->lines) {
    392     size += sizeof(uint16_t) * irep->ilen; /* lineno */
    393   }
    394 
    395   return size;
    396 }
    397 
    398 static size_t
    399 write_lineno_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t* bin)
    400 {
    401   uint8_t *cur = bin;
    402   size_t iseq_no;
    403   size_t filename_len;
    404   ptrdiff_t diff;
    405 
    406   cur += sizeof(uint32_t); /* record size */
    407 
    408   if (irep->filename) {
    409     filename_len = strlen(irep->filename);
    410   }
    411   else {
    412     filename_len = 0;
    413   }
    414   mrb_assert_int_fit(size_t, filename_len, uint16_t, UINT16_MAX);
    415   cur += uint16_to_bin((uint16_t)filename_len, cur); /* filename size */
    416 
    417   if (filename_len) {
    418     memcpy(cur, irep->filename, filename_len);
    419     cur += filename_len; /* filename */
    420   }
    421 
    422   if (irep->lines) {
    423     mrb_assert_int_fit(size_t, irep->ilen, uint32_t, UINT32_MAX);
    424     cur += uint32_to_bin((uint32_t)(irep->ilen), cur); /* niseq */
    425     for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) {
    426       cur += uint16_to_bin(irep->lines[iseq_no], cur); /* opcode */
    427     }
    428   }
    429   else {
    430     cur += uint32_to_bin(0, cur); /* niseq */
    431   }
    432 
    433   diff = cur - bin;
    434   mrb_assert_int_fit(ptrdiff_t, diff, uint32_t, UINT32_MAX);
    435 
    436   uint32_to_bin((uint32_t)diff, bin); /* record size */
    437 
    438   mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
    439   return (size_t)diff;
    440 }
    441 
    442 static size_t
    443 write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin)
    444 {
    445   size_t i;
    446   size_t rlen, size = 0;
    447 
    448   rlen = write_lineno_record_1(mrb, irep, bin);
    449   bin += rlen;
    450   size += rlen;
    451   for (i=0; i<irep->rlen; i++) {
    452     rlen = write_lineno_record(mrb, irep, bin);
    453     bin += rlen;
    454     size += rlen;
    455   }
    456   return size;
    457 }
    458 
    459 static int
    460 write_section_lineno(mrb_state *mrb, mrb_irep *irep, uint8_t *bin)
    461 {
    462   size_t section_size = 0;
    463   size_t rlen = 0; /* size of irep record */
    464   uint8_t *cur = bin;
    465 
    466   if (mrb == NULL || bin == NULL) {
    467     return MRB_DUMP_INVALID_ARGUMENT;
    468   }
    469 
    470   cur += sizeof(struct rite_section_lineno_header);
    471   section_size += sizeof(struct rite_section_lineno_header);
    472 
    473   rlen = write_lineno_record(mrb, irep, cur);
    474   section_size += rlen;
    475 
    476   write_section_lineno_header(mrb, section_size, bin);
    477 
    478   return MRB_DUMP_OK;
    479 }
    480 
    481369static size_t
    482370get_debug_record_size(mrb_state *mrb, mrb_irep *irep)
     
    484372  size_t ret = 0;
    485373  uint16_t f_idx;
    486   size_t i;
     374  int i;
    487375
    488376  ret += sizeof(uint32_t); /* record size */
     
    532420{
    533421  mrb_sym *filenames = *fp;
    534   size_t i, size = 0;
     422  size_t size = 0;
    535423  mrb_irep_debug_info *di = irep->debug_info;
     424  int i;
    536425
    537426  mrb_assert(lp);
     
    548437
    549438      /* filename */
    550       mrb_sym2name_len(mrb, file->filename_sym, &filename_len);
     439      mrb_sym_name_len(mrb, file->filename_sym, &filename_len);
    551440      size += sizeof(uint16_t) + (size_t)filename_len;
    552441    }
     
    606495  ret = cur - bin;
    607496  mrb_assert_int_fit(ptrdiff_t, ret, uint32_t, UINT32_MAX);
    608   uint32_to_bin(ret, bin);
     497  uint32_to_bin((uint32_t)ret, bin);
    609498
    610499  mrb_assert_int_fit(ptrdiff_t, ret, size_t, SIZE_MAX);
     
    616505{
    617506  size_t size, len;
    618   size_t irep_no;
     507  int irep_no;
    619508
    620509  size = len = write_debug_record_1(mrb, irep, bin, filenames, filenames_len);
     
    652541  section_size += sizeof(uint16_t);
    653542  for (i = 0; i < filenames_len; ++i) {
    654     sym = mrb_sym2name_len(mrb, filenames[i], &sym_len);
     543    sym = mrb_sym_name_len(mrb, filenames[i], &sym_len);
    655544    mrb_assert(sym);
    656     cur += uint16_to_bin(sym_len, cur);
     545    cur += uint16_to_bin((uint16_t)sym_len, cur);
    657546    memcpy(cur, sym, sym_len);
    658547    cur += sym_len;
     
    666555  memcpy(header->section_ident, RITE_SECTION_DEBUG_IDENT, sizeof(header->section_ident));
    667556  mrb_assert(section_size <= INT32_MAX);
    668   uint32_to_bin(section_size, header->section_size);
     557  uint32_to_bin((uint32_t)section_size, header->section_size);
    669558
    670559  return MRB_DUMP_OK;
     
    674563create_lv_sym_table(mrb_state *mrb, const mrb_irep *irep, mrb_sym **syms, uint32_t *syms_len)
    675564{
    676   size_t i;
     565  int i;
    677566
    678567  if (*syms == NULL) {
     
    706595
    707596  for (i = 0; i < syms_len; ++i) {
    708     str = mrb_sym2name_len(mrb, syms[i], &str_len);
    709     cur += uint16_to_bin(str_len, cur);
     597    str = mrb_sym_name_len(mrb, syms[i], &str_len);
     598    cur += uint16_to_bin((uint16_t)str_len, cur);
    710599    memcpy(cur, str, str_len);
    711600    cur += str_len;
     
    721610{
    722611  uint8_t *cur = *start;
    723   size_t i;
     612  int i;
    724613
    725614  for (i = 0; i + 1 < irep->nlocals; ++i) {
     
    749638get_lv_record_size(mrb_state *mrb, mrb_irep *irep)
    750639{
    751   size_t ret = 0, i;
     640  size_t ret = 0;
     641  int i;
    752642
    753643  ret += (sizeof(uint16_t) + sizeof(uint16_t)) * (irep->nlocals - 1);
     
    769659  for (i = 0; i < syms_len; ++i) {
    770660    mrb_int str_len;
    771     mrb_sym2name_len(mrb, syms[i], &str_len);
     661    mrb_sym_name_len(mrb, syms[i], &str_len);
    772662    ret += str_len;
    773663  }
     
    807697  diff = cur - start;
    808698  mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
    809   uint32_to_bin(diff, header->section_size);
     699  uint32_to_bin((uint32_t)diff, header->section_size);
    810700
    811701lv_section_exit:
     
    842732  uint32_to_bin((uint32_t)binary_size, header->binary_size);
    843733
    844   offset = (&(header->binary_crc[0]) - bin) + sizeof(uint16_t);
     734  offset = (uint32_t)((&(header->binary_crc[0]) - bin) + sizeof(uint16_t));
    845735  crc = calc_crc_16_ccitt(bin + offset, binary_size - offset, 0);
    846736  uint16_to_bin(crc, header->binary_crc);
     
    850740
    851741static mrb_bool
    852 is_debug_info_defined(mrb_irep *irep)
    853 {
    854   size_t i;
     742debug_info_defined_p(mrb_irep *irep)
     743{
     744  int i;
    855745
    856746  if (!irep->debug_info) return FALSE;
    857747  for (i=0; i<irep->rlen; i++) {
    858     if (!is_debug_info_defined(irep->reps[i])) return FALSE;
     748    if (!debug_info_defined_p(irep->reps[i])) return FALSE;
    859749  }
    860750  return TRUE;
     
    862752
    863753static mrb_bool
    864 is_lv_defined(mrb_irep *irep)
    865 {
    866   size_t i;
     754lv_defined_p(mrb_irep *irep)
     755{
     756  int i;
    867757
    868758  if (irep->lv) { return TRUE; }
    869759
    870760  for (i = 0; i < irep->rlen; ++i) {
    871     if (is_lv_defined(irep->reps[i])) { return TRUE; }
     761    if (lv_defined_p(irep->reps[i])) { return TRUE; }
    872762  }
    873763
     
    898788  size_t section_lineno_size = 0, section_lv_size = 0;
    899789  uint8_t *cur = NULL;
    900   mrb_bool const debug_info_defined = is_debug_info_defined(irep), lv_defined = is_lv_defined(irep);
     790  mrb_bool const debug_info_defined = debug_info_defined_p(irep), lv_defined = lv_defined_p(irep);
    901791  mrb_sym *lv_syms = NULL; uint32_t lv_syms_len = 0;
    902792  mrb_sym *filenames = NULL; uint16_t filenames_len = 0;
     
    923813      section_lineno_size += get_debug_record_size(mrb, irep);
    924814    }
    925     else {
    926       section_lineno_size += sizeof(struct rite_section_lineno_header);
    927       section_lineno_size += get_lineno_record_size(mrb, irep);
    928     }
    929815  }
    930816
     
    954840    if (debug_info_defined) {
    955841      result = write_section_debug(mrb, irep, cur, filenames, filenames_len);
    956     }
    957     else {
    958       result = write_section_lineno(mrb, irep, cur);
    959     }
    960     if (result != MRB_DUMP_OK) {
    961       goto error_exit;
     842      if (result != MRB_DUMP_OK) {
     843        goto error_exit;
     844      }
    962845    }
    963846    cur += section_lineno_size;
     
    1061944    }
    1062945    if (fprintf(fp,
     946          "#ifdef __cplusplus\n"
    1063947          "extern const uint8_t %s[];\n"
     948          "#endif\n"
    1064949          "const uint8_t\n"
    1065950          "#if defined __GNUC__\n"
  • EcnlProtoTool/trunk/mruby-2.1.1/src/enum.c

    r331 r439  
    66
    77#include <mruby.h>
     8#include <mruby/proc.h>
     9
     10/* internal method `__update_hash(oldhash, index, itemhash)` */
     11static mrb_value
     12enum_update_hash(mrb_state *mrb, mrb_value self)
     13{
     14  mrb_int hash;
     15  mrb_int index;
     16  mrb_int hv;
     17
     18  mrb_get_args(mrb, "iii", &hash, &index, &hv);
     19  hash ^= ((uint32_t)hv << (index % 16));
     20
     21  return mrb_fixnum_value(hash);
     22}
    823
    924void
    1025mrb_init_enumerable(mrb_state *mrb)
    1126{
    12   mrb_define_module(mrb, "Enumerable");  /* 15.3.2 */
     27  struct RClass *enumerable;
     28  enumerable = mrb_define_module(mrb, "Enumerable");  /* 15.3.2 */
     29  mrb_define_module_function(mrb, enumerable, "__update_hash", enum_update_hash, MRB_ARGS_REQ(3));
    1330}
    14 
  • EcnlProtoTool/trunk/mruby-2.1.1/src/error.c

    r331 r439  
    1414#include <mruby/string.h>
    1515#include <mruby/variable.h>
    16 #include <mruby/debug.h>
    1716#include <mruby/error.h>
    1817#include <mruby/class.h>
     
    2928mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str)
    3029{
    31   str = mrb_str_to_str(mrb, str);
     30  mrb_to_str(mrb, str);
    3231  return mrb_obj_new(mrb, c, 1, &str);
    3332}
     
    4544{
    4645  mrb_value mesg;
    47   mrb_int argc;
    48   mrb_value *argv;
    49 
    50   if (mrb_get_args(mrb, "|o*", &mesg, &argv, &argc) >= 1) {
     46
     47  if (mrb_get_args(mrb, "|o", &mesg) == 1) {
    5148    mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "mesg"), mesg);
    5249  }
     
    7269  mrb_value exc;
    7370  mrb_value a;
    74   int argc;
     71  mrb_int argc;
    7572
    7673  argc = mrb_get_args(mrb, "|o", &a);
     
    9188 */
    9289
    93 static mrb_value
     90mrb_value
    9491exc_to_s(mrb_state *mrb, mrb_value exc)
    9592{
     
    131128 */
    132129
    133 static mrb_value
    134 exc_inspect(mrb_state *mrb, mrb_value exc)
    135 {
    136   mrb_value str, mesg, file, line;
    137   mrb_bool append_mesg;
    138   const char *cname;
    139 
    140   mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg"));
    141   file = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "file"));
    142   line = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "line"));
    143 
    144   append_mesg = !mrb_nil_p(mesg);
    145   if (append_mesg) {
    146     mesg = mrb_obj_as_string(mrb, mesg);
    147     append_mesg = RSTRING_LEN(mesg) > 0;
    148   }
    149 
    150   cname = mrb_obj_classname(mrb, exc);
    151   str = mrb_str_new_cstr(mrb, cname);
    152   if (mrb_string_p(file) && mrb_fixnum_p(line)) {
    153     if (append_mesg) {
    154       str = mrb_format(mrb, "%S:%S:%S (%S)", file, line, mesg, str);
    155     }
    156     else {
    157       str = mrb_format(mrb, "%S:%S:%S", file, line, str);
    158     }
    159   }
    160   else if (append_mesg) {
    161     str = mrb_format(mrb, "%S:%S", str, mesg);
    162   }
    163   return str;
     130mrb_value
     131mrb_exc_inspect(mrb_state *mrb, mrb_value exc)
     132{
     133  mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg"));
     134  mrb_value cname = mrb_mod_to_s(mrb, mrb_obj_value(mrb_obj_class(mrb, exc)));
     135  mesg = mrb_obj_as_string(mrb, mesg);
     136  return RSTRING_LEN(mesg) == 0 ? cname : mrb_format(mrb, "%v (%v)", mesg, cname);
    164137}
    165138
     
    195168}
    196169
    197 static void
    198 exc_debug_info(mrb_state *mrb, struct RObject *exc)
    199 {
    200   mrb_callinfo *ci = mrb->c->ci;
    201   mrb_code *pc = ci->pc;
    202 
    203   while (ci >= mrb->c->cibase) {
    204     mrb_code *err = ci->err;
    205 
    206     if (!err && pc) err = pc - 1;
    207     if (err && ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) {
    208       mrb_irep *irep = ci->proc->body.irep;
    209 
    210       int32_t const line = mrb_debug_get_line(irep, (uint32_t)(err - irep->iseq));
    211       char const* file = mrb_debug_get_filename(irep, (uint32_t)(err - irep->iseq));
    212       if (line != -1 && file) {
    213         mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "file"), mrb_str_new_cstr(mrb, file));
    214         mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "line"), mrb_fixnum_value(line));
    215         return;
    216       }
    217     }
    218     pc = ci->pc;
    219     ci--;
    220   }
    221 }
    222 
    223170void
    224171mrb_exc_set(mrb_state *mrb, mrb_value exc)
     
    229176  else {
    230177    mrb->exc = mrb_obj_ptr(exc);
    231     if (!mrb->gc.out_of_memory) {
    232       exc_debug_info(mrb, mrb->exc);
     178    if (mrb->gc.arena_idx > 0 &&
     179        (struct RBasic*)mrb->exc == mrb->gc.arena[mrb->gc.arena_idx-1]) {
     180      mrb->gc.arena_idx--;
     181    }
     182    if (!mrb->gc.out_of_memory && !mrb_frozen_p(mrb->exc)) {
    233183      mrb_keep_backtrace(mrb, exc);
    234184    }
     
    239189mrb_exc_raise(mrb_state *mrb, mrb_value exc)
    240190{
    241   if (!mrb_obj_is_kind_of(mrb, exc, mrb->eException_class)) {
    242     mrb_raise(mrb, E_TYPE_ERROR, "exception object expected");
    243   }
    244   mrb_exc_set(mrb, exc);
     191  if (mrb_break_p(exc)) {
     192    mrb->exc = mrb_obj_ptr(exc);
     193  }
     194  else {
     195    if (!mrb_obj_is_kind_of(mrb, exc, mrb->eException_class)) {
     196      mrb_raise(mrb, E_TYPE_ERROR, "exception object expected");
     197    }
     198    mrb_exc_set(mrb, exc);
     199  }
    245200  if (!mrb->jmp) {
    246201    mrb_p(mrb, exc);
     
    256211}
    257212
     213/*
     214 * <code>vsprintf</code> like formatting.
     215 *
     216 * The syntax of a format sequence is as follows.
     217 *
     218 *   %[modifier]specifier
     219 *
     220 * The modifiers are:
     221 *
     222 *   ----------+------------------------------------------------------------
     223 *   Modifier  | Meaning
     224 *   ----------+------------------------------------------------------------
     225 *       !     | Convert to string by corresponding `inspect` instead of
     226 *             | corresponding `to_s`.
     227 *   ----------+------------------------------------------------------------
     228 *
     229 * The specifiers are:
     230 *
     231 *   ----------+----------------+--------------------------------------------
     232 *   Specifier | Argument Type  | Note
     233 *   ----------+----------------+--------------------------------------------
     234 *       c     | char           |
     235 *       d     | int            |
     236 *       f     | mrb_float      |
     237 *       i     | mrb_int        |
     238 *       l     | char*, size_t  | Arguments are string and length.
     239 *       n     | mrb_sym        |
     240 *       s     | char*          | Argument is NUL terminated string.
     241 *       t     | mrb_value      | Convert to type (class) of object.
     242 *      v,S    | mrb_value      |
     243 *       C     | struct RClass* |
     244 *       T     | mrb_value      | Convert to real type (class) of object.
     245 *       Y     | mrb_value      | Same as `!v` if argument is `true`, `false`
     246 *             |                | or `nil`, otherwise same as `T`.
     247 *       %     | -              | Convert to percent sign itself (no argument
     248 *             |                | taken).
     249 *   ----------+----------------+--------------------------------------------
     250 */
    258251MRB_API mrb_value
    259252mrb_vformat(mrb_state *mrb, const char *format, va_list ap)
    260253{
    261   const char *p = format;
    262   const char *b = p;
    263   ptrdiff_t size;
    264   mrb_value ary = mrb_ary_new_capa(mrb, 4);
     254  const char *chars, *p = format, *b = format, *e;
     255  char ch;
     256  size_t len;
     257  mrb_int i;
     258  struct RClass *cls;
     259  mrb_bool inspect = FALSE;
     260  mrb_value result = mrb_str_new_capa(mrb, 128), obj, str;
    265261  int ai = mrb_gc_arena_save(mrb);
    266262
    267263  while (*p) {
    268264    const char c = *p++;
    269 
     265    e = p;
    270266    if (c == '%') {
    271       if (*p == 'S') {
    272         size = p - b - 1;
    273         mrb_ary_push(mrb, ary, mrb_str_new(mrb, b, size));
    274         mrb_ary_push(mrb, ary, va_arg(ap, mrb_value));
    275         b = p + 1;
     267      if (*p == '!') {
     268        inspect = TRUE;
     269        ++p;
    276270      }
     271      if (!*p) break;
     272      switch (*p) {
     273        case 'c':
     274          ch = (char)va_arg(ap, int);
     275          chars = &ch;
     276          len = 1;
     277          goto L_cat;
     278        case 'd': case 'i':
     279#if MRB_INT_MAX < INT_MAX
     280          i = (mrb_int)va_arg(ap, int);
     281#else
     282          i = *p == 'd' ? (mrb_int)va_arg(ap, int) : va_arg(ap, mrb_int);
     283#endif
     284          obj = mrb_fixnum_value(i);
     285          goto L_cat_obj;
     286#ifndef MRB_WITHOUT_FLOAT
     287        case 'f':
     288          obj = mrb_float_value(mrb, (mrb_float)va_arg(ap, double));
     289          goto L_cat_obj;
     290#endif
     291        case 'l':
     292          chars = va_arg(ap, char*);
     293          len = va_arg(ap, size_t);
     294        L_cat:
     295          if (inspect) {
     296            obj = mrb_str_new(mrb, chars, len);
     297            goto L_cat_obj;
     298          }
     299          mrb_str_cat(mrb, result, b,  e - b - 1);
     300          mrb_str_cat(mrb, result, chars, len);
     301          b = ++p;
     302          mrb_gc_arena_restore(mrb, ai);
     303          break;
     304        case 'n':
     305#if UINT32_MAX < INT_MAX
     306          obj = mrb_symbol_value((mrb_sym)va_arg(ap, int));
     307#else
     308          obj = mrb_symbol_value(va_arg(ap, mrb_sym));
     309#endif
     310          goto L_cat_obj;
     311        case 's':
     312          chars = va_arg(ap, char*);
     313          len = strlen(chars);
     314          goto L_cat;
     315        case 't':
     316          cls = mrb_class(mrb, va_arg(ap, mrb_value));
     317          goto L_cat_class;
     318        case 'v': case 'S':
     319          obj = va_arg(ap, mrb_value);
     320        L_cat_obj:
     321          str = (inspect ? mrb_inspect : mrb_obj_as_string)(mrb, obj);
     322          chars = RSTRING_PTR(str);
     323          len = RSTRING_LEN(str);
     324          inspect = FALSE;
     325          goto L_cat;
     326        case 'C':
     327          cls = va_arg(ap, struct RClass*);
     328        L_cat_class:
     329          obj = mrb_obj_value(cls);
     330          goto L_cat_obj;
     331        case 'T':
     332          obj = va_arg(ap, mrb_value);
     333        L_cat_real_class_of:
     334          cls = mrb_obj_class(mrb, obj);
     335          goto L_cat_class;
     336        case 'Y':
     337          obj = va_arg(ap, mrb_value);
     338          if (!mrb_test(obj) || mrb_true_p(obj)) {
     339            inspect = TRUE;
     340            goto L_cat_obj;
     341          }
     342          else {
     343            goto L_cat_real_class_of;
     344          }
     345        case '%':
     346        L_cat_current:
     347          chars = p;
     348          len = 1;
     349          goto L_cat;
     350        default:
     351          mrb_raisef(mrb, E_ARGUMENT_ERROR, "malformed format string - %%%c", *p);
     352      }
    277353    }
    278354    else if (c == '\\') {
    279       if (*p) {
    280         size = p - b - 1;
    281         mrb_ary_push(mrb, ary, mrb_str_new(mrb, b, size));
    282         mrb_ary_push(mrb, ary, mrb_str_new(mrb, p, 1));
    283         b = ++p;
    284       }
    285       else {
    286         break;
    287       }
    288     }
    289     mrb_gc_arena_restore(mrb, ai);
    290   }
    291   if (b == format) {
    292     return mrb_str_new_cstr(mrb, format);
    293   }
    294   else {
    295     size = p - b;
    296     if (size > 0) {
    297       mrb_ary_push(mrb, ary, mrb_str_new(mrb, b, size));
    298       mrb_gc_arena_restore(mrb, ai);
    299     }
    300     return mrb_ary_join(mrb, ary, mrb_nil_value());
    301   }
     355      if (!*p) break;
     356      goto L_cat_current;
     357
     358    }
     359  }
     360
     361  mrb_str_cat(mrb, result, b, p - b);
     362  return result;
    302363}
    303364
     
    319380{
    320381  mrb_value mesg;
     382  static int called = 0;
    321383
    322384  mesg = mrb_vformat(mrb, fmt, ap);
     
    327389    argv[0] = mesg;
    328390  }
     391  if (called)
     392    mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
     393  called = 1;
    329394  mrb_exc_raise(mrb, mrb_obj_new(mrb, c, argc+1, argv));
    330395}
     
    363428  fputs("warning: ", stderr);
    364429  fwrite(RSTRING_PTR(str), RSTRING_LEN(str), 1, stderr);
     430  putc('\n', stderr);
    365431  va_end(ap);
    366432#endif
     
    384450
    385451MRB_API mrb_value
    386 mrb_make_exception(mrb_state *mrb, int argc, const mrb_value *argv)
     452mrb_make_exception(mrb_state *mrb, mrb_int argc, const mrb_value *argv)
    387453{
    388454  mrb_value mesg;
     
    420486      break;
    421487    default:
    422       mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 0..3)", mrb_fixnum_value(argc));
     488      mrb_argnum_error(mrb, argc, 0, 3);
    423489      break;
    424490  }
     
    470536}
    471537
     538MRB_API mrb_noreturn void
     539mrb_frozen_error(mrb_state *mrb, void *frozen_obj)
     540{
     541  mrb_raisef(mrb, E_FROZEN_ERROR, "can't modify frozen %t", mrb_obj_value(frozen_obj));
     542}
     543
     544MRB_API mrb_noreturn void
     545mrb_argnum_error(mrb_state *mrb, mrb_int argc, int min, int max)
     546{
     547#define FMT(exp) "wrong number of arguments (given %i, expected " exp ")"
     548  if (min == max)
     549    mrb_raisef(mrb, E_ARGUMENT_ERROR, FMT("%d"), argc, min);
     550  else if (max < 0)
     551    mrb_raisef(mrb, E_ARGUMENT_ERROR, FMT("%d+"), argc, min);
     552  else
     553    mrb_raisef(mrb, E_ARGUMENT_ERROR, FMT("%d..%d"), argc, min, max);
     554#undef FMT
     555}
     556
    472557void
    473558mrb_init_exception(mrb_state *mrb)
     
    477562  mrb->eException_class = exception = mrb_define_class(mrb, "Exception", mrb->object_class); /* 15.2.22 */
    478563  MRB_SET_INSTANCE_TT(exception, MRB_TT_EXCEPTION);
    479   mrb_define_class_method(mrb, exception, "exception", mrb_instance_new,  MRB_ARGS_ANY());
    480   mrb_define_method(mrb, exception, "exception",       exc_exception,     MRB_ARGS_ANY());
    481   mrb_define_method(mrb, exception, "initialize",      exc_initialize,    MRB_ARGS_ANY());
     564  mrb_define_class_method(mrb, exception, "exception", mrb_instance_new,  MRB_ARGS_OPT(1));
     565  mrb_define_method(mrb, exception, "exception",       exc_exception,     MRB_ARGS_OPT(1));
     566  mrb_define_method(mrb, exception, "initialize",      exc_initialize,    MRB_ARGS_OPT(1));
    482567  mrb_define_method(mrb, exception, "to_s",            exc_to_s,          MRB_ARGS_NONE());
    483568  mrb_define_method(mrb, exception, "message",         exc_message,       MRB_ARGS_NONE());
    484   mrb_define_method(mrb, exception, "inspect",         exc_inspect,       MRB_ARGS_NONE());
     569  mrb_define_method(mrb, exception, "inspect",         mrb_exc_inspect,   MRB_ARGS_NONE());
    485570  mrb_define_method(mrb, exception, "backtrace",       mrb_exc_backtrace, MRB_ARGS_NONE());
    486571  mrb_define_method(mrb, exception, "set_backtrace",   exc_set_backtrace, MRB_ARGS_REQ(1));
  • EcnlProtoTool/trunk/mruby-2.1.1/src/etc.c

    r331 r439  
    11/*
    2 ** etc.c -
     2** etc.c
    33**
    44** See Copyright Notice in mruby.h
     
    99#include <mruby/data.h>
    1010#include <mruby/class.h>
    11 #include <mruby/re.h>
    12 #include <mruby/irep.h>
    1311
    1412MRB_API struct RData*
     
    2725mrb_data_check_type(mrb_state *mrb, mrb_value obj, const mrb_data_type *type)
    2826{
    29   if (mrb_type(obj) != MRB_TT_DATA) {
     27  if (!mrb_data_p(obj)) {
    3028    mrb_check_type(mrb, obj, MRB_TT_DATA);
    3129  }
     
    3432
    3533    if (t2) {
    36       mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected %S)",
    37                  mrb_str_new_cstr(mrb, t2->struct_name), mrb_str_new_cstr(mrb, type->struct_name));
     34      mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %s (expected %s)",
     35                 t2->struct_name, type->struct_name);
    3836    }
    3937    else {
    40       struct RClass *c = mrb_class(mrb, obj);
    41 
    42       mrb_raisef(mrb, E_TYPE_ERROR, "uninitialized %S (expected %S)",
    43                  mrb_obj_value(c), mrb_str_new_cstr(mrb, type->struct_name));
     38      mrb_raisef(mrb, E_TYPE_ERROR, "uninitialized %t (expected %s)",
     39                 obj, type->struct_name);
    4440    }
    4541  }
     
    4945mrb_data_check_get_ptr(mrb_state *mrb, mrb_value obj, const mrb_data_type *type)
    5046{
    51   if (mrb_type(obj) != MRB_TT_DATA) {
     47  if (!mrb_data_p(obj)) {
    5248    return NULL;
    5349  }
     
    6864mrb_obj_to_sym(mrb_state *mrb, mrb_value name)
    6965{
    70   mrb_sym id;
    71 
    72   switch (mrb_type(name)) {
    73     default:
    74       name = mrb_check_string_type(mrb, name);
    75       if (mrb_nil_p(name)) {
    76         name = mrb_inspect(mrb, name);
    77         mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", name);
    78       }
    79       /* fall through */
    80     case MRB_TT_STRING:
    81       name = mrb_str_intern(mrb, name);
    82       /* fall through */
    83     case MRB_TT_SYMBOL:
    84       id = mrb_symbol(name);
    85   }
    86   return id;
     66  if (mrb_symbol_p(name)) return mrb_symbol(name);
     67  if (mrb_string_p(name)) return mrb_intern_str(mrb, name);
     68  mrb_raisef(mrb, E_TYPE_ERROR, "%!v is not a symbol nor a string", name);
     69  return 0;  /* not reached */
    8770}
    8871
    8972MRB_API mrb_int
     73#ifdef MRB_WITHOUT_FLOAT
     74mrb_fixnum_id(mrb_int f)
     75#else
    9076mrb_float_id(mrb_float f)
     77#endif
    9178{
    9279  const char *p = (const char*)&f;
    9380  int len = sizeof(f);
    94   mrb_int id = 0;
    95 
     81  uint32_t id = 0;
     82
     83#ifndef MRB_WITHOUT_FLOAT
     84  /* normalize -0.0 to 0.0 */
     85  if (f == 0) f = 0.0;
     86#endif
    9687  while (len--) {
    9788    id = id*65599 + *p;
     
    10091  id = id + (id>>5);
    10192
    102   return id;
     93  return (mrb_int)id;
    10394}
    10495
     
    124115    return MakeID(mrb_symbol(obj));
    125116  case MRB_TT_FIXNUM:
     117#ifdef MRB_WITHOUT_FLOAT
     118    return MakeID(mrb_fixnum_id(mrb_fixnum(obj)));
     119#else
    126120    return MakeID2(mrb_float_id((mrb_float)mrb_fixnum(obj)), MRB_TT_FLOAT);
    127121  case MRB_TT_FLOAT:
    128122    return MakeID(mrb_float_id(mrb_float(obj)));
     123#endif
    129124  case MRB_TT_STRING:
    130125  case MRB_TT_OBJECT:
     
    147142
    148143#ifdef MRB_WORD_BOXING
     144#ifndef MRB_WITHOUT_FLOAT
    149145MRB_API mrb_value
    150146mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f)
     
    154150  v.value.p = mrb_obj_alloc(mrb, MRB_TT_FLOAT, mrb->float_class);
    155151  v.value.fp->f = f;
     152  MRB_SET_FROZEN_FLAG(v.value.bp);
    156153  return v;
    157154}
     
    164161  nf->c = mrb->float_class;
    165162  nf->f = f;
     163  MRB_SET_FROZEN_FLAG(nf);
    166164  return mrb_obj_value(nf);
    167165}
     166#endif  /* MRB_WITHOUT_FLOAT */
    168167
    169168MRB_API mrb_value
     
    177176}
    178177#endif  /* MRB_WORD_BOXING */
    179 
    180 MRB_API mrb_bool
    181 mrb_regexp_p(mrb_state *mrb, mrb_value v)
    182 {
    183   if (mrb->flags & MRB_STATE_NO_REGEXP) {
    184     return FALSE;
    185   }
    186   if ((mrb->flags & MRB_STATE_REGEXP) || mrb_class_defined(mrb, REGEXP_CLASS)) {
    187     mrb->flags |= MRB_STATE_REGEXP;
    188     return mrb_obj_is_kind_of(mrb, v, mrb_class_get(mrb, REGEXP_CLASS));
    189   }
    190   else {
    191     mrb->flags |= MRB_STATE_REGEXP;
    192     mrb->flags |= MRB_STATE_NO_REGEXP;
    193   }
    194   return FALSE;
    195 }
    196178
    197179#if defined _MSC_VER && _MSC_VER < 1900
  • EcnlProtoTool/trunk/mruby-2.1.1/src/fmt_fp.c

    r331 r439  
     1#ifndef MRB_WITHOUT_FLOAT
     2#if defined(MRB_DISABLE_STDIO) || defined(_WIN32) || defined(_WIN64)
    13/*
    24
     
    2931#include <limits.h>
    3032#include <string.h>
    31 #include <stdint.h>
    3233#include <math.h>
    3334#include <float.h>
     
    6263#define PAD_SIZE 256
    6364static void
    64 pad(struct fmt_args *f, char c, int w, int l, int fl)
     65pad(struct fmt_args *f, char c, ptrdiff_t w, ptrdiff_t l, uint8_t fl)
    6566{
    6667  char pad[PAD_SIZE];
     
    9293
    9394static int
    94 fmt_fp(struct fmt_args *f, long double y, int w, int p, int fl, int t)
     95fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
    9596{
    9697  uint32_t big[(LDBL_MANT_DIG+28)/29 + 1          // mantissa expansion
     
    9899  uint32_t *a, *d, *r, *z;
    99100  uint32_t i;
    100   int e2=0, e, j, l;
     101  int e2=0, e, j;
     102  ptrdiff_t l;
    101103  char buf[9+LDBL_MANT_DIG/4], *s;
    102104  const char *prefix="-0X+0X 0X-0x+0x 0x";
    103   int pl;
     105  ptrdiff_t pl;
    104106  char ebuf0[3*sizeof(int)], *ebuf=&ebuf0[3*sizeof(int)], *estr;
    105107
     
    116118    const char *ss = (t&32)?"inf":"INF";
    117119    if (y!=y) ss=(t&32)?"nan":"NAN";
    118     pad(f, ' ', w, 3+pl, fl&~ZERO_PAD);
     120    pad(f, ' ', 0, 3+pl, fl&~ZERO_PAD);
    119121    out(f, prefix, pl);
    120122    out(f, ss, 3);
    121     pad(f, ' ', w, 3+pl, fl^LEFT_ADJ);
    122     return MAX(w, 3+pl);
     123    pad(f, ' ', 0, 3+pl, fl^LEFT_ADJ);
     124    return 3+(int)pl;
    123125  }
    124126
     
    128130  if ((t|32)=='a') {
    129131    long double round = 8.0;
    130     int re;
     132    ptrdiff_t re;
    131133
    132134    if (t&32) prefix += 9;
     
    168170      l = (s-buf) + (ebuf-estr);
    169171
    170     pad(f, ' ', w, pl+l, fl);
     172    pad(f, ' ', 0, pl+l, fl);
    171173    out(f, prefix, pl);
    172     pad(f, '0', w, pl+l, fl^ZERO_PAD);
     174    pad(f, '0', 0, pl+l, fl^ZERO_PAD);
    173175    out(f, buf, s-buf);
    174176    pad(f, '0', l-(ebuf-estr)-(s-buf), 0, 0);
    175177    out(f, estr, ebuf-estr);
    176     pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
    177     return MAX(w, pl+l);
     178    pad(f, ' ', 0, pl+l, fl^LEFT_ADJ);
     179    return (int)pl+(int)l;
    178180  }
    179181  if (p<0) p=6;
     
    203205  while (e2<0) {
    204206    uint32_t carry=0, *b;
    205     int sh=MIN(9,-e2), need=1+(p+LDBL_MANT_DIG/3+8)/9;
     207    int sh=MIN(9,-e2), need=1+((int)p+LDBL_MANT_DIG/3+8)/9;
    206208    for (d=a; d<z; d++) {
    207209      uint32_t rm = *d & ((1<<sh)-1);
     
    217219  }
    218220
    219   if (a<z) for (i=10, e=9*(r-a); *a>=i; i*=10, e++);
     221  if (a<z) for (i=10, e=9*(int)(r-a); *a>=i; i*=10, e++);
    220222  else e=0;
    221223
    222224  /* Perform rounding: j is precision after the radix (possibly neg) */
    223   j = p - ((t|32)!='f')*e - ((t|32)=='g' && p);
     225  j = (int)p - ((t|32)!='f')*e - ((t|32)=='g' && p);
    224226  if (j < 9*(z-r-1)) {
    225227    uint32_t x;
     
    248250          (*d)++;
    249251        }
    250         for (i=10, e=9*(r-a); *a>=i; i*=10, e++);
     252        for (i=10, e=9*(int)(r-a); *a>=i; i*=10, e++);
    251253      }
    252254    }
     
    287289  }
    288290
    289   pad(f, ' ', w, pl+l, fl);
     291  pad(f, ' ', 0, pl+l, fl);
    290292  out(f, prefix, pl);
    291   pad(f, '0', w, pl+l, fl^ZERO_PAD);
     293  pad(f, '0', 0, pl+l, fl^ZERO_PAD);
    292294
    293295  if ((t|32)=='f') {
     
    318320      }
    319321      out(f, ss, MIN(buf+9-ss, p));
    320       p -= buf+9-ss;
     322      p -= (int)(buf+9-ss);
    321323    }
    322324    pad(f, '0', p+18, 18, 0);
     
    324326  }
    325327
    326   pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
    327 
    328   return MAX(w, pl+l);
     328  pad(f, ' ', 0, pl+l, fl^LEFT_ADJ);
     329
     330  return (int)pl+(int)l;
    329331}
    330332
     
    332334fmt_core(struct fmt_args *f, const char *fmt, mrb_float flo)
    333335{
    334   int p;
     336  ptrdiff_t p;
    335337
    336338  if (*fmt != '%') {
     
    352354  case 'e': case 'f': case 'g': case 'a':
    353355  case 'E': case 'F': case 'G': case 'A':
    354     return fmt_fp(f, flo, 0, p, 0, *fmt);
     356    return fmt_fp(f, flo, p, 0, *fmt);
    355357  default:
    356358    return -1;
     
    364366
    365367  f.mrb = mrb;
    366   f.str = mrb_str_buf_new(mrb, 24);
     368  f.str = mrb_str_new_capa(mrb, 24);
    367369  if (fmt_core(&f, fmt, mrb_float(flo)) < 0) {
    368370    mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format string");
     
    370372  return f.str;
    371373}
     374#else   /* MRB_DISABLE_STDIO || _WIN32 || _WIN64 */
     375#include <mruby.h>
     376#include <stdio.h>
     377
     378mrb_value
     379mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt)
     380{
     381  char buf[25];
     382
     383  snprintf(buf, sizeof(buf), fmt, mrb_float(flo));
     384  return mrb_str_new_cstr(mrb, buf);
     385}
     386#endif  /* MRB_DISABLE_STDIO || _WIN32 || _WIN64 */
     387#endif
  • EcnlProtoTool/trunk/mruby-2.1.1/src/gc.c

    r331 r439  
    1111#include <mruby/class.h>
    1212#include <mruby/data.h>
     13#include <mruby/istruct.h>
    1314#include <mruby/hash.h>
    1415#include <mruby/proc.h>
     
    110111    struct RRange range;
    111112    struct RData data;
     113    struct RIStruct istruct;
    112114    struct RProc proc;
    113115    struct REnv env;
     116    struct RFiber fiber;
    114117    struct RException exc;
    115118    struct RBreak brk;
    116119#ifdef MRB_WORD_BOXING
     120#ifndef MRB_WITHOUT_FLOAT
    117121    struct RFloat floatv;
     122#endif
    118123    struct RCptr cptr;
    119124#endif
     
    176181#define GC_STEP_SIZE 1024
    177182
    178 /* white: 011, black: 100, gray: 000 */
     183/* white: 001 or 010, black: 100, gray: 000 */
    179184#define GC_GRAY 0
    180185#define GC_WHITE_A 1
     
    273278}
    274279
     280MRB_API void*
     281mrb_alloca(mrb_state *mrb, size_t size)
     282{
     283  struct RString *s;
     284  s = (struct RString*)mrb_obj_alloc(mrb, MRB_TT_STRING, mrb->string_class);
     285  return s->as.heap.ptr = (char*)mrb_malloc(mrb, size);
     286}
     287
     288static mrb_bool
     289heap_p(mrb_gc *gc, struct RBasic *object)
     290{
     291  mrb_heap_page* page;
     292
     293  page = gc->heaps;
     294  while (page) {
     295    RVALUE *p;
     296
     297    p = objects(page);
     298    if (&p[0].as.basic <= object && object <= &p[MRB_HEAP_PAGE_SIZE].as.basic) {
     299      return TRUE;
     300    }
     301    page = page->next;
     302  }
     303  return FALSE;
     304}
     305
    275306MRB_API mrb_bool
    276307mrb_object_dead_p(mrb_state *mrb, struct RBasic *object) {
    277   return is_dead(&mrb->gc, object);
     308  mrb_gc *gc = &mrb->gc;
     309  if (!heap_p(gc, object)) return TRUE;
     310  return is_dead(gc, object);
    278311}
    279312
     
    343376#define DEFAULT_GC_INTERVAL_RATIO 200
    344377#define DEFAULT_GC_STEP_RATIO 200
    345 #define DEFAULT_MAJOR_GC_INC_RATIO 200
     378#define MAJOR_GC_INC_RATIO 120
     379#define MAJOR_GC_TOOMANY 10000
    346380#define is_generational(gc) ((gc)->generational)
    347381#define is_major_gc(gc) (is_generational(gc) && (gc)->full)
     
    374408static void obj_free(mrb_state *mrb, struct RBasic *obj, int end);
    375409
    376 void
     410static void
    377411free_heap(mrb_state *mrb, mrb_gc *gc)
    378412{
     
    413447  if (gc->arena_idx >= gc->arena_capa) {
    414448    /* extend arena */
    415     gc->arena_capa = (int)(gc->arena_capa * 1.5);
     449    gc->arena_capa = (int)(gc->arena_capa * 3 / 2);
    416450    gc->arena = (struct RBasic**)mrb_realloc(mrb, gc->arena, sizeof(struct RBasic*)*gc->arena_capa);
    417451  }
     
    441475mrb_gc_register(mrb_state *mrb, mrb_value obj)
    442476{
    443   mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME);
    444   mrb_value table = mrb_gv_get(mrb, root);
    445 
    446   if (mrb_nil_p(table) || mrb_type(table) != MRB_TT_ARRAY) {
     477  mrb_sym root;
     478  mrb_value table;
     479
     480  if (mrb_immediate_p(obj)) return;
     481  root = mrb_intern_lit(mrb, GC_ROOT_NAME);
     482  table = mrb_gv_get(mrb, root);
     483  if (mrb_nil_p(table) || !mrb_array_p(table)) {
    447484    table = mrb_ary_new(mrb);
    448485    mrb_gv_set(mrb, root, table);
     
    455492mrb_gc_unregister(mrb_state *mrb, mrb_value obj)
    456493{
    457   mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME);
    458   mrb_value table = mrb_gv_get(mrb, root);
     494  mrb_sym root;
     495  mrb_value table;
    459496  struct RArray *a;
    460497  mrb_int i;
    461498
     499  if (mrb_immediate_p(obj)) return;
     500  root = mrb_intern_lit(mrb, GC_ROOT_NAME);
     501  table = mrb_gv_get(mrb, root);
    462502  if (mrb_nil_p(table)) return;
    463   if (mrb_type(table) != MRB_TT_ARRAY) {
     503  if (!mrb_array_p(table)) {
    464504    mrb_gv_set(mrb, root, mrb_nil_value());
    465505    return;
     
    467507  a = mrb_ary_ptr(table);
    468508  mrb_ary_modify(mrb, a);
    469   for (i = 0; i < a->len; i++) {
    470     if (mrb_obj_eq(mrb, a->ptr[i], obj)) {
    471       a->len--;
    472       memmove(&a->ptr[i], &a->ptr[i + 1], (a->len - i) * sizeof(a->ptr[i]));
     509  for (i = 0; i < ARY_LEN(a); i++) {
     510    if (mrb_ptr(ARY_PTR(a)[i]) == mrb_ptr(obj)) {
     511      mrb_int len = ARY_LEN(a)-1;
     512      mrb_value *ptr = ARY_PTR(a);
     513
     514      ARY_SET_LEN(a, len);
     515      memmove(&ptr[i], &ptr[i + 1], (len - i) * sizeof(mrb_value));
    473516      break;
    474517    }
     
    480523{
    481524  struct RBasic *p;
    482   static const RVALUE RVALUE_zero = { { { MRB_TT_FALSE } } };
     525  static const RVALUE RVALUE_zero = { { { NULL, NULL, MRB_TT_FALSE } } };
    483526  mrb_gc *gc = &mrb->gc;
    484527
     
    501544        ttype != MRB_TT_ENV &&
    502545        ttype != tt) {
    503       mrb_raisef(mrb, E_TYPE_ERROR, "allocation failure of %S", mrb_obj_value(cls));
     546      mrb_raisef(mrb, E_TYPE_ERROR, "allocation failure of %C", cls);
    504547    }
    505548  }
     
    543586}
    544587
     588static int
     589ci_nregs(mrb_callinfo *ci)
     590{
     591  struct RProc *p = ci->proc;
     592  int n = 0;
     593
     594  if (!p) {
     595    if (ci->argc < 0) return 3;
     596    return ci->argc+2;
     597  }
     598  if (!MRB_PROC_CFUNC_P(p) && p->body.irep) {
     599    n = p->body.irep->nregs;
     600  }
     601  if (ci->argc < 0) {
     602    if (n < 3) n = 3; /* self + args + blk */
     603  }
     604  if (ci->argc > n) {
     605    n = ci->argc + 2; /* self + blk */
     606  }
     607  return n;
     608}
     609
    545610static void
    546611mark_context_stack(mrb_state *mrb, struct mrb_context *c)
     
    549614  size_t e;
    550615  mrb_value nil;
    551   int nregs;
    552616
    553617  if (c->stack == NULL) return;
    554618  e = c->stack - c->stbase;
    555619  if (c->ci) {
    556     nregs = c->ci->argc + 2;
    557     if (c->ci->nregs > nregs)
    558       nregs = c->ci->nregs;
    559     e += nregs;
     620    e += ci_nregs(c->ci);
    560621  }
    561622  if (c->stbase + e > c->stend) e = c->stend - c->stbase;
     
    579640  int i;
    580641  mrb_callinfo *ci;
     642
     643 start:
     644  if (c->status == MRB_FIBER_TERMINATED) return;
    581645
    582646  /* mark VM stack */
     
    592656  }
    593657  /* mark ensure stack */
    594   for (i=0; i<c->esize; i++) {
    595     if (c->ensure[i] == NULL) break;
     658  for (i=0; i<c->eidx; i++) {
    596659    mrb_gc_mark(mrb, (struct RBasic*)c->ensure[i]);
    597660  }
     
    599662  mrb_gc_mark(mrb, (struct RBasic*)c->fib);
    600663  if (c->prev) {
    601     mark_context(mrb, c->prev);
     664    c = c->prev;
     665    goto start;
    602666  }
    603667}
     
    614678    {
    615679      struct RClass *c = (struct RClass*)obj;
    616       if (MRB_FLAG_TEST(c, MRB_FLAG_IS_ORIGIN))
     680      if (MRB_FLAG_TEST(c, MRB_FL_CLASS_IS_ORIGIN))
    617681        mrb_gc_mark_mt(mrb, c);
    618682      mrb_gc_mark(mrb, (struct RBasic*)((struct RClass*)obj)->super);
     
    641705      struct RProc *p = (struct RProc*)obj;
    642706
    643       mrb_gc_mark(mrb, (struct RBasic*)p->env);
    644       mrb_gc_mark(mrb, (struct RBasic*)p->target_class);
     707      mrb_gc_mark(mrb, (struct RBasic*)p->upper);
     708      mrb_gc_mark(mrb, (struct RBasic*)p->e.env);
    645709    }
    646710    break;
     
    651715      mrb_int i, len;
    652716
    653       if (MRB_ENV_STACK_SHARED_P(e)) {
    654         if (e->cxt.c->fib) {
    655           mrb_gc_mark(mrb, (struct RBasic*)e->cxt.c->fib);
    656         }
    657         break;
     717      if (MRB_ENV_STACK_SHARED_P(e) && e->cxt && e->cxt->fib) {
     718        mrb_gc_mark(mrb, (struct RBasic*)e->cxt->fib);
    658719      }
    659720      len = MRB_ENV_STACK_LEN(e);
     
    677738      size_t i, e;
    678739
    679       for (i=0,e=a->len; i<e; i++) {
    680         mrb_gc_mark_value(mrb, a->ptr[i]);
     740      for (i=0,e=ARY_LEN(a); i<e; i++) {
     741        mrb_gc_mark_value(mrb, ARY_PTR(a)[i]);
    681742      }
    682743    }
     
    689750
    690751  case MRB_TT_STRING:
     752    if (RSTR_FSHARED_P(obj)) {
     753      struct RString *s = (struct RString*)obj;
     754      mrb_gc_mark(mrb, (struct RBasic*)s->as.heap.aux.fshared);
     755    }
    691756    break;
    692757
    693758  case MRB_TT_RANGE:
    694     {
    695       struct RRange *r = (struct RRange*)obj;
    696 
    697       if (r->edges) {
    698         mrb_gc_mark_value(mrb, r->edges->beg);
    699         mrb_gc_mark_value(mrb, r->edges->end);
    700       }
    701     }
     759    mrb_gc_mark_range(mrb, (struct RRange*)obj);
    702760    break;
    703761
     
    728786    return;
    729787
     788#ifndef MRB_WITHOUT_FLOAT
    730789  case MRB_TT_FLOAT:
    731790#ifdef MRB_WORD_BOXING
     
    733792#else
    734793    return;
     794#endif
    735795#endif
    736796
     
    748808    mrb_gc_free_mt(mrb, (struct RClass*)obj);
    749809    mrb_gc_free_iv(mrb, (struct RObject*)obj);
     810    mrb_mc_clear_by_class(mrb, (struct RClass*)obj);
    750811    break;
    751812  case MRB_TT_ICLASS:
    752     if (MRB_FLAG_TEST(obj, MRB_FLAG_IS_ORIGIN))
     813    if (MRB_FLAG_TEST(obj, MRB_FL_CLASS_IS_ORIGIN))
    753814      mrb_gc_free_mt(mrb, (struct RClass*)obj);
     815    mrb_mc_clear_by_class(mrb, (struct RClass*)obj);
    754816    break;
    755817  case MRB_TT_ENV:
     
    759821      if (MRB_ENV_STACK_SHARED_P(e)) {
    760822        /* cannot be freed */
    761         return;
     823        e->stack = NULL;
     824        break;
    762825      }
    763826      mrb_free(mrb, e->stack);
     
    770833      struct mrb_context *c = ((struct RFiber*)obj)->cxt;
    771834
    772       if (!end && c && c != mrb->root_c) {
    773         mrb_callinfo *ci = c->ci;
    774         mrb_callinfo *ce = c->cibase;
    775 
    776         while (ce <= ci) {
    777           struct REnv *e = ci->env;
    778           if (e && !is_dead(&mrb->gc, e) &&
    779               e->tt == MRB_TT_ENV && MRB_ENV_STACK_SHARED_P(e)) {
    780             mrb_env_unshare(mrb, e);
     835      if (c && c != mrb->root_c) {
     836        if (!end && c->status != MRB_FIBER_TERMINATED) {
     837          mrb_callinfo *ci = c->ci;
     838          mrb_callinfo *ce = c->cibase;
     839
     840          while (ce <= ci) {
     841            struct REnv *e = ci->env;
     842            if (e && !mrb_object_dead_p(mrb, (struct RBasic*)e) &&
     843                e->tt == MRB_TT_ENV && MRB_ENV_STACK_SHARED_P(e)) {
     844              mrb_env_unshare(mrb, e);
     845            }
     846            ci--;
    781847          }
    782           ci--;
    783848        }
    784849        mrb_free_context(mrb, c);
     
    789854  case MRB_TT_ARRAY:
    790855    if (ARY_SHARED_P(obj))
    791       mrb_ary_decref(mrb, ((struct RArray*)obj)->aux.shared);
    792     else
    793       mrb_free(mrb, ((struct RArray*)obj)->ptr);
     856      mrb_ary_decref(mrb, ((struct RArray*)obj)->as.heap.aux.shared);
     857    else if (!ARY_EMBED_P(obj))
     858      mrb_free(mrb, ((struct RArray*)obj)->as.heap.ptr);
    794859    break;
    795860
     
    808873
    809874      if (!MRB_PROC_CFUNC_P(p) && p->body.irep) {
    810         mrb_irep_decref(mrb, p->body.irep);
     875        mrb_irep *irep = p->body.irep;
     876        if (end) {
     877          mrb_irep_cutref(mrb, irep);
     878        }
     879        mrb_irep_decref(mrb, irep);
    811880      }
    812881    }
     
    814883
    815884  case MRB_TT_RANGE:
    816     mrb_free(mrb, ((struct RRange*)obj)->edges);
     885    mrb_gc_free_range(mrb, ((struct RRange*)obj));
    817886    break;
    818887
     
    858927  mrb_gc_mark(mrb, (struct RBasic*)mrb->array_class);
    859928  mrb_gc_mark(mrb, (struct RBasic*)mrb->hash_class);
    860 
     929  mrb_gc_mark(mrb, (struct RBasic*)mrb->range_class);
     930
     931#ifndef MRB_WITHOUT_FLOAT
    861932  mrb_gc_mark(mrb, (struct RBasic*)mrb->float_class);
     933#endif
    862934  mrb_gc_mark(mrb, (struct RBasic*)mrb->fixnum_class);
    863935  mrb_gc_mark(mrb, (struct RBasic*)mrb->true_class);
     
    918990
    919991  case MRB_TT_ENV:
    920     children += (int)obj->flags;
     992    children += MRB_ENV_STACK_LEN(obj);
    921993    break;
    922994
     
    927999      mrb_callinfo *ci;
    9281000
    929       if (!c) break;
     1001      if (!c || c->status == MRB_FIBER_TERMINATED) break;
     1002
    9301003      /* mark stack */
    9311004      i = c->stack - c->stbase;
    932       if (c->ci) i += c->ci->nregs;
     1005
     1006      if (c->ci) {
     1007        i += ci_nregs(c->ci);
     1008      }
    9331009      if (c->stbase + i > c->stend) i = c->stend - c->stbase;
    9341010      children += i;
     
    9491025    {
    9501026      struct RArray *a = (struct RArray*)obj;
    951       children += a->len;
     1027      children += ARY_LEN(a);
    9521028    }
    9531029    break;
     
    11901266
    11911267    if (is_major_gc(gc)) {
    1192       gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO;
     1268      size_t threshold = gc->live_after_mark/100 * MAJOR_GC_INC_RATIO;
     1269
    11931270      gc->full = FALSE;
     1271      if (threshold < MAJOR_GC_TOOMANY) {
     1272        gc->majorgc_old_threshold = threshold;
     1273      }
     1274      else {
     1275        /* too many objects allocated during incremental GC, */
     1276        /* instead of increasing threshold, invoke full GC. */
     1277        mrb_full_gc(mrb);
     1278      }
    11941279    }
    11951280    else if (is_minor_gc(gc)) {
     
    12291314
    12301315  if (is_generational(gc)) {
    1231     gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO;
     1316    gc->majorgc_old_threshold = gc->live_after_mark/100 * MAJOR_GC_INC_RATIO;
    12321317    gc->full = FALSE;
    12331318  }
     
    12401325{
    12411326  mrb_full_gc(mrb);
    1242 }
    1243 
    1244 MRB_API int
    1245 mrb_gc_arena_save(mrb_state *mrb)
    1246 {
    1247   return mrb->gc.arena_idx;
    1248 }
    1249 
    1250 MRB_API void
    1251 mrb_gc_arena_restore(mrb_state *mrb, int idx)
    1252 {
    1253   mrb_gc *gc = &mrb->gc;
    1254 
    1255 #ifndef MRB_GC_FIXED_ARENA
    1256   int capa = gc->arena_capa;
    1257 
    1258   if (idx < capa / 2) {
    1259     capa = (int)(capa * 0.66);
    1260     if (capa < MRB_GC_ARENA_SIZE) {
    1261       capa = MRB_GC_ARENA_SIZE;
    1262     }
    1263     if (capa != gc->arena_capa) {
    1264       gc->arena = (struct RBasic**)mrb_realloc(mrb, gc->arena, sizeof(struct RBasic*)*capa);
    1265       gc->arena_capa = capa;
    1266     }
    1267   }
    1268 #endif
    1269   gc->arena_idx = idx;
    12701327}
    12711328
     
    14071464
    14081465  mrb_get_args(mrb, "i", &ratio);
    1409   mrb->gc.interval_ratio = ratio;
     1466  mrb->gc.interval_ratio = (int)ratio;
    14101467  return mrb_nil_value();
    14111468}
     
    14401497
    14411498  mrb_get_args(mrb, "i", &ratio);
    1442   mrb->gc.step_ratio = ratio;
     1499  mrb->gc.step_ratio = (int)ratio;
    14431500  return mrb_nil_value();
    14441501}
     
    14581515  else if (!is_generational(gc) && enable) {
    14591516    incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT);
    1460     gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO;
     1517    gc->majorgc_old_threshold = gc->live_after_mark/100 * MAJOR_GC_INC_RATIO;
    14611518    gc->full = FALSE;
    14621519  }
     
    15231580  mrb_bool iterating = mrb->gc.iterating;
    15241581
     1582  mrb_full_gc(mrb);
    15251583  mrb->gc.iterating = TRUE;
    15261584  if (iterating) {
     
    15351593      gc_each_objects(mrb, &mrb->gc, callback, data);
    15361594      mrb->jmp = prev_jmp;
    1537       mrb->gc.iterating = iterating; 
     1595      mrb->gc.iterating = iterating;
    15381596   } MRB_CATCH(&c_jmp) {
    15391597      mrb->gc.iterating = iterating;
     
    15541612{
    15551613  struct RClass *gc;
     1614
     1615  mrb_static_assert(sizeof(RVALUE) <= sizeof(void*) * 6,
     1616                    "RVALUE size must be within 6 words");
    15561617
    15571618  gc = mrb_define_module(mrb, "GC");
  • EcnlProtoTool/trunk/mruby-2.1.1/src/hash.c

    r331 r439  
    99#include <mruby/class.h>
    1010#include <mruby/hash.h>
    11 #include <mruby/khash.h>
    1211#include <mruby/string.h>
    1312#include <mruby/variable.h>
    1413
     14#ifndef MRB_WITHOUT_FLOAT
    1515/* a function to get hash value of a float number */
    1616mrb_int mrb_float_id(mrb_float f);
    17 
    18 static inline khint_t
    19 mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key)
    20 {
    21   enum mrb_vtype t = mrb_type(key);
     17#endif
     18
     19#ifndef MRB_HT_INIT_SIZE
     20#define MRB_HT_INIT_SIZE 4
     21#endif
     22#define HT_SEG_INCREASE_RATIO 6 / 5
     23
     24struct segkv {
     25  mrb_value key;
     26  mrb_value val;
     27};
     28
     29typedef struct segment {
     30  uint16_t size;
     31  struct segment *next;
     32  struct segkv e[];
     33} segment;
     34
     35typedef struct segindex {
     36  size_t size;
     37  size_t capa;
     38  struct segkv *table[];
     39} segindex;
     40
     41/* hash table structure */
     42typedef struct htable {
     43  segment *rootseg;
     44  segment *lastseg;
     45  mrb_int size;
     46  uint16_t last_len;
     47  segindex *index;
     48} htable;
     49
     50static /* inline */ size_t
     51ht_hash_func(mrb_state *mrb, htable *t, mrb_value key)
     52{
     53  enum mrb_vtype tt = mrb_type(key);
    2254  mrb_value hv;
    23   const char *p;
    24   mrb_int i, len;
    25   khint_t h;
    26 
    27   switch (t) {
     55  size_t h;
     56  segindex *index = t->index;
     57  size_t capa = index ? index->capa : 0;
     58
     59  switch (tt) {
    2860  case MRB_TT_STRING:
    29     p = RSTRING_PTR(key);
    30     len = RSTRING_LEN(key);
    31     h = 0;
    32     for (i=0; i<len; i++) {
    33       h = (h << 5) - h + *p++;
    34     }
    35     return h;
    36 
     61    h = mrb_str_hash(mrb, key);
     62    break;
     63
     64  case MRB_TT_TRUE:
     65  case MRB_TT_FALSE:
    3766  case MRB_TT_SYMBOL:
    38     h = (khint_t)mrb_symbol(key);
    39     return kh_int_hash_func(mrb, h);
    40 
    4167  case MRB_TT_FIXNUM:
    42     h = (khint_t)mrb_float_id((mrb_float)mrb_fixnum(key));
    43     return kh_int_hash_func(mrb, h);
    44 
     68#ifndef MRB_WITHOUT_FLOAT
    4569  case MRB_TT_FLOAT:
    46     h = (khint_t)mrb_float_id(mrb_float(key));
    47     return kh_int_hash_func(mrb, h);
     70#endif
     71    h = (size_t)mrb_obj_id(key);
     72    break;
    4873
    4974  default:
    5075    hv = mrb_funcall(mrb, key, "hash", 0);
    51     h = (khint_t)t ^ mrb_fixnum(hv);
    52     return kh_int_hash_func(mrb, h);
    53   }
    54 }
    55 
    56 static inline khint_t
    57 mrb_hash_ht_hash_equal(mrb_state *mrb, mrb_value a, mrb_value b)
    58 {
    59   enum mrb_vtype t = mrb_type(a);
    60 
    61   switch (t) {
     76    h = (size_t)t ^ (size_t)mrb_fixnum(hv);
     77    break;
     78  }
     79  if (index && (index != t->index || capa != index->capa)) {
     80    mrb_raise(mrb, E_RUNTIME_ERROR, "hash modified");
     81  }
     82  return ((h)^((h)<<2)^((h)>>2));
     83}
     84
     85static inline mrb_bool
     86ht_hash_equal(mrb_state *mrb, htable *t, mrb_value a, mrb_value b)
     87{
     88  enum mrb_vtype tt = mrb_type(a);
     89
     90  switch (tt) {
    6291  case MRB_TT_STRING:
    6392    return mrb_str_equal(mrb, a, b);
    6493
    6594  case MRB_TT_SYMBOL:
    66     if (mrb_type(b) != MRB_TT_SYMBOL) return FALSE;
     95    if (!mrb_symbol_p(b)) return FALSE;
    6796    return mrb_symbol(a) == mrb_symbol(b);
    6897
     
    71100    case MRB_TT_FIXNUM:
    72101      return mrb_fixnum(a) == mrb_fixnum(b);
     102#ifndef MRB_WITHOUT_FLOAT
    73103    case MRB_TT_FLOAT:
    74104      return (mrb_float)mrb_fixnum(a) == mrb_float(b);
     105#endif
    75106    default:
    76107      return FALSE;
    77108    }
    78109
     110#ifndef MRB_WITHOUT_FLOAT
    79111  case MRB_TT_FLOAT:
    80112    switch (mrb_type(b)) {
     
    86118      return FALSE;
    87119    }
     120#endif
    88121
    89122  default:
    90     return mrb_eql(mrb, a, b);
    91   }
    92 }
    93 
    94 KHASH_DEFINE (ht, mrb_value, mrb_hash_value, TRUE, mrb_hash_ht_hash_func, mrb_hash_ht_hash_equal)
     123    {
     124      segindex *index = t->index;
     125      size_t capa = index ? index->capa : 0;
     126      mrb_bool eql = mrb_eql(mrb, a, b);
     127      if (index && (index != t->index || capa != index->capa)) {
     128        mrb_raise(mrb, E_RUNTIME_ERROR, "hash modified");
     129      }
     130      return eql;
     131    }
     132  }
     133}
     134
     135/* Creates the hash table. */
     136static htable*
     137ht_new(mrb_state *mrb)
     138{
     139  htable *t;
     140
     141  t = (htable*)mrb_malloc(mrb, sizeof(htable));
     142  t->size = 0;
     143  t->rootseg =  NULL;
     144  t->lastseg =  NULL;
     145  t->last_len = 0;
     146  t->index = NULL;
     147
     148  return t;
     149}
     150
     151#define power2(v) do { \
     152  v--;\
     153  v |= v >> 1;\
     154  v |= v >> 2;\
     155  v |= v >> 4;\
     156  v |= v >> 8;\
     157  v |= v >> 16;\
     158  v++;\
     159} while (0)
     160
     161#ifndef UPPER_BOUND
     162#define UPPER_BOUND(x) ((x)>>2|(x)>>1)
     163#endif
     164
     165#define HT_MASK(index) ((index->capa)-1)
     166
     167/* Build index for the hash table */
     168static void
     169ht_index(mrb_state *mrb, htable *t)
     170{
     171  size_t size = (size_t)t->size;
     172  size_t mask;
     173  segindex *index = t->index;
     174  segment *seg;
     175  size_t i;
     176
     177  /* allocate index table */
     178  if (index && index->size >= UPPER_BOUND(index->capa)) {
     179    size = index->capa+1;
     180  }
     181  power2(size);
     182  if (!index || index->capa < size) {
     183    index = (segindex*)mrb_realloc_simple(mrb, index, sizeof(segindex)+sizeof(struct segkv*)*size);
     184    if (index == NULL) {
     185      mrb_free(mrb, t->index);
     186      t->index = NULL;
     187      return;
     188    }
     189    t->index = index;
     190  }
     191  index->size = t->size;
     192  index->capa = size;
     193  for (i=0; i<size; i++) {
     194    index->table[i] = NULL;
     195  }
     196
     197  /* rebuld index */
     198  mask = HT_MASK(index);
     199  seg = t->rootseg;
     200  while (seg) {
     201    for (i=0; i<seg->size; i++) {
     202      mrb_value key;
     203      size_t k, step = 0;
     204
     205      if (!seg->next && i >= (size_t)t->last_len) {
     206        return;
     207      }
     208      key = seg->e[i].key;
     209      if (mrb_undef_p(key)) continue;
     210      k = ht_hash_func(mrb, t, key) & mask;
     211      while (index->table[k]) {
     212        k = (k+(++step)) & mask;
     213      }
     214      index->table[k] = &seg->e[i];
     215    }
     216    seg = seg->next;
     217  }
     218}
     219
     220/* Compacts the hash table removing deleted entries. */
     221static void
     222ht_compact(mrb_state *mrb, htable *t)
     223{
     224  segment *seg;
     225  uint16_t i, i2;
     226  segment *seg2 = NULL;
     227  mrb_int size = 0;
     228
     229  if (t == NULL) return;
     230  seg = t->rootseg;
     231  if (t->index && (size_t)t->size == t->index->size) {
     232    ht_index(mrb, t);
     233    return;
     234  }
     235  while (seg) {
     236    for (i=0; i<seg->size; i++) {
     237      mrb_value k = seg->e[i].key;
     238
     239      if (!seg->next && i >= t->last_len) {
     240        goto exit;
     241      }
     242      if (mrb_undef_p(k)) {     /* found deleted key */
     243        if (seg2 == NULL) {
     244          seg2 = seg;
     245          i2 = i;
     246        }
     247      }
     248      else {
     249        size++;
     250        if (seg2 != NULL) {
     251          seg2->e[i2++] = seg->e[i];
     252          if (i2 >= seg2->size) {
     253            seg2 = seg2->next;
     254            i2 = 0;
     255          }
     256        }
     257      }
     258    }
     259    seg = seg->next;
     260  }
     261 exit:
     262  /* reached at end */
     263  t->size = size;
     264  if (seg2) {
     265    seg = seg2->next;
     266    seg2->next = NULL;
     267    t->last_len = i2;
     268    t->lastseg = seg2;
     269    while (seg) {
     270      seg2 = seg->next;
     271      mrb_free(mrb, seg);
     272      seg = seg2;
     273    }
     274  }
     275  if (t->index) {
     276    ht_index(mrb, t);
     277  }
     278}
     279
     280static segment*
     281segment_alloc(mrb_state *mrb, segment *seg)
     282{
     283  uint32_t size;
     284
     285  if (!seg) size = MRB_HT_INIT_SIZE;
     286  else {
     287    size = seg->size*HT_SEG_INCREASE_RATIO + 1;
     288    if (size > UINT16_MAX) size = UINT16_MAX;
     289  }
     290
     291  seg = (segment*)mrb_malloc(mrb, sizeof(segment)+sizeof(struct segkv)*size);
     292  seg->size = size;
     293  seg->next = NULL;
     294
     295  return seg;
     296}
     297
     298/* Set the value for the key in the indexed table. */
     299static void
     300ht_index_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val)
     301{
     302  segindex *index = t->index;
     303  size_t k, sp, step = 0, mask;
     304  segment *seg;
     305
     306  if (index->size >= UPPER_BOUND(index->capa)) {
     307    /* need to expand table */
     308    ht_compact(mrb, t);
     309    index = t->index;
     310  }
     311  mask = HT_MASK(index);
     312  sp = index->capa;
     313  k = ht_hash_func(mrb, t, key) & mask;
     314  while (index->table[k]) {
     315    mrb_value key2 = index->table[k]->key;
     316    if (mrb_undef_p(key2)) {
     317      if (sp == index->capa) sp = k;
     318    }
     319    else if (ht_hash_equal(mrb, t, key, key2)) {
     320      index->table[k]->val = val;
     321      return;
     322    }
     323    k = (k+(++step)) & mask;
     324  }
     325  if (sp < index->capa) {
     326    k = sp;
     327  }
     328
     329  /* put the value at the last */
     330  seg = t->lastseg;
     331  if (t->last_len < seg->size) {
     332    index->table[k] = &seg->e[t->last_len++];
     333  }
     334  else {                        /* append a new segment */
     335    seg->next = segment_alloc(mrb, seg);
     336    seg = seg->next;
     337    seg->next = NULL;
     338    t->lastseg = seg;
     339    t->last_len = 1;
     340    index->table[k] = &seg->e[0];
     341  }
     342  index->table[k]->key = key;
     343  index->table[k]->val = val;
     344  index->size++;
     345  t->size++;
     346}
     347
     348/* Set the value for the key in the hash table. */
     349static void
     350ht_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val)
     351{
     352  segment *seg;
     353  mrb_int i, deleted = 0;
     354
     355  if (t == NULL) return;
     356  if (t->index) {
     357    ht_index_put(mrb, t, key, val);
     358    return;
     359  }
     360  seg = t->rootseg;
     361  while (seg) {
     362    for (i=0; i<seg->size; i++) {
     363      mrb_value k = seg->e[i].key;
     364      /* Found room in last segment after last_len */
     365      if (!seg->next && i >= t->last_len) {
     366        seg->e[i].key = key;
     367        seg->e[i].val = val;
     368        t->last_len = i+1;
     369        t->size++;
     370        return;
     371      }
     372      if (mrb_undef_p(k)) {
     373        deleted++;
     374        continue;
     375      }
     376      if (ht_hash_equal(mrb, t, k, key)) {
     377        seg->e[i].val = val;
     378        return;
     379      }
     380    }
     381    seg = seg->next;
     382  }
     383  /* Not found */
     384
     385  /* Compact if last segment has room */
     386  if (deleted > 0 && deleted > MRB_HT_INIT_SIZE) {
     387    ht_compact(mrb, t);
     388  }
     389  t->size++;
     390
     391  /* check if thre's room after compaction */
     392  if (t->lastseg && t->last_len < t->lastseg->size) {
     393    seg = t->lastseg;
     394    i = t->last_len;
     395  }
     396  else {
     397    /* append new segment */
     398    seg = segment_alloc(mrb, t->lastseg);
     399    i = 0;
     400    if (t->rootseg == NULL) {
     401      t->rootseg = seg;
     402    }
     403    else {
     404      t->lastseg->next = seg;
     405    }
     406    t->lastseg = seg;
     407  }
     408  seg->e[i].key = key;
     409  seg->e[i].val = val;
     410  t->last_len = i+1;
     411  if (t->index == NULL && t->size > MRB_HT_INIT_SIZE*4) {
     412    ht_index(mrb, t);
     413  }
     414}
     415
     416/* Get a value for a key from the indexed table. */
     417static mrb_bool
     418ht_index_get(mrb_state *mrb, htable *t, mrb_value key, mrb_value *vp)
     419{
     420  segindex *index = t->index;
     421  size_t mask = HT_MASK(index);
     422  size_t k = ht_hash_func(mrb, t, key) & mask;
     423  size_t step = 0;
     424
     425  while (index->table[k]) {
     426    mrb_value key2 = index->table[k]->key;
     427    if (!mrb_undef_p(key2) && ht_hash_equal(mrb, t, key, key2)) {
     428      if (vp) *vp = index->table[k]->val;
     429      return TRUE;
     430    }
     431    k = (k+(++step)) & mask;
     432  }
     433  return FALSE;
     434}
     435
     436/* Get a value for a key from the hash table. */
     437static mrb_bool
     438ht_get(mrb_state *mrb, htable *t, mrb_value key, mrb_value *vp)
     439{
     440  segment *seg;
     441  mrb_int i;
     442
     443  if (t == NULL) return FALSE;
     444  if (t->index) {
     445    return ht_index_get(mrb, t, key, vp);
     446  }
     447
     448  seg = t->rootseg;
     449  while (seg) {
     450    for (i=0; i<seg->size; i++) {
     451      mrb_value k = seg->e[i].key;
     452
     453      if (!seg->next && i >= t->last_len) {
     454        return FALSE;
     455      }
     456      if (mrb_undef_p(k)) continue;
     457      if (ht_hash_equal(mrb, t, k, key)) {
     458        if (vp) *vp = seg->e[i].val;
     459        return TRUE;
     460      }
     461    }
     462    seg = seg->next;
     463  }
     464  return FALSE;
     465}
     466
     467/* Deletes the value for the symbol from the hash table. */
     468/* Deletion is done by overwriting keys by `undef`. */
     469static mrb_bool
     470ht_del(mrb_state *mrb, htable *t, mrb_value key, mrb_value *vp)
     471{
     472  segment *seg;
     473  mrb_int i;
     474
     475  if (t == NULL) return FALSE;
     476  seg = t->rootseg;
     477  while (seg) {
     478    for (i=0; i<seg->size; i++) {
     479      mrb_value key2;
     480
     481      if (!seg->next && i >= t->last_len) {
     482        /* not found */
     483        return FALSE;
     484      }
     485      key2 = seg->e[i].key;
     486      if (!mrb_undef_p(key2) && ht_hash_equal(mrb, t, key, key2)) {
     487        if (vp) *vp = seg->e[i].val;
     488        seg->e[i].key = mrb_undef_value();
     489        t->size--;
     490        return TRUE;
     491      }
     492    }
     493    seg = seg->next;
     494  }
     495  return FALSE;
     496}
     497
     498/* Iterates over the hash table. */
     499static void
     500ht_foreach(mrb_state *mrb, htable *t, mrb_hash_foreach_func *func, void *p)
     501{
     502  segment *seg;
     503  mrb_int i;
     504
     505  if (t == NULL) return;
     506  seg = t->rootseg;
     507  while (seg) {
     508    for (i=0; i<seg->size; i++) {
     509      /* no value in last segment after last_len */
     510      if (!seg->next && i >= t->last_len) {
     511        return;
     512      }
     513      if (mrb_undef_p(seg->e[i].key)) continue;
     514      if ((*func)(mrb, seg->e[i].key, seg->e[i].val, p) != 0)
     515        return;
     516    }
     517    seg = seg->next;
     518  }
     519}
     520
     521/* Iterates over the hash table. */
     522MRB_API void
     523mrb_hash_foreach(mrb_state *mrb, struct RHash *hash, mrb_hash_foreach_func *func, void *p)
     524{
     525  ht_foreach(mrb, hash->ht, func, p);
     526}
     527
     528/* Copy the hash table. */
     529static htable*
     530ht_copy(mrb_state *mrb, htable *t)
     531{
     532  segment *seg;
     533  htable *t2;
     534  mrb_int i;
     535
     536  seg = t->rootseg;
     537  t2 = ht_new(mrb);
     538  if (t->size == 0) return t2;
     539
     540  while (seg) {
     541    for (i=0; i<seg->size; i++) {
     542      mrb_value key = seg->e[i].key;
     543      mrb_value val = seg->e[i].val;
     544
     545      if ((seg->next == NULL) && (i >= t->last_len)) {
     546        return t2;
     547      }
     548      if (mrb_undef_p(key)) continue; /* skip deleted key */
     549      ht_put(mrb, t2, key, val);
     550    }
     551    seg = seg->next;
     552  }
     553  return t2;
     554}
     555
     556/* Free memory of the hash table. */
     557static void
     558ht_free(mrb_state *mrb, htable *t)
     559{
     560  segment *seg;
     561
     562  if (!t) return;
     563  seg = t->rootseg;
     564  while (seg) {
     565    segment *p = seg;
     566    seg = seg->next;
     567    mrb_free(mrb, p);
     568  }
     569  if (t->index) mrb_free(mrb, t->index);
     570  mrb_free(mrb, t);
     571}
    95572
    96573static void mrb_hash_modify(mrb_state *mrb, mrb_value hash);
    97574
    98575static inline mrb_value
    99 mrb_hash_ht_key(mrb_state *mrb, mrb_value key)
    100 {
    101   if (mrb_string_p(key) && !MRB_FROZEN_P(mrb_str_ptr(key))) {
     576ht_key(mrb_state *mrb, mrb_value key)
     577{
     578  if (mrb_string_p(key) && !mrb_frozen_p(mrb_str_ptr(key))) {
    102579    key = mrb_str_dup(mrb, key);
    103580    MRB_SET_FROZEN_FLAG(mrb_str_ptr(key));
     
    106583}
    107584
    108 #define KEY(key) mrb_hash_ht_key(mrb, key)
     585#define KEY(key) ht_key(mrb, key)
     586
     587static int
     588hash_mark_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p)
     589{
     590  mrb_gc_mark_value(mrb, key);
     591  mrb_gc_mark_value(mrb, val);
     592  return 0;
     593}
    109594
    110595void
    111596mrb_gc_mark_hash(mrb_state *mrb, struct RHash *hash)
    112597{
    113   khiter_t k;
    114   khash_t(ht) *h = hash->ht;
    115 
    116   if (!h) return;
    117   for (k = kh_begin(h); k != kh_end(h); k++) {
    118     if (kh_exist(h, k)) {
    119       mrb_value key = kh_key(h, k);
    120       mrb_value val = kh_value(h, k).v;
    121 
    122       mrb_gc_mark_value(mrb, key);
    123       mrb_gc_mark_value(mrb, val);
    124     }
    125   }
     598  ht_foreach(mrb, hash->ht, hash_mark_i, NULL);
    126599}
    127600
     
    130603{
    131604  if (!hash->ht) return 0;
    132   return kh_size(hash->ht)*2;
     605  return hash->ht->size*2;
    133606}
    134607
     
    136609mrb_gc_free_hash(mrb_state *mrb, struct RHash *hash)
    137610{
    138   if (hash->ht) kh_destroy(ht, mrb, hash->ht);
    139 }
    140 
     611  ht_free(mrb, hash->ht);
     612}
     613
     614MRB_API mrb_value
     615mrb_hash_new(mrb_state *mrb)
     616{
     617  struct RHash *h;
     618
     619  h = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
     620  h->ht = 0;
     621  h->iv = 0;
     622  return mrb_obj_value(h);
     623}
    141624
    142625MRB_API mrb_value
     
    146629
    147630  h = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
    148   h->ht = kh_init(ht, mrb);
    149   if (capa > 0) {
    150     kh_resize(ht, mrb, h->ht, capa);
    151   }
     631  /* preallocate hash table */
     632  h->ht = ht_new(mrb);
     633  /* capacity ignored */
    152634  h->iv = 0;
    153635  return mrb_obj_value(h);
    154636}
    155637
    156 MRB_API mrb_value
    157 mrb_hash_new(mrb_state *mrb)
    158 {
    159   return mrb_hash_new_capa(mrb, 0);
    160 }
    161 
    162638static mrb_value mrb_hash_default(mrb_state *mrb, mrb_value hash);
    163639static mrb_value hash_default(mrb_state *mrb, mrb_value hash, mrb_value key);
    164640
     641static mrb_value
     642mrb_hash_init_copy(mrb_state *mrb, mrb_value self)
     643{
     644  mrb_value orig;
     645  struct RHash* copy;
     646  htable *orig_h;
     647  mrb_value ifnone, vret;
     648
     649  mrb_get_args(mrb, "o", &orig);
     650  if (mrb_obj_equal(mrb, self, orig)) return self;
     651  if ((mrb_type(self) != mrb_type(orig)) || (mrb_obj_class(mrb, self) != mrb_obj_class(mrb, orig))) {
     652      mrb_raise(mrb, E_TYPE_ERROR, "initialize_copy should take same class object");
     653  }
     654
     655  orig_h = RHASH_TBL(self);
     656  copy = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
     657  copy->ht = ht_copy(mrb, orig_h);
     658
     659  if (MRB_RHASH_DEFAULT_P(self)) {
     660    copy->flags |= MRB_HASH_DEFAULT;
     661  }
     662  if (MRB_RHASH_PROCDEFAULT_P(self)) {
     663    copy->flags |= MRB_HASH_PROC_DEFAULT;
     664  }
     665  vret = mrb_obj_value(copy);
     666  ifnone = RHASH_IFNONE(self);
     667  if (!mrb_nil_p(ifnone)) {
     668      mrb_iv_set(mrb, vret, mrb_intern_lit(mrb, "ifnone"), ifnone);
     669  }
     670  return vret;
     671}
     672
     673static int
     674check_kdict_i(mrb_state *mrb, mrb_value key, mrb_value val, void *data)
     675{
     676  if (!mrb_symbol_p(key)) {
     677    mrb_raise(mrb, E_ARGUMENT_ERROR, "keyword argument hash with non symbol keys");
     678  }
     679  return 0;
     680}
     681
     682void
     683mrb_hash_check_kdict(mrb_state *mrb, mrb_value self)
     684{
     685  htable *t;
     686
     687  t = RHASH_TBL(self);
     688  if (!t || t->size == 0) return;
     689  ht_foreach(mrb, t, check_kdict_i, NULL);
     690}
     691
     692MRB_API mrb_value
     693mrb_hash_dup(mrb_state *mrb, mrb_value self)
     694{
     695  struct RHash* copy;
     696  htable *orig_h;
     697
     698  orig_h = RHASH_TBL(self);
     699  copy = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
     700  copy->ht = orig_h ? ht_copy(mrb, orig_h) : NULL;
     701  return mrb_obj_value(copy);
     702}
     703
    165704MRB_API mrb_value
    166705mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key)
    167706{
    168   khash_t(ht) *h = RHASH_TBL(hash);
    169   khiter_t k;
     707  mrb_value val;
    170708  mrb_sym mid;
    171709
    172   if (h) {
    173     k = kh_get(ht, mrb, h, key);
    174     if (k != kh_end(h))
    175       return kh_value(h, k).v;
     710  if (ht_get(mrb, RHASH_TBL(hash), key, &val)) {
     711    return val;
    176712  }
    177713
     
    187723mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def)
    188724{
    189   khash_t(ht) *h = RHASH_TBL(hash);
    190   khiter_t k;
    191 
    192   if (h) {
    193     k = kh_get(ht, mrb, h, key);
    194     if (k != kh_end(h))
    195       return kh_value(h, k).v;
    196   }
    197 
     725  mrb_value val;
     726
     727  if (ht_get(mrb, RHASH_TBL(hash), key, &val)) {
     728    return val;
     729  }
    198730  /* not found */
    199731  return def;
     
    203735mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val)
    204736{
    205   khash_t(ht) *h;
    206   khiter_t k;
    207   int r;
    208 
    209737  mrb_hash_modify(mrb, hash);
    210   h = RHASH_TBL(hash);
    211 
    212   if (!h) h = RHASH_TBL(hash) = kh_init(ht, mrb);
    213   k = kh_put2(ht, mrb, h, key, &r);
    214   kh_value(h, k).v = val;
    215 
    216   if (r != 0) {
    217     /* expand */
    218     int ai = mrb_gc_arena_save(mrb);
    219     key = kh_key(h, k) = KEY(key);
    220     mrb_gc_arena_restore(mrb, ai);
    221     kh_value(h, k).n = kh_size(h)-1;
    222   }
    223 
     738
     739  key = KEY(key);
     740  ht_put(mrb, RHASH_TBL(hash), key, val);
    224741  mrb_field_write_barrier_value(mrb, (struct RBasic*)RHASH(hash), key);
    225742  mrb_field_write_barrier_value(mrb, (struct RBasic*)RHASH(hash), val);
     
    227744}
    228745
    229 static mrb_value
    230 mrb_hash_dup(mrb_state *mrb, mrb_value hash)
    231 {
    232   struct RHash* ret;
    233   khash_t(ht) *h, *ret_h;
    234   khiter_t k, ret_k;
    235   mrb_value ifnone, vret;
    236 
    237   h = RHASH_TBL(hash);
    238   ret = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
    239   ret->ht = kh_init(ht, mrb);
    240 
    241   if (h && kh_size(h) > 0) {
    242     ret_h = ret->ht;
    243 
    244     for (k = kh_begin(h); k != kh_end(h); k++) {
    245       if (kh_exist(h, k)) {
    246         int ai = mrb_gc_arena_save(mrb);
    247         ret_k = kh_put(ht, mrb, ret_h, KEY(kh_key(h, k)));
    248         mrb_gc_arena_restore(mrb, ai);
    249         kh_val(ret_h, ret_k).v = kh_val(h, k).v;
    250         kh_val(ret_h, ret_k).n = kh_size(ret_h)-1;
    251       }
    252     }
    253   }
    254 
    255   if (MRB_RHASH_DEFAULT_P(hash)) {
    256     ret->flags |= MRB_HASH_DEFAULT;
    257   }
    258   if (MRB_RHASH_PROCDEFAULT_P(hash)) {
    259     ret->flags |= MRB_HASH_PROC_DEFAULT;
    260   }
    261   vret = mrb_obj_value(ret);
    262   ifnone = RHASH_IFNONE(hash);
    263   if (!mrb_nil_p(ifnone)) {
    264       mrb_iv_set(mrb, vret, mrb_intern_lit(mrb, "ifnone"), ifnone);
    265   }
    266   return vret;
    267 }
    268 
    269 MRB_API mrb_value
    270 mrb_check_hash_type(mrb_state *mrb, mrb_value hash)
    271 {
    272   return mrb_check_convert_type(mrb, hash, MRB_TT_HASH, "Hash", "to_hash");
    273 }
    274 
    275 MRB_API khash_t(ht)*
    276 mrb_hash_tbl(mrb_state *mrb, mrb_value hash)
    277 {
    278   khash_t(ht) *h = RHASH_TBL(hash);
    279 
    280   if (!h) {
    281     return RHASH_TBL(hash) = kh_init(ht, mrb);
    282   }
    283   return h;
    284 }
    285 
    286746static void
    287747mrb_hash_modify(mrb_state *mrb, mrb_value hash)
    288748{
    289   if (MRB_FROZEN_P(mrb_hash_ptr(hash))) {
    290     mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen hash");
    291   }
    292   mrb_hash_tbl(mrb, hash);
     749  mrb_check_frozen(mrb, mrb_hash_ptr(hash));
     750  if (!RHASH_TBL(hash)) {
     751    RHASH_TBL(hash) = ht_new(mrb);
     752  }
    293753}
    294754
     
    340800  if (!mrb_nil_p(block)) {
    341801    if (ifnone_p) {
    342       mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
     802      mrb_argnum_error(mrb, 1, 0, 0);
    343803    }
    344804    RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT;
     
    530990mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key)
    531991{
    532   khash_t(ht) *h = RHASH_TBL(hash);
    533   khiter_t k;
    534   mrb_value delVal;
    535   mrb_int n;
    536 
    537   if (h) {
    538     k = kh_get(ht, mrb, h, key);
    539     if (k != kh_end(h)) {
    540       delVal = kh_value(h, k).v;
    541       n = kh_value(h, k).n;
    542       kh_del(ht, mrb, h, k);
    543       for (k = kh_begin(h); k != kh_end(h); k++) {
    544         if (!kh_exist(h, k)) continue;
    545         if (kh_value(h, k).n > n) kh_value(h, k).n--;
    546       }
    547       return delVal;
    548     }
     992  htable *t = RHASH_TBL(hash);
     993  mrb_value del_val;
     994
     995  if (ht_del(mrb, t, key, &del_val)) {
     996    return del_val;
    549997  }
    550998
     
    5531001}
    5541002
    555 /* 15.2.13.4.8  */
    556 /*
    557  *  call-seq:
    558  *     hsh.delete(key)                   -> value
    559  *     hsh.delete(key) {| key | block }  -> value
    560  *
    561  *  Deletes and returns a key-value pair from <i>hsh</i> whose key is
    562  *  equal to <i>key</i>. If the key is not found, returns the
    563  *  <em>default value</em>. If the optional code block is given and the
    564  *  key is not found, pass in the key and return the result of
    565  *  <i>block</i>.
    566  *
    567  *      h = { "a" => 100, "b" => 200 }
    568  *      h.delete("a")                              #=> 100
    569  *      h.delete("z")                              #=> nil
    570  *      h.delete("z") { |el| "#{el} not found" }   #=> "z not found"
    571  *
    572  */
    5731003static mrb_value
    5741004mrb_hash_delete(mrb_state *mrb, mrb_value self)
     
    5811011}
    5821012
     1013/* find first element in the hash table, and remove it. */
     1014static void
     1015ht_shift(mrb_state *mrb, htable *t, mrb_value *kp, mrb_value *vp)
     1016{
     1017  segment *seg = t->rootseg;
     1018  mrb_int i;
     1019
     1020  while (seg) {
     1021    for (i=0; i<seg->size; i++) {
     1022      mrb_value key;
     1023
     1024      if (!seg->next && i >= t->last_len) {
     1025        return;
     1026      }
     1027      key = seg->e[i].key;
     1028      if (mrb_undef_p(key)) continue;
     1029      *kp = key;
     1030      *vp = seg->e[i].val;
     1031      /* delete element */
     1032      seg->e[i].key = mrb_undef_value();
     1033      t->size--;
     1034      return;
     1035    }
     1036    seg = seg->next;
     1037  }
     1038}
     1039
    5831040/* 15.2.13.4.24 */
    5841041/*
     
    5981055mrb_hash_shift(mrb_state *mrb, mrb_value hash)
    5991056{
    600   khash_t(ht) *h = RHASH_TBL(hash);
    601   khiter_t k;
    602   mrb_value delKey, delVal;
     1057  htable *t = RHASH_TBL(hash);
    6031058
    6041059  mrb_hash_modify(mrb, hash);
    605   if (h && kh_size(h) > 0) {
    606     for (k = kh_begin(h); k != kh_end(h); k++) {
    607       if (!kh_exist(h, k)) continue;
    608 
    609       delKey = kh_key(h, k);
    610       mrb_gc_protect(mrb, delKey);
    611       delVal = mrb_hash_delete_key(mrb, hash, delKey);
    612       mrb_gc_protect(mrb, delVal);
    613 
    614       return mrb_assoc_new(mrb, delKey, delVal);
    615     }
     1060  if (t && t->size > 0) {
     1061    mrb_value del_key, del_val;
     1062
     1063    ht_shift(mrb, t, &del_key, &del_val);
     1064    mrb_gc_protect(mrb, del_key);
     1065    mrb_gc_protect(mrb, del_val);
     1066    return mrb_assoc_new(mrb, del_key, del_val);
    6161067  }
    6171068
     
    6421093mrb_hash_clear(mrb_state *mrb, mrb_value hash)
    6431094{
    644   khash_t(ht) *h = RHASH_TBL(hash);
     1095  htable *t = RHASH_TBL(hash);
    6451096
    6461097  mrb_hash_modify(mrb, hash);
    647   if (h) kh_clear(ht, mrb, h);
     1098  if (t) {
     1099    ht_free(mrb, t);
     1100    RHASH_TBL(hash) = NULL;
     1101  }
    6481102  return hash;
    6491103}
     
    6781132}
    6791133
     1134MRB_API mrb_int
     1135mrb_hash_size(mrb_state *mrb, mrb_value hash)
     1136{
     1137  htable *t = RHASH_TBL(hash);
     1138
     1139  if (!t) return 0;
     1140  return t->size;
     1141}
     1142
    6801143/* 15.2.13.4.20 */
    6811144/* 15.2.13.4.25 */
     
    6951158mrb_hash_size_m(mrb_state *mrb, mrb_value self)
    6961159{
    697   khash_t(ht) *h = RHASH_TBL(self);
    698 
    699   if (!h) return mrb_fixnum_value(0);
    700   return mrb_fixnum_value(kh_size(h));
     1160  mrb_int size = mrb_hash_size(mrb, self);
     1161  return mrb_fixnum_value(size);
     1162}
     1163
     1164MRB_API mrb_bool
     1165mrb_hash_empty_p(mrb_state *mrb, mrb_value self)
     1166{
     1167  htable *t = RHASH_TBL(self);
     1168
     1169  if (!t) return TRUE;
     1170  return t->size == 0;
    7011171}
    7021172
     
    7111181 *
    7121182 */
    713 MRB_API mrb_value
    714 mrb_hash_empty_p(mrb_state *mrb, mrb_value self)
    715 {
    716   khash_t(ht) *h = RHASH_TBL(self);
    717 
    718   if (h) return mrb_bool_value(kh_size(h) == 0);
    719   return mrb_true_value();
    720 }
    721 
    722 /* 15.2.13.4.29 (x)*/
    723 /*
    724  * call-seq:
    725  *    hsh.to_hash   => hsh
    726  *
    727  * Returns +self+.
    728  */
    729 
    730 static mrb_value
    731 mrb_hash_to_hash(mrb_state *mrb, mrb_value hash)
    732 {
    733   return hash;
     1183static mrb_value
     1184mrb_hash_empty_m(mrb_state *mrb, mrb_value self)
     1185{
     1186  return mrb_bool_value(mrb_hash_empty_p(mrb, self));
     1187}
     1188
     1189static int
     1190hash_keys_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p)
     1191{
     1192  mrb_ary_push(mrb, *(mrb_value*)p, key);
     1193  return 0;
    7341194}
    7351195
     
    7501210mrb_hash_keys(mrb_state *mrb, mrb_value hash)
    7511211{
    752   khash_t(ht) *h = RHASH_TBL(hash);
    753   khiter_t k;
    754   mrb_int end;
     1212  htable *t = RHASH_TBL(hash);
     1213  mrb_int size;
    7551214  mrb_value ary;
    756   mrb_value *p;
    757 
    758   if (!h || kh_size(h) == 0) return mrb_ary_new(mrb);
    759   ary = mrb_ary_new_capa(mrb, kh_size(h));
    760   end = kh_size(h)-1;
    761   mrb_ary_set(mrb, ary, end, mrb_nil_value());
    762   p = mrb_ary_ptr(ary)->ptr;
    763   for (k = kh_begin(h); k != kh_end(h); k++) {
    764     if (kh_exist(h, k)) {
    765       mrb_value kv = kh_key(h, k);
    766       mrb_hash_value hv = kh_value(h, k);
    767 
    768       if (hv.n <= end) {
    769         p[hv.n] = kv;
    770       }
    771       else {
    772         p[end] = kv;
    773       }
    774     }
    775   }
     1215
     1216  if (!t || (size = t->size) == 0)
     1217    return mrb_ary_new(mrb);
     1218  ary = mrb_ary_new_capa(mrb, size);
     1219  ht_foreach(mrb, t, hash_keys_i, (void*)&ary);
    7761220  return ary;
     1221}
     1222
     1223static int
     1224hash_vals_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p)
     1225{
     1226  mrb_ary_push(mrb, *(mrb_value*)p, val);
     1227  return 0;
    7771228}
    7781229
     
    7931244mrb_hash_values(mrb_state *mrb, mrb_value hash)
    7941245{
    795   khash_t(ht) *h = RHASH_TBL(hash);
    796   khiter_t k;
     1246  htable *t = RHASH_TBL(hash);
     1247  mrb_int size;
    7971248  mrb_value ary;
    7981249
    799   if (!h) return mrb_ary_new(mrb);
    800   ary = mrb_ary_new_capa(mrb, kh_size(h));
    801   for (k = kh_begin(h); k != kh_end(h); k++) {
    802     if (kh_exist(h, k)) {
    803       mrb_hash_value hv = kh_value(h, k);
    804 
    805       mrb_ary_set(mrb, ary, hv.n, hv.v);
    806     }
    807   }
     1250  if (!t || (size = t->size) == 0)
     1251    return mrb_ary_new(mrb);
     1252  ary = mrb_ary_new_capa(mrb, size);
     1253  ht_foreach(mrb, t, hash_vals_i, (void*)&ary);
    8081254  return ary;
    8091255}
     
    8281274 */
    8291275
     1276MRB_API mrb_bool
     1277mrb_hash_key_p(mrb_state *mrb, mrb_value hash, mrb_value key)
     1278{
     1279  htable *t;
     1280
     1281  t = RHASH_TBL(hash);
     1282  if (ht_get(mrb, t, key, NULL)) {
     1283    return TRUE;
     1284  }
     1285  return FALSE;
     1286}
     1287
    8301288static mrb_value
    8311289mrb_hash_has_key(mrb_state *mrb, mrb_value hash)
    8321290{
    8331291  mrb_value key;
    834   khash_t(ht) *h;
    835   khiter_t k;
     1292  mrb_bool key_p;
    8361293
    8371294  mrb_get_args(mrb, "o", &key);
    838 
    839   h = RHASH_TBL(hash);
    840   if (h) {
    841     k = kh_get(ht, mrb, h, key);
    842     return mrb_bool_value(k != kh_end(h));
    843   }
    844   return mrb_false_value();
     1295  key_p = mrb_hash_key_p(mrb, hash, key);
     1296  return mrb_bool_value(key_p);
     1297}
     1298
     1299struct has_v_arg {
     1300  mrb_bool found;
     1301  mrb_value val;
     1302};
     1303
     1304static int
     1305hash_has_value_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p)
     1306{
     1307  struct has_v_arg *arg = (struct has_v_arg*)p;
     1308 
     1309  if (mrb_equal(mrb, arg->val, val)) {
     1310    arg->found = TRUE;
     1311    return 1;
     1312  }
     1313  return 0;
    8451314}
    8461315
     
    8641333{
    8651334  mrb_value val;
    866   khash_t(ht) *h;
    867   khiter_t k;
    868 
     1335  struct has_v_arg arg;
     1336 
    8691337  mrb_get_args(mrb, "o", &val);
    870   h = RHASH_TBL(hash);
    871 
    872   if (h) {
    873     for (k = kh_begin(h); k != kh_end(h); k++) {
    874       if (!kh_exist(h, k)) continue;
    875 
    876       if (mrb_equal(mrb, kh_value(h, k).v, val)) {
    877         return mrb_true_value();
    878       }
    879     }
    880   }
    881   return mrb_false_value();
     1338  arg.found = FALSE;
     1339  arg.val = val;
     1340  ht_foreach(mrb, RHASH_TBL(hash), hash_has_value_i, &arg);
     1341  return mrb_bool_value(arg.found);
     1342}
     1343
     1344static int
     1345merge_i(mrb_state *mrb, mrb_value key, mrb_value val, void *data)
     1346{
     1347  htable *h1 = (htable*)data;
     1348
     1349  ht_put(mrb, h1, key, val);
     1350  return 0;
     1351}
     1352
     1353MRB_API void
     1354mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2)
     1355{
     1356  htable *h1, *h2;
     1357
     1358  mrb_hash_modify(mrb, hash1);
     1359  hash2 = mrb_ensure_hash_type(mrb, hash2);
     1360  h1 = RHASH_TBL(hash1);
     1361  h2 = RHASH_TBL(hash2);
     1362
     1363  if (!h2) return;
     1364  if (!h1) {
     1365    RHASH_TBL(hash1) = ht_copy(mrb, h2);
     1366    return;
     1367  }
     1368  ht_foreach(mrb, h2, merge_i, h1);
     1369  mrb_write_barrier(mrb, (struct RBasic*)RHASH(hash1));
     1370  return;
     1371}
     1372
     1373/*
     1374 *  call-seq:
     1375 *    hsh.rehash -> hsh
     1376 *
     1377 *  Rebuilds the hash based on the current hash values for each key. If
     1378 *  values of key objects have changed since they were inserted, this
     1379 *  method will reindex <i>hsh</i>.
     1380 *
     1381 *     keys = (1..17).map{|n| [n]}
     1382 *     k = keys[0]
     1383 *     h = {}
     1384 *     keys.each{|key| h[key] = key[0]}
     1385 *     h     #=> { [1]=> 1, [2]=> 2, [3]=> 3, [4]=> 4, [5]=> 5, [6]=> 6, [7]=> 7,
     1386 *                 [8]=> 8, [9]=> 9,[10]=>10,[11]=>11,[12]=>12,[13]=>13,[14]=>14,
     1387 *                [15]=>15,[16]=>16,[17]=>17}
     1388 *     h[k]  #=> 1
     1389 *     k[0] = keys.size + 1
     1390 *     h     #=> {[18]=> 1, [2]=> 2, [3]=> 3, [4]=> 4, [5]=> 5, [6]=> 6, [7]=> 7,
     1391 *                 [8]=> 8, [9]=> 9,[10]=>10,[11]=>11,[12]=>12,[13]=>13,[14]=>14,
     1392 *                [15]=>15,[16]=>16,[17]=>17}
     1393 *     h[k]  #=> nil
     1394 *     h.rehash
     1395 *     h[k]  #=> 1
     1396 */
     1397static mrb_value
     1398mrb_hash_rehash(mrb_state *mrb, mrb_value self)
     1399{
     1400  ht_compact(mrb, RHASH_TBL(self));
     1401  return self;
    8821402}
    8831403
     
    8901410  MRB_SET_INSTANCE_TT(h, MRB_TT_HASH);
    8911411
     1412  mrb_define_method(mrb, h, "initialize_copy", mrb_hash_init_copy,   MRB_ARGS_REQ(1));
    8921413  mrb_define_method(mrb, h, "[]",              mrb_hash_aget,        MRB_ARGS_REQ(1)); /* 15.2.13.4.2  */
    8931414  mrb_define_method(mrb, h, "[]=",             mrb_hash_aset,        MRB_ARGS_REQ(2)); /* 15.2.13.4.3  */
    8941415  mrb_define_method(mrb, h, "clear",           mrb_hash_clear,       MRB_ARGS_NONE()); /* 15.2.13.4.4  */
    895   mrb_define_method(mrb, h, "default",         mrb_hash_default,     MRB_ARGS_ANY());  /* 15.2.13.4.5  */
     1416  mrb_define_method(mrb, h, "default",         mrb_hash_default,     MRB_ARGS_OPT(1));  /* 15.2.13.4.5  */
    8961417  mrb_define_method(mrb, h, "default=",        mrb_hash_set_default, MRB_ARGS_REQ(1)); /* 15.2.13.4.6  */
    8971418  mrb_define_method(mrb, h, "default_proc",    mrb_hash_default_proc,MRB_ARGS_NONE()); /* 15.2.13.4.7  */
    8981419  mrb_define_method(mrb, h, "default_proc=",   mrb_hash_set_default_proc,MRB_ARGS_REQ(1)); /* 15.2.13.4.7  */
    8991420  mrb_define_method(mrb, h, "__delete",        mrb_hash_delete,      MRB_ARGS_REQ(1)); /* core of 15.2.13.4.8  */
    900   mrb_define_method(mrb, h, "empty?",          mrb_hash_empty_p,     MRB_ARGS_NONE()); /* 15.2.13.4.12 */
     1421  mrb_define_method(mrb, h, "empty?",          mrb_hash_empty_m,     MRB_ARGS_NONE()); /* 15.2.13.4.12 */
    9011422  mrb_define_method(mrb, h, "has_key?",        mrb_hash_has_key,     MRB_ARGS_REQ(1)); /* 15.2.13.4.13 */
    9021423  mrb_define_method(mrb, h, "has_value?",      mrb_hash_has_value,   MRB_ARGS_REQ(1)); /* 15.2.13.4.14 */
    9031424  mrb_define_method(mrb, h, "include?",        mrb_hash_has_key,     MRB_ARGS_REQ(1)); /* 15.2.13.4.15 */
    904   mrb_define_method(mrb, h, "initialize",      mrb_hash_init,        MRB_ARGS_OPT(1)); /* 15.2.13.4.16 */
     1425  mrb_define_method(mrb, h, "initialize",      mrb_hash_init,        MRB_ARGS_OPT(1)|MRB_ARGS_BLOCK()); /* 15.2.13.4.16 */
    9051426  mrb_define_method(mrb, h, "key?",            mrb_hash_has_key,     MRB_ARGS_REQ(1)); /* 15.2.13.4.18 */
    9061427  mrb_define_method(mrb, h, "keys",            mrb_hash_keys,        MRB_ARGS_NONE()); /* 15.2.13.4.19 */
     
    9081429  mrb_define_method(mrb, h, "member?",         mrb_hash_has_key,     MRB_ARGS_REQ(1)); /* 15.2.13.4.21 */
    9091430  mrb_define_method(mrb, h, "shift",           mrb_hash_shift,       MRB_ARGS_NONE()); /* 15.2.13.4.24 */
    910   mrb_define_method(mrb, h, "dup",             mrb_hash_dup,         MRB_ARGS_NONE());
    9111431  mrb_define_method(mrb, h, "size",            mrb_hash_size_m,      MRB_ARGS_NONE()); /* 15.2.13.4.25 */
    9121432  mrb_define_method(mrb, h, "store",           mrb_hash_aset,        MRB_ARGS_REQ(2)); /* 15.2.13.4.26 */
    9131433  mrb_define_method(mrb, h, "value?",          mrb_hash_has_value,   MRB_ARGS_REQ(1)); /* 15.2.13.4.27 */
    9141434  mrb_define_method(mrb, h, "values",          mrb_hash_values,      MRB_ARGS_NONE()); /* 15.2.13.4.28 */
    915 
    916   mrb_define_method(mrb, h, "to_hash",         mrb_hash_to_hash,     MRB_ARGS_NONE()); /* 15.2.13.4.29 (x)*/
    917 }
     1435  mrb_define_method(mrb, h, "rehash",          mrb_hash_rehash,      MRB_ARGS_NONE());
     1436}
  • EcnlProtoTool/trunk/mruby-2.1.1/src/kernel.c

    r331 r439  
    1515#include <mruby/istruct.h>
    1616
    17 typedef enum {
    18   NOEX_PUBLIC    = 0x00,
    19   NOEX_NOSUPER   = 0x01,
    20   NOEX_PRIVATE   = 0x02,
    21   NOEX_PROTECTED = 0x04,
    22   NOEX_MASK      = 0x06,
    23   NOEX_BASIC     = 0x08,
    24   NOEX_UNDEF     = NOEX_NOSUPER,
    25   NOEX_MODFUNC   = 0x12,
    26   NOEX_SUPER     = 0x20,
    27   NOEX_VCALL     = 0x40,
    28   NOEX_RESPONDS  = 0x80
    29 } mrb_method_flag_t;
    30 
    3117MRB_API mrb_bool
    3218mrb_func_basic_p(mrb_state *mrb, mrb_value obj, mrb_sym mid, mrb_func_t func)
    3319{
    34   struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mid);
    35   if (MRB_PROC_CFUNC_P(me) && (me->body.func == func))
     20  struct RClass *c = mrb_class(mrb, obj);
     21  mrb_method_t m = mrb_method_search_vm(mrb, &c, mid);
     22  struct RProc *p;
     23
     24  if (MRB_METHOD_UNDEF_P(m)) return FALSE;
     25  if (MRB_METHOD_FUNC_P(m))
     26    return MRB_METHOD_FUNC(m) == func;
     27  p = MRB_METHOD_PROC(m);
     28  if (MRB_PROC_CFUNC_P(p) && (MRB_PROC_CFUNC(p) == func))
    3629    return TRUE;
    3730  return FALSE;
     
    6154mrb_obj_inspect(mrb_state *mrb, mrb_value obj)
    6255{
    63   if ((mrb_type(obj) == MRB_TT_OBJECT) && mrb_obj_basic_to_s_p(mrb, obj)) {
     56  if (mrb_object_p(obj) && mrb_obj_basic_to_s_p(mrb, obj)) {
    6457    return mrb_obj_iv_inspect(mrb, mrb_obj_ptr(obj));
    6558  }
     
    135128mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
    136129{
    137   mrb_callinfo *ci = mrb->c->ci;
     130  mrb_callinfo *ci = &mrb->c->ci[-1];
     131  mrb_callinfo *cibase = mrb->c->cibase;
    138132  mrb_value *bp;
    139 
    140   bp = ci->stackent + 1;
    141   ci--;
    142   if (ci <= mrb->c->cibase) {
     133  struct RProc *p;
     134
     135  if (ci <= cibase) {
     136    /* toplevel does not have block */
    143137    return mrb_false_value();
    144138  }
    145   /* block_given? called within block; check upper scope */
    146   if (ci->proc->env) {
    147     struct REnv *e = ci->proc->env;
    148 
    149     while (e->c) {
    150       e = (struct REnv*)e->c;
    151     }
     139  p = ci->proc;
     140  /* search method/class/module proc */
     141  while (p) {
     142    if (MRB_PROC_SCOPE_P(p)) break;
     143    p = p->upper;
     144  }
     145  if (p == NULL) return mrb_false_value();
     146  /* search ci corresponding to proc */
     147  while (cibase < ci) {
     148    if (ci->proc == p) break;
     149    ci--;
     150  }
     151  if (ci == cibase) {
     152    return mrb_false_value();
     153  }
     154  else if (ci->env) {
     155    struct REnv *e = ci->env;
     156    int bidx;
     157
    152158    /* top-level does not have block slot (always false) */
    153159    if (e->stack == mrb->c->stbase)
    154160      return mrb_false_value();
    155     if (e->stack && e->cioff < 0) {
    156       /* use saved block arg position */
    157       bp = &e->stack[-e->cioff];
    158       ci = 0;                 /* no callinfo available */
     161    /* use saved block arg position */
     162    bidx = MRB_ENV_BIDX(e);
     163    /* bidx may be useless (e.g. define_method) */
     164    if (bidx >= MRB_ENV_STACK_LEN(e))
     165      return mrb_false_value();
     166    bp = &e->stack[bidx];
     167  }
     168  else {
     169    bp = ci[1].stackent+1;
     170    if (ci->argc >= 0) {
     171      bp += ci->argc;
    159172    }
    160173    else {
    161       ci = e->cxt.c->cibase + e->cioff;
    162       bp = ci[1].stackent + 1;
    163     }
    164   }
    165   if (ci && ci->argc > 0) {
    166     bp += ci->argc;
     174      bp++;
     175    }
    167176  }
    168177  if (mrb_nil_p(*bp))
     
    231240  /* if the origin is not the same as the class, then the origin and
    232241     the current class need to be copied */
    233   if (sc->flags & MRB_FLAG_IS_PREPENDED) {
     242  if (sc->flags & MRB_FL_CLASS_IS_PREPENDED) {
    234243    struct RClass *c0 = sc->super;
    235244    struct RClass *c1 = dc;
    236245
    237246    /* copy prepended iclasses */
    238     while (!(c0->flags & MRB_FLAG_IS_ORIGIN)) {
     247    while (!(c0->flags & MRB_FL_CLASS_IS_ORIGIN)) {
    239248      c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0)));
    240249      c1 = c1->super;
     
    242251    }
    243252    c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0)));
    244     c1->super->flags |= MRB_FLAG_IS_ORIGIN;
     253    c1->super->flags |= MRB_FL_CLASS_IS_ORIGIN;
    245254  }
    246255  if (sc->mt) {
     
    258267{
    259268  switch (mrb_type(obj)) {
     269    case MRB_TT_ICLASS:
     270      copy_class(mrb, dest, obj);
     271      return;
    260272    case MRB_TT_CLASS:
    261273    case MRB_TT_MODULE:
    262274      copy_class(mrb, dest, obj);
    263       /* fall through */
     275      mrb_iv_copy(mrb, dest, obj);
     276      mrb_iv_remove(mrb, dest, mrb_intern_lit(mrb, "__classname__"));
     277      break;
    264278    case MRB_TT_OBJECT:
    265279    case MRB_TT_SCLASS:
     
    312326
    313327  if (mrb_immediate_p(self)) {
    314     mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %S", self);
    315   }
    316   if (mrb_type(self) == MRB_TT_SCLASS) {
     328    mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %v", self);
     329  }
     330  if (mrb_sclass_p(self)) {
    317331    mrb_raise(mrb, E_TYPE_ERROR, "can't clone singleton class");
    318332  }
    319333  p = (struct RObject*)mrb_obj_alloc(mrb, mrb_type(self), mrb_obj_class(mrb, self));
    320334  p->c = mrb_singleton_class_clone(mrb, self);
     335  mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)p->c);
    321336  clone = mrb_obj_value(p);
    322337  init_copy(mrb, clone, self);
     338  p->flags |= mrb_obj_ptr(self)->flags & MRB_FL_OBJ_IS_FROZEN;
    323339
    324340  return clone;
     
    351367
    352368  if (mrb_immediate_p(obj)) {
    353     mrb_raisef(mrb, E_TYPE_ERROR, "can't dup %S", obj);
    354   }
    355   if (mrb_type(obj) == MRB_TT_SCLASS) {
     369    mrb_raisef(mrb, E_TYPE_ERROR, "can't dup %v", obj);
     370  }
     371  if (mrb_sclass_p(obj)) {
    356372    mrb_raise(mrb, E_TYPE_ERROR, "can't dup singleton class");
    357373  }
     
    369385
    370386  if (argc == 0) {
    371     mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (at least 1)");
     387    mrb_argnum_error(mrb, argc, 1, -1);
    372388  }
    373389  for (i = 0; i < argc; i++) {
     
    411427  mrb_value *argv;
    412428  mrb_int argc;
    413   mrb_value args;
    414429
    415430  mrb_get_args(mrb, "*", &argv, &argc);
    416   args = mrb_ary_new_from_values(mrb, argc, argv);
    417   argv = (mrb_value*)RARRAY_PTR(args);
    418431  return mrb_obj_extend(mrb, argc, argv, self);
    419432}
    420433
    421 static mrb_value
     434MRB_API mrb_value
    422435mrb_obj_freeze(mrb_state *mrb, mrb_value self)
    423436{
    424   struct RBasic *b;
    425 
    426   switch (mrb_type(self)) {
    427     case MRB_TT_FALSE:
    428     case MRB_TT_TRUE:
    429     case MRB_TT_FIXNUM:
    430     case MRB_TT_SYMBOL:
    431     case MRB_TT_FLOAT:
    432       return self;
    433     default:
    434       break;
    435   }
    436 
    437   b = mrb_basic_ptr(self);
    438   if (!MRB_FROZEN_P(b)) {
    439     MRB_SET_FROZEN_FLAG(b);
     437  if (!mrb_immediate_p(self)) {
     438    struct RBasic *b = mrb_basic_ptr(self);
     439    if (!mrb_frozen_p(b)) {
     440      MRB_SET_FROZEN_FLAG(b);
     441      if (b->c->tt == MRB_TT_SCLASS) MRB_SET_FROZEN_FLAG(b->c);
     442    }
    440443  }
    441444  return self;
     
    445448mrb_obj_frozen(mrb_state *mrb, mrb_value self)
    446449{
    447   struct RBasic *b;
    448 
    449   switch (mrb_type(self)) {
    450     case MRB_TT_FALSE:
    451     case MRB_TT_TRUE:
    452     case MRB_TT_FIXNUM:
    453     case MRB_TT_SYMBOL:
    454     case MRB_TT_FLOAT:
    455       return mrb_true_value();
    456     default:
    457       break;
    458   }
    459 
    460   b = mrb_basic_ptr(self);
    461   if (!MRB_FROZEN_P(b)) {
    462     return mrb_false_value();
    463   }
    464   return mrb_true_value();
     450  return mrb_bool_value(mrb_immediate_p(self) || mrb_frozen_p(mrb_basic_ptr(self)));
    465451}
    466452
     
    476462 *  <code>Fixnum</code> will be truncated before being used.
    477463 */
    478 MRB_API mrb_value
     464static mrb_value
    479465mrb_obj_hash(mrb_state *mrb, mrb_value self)
    480466{
     
    520506
    521507  return mrb_bool_value(mrb_obj_is_instance_of(mrb, self, mrb_class_ptr(arg)));
    522 }
    523 
    524 /* 15.3.1.3.20 */
    525 /*
    526  *  call-seq:
    527  *     obj.instance_variable_defined?(symbol)    -> true or false
    528  *
    529  *  Returns <code>true</code> if the given instance variable is
    530  *  defined in <i>obj</i>.
    531  *
    532  *     class Fred
    533  *       def initialize(p1, p2)
    534  *         @a, @b = p1, p2
    535  *       end
    536  *     end
    537  *     fred = Fred.new('cat', 99)
    538  *     fred.instance_variable_defined?(:@a)    #=> true
    539  *     fred.instance_variable_defined?("@b")   #=> true
    540  *     fred.instance_variable_defined?("@c")   #=> false
    541  */
    542 static mrb_value
    543 mrb_obj_ivar_defined(mrb_state *mrb, mrb_value self)
    544 {
    545   mrb_sym sym;
    546 
    547   mrb_get_args(mrb, "n", &sym);
    548   mrb_iv_check(mrb, sym);
    549   return mrb_bool_value(mrb_iv_defined(mrb, self, sym));
    550 }
    551 
    552 /* 15.3.1.3.21 */
    553 /*
    554  *  call-seq:
    555  *     obj.instance_variable_get(symbol)    -> obj
    556  *
    557  *  Returns the value of the given instance variable, or nil if the
    558  *  instance variable is not set. The <code>@</code> part of the
    559  *  variable name should be included for regular instance
    560  *  variables. Throws a <code>NameError</code> exception if the
    561  *  supplied symbol is not valid as an instance variable name.
    562  *
    563  *     class Fred
    564  *       def initialize(p1, p2)
    565  *         @a, @b = p1, p2
    566  *       end
    567  *     end
    568  *     fred = Fred.new('cat', 99)
    569  *     fred.instance_variable_get(:@a)    #=> "cat"
    570  *     fred.instance_variable_get("@b")   #=> 99
    571  */
    572 static mrb_value
    573 mrb_obj_ivar_get(mrb_state *mrb, mrb_value self)
    574 {
    575   mrb_sym iv_name;
    576 
    577   mrb_get_args(mrb, "n", &iv_name);
    578   mrb_iv_check(mrb, iv_name);
    579   return mrb_iv_get(mrb, self, iv_name);
    580 }
    581 
    582 /* 15.3.1.3.22 */
    583 /*
    584  *  call-seq:
    585  *     obj.instance_variable_set(symbol, obj)    -> obj
    586  *
    587  *  Sets the instance variable names by <i>symbol</i> to
    588  *  <i>object</i>, thereby frustrating the efforts of the class's
    589  *  author to attempt to provide proper encapsulation. The variable
    590  *  did not have to exist prior to this call.
    591  *
    592  *     class Fred
    593  *       def initialize(p1, p2)
    594  *         @a, @b = p1, p2
    595  *       end
    596  *     end
    597  *     fred = Fred.new('cat', 99)
    598  *     fred.instance_variable_set(:@a, 'dog')   #=> "dog"
    599  *     fred.instance_variable_set(:@c, 'cat')   #=> "cat"
    600  *     fred.inspect                             #=> "#<Fred:0x401b3da8 @a=\"dog\", @b=99, @c=\"cat\">"
    601  */
    602 static mrb_value
    603 mrb_obj_ivar_set(mrb_state *mrb, mrb_value self)
    604 {
    605   mrb_sym iv_name;
    606   mrb_value val;
    607 
    608   mrb_get_args(mrb, "no", &iv_name, &val);
    609   mrb_iv_check(mrb, iv_name);
    610   mrb_iv_set(mrb, self, iv_name, val);
    611   return val;
    612508}
    613509
     
    652548KHASH_DEFINE(st, mrb_sym, char, FALSE, kh_int_hash_func, kh_int_hash_equal)
    653549
    654 static void
    655 method_entry_loop(mrb_state *mrb, struct RClass* klass, khash_t(st)* set)
    656 {
    657   khint_t i;
    658 
    659   khash_t(mt) *h = klass->mt;
    660   if (!h) return;
    661   for (i=0;i<kh_end(h);i++) {
    662     if (kh_exist(h, i) && kh_value(h, i)) {
    663       kh_put(st, mrb, set, kh_key(h, i));
    664     }
    665   }
    666 }
    667 
    668 mrb_value
    669 mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* klass, int obj)
    670 {
    671   khint_t i;
    672   mrb_value ary;
    673   mrb_bool prepended = FALSE;
    674   struct RClass* oldklass;
    675   khash_t(st)* set = kh_init(st, mrb);
    676 
    677   if (!recur && (klass->flags & MRB_FLAG_IS_PREPENDED)) {
    678     MRB_CLASS_ORIGIN(klass);
    679     prepended = TRUE;
    680   }
    681 
    682   oldklass = 0;
    683   while (klass && (klass != oldklass)) {
    684     method_entry_loop(mrb, klass, set);
    685     if ((klass->tt == MRB_TT_ICLASS && !prepended) ||
    686         (klass->tt == MRB_TT_SCLASS)) {
    687     }
    688     else {
    689       if (!recur) break;
    690     }
    691     oldklass = klass;
    692     klass = klass->super;
    693   }
    694 
    695   ary = mrb_ary_new(mrb);
    696   for (i=0;i<kh_end(set);i++) {
    697     if (kh_exist(set, i)) {
    698       mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set, i)));
    699     }
    700   }
    701   kh_destroy(st, mrb, set);
    702 
    703   return ary;
    704 }
    705 
    706 static mrb_value
    707 mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj)
    708 {
    709   khint_t i;
    710   mrb_value ary;
    711   struct RClass* klass;
    712   khash_t(st)* set = kh_init(st, mrb);
    713 
    714   klass = mrb_class(mrb, obj);
    715 
    716   if (klass && (klass->tt == MRB_TT_SCLASS)) {
    717       method_entry_loop(mrb, klass, set);
    718       klass = klass->super;
    719   }
    720   if (recur) {
    721       while (klass && ((klass->tt == MRB_TT_SCLASS) || (klass->tt == MRB_TT_ICLASS))) {
    722         method_entry_loop(mrb, klass, set);
    723         klass = klass->super;
    724       }
    725   }
    726 
    727   ary = mrb_ary_new(mrb);
    728   for (i=0;i<kh_end(set);i++) {
    729     if (kh_exist(set, i)) {
    730       mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set, i)));
    731     }
    732   }
    733   kh_destroy(st, mrb, set);
    734 
    735   return ary;
    736 }
    737 
    738 static mrb_value
    739 mrb_obj_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj, mrb_method_flag_t flag)
    740 {
    741   return mrb_class_instance_method_list(mrb, recur, mrb_class(mrb, obj), 0);
    742 }
    743 /* 15.3.1.3.31 */
    744 /*
    745  *  call-seq:
    746  *     obj.methods    -> array
    747  *
    748  *  Returns a list of the names of methods publicly accessible in
    749  *  <i>obj</i>. This will include all the methods accessible in
    750  *  <i>obj</i>'s ancestors.
    751  *
    752  *     class Klass
    753  *       def kMethod()
    754  *       end
    755  *     end
    756  *     k = Klass.new
    757  *     k.methods[0..9]    #=> [:kMethod, :respond_to?, :nil?, :is_a?,
    758  *                        #    :class, :instance_variable_set,
    759  *                        #    :methods, :extend, :__send__, :instance_eval]
    760  *     k.methods.length   #=> 42
    761  */
    762 static mrb_value
    763 mrb_obj_methods_m(mrb_state *mrb, mrb_value self)
    764 {
    765   mrb_bool recur = TRUE;
    766   mrb_get_args(mrb, "|b", &recur);
    767   return mrb_obj_methods(mrb, recur, self, (mrb_method_flag_t)0); /* everything but private */
    768 }
    769 
    770550/* 15.3.1.3.32 */
    771551/*
     
    780560{
    781561  return mrb_false_value();
    782 }
    783 
    784 /* 15.3.1.3.36 */
    785 /*
    786  *  call-seq:
    787  *     obj.private_methods(all=true)   -> array
    788  *
    789  *  Returns the list of private methods accessible to <i>obj</i>. If
    790  *  the <i>all</i> parameter is set to <code>false</code>, only those methods
    791  *  in the receiver will be listed.
    792  */
    793 static mrb_value
    794 mrb_obj_private_methods(mrb_state *mrb, mrb_value self)
    795 {
    796   mrb_bool recur = TRUE;
    797   mrb_get_args(mrb, "|b", &recur);
    798   return mrb_obj_methods(mrb, recur, self, NOEX_PRIVATE); /* private attribute not define */
    799 }
    800 
    801 /* 15.3.1.3.37 */
    802 /*
    803  *  call-seq:
    804  *     obj.protected_methods(all=true)   -> array
    805  *
    806  *  Returns the list of protected methods accessible to <i>obj</i>. If
    807  *  the <i>all</i> parameter is set to <code>false</code>, only those methods
    808  *  in the receiver will be listed.
    809  */
    810 static mrb_value
    811 mrb_obj_protected_methods(mrb_state *mrb, mrb_value self)
    812 {
    813   mrb_bool recur = TRUE;
    814   mrb_get_args(mrb, "|b", &recur);
    815   return mrb_obj_methods(mrb, recur, self, NOEX_PROTECTED); /* protected attribute not define */
    816 }
    817 
    818 /* 15.3.1.3.38 */
    819 /*
    820  *  call-seq:
    821  *     obj.public_methods(all=true)   -> array
    822  *
    823  *  Returns the list of public methods accessible to <i>obj</i>. If
    824  *  the <i>all</i> parameter is set to <code>false</code>, only those methods
    825  *  in the receiver will be listed.
    826  */
    827 static mrb_value
    828 mrb_obj_public_methods(mrb_state *mrb, mrb_value self)
    829 {
    830   mrb_bool recur = TRUE;
    831   mrb_get_args(mrb, "|b", &recur);
    832   return mrb_obj_methods(mrb, recur, self, NOEX_PUBLIC); /* public attribute not define */
    833562}
    834563
     
    858587{
    859588  mrb_value a[2], exc;
    860   int argc;
     589  mrb_int argc;
    861590
    862591
     
    910639
    911640  mrb_get_args(mrb, "n", &sym);
    912   mrb_iv_check(mrb, sym);
     641  mrb_iv_name_sym_check(mrb, sym);
    913642  val = mrb_iv_remove(mrb, self, sym);
    914643  if (mrb_undef_p(val)) {
    915     mrb_name_error(mrb, sym, "instance variable %S not defined", mrb_sym2str(mrb, sym));
     644    mrb_name_error(mrb, sym, "instance variable %n not defined", sym);
    916645  }
    917646  return val;
     
    921650mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args)
    922651{
    923   mrb_sym inspect;
    924   mrb_value repr;
    925 
    926   inspect = mrb_intern_lit(mrb, "inspect");
    927   if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) {
    928     /* method missing in inspect; avoid recursion */
    929     repr = mrb_any_to_s(mrb, self);
    930   }
    931   else if (mrb_respond_to(mrb, self, inspect) && mrb->c->ci - mrb->c->cibase < 16) {
    932     repr = mrb_funcall_argv(mrb, self, inspect, 0, 0);
    933     if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) {
    934       repr = mrb_any_to_s(mrb, self);
    935     }
    936   }
    937   else {
    938     repr = mrb_any_to_s(mrb, self);
    939   }
    940 
    941   mrb_no_method_error(mrb, name, args, "undefined method '%S' for %S",
    942                       mrb_sym2str(mrb, name), repr);
     652  mrb_no_method_error(mrb, name, args, "undefined method '%n'", name);
    943653}
    944654
     
    976686 *     r.mm      #=> 2000
    977687 */
    978 #ifdef MRB_DEFAULT_METHOD_MISSING
    979688static mrb_value
    980689mrb_obj_missing(mrb_state *mrb, mrb_value mod)
     
    984693  mrb_int alen;
    985694
    986   mrb_get_args(mrb, "n*", &name, &a, &alen);
     695  mrb_get_args(mrb, "n*!", &name, &a, &alen);
    987696  mrb_method_missing(mrb, name, mod, mrb_ary_new_from_values(mrb, alen, a));
    988697  /* not reached */
    989698  return mrb_nil_value();
    990699}
    991 #endif
    992700
    993701static inline mrb_bool
     
    996704  return mrb_respond_to(mrb, obj, id);
    997705}
     706
    998707/* 15.3.1.3.43 */
    999708/*
     
    1015724obj_respond_to(mrb_state *mrb, mrb_value self)
    1016725{
    1017   mrb_value mid;
    1018726  mrb_sym id, rtm_id;
    1019   mrb_bool priv = FALSE, respond_to_p = TRUE;
    1020 
    1021   mrb_get_args(mrb, "o|b", &mid, &priv);
    1022 
    1023   if (mrb_symbol_p(mid)) {
    1024     id = mrb_symbol(mid);
    1025   }
    1026   else {
    1027     mrb_value tmp;
    1028     if (mrb_string_p(mid)) {
    1029       tmp = mrb_check_intern_str(mrb, mid);
    1030     }
    1031     else {
    1032       tmp = mrb_check_string_type(mrb, mid);
    1033       if (mrb_nil_p(tmp)) {
    1034         tmp = mrb_inspect(mrb, mid);
    1035         mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", tmp);
    1036       }
    1037       tmp = mrb_check_intern_str(mrb, tmp);
    1038     }
    1039     if (mrb_nil_p(tmp)) {
    1040       respond_to_p = FALSE;
    1041     }
    1042     else {
    1043       id = mrb_symbol(tmp);
    1044     }
    1045   }
    1046 
    1047   if (respond_to_p) {
    1048     respond_to_p = basic_obj_respond_to(mrb, self, id, !priv);
    1049   }
    1050 
     727  mrb_bool priv = FALSE, respond_to_p;
     728
     729  mrb_get_args(mrb, "n|b", &id, &priv);
     730  respond_to_p = basic_obj_respond_to(mrb, self, id, !priv);
    1051731  if (!respond_to_p) {
    1052732    rtm_id = mrb_intern_lit(mrb, "respond_to_missing?");
    1053733    if (basic_obj_respond_to(mrb, self, rtm_id, !priv)) {
    1054734      mrb_value args[2], v;
    1055       args[0] = mid;
     735      args[0] = mrb_symbol_value(id);
    1056736      args[1] = mrb_bool_value(priv);
    1057737      v = mrb_funcall_argv(mrb, self, rtm_id, 2, args);
     
    1060740  }
    1061741  return mrb_bool_value(respond_to_p);
    1062 }
    1063 
    1064 /* 15.3.1.3.45 */
    1065 /*
    1066  *  call-seq:
    1067  *     obj.singleton_methods(all=true)    -> array
    1068  *
    1069  *  Returns an array of the names of singleton methods for <i>obj</i>.
    1070  *  If the optional <i>all</i> parameter is true, the list will include
    1071  *  methods in modules included in <i>obj</i>.
    1072  *  Only public and protected singleton methods are returned.
    1073  *
    1074  *     module Other
    1075  *       def three() end
    1076  *     end
    1077  *
    1078  *     class Single
    1079  *       def Single.four() end
    1080  *     end
    1081  *
    1082  *     a = Single.new
    1083  *
    1084  *     def a.one()
    1085  *     end
    1086  *
    1087  *     class << a
    1088  *       include Other
    1089  *       def two()
    1090  *       end
    1091  *     end
    1092  *
    1093  *     Single.singleton_methods    #=> [:four]
    1094  *     a.singleton_methods(false)  #=> [:two, :one]
    1095  *     a.singleton_methods         #=> [:two, :one, :three]
    1096  */
    1097 static mrb_value
    1098 mrb_obj_singleton_methods_m(mrb_state *mrb, mrb_value self)
    1099 {
    1100   mrb_bool recur = TRUE;
    1101   mrb_get_args(mrb, "|b", &recur);
    1102   return mrb_obj_singleton_methods(mrb, recur, self);
    1103 }
    1104 
    1105 static mrb_value
    1106 mod_define_singleton_method(mrb_state *mrb, mrb_value self)
    1107 {
    1108   struct RProc *p;
    1109   mrb_sym mid;
    1110   mrb_value blk = mrb_nil_value();
    1111 
    1112   mrb_get_args(mrb, "n&", &mid, &blk);
    1113   if (mrb_nil_p(blk)) {
    1114     mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
    1115   }
    1116   p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
    1117   mrb_proc_copy(p, mrb_proc_ptr(blk));
    1118   p->flags |= MRB_PROC_STRICT;
    1119   mrb_define_method_raw(mrb, mrb_class_ptr(mrb_singleton_class(mrb, self)), mid, p);
    1120   return mrb_symbol_value(mid);
    1121742}
    1122743
     
    1138759}
    1139760
    1140 static mrb_value
    1141 mrb_local_variables(mrb_state *mrb, mrb_value self)
    1142 {
    1143   struct RProc *proc;
    1144   mrb_value vars;
    1145   struct mrb_irep *irep;
    1146   size_t i;
    1147 
    1148   proc = mrb->c->ci[-1].proc;
    1149 
    1150   if (MRB_PROC_CFUNC_P(proc)) {
    1151     return mrb_ary_new(mrb);
    1152   }
    1153 
    1154   irep = proc->body.irep;
    1155   if (!irep->lv) {
    1156     return mrb_ary_new(mrb);
    1157   }
    1158   vars = mrb_hash_new(mrb);
    1159   for (i = 0; i + 1 < irep->nlocals; ++i) {
    1160     if (irep->lv[i].name) {
    1161       mrb_hash_set(mrb, vars, mrb_symbol_value(irep->lv[i].name), mrb_true_value());
    1162     }
    1163   }
    1164   if (proc->env) {
    1165     struct REnv *e = proc->env;
    1166 
    1167     while (e) {
    1168       if (MRB_ENV_STACK_SHARED_P(e) &&
    1169           !MRB_PROC_CFUNC_P(e->cxt.c->cibase[e->cioff].proc)) {
    1170         irep = e->cxt.c->cibase[e->cioff].proc->body.irep;
    1171         if (irep->lv) {
    1172           for (i = 0; i + 1 < irep->nlocals; ++i) {
    1173             if (irep->lv[i].name) {
    1174               mrb_hash_set(mrb, vars, mrb_symbol_value(irep->lv[i].name), mrb_true_value());
    1175             }
    1176           }
    1177         }
    1178       }
    1179       e = (struct REnv*)e->c;
    1180     }
    1181   }
    1182 
    1183   return mrb_hash_keys(mrb, vars);
    1184 }
    1185 
    1186761mrb_value mrb_obj_equal_m(mrb_state *mrb, mrb_value);
     762
    1187763void
    1188764mrb_init_kernel(mrb_state *mrb)
     
    1192768  mrb->kernel_module = krn = mrb_define_module(mrb, "Kernel");                                                    /* 15.3.1 */
    1193769  mrb_define_class_method(mrb, krn, "block_given?",         mrb_f_block_given_p_m,           MRB_ARGS_NONE());    /* 15.3.1.2.2  */
    1194   mrb_define_class_method(mrb, krn, "global_variables",     mrb_f_global_variables,          MRB_ARGS_NONE());    /* 15.3.1.2.4  */
    1195770  mrb_define_class_method(mrb, krn, "iterator?",            mrb_f_block_given_p_m,           MRB_ARGS_NONE());    /* 15.3.1.2.5  */
    1196   mrb_define_class_method(mrb, krn, "local_variables",      mrb_local_variables,             MRB_ARGS_NONE());    /* 15.3.1.2.7  */
    1197771;     /* 15.3.1.2.11 */
    1198772  mrb_define_class_method(mrb, krn, "raise",                mrb_f_raise,                     MRB_ARGS_OPT(2));    /* 15.3.1.2.12 */
    1199773
    1200   mrb_define_method(mrb, krn, "singleton_class",            mrb_singleton_class,             MRB_ARGS_NONE());
    1201774
    1202775  mrb_define_method(mrb, krn, "===",                        mrb_equal_m,                     MRB_ARGS_REQ(1));    /* 15.3.1.3.2  */
     
    1206779  mrb_define_method(mrb, krn, "dup",                        mrb_obj_dup,                     MRB_ARGS_NONE());    /* 15.3.1.3.9  */
    1207780  mrb_define_method(mrb, krn, "eql?",                       mrb_obj_equal_m,                 MRB_ARGS_REQ(1));    /* 15.3.1.3.10 */
    1208   mrb_define_method(mrb, krn, "equal?",                     mrb_obj_equal_m,                 MRB_ARGS_REQ(1));    /* 15.3.1.3.11 */
    1209781  mrb_define_method(mrb, krn, "extend",                     mrb_obj_extend_m,                MRB_ARGS_ANY());     /* 15.3.1.3.13 */
    1210782  mrb_define_method(mrb, krn, "freeze",                     mrb_obj_freeze,                  MRB_ARGS_NONE());
    1211783  mrb_define_method(mrb, krn, "frozen?",                    mrb_obj_frozen,                  MRB_ARGS_NONE());
    1212   mrb_define_method(mrb, krn, "global_variables",           mrb_f_global_variables,          MRB_ARGS_NONE());    /* 15.3.1.3.14 */
    1213784  mrb_define_method(mrb, krn, "hash",                       mrb_obj_hash,                    MRB_ARGS_NONE());    /* 15.3.1.3.15 */
    1214785  mrb_define_method(mrb, krn, "initialize_copy",            mrb_obj_init_copy,               MRB_ARGS_REQ(1));    /* 15.3.1.3.16 */
    1215786  mrb_define_method(mrb, krn, "inspect",                    mrb_obj_inspect,                 MRB_ARGS_NONE());    /* 15.3.1.3.17 */
    1216787  mrb_define_method(mrb, krn, "instance_of?",               obj_is_instance_of,              MRB_ARGS_REQ(1));    /* 15.3.1.3.19 */
    1217   mrb_define_method(mrb, krn, "instance_variable_defined?", mrb_obj_ivar_defined,            MRB_ARGS_REQ(1));    /* 15.3.1.3.20 */
    1218   mrb_define_method(mrb, krn, "instance_variable_get",      mrb_obj_ivar_get,                MRB_ARGS_REQ(1));    /* 15.3.1.3.21 */
    1219   mrb_define_method(mrb, krn, "instance_variable_set",      mrb_obj_ivar_set,                MRB_ARGS_REQ(2));    /* 15.3.1.3.22 */
    1220   mrb_define_method(mrb, krn, "instance_variables",         mrb_obj_instance_variables,      MRB_ARGS_NONE());    /* 15.3.1.3.23 */
     788
    1221789  mrb_define_method(mrb, krn, "is_a?",                      mrb_obj_is_kind_of_m,            MRB_ARGS_REQ(1));    /* 15.3.1.3.24 */
    1222790  mrb_define_method(mrb, krn, "iterator?",                  mrb_f_block_given_p_m,           MRB_ARGS_NONE());    /* 15.3.1.3.25 */
    1223791  mrb_define_method(mrb, krn, "kind_of?",                   mrb_obj_is_kind_of_m,            MRB_ARGS_REQ(1));    /* 15.3.1.3.26 */
    1224   mrb_define_method(mrb, krn, "local_variables",            mrb_local_variables,             MRB_ARGS_NONE());    /* 15.3.1.3.28 */
    1225 #ifdef MRB_DEFAULT_METHOD_MISSING
    1226792  mrb_define_method(mrb, krn, "method_missing",             mrb_obj_missing,                 MRB_ARGS_ANY());     /* 15.3.1.3.30 */
    1227 #endif
    1228   mrb_define_method(mrb, krn, "methods",                    mrb_obj_methods_m,               MRB_ARGS_OPT(1));    /* 15.3.1.3.31 */
    1229793  mrb_define_method(mrb, krn, "nil?",                       mrb_false,                       MRB_ARGS_NONE());    /* 15.3.1.3.32 */
    1230794  mrb_define_method(mrb, krn, "object_id",                  mrb_obj_id_m,                    MRB_ARGS_NONE());    /* 15.3.1.3.33 */
    1231   mrb_define_method(mrb, krn, "private_methods",            mrb_obj_private_methods,         MRB_ARGS_OPT(1));    /* 15.3.1.3.36 */
    1232   mrb_define_method(mrb, krn, "protected_methods",          mrb_obj_protected_methods,       MRB_ARGS_OPT(1));    /* 15.3.1.3.37 */
    1233   mrb_define_method(mrb, krn, "public_methods",             mrb_obj_public_methods,          MRB_ARGS_OPT(1));    /* 15.3.1.3.38 */
    1234795  mrb_define_method(mrb, krn, "raise",                      mrb_f_raise,                     MRB_ARGS_ANY());     /* 15.3.1.3.40 */
    1235796  mrb_define_method(mrb, krn, "remove_instance_variable",   mrb_obj_remove_instance_variable,MRB_ARGS_REQ(1));    /* 15.3.1.3.41 */
    1236   mrb_define_method(mrb, krn, "respond_to?",                obj_respond_to,                  MRB_ARGS_ANY());     /* 15.3.1.3.43 */
    1237   mrb_define_method(mrb, krn, "send",                       mrb_f_send,                      MRB_ARGS_ANY());     /* 15.3.1.3.44 */
    1238   mrb_define_method(mrb, krn, "singleton_methods",          mrb_obj_singleton_methods_m,     MRB_ARGS_OPT(1));    /* 15.3.1.3.45 */
    1239   mrb_define_method(mrb, krn, "define_singleton_method",    mod_define_singleton_method,     MRB_ARGS_ANY());
     797  mrb_define_method(mrb, krn, "respond_to?",                obj_respond_to,                  MRB_ARGS_ARG(1,1));     /* 15.3.1.3.43 */
    1240798  mrb_define_method(mrb, krn, "to_s",                       mrb_any_to_s,                    MRB_ARGS_NONE());    /* 15.3.1.3.46 */
    1241799  mrb_define_method(mrb, krn, "__case_eqq",                 mrb_obj_ceqq,                    MRB_ARGS_REQ(1));    /* internal */
     800  mrb_define_method(mrb, krn, "__to_int",                   mrb_to_int,                      MRB_ARGS_NONE()); /* internal */
     801  mrb_define_method(mrb, krn, "__to_str",                   mrb_to_str,                      MRB_ARGS_NONE()); /* internal */
    1242802
    1243803  mrb_include_module(mrb, mrb->object_class, mrb->kernel_module);
    1244   mrb_alias_method(mrb, mrb->module_class, mrb_intern_lit(mrb, "dup"), mrb_intern_lit(mrb, "clone"));
    1245 }
     804}
  • EcnlProtoTool/trunk/mruby-2.1.1/src/load.c

    r331 r439  
    88#include <stdlib.h>
    99#include <string.h>
     10#include <math.h>
    1011#include <mruby/dump.h>
    1112#include <mruby/irep.h>
     
    2526#define FLAG_SRC_STATIC 0
    2627
    27 #define SIZE_ERROR_MUL(nmemb, size) ((nmemb) > SIZE_MAX / (size))
     28#define SIZE_ERROR_MUL(nmemb, size) ((size_t)(nmemb) > SIZE_MAX / (size))
    2829
    2930static size_t
     
    4142}
    4243
     44#ifndef MRB_WITHOUT_FLOAT
     45double mrb_str_len_to_dbl(mrb_state *mrb, const char *s, size_t len, mrb_bool badcheck);
     46
     47static double
     48str_to_double(mrb_state *mrb, const char *p, size_t len)
     49{
     50  /* `i`, `inf`, `infinity` */
     51  if (len > 0 && p[0] == 'i') return INFINITY;
     52
     53  /* `I`, `-inf`, `-infinity` */
     54  if (p[0] == 'I' || (len > 1 && p[0] == '-' && p[1] == 'i')) return -INFINITY;
     55  return mrb_str_len_to_dbl(mrb, p, len, TRUE);
     56}
     57#endif
     58
     59mrb_value mrb_str_len_to_inum(mrb_state *mrb, const char *str, mrb_int len, mrb_int base, int badcheck);
     60
    4361static mrb_irep*
    4462read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags)
    4563{
    46   size_t i;
     64  int i;
    4765  const uint8_t *src = bin;
    4866  ptrdiff_t diff;
    4967  uint16_t tt, pool_data_len, snl;
    50   size_t plen;
     68  int plen;
    5169  int ai = mrb_gc_arena_save(mrb);
    5270  mrb_irep *irep = mrb_add_irep(mrb);
     
    6987  /* Binary Data Section */
    7088  /* ISEQ BLOCK */
    71   irep->ilen = (size_t)bin_to_uint32(src);
     89  irep->ilen = (uint16_t)bin_to_uint32(src);
    7290  src += sizeof(uint32_t);
    7391  src += skip_padding(src);
     
    8098        (flags & FLAG_BYTEORDER_NATIVE)) {
    8199      irep->iseq = (mrb_code*)src;
    82       src += sizeof(uint32_t) * irep->ilen;
     100      src += sizeof(mrb_code) * irep->ilen;
    83101      irep->flags |= MRB_ISEQ_NO_FREE;
    84102    }
    85103    else {
    86       irep->iseq = (mrb_code *)mrb_malloc(mrb, sizeof(mrb_code) * irep->ilen);
    87       if (flags & FLAG_BYTEORDER_NATIVE) {
    88         memcpy(irep->iseq, src, sizeof(uint32_t) * irep->ilen);
    89         src += sizeof(uint32_t) * irep->ilen;
    90       }
    91       else if (flags & FLAG_BYTEORDER_BIG) {
    92         for (i = 0; i < irep->ilen; i++) {
    93           irep->iseq[i] = (mrb_code)bin_to_uint32(src);     /* iseq */
    94           src += sizeof(uint32_t);
    95         }
    96       }
    97       else {
    98         for (i = 0; i < irep->ilen; i++) {
    99           irep->iseq[i] = (mrb_code)bin_to_uint32l(src);     /* iseq */
    100           src += sizeof(uint32_t);
    101         }
    102       }
     104      size_t data_len = sizeof(mrb_code) * irep->ilen;
     105      void *buf = mrb_malloc(mrb, data_len);
     106      irep->iseq = (mrb_code *)buf;
     107      memcpy(buf, src, data_len);
     108      src += data_len;
    103109    }
    104110  }
    105111
    106112  /* POOL BLOCK */
    107   plen = (size_t)bin_to_uint32(src); /* number of pool */
     113  plen = bin_to_uint32(src); /* number of pool */
    108114  src += sizeof(uint32_t);
    109115  if (plen > 0) {
     
    114120
    115121    for (i = 0; i < plen; i++) {
    116       mrb_value s;
     122      const char *s;
     123      mrb_bool st = (flags & FLAG_SRC_MALLOC)==0;
    117124
    118125      tt = *src++; /* pool TT */
    119126      pool_data_len = bin_to_uint16(src); /* pool data length */
    120127      src += sizeof(uint16_t);
    121       if (flags & FLAG_SRC_MALLOC) {
    122         s = mrb_str_new(mrb, (char *)src, pool_data_len);
    123       }
    124       else {
    125         s = mrb_str_new_static(mrb, (char *)src, pool_data_len);
    126       }
     128      s = (const char*)src;
    127129      src += pool_data_len;
    128130      switch (tt) { /* pool data */
    129       case IREP_TT_FIXNUM:
    130         irep->pool[i] = mrb_str_to_inum(mrb, s, 10, FALSE);
     131      case IREP_TT_FIXNUM: {
     132        mrb_value num = mrb_str_len_to_inum(mrb, s, pool_data_len, 10, FALSE);
     133#ifdef MRB_WITHOUT_FLOAT
     134        irep->pool[i] = num;
     135#else
     136        irep->pool[i] = mrb_float_p(num)? mrb_float_pool(mrb, mrb_float(num)) : num;
     137#endif
     138        }
    131139        break;
    132140
     141#ifndef MRB_WITHOUT_FLOAT
    133142      case IREP_TT_FLOAT:
    134         irep->pool[i] = mrb_float_pool(mrb, mrb_str_to_dbl(mrb, s, FALSE));
     143        irep->pool[i] = mrb_float_pool(mrb, str_to_double(mrb, s, pool_data_len));
    135144        break;
     145#endif
    136146
    137147      case IREP_TT_STRING:
    138         irep->pool[i] = mrb_str_pool(mrb, s);
     148        irep->pool[i] = mrb_str_pool(mrb, s, pool_data_len, st);
    139149        break;
    140150
     
    150160
    151161  /* SYMS BLOCK */
    152   irep->slen = (size_t)bin_to_uint32(src);  /* syms length */
     162  irep->slen = (uint16_t)bin_to_uint32(src);  /* syms length */
    153163  src += sizeof(uint32_t);
    154164  if (irep->slen > 0) {
     
    192202{
    193203  mrb_irep *irep = read_irep_record_1(mrb, bin, len, flags);
    194   size_t i;
     204  int i;
    195205
    196206  if (irep == NULL) {
     
    222232
    223233static int
    224 read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t *len)
    225 {
    226   size_t i, fname_len, niseq;
    227   char *fname;
    228   uint16_t *lines;
    229 
    230   *len = 0;
    231   bin += sizeof(uint32_t); /* record size */
    232   *len += sizeof(uint32_t);
    233   fname_len = bin_to_uint16(bin);
    234   bin += sizeof(uint16_t);
    235   *len += sizeof(uint16_t);
    236   fname = (char *)mrb_malloc(mrb, fname_len + 1);
    237   memcpy(fname, bin, fname_len);
    238   fname[fname_len] = '\0';
    239   bin += fname_len;
    240   *len += fname_len;
    241 
    242   niseq = (size_t)bin_to_uint32(bin);
    243   bin += sizeof(uint32_t); /* niseq */
    244   *len += sizeof(uint32_t);
    245 
    246   if (SIZE_ERROR_MUL(niseq, sizeof(uint16_t))) {
    247     return MRB_DUMP_GENERAL_FAILURE;
    248   }
    249   lines = (uint16_t *)mrb_malloc(mrb, niseq * sizeof(uint16_t));
    250   for (i = 0; i < niseq; i++) {
    251     lines[i] = bin_to_uint16(bin);
    252     bin += sizeof(uint16_t); /* niseq */
    253     *len += sizeof(uint16_t);
    254   }
    255 
    256   irep->filename = fname;
    257   irep->lines = lines;
    258   return MRB_DUMP_OK;
    259 }
    260 
    261 static int
    262 read_lineno_record(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t *lenp)
    263 {
    264   int result = read_lineno_record_1(mrb, bin, irep, lenp);
    265   size_t i;
    266 
    267   if (result != MRB_DUMP_OK) return result;
    268   for (i = 0; i < irep->rlen; i++) {
    269     size_t len;
    270 
    271     result = read_lineno_record(mrb, bin, irep->reps[i], &len);
    272     if (result != MRB_DUMP_OK) break;
    273     bin += len;
    274     *lenp += len;
    275   }
    276   return result;
    277 }
    278 
    279 static int
    280 read_section_lineno(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep)
    281 {
    282   size_t len;
    283 
    284   len = 0;
    285   bin += sizeof(struct rite_section_lineno_header);
    286 
    287   /* Read Binary Data Section */
    288   return read_lineno_record(mrb, bin, irep, &len);
    289 }
    290 
    291 static int
    292234read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *record_len, const mrb_sym *filenames, size_t filenames_len)
    293235{
    294236  const uint8_t *bin = start;
    295237  ptrdiff_t diff;
    296   size_t record_size, i;
     238  size_t record_size;
    297239  uint16_t f_idx;
     240  int i;
    298241
    299242  if (irep->debug_info) { return MRB_DUMP_INVALID_IREP; }
    300243
    301244  irep->debug_info = (mrb_irep_debug_info*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info));
    302   irep->debug_info->pc_count = irep->ilen;
     245  irep->debug_info->pc_count = (uint32_t)irep->ilen;
    303246
    304247  record_size = (size_t)bin_to_uint32(bin);
     
    312255    mrb_irep_debug_info_file *file;
    313256    uint16_t filename_idx;
    314     mrb_int len;
    315257
    316258    file = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*file));
     
    325267    mrb_assert(filename_idx < filenames_len);
    326268    file->filename_sym = filenames[filename_idx];
    327     len = 0;
    328     file->filename = mrb_sym2name_len(mrb, file->filename_sym, &len);
    329269
    330270    file->line_entry_count = bin_to_uint32(bin);
     
    433373{
    434374  const uint8_t *bin = start;
    435   size_t i;
    436375  ptrdiff_t diff;
     376  int i;
    437377
    438378  irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (irep->nlocals - 1));
     
    517457
    518458static int
    519 read_binary_header(const uint8_t *bin, size_t *bin_size, uint16_t *crc, uint8_t *flags)
     459read_binary_header(const uint8_t *bin, size_t bufsize, size_t *bin_size, uint16_t *crc, uint8_t *flags)
    520460{
    521461  const struct rite_binary_header *header = (const struct rite_binary_header *)bin;
     462
     463  if (bufsize < sizeof(struct rite_binary_header)) {
     464    return MRB_DUMP_READ_FAULT;
     465  }
    522466
    523467  if (memcmp(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)) == 0) {
     
    537481  }
    538482
     483  if (memcmp(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version)) != 0) {
     484    return MRB_DUMP_INVALID_FILE_HEADER;
     485  }
     486
    539487  if (crc) {
    540488    *crc = bin_to_uint16(header->binary_crc);
     
    542490  *bin_size = (size_t)bin_to_uint32(header->binary_size);
    543491
     492  if (bufsize < *bin_size) {
     493    return MRB_DUMP_READ_FAULT;
     494  }
     495
    544496  return MRB_DUMP_OK;
    545497}
    546498
    547499static mrb_irep*
    548 read_irep(mrb_state *mrb, const uint8_t *bin, uint8_t flags)
     500read_irep(mrb_state *mrb, const uint8_t *bin, size_t bufsize, uint8_t flags)
    549501{
    550502  int result;
     
    559511  }
    560512
    561   result = read_binary_header(bin, &bin_size, &crc, &flags);
     513  result = read_binary_header(bin, bufsize, &bin_size, &crc, &flags);
    562514  if (result != MRB_DUMP_OK) {
    563515    return NULL;
     
    576528      if (!irep) return NULL;
    577529    }
    578     else if (memcmp(section_header->section_ident, RITE_SECTION_LINENO_IDENT, sizeof(section_header->section_ident)) == 0) {
    579       if (!irep) return NULL;   /* corrupted data */
    580       result = read_section_lineno(mrb, bin, irep);
    581       if (result < MRB_DUMP_OK) {
    582         return NULL;
    583       }
    584     }
    585530    else if (memcmp(section_header->section_ident, RITE_SECTION_DEBUG_IDENT, sizeof(section_header->section_ident)) == 0) {
    586531      if (!irep) return NULL;   /* corrupted data */
     
    606551mrb_read_irep(mrb_state *mrb, const uint8_t *bin)
    607552{
    608 #ifdef MRB_USE_ETEXT_EDATA
     553#if defined(MRB_USE_LINK_TIME_RO_DATA_P) || defined(MRB_USE_CUSTOM_RO_DATA_P)
    609554  uint8_t flags = mrb_ro_data_p((char*)bin) ? FLAG_SRC_STATIC : FLAG_SRC_MALLOC;
    610555#else
     
    612557#endif
    613558
    614   return read_irep(mrb, bin, flags);
     559  return read_irep(mrb, bin, (size_t)-1, flags);
     560}
     561
     562MRB_API mrb_irep*
     563mrb_read_irep_buf(mrb_state *mrb, const void *buf, size_t bufsize)
     564{
     565  return read_irep(mrb, (const uint8_t *)buf, bufsize, FLAG_SRC_MALLOC);
    615566}
    616567
     
    623574}
    624575
    625 MRB_API mrb_value
    626 mrb_load_irep_cxt(mrb_state *mrb, const uint8_t *bin, mrbc_context *c)
    627 {
    628   mrb_irep *irep = mrb_read_irep(mrb, bin);
     576void mrb_codedump_all(mrb_state*, struct RProc*);
     577
     578static mrb_value
     579load_irep(mrb_state *mrb, mrb_irep *irep, mrbc_context *c)
     580{
    629581  struct RProc *proc;
    630582
     
    634586  }
    635587  proc = mrb_proc_new(mrb, irep);
     588  proc->c = NULL;
    636589  mrb_irep_decref(mrb, irep);
     590  if (c && c->dump_result) mrb_codedump_all(mrb, proc);
    637591  if (c && c->no_exec) return mrb_obj_value(proc);
    638592  return mrb_top_run(mrb, proc, mrb_top_self(mrb), 0);
     
    640594
    641595MRB_API mrb_value
     596mrb_load_irep_cxt(mrb_state *mrb, const uint8_t *bin, mrbc_context *c)
     597{
     598  return load_irep(mrb, mrb_read_irep(mrb, bin), c);
     599}
     600
     601MRB_API mrb_value
     602mrb_load_irep_buf_cxt(mrb_state *mrb, const void *buf, size_t bufsize, mrbc_context *c)
     603{
     604  return load_irep(mrb, mrb_read_irep_buf(mrb, buf, bufsize), c);
     605}
     606
     607MRB_API mrb_value
    642608mrb_load_irep(mrb_state *mrb, const uint8_t *bin)
    643609{
    644610  return mrb_load_irep_cxt(mrb, bin, NULL);
     611}
     612
     613MRB_API mrb_value
     614mrb_load_irep_buf(mrb_state *mrb, const void *buf, size_t bufsize)
     615{
     616  return mrb_load_irep_buf_cxt(mrb, buf, bufsize, NULL);
    645617}
    646618
     
    665637    goto irep_exit;
    666638  }
    667   result = read_binary_header(buf, &buf_size, NULL, &flags);
     639  result = read_binary_header(buf, (size_t)-1, &buf_size, NULL, &flags);
    668640  if (result != MRB_DUMP_OK || buf_size <= header_size) {
    669641    goto irep_exit;
     
    674646    goto irep_exit;
    675647  }
    676   irep = read_irep(mrb, buf, FLAG_SRC_MALLOC);
     648  irep = read_irep(mrb, buf, (size_t)-1, FLAG_SRC_MALLOC);
    677649
    678650irep_exit:
     
    681653}
    682654
    683 void mrb_codedump_all(mrb_state*, struct RProc*);
    684 
    685655MRB_API mrb_value
    686656mrb_load_irep_file_cxt(mrb_state *mrb, FILE* fp, mrbc_context *c)
    687657{
    688   mrb_irep *irep = mrb_read_irep_file(mrb, fp);
    689   mrb_value val;
    690   struct RProc *proc;
    691 
    692   if (!irep) {
    693     irep_error(mrb);
    694     return mrb_nil_value();
    695   }
    696   proc = mrb_proc_new(mrb, irep);
    697   mrb_irep_decref(mrb, irep);
    698   if (c && c->dump_result) mrb_codedump_all(mrb, proc);
    699   if (c && c->no_exec) return mrb_obj_value(proc);
    700   val = mrb_top_run(mrb, proc, mrb_top_self(mrb), 0);
    701   return val;
     658  return load_irep(mrb, mrb_read_irep_file(mrb, fp), c);
    702659}
    703660
  • EcnlProtoTool/trunk/mruby-2.1.1/src/mruby_core.rake

    r331 r439  
    1212    objs += %w(vm error).map { |v| compile_as_cxx "#{current_dir}/#{v}.c", "#{current_build_dir}/#{v}.cxx" }
    1313  end
    14   self.libmruby << objs
     14  self.libmruby_objs << objs
    1515
    16   file libfile("#{build_dir}/lib/libmruby_core") => objs do |t|
     16  file libmruby_core_static => objs do |t|
    1717    archiver.run t.name, t.prerequisites
    1818  end
  • EcnlProtoTool/trunk/mruby-2.1.1/src/numeric.c

    r331 r439  
    55*/
    66
     7#ifndef MRB_WITHOUT_FLOAT
    78#include <float.h>
     9#include <math.h>
     10#endif
    811#include <limits.h>
    9 #include <math.h>
    1012#include <stdlib.h>
     13#include <string.h>
    1114
    1215#include <mruby.h>
     
    1619#include <mruby/class.h>
    1720
     21#ifndef MRB_WITHOUT_FLOAT
    1822#ifdef MRB_USE_FLOAT
    1923#define trunc(f) truncf(f)
     
    2125#define ceil(f) ceilf(f)
    2226#define fmod(x,y) fmodf(x,y)
    23 #define MRB_FLO_TO_STR_FMT "%.7g"
    24 #else
    25 #define MRB_FLO_TO_STR_FMT "%.14g"
    26 #endif
    27 
     27#define FLO_TO_STR_PREC 8
     28#else
     29#define FLO_TO_STR_PREC 16
     30#endif
     31#endif
     32
     33#ifndef MRB_WITHOUT_FLOAT
    2834MRB_API mrb_float
    2935mrb_to_flo(mrb_state *mrb, mrb_value val)
     
    4046}
    4147
     48MRB_API mrb_value
     49mrb_int_value(mrb_state *mrb, mrb_float f)
     50{
     51  if (FIXABLE_FLOAT(f)) {
     52    return mrb_fixnum_value((mrb_int)f);
     53  }
     54  return mrb_float_value(mrb, f);
     55}
     56#endif
     57
    4258/*
    4359 * call-seq:
     
    5066 */
    5167static mrb_value
    52 num_pow(mrb_state *mrb, mrb_value x)
    53 {
    54   mrb_value y;
     68integral_pow(mrb_state *mrb, mrb_value x)
     69{
     70  mrb_value y;
     71#ifndef MRB_WITHOUT_FLOAT
    5572  mrb_float d;
     73#endif
    5674
    5775  mrb_get_args(mrb, "o", &y);
     
    6280    mrb_int result = 1;
    6381
    64     if (exp < 0) goto float_pow;
     82    if (exp < 0)
     83#ifdef MRB_WITHOUT_FLOAT
     84      return mrb_fixnum_value(0);
     85#else
     86      goto float_pow;
     87#endif
    6588    for (;;) {
    6689      if (exp & 1) {
    6790        if (mrb_int_mul_overflow(result, base, &result)) {
     91#ifndef MRB_WITHOUT_FLOAT
    6892          goto float_pow;
     93#endif
    6994        }
    7095      }
     
    7297      if (exp == 0) break;
    7398      if (mrb_int_mul_overflow(base, base, &base)) {
     99#ifndef MRB_WITHOUT_FLOAT
    74100        goto float_pow;
     101#endif
    75102      }
    76103    }
    77104    return mrb_fixnum_value(result);
    78105  }
     106#ifdef MRB_WITHOUT_FLOAT
     107  mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
     108#else
    79109 float_pow:
    80110  d = pow(mrb_to_flo(mrb, x), mrb_to_flo(mrb, y));
    81111  return mrb_float_value(mrb, d);
     112#endif
     113}
     114
     115static mrb_value
     116integral_idiv(mrb_state *mrb, mrb_value x)
     117{
     118#ifdef MRB_WITHOUT_FLOAT
     119  mrb_value y;
     120
     121  mrb_get_args(mrb, "o", &y);
     122  if (!mrb_fixnum_p(y)) {
     123    mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
     124  }
     125  return mrb_fixnum_value(mrb_fixnum(x) / mrb_fixnum(y));
     126#else
     127  mrb_float y;
     128
     129  mrb_get_args(mrb, "f", &y);
     130  return mrb_int_value(mrb, mrb_to_flo(mrb, x) / y);
     131#endif
    82132}
    83133
     
    93143 */
    94144
    95 mrb_value
    96 mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y)
    97 {
    98   return mrb_float_value(mrb, mrb_to_flo(mrb, x) / mrb_to_flo(mrb, y));
    99 }
    100 
    101145/* 15.2.9.3.19(x) */
    102146/*
     
    108152
    109153static mrb_value
    110 num_div(mrb_state *mrb, mrb_value x)
    111 {
     154integral_div(mrb_state *mrb, mrb_value x)
     155{
     156#ifdef MRB_WITHOUT_FLOAT
     157  mrb_value y;
     158
     159  mrb_get_args(mrb, "o", &y);
     160  if (!mrb_fixnum_p(y)) {
     161    mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
     162  }
     163  return mrb_fixnum_value(mrb_fixnum(x) / mrb_fixnum(y));
     164#else
    112165  mrb_float y;
    113166
    114167  mrb_get_args(mrb, "f", &y);
    115168  return mrb_float_value(mrb, mrb_to_flo(mrb, x) / y);
    116 }
    117 
     169#endif
     170}
     171
     172static mrb_value
     173integral_coerce_step_counter(mrb_state *mrb, mrb_value self)
     174{
     175  mrb_value num, step;
     176
     177  mrb_get_args(mrb, "oo", &num, &step);
     178
     179#ifndef MRB_WITHOUT_FLOAT
     180  if (mrb_float_p(self) || mrb_float_p(num) || mrb_float_p(step)) {
     181    return mrb_Float(mrb, self);
     182  }
     183#endif
     184
     185  return self;
     186}
     187
     188#ifndef MRB_WITHOUT_FLOAT
    118189/********************************************************************
    119190 *
     
    139210flo_to_s(mrb_state *mrb, mrb_value flt)
    140211{
    141   if (isnan(mrb_float(flt))) {
     212  mrb_float f = mrb_float(flt);
     213
     214  if (isinf(f)) {
     215    return f < 0 ? mrb_str_new_lit(mrb, "-Infinity")
     216                 : mrb_str_new_lit(mrb, "Infinity");
     217  }
     218  else if (isnan(f)) {
    142219    return mrb_str_new_lit(mrb, "NaN");
    143220  }
    144   return mrb_float_to_str(mrb, flt, MRB_FLO_TO_STR_FMT);
     221  else {
     222    char fmt[] = "%." MRB_STRINGIZE(FLO_TO_STR_PREC) "g";
     223    mrb_value str = mrb_float_to_str(mrb, flt, fmt);
     224    mrb_int len;
     225    char *begp, *p, *endp;
     226
     227    insert_dot_zero:
     228    begp = RSTRING_PTR(str);
     229    len = RSTRING_LEN(str);
     230    for (p = begp, endp = p + len; p < endp; ++p) {
     231      if (*p == '.') {
     232        return str;
     233      }
     234      else if (*p == 'e') {
     235        ptrdiff_t e_pos = p - begp;
     236        mrb_str_cat(mrb, str, ".0", 2);
     237        p = RSTRING_PTR(str) + e_pos;
     238        memmove(p + 2, p, len - e_pos);
     239        memcpy(p, ".0", 2);
     240        return str;
     241      }
     242    }
     243
     244    if (FLO_TO_STR_PREC + (begp[0] == '-') <= len) {
     245      --fmt[sizeof(fmt) - 3];  /* %.16g(%.8g) -> %.15g(%.7g) */
     246      str = mrb_float_to_str(mrb, flt, fmt);
     247      goto insert_dot_zero;
     248    }
     249
     250    return str;
     251  }
    145252}
    146253
     
    182289
    183290static void
    184 flodivmod(mrb_state *mrb, mrb_float x, mrb_float y, mrb_float *divp, mrb_float *modp)
    185 {
    186   mrb_float div;
    187   mrb_float mod;
    188 
     291flodivmod(mrb_state *mrb, double x, double y, mrb_float *divp, mrb_float *modp)
     292{
     293  double div, mod;
     294
     295  if (isnan(y)) {
     296    /* y is NaN so all results are NaN */
     297    div = mod = y;
     298    goto exit;
     299  }
    189300  if (y == 0.0) {
    190     div = INFINITY;
     301    if (x == 0) div = NAN;
     302    else if (x > 0.0) div = INFINITY;
     303    else div = -INFINITY;       /* x < 0.0 */
    191304    mod = NAN;
     305    goto exit;
     306  }
     307  if ((x == 0.0) || (isinf(y) && !isinf(x))) {
     308    mod = x;
    192309  }
    193310  else {
    194311    mod = fmod(x, y);
    195     if (isinf(x) && isfinite(y))
    196       div = x;
    197     else
    198       div = (x - mod) / y;
    199     if (y*mod < 0) {
    200       mod += y;
    201       div -= 1.0;
    202     }
    203   }
    204 
     312  }
     313  if (isinf(x) && !isinf(y)) {
     314    div = x;
     315  }
     316  else {
     317    div = (x - mod) / y;
     318    if (modp && divp) div = round(div);
     319  }
     320  if (div == 0) div = 0.0;
     321  if (mod == 0) mod = 0.0;
     322  if (y*mod < 0) {
     323    mod += y;
     324    div -= 1.0;
     325  }
     326 exit:
    205327  if (modp) *modp = mod;
    206328  if (divp) *divp = div;
     
    230352  return mrb_float_value(mrb, mod);
    231353}
     354#endif
    232355
    233356/* 15.2.8.3.16 */
     
    253376}
    254377
     378#ifndef MRB_WITHOUT_FLOAT
    255379static mrb_value
    256380flo_eql(mrb_state *mrb, mrb_value x)
     
    260384  mrb_get_args(mrb, "o", &y);
    261385  if (!mrb_float_p(y)) return mrb_false_value();
    262   return mrb_bool_value(mrb_float(x) == (mrb_float)mrb_fixnum(y));
     386  return mrb_bool_value(mrb_float(x) == mrb_float(y));
    263387}
    264388
     
    312436int64_value(mrb_state *mrb, int64_t v)
    313437{
    314   if (FIXABLE(v)) {
     438  if (TYPED_FIXABLE(v,int64_t)) {
    315439    return mrb_fixnum_value((mrb_int)v);
    316440  }
     
    322446{
    323447  int64_t v1;
    324   mrb_get_args(mrb, "");
    325448  v1 = (int64_t)mrb_float(x);
    326449  return int64_value(mrb, ~v1);
     
    375498    while (width++) {
    376499      val /= 2;
     500      if (val < 1.0) {
     501        val = 0;
     502        break;
     503      }
    377504    }
    378505#if defined(_ISOC99_SOURCE)
    379506    val = trunc(val);
    380507#else
    381     val = val > 0 ? floor(val) : ceil(val);
     508    if (val > 0){
     509        val = floor(val);
     510    } else {
     511        val = ceil(val);
     512    }
    382513#endif
    383514    if (val == 0 && mrb_float(x) < 0) {
     
    390521    }
    391522  }
    392   if (FIXABLE_FLOAT(val)) {
    393     return mrb_fixnum_value((mrb_int)val);
    394   }
    395   return mrb_float_value(mrb, val);
    396 }
    397 
    398 static mrb_value
    399 flo_lshift(mrb_state *mrb, mrb_value x)
     523  return mrb_int_value(mrb, val);
     524}
     525
     526static mrb_value
     527flo_rshift(mrb_state *mrb, mrb_value x)
    400528{
    401529  mrb_int width;
     
    406534
    407535static mrb_value
    408 flo_rshift(mrb_state *mrb, mrb_value x)
     536flo_lshift(mrb_state *mrb, mrb_value x)
    409537{
    410538  mrb_int width;
     
    412540  mrb_get_args(mrb, "i", &width);
    413541  return flo_shift(mrb, x, width);
    414 }
    415 
    416 /* 15.2.8.3.18 */
    417 /*
    418  * call-seq:
    419  *   flt.hash  ->  integer
    420  *
    421  * Returns a hash code for this float.
    422  */
    423 static mrb_value
    424 flo_hash(mrb_state *mrb, mrb_value num)
    425 {
    426   mrb_float d;
    427   char *c;
    428   size_t i;
    429   mrb_int hash;
    430 
    431   d = (mrb_float)mrb_fixnum(num);
    432   /* normalize -0.0 to 0.0 */
    433   if (d == 0) d = 0.0;
    434   c = (char*)&d;
    435   for (hash=0,i=0; i<sizeof(mrb_float); i++) {
    436     hash = (hash * 971) ^ (unsigned char)c[i];
    437   }
    438   if (hash < 0) hash = -hash;
    439   return mrb_fixnum_value(hash);
    440542}
    441543
     
    525627
    526628  mrb_check_num_exact(mrb, f);
    527   if (!FIXABLE_FLOAT(f)) {
    528     return mrb_float_value(mrb, f);
    529   }
    530   return mrb_fixnum_value((mrb_int)f);
     629  return mrb_int_value(mrb, f);
    531630}
    532631
     
    551650
    552651  mrb_check_num_exact(mrb, f);
    553   if (!FIXABLE_FLOAT(f)) {
    554     return mrb_float_value(mrb, f);
    555   }
    556   return mrb_fixnum_value((mrb_int)f);
     652  return mrb_int_value(mrb, f);
    557653}
    558654
     
    605701  f = 1.0;
    606702  i = ndigits >= 0 ? ndigits : -ndigits;
     703  if (ndigits > DBL_DIG+2) return num;
    607704  while  (--i >= 0)
    608705    f = f*10.0;
     
    635732    return mrb_float_value(mrb, number);
    636733  }
    637   return mrb_fixnum_value((mrb_int)number);
     734  return mrb_int_value(mrb, number);
    638735}
    639736
     
    643740 *  call-seq:
    644741 *     flt.to_i      ->  integer
    645  *     flt.to_int    ->  integer
    646742 *     flt.truncate  ->  integer
    647743 *
     
    658754
    659755  mrb_check_num_exact(mrb, f);
    660   if (!FIXABLE_FLOAT(f)) {
    661     return mrb_float_value(mrb, f);
    662   }
    663   return mrb_fixnum_value((mrb_int)f);
     756  return mrb_int_value(mrb, f);
    664757}
    665758
     
    669762  return mrb_bool_value(isnan(mrb_float(num)));
    670763}
     764#endif
    671765
    672766/*
     
    682776 *  call-seq:
    683777 *     int.to_i      ->  integer
    684  *     int.to_int    ->  integer
    685778 *
    686779 *  As <i>int</i> is already an <code>Integer</code>, all these
     
    694787}
    695788
    696 mrb_value
    697 mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y)
     789static mrb_value
     790fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y)
    698791{
    699792  mrb_int a;
     
    706799    b = mrb_fixnum(y);
    707800    if (mrb_int_mul_overflow(a, b, &c)) {
     801#ifndef MRB_WITHOUT_FLOAT
    708802      return mrb_float_value(mrb, (mrb_float)a * (mrb_float)b);
     803#endif
    709804    }
    710805    return mrb_fixnum_value(c);
    711806  }
     807#ifdef MRB_WITHOUT_FLOAT
     808  mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
     809#else
    712810  return mrb_float_value(mrb, (mrb_float)a * mrb_to_flo(mrb, y));
     811#endif
     812}
     813
     814MRB_API mrb_value
     815mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y)
     816{
     817  if (mrb_fixnum_p(x)) {
     818    return fixnum_mul(mrb, x, y);
     819  }
     820#ifndef MRB_WITHOUT_FLOAT
     821  if (mrb_float_p(x)) {
     822    return mrb_float_value(mrb, mrb_float(x) * mrb_to_flo(mrb, y));
     823  }
     824#endif
     825  mrb_raise(mrb, E_TYPE_ERROR, "no number multiply");
     826  return mrb_nil_value();       /* not reached */
    713827}
    714828
     
    729843
    730844  mrb_get_args(mrb, "o", &y);
    731   return mrb_fixnum_mul(mrb, x, y);
     845  return fixnum_mul(mrb, x, y);
    732846}
    733847
     
    774888{
    775889  mrb_value y;
    776   mrb_int a;
     890  mrb_int a, b;
    777891
    778892  mrb_get_args(mrb, "o", &y);
    779893  a = mrb_fixnum(x);
    780   if (mrb_fixnum_p(y)) {
    781     mrb_int b, mod;
    782 
    783     if ((b=mrb_fixnum(y)) == 0) {
     894   if (mrb_fixnum_p(y) && a != MRB_INT_MIN && (b=mrb_fixnum(y)) != MRB_INT_MIN) {
     895    mrb_int mod;
     896
     897    if (b == 0) {
     898#ifdef MRB_WITHOUT_FLOAT
     899      /* ZeroDivisionError */
     900      return mrb_fixnum_value(0);
     901#else
     902      if (a > 0) return mrb_float_value(mrb, INFINITY);
     903      if (a < 0) return mrb_float_value(mrb, INFINITY);
    784904      return mrb_float_value(mrb, NAN);
    785     }
    786     fixdivmod(mrb, a, b, 0, &mod);
     905#endif
     906    }
     907    fixdivmod(mrb, a, b, NULL, &mod);
    787908    return mrb_fixnum_value(mod);
    788909  }
     910#ifdef MRB_WITHOUT_FLOAT
     911  mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
     912#else
    789913  else {
    790914    mrb_float mod;
    791915
    792     flodivmod(mrb, (mrb_float)a, mrb_to_flo(mrb, y), 0, &mod);
     916    flodivmod(mrb, (mrb_float)a, mrb_to_flo(mrb, y), NULL, &mod);
    793917    return mrb_float_value(mrb, mod);
    794918  }
     919#endif
    795920}
    796921
     
    812937
    813938    if (mrb_fixnum(y) == 0) {
    814       return mrb_assoc_new(mrb, mrb_float_value(mrb, INFINITY),
    815         mrb_float_value(mrb, NAN));
     939#ifdef MRB_WITHOUT_FLOAT
     940      return mrb_assoc_new(mrb, mrb_fixnum_value(0), mrb_fixnum_value(0));
     941#else
     942      return mrb_assoc_new(mrb, ((mrb_fixnum(x) == 0) ?
     943                                 mrb_float_value(mrb, NAN):
     944                                 mrb_float_value(mrb, INFINITY)),
     945                           mrb_float_value(mrb, NAN));
     946#endif
    816947    }
    817948    fixdivmod(mrb, mrb_fixnum(x), mrb_fixnum(y), &div, &mod);
    818949    return mrb_assoc_new(mrb, mrb_fixnum_value(div), mrb_fixnum_value(mod));
    819950  }
     951#ifdef MRB_WITHOUT_FLOAT
     952  mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
     953#else
    820954  else {
    821955    mrb_float div, mod;
     
    823957
    824958    flodivmod(mrb, (mrb_float)mrb_fixnum(x), mrb_to_flo(mrb, y), &div, &mod);
    825     a = mrb_float_value(mrb, (mrb_int)div);
     959    a = mrb_int_value(mrb, div);
    826960    b = mrb_float_value(mrb, mod);
    827961    return mrb_assoc_new(mrb, a, b);
    828962  }
    829 }
    830 
     963#endif
     964}
     965
     966#ifndef MRB_WITHOUT_FLOAT
    831967static mrb_value
    832968flo_divmod(mrb_state *mrb, mrb_value x)
     
    839975
    840976  flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), &div, &mod);
    841   a = mrb_float_value(mrb, (mrb_int)div);
     977  a = mrb_int_value(mrb, div);
    842978  b = mrb_float_value(mrb, mod);
    843979  return mrb_assoc_new(mrb, a, b);
    844980}
     981#endif
    845982
    846983/* 15.2.8.3.7  */
     
    8651002  case MRB_TT_FIXNUM:
    8661003    return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y));
     1004#ifndef MRB_WITHOUT_FLOAT
    8671005  case MRB_TT_FLOAT:
    8681006    return mrb_bool_value((mrb_float)mrb_fixnum(x) == mrb_float(y));
     1007#endif
    8691008  default:
    8701009    return mrb_false_value();
     
    8911030}
    8921031
     1032#ifdef MRB_WITHOUT_FLOAT
     1033#define bit_op(x,y,op1,op2) do {\
     1034  return mrb_fixnum_value(mrb_fixnum(x) op2 mrb_fixnum(y));\
     1035} while(0)
     1036#else
    8931037static mrb_value flo_and(mrb_state *mrb, mrb_value x);
    8941038static mrb_value flo_or(mrb_state *mrb, mrb_value x);
     
    8961040#define bit_op(x,y,op1,op2) do {\
    8971041  if (mrb_fixnum_p(y)) return mrb_fixnum_value(mrb_fixnum(x) op2 mrb_fixnum(y));\
    898   return flo_ ## op1(mrb, mrb_float_value(mrb, mrb_fixnum(x)));\
     1042  return flo_ ## op1(mrb, mrb_float_value(mrb, (mrb_float)mrb_fixnum(x)));\
    8991043} while(0)
     1044#endif
    9001045
    9011046/* 15.2.8.3.9  */
     
    9561101{
    9571102  if (width < 0) {              /* mrb_int overflow */
     1103#ifdef MRB_WITHOUT_FLOAT
     1104    return mrb_fixnum_value(0);
     1105#else
    9581106    return mrb_float_value(mrb, INFINITY);
     1107#endif
    9591108  }
    9601109  if (val > 0) {
    9611110    if ((width > NUMERIC_SHIFT_WIDTH_MAX) ||
    9621111        (val   > (MRB_INT_MAX >> width))) {
     1112#ifdef MRB_WITHOUT_FLOAT
     1113      return mrb_fixnum_value(-1);
     1114#else
    9631115      goto bit_overflow;
    964     }
     1116#endif
     1117    }
     1118    return mrb_fixnum_value(val << width);
    9651119  }
    9661120  else {
    9671121    if ((width > NUMERIC_SHIFT_WIDTH_MAX) ||
    968         (val   < (MRB_INT_MIN >> width))) {
     1122        (val   <= (MRB_INT_MIN >> width))) {
     1123#ifdef MRB_WITHOUT_FLOAT
     1124      return mrb_fixnum_value(0);
     1125#else
    9691126      goto bit_overflow;
    970     }
    971   }
    972 
    973   return mrb_fixnum_value(val << width);
    974 
     1127#endif
     1128    }
     1129    return mrb_fixnum_value(val * ((mrb_int)1 << width));
     1130  }
     1131
     1132#ifndef MRB_WITHOUT_FLOAT
    9751133bit_overflow:
    9761134  {
     
    9811139    return mrb_float_value(mrb, f);
    9821140  }
     1141#endif
    9831142}
    9841143
     
    10571216 */
    10581217
     1218#ifndef MRB_WITHOUT_FLOAT
    10591219static mrb_value
    10601220fix_to_f(mrb_state *mrb, mrb_value num)
     
    10701230 *  to numerical classes which don't support them.
    10711231 *
    1072  *     Float::INFINITY.to_r
     1232 *     Float::INFINITY.to_i
    10731233 *
    10741234 *  <em>raises the exception:</em>
     
    10891249    mrb_float d = mrb_float(x);
    10901250
    1091     if (isinf(d)) {
    1092       mrb_raise(mrb, E_FLOATDOMAIN_ERROR, d < 0 ? "-Infinity" : "Infinity");
    1093     }
    1094     if (isnan(d)) {
    1095       mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN");
    1096     }
     1251    mrb_check_num_exact(mrb, d);
    10971252    if (FIXABLE_FLOAT(d)) {
    10981253      z = (mrb_int)d;
    10991254    }
    11001255    else {
    1101       mrb_raisef(mrb, E_ARGUMENT_ERROR, "number (%S) too big for integer", x);
     1256      mrb_raisef(mrb, E_RANGE_ERROR, "number (%v) too big for integer", x);
    11021257    }
    11031258  }
    11041259  return mrb_fixnum_value(z);
    11051260}
    1106 
    1107 mrb_value
    1108 mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y)
     1261#endif
     1262
     1263static mrb_value
     1264fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y)
    11091265{
    11101266  mrb_int a;
     
    11171273    b = mrb_fixnum(y);
    11181274    if (mrb_int_add_overflow(a, b, &c)) {
     1275#ifndef MRB_WITHOUT_FLOAT
    11191276      return mrb_float_value(mrb, (mrb_float)a + (mrb_float)b);
     1277#endif
    11201278    }
    11211279    return mrb_fixnum_value(c);
    11221280  }
     1281#ifdef MRB_WITHOUT_FLOAT
     1282  mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
     1283#else
    11231284  return mrb_float_value(mrb, (mrb_float)a + mrb_to_flo(mrb, y));
     1285#endif
     1286}
     1287
     1288MRB_API mrb_value
     1289mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y)
     1290{
     1291  if (mrb_fixnum_p(x)) {
     1292    return fixnum_plus(mrb, x, y);
     1293  }
     1294#ifndef MRB_WITHOUT_FLOAT
     1295  if (mrb_float_p(x)) {
     1296    return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y));
     1297  }
     1298#endif
     1299  mrb_raise(mrb, E_TYPE_ERROR, "no number addition");
     1300  return mrb_nil_value();       /* not reached */
    11241301}
    11251302
     
    11391316
    11401317  mrb_get_args(mrb, "o", &other);
    1141   return mrb_fixnum_plus(mrb, self, other);
    1142 }
    1143 
    1144 mrb_value
    1145 mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y)
     1318  return fixnum_plus(mrb, self, other);
     1319}
     1320
     1321static mrb_value
     1322fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y)
    11461323{
    11471324  mrb_int a;
     
    11531330    b = mrb_fixnum(y);
    11541331    if (mrb_int_sub_overflow(a, b, &c)) {
     1332#ifndef MRB_WITHOUT_FLOAT
    11551333      return mrb_float_value(mrb, (mrb_float)a - (mrb_float)b);
     1334#endif
    11561335    }
    11571336    return mrb_fixnum_value(c);
    11581337  }
     1338#ifdef MRB_WITHOUT_FLOAT
     1339  mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
     1340#else
    11591341  return mrb_float_value(mrb, (mrb_float)a - mrb_to_flo(mrb, y));
     1342#endif
     1343}
     1344
     1345MRB_API mrb_value
     1346mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y)
     1347{
     1348  if (mrb_fixnum_p(x)) {
     1349    return fixnum_minus(mrb, x, y);
     1350  }
     1351#ifndef MRB_WITHOUT_FLOAT
     1352  if (mrb_float_p(x)) {
     1353    return mrb_float_value(mrb, mrb_float(x) - mrb_to_flo(mrb, y));
     1354  }
     1355#endif
     1356  mrb_raise(mrb, E_TYPE_ERROR, "no number subtraction");
     1357  return mrb_nil_value();       /* not reached */
    11601358}
    11611359
     
    11761374
    11771375  mrb_get_args(mrb, "o", &other);
    1178   return mrb_fixnum_minus(mrb, self, other);
     1376  return fixnum_minus(mrb, self, other);
    11791377}
    11801378
    11811379
    11821380MRB_API mrb_value
    1183 mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base)
     1381mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base)
    11841382{
    11851383  char buf[MRB_INT_BIT+1];
     
    11881386
    11891387  if (base < 2 || 36 < base) {
    1190     mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %S", mrb_fixnum_value(base));
     1388    mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %i", base);
    11911389  }
    11921390
     
    12321430  mrb_get_args(mrb, "|i", &base);
    12331431  return mrb_fixnum_to_str(mrb, self, base);
     1432}
     1433
     1434/* compare two numbers: (1:0:-1; -2 for error) */
     1435static mrb_int
     1436cmpnum(mrb_state *mrb, mrb_value v1, mrb_value v2)
     1437{
     1438#ifdef MRB_WITHOUT_FLOAT
     1439  mrb_int x, y;
     1440#else
     1441  mrb_float x, y;
     1442#endif
     1443
     1444#ifdef MRB_WITHOUT_FLOAT
     1445  x = mrb_fixnum(v1);
     1446#else
     1447  x = mrb_to_flo(mrb, v1);
     1448#endif
     1449  switch (mrb_type(v2)) {
     1450  case MRB_TT_FIXNUM:
     1451#ifdef MRB_WITHOUT_FLOAT
     1452    y = mrb_fixnum(v2);
     1453#else
     1454    y = (mrb_float)mrb_fixnum(v2);
     1455#endif
     1456    break;
     1457#ifndef MRB_WITHOUT_FLOAT
     1458  case MRB_TT_FLOAT:
     1459    y = mrb_float(v2);
     1460    break;
     1461#endif
     1462  default:
     1463    return -2;
     1464  }
     1465  if (x > y)
     1466    return 1;
     1467  else {
     1468    if (x < y)
     1469      return -1;
     1470    return 0;
     1471  }
    12341472}
    12351473
     
    12461484 */
    12471485static mrb_value
    1248 num_cmp(mrb_state *mrb, mrb_value self)
     1486integral_cmp(mrb_state *mrb, mrb_value self)
    12491487{
    12501488  mrb_value other;
    1251   mrb_float x, y;
     1489  mrb_int n;
    12521490
    12531491  mrb_get_args(mrb, "o", &other);
    1254 
    1255   x = mrb_to_flo(mrb, self);
    1256   switch (mrb_type(other)) {
     1492  n = cmpnum(mrb, self, other);
     1493  if (n == -2) return mrb_nil_value();
     1494  return mrb_fixnum_value(n);
     1495}
     1496
     1497static mrb_noreturn void
     1498cmperr(mrb_state *mrb, mrb_value v1, mrb_value v2)
     1499{
     1500  mrb_raisef(mrb, E_ARGUMENT_ERROR, "comparison of %t with %t failed", v1, v2);
     1501}
     1502
     1503static mrb_value
     1504integral_lt(mrb_state *mrb, mrb_value self)
     1505{
     1506  mrb_value other;
     1507  mrb_int n;
     1508
     1509  mrb_get_args(mrb, "o", &other);
     1510  n = cmpnum(mrb, self, other);
     1511  if (n == -2) cmperr(mrb, self, other);
     1512  if (n < 0) return mrb_true_value();
     1513  return mrb_false_value();
     1514}
     1515
     1516static mrb_value
     1517integral_le(mrb_state *mrb, mrb_value self)
     1518{
     1519  mrb_value other;
     1520  mrb_int n;
     1521
     1522  mrb_get_args(mrb, "o", &other);
     1523  n = cmpnum(mrb, self, other);
     1524  if (n == -2) cmperr(mrb, self, other);
     1525  if (n <= 0) return mrb_true_value();
     1526  return mrb_false_value();
     1527}
     1528
     1529static mrb_value
     1530integral_gt(mrb_state *mrb, mrb_value self)
     1531{
     1532  mrb_value other;
     1533  mrb_int n;
     1534
     1535  mrb_get_args(mrb, "o", &other);
     1536  n = cmpnum(mrb, self, other);
     1537  if (n == -2) cmperr(mrb, self, other);
     1538  if (n > 0) return mrb_true_value();
     1539  return mrb_false_value();
     1540}
     1541
     1542static mrb_value
     1543integral_ge(mrb_state *mrb, mrb_value self)
     1544{
     1545  mrb_value other;
     1546  mrb_int n;
     1547
     1548  mrb_get_args(mrb, "o", &other);
     1549  n = cmpnum(mrb, self, other);
     1550  if (n == -2) cmperr(mrb, self, other);
     1551  if (n >= 0) return mrb_true_value();
     1552  return mrb_false_value();
     1553}
     1554
     1555MRB_API mrb_int
     1556mrb_cmp(mrb_state *mrb, mrb_value obj1, mrb_value obj2)
     1557{
     1558  mrb_value v;
     1559
     1560  switch (mrb_type(obj1)) {
    12571561  case MRB_TT_FIXNUM:
    1258     y = (mrb_float)mrb_fixnum(other);
    1259     break;
    12601562  case MRB_TT_FLOAT:
    1261     y = mrb_float(other);
    1262     break;
     1563    return cmpnum(mrb, obj1, obj2);
     1564  case MRB_TT_STRING:
     1565    if (!mrb_string_p(obj2))
     1566      return -2;
     1567    return mrb_str_cmp(mrb, obj1, obj2);
    12631568  default:
    1264     return mrb_nil_value();
    1265   }
    1266   if (x > y)
    1267     return mrb_fixnum_value(1);
    1268   else {
    1269     if (x < y)
    1270       return mrb_fixnum_value(-1);
    1271     return mrb_fixnum_value(0);
    1272   }
     1569    v = mrb_funcall(mrb, obj1, "<=>", 1, obj2);
     1570    if (mrb_nil_p(v) || !mrb_fixnum_p(v))
     1571      return -2;
     1572    return mrb_fixnum(v);
     1573  }
     1574}
     1575
     1576static mrb_value
     1577num_finite_p(mrb_state *mrb, mrb_value self)
     1578{
     1579  return mrb_true_value();
     1580}
     1581
     1582static mrb_value
     1583num_infinite_p(mrb_state *mrb, mrb_value self)
     1584{
     1585  return mrb_false_value();
    12731586}
    12741587
     
    12811594 * and <code>other</code>.
    12821595 */
     1596#ifndef MRB_WITHOUT_FLOAT
    12831597static mrb_value
    12841598flo_plus(mrb_state *mrb, mrb_value x)
     
    12891603  return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y));
    12901604}
     1605#endif
    12911606
    12921607/* ------------------------------------------------------------------------*/
     
    12941609mrb_init_numeric(mrb_state *mrb)
    12951610{
    1296   struct RClass *numeric, *integer, *fixnum, *fl;
     1611  struct RClass *numeric, *integer, *fixnum, *integral;
     1612#ifndef MRB_WITHOUT_FLOAT
     1613  struct RClass *fl;
     1614#endif
     1615
     1616  integral = mrb_define_module(mrb, "Integral");
     1617  mrb_define_method(mrb, integral,"**",       integral_pow,    MRB_ARGS_REQ(1));
     1618  mrb_define_method(mrb, integral,"/",        integral_div,    MRB_ARGS_REQ(1)); /* 15.2.{8,9}.3.6  */
     1619  mrb_define_method(mrb, integral,"quo",      integral_div,    MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */
     1620  mrb_define_method(mrb, integral,"div",      integral_idiv,   MRB_ARGS_REQ(1));
     1621  mrb_define_method(mrb, integral,"<=>",      integral_cmp,    MRB_ARGS_REQ(1)); /* 15.2.{8,9}.3.1  */
     1622  mrb_define_method(mrb, integral,"<",        integral_lt,     MRB_ARGS_REQ(1));
     1623  mrb_define_method(mrb, integral,"<=",       integral_le,     MRB_ARGS_REQ(1));
     1624  mrb_define_method(mrb, integral,">",        integral_gt,     MRB_ARGS_REQ(1));
     1625  mrb_define_method(mrb, integral,">=",       integral_ge,     MRB_ARGS_REQ(1));
     1626  mrb_define_method(mrb, integral,"__coerce_step_counter", integral_coerce_step_counter, MRB_ARGS_REQ(2));
    12971627
    12981628  /* Numeric Class */
    12991629  numeric = mrb_define_class(mrb, "Numeric",  mrb->object_class);                /* 15.2.7 */
    1300 
    1301   mrb_define_method(mrb, numeric, "**",       num_pow,         MRB_ARGS_REQ(1));
    1302   mrb_define_method(mrb, numeric, "/",        num_div,         MRB_ARGS_REQ(1)); /* 15.2.8.3.4  */
    1303   mrb_define_method(mrb, numeric, "quo",      num_div,         MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */
    1304   mrb_define_method(mrb, numeric, "<=>",      num_cmp,         MRB_ARGS_REQ(1)); /* 15.2.9.3.6  */
     1630  mrb_define_method(mrb, numeric, "finite?",  num_finite_p,    MRB_ARGS_NONE());
     1631  mrb_define_method(mrb, numeric, "infinite?",num_infinite_p,  MRB_ARGS_NONE());
    13051632
    13061633  /* Integer Class */
     
    13101637  mrb_define_method(mrb, integer, "to_i",     int_to_i,        MRB_ARGS_NONE()); /* 15.2.8.3.24 */
    13111638  mrb_define_method(mrb, integer, "to_int",   int_to_i,        MRB_ARGS_NONE());
    1312   mrb_define_method(mrb, integer, "ceil",     int_to_i,        MRB_ARGS_REQ(1)); /* 15.2.8.3.8 (x) */
    1313   mrb_define_method(mrb, integer, "floor",    int_to_i,        MRB_ARGS_REQ(1)); /* 15.2.8.3.10 (x) */
    1314   mrb_define_method(mrb, integer, "round",    int_to_i,        MRB_ARGS_REQ(1)); /* 15.2.8.3.12 (x) */
    1315   mrb_define_method(mrb, integer, "truncate", int_to_i,        MRB_ARGS_REQ(1)); /* 15.2.8.3.15 (x) */
     1639#ifndef MRB_WITHOUT_FLOAT
     1640  mrb_define_method(mrb, integer, "ceil",     int_to_i,        MRB_ARGS_NONE()); /* 15.2.8.3.8 (x) */
     1641  mrb_define_method(mrb, integer, "floor",    int_to_i,        MRB_ARGS_NONE()); /* 15.2.8.3.10 (x) */
     1642  mrb_define_method(mrb, integer, "round",    int_to_i,        MRB_ARGS_NONE()); /* 15.2.8.3.12 (x) */
     1643  mrb_define_method(mrb, integer, "truncate", int_to_i,        MRB_ARGS_NONE()); /* 15.2.8.3.15 (x) */
     1644#endif
    13161645
    13171646  /* Fixnum Class */
     
    13291658  mrb_define_method(mrb, fixnum,  ">>",       fix_rshift,      MRB_ARGS_REQ(1)); /* 15.2.8.3.13 */
    13301659  mrb_define_method(mrb, fixnum,  "eql?",     fix_eql,         MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */
    1331   mrb_define_method(mrb, fixnum,  "hash",     flo_hash,        MRB_ARGS_NONE()); /* 15.2.8.3.18 */
     1660#ifndef MRB_WITHOUT_FLOAT
    13321661  mrb_define_method(mrb, fixnum,  "to_f",     fix_to_f,        MRB_ARGS_NONE()); /* 15.2.8.3.23 */
    1333   mrb_define_method(mrb, fixnum,  "to_s",     fix_to_s,        MRB_ARGS_NONE()); /* 15.2.8.3.25 */
    1334   mrb_define_method(mrb, fixnum,  "inspect",  fix_to_s,        MRB_ARGS_NONE());
     1662#endif
     1663  mrb_define_method(mrb, fixnum,  "to_s",     fix_to_s,        MRB_ARGS_OPT(1)); /* 15.2.8.3.25 */
     1664  mrb_define_method(mrb, fixnum,  "inspect",  fix_to_s,        MRB_ARGS_OPT(1));
    13351665  mrb_define_method(mrb, fixnum,  "divmod",   fix_divmod,      MRB_ARGS_REQ(1)); /* 15.2.8.3.30 (x) */
    13361666
     1667#ifndef MRB_WITHOUT_FLOAT
    13371668  /* Float Class */
    13381669  mrb->float_class = fl = mrb_define_class(mrb, "Float", numeric);                 /* 15.2.9 */
     
    13481679  mrb_define_method(mrb, fl,      "|",         flo_or,         MRB_ARGS_REQ(1));
    13491680  mrb_define_method(mrb, fl,      "^",         flo_xor,        MRB_ARGS_REQ(1));
    1350   mrb_define_method(mrb, fl,      ">>",        flo_lshift,     MRB_ARGS_REQ(1));
    1351   mrb_define_method(mrb, fl,      "<<",        flo_rshift,     MRB_ARGS_REQ(1));
     1681  mrb_define_method(mrb, fl,      ">>",        flo_rshift,     MRB_ARGS_REQ(1));
     1682  mrb_define_method(mrb, fl,      "<<",        flo_lshift,     MRB_ARGS_REQ(1));
    13521683  mrb_define_method(mrb, fl,      "ceil",      flo_ceil,       MRB_ARGS_NONE()); /* 15.2.9.3.8  */
    13531684  mrb_define_method(mrb, fl,      "finite?",   flo_finite_p,   MRB_ARGS_NONE()); /* 15.2.9.3.9  */
     
    13721703  mrb_define_const(mrb, fl, "NAN", mrb_float_value(mrb, NAN));
    13731704#endif
    1374 }
     1705
     1706  mrb_include_module(mrb, fl, integral);
     1707#endif
     1708}
  • EcnlProtoTool/trunk/mruby-2.1.1/src/object.c

    r331 r439  
    2525    return (mrb_symbol(v1) == mrb_symbol(v2));
    2626
     27#ifndef MRB_WITHOUT_FLOAT
    2728  case MRB_TT_FLOAT:
    2829    return (mrb_float(v1) == mrb_float(v2));
     30#endif
    2931
    3032  default:
     
    8284nil_to_s(mrb_state *mrb, mrb_value obj)
    8385{
    84   return mrb_str_new(mrb, 0, 0);
     86  return mrb_str_new_frozen(mrb, 0, 0);
    8587}
    8688
     
    8890nil_inspect(mrb_state *mrb, mrb_value obj)
    8991{
    90   return mrb_str_new_lit(mrb, "nil");
     92  return mrb_str_new_lit_frozen(mrb, "nil");
    9193}
    9294
     
    149151true_to_s(mrb_state *mrb, mrb_value obj)
    150152{
    151   return mrb_str_new_lit(mrb, "true");
     153  return mrb_str_new_lit_frozen(mrb, "true");
    152154}
    153155
     
    256258false_to_s(mrb_state *mrb, mrb_value obj)
    257259{
    258   return mrb_str_new_lit(mrb, "false");
     260  return mrb_str_new_lit_frozen(mrb, "false");
    259261}
    260262
     
    296298
    297299static mrb_value
    298 inspect_type(mrb_state *mrb, mrb_value val)
    299 {
    300   if (mrb_type(val) == MRB_TT_FALSE || mrb_type(val) == MRB_TT_TRUE) {
    301     return mrb_inspect(mrb, val);
    302   }
    303   else {
    304     return mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, val));
    305   }
    306 }
    307 
    308 static mrb_value
    309300convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *method, mrb_bool raise)
    310301{
     
    314305  if (!mrb_respond_to(mrb, val, m)) {
    315306    if (raise) {
    316       mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into %S", inspect_type(mrb, val), mrb_str_new_cstr(mrb, tname));
     307      mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %Y into %s", val, tname);
    317308    }
    318309    return mrb_nil_value();
    319310  }
    320311  return mrb_funcall_argv(mrb, val, m, 0, 0);
    321 }
    322 
    323 MRB_API mrb_value
    324 mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method)
    325 {
    326   mrb_value v;
    327 
    328   if (mrb_fixnum_p(val)) return val;
    329   v = convert_type(mrb, val, "Integer", method, FALSE);
    330   if (mrb_nil_p(v) || !mrb_fixnum_p(v)) {
    331     return mrb_nil_value();
    332   }
    333   return v;
    334312}
    335313
     
    342320  v = convert_type(mrb, val, tname, method, TRUE);
    343321  if (mrb_type(v) != type) {
    344     mrb_raisef(mrb, E_TYPE_ERROR, "%S cannot be converted to %S by #%S", val,
    345                mrb_str_new_cstr(mrb, tname), mrb_str_new_cstr(mrb, method));
     322    mrb_raisef(mrb, E_TYPE_ERROR, "%v cannot be converted to %s by #%s", val, tname, method);
    346323  }
    347324  return v;
     
    374351  {MRB_TT_SCLASS, "SClass"},
    375352  {MRB_TT_PROC,   "Proc"},
     353#ifndef MRB_WITHOUT_FLOAT
    376354  {MRB_TT_FLOAT,  "Float"},
     355#endif
    377356  {MRB_TT_ARRAY,  "Array"},
    378357  {MRB_TT_HASH,   "Hash"},
     
    406385          etype = "Fixnum";
    407386        }
    408         else if (mrb_type(x) == MRB_TT_SYMBOL) {
     387        else if (mrb_symbol_p(x)) {
    409388          etype = "Symbol";
    410389        }
     
    415394          etype = mrb_obj_classname(mrb, x);
    416395        }
    417         mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected %S)",
    418                    mrb_str_new_cstr(mrb, etype), mrb_str_new_cstr(mrb, type->name));
     396        mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %s (expected %s)",
     397                   etype, type->name);
    419398      }
    420399      type++;
    421400    }
    422     mrb_raisef(mrb, E_TYPE_ERROR, "unknown type %S (%S given)",
    423                mrb_fixnum_value(t), mrb_fixnum_value(mrb_type(x)));
     401    mrb_raisef(mrb, E_TYPE_ERROR, "unknown type %d (%d given)", t, mrb_type(x));
    424402  }
    425403}
     
    439417mrb_any_to_s(mrb_state *mrb, mrb_value obj)
    440418{
    441   mrb_value str = mrb_str_buf_new(mrb, 20);
     419  mrb_value str = mrb_str_new_capa(mrb, 20);
    442420  const char *cname = mrb_obj_classname(mrb, obj);
    443421
    444422  mrb_str_cat_lit(mrb, str, "#<");
    445423  mrb_str_cat_cstr(mrb, str, cname);
    446   mrb_str_cat_lit(mrb, str, ":");
    447   mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_ptr(obj)));
     424  if (!mrb_immediate_p(obj)) {
     425    mrb_str_cat_lit(mrb, str, ":");
     426    mrb_str_cat_str(mrb, str, mrb_ptr_to_str(mrb, mrb_ptr(obj)));
     427  }
    448428  mrb_str_cat_lit(mrb, str, ">");
    449429
     
    502482}
    503483
    504 static mrb_value
    505 mrb_to_integer(mrb_state *mrb, mrb_value val, const char *method)
    506 {
    507   mrb_value v;
    508 
    509   if (mrb_fixnum_p(val)) return val;
    510   v = convert_type(mrb, val, "Integer", method, TRUE);
    511   if (!mrb_obj_is_kind_of(mrb, v, mrb->fixnum_class)) {
    512     mrb_value type = inspect_type(mrb, val);
    513     mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Integer (%S#%S gives %S)",
    514                type, type, mrb_str_new_cstr(mrb, method), inspect_type(mrb, v));
    515   }
    516   return v;
    517 }
    518 
    519484MRB_API mrb_value
    520485mrb_to_int(mrb_state *mrb, mrb_value val)
    521486{
    522   return mrb_to_integer(mrb, val, "to_int");
    523 }
    524 
    525 MRB_API mrb_value
    526 mrb_convert_to_integer(mrb_state *mrb, mrb_value val, int base)
     487
     488  if (!mrb_fixnum_p(val)) {
     489#ifndef MRB_WITHOUT_FLOAT
     490    if (mrb_float_p(val)) {
     491      return mrb_flo_to_fixnum(mrb, val);
     492    }
     493#endif
     494    mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %Y to Integer", val);
     495  }
     496  return val;
     497}
     498
     499MRB_API mrb_value
     500mrb_convert_to_integer(mrb_state *mrb, mrb_value val, mrb_int base)
    527501{
    528502  mrb_value tmp;
     
    530504  if (mrb_nil_p(val)) {
    531505    if (base != 0) goto arg_error;
    532       mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Integer");
     506    mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Integer");
    533507  }
    534508  switch (mrb_type(val)) {
     509#ifndef MRB_WITHOUT_FLOAT
    535510    case MRB_TT_FLOAT:
    536511      if (base != 0) goto arg_error;
    537       else {
    538         mrb_float f = mrb_float(val);
    539         if (FIXABLE_FLOAT(f)) {
    540           break;
    541         }
    542       }
    543512      return mrb_flo_to_fixnum(mrb, val);
     513#endif
    544514
    545515    case MRB_TT_FIXNUM:
     
    563533    mrb_raise(mrb, E_ARGUMENT_ERROR, "base specified for non string value");
    564534  }
    565   tmp = convert_type(mrb, val, "Integer", "to_int", FALSE);
    566   if (mrb_nil_p(tmp)) {
    567     return mrb_to_integer(mrb, val, "to_i");
    568   }
    569   return tmp;
     535  /* to raise TypeError */
     536  return mrb_to_int(mrb, val);
    570537}
    571538
     
    576543}
    577544
     545#ifndef MRB_WITHOUT_FLOAT
    578546MRB_API mrb_value
    579547mrb_Float(mrb_state *mrb, mrb_value val)
     
    596564  }
    597565}
     566#endif
     567
     568MRB_API mrb_value
     569mrb_to_str(mrb_state *mrb, mrb_value val)
     570{
     571  return mrb_ensure_string_type(mrb, val);
     572}
     573
     574/* obsolete: use mrb_ensure_string_type() instead */
     575MRB_API mrb_value
     576mrb_string_type(mrb_state *mrb, mrb_value str)
     577{
     578  return mrb_ensure_string_type(mrb, str);
     579}
     580
     581MRB_API mrb_value
     582mrb_ensure_string_type(mrb_state *mrb, mrb_value str)
     583{
     584  if (!mrb_string_p(str)) {
     585    mrb_raisef(mrb, E_TYPE_ERROR, "%Y cannot be converted to String", str);
     586  }
     587  return str;
     588}
     589
     590MRB_API mrb_value
     591mrb_check_string_type(mrb_state *mrb, mrb_value str)
     592{
     593  if (!mrb_string_p(str)) return mrb_nil_value();
     594  return str;
     595}
     596
     597MRB_API mrb_value
     598mrb_ensure_array_type(mrb_state *mrb, mrb_value ary)
     599{
     600  if (!mrb_array_p(ary)) {
     601    mrb_raisef(mrb, E_TYPE_ERROR, "%Y cannot be converted to Array", ary);
     602  }
     603  return ary;
     604}
     605
     606MRB_API mrb_value
     607mrb_check_array_type(mrb_state *mrb, mrb_value ary)
     608{
     609  if (!mrb_array_p(ary)) return mrb_nil_value();
     610  return ary;
     611}
     612
     613MRB_API mrb_value
     614mrb_ensure_hash_type(mrb_state *mrb, mrb_value hash)
     615{
     616  if (!mrb_hash_p(hash)) {
     617    mrb_raisef(mrb, E_TYPE_ERROR, "%Y cannot be converted to Hash", hash);
     618  }
     619  return hash;
     620}
     621
     622MRB_API mrb_value
     623mrb_check_hash_type(mrb_state *mrb, mrb_value hash)
     624{
     625  if (!mrb_hash_p(hash)) return mrb_nil_value();
     626  return hash;
     627}
    598628
    599629MRB_API mrb_value
  • EcnlProtoTool/trunk/mruby-2.1.1/src/pool.c

    r331 r439  
    55*/
    66
    7 #include <stddef.h>
    8 #include <stdint.h>
    97#include <string.h>
    108#include <mruby.h>
     
    2624/* end of configuration section */
    2725
     26/* Disable MSVC warning "C4200: nonstandard extension used: zero-sized array
     27 * in struct/union" when in C++ mode */
     28#ifdef _MSC_VER
     29#pragma warning(push)
     30#pragma warning(disable : 4200)
     31#endif
     32
    2833struct mrb_pool_page {
    2934  struct mrb_pool_page *next;
     
    3338  char page[];
    3439};
     40
     41#ifdef _MSC_VER
     42#pragma warning(pop)
     43#endif
    3544
    3645struct mrb_pool {
  • EcnlProtoTool/trunk/mruby-2.1.1/src/print.c

    r331 r439  
    3232{
    3333  mrb_print_backtrace(mrb);
    34   printstr(mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0), stderr);
    3534}
    3635
  • EcnlProtoTool/trunk/mruby-2.1.1/src/proc.c

    r331 r439  
    1010#include <mruby/opcode.h>
    1111
    12 static mrb_code call_iseq[] = {
    13   MKOP_A(OP_CALL, 0),
     12static const mrb_code call_iseq[] = {
     13  OP_CALL,
    1414};
    1515
    16 struct RProc *
     16struct RProc*
    1717mrb_proc_new(mrb_state *mrb, mrb_irep *irep)
    1818{
     
    2121
    2222  p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
    23   p->target_class = 0;
    2423  if (ci) {
    25     if (ci->proc)
    26       p->target_class = ci->proc->target_class;
    27     if (!p->target_class)
    28       p->target_class = ci->target_class;
     24    struct RClass *tc = NULL;
     25
     26    if (ci->proc) {
     27      tc = MRB_PROC_TARGET_CLASS(ci->proc);
     28    }
     29    if (tc == NULL) {
     30      tc = ci->target_class;
     31    }
     32    p->upper = ci->proc;
     33    p->e.target_class = tc;
    2934  }
    3035  p->body.irep = irep;
    31   p->env = 0;
    3236  mrb_irep_incref(mrb, irep);
    3337
     
    3640
    3741static struct REnv*
    38 env_new(mrb_state *mrb, int nlocals)
     42env_new(mrb_state *mrb, mrb_int nlocals)
    3943{
    4044  struct REnv *e;
    41 
    42   e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)mrb->c->ci->proc->env);
    43   MRB_SET_ENV_STACK_LEN(e, nlocals);
    44   e->cxt.c = mrb->c;
    45   e->cioff = mrb->c->ci - mrb->c->cibase;
     45  mrb_callinfo *ci = mrb->c->ci;
     46  int bidx;
     47
     48  e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, NULL);
     49  MRB_ENV_SET_STACK_LEN(e, nlocals);
     50  bidx = ci->argc;
     51  if (ci->argc < 0) bidx = 2;
     52  else bidx += 1;
     53  MRB_ENV_SET_BIDX(e, bidx);
     54  e->mid = ci->mid;
    4655  e->stack = mrb->c->stack;
     56  e->cxt = mrb->c;
    4757
    4858  return e;
     
    5060
    5161static void
    52 closure_setup(mrb_state *mrb, struct RProc *p, int nlocals)
    53 {
    54   struct REnv *e;
    55 
    56   if (!mrb->c->ci->env) {
    57     e = env_new(mrb, nlocals);
    58     mrb->c->ci->env = e;
    59   }
    60   else {
    61     e = mrb->c->ci->env;
    62   }
    63   p->env = e;
    64   mrb_field_write_barrier(mrb, (struct RBasic *)p, (struct RBasic *)p->env);
    65 }
    66 
    67 struct RProc *
     62closure_setup(mrb_state *mrb, struct RProc *p)
     63{
     64  mrb_callinfo *ci = mrb->c->ci;
     65  struct RProc *up = p->upper;
     66  struct REnv *e = NULL;
     67
     68  if (ci && ci->env) {
     69    e = ci->env;
     70  }
     71  else if (up) {
     72    struct RClass *tc = MRB_PROC_TARGET_CLASS(p);
     73
     74    e = env_new(mrb, up->body.irep->nlocals);
     75    ci->env = e;
     76    if (tc) {
     77      e->c = tc;
     78      mrb_field_write_barrier(mrb, (struct RBasic*)e, (struct RBasic*)tc);
     79    }
     80    if (MRB_PROC_ENV_P(up) && MRB_PROC_ENV(up)->cxt == NULL) {
     81      e->mid = MRB_PROC_ENV(up)->mid;
     82    }
     83  }
     84  if (e) {
     85    p->e.env = e;
     86    p->flags |= MRB_PROC_ENVSET;
     87    mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)e);
     88  }
     89}
     90
     91struct RProc*
    6892mrb_closure_new(mrb_state *mrb, mrb_irep *irep)
    6993{
    7094  struct RProc *p = mrb_proc_new(mrb, irep);
    7195
    72   closure_setup(mrb, p, mrb->c->ci->proc->body.irep->nlocals);
     96  closure_setup(mrb, p);
    7397  return p;
    7498}
    7599
    76 MRB_API struct RProc *
     100MRB_API struct RProc*
    77101mrb_proc_new_cfunc(mrb_state *mrb, mrb_func_t func)
    78102{
     
    81105  p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
    82106  p->body.func = func;
    83   p->flags |= MRB_PROC_CFUNC;
    84   p->env = 0;
     107  p->flags |= MRB_PROC_CFUNC_FL;
     108  p->upper = 0;
     109  p->e.target_class = 0;
    85110
    86111  return p;
    87112}
    88113
    89 MRB_API struct RProc *
     114MRB_API struct RProc*
    90115mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const mrb_value *argv)
    91116{
     
    94119  int i;
    95120
    96   p->env = e = env_new(mrb, argc);
    97   mrb_field_write_barrier(mrb, (struct RBasic *)p, (struct RBasic *)p->env);
     121  p->e.env = e = env_new(mrb, argc);
     122  p->flags |= MRB_PROC_ENVSET;
     123  mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)e);
    98124  MRB_ENV_UNSHARE_STACK(e);
    99125  e->stack = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * argc);
     
    111137}
    112138
    113 MRB_API struct RProc *
     139MRB_API struct RProc*
    114140mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals)
    115141{
     
    121147{
    122148  struct RProc *p = mrb->c->ci->proc;
    123   struct REnv *e = p->env;
    124 
    125   if (!MRB_PROC_CFUNC_P(p)) {
     149  struct REnv *e;
     150
     151  if (!p || !MRB_PROC_CFUNC_P(p)) {
    126152    mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from non-cfunc proc.");
    127153  }
     154  e = MRB_PROC_ENV(p);
    128155  if (!e) {
    129156    mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from cfunc Proc without REnv.");
    130157  }
    131158  if (idx < 0 || MRB_ENV_STACK_LEN(e) <= idx) {
    132     mrb_raisef(mrb, E_INDEX_ERROR, "Env index out of range: %S (expected: 0 <= index < %S)",
    133                mrb_fixnum_value(idx), mrb_fixnum_value(MRB_ENV_STACK_LEN(e)));
     159    mrb_raisef(mrb, E_INDEX_ERROR, "Env index out of range: %i (expected: 0 <= index < %i)",
     160               idx, MRB_ENV_STACK_LEN(e));
    134161  }
    135162
     
    140167mrb_proc_copy(struct RProc *a, struct RProc *b)
    141168{
     169  if (a->body.irep) {
     170    /* already initialized proc */
     171    return;
     172  }
    142173  a->flags = b->flags;
    143174  a->body = b->body;
     
    145176    a->body.irep->refcnt++;
    146177  }
    147   a->target_class = b->target_class;
    148   a->env = b->env;
     178  a->upper = b->upper;
     179  a->e.env = b->e.env;
     180  /* a->e.target_class = a->e.target_class; */
    149181}
    150182
     
    156188  struct RProc *p;
    157189
    158   mrb_get_args(mrb, "&", &blk);
    159   if (mrb_nil_p(blk)) {
    160     /* Calling Proc.new without a block is not implemented yet */
    161     mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block");
    162   }
     190  /* Calling Proc.new without a block is not implemented yet */
     191  mrb_get_args(mrb, "&!", &blk);
    163192  p = (struct RProc *)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb_class_ptr(proc_class));
    164193  mrb_proc_copy(p, mrb_proc_ptr(blk));
    165194  proc = mrb_obj_value(p);
    166   mrb_funcall_with_block(mrb, proc, mrb_intern_lit(mrb, "initialize"), 0, NULL, blk);
     195  mrb_funcall_with_block(mrb, proc, mrb_intern_lit(mrb, "initialize"), 0, NULL, proc);
     196  if (!MRB_PROC_STRICT_P(p) &&
     197      mrb->c->ci > mrb->c->cibase && MRB_PROC_ENV(p) == mrb->c->ci[-1].env) {
     198    p->flags |= MRB_PROC_ORPHAN;
     199  }
    167200  return proc;
    168201}
     
    174207
    175208  mrb_get_args(mrb, "o", &proc);
    176   if (mrb_type(proc) != MRB_TT_PROC) {
     209  if (!mrb_proc_p(proc)) {
    177210    mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc");
    178211  }
     
    181214}
    182215
    183 int
    184 mrb_proc_cfunc_p(struct RProc *p)
    185 {
    186   return MRB_PROC_CFUNC_P(p);
    187 }
    188 
    189 mrb_value
    190 mrb_proc_call_cfunc(mrb_state *mrb, struct RProc *p, mrb_value self)
    191 {
    192   return (p->body.func)(mrb, self);
    193 }
    194 
    195216/* 15.2.17.4.2 */
    196217static mrb_value
    197 mrb_proc_arity(mrb_state *mrb, mrb_value self)
    198 {
    199   struct RProc *p = mrb_proc_ptr(self);
    200   struct mrb_irep *irep;
    201   mrb_code *iseq;
    202   mrb_aspec aspec;
    203   int ma, op, ra, pa, arity;
    204 
    205   if (MRB_PROC_CFUNC_P(p)) {
    206     /* TODO cfunc aspec not implemented yet */
    207     return mrb_fixnum_value(-1);
    208   }
    209 
    210   irep = p->body.irep;
    211   if (!irep) {
    212     return mrb_fixnum_value(0);
    213   }
    214 
    215   iseq = irep->iseq;
    216   /* arity is depend on OP_ENTER */
    217   if (GET_OPCODE(*iseq) != OP_ENTER) {
    218     return mrb_fixnum_value(0);
    219   }
    220 
    221   aspec = GETARG_Ax(*iseq);
    222   ma = MRB_ASPEC_REQ(aspec);
    223   op = MRB_ASPEC_OPT(aspec);
    224   ra = MRB_ASPEC_REST(aspec);
    225   pa = MRB_ASPEC_POST(aspec);
    226   arity = ra || (MRB_PROC_STRICT_P(p) && op) ? -(ma + pa + 1) : ma + pa;
    227 
    228   return mrb_fixnum_value(arity);
     218proc_arity(mrb_state *mrb, mrb_value self)
     219{
     220  return mrb_fixnum_value(mrb_proc_arity(mrb_proc_ptr(self)));
    229221}
    230222
     
    248240    mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block");
    249241  }
    250   if (mrb_type(blk) != MRB_TT_PROC) {
     242  if (!mrb_proc_p(blk)) {
    251243    mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc");
    252244  }
     
    261253}
    262254
     255mrb_int
     256mrb_proc_arity(const struct RProc *p)
     257{
     258  struct mrb_irep *irep;
     259  const mrb_code *pc;
     260  mrb_aspec aspec;
     261  int ma, op, ra, pa, arity;
     262
     263  if (MRB_PROC_CFUNC_P(p)) {
     264    /* TODO cfunc aspec not implemented yet */
     265    return -1;
     266  }
     267
     268  irep = p->body.irep;
     269  if (!irep) {
     270    return 0;
     271  }
     272
     273  pc = irep->iseq;
     274  /* arity is depend on OP_ENTER */
     275  if (*pc != OP_ENTER) {
     276    return 0;
     277  }
     278
     279  aspec = PEEK_W(pc+1);
     280  ma = MRB_ASPEC_REQ(aspec);
     281  op = MRB_ASPEC_OPT(aspec);
     282  ra = MRB_ASPEC_REST(aspec);
     283  pa = MRB_ASPEC_POST(aspec);
     284  arity = ra || (MRB_PROC_STRICT_P(p) && op) ? -(ma + pa + 1) : ma + pa;
     285
     286  return arity;
     287}
     288
    263289void
    264290mrb_init_proc(mrb_state *mrb)
    265291{
    266   struct RProc *m;
     292  struct RProc *p;
     293  mrb_method_t m;
    267294  mrb_irep *call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep));
    268295  static const mrb_irep mrb_irep_zero = { 0 };
     
    274301  call_irep->nregs = 2;         /* receiver and block */
    275302
    276   mrb_define_class_method(mrb, mrb->proc_class, "new", mrb_proc_s_new, MRB_ARGS_ANY());
     303  mrb_define_class_method(mrb, mrb->proc_class, "new", mrb_proc_s_new, MRB_ARGS_NONE()|MRB_ARGS_BLOCK());
    277304  mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1));
    278   mrb_define_method(mrb, mrb->proc_class, "arity", mrb_proc_arity, MRB_ARGS_NONE());
    279 
    280   m = mrb_proc_new(mrb, call_irep);
     305  mrb_define_method(mrb, mrb->proc_class, "arity", proc_arity, MRB_ARGS_NONE());
     306
     307  p = mrb_proc_new(mrb, call_irep);
     308  MRB_METHOD_FROM_PROC(m, p);
    281309  mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "call"), m);
    282310  mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "[]"), m);
    283311
    284   mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.2.6  */
    285   mrb_define_method(mrb, mrb->kernel_module,       "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.3.27 */
    286 }
     312  mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()|MRB_ARGS_BLOCK()); /* 15.3.1.2.6  */
     313  mrb_define_method(mrb, mrb->kernel_module,       "lambda", proc_lambda, MRB_ARGS_NONE()|MRB_ARGS_BLOCK()); /* 15.3.1.3.27 */
     314}
  • EcnlProtoTool/trunk/mruby-2.1.1/src/range.c

    r331 r439  
    1111#include <mruby/array.h>
    1212
    13 #define RANGE_CLASS (mrb_class_get(mrb, "Range"))
    14 
    15 MRB_API struct RRange*
    16 mrb_range_ptr(mrb_state *mrb, mrb_value v)
    17 {
    18   struct RRange *r = (struct RRange*)mrb_ptr(v);
    19 
    20   if (r->edges == NULL) {
    21     mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized range");
    22   }
    23   return r;
    24 }
     13#define RANGE_INITIALIZED_MASK 1
     14#define RANGE_INITIALIZED(p) ((p)->flags |= RANGE_INITIALIZED_MASK)
     15#define RANGE_INITIALIZED_P(p) ((p)->flags & RANGE_INITIALIZED_MASK)
    2516
    2617static void
    27 range_check(mrb_state *mrb, mrb_value a, mrb_value b)
    28 {
    29   mrb_value ans;
     18r_check(mrb_state *mrb, mrb_value a, mrb_value b)
     19{
    3020  enum mrb_vtype ta;
    3121  enum mrb_vtype tb;
     22  mrb_int n;
    3223
    3324  ta = mrb_type(a);
    3425  tb = mrb_type(b);
     26#ifdef MRB_WITHOUT_FLOAT
     27  if (ta == MRB_TT_FIXNUM && tb == MRB_TT_FIXNUM ) {
     28#else
    3529  if ((ta == MRB_TT_FIXNUM || ta == MRB_TT_FLOAT) &&
    3630      (tb == MRB_TT_FIXNUM || tb == MRB_TT_FLOAT)) {
     31#endif
    3732    return;
    3833  }
    3934
    40   ans =  mrb_funcall(mrb, a, "<=>", 1, b);
    41   if (mrb_nil_p(ans)) {
    42     /* can not be compared */
     35  n = mrb_cmp(mrb, a, b);
     36  if (n == -2) {                /* can not be compared */
    4337    mrb_raise(mrb, E_ARGUMENT_ERROR, "bad value for range");
    4438  }
    4539}
    4640
    47 MRB_API mrb_value
    48 mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, mrb_bool excl)
    49 {
    50   struct RRange *r;
    51 
    52   range_check(mrb, beg, end);
    53   r = (struct RRange*)mrb_obj_alloc(mrb, MRB_TT_RANGE, RANGE_CLASS);
     41static mrb_bool
     42r_le(mrb_state *mrb, mrb_value a, mrb_value b)
     43{
     44  mrb_int n = mrb_cmp(mrb, a, b);
     45
     46  if (n == 0 || n == -1) return TRUE;
     47  return FALSE;
     48}
     49
     50static mrb_bool
     51r_gt(mrb_state *mrb, mrb_value a, mrb_value b)
     52{
     53  return mrb_cmp(mrb, a, b) == 1;
     54}
     55
     56static mrb_bool
     57r_ge(mrb_state *mrb, mrb_value a, mrb_value b)
     58{
     59  mrb_int n = mrb_cmp(mrb, a, b);
     60
     61  if (n == 0 || n == 1) return TRUE;
     62  return FALSE;
     63}
     64
     65static void
     66range_ptr_alloc_edges(mrb_state *mrb, struct RRange *r)
     67{
     68#ifndef MRB_RANGE_EMBED
    5469  r->edges = (mrb_range_edges *)mrb_malloc(mrb, sizeof(mrb_range_edges));
    55   r->edges->beg = beg;
    56   r->edges->end = end;
    57   r->excl = excl;
    58   return mrb_range_value(r);
     70#endif
     71}
     72
     73static struct RRange *
     74range_ptr_init(mrb_state *mrb, struct RRange *r, mrb_value beg, mrb_value end, mrb_bool excl)
     75{
     76  r_check(mrb, beg, end);
     77
     78  if (r) {
     79    if (RANGE_INITIALIZED_P(r)) {
     80      /* Ranges are immutable, so that they should be initialized only once. */
     81      mrb_name_error(mrb, mrb_intern_lit(mrb, "initialize"), "'initialize' called twice");
     82    }
     83    else {
     84      range_ptr_alloc_edges(mrb, r);
     85    }
     86  }
     87  else {
     88    r = (struct RRange*)mrb_obj_alloc(mrb, MRB_TT_RANGE, mrb->range_class);
     89    range_ptr_alloc_edges(mrb, r);
     90  }
     91
     92  RANGE_BEG(r) = beg;
     93  RANGE_END(r) = end;
     94  RANGE_EXCL(r) = excl;
     95  RANGE_INITIALIZED(r);
     96
     97  return r;
     98}
     99
     100static void
     101range_ptr_replace(mrb_state *mrb, struct RRange *r, mrb_value beg, mrb_value end, mrb_bool excl)
     102{
     103  range_ptr_init(mrb, r, beg, end, excl);
     104  mrb_write_barrier(mrb, (struct RBasic*)r);
    59105}
    60106
     
    66112 *  Returns the first object in <i>rng</i>.
    67113 */
    68 mrb_value
    69 mrb_range_beg(mrb_state *mrb, mrb_value range)
    70 {
    71   struct RRange *r = mrb_range_ptr(mrb, range);
    72 
    73   return r->edges->beg;
     114static mrb_value
     115range_beg(mrb_state *mrb, mrb_value range)
     116{
     117  return mrb_range_beg(mrb, range);
    74118}
    75119
     
    84128 *     (1...10).end   #=> 10
    85129 */
    86 
    87 mrb_value
    88 mrb_range_end(mrb_state *mrb, mrb_value range)
    89 {
    90   struct RRange *r = mrb_range_ptr(mrb, range);
    91 
    92   return r->edges->end;
     130static mrb_value
     131range_end(mrb_state *mrb, mrb_value range)
     132{
     133  return mrb_range_end(mrb, range);
    93134}
    94135
     
    99140 *  Returns <code>true</code> if <i>range</i> excludes its end value.
    100141 */
    101 mrb_value
    102 mrb_range_excl(mrb_state *mrb, mrb_value range)
    103 {
    104   struct RRange *r = mrb_range_ptr(mrb, range);
    105 
    106   return mrb_bool_value(r->excl);
    107 }
    108 
    109 static void
    110 range_init(mrb_state *mrb, mrb_value range, mrb_value beg, mrb_value end, mrb_bool exclude_end)
    111 {
    112   struct RRange *r = mrb_range_raw_ptr(range);
    113 
    114   range_check(mrb, beg, end);
    115   r->excl = exclude_end;
    116   if (!r->edges) {
    117     r->edges = (mrb_range_edges *)mrb_malloc(mrb, sizeof(mrb_range_edges));
    118   }
    119   r->edges->beg = beg;
    120   r->edges->end = end;
    121 }
     142static mrb_value
     143range_excl(mrb_state *mrb, mrb_value range)
     144{
     145  return mrb_bool_value(mrb_range_excl_p(mrb, range));
     146}
     147
    122148/*
    123149 *  call-seq:
     
    128154 *  the end object; otherwise, it will be excluded.
    129155 */
    130 
    131 mrb_value
    132 mrb_range_initialize(mrb_state *mrb, mrb_value range)
     156static mrb_value
     157range_initialize(mrb_state *mrb, mrb_value range)
    133158{
    134159  mrb_value beg, end;
    135   mrb_bool exclusive;
    136   int n;
    137 
    138   n = mrb_get_args(mrb, "oo|b", &beg, &end, &exclusive);
    139   if (n != 3) {
    140     exclusive = FALSE;
    141   }
    142   /* Ranges are immutable, so that they should be initialized only once. */
    143   if (mrb_range_raw_ptr(range)->edges) {
    144     mrb_name_error(mrb, mrb_intern_lit(mrb, "initialize"), "`initialize' called twice");
    145   }
    146   range_init(mrb, range, beg, end, exclusive);
     160  mrb_bool exclusive = FALSE;
     161
     162  mrb_get_args(mrb, "oo|b", &beg, &end, &exclusive);
     163  range_ptr_replace(mrb, mrb_range_raw_ptr(range), beg, end, exclusive);
    147164  return range;
    148165}
     166
    149167/*
    150168 *  call-seq:
     
    159177 *    (0..2) == Range.new(0,2)    #=> true
    160178 *    (0..2) == (0...2)           #=> false
    161  *
    162  */
    163 
    164 mrb_value
    165 mrb_range_eq(mrb_state *mrb, mrb_value range)
     179 */
     180static mrb_value
     181range_eq(mrb_state *mrb, mrb_value range)
    166182{
    167183  struct RRange *rr;
    168184  struct RRange *ro;
    169   mrb_value obj, v1, v2;
     185  mrb_value obj;
     186  mrb_bool v1, v2;
    170187
    171188  mrb_get_args(mrb, "o", &obj);
     
    178195  rr = mrb_range_ptr(mrb, range);
    179196  ro = mrb_range_ptr(mrb, obj);
    180   v1 = mrb_funcall(mrb, rr->edges->beg, "==", 1, ro->edges->beg);
    181   v2 = mrb_funcall(mrb, rr->edges->end, "==", 1, ro->edges->end);
    182   if (!mrb_bool(v1) || !mrb_bool(v2) || rr->excl != ro->excl) {
     197  v1 = mrb_equal(mrb, RANGE_BEG(rr), RANGE_BEG(ro));
     198  v2 = mrb_equal(mrb, RANGE_END(rr), RANGE_END(ro));
     199  if (!v1 || !v2 || RANGE_EXCL(rr) != RANGE_EXCL(ro)) {
    183200    return mrb_false_value();
    184201  }
    185202  return mrb_true_value();
    186 }
    187 
    188 static mrb_bool
    189 r_le(mrb_state *mrb, mrb_value a, mrb_value b)
    190 {
    191   mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
    192   /* output :a < b => -1, a = b =>  0, a > b => +1 */
    193 
    194   if (mrb_fixnum_p(r)) {
    195     mrb_int c = mrb_fixnum(r);
    196     if (c == 0 || c == -1) return TRUE;
    197   }
    198 
    199   return FALSE;
    200 }
    201 
    202 static mrb_bool
    203 r_gt(mrb_state *mrb, mrb_value a, mrb_value b)
    204 {
    205   mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b);
    206   /* output :a < b => -1, a = b =>  0, a > b => +1 */
    207 
    208   return mrb_fixnum_p(r) && mrb_fixnum(r) == 1;
    209 }
    210 
    211 static mrb_bool
    212 r_ge(mrb_state *mrb, mrb_value a, mrb_value b)
    213 {
    214   mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
    215   /* output :a < b => -1, a = b =>  0, a > b => +1 */
    216 
    217   if (mrb_fixnum_p(r)) {
    218     mrb_int c = mrb_fixnum(r);
    219     if (c == 0 || c == 1) return TRUE;
    220   }
    221 
    222   return FALSE;
    223203}
    224204
     
    228208 *     range.member?(val)  =>  true or false
    229209 *     range.include?(val) =>  true or false
    230  *
    231  */
    232 mrb_value
    233 mrb_range_include(mrb_state *mrb, mrb_value range)
     210 */
     211static mrb_value
     212range_include(mrb_state *mrb, mrb_value range)
    234213{
    235214  mrb_value val;
     
    240219  mrb_get_args(mrb, "o", &val);
    241220
    242   beg = r->edges->beg;
    243   end = r->edges->end;
    244   include_p = r_le(mrb, beg, val) &&           /* beg <= val */
    245               (r->excl ? r_gt(mrb, end, val)   /* end >  val */
    246                        : r_ge(mrb, end, val)); /* end >= val */
     221  beg = RANGE_BEG(r);
     222  end = RANGE_END(r);
     223  include_p = r_le(mrb, beg, val) &&                 /* beg <= val */
     224              (RANGE_EXCL(r) ? r_gt(mrb, end, val)   /* end >  val */
     225                             : r_ge(mrb, end, val)); /* end >= val */
    247226
    248227  return mrb_bool_value(include_p);
    249 }
    250 
    251 MRB_API mrb_int
    252 mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc)
    253 {
    254   mrb_int beg, end;
    255   struct RRange *r;
    256 
    257   if (mrb_type(range) != MRB_TT_RANGE) return 0;
    258   r = mrb_range_ptr(mrb, range);
    259 
    260   beg = mrb_int(mrb, r->edges->beg);
    261   end = mrb_int(mrb, r->edges->end);
    262 
    263   if (beg < 0) {
    264     beg += len;
    265     if (beg < 0) return 2;
    266   }
    267 
    268   if (trunc) {
    269     if (beg > len) return 2;
    270     if (end > len) end = len;
    271   }
    272 
    273   if (end < 0) end += len;
    274   if (!r->excl && (!trunc || end < len))
    275     end++;                      /* include end point */
    276   len = end - beg;
    277   if (len < 0) len = 0;
    278 
    279   *begp = beg;
    280   *lenp = len;
    281   return 1;
    282228}
    283229
     
    289235 * Convert this range object to a printable form.
    290236 */
    291 
    292237static mrb_value
    293238range_to_s(mrb_state *mrb, mrb_value range)
     
    296241  struct RRange *r = mrb_range_ptr(mrb, range);
    297242
    298   str  = mrb_obj_as_string(mrb, r->edges->beg);
    299   str2 = mrb_obj_as_string(mrb, r->edges->end);
     243  str  = mrb_obj_as_string(mrb, RANGE_BEG(r));
     244  str2 = mrb_obj_as_string(mrb, RANGE_END(r));
    300245  str  = mrb_str_dup(mrb, str);
    301   mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2);
     246  mrb_str_cat(mrb, str, "...", RANGE_EXCL(r) ? 3 : 2);
    302247  mrb_str_cat_str(mrb, str, str2);
    303248
     
    314259 * objects).
    315260 */
    316 
    317261static mrb_value
    318262range_inspect(mrb_state *mrb, mrb_value range)
     
    321265  struct RRange *r = mrb_range_ptr(mrb, range);
    322266
    323   str  = mrb_inspect(mrb, r->edges->beg);
    324   str2 = mrb_inspect(mrb, r->edges->end);
     267  str  = mrb_inspect(mrb, RANGE_BEG(r));
     268  str2 = mrb_inspect(mrb, RANGE_END(r));
    325269  str  = mrb_str_dup(mrb, str);
    326   mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2);
     270  mrb_str_cat(mrb, str, "...", RANGE_EXCL(r) ? 3 : 2);
    327271  mrb_str_cat_str(mrb, str, str2);
    328272
     
    342286 *    (0..2).eql?(Range.new(0,2))  #=> true
    343287 *    (0..2).eql?(0...2)           #=> false
    344  *
    345  */
    346 
     288 */
    347289static mrb_value
    348290range_eql(mrb_state *mrb, mrb_value range)
     
    354296
    355297  if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
    356   if (!mrb_obj_is_kind_of(mrb, obj, RANGE_CLASS)) {
    357     return mrb_false_value();
    358   }
    359   if (mrb_type(obj) != MRB_TT_RANGE) return mrb_false_value();
     298  if (!mrb_obj_is_kind_of(mrb, obj, mrb->range_class)) return mrb_false_value();
     299  if (!mrb_range_p(obj)) return mrb_false_value();
    360300
    361301  r = mrb_range_ptr(mrb, range);
    362302  o = mrb_range_ptr(mrb, obj);
    363   if (!mrb_eql(mrb, r->edges->beg, o->edges->beg) ||
    364       !mrb_eql(mrb, r->edges->end, o->edges->end) ||
    365       (r->excl != o->excl)) {
     303  if (!mrb_eql(mrb, RANGE_BEG(r), RANGE_BEG(o)) ||
     304      !mrb_eql(mrb, RANGE_END(r), RANGE_END(o)) ||
     305      (RANGE_EXCL(r) != RANGE_EXCL(o))) {
    366306    return mrb_false_value();
    367307  }
     
    384324
    385325  r = mrb_range_ptr(mrb, src);
    386   range_init(mrb, copy, r->edges->beg, r->edges->end, r->excl);
     326  range_ptr_replace(mrb, mrb_range_raw_ptr(copy), RANGE_BEG(r), RANGE_END(r), RANGE_EXCL(r));
    387327
    388328  return copy;
     
    400340      mrb_ary_push(mrb, result, func(mrb, obj, mrb_fixnum(argv[i])));
    401341    }
    402     else if (mrb_range_beg_len(mrb, argv[i], &beg, &len, olen, FALSE) == 1) {
     342    else if (mrb_range_beg_len(mrb, argv[i], &beg, &len, olen, FALSE) == MRB_RANGE_OK) {
    403343      mrb_int const end = olen < beg + len ? olen : beg + len;
    404344      for (j = beg; j < end; ++j) {
     
    411351    }
    412352    else {
    413       mrb_raisef(mrb, E_TYPE_ERROR, "invalid values selector: %S", argv[i]);
     353      mrb_raisef(mrb, E_TYPE_ERROR, "invalid values selector: %v", argv[i]);
    414354    }
    415355  }
    416356
    417357  return result;
     358}
     359
     360void
     361mrb_gc_mark_range(mrb_state *mrb, struct RRange *r)
     362{
     363  if (RANGE_INITIALIZED_P(r)) {
     364    mrb_gc_mark_value(mrb, RANGE_BEG(r));
     365    mrb_gc_mark_value(mrb, RANGE_END(r));
     366  }
     367}
     368
     369MRB_API struct RRange*
     370mrb_range_ptr(mrb_state *mrb, mrb_value range)
     371{
     372  struct RRange *r = mrb_range_raw_ptr(range);
     373
     374  /* check for if #initialize_copy was removed [#3320] */
     375  if (!RANGE_INITIALIZED_P(r)) {
     376    mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized range");
     377  }
     378  return r;
     379}
     380
     381MRB_API mrb_value
     382mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, mrb_bool excl)
     383{
     384  struct RRange *r = range_ptr_init(mrb, NULL, beg, end, excl);
     385  return mrb_range_value(r);
     386}
     387
     388MRB_API enum mrb_range_beg_len
     389mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc)
     390{
     391  mrb_int beg, end;
     392  struct RRange *r;
     393
     394  if (!mrb_range_p(range)) return MRB_RANGE_TYPE_MISMATCH;
     395  r = mrb_range_ptr(mrb, range);
     396
     397  beg = mrb_int(mrb, RANGE_BEG(r));
     398  end = mrb_int(mrb, RANGE_END(r));
     399
     400  if (beg < 0) {
     401    beg += len;
     402    if (beg < 0) return MRB_RANGE_OUT;
     403  }
     404
     405  if (trunc) {
     406    if (beg > len) return MRB_RANGE_OUT;
     407    if (end > len) end = len;
     408  }
     409
     410  if (end < 0) end += len;
     411  if (!RANGE_EXCL(r) && (!trunc || end < len)) end++;  /* include end point */
     412  len = end - beg;
     413  if (len < 0) len = 0;
     414
     415  *begp = beg;
     416  *lenp = len;
     417  return MRB_RANGE_OK;
    418418}
    419419
     
    424424
    425425  r = mrb_define_class(mrb, "Range", mrb->object_class);                                /* 15.2.14 */
     426  mrb->range_class = r;
    426427  MRB_SET_INSTANCE_TT(r, MRB_TT_RANGE);
    427428
    428   mrb_define_method(mrb, r, "begin",           mrb_range_beg,         MRB_ARGS_NONE()); /* 15.2.14.4.3  */
    429   mrb_define_method(mrb, r, "end",             mrb_range_end,         MRB_ARGS_NONE()); /* 15.2.14.4.5  */
    430   mrb_define_method(mrb, r, "==",              mrb_range_eq,          MRB_ARGS_REQ(1)); /* 15.2.14.4.1  */
    431   mrb_define_method(mrb, r, "===",             mrb_range_include,     MRB_ARGS_REQ(1)); /* 15.2.14.4.2  */
    432   mrb_define_method(mrb, r, "exclude_end?",    mrb_range_excl,        MRB_ARGS_NONE()); /* 15.2.14.4.6  */
    433   mrb_define_method(mrb, r, "first",           mrb_range_beg,         MRB_ARGS_NONE()); /* 15.2.14.4.7  */
    434   mrb_define_method(mrb, r, "include?",        mrb_range_include,     MRB_ARGS_REQ(1)); /* 15.2.14.4.8  */
    435   mrb_define_method(mrb, r, "initialize",      mrb_range_initialize,  MRB_ARGS_ANY());  /* 15.2.14.4.9  */
    436   mrb_define_method(mrb, r, "last",            mrb_range_end,         MRB_ARGS_NONE()); /* 15.2.14.4.10 */
    437   mrb_define_method(mrb, r, "member?",         mrb_range_include,     MRB_ARGS_REQ(1)); /* 15.2.14.4.11 */
    438 
     429  mrb_define_method(mrb, r, "begin",           range_beg,             MRB_ARGS_NONE()); /* 15.2.14.4.3  */
     430  mrb_define_method(mrb, r, "end",             range_end,             MRB_ARGS_NONE()); /* 15.2.14.4.5  */
     431  mrb_define_method(mrb, r, "==",              range_eq,              MRB_ARGS_REQ(1)); /* 15.2.14.4.1  */
     432  mrb_define_method(mrb, r, "===",             range_include,         MRB_ARGS_REQ(1)); /* 15.2.14.4.2  */
     433  mrb_define_method(mrb, r, "exclude_end?",    range_excl,            MRB_ARGS_NONE()); /* 15.2.14.4.6  */
     434  mrb_define_method(mrb, r, "first",           range_beg,             MRB_ARGS_NONE()); /* 15.2.14.4.7  */
     435  mrb_define_method(mrb, r, "include?",        range_include,         MRB_ARGS_REQ(1)); /* 15.2.14.4.8  */
     436  mrb_define_method(mrb, r, "initialize",      range_initialize,      MRB_ARGS_ANY());  /* 15.2.14.4.9  */
     437  mrb_define_method(mrb, r, "last",            range_end,             MRB_ARGS_NONE()); /* 15.2.14.4.10 */
     438  mrb_define_method(mrb, r, "member?",         range_include,         MRB_ARGS_REQ(1)); /* 15.2.14.4.11 */
    439439  mrb_define_method(mrb, r, "to_s",            range_to_s,            MRB_ARGS_NONE()); /* 15.2.14.4.12(x) */
    440440  mrb_define_method(mrb, r, "inspect",         range_inspect,         MRB_ARGS_NONE()); /* 15.2.14.4.13(x) */
  • EcnlProtoTool/trunk/mruby-2.1.1/src/state.c

    r331 r439  
    1212#include <mruby/debug.h>
    1313#include <mruby/string.h>
     14#include <mruby/class.h>
    1415
    1516void mrb_init_core(mrb_state*);
     
    1819void mrb_gc_init(mrb_state*, mrb_gc *gc);
    1920void mrb_gc_destroy(mrb_state*, mrb_gc *gc);
    20 
    21 static mrb_value
    22 inspect_main(mrb_state *mrb, mrb_value mod)
    23 {
    24   return mrb_str_new_lit(mrb, "main");
    25 }
    2621
    2722MRB_API mrb_state*
     
    3227  mrb_state *mrb;
    3328
     29  if (f == NULL) f = mrb_default_allocf;
    3430  mrb = (mrb_state *)(f)(NULL, NULL, sizeof(mrb_state), ud);
    3531  if (mrb == NULL) return NULL;
     
    6258}
    6359
    64 struct alloca_header {
    65   struct alloca_header *next;
    66   char buf[];
    67 };
    68 
    69 MRB_API void*
    70 mrb_alloca(mrb_state *mrb, size_t size)
    71 {
    72   struct alloca_header *p;
    73 
    74   p = (struct alloca_header*) mrb_malloc(mrb, sizeof(struct alloca_header)+size);
    75   p->next = mrb->mems;
    76   mrb->mems = p;
    77   return (void*)p->buf;
    78 }
    79 
    80 static void
    81 mrb_alloca_free(mrb_state *mrb)
    82 {
    83   struct alloca_header *p;
    84   struct alloca_header *tmp;
    85 
    86   if (mrb == NULL) return;
    87   p = mrb->mems;
    88 
    89   while (p) {
    90     tmp = p;
    91     p = p->next;
    92     mrb_free(mrb, tmp);
    93   }
    94 }
    95 
    9660MRB_API mrb_state*
    9761mrb_open(void)
     
    11276
    11377  if (!disable_gems) {
     78#ifndef DISABLE_GEMS
    11479    mrb_init_mrbgems(mrb);
    11580    mrb_gc_arena_restore(mrb, 0);
     81#endif
    11682  }
    11783  return mrb;
     
    136102
    137103void
     104mrb_irep_cutref(mrb_state *mrb, mrb_irep *irep)
     105{
     106  mrb_irep *tmp;
     107  int i;
     108
     109  for (i=0; i<irep->rlen; i++) {
     110    tmp = irep->reps[i];
     111    irep->reps[i] = NULL;
     112    if (tmp) mrb_irep_decref(mrb, tmp);
     113  }
     114}
     115
     116void
    138117mrb_irep_free(mrb_state *mrb, mrb_irep *irep)
    139118{
    140   size_t i;
     119  int i;
    141120
    142121  if (!(irep->flags & MRB_ISEQ_NO_FREE))
    143     mrb_free(mrb, irep->iseq);
     122    mrb_free(mrb, (void*)irep->iseq);
    144123  if (irep->pool) for (i=0; i<irep->plen; i++) {
    145     if (mrb_type(irep->pool[i]) == MRB_TT_STRING) {
     124    if (mrb_string_p(irep->pool[i])) {
    146125      mrb_gc_free_str(mrb, RSTRING(irep->pool[i]));
    147126      mrb_free(mrb, mrb_obj_ptr(irep->pool[i]));
    148127    }
    149 #ifdef MRB_WORD_BOXING
    150     else if (mrb_type(irep->pool[i]) == MRB_TT_FLOAT) {
     128#if defined(MRB_WORD_BOXING) && !defined(MRB_WITHOUT_FLOAT)
     129    else if (mrb_float_p(irep->pool[i])) {
    151130      mrb_free(mrb, mrb_obj_ptr(irep->pool[i]));
    152131    }
     
    156135  mrb_free(mrb, irep->syms);
    157136  for (i=0; i<irep->rlen; i++) {
    158     mrb_irep_decref(mrb, irep->reps[i]);
     137    if (irep->reps[i])
     138      mrb_irep_decref(mrb, irep->reps[i]);
    159139  }
    160140  mrb_free(mrb, irep->reps);
    161141  mrb_free(mrb, irep->lv);
    162   if (irep->own_filename) {
    163     mrb_free(mrb, (void *)irep->filename);
    164   }
    165   mrb_free(mrb, irep->lines);
    166142  mrb_debug_info_free(mrb, irep->debug_info);
    167143  mrb_free(mrb, irep);
    168 }
    169 
    170 mrb_value
    171 mrb_str_pool(mrb_state *mrb, mrb_value str)
    172 {
    173   struct RString *s = mrb_str_ptr(str);
    174   struct RString *ns;
    175   char *ptr;
    176   mrb_int len;
    177 
    178   ns = (struct RString *)mrb_malloc(mrb, sizeof(struct RString));
    179   ns->tt = MRB_TT_STRING;
    180   ns->c = mrb->string_class;
    181 
    182   if (RSTR_NOFREE_P(s)) {
    183     ns->flags = MRB_STR_NOFREE;
    184     ns->as.heap.ptr = s->as.heap.ptr;
    185     ns->as.heap.len = s->as.heap.len;
    186     ns->as.heap.aux.capa = 0;
    187   }
    188   else {
    189     ns->flags = 0;
    190     if (RSTR_EMBED_P(s)) {
    191       ptr = s->as.ary;
    192       len = RSTR_EMBED_LEN(s);
    193     }
    194     else {
    195       ptr = s->as.heap.ptr;
    196       len = s->as.heap.len;
    197     }
    198 
    199     if (len < RSTRING_EMBED_LEN_MAX) {
    200       RSTR_SET_EMBED_FLAG(ns);
    201       RSTR_SET_EMBED_LEN(ns, len);
    202       if (ptr) {
    203         memcpy(ns->as.ary, ptr, len);
    204       }
    205       ns->as.ary[len] = '\0';
    206     }
    207     else {
    208       ns->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)len+1);
    209       ns->as.heap.len = len;
    210       ns->as.heap.aux.capa = len;
    211       if (ptr) {
    212         memcpy(ns->as.heap.ptr, ptr, len);
    213       }
    214       ns->as.heap.ptr[len] = '\0';
    215     }
    216   }
    217   return mrb_obj_value(ns);
    218144}
    219145
     
    246172
    247173  /* free */
     174  mrb_gc_destroy(mrb, &mrb->gc);
     175  mrb_free_context(mrb, mrb->root_c);
    248176  mrb_gc_free_gv(mrb);
    249   mrb_free_context(mrb, mrb->root_c);
    250177  mrb_free_symtbl(mrb);
    251   mrb_alloca_free(mrb);
    252   mrb_gc_destroy(mrb, &mrb->gc);
    253178  mrb_free(mrb, mrb);
    254179}
     
    263188  *irep = mrb_irep_zero;
    264189  irep->refcnt = 1;
    265   irep->own_filename = FALSE;
    266190
    267191  return irep;
     
    271195mrb_top_self(mrb_state *mrb)
    272196{
    273   if (!mrb->top_self) {
    274     mrb->top_self = (struct RObject*)mrb_obj_alloc(mrb, MRB_TT_OBJECT, mrb->object_class);
    275     mrb_define_singleton_method(mrb, mrb->top_self, "inspect", inspect_main, MRB_ARGS_NONE());
    276     mrb_define_singleton_method(mrb, mrb->top_self, "to_s", inspect_main, MRB_ARGS_NONE());
    277   }
    278197  return mrb_obj_value(mrb->top_self);
    279198}
  • EcnlProtoTool/trunk/mruby-2.1.1/src/string.c

    r331 r439  
    99#endif
    1010
     11#ifndef MRB_WITHOUT_FLOAT
    1112#include <float.h>
     13#include <math.h>
     14#endif
    1215#include <limits.h>
    1316#include <stddef.h>
     
    1922#include <mruby/range.h>
    2023#include <mruby/string.h>
    21 #include <mruby/re.h>
     24#include <mruby/numeric.h>
    2225
    2326typedef struct mrb_shared_string {
    24   mrb_bool nofree : 1;
    2527  int refcnt;
     28  mrb_ssize capa;
    2629  char *ptr;
    27   mrb_int len;
    2830} mrb_shared_string;
    2931
     
    3133
    3234#define mrb_obj_alloc_string(mrb) ((struct RString*)mrb_obj_alloc((mrb), MRB_TT_STRING, (mrb)->string_class))
     35
     36static struct RString*
     37str_init_normal_capa(mrb_state *mrb, struct RString *s,
     38                     const char *p, size_t len, size_t capa)
     39{
     40  char *dst = (char *)mrb_malloc(mrb, capa + 1);
     41  if (p) memcpy(dst, p, len);
     42  dst[len] = '\0';
     43  s->as.heap.ptr = dst;
     44  s->as.heap.len = (mrb_ssize)len;
     45  s->as.heap.aux.capa = (mrb_ssize)capa;
     46  RSTR_UNSET_TYPE_FLAG(s);
     47  return s;
     48}
     49
     50static struct RString*
     51str_init_normal(mrb_state *mrb, struct RString *s, const char *p, size_t len)
     52{
     53  return str_init_normal_capa(mrb, s, p, len, len);
     54}
     55
     56static struct RString*
     57str_init_embed(struct RString *s, const char *p, size_t len)
     58{
     59  if (p) memcpy(RSTR_EMBED_PTR(s), p, len);
     60  RSTR_EMBED_PTR(s)[len] = '\0';
     61  RSTR_SET_TYPE_FLAG(s, EMBED);
     62  RSTR_SET_EMBED_LEN(s, len);
     63  return s;
     64}
     65
     66static struct RString*
     67str_init_nofree(struct RString *s, const char *p, size_t len)
     68{
     69  s->as.heap.ptr = (char *)p;
     70  s->as.heap.len = (mrb_ssize)len;
     71  s->as.heap.aux.capa = 0;             /* nofree */
     72  RSTR_SET_TYPE_FLAG(s, NOFREE);
     73  return s;
     74}
     75
     76static struct RString*
     77str_init_shared(mrb_state *mrb, const struct RString *orig, struct RString *s, mrb_shared_string *shared)
     78{
     79  if (shared) {
     80    shared->refcnt++;
     81  }
     82  else {
     83    shared = (mrb_shared_string *)mrb_malloc(mrb, sizeof(mrb_shared_string));
     84    shared->refcnt = 1;
     85    shared->ptr = orig->as.heap.ptr;
     86    shared->capa = orig->as.heap.aux.capa;
     87  }
     88  s->as.heap.ptr = orig->as.heap.ptr;
     89  s->as.heap.len = orig->as.heap.len;
     90  s->as.heap.aux.shared = shared;
     91  RSTR_SET_TYPE_FLAG(s, SHARED);
     92  return s;
     93}
     94
     95static struct RString*
     96str_init_fshared(const struct RString *orig, struct RString *s, struct RString *fshared)
     97{
     98  s->as.heap.ptr = orig->as.heap.ptr;
     99  s->as.heap.len = orig->as.heap.len;
     100  s->as.heap.aux.fshared = fshared;
     101  RSTR_SET_TYPE_FLAG(s, FSHARED);
     102  return s;
     103}
     104
     105static struct RString*
     106str_init_modifiable(mrb_state *mrb, struct RString *s, const char *p, size_t len)
     107{
     108  if (RSTR_EMBEDDABLE_P(len)) {
     109    return str_init_embed(s, p, len);
     110  }
     111  else {
     112    return str_init_normal(mrb, s, p, len);
     113  }
     114}
    33115
    34116static struct RString*
    35117str_new_static(mrb_state *mrb, const char *p, size_t len)
    36118{
    37   struct RString *s;
    38 
    39   if (len >= MRB_INT_MAX) {
     119  if (RSTR_EMBEDDABLE_P(len)) {
     120    return str_init_embed(mrb_obj_alloc_string(mrb), p, len);
     121  }
     122  if (len >= MRB_SSIZE_MAX) {
    40123    mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
    41124  }
    42   s = mrb_obj_alloc_string(mrb);
    43   s->as.heap.len = len;
    44   s->as.heap.aux.capa = 0;             /* nofree */
    45   s->as.heap.ptr = (char *)p;
    46   s->flags = MRB_STR_NOFREE;
    47 
    48   return s;
     125  return str_init_nofree(mrb_obj_alloc_string(mrb), p, len);
    49126}
    50127
     
    52129str_new(mrb_state *mrb, const char *p, size_t len)
    53130{
     131  if (RSTR_EMBEDDABLE_P(len)) {
     132    return str_init_embed(mrb_obj_alloc_string(mrb), p, len);
     133  }
     134  if (len >= MRB_SSIZE_MAX) {
     135    mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
     136  }
     137  if (p && mrb_ro_data_p(p)) {
     138    return str_init_nofree(mrb_obj_alloc_string(mrb), p, len);
     139  }
     140  return str_init_normal(mrb, mrb_obj_alloc_string(mrb), p, len);
     141}
     142
     143static inline void
     144str_with_class(struct RString *s, mrb_value obj)
     145{
     146  s->c = mrb_str_ptr(obj)->c;
     147}
     148
     149static mrb_value
     150mrb_str_new_empty(mrb_state *mrb, mrb_value str)
     151{
     152  struct RString *s = str_new(mrb, 0, 0);
     153
     154  str_with_class(s, str);
     155  return mrb_obj_value(s);
     156}
     157
     158MRB_API mrb_value
     159mrb_str_new_capa(mrb_state *mrb, size_t capa)
     160{
    54161  struct RString *s;
    55162
    56   if (p && mrb_ro_data_p(p)) {
    57     return str_new_static(mrb, p, len);
    58   }
    59   s = mrb_obj_alloc_string(mrb);
    60   if (len < RSTRING_EMBED_LEN_MAX) {
    61     RSTR_SET_EMBED_FLAG(s);
    62     RSTR_SET_EMBED_LEN(s, len);
    63     if (p) {
    64       memcpy(s->as.ary, p, len);
    65     }
     163  if (RSTR_EMBEDDABLE_P(capa)) {
     164    s = str_init_embed(mrb_obj_alloc_string(mrb), NULL, 0);
     165  }
     166  else if (capa >= MRB_SSIZE_MAX) {
     167    mrb_raise(mrb, E_ARGUMENT_ERROR, "string capacity size too big");
     168    /* not reached */
     169    s = NULL;
    66170  }
    67171  else {
    68     if (len >= MRB_INT_MAX) {
    69       mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
    70     }
    71     s->as.heap.len = len;
    72     s->as.heap.aux.capa = len;
    73     s->as.heap.ptr = (char *)mrb_malloc(mrb, len+1);
    74     if (p) {
    75       memcpy(s->as.heap.ptr, p, len);
    76     }
    77   }
    78   RSTR_PTR(s)[len] = '\0';
    79   return s;
    80 }
    81 
    82 static inline void
    83 str_with_class(mrb_state *mrb, struct RString *s, mrb_value obj)
    84 {
    85   s->c = mrb_str_ptr(obj)->c;
    86 }
    87 
    88 static mrb_value
    89 mrb_str_new_empty(mrb_state *mrb, mrb_value str)
    90 {
    91   struct RString *s = str_new(mrb, 0, 0);
    92 
    93   str_with_class(mrb, s, str);
     172    s = str_init_normal_capa(mrb, mrb_obj_alloc_string(mrb), NULL, 0, capa);
     173  }
     174
    94175  return mrb_obj_value(s);
    95176}
     
    102183mrb_str_buf_new(mrb_state *mrb, size_t capa)
    103184{
    104   struct RString *s;
    105 
    106   s = mrb_obj_alloc_string(mrb);
    107 
    108   if (capa >= MRB_INT_MAX) {
    109     mrb_raise(mrb, E_ARGUMENT_ERROR, "string capacity size too big");
    110   }
    111185  if (capa < MRB_STR_BUF_MIN_SIZE) {
    112186    capa = MRB_STR_BUF_MIN_SIZE;
    113187  }
    114   s->as.heap.len = 0;
    115   s->as.heap.aux.capa = capa;
    116   s->as.heap.ptr = (char *)mrb_malloc(mrb, capa+1);
    117   RSTR_PTR(s)[0] = '\0';
    118 
    119   return mrb_obj_value(s);
     188  return mrb_str_new_capa(mrb, capa);
    120189}
    121190
     
    123192resize_capa(mrb_state *mrb, struct RString *s, size_t capacity)
    124193{
    125 #if SIZE_MAX > MRB_INT_MAX
    126     mrb_assert(capacity < MRB_INT_MAX);
     194#if SIZE_MAX > MRB_SSIZE_MAX
     195    mrb_assert(capacity < MRB_SSIZE_MAX);
    127196#endif
    128197  if (RSTR_EMBED_P(s)) {
    129     if (RSTRING_EMBED_LEN_MAX < capacity) {
    130       char *const tmp = (char *)mrb_malloc(mrb, capacity+1);
    131       const mrb_int len = RSTR_EMBED_LEN(s);
    132       memcpy(tmp, s->as.ary, len);
    133       RSTR_UNSET_EMBED_FLAG(s);
    134       s->as.heap.ptr = tmp;
    135       s->as.heap.len = len;
    136       s->as.heap.aux.capa = (mrb_int)capacity;
     198    if (!RSTR_EMBEDDABLE_P(capacity)) {
     199      str_init_normal_capa(mrb, s, RSTR_EMBED_PTR(s), RSTR_EMBED_LEN(s), capacity);
    137200    }
    138201  }
    139202  else {
    140203    s->as.heap.ptr = (char*)mrb_realloc(mrb, RSTR_PTR(s), capacity+1);
    141     s->as.heap.aux.capa = (mrb_int)capacity;
    142   }
    143 }
    144 
    145 static void
    146 str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len)
    147 {
    148   size_t capa;
    149   size_t total;
    150   ptrdiff_t off = -1;
    151 
    152   if (len == 0) return;
    153   mrb_str_modify(mrb, s);
    154   if (ptr >= RSTR_PTR(s) && ptr <= RSTR_PTR(s) + (size_t)RSTR_LEN(s)) {
    155       off = ptr - RSTR_PTR(s);
    156   }
    157 
    158   capa = RSTR_CAPA(s);
    159   if (capa <= RSTRING_EMBED_LEN_MAX)
    160     capa = RSTRING_EMBED_LEN_MAX+1;
    161 
    162   total = RSTR_LEN(s)+len;
    163   if (total >= MRB_INT_MAX) {
    164   size_error:
    165     mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
    166   }
    167   if (capa <= total) {
    168     while (total > capa) {
    169       if (capa <= MRB_INT_MAX / 2) {
    170         capa *= 2;
    171       }
    172       else {
    173         capa = total;
    174       }
    175     }
    176     if (capa < total || capa > MRB_INT_MAX) {
    177       goto size_error;
    178     }
    179     resize_capa(mrb, s, capa);
    180   }
    181   if (off != -1) {
    182       ptr = RSTR_PTR(s) + off;
    183   }
    184   memcpy(RSTR_PTR(s) + RSTR_LEN(s), ptr, len);
    185   mrb_assert_int_fit(size_t, total, mrb_int, MRB_INT_MAX);
    186   RSTR_SET_LEN(s, total);
    187   RSTR_PTR(s)[total] = '\0';   /* sentinel */
     204    s->as.heap.aux.capa = (mrb_ssize)capacity;
     205  }
    188206}
    189207
     
    194212}
    195213
    196 /*
    197  *  call-seq: (Caution! NULL string)
    198  *     String.new(str="")   => new_str
    199  *
    200  *  Returns a new string object containing a copy of <i>str</i>.
    201  */
    202 
    203214MRB_API mrb_value
    204215mrb_str_new_cstr(mrb_state *mrb, const char *p)
     
    231242  shared->refcnt--;
    232243  if (shared->refcnt == 0) {
    233     if (!shared->nofree) {
    234       mrb_free(mrb, shared->ptr);
    235     }
     244    mrb_free(mrb, shared->ptr);
    236245    mrb_free(mrb, shared);
     246  }
     247}
     248
     249static void
     250str_modify_keep_ascii(mrb_state *mrb, struct RString *s)
     251{
     252  if (RSTR_SHARED_P(s)) {
     253    mrb_shared_string *shared = s->as.heap.aux.shared;
     254
     255    if (shared->refcnt == 1 && s->as.heap.ptr == shared->ptr) {
     256      s->as.heap.aux.capa = shared->capa;
     257      s->as.heap.ptr[s->as.heap.len] = '\0';
     258      RSTR_UNSET_SHARED_FLAG(s);
     259      mrb_free(mrb, shared);
     260    }
     261    else {
     262      str_init_modifiable(mrb, s, s->as.heap.ptr, (size_t)s->as.heap.len);
     263      str_decref(mrb, shared);
     264    }
     265  }
     266  else if (RSTR_NOFREE_P(s) || RSTR_FSHARED_P(s)) {
     267    str_init_modifiable(mrb, s, s->as.heap.ptr, (size_t)s->as.heap.len);
     268  }
     269}
     270
     271static void
     272check_null_byte(mrb_state *mrb, mrb_value str)
     273{
     274  mrb_to_str(mrb, str);
     275  if (memchr(RSTRING_PTR(str), '\0', RSTRING_LEN(str))) {
     276    mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
    237277  }
    238278}
     
    245285  else if (RSTR_SHARED_P(str))
    246286    str_decref(mrb, str->as.heap.aux.shared);
    247   else if (!RSTR_NOFREE_P(str))
     287  else if (!RSTR_NOFREE_P(str) && !RSTR_FSHARED_P(str))
    248288    mrb_free(mrb, str->as.heap.ptr);
    249289}
     
    262302};
    263303
    264 static mrb_int
    265 utf8len(const char* p, const char* e)
     304mrb_int
     305mrb_utf8len(const char* p, const char* e)
    266306{
    267307  mrb_int len;
    268308  mrb_int i;
    269309
     310  if ((unsigned char)*p < 0x80) return 1;
    270311  len = utf8len_codepage[(unsigned char)*p];
    271   if (p + len > e) return 1;
     312  if (len == 1) return 1;
     313  if (len > e - p) return 1;
    272314  for (i = 1; i < len; ++i)
    273315    if ((p[i] & 0xc0) != 0x80)
     
    276318}
    277319
     320mrb_int
     321mrb_utf8_strlen(const char *str, mrb_int byte_len)
     322{
     323  mrb_int total = 0;
     324  const char *p = str;
     325  const char *e = p + byte_len;
     326
     327  while (p < e) {
     328    p += mrb_utf8len(p, e);
     329    total++;
     330  }
     331  return total;
     332}
     333
    278334static mrb_int
    279 utf8_strlen(mrb_value str, mrb_int len)
    280 {
    281   mrb_int total = 0;
    282   char* p = RSTRING_PTR(str);
    283   char* e = p;
    284   if (RSTRING(str)->flags & MRB_STR_NO_UTF) {
    285     return RSTRING_LEN(str);
    286   }
    287   e += len < 0 ? RSTRING_LEN(str) : len;
    288   while (p<e) {
    289     p += utf8len(p, e);
    290     total++;
    291   }
    292   if (RSTRING_LEN(str) == total) {
    293     RSTRING(str)->flags |= MRB_STR_NO_UTF;
    294   }
    295   return total;
    296 }
    297 
    298 #define RSTRING_CHAR_LEN(s) utf8_strlen(s, -1)
     335utf8_strlen(mrb_value str)
     336{
     337  struct RString *s = mrb_str_ptr(str);
     338  mrb_int byte_len = RSTR_LEN(s);
     339
     340  if (RSTR_ASCII_P(s)) {
     341    return byte_len;
     342  }
     343  else {
     344    mrb_int utf8_len = mrb_utf8_strlen(RSTR_PTR(s), byte_len);
     345    if (byte_len == utf8_len) RSTR_SET_ASCII_FLAG(s);
     346    return utf8_len;
     347  }
     348}
     349
     350#define RSTRING_CHAR_LEN(s) utf8_strlen(s)
    299351
    300352/* map character index to byte offset index */
     
    302354chars2bytes(mrb_value s, mrb_int off, mrb_int idx)
    303355{
    304   mrb_int i, b, n;
    305   const char *p = RSTRING_PTR(s) + off;
    306   const char *e = RSTRING_END(s);
    307 
    308   for (b=i=0; p<e && i<idx; i++) {
    309     n = utf8len(p, e);
    310     b += n;
    311     p += n;
    312   }
    313   return b;
     356  if (RSTR_ASCII_P(mrb_str_ptr(s))) {
     357    return idx;
     358  }
     359  else {
     360    mrb_int i, b, n;
     361    const char *p = RSTRING_PTR(s) + off;
     362    const char *e = RSTRING_END(s);
     363
     364    for (b=i=0; p<e && i<idx; i++) {
     365      n = mrb_utf8len(p, e);
     366      b += n;
     367      p += n;
     368    }
     369    return b;
     370  }
    314371}
    315372
    316373/* map byte offset to character index */
    317374static mrb_int
    318 bytes2chars(char *p, mrb_int bi)
    319 {
    320   mrb_int i, b, n;
    321 
    322   for (b=i=0; b<bi; i++) {
    323     n = utf8len_codepage[(unsigned char)*p];
    324     b += n;
    325     p += n;
    326   }
    327   if (b != bi) return -1;
     375bytes2chars(char *p, mrb_int len, mrb_int bi)
     376{
     377  const char *e = p + (size_t)len;
     378  const char *pivot = p + bi;
     379  mrb_int i;
     380
     381  for (i = 0; p < pivot; i ++) {
     382    p += mrb_utf8len(p, e);
     383  }
     384  if (p != pivot) return -1;
    328385  return i;
     386}
     387
     388static const char *
     389char_adjust(const char *beg, const char *end, const char *ptr)
     390{
     391  if ((ptr > beg || ptr < end) && (*ptr & 0xc0) == 0x80) {
     392    const int utf8_adjust_max = 3;
     393    const char *p;
     394
     395    if (ptr - beg > utf8_adjust_max) {
     396      beg = ptr - utf8_adjust_max;
     397    }
     398
     399    p = ptr;
     400    while (p > beg) {
     401      p --;
     402      if ((*p & 0xc0) != 0x80) {
     403        int clen = mrb_utf8len(p, end);
     404        if (clen > ptr - p) return p;
     405        break;
     406      }
     407    }
     408  }
     409
     410  return ptr;
     411}
     412
     413static const char *
     414char_backtrack(const char *ptr, const char *end)
     415{
     416  if (ptr < end) {
     417    const int utf8_bytelen_max = 4;
     418    const char *p;
     419
     420    if (end - ptr > utf8_bytelen_max) {
     421      ptr = end - utf8_bytelen_max;
     422    }
     423
     424    p = end;
     425    while (p > ptr) {
     426      p --;
     427      if ((*p & 0xc0) != 0x80) {
     428        int clen = utf8len_codepage[(unsigned char)*p];
     429        if (clen == end - p) { return p; }
     430        break;
     431      }
     432    }
     433  }
     434
     435  return end - 1;
     436}
     437
     438static mrb_int
     439str_index_str_by_char_search(mrb_state *mrb, const char *p, const char *pend, const char *s, const mrb_int slen, mrb_int off)
     440{
     441  /* Based on Quick Search algorithm (Boyer-Moore-Horspool algorithm) */
     442
     443  ptrdiff_t qstable[1 << CHAR_BIT];
     444
     445  /* Preprocessing */
     446  {
     447    mrb_int i;
     448
     449    for (i = 0; i < 1 << CHAR_BIT; i ++) {
     450      qstable[i] = slen;
     451    }
     452    for (i = 0; i < slen; i ++) {
     453      qstable[(unsigned char)s[i]] = slen - (i + 1);
     454    }
     455  }
     456
     457  /* Searching */
     458  while (p < pend && pend - p >= slen) {
     459    const char *pivot;
     460
     461    if (memcmp(p, s, slen) == 0) {
     462      return off;
     463    }
     464
     465    pivot = p + qstable[(unsigned char)p[slen - 1]];
     466    if (pivot >= pend || pivot < p /* overflowed */) { return -1; }
     467
     468    do {
     469      p += mrb_utf8len(p, pend);
     470      off ++;
     471    } while (p < pivot);
     472  }
     473
     474  return -1;
     475}
     476
     477static mrb_int
     478str_index_str_by_char(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
     479{
     480  const char *p = RSTRING_PTR(str);
     481  const char *pend = p + RSTRING_LEN(str);
     482  const char *s = RSTRING_PTR(sub);
     483  const mrb_int slen = RSTRING_LEN(sub);
     484  mrb_int off = pos;
     485
     486  for (; pos > 0; pos --) {
     487    if (pend - p < 1) { return -1; }
     488    p += mrb_utf8len(p, pend);
     489  }
     490
     491  if (slen < 1) { return off; }
     492
     493  return str_index_str_by_char_search(mrb, p, pend, s, slen, off);
    329494}
    330495
     
    333498#define RSTRING_CHAR_LEN(s) RSTRING_LEN(s)
    334499#define chars2bytes(p, off, ci) (ci)
    335 #define bytes2chars(p, bi) (bi)
     500#define bytes2chars(p, end, bi) (bi)
     501#define char_adjust(beg, end, ptr) (ptr)
     502#define char_backtrack(ptr, end) ((end) - 1)
    336503#define BYTES_ALIGN_CHECK(pos)
     504#define str_index_str_by_char(mrb, str, sub, pos) str_index_str(mrb, str, sub, pos)
     505#endif
     506
     507#ifndef MRB_QS_SHORT_STRING_LENGTH
     508#define MRB_QS_SHORT_STRING_LENGTH 2048
    337509#endif
    338510
     
    340512mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n)
    341513{
    342   const unsigned char *x = xs, *xe = xs + m;
    343   const unsigned char *y = ys;
    344   int i, qstable[256];
    345 
    346   /* Preprocessing */
    347   for (i = 0; i < 256; ++i)
    348     qstable[i] = m + 1;
    349   for (; x < xe; ++x)
    350     qstable[*x] = xe - x;
    351   /* Searching */
    352   for (; y + m <= ys + n; y += *(qstable + y[m])) {
    353     if (*xs == *y && memcmp(xs, y, m) == 0)
    354       return y - ys;
    355   }
    356   return -1;
     514  if (n + m < MRB_QS_SHORT_STRING_LENGTH) {
     515    const unsigned char *y = ys;
     516    const unsigned char *ye = ys+n-m+1;
     517
     518    for (;;) {
     519      y = (const unsigned char*)memchr(y, xs[0], (size_t)(ye-y));
     520      if (y == NULL) return -1;
     521      if (memcmp(xs, y, m) == 0) {
     522        return (mrb_int)(y - ys);
     523      }
     524      y++;
     525    }
     526    return -1;
     527  }
     528  else {
     529    const unsigned char *x = xs, *xe = xs + m;
     530    const unsigned char *y = ys;
     531    int i;
     532    ptrdiff_t qstable[256];
     533
     534    /* Preprocessing */
     535    for (i = 0; i < 256; ++i)
     536      qstable[i] = m + 1;
     537    for (; x < xe; ++x)
     538      qstable[*x] = xe - x;
     539    /* Searching */
     540    for (; y + m <= ys + n; y += *(qstable + y[m])) {
     541      if (*xs == *y && memcmp(xs, y, m) == 0)
     542        return (mrb_int)(y - ys);
     543    }
     544    return -1;
     545  }
    357546}
    358547
     
    373562
    374563    if (ys)
    375       return ys - y;
     564      return (mrb_int)(ys - y);
    376565    else
    377566      return -1;
     
    381570
    382571static void
    383 str_make_shared(mrb_state *mrb, struct RString *s)
    384 {
    385   if (!RSTR_SHARED_P(s)) {
    386     mrb_shared_string *shared = (mrb_shared_string *)mrb_malloc(mrb, sizeof(mrb_shared_string));
    387 
    388     shared->refcnt = 1;
    389     if (RSTR_EMBED_P(s)) {
    390       const mrb_int len = RSTR_EMBED_LEN(s);
    391       char *const tmp = (char *)mrb_malloc(mrb, len+1);
    392       memcpy(tmp, s->as.ary, len);
    393       tmp[len] = '\0';
    394       RSTR_UNSET_EMBED_FLAG(s);
    395       s->as.heap.ptr = tmp;
    396       s->as.heap.len = len;
    397       shared->nofree = FALSE;
    398       shared->ptr = s->as.heap.ptr;
    399     }
    400     else if (RSTR_NOFREE_P(s)) {
    401       shared->nofree = TRUE;
    402       shared->ptr = s->as.heap.ptr;
    403       RSTR_UNSET_NOFREE_FLAG(s);
    404     }
    405     else {
    406       shared->nofree = FALSE;
    407       if (s->as.heap.aux.capa > s->as.heap.len) {
    408         s->as.heap.ptr = shared->ptr = (char *)mrb_realloc(mrb, s->as.heap.ptr, s->as.heap.len+1);
    409       }
    410       else {
    411         shared->ptr = s->as.heap.ptr;
    412       }
    413     }
    414     shared->len = s->as.heap.len;
    415     s->as.heap.aux.shared = shared;
    416     RSTR_SET_SHARED_FLAG(s);
    417   }
    418 }
    419 
    420 static mrb_value
    421 byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
     572str_share(mrb_state *mrb, struct RString *orig, struct RString *s)
     573{
     574  size_t len = (size_t)orig->as.heap.len;
     575
     576  mrb_assert(!RSTR_EMBED_P(orig));
     577  if (RSTR_NOFREE_P(orig)) {
     578    str_init_nofree(s, orig->as.heap.ptr, len);
     579  }
     580  else if (RSTR_SHARED_P(orig)) {
     581    str_init_shared(mrb, orig, s, orig->as.heap.aux.shared);
     582  }
     583  else if (RSTR_FSHARED_P(orig)) {
     584    str_init_fshared(orig, s, orig->as.heap.aux.fshared);
     585  }
     586  else if (mrb_frozen_p(orig) && !RSTR_POOL_P(orig)) {
     587    str_init_fshared(orig, s, orig);
     588  }
     589  else {
     590    if (orig->as.heap.aux.capa > orig->as.heap.len) {
     591      orig->as.heap.ptr = (char *)mrb_realloc(mrb, orig->as.heap.ptr, len+1);
     592      orig->as.heap.aux.capa = (mrb_ssize)len;
     593    }
     594    str_init_shared(mrb, orig, s, NULL);
     595    str_init_shared(mrb, orig, orig, s->as.heap.aux.shared);
     596  }
     597}
     598
     599mrb_value
     600mrb_str_pool(mrb_state *mrb, const char *p, mrb_int len, mrb_bool nofree)
     601{
     602  struct RString *s = (struct RString *)mrb_malloc(mrb, sizeof(struct RString));
     603
     604  s->tt = MRB_TT_STRING;
     605  s->c = mrb->string_class;
     606  s->flags = 0;
     607
     608  if (RSTR_EMBEDDABLE_P(len)) {
     609    str_init_embed(s, p, len);
     610  }
     611  else if (nofree) {
     612    str_init_nofree(s, p, len);
     613  }
     614  else {
     615    str_init_normal(mrb, s, p, len);
     616  }
     617  RSTR_SET_POOL_FLAG(s);
     618  MRB_SET_FROZEN_FLAG(s);
     619  return mrb_obj_value(s);
     620}
     621
     622mrb_value
     623mrb_str_byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
    422624{
    423625  struct RString *orig, *s;
    424   mrb_shared_string *shared;
    425626
    426627  orig = mrb_str_ptr(str);
    427   if (RSTR_EMBED_P(orig) || RSTR_LEN(orig) == 0) {
    428     s = str_new(mrb, orig->as.ary+beg, len);
     628  s = mrb_obj_alloc_string(mrb);
     629  if (RSTR_EMBEDDABLE_P(len)) {
     630    str_init_embed(s, RSTR_PTR(orig)+beg, len);
    429631  }
    430632  else {
    431     str_make_shared(mrb, orig);
    432     shared = orig->as.heap.aux.shared;
    433     s = mrb_obj_alloc_string(mrb);
    434     s->as.heap.ptr = orig->as.heap.ptr + beg;
    435     s->as.heap.len = len;
    436     s->as.heap.aux.shared = shared;
    437     RSTR_SET_SHARED_FLAG(s);
    438     shared->refcnt++;
    439   }
    440 
     633    str_share(mrb, orig, s);
     634    s->as.heap.ptr += (mrb_ssize)beg;
     635    s->as.heap.len = (mrb_ssize)len;
     636  }
     637  RSTR_COPY_ASCII_FLAG(s, orig);
    441638  return mrb_obj_value(s);
     639}
     640
     641static void
     642str_range_to_bytes(mrb_value str, mrb_int *pos, mrb_int *len)
     643{
     644  *pos = chars2bytes(str, 0, *pos);
     645  *len = chars2bytes(str, *pos, *len);
    442646}
    443647#ifdef MRB_UTF8_STRING
     
    445649str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
    446650{
    447   beg = chars2bytes(str, 0, beg);
    448   len = chars2bytes(str, beg, len);
    449 
    450   return byte_subseq(mrb, str, beg, len);
     651  str_range_to_bytes(str, &beg, &len);
     652  return mrb_str_byte_subseq(mrb, str, beg, len);
    451653}
    452654#else
    453 #define str_subseq(mrb, str, beg, len) byte_subseq(mrb, str, beg, len)
     655#define str_subseq(mrb, str, beg, len) mrb_str_byte_subseq(mrb, str, beg, len)
    454656#endif
    455657
     658mrb_bool
     659mrb_str_beg_len(mrb_int str_len, mrb_int *begp, mrb_int *lenp)
     660{
     661  if (str_len < *begp || *lenp < 0) return FALSE;
     662  if (*begp < 0) {
     663    *begp += str_len;
     664    if (*begp < 0) return FALSE;
     665  }
     666  if (*lenp > str_len - *begp)
     667    *lenp = str_len - *begp;
     668  if (*lenp <= 0) {
     669    *lenp = 0;
     670  }
     671  return TRUE;
     672}
     673
    456674static mrb_value
    457675str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
    458676{
    459   mrb_int clen = RSTRING_CHAR_LEN(str);
    460 
    461   if (len < 0) return mrb_nil_value();
    462   if (clen == 0) {
    463     len = 0;
    464   }
    465   else if (beg < 0) {
    466     beg = clen + beg;
    467   }
    468   if (beg > clen) return mrb_nil_value();
    469   if (beg < 0) {
    470     beg += clen;
    471     if (beg < 0) return mrb_nil_value();
    472   }
    473   if (len > clen - beg)
    474     len = clen - beg;
    475   if (len <= 0) {
    476     len = 0;
    477   }
    478   return str_subseq(mrb, str, beg, len);
    479 }
    480 
    481 static mrb_int
    482 str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset)
     677  return mrb_str_beg_len(RSTRING_CHAR_LEN(str), &beg, &len) ?
     678    str_subseq(mrb, str, beg, len) : mrb_nil_value();
     679}
     680
     681MRB_API mrb_int
     682mrb_str_index(mrb_state *mrb, mrb_value str, const char *sptr, mrb_int slen, mrb_int offset)
    483683{
    484684  mrb_int pos;
    485   char *s, *sptr;
    486   mrb_int len, slen;
     685  char *s;
     686  mrb_int len;
    487687
    488688  len = RSTRING_LEN(str);
    489   slen = RSTRING_LEN(sub);
    490689  if (offset < 0) {
    491690    offset += len;
     
    499698  if (slen == 0) return offset;
    500699  /* need proceed one character at a time */
    501   sptr = RSTRING_PTR(sub);
    502   slen = RSTRING_LEN(sub);
    503700  len = RSTRING_LEN(str) - offset;
    504701  pos = mrb_memsearch(sptr, slen, s, len);
     
    507704}
    508705
    509 static void
    510 check_frozen(mrb_state *mrb, struct RString *s)
    511 {
    512   if (MRB_FROZEN_P(s)) {
    513     mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen string");
    514   }
     706static mrb_int
     707str_index_str(mrb_state *mrb, mrb_value str, mrb_value str2, mrb_int offset)
     708{
     709  const char *ptr;
     710  mrb_int len;
     711
     712  ptr = RSTRING_PTR(str2);
     713  len = RSTRING_LEN(str2);
     714
     715  return mrb_str_index(mrb, str, ptr, len, offset);
    515716}
    516717
     
    518719str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
    519720{
    520   long len;
    521 
    522   check_frozen(mrb, s1);
     721  size_t len;
     722
     723  mrb_check_frozen(mrb, s1);
    523724  if (s1 == s2) return mrb_obj_value(s1);
    524   s1->flags &= ~MRB_STR_NO_UTF;
    525   s1->flags |= s2->flags&MRB_STR_NO_UTF;
    526   len = RSTR_LEN(s2);
     725  RSTR_COPY_ASCII_FLAG(s1, s2);
    527726  if (RSTR_SHARED_P(s1)) {
    528727    str_decref(mrb, s1->as.heap.aux.shared);
    529728  }
    530   else if (!RSTR_EMBED_P(s1) && !RSTR_NOFREE_P(s1)) {
     729  else if (!RSTR_EMBED_P(s1) && !RSTR_NOFREE_P(s1) && !RSTR_FSHARED_P(s1)
     730           && s1->as.heap.ptr) {
    531731    mrb_free(mrb, s1->as.heap.ptr);
    532732  }
    533733
    534   RSTR_UNSET_NOFREE_FLAG(s1);
    535 
    536   if (RSTR_SHARED_P(s2)) {
    537 L_SHARE:
    538     RSTR_UNSET_EMBED_FLAG(s1);
    539     s1->as.heap.ptr = s2->as.heap.ptr;
    540     s1->as.heap.len = len;
    541     s1->as.heap.aux.shared = s2->as.heap.aux.shared;
    542     RSTR_SET_SHARED_FLAG(s1);
    543     s1->as.heap.aux.shared->refcnt++;
     734  len = (size_t)RSTR_LEN(s2);
     735  if (RSTR_EMBEDDABLE_P(len)) {
     736    str_init_embed(s1, RSTR_PTR(s2), len);
    544737  }
    545738  else {
    546     if (len <= RSTRING_EMBED_LEN_MAX) {
    547       RSTR_UNSET_SHARED_FLAG(s1);
    548       RSTR_SET_EMBED_FLAG(s1);
    549       memcpy(s1->as.ary, RSTR_PTR(s2), len);
    550       RSTR_SET_EMBED_LEN(s1, len);
    551     }
    552     else {
    553       str_make_shared(mrb, s2);
    554       goto L_SHARE;
    555     }
     739    str_share(mrb, s2, s1);
    556740  }
    557741
     
    562746str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
    563747{
    564   char *s, *sbeg, *t;
     748  const char *s, *sbeg, *t;
    565749  struct RString *ps = mrb_str_ptr(str);
    566750  mrb_int len = RSTRING_LEN(sub);
     
    575759  t = RSTRING_PTR(sub);
    576760  if (len) {
     761    s = char_adjust(sbeg, sbeg + RSTR_LEN(ps), s);
    577762    while (sbeg <= s) {
    578763      if (memcmp(s, t, len) == 0) {
    579         return s - RSTR_PTR(ps);
    580       }
    581       s--;
     764        return (mrb_int)(s - RSTR_PTR(ps));
     765      }
     766      s = char_backtrack(sbeg, s);
    582767    }
    583768    return -1;
     
    607792
    608793char*
    609 mrb_utf8_from_locale(const char *str, size_t len)
     794mrb_utf8_from_locale(const char *str, int len)
    610795{
    611796  wchar_t* wcsp;
    612797  char* mbsp;
    613   size_t mbssize, wcssize;
     798  int mbssize, wcssize;
    614799
    615800  if (len == 0)
    616801    return strdup("");
    617802  if (len == -1)
    618     len = strlen(str);
     803    len = (int)strlen(str);
    619804  wcssize = MultiByteToWideChar(GetACP(), 0, str, len,  NULL, 0);
    620805  wcsp = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t));
     
    637822
    638823char*
    639 mrb_locale_from_utf8(const char *utf8, size_t len)
     824mrb_locale_from_utf8(const char *utf8, int len)
    640825{
    641826  wchar_t* wcsp;
    642827  char* mbsp;
    643   size_t mbssize, wcssize;
     828  int mbssize, wcssize;
    644829
    645830  if (len == 0)
    646831    return strdup("");
    647832  if (len == -1)
    648     len = strlen(utf8);
     833    len = (int)strlen(utf8);
    649834  wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, len,  NULL, 0);
    650835  wcsp = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t));
     
    667852
    668853MRB_API void
     854mrb_str_modify_keep_ascii(mrb_state *mrb, struct RString *s)
     855{
     856  mrb_check_frozen(mrb, s);
     857  str_modify_keep_ascii(mrb, s);
     858}
     859
     860MRB_API void
    669861mrb_str_modify(mrb_state *mrb, struct RString *s)
    670862{
    671   check_frozen(mrb, s);
    672   s->flags &= ~MRB_STR_NO_UTF;
    673   if (RSTR_SHARED_P(s)) {
    674     mrb_shared_string *shared = s->as.heap.aux.shared;
    675 
    676     if (shared->nofree == 0 && shared->refcnt == 1 && s->as.heap.ptr == shared->ptr) {
    677       s->as.heap.ptr = shared->ptr;
    678       s->as.heap.aux.capa = shared->len;
    679       RSTR_PTR(s)[s->as.heap.len] = '\0';
    680       mrb_free(mrb, shared);
    681     }
    682     else {
    683       char *ptr, *p;
    684       mrb_int len;
    685 
    686       p = RSTR_PTR(s);
    687       len = s->as.heap.len;
    688       if (len < RSTRING_EMBED_LEN_MAX) {
    689         RSTR_SET_EMBED_FLAG(s);
    690         RSTR_SET_EMBED_LEN(s, len);
    691         ptr = RSTR_PTR(s);
    692       }
    693       else {
    694         ptr = (char *)mrb_malloc(mrb, (size_t)len + 1);
    695         s->as.heap.ptr = ptr;
    696         s->as.heap.aux.capa = len;
    697       }
    698       if (p) {
    699         memcpy(ptr, p, len);
    700       }
    701       ptr[len] = '\0';
    702       str_decref(mrb, shared);
    703     }
    704     RSTR_UNSET_SHARED_FLAG(s);
    705     return;
    706   }
    707   if (RSTR_NOFREE_P(s)) {
    708     char *p = s->as.heap.ptr;
    709     mrb_int len = s->as.heap.len;
    710 
    711     RSTR_UNSET_NOFREE_FLAG(s);
    712     if (len < RSTRING_EMBED_LEN_MAX) {
    713       RSTR_SET_EMBED_FLAG(s);
    714       RSTR_SET_EMBED_LEN(s, len);
    715     }
    716     else {
    717       s->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)len+1);
    718       s->as.heap.aux.capa = len;
    719     }
    720     if (p) {
    721       memcpy(RSTR_PTR(s), p, len);
    722     }
    723     RSTR_PTR(s)[len] = '\0';
    724     return;
    725   }
     863  mrb_str_modify_keep_ascii(mrb, s);
     864  RSTR_UNSET_ASCII_FLAG(s);
    726865}
    727866
     
    732871  struct RString *s = mrb_str_ptr(str);
    733872
     873  if (len < 0) {
     874    mrb_raise(mrb, E_ARGUMENT_ERROR, "negative (or overflowed) string size");
     875  }
    734876  mrb_str_modify(mrb, s);
    735877  slen = RSTR_LEN(s);
     
    749891  struct RString *s;
    750892
    751   if (!mrb_string_p(str0)) {
    752     mrb_raise(mrb, E_TYPE_ERROR, "expected String");
    753   }
    754 
     893  check_null_byte(mrb, str0);
    755894  s = str_new(mrb, RSTRING_PTR(str0), RSTRING_LEN(str0));
    756   if ((strlen(RSTR_PTR(s)) ^ RSTR_LEN(s)) != 0) {
    757     mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
    758   }
    759895  return RSTR_PTR(s);
    760896}
    761897
    762 /*
    763  *  call-seq: (Caution! String("abcd") change)
    764  *     String("abcdefg") = String("abcd") + String("efg")
    765  *
    766  *  Returns a new string object containing a copy of <i>str</i>.
    767  */
    768898MRB_API void
    769899mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other)
    770900{
    771   struct RString *s1 = mrb_str_ptr(self), *s2;
    772   mrb_int len;
    773 
    774   mrb_str_modify(mrb, s1);
    775   if (!mrb_string_p(other)) {
    776     other = mrb_str_to_str(mrb, other);
    777   }
    778   s2 = mrb_str_ptr(other);
    779   if (RSTR_LEN(s2) == 0) {
    780     return;
    781   }
    782   len = RSTR_LEN(s1) + RSTR_LEN(s2);
    783 
    784   if (len < 0 || len >= MRB_INT_MAX) {
    785     mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
    786   }
    787   if (RSTRING_CAPA(self) < len) {
    788     resize_capa(mrb, s1, len);
    789   }
    790   memcpy(RSTR_PTR(s1)+RSTR_LEN(s1), RSTR_PTR(s2), RSTR_LEN(s2));
    791   RSTR_SET_LEN(s1, len);
    792   RSTR_PTR(s1)[len] = '\0';
    793 }
    794 
    795 /*
    796  *  call-seq: (Caution! String("abcd") remain)
    797  *     String("abcdefg") = String("abcd") + String("efg")
    798  *
    799  *  Returns a new string object containing a copy of <i>str</i>.
    800  */
     901  other = mrb_str_to_str(mrb, other);
     902  mrb_str_cat_str(mrb, self, other);
     903}
     904
    801905MRB_API mrb_value
    802906mrb_str_plus(mrb_state *mrb, mrb_value a, mrb_value b)
     
    816920
    817921/*
    818  *  call-seq: (Caution! String("abcd") remain) for stack_argument
    819  *     String("abcdefg") = String("abcd") + String("efg")
    820  *
    821  *  Returns a new string object containing a copy of <i>str</i>.
     922 *  call-seq:
     923 *     str + other_str   -> new_str
     924 *
     925 *  Concatenation---Returns a new <code>String</code> containing
     926 *  <i>other_str</i> concatenated to <i>str</i>.
     927 *
     928 *     "Hello from " + self.to_s   #=> "Hello from main"
    822929 */
    823930static mrb_value
     
    873980    mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argument");
    874981  }
    875   if (times && MRB_INT_MAX / times < RSTRING_LEN(self)) {
     982  if (times && MRB_SSIZE_MAX / times < RSTRING_LEN(self)) {
    876983    mrb_raise(mrb, E_ARGUMENT_ERROR, "argument too big");
    877984  }
     
    879986  len = RSTRING_LEN(self)*times;
    880987  str2 = str_new(mrb, 0, len);
    881   str_with_class(mrb, str2, self);
     988  str_with_class(str2, self);
    882989  p = RSTR_PTR(str2);
    883990  if (len > 0) {
     
    891998  }
    892999  p[RSTR_LEN(str2)] = '\0';
     1000  RSTR_COPY_ASCII_FLAG(str2, mrb_str_ptr(self));
    8931001
    8941002  return mrb_obj_value(str2);
     
    9591067  mrb_get_args(mrb, "o", &str2);
    9601068  if (!mrb_string_p(str2)) {
    961     if (!mrb_respond_to(mrb, str2, mrb_intern_lit(mrb, "to_s"))) {
    962       return mrb_nil_value();
    963     }
    964     else if (!mrb_respond_to(mrb, str2, mrb_intern_lit(mrb, "<=>"))) {
    965       return mrb_nil_value();
    966     }
    967     else {
    968       mrb_value tmp = mrb_funcall(mrb, str2, "<=>", 1, str1);
    969 
    970       if (!mrb_nil_p(tmp)) return mrb_nil_value();
    971       if (!mrb_fixnum_p(tmp)) {
    972         return mrb_funcall(mrb, mrb_fixnum_value(0), "-", 1, tmp);
    973       }
    974       result = -mrb_fixnum(tmp);
    975     }
     1069    return mrb_nil_value();
    9761070  }
    9771071  else {
     
    9951089mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2)
    9961090{
    997   if (mrb_immediate_p(str2)) return FALSE;
    998   if (!mrb_string_p(str2)) {
    999     if (mrb_nil_p(str2)) return FALSE;
    1000     if (!mrb_respond_to(mrb, str2, mrb_intern_lit(mrb, "to_str"))) {
    1001       return FALSE;
    1002     }
    1003     str2 = mrb_funcall(mrb, str2, "to_str", 0);
    1004     return mrb_equal(mrb, str2, str1);
    1005   }
     1091  if (!mrb_string_p(str2)) return FALSE;
    10061092  return str_eql(mrb, str1, str2);
    10071093}
     
    10281114}
    10291115/* ---------------------------------- */
     1116
    10301117MRB_API mrb_value
    10311118mrb_str_to_str(mrb_state *mrb, mrb_value str)
    10321119{
    1033   mrb_value s;
    1034 
    1035   if (!mrb_string_p(str)) {
    1036     s = mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str");
    1037     if (mrb_nil_p(s)) {
    1038       s = mrb_convert_type(mrb, str, MRB_TT_STRING, "String", "to_s");
    1039     }
    1040     return s;
    1041   }
    1042   return str;
    1043 }
    1044 
     1120  switch (mrb_type(str)) {
     1121  case MRB_TT_STRING:
     1122    return str;
     1123  case MRB_TT_SYMBOL:
     1124    return mrb_sym_str(mrb, mrb_symbol(str));
     1125  case MRB_TT_FIXNUM:
     1126    return mrb_fixnum_to_str(mrb, str, 10);
     1127  case MRB_TT_CLASS:
     1128  case MRB_TT_MODULE:
     1129    return mrb_mod_to_s(mrb, str);
     1130  default:
     1131    return mrb_convert_type(mrb, str, MRB_TT_STRING, "String", "to_s");
     1132  }
     1133}
     1134
     1135/* obslete: use RSTRING_PTR() */
    10451136MRB_API const char*
    1046 mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr)
    1047 {
    1048   mrb_value str = mrb_str_to_str(mrb, ptr);
     1137mrb_string_value_ptr(mrb_state *mrb, mrb_value str)
     1138{
     1139  str = mrb_str_to_str(mrb, str);
    10491140  return RSTRING_PTR(str);
    10501141}
    10511142
     1143/* obslete: use RSTRING_LEN() */
    10521144MRB_API mrb_int
    10531145mrb_string_value_len(mrb_state *mrb, mrb_value ptr)
    10541146{
    1055   mrb_value str = mrb_str_to_str(mrb, ptr);
    1056   return RSTRING_LEN(str);
    1057 }
    1058 
    1059 void
    1060 mrb_noregexp(mrb_state *mrb, mrb_value self)
    1061 {
    1062   mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp class not implemented");
    1063 }
    1064 
    1065 void
    1066 mrb_regexp_check(mrb_state *mrb, mrb_value obj)
    1067 {
    1068   if (mrb_regexp_p(mrb, obj)) {
    1069     mrb_noregexp(mrb, obj);
    1070   }
     1147  mrb_to_str(mrb, ptr);
     1148  return RSTRING_LEN(ptr);
    10711149}
    10721150
     
    10771155  struct RString *dup = str_new(mrb, 0, 0);
    10781156
    1079   str_with_class(mrb, dup, str);
     1157  str_with_class(dup, str);
    10801158  return str_replace(mrb, dup, s);
    10811159}
    10821160
    1083 static mrb_value
    1084 mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value indx)
    1085 {
    1086   mrb_int idx;
    1087 
    1088   mrb_regexp_check(mrb, indx);
    1089   switch (mrb_type(indx)) {
    1090     case MRB_TT_FIXNUM:
    1091       idx = mrb_fixnum(indx);
    1092 
    1093 num_index:
    1094       str = str_substr(mrb, str, idx, 1);
    1095       if (!mrb_nil_p(str) && RSTRING_LEN(str) == 0) return mrb_nil_value();
    1096       return str;
    1097 
    1098     case MRB_TT_STRING:
    1099       if (str_index(mrb, str, indx, 0) != -1)
    1100         return mrb_str_dup(mrb, indx);
    1101       return mrb_nil_value();
    1102 
    1103     case MRB_TT_RANGE:
    1104       goto range_arg;
    1105 
    1106     default:
    1107       indx = mrb_Integer(mrb, indx);
    1108       if (mrb_nil_p(indx)) {
    1109       range_arg:
    1110         {
    1111           mrb_int beg, len;
    1112 
    1113           len = RSTRING_CHAR_LEN(str);
    1114           switch (mrb_range_beg_len(mrb, indx, &beg, &len, len, TRUE)) {
    1115           case 1:
    1116             return str_subseq(mrb, str, beg, len);
    1117           case 2:
    1118             return mrb_nil_value();
     1161enum str_convert_range {
     1162  /* `beg` and `len` are byte unit in `0 ... str.bytesize` */
     1163  STR_BYTE_RANGE_CORRECTED = 1,
     1164
     1165  /* `beg` and `len` are char unit in any range */
     1166  STR_CHAR_RANGE = 2,
     1167
     1168  /* `beg` and `len` are char unit in `0 ... str.size` */
     1169  STR_CHAR_RANGE_CORRECTED = 3,
     1170
     1171  /* `beg` is out of range */
     1172  STR_OUT_OF_RANGE = -1
     1173};
     1174
     1175static enum str_convert_range
     1176str_convert_range(mrb_state *mrb, mrb_value str, mrb_value indx, mrb_value alen, mrb_int *beg, mrb_int *len)
     1177{
     1178  if (!mrb_undef_p(alen)) {
     1179    *beg = mrb_int(mrb, indx);
     1180    *len = mrb_int(mrb, alen);
     1181    return STR_CHAR_RANGE;
     1182  }
     1183  else {
     1184    switch (mrb_type(indx)) {
     1185      case MRB_TT_FIXNUM:
     1186        *beg = mrb_fixnum(indx);
     1187        *len = 1;
     1188        return STR_CHAR_RANGE;
     1189
     1190      case MRB_TT_STRING:
     1191        *beg = str_index_str(mrb, str, indx, 0);
     1192        if (*beg < 0) { break; }
     1193        *len = RSTRING_LEN(indx);
     1194        return STR_BYTE_RANGE_CORRECTED;
     1195
     1196      case MRB_TT_RANGE:
     1197        goto range_arg;
     1198
     1199      default:
     1200        indx = mrb_to_int(mrb, indx);
     1201        if (mrb_fixnum_p(indx)) {
     1202          *beg = mrb_fixnum(indx);
     1203          *len = 1;
     1204          return STR_CHAR_RANGE;
     1205        }
     1206range_arg:
     1207        *len = RSTRING_CHAR_LEN(str);
     1208        switch (mrb_range_beg_len(mrb, indx, beg, len, *len, TRUE)) {
     1209          case MRB_RANGE_OK:
     1210            return STR_CHAR_RANGE_CORRECTED;
     1211          case MRB_RANGE_OUT:
     1212            return STR_OUT_OF_RANGE;
    11191213          default:
    11201214            break;
    1121           }
    11221215        }
     1216
    11231217        mrb_raise(mrb, E_TYPE_ERROR, "can't convert to Fixnum");
    1124       }
    1125       idx = mrb_fixnum(indx);
    1126       goto num_index;
    1127   }
    1128   return mrb_nil_value();    /* not reached */
     1218    }
     1219  }
     1220  return STR_OUT_OF_RANGE;
     1221}
     1222
     1223static mrb_value
     1224mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value indx, mrb_value alen)
     1225{
     1226  mrb_int beg, len;
     1227
     1228  switch (str_convert_range(mrb, str, indx, alen, &beg, &len)) {
     1229    case STR_CHAR_RANGE_CORRECTED:
     1230      return str_subseq(mrb, str, beg, len);
     1231    case STR_CHAR_RANGE:
     1232      str = str_substr(mrb, str, beg, len);
     1233      if (mrb_undef_p(alen) && !mrb_nil_p(str) && RSTRING_LEN(str) == 0) return mrb_nil_value();
     1234      return str;
     1235    case STR_BYTE_RANGE_CORRECTED:
     1236      if (mrb_string_p(indx)) {
     1237        return mrb_str_dup(mrb, indx);
     1238      }
     1239      else {
     1240        return mrb_str_byte_subseq(mrb, str, beg, len);
     1241      }
     1242    case STR_OUT_OF_RANGE:
     1243    default:
     1244      return mrb_nil_value();
     1245  }
    11291246}
    11301247
     
    11361253 *     str[fixnum, fixnum]         => new_str or nil
    11371254 *     str[range]                  => new_str or nil
    1138  *     str[regexp]                 => new_str or nil
    1139  *     str[regexp, fixnum]         => new_str or nil
    11401255 *     str[other_str]              => new_str or nil
    11411256 *     str.slice(fixnum)           => fixnum or nil
     
    11731288{
    11741289  mrb_value a1, a2;
    1175   int argc;
    1176 
    1177   argc = mrb_get_args(mrb, "o|o", &a1, &a2);
    1178   if (argc == 2) {
    1179     mrb_int n1, n2;
    1180 
    1181     mrb_regexp_check(mrb, a1);
    1182     mrb_get_args(mrb, "ii", &n1, &n2);
    1183     return str_substr(mrb, str, n1, n2);
    1184   }
    1185   if (argc != 1) {
    1186     mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 1)", mrb_fixnum_value(argc));
    1187   }
    1188   return mrb_str_aref(mrb, str, a1);
     1290
     1291  if (mrb_get_args(mrb, "o|o", &a1, &a2) == 1) {
     1292    a2 = mrb_undef_value();
     1293  }
     1294
     1295  return mrb_str_aref(mrb, str, a1, a2);
     1296}
     1297
     1298static mrb_noreturn void
     1299str_out_of_index(mrb_state *mrb, mrb_value index)
     1300{
     1301  mrb_raisef(mrb, E_INDEX_ERROR, "index %v out of string", index);
     1302}
     1303
     1304static mrb_value
     1305str_replace_partial(mrb_state *mrb, mrb_value src, mrb_int pos, mrb_int end, mrb_value rep)
     1306{
     1307  const mrb_int shrink_threshold = 256;
     1308  struct RString *str = mrb_str_ptr(src);
     1309  mrb_int len = RSTR_LEN(str);
     1310  mrb_int replen, newlen;
     1311  char *strp;
     1312
     1313  if (end > len) { end = len; }
     1314
     1315  if (pos < 0 || pos > len) {
     1316    str_out_of_index(mrb, mrb_fixnum_value(pos));
     1317  }
     1318
     1319  replen = (mrb_nil_p(rep) ? 0 : RSTRING_LEN(rep));
     1320  newlen = replen + len - (end - pos);
     1321
     1322  if (newlen >= MRB_SSIZE_MAX || newlen < replen /* overflowed */) {
     1323    mrb_raise(mrb, E_RUNTIME_ERROR, "string size too big");
     1324  }
     1325
     1326  mrb_str_modify(mrb, str);
     1327
     1328  if (len < newlen) {
     1329    resize_capa(mrb, str, newlen);
     1330  }
     1331
     1332  strp = RSTR_PTR(str);
     1333
     1334  memmove(strp + newlen - (len - end), strp + end, len - end);
     1335  if (!mrb_nil_p(rep)) {
     1336    memmove(strp + pos, RSTRING_PTR(rep), replen);
     1337  }
     1338  RSTR_SET_LEN(str, newlen);
     1339  strp[newlen] = '\0';
     1340
     1341  if (len - newlen >= shrink_threshold) {
     1342    resize_capa(mrb, str, newlen);
     1343  }
     1344
     1345  return src;
     1346}
     1347
     1348#define IS_EVSTR(p,e) ((p) < (e) && (*(p) == '$' || *(p) == '@' || *(p) == '{'))
     1349
     1350static mrb_value
     1351str_escape(mrb_state *mrb, mrb_value str, mrb_bool inspect)
     1352{
     1353  const char *p, *pend;
     1354  char buf[4];  /* `\x??` or UTF-8 character */
     1355  mrb_value result = mrb_str_new_lit(mrb, "\"");
     1356#ifdef MRB_UTF8_STRING
     1357  uint32_t ascii_flag = MRB_STR_ASCII;
     1358#endif
     1359
     1360  p = RSTRING_PTR(str); pend = RSTRING_END(str);
     1361  for (;p < pend; p++) {
     1362    unsigned char c, cc;
     1363#ifdef MRB_UTF8_STRING
     1364    if (inspect) {
     1365      mrb_int clen = mrb_utf8len(p, pend);
     1366      if (clen > 1) {
     1367        mrb_int i;
     1368
     1369        for (i=0; i<clen; i++) {
     1370          buf[i] = p[i];
     1371        }
     1372        mrb_str_cat(mrb, result, buf, clen);
     1373        p += clen-1;
     1374        ascii_flag = 0;
     1375        continue;
     1376      }
     1377    }
     1378#endif
     1379    c = *p;
     1380    if (c == '"'|| c == '\\' || (c == '#' && IS_EVSTR(p+1, pend))) {
     1381      buf[0] = '\\'; buf[1] = c;
     1382      mrb_str_cat(mrb, result, buf, 2);
     1383      continue;
     1384    }
     1385    if (ISPRINT(c)) {
     1386      buf[0] = c;
     1387      mrb_str_cat(mrb, result, buf, 1);
     1388      continue;
     1389    }
     1390    switch (c) {
     1391      case '\n': cc = 'n'; break;
     1392      case '\r': cc = 'r'; break;
     1393      case '\t': cc = 't'; break;
     1394      case '\f': cc = 'f'; break;
     1395      case '\013': cc = 'v'; break;
     1396      case '\010': cc = 'b'; break;
     1397      case '\007': cc = 'a'; break;
     1398      case 033: cc = 'e'; break;
     1399      default: cc = 0; break;
     1400    }
     1401    if (cc) {
     1402      buf[0] = '\\';
     1403      buf[1] = (char)cc;
     1404      mrb_str_cat(mrb, result, buf, 2);
     1405      continue;
     1406    }
     1407    else {
     1408      buf[0] = '\\';
     1409      buf[1] = 'x';
     1410      buf[3] = mrb_digitmap[c % 16]; c /= 16;
     1411      buf[2] = mrb_digitmap[c % 16];
     1412      mrb_str_cat(mrb, result, buf, 4);
     1413      continue;
     1414    }
     1415  }
     1416  mrb_str_cat_lit(mrb, result, "\"");
     1417#ifdef MRB_UTF8_STRING
     1418  if (inspect) {
     1419    mrb_str_ptr(str)->flags |= ascii_flag;
     1420    mrb_str_ptr(result)->flags |= ascii_flag;
     1421  }
     1422  else {
     1423    RSTR_SET_ASCII_FLAG(mrb_str_ptr(result));
     1424  }
     1425#endif
     1426
     1427  return result;
     1428}
     1429
     1430static void
     1431mrb_str_aset(mrb_state *mrb, mrb_value str, mrb_value indx, mrb_value alen, mrb_value replace)
     1432{
     1433  mrb_int beg, len, charlen;
     1434
     1435  mrb_to_str(mrb, replace);
     1436
     1437  switch (str_convert_range(mrb, str, indx, alen, &beg, &len)) {
     1438    case STR_OUT_OF_RANGE:
     1439    default:
     1440      mrb_raise(mrb, E_INDEX_ERROR, "string not matched");
     1441    case STR_CHAR_RANGE:
     1442      if (len < 0) {
     1443        mrb_raisef(mrb, E_INDEX_ERROR, "negative length %v", alen);
     1444      }
     1445      charlen = RSTRING_CHAR_LEN(str);
     1446      if (beg < 0) { beg += charlen; }
     1447      if (beg < 0 || beg > charlen) { str_out_of_index(mrb, indx); }
     1448      /* fall through */
     1449    case STR_CHAR_RANGE_CORRECTED:
     1450      str_range_to_bytes(str, &beg, &len);
     1451      /* fall through */
     1452    case STR_BYTE_RANGE_CORRECTED:
     1453      str_replace_partial(mrb, str, beg, beg + len, replace);
     1454  }
     1455}
     1456
     1457/*
     1458 * call-seq:
     1459 *    str[fixnum] = replace
     1460 *    str[fixnum, fixnum] = replace
     1461 *    str[range] = replace
     1462 *    str[other_str] = replace
     1463 *
     1464 * Modify +self+ by replacing the content of +self+.
     1465 * The portion of the string affected is determined using the same criteria as +String#[]+.
     1466 */
     1467static mrb_value
     1468mrb_str_aset_m(mrb_state *mrb, mrb_value str)
     1469{
     1470  mrb_value indx, alen, replace;
     1471
     1472  switch (mrb_get_args(mrb, "oo|S!", &indx, &alen, &replace)) {
     1473    case 2:
     1474      replace = alen;
     1475      alen = mrb_undef_value();
     1476      break;
     1477    case 3:
     1478      break;
     1479  }
     1480  mrb_str_aset(mrb, str, indx, alen, replace);
     1481  return str;
    11891482}
    11901483
     
    12091502  struct RString *s = mrb_str_ptr(str);
    12101503
    1211   mrb_str_modify(mrb, s);
     1504  mrb_str_modify_keep_ascii(mrb, s);
    12121505  if (RSTR_LEN(s) == 0 || !RSTR_PTR(s)) return mrb_nil_value();
    12131506  p = RSTR_PTR(s); pend = RSTR_PTR(s) + RSTR_LEN(s);
     
    12671560  struct RString *s = mrb_str_ptr(str);
    12681561
    1269   mrb_str_modify(mrb, s);
    12701562  argc = mrb_get_args(mrb, "|S", &rs);
     1563  mrb_str_modify_keep_ascii(mrb, s);
    12711564  len = RSTR_LEN(s);
    12721565  if (argc == 0) {
     
    13301623 *
    13311624 *  Returns a new <code>String</code> with the given record separator removed
    1332  *  from the end of <i>str</i> (if present). If <code>$/</code> has not been
    1333  *  changed from the default Ruby record separator, then <code>chomp</code> also
    1334  *  removes carriage return characters (that is it will remove <code>\n</code>,
     1625 *  from the end of <i>str</i> (if present). <code>chomp</code> also removes
     1626 *  carriage return characters (that is it will remove <code>\n</code>,
    13351627 *  <code>\r</code>, and <code>\r\n</code>).
    13361628 *
     
    13671659  struct RString *s = mrb_str_ptr(str);
    13681660
    1369   mrb_str_modify(mrb, s);
     1661  mrb_str_modify_keep_ascii(mrb, s);
    13701662  if (RSTR_LEN(s) > 0) {
    13711663    mrb_int len;
     
    13741666    const char* e = p + RSTR_LEN(s);
    13751667    while (p<e) {
    1376       mrb_int clen = utf8len(p, e);
     1668      mrb_int clen = mrb_utf8len(p, e);
    13771669      if (p + clen>=e) break;
    13781670      p += clen;
     
    14361728  struct RString *s = mrb_str_ptr(str);
    14371729
    1438   mrb_str_modify(mrb, s);
     1730  mrb_str_modify_keep_ascii(mrb, s);
    14391731  p = RSTR_PTR(s);
    14401732  pend = RSTR_PTR(s) + RSTR_LEN(s);
     
    15041796
    15051797  mrb_get_args(mrb, "o", &str2);
    1506   eql_p = (mrb_type(str2) == MRB_TT_STRING) && str_eql(mrb, self, str2);
     1798  eql_p = (mrb_string_p(str2)) && str_eql(mrb, self, str2);
    15071799
    15081800  return mrb_bool_value(eql_p);
     
    15151807}
    15161808
    1517 mrb_int
     1809uint32_t
    15181810mrb_str_hash(mrb_state *mrb, mrb_value str)
    15191811{
     
    15221814  mrb_int len = RSTR_LEN(s);
    15231815  char *p = RSTR_PTR(s);
    1524   mrb_int key = 0;
     1816  uint64_t key = 0;
    15251817
    15261818  while (len--) {
     
    15281820    p++;
    15291821  }
    1530   return key + (key>>5);
     1822  return (uint32_t)(key + (key>>5));
    15311823}
    15321824
     
    15641856
    15651857  mrb_get_args(mrb, "S", &str2);
    1566   if (str_index(mrb, self, str2, 0) < 0)
     1858  if (str_index_str(mrb, self, str2, 0) < 0)
    15671859    return mrb_bool_value(FALSE);
    15681860  return mrb_bool_value(TRUE);
     
    15731865 *  call-seq:
    15741866 *     str.index(substring [, offset])   => fixnum or nil
    1575  *     str.index(fixnum [, offset])      => fixnum or nil
    1576  *     str.index(regexp [, offset])      => fixnum or nil
    15771867 *
    15781868 *  Returns the index of the first occurrence of the given
    1579  *  <i>substring</i>,
    1580  *  character (<i>fixnum</i>), or pattern (<i>regexp</i>) in <i>str</i>.
    1581  *  Returns
    1582  *  <code>nil</code> if not found.
     1869 *  <i>substring</i>. Returns <code>nil</code> if not found.
    15831870 *  If the second parameter is present, it
    15841871 *  specifies the position in the string to begin the search.
    15851872 *
    1586  *     "hello".index('e')             #=> 1
     1873 *     "hello".index('l')             #=> 2
    15871874 *     "hello".index('lo')            #=> 3
    15881875 *     "hello".index('a')             #=> nil
    1589  *     "hello".index(101)             #=> 1(101=0x65='e')
    1590  *     "hello".index(/[aeiou]/, -3)   #=> 4
    1591  */
    1592 static mrb_value
    1593 mrb_str_index(mrb_state *mrb, mrb_value str)
    1594 {
    1595   mrb_value *argv;
    1596   mrb_int argc;
     1876 *     "hello".index('l', -2)         #=> 3
     1877 */
     1878static mrb_value
     1879mrb_str_index_m(mrb_state *mrb, mrb_value str)
     1880{
    15971881  mrb_value sub;
    1598   mrb_int pos, clen;
    1599 
    1600   mrb_get_args(mrb, "*", &argv, &argc);
    1601   if (argc == 2) {
    1602     mrb_get_args(mrb, "oi", &sub, &pos);
    1603   }
    1604   else {
     1882  mrb_int pos;
     1883
     1884  if (mrb_get_args(mrb, "S|i", &sub, &pos) == 1) {
    16051885    pos = 0;
    1606     if (argc > 0)
    1607       sub = argv[0];
    1608     else
    1609       sub = mrb_nil_value();
    1610   }
    1611   mrb_regexp_check(mrb, sub);
    1612   clen = RSTRING_CHAR_LEN(str);
    1613   if (pos < 0) {
     1886  }
     1887  else if (pos < 0) {
     1888    mrb_int clen = RSTRING_CHAR_LEN(str);
    16141889    pos += clen;
    16151890    if (pos < 0) {
     
    16171892    }
    16181893  }
    1619   if (pos > clen) return mrb_nil_value();
    1620   pos = chars2bytes(str, 0, pos);
    1621 
    1622   switch (mrb_type(sub)) {
    1623     default: {
    1624       mrb_value tmp;
    1625 
    1626       tmp = mrb_check_string_type(mrb, sub);
    1627       if (mrb_nil_p(tmp)) {
    1628         mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %S given", sub);
    1629       }
    1630       sub = tmp;
    1631     }
    1632     /* fall through */
    1633     case MRB_TT_STRING:
    1634       pos = str_index(mrb, str, sub, pos);
    1635       break;
    1636   }
     1894  pos = str_index_str_by_char(mrb, str, sub, pos);
    16371895
    16381896  if (pos == -1) return mrb_nil_value();
    1639   pos = bytes2chars(RSTRING_PTR(str), pos);
    16401897  BYTES_ALIGN_CHECK(pos);
    16411898  return mrb_fixnum_value(pos);
    16421899}
    1643 
    1644 #define STR_REPLACE_SHARED_MIN 10
    16451900
    16461901/* 15.2.10.5.24 */
     
    17121967mrb_obj_as_string(mrb_state *mrb, mrb_value obj)
    17131968{
    1714   mrb_value str;
    1715 
    17161969  if (mrb_string_p(obj)) {
    17171970    return obj;
    17181971  }
    1719   str = mrb_funcall(mrb, obj, "to_s", 0);
    1720   if (!mrb_string_p(str))
    1721     return mrb_any_to_s(mrb, obj);
    1722   return str;
     1972  return mrb_str_to_str(mrb, obj);
    17231973}
    17241974
     
    17532003}
    17542004
    1755 MRB_API mrb_value
    1756 mrb_string_type(mrb_state *mrb, mrb_value str)
    1757 {
    1758   return mrb_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str");
    1759 }
    1760 
    1761 MRB_API mrb_value
    1762 mrb_check_string_type(mrb_state *mrb, mrb_value str)
    1763 {
    1764   return mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str");
     2005static inline void
     2006str_reverse(char *p, char *e)
     2007{
     2008  char c;
     2009
     2010  while (p < e) {
     2011    c = *p;
     2012    *p++ = *e;
     2013    *e-- = c;
     2014  }
    17652015}
    17662016
     
    17752025mrb_str_reverse_bang(mrb_state *mrb, mrb_value str)
    17762026{
     2027  struct RString *s = mrb_str_ptr(str);
     2028  char *p, *e;
     2029
    17772030#ifdef MRB_UTF8_STRING
    17782031  mrb_int utf8_len = RSTRING_CHAR_LEN(str);
    1779   mrb_int len = RSTRING_LEN(str);
    1780 
    1781   if (utf8_len == len) goto bytes;
    1782   if (utf8_len > 1) {
    1783     char *buf;
    1784     char *p, *e, *r;
    1785 
    1786     mrb_str_modify(mrb, mrb_str_ptr(str));
    1787     len = RSTRING_LEN(str);
    1788     buf = (char*)mrb_malloc(mrb, (size_t)len);
    1789     p = buf;
    1790     e = buf + len;
    1791 
    1792     memcpy(buf, RSTRING_PTR(str), len);
    1793     r = RSTRING_PTR(str) + len;
    1794 
     2032  mrb_int len = RSTR_LEN(s);
     2033
     2034  if (utf8_len < 2) return str;
     2035  if (utf8_len < len) {
     2036    mrb_str_modify(mrb, s);
     2037    p = RSTR_PTR(s);
     2038    e = p + RSTR_LEN(s);
    17952039    while (p<e) {
    1796       mrb_int clen = utf8len(p, e);
    1797       r -= clen;
    1798       memcpy(r, p, clen);
     2040      mrb_int clen = mrb_utf8len(p, e);
     2041      str_reverse(p, p + clen - 1);
    17992042      p += clen;
    18002043    }
    1801     mrb_free(mrb, buf);
     2044    goto bytes;
     2045  }
     2046#endif
     2047
     2048  if (RSTR_LEN(s) > 1) {
     2049    mrb_str_modify(mrb, s);
     2050    goto bytes;
    18022051  }
    18032052  return str;
    18042053
    18052054 bytes:
    1806 #endif
    1807   {
    1808     struct RString *s = mrb_str_ptr(str);
    1809     char *p, *e;
    1810     char c;
    1811 
    1812     mrb_str_modify(mrb, s);
    1813     if (RSTR_LEN(s) > 1) {
    1814       p = RSTR_PTR(s);
    1815       e = p + RSTR_LEN(s) - 1;
    1816       while (p < e) {
    1817       c = *p;
    1818       *p++ = *e;
    1819       *e-- = c;
    1820       }
    1821     }
    1822     return str;
    1823   }
     2055  p = RSTR_PTR(s);
     2056  e = p + RSTR_LEN(s) - 1;
     2057  str_reverse(p, e);
     2058  return str;
    18242059}
    18252060
     
    18452080/*
    18462081 *  call-seq:
    1847  *     str.rindex(substring [, fixnum])   => fixnum or nil
    1848  *     str.rindex(fixnum [, fixnum])   => fixnum or nil
    1849  *     str.rindex(regexp [, fixnum])   => fixnum or nil
    1850  *
    1851  *  Returns the index of the last occurrence of the given <i>substring</i>,
    1852  *  character (<i>fixnum</i>), or pattern (<i>regexp</i>) in <i>str</i>. Returns
    1853  *  <code>nil</code> if not found. If the second parameter is present, it
    1854  *  specifies the position in the string to end the search---characters beyond
    1855  *  this point will not be considered.
     2082 *     str.rindex(substring [, offset])   => fixnum or nil
     2083 *
     2084 *  Returns the index of the last occurrence of the given <i>substring</i>.
     2085 *  Returns <code>nil</code> if not found. If the second parameter is
     2086 *  present, it specifies the position in the string to end the
     2087 *  search---characters beyond this point will not be considered.
    18562088 *
    18572089 *     "hello".rindex('e')             #=> 1
    18582090 *     "hello".rindex('l')             #=> 3
    18592091 *     "hello".rindex('a')             #=> nil
    1860  *     "hello".rindex(101)             #=> 1
    1861  *     "hello".rindex(/[aeiou]/, -2)   #=> 1
     2092 *     "hello".rindex('l', 2)          #=> 2
    18622093 */
    18632094static mrb_value
    18642095mrb_str_rindex(mrb_state *mrb, mrb_value str)
    18652096{
    1866   mrb_value *argv;
    1867   mrb_int argc;
    18682097  mrb_value sub;
    18692098  mrb_int pos, len = RSTRING_CHAR_LEN(str);
    18702099
    1871   mrb_get_args(mrb, "*", &argv, &argc);
    1872   if (argc == 2) {
    1873     mrb_get_args(mrb, "oi", &sub, &pos);
     2100  if (mrb_get_args(mrb, "S|i", &sub, &pos) == 1) {
     2101    pos = len;
     2102  }
     2103  else {
    18742104    if (pos < 0) {
    18752105      pos += len;
    18762106      if (pos < 0) {
    1877         mrb_regexp_check(mrb, sub);
    18782107        return mrb_nil_value();
    18792108      }
     
    18812110    if (pos > len) pos = len;
    18822111  }
    1883   else {
    1884     pos = len;
    1885     if (argc > 0)
    1886       sub = argv[0];
    1887     else
    1888       sub = mrb_nil_value();
    1889   }
    18902112  pos = chars2bytes(str, 0, pos);
    1891   mrb_regexp_check(mrb, sub);
    1892 
    1893   switch (mrb_type(sub)) {
    1894     default: {
    1895       mrb_value tmp;
    1896 
    1897       tmp = mrb_check_string_type(mrb, sub);
    1898       if (mrb_nil_p(tmp)) {
    1899         mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %S given", sub);
    1900       }
    1901       sub = tmp;
    1902     }
    1903      /* fall through */
    1904     case MRB_TT_STRING:
    1905       pos = str_rindex(mrb, str, sub, pos);
    1906       if (pos >= 0) {
    1907         pos = bytes2chars(RSTRING_PTR(str), pos);
    1908         BYTES_ALIGN_CHECK(pos);
    1909         return mrb_fixnum_value(pos);
    1910       }
    1911       break;
    1912 
    1913   } /* end of switch (TYPE(sub)) */
     2113  pos = str_rindex(mrb, str, sub, pos);
     2114  if (pos >= 0) {
     2115    pos = bytes2chars(RSTRING_PTR(str), RSTRING_LEN(str), pos);
     2116    BYTES_ALIGN_CHECK(pos);
     2117    return mrb_fixnum_value(pos);
     2118  }
    19142119  return mrb_nil_value();
    19152120}
     
    19192124/*
    19202125 *  call-seq:
    1921  *     str.split(pattern="\n", [limit])   => anArray
     2126 *     str.split(separator=nil, [limit])   => anArray
    19222127 *
    19232128 *  Divides <i>str</i> into substrings based on a delimiter, returning an array
    19242129 *  of these substrings.
    19252130 *
    1926  *  If <i>pattern</i> is a <code>String</code>, then its contents are used as
    1927  *  the delimiter when splitting <i>str</i>. If <i>pattern</i> is a single
     2131 *  If <i>separator</i> is a <code>String</code>, then its contents are used as
     2132 *  the delimiter when splitting <i>str</i>. If <i>separator</i> is a single
    19282133 *  space, <i>str</i> is split on whitespace, with leading whitespace and runs
    19292134 *  of contiguous whitespace characters ignored.
    19302135 *
    1931  *  If <i>pattern</i> is a <code>Regexp</code>, <i>str</i> is divided where the
    1932  *  pattern matches. Whenever the pattern matches a zero-length string,
    1933  *  <i>str</i> is split into individual characters.
    1934  *
    1935  *  If <i>pattern</i> is omitted, the value of <code>$;</code> is used.  If
    1936  *  <code>$;</code> is <code>nil</code> (which is the default), <i>str</i> is
    1937  *  split on whitespace as if ' ' were specified.
     2136 *  If <i>separator</i> is omitted or <code>nil</code> (which is the default),
     2137 *  <i>str</i> is split on whitespace as if ' ' were specified.
    19382138 *
    19392139 *  If the <i>limit</i> parameter is omitted, trailing null fields are
     
    19462146 *     " now's  the time".split        #=> ["now's", "the", "time"]
    19472147 *     " now's  the time".split(' ')   #=> ["now's", "the", "time"]
    1948  *     " now's  the time".split(/ /)   #=> ["", "now's", "", "the", "time"]
    1949  *     "hello".split(//)               #=> ["h", "e", "l", "l", "o"]
    1950  *     "hello".split(//, 3)            #=> ["h", "e", "llo"]
    19512148 *
    19522149 *     "mellow yellow".split("ello")   #=> ["m", "w y", "w"]
     
    19592156mrb_str_split_m(mrb_state *mrb, mrb_value str)
    19602157{
    1961   int argc;
     2158  mrb_int argc;
    19622159  mrb_value spat = mrb_nil_value();
    1963   enum {awk, string, regexp} split_type = string;
     2160  enum {awk, string} split_type = string;
    19642161  mrb_int i = 0;
    19652162  mrb_int beg;
     
    19832180    split_type = awk;
    19842181  }
    1985   else {
    1986     if (mrb_string_p(spat)) {
    1987       split_type = string;
    1988       if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' ') {
    1989           split_type = awk;
    1990       }
    1991     }
    1992     else {
    1993       mrb_noregexp(mrb, str);
    1994     }
     2182  else if (!mrb_string_p(spat)) {
     2183    mrb_raise(mrb, E_TYPE_ERROR, "expected String");
     2184  }
     2185  else if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' ') {
     2186    split_type = awk;
    19952187  }
    19962188
     
    20182210      }
    20192211      else if (ISSPACE(c)) {
    2020         mrb_ary_push(mrb, result, byte_subseq(mrb, str, beg, end-beg));
     2212        mrb_ary_push(mrb, result, mrb_str_byte_subseq(mrb, str, beg, end-beg));
    20212213        mrb_gc_arena_restore(mrb, ai);
    20222214        skip = TRUE;
     
    20292221    }
    20302222  }
    2031   else if (split_type == string) {
     2223  else {                        /* split_type == string */
    20322224    mrb_int str_len = RSTRING_LEN(str);
    20332225    mrb_int pat_len = RSTRING_LEN(spat);
     
    20432235        end = chars2bytes(str, idx, 1);
    20442236      }
    2045       mrb_ary_push(mrb, result, byte_subseq(mrb, str, idx, end));
     2237      mrb_ary_push(mrb, result, mrb_str_byte_subseq(mrb, str, idx, end));
    20462238      mrb_gc_arena_restore(mrb, ai);
    20472239      idx += end + pat_len;
     
    20502242    beg = idx;
    20512243  }
    2052   else {
    2053     mrb_noregexp(mrb, str);
    2054   }
    20552244  if (RSTRING_LEN(str) > 0 && (lim_p || RSTRING_LEN(str) > beg || lim < 0)) {
    20562245    if (RSTRING_LEN(str) == beg) {
     
    20582247    }
    20592248    else {
    2060       tmp = byte_subseq(mrb, str, beg, RSTRING_LEN(str)-beg);
     2249      tmp = mrb_str_byte_subseq(mrb, str, beg, RSTRING_LEN(str)-beg);
    20612250    }
    20622251    mrb_ary_push(mrb, result, tmp);
     
    20722261}
    20732262
    2074 MRB_API mrb_value
    2075 mrb_str_len_to_inum(mrb_state *mrb, const char *str, size_t len, int base, int badcheck)
     2263mrb_value
     2264mrb_str_len_to_inum(mrb_state *mrb, const char *str, mrb_int len, mrb_int base, int badcheck)
    20762265{
    20772266  const char *p = str;
     
    21562345    default:
    21572346      if (base < 2 || 36 < base) {
    2158         mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %S", mrb_fixnum_value(base));
     2347        mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %i", base);
    21592348      }
    21602349      break;
     
    21832372      p--;
    21842373  }
    2185   if (p == pend) {
     2374  if (p == pend || *p == '_') {
    21862375    if (badcheck) goto bad;
    21872376    return mrb_fixnum_value(0);
     
    22092398    n += c;
    22102399    if (n > (uint64_t)MRB_INT_MAX + (sign ? 0 : 1)) {
    2211       mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%S) too big for integer",
    2212                  mrb_str_new(mrb, str, pend-str));
     2400#ifndef MRB_WITHOUT_FLOAT
     2401      if (base == 10) {
     2402        return mrb_float_value(mrb, mrb_str_to_dbl(mrb, mrb_str_new(mrb, str, len), badcheck));
     2403      }
     2404      else
     2405#endif
     2406      {
     2407        mrb_raisef(mrb, E_RANGE_ERROR, "string (%l) too big for integer", str, pend-str);
     2408      }
    22132409    }
    22142410  }
    22152411  val = (mrb_int)n;
    22162412  if (badcheck) {
    2217     if (p == str) goto bad; /* no number */
     2413    if (p == str) goto bad;             /* no number */
     2414    if (*(p - 1) == '_') goto bad;      /* trailing '_' */
    22182415    while (p<pend && ISSPACE(*p)) p++;
    2219     if (p<pend) goto bad;       /* trailing garbage */
     2416    if (p<pend) goto bad;               /* trailing garbage */
    22202417  }
    22212418
     
    22252422  /* not reached */
    22262423 bad:
    2227   mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for number(%S)",
    2228              mrb_inspect(mrb, mrb_str_new(mrb, str, pend-str)));
     2424  mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for number(%!l)", str, pend-str);
    22292425  /* not reached */
    22302426  return mrb_fixnum_value(0);
     
    22322428
    22332429MRB_API mrb_value
    2234 mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
     2430mrb_cstr_to_inum(mrb_state *mrb, const char *str, mrb_int base, mrb_bool badcheck)
    22352431{
    22362432  return mrb_str_len_to_inum(mrb, str, strlen(str), base, badcheck);
    22372433}
    22382434
     2435/* obslete: use RSTRING_CSTR() or mrb_string_cstr() */
    22392436MRB_API const char*
    22402437mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr)
    22412438{
    2242   mrb_value str = mrb_str_to_str(mrb, *ptr);
    2243   struct RString *ps = mrb_str_ptr(str);
    2244   mrb_int len = mrb_str_strlen(mrb, ps);
    2245   char *p = RSTR_PTR(ps);
    2246 
    2247   if (!p || p[len] != '\0') {
    2248     if (MRB_FROZEN_P(ps)) {
    2249       *ptr = str = mrb_str_dup(mrb, str);
    2250       ps = mrb_str_ptr(str);
    2251     }
    2252     mrb_str_modify(mrb, ps);
    2253     return RSTR_PTR(ps);
    2254   }
    2255   return p;
     2439  struct RString *ps;
     2440  const char *p;
     2441  mrb_int len;
     2442
     2443  check_null_byte(mrb, *ptr);
     2444  ps = mrb_str_ptr(*ptr);
     2445  p = RSTR_PTR(ps);
     2446  len = RSTR_LEN(ps);
     2447  if (p[len] == '\0') {
     2448    return p;
     2449  }
     2450
     2451  /*
     2452   * Even after str_modify_keep_ascii(), NULL termination is not ensured if
     2453   * RSTR_SET_LEN() is used explicitly (e.g. String#delete_suffix!).
     2454   */
     2455  str_modify_keep_ascii(mrb, ps);
     2456  RSTR_PTR(ps)[len] = '\0';
     2457  return RSTR_PTR(ps);
     2458}
     2459
     2460MRB_API const char*
     2461mrb_string_cstr(mrb_state *mrb, mrb_value str)
     2462{
     2463  return mrb_string_value_cstr(mrb, &str);
    22562464}
    22572465
     
    22622470  mrb_int len;
    22632471
    2264   s = mrb_string_value_ptr(mrb, str);
     2472  mrb_to_str(mrb, str);
     2473  s = RSTRING_PTR(str);
    22652474  len = RSTRING_LEN(str);
    22662475  return mrb_str_len_to_inum(mrb, s, len, base, badcheck);
     
    22952504  mrb_get_args(mrb, "|i", &base);
    22962505  if (base < 0) {
    2297     mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %S", mrb_fixnum_value(base));
     2506    mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %i", base);
    22982507  }
    22992508  return mrb_str_to_inum(mrb, self, base, FALSE);
    23002509}
    23012510
    2302 MRB_API double
    2303 mrb_cstr_to_dbl(mrb_state *mrb, const char * p, mrb_bool badcheck)
    2304 {
     2511#ifndef MRB_WITHOUT_FLOAT
     2512double
     2513mrb_str_len_to_dbl(mrb_state *mrb, const char *s, size_t len, mrb_bool badcheck)
     2514{
     2515  char buf[DBL_DIG * 4 + 20];
     2516  const char *p = s, *p2;
     2517  const char *pend = p + len;
    23052518  char *end;
    2306   char buf[DBL_DIG * 4 + 10];
     2519  char *n;
     2520  char prev = 0;
    23072521  double d;
    2308 
    2309   enum {max_width = 20};
     2522  mrb_bool dot = FALSE;
    23102523
    23112524  if (!p) return 0.0;
    2312   while (ISSPACE(*p)) p++;
    2313 
    2314   if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
    2315     return 0.0;
    2316   }
     2525  while (p<pend && ISSPACE(*p)) p++;
     2526  p2 = p;
     2527
     2528  if (pend - p > 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
     2529    mrb_value x;
     2530
     2531    if (!badcheck) return 0.0;
     2532    x = mrb_str_len_to_inum(mrb, p, pend-p, 0, badcheck);
     2533    if (mrb_fixnum_p(x))
     2534      d = (double)mrb_fixnum(x);
     2535    else /* if (mrb_float_p(x)) */
     2536      d = mrb_float(x);
     2537    return d;
     2538  }
     2539  while (p < pend) {
     2540    if (!*p) {
     2541      if (badcheck) {
     2542        mrb_raise(mrb, E_ARGUMENT_ERROR, "string for Float contains null byte");
     2543        /* not reached */
     2544      }
     2545      pend = p;
     2546      p = p2;
     2547      goto nocopy;
     2548    }
     2549    if (!badcheck && *p == ' ') {
     2550      pend = p;
     2551      p = p2;
     2552      goto nocopy;
     2553    }
     2554    if (*p == '_') break;
     2555    p++;
     2556  }
     2557  p = p2;
     2558  n = buf;
     2559  while (p < pend) {
     2560    char c = *p++;
     2561    if (c == '.') dot = TRUE;
     2562    if (c == '_') {
     2563      /* remove an underscore between digits */
     2564      if (n == buf || !ISDIGIT(prev) || p == pend) {
     2565        if (badcheck) goto bad;
     2566        break;
     2567      }
     2568    }
     2569    else if (badcheck && prev == '_' && !ISDIGIT(c)) goto bad;
     2570    else {
     2571      const char *bend = buf+sizeof(buf)-1;
     2572      if (n==bend) {            /* buffer overflow */
     2573        if (dot) break;         /* cut off remaining fractions */
     2574        return INFINITY;
     2575      }
     2576      *n++ = c;
     2577    }
     2578    prev = c;
     2579  }
     2580  *n = '\0';
     2581  p = buf;
     2582  pend = n;
     2583nocopy:
    23172584  d = mrb_float_read(p, &end);
    23182585  if (p == end) {
    23192586    if (badcheck) {
    23202587bad:
    2321       mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for float(%S)", mrb_str_new_cstr(mrb, p));
     2588      mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for float(%!s)", s);
    23222589      /* not reached */
    23232590    }
    23242591    return d;
    23252592  }
    2326   if (*end) {
    2327     char *n = buf;
    2328     char *e = buf + sizeof(buf) - 1;
    2329     char prev = 0;
    2330 
    2331     while (p < end && n < e) prev = *n++ = *p++;
    2332     while (*p) {
    2333       if (*p == '_') {
    2334         /* remove underscores between digits */
    2335         if (badcheck) {
    2336           if (n == buf || !ISDIGIT(prev)) goto bad;
    2337           ++p;
    2338           if (!ISDIGIT(*p)) goto bad;
    2339         }
    2340         else {
    2341           while (*++p == '_');
    2342           continue;
    2343         }
    2344       }
    2345       prev = *p++;
    2346       if (n < e) *n++ = prev;
    2347     }
    2348     *n = '\0';
    2349     p = buf;
    2350 
    2351     if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
    2352       return 0.0;
    2353     }
    2354 
    2355     d = mrb_float_read(p, &end);
    2356     if (badcheck) {
    2357       if (!end || p == end) goto bad;
    2358       while (*end && ISSPACE(*end)) end++;
    2359       if (*end) goto bad;
    2360     }
     2593  if (badcheck) {
     2594    if (!end || p == end) goto bad;
     2595    while (end<pend && ISSPACE(*end)) end++;
     2596    if (end<pend) goto bad;
    23612597  }
    23622598  return d;
     2599}
     2600
     2601MRB_API double
     2602mrb_cstr_to_dbl(mrb_state *mrb, const char *s, mrb_bool badcheck)
     2603{
     2604  return mrb_str_len_to_dbl(mrb, s, strlen(s), badcheck);
    23632605}
    23642606
     
    23662608mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck)
    23672609{
    2368   char *s;
    2369   mrb_int len;
    2370 
    2371   str = mrb_str_to_str(mrb, str);
    2372   s = RSTRING_PTR(str);
    2373   len = RSTRING_LEN(str);
    2374   if (s) {
    2375     if (badcheck && memchr(s, '\0', len)) {
    2376       mrb_raise(mrb, E_ARGUMENT_ERROR, "string for Float contains null byte");
    2377     }
    2378     if (s[len]) {    /* no sentinel somehow */
    2379       struct RString *temp_str = str_new(mrb, s, len);
    2380       s = RSTR_PTR(temp_str);
    2381     }
    2382   }
    2383   return mrb_cstr_to_dbl(mrb, s, badcheck);
     2610  return mrb_str_len_to_dbl(mrb, RSTRING_PTR(str), RSTRING_LEN(str), badcheck);
    23842611}
    23852612
     
    24032630  return mrb_float_value(mrb, mrb_str_to_dbl(mrb, self, FALSE));
    24042631}
     2632#endif
    24052633
    24062634/* 15.2.10.5.40 */
     
    24082636 *  call-seq:
    24092637 *     str.to_s     => str
    2410  *     str.to_str   => str
    24112638 *
    24122639 *  Returns the receiver.
     
    24362663  mrb_bool modify = FALSE;
    24372664
    2438   mrb_str_modify(mrb, s);
     2665  mrb_str_modify_keep_ascii(mrb, s);
    24392666  p = RSTRING_PTR(str);
    24402667  pend = RSTRING_END(str);
     
    24722699}
    24732700
    2474 #define IS_EVSTR(p,e) ((p) < (e) && (*(p) == '$' || *(p) == '@' || *(p) == '{'))
    2475 
    24762701/*
    24772702 *  call-seq:
     
    24842709mrb_str_dump(mrb_state *mrb, mrb_value str)
    24852710{
    2486   mrb_int len;
    2487   const char *p, *pend;
    2488   char *q;
    2489   struct RString *result;
    2490 
    2491   len = 2;                  /* "" */
    2492   p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
    2493   while (p < pend) {
    2494     unsigned char c = *p++;
    2495     switch (c) {
    2496       case '"':  case '\\':
    2497       case '\n': case '\r':
    2498       case '\t': case '\f':
    2499       case '\013': case '\010': case '\007': case '\033':
    2500         len += 2;
    2501         break;
    2502 
    2503       case '#':
    2504         len += IS_EVSTR(p, pend) ? 2 : 1;
    2505         break;
    2506 
    2507       default:
    2508         if (ISPRINT(c)) {
    2509           len++;
    2510         }
    2511         else {
    2512           len += 4;                /* \NNN */
    2513         }
    2514         break;
    2515     }
    2516   }
    2517 
    2518   result = str_new(mrb, 0, len);
    2519   str_with_class(mrb, result, str);
    2520   p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
    2521   q = RSTR_PTR(result);
    2522   *q++ = '"';
    2523   while (p < pend) {
    2524     unsigned char c = *p++;
    2525 
    2526     switch (c) {
    2527       case '"':
    2528       case '\\':
    2529         *q++ = '\\';
    2530         *q++ = c;
    2531         break;
    2532 
    2533       case '\n':
    2534         *q++ = '\\';
    2535         *q++ = 'n';
    2536         break;
    2537 
    2538       case '\r':
    2539         *q++ = '\\';
    2540         *q++ = 'r';
    2541         break;
    2542 
    2543       case '\t':
    2544         *q++ = '\\';
    2545         *q++ = 't';
    2546         break;
    2547 
    2548       case '\f':
    2549         *q++ = '\\';
    2550         *q++ = 'f';
    2551         break;
    2552 
    2553       case '\013':
    2554         *q++ = '\\';
    2555         *q++ = 'v';
    2556         break;
    2557 
    2558       case '\010':
    2559         *q++ = '\\';
    2560         *q++ = 'b';
    2561         break;
    2562 
    2563       case '\007':
    2564         *q++ = '\\';
    2565         *q++ = 'a';
    2566         break;
    2567 
    2568       case '\033':
    2569         *q++ = '\\';
    2570         *q++ = 'e';
    2571         break;
    2572 
    2573       case '#':
    2574         if (IS_EVSTR(p, pend)) *q++ = '\\';
    2575         *q++ = '#';
    2576         break;
    2577 
    2578       default:
    2579         if (ISPRINT(c)) {
    2580           *q++ = c;
    2581         }
    2582         else {
    2583           *q++ = '\\';
    2584           q[2] = '0' + c % 8; c /= 8;
    2585           q[1] = '0' + c % 8; c /= 8;
    2586           q[0] = '0' + c % 8;
    2587           q += 3;
    2588         }
    2589     }
    2590   }
    2591   *q = '"';
    2592   return mrb_obj_value(result);
     2711  return str_escape(mrb, str, FALSE);
    25932712}
    25942713
     
    25962715mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len)
    25972716{
    2598   str_buf_cat(mrb, mrb_str_ptr(str), ptr, len);
     2717  struct RString *s = mrb_str_ptr(str);
     2718  size_t capa;
     2719  size_t total;
     2720  ptrdiff_t off = -1;
     2721
     2722  if (len == 0) return str;
     2723  mrb_str_modify(mrb, s);
     2724  if (ptr >= RSTR_PTR(s) && ptr <= RSTR_PTR(s) + (size_t)RSTR_LEN(s)) {
     2725      off = ptr - RSTR_PTR(s);
     2726  }
     2727
     2728  capa = RSTR_CAPA(s);
     2729  total = RSTR_LEN(s)+len;
     2730  if (total >= MRB_SSIZE_MAX) {
     2731  size_error:
     2732    mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
     2733  }
     2734  if (capa <= total) {
     2735    if (capa == 0) capa = 1;
     2736    while (capa <= total) {
     2737      if (capa <= MRB_SSIZE_MAX / 2) {
     2738        capa *= 2;
     2739      }
     2740      else {
     2741        capa = total+1;
     2742      }
     2743    }
     2744    if (capa <= total || capa > MRB_SSIZE_MAX) {
     2745      goto size_error;
     2746    }
     2747    resize_capa(mrb, s, capa);
     2748  }
     2749  if (off != -1) {
     2750      ptr = RSTR_PTR(s) + off;
     2751  }
     2752  memcpy(RSTR_PTR(s) + RSTR_LEN(s), ptr, len);
     2753  mrb_assert_int_fit(size_t, total, mrb_ssize, MRB_SSIZE_MAX);
     2754  RSTR_SET_LEN(s, total);
     2755  RSTR_PTR(s)[total] = '\0';   /* sentinel */
    25992756  return str;
    26002757}
     
    26092766mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2)
    26102767{
     2768  if (mrb_str_ptr(str) == mrb_str_ptr(str2)) {
     2769    mrb_str_modify(mrb, mrb_str_ptr(str));
     2770  }
    26112771  return mrb_str_cat(mrb, str, RSTRING_PTR(str2), RSTRING_LEN(str2));
    26122772}
     
    26152775mrb_str_append(mrb_state *mrb, mrb_value str1, mrb_value str2)
    26162776{
    2617   str2 = mrb_str_to_str(mrb, str2);
     2777  mrb_to_str(mrb, str2);
    26182778  return mrb_str_cat_str(mrb, str1, str2);
    26192779}
    2620 
    2621 #define CHAR_ESC_LEN 13 /* sizeof(\x{ hex of 32bit unsigned int } \0) */
    26222780
    26232781/*
     
    26352793mrb_str_inspect(mrb_state *mrb, mrb_value str)
    26362794{
    2637   const char *p, *pend;
    2638   char buf[CHAR_ESC_LEN + 1];
    2639   mrb_value result = mrb_str_new_lit(mrb, "\"");
    2640 
    2641   p = RSTRING_PTR(str); pend = RSTRING_END(str);
    2642   for (;p < pend; p++) {
    2643     unsigned char c, cc;
    2644 #ifdef MRB_UTF8_STRING
    2645     mrb_int clen;
    2646 
    2647     clen = utf8len(p, pend);
    2648     if (clen > 1) {
    2649       mrb_int i;
    2650 
    2651       for (i=0; i<clen; i++) {
    2652         buf[i] = p[i];
    2653       }
    2654       mrb_str_cat(mrb, result, buf, clen);
    2655       p += clen-1;
    2656       continue;
    2657     }
    2658 #endif
    2659     c = *p;
    2660     if (c == '"'|| c == '\\' || (c == '#' && IS_EVSTR(p+1, pend))) {
    2661       buf[0] = '\\'; buf[1] = c;
    2662       mrb_str_cat(mrb, result, buf, 2);
    2663       continue;
    2664     }
    2665     if (ISPRINT(c)) {
    2666       buf[0] = c;
    2667       mrb_str_cat(mrb, result, buf, 1);
    2668       continue;
    2669     }
    2670     switch (c) {
    2671       case '\n': cc = 'n'; break;
    2672       case '\r': cc = 'r'; break;
    2673       case '\t': cc = 't'; break;
    2674       case '\f': cc = 'f'; break;
    2675       case '\013': cc = 'v'; break;
    2676       case '\010': cc = 'b'; break;
    2677       case '\007': cc = 'a'; break;
    2678       case 033: cc = 'e'; break;
    2679       default: cc = 0; break;
    2680     }
    2681     if (cc) {
    2682       buf[0] = '\\';
    2683       buf[1] = (char)cc;
    2684       mrb_str_cat(mrb, result, buf, 2);
    2685       continue;
    2686     }
    2687     else {
    2688       buf[0] = '\\';
    2689       buf[3] = '0' + c % 8; c /= 8;
    2690       buf[2] = '0' + c % 8; c /= 8;
    2691       buf[1] = '0' + c % 8;
    2692       mrb_str_cat(mrb, result, buf, 4);
    2693       continue;
    2694     }
    2695   }
    2696   mrb_str_cat_lit(mrb, result, "\"");
    2697 
    2698   return result;
     2795  return str_escape(mrb, str, TRUE);
    26992796}
    27002797
     
    27222819}
    27232820
     2821/*
     2822 *  call-seq:
     2823 *     str.getbyte(index)          -> 0 .. 255
     2824 *
     2825 *  returns the <i>index</i>th byte as an integer.
     2826 */
     2827static mrb_value
     2828mrb_str_getbyte(mrb_state *mrb, mrb_value str)
     2829{
     2830  mrb_int pos;
     2831  mrb_get_args(mrb, "i", &pos);
     2832
     2833  if (pos < 0)
     2834    pos += RSTRING_LEN(str);
     2835  if (pos < 0 ||  RSTRING_LEN(str) <= pos)
     2836    return mrb_nil_value();
     2837
     2838  return mrb_fixnum_value((unsigned char)RSTRING_PTR(str)[pos]);
     2839}
     2840
     2841/*
     2842 *  call-seq:
     2843 *     str.setbyte(index, integer) -> integer
     2844 *
     2845 *  modifies the <i>index</i>th byte as <i>integer</i>.
     2846 */
     2847static mrb_value
     2848mrb_str_setbyte(mrb_state *mrb, mrb_value str)
     2849{
     2850  mrb_int pos, byte;
     2851  mrb_int len;
     2852
     2853  mrb_get_args(mrb, "ii", &pos, &byte);
     2854
     2855  len = RSTRING_LEN(str);
     2856  if (pos < -len || len <= pos)
     2857    mrb_raisef(mrb, E_INDEX_ERROR, "index %i out of string", pos);
     2858  if (pos < 0)
     2859    pos += len;
     2860
     2861  mrb_str_modify(mrb, mrb_str_ptr(str));
     2862  byte &= 0xff;
     2863  RSTRING_PTR(str)[pos] = (unsigned char)byte;
     2864  return mrb_fixnum_value((unsigned char)byte);
     2865}
     2866
     2867/*
     2868 *  call-seq:
     2869 *     str.byteslice(integer)           -> new_str or nil
     2870 *     str.byteslice(integer, integer)   -> new_str or nil
     2871 *     str.byteslice(range)            -> new_str or nil
     2872 *
     2873 *  Byte Reference---If passed a single Integer, returns a
     2874 *  substring of one byte at that position. If passed two Integer
     2875 *  objects, returns a substring starting at the offset given by the first, and
     2876 *  a length given by the second. If given a Range, a substring containing
     2877 *  bytes at offsets given by the range is returned. In all three cases, if
     2878 *  an offset is negative, it is counted from the end of <i>str</i>. Returns
     2879 *  <code>nil</code> if the initial offset falls outside the string, the length
     2880 *  is negative, or the beginning of the range is greater than the end.
     2881 *  The encoding of the resulted string keeps original encoding.
     2882 *
     2883 *     "hello".byteslice(1)     #=> "e"
     2884 *     "hello".byteslice(-1)    #=> "o"
     2885 *     "hello".byteslice(1, 2)  #=> "el"
     2886 *     "\x80\u3042".byteslice(1, 3) #=> "\u3042"
     2887 *     "\x03\u3042\xff".byteslice(1..3) #=> "\u3042"
     2888 */
     2889static mrb_value
     2890mrb_str_byteslice(mrb_state *mrb, mrb_value str)
     2891{
     2892  mrb_value a1, a2;
     2893  mrb_int str_len = RSTRING_LEN(str), beg, len;
     2894  mrb_bool empty = TRUE;
     2895
     2896  if (mrb_get_args(mrb, "o|o", &a1, &a2) == 2) {
     2897    beg = mrb_fixnum(mrb_to_int(mrb, a1));
     2898    len = mrb_fixnum(mrb_to_int(mrb, a2));
     2899  }
     2900  else if (mrb_range_p(a1)) {
     2901    if (mrb_range_beg_len(mrb, a1, &beg, &len, str_len, TRUE) != MRB_RANGE_OK) {
     2902      return mrb_nil_value();
     2903    }
     2904  }
     2905  else {
     2906    beg = mrb_fixnum(mrb_to_int(mrb, a1));
     2907    len = 1;
     2908    empty = FALSE;
     2909  }
     2910
     2911  if (mrb_str_beg_len(str_len, &beg, &len) && (empty || len != 0)) {
     2912    return mrb_str_byte_subseq(mrb, str, beg, len);
     2913  }
     2914  else {
     2915    return mrb_nil_value();
     2916  }
     2917}
     2918
    27242919/* ---------------------------*/
    27252920void
     
    27282923  struct RClass *s;
    27292924
    2730   mrb_static_assert(RSTRING_EMBED_LEN_MAX < (1 << 5), "pointer size too big for embedded string");
     2925  mrb_static_assert(RSTRING_EMBED_LEN_MAX < (1 << MRB_STR_EMBED_LEN_BIT),
     2926                    "pointer size too big for embedded string");
    27312927
    27322928  mrb->string_class = s = mrb_define_class(mrb, "String", mrb->object_class);             /* 15.2.10 */
     
    27402936  mrb_define_method(mrb, s, "*",               mrb_str_times,           MRB_ARGS_REQ(1)); /* 15.2.10.5.5  */
    27412937  mrb_define_method(mrb, s, "[]",              mrb_str_aref_m,          MRB_ARGS_ANY());  /* 15.2.10.5.6  */
     2938  mrb_define_method(mrb, s, "[]=",             mrb_str_aset_m,          MRB_ARGS_ANY());
    27422939  mrb_define_method(mrb, s, "capitalize",      mrb_str_capitalize,      MRB_ARGS_NONE()); /* 15.2.10.5.7  */
    27432940  mrb_define_method(mrb, s, "capitalize!",     mrb_str_capitalize_bang, MRB_ARGS_NONE()); /* 15.2.10.5.8  */
     
    27532950  mrb_define_method(mrb, s, "hash",            mrb_str_hash_m,          MRB_ARGS_NONE()); /* 15.2.10.5.20 */
    27542951  mrb_define_method(mrb, s, "include?",        mrb_str_include,         MRB_ARGS_REQ(1)); /* 15.2.10.5.21 */
    2755   mrb_define_method(mrb, s, "index",           mrb_str_index,           MRB_ARGS_ANY());  /* 15.2.10.5.22 */
     2952  mrb_define_method(mrb, s, "index",           mrb_str_index_m,         MRB_ARGS_ARG(1,1));  /* 15.2.10.5.22 */
    27562953  mrb_define_method(mrb, s, "initialize",      mrb_str_init,            MRB_ARGS_REQ(1)); /* 15.2.10.5.23 */
    27572954  mrb_define_method(mrb, s, "initialize_copy", mrb_str_replace,         MRB_ARGS_REQ(1)); /* 15.2.10.5.24 */
     
    27662963  mrb_define_method(mrb, s, "split",           mrb_str_split_m,         MRB_ARGS_ANY());  /* 15.2.10.5.35 */
    27672964
     2965#ifndef MRB_WITHOUT_FLOAT
    27682966  mrb_define_method(mrb, s, "to_f",            mrb_str_to_f,            MRB_ARGS_NONE()); /* 15.2.10.5.38 */
     2967#endif
    27692968  mrb_define_method(mrb, s, "to_i",            mrb_str_to_i,            MRB_ARGS_ANY());  /* 15.2.10.5.39 */
    27702969  mrb_define_method(mrb, s, "to_s",            mrb_str_to_s,            MRB_ARGS_NONE()); /* 15.2.10.5.40 */
     
    27752974  mrb_define_method(mrb, s, "inspect",         mrb_str_inspect,         MRB_ARGS_NONE()); /* 15.2.10.5.46(x) */
    27762975  mrb_define_method(mrb, s, "bytes",           mrb_str_bytes,           MRB_ARGS_NONE());
    2777 }
    2778 
    2779 /*
    2780  *      Source code for the "strtod" library procedure.
     2976
     2977  mrb_define_method(mrb, s, "getbyte",         mrb_str_getbyte,         MRB_ARGS_REQ(1));
     2978  mrb_define_method(mrb, s, "setbyte",         mrb_str_setbyte,         MRB_ARGS_REQ(2));
     2979  mrb_define_method(mrb, s, "byteslice",       mrb_str_byteslice,       MRB_ARGS_ARG(1,1));
     2980}
     2981
     2982#ifndef MRB_WITHOUT_FLOAT
     2983/*
     2984 * Source code for the "strtod" library procedure.
    27812985 *
    27822986 * Copyright (c) 1988-1993 The Regents of the University of California.
     
    28043008static const double powersOf10[] = {/* Table giving binary powers of 10.  Entry */
    28053009    10.,                            /* is 10^2^i.  Used to convert decimal */
    2806     100.,                           /* exponents into floating-point numbers. */
     3010    100.,                           /* exponents into floating-point numbers. */
    28073011    1.0e4,
    28083012    1.0e8,
     
    28163020MRB_API double
    28173021mrb_float_read(const char *string, char **endPtr)
    2818 /*  const char *string;            A decimal ASCII floating-point number,
    2819                                 * optionally preceded by white space.
    2820                                 * Must have form "-I.FE-X", where I is the
    2821                                 * integer part of the mantissa, F is the
    2822                                 * fractional part of the mantissa, and X
    2823                                 * is the exponent.  Either of the signs
    2824                                 * may be "+", "-", or omitted.  Either I
    2825                                 * or F may be omitted, or both.  The decimal
    2826                                 * point isn't necessary unless F is present.
    2827                                 * The "E" may actually be an "e".  E and X
    2828                                 * may both be omitted (but not just one).
    2829                                 */
    2830 /*  char **endPtr;                 If non-NULL, store terminating character's
    2831                                 * address here. */
     3022/*  const char *string;            A decimal ASCII floating-point number,
     3023                                * optionally preceded by white space.
     3024                                * Must have form "-I.FE-X", where I is the
     3025                                * integer part of the mantissa, F is the
     3026                                * fractional part of the mantissa, and X
     3027                                * is the exponent.  Either of the signs
     3028                                * may be "+", "-", or omitted.  Either I
     3029                                * or F may be omitted, or both.  The decimal
     3030                                * point isn't necessary unless F is present.
     3031                                * The "E" may actually be an "e".  E and X
     3032                                * may both be omitted (but not just one).
     3033                                */
     3034/*  char **endPtr;                 If non-NULL, store terminating character's
     3035                                * address here. */
    28323036{
    28333037    int sign, expSign = FALSE;
    28343038    double fraction, dblExp;
    28353039    const double *d;
    2836     register const char *p;
    2837     register int c;
    2838     int exp = 0;                /* Exponent read from "EX" field. */
    2839     int fracExp = 0;            /* Exponent that derives from the fractional
    2840                                 * part.  Under normal circumstatnces, it is
    2841                                 * the negative of the number of digits in F.
    2842                                 * However, if I is very long, the last digits
    2843                                 * of I get dropped (otherwise a long I with a
    2844                                 * large negative exponent could cause an
    2845                                 * unnecessary overflow on I alone).  In this
    2846                                 * case, fracExp is incremented one for each
    2847                                 * dropped digit. */
    2848     int mantSize;               /* Number of digits in mantissa. */
    2849     int decPt;                  /* Number of mantissa digits BEFORE decimal
    2850                                 * point. */
    2851     const char *pExp;           /* Temporarily holds location of exponent
    2852                                 * in string. */
     3040    const char *p;
     3041    int c;
     3042    int exp = 0;                /* Exponent read from "EX" field. */
     3043    int fracExp = 0;            /* Exponent that derives from the fractional
     3044                                * part.  Under normal circumstatnces, it is
     3045                                * the negative of the number of digits in F.
     3046                                * However, if I is very long, the last digits
     3047                                * of I get dropped (otherwise a long I with a
     3048                                * large negative exponent could cause an
     3049                                * unnecessary overflow on I alone).  In this
     3050                                * case, fracExp is incremented one for each
     3051                                * dropped digit. */
     3052    int mantSize;               /* Number of digits in mantissa. */
     3053    int decPt;                  /* Number of mantissa digits BEFORE decimal
     3054                                * point. */
     3055    const char *pExp;           /* Temporarily holds location of exponent
     3056                                * in string. */
    28533057
    28543058    /*
     
    28573061
    28583062    p = string;
    2859     while (isspace(*p)) {
    2860         p += 1;
     3063    while (ISSPACE(*p)) {
     3064      p += 1;
    28613065    }
    28623066    if (*p == '-') {
    2863         sign = TRUE;
    2864         p += 1;
     3067      sign = TRUE;
     3068      p += 1;
    28653069    }
    28663070    else {
    2867         if (*p == '+') {
    2868             p += 1;
    2869         }
    2870         sign = FALSE;
     3071      if (*p == '+') {
     3072        p += 1;
     3073      }
     3074      sign = FALSE;
    28713075    }
    28723076
     
    28793083    for (mantSize = 0; ; mantSize += 1)
    28803084    {
    2881         c = *p;
    2882         if (!isdigit(c)) {
    2883             if ((c != '.') || (decPt >= 0)) {
    2884                 break;
    2885             }
    2886             decPt = mantSize;
    2887         }
    2888         p += 1;
     3085      c = *p;
     3086      if (!ISDIGIT(c)) {
     3087        if ((c != '.') || (decPt >= 0)) {
     3088          break;
     3089        }
     3090        decPt = mantSize;
     3091      }
     3092      p += 1;
    28893093    }
    28903094
     
    28993103    p -= mantSize;
    29003104    if (decPt < 0) {
    2901         decPt = mantSize;
     3105      decPt = mantSize;
    29023106    }
    29033107    else {
    2904         mantSize -= 1;                  /* One of the digits was the point. */
     3108      mantSize -= 1; /* One of the digits was the point. */
    29053109    }
    29063110    if (mantSize > 18) {
    2907         if (decPt - 18 > 29999) {
    2908             fracExp = 29999;
    2909         }
    2910         else {
    2911             fracExp = decPt - 18;
    2912         }
    2913         mantSize = 18;
     3111      if (decPt - 18 > 29999) {
     3112        fracExp = 29999;
     3113      }
     3114      else {
     3115        fracExp = decPt - 18;
     3116      }
     3117      mantSize = 18;
    29143118    }
    29153119    else {
    2916         fracExp = decPt - mantSize;
     3120      fracExp = decPt - mantSize;
    29173121    }
    29183122    if (mantSize == 0) {
    2919         fraction = 0.0;
    2920         p = string;
    2921         goto done;
     3123      fraction = 0.0;
     3124      p = string;
     3125      goto done;
    29223126    }
    29233127    else {
    2924         int frac1, frac2;
    2925         frac1 = 0;
    2926         for ( ; mantSize > 9; mantSize -= 1)
    2927         {
    2928             c = *p;
    2929             p += 1;
    2930             if (c == '.') {
    2931                 c = *p;
    2932                 p += 1;
    2933             }
    2934             frac1 = 10*frac1 + (c - '0');
    2935         }
    2936         frac2 = 0;
    2937         for (; mantSize > 0; mantSize -= 1)
    2938         {
    2939             c = *p;
    2940             p += 1;
    2941             if (c == '.') {
    2942                 c = *p;
    2943                 p += 1;
    2944             }
    2945             frac2 = 10*frac2 + (c - '0');
    2946         }
    2947         fraction = (1.0e9 * frac1) + frac2;
     3128      int frac1, frac2;
     3129      frac1 = 0;
     3130      for ( ; mantSize > 9; mantSize -= 1)
     3131      {
     3132        c = *p;
     3133        p += 1;
     3134        if (c == '.') {
     3135          c = *p;
     3136          p += 1;
     3137        }
     3138        frac1 = 10*frac1 + (c - '0');
     3139      }
     3140      frac2 = 0;
     3141      for (; mantSize > 0; mantSize -= 1)
     3142      {
     3143        c = *p;
     3144        p += 1;
     3145        if (c == '.') {
     3146          c = *p;
     3147          p += 1;
     3148        }
     3149        frac2 = 10*frac2 + (c - '0');
     3150      }
     3151      fraction = (1.0e9 * frac1) + frac2;
    29483152    }
    29493153
     
    29543158    p = pExp;
    29553159    if ((*p == 'E') || (*p == 'e')) {
    2956         p += 1;
    2957         if (*p == '-') {
    2958             expSign = TRUE;
    2959             p += 1;
    2960         }
    2961         else {
    2962             if (*p == '+') {
    2963                 p += 1;
    2964             }
    2965             expSign = FALSE;
    2966         }
    2967         while (isdigit(*p)) {
    2968             exp = exp * 10 + (*p - '0');
    2969             if (exp > 19999) {
    2970                 exp = 19999;
    2971             }
    2972             p += 1;
    2973         }
     3160      p += 1;
     3161      if (*p == '-') {
     3162        expSign = TRUE;
     3163        p += 1;
     3164      }
     3165      else {
     3166        if (*p == '+') {
     3167          p += 1;
     3168        }
     3169        expSign = FALSE;
     3170      }
     3171      while (ISDIGIT(*p)) {
     3172        exp = exp * 10 + (*p - '0');
     3173        if (exp > 19999) {
     3174          exp = 19999;
     3175        }
     3176        p += 1;
     3177      }
    29743178    }
    29753179    if (expSign) {
    2976         exp = fracExp - exp;
     3180      exp = fracExp - exp;
    29773181    }
    29783182    else {
    2979         exp = fracExp + exp;
     3183      exp = fracExp + exp;
    29803184    }
    29813185
     
    29883192
    29893193    if (exp < 0) {
    2990         expSign = TRUE;
    2991         exp = -exp;
     3194      expSign = TRUE;
     3195      exp = -exp;
    29923196    }
    29933197    else {
    2994         expSign = FALSE;
     3198      expSign = FALSE;
    29953199    }
    29963200    if (exp > maxExponent) {
    2997         exp = maxExponent;
    2998         errno = ERANGE;
     3201      exp = maxExponent;
     3202      errno = ERANGE;
    29993203    }
    30003204    dblExp = 1.0;
    30013205    for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
    3002         if (exp & 01) {
    3003             dblExp *= *d;
    3004         }
     3206      if (exp & 01) {
     3207        dblExp *= *d;
     3208      }
    30053209    }
    30063210    if (expSign) {
    3007         fraction /= dblExp;
     3211      fraction /= dblExp;
    30083212    }
    30093213    else {
    3010         fraction *= dblExp;
     3214      fraction *= dblExp;
    30113215    }
    30123216
    30133217done:
    30143218    if (endPtr != NULL) {
    3015         *endPtr = (char *) p;
     3219      *endPtr = (char *) p;
    30163220    }
    30173221
    30183222    if (sign) {
    3019         return -fraction;
     3223      return -fraction;
    30203224    }
    30213225    return fraction;
    30223226}
     3227#endif
  • EcnlProtoTool/trunk/mruby-2.1.1/src/symbol.c

    r331 r439  
    1616typedef struct symbol_name {
    1717  mrb_bool lit : 1;
     18  uint8_t prev;
    1819  uint16_t len;
    1920  const char *name;
    2021} symbol_name;
    2122
    22 static inline khint_t
    23 sym_hash_func(mrb_state *mrb, mrb_sym s)
    24 {
    25   khint_t h = 0;
    26   size_t i, len = mrb->symtbl[s].len;
    27   const char *p = mrb->symtbl[s].name;
    28 
    29   for (i=0; i<len; i++) {
    30     h = (h << 5) - h + *p++;
    31   }
    32   return h;
    33 }
    34 #define sym_hash_equal(mrb,a, b) (mrb->symtbl[a].len == mrb->symtbl[b].len && memcmp(mrb->symtbl[a].name, mrb->symtbl[b].name, mrb->symtbl[a].len) == 0)
    35 
    36 KHASH_DECLARE(n2s, mrb_sym, mrb_sym, FALSE)
    37 KHASH_DEFINE (n2s, mrb_sym, mrb_sym, FALSE, sym_hash_func, sym_hash_equal)
    38 /* ------------------------------------------------------ */
     23#define SYMBOL_INLINE_BIT_POS       1
     24#define SYMBOL_INLINE_LOWER_BIT_POS 2
     25#define SYMBOL_INLINE               (1 << (SYMBOL_INLINE_BIT_POS - 1))
     26#define SYMBOL_INLINE_LOWER         (1 << (SYMBOL_INLINE_LOWER_BIT_POS - 1))
     27#define SYMBOL_NORMAL_SHIFT         SYMBOL_INLINE_BIT_POS
     28#define SYMBOL_INLINE_SHIFT         SYMBOL_INLINE_LOWER_BIT_POS
     29#ifdef MRB_ENABLE_ALL_SYMBOLS
     30# define SYMBOL_INLINE_P(sym) FALSE
     31# define SYMBOL_INLINE_LOWER_P(sym) FALSE
     32# define sym_inline_pack(name, len) 0
     33# define sym_inline_unpack(sym, buf, lenp) NULL
     34#else
     35# define SYMBOL_INLINE_P(sym) ((sym) & SYMBOL_INLINE)
     36# define SYMBOL_INLINE_LOWER_P(sym) ((sym) & SYMBOL_INLINE_LOWER)
     37#endif
    3938
    4039static void
     
    4645}
    4746
     47#ifndef MRB_ENABLE_ALL_SYMBOLS
     48static const char pack_table[] = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
     49
     50static mrb_sym
     51sym_inline_pack(const char *name, size_t len)
     52{
     53  const size_t lower_length_max = (MRB_SYMBOL_BIT - 2) / 5;
     54  const size_t mix_length_max   = (MRB_SYMBOL_BIT - 2) / 6;
     55
     56  char c;
     57  const char *p;
     58  size_t i;
     59  mrb_sym sym = 0;
     60  mrb_bool lower = TRUE;
     61
     62  if (len > lower_length_max) return 0; /* too long */
     63  for (i=0; i<len; i++) {
     64    uint32_t bits;
     65
     66    c = name[i];
     67    if (c == 0) return 0;       /* NUL in name */
     68    p = strchr(pack_table, (int)c);
     69    if (p == 0) return 0;       /* non alnum char */
     70    bits = (uint32_t)(p - pack_table)+1;
     71    if (bits > 27) lower = FALSE;
     72    if (i >= mix_length_max) break;
     73    sym |= bits<<(i*6+SYMBOL_INLINE_SHIFT);
     74  }
     75  if (lower) {
     76    sym = 0;
     77    for (i=0; i<len; i++) {
     78      uint32_t bits;
     79
     80      c = name[i];
     81      p = strchr(pack_table, (int)c);
     82      bits = (uint32_t)(p - pack_table)+1;
     83      sym |= bits<<(i*5+SYMBOL_INLINE_SHIFT);
     84    }
     85    return sym | SYMBOL_INLINE | SYMBOL_INLINE_LOWER;
     86  }
     87  if (len > mix_length_max) return 0;
     88  return sym | SYMBOL_INLINE;
     89}
     90
     91static const char*
     92sym_inline_unpack(mrb_sym sym, char *buf, mrb_int *lenp)
     93{
     94  int bit_per_char = SYMBOL_INLINE_LOWER_P(sym) ? 5 : 6;
     95  int i;
     96
     97  mrb_assert(SYMBOL_INLINE_P(sym));
     98
     99  for (i=0; i<30/bit_per_char; i++) {
     100    uint32_t bits = sym>>(i*bit_per_char+SYMBOL_INLINE_SHIFT) & ((1<<bit_per_char)-1);
     101    if (bits == 0) break;
     102    buf[i] = pack_table[bits-1];;
     103  }
     104  buf[i] = '\0';
     105  if (lenp) *lenp = i;
     106  return buf;
     107}
     108#endif
     109
     110static uint8_t
     111symhash(const char *key, size_t len)
     112{
     113    uint32_t hash, i;
     114
     115    for(hash = i = 0; i < len; ++i) {
     116        hash += key[i];
     117        hash += (hash << 10);
     118        hash ^= (hash >> 6);
     119    }
     120    hash += (hash << 3);
     121    hash ^= (hash >> 11);
     122    hash += (hash << 15);
     123    return hash & 0xff;
     124}
     125
     126static mrb_sym
     127find_symbol(mrb_state *mrb, const char *name, size_t len, uint8_t *hashp)
     128{
     129  mrb_sym i;
     130  symbol_name *sname;
     131  uint8_t hash;
     132
     133  /* inline symbol */
     134  i = sym_inline_pack(name, len);
     135  if (i > 0) return i;
     136
     137  hash = symhash(name, len);
     138  if (hashp) *hashp = hash;
     139
     140  i = mrb->symhash[hash];
     141  if (i == 0) return 0;
     142  do {
     143    sname = &mrb->symtbl[i];
     144    if (sname->len == len && memcmp(sname->name, name, len) == 0) {
     145      return i<<SYMBOL_NORMAL_SHIFT;
     146    }
     147    if (sname->prev == 0xff) {
     148      i -= 0xff;
     149      sname = &mrb->symtbl[i];
     150      while (mrb->symtbl < sname) {
     151        if (sname->len == len && memcmp(sname->name, name, len) == 0) {
     152          return (mrb_sym)(sname - mrb->symtbl)<<SYMBOL_NORMAL_SHIFT;
     153        }
     154        sname--;
     155      }
     156      return 0;
     157    }
     158    i -= sname->prev;
     159  } while (sname->prev > 0);
     160  return 0;
     161}
     162
    48163static mrb_sym
    49164sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit)
    50165{
    51   khash_t(n2s) *h = mrb->name2sym;
    52   symbol_name *sname = mrb->symtbl; /* symtbl[0] for working memory */
    53   khiter_t k;
    54166  mrb_sym sym;
    55   char *p;
     167  symbol_name *sname;
     168  uint8_t hash;
    56169
    57170  sym_validate_len(mrb, len);
    58   if (sname) {
    59     sname->lit = lit;
    60     sname->len = (uint16_t)len;
    61     sname->name = name;
    62     k = kh_get(n2s, mrb, h, 0);
    63     if (k != kh_end(h))
    64       return kh_key(h, k);
    65   }
     171  sym = find_symbol(mrb, name, len, &hash);
     172  if (sym > 0) return sym;
    66173
    67174  /* registering a new symbol */
     
    69176  if (mrb->symcapa < sym) {
    70177    if (mrb->symcapa == 0) mrb->symcapa = 100;
    71     else mrb->symcapa = (size_t)(mrb->symcapa * 1.2);
     178    else mrb->symcapa = (size_t)(mrb->symcapa * 6 / 5);
    72179    mrb->symtbl = (symbol_name*)mrb_realloc(mrb, mrb->symtbl, sizeof(symbol_name)*(mrb->symcapa+1));
    73180  }
     
    79186  }
    80187  else {
    81     p = (char *)mrb_malloc(mrb, len+1);
     188    char *p = (char *)mrb_malloc(mrb, len+1);
    82189    memcpy(p, name, len);
    83190    p[len] = 0;
     
    85192    sname->lit = FALSE;
    86193  }
    87   kh_put(n2s, mrb, h, sym);
    88 
    89   return sym;
     194  if (mrb->symhash[hash]) {
     195    mrb_sym i = sym - mrb->symhash[hash];
     196    if (i > 0xff)
     197      sname->prev = 0xff;
     198    else
     199      sname->prev = i;
     200  }
     201  else {
     202    sname->prev = 0;
     203  }
     204  mrb->symhash[hash] = sym;
     205
     206  return sym<<SYMBOL_NORMAL_SHIFT;
    90207}
    91208
     
    117234mrb_check_intern(mrb_state *mrb, const char *name, size_t len)
    118235{
    119   khash_t(n2s) *h = mrb->name2sym;
    120   symbol_name *sname = mrb->symtbl;
    121   khiter_t k;
     236  mrb_sym sym;
    122237
    123238  sym_validate_len(mrb, len);
    124   sname->len = (uint16_t)len;
    125   sname->name = name;
    126 
    127   k = kh_get(n2s, mrb, h, 0);
    128   if (k != kh_end(h)) {
    129     return mrb_symbol_value(kh_key(h, k));
    130   }
     239  sym = find_symbol(mrb, name, len, NULL);
     240  if (sym > 0) return mrb_symbol_value(sym);
    131241  return mrb_nil_value();
    132242}
     
    135245mrb_check_intern_cstr(mrb_state *mrb, const char *name)
    136246{
    137   return mrb_check_intern(mrb, name, (mrb_int)strlen(name));
     247  return mrb_check_intern(mrb, name, strlen(name));
    138248}
    139249
     
    144254}
    145255
    146 /* lenp must be a pointer to a size_t variable */
    147 MRB_API const char*
    148 mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp)
    149 {
     256static const char*
     257sym2name_len(mrb_state *mrb, mrb_sym sym, char *buf, mrb_int *lenp)
     258{
     259  if (SYMBOL_INLINE_P(sym)) return sym_inline_unpack(sym, buf, lenp);
     260
     261  sym >>= SYMBOL_NORMAL_SHIFT;
    150262  if (sym == 0 || mrb->symidx < sym) {
    151263    if (lenp) *lenp = 0;
     
    155267  if (lenp) *lenp = mrb->symtbl[sym].len;
    156268  return mrb->symtbl[sym].name;
     269}
     270
     271MRB_API const char*
     272mrb_sym_name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp)
     273{
     274  return sym2name_len(mrb, sym, mrb->symbuf, lenp);
    157275}
    158276
     
    168286  }
    169287  mrb_free(mrb, mrb->symtbl);
    170   kh_destroy(n2s, mrb, mrb->name2sym);
    171288}
    172289
     
    174291mrb_init_symtbl(mrb_state *mrb)
    175292{
    176   mrb->name2sym = kh_init(n2s, mrb);
    177293}
    178294
     
    210326 */
    211327
    212 
    213 /* 15.2.11.3.1  */
    214 /*
    215  *  call-seq:
    216  *     sym == obj   -> true or false
    217  *
    218  *  Equality---If <i>sym</i> and <i>obj</i> are exactly the same
    219  *  symbol, returns <code>true</code>.
    220  */
    221 
    222 static mrb_value
    223 sym_equal(mrb_state *mrb, mrb_value sym1)
    224 {
    225   mrb_value sym2;
    226 
    227   mrb_get_args(mrb, "o", &sym2);
    228 
    229   return mrb_bool_value(mrb_obj_equal(mrb, sym1, sym2));
    230 }
    231 
    232328/* 15.2.11.3.2  */
    233329/* 15.2.11.3.3  */
     
    242338 */
    243339static mrb_value
    244 mrb_sym_to_s(mrb_state *mrb, mrb_value sym)
    245 {
    246   mrb_sym id = mrb_symbol(sym);
    247   const char *p;
    248   mrb_int len;
    249 
    250   p = mrb_sym2name_len(mrb, id, &len);
    251   return mrb_str_new_static(mrb, p, len);
     340sym_to_s(mrb_state *mrb, mrb_value sym)
     341{
     342  return mrb_sym_str(mrb, mrb_symbol(sym));
    252343}
    253344
     
    388479          case '!': case '?': case '=': ++m;
    389480          default: break;
    390             }
    391481        }
     482      }
    392483      break;
    393484  }
     
    404495  char *sp;
    405496
    406   name = mrb_sym2name_len(mrb, id, &len);
     497  name = mrb_sym_name_len(mrb, id, &len);
    407498  str = mrb_str_new(mrb, 0, len+1);
    408499  sp = RSTRING_PTR(str);
    409   RSTRING_PTR(str)[0] = ':';
     500  sp[0] = ':';
    410501  memcpy(sp+1, name, len);
    411502  mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
    412503  if (!symname_p(name) || strlen(name) != (size_t)len) {
    413     str = mrb_str_dump(mrb, str);
     504    str = mrb_str_inspect(mrb, str);
    414505    sp = RSTRING_PTR(str);
    415506    sp[0] = ':';
    416507    sp[1] = '"';
    417508  }
     509#ifdef MRB_UTF8_STRING
     510  if (SYMBOL_INLINE_P(id)) RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
     511#endif
    418512  return str;
    419513}
    420514
    421515MRB_API mrb_value
    422 mrb_sym2str(mrb_state *mrb, mrb_sym sym)
     516mrb_sym_str(mrb_state *mrb, mrb_sym sym)
    423517{
    424518  mrb_int len;
    425   const char *name = mrb_sym2name_len(mrb, sym, &len);
     519  const char *name = mrb_sym_name_len(mrb, sym, &len);
    426520
    427521  if (!name) return mrb_undef_value(); /* can't happen */
     522  if (SYMBOL_INLINE_P(sym)) {
     523    mrb_value str = mrb_str_new(mrb, name, len);
     524    RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
     525    return str;
     526  }
    428527  return mrb_str_new_static(mrb, name, len);
    429528}
    430529
     530static const char*
     531sym_name(mrb_state *mrb, mrb_sym sym, mrb_bool dump)
     532{
     533  mrb_int len;
     534  const char *name = mrb_sym_name_len(mrb, sym, &len);
     535
     536  if (!name) return NULL;
     537  if (strlen(name) == (size_t)len && (!dump || symname_p(name))) {
     538    return name;
     539  }
     540  else {
     541    mrb_value str = SYMBOL_INLINE_P(sym) ?
     542      mrb_str_new(mrb, name, len) : mrb_str_new_static(mrb, name, len);
     543    str = mrb_str_dump(mrb, str);
     544    return RSTRING_PTR(str);
     545  }
     546}
     547
    431548MRB_API const char*
    432 mrb_sym2name(mrb_state *mrb, mrb_sym sym)
    433 {
    434   mrb_int len;
    435   const char *name = mrb_sym2name_len(mrb, sym, &len);
    436 
    437   if (!name) return NULL;
    438   if (symname_p(name) && strlen(name) == (size_t)len) {
    439     return name;
    440   }
    441   else {
    442     mrb_value str = mrb_str_dump(mrb, mrb_str_new_static(mrb, name, len));
    443     return RSTRING_PTR(str);
    444   }
     549mrb_sym_name(mrb_state *mrb, mrb_sym sym)
     550{
     551  return sym_name(mrb, sym, FALSE);
     552}
     553
     554MRB_API const char*
     555mrb_sym_dump(mrb_state *mrb, mrb_sym sym)
     556{
     557  return sym_name(mrb, sym, TRUE);
    445558}
    446559
     
    454567
    455568  mrb_get_args(mrb, "o", &s2);
    456   if (mrb_type(s2) != MRB_TT_SYMBOL) return mrb_nil_value();
     569  if (!mrb_symbol_p(s2)) return mrb_nil_value();
    457570  sym1 = mrb_symbol(s1);
    458571  sym2 = mrb_symbol(s2);
     
    462575    int retval;
    463576    mrb_int len, len1, len2;
    464 
    465     p1 = mrb_sym2name_len(mrb, sym1, &len1);
    466     p2 = mrb_sym2name_len(mrb, sym2, &len2);
     577    char buf1[8], buf2[8];
     578
     579    p1 = sym2name_len(mrb, sym1, buf1, &len1);
     580    p2 = sym2name_len(mrb, sym2, buf2, &len2);
    467581    len = lesser(len1, len2);
    468582    retval = memcmp(p1, p2, len);
     
    482596  struct RClass *sym;
    483597
    484   mrb->symbol_class = sym = mrb_define_class(mrb, "Symbol", mrb->object_class);                 /* 15.2.11 */
     598  mrb->symbol_class = sym = mrb_define_class(mrb, "Symbol", mrb->object_class);  /* 15.2.11 */
    485599  MRB_SET_INSTANCE_TT(sym, MRB_TT_SYMBOL);
    486600  mrb_undef_class_method(mrb,  sym, "new");
    487601
    488   mrb_define_method(mrb, sym, "===",             sym_equal,      MRB_ARGS_REQ(1));              /* 15.2.11.3.1  */
    489   mrb_define_method(mrb, sym, "id2name",         mrb_sym_to_s,   MRB_ARGS_NONE());              /* 15.2.11.3.2  */
    490   mrb_define_method(mrb, sym, "to_s",            mrb_sym_to_s,   MRB_ARGS_NONE());              /* 15.2.11.3.3  */
    491   mrb_define_method(mrb, sym, "to_sym",          sym_to_sym,     MRB_ARGS_NONE());              /* 15.2.11.3.4  */
    492   mrb_define_method(mrb, sym, "inspect",         sym_inspect,    MRB_ARGS_NONE());              /* 15.2.11.3.5(x)  */
    493   mrb_define_method(mrb, sym, "<=>",             sym_cmp,        MRB_ARGS_REQ(1));
    494 }
     602  mrb_define_method(mrb, sym, "id2name", sym_to_s,    MRB_ARGS_NONE());          /* 15.2.11.3.2 */
     603  mrb_define_method(mrb, sym, "to_s",    sym_to_s,    MRB_ARGS_NONE());          /* 15.2.11.3.3 */
     604  mrb_define_method(mrb, sym, "to_sym",  sym_to_sym,  MRB_ARGS_NONE());          /* 15.2.11.3.4 */
     605  mrb_define_method(mrb, sym, "inspect", sym_inspect, MRB_ARGS_NONE());          /* 15.2.11.3.5(x) */
     606  mrb_define_method(mrb, sym, "<=>",     sym_cmp,     MRB_ARGS_REQ(1));
     607}
  • EcnlProtoTool/trunk/mruby-2.1.1/src/variable.c

    r331 r439  
    1010#include <mruby/proc.h>
    1111#include <mruby/string.h>
    12 
    13 typedef int (iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*);
    14 
    15 #ifdef MRB_USE_IV_SEGLIST
    16 
    17 #ifndef MRB_SEGMENT_SIZE
    18 #define MRB_SEGMENT_SIZE 4
     12#include <mruby/variable.h>
     13
     14#ifndef MRB_IV_SEGMENT_SIZE
     15#define MRB_IV_SEGMENT_SIZE 4
    1916#endif
    2017
    2118typedef struct segment {
    22   mrb_sym key[MRB_SEGMENT_SIZE];
    23   mrb_value val[MRB_SEGMENT_SIZE];
     19  mrb_sym key[MRB_IV_SEGMENT_SIZE];
     20  mrb_value val[MRB_IV_SEGMENT_SIZE];
    2421  struct segment *next;
    2522} segment;
     
    3229} iv_tbl;
    3330
    34 /*
    35  * Creates the instance variable table.
    36  *
    37  * Parameters
    38  *   mrb
    39  * Returns
    40  *   the instance variable table.
    41  */
     31/* Creates the instance variable table. */
    4232static iv_tbl*
    4333iv_new(mrb_state *mrb)
     
    5343}
    5444
    55 /*
    56  * Set the value for the symbol in the instance variable table.
    57  *
    58  * Parameters
    59  *   mrb
    60  *   t     the instance variable table to be set in.
    61  *   sym   the symbol to be used as the key.
    62  *   val   the value to be set.
    63  */
     45/* Set the value for the symbol in the instance variable table. */
    6446static void
    6547iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
    6648{
    67   segment *seg = t->rootseg;
     49  segment *seg;
    6850  segment *prev = NULL;
    6951  segment *matched_seg = NULL;
     
    7153  size_t i;
    7254
     55  if (t == NULL) return;
     56  seg = t->rootseg;
    7357  while (seg) {
    74     for (i=0; i<MRB_SEGMENT_SIZE; i++) {
     58    for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) {
    7559      mrb_sym key = seg->key[i];
    7660      /* Found room in last segment after last_len */
     
    9680
    9781  /* Not found */
    98   t->size++;
    9982  if (matched_seg) {
    10083    matched_seg->key[matched_idx] = sym;
    10184    matched_seg->val[matched_idx] = val;
     85    t->size++;
    10286    return;
    10387  }
    10488
    10589  seg = (segment*)mrb_malloc(mrb, sizeof(segment));
    106   if (!seg) return;
    10790  seg->next = NULL;
    10891  seg->key[0] = sym;
    10992  seg->val[0] = val;
    11093  t->last_len = 1;
     94  t->size++;
    11195  if (prev) {
    11296    prev->next = seg;
     
    117101}
    118102
    119 /*
    120  * Get a value for a symbol from the instance variable table.
    121  *
    122  * Parameters
    123  *   mrb
    124  *   t     the variable table to be searched.
    125  *   sym   the symbol to be used as the key.
    126  *   vp    the value pointer. Receives the value if the specified symbol is
    127  *         contained in the instance variable table.
    128  * Returns
    129  *   true if the specified symbol is contained in the instance variable table.
    130  */
     103/* Get a value for a symbol from the instance variable table. */
    131104static mrb_bool
    132105iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
     
    135108  size_t i;
    136109
     110  if (t == NULL) return FALSE;
    137111  seg = t->rootseg;
    138112  while (seg) {
    139     for (i=0; i<MRB_SEGMENT_SIZE; i++) {
     113    for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) {
    140114      mrb_sym key = seg->key[i];
    141115
     
    153127}
    154128
    155 /*
    156  * Deletes the value for the symbol from the instance variable table.
    157  *
    158  * Parameters
    159  *   t    the variable table to be searched.
    160  *   sym  the symbol to be used as the key.
    161  *   vp   the value pointer. Receive the deleted value if the symbol is
    162  *        contained in the instance variable table.
    163  * Returns
    164  *   true if the specified symbol is contained in the instance variable table.
    165  */
     129/* Deletes the value for the symbol from the instance variable table. */
    166130static mrb_bool
    167131iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
     
    170134  size_t i;
    171135
     136  if (t == NULL) return FALSE;
    172137  seg = t->rootseg;
    173138  while (seg) {
    174     for (i=0; i<MRB_SEGMENT_SIZE; i++) {
     139    for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) {
    175140      mrb_sym key = seg->key[i];
    176141
     
    190155}
    191156
    192 static mrb_bool
    193 iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
     157/* Iterates over the instance variable table. */
     158static void
     159iv_foreach(mrb_state *mrb, iv_tbl *t, mrb_iv_foreach_func *func, void *p)
    194160{
    195161  segment *seg;
    196162  size_t i;
    197   int n;
    198 
     163
     164  if (t == NULL) return;
    199165  seg = t->rootseg;
    200166  while (seg) {
    201     for (i=0; i<MRB_SEGMENT_SIZE; i++) {
     167    for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) {
    202168      mrb_sym key = seg->key[i];
    203169
    204170      /* no value in last segment after last_len */
    205171      if (!seg->next && i >= t->last_len) {
    206         return FALSE;
     172        return;
    207173      }
    208174      if (key != 0) {
    209         n =(*func)(mrb, key, seg->val[i], p);
    210         if (n > 0) return FALSE;
    211         if (n < 0) {
    212           t->size--;
    213           seg->key[i] = 0;
     175        if ((*func)(mrb, key, seg->val[i], p) != 0) {
     176          return;
    214177        }
    215178      }
     
    217180    seg = seg->next;
    218181  }
    219   return TRUE;
    220 }
    221 
     182  return;
     183}
     184
     185/* Get the size of the instance variable table. */
    222186static size_t
    223187iv_size(mrb_state *mrb, iv_tbl *t)
     
    226190  size_t size = 0;
    227191
    228   if (!t) return 0;
     192  if (t == NULL) return 0;
    229193  if (t->size > 0) return t->size;
    230194  seg = t->rootseg;
     
    235199    }
    236200    seg = seg->next;
    237     size += MRB_SEGMENT_SIZE;
     201    size += MRB_IV_SEGMENT_SIZE;
    238202  }
    239203  /* empty iv_tbl */
     
    241205}
    242206
     207/* Copy the instance variable table. */
    243208static iv_tbl*
    244209iv_copy(mrb_state *mrb, iv_tbl *t)
     
    253218
    254219  while (seg != NULL) {
    255     for (i=0; i<MRB_SEGMENT_SIZE; i++) {
     220    for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) {
    256221      mrb_sym key = seg->key[i];
    257222      mrb_value val = seg->val[i];
     
    267232}
    268233
     234/* Free memory of the instance variable table. */
    269235static void
    270236iv_free(mrb_state *mrb, iv_tbl *t)
     
    281247}
    282248
    283 #else
    284 
    285 #include <mruby/khash.h>
    286 
    287 #ifndef MRB_IVHASH_INIT_SIZE
    288 #define MRB_IVHASH_INIT_SIZE 8
    289 #endif
    290 
    291 KHASH_DECLARE(iv, mrb_sym, mrb_value, TRUE)
    292 KHASH_DEFINE(iv, mrb_sym, mrb_value, TRUE, kh_int_hash_func, kh_int_hash_equal)
    293 
    294 typedef struct iv_tbl {
    295   khash_t(iv) h;
    296 } iv_tbl;
    297 
    298 static iv_tbl*
    299 iv_new(mrb_state *mrb)
    300 {
    301   return (iv_tbl*)kh_init_size(iv, mrb, MRB_IVHASH_INIT_SIZE);
    302 }
    303 
    304 static void
    305 iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
    306 {
    307   khash_t(iv) *h = &t->h;
    308   khiter_t k;
    309 
    310   k = kh_put(iv, mrb, h, sym);
    311   kh_value(h, k) = val;
    312 }
    313 
    314 static mrb_bool
    315 iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
    316 {
    317   khash_t(iv) *h = &t->h;
    318   khiter_t k;
    319 
    320   k = kh_get(iv, mrb, h, sym);
    321   if (k != kh_end(h)) {
    322     if (vp) *vp = kh_value(h, k);
    323     return TRUE;
    324   }
    325   return FALSE;
    326 }
    327 
    328 static mrb_bool
    329 iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
    330 {
    331   khash_t(iv) *h = &t->h;
    332   khiter_t k;
    333 
    334   if (h) {
    335     k = kh_get(iv, mrb, h, sym);
    336     if (k != kh_end(h)) {
    337       mrb_value val = kh_value(h, k);
    338       kh_del(iv, mrb, h, k);
    339       if (vp) *vp = val;
    340       return TRUE;
    341     }
    342   }
    343   return FALSE;
    344 }
    345 
    346 static mrb_bool
    347 iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
    348 {
    349   khash_t(iv) *h = &t->h;
    350   khiter_t k;
    351   int n;
    352 
    353   if (h) {
    354     for (k = kh_begin(h); k != kh_end(h); k++) {
    355       if (kh_exist(h, k)) {
    356         n = (*func)(mrb, kh_key(h, k), kh_value(h, k), p);
    357         if (n > 0) return FALSE;
    358         if (n < 0) {
    359           kh_del(iv, mrb, h, k);
    360         }
    361       }
    362     }
    363   }
    364   return TRUE;
    365 }
    366 
    367 static size_t
    368 iv_size(mrb_state *mrb, iv_tbl *t)
    369 {
    370   khash_t(iv) *h;
    371 
    372   if (t && (h = &t->h)) {
    373     return kh_size(h);
    374   }
    375   return 0;
    376 }
    377 
    378 static iv_tbl*
    379 iv_copy(mrb_state *mrb, iv_tbl *t)
    380 {
    381   return (iv_tbl*)kh_copy(iv, mrb, &t->h);
    382 }
    383 
    384 static void
    385 iv_free(mrb_state *mrb, iv_tbl *t)
    386 {
    387   kh_destroy(iv, mrb, &t->h);
    388 }
    389 
    390 #endif
    391 
    392249static int
    393250iv_mark_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
     
    400257mark_tbl(mrb_state *mrb, iv_tbl *t)
    401258{
    402   if (t) {
    403     iv_foreach(mrb, t, iv_mark_i, 0);
    404   }
     259  iv_foreach(mrb, t, iv_mark_i, 0);
    405260}
    406261
     
    485340}
    486341
     342static inline void assign_class_name(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
     343
     344void
     345mrb_obj_iv_set_force(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
     346{
     347  assign_class_name(mrb, obj, sym, v);
     348  if (!obj->iv) {
     349    obj->iv = iv_new(mrb);
     350  }
     351  iv_put(mrb, obj->iv, sym, v);
     352  mrb_write_barrier(mrb, (struct RBasic*)obj);
     353}
     354
    487355MRB_API void
    488356mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
    489357{
    490   iv_tbl *t = obj->iv;
    491 
    492   if (MRB_FROZEN_P(obj)) {
    493     mrb_raisef(mrb, E_RUNTIME_ERROR, "can't modify frozen %S", mrb_obj_value(obj));
    494   }
    495   if (!t) {
    496     t = obj->iv = iv_new(mrb);
    497   }
    498   mrb_write_barrier(mrb, (struct RBasic*)obj);
    499   iv_put(mrb, t, sym, v);
    500 }
    501 
    502 MRB_API void
    503 mrb_obj_iv_ifnone(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
    504 {
    505   iv_tbl *t = obj->iv;
    506 
    507   if (!t) {
    508     t = obj->iv = iv_new(mrb);
    509   }
    510   else if (iv_get(mrb, t, sym, &v)) {
    511     return;
    512   }
    513   mrb_write_barrier(mrb, (struct RBasic*)obj);
    514   iv_put(mrb, t, sym, v);
     358  mrb_check_frozen(mrb, obj);
     359  mrb_obj_iv_set_force(mrb, obj, sym, v);
     360}
     361
     362/* Iterates over the instance variable table. */
     363MRB_API void
     364mrb_iv_foreach(mrb_state *mrb, mrb_value obj, mrb_iv_foreach_func *func, void *p)
     365{
     366  if (!obj_iv_p(obj)) return;
     367  iv_foreach(mrb, mrb_obj_ptr(obj)->iv, func, p);
     368}
     369
     370static inline mrb_bool
     371namespace_p(enum mrb_vtype tt)
     372{
     373  return tt == MRB_TT_CLASS || tt == MRB_TT_MODULE ? TRUE : FALSE;
     374}
     375
     376static inline void
     377assign_class_name(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
     378{
     379  if (namespace_p(obj->tt) && namespace_p(mrb_type(v))) {
     380    struct RObject *c = mrb_obj_ptr(v);
     381    if (obj != c && ISUPPER(mrb_sym_name_len(mrb, sym, NULL)[0])) {
     382      mrb_sym id_classname = mrb_intern_lit(mrb, "__classname__");
     383      mrb_value o = mrb_obj_iv_get(mrb, c, id_classname);
     384
     385      if (mrb_nil_p(o)) {
     386        mrb_sym id_outer = mrb_intern_lit(mrb, "__outer__");
     387        o = mrb_obj_iv_get(mrb, c, id_outer);
     388
     389        if (mrb_nil_p(o)) {
     390          if ((struct RClass *)obj == mrb->object_class) {
     391            mrb_obj_iv_set_force(mrb, c, id_classname, mrb_symbol_value(sym));
     392          }
     393          else {
     394            mrb_obj_iv_set_force(mrb, c, id_outer, mrb_obj_value(obj));
     395          }
     396        }
     397      }
     398    }
     399  }
    515400}
    516401
     
    545430}
    546431
    547 #define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c))
    548 
    549432MRB_API mrb_bool
    550 mrb_iv_p(mrb_state *mrb, mrb_sym iv_name)
     433mrb_iv_name_sym_p(mrb_state *mrb, mrb_sym iv_name)
    551434{
    552435  const char *s;
    553   mrb_int i, len;
    554 
    555   s = mrb_sym2name_len(mrb, iv_name, &len);
     436  mrb_int len;
     437
     438  s = mrb_sym_name_len(mrb, iv_name, &len);
    556439  if (len < 2) return FALSE;
    557440  if (s[0] != '@') return FALSE;
    558   if (s[1] == '@') return FALSE;
    559   for (i=1; i<len; i++) {
    560     if (!identchar(s[i])) return FALSE;
    561   }
    562   return TRUE;
    563 }
    564 
    565 MRB_API void
    566 mrb_iv_check(mrb_state *mrb, mrb_sym iv_name)
    567 {
    568   if (!mrb_iv_p(mrb, iv_name)) {
    569     mrb_name_error(mrb, iv_name, "'%S' is not allowed as an instance variable name", mrb_sym2str(mrb, iv_name));
     441  if (ISDIGIT(s[1])) return FALSE;
     442  return mrb_ident_p(s+1, len-1);
     443}
     444
     445MRB_API void
     446mrb_iv_name_sym_check(mrb_state *mrb, mrb_sym iv_name)
     447{
     448  if (!mrb_iv_name_sym_p(mrb, iv_name)) {
     449    mrb_name_error(mrb, iv_name, "'%n' is not allowed as an instance variable name", iv_name);
    570450  }
    571451}
     
    604484    mrb_str_cat_lit(mrb, str, ", ");
    605485  }
    606   s = mrb_sym2name_len(mrb, sym, &len);
     486  s = mrb_sym_name_len(mrb, sym, &len);
    607487  mrb_str_cat(mrb, str, s, len);
    608488  mrb_str_cat_lit(mrb, str, "=");
    609   if (mrb_type(v) == MRB_TT_OBJECT) {
     489  if (mrb_object_p(v)) {
    610490    ins = mrb_any_to_s(mrb, v);
    611491  }
     
    625505  if (len > 0) {
    626506    const char *cn = mrb_obj_classname(mrb, mrb_obj_value(obj));
    627     mrb_value str = mrb_str_buf_new(mrb, 30);
     507    mrb_value str = mrb_str_new_capa(mrb, 30);
    628508
    629509    mrb_str_cat_lit(mrb, str, "-<");
    630510    mrb_str_cat_cstr(mrb, str, cn);
    631511    mrb_str_cat_lit(mrb, str, ":");
    632     mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, obj));
     512    mrb_str_cat_str(mrb, str, mrb_ptr_to_str(mrb, obj));
    633513
    634514    iv_foreach(mrb, t, inspect_i, &str);
     
    646526    mrb_value val;
    647527
    648     if (t && iv_del(mrb, t, sym, &val)) {
     528    mrb_check_frozen(mrb, mrb_obj_ptr(obj));
     529    if (iv_del(mrb, t, sym, &val)) {
    649530      return val;
    650531    }
    651532  }
    652533  return mrb_undef_value();
    653 }
    654 
    655 mrb_value
    656 mrb_vm_iv_get(mrb_state *mrb, mrb_sym sym)
    657 {
    658   /* get self */
    659   return mrb_iv_get(mrb, mrb->c->stack[0], sym);
    660 }
    661 
    662 void
    663 mrb_vm_iv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
    664 {
    665   /* get self */
    666   mrb_iv_set(mrb, mrb->c->stack[0], sym, v);
    667534}
    668535
     
    675542
    676543  ary = *(mrb_value*)p;
    677   s = mrb_sym2name_len(mrb, sym, &len);
     544  s = mrb_sym_name_len(mrb, sym, &len);
    678545  if (len > 1 && s[0] == '@' && s[1] != '@') {
    679546    mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
     
    705572
    706573  ary = mrb_ary_new(mrb);
    707   if (obj_iv_p(self) && mrb_obj_ptr(self)->iv) {
     574  if (obj_iv_p(self)) {
    708575    iv_foreach(mrb, mrb_obj_ptr(self)->iv, iv_i, &ary);
    709576  }
     
    719586
    720587  ary = *(mrb_value*)p;
    721   s = mrb_sym2name_len(mrb, sym, &len);
     588  s = mrb_sym_name_len(mrb, sym, &len);
    722589  if (len > 2 && s[0] == '@' && s[1] == '@') {
    723590    mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
     
    729596/*
    730597 *  call-seq:
    731  *     mod.class_variables   -> array
     598 *     mod.class_variables(inherit=true)   -> array
    732599 *
    733600 *  Returns an array of the names of class variables in <i>mod</i>.
     
    747614  mrb_value ary;
    748615  struct RClass *c;
    749 
     616  mrb_bool inherit = TRUE;
     617
     618  mrb_get_args(mrb, "|b", &inherit);
    750619  ary = mrb_ary_new(mrb);
    751620  c = mrb_class_ptr(mod);
    752621  while (c) {
    753     if (c->iv) {
    754       iv_foreach(mrb, c->iv, cv_i, &ary);
    755     }
     622    iv_foreach(mrb, c->iv, cv_i, &ary);
     623    if (!inherit) break;
    756624    c = c->super;
    757625  }
     
    759627}
    760628
    761 MRB_API mrb_value
     629mrb_value
    762630mrb_mod_cv_get(mrb_state *mrb, struct RClass *c, mrb_sym sym)
    763631{
     
    790658    }
    791659  }
    792   mrb_name_error(mrb, sym, "uninitialized class variable %S in %S",
    793                  mrb_sym2str(mrb, sym), mrb_obj_value(cls));
     660  mrb_name_error(mrb, sym, "uninitialized class variable %n in %C", sym, cls);
    794661  /* not reached */
    795662  return mrb_nil_value();
     
    808675
    809676  while (c) {
    810     if (c->iv) {
    811       iv_tbl *t = c->iv;
    812 
    813       if (iv_get(mrb, t, sym, NULL)) {
    814         mrb_write_barrier(mrb, (struct RBasic*)c);
    815         iv_put(mrb, t, sym, v);
    816         return;
    817       }
     677    iv_tbl *t = c->iv;
     678
     679    if (iv_get(mrb, t, sym, NULL)) {
     680      mrb_check_frozen(mrb, c);
     681      iv_put(mrb, t, sym, v);
     682      mrb_write_barrier(mrb, (struct RBasic*)c);
     683      return;
    818684    }
    819685    c = c->super;
     
    840706  }
    841707
     708  mrb_check_frozen(mrb, c);
    842709  if (!c->iv) {
    843710    c->iv = iv_new(mrb);
    844711  }
    845712
     713  iv_put(mrb, c->iv, sym, v);
    846714  mrb_write_barrier(mrb, (struct RBasic*)c);
    847   iv_put(mrb, c->iv, sym, v);
    848715}
    849716
     
    854721}
    855722
    856 MRB_API mrb_bool
     723mrb_bool
    857724mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym)
    858725{
    859726  while (c) {
    860     if (c->iv) {
    861       iv_tbl *t = c->iv;
    862       if (iv_get(mrb, t, sym, NULL)) return TRUE;
    863     }
     727    iv_tbl *t = c->iv;
     728    if (iv_get(mrb, t, sym, NULL)) return TRUE;
    864729    c = c->super;
    865730  }
     
    877742mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym)
    878743{
    879   struct RClass *c = mrb->c->ci->proc->target_class;
    880 
    881   if (!c) c = mrb->c->ci->target_class;
    882 
     744  struct RClass *c;
     745
     746  struct RProc *p = mrb->c->ci->proc;
     747
     748  for (;;) {
     749    c = MRB_PROC_TARGET_CLASS(p);
     750    if (c->tt != MRB_TT_SCLASS) break;
     751    p = p->upper;
     752  }
    883753  return mrb_mod_cv_get(mrb, c, sym);
    884754}
     
    887757mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
    888758{
    889   struct RClass *c = mrb->c->ci->proc->target_class;
    890 
    891   if (!c) c = mrb->c->ci->target_class;
     759  struct RClass *c;
     760  struct RProc *p = mrb->c->ci->proc;
     761
     762  for (;;) {
     763    c = MRB_PROC_TARGET_CLASS(p);
     764    if (c->tt != MRB_TT_SCLASS) break;
     765    p = p->upper;
     766  }
    892767  mrb_mod_cv_set(mrb, c, sym, v);
    893768}
     
    912787  struct RClass *c = base;
    913788  mrb_value v;
    914   iv_tbl *t;
    915789  mrb_bool retry = FALSE;
    916790  mrb_value name;
     
    919793  while (c) {
    920794    if (c->iv) {
    921       t = c->iv;
    922       if (iv_get(mrb, t, sym, &v))
     795      if (iv_get(mrb, c->iv, sym, &v))
    923796        return v;
    924797    }
    925798    c = c->super;
    926799  }
    927   if (!retry && base && base->tt == MRB_TT_MODULE) {
     800  if (!retry && base->tt == MRB_TT_MODULE) {
    928801    c = mrb->object_class;
    929802    retry = TRUE;
     
    944817mrb_vm_const_get(mrb_state *mrb, mrb_sym sym)
    945818{
    946   struct RClass *c = mrb->c->ci->proc->target_class;
    947 
    948   if (!c) c = mrb->c->ci->target_class;
    949   if (c) {
    950     struct RClass *c2;
    951     mrb_value v;
    952 
    953     if (c->iv && iv_get(mrb, c->iv, sym, &v)) {
     819  struct RClass *c;
     820  struct RClass *c2;
     821  mrb_value v;
     822  struct RProc *proc;
     823
     824  c = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc);
     825  if (iv_get(mrb, c->iv, sym, &v)) {
     826    return v;
     827  }
     828  c2 = c;
     829  while (c2 && c2->tt == MRB_TT_SCLASS) {
     830    mrb_value klass;
     831
     832    if (!iv_get(mrb, c2->iv, mrb_intern_lit(mrb, "__attached__"), &klass)) {
     833      c2 = NULL;
     834      break;
     835    }
     836    c2 = mrb_class_ptr(klass);
     837  }
     838  if (c2 && (c2->tt == MRB_TT_CLASS || c2->tt == MRB_TT_MODULE)) c = c2;
     839  mrb_assert(!MRB_PROC_CFUNC_P(mrb->c->ci->proc));
     840  proc = mrb->c->ci->proc;
     841  while (proc) {
     842    c2 = MRB_PROC_TARGET_CLASS(proc);
     843    if (c2 && iv_get(mrb, c2->iv, sym, &v)) {
    954844      return v;
    955845    }
    956     c2 = c;
    957     while (c2 && c2->tt == MRB_TT_SCLASS) {
    958       mrb_value klass;
    959       klass = mrb_obj_iv_get(mrb, (struct RObject *)c2,
    960                              mrb_intern_lit(mrb, "__attached__"));
    961       c2 = mrb_class_ptr(klass);
    962     }
    963     if (c2->tt == MRB_TT_CLASS || c2->tt == MRB_TT_MODULE) c = c2;
    964     c2 = c;
    965     for (;;) {
    966       c2 = mrb_class_outer_module(mrb, c2);
    967       if (!c2) break;
    968       if (c2->iv && iv_get(mrb, c2->iv, sym, &v)) {
    969         return v;
    970       }
    971     }
     846    proc = proc->upper;
    972847  }
    973848  return const_get(mrb, c, sym);
     
    978853{
    979854  mod_const_check(mrb, mod);
     855  if (mrb_type(v) == MRB_TT_CLASS || mrb_type(v) == MRB_TT_MODULE) {
     856    mrb_class_name_class(mrb, mrb_class_ptr(mod), mrb_class_ptr(v), sym);
     857  }
    980858  mrb_iv_set(mrb, mod, sym, v);
    981859}
     
    984862mrb_vm_const_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
    985863{
    986   struct RClass *c = mrb->c->ci->proc->target_class;
    987 
    988   if (!c) c = mrb->c->ci->target_class;
     864  struct RClass *c;
     865
     866  c = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc);
    989867  mrb_obj_iv_set(mrb, (struct RObject*)c, sym, v);
    990868}
     
    1017895
    1018896  ary = *(mrb_value*)p;
    1019   s = mrb_sym2name_len(mrb, sym, &len);
     897  s = mrb_sym_name_len(mrb, sym, &len);
    1020898  if (len >= 1 && ISUPPER(s[0])) {
    1021     mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
     899    mrb_int i, alen = RARRAY_LEN(ary);
     900
     901    for (i=0; i<alen; i++) {
     902      if (mrb_symbol(RARRAY_PTR(ary)[i]) == sym)
     903        break;
     904    }
     905    if (i==alen) {
     906      mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
     907    }
    1022908  }
    1023909  return 0;
     
    1041927  ary = mrb_ary_new(mrb);
    1042928  while (c) {
    1043     if (c->iv) {
    1044       iv_foreach(mrb, c->iv, const_i, &ary);
    1045     }
     929    iv_foreach(mrb, c->iv, const_i, &ary);
    1046930    if (!inherit) break;
    1047931    c = c->super;
     
    1056940  mrb_value v;
    1057941
    1058   if (!mrb->globals) {
    1059     return mrb_nil_value();
    1060   }
    1061942  if (iv_get(mrb, mrb->globals, sym, &v))
    1062943    return v;
     
    1070951
    1071952  if (!mrb->globals) {
    1072     t = mrb->globals = iv_new(mrb);
    1073   }
    1074   else {
    1075     t = mrb->globals;
    1076   }
     953    mrb->globals = iv_new(mrb);
     954  }
     955  t = mrb->globals;
    1077956  iv_put(mrb, t, sym, v);
    1078957}
     
    1081960mrb_gv_remove(mrb_state *mrb, mrb_sym sym)
    1082961{
    1083   if (!mrb->globals) {
    1084     return;
    1085   }
    1086962  iv_del(mrb, mrb->globals, sym, NULL);
    1087963}
     
    1112988  iv_tbl *t = mrb->globals;
    1113989  mrb_value ary = mrb_ary_new(mrb);
    1114   size_t i;
    1115   char buf[3];
    1116 
    1117   if (t) {
    1118     iv_foreach(mrb, t, gv_i, &ary);
    1119   }
    1120   buf[0] = '$';
    1121   buf[2] = 0;
    1122   for (i = 1; i <= 9; ++i) {
    1123     buf[1] = (char)(i + '0');
    1124     mrb_ary_push(mrb, ary, mrb_symbol_value(mrb_intern(mrb, buf, 2)));
    1125   }
     990
     991  iv_foreach(mrb, t, gv_i, &ary);
    1126992  return ary;
    1127993}
     
    1132998  struct RClass *klass = mrb_class_ptr(mod);
    1133999  struct RClass *tmp;
    1134   mrb_bool mod_retry = 0;
     1000  mrb_bool mod_retry = FALSE;
    11351001
    11361002  tmp = klass;
    11371003retry:
    11381004  while (tmp) {
    1139     if (tmp->iv && iv_get(mrb, tmp->iv, id, NULL)) {
     1005    if (iv_get(mrb, tmp->iv, id, NULL)) {
    11401006      return TRUE;
    11411007    }
     
    11441010  }
    11451011  if (!exclude && !mod_retry && (klass->tt == MRB_TT_MODULE)) {
    1146     mod_retry = 1;
     1012    mod_retry = TRUE;
    11471013    tmp = mrb->object_class;
    11481014    goto retry;
     
    11871053}
    11881054
    1189 mrb_sym
    1190 mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer)
    1191 {
    1192   mrb_value name;
    1193 
    1194   name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__classid__"));
    1195   if (mrb_nil_p(name)) {
    1196 
    1197     if (!outer) return 0;
    1198     else {
    1199       struct csym_arg arg;
    1200 
    1201       arg.c = c;
    1202       arg.sym = 0;
    1203       iv_foreach(mrb, outer->iv, csym_i, &arg);
    1204       return arg.sym;
    1205     }
    1206   }
    1207   return mrb_symbol(name);
    1208 }
     1055static mrb_sym
     1056find_class_sym(mrb_state *mrb, struct RClass *outer, struct RClass *c)
     1057{
     1058  struct csym_arg arg;
     1059
     1060  if (!outer) return 0;
     1061  if (outer == c) return 0;
     1062  arg.c = c;
     1063  arg.sym = 0;
     1064  iv_foreach(mrb, outer->iv, csym_i, &arg);
     1065  return arg.sym;
     1066}
     1067
     1068static struct RClass*
     1069outer_class(mrb_state *mrb, struct RClass *c)
     1070{
     1071  mrb_value ov;
     1072
     1073  ov = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"));
     1074  if (mrb_nil_p(ov)) return NULL;
     1075  switch (mrb_type(ov)) {
     1076  case MRB_TT_CLASS:
     1077  case MRB_TT_MODULE:
     1078    return mrb_class_ptr(ov);
     1079  default:
     1080    break;
     1081  }
     1082  return NULL;
     1083}
     1084
     1085static mrb_bool
     1086detect_outer_loop(mrb_state *mrb, struct RClass *c)
     1087{
     1088  struct RClass *t = c;         /* tortoise */
     1089  struct RClass *h = c;         /* hare */
     1090
     1091  for (;;) {
     1092    if (h == NULL) return FALSE;
     1093    h = outer_class(mrb, h);
     1094    if (h == NULL) return FALSE;
     1095    h = outer_class(mrb, h);
     1096    t = outer_class(mrb, t);
     1097    if (t == h) return TRUE;
     1098  }
     1099}
     1100
     1101mrb_value
     1102mrb_class_find_path(mrb_state *mrb, struct RClass *c)
     1103{
     1104  struct RClass *outer;
     1105  mrb_value path;
     1106  mrb_sym name;
     1107  const char *str;
     1108  mrb_int len;
     1109
     1110  if (detect_outer_loop(mrb, c)) return mrb_nil_value();
     1111  outer = outer_class(mrb, c);
     1112  if (outer == NULL) return mrb_nil_value();
     1113  name = find_class_sym(mrb, outer, c);
     1114  if (name == 0) return mrb_nil_value();
     1115  str = mrb_class_name(mrb, outer);
     1116  path = mrb_str_new_capa(mrb, 40);
     1117  mrb_str_cat_cstr(mrb, path, str);
     1118  mrb_str_cat_cstr(mrb, path, "::");
     1119
     1120  str = mrb_sym_name_len(mrb, name, &len);
     1121  mrb_str_cat(mrb, path, str, len);
     1122  if (RSTRING_PTR(path)[0] != '#') {
     1123    iv_del(mrb, c->iv, mrb_intern_lit(mrb, "__outer__"), NULL);
     1124    iv_put(mrb, c->iv, mrb_intern_lit(mrb, "__classname__"), path);
     1125    mrb_field_write_barrier_value(mrb, (struct RBasic*)c, path);
     1126    path = mrb_str_dup(mrb, path);
     1127  }
     1128  return path;
     1129}
     1130
     1131#define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c))
     1132
     1133mrb_bool
     1134mrb_ident_p(const char *s, mrb_int len)
     1135{
     1136  mrb_int i;
     1137
     1138  for (i = 0; i < len; i++) {
     1139    if (!identchar(s[i])) return FALSE;
     1140  }
     1141  return TRUE;
     1142}
  • EcnlProtoTool/trunk/mruby-2.1.1/src/vm.c

    r331 r439  
    77#include <stddef.h>
    88#include <stdarg.h>
     9#ifndef MRB_WITHOUT_FLOAT
    910#include <math.h>
     11#endif
    1012#include <mruby.h>
    1113#include <mruby/array.h>
     
    2325#include <mruby/throw.h>
    2426
    25 #ifndef MRB_DISABLE_STDIO
     27#ifdef MRB_DISABLE_STDIO
    2628#if defined(__cplusplus)
    2729extern "C" {
     
    5254#ifndef MRB_FUNCALL_DEPTH_MAX
    5355#define MRB_FUNCALL_DEPTH_MAX 512
     56#endif
     57
     58/* Maximum depth of ecall() recursion. */
     59#ifndef MRB_ECALL_DEPTH_MAX
     60#define MRB_ECALL_DEPTH_MAX 512
    5461#endif
    5562
     
    6673#endif
    6774
    68 #define ARENA_RESTORE(mrb,ai) (mrb)->gc.arena_idx = (ai)
     75
     76#ifndef MRB_GC_FIXED_ARENA
     77static void
     78mrb_gc_arena_shrink(mrb_state *mrb, int idx)
     79{
     80  mrb_gc *gc = &mrb->gc;
     81  int capa = gc->arena_capa;
     82
     83  if (idx < capa / 4) {
     84    capa >>= 2;
     85    if (capa < MRB_GC_ARENA_SIZE) {
     86      capa = MRB_GC_ARENA_SIZE;
     87    }
     88    if (capa != gc->arena_capa) {
     89      gc->arena = (struct RBasic**)mrb_realloc(mrb, gc->arena, sizeof(struct RBasic*)*capa);
     90      gc->arena_capa = capa;
     91    }
     92  }
     93}
     94#else
     95#define mrb_gc_arena_shrink(mrb,idx)
     96#endif
    6997
    7098#define CALL_MAXARGS 127
     
    116144
    117145static inline void
    118 envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase, size_t size)
     146envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase, size_t oldsize)
    119147{
    120148  mrb_callinfo *ci = mrb->c->cibase;
     
    126154
    127155    if (e && MRB_ENV_STACK_SHARED_P(e) &&
    128         (st = e->stack) && oldbase <= st && st < oldbase+size) {
     156        (st = e->stack) && oldbase <= st && st < oldbase+oldsize) {
    129157      ptrdiff_t off = e->stack - oldbase;
    130158
    131159      e->stack = newbase + off;
    132160    }
     161
     162    if (ci->proc && MRB_PROC_ENV_P(ci->proc) && ci->env != MRB_PROC_ENV(ci->proc)) {
     163      e = MRB_PROC_ENV(ci->proc);
     164
     165      if (e && MRB_ENV_STACK_SHARED_P(e) &&
     166          (st = e->stack) && oldbase <= st && st < oldbase+oldsize) {
     167        ptrdiff_t off = e->stack - oldbase;
     168
     169        e->stack = newbase + off;
     170      }
     171    }
     172
    133173    ci->stackent = newbase + (ci->stackent - oldbase);
    134174    ci++;
     
    139179
    140180static void
    141 stack_extend_alloc(mrb_state *mrb, int room)
     181stack_extend_alloc(mrb_state *mrb, mrb_int room)
    142182{
    143183  mrb_value *oldbase = mrb->c->stbase;
     
    149189  if (off > size) size = off;
    150190#ifdef MRB_STACK_EXTEND_DOUBLING
    151   if (room <= size)
     191  if ((size_t)room <= size)
    152192    size *= 2;
    153193  else
     
    168208  }
    169209  stack_clear(&(newstack[oldsize]), size - oldsize);
    170   envadjust(mrb, oldbase, newstack, size);
     210  envadjust(mrb, oldbase, newstack, oldsize);
    171211  mrb->c->stbase = newstack;
    172212  mrb->c->stack = mrb->c->stbase + off;
     
    180220}
    181221
    182 static inline void
    183 stack_extend(mrb_state *mrb, int room)
     222MRB_API void
     223mrb_stack_extend(mrb_state *mrb, mrb_int room)
    184224{
    185225  if (mrb->c->stack + room >= mrb->c->stend) {
     
    191231uvenv(mrb_state *mrb, int up)
    192232{
    193   struct REnv *e = mrb->c->ci->proc->env;
     233  struct RProc *proc = mrb->c->ci->proc;
     234  struct REnv *e;
    194235
    195236  while (up--) {
    196     if (!e) return NULL;
    197     e = (struct REnv*)e->c;
    198   }
    199   return e;
    200 }
    201 
    202 static inline mrb_bool
    203 is_strict(mrb_state *mrb, struct REnv *e)
    204 {
    205   int cioff = e->cioff;
    206 
    207   if (MRB_ENV_STACK_SHARED_P(e) && e->cxt.c->cibase[cioff].proc &&
    208       MRB_PROC_STRICT_P(e->cxt.c->cibase[cioff].proc)) {
    209     return TRUE;
    210   }
    211   return FALSE;
    212 }
    213 
    214 static inline struct REnv*
    215 top_env(mrb_state *mrb, struct RProc *proc)
    216 {
    217   struct REnv *e = proc->env;
    218 
    219   if (is_strict(mrb, e)) return e;
    220   while (e->c) {
    221     e = (struct REnv*)e->c;
    222     if (is_strict(mrb, e)) return e;
    223   }
    224   return e;
     237    proc = proc->upper;
     238    if (!proc) return NULL;
     239  }
     240  e = MRB_PROC_ENV(proc);
     241  if (e) return e;              /* proc has enclosed env */
     242  else {
     243    mrb_callinfo *ci = mrb->c->ci;
     244    mrb_callinfo *cb = mrb->c->cibase;
     245
     246    while (cb <= ci) {
     247      if (ci->proc == proc) {
     248        return ci->env;
     249      }
     250      ci--;
     251    }
     252  }
     253  return NULL;
     254}
     255
     256static inline struct RProc*
     257top_proc(mrb_state *mrb, struct RProc *proc)
     258{
     259  while (proc->upper) {
     260    if (MRB_PROC_SCOPE_P(proc) || MRB_PROC_STRICT_P(proc))
     261      return proc;
     262    proc = proc->upper;
     263  }
     264  return proc;
    225265}
    226266
     
    229269#define CI_ACC_RESUMED -3
    230270
    231 static mrb_callinfo*
     271static inline mrb_callinfo*
    232272cipush(mrb_state *mrb)
    233273{
    234274  struct mrb_context *c = mrb->c;
     275  static const mrb_callinfo ci_zero = { 0 };
    235276  mrb_callinfo *ci = c->ci;
    236277
     
    245286  }
    246287  ci = ++c->ci;
     288  *ci = ci_zero;
    247289  ci->epos = mrb->c->eidx;
    248290  ci->ridx = ridx;
    249   ci->env = 0;
    250   ci->pc = 0;
    251   ci->err = 0;
    252   ci->proc = 0;
    253   ci->acc = 0;
    254291
    255292  return ci;
    256293}
    257294
    258 MRB_API void
     295void
    259296mrb_env_unshare(mrb_state *mrb, struct REnv *e)
    260297{
    261   size_t len = (size_t)MRB_ENV_STACK_LEN(e);
    262   ptrdiff_t cioff = e->cioff;
    263   mrb_value *p;
    264 
    265   if (!MRB_ENV_STACK_SHARED_P(e)) return;
    266   if (e->cxt.c != mrb->c) return;
    267   if (e->cioff == 0 && e->cxt.c == mrb->root_c) return;
    268   MRB_ENV_UNSHARE_STACK(e);
    269   if (!e->c) {
    270     /* save block argument position (negated) */
    271     e->cioff = -e->cxt.c->cibase[cioff].argc-1;
    272   }
    273   e->cxt.mid = e->cxt.c->cibase[cioff].mid;
    274   p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
    275   if (len > 0) {
    276     stack_copy(p, e->stack, len);
    277   }
    278   e->stack = p;
    279   mrb_write_barrier(mrb, (struct RBasic *)e);
    280 }
    281 
    282 static void
     298  if (e == NULL) return;
     299  else {
     300    size_t len = (size_t)MRB_ENV_STACK_LEN(e);
     301    mrb_value *p;
     302
     303    if (!MRB_ENV_STACK_SHARED_P(e)) return;
     304    if (e->cxt != mrb->c) return;
     305    if (e == mrb->c->cibase->env) return; /* for mirb */
     306    p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
     307    if (len > 0) {
     308      stack_copy(p, e->stack, len);
     309    }
     310    e->stack = p;
     311    MRB_ENV_UNSHARE_STACK(e);
     312    mrb_write_barrier(mrb, (struct RBasic *)e);
     313  }
     314}
     315
     316static inline void
    283317cipop(mrb_state *mrb)
    284318{
     
    287321
    288322  c->ci--;
    289 
    290   if (env) {
    291     mrb_env_unshare(mrb, env);
    292   }
     323  if (env) mrb_env_unshare(mrb, env);
    293324}
    294325
     
    296327
    297328static void
    298 ecall(mrb_state *mrb, int i)
     329ecall(mrb_state *mrb)
    299330{
    300331  struct RProc *p;
    301   mrb_callinfo *ci = mrb->c->ci;
    302   mrb_value *self = mrb->c->stack;
     332  struct mrb_context *c = mrb->c;
     333  mrb_callinfo *ci = c->ci;
    303334  struct RObject *exc;
     335  struct REnv *env;
    304336  ptrdiff_t cioff;
    305337  int ai = mrb_gc_arena_save(mrb);
     338  uint16_t i = --c->eidx;
     339  int nregs;
    306340
    307341  if (i<0) return;
    308   if (ci - mrb->c->cibase > MRB_FUNCALL_DEPTH_MAX) {
     342  /* restrict total call depth of ecall() */
     343  if (++mrb->ecall_nest > MRB_ECALL_DEPTH_MAX) {
    309344    mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
    310345  }
    311   p = mrb->c->ensure[i];
     346  p = c->ensure[i];
    312347  if (!p) return;
    313   mrb->c->ensure[i] = NULL;
    314   cioff = ci - mrb->c->cibase;
     348  mrb_assert(!MRB_PROC_CFUNC_P(p));
     349  c->ensure[i] = NULL;
     350  nregs = p->upper->body.irep->nregs;
     351  if (ci->proc && !MRB_PROC_CFUNC_P(ci->proc) &&
     352      ci->proc->body.irep->nregs > nregs) {
     353    nregs = ci->proc->body.irep->nregs;
     354  }
     355  cioff = ci - c->cibase;
    315356  ci = cipush(mrb);
    316357  ci->stackent = mrb->c->stack;
     
    319360  ci->argc = 0;
    320361  ci->proc = p;
    321   ci->nregs = p->body.irep->nregs;
    322   ci->target_class = p->target_class;
    323   mrb->c->stack = mrb->c->stack + ci[-1].nregs;
     362  ci->target_class = MRB_PROC_TARGET_CLASS(p);
     363  env = MRB_PROC_ENV(p);
     364  mrb_assert(env);
     365  c->stack += nregs;
    324366  exc = mrb->exc; mrb->exc = 0;
    325367  if (exc) {
    326368    mrb_gc_protect(mrb, mrb_obj_value(exc));
    327369  }
    328   mrb_run(mrb, p, *self);
    329   mrb->c->ci = mrb->c->cibase + cioff;
     370  if (mrb->c->fib) {
     371    mrb_gc_protect(mrb, mrb_obj_value(mrb->c->fib));
     372  }
     373  mrb_run(mrb, p, env->stack[0]);
     374  mrb->c = c;
     375  c->ci = c->cibase + cioff;
    330376  if (!mrb->exc) mrb->exc = exc;
    331377  mrb_gc_arena_restore(mrb, ai);
     378  mrb->ecall_nest--;
    332379}
    333380
     
    356403}
    357404
     405static int
     406ci_nregs(mrb_callinfo *ci)
     407{
     408  struct RProc *p;
     409  int n = 0;
     410
     411  if (!ci) return 3;
     412  p = ci->proc;
     413  if (!p) {
     414    if (ci->argc < 0) return 3;
     415    return ci->argc+2;
     416  }
     417  if (!MRB_PROC_CFUNC_P(p) && p->body.irep) {
     418    n = p->body.irep->nregs;
     419  }
     420  if (ci->argc < 0) {
     421    if (n < 3) n = 3; /* self + args + blk */
     422  }
     423  if (ci->argc > n) {
     424    n = ci->argc + 2; /* self + blk */
     425  }
     426  return n;
     427}
     428
    358429MRB_API mrb_value
    359430mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv, mrb_value blk)
    360431{
    361432  mrb_value val;
     433  int ai = mrb_gc_arena_save(mrb);
    362434
    363435  if (!mrb->jmp) {
     
    383455  }
    384456  else {
    385     struct RProc *p;
     457    mrb_method_t m;
    386458    struct RClass *c;
    387459    mrb_callinfo *ci;
    388     int n;
     460    int n = ci_nregs(mrb->c->ci);
    389461    ptrdiff_t voff = -1;
    390462
     
    392464      stack_init(mrb);
    393465    }
    394     n = mrb->c->ci->nregs;
    395466    if (argc < 0) {
    396       mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%S)", mrb_fixnum_value(argc));
     467      mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%i)", argc);
    397468    }
    398469    c = mrb_class(mrb, self);
    399     p = mrb_method_search_vm(mrb, &c, mid);
    400     if (!p) {
     470    m = mrb_method_search_vm(mrb, &c, mid);
     471    if (MRB_METHOD_UNDEF_P(m)) {
    401472      mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
    402473      mrb_value args = mrb_ary_new_from_values(mrb, argc, argv);
    403       p = mrb_method_search_vm(mrb, &c, missing);
    404       if (!p) {
     474      m = mrb_method_search_vm(mrb, &c, missing);
     475      if (MRB_METHOD_UNDEF_P(m)) {
    405476        mrb_method_missing(mrb, mid, self, args);
    406477      }
    407478      mrb_ary_unshift(mrb, args, mrb_symbol_value(mid));
    408       stack_extend(mrb, n+2);
     479      mrb_stack_extend(mrb, n+2);
    409480      mrb->c->stack[n+1] = args;
    410481      argc = -1;
     
    415486    ci = cipush(mrb);
    416487    ci->mid = mid;
    417     ci->proc = p;
    418488    ci->stackent = mrb->c->stack;
    419     ci->argc = argc;
     489    ci->argc = (int)argc;
    420490    ci->target_class = c;
    421491    mrb->c->stack = mrb->c->stack + n;
     492    if (argc < 0) argc = 1;
    422493    if (mrb->c->stbase <= argv && argv < mrb->c->stend) {
    423494      voff = argv - mrb->c->stbase;
    424495    }
    425     if (MRB_PROC_CFUNC_P(p)) {
    426       ci->nregs = argc + 2;
    427       stack_extend(mrb, ci->nregs);
    428     }
    429     else if (argc >= CALL_MAXARGS) {
     496    if (argc >= CALL_MAXARGS) {
    430497      mrb_value args = mrb_ary_new_from_values(mrb, argc, argv);
    431       stack_extend(mrb, ci->nregs);
     498
    432499      mrb->c->stack[1] = args;
    433500      ci->argc = -1;
    434501      argc = 1;
    435502    }
    436     else {
    437       if (argc < 0) argc = 1;
    438       ci->nregs = p->body.irep->nregs + argc;
    439       stack_extend(mrb, ci->nregs);
     503    mrb_stack_extend(mrb, argc + 2);
     504    if (MRB_METHOD_PROC_P(m)) {
     505      struct RProc *p = MRB_METHOD_PROC(m);
     506
     507      ci->proc = p;
     508      if (!MRB_PROC_CFUNC_P(p)) {
     509        mrb_stack_extend(mrb, p->body.irep->nregs + argc);
     510      }
    440511    }
    441512    if (voff >= 0) {
     
    448519    mrb->c->stack[argc+1] = blk;
    449520
    450     if (MRB_PROC_CFUNC_P(p)) {
    451       int ai = mrb_gc_arena_save(mrb);
    452 
     521    if (MRB_METHOD_CFUNC_P(m)) {
    453522      ci->acc = CI_ACC_DIRECT;
    454       val = p->body.func(mrb, self);
     523      val = MRB_METHOD_CFUNC(m)(mrb, self);
    455524      mrb->c->stack = mrb->c->ci->stackent;
    456525      cipop(mrb);
    457       mrb_gc_arena_restore(mrb, ai);
    458526    }
    459527    else {
    460528      ci->acc = CI_ACC_SKIP;
    461       val = mrb_run(mrb, p, self);
    462     }
    463   }
     529      val = mrb_run(mrb, MRB_METHOD_PROC(m), self);
     530    }
     531  }
     532  mrb_gc_arena_restore(mrb, ai);
    464533  mrb_gc_protect(mrb, val);
    465534  return val;
     
    476545{
    477546  mrb_callinfo *ci = mrb->c->ci;
     547  int keep, nregs;
    478548
    479549  mrb->c->stack[0] = self;
    480550  ci->proc = p;
    481   ci->target_class = p->target_class;
    482551  if (MRB_PROC_CFUNC_P(p)) {
    483     return p->body.func(mrb, self);
    484   }
    485   if (ci->argc < 0) {
    486     stack_extend(mrb, (p->body.irep->nregs < 3) ? 3 : p->body.irep->nregs);
     552    return MRB_PROC_CFUNC(p)(mrb, self);
     553  }
     554  nregs = p->body.irep->nregs;
     555  if (ci->argc < 0) keep = 3;
     556  else keep = ci->argc + 2;
     557  if (nregs < keep) {
     558    mrb_stack_extend(mrb, keep);
    487559  }
    488560  else {
    489     stack_extend(mrb, p->body.irep->nregs);
    490   }
    491 
    492   ci->nregs = p->body.irep->nregs;
     561    mrb_stack_extend(mrb, nregs);
     562    stack_clear(mrb->c->stack+keep, nregs-keep);
     563  }
     564
    493565  ci = cipush(mrb);
    494   ci->nregs = 0;
    495566  ci->target_class = 0;
    496567  ci->pc = p->body.irep->iseq;
     
    520591 *     k.send :hello, "gentle", "readers"   #=> "Hello gentle readers"
    521592 */
    522 MRB_API mrb_value
     593mrb_value
    523594mrb_f_send(mrb_state *mrb, mrb_value self)
    524595{
     
    526597  mrb_value block, *argv, *regs;
    527598  mrb_int argc, i, len;
    528   struct RProc *p;
     599  mrb_method_t m;
    529600  struct RClass *c;
    530601  mrb_callinfo *ci;
     
    538609
    539610  c = mrb_class(mrb, self);
    540   p = mrb_method_search_vm(mrb, &c, name);
    541 
    542   if (!p) {                     /* call method_mising */
     611  m = mrb_method_search_vm(mrb, &c, name);
     612  if (MRB_METHOD_UNDEF_P(m)) {            /* call method_mising */
    543613    goto funcall;
    544614  }
     
    558628  }
    559629
    560   return mrb_exec_irep(mrb, self, p);
     630  if (MRB_METHOD_CFUNC_P(m)) {
     631    if (MRB_METHOD_PROC_P(m)) {
     632      ci->proc = MRB_METHOD_PROC(m);
     633    }
     634    return MRB_METHOD_CFUNC(m)(mrb, self);
     635  }
     636  return mrb_exec_irep(mrb, self, MRB_METHOD_PROC(m));
    561637}
    562638
     
    566642  struct RProc *p;
    567643  mrb_callinfo *ci;
    568   mrb_int max = 3;
     644  int nregs;
    569645
    570646  if (mrb_nil_p(blk)) {
     
    582658  ci->mid = ci[-1].mid;
    583659  if (MRB_PROC_CFUNC_P(p)) {
    584     stack_extend(mrb, 3);
     660    mrb_stack_extend(mrb, 3);
    585661    mrb->c->stack[0] = self;
    586662    mrb->c->stack[1] = self;
    587663    mrb->c->stack[2] = mrb_nil_value();
    588     return p->body.func(mrb, self);
    589   }
    590   ci->nregs = p->body.irep->nregs;
    591   if (max < ci->nregs) max = ci->nregs;
    592   stack_extend(mrb, max);
     664    return MRB_PROC_CFUNC(p)(mrb, self);
     665  }
     666  nregs = p->body.irep->nregs;
     667  if (nregs < 3) nregs = 3;
     668  mrb_stack_extend(mrb, nregs);
    593669  mrb->c->stack[0] = self;
    594670  mrb->c->stack[1] = self;
    595   mrb->c->stack[2] = mrb_nil_value();
     671  stack_clear(mrb->c->stack+2, nregs-2);
    596672  ci = cipush(mrb);
    597   ci->nregs = 0;
    598673  ci->target_class = 0;
    599674  ci->pc = p->body.irep->iseq;
     
    659734  case MRB_TT_SYMBOL:
    660735  case MRB_TT_FIXNUM:
     736#ifndef MRB_WITHOUT_FLOAT
    661737  case MRB_TT_FLOAT:
     738#endif
    662739    c = 0;
    663740    break;
     
    676753  mrb_sym mid = mrb->c->ci->mid;
    677754  mrb_callinfo *ci;
    678   int n = mrb->c->ci->nregs;
    679755  mrb_value val;
     756  int n;
    680757
    681758  if (mrb_nil_p(b)) {
    682759    mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
    683760  }
    684   if (mrb->c->ci - mrb->c->cibase > MRB_FUNCALL_DEPTH_MAX) {
     761  ci = mrb->c->ci;
     762  n = ci_nregs(ci);
     763  if (ci - mrb->c->cibase > MRB_FUNCALL_DEPTH_MAX) {
    685764    mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
    686765  }
     
    690769  ci->proc = p;
    691770  ci->stackent = mrb->c->stack;
    692   ci->argc = argc;
     771  ci->argc = (int)argc;
    693772  ci->target_class = c;
    694773  ci->acc = CI_ACC_SKIP;
     774  n = MRB_PROC_CFUNC_P(p) ? (int)(argc+2) : p->body.irep->nregs;
    695775  mrb->c->stack = mrb->c->stack + n;
    696   if (MRB_PROC_CFUNC_P(p)) {
    697     ci->nregs = argc + 2;
    698     stack_extend(mrb, ci->nregs);
    699   }
    700   else {
    701     ci->nregs = p->body.irep->nregs;
    702     stack_extend(mrb, ci->nregs);
    703   }
     776  mrb_stack_extend(mrb, n);
    704777
    705778  mrb->c->stack[0] = self;
     
    710783
    711784  if (MRB_PROC_CFUNC_P(p)) {
    712     val = p->body.func(mrb, self);
     785    val = MRB_PROC_CFUNC(p)(mrb, self);
    713786    mrb->c->stack = mrb->c->ci->stackent;
     787    cipop(mrb);
    714788  }
    715789  else {
    716     int cioff = mrb->c->ci - mrb->c->cibase;
    717790    val = mrb_run(mrb, p, self);
    718     mrb->c->ci = mrb->c->cibase + cioff;
    719   }
    720   cipop(mrb);
     791  }
    721792  return val;
    722793}
     
    727798  struct RProc *p = mrb_proc_ptr(b);
    728799
    729   return mrb_yield_with_class(mrb, b, argc, argv, p->env->stack[0], p->target_class);
     800  return mrb_yield_with_class(mrb, b, argc, argv, MRB_PROC_ENV(p)->stack[0], MRB_PROC_TARGET_CLASS(p));
    730801}
    731802
     
    735806  struct RProc *p = mrb_proc_ptr(b);
    736807
    737   return mrb_yield_with_class(mrb, b, 1, &arg, p->env->stack[0], p->target_class);
     808  return mrb_yield_with_class(mrb, b, 1, &arg, MRB_PROC_ENV(p)->stack[0], MRB_PROC_TARGET_CLASS(p));
    738809}
    739810
     
    747818    mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
    748819  }
    749   if (mrb_type(b) != MRB_TT_PROC) {
     820  if (!mrb_proc_p(b)) {
    750821    mrb_raise(mrb, E_TYPE_ERROR, "not a block");
    751822  }
     
    754825  ci = mrb->c->ci;
    755826
    756   stack_extend(mrb, 3);
     827  mrb_stack_extend(mrb, 3);
    757828  mrb->c->stack[1] = mrb_ary_new_from_values(mrb, argc, argv);
    758829  mrb->c->stack[2] = mrb_nil_value();
     
    767838
    768839  brk = (struct RBreak*)mrb_obj_alloc(mrb, MRB_TT_BREAK, NULL);
    769   brk->iv = NULL;
    770   brk->proc = p;
    771   brk->val = val;
     840  mrb_break_proc_set(brk, p);
     841  mrb_break_value_set(brk, val);
    772842
    773843  return brk;
     
    789859  mrb_value exc;
    790860
    791   msg = mrb_str_buf_new(mrb, sizeof(lead) + 7);
     861  msg = mrb_str_new_capa(mrb, sizeof(lead) + 7);
    792862  mrb_str_cat(mrb, msg, lead, sizeof(lead) - 1);
    793863  mrb_str_cat(mrb, msg, kind_str[kind], kind_str_len[kind]);
     
    810880  }
    811881  if (mrb->c->ci->mid) {
    812     str = mrb_format(mrb, "'%S': wrong number of arguments (%S for %S)",
    813                   mrb_sym2str(mrb, mrb->c->ci->mid),
    814                   mrb_fixnum_value(argc), mrb_fixnum_value(num));
     882    str = mrb_format(mrb, "'%n': wrong number of arguments (%i for %i)",
     883                     mrb->c->ci->mid, argc, num);
    815884  }
    816885  else {
    817     str = mrb_format(mrb, "wrong number of arguments (%S for %S)",
    818                      mrb_fixnum_value(argc), mrb_fixnum_value(num));
     886    str = mrb_format(mrb, "wrong number of arguments (%i for %i)", argc, num);
    819887  }
    820888  exc = mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str);
     
    822890}
    823891
    824 #define ERR_PC_SET(mrb, pc) mrb->c->ci->err = pc;
    825 #define ERR_PC_CLR(mrb)     mrb->c->ci->err = 0;
     892#define ERR_PC_SET(mrb) mrb->c->ci->err = pc0;
     893#define ERR_PC_CLR(mrb) mrb->c->ci->err = 0;
    826894#ifdef MRB_ENABLE_DEBUG_HOOK
    827895#define CODE_FETCH_HOOK(mrb, irep, pc, regs) if ((mrb)->code_fetch_hook) (mrb)->code_fetch_hook((mrb), (irep), (pc), (regs));
     
    836904#endif
    837905
    838 
     906#ifndef MRB_DISABLE_DIRECT_THREADING
    839907#if defined __GNUC__ || defined __clang__ || defined __INTEL_COMPILER
    840908#define DIRECT_THREADED
    841909#endif
     910#endif /* ifndef MRB_DISABLE_DIRECT_THREADING */
    842911
    843912#ifndef DIRECT_THREADED
    844913
    845 #define INIT_DISPATCH for (;;) { i = BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); switch (GET_OPCODE(i)) {
    846 #define CASE(op) case op:
    847 #define NEXT pc++; break
    848 #define JUMP break
     914#define INIT_DISPATCH for (;;) { insn = BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); switch (insn) {
     915#define CASE(insn,ops) case insn: pc0=pc++; FETCH_ ## ops ();; L_ ## insn ## _BODY:
     916#define NEXT break
     917#define JUMP NEXT
    849918#define END_DISPATCH }}
    850919
     
    852921
    853922#define INIT_DISPATCH JUMP; return mrb_nil_value();
    854 #define CASE(op) L_ ## op:
    855 #define NEXT i=BYTECODE_DECODER(*++pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[GET_OPCODE(i)]
    856 #define JUMP i=BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[GET_OPCODE(i)]
     923#define CASE(insn,ops) L_ ## insn: pc0=pc++; FETCH_ ## ops (); L_ ## insn ## _BODY:
     924#define NEXT insn=BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[insn]
     925#define JUMP NEXT
    857926
    858927#define END_DISPATCH
     
    866935  mrb_value result;
    867936  struct mrb_context *c = mrb->c;
    868   int cioff = c->ci - c->cibase;
     937  ptrdiff_t cioff = c->ci - c->cibase;
    869938  unsigned int nregs = irep->nregs;
    870939
     
    874943  if (stack_keep > nregs)
    875944    nregs = stack_keep;
    876   stack_extend(mrb, nregs);
     945  mrb_stack_extend(mrb, nregs);
    877946  stack_clear(c->stack + stack_keep, nregs - stack_keep);
    878947  c->stack[0] = self;
    879948  result = mrb_vm_exec(mrb, proc, irep->iseq);
    880   if (c->ci - c->cibase > cioff) {
    881     c->ci = c->cibase + cioff;
    882   }
    883949  if (mrb->c != c) {
    884950    if (mrb->c->fib) {
     
    887953    mrb->c = c;
    888954  }
     955  else if (c->ci - c->cibase > cioff) {
     956    c->ci = c->cibase + cioff;
     957  }
    889958  return result;
    890959}
    891960
     961static mrb_bool
     962check_target_class(mrb_state *mrb)
     963{
     964  if (!mrb->c->ci->target_class) {
     965    mrb_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, "no target class or module");
     966    mrb_exc_set(mrb, exc);
     967    return FALSE;
     968  }
     969  return TRUE;
     970}
     971
     972void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self);
     973
    892974MRB_API mrb_value
    893 mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
    894 {
    895   /* mrb_assert(mrb_proc_cfunc_p(proc)) */
     975mrb_vm_exec(mrb_state *mrb, struct RProc *proc, const mrb_code *pc)
     976{
     977  /* mrb_assert(MRB_PROC_CFUNC_P(proc)) */
     978  const mrb_code *pc0 = pc;
    896979  mrb_irep *irep = proc->body.irep;
    897980  mrb_value *pool = irep->pool;
    898981  mrb_sym *syms = irep->syms;
    899   mrb_code i;
     982  mrb_code insn;
    900983  int ai = mrb_gc_arena_save(mrb);
    901984  struct mrb_jmpbuf *prev_jmp = mrb->jmp;
    902985  struct mrb_jmpbuf c_jmp;
     986  uint32_t a;
     987  uint16_t b;
     988  uint8_t c;
     989  mrb_sym mid;
    903990
    904991#ifdef DIRECT_THREADED
    905992  static void *optable[] = {
    906     &&L_OP_NOP, &&L_OP_MOVE,
    907     &&L_OP_LOADL, &&L_OP_LOADI, &&L_OP_LOADSYM, &&L_OP_LOADNIL,
    908     &&L_OP_LOADSELF, &&L_OP_LOADT, &&L_OP_LOADF,
    909     &&L_OP_GETGLOBAL, &&L_OP_SETGLOBAL, &&L_OP_GETSPECIAL, &&L_OP_SETSPECIAL,
    910     &&L_OP_GETIV, &&L_OP_SETIV, &&L_OP_GETCV, &&L_OP_SETCV,
    911     &&L_OP_GETCONST, &&L_OP_SETCONST, &&L_OP_GETMCNST, &&L_OP_SETMCNST,
    912     &&L_OP_GETUPVAR, &&L_OP_SETUPVAR,
    913     &&L_OP_JMP, &&L_OP_JMPIF, &&L_OP_JMPNOT,
    914     &&L_OP_ONERR, &&L_OP_RESCUE, &&L_OP_POPERR, &&L_OP_RAISE, &&L_OP_EPUSH, &&L_OP_EPOP,
    915     &&L_OP_SEND, &&L_OP_SENDB, &&L_OP_FSEND,
    916     &&L_OP_CALL, &&L_OP_SUPER, &&L_OP_ARGARY, &&L_OP_ENTER,
    917     &&L_OP_KARG, &&L_OP_KDICT, &&L_OP_RETURN, &&L_OP_TAILCALL, &&L_OP_BLKPUSH,
    918     &&L_OP_ADD, &&L_OP_ADDI, &&L_OP_SUB, &&L_OP_SUBI, &&L_OP_MUL, &&L_OP_DIV,
    919     &&L_OP_EQ, &&L_OP_LT, &&L_OP_LE, &&L_OP_GT, &&L_OP_GE,
    920     &&L_OP_ARRAY, &&L_OP_ARYCAT, &&L_OP_ARYPUSH, &&L_OP_AREF, &&L_OP_ASET, &&L_OP_APOST,
    921     &&L_OP_STRING, &&L_OP_STRCAT, &&L_OP_HASH,
    922     &&L_OP_LAMBDA, &&L_OP_RANGE, &&L_OP_OCLASS,
    923     &&L_OP_CLASS, &&L_OP_MODULE, &&L_OP_EXEC,
    924     &&L_OP_METHOD, &&L_OP_SCLASS, &&L_OP_TCLASS,
    925     &&L_OP_DEBUG, &&L_OP_STOP, &&L_OP_ERR,
     993#define OPCODE(x,_) &&L_OP_ ## x,
     994#include "mruby/ops.h"
     995#undef OPCODE
    926996  };
    927997#endif
     
    9341004  if (exc_catched) {
    9351005    exc_catched = FALSE;
     1006    mrb_gc_arena_restore(mrb, ai);
    9361007    if (mrb->exc && mrb->exc->tt == MRB_TT_BREAK)
    9371008      goto L_BREAK;
     
    9401011  mrb->jmp = &c_jmp;
    9411012  mrb->c->ci->proc = proc;
    942   mrb->c->ci->nregs = irep->nregs;
    9431013
    9441014#define regs (mrb->c->stack)
    9451015  INIT_DISPATCH {
    946     CASE(OP_NOP) {
     1016    CASE(OP_NOP, Z) {
    9471017      /* do nothing */
    9481018      NEXT;
    9491019    }
    9501020
    951     CASE(OP_MOVE) {
    952       /* A B    R(A) := R(B) */
    953       int a = GETARG_A(i);
    954       int b = GETARG_B(i);
     1021    CASE(OP_MOVE, BB) {
    9551022      regs[a] = regs[b];
    9561023      NEXT;
    9571024    }
    9581025
    959     CASE(OP_LOADL) {
    960       /* A Bx   R(A) := Pool(Bx) */
    961       int a = GETARG_A(i);
    962       int bx = GETARG_Bx(i);
     1026    CASE(OP_LOADL, BB) {
    9631027#ifdef MRB_WORD_BOXING
    964       mrb_value val = pool[bx];
     1028      mrb_value val = pool[b];
     1029#ifndef MRB_WITHOUT_FLOAT
    9651030      if (mrb_float_p(val)) {
    9661031        val = mrb_float_value(mrb, mrb_float(val));
    9671032      }
     1033#endif
    9681034      regs[a] = val;
    9691035#else
    970       regs[a] = pool[bx];
    971 #endif
    972       NEXT;
    973     }
    974 
    975     CASE(OP_LOADI) {
    976       /* A sBx  R(A) := sBx */
    977       SET_INT_VALUE(regs[GETARG_A(i)], GETARG_sBx(i));
    978       NEXT;
    979     }
    980 
    981     CASE(OP_LOADSYM) {
    982       /* A Bx   R(A) := Syms(Bx) */
    983       int a = GETARG_A(i);
    984       int bx = GETARG_Bx(i);
    985       SET_SYM_VALUE(regs[a], syms[bx]);
    986       NEXT;
    987     }
    988 
    989     CASE(OP_LOADSELF) {
    990       /* A      R(A) := self */
    991       int a = GETARG_A(i);
     1036      regs[a] = pool[b];
     1037#endif
     1038      NEXT;
     1039    }
     1040
     1041    CASE(OP_LOADI, BB) {
     1042      SET_INT_VALUE(regs[a], b);
     1043      NEXT;
     1044    }
     1045
     1046    CASE(OP_LOADINEG, BB) {
     1047      SET_INT_VALUE(regs[a], -b);
     1048      NEXT;
     1049    }
     1050
     1051    CASE(OP_LOADI__1,B) goto L_LOADI;
     1052    CASE(OP_LOADI_0,B) goto L_LOADI;
     1053    CASE(OP_LOADI_1,B) goto L_LOADI;
     1054    CASE(OP_LOADI_2,B) goto L_LOADI;
     1055    CASE(OP_LOADI_3,B) goto L_LOADI;
     1056    CASE(OP_LOADI_4,B) goto L_LOADI;
     1057    CASE(OP_LOADI_5,B) goto L_LOADI;
     1058    CASE(OP_LOADI_6,B) goto L_LOADI;
     1059    CASE(OP_LOADI_7, B) {
     1060    L_LOADI:
     1061      SET_INT_VALUE(regs[a], (mrb_int)insn - (mrb_int)OP_LOADI_0);
     1062      NEXT;
     1063    }
     1064
     1065    CASE(OP_LOADSYM, BB) {
     1066      SET_SYM_VALUE(regs[a], syms[b]);
     1067      NEXT;
     1068    }
     1069
     1070    CASE(OP_LOADNIL, B) {
     1071      SET_NIL_VALUE(regs[a]);
     1072      NEXT;
     1073    }
     1074
     1075    CASE(OP_LOADSELF, B) {
    9921076      regs[a] = regs[0];
    9931077      NEXT;
    9941078    }
    9951079
    996     CASE(OP_LOADT) {
    997       /* A      R(A) := true */
    998       int a = GETARG_A(i);
     1080    CASE(OP_LOADT, B) {
    9991081      SET_TRUE_VALUE(regs[a]);
    10001082      NEXT;
    10011083    }
    10021084
    1003     CASE(OP_LOADF) {
    1004       /* A      R(A) := false */
    1005       int a = GETARG_A(i);
     1085    CASE(OP_LOADF, B) {
    10061086      SET_FALSE_VALUE(regs[a]);
    10071087      NEXT;
    10081088    }
    10091089
    1010     CASE(OP_GETGLOBAL) {
    1011       /* A Bx   R(A) := getglobal(Syms(Bx)) */
    1012       int a = GETARG_A(i);
    1013       int bx = GETARG_Bx(i);
    1014       mrb_value val = mrb_gv_get(mrb, syms[bx]);
     1090    CASE(OP_GETGV, BB) {
     1091      mrb_value val = mrb_gv_get(mrb, syms[b]);
    10151092      regs[a] = val;
    10161093      NEXT;
    10171094    }
    10181095
    1019     CASE(OP_SETGLOBAL) {
    1020       /* A Bx   setglobal(Syms(Bx), R(A)) */
    1021       int a = GETARG_A(i);
    1022       int bx = GETARG_Bx(i);
    1023       mrb_gv_set(mrb, syms[bx], regs[a]);
    1024       NEXT;
    1025     }
    1026 
    1027     CASE(OP_GETSPECIAL) {
    1028       /* A Bx   R(A) := Special[Bx] */
    1029       int a = GETARG_A(i);
    1030       int bx = GETARG_Bx(i);
    1031       mrb_value val = mrb_vm_special_get(mrb, bx);
     1096    CASE(OP_SETGV, BB) {
     1097      mrb_gv_set(mrb, syms[b], regs[a]);
     1098      NEXT;
     1099    }
     1100
     1101    CASE(OP_GETSV, BB) {
     1102      mrb_value val = mrb_vm_special_get(mrb, b);
    10321103      regs[a] = val;
    10331104      NEXT;
    10341105    }
    10351106
    1036     CASE(OP_SETSPECIAL) {
    1037       /* A Bx   Special[Bx] := R(A) */
    1038       int a = GETARG_A(i);
    1039       int bx = GETARG_Bx(i);
    1040       mrb_vm_special_set(mrb, bx, regs[a]);
    1041       NEXT;
    1042     }
    1043 
    1044     CASE(OP_GETIV) {
    1045       /* A Bx   R(A) := ivget(Bx) */
    1046       int a = GETARG_A(i);
    1047       int bx = GETARG_Bx(i);
    1048       mrb_value val = mrb_vm_iv_get(mrb, syms[bx]);
    1049       regs[a] = val;
    1050       NEXT;
    1051     }
    1052 
    1053     CASE(OP_SETIV) {
    1054       /* A Bx   ivset(Syms(Bx),R(A)) */
    1055       int a = GETARG_A(i);
    1056       int bx = GETARG_Bx(i);
    1057       mrb_vm_iv_set(mrb, syms[bx], regs[a]);
    1058       NEXT;
    1059     }
    1060 
    1061     CASE(OP_GETCV) {
    1062       /* A Bx   R(A) := cvget(Syms(Bx)) */
    1063       int a = GETARG_A(i);
    1064       int bx = GETARG_Bx(i);
     1107    CASE(OP_SETSV, BB) {
     1108      mrb_vm_special_set(mrb, b, regs[a]);
     1109      NEXT;
     1110    }
     1111
     1112    CASE(OP_GETIV, BB) {
     1113      regs[a] = mrb_iv_get(mrb, regs[0], syms[b]);
     1114      NEXT;
     1115    }
     1116
     1117    CASE(OP_SETIV, BB) {
     1118      mrb_iv_set(mrb, regs[0], syms[b], regs[a]);
     1119      NEXT;
     1120    }
     1121
     1122    CASE(OP_GETCV, BB) {
    10651123      mrb_value val;
    1066       ERR_PC_SET(mrb, pc);
    1067       val = mrb_vm_cv_get(mrb, syms[bx]);
     1124      ERR_PC_SET(mrb);
     1125      val = mrb_vm_cv_get(mrb, syms[b]);
    10681126      ERR_PC_CLR(mrb);
    10691127      regs[a] = val;
     
    10711129    }
    10721130
    1073     CASE(OP_SETCV) {
    1074       /* A Bx   cvset(Syms(Bx),R(A)) */
    1075       int a = GETARG_A(i);
    1076       int bx = GETARG_Bx(i);
    1077       mrb_vm_cv_set(mrb, syms[bx], regs[a]);
    1078       NEXT;
    1079     }
    1080 
    1081     CASE(OP_GETCONST) {
    1082       /* A Bx    R(A) := constget(Syms(Bx)) */
     1131    CASE(OP_SETCV, BB) {
     1132      mrb_vm_cv_set(mrb, syms[b], regs[a]);
     1133      NEXT;
     1134    }
     1135
     1136    CASE(OP_GETCONST, BB) {
    10831137      mrb_value val;
    1084       int a = GETARG_A(i);
    1085       int bx = GETARG_Bx(i);
    1086       mrb_sym sym = syms[bx];
    1087 
    1088       ERR_PC_SET(mrb, pc);
     1138      mrb_sym sym = syms[b];
     1139
     1140      ERR_PC_SET(mrb);
    10891141      val = mrb_vm_const_get(mrb, sym);
    10901142      ERR_PC_CLR(mrb);
     
    10931145    }
    10941146
    1095     CASE(OP_SETCONST) {
    1096       /* A Bx   constset(Syms(Bx),R(A)) */
    1097       int a = GETARG_A(i);
    1098       int bx = GETARG_Bx(i);
    1099       mrb_vm_const_set(mrb, syms[bx], regs[a]);
    1100       NEXT;
    1101     }
    1102 
    1103     CASE(OP_GETMCNST) {
    1104       /* A Bx   R(A) := R(A)::Syms(Bx) */
     1147    CASE(OP_SETCONST, BB) {
     1148      mrb_vm_const_set(mrb, syms[b], regs[a]);
     1149      NEXT;
     1150    }
     1151
     1152    CASE(OP_GETMCNST, BB) {
    11051153      mrb_value val;
    1106       int a = GETARG_A(i);
    1107       int bx = GETARG_Bx(i);
    1108 
    1109       ERR_PC_SET(mrb, pc);
    1110       val = mrb_const_get(mrb, regs[a], syms[bx]);
     1154
     1155      ERR_PC_SET(mrb);
     1156      val = mrb_const_get(mrb, regs[a], syms[b]);
    11111157      ERR_PC_CLR(mrb);
    11121158      regs[a] = val;
     
    11141160    }
    11151161
    1116     CASE(OP_SETMCNST) {
    1117       /* A Bx    R(A+1)::Syms(Bx) := R(A) */
    1118       int a = GETARG_A(i);
    1119       int bx = GETARG_Bx(i);
    1120       mrb_const_set(mrb, regs[a+1], syms[bx], regs[a]);
    1121       NEXT;
    1122     }
    1123 
    1124     CASE(OP_GETUPVAR) {
    1125       /* A B C  R(A) := uvget(B,C) */
    1126       int a = GETARG_A(i);
    1127       int b = GETARG_B(i);
    1128       int c = GETARG_C(i);
     1162    CASE(OP_SETMCNST, BB) {
     1163      mrb_const_set(mrb, regs[a+1], syms[b], regs[a]);
     1164      NEXT;
     1165    }
     1166
     1167    CASE(OP_GETUPVAR, BBB) {
    11291168      mrb_value *regs_a = regs + a;
    11301169      struct REnv *e = uvenv(mrb, c);
    11311170
    1132       if (!e) {
     1171      if (e && b < MRB_ENV_STACK_LEN(e)) {
     1172        *regs_a = e->stack[b];
     1173      }
     1174      else {
    11331175        *regs_a = mrb_nil_value();
    11341176      }
    1135       else {
    1136         *regs_a = e->stack[b];
    1137       }
    1138       NEXT;
    1139     }
    1140 
    1141     CASE(OP_SETUPVAR) {
    1142       /* A B C  uvset(B,C,R(A)) */
    1143       int a = GETARG_A(i);
    1144       int b = GETARG_B(i);
    1145       int c = GETARG_C(i);
    1146 
     1177      NEXT;
     1178    }
     1179
     1180    CASE(OP_SETUPVAR, BBB) {
    11471181      struct REnv *e = uvenv(mrb, c);
    11481182
     
    11581192    }
    11591193
    1160     CASE(OP_JMP) {
    1161       /* sBx    pc+=sBx */
    1162       int sbx = GETARG_sBx(i);
    1163       pc += sbx;
     1194    CASE(OP_JMP, S) {
     1195      pc = irep->iseq+a;
    11641196      JUMP;
    11651197    }
    1166 
    1167     CASE(OP_JMPIF) {
    1168       /* A sBx  if R(A) pc+=sBx */
    1169       int a = GETARG_A(i);
    1170       int sbx = GETARG_sBx(i);
     1198    CASE(OP_JMPIF, BS) {
    11711199      if (mrb_test(regs[a])) {
    1172         pc += sbx;
     1200        pc = irep->iseq+b;
    11731201        JUMP;
    11741202      }
    11751203      NEXT;
    11761204    }
    1177 
    1178     CASE(OP_JMPNOT) {
    1179       /* A sBx  if !R(A) pc+=sBx */
    1180       int a = GETARG_A(i);
    1181       int sbx = GETARG_sBx(i);
     1205    CASE(OP_JMPNOT, BS) {
    11821206      if (!mrb_test(regs[a])) {
    1183         pc += sbx;
     1207        pc = irep->iseq+b;
    11841208        JUMP;
    11851209      }
    11861210      NEXT;
    11871211    }
    1188 
    1189     CASE(OP_ONERR) {
    1190       /* sBx    pc+=sBx on exception */
    1191       int sbx = GETARG_sBx(i);
     1212    CASE(OP_JMPNIL, BS) {
     1213      if (mrb_nil_p(regs[a])) {
     1214        pc = irep->iseq+b;
     1215        JUMP;
     1216      }
     1217      NEXT;
     1218    }
     1219
     1220    CASE(OP_ONERR, S) {
     1221      /* check rescue stack */
     1222      if (mrb->c->ci->ridx == UINT16_MAX-1) {
     1223        mrb_value exc = mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "too many nested rescues");
     1224        mrb_exc_set(mrb, exc);
     1225        goto L_RAISE;
     1226      }
     1227      /* expand rescue stack */
    11921228      if (mrb->c->rsize <= mrb->c->ci->ridx) {
    11931229        if (mrb->c->rsize == 0) mrb->c->rsize = RESCUE_STACK_INIT_SIZE;
    1194         else mrb->c->rsize *= 2;
    1195         mrb->c->rescue = (mrb_code **)mrb_realloc(mrb, mrb->c->rescue, sizeof(mrb_code*) * mrb->c->rsize);
    1196       }
    1197       mrb->c->rescue[mrb->c->ci->ridx++] = pc + sbx;
    1198       NEXT;
    1199     }
    1200 
    1201     CASE(OP_RESCUE) {
    1202       /* A B    R(A) := exc; clear(exc); R(B) := matched (bool) */
    1203       int a = GETARG_A(i);
    1204       int b = GETARG_B(i);
    1205       int c = GETARG_C(i);
    1206       mrb_value exc;
    1207 
    1208       if (c == 0) {
    1209         exc = mrb_obj_value(mrb->exc);
    1210         mrb->exc = 0;
    1211       }
    1212       else {           /* continued; exc taken from R(A) */
    1213         exc = regs[a];
    1214       }
    1215       if (b != 0) {
    1216         mrb_value e = regs[b];
    1217         struct RClass *ec;
    1218 
    1219         switch (mrb_type(e)) {
    1220         case MRB_TT_CLASS:
    1221         case MRB_TT_MODULE:
    1222           break;
    1223         default:
    1224           {
    1225             mrb_value exc;
    1226 
    1227             exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR,
    1228                   "class or module required for rescue clause");
    1229             mrb_exc_set(mrb, exc);
    1230             goto L_RAISE;
    1231           }
    1232         }
    1233         ec = mrb_class_ptr(e);
    1234         regs[b] = mrb_bool_value(mrb_obj_is_kind_of(mrb, exc, ec));
    1235       }
    1236       if (a != 0 && c == 0) {
    1237         regs[a] = exc;
    1238       }
    1239       NEXT;
    1240     }
    1241 
    1242     CASE(OP_POPERR) {
    1243       /* A      A.times{rescue_pop()} */
    1244       int a = GETARG_A(i);
    1245 
    1246       while (a--) {
    1247         mrb->c->ci->ridx--;
    1248       }
    1249       NEXT;
    1250     }
    1251 
    1252     CASE(OP_RAISE) {
    1253       /* A      raise(R(A)) */
    1254       int a = GETARG_A(i);
    1255 
     1230        else {
     1231          mrb->c->rsize *= 2;
     1232          if (mrb->c->rsize <= mrb->c->ci->ridx) {
     1233            mrb->c->rsize = UINT16_MAX;
     1234          }
     1235        }
     1236        mrb->c->rescue = (uint16_t*)mrb_realloc(mrb, mrb->c->rescue, sizeof(uint16_t)*mrb->c->rsize);
     1237      }
     1238      /* push rescue stack */
     1239      mrb->c->rescue[mrb->c->ci->ridx++] = a;
     1240      NEXT;
     1241    }
     1242
     1243    CASE(OP_EXCEPT, B) {
     1244      mrb_value exc = mrb_obj_value(mrb->exc);
     1245      mrb->exc = 0;
     1246      regs[a] = exc;
     1247      NEXT;
     1248    }
     1249    CASE(OP_RESCUE, BB) {
     1250      mrb_value exc = regs[a];  /* exc on stack */
     1251      mrb_value e = regs[b];
     1252      struct RClass *ec;
     1253
     1254      switch (mrb_type(e)) {
     1255      case MRB_TT_CLASS:
     1256      case MRB_TT_MODULE:
     1257        break;
     1258      default:
     1259        {
     1260          mrb_value exc;
     1261
     1262          exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR,
     1263                                    "class or module required for rescue clause");
     1264          mrb_exc_set(mrb, exc);
     1265          goto L_RAISE;
     1266        }
     1267      }
     1268      ec = mrb_class_ptr(e);
     1269      regs[b] = mrb_bool_value(mrb_obj_is_kind_of(mrb, exc, ec));
     1270      NEXT;
     1271    }
     1272
     1273    CASE(OP_POPERR, B) {
     1274      mrb->c->ci->ridx -= a;
     1275      NEXT;
     1276    }
     1277
     1278    CASE(OP_RAISE, B) {
    12561279      mrb_exc_set(mrb, regs[a]);
    12571280      goto L_RAISE;
    12581281    }
    12591282
    1260     CASE(OP_EPUSH) {
    1261       /* Bx     ensure_push(SEQ[Bx]) */
    1262       int bx = GETARG_Bx(i);
     1283    CASE(OP_EPUSH, B) {
    12631284      struct RProc *p;
    12641285
    1265       p = mrb_closure_new(mrb, irep->reps[bx]);
    1266       /* push ensure_stack */
     1286      p = mrb_closure_new(mrb, irep->reps[a]);
     1287      /* check ensure stack */
     1288      if (mrb->c->eidx == UINT16_MAX-1) {
     1289        mrb_value exc = mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "too many nested ensures");
     1290        mrb_exc_set(mrb, exc);
     1291        goto L_RAISE;
     1292      }
     1293      /* expand ensure stack */
    12671294      if (mrb->c->esize <= mrb->c->eidx+1) {
    12681295        if (mrb->c->esize == 0) mrb->c->esize = ENSURE_STACK_INIT_SIZE;
    1269         else mrb->c->esize *= 2;
    1270         mrb->c->ensure = (struct RProc **)mrb_realloc(mrb, mrb->c->ensure, sizeof(struct RProc*) * mrb->c->esize);
    1271       }
     1296        else {
     1297          mrb->c->esize *= 2;
     1298          if (mrb->c->esize <= mrb->c->eidx) {
     1299            mrb->c->esize = UINT16_MAX;
     1300          }
     1301        }
     1302        mrb->c->ensure = (struct RProc**)mrb_realloc(mrb, mrb->c->ensure, sizeof(struct RProc*)*mrb->c->esize);
     1303      }
     1304      /* push ensure stack */
    12721305      mrb->c->ensure[mrb->c->eidx++] = p;
    12731306      mrb->c->ensure[mrb->c->eidx] = NULL;
    1274       ARENA_RESTORE(mrb, ai);
    1275       NEXT;
    1276     }
    1277 
    1278     CASE(OP_EPOP) {
    1279       /* A      A.times{ensure_pop().call} */
    1280       int a = GETARG_A(i);
     1307      mrb_gc_arena_restore(mrb, ai);
     1308      NEXT;
     1309    }
     1310
     1311    CASE(OP_EPOP, B) {
    12811312      mrb_callinfo *ci = mrb->c->ci;
    1282       int n, epos = ci->epos;
    1283 
    1284       for (n=0; n<a && mrb->c->eidx > epos; n++) {
    1285         ecall(mrb, --mrb->c->eidx);
    1286         ARENA_RESTORE(mrb, ai);
    1287       }
    1288       NEXT;
    1289     }
    1290 
    1291     CASE(OP_LOADNIL) {
    1292       /* A     R(A) := nil */
    1293       int a = GETARG_A(i);
    1294 
    1295       SET_NIL_VALUE(regs[a]);
    1296       NEXT;
    1297     }
    1298 
    1299     CASE(OP_SENDB) {
    1300       /* A B C  R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C),&R(A+C+1))*/
    1301       /* fall through */
     1313      unsigned int n, epos = ci->epos;
     1314      mrb_value self = regs[0];
     1315      struct RClass *target_class = ci->target_class;
     1316
     1317      if (mrb->c->eidx <= epos) {
     1318        NEXT;
     1319      }
     1320
     1321      if (a > (int)mrb->c->eidx - epos)
     1322        a = mrb->c->eidx - epos;
     1323      for (n=0; n<a; n++) {
     1324        int nregs = irep->nregs;
     1325
     1326        proc = mrb->c->ensure[epos+n];
     1327        mrb->c->ensure[epos+n] = NULL;
     1328        if (proc == NULL) continue;
     1329        irep = proc->body.irep;
     1330        ci = cipush(mrb);
     1331        ci->mid = ci[-1].mid;
     1332        ci->argc = 0;
     1333        ci->proc = proc;
     1334        ci->stackent = mrb->c->stack;
     1335        ci->target_class = target_class;
     1336        ci->pc = pc;
     1337        ci->acc = nregs;
     1338        mrb->c->stack += ci->acc;
     1339        mrb_stack_extend(mrb, irep->nregs);
     1340        regs[0] = self;
     1341        pc = irep->iseq;
     1342      }
     1343      pool = irep->pool;
     1344      syms = irep->syms;
     1345      mrb->c->eidx = epos;
     1346      JUMP;
     1347    }
     1348
     1349    CASE(OP_SENDV, BB) {
     1350      c = CALL_MAXARGS;
     1351      goto L_SEND;
    13021352    };
    13031353
    1304   L_SEND:
    1305     CASE(OP_SEND) {
    1306       /* A B C  R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C)) */
    1307       int a = GETARG_A(i);
    1308       int n = GETARG_C(i);
    1309       struct RProc *m;
    1310       struct RClass *c;
     1354    CASE(OP_SENDVB, BB) {
     1355      c = CALL_MAXARGS;
     1356      goto L_SENDB;
     1357    };
     1358
     1359    CASE(OP_SEND, BBB)
     1360    L_SEND:
     1361    {
     1362      /* push nil after arguments */
     1363      int bidx = (c == CALL_MAXARGS) ? a+2 : a+c+1;
     1364      SET_NIL_VALUE(regs[bidx]);
     1365      goto L_SENDB;
     1366    };
     1367    L_SEND_SYM:
     1368    {
     1369      /* push nil after arguments */
     1370      int bidx = (c == CALL_MAXARGS) ? a+2 : a+c+1;
     1371      SET_NIL_VALUE(regs[bidx]);
     1372      goto L_SENDB_SYM;
     1373    };
     1374
     1375    CASE(OP_SENDB, BBB)
     1376    L_SENDB:
     1377    mid = syms[b];
     1378    L_SENDB_SYM:
     1379    {
     1380      int argc = (c == CALL_MAXARGS) ? -1 : c;
     1381      int bidx = (argc < 0) ? a+2 : a+c+1;
     1382      mrb_method_t m;
     1383      struct RClass *cls;
    13111384      mrb_callinfo *ci = mrb->c->ci;
    1312       mrb_value recv, result;
    1313       mrb_sym mid = syms[GETARG_B(i)];
    1314       int bidx;
    1315       mrb_value blk;
     1385      mrb_value recv, blk;
     1386
     1387      mrb_assert(bidx < irep->nregs);
    13161388
    13171389      recv = regs[a];
    1318       if (n == CALL_MAXARGS) {
    1319         bidx = a+2;
    1320       }
    1321       else {
    1322         bidx = a+n+1;
    1323       }
    1324       if (GET_OPCODE(i) != OP_SENDB) {
    1325         if (bidx >= ci->nregs) {
    1326           stack_extend(mrb, bidx+1);
    1327           ci->nregs = bidx+1;
    1328         }
    1329         SET_NIL_VALUE(regs[bidx]);
    1330         blk = mrb_nil_value();
    1331       }
    1332       else {
    1333         blk = regs[bidx];
    1334         if (!mrb_nil_p(blk) && mrb_type(blk) != MRB_TT_PROC) {
    1335           if (bidx >= ci->nregs) {
    1336             stack_extend(mrb, bidx+1);
    1337             ci->nregs = bidx+1;
    1338           }
    1339           result = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc");
    1340           blk = regs[bidx] = result;
    1341         }
    1342       }
    1343       c = mrb_class(mrb, recv);
    1344       m = mrb_method_search_vm(mrb, &c, mid);
    1345       if (!m) {
    1346         mrb_value sym = mrb_symbol_value(mid);
     1390      blk = regs[bidx];
     1391      if (!mrb_nil_p(blk) && !mrb_proc_p(blk)) {
     1392        blk = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc");
     1393        /* The stack might have been reallocated during mrb_convert_type(),
     1394           see #3622 */
     1395        regs[bidx] = blk;
     1396      }
     1397      cls = mrb_class(mrb, recv);
     1398      m = mrb_method_search_vm(mrb, &cls, mid);
     1399      if (MRB_METHOD_UNDEF_P(m)) {
    13471400        mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
    1348 
    1349         m = mrb_method_search_vm(mrb, &c, missing);
    1350         if (!m) {
    1351           mrb_value args;
    1352 
    1353           if (n == CALL_MAXARGS) {
    1354             args = regs[a+1];
    1355           }
    1356           else {
    1357             args = mrb_ary_new_from_values(mrb, n, regs+a+1);
    1358           }
    1359           ERR_PC_SET(mrb, pc);
     1401        m = mrb_method_search_vm(mrb, &cls, missing);
     1402        if (MRB_METHOD_UNDEF_P(m) || (missing == mrb->c->ci->mid && mrb_obj_eq(mrb, regs[0], recv))) {
     1403          mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, c, regs+a+1);
     1404          ERR_PC_SET(mrb);
    13601405          mrb_method_missing(mrb, mid, recv, args);
    13611406        }
     1407        if (argc >= 0) {
     1408          if (a+2 >= irep->nregs) {
     1409            mrb_stack_extend(mrb, a+3);
     1410          }
     1411          regs[a+1] = mrb_ary_new_from_values(mrb, c, regs+a+1);
     1412          regs[a+2] = blk;
     1413          argc = -1;
     1414        }
     1415        mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(mid));
    13621416        mid = missing;
    1363         if (n != CALL_MAXARGS) {
    1364           if (a+2 >= irep->nregs) {
    1365             stack_extend(mrb, a+3);
    1366           }
    1367           regs[a+1] = mrb_ary_new_from_values(mrb, n, regs+a+1);
    1368           regs[a+2] = blk;
    1369           n = CALL_MAXARGS;
    1370         }
    1371         mrb_ary_unshift(mrb, regs[a+1], sym);
    13721417      }
    13731418
     
    13751420      ci = cipush(mrb);
    13761421      ci->mid = mid;
    1377       ci->proc = m;
    13781422      ci->stackent = mrb->c->stack;
    1379       ci->target_class = c;
    1380 
    1381       ci->pc = pc + 1;
     1423      ci->target_class = cls;
     1424      ci->argc = argc;
     1425
     1426      ci->pc = pc;
    13821427      ci->acc = a;
    13831428
     
    13851430      mrb->c->stack += a;
    13861431
    1387       if (MRB_PROC_CFUNC_P(m)) {
    1388         if (n == CALL_MAXARGS) {
    1389           ci->argc = -1;
    1390           ci->nregs = 3;
     1432      if (MRB_METHOD_CFUNC_P(m)) {
     1433        if (MRB_METHOD_PROC_P(m)) {
     1434          struct RProc *p = MRB_METHOD_PROC(m);
     1435
     1436          ci->proc = p;
     1437          recv = p->body.func(mrb, recv);
     1438        }
     1439        else if (MRB_METHOD_NOARG_P(m) &&
     1440                 (argc > 0 || (argc == -1 && RARRAY_LEN(regs[1]) != 0))) {
     1441          argnum_error(mrb, 0);
     1442          goto L_RAISE;
    13911443        }
    13921444        else {
    1393           ci->argc = n;
    1394           ci->nregs = n + 2;
    1395         }
    1396         result = m->body.func(mrb, recv);
     1445          recv = MRB_METHOD_FUNC(m)(mrb, recv);
     1446        }
    13971447        mrb_gc_arena_restore(mrb, ai);
     1448        mrb_gc_arena_shrink(mrb, ai);
    13981449        if (mrb->exc) goto L_RAISE;
    13991450        ci = mrb->c->ci;
    1400         if (GET_OPCODE(i) == OP_SENDB) {
    1401           if (mrb_type(blk) == MRB_TT_PROC) {
    1402             struct RProc *p = mrb_proc_ptr(blk);
    1403 
    1404             if (p && !MRB_PROC_STRICT_P(p) && p->env == ci[-1].env) {
    1405               p->flags |= MRB_PROC_ORPHAN;
    1406             }
     1451        if (mrb_proc_p(blk)) {
     1452          struct RProc *p = mrb_proc_ptr(blk);
     1453          if (p && !MRB_PROC_STRICT_P(p) && MRB_PROC_ENV(p) == ci[-1].env) {
     1454            p->flags |= MRB_PROC_ORPHAN;
    14071455          }
    14081456        }
     
    14101458          if (ci->acc == CI_ACC_RESUMED) {
    14111459            mrb->jmp = prev_jmp;
    1412             return result;
     1460            return recv;
    14131461          }
    14141462          else {
     
    14201468          }
    14211469        }
    1422         mrb->c->stack[0] = result;
     1470        mrb->c->stack[0] = recv;
    14231471        /* pop stackpos */
    14241472        mrb->c->stack = ci->stackent;
     
    14291477      else {
    14301478        /* setup environment for calling method */
    1431         proc = mrb->c->ci->proc = m;
    1432         irep = m->body.irep;
     1479        proc = ci->proc = MRB_METHOD_PROC(m);
     1480        irep = proc->body.irep;
    14331481        pool = irep->pool;
    14341482        syms = irep->syms;
    1435         ci->nregs = irep->nregs;
    1436         if (n == CALL_MAXARGS) {
    1437           ci->argc = -1;
    1438           stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs);
    1439         }
    1440         else {
    1441           ci->argc = n;
    1442           stack_extend(mrb, irep->nregs);
    1443         }
     1483        mrb_stack_extend(mrb, (argc < 0 && irep->nregs < 3) ? 3 : irep->nregs);
    14441484        pc = irep->iseq;
    14451485        JUMP;
     
    14471487    }
    14481488
    1449     CASE(OP_FSEND) {
    1450       /* A B C  R(A) := fcall(R(A),Syms(B),R(A+1),... ,R(A+C-1)) */
    1451       /* not implemented yet */
    1452       NEXT;
    1453     }
    1454 
    1455     CASE(OP_CALL) {
    1456       /* A      R(A) := self.call(frame.argc, frame.argv) */
     1489    CASE(OP_CALL, Z) {
    14571490      mrb_callinfo *ci;
    14581491      mrb_value recv = mrb->c->stack[0];
     
    14611494      /* replace callinfo */
    14621495      ci = mrb->c->ci;
    1463       ci->target_class = m->target_class;
     1496      ci->target_class = MRB_PROC_TARGET_CLASS(m);
    14641497      ci->proc = m;
    1465       if (m->env) {
    1466         mrb_sym mid;
    1467 
    1468         if (MRB_ENV_STACK_SHARED_P(m->env)) {
    1469           mid = m->env->cxt.c->cibase[m->env->cioff].mid;
    1470         }
    1471         else {
    1472           mid = m->env->cxt.mid;
    1473         }
    1474         if (mid) ci->mid = mid;
    1475         if (!m->env->stack) {
    1476           m->env->stack = mrb->c->stack;
     1498      if (MRB_PROC_ENV_P(m)) {
     1499        struct REnv *e = MRB_PROC_ENV(m);
     1500
     1501        ci->mid = e->mid;
     1502        if (!e->stack) {
     1503          e->stack = mrb->c->stack;
    14771504        }
    14781505      }
     
    14801507      /* prepare stack */
    14811508      if (MRB_PROC_CFUNC_P(m)) {
    1482         recv = m->body.func(mrb, recv);
     1509        recv = MRB_PROC_CFUNC(m)(mrb, recv);
    14831510        mrb_gc_arena_restore(mrb, ai);
     1511        mrb_gc_arena_shrink(mrb, ai);
    14841512        if (mrb->exc) goto L_RAISE;
    14851513        /* pop stackpos */
     
    15001528        if (!irep) {
    15011529          mrb->c->stack[0] = mrb_nil_value();
    1502           goto L_RETURN;
     1530          a = 0;
     1531          c = OP_R_NORMAL;
     1532          goto L_OP_RETURN_BODY;
    15031533        }
    15041534        pool = irep->pool;
    15051535        syms = irep->syms;
    1506         ci->nregs = irep->nregs;
    1507         stack_extend(mrb, irep->nregs);
     1536        mrb_stack_extend(mrb, irep->nregs);
    15081537        if (ci->argc < 0) {
    15091538          if (irep->nregs > 3) {
     
    15141543          stack_clear(regs+ci->argc+2, irep->nregs-ci->argc-2);
    15151544        }
    1516         if (m->env) {
    1517           regs[0] = m->env->stack[0];
     1545        if (MRB_PROC_ENV_P(m)) {
     1546          regs[0] = MRB_PROC_ENV(m)->stack[0];
    15181547        }
    15191548        pc = irep->iseq;
     
    15221551    }
    15231552
    1524     CASE(OP_SUPER) {
    1525       /* A C  R(A) := super(R(A+1),... ,R(A+C+1)) */
    1526       mrb_value recv;
     1553    CASE(OP_SUPER, BB) {
     1554      int argc = (b == CALL_MAXARGS) ? -1 : b;
     1555      int bidx = (argc < 0) ? a+2 : a+b+1;
     1556      mrb_method_t m;
     1557      struct RClass *cls;
    15271558      mrb_callinfo *ci = mrb->c->ci;
    1528       struct RProc *m;
    1529       struct RClass *c;
     1559      mrb_value recv, blk;
     1560      struct RProc *p = ci->proc;
    15301561      mrb_sym mid = ci->mid;
    1531       int a = GETARG_A(i);
    1532       int n = GETARG_C(i);
    1533       mrb_value blk;
    1534       int bidx;
    1535 
    1536       if (mid == 0 || !ci->target_class) {
    1537         mrb_value exc;
    1538 
    1539         exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method");
     1562      struct RClass* target_class = MRB_PROC_TARGET_CLASS(p);
     1563
     1564      if (MRB_PROC_ENV_P(p) && p->e.env->mid && p->e.env->mid != mid) { /* alias support */
     1565        mid = p->e.env->mid;    /* restore old mid */
     1566      }
     1567      mrb_assert(bidx < irep->nregs);
     1568
     1569      if (mid == 0 || !target_class) {
     1570        mrb_value exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method");
    15401571        mrb_exc_set(mrb, exc);
    15411572        goto L_RAISE;
    15421573      }
     1574      if (target_class->tt == MRB_TT_MODULE) {
     1575        target_class = ci->target_class;
     1576        if (target_class->tt != MRB_TT_ICLASS) {
     1577          mrb_value exc = mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "superclass info lost [mruby limitations]");
     1578          mrb_exc_set(mrb, exc);
     1579          goto L_RAISE;
     1580        }
     1581      }
    15431582      recv = regs[0];
    1544       c = mrb->c->ci->target_class->super;
    1545       m = mrb_method_search_vm(mrb, &c, mid);
    1546       if (!m) {
     1583      if (!mrb_obj_is_kind_of(mrb, recv, target_class)) {
     1584        mrb_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR,
     1585                                            "self has wrong type to call super in this context");
     1586        mrb_exc_set(mrb, exc);
     1587        goto L_RAISE;
     1588      }
     1589      blk = regs[bidx];
     1590      if (!mrb_nil_p(blk) && !mrb_proc_p(blk)) {
     1591        blk = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc");
     1592        /* The stack or ci stack might have been reallocated during
     1593           mrb_convert_type(), see #3622 and #3784 */
     1594        regs[bidx] = blk;
     1595        ci = mrb->c->ci;
     1596      }
     1597      cls = target_class->super;
     1598      m = mrb_method_search_vm(mrb, &cls, mid);
     1599      if (MRB_METHOD_UNDEF_P(m)) {
    15471600        mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
    1548         m = mrb_method_search_vm(mrb, &c, missing);
    1549         if (!m) {
    1550           mrb_value args;
    1551 
    1552           if (n == CALL_MAXARGS) {
    1553             args = regs[a+1];
    1554           }
    1555           else {
    1556             args = mrb_ary_new_from_values(mrb, n, regs+a+1);
    1557           }
    1558           ERR_PC_SET(mrb, pc);
     1601
     1602        if (mid != missing) {
     1603          cls = mrb_class(mrb, recv);
     1604        }
     1605        m = mrb_method_search_vm(mrb, &cls, missing);
     1606        if (MRB_METHOD_UNDEF_P(m)) {
     1607          mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, b, regs+a+1);
     1608          ERR_PC_SET(mrb);
    15591609          mrb_method_missing(mrb, mid, recv, args);
    15601610        }
    15611611        mid = missing;
    1562         if (n == CALL_MAXARGS-1) {
    1563           regs[a+1] = mrb_ary_new_from_values(mrb, n, regs+a+1);
    1564           n++;
    1565         }
    1566         if (n == CALL_MAXARGS) {
    1567           mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid));
    1568         }
    1569         else {
    1570           value_move(regs+a+2, regs+a+1, ++n);
    1571           SET_SYM_VALUE(regs[a+1], ci->mid);
    1572         }
    1573       }
    1574 
    1575       if (n == CALL_MAXARGS) {
    1576         bidx = a+2;
    1577       }
    1578       else {
    1579         bidx = a+n+1;
    1580       }
    1581       blk = regs[bidx];
    1582       if (!mrb_nil_p(blk) && mrb_type(blk) != MRB_TT_PROC) {
    1583         mrb_value result;
    1584 
    1585         if (bidx >= ci->nregs) {
    1586           stack_extend(mrb, bidx+1);
    1587           ci->nregs = bidx+1;
    1588         }
    1589         result = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc");
    1590         regs[bidx] = result;
     1612        if (argc >= 0) {
     1613          if (a+2 >= irep->nregs) {
     1614            mrb_stack_extend(mrb, a+3);
     1615          }
     1616          regs[a+1] = mrb_ary_new_from_values(mrb, b, regs+a+1);
     1617          regs[a+2] = blk;
     1618          argc = -1;
     1619        }
     1620        mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid));
    15911621      }
    15921622
     
    15941624      ci = cipush(mrb);
    15951625      ci->mid = mid;
    1596       ci->proc = m;
    15971626      ci->stackent = mrb->c->stack;
    1598       ci->target_class = c;
    1599       ci->pc = pc + 1;
    1600       if (n == CALL_MAXARGS) {
    1601         ci->argc = -1;
    1602       }
    1603       else {
    1604         ci->argc = n;
    1605       }
     1627      ci->target_class = cls;
     1628      ci->pc = pc;
     1629      ci->argc = argc;
    16061630
    16071631      /* prepare stack */
     
    16091633      mrb->c->stack[0] = recv;
    16101634
    1611       if (MRB_PROC_CFUNC_P(m)) {
     1635      if (MRB_METHOD_CFUNC_P(m)) {
    16121636        mrb_value v;
    16131637
    1614         if (n == CALL_MAXARGS) {
    1615           ci->nregs = 3;
    1616         }
    1617         else {
    1618           ci->nregs = n + 2;
    1619         }
    1620         v = m->body.func(mrb, recv);
     1638        if (MRB_METHOD_PROC_P(m)) {
     1639          ci->proc = MRB_METHOD_PROC(m);
     1640        }
     1641        v = MRB_METHOD_CFUNC(m)(mrb, recv);
    16211642        mrb_gc_arena_restore(mrb, ai);
    16221643        if (mrb->exc) goto L_RAISE;
     
    16471668
    16481669        /* setup environment for calling method */
    1649         ci->proc = m;
    1650         irep = m->body.irep;
     1670        proc = ci->proc = MRB_METHOD_PROC(m);
     1671        irep = proc->body.irep;
    16511672        pool = irep->pool;
    16521673        syms = irep->syms;
    1653         ci->nregs = irep->nregs;
    1654         if (n == CALL_MAXARGS) {
    1655           stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs);
    1656         }
    1657         else {
    1658           stack_extend(mrb, irep->nregs);
    1659         }
     1674        mrb_stack_extend(mrb, (argc < 0 && irep->nregs < 3) ? 3 : irep->nregs);
    16601675        pc = irep->iseq;
    16611676        JUMP;
     
    16631678    }
    16641679
    1665     CASE(OP_ARGARY) {
    1666       /* A Bx   R(A) := argument array (16=6:1:5:4) */
    1667       int a = GETARG_A(i);
    1668       int bx = GETARG_Bx(i);
    1669       int m1 = (bx>>10)&0x3f;
    1670       int r  = (bx>>9)&0x1;
    1671       int m2 = (bx>>4)&0x1f;
    1672       int lv = (bx>>0)&0xf;
     1680    CASE(OP_ARGARY, BS) {
     1681      int m1 = (b>>11)&0x3f;
     1682      int r  = (b>>10)&0x1;
     1683      int m2 = (b>>5)&0x1f;
     1684      int kd = (b>>4)&0x1;
     1685      int lv = (b>>0)&0xf;
    16731686      mrb_value *stack;
    16741687
     
    16851698        struct REnv *e = uvenv(mrb, lv-1);
    16861699        if (!e) goto L_NOSUPER;
     1700        if (MRB_ENV_STACK_LEN(e) <= m1+r+m2+kd+1)
     1701          goto L_NOSUPER;
    16871702        stack = e->stack + 1;
    16881703      }
    16891704      if (r == 0) {
    1690         regs[a] = mrb_ary_new_from_values(mrb, m1+m2, stack);
     1705        regs[a] = mrb_ary_new_from_values(mrb, m1+m2+kd, stack);
    16911706      }
    16921707      else {
     
    16981713          struct RArray *ary = mrb_ary_ptr(stack[m1]);
    16991714
    1700           pp = ary->ptr;
    1701           len = ary->len;
    1702         }
    1703         regs[a] = mrb_ary_new_capa(mrb, m1+len+m2);
     1715          pp = ARY_PTR(ary);
     1716          len = (int)ARY_LEN(ary);
     1717        }
     1718        regs[a] = mrb_ary_new_capa(mrb, m1+len+m2+kd);
    17041719        rest = mrb_ary_ptr(regs[a]);
    17051720        if (m1 > 0) {
    1706           stack_copy(rest->ptr, stack, m1);
     1721          stack_copy(ARY_PTR(rest), stack, m1);
    17071722        }
    17081723        if (len > 0) {
    1709           stack_copy(rest->ptr+m1, pp, len);
     1724          stack_copy(ARY_PTR(rest)+m1, pp, len);
    17101725        }
    17111726        if (m2 > 0) {
    1712           stack_copy(rest->ptr+m1+len, stack+m1+1, m2);
    1713         }
    1714         rest->len = m1+len+m2;
     1727          stack_copy(ARY_PTR(rest)+m1+len, stack+m1+1, m2);
     1728        }
     1729        if (kd) {
     1730          stack_copy(ARY_PTR(rest)+m1+len+m2, stack+m1+m2+1, kd);
     1731        }
     1732        ARY_SET_LEN(rest, m1+len+m2+kd);
    17151733      }
    17161734      regs[a+1] = stack[m1+r+m2];
    1717       ARENA_RESTORE(mrb, ai);
    1718       NEXT;
    1719     }
    1720 
    1721     CASE(OP_ENTER) {
    1722       /* Ax             arg setup according to flags (23=5:5:1:5:5:1:1) */
    1723       /* number of optional arguments times OP_JMP should follow */
    1724       mrb_aspec ax = GETARG_Ax(i);
    1725       int m1 = MRB_ASPEC_REQ(ax);
    1726       int o  = MRB_ASPEC_OPT(ax);
    1727       int r  = MRB_ASPEC_REST(ax);
    1728       int m2 = MRB_ASPEC_POST(ax);
     1735      mrb_gc_arena_restore(mrb, ai);
     1736      NEXT;
     1737    }
     1738
     1739    CASE(OP_ENTER, W) {
     1740      int m1 = MRB_ASPEC_REQ(a);
     1741      int o  = MRB_ASPEC_OPT(a);
     1742      int r  = MRB_ASPEC_REST(a);
     1743      int m2 = MRB_ASPEC_POST(a);
     1744      int kd = (MRB_ASPEC_KEY(a) > 0 || MRB_ASPEC_KDICT(a))? 1 : 0;
    17291745      /* unused
    1730       int k  = MRB_ASPEC_KEY(ax);
    1731       int kd = MRB_ASPEC_KDICT(ax);
    1732       int b  = MRB_ASPEC_BLOCK(ax);
     1746      int b  = MRB_ASPEC_BLOCK(a);
    17331747      */
    17341748      int argc = mrb->c->ci->argc;
    17351749      mrb_value *argv = regs+1;
    1736       mrb_value *argv0 = argv;
    1737       int len = m1 + o + r + m2;
     1750      mrb_value * const argv0 = argv;
     1751      int const len = m1 + o + r + m2;
     1752      int const blk_pos = len + kd + 1;
    17381753      mrb_value *blk = &argv[argc < 0 ? 1 : argc];
    1739 
     1754      mrb_value kdict;
     1755      int kargs = kd;
     1756
     1757      /* arguments is passed with Array */
    17401758      if (argc < 0) {
    17411759        struct RArray *ary = mrb_ary_ptr(regs[1]);
    1742         argv = ary->ptr;
    1743         argc = ary->len;
     1760        argv = ARY_PTR(ary);
     1761        argc = (int)ARY_LEN(ary);
    17441762        mrb_gc_protect(mrb, regs[1]);
    17451763      }
     1764
     1765      /* strict argument check */
    17461766      if (mrb->c->ci->proc && MRB_PROC_STRICT_P(mrb->c->ci->proc)) {
    1747         if (argc >= 0) {
    1748           if (argc < m1 + m2 || (r == 0 && argc > len)) {
     1767        if (argc < m1 + m2 || (r == 0 && argc > len + kd)) {
     1768          argnum_error(mrb, m1+m2);
     1769          goto L_RAISE;
     1770        }
     1771      }
     1772      /* extract first argument array to arguments */
     1773      else if (len > 1 && argc == 1 && mrb_array_p(argv[0])) {
     1774        mrb_gc_protect(mrb, argv[0]);
     1775        argc = (int)RARRAY_LEN(argv[0]);
     1776        argv = RARRAY_PTR(argv[0]);
     1777      }
     1778
     1779      if (kd) {
     1780        /* check last arguments is hash if method takes keyword arguments */
     1781        if (argc == m1+m2) {
     1782          kdict = mrb_hash_new(mrb);
     1783          kargs = 0;
     1784        }
     1785        else {
     1786          if (argv && argc > 0 && mrb_hash_p(argv[argc-1])) {
     1787            kdict = argv[argc-1];
     1788            mrb_hash_check_kdict(mrb, kdict);
     1789          }
     1790          else if (r || argc <= m1+m2+o
     1791                   || !(mrb->c->ci->proc && MRB_PROC_STRICT_P(mrb->c->ci->proc))) {
     1792            kdict = mrb_hash_new(mrb);
     1793            kargs = 0;
     1794          }
     1795          else {
    17491796            argnum_error(mrb, m1+m2);
    17501797            goto L_RAISE;
    17511798          }
    1752         }
    1753       }
    1754       else if (len > 1 && argc == 1 && mrb_array_p(argv[0])) {
    1755         mrb_gc_protect(mrb, argv[0]);
    1756         argc = mrb_ary_ptr(argv[0])->len;
    1757         argv = mrb_ary_ptr(argv[0])->ptr;
    1758       }
    1759       if (argc < len) {
     1799          if (MRB_ASPEC_KEY(a) > 0) {
     1800            kdict = mrb_hash_dup(mrb, kdict);
     1801          }
     1802        }
     1803      }
     1804
     1805      /* no rest arguments */
     1806      if (argc-kargs < len) {
    17601807        int mlen = m2;
    17611808        if (argc < m1+m2) {
    1762           if (m1 < argc)
    1763             mlen = argc - m1;
    1764           else
    1765             mlen = 0;
    1766         }
    1767         regs[len+1] = *blk; /* move block */
    1768         SET_NIL_VALUE(regs[argc+1]);
     1809          mlen = m1 < argc ? argc - m1 : 0;
     1810        }
     1811        regs[blk_pos] = *blk; /* move block */
     1812        if (kd) regs[len + 1] = kdict;
     1813
     1814        /* copy mandatory and optional arguments */
    17691815        if (argv0 != argv) {
    17701816          value_move(&regs[1], argv, argc-mlen); /* m1 + o */
     
    17731819          stack_clear(&regs[argc+1], m1-argc);
    17741820        }
     1821        /* copy post mandatory arguments */
    17751822        if (mlen) {
    17761823          value_move(&regs[len-m2+1], &argv[argc-mlen], mlen);
     
    17791826          stack_clear(&regs[len-m2+mlen+1], m2-mlen);
    17801827        }
     1828        /* initalize rest arguments with empty Array */
    17811829        if (r) {
    17821830          regs[m1+o+1] = mrb_ary_new_capa(mrb, 0);
    17831831        }
    1784         if (o == 0 || argc < m1+m2) pc++;
    1785         else
    1786           pc += argc - m1 - m2 + 1;
     1832        /* skip initailizer of passed arguments */
     1833        if (o > 0 && argc-kargs > m1+m2)
     1834          pc += (argc - kargs - m1 - m2)*3;
    17871835      }
    17881836      else {
    17891837        int rnum = 0;
    17901838        if (argv0 != argv) {
    1791           regs[len+1] = *blk; /* move block */
     1839          regs[blk_pos] = *blk; /* move block */
     1840          if (kd) regs[len + 1] = kdict;
    17921841          value_move(&regs[1], argv, m1+o);
    17931842        }
    17941843        if (r) {
    1795           rnum = argc-m1-o-m2;
    1796           regs[m1+o+1] = mrb_ary_new_from_values(mrb, rnum, argv+m1+o);
     1844          mrb_value ary;
     1845
     1846          rnum = argc-m1-o-m2-kargs;
     1847          ary = mrb_ary_new_from_values(mrb, rnum, argv+m1+o);
     1848          regs[m1+o+1] = ary;
    17971849        }
    17981850        if (m2) {
     
    18021854        }
    18031855        if (argv0 == argv) {
    1804           regs[len+1] = *blk; /* move block */
    1805         }
    1806         pc += o + 1;
    1807       }
    1808       mrb->c->ci->argc = len;
     1856          regs[blk_pos] = *blk; /* move block */
     1857          if (kd) regs[len + 1] = kdict;
     1858        }
     1859        pc += o*3;
     1860      }
     1861
     1862      /* format arguments for generated code */
     1863      mrb->c->ci->argc = len + kd;
     1864
    18091865      /* clear local (but non-argument) variables */
    1810       if (irep->nlocals-len-2 > 0) {
    1811         stack_clear(&regs[len+2], irep->nlocals-len-2);
     1866      if (irep->nlocals-blk_pos-1 > 0) {
     1867        stack_clear(&regs[blk_pos+1], irep->nlocals-blk_pos-1);
    18121868      }
    18131869      JUMP;
    18141870    }
    18151871
    1816     CASE(OP_KARG) {
    1817       /* A B C          R(A) := kdict[Syms(B)]; if C kdict.rm(Syms(B)) */
    1818       /* if C == 2; raise unless kdict.empty? */
    1819       /* OP_JMP should follow to skip init code */
    1820       NEXT;
    1821     }
    1822 
    1823     CASE(OP_KDICT) {
    1824       /* A C            R(A) := kdict */
    1825       NEXT;
    1826     }
    1827 
     1872    CASE(OP_KARG, BB) {
     1873      mrb_value k = mrb_symbol_value(syms[b]);
     1874      mrb_value kdict = regs[mrb->c->ci->argc];
     1875
     1876      if (!mrb_hash_p(kdict) || !mrb_hash_key_p(mrb, kdict, k)) {
     1877        mrb_value str = mrb_format(mrb, "missing keyword: %v", k);
     1878        mrb_exc_set(mrb, mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str));
     1879        goto L_RAISE;
     1880      }
     1881      regs[a] = mrb_hash_get(mrb, kdict, k);
     1882      mrb_hash_delete_key(mrb, kdict, k);
     1883      NEXT;
     1884    }
     1885
     1886    CASE(OP_KEY_P, BB) {
     1887      mrb_value k = mrb_symbol_value(syms[b]);
     1888      mrb_value kdict = regs[mrb->c->ci->argc];
     1889      mrb_bool key_p = FALSE;
     1890
     1891      if (mrb_hash_p(kdict)) {
     1892        key_p = mrb_hash_key_p(mrb, kdict, k);
     1893      }
     1894      regs[a] = mrb_bool_value(key_p);
     1895      NEXT;
     1896    }
     1897
     1898    CASE(OP_KEYEND, Z) {
     1899      mrb_value kdict = regs[mrb->c->ci->argc];
     1900
     1901      if (mrb_hash_p(kdict) && !mrb_hash_empty_p(mrb, kdict)) {
     1902        mrb_value keys = mrb_hash_keys(mrb, kdict);
     1903        mrb_value key1 = RARRAY_PTR(keys)[0];
     1904        mrb_value str = mrb_format(mrb, "unknown keyword: %v", key1);
     1905        mrb_exc_set(mrb, mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str));
     1906        goto L_RAISE;
     1907      }
     1908      NEXT;
     1909    }
     1910
     1911    CASE(OP_BREAK, B) {
     1912      c = OP_R_BREAK;
     1913      goto L_RETURN;
     1914    }
     1915    CASE(OP_RETURN_BLK, B) {
     1916      c = OP_R_RETURN;
     1917      goto L_RETURN;
     1918    }
     1919    CASE(OP_RETURN, B)
     1920    c = OP_R_NORMAL;
    18281921    L_RETURN:
    1829       i = MKOP_AB(OP_RETURN, GETARG_A(i), OP_R_NORMAL);
    1830       /* fall through */
    1831     CASE(OP_RETURN) {
    1832       /* A B     return R(A) (B=normal,in-block return/break) */
    1833       mrb_callinfo *ci;
     1922    {
     1923       mrb_callinfo *ci;
     1924
     1925#define ecall_adjust() do {\
     1926  ptrdiff_t cioff = ci - mrb->c->cibase;\
     1927  ecall(mrb);\
     1928  ci = mrb->c->cibase + cioff;\
     1929} while (0)
    18341930
    18351931      ci = mrb->c->ci;
     
    18431939          blk = regs[ci->argc+1];
    18441940        }
    1845         if (mrb_type(blk) == MRB_TT_PROC) {
     1941        if (mrb_proc_p(blk)) {
    18461942          struct RProc *p = mrb_proc_ptr(blk);
    18471943
    1848           if (!MRB_PROC_STRICT_P(proc) &&
    1849               ci > mrb->c->cibase && p->env == ci[-1].env) {
     1944          if (!MRB_PROC_STRICT_P(p) &&
     1945              ci > mrb->c->cibase && MRB_PROC_ENV(p) == ci[-1].env) {
    18501946            p->flags |= MRB_PROC_ORPHAN;
    18511947          }
     
    18551951      if (mrb->exc) {
    18561952        mrb_callinfo *ci0;
    1857         mrb_value *stk;
    18581953
    18591954      L_RAISE:
     
    18631958          goto L_RESCUE;
    18641959        }
    1865         stk = mrb->c->stack;
    18661960        while (ci[0].ridx == ci[-1].ridx) {
    18671961          cipop(mrb);
     
    18731967          ci = mrb->c->ci;
    18741968          if (ci == mrb->c->cibase) {
    1875             mrb->c->stack = stk;
    18761969            if (ci->ridx == 0) {
    18771970            L_FTOP:             /* fiber top */
     
    18831976                struct mrb_context *c = mrb->c;
    18841977
    1885                 if (c->fib) {
    1886                   mrb_write_barrier(mrb, (struct RBasic*)c->fib);
     1978                while (c->eidx > ci->epos) {
     1979                  ecall_adjust();
    18871980                }
     1981                c->status = MRB_FIBER_TERMINATED;
    18881982                mrb->c = c->prev;
    18891983                c->prev = NULL;
     
    18961990          if (ci[0].ridx == ci[-1].ridx) {
    18971991            while (mrb->c->eidx > ci->epos) {
    1898               ecall(mrb, --mrb->c->eidx);
    1899               ci = mrb->c->ci;
     1992              ecall_adjust();
    19001993            }
    19011994          }
     
    19072000        pool = irep->pool;
    19082001        syms = irep->syms;
    1909         if (ci != ci0) {
     2002        if (ci < ci0) {
    19102003          mrb->c->stack = ci[1].stackent;
    19112004        }
    1912         stack_extend(mrb, irep->nregs);
    1913         pc = mrb->c->rescue[--ci->ridx];
     2005        mrb_stack_extend(mrb, irep->nregs);
     2006        pc = irep->iseq+mrb->c->rescue[--ci->ridx];
    19142007      }
    19152008      else {
    19162009        int acc;
    19172010        mrb_value v;
    1918 
    1919         v = regs[GETARG_A(i)];
     2011        struct RProc *dst;
     2012
     2013        ci = mrb->c->ci;
     2014        v = regs[a];
    19202015        mrb_gc_protect(mrb, v);
    1921         switch (GETARG_B(i)) {
     2016        switch (c) {
    19222017        case OP_R_RETURN:
    19232018          /* Fall through to OP_R_NORMAL otherwise */
    1924           if (ci->acc >=0 && proc->env && !MRB_PROC_STRICT_P(proc)) {
    1925             struct REnv *e = top_env(mrb, proc);
    1926             mrb_callinfo *ce;
    1927 
    1928             if (!MRB_ENV_STACK_SHARED_P(e) || e->cxt.c != mrb->c) {
    1929               localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
    1930               goto L_RAISE;
     2019          if (ci->acc >=0 && MRB_PROC_ENV_P(proc) && !MRB_PROC_STRICT_P(proc)) {
     2020            mrb_callinfo *cibase = mrb->c->cibase;
     2021            dst = top_proc(mrb, proc);
     2022
     2023            if (MRB_PROC_ENV_P(dst)) {
     2024              struct REnv *e = MRB_PROC_ENV(dst);
     2025
     2026              if (!MRB_ENV_STACK_SHARED_P(e) || (e->cxt && e->cxt != mrb->c)) {
     2027                localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
     2028                goto L_RAISE;
     2029              }
    19312030            }
    1932            
    1933             ce = mrb->c->cibase + e->cioff;
    1934             while (ci >= ce) {
    1935               if (ci->env) {
    1936                 mrb_env_unshare(mrb, ci->env);
    1937               }
     2031            while (cibase <= ci && ci->proc != dst) {
    19382032              if (ci->acc < 0) {
    19392033                localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
     
    19422036              ci--;
    19432037            }
    1944             if (ce == mrb->c->cibase) {
     2038            if (ci <= cibase) {
    19452039              localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
    19462040              goto L_RAISE;
    19472041            }
    1948             mrb->c->stack = mrb->c->ci->stackent;
    1949             mrb->c->ci = ce;
    19502042            break;
    19512043          }
     2044          /* fallthrough */
    19522045        case OP_R_NORMAL:
    19532046        NORMAL_RETURN:
    19542047          if (ci == mrb->c->cibase) {
    1955             if (!mrb->c->prev) { /* toplevel return */
    1956               localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
    1957               goto L_RAISE;
     2048            struct mrb_context *c = mrb->c;
     2049
     2050            if (!c->prev) { /* toplevel return */
     2051              regs[irep->nlocals] = v;
     2052              goto L_STOP;
    19582053            }
    1959             if (mrb->c->prev->ci == mrb->c->prev->cibase) {
     2054            if (c->prev->ci == c->prev->cibase) {
    19602055              mrb_value exc = mrb_exc_new_str_lit(mrb, E_FIBER_ERROR, "double resume");
    19612056              mrb_exc_set(mrb, exc);
    19622057              goto L_RAISE;
    19632058            }
    1964             while (mrb->c->eidx > 0) {
    1965               ecall(mrb, --mrb->c->eidx);
     2059            while (c->eidx > 0) {
     2060              ecall(mrb);
    19662061            }
    19672062            /* automatic yield at the end */
    1968             mrb->c->status = MRB_FIBER_TERMINATED;
    1969             mrb->c = mrb->c->prev;
     2063            c->status = MRB_FIBER_TERMINATED;
     2064            mrb->c = c->prev;
     2065            c->prev = NULL;
    19702066            mrb->c->status = MRB_FIBER_RUNNING;
    1971           }
    1972           ci = mrb->c->ci;
     2067            ci = mrb->c->ci;
     2068          }
    19732069          break;
    19742070        case OP_R_BREAK:
    19752071          if (MRB_PROC_STRICT_P(proc)) goto NORMAL_RETURN;
    1976           if (MRB_PROC_ORPHAN_P(proc)) { 
     2072          if (MRB_PROC_ORPHAN_P(proc)) {
    19772073            mrb_value exc;
    19782074
     
    19832079            goto L_RAISE;
    19842080          }
    1985           if (!proc->env || !MRB_ENV_STACK_SHARED_P(proc->env)) {
     2081          if (!MRB_PROC_ENV_P(proc) || !MRB_ENV_STACK_SHARED_P(MRB_PROC_ENV(proc))) {
    19862082            goto L_BREAK_ERROR;
    19872083          }
     2084          else {
     2085            struct REnv *e = MRB_PROC_ENV(proc);
     2086
     2087            if (e->cxt != mrb->c) {
     2088              goto L_BREAK_ERROR;
     2089            }
     2090          }
     2091          while (mrb->c->eidx > mrb->c->ci->epos) {
     2092            ecall_adjust();
     2093          }
    19882094          /* break from fiber block */
    1989           if (mrb->c->ci == mrb->c->cibase && mrb->c->ci->pc) {
     2095          if (ci == mrb->c->cibase && ci->pc) {
    19902096            struct mrb_context *c = mrb->c;
    19912097
    1992             while (mrb->c->eidx > 0) {
    1993               ecall(mrb, --mrb->c->eidx);
    1994             }
    19952098            mrb->c = c->prev;
    19962099            c->prev = NULL;
     
    19982101          }
    19992102          if (ci->acc < 0) {
    2000             while (mrb->c->eidx > mrb->c->ci->epos) {
    2001               ecall(mrb, --mrb->c->eidx);
    2002             }
    2003             ARENA_RESTORE(mrb, ai);
     2103            mrb_gc_arena_restore(mrb, ai);
    20042104            mrb->c->vmexec = FALSE;
    20052105            mrb->exc = (struct RObject*)break_new(mrb, proc, v);
     
    20092109          if (FALSE) {
    20102110          L_BREAK:
    2011             v = ((struct RBreak*)mrb->exc)->val;
    2012             proc = ((struct RBreak*)mrb->exc)->proc;
     2111            v = mrb_break_value_get((struct RBreak*)mrb->exc);
     2112            proc = mrb_break_proc_get((struct RBreak*)mrb->exc);
    20132113            mrb->exc = NULL;
    20142114            ci = mrb->c->ci;
    20152115          }
    20162116          mrb->c->stack = ci->stackent;
    2017           mrb->c->ci = mrb->c->cibase + proc->env->cioff + 1;
    2018           while (ci > mrb->c->ci) {
    2019             if (ci->env) {
    2020               mrb_env_unshare(mrb, ci->env);
    2021             }
     2117          proc = proc->upper;
     2118          while (mrb->c->cibase < ci &&  ci[-1].proc != proc) {
    20222119            if (ci[-1].acc == CI_ACC_SKIP) {
    2023               mrb->c->ci = ci;
     2120              while (ci < mrb->c->ci) {
     2121                cipop(mrb);
     2122              }
    20242123              goto L_BREAK_ERROR;
    20252124            }
    20262125            ci--;
     2126          }
     2127          if (ci == mrb->c->cibase) {
     2128            goto L_BREAK_ERROR;
    20272129          }
    20282130          break;
     
    20312133          break;
    20322134        }
    2033         while (mrb->c->eidx > mrb->c->ci->epos) {
    2034           ecall(mrb, --mrb->c->eidx);
    2035         }
    2036         if (mrb->c->vmexec && !mrb->c->ci->target_class) {
    2037           ARENA_RESTORE(mrb, ai);
     2135        while (ci < mrb->c->ci) {
     2136          cipop(mrb);
     2137        }
     2138        ci[0].ridx = ci[-1].ridx;
     2139        while (mrb->c->eidx > ci->epos) {
     2140          ecall_adjust();
     2141        }
     2142        if (mrb->c->vmexec && !ci->target_class) {
     2143          mrb_gc_arena_restore(mrb, ai);
    20382144          mrb->c->vmexec = FALSE;
    20392145          mrb->jmp = prev_jmp;
    20402146          return v;
    20412147        }
    2042         ci = mrb->c->ci;
    20432148        acc = ci->acc;
    20442149        mrb->c->stack = ci->stackent;
    20452150        cipop(mrb);
    20462151        if (acc == CI_ACC_SKIP || acc == CI_ACC_DIRECT) {
    2047           ARENA_RESTORE(mrb, ai);
     2152          mrb_gc_arena_restore(mrb, ai);
    20482153          mrb->jmp = prev_jmp;
    20492154          return v;
    20502155        }
    20512156        pc = ci->pc;
    2052         DEBUG(fprintf(stderr, "from :%s\n", mrb_sym2name(mrb, ci->mid)));
     2157        ci = mrb->c->ci;
     2158        DEBUG(fprintf(stderr, "from :%s\n", mrb_sym_name(mrb, ci->mid)));
    20532159        proc = mrb->c->ci->proc;
    20542160        irep = proc->body.irep;
     
    20572163
    20582164        regs[acc] = v;
    2059         ARENA_RESTORE(mrb, ai);
     2165        mrb_gc_arena_restore(mrb, ai);
    20602166      }
    20612167      JUMP;
    20622168    }
    20632169
    2064     CASE(OP_TAILCALL) {
    2065       /* A B C  return call(R(A),Syms(B),R(A+1),... ,R(A+C+1)) */
    2066       int a = GETARG_A(i);
    2067       int n = GETARG_C(i);
    2068       struct RProc *m;
    2069       struct RClass *c;
    2070       mrb_callinfo *ci;
    2071       mrb_value recv;
    2072       mrb_sym mid = syms[GETARG_B(i)];
    2073 
    2074       recv = regs[a];
    2075       c = mrb_class(mrb, recv);
    2076       m = mrb_method_search_vm(mrb, &c, mid);
    2077       if (!m) {
    2078         mrb_value sym = mrb_symbol_value(mid);
    2079         mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
    2080         m = mrb_method_search_vm(mrb, &c, missing);
    2081         if (!m) {
    2082           mrb_value args;
    2083 
    2084           if (n == CALL_MAXARGS) {
    2085             args = regs[a+1];
    2086           }
    2087           else {
    2088             args = mrb_ary_new_from_values(mrb, n, regs+a+1);
    2089           }
    2090           ERR_PC_SET(mrb, pc);
    2091           mrb_method_missing(mrb, mid, recv, args);
    2092         }
    2093         mid = missing;
    2094         if (n == CALL_MAXARGS) {
    2095           mrb_ary_unshift(mrb, regs[a+1], sym);
    2096         }
    2097         else {
    2098           value_move(regs+a+2, regs+a+1, ++n);
    2099           regs[a+1] = sym;
    2100         }
    2101       }
    2102 
    2103       /* replace callinfo */
    2104       ci = mrb->c->ci;
    2105       ci->mid = mid;
    2106       ci->target_class = c;
    2107       if (n == CALL_MAXARGS) {
    2108         ci->argc = -1;
    2109       }
    2110       else {
    2111         ci->argc = n;
    2112       }
    2113 
    2114       /* move stack */
    2115       value_move(mrb->c->stack, &regs[a], ci->argc+1);
    2116 
    2117       if (MRB_PROC_CFUNC_P(m)) {
    2118         mrb_value v = m->body.func(mrb, recv);
    2119         mrb->c->stack[0] = v;
    2120         mrb_gc_arena_restore(mrb, ai);
    2121         goto L_RETURN;
    2122       }
    2123       else {
    2124         /* setup environment for calling method */
    2125         irep = m->body.irep;
    2126         pool = irep->pool;
    2127         syms = irep->syms;
    2128         if (ci->argc < 0) {
    2129           stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs);
    2130         }
    2131         else {
    2132           stack_extend(mrb, irep->nregs);
    2133         }
    2134         pc = irep->iseq;
    2135       }
    2136       JUMP;
    2137     }
    2138 
    2139     CASE(OP_BLKPUSH) {
    2140       /* A Bx   R(A) := block (16=6:1:5:4) */
    2141       int a = GETARG_A(i);
    2142       int bx = GETARG_Bx(i);
    2143       int m1 = (bx>>10)&0x3f;
    2144       int r  = (bx>>9)&0x1;
    2145       int m2 = (bx>>4)&0x1f;
    2146       int lv = (bx>>0)&0xf;
     2170    CASE(OP_BLKPUSH, BS) {
     2171      int m1 = (b>>11)&0x3f;
     2172      int r  = (b>>10)&0x1;
     2173      int m2 = (b>>5)&0x1f;
     2174      int kd = (b>>4)&0x1;
     2175      int lv = (b>>0)&0xf;
    21472176      mrb_value *stack;
    21482177
     
    21502179      else {
    21512180        struct REnv *e = uvenv(mrb, lv-1);
    2152         if (!e || e->cioff == 0 ||
    2153             (!MRB_ENV_STACK_SHARED_P(e) && e->cxt.mid == 0)) {
     2181        if (!e || (!MRB_ENV_STACK_SHARED_P(e) && e->mid == 0) ||
     2182            MRB_ENV_STACK_LEN(e) <= m1+r+m2+1) {
    21542183          localjump_error(mrb, LOCALJUMP_ERROR_YIELD);
    21552184          goto L_RAISE;
     
    21612190        goto L_RAISE;
    21622191      }
    2163       regs[a] = stack[m1+r+m2];
     2192      regs[a] = stack[m1+r+m2+kd];
    21642193      NEXT;
    21652194    }
    21662195
    21672196#define TYPES2(a,b) ((((uint16_t)(a))<<8)|(((uint16_t)(b))&0xff))
    2168 #define OP_MATH_BODY(op,v1,v2) do {\
    2169   v1(regs[a]) = v1(regs[a]) op v2(regs[a+1]);\
    2170 } while(0)
    2171 
    2172     CASE(OP_ADD) {
    2173       /* A B C  R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1)*/
    2174       int a = GETARG_A(i);
     2197#define OP_MATH(op_name)                                                    \
     2198  /* need to check if op is overridden */                                   \
     2199  switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {                  \
     2200    OP_MATH_CASE_FIXNUM(op_name);                                           \
     2201    OP_MATH_CASE_FLOAT(op_name, fixnum, float);                             \
     2202    OP_MATH_CASE_FLOAT(op_name, float,  fixnum);                            \
     2203    OP_MATH_CASE_FLOAT(op_name, float,  float);                             \
     2204    OP_MATH_CASE_STRING_##op_name();                                        \
     2205    default:                                                                \
     2206      c = 1;                                                                \
     2207      mid = mrb_intern_lit(mrb, MRB_STRINGIZE(OP_MATH_OP_##op_name));       \
     2208      goto L_SEND_SYM;                                                      \
     2209  }                                                                         \
     2210  NEXT;
     2211#define OP_MATH_CASE_FIXNUM(op_name)                                        \
     2212  case TYPES2(MRB_TT_FIXNUM, MRB_TT_FIXNUM):                                \
     2213    {                                                                       \
     2214      mrb_int x = mrb_fixnum(regs[a]), y = mrb_fixnum(regs[a+1]), z;        \
     2215      if (mrb_int_##op_name##_overflow(x, y, &z))                           \
     2216        OP_MATH_OVERFLOW_INT(op_name, x, y, z);                             \
     2217      else                                                                  \
     2218        SET_INT_VALUE(regs[a], z);                                          \
     2219    }                                                                       \
     2220    break
     2221#ifdef MRB_WITHOUT_FLOAT
     2222#define OP_MATH_CASE_FLOAT(op_name, t1, t2) (void)0
     2223#define OP_MATH_OVERFLOW_INT(op_name, x, y, z) SET_INT_VALUE(regs[a], z)
     2224#else
     2225#define OP_MATH_CASE_FLOAT(op_name, t1, t2)                                     \
     2226  case TYPES2(OP_MATH_TT_##t1, OP_MATH_TT_##t2):                                \
     2227    {                                                                           \
     2228      mrb_float z = mrb_##t1(regs[a]) OP_MATH_OP_##op_name mrb_##t2(regs[a+1]); \
     2229      SET_FLOAT_VALUE(mrb, regs[a], z);                                         \
     2230    }                                                                           \
     2231    break
     2232#define OP_MATH_OVERFLOW_INT(op_name, x, y, z) \
     2233  SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x OP_MATH_OP_##op_name (mrb_float)y)
     2234#endif
     2235#define OP_MATH_CASE_STRING_add()                                           \
     2236  case TYPES2(MRB_TT_STRING, MRB_TT_STRING):                                \
     2237    regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]);                        \
     2238    mrb_gc_arena_restore(mrb, ai);                                          \
     2239    break
     2240#define OP_MATH_CASE_STRING_sub() (void)0
     2241#define OP_MATH_CASE_STRING_mul() (void)0
     2242#define OP_MATH_OP_add +
     2243#define OP_MATH_OP_sub -
     2244#define OP_MATH_OP_mul *
     2245#define OP_MATH_TT_fixnum MRB_TT_FIXNUM
     2246#define OP_MATH_TT_float  MRB_TT_FLOAT
     2247
     2248    CASE(OP_ADD, B) {
     2249      OP_MATH(add);
     2250    }
     2251
     2252    CASE(OP_SUB, B) {
     2253      OP_MATH(sub);
     2254    }
     2255
     2256    CASE(OP_MUL, B) {
     2257      OP_MATH(mul);
     2258    }
     2259
     2260    CASE(OP_DIV, B) {
     2261#ifndef MRB_WITHOUT_FLOAT
     2262      double x, y, f;
     2263#endif
    21752264
    21762265      /* need to check if op is overridden */
    21772266      switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
    21782267      case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
    2179         {
    2180           mrb_int x, y, z;
    2181           mrb_value *regs_a = regs + a;
    2182 
    2183           x = mrb_fixnum(regs_a[0]);
    2184           y = mrb_fixnum(regs_a[1]);
    2185           if (mrb_int_add_overflow(x, y, &z)) {
    2186             SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x + (mrb_float)y);
    2187             break;
    2188           }
    2189           SET_INT_VALUE(regs[a], z);
    2190         }
    2191         break;
    2192       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
    2193         {
    2194           mrb_int x = mrb_fixnum(regs[a]);
    2195           mrb_float y = mrb_float(regs[a+1]);
    2196           SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + y);
    2197         }
    2198         break;
    2199       case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
    2200 #ifdef MRB_WORD_BOXING
    2201         {
    2202           mrb_float x = mrb_float(regs[a]);
    2203           mrb_int y = mrb_fixnum(regs[a+1]);
    2204           SET_FLOAT_VALUE(mrb, regs[a], x + y);
    2205         }
    2206 #else
    2207         OP_MATH_BODY(+,mrb_float,mrb_fixnum);
    2208 #endif
    2209         break;
    2210       case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
    2211 #ifdef MRB_WORD_BOXING
    2212         {
    2213           mrb_float x = mrb_float(regs[a]);
    2214           mrb_float y = mrb_float(regs[a+1]);
    2215           SET_FLOAT_VALUE(mrb, regs[a], x + y);
    2216         }
    2217 #else
    2218         OP_MATH_BODY(+,mrb_float,mrb_float);
    2219 #endif
    2220         break;
    2221       case TYPES2(MRB_TT_STRING,MRB_TT_STRING):
    2222         regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]);
    2223         break;
    2224       default:
    2225         goto L_SEND;
    2226       }
    2227       ARENA_RESTORE(mrb, ai);
    2228       NEXT;
    2229     }
    2230 
    2231     CASE(OP_SUB) {
    2232       /* A B C  R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1)*/
    2233       int a = GETARG_A(i);
    2234 
    2235       /* need to check if op is overridden */
    2236       switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
    2237       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
    2238         {
    2239           mrb_int x, y, z;
    2240 
    2241           x = mrb_fixnum(regs[a]);
    2242           y = mrb_fixnum(regs[a+1]);
    2243           if (mrb_int_sub_overflow(x, y, &z)) {
    2244             SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - (mrb_float)y);
    2245             break;
    2246           }
    2247           SET_INT_VALUE(regs[a], z);
    2248         }
    2249         break;
    2250       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
    2251         {
    2252           mrb_int x = mrb_fixnum(regs[a]);
    2253           mrb_float y = mrb_float(regs[a+1]);
    2254           SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - y);
    2255         }
    2256         break;
    2257       case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
    2258 #ifdef MRB_WORD_BOXING
    2259         {
    2260           mrb_float x = mrb_float(regs[a]);
    2261           mrb_int y = mrb_fixnum(regs[a+1]);
    2262           SET_FLOAT_VALUE(mrb, regs[a], x - y);
    2263         }
    2264 #else
    2265         OP_MATH_BODY(-,mrb_float,mrb_fixnum);
    2266 #endif
    2267         break;
    2268       case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
    2269 #ifdef MRB_WORD_BOXING
    2270         {
    2271           mrb_float x = mrb_float(regs[a]);
    2272           mrb_float y = mrb_float(regs[a+1]);
    2273           SET_FLOAT_VALUE(mrb, regs[a], x - y);
    2274         }
    2275 #else
    2276         OP_MATH_BODY(-,mrb_float,mrb_float);
    2277 #endif
    2278         break;
    2279       default:
    2280         goto L_SEND;
    2281       }
    2282       NEXT;
    2283     }
    2284 
    2285     CASE(OP_MUL) {
    2286       /* A B C  R(A) := R(A)*R(A+1) (Syms[B]=:*,C=1)*/
    2287       int a = GETARG_A(i);
    2288 
    2289       /* need to check if op is overridden */
    2290       switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
    2291       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
    2292         {
    2293           mrb_int x, y, z;
    2294 
    2295           x = mrb_fixnum(regs[a]);
    2296           y = mrb_fixnum(regs[a+1]);
    2297           if (mrb_int_mul_overflow(x, y, &z)) {
    2298             SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x * (mrb_float)y);
    2299             break;
    2300           }
    2301           SET_INT_VALUE(regs[a], z);
    2302         }
    2303         break;
    2304       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
    2305         {
    2306           mrb_int x = mrb_fixnum(regs[a]);
    2307           mrb_float y = mrb_float(regs[a+1]);
    2308           SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x * y);
    2309         }
    2310         break;
    2311       case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
    2312 #ifdef MRB_WORD_BOXING
    2313         {
    2314           mrb_float x = mrb_float(regs[a]);
    2315           mrb_int y = mrb_fixnum(regs[a+1]);
    2316           SET_FLOAT_VALUE(mrb, regs[a], x * y);
    2317         }
    2318 #else
    2319         OP_MATH_BODY(*,mrb_float,mrb_fixnum);
    2320 #endif
    2321         break;
    2322       case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
    2323 #ifdef MRB_WORD_BOXING
    2324         {
    2325           mrb_float x = mrb_float(regs[a]);
    2326           mrb_float y = mrb_float(regs[a+1]);
    2327           SET_FLOAT_VALUE(mrb, regs[a], x * y);
    2328         }
    2329 #else
    2330         OP_MATH_BODY(*,mrb_float,mrb_float);
    2331 #endif
    2332         break;
    2333       default:
    2334         goto L_SEND;
    2335       }
    2336       NEXT;
    2337     }
    2338 
    2339     CASE(OP_DIV) {
    2340       /* A B C  R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1)*/
    2341       int a = GETARG_A(i);
    2342 
    2343       /* need to check if op is overridden */
    2344       switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
    2345       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
     2268#ifdef MRB_WITHOUT_FLOAT
    23462269        {
    23472270          mrb_int x = mrb_fixnum(regs[a]);
    23482271          mrb_int y = mrb_fixnum(regs[a+1]);
    2349           SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x / (mrb_float)y);
    2350         }
     2272          SET_INT_VALUE(regs[a], y ? x / y : 0);
     2273        }
     2274        break;
     2275#else
     2276        x = (mrb_float)mrb_fixnum(regs[a]);
     2277        y = (mrb_float)mrb_fixnum(regs[a+1]);
    23512278        break;
    23522279      case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
    2353         {
    2354           mrb_int x = mrb_fixnum(regs[a]);
    2355           mrb_float y = mrb_float(regs[a+1]);
    2356           SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x / y);
    2357         }
     2280        x = (mrb_float)mrb_fixnum(regs[a]);
     2281        y = mrb_float(regs[a+1]);
    23582282        break;
    23592283      case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
    2360 #ifdef MRB_WORD_BOXING
    2361         {
    2362           mrb_float x = mrb_float(regs[a]);
    2363           mrb_int y = mrb_fixnum(regs[a+1]);
    2364           SET_FLOAT_VALUE(mrb, regs[a], x / y);
    2365         }
    2366 #else
    2367         OP_MATH_BODY(/,mrb_float,mrb_fixnum);
    2368 #endif
     2284        x = mrb_float(regs[a]);
     2285        y = (mrb_float)mrb_fixnum(regs[a+1]);
    23692286        break;
    23702287      case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
    2371 #ifdef MRB_WORD_BOXING
    2372         {
    2373           mrb_float x = mrb_float(regs[a]);
    2374           mrb_float y = mrb_float(regs[a+1]);
    2375           SET_FLOAT_VALUE(mrb, regs[a], x / y);
    2376         }
     2288        x = mrb_float(regs[a]);
     2289        y = mrb_float(regs[a+1]);
     2290        break;
     2291#endif
     2292      default:
     2293        c = 1;
     2294        mid = mrb_intern_lit(mrb, "/");
     2295        goto L_SEND_SYM;
     2296      }
     2297
     2298#ifndef MRB_WITHOUT_FLOAT
     2299      if (y == 0) {
     2300        if (x > 0) f = INFINITY;
     2301        else if (x < 0) f = -INFINITY;
     2302        else /* if (x == 0) */ f = NAN;
     2303      }
     2304      else {
     2305        f = x / y;
     2306      }
     2307      SET_FLOAT_VALUE(mrb, regs[a], f);
     2308#endif
     2309      NEXT;
     2310    }
     2311
     2312#define OP_MATHI(op_name)                                                   \
     2313  /* need to check if op is overridden */                                   \
     2314  switch (mrb_type(regs[a])) {                                              \
     2315    OP_MATHI_CASE_FIXNUM(op_name);                                          \
     2316    OP_MATHI_CASE_FLOAT(op_name);                                           \
     2317    default:                                                                \
     2318      SET_INT_VALUE(regs[a+1], b);                                          \
     2319      c = 1;                                                                \
     2320      mid = mrb_intern_lit(mrb, MRB_STRINGIZE(OP_MATH_OP_##op_name));       \
     2321      goto L_SEND_SYM;                                                      \
     2322  }                                                                         \
     2323  NEXT;
     2324#define OP_MATHI_CASE_FIXNUM(op_name)                                       \
     2325  case MRB_TT_FIXNUM:                                                       \
     2326    {                                                                       \
     2327      mrb_int x = mrb_fixnum(regs[a]), y = (mrb_int)b, z;                   \
     2328      if (mrb_int_##op_name##_overflow(x, y, &z))                           \
     2329        OP_MATH_OVERFLOW_INT(op_name, x, y, z);                             \
     2330      else                                                                  \
     2331        SET_INT_VALUE(regs[a], z);                                          \
     2332    }                                                                       \
     2333    break
     2334#ifdef MRB_WITHOUT_FLOAT
     2335#define OP_MATHI_CASE_FLOAT(op_name) (void)0
    23772336#else
    2378         OP_MATH_BODY(/,mrb_float,mrb_float);
    2379 #endif
    2380         break;
    2381       default:
    2382         goto L_SEND;
    2383       }
    2384 #ifdef MRB_NAN_BOXING
    2385       if (isnan(mrb_float(regs[a]))) {
    2386         mrb_value v = mrb_float_value(mrb, mrb_float(regs[a]));
    2387         regs[a] = v;
    2388       }
    2389 #endif
    2390       NEXT;
    2391     }
    2392 
    2393     CASE(OP_ADDI) {
    2394       /* A B C  R(A) := R(A)+C (Syms[B]=:+)*/
    2395       int a = GETARG_A(i);
    2396 
    2397       /* need to check if + is overridden */
    2398       switch (mrb_type(regs[a])) {
    2399       case MRB_TT_FIXNUM:
    2400         {
    2401           mrb_int x = mrb_fixnum(regs[a]);
    2402           mrb_int y = GETARG_C(i);
    2403           mrb_int z;
    2404 
    2405           if (mrb_int_add_overflow(x, y, &z)) {
    2406             SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + (mrb_float)y);
    2407             break;
    2408           }
    2409           SET_INT_VALUE(regs[a], z);
    2410         }
    2411         break;
    2412       case MRB_TT_FLOAT:
    2413 #ifdef MRB_WORD_BOXING
    2414         {
    2415           mrb_float x = mrb_float(regs[a]);
    2416           SET_FLOAT_VALUE(mrb, regs[a], x + GETARG_C(i));
    2417         }
     2337#define OP_MATHI_CASE_FLOAT(op_name)                                        \
     2338  case MRB_TT_FLOAT:                                                        \
     2339    {                                                                       \
     2340      mrb_float z = mrb_float(regs[a]) OP_MATH_OP_##op_name b;              \
     2341      SET_FLOAT_VALUE(mrb, regs[a], z);                                     \
     2342    }                                                                       \
     2343    break
     2344#endif
     2345
     2346    CASE(OP_ADDI, BB) {
     2347      OP_MATHI(add);
     2348    }
     2349
     2350    CASE(OP_SUBI, BB) {
     2351      OP_MATHI(sub);
     2352    }
     2353
     2354#define OP_CMP_BODY(op,v1,v2) (v1(regs[a]) op v2(regs[a+1]))
     2355
     2356#ifdef MRB_WITHOUT_FLOAT
     2357#define OP_CMP(op) do {\
     2358  int result;\
     2359  /* need to check if - is overridden */\
     2360  switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\
     2361  case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\
     2362    result = OP_CMP_BODY(op,mrb_fixnum,mrb_fixnum);\
     2363    break;\
     2364  default:\
     2365    c = 1;\
     2366    mid = mrb_intern_lit(mrb, # op);\
     2367    goto L_SEND_SYM;\
     2368  }\
     2369  if (result) {\
     2370    SET_TRUE_VALUE(regs[a]);\
     2371  }\
     2372  else {\
     2373    SET_FALSE_VALUE(regs[a]);\
     2374  }\
     2375} while(0)
    24182376#else
    2419         mrb_float(regs[a]) += GETARG_C(i);
    2420 #endif
    2421         break;
    2422       default:
    2423         SET_INT_VALUE(regs[a+1], GETARG_C(i));
    2424         i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1);
    2425         goto L_SEND;
    2426       }
    2427       NEXT;
    2428     }
    2429 
    2430     CASE(OP_SUBI) {
    2431       /* A B C  R(A) := R(A)-C (Syms[B]=:-)*/
    2432       int a = GETARG_A(i);
    2433       mrb_value *regs_a = regs + a;
    2434 
    2435       /* need to check if + is overridden */
    2436       switch (mrb_type(regs_a[0])) {
    2437       case MRB_TT_FIXNUM:
    2438         {
    2439           mrb_int x = mrb_fixnum(regs_a[0]);
    2440           mrb_int y = GETARG_C(i);
    2441           mrb_int z;
    2442 
    2443           if (mrb_int_sub_overflow(x, y, &z)) {
    2444             SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x - (mrb_float)y);
    2445           }
    2446           else {
    2447             SET_INT_VALUE(regs_a[0], z);
    2448           }
    2449         }
    2450         break;
    2451       case MRB_TT_FLOAT:
    2452 #ifdef MRB_WORD_BOXING
    2453         {
    2454           mrb_float x = mrb_float(regs[a]);
    2455           SET_FLOAT_VALUE(mrb, regs[a], x - GETARG_C(i));
    2456         }
    2457 #else
    2458         mrb_float(regs_a[0]) -= GETARG_C(i);
    2459 #endif
    2460         break;
    2461       default:
    2462         SET_INT_VALUE(regs_a[1], GETARG_C(i));
    2463         i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1);
    2464         goto L_SEND;
    2465       }
    2466       NEXT;
    2467     }
    2468 
    2469 #define OP_CMP_BODY(op,v1,v2) (v1(regs[a]) op v2(regs[a+1]))
    2470 
    24712377#define OP_CMP(op) do {\
    24722378  int result;\
     
    24862392    break;\
    24872393  default:\
    2488     goto L_SEND;\
     2394    c = 1;\
     2395    mid = mrb_intern_lit(mrb, # op);\
     2396    goto L_SEND_SYM;\
    24892397  }\
    24902398  if (result) {\
     
    24952403  }\
    24962404} while(0)
    2497 
    2498     CASE(OP_EQ) {
    2499       /* A B C  R(A) := R(A)==R(A+1) (Syms[B]=:==,C=1)*/
    2500       int a = GETARG_A(i);
     2405#endif
     2406
     2407    CASE(OP_EQ, B) {
    25012408      if (mrb_obj_eq(mrb, regs[a], regs[a+1])) {
    25022409        SET_TRUE_VALUE(regs[a]);
     
    25082415    }
    25092416
    2510     CASE(OP_LT) {
    2511       /* A B C  R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1)*/
    2512       int a = GETARG_A(i);
     2417    CASE(OP_LT, B) {
    25132418      OP_CMP(<);
    25142419      NEXT;
    25152420    }
    25162421
    2517     CASE(OP_LE) {
    2518       /* A B C  R(A) := R(A)<=R(A+1) (Syms[B]=:<=,C=1)*/
    2519       int a = GETARG_A(i);
     2422    CASE(OP_LE, B) {
    25202423      OP_CMP(<=);
    25212424      NEXT;
    25222425    }
    25232426
    2524     CASE(OP_GT) {
    2525       /* A B C  R(A) := R(A)>R(A+1) (Syms[B]=:>,C=1)*/
    2526       int a = GETARG_A(i);
     2427    CASE(OP_GT, B) {
    25272428      OP_CMP(>);
    25282429      NEXT;
    25292430    }
    25302431
    2531     CASE(OP_GE) {
    2532       /* A B C  R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1)*/
    2533       int a = GETARG_A(i);
     2432    CASE(OP_GE, B) {
    25342433      OP_CMP(>=);
    25352434      NEXT;
    25362435    }
    25372436
    2538     CASE(OP_ARRAY) {
    2539       /* A B C          R(A) := ary_new(R(B),R(B+1)..R(B+C)) */
    2540       int a = GETARG_A(i);
    2541       int b = GETARG_B(i);
    2542       int c = GETARG_C(i);
     2437    CASE(OP_ARRAY, BB) {
     2438      mrb_value v = mrb_ary_new_from_values(mrb, b, &regs[a]);
     2439      regs[a] = v;
     2440      mrb_gc_arena_restore(mrb, ai);
     2441      NEXT;
     2442    }
     2443    CASE(OP_ARRAY2, BBB) {
    25432444      mrb_value v = mrb_ary_new_from_values(mrb, c, &regs[b]);
    25442445      regs[a] = v;
    2545       ARENA_RESTORE(mrb, ai);
    2546       NEXT;
    2547     }
    2548 
    2549     CASE(OP_ARYCAT) {
    2550       /* A B            mrb_ary_concat(R(A),R(B)) */
    2551       int a = GETARG_A(i);
    2552       int b = GETARG_B(i);
    2553       mrb_value splat = mrb_ary_splat(mrb, regs[b]);
    2554       mrb_ary_concat(mrb, regs[a], splat);
    2555       ARENA_RESTORE(mrb, ai);
    2556       NEXT;
    2557     }
    2558 
    2559     CASE(OP_ARYPUSH) {
    2560       /* A B            R(A).push(R(B)) */
    2561       int a = GETARG_A(i);
    2562       int b = GETARG_B(i);
    2563       mrb_ary_push(mrb, regs[a], regs[b]);
    2564       NEXT;
    2565     }
    2566 
    2567     CASE(OP_AREF) {
    2568       /* A B C          R(A) := R(B)[C] */
    2569       int a = GETARG_A(i);
    2570       int b = GETARG_B(i);
    2571       int c = GETARG_C(i);
     2446      mrb_gc_arena_restore(mrb, ai);
     2447      NEXT;
     2448    }
     2449
     2450    CASE(OP_ARYCAT, B) {
     2451      mrb_value splat = mrb_ary_splat(mrb, regs[a+1]);
     2452      if (mrb_nil_p(regs[a])) {
     2453        regs[a] = splat;
     2454      }
     2455      else {
     2456        mrb_ary_concat(mrb, regs[a], splat);
     2457      }
     2458      mrb_gc_arena_restore(mrb, ai);
     2459      NEXT;
     2460    }
     2461
     2462    CASE(OP_ARYPUSH, B) {
     2463      mrb_ary_push(mrb, regs[a], regs[a+1]);
     2464      NEXT;
     2465    }
     2466
     2467    CASE(OP_ARYDUP, B) {
     2468      mrb_value ary = regs[a];
     2469      if (mrb_array_p(ary)) {
     2470        ary = mrb_ary_new_from_values(mrb, RARRAY_LEN(ary), RARRAY_PTR(ary));
     2471      }
     2472      else {
     2473        ary = mrb_ary_new_from_values(mrb, 1, &ary);
     2474      }
     2475      regs[a] = ary;
     2476      NEXT;
     2477    }
     2478
     2479    CASE(OP_AREF, BBB) {
    25722480      mrb_value v = regs[b];
    25732481
     
    25872495    }
    25882496
    2589     CASE(OP_ASET) {
    2590       /* A B C          R(B)[C] := R(A) */
    2591       int a = GETARG_A(i);
    2592       int b = GETARG_B(i);
    2593       int c = GETARG_C(i);
     2497    CASE(OP_ASET, BBB) {
    25942498      mrb_ary_set(mrb, regs[b], c, regs[a]);
    25952499      NEXT;
    25962500    }
    25972501
    2598     CASE(OP_APOST) {
    2599       /* A B C  *R(A),R(A+1)..R(A+C) := R(A) */
    2600       int a = GETARG_A(i);
     2502    CASE(OP_APOST, BBB) {
    26012503      mrb_value v = regs[a];
    2602       int pre  = GETARG_B(i);
    2603       int post = GETARG_C(i);
     2504      int pre  = b;
     2505      int post = c;
    26042506      struct RArray *ary;
    26052507      int len, idx;
     
    26092511      }
    26102512      ary = mrb_ary_ptr(v);
    2611       len = ary->len;
     2513      len = (int)ARY_LEN(ary);
    26122514      if (len > pre + post) {
    2613         v = mrb_ary_new_from_values(mrb, len - pre - post, ary->ptr+pre);
     2515        v = mrb_ary_new_from_values(mrb, len - pre - post, ARY_PTR(ary)+pre);
    26142516        regs[a++] = v;
    26152517        while (post--) {
    2616           regs[a++] = ary->ptr[len-post-1];
     2518          regs[a++] = ARY_PTR(ary)[len-post-1];
    26172519        }
    26182520      }
     
    26212523        regs[a++] = v;
    26222524        for (idx=0; idx+pre<len; idx++) {
    2623           regs[a+idx] = ary->ptr[pre+idx];
     2525          regs[a+idx] = ARY_PTR(ary)[pre+idx];
    26242526        }
    26252527        while (idx < post) {
     
    26282530        }
    26292531      }
    2630       ARENA_RESTORE(mrb, ai);
    2631       NEXT;
    2632     }
    2633 
    2634     CASE(OP_STRING) {
    2635       /* A Bx           R(A) := str_new(Lit(Bx)) */
    2636       mrb_value str = mrb_str_dup(mrb, pool[GETARG_Bx(i)]);
    2637       regs[GETARG_A(i)] = str;
    2638       ARENA_RESTORE(mrb, ai);
    2639       NEXT;
    2640     }
    2641 
    2642     CASE(OP_STRCAT) {
    2643       /* A B    R(A).concat(R(B)) */
    2644       mrb_str_concat(mrb, regs[GETARG_A(i)], regs[GETARG_B(i)]);
    2645       NEXT;
    2646     }
    2647 
    2648     CASE(OP_HASH) {
    2649       /* A B C   R(A) := hash_new(R(B),R(B+1)..R(B+C)) */
    2650       int b = GETARG_B(i);
    2651       int c = GETARG_C(i);
    2652       int lim = b+c*2;
    2653       mrb_value hash = mrb_hash_new_capa(mrb, c);
    2654 
    2655       while (b < lim) {
    2656         mrb_hash_set(mrb, hash, regs[b], regs[b+1]);
    2657         b+=2;
    2658       }
    2659       regs[GETARG_A(i)] = hash;
    2660       ARENA_RESTORE(mrb, ai);
    2661       NEXT;
    2662     }
    2663 
    2664     CASE(OP_LAMBDA) {
    2665       /* A b c  R(A) := lambda(SEQ[b],c) (b:c = 14:2) */
     2532      mrb_gc_arena_restore(mrb, ai);
     2533      NEXT;
     2534    }
     2535
     2536    CASE(OP_INTERN, B) {
     2537      mrb_sym sym = mrb_intern_str(mrb, regs[a]);
     2538
     2539      regs[a] = mrb_symbol_value(sym);
     2540      mrb_gc_arena_restore(mrb, ai);
     2541      NEXT;
     2542    }
     2543
     2544    CASE(OP_STRING, BB) {
     2545      mrb_value str = mrb_str_dup(mrb, pool[b]);
     2546
     2547      regs[a] = str;
     2548      mrb_gc_arena_restore(mrb, ai);
     2549      NEXT;
     2550    }
     2551
     2552    CASE(OP_STRCAT, B) {
     2553      mrb_str_concat(mrb, regs[a], regs[a+1]);
     2554      NEXT;
     2555    }
     2556
     2557    CASE(OP_HASH, BB) {
     2558      mrb_value hash = mrb_hash_new_capa(mrb, b);
     2559      int i;
     2560      int lim = a+b*2;
     2561
     2562      for (i=a; i<lim; i+=2) {
     2563        mrb_hash_set(mrb, hash, regs[i], regs[i+1]);
     2564      }
     2565      regs[a] = hash;
     2566      mrb_gc_arena_restore(mrb, ai);
     2567      NEXT;
     2568    }
     2569
     2570    CASE(OP_HASHADD, BB) {
     2571      mrb_value hash;
     2572      int i;
     2573      int lim = a+b*2+1;
     2574
     2575      hash = mrb_ensure_hash_type(mrb, regs[a]);
     2576      for (i=a+1; i<lim; i+=2) {
     2577        mrb_hash_set(mrb, hash, regs[i], regs[i+1]);
     2578      }
     2579      mrb_gc_arena_restore(mrb, ai);
     2580      NEXT;
     2581    }
     2582    CASE(OP_HASHCAT, B) {
     2583      mrb_value hash = mrb_ensure_hash_type(mrb, regs[a]);
     2584
     2585      mrb_hash_merge(mrb, hash, regs[a+1]);
     2586      mrb_gc_arena_restore(mrb, ai);
     2587      NEXT;
     2588    }
     2589
     2590    CASE(OP_LAMBDA, BB)
     2591    c = OP_L_LAMBDA;
     2592    L_MAKE_LAMBDA:
     2593    {
    26662594      struct RProc *p;
    2667       int c = GETARG_c(i);
     2595      mrb_irep *nirep = irep->reps[b];
    26682596
    26692597      if (c & OP_L_CAPTURE) {
    2670         p = mrb_closure_new(mrb, irep->reps[GETARG_b(i)]);
     2598        p = mrb_closure_new(mrb, nirep);
    26712599      }
    26722600      else {
    2673         p = mrb_proc_new(mrb, irep->reps[GETARG_b(i)]);
     2601        p = mrb_proc_new(mrb, nirep);
     2602        p->flags |= MRB_PROC_SCOPE;
    26742603      }
    26752604      if (c & OP_L_STRICT) p->flags |= MRB_PROC_STRICT;
    2676       regs[GETARG_A(i)] = mrb_obj_value(p);
    2677       ARENA_RESTORE(mrb, ai);
    2678       NEXT;
    2679     }
    2680 
    2681     CASE(OP_OCLASS) {
    2682       /* A      R(A) := ::Object */
    2683       regs[GETARG_A(i)] = mrb_obj_value(mrb->object_class);
    2684       NEXT;
    2685     }
    2686 
    2687     CASE(OP_CLASS) {
    2688       /* A B    R(A) := newclass(R(A),Syms(B),R(A+1)) */
     2605      regs[a] = mrb_obj_value(p);
     2606      mrb_gc_arena_restore(mrb, ai);
     2607      NEXT;
     2608    }
     2609    CASE(OP_BLOCK, BB) {
     2610      c = OP_L_BLOCK;
     2611      goto L_MAKE_LAMBDA;
     2612    }
     2613    CASE(OP_METHOD, BB) {
     2614      c = OP_L_METHOD;
     2615      goto L_MAKE_LAMBDA;
     2616    }
     2617
     2618    CASE(OP_RANGE_INC, B) {
     2619      mrb_value val = mrb_range_new(mrb, regs[a], regs[a+1], FALSE);
     2620      regs[a] = val;
     2621      mrb_gc_arena_restore(mrb, ai);
     2622      NEXT;
     2623    }
     2624
     2625    CASE(OP_RANGE_EXC, B) {
     2626      mrb_value val = mrb_range_new(mrb, regs[a], regs[a+1], TRUE);
     2627      regs[a] = val;
     2628      mrb_gc_arena_restore(mrb, ai);
     2629      NEXT;
     2630    }
     2631
     2632    CASE(OP_OCLASS, B) {
     2633      regs[a] = mrb_obj_value(mrb->object_class);
     2634      NEXT;
     2635    }
     2636
     2637    CASE(OP_CLASS, BB) {
    26892638      struct RClass *c = 0, *baseclass;
    2690       int a = GETARG_A(i);
    26912639      mrb_value base, super;
    2692       mrb_sym id = syms[GETARG_B(i)];
     2640      mrb_sym id = syms[b];
    26932641
    26942642      base = regs[a];
    26952643      super = regs[a+1];
    26962644      if (mrb_nil_p(base)) {
    2697         baseclass = mrb->c->ci->proc->target_class;
    2698         if (!baseclass) baseclass = mrb->c->ci->target_class;
    2699 
     2645        baseclass = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc);
    27002646        base = mrb_obj_value(baseclass);
    27012647      }
    27022648      c = mrb_vm_define_class(mrb, base, super, id);
    27032649      regs[a] = mrb_obj_value(c);
    2704       ARENA_RESTORE(mrb, ai);
    2705       NEXT;
    2706     }
    2707 
    2708     CASE(OP_MODULE) {
    2709       /* A B            R(A) := newmodule(R(A),Syms(B)) */
    2710       struct RClass *c = 0, *baseclass;
    2711       int a = GETARG_A(i);
     2650      mrb_gc_arena_restore(mrb, ai);
     2651      NEXT;
     2652    }
     2653
     2654    CASE(OP_MODULE, BB) {
     2655      struct RClass *cls = 0, *baseclass;
    27122656      mrb_value base;
    2713       mrb_sym id = syms[GETARG_B(i)];
     2657      mrb_sym id = syms[b];
    27142658
    27152659      base = regs[a];
    27162660      if (mrb_nil_p(base)) {
    2717         baseclass = mrb->c->ci->proc->target_class;
    2718         if (!baseclass) baseclass = mrb->c->ci->target_class;
    2719 
     2661        baseclass = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc);
    27202662        base = mrb_obj_value(baseclass);
    27212663      }
    2722       c = mrb_vm_define_module(mrb, base, id);
    2723       regs[a] = mrb_obj_value(c);
    2724       ARENA_RESTORE(mrb, ai);
    2725       NEXT;
    2726     }
    2727 
    2728     CASE(OP_EXEC) {
    2729       /* A Bx   R(A) := blockexec(R(A),SEQ[Bx]) */
    2730       int a = GETARG_A(i);
     2664      cls = mrb_vm_define_module(mrb, base, id);
     2665      regs[a] = mrb_obj_value(cls);
     2666      mrb_gc_arena_restore(mrb, ai);
     2667      NEXT;
     2668    }
     2669
     2670    CASE(OP_EXEC, BB) {
    27312671      mrb_callinfo *ci;
    27322672      mrb_value recv = regs[a];
    27332673      struct RProc *p;
     2674      mrb_irep *nirep = irep->reps[b];
    27342675
    27352676      /* prepare closure */
    2736       p = mrb_closure_new(mrb, irep->reps[GETARG_Bx(i)]);
     2677      p = mrb_proc_new(mrb, nirep);
    27372678      p->c = NULL;
    2738 
    2739       /* prepare stack */
     2679      mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)proc);
     2680      MRB_PROC_SET_TARGET_CLASS(p, mrb_class_ptr(recv));
     2681      p->flags |= MRB_PROC_SCOPE;
     2682
     2683      /* prepare call stack */
    27402684      ci = cipush(mrb);
    2741       ci->pc = pc + 1;
     2685      ci->pc = pc;
    27422686      ci->acc = a;
    27432687      ci->mid = 0;
     
    27492693      mrb->c->stack += a;
    27502694
    2751       /* setup closure */
    2752       p->target_class = ci->target_class;
     2695      /* setup block to call */
    27532696      ci->proc = p;
    27542697
     
    27562699      pool = irep->pool;
    27572700      syms = irep->syms;
    2758       stack_extend(mrb, irep->nregs);
     2701      mrb_stack_extend(mrb, irep->nregs);
    27592702      stack_clear(regs+1, irep->nregs-1);
    2760       ci->nregs = irep->nregs;
    27612703      pc = irep->iseq;
    27622704      JUMP;
    27632705    }
    27642706
    2765     CASE(OP_METHOD) {
    2766       /* A B            R(A).newmethod(Syms(B),R(A+1)) */
    2767       int a = GETARG_A(i);
    2768       struct RClass *c = mrb_class_ptr(regs[a]);
     2707    CASE(OP_DEF, BB) {
     2708      struct RClass *target = mrb_class_ptr(regs[a]);
    27692709      struct RProc *p = mrb_proc_ptr(regs[a+1]);
    2770 
    2771       mrb_define_method_raw(mrb, c, syms[GETARG_B(i)], p);
    2772       ARENA_RESTORE(mrb, ai);
    2773       NEXT;
    2774     }
    2775 
    2776     CASE(OP_SCLASS) {
    2777       /* A B    R(A) := R(B).singleton_class */
    2778       regs[GETARG_A(i)] = mrb_singleton_class(mrb, regs[GETARG_B(i)]);
    2779       ARENA_RESTORE(mrb, ai);
    2780       NEXT;
    2781     }
    2782 
    2783     CASE(OP_TCLASS) {
    2784       /* A      R(A) := target_class */
    2785       if (!mrb->c->ci->target_class) {
    2786         mrb_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, "no target class or module");
    2787         mrb_exc_set(mrb, exc);
    2788         goto L_RAISE;
    2789       }
    2790       regs[GETARG_A(i)] = mrb_obj_value(mrb->c->ci->target_class);
    2791       NEXT;
    2792     }
    2793 
    2794     CASE(OP_RANGE) {
    2795       /* A B C  R(A) := range_new(R(B),R(B+1),C) */
    2796       int b = GETARG_B(i);
    2797       mrb_value val = mrb_range_new(mrb, regs[b], regs[b+1], GETARG_C(i));
    2798       regs[GETARG_A(i)] = val;
    2799       ARENA_RESTORE(mrb, ai);
    2800       NEXT;
    2801     }
    2802 
    2803     CASE(OP_DEBUG) {
    2804       /* A B C    debug print R(A),R(B),R(C) */
     2710      mrb_method_t m;
     2711
     2712      MRB_METHOD_FROM_PROC(m, p);
     2713      mrb_define_method_raw(mrb, target, syms[b], m);
     2714      mrb_gc_arena_restore(mrb, ai);
     2715      NEXT;
     2716    }
     2717
     2718    CASE(OP_SCLASS, B) {
     2719      regs[a] = mrb_singleton_class(mrb, regs[a]);
     2720      mrb_gc_arena_restore(mrb, ai);
     2721      NEXT;
     2722    }
     2723
     2724    CASE(OP_TCLASS, B) {
     2725      if (!check_target_class(mrb)) goto L_RAISE;
     2726      regs[a] = mrb_obj_value(mrb->c->ci->target_class);
     2727      NEXT;
     2728    }
     2729
     2730    CASE(OP_ALIAS, BB) {
     2731      struct RClass *target;
     2732
     2733      if (!check_target_class(mrb)) goto L_RAISE;
     2734      target = mrb->c->ci->target_class;
     2735      mrb_alias_method(mrb, target, syms[a], syms[b]);
     2736      NEXT;
     2737    }
     2738    CASE(OP_UNDEF, B) {
     2739      struct RClass *target;
     2740
     2741      if (!check_target_class(mrb)) goto L_RAISE;
     2742      target = mrb->c->ci->target_class;
     2743      mrb_undef_method_id(mrb, target, syms[a]);
     2744      NEXT;
     2745    }
     2746
     2747    CASE(OP_DEBUG, Z) {
     2748      FETCH_BBB();
    28052749#ifdef MRB_ENABLE_DEBUG_HOOK
    28062750      mrb->debug_op_hook(mrb, irep, pc, regs);
    28072751#else
    28082752#ifndef MRB_DISABLE_STDIO
    2809       printf("OP_DEBUG %d %d %d\n", GETARG_A(i), GETARG_B(i), GETARG_C(i));
     2753      printf("OP_DEBUG %d %d %d\n", a, b, c);
    28102754#else
    28112755      abort();
     
    28152759    }
    28162760
    2817     CASE(OP_STOP) {
     2761    CASE(OP_ERR, B) {
     2762      mrb_value msg = mrb_str_dup(mrb, pool[a]);
     2763      mrb_value exc;
     2764
     2765      exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg);
     2766      ERR_PC_SET(mrb);
     2767      mrb_exc_set(mrb, exc);
     2768      goto L_RAISE;
     2769    }
     2770
     2771    CASE(OP_EXT1, Z) {
     2772      insn = READ_B();
     2773      switch (insn) {
     2774#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _1(); goto L_OP_ ## insn ## _BODY;
     2775#include "mruby/ops.h"
     2776#undef OPCODE
     2777      }
     2778      pc--;
     2779      NEXT;
     2780    }
     2781    CASE(OP_EXT2, Z) {
     2782      insn = READ_B();
     2783      switch (insn) {
     2784#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _2(); goto L_OP_ ## insn ## _BODY;
     2785#include "mruby/ops.h"
     2786#undef OPCODE
     2787      }
     2788      pc--;
     2789      NEXT;
     2790    }
     2791    CASE(OP_EXT3, Z) {
     2792      uint8_t insn = READ_B();
     2793      switch (insn) {
     2794#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _3(); goto L_OP_ ## insn ## _BODY;
     2795#include "mruby/ops.h"
     2796#undef OPCODE
     2797      }
     2798      pc--;
     2799      NEXT;
     2800    }
     2801
     2802    CASE(OP_STOP, Z) {
    28182803      /*        stop VM */
    28192804    L_STOP:
    2820       {
    2821         int epos = mrb->c->ci->epos;
    2822 
    2823         while (mrb->c->eidx > epos) {
    2824           ecall(mrb, --mrb->c->eidx);
    2825         }
    2826       }
     2805      while (mrb->c->eidx > 0) {
     2806        ecall(mrb);
     2807      }
     2808      mrb->c->cibase->ridx = 0;
    28272809      ERR_PC_CLR(mrb);
    28282810      mrb->jmp = prev_jmp;
     
    28322814      return regs[irep->nlocals];
    28332815    }
    2834 
    2835     CASE(OP_ERR) {
    2836       /* Bx     raise RuntimeError with message Lit(Bx) */
    2837       mrb_value msg = mrb_str_dup(mrb, pool[GETARG_Bx(i)]);
    2838       mrb_value exc;
    2839 
    2840       if (GETARG_A(i) == 0) {
    2841         exc = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, msg);
    2842       }
    2843       else {
    2844         exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg);
    2845       }
    2846       mrb_exc_set(mrb, exc);
    2847       goto L_RAISE;
    2848     }
    28492816  }
    28502817  END_DISPATCH;
    28512818#undef regs
    2852 
    28532819  }
    28542820  MRB_CATCH(&c_jmp) {
     
    28842850  }
    28852851  ci = cipush(mrb);
     2852  ci->stackent = mrb->c->stack;
    28862853  ci->mid = 0;
    2887   ci->nregs = 1;   /* protect the receiver */
    28882854  ci->acc = CI_ACC_SKIP;
    28892855  ci->target_class = mrb->object_class;
    28902856  v = mrb_vm_run(mrb, proc, self, stack_keep);
    2891   cipop(mrb);
    28922857
    28932858  return v;
Note: See TracChangeset for help on using the changeset viewer.