diff options
| author | Paolo Bosetti <[email protected]> | 2012-08-06 15:02:03 +0200 |
|---|---|---|
| committer | Paolo Bosetti <[email protected]> | 2012-08-06 15:02:56 +0200 |
| commit | aa0d2f91447c49363059f2e95cb9023f65a6fbef (patch) | |
| tree | 2cfa325956e62648f2161564adfdf6dddc45b737 /src | |
| parent | fd097b8aff7b91bd105fc1daec5a4050a947b763 (diff) | |
| parent | 193c98ae540d43d082795fd77ea81a4f6f7fd0f6 (diff) | |
| download | mruby-aa0d2f91447c49363059f2e95cb9023f65a6fbef.tar.gz mruby-aa0d2f91447c49363059f2e95cb9023f65a6fbef.zip | |
Updated Xcode project build settings in conformity with 10.8/Xcode 4.4
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile | 17 | ||||
| -rw-r--r-- | src/array.c | 508 | ||||
| -rw-r--r-- | src/cdump.c | 51 | ||||
| -rw-r--r-- | src/class.c | 560 | ||||
| -rw-r--r-- | src/codegen.c | 479 | ||||
| -rw-r--r-- | src/compar.c | 35 | ||||
| -rw-r--r-- | src/dump.c | 59 | ||||
| -rw-r--r-- | src/error.c | 187 | ||||
| -rw-r--r-- | src/error.h | 3 | ||||
| -rw-r--r-- | src/etc.c | 216 | ||||
| -rw-r--r-- | src/gc.c | 147 | ||||
| -rw-r--r-- | src/gc.h | 54 | ||||
| -rw-r--r-- | src/hash.c | 106 | ||||
| -rw-r--r-- | src/init.c | 16 | ||||
| -rw-r--r-- | src/kernel.c | 480 | ||||
| -rw-r--r-- | src/load.c | 64 | ||||
| -rw-r--r-- | src/math.c | 119 | ||||
| -rw-r--r-- | src/node.h | 26 | ||||
| -rw-r--r-- | src/numeric.c | 305 | ||||
| -rw-r--r-- | src/object.c | 51 | ||||
| -rw-r--r-- | src/opcode.h | 18 | ||||
| -rw-r--r-- | src/parse.y | 553 | ||||
| -rw-r--r-- | src/pool.c | 23 | ||||
| -rw-r--r-- | src/print.c | 32 | ||||
| -rw-r--r-- | src/proc.c | 70 | ||||
| -rw-r--r-- | src/range.c | 144 | ||||
| -rw-r--r-- | src/re.c | 56 | ||||
| -rw-r--r-- | src/re.h | 1 | ||||
| -rw-r--r-- | src/regcomp.c | 8 | ||||
| -rw-r--r-- | src/regenc.c | 8 | ||||
| -rw-r--r-- | src/regerror.c | 4 | ||||
| -rw-r--r-- | src/regexec.c | 4 | ||||
| -rw-r--r-- | src/regparse.c | 8 | ||||
| -rw-r--r-- | src/sprintf.c | 52 | ||||
| -rw-r--r-- | src/st.c | 12 | ||||
| -rw-r--r-- | src/state.c | 7 | ||||
| -rw-r--r-- | src/string.c | 512 | ||||
| -rw-r--r-- | src/struct.c | 220 | ||||
| -rw-r--r-- | src/symbol.c | 173 | ||||
| -rw-r--r-- | src/time.c | 282 | ||||
| -rw-r--r-- | src/variable.c | 188 | ||||
| -rw-r--r-- | src/vm.c | 284 |
42 files changed, 3326 insertions, 2816 deletions
diff --git a/src/Makefile b/src/Makefile index 61012ea68..13f80b694 100644 --- a/src/Makefile +++ b/src/Makefile @@ -19,12 +19,19 @@ OBJS := $(OBJ1) $(OBJ2) $(OBJ3) # libraries, includes INCLUDES = -I$(BASEDIR) -I$(BASEDIR)/../include -DEBUG_MODE = 1 -ifeq ($(DEBUG_MODE),1) -CFLAGS = -g -O3 -else -CFLAGS = -O3 +ifeq ($(strip $(COMPILE_MODE)),) + # default compile option + COMPILE_MODE = debug endif + +ifeq ($(COMPILE_MODE),debug) + CFLAGS = -g -O3 +else ifeq ($(COMPILE_MODE),release) + CFLAGS = -O3 +else ifeq ($(COMPILE_MODE),small) + CFLAGS = -Os +endif + ALL_CFLAGS = -Wall -Werror-implicit-function-declaration $(CFLAGS) diff --git a/src/array.c b/src/array.c index 187a8404d..804c946da 100644 --- a/src/array.c +++ b/src/array.c @@ -10,15 +10,14 @@ #include "mruby/string.h" #include "mruby/class.h" -//#define ARY_DEFAULT_LEN 16 #define ARY_DEFAULT_LEN 4 #define ARY_SHRINK_RATIO 5 /* must be larger than 2 */ -#ifdef LONG_MAX -# define ARY_MAX_SIZE (LONG_MAX / sizeof(mrb_value)) +#ifdef INT_MAX +# define ARY_MAX_SIZE (INT_MAX / sizeof(mrb_value)) #endif static inline mrb_value -ary_elt(mrb_value ary, long offset) +ary_elt(mrb_value ary, int offset) { if (RARRAY_LEN(ary) == 0) return mrb_nil_value(); if (offset < 0 || RARRAY_LEN(ary) <= offset) { @@ -28,12 +27,12 @@ ary_elt(mrb_value ary, long offset) } static struct RArray* -ary_new_capa(mrb_state *mrb, size_t capa) +ary_new_capa(mrb_state *mrb, int capa) { struct RArray *a; - size_t blen; + int blen; -#ifdef LONG_MAX +#ifdef INT_MAX if (capa > ARY_MAX_SIZE) { mrb_raise(mrb, E_ARGUMENT_ERROR, "ary size too big"); } @@ -47,16 +46,15 @@ ary_new_capa(mrb_state *mrb, size_t capa) } a = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class); - a->buf = mrb_malloc(mrb, blen); - memset(a->buf, 0, blen); - a->capa = capa; + a->ptr = (mrb_value *)mrb_calloc(mrb, blen, 1); + a->aux.capa = capa; a->len = 0; return a; } mrb_value -mrb_ary_new_capa(mrb_state *mrb, size_t capa) +mrb_ary_new_capa(mrb_state *mrb, int capa) { struct RArray *a = ary_new_capa(mrb, capa); return mrb_obj_value(a); @@ -69,14 +67,14 @@ mrb_ary_new(mrb_state *mrb) } mrb_value -mrb_ary_new_from_values(mrb_state *mrb, size_t size, mrb_value *vals) +mrb_ary_new_from_values(mrb_state *mrb, int size, mrb_value *vals) { mrb_value ary; struct RArray *a; ary = mrb_ary_new_capa(mrb, size); a = mrb_ary_ptr(ary); - memcpy(a->buf, vals, sizeof(mrb_value)*size); + memcpy(a->ptr, vals, sizeof(mrb_value)*size); a->len = size; return ary; @@ -91,22 +89,70 @@ mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr) return mrb_ary_new_from_values(mrb, 2, arv); } -void -ary_fill_with_nil(mrb_value *buf, size_t size) +static void +ary_fill_with_nil(mrb_value *ptr, int size) { mrb_value nil = mrb_nil_value(); while((int)(size--)) { - *buf++ = nil; + *ptr++ = nil; } } -void -mrb_ary_expand_capa(mrb_state *mrb, struct RArray *a, size_t len) +static void +ary_modify(mrb_state *mrb, struct RArray *a) +{ + if (a->flags & MRB_ARY_SHARED) { + struct mrb_shared_array *shared = a->aux.shared; + + if (shared->refcnt == 1 && a->ptr == shared->ptr) { + a->ptr = shared->ptr; + a->aux.capa = a->len; + mrb_free(mrb, shared); + } + else { + mrb_value *ptr, *p; + int len; + + p = a->ptr; + len = a->len * sizeof(mrb_value); + ptr = (mrb_value *)mrb_malloc(mrb, len); + if (p) { + memcpy(ptr, p, len); + } + a->ptr = ptr; + a->aux.capa = a->len; + mrb_ary_decref(mrb, shared); + } + a->flags &= ~MRB_ARY_SHARED; + } +} + +static void +ary_make_shared(mrb_state *mrb, struct RArray *a) +{ + if (!(a->flags & MRB_ARY_SHARED)) { + struct mrb_shared_array *shared = (struct mrb_shared_array *)mrb_malloc(mrb, sizeof(struct mrb_shared_array)); + + shared->refcnt = 1; + if (a->aux.capa > a->len) { + a->ptr = shared->ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*a->len+1); + } + else { + shared->ptr = a->ptr; + } + shared->len = a->len; + a->aux.shared = shared; + a->flags |= MRB_ARY_SHARED; + } +} + +static void +ary_expand_capa(mrb_state *mrb, struct RArray *a, int len) { - size_t capa = a->capa; + int capa = a->aux.capa; -#ifdef LONG_MAX +#ifdef INT_MAX if (len > ARY_MAX_SIZE) { mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } @@ -121,20 +167,20 @@ mrb_ary_expand_capa(mrb_state *mrb, struct RArray *a, size_t len) } } -#ifdef LONG_MAX +#ifdef INT_MAX if (capa > ARY_MAX_SIZE) capa = ARY_MAX_SIZE; /* len <= capa <= ARY_MAX_SIZE */ #endif - if (capa > a->capa) { - a->capa = capa; - a->buf = mrb_realloc(mrb, a->buf, sizeof(mrb_value)*capa); + if (capa > a->aux.capa) { + a->aux.capa = capa; + a->ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa); } } -void -mrb_ary_shrink_capa(mrb_state *mrb, struct RArray *a) +static void +ary_shrink_capa(mrb_state *mrb, struct RArray *a) { - size_t capa = a->capa; + int capa = a->aux.capa; if (capa < ARY_DEFAULT_LEN * 2) return; if (capa <= a->len * ARY_SHRINK_RATIO) return; @@ -147,9 +193,9 @@ mrb_ary_shrink_capa(mrb_state *mrb, struct RArray *a) } } while(capa > a->len * ARY_SHRINK_RATIO); - if (capa > a->len && capa < a->capa) { - a->capa = capa; - a->buf = mrb_realloc(mrb, a->buf, sizeof(mrb_value)*capa); + if (capa > a->len && capa < a->aux.capa) { + a->aux.capa = capa; + a->ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa); } } @@ -160,29 +206,37 @@ mrb_ary_s_create(mrb_state *mrb, mrb_value self) int len; mrb_get_args(mrb, "*", &vals, &len); - return mrb_ary_new_from_values(mrb, (size_t)len, vals); + return mrb_ary_new_from_values(mrb, (int)len, vals); +} + +static void +ary_concat(mrb_state *mrb, struct RArray *a, mrb_value *ptr, int blen) +{ + int len = a->len + blen; + + ary_modify(mrb, a); + if (a->aux.capa < len) ary_expand_capa(mrb, a, len); + memcpy(a->ptr+a->len, ptr, sizeof(mrb_value)*blen); + mrb_write_barrier(mrb, (struct RBasic*)a); + a->len = len; } void mrb_ary_concat(mrb_state *mrb, mrb_value self, mrb_value other) { - struct RArray *a1 = mrb_ary_ptr(self); struct RArray *a2 = mrb_ary_ptr(other); - size_t len = a1->len + a2->len; - if (a1->capa < len) mrb_ary_expand_capa(mrb, a1, len); - memcpy(a1->buf+a1->len, a2->buf, sizeof(mrb_value)*a2->len); - mrb_write_barrier(mrb, (struct RBasic*)a1); - a1->len = len; + ary_concat(mrb, mrb_ary_ptr(self), a2->ptr, a2->len); } mrb_value mrb_ary_concat_m(mrb_state *mrb, mrb_value self) { - mrb_value other; + mrb_value *ptr; + int blen; - mrb_get_args(mrb, "A", &other); - mrb_ary_concat(mrb, self, other); + mrb_get_args(mrb, "a", &ptr, &blen); + ary_concat(mrb, mrb_ary_ptr(self), ptr, blen); return self; } @@ -191,15 +245,16 @@ mrb_ary_plus(mrb_state *mrb, mrb_value self) { struct RArray *a1 = mrb_ary_ptr(self); struct RArray *a2; - mrb_value other; mrb_value ary; + mrb_value *ptr; + int blen; - mrb_get_args(mrb, "A", &other); - ary = mrb_ary_new_capa(mrb, a1->len + RARRAY_LEN(other)); + mrb_get_args(mrb, "a", &ptr, &blen); + ary = mrb_ary_new_capa(mrb, a1->len + blen); a2 = mrb_ary_ptr(ary); - memcpy(a2->buf, a1->buf, sizeof(mrb_value)*a1->len); - memcpy(a2->buf + a1->len, RARRAY_PTR(other), sizeof(mrb_value)*RARRAY_LEN(other)); - a2->len = a1->len + RARRAY_LEN(other); + memcpy(a2->ptr, a1->ptr, sizeof(mrb_value)*a1->len); + memcpy(a2->ptr + a1->len, ptr, sizeof(mrb_value)*blen); + a2->len = a1->len + blen; return ary; } @@ -228,12 +283,12 @@ mrb_ary_cmp(mrb_state *mrb, mrb_value ary1) mrb_value ary2; struct RArray *a1, *a2; mrb_value r = mrb_nil_value(); - long i, len; + int i, len; mrb_get_args(mrb, "o", &ary2); if (mrb_type(ary2) != MRB_TT_ARRAY) return mrb_nil_value(); a1 = RARRAY(ary1); a2 = RARRAY(ary2); - if (a1->len == a2->len && a1->buf == a2->buf) return mrb_fixnum_value(0); + if (a1->len == a2->len && a1->ptr == a2->ptr) return mrb_fixnum_value(0); else { len = RARRAY_LEN(ary1); if (len > RARRAY_LEN(ary2)) { @@ -248,22 +303,32 @@ mrb_ary_cmp(mrb_state *mrb, mrb_value ary1) return mrb_fixnum_value((len == 0)? 0: (len > 0)? 1: -1); } -void -mrb_ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, size_t len) +static void +ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, int len) { - if (a->capa < len) mrb_ary_expand_capa(mrb, a, len); - memcpy(a->buf, argv, sizeof(mrb_value)*len); + ary_modify(mrb, a); + if (a->aux.capa < len) + ary_expand_capa(mrb, a, len); + memcpy(a->ptr, argv, sizeof(mrb_value)*len); mrb_write_barrier(mrb, (struct RBasic*)a); a->len = len; } +void +mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other) +{ + struct RArray *a2 = mrb_ary_ptr(other); + + ary_replace(mrb, mrb_ary_ptr(self), a2->ptr, a2->len); +} + mrb_value mrb_ary_replace_m(mrb_state *mrb, mrb_value self) { mrb_value other; - mrb_get_args(mrb, "o", &other); - mrb_ary_replace(mrb, mrb_ary_ptr(self), RARRAY_PTR(other), RARRAY_LEN(other)); + mrb_get_args(mrb, "A", &other); + mrb_ary_replace(mrb, self, other); return self; } @@ -274,9 +339,8 @@ mrb_ary_times(mrb_state *mrb, mrb_value self) struct RArray *a1 = mrb_ary_ptr(self); struct RArray *a2; mrb_value ary; - mrb_value *buf; + mrb_value *ptr; mrb_int times; - //size_t len; mrb_get_args(mrb, "i", ×); if (times < 0) { @@ -286,38 +350,32 @@ mrb_ary_times(mrb_state *mrb, mrb_value self) ary = mrb_ary_new_capa(mrb, a1->len * times); a2 = mrb_ary_ptr(ary); - buf = a2->buf; + ptr = a2->ptr; while(times--) { - memcpy(buf, a1->buf, sizeof(mrb_value)*(a1->len)); - buf += a1->len; + memcpy(ptr, a1->ptr, sizeof(mrb_value)*(a1->len)); + ptr += a1->len; a2->len += a1->len; } return ary; } -static void -ary_reverse(struct RArray *a) -{ - mrb_value *p1, *p2; - - p1 = a->buf; - p2 = a->buf + a->len - 1; - - while(p1 < p2) { - mrb_value tmp = *p1; - *p1++ = *p2; - *p2-- = tmp; - } -} - mrb_value mrb_ary_reverse_bang(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); if (a->len > 1) { - ary_reverse(a); + mrb_value *p1, *p2; + + p1 = a->ptr; + p2 = a->ptr + a->len - 1; + + while(p1 < p2) { + mrb_value tmp = *p1; + *p1++ = *p2; + *p2-- = tmp; + } } return self; } @@ -325,33 +383,41 @@ mrb_ary_reverse_bang(mrb_state *mrb, mrb_value self) mrb_value mrb_ary_reverse(mrb_state *mrb, mrb_value self) { - struct RArray *a = mrb_ary_ptr(self); + struct RArray *a = mrb_ary_ptr(self), *b; mrb_value ary; ary = mrb_ary_new_capa(mrb, a->len); + b = mrb_ary_ptr(ary); if (a->len > 0) { - mrb_ary_replace(mrb, mrb_ary_ptr(ary), a->buf, a->len); - ary_reverse(mrb_ary_ptr(ary)); + mrb_value *p1, *p2, *e; + + p1 = a->ptr; + e = p1 + a->len; + p2 = b->ptr + a->len - 1; + while(p1 < e) { + *p2-- = *p1++; + } + b->len = a->len; } return ary; } mrb_value -mrb_ary_new4(mrb_state *mrb, long n, const mrb_value *elts) +mrb_ary_new4(mrb_state *mrb, int n, const mrb_value *elts) { mrb_value ary; - ary = mrb_ary_new_capa(mrb, n);//mrb_ary_new2(n); + ary = mrb_ary_new_capa(mrb, n); if (n > 0 && elts) { memcpy(RARRAY_PTR(ary), elts, sizeof(mrb_value)*n); - RARRAY_LEN(ary) = n; //ARY_SET_LEN(ary, n); + RARRAY_LEN(ary) = n; } return ary; } mrb_value -mrb_ary_new_elts(mrb_state *mrb, long n, const mrb_value *elts) +mrb_ary_new_elts(mrb_state *mrb, int n, const mrb_value *elts) { return mrb_ary_new4(mrb, n, elts); } @@ -361,22 +427,14 @@ mrb_ary_push(mrb_state *mrb, mrb_value ary, mrb_value elem) /* mrb_ary_push */ { struct RArray *a = mrb_ary_ptr(ary); - if (a->len == a->capa) mrb_ary_expand_capa(mrb, a, a->len + 1); - a->buf[a->len++] = elem; + ary_modify(mrb, a); + if (a->len == a->aux.capa) + ary_expand_capa(mrb, a, a->len + 1); + a->ptr[a->len++] = elem; mrb_write_barrier(mrb, (struct RBasic*)a); } mrb_value -mrb_ary_pop(mrb_state *mrb, mrb_value ary) -{ - struct RArray *a = mrb_ary_ptr(ary); - - if (a->len == 0) return mrb_nil_value(); - - return a->buf[--a->len]; -} - -mrb_value mrb_ary_push_m(mrb_state *mrb, mrb_value self) { mrb_value *argv; @@ -391,30 +449,45 @@ mrb_ary_push_m(mrb_state *mrb, mrb_value self) } mrb_value -mrb_ary_pop_m(mrb_state *mrb, mrb_value self) +mrb_ary_pop(mrb_state *mrb, mrb_value ary) { - struct RArray *a = mrb_ary_ptr(self); + struct RArray *a = mrb_ary_ptr(ary); - return ((a->len == 0)? mrb_nil_value(): mrb_ary_pop(mrb, self)); + if (a->len == 0) return mrb_nil_value(); + return a->ptr[--a->len]; } +#define ARY_SHIFT_SHARED_MIN 10 + mrb_value mrb_ary_shift(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); - mrb_value *buf = a->buf; - size_t size = a->len; mrb_value val; - if (size == 0) return mrb_nil_value(); - - val = *buf; - while((int)(--size)) { - *buf = *(buf+1); - ++buf; + if (a->len == 0) return mrb_nil_value(); + if (a->flags & MRB_ARY_SHARED) { + L_SHIFT: + val = a->ptr[0]; + a->ptr++; + a->len--; + return val; } - --a->len; + if (a->len > ARY_SHIFT_SHARED_MIN) { + ary_make_shared(mrb, a); + goto L_SHIFT; + } + else { + mrb_value *ptr = a->ptr; + int size = a->len; + val = *ptr; + while((int)(--size)) { + *ptr = *(ptr+1); + ++ptr; + } + --a->len; + } return val; } @@ -427,10 +500,20 @@ mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item) { struct RArray *a = mrb_ary_ptr(self); - if (a->capa < a->len + 1) mrb_ary_expand_capa(mrb, a, a->len + 1); - memmove(a->buf + 1, a->buf, sizeof(mrb_value)*a->len); - memcpy(a->buf, &item, sizeof(mrb_value)); - a->len += 1; + if ((a->flags & MRB_ARY_SHARED) + && a->aux.shared->refcnt == 1 /* shared only referenced from this array */ + && a->ptr - a->aux.shared->ptr >= 1) /* there's room for unshifted item */ { + a->ptr--; + a->ptr[0] = item; + } + else { + ary_modify(mrb, a); + if (a->aux.capa < a->len + 1) + ary_expand_capa(mrb, a, a->len + 1); + memmove(a->ptr + 1, a->ptr, sizeof(mrb_value)*a->len); + a->ptr[0] = item; + } + a->len++; mrb_write_barrier(mrb, (struct RBasic*)a); return self; @@ -444,10 +527,19 @@ mrb_ary_unshift_m(mrb_state *mrb, mrb_value self) int len; mrb_get_args(mrb, "*", &vals, &len); - if (len == 0) return self; - if (a->capa < a->len + len) mrb_ary_expand_capa(mrb, a, a->len + len); - memmove(a->buf + len, a->buf, sizeof(mrb_value)*a->len); - memcpy(a->buf, vals, sizeof(mrb_value)*len); + if ((a->flags & MRB_ARY_SHARED) + && a->aux.shared->refcnt == 1 /* shared only referenced from this array */ + && a->ptr - a->aux.shared->ptr >= len) /* there's room for unshifted item */ { + a->ptr -= len; + } + else { + ary_modify(mrb, a); + if (len == 0) return self; + if (a->aux.capa < a->len + len) + ary_expand_capa(mrb, a, a->len + len); + memmove(a->ptr + len, a->ptr, sizeof(mrb_value)*a->len); + } + memcpy(a->ptr, vals, sizeof(mrb_value)*len); a->len += len; mrb_write_barrier(mrb, (struct RBasic*)a); @@ -461,9 +553,9 @@ mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n) /* range check */ if (n < 0) n += a->len; - if (n < 0 || a->len <= (size_t)n) return mrb_nil_value(); + if (n < 0 || a->len <= (int)n) return mrb_nil_value(); - return a->buf[n]; + return a->ptr[n]; } void @@ -471,18 +563,22 @@ mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val) /* rb_ary_s { struct RArray *a = mrb_ary_ptr(ary); + ary_modify(mrb, a); /* range check */ - if (n < 0) n += a->len; if (n < 0) { - mrb_raise(mrb, E_INDEX_ERROR, "index %ld out of array", n - a->len); + n += a->len; + if (n < 0) { + mrb_raise(mrb, E_INDEX_ERROR, "index %ld out of array", n - a->len); + } } - if (a->len <= (size_t)n) { - if (a->capa <= (size_t)n) mrb_ary_expand_capa(mrb, a, n + 1); - ary_fill_with_nil(a->buf + a->len, n + 1 - a->len); + if (a->len <= (int)n) { + if (a->aux.capa <= (int)n) + ary_expand_capa(mrb, a, n + 1); + ary_fill_with_nil(a->ptr + a->len, n + 1 - a->len); a->len = n + 1; } - a->buf[n] = val; + a->ptr[n] = val; mrb_write_barrier(mrb, (struct RBasic*)a); } @@ -491,14 +587,17 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val { struct RArray *a = mrb_ary_ptr(ary); mrb_int tail; - size_t size; + int size; mrb_value *argv; int i, argc; + ary_modify(mrb, a); /* range check */ - if (head < 0) head += a->len; if (head < 0) { - mrb_raise(mrb, E_INDEX_ERROR, "index is out of array"); + head += a->len; + if (head < 0) { + mrb_raise(mrb, E_INDEX_ERROR, "index is out of array"); + } } tail = head + len; @@ -515,17 +614,18 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val if (tail < a->len) size += a->len - tail; - if (size > a->capa) mrb_ary_expand_capa(mrb, a, size); + if (size > a->aux.capa) + ary_expand_capa(mrb, a, size); if (head > a->len) { - ary_fill_with_nil(a->buf + a->len, (size_t)(head - a->len)); + ary_fill_with_nil(a->ptr + a->len, (int)(head - a->len)); } else if (head < a->len) { - memmove(a->buf + head + argc, a->buf + tail, sizeof(mrb_value)*(a->len - tail)); + memmove(a->ptr + head + argc, a->ptr + tail, sizeof(mrb_value)*(a->len - tail)); } for(i = 0; i < argc; i++) { - *(a->buf + head + i) = *(argv + i); + *(a->ptr + head + i) = *(argv + i); } a->len = size; @@ -539,6 +639,32 @@ mrb_ary_alen(mrb_state *mrb, mrb_value ary) return RARRAY_LEN(ary); } +void +mrb_ary_decref(mrb_state *mrb, struct mrb_shared_array *shared) +{ + shared->refcnt--; + if (shared->refcnt == 0) { + mrb_free(mrb, shared->ptr); + mrb_free(mrb, shared); + } +} + +static mrb_value +ary_subseq(mrb_state *mrb, struct RArray *a, int beg, int len) +{ + struct RArray *b; + + ary_make_shared(mrb, a); + b = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class); + b->ptr = a->ptr + beg; + b->len = len; + b->aux.shared = a->aux.shared; + b->aux.shared->refcnt++; + b->flags |= MRB_ARY_SHARED; + + return mrb_obj_value(b); +} + mrb_value mrb_ary_aget(mrb_state *mrb, mrb_value self) { @@ -556,13 +682,13 @@ mrb_ary_aget(mrb_state *mrb, mrb_value self) if (mrb_type(argv[0]) != MRB_TT_FIXNUM) { mrb_raise(mrb, E_TYPE_ERROR, "expected Fixnum"); } - len = mrb_fixnum(argv[0]); if (index < 0) index += a->len; - if (index < 0 || a->len < (size_t)index) return mrb_nil_value(); - if ((len = mrb_fixnum(argv[0])) < 0) return mrb_nil_value(); - if (a->len == (size_t)index) return mrb_ary_new(mrb); - if ((size_t)len > a->len - index) len = a->len - index; - return mrb_ary_new_from_values(mrb, len, a->buf + index); + if (index < 0 || a->len < (int)index) return mrb_nil_value(); + len = mrb_fixnum(argv[0]); + if (len < 0) return mrb_nil_value(); + if (a->len == (int)index) return mrb_ary_new(mrb); + if ((int)len > a->len - index) len = a->len - index; + return ary_subseq(mrb, a, index, len); default: mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); @@ -606,24 +732,25 @@ mrb_ary_delete_at(mrb_state *mrb, mrb_value self) struct RArray *a = mrb_ary_ptr(self); mrb_int index; mrb_value val; - mrb_value *buf; - size_t len; + mrb_value *ptr; + int len; mrb_get_args(mrb, "i", &index); if (index < 0) index += a->len; - if (index < 0 || a->len <= (size_t)index) return mrb_nil_value(); + if (index < 0 || a->len <= (int)index) return mrb_nil_value(); - val = a->buf[index]; + ary_modify(mrb, a); + val = a->ptr[index]; - buf = a->buf + index; + ptr = a->ptr + index; len = a->len - index; while((int)(--len)) { - *buf = *(buf+1); - ++buf; + *ptr = *(ptr+1); + ++ptr; } --a->len; - mrb_ary_shrink_capa(mrb, a); + ary_shrink_capa(mrb, a); return val; } @@ -632,30 +759,27 @@ mrb_value mrb_ary_first(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); - //mrb_value ary; - size_t size; - mrb_value *vals; - int len; + int size; - mrb_get_args(mrb, "*", &vals, &len); - if (len > 1) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); + if (mrb_get_args(mrb, "|i", &size) == 0) { + return (a->len > 0)? a->ptr[0]: mrb_nil_value(); + } + if (size < 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "negative array size"); } - if (len == 0) return (a->len > 0)? a->buf[0]: mrb_nil_value(); - - /* len == 1 */ - size = mrb_fixnum(*vals); if (size > a->len) size = a->len; - return mrb_ary_new_from_values(mrb, size, a->buf); + if (a->flags & MRB_ARY_SHARED) { + return ary_subseq(mrb, a, 0, size); + } + return mrb_ary_new_from_values(mrb, size, a->ptr); } mrb_value mrb_ary_last(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); - //mrb_value ary; - size_t size; + int size; mrb_value *vals; int len; @@ -664,19 +788,25 @@ mrb_ary_last(mrb_state *mrb, mrb_value self) mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); } - if (len == 0) return (a->len > 0)? a->buf[a->len - 1]: mrb_nil_value(); + if (len == 0) return (a->len > 0)? a->ptr[a->len - 1]: mrb_nil_value(); /* len == 1 */ size = mrb_fixnum(*vals); + if (size < 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "negative array size"); + } if (size > a->len) size = a->len; - return mrb_ary_new_from_values(mrb, size, a->buf + a->len - size); + if ((a->flags & MRB_ARY_SHARED) || size > ARY_DEFAULT_LEN) { + return ary_subseq(mrb, a, a->len - size, size); + } + return mrb_ary_new_from_values(mrb, size, a->ptr + a->len - size); } mrb_value mrb_ary_index_m(mrb_state *mrb, mrb_value self) { mrb_value obj; - long i; + int i; mrb_get_args(mrb, "o", &obj); for (i = 0; i < RARRAY_LEN(self); i++) { @@ -691,7 +821,7 @@ mrb_value mrb_ary_rindex_m(mrb_state *mrb, mrb_value self) { mrb_value obj; - long i; + int i; mrb_get_args(mrb, "o", &obj); for (i = RARRAY_LEN(self) - 1; i >= 0; i--) { @@ -727,7 +857,8 @@ mrb_ary_clear(mrb_state *mrb, mrb_value self) struct RArray *a = mrb_ary_ptr(self); a->len = 0; - mrb_ary_shrink_capa(mrb, a); + ary_modify(mrb, a); + ary_shrink_capa(mrb, a); return self; } @@ -747,7 +878,7 @@ mrb_check_array_type(mrb_state *mrb, mrb_value ary) } mrb_value -mrb_ary_entry(mrb_value ary, long offset) +mrb_ary_entry(mrb_value ary, int offset) { if (offset < 0) { offset += RARRAY_LEN(ary); @@ -755,58 +886,43 @@ mrb_ary_entry(mrb_value ary, long offset) return ary_elt(ary, offset); } -void -mrb_mem_clear(mrb_value *mem, long size) -{ - while (size--) { - *mem++ = mrb_nil_value(); - } -} - -mrb_value -mrb_ary_tmp_new(mrb_state *mrb, long capa) -{ - return mrb_ary_new_capa(mrb, capa);//ary_new(0, capa); -} - static mrb_value inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list) { - long i; + int i; mrb_value s, arystr; - char *head = "["; - char *sep = ", "; - char *tail = "]"; + char head[] = { '[' }; + char sep[] = { ',', ' ' }; + char tail[] = { ']' }; /* check recursive */ for(i=0; i<RARRAY_LEN(list); i++) { if (mrb_obj_equal(mrb, ary, RARRAY_PTR(list)[i])) { - return mrb_str_new2(mrb, "[...]"); + return mrb_str_new(mrb, "[...]", 5); } } mrb_ary_push(mrb, list, ary); arystr = mrb_str_buf_new(mrb, 64); - mrb_str_buf_cat(mrb, arystr, head, strlen(head)); + mrb_str_buf_cat(mrb, arystr, head, sizeof(head)); for(i=0; i<RARRAY_LEN(ary); i++) { int ai = mrb_gc_arena_save(mrb); if (i > 0) { - mrb_str_buf_cat(mrb, arystr, sep, strlen(sep)); + mrb_str_buf_cat(mrb, arystr, sep, sizeof(sep)); } if (mrb_type(RARRAY_PTR(ary)[i]) == MRB_TT_ARRAY) { s = inspect_ary(mrb, RARRAY_PTR(ary)[i], list); } else { s = mrb_inspect(mrb, RARRAY_PTR(ary)[i]); } - //mrb_str_buf_append(mrb, arystr, s); mrb_str_buf_cat(mrb, arystr, RSTRING_PTR(s), RSTRING_LEN(s)); mrb_gc_arena_restore(mrb, ai); } - mrb_str_buf_cat(mrb, arystr, tail, strlen(tail)); + mrb_str_buf_cat(mrb, arystr, tail, sizeof(tail)); mrb_ary_pop(mrb, list); return arystr; @@ -824,7 +940,7 @@ inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list) static mrb_value mrb_ary_inspect(mrb_state *mrb, mrb_value ary) { - if (RARRAY_LEN(ary) == 0) return mrb_str_new2(mrb, "[]"); + if (RARRAY_LEN(ary) == 0) return mrb_str_new(mrb, "[]", 2); #if 0 /* THREAD */ return mrb_exec_recursive(inspect_ary_r, ary, 0); #else @@ -835,7 +951,7 @@ mrb_ary_inspect(mrb_state *mrb, mrb_value ary) static mrb_value join_ary(mrb_state *mrb, mrb_value ary, mrb_value sep, mrb_value list) { - long i; + int i; mrb_value result, val, tmp; /* check recursive */ @@ -851,7 +967,6 @@ join_ary(mrb_state *mrb, mrb_value ary, mrb_value sep, mrb_value list) for(i=0; i<RARRAY_LEN(ary); i++) { if (i > 0 && !mrb_nil_p(sep)) { - //mrb_str_buf_append(mrb, result, sep); // segv (encoding error?) mrb_str_buf_cat(mrb, result, RSTRING_PTR(sep), RSTRING_LEN(sep)); } @@ -864,7 +979,6 @@ join_ary(mrb_state *mrb, mrb_value ary, mrb_value sep, mrb_value list) case MRB_TT_STRING: str_join: - //mrb_str_buf_append(mrb, result, val); mrb_str_buf_cat(mrb, result, RSTRING_PTR(val), RSTRING_LEN(val)); break; @@ -898,7 +1012,7 @@ mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep) /* * call-seq: - * ary.join(sep=nil) -> str + * ary.join(sep="") -> str * * Returns a string created by converting each element of the array to * a string, separated by <i>sep</i>. @@ -912,7 +1026,7 @@ mrb_ary_join_m(mrb_state *mrb, mrb_value ary) { mrb_value sep = mrb_nil_value(); - mrb_get_args(mrb, "|o", &sep); + mrb_get_args(mrb, "|S", &sep); return mrb_ary_join(mrb, ary, sep); } @@ -951,7 +1065,7 @@ mrb_ary_equal(mrb_state *mrb, mrb_value ary1) } if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value(); else { - long i; + int i; for (i=0; i<RARRAY_LEN(ary1); i++) { if (!mrb_equal(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) @@ -980,7 +1094,7 @@ mrb_ary_eql(mrb_state *mrb, mrb_value ary1) if (mrb_type(ary2) != MRB_TT_ARRAY) return mrb_false_value(); if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value(); else { - long i; + int i; for (i=0; i<RARRAY_LEN(ary1); i++) { if (!mrb_eql(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) @@ -1010,13 +1124,13 @@ mrb_init_array(mrb_state *mrb) mrb_define_method(mrb, a, "concat", mrb_ary_concat_m, ARGS_REQ(1)); /* 15.2.12.5.8 */ mrb_define_method(mrb, a, "delete_at", mrb_ary_delete_at, ARGS_REQ(1)); /* 15.2.12.5.9 */ mrb_define_method(mrb, a, "empty?", mrb_ary_empty_p, ARGS_NONE()); /* 15.2.12.5.12 */ - mrb_define_method(mrb, a, "first", mrb_ary_first, ARGS_ANY()); /* 15.2.12.5.13 */ + mrb_define_method(mrb, a, "first", mrb_ary_first, ARGS_OPT(1)); /* 15.2.12.5.13 */ mrb_define_method(mrb, a, "index", mrb_ary_index_m, ARGS_REQ(1)); /* 15.2.12.5.14 */ mrb_define_method(mrb, a, "initialize_copy", mrb_ary_replace_m, ARGS_REQ(1)); /* 15.2.12.5.16 */ mrb_define_method(mrb, a, "join", mrb_ary_join_m, ARGS_ANY()); /* 15.2.12.5.17 */ mrb_define_method(mrb, a, "last", mrb_ary_last, ARGS_ANY()); /* 15.2.12.5.18 */ mrb_define_method(mrb, a, "length", mrb_ary_size, ARGS_NONE()); /* 15.2.12.5.19 */ - mrb_define_method(mrb, a, "pop", mrb_ary_pop_m, ARGS_NONE()); /* 15.2.12.5.21 */ + mrb_define_method(mrb, a, "pop", mrb_ary_pop, ARGS_NONE()); /* 15.2.12.5.21 */ mrb_define_method(mrb, a, "push", mrb_ary_push_m, ARGS_ANY()); /* 15.2.12.5.22 */ mrb_define_method(mrb, a, "replace", mrb_ary_replace_m, ARGS_REQ(1)); /* 15.2.12.5.23 */ mrb_define_method(mrb, a, "reverse", mrb_ary_reverse, ARGS_NONE()); /* 15.2.12.5.24 */ @@ -1031,5 +1145,5 @@ mrb_init_array(mrb_state *mrb) mrb_define_alias(mrb, a, "to_s", "inspect"); /* 15.2.12.5.32 (x) */ mrb_define_method(mrb, a, "==", mrb_ary_equal, ARGS_REQ(1)); /* 15.2.12.5.33 (x) */ mrb_define_method(mrb, a, "eql?", mrb_ary_eql, ARGS_REQ(1)); /* 15.2.12.5.34 (x) */ - mrb_define_method(mrb, a, "<=>", mrb_ary_cmp, ARGS_REQ(1)); /* 15.2.12.5.36 (x) */ + mrb_define_method(mrb, a, "<=>", mrb_ary_cmp, ARGS_REQ(1)); /* 15.2.12.5.36 (x) */ } diff --git a/src/cdump.c b/src/cdump.c index f9525d042..32982e6fe 100644 --- a/src/cdump.c +++ b/src/cdump.c @@ -10,7 +10,6 @@ #include "mruby/irep.h" #include "mruby/string.h" -#include "re.h" #define MRB_CDUMP_LINE_LEN 128 @@ -45,7 +44,7 @@ str_format_len(mrb_value str) char *src; - for (src = RSTRING_PTR(str); src < RSTRING_END(str);) { + for (src = RSTRING_PTR(str); src < RSTRING_END(str); src++) { switch (*src) { case 0x07:/* BEL */ /* fall through */ case 0x08:/* BS */ /* fall through */ @@ -58,11 +57,11 @@ str_format_len(mrb_value str) case 0x27:/* ' */ /* fall through */ case 0x3F:/* ? */ /* fall through */ case 0x5C:/* \ */ /* fall through */ - dump_len += 2; src += 2; + dump_len += 2; break; default: - dump_len++; src++; + dump_len++; break; } } @@ -73,22 +72,23 @@ str_format_len(mrb_value str) static char* str_to_format(mrb_value str, char *buf) { - char *src, *dst; + char *src; + char *dst; - for (src = RSTRING_PTR(str), dst = buf; src < RSTRING_END(str);) { + for (src = RSTRING_PTR(str), dst = buf; src < RSTRING_END(str); src++) { switch (*src) { - case 0x07:/* BEL */ memcpy(dst, "\\a", 2); dst+=2; src+=2; break; - case 0x08:/* BS */ memcpy(dst, "\\b", 2); dst+=2; src+=2; break; - case 0x09:/* HT */ memcpy(dst, "\\t", 2); dst+=2; src+=2; break; - case 0x0A:/* LF */ memcpy(dst, "\\n", 2); dst+=2; src+=2; break; - case 0x0B:/* VT */ memcpy(dst, "\\v", 2); dst+=2; src+=2; break; - case 0x0C:/* FF */ memcpy(dst, "\\f", 2); dst+=2; src+=2; break; - case 0x0D:/* CR */ memcpy(dst, "\\r", 2); dst+=2; src+=2; break; - case 0x22:/* " */ memcpy(dst, "\\\"", 2); dst+=2; src+=2; break; - case 0x27:/* ' */ memcpy(dst, "\\\'", 2); dst+=2; src+=2; break; - case 0x3F:/* ? */ memcpy(dst, "\\\?", 2); dst+=2; src+=2; break; - case 0x5C:/* \ */ memcpy(dst, "\\\\", 2); dst+=2; src+=2; break; - default: *dst++ = *src++; break; + case 0x07:/* BEL */ *dst++ = '\\'; *dst++ = 'a'; break; + case 0x08:/* BS */ *dst++ = '\\'; *dst++ = 'b'; break; + case 0x09:/* HT */ *dst++ = '\\'; *dst++ = 't'; break; + case 0x0A:/* LF */ *dst++ = '\\'; *dst++ = 'n'; break; + case 0x0B:/* VT */ *dst++ = '\\'; *dst++ = 'v'; break; + case 0x0C:/* FF */ *dst++ = '\\'; *dst++ = 'f'; break; + case 0x0D:/* CR */ *dst++ = '\\'; *dst++ = 'r'; break; + case 0x22:/* " */ *dst++ = '\\'; *dst++ = '\"'; break; + case 0x27:/* ' */ *dst++ = '\\'; *dst++ = '\''; break; + case 0x3F:/* ? */ *dst++ = '\\'; *dst++ = '\?'; break; + case 0x5C:/* \ */ *dst++ = '\\'; *dst++ = '\\'; break; + default: *dst++ = *src; break; } } @@ -107,10 +107,11 @@ make_cdump_irep(mrb_state *mrb, int irep_no, FILE *f) return -1; buf_len = MRB_CDUMP_LINE_LEN; - if ((buf = mrb_malloc(mrb, buf_len)) == 0 ) { + if ((buf = (char *)mrb_malloc(mrb, buf_len)) == 0 ) { return MRB_CDUMP_GENERAL_FAILURE; } + SOURCE_CODE0 (" ai = mrb->arena_idx;"); SOURCE_CODE0 (" irep = mrb->irep[idx] = mrb_malloc(mrb, sizeof(mrb_irep));"); SOURCE_CODE0 (" irep->idx = idx++;"); SOURCE_CODE (" irep->flags = %d | MRB_ISEQ_NOFREE;", irep->flags); @@ -137,11 +138,13 @@ make_cdump_irep(mrb_state *mrb, int irep_no, FILE *f) switch (irep->pool[n].tt) { case MRB_TT_FLOAT: SOURCE_CODE(" irep->pool[%d] = mrb_float_value(%.16e);", n, irep->pool[n].value.f); break; - case MRB_TT_STRING: + case MRB_TT_FIXNUM: + SOURCE_CODE(" irep->pool[%d] = mrb_fixnum_value(%d);", n, irep->pool[n].value.i); break; + case MRB_TT_STRING: str_len = str_format_len(irep->pool[n]) + 1; if ( str_len > buf_len ) { buf_len = str_len; - if ((buf = mrb_realloc(mrb, buf, buf_len)) == 0 ) { + if ((buf = (char *)mrb_realloc(mrb, buf, buf_len)) == 0 ) { return MRB_CDUMP_GENERAL_FAILURE; } } @@ -154,6 +157,8 @@ make_cdump_irep(mrb_state *mrb, int irep_no, FILE *f) } else SOURCE_CODE0 (" irep->pool = NULL;"); + SOURCE_CODE0 (" mrb->irep_len = idx;"); + SOURCE_CODE0 (" mrb->arena_idx = ai;"); SOURCE_CODE0(""); return MRB_CDUMP_OK; } @@ -184,6 +189,7 @@ mrb_cdump_irep(mrb_state *mrb, int n, FILE *f,const char *initname) SOURCE_CODE0("{"); SOURCE_CODE0(" int n = mrb->irep_len;"); SOURCE_CODE0(" int idx = n;"); + SOURCE_CODE0(" int ai;"); SOURCE_CODE0(" mrb_irep *irep;"); SOURCE_CODE0(""); SOURCE_CODE (" mrb_add_irep(mrb, idx+%d);", irep_num); @@ -193,9 +199,6 @@ mrb_cdump_irep(mrb_state *mrb, int n, FILE *f,const char *initname) return -1; } - SOURCE_CODE0(" mrb->irep_len = idx;"); - SOURCE_CODE0(""); - SOURCE_CODE0(" extern mrb_value mrb_top_self(mrb_state *mrb);"); SOURCE_CODE0(" mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));"); SOURCE_CODE0("}"); diff --git a/src/class.c b/src/class.c index b13ab2288..7802c34bd 100644 --- a/src/class.c +++ b/src/class.c @@ -15,10 +15,8 @@ #include "mruby/array.h" #include "error.h" -#include "mruby/khash.h" - -KHASH_MAP_INIT_INT(mt, struct RProc*); -KHASH_MAP_INIT_INT(iv, mrb_value); +KHASH_DEFINE(iv, mrb_sym, mrb_value, 1, kh_int_hash_func, kh_int_hash_equal); +KHASH_DEFINE(mt, mrb_sym, struct RProc*, 1, kh_int_hash_func, kh_int_hash_equal); typedef struct fc_result { mrb_sym name; @@ -28,9 +26,6 @@ typedef struct fc_result { struct fc_result *prev; } fcresult_t; -int kiv_lookup(khash_t(iv) *table, mrb_sym key, mrb_value *value); -extern struct kh_iv *mrb_class_tbl; - void mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c) { @@ -42,7 +37,7 @@ mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c) if (kh_exist(h, k)){ struct RProc *m = kh_value(h, k); if (m) { - paint_black(m); + mrb_gc_mark(mrb, (struct RBasic*)m); } } } @@ -120,7 +115,6 @@ mrb_define_module_id(mrb_state *mrb, mrb_sym name) { struct RClass *m = mrb_module_new(mrb); - m->mt = kh_init(mt, mrb); mrb_obj_iv_set(mrb, (struct RObject*)mrb->object_class, name, mrb_obj_value(m)); mrb_name_class(mrb, m, name); @@ -193,34 +187,60 @@ mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super) struct RClass* mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id) { - struct RClass *c = 0; + struct RClass *c, *s; if (mrb_const_defined(mrb, outer, id)) { mrb_value v = mrb_const_get(mrb, outer, id); + mrb_check_type(mrb, v, MRB_TT_CLASS); c = mrb_class_ptr(v); - if (!mrb_nil_p(super) && (c->tt != MRB_TT_CLASS || c->super != mrb_class_ptr(super))) { - c = 0; + if (!mrb_nil_p(super)) { + if (mrb_type(super) != MRB_TT_CLASS) { + mrb_raise(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)", mrb_obj_classname(mrb, super)); + } + + if (!c->super || mrb_class_ptr(super) != mrb_class_real(c->super)) { + mrb_raise(mrb, E_TYPE_ERROR, "superclass mismatch for class %s", mrb_sym2name(mrb, id)); + } } + + return c; } - if (!c) { - struct RClass *s = 0; - if (!mrb_nil_p(super)) { - mrb_check_type(mrb, super, MRB_TT_CLASS); - s = mrb_class_ptr(super); - } - if (!s) { - s = mrb->object_class; + if (!mrb_nil_p(super)) { + if (mrb_type(super) != MRB_TT_CLASS) { + mrb_raise(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)", mrb_obj_classname(mrb, super)); } - c = mrb_class_new(mrb, s); - setup_class(mrb, outer, c, id); - mrb_funcall(mrb, mrb_obj_value(s), "inherited", 1, mrb_obj_value(c)); + s = mrb_class_ptr(super); + } + else { + s = mrb->object_class; } + c = mrb_class_new(mrb, s); + setup_class(mrb, outer, c, id); + mrb_funcall(mrb, mrb_obj_value(s), "inherited", 1, mrb_obj_value(c)); + return c; } +static struct RClass * +class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id) +{ + mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id); + + if (c.tt != MRB_TT_MODULE && c.tt != MRB_TT_CLASS) { + mrb_raise(mrb, E_TYPE_ERROR, "%s is not a class/module", mrb_sym2name(mrb, id)); + } + return mrb_class_ptr(c); +} + +struct RClass * +mrb_class_get(mrb_state *mrb, const char *name) +{ + return class_from_sym(mrb, mrb->object_class, mrb_intern(mrb, name)); +} + /*! * Defines a class under the namespace of \a outer. * \param outer a class which contains the new class. @@ -244,10 +264,7 @@ mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, s mrb_sym id = mrb_intern(mrb, name); if (mrb_const_defined_at(mrb, outer, id)) { - c = mrb_class_from_sym(mrb, outer, id); - if (c->tt != MRB_TT_CLASS) { - mrb_raise(mrb, E_TYPE_ERROR, "%s is not a class", mrb_sym2name(mrb, id)); - } + c = class_from_sym(mrb, outer, id); if (mrb_class_real(c->super) != super) { mrb_name_error(mrb, id, "%s is already defined", mrb_sym2name(mrb, id)); } @@ -259,7 +276,6 @@ mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, s } c = mrb_class_new(mrb, super); setup_class(mrb, mrb_obj_value(outer), c, id); - mrb_const_set(mrb, mrb_obj_value(outer), id, mrb_obj_value(c)); return c; } @@ -271,15 +287,11 @@ mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name) mrb_sym id = mrb_intern(mrb, name); if (mrb_const_defined_at(mrb, outer, id)) { - c = mrb_class_from_sym(mrb, outer, id); - if (c->tt != MRB_TT_MODULE) { - mrb_raise(mrb, E_TYPE_ERROR, "%s is not a module", mrb_sym2name(mrb, id)); - } + c = class_from_sym(mrb, outer, id); return c; } c = mrb_module_new(mrb); setup_class(mrb, mrb_obj_value(outer), c, id); - mrb_const_set(mrb, mrb_obj_value(outer), id, mrb_obj_value(c)); return c; } @@ -316,10 +328,12 @@ mrb_define_method_vm(mrb_state *mrb, struct RClass *c, mrb_sym name, mrb_value b { khash_t(mt) *h = c->mt; khiter_t k; + struct RProc *p; if (!h) h = c->mt = kh_init(mt, mrb); k = kh_put(mt, h, name); - kh_value(h, k) = mrb_proc_ptr(body); + p = mrb_proc_ptr(body); + kh_value(h, k) = p; } static mrb_value @@ -370,6 +384,7 @@ to_hash(mrb_state *mrb, mrb_value val) a: Array [mrb_value*,int] f: Float [mrb_float] i: Integer [mrb_int] + n: Symbol [mrb_sym] &: Block [mrb_value] *: rest argument [mrb_value*,int] |: optional @@ -389,15 +404,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) struct RArray *a = mrb_ary_ptr(mrb->stack[1]); argc = a->len; - sp = a->buf; + sp = a->ptr; } while ((c = *format++)) { switch (c) { case '|': case '*': case '&': break; default: - if (argc <= i) { - if (opt) continue; + if (argc <= i && !opt) { mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); } } @@ -408,8 +422,10 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_value *p; p = va_arg(ap, mrb_value*); - *p = *sp; - i++; sp++; + if (i < argc) { + *p = *sp++; + i++; + } } break; case 'S': @@ -417,8 +433,10 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_value *p; p = va_arg(ap, mrb_value*); - *p = to_str(mrb, *sp); - i++; sp++; + if (i < argc) { + *p = to_str(mrb, *sp++); + i++; + } } break; case 'A': @@ -426,8 +444,10 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_value *p; p = va_arg(ap, mrb_value*); - *p = to_ary(mrb, *sp); - i++; sp++; + if (i < argc) { + *p = to_ary(mrb, *sp++); + i++; + } } break; case 'H': @@ -435,8 +455,10 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_value *p; p = va_arg(ap, mrb_value*); - *p = to_hash(mrb, *sp); - i++; sp++; + if (i < argc) { + *p = to_hash(mrb, *sp++); + i++; + } } break; case 's': @@ -446,13 +468,15 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) char **ps = 0; int *pl = 0; - ss = to_str(mrb, *sp); - s = mrb_str_ptr(ss); ps = va_arg(ap, char**); - *ps = s->buf; pl = va_arg(ap, int*); - *pl = s->len; - i++; sp++; + if (i < argc) { + ss = to_str(mrb, *sp++); + s = mrb_str_ptr(ss); + *ps = s->ptr; + *pl = s->len; + i++; + } } break; case 'z': @@ -461,14 +485,16 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) struct RString *s; char **ps; - ss = to_str(mrb, *sp); - s = mrb_str_ptr(ss); - if (strlen(s->buf) != s->len) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "String contains NUL"); - } ps = va_arg(ap, char**); - *ps = s->buf; - i++; sp++; + if (i < argc) { + ss = to_str(mrb, *sp++); + s = mrb_str_ptr(ss); + if (strlen(s->ptr) != s->len) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "String contains NUL"); + } + *ps = s->ptr; + i++; + } } break; case 'a': @@ -478,13 +504,15 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_value **pb; int *pl; - aa = to_ary(mrb, *sp); - a = mrb_ary_ptr(aa); pb = va_arg(ap, mrb_value**); - *pb = a->buf; pl = va_arg(ap, int*); - *pl = a->len; - i++; sp++; + if (i < argc) { + aa = to_ary(mrb, *sp++); + a = mrb_ary_ptr(aa); + *pb = a->ptr; + *pl = a->len; + i++; + } } break; case 'f': @@ -492,26 +520,29 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_float *p; p = va_arg(ap, mrb_float*); - switch (sp->tt) { - case MRB_TT_FLOAT: - *p = mrb_float(*sp); - break; - case MRB_TT_FIXNUM: - *p = (mrb_float)mrb_fixnum(*sp); - break; - case MRB_TT_FALSE: - *p = 0.0; - break; - default: - { - mrb_value tmp; - - tmp = mrb_convert_type(mrb, *sp, MRB_TT_FLOAT, "Float", "to_f"); - *p = mrb_float(tmp); + if (i < argc) { + switch (sp->tt) { + case MRB_TT_FLOAT: + *p = mrb_float(*sp); + break; + case MRB_TT_FIXNUM: + *p = (mrb_float)mrb_fixnum(*sp); + break; + case MRB_TT_FALSE: + *p = 0.0; + break; + default: + { + mrb_value tmp; + + tmp = mrb_convert_type(mrb, *sp, MRB_TT_FLOAT, "Float", "to_f"); + *p = mrb_float(tmp); + } + break; } - break; - } - i++; sp++; + sp++; + i++; + } } break; case 'i': @@ -519,37 +550,69 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_int *p; p = va_arg(ap, mrb_int*); - switch (sp->tt) { - case MRB_TT_FIXNUM: - *p = mrb_fixnum(*sp); - break; - case MRB_TT_FLOAT: - *p = (mrb_int)mrb_float(*sp); - break; - case MRB_TT_FALSE: - *p = 0; - break; - default: - { - mrb_value tmp; + if (i < argc) { + switch (sp->tt) { + case MRB_TT_FIXNUM: + *p = mrb_fixnum(*sp); + break; + case MRB_TT_FLOAT: + { + mrb_float f = mrb_float(*sp); + + if (!FIXABLE(f)) { + mrb_raise(mrb, E_RANGE_ERROR, "float too big for int"); + } + *p = (mrb_int)f; + } + break; + case MRB_TT_FALSE: + *p = 0; + break; + default: + { + mrb_value tmp; + + tmp = mrb_convert_type(mrb, *sp, MRB_TT_FIXNUM, "Integer", "to_int"); + *p = mrb_fixnum(tmp); + } + break; + } + sp++; + i++; + } + } + break; + case 'n': + { + mrb_sym *symp; + + symp = va_arg(ap, mrb_sym*); + if (i < argc) { + mrb_value ss; - tmp = mrb_convert_type(mrb, *sp, MRB_TT_FIXNUM, "Integer", "to_int"); - *p = mrb_fixnum(tmp); + ss = *sp++; + if (mrb_type(ss) == MRB_TT_SYMBOL) { + *symp = mrb_symbol(ss); } - break; - } - i++; sp++; + else { + *symp = mrb_intern_str(mrb, to_str(mrb, ss)); + } + i++; + } } break; case '&': { - mrb_value *p, *bp = mrb->stack + 1; + mrb_value *p, *bp; p = va_arg(ap, mrb_value*); - if (mrb->ci->argc > 0) { - bp += mrb->ci->argc; + if (mrb->ci->argc < 0) { + bp = mrb->stack + 2; } + else { + bp = mrb->stack + mrb->ci->argc + 1; + } *p = *bp; } break; @@ -579,6 +642,9 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) } } break; + default: + mrb_raise(mrb, E_ARGUMENT_ERROR, "invalide argument specifier %c", c); + break; } } if (!c && argc > i) { @@ -603,28 +669,120 @@ boot_defclass(mrb_state *mrb, struct RClass *super) void mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m) { - struct RClass *ic; + struct RClass *ins_pos; - ic = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, mrb->class_class); - ic->c = m; - ic->mt = m->mt; - ic->iv = m->iv; - ic->super = c->super; - c->super = ic; - mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)ic); + ins_pos = c; + while (m) { + struct RClass *p = c, *ic; + int superclass_seen = 0; + + while(p) { + if (c != p && p->tt == MRB_TT_CLASS) { + superclass_seen = 1; + } + else if (p->mt == m->mt){ + if (p->tt == MRB_TT_ICLASS && !superclass_seen) { + ins_pos = p; + } + goto skip; + } + p = p->super; + } + ic = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, mrb->class_class); + if (m->tt == MRB_TT_ICLASS) { + ic->c = m->c; + } + else { + ic->c = m; + } + ic->mt = m->mt; + ic->iv = m->iv; + ic->super = ins_pos->super; + ins_pos->super = ic; + mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ic); + ins_pos = ic; + skip: + m = m->super; + } } static mrb_value -mrb_mod_include(mrb_state *mrb, mrb_value klass) +mrb_mod_append_features(mrb_state *mrb, mrb_value mod) { - mrb_value mod; + mrb_value klass; - mrb_get_args(mrb, "o", &mod); mrb_check_type(mrb, mod, MRB_TT_MODULE); + mrb_get_args(mrb, "o", &klass); mrb_include_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod)); return mod; } +static mrb_value +mrb_mod_include(mrb_state *mrb, mrb_value klass) +{ + mrb_value *argv; + int argc, i; + + mrb_get_args(mrb, "*", &argv, &argc); + for (i=0; i<argc; i++) { + mrb_check_type(mrb, argv[i], MRB_TT_MODULE); + } + while (argc--) { + mrb_funcall(mrb, argv[argc], "append_features", 1, klass); + mrb_funcall(mrb, argv[argc], "included", 1, klass); + } + + return klass; +} + +static mrb_value +mrb_mod_ancestors(mrb_state *mrb, mrb_value self) +{ + mrb_value result; + struct RClass *c = mrb_class_ptr(self); + + result = mrb_ary_new(mrb); + while (c) { + if (c->tt == MRB_TT_ICLASS) { + mrb_ary_push(mrb, result, mrb_obj_value(c->c)); + } + else { + mrb_ary_push(mrb, result, mrb_obj_value(c)); + } + c = c->super; + } + + return result; +} + +static mrb_value +mrb_mod_extend_object(mrb_state *mrb, mrb_value mod) +{ + mrb_value obj; + + mrb_check_type(mrb, mod, MRB_TT_MODULE); + mrb_get_args(mrb, "o", &obj); + mrb_include_module(mrb, mrb_class_ptr(mrb_singleton_class(mrb, obj)), mrb_class_ptr(mod)); + return mod; +} + +static mrb_value +mrb_mod_included_modules(mrb_state *mrb, mrb_value self) +{ + mrb_value result; + struct RClass *c = mrb_class_ptr(self); + + result = mrb_ary_new(mrb); + while (c) { + if (c->tt == MRB_TT_ICLASS) { + mrb_ary_push(mrb, result, mrb_obj_value(c->c)); + } + c = c->super; + } + + return result; +} + static struct RClass * mrb_singleton_class_ptr(mrb_state *mrb, struct RClass *c) { @@ -648,11 +806,16 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v) switch (mrb_type(v)) { case MRB_TT_FALSE: + if (mrb_nil_p(v)) + return mrb_obj_value(mrb->nil_class); + return mrb_obj_value(mrb->false_class); case MRB_TT_TRUE: + return mrb_obj_value(mrb->true_class); case MRB_TT_SYMBOL: case MRB_TT_FIXNUM: case MRB_TT_FLOAT: - return mrb_nil_value(); /* should raise TypeError */ + mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton"); + return mrb_nil_value(); /* not reached */ default: break; } @@ -662,15 +825,16 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v) } void -mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec) +mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, int aspec) { - mrb_define_method_id(mrb, c->c, mrb_intern(mrb, name), func, aspec); + o->c = mrb_singleton_class_ptr(mrb, o->c); + mrb_define_method_id(mrb, o->c, mrb_intern(mrb, name), func, aspec); } void -mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, int aspec) +mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec) { - mrb_define_method_id(mrb, mrb_singleton_class_ptr(mrb, o->c), mrb_intern(mrb, name), func, aspec); + mrb_define_singleton_method(mrb, (struct RObject*)c, name, func, aspec); } void @@ -716,34 +880,48 @@ mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid) return m; } +#ifndef MRB_FUNCALL_ARGC_MAX +#define MRB_FUNCALL_ARGC_MAX 16 +#endif + mrb_value -mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc,...) +mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...) { - mrb_value args[16]; + mrb_sym mid = mrb_intern(mrb, name); va_list ap; int i; if (argc == 0) { - for (i=0; i<5; i++) { - args[i] = mrb_nil_value(); - } + return mrb_funcall_argv(mrb, self, mid, 0, 0); + } + else if (argc == 1) { + mrb_value v; + + va_start(ap, argc); + v = va_arg(ap, mrb_value); + va_end(ap); + return mrb_funcall_argv(mrb, self, mid, 1, &v); } else { + mrb_value argv[MRB_FUNCALL_ARGC_MAX]; + + if (argc > MRB_FUNCALL_ARGC_MAX) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%d)", MRB_FUNCALL_ARGC_MAX); + } + va_start(ap, argc); - // assert(argc < 16); - for (i=0; i<argc; i++) { - args[i] = va_arg(ap, mrb_value); + for (i = 0; i < argc; i++) { + argv[i] = va_arg(ap, mrb_value); } va_end(ap); + return mrb_funcall_argv(mrb, self, mid, argc, argv); } - return mrb_funcall_argv(mrb, self, name, argc, args); } - void mrb_obj_call_init(mrb_state *mrb, mrb_value obj, int argc, mrb_value *argv) { - mrb_funcall_argv(mrb, obj, "initialize", argc, argv); + mrb_funcall_argv(mrb, obj, mrb_intern(mrb, "initialize"), argc, argv); } /* @@ -782,7 +960,7 @@ mrb_class_new_instance_m(mrb_state *mrb, mrb_value klass) c = (struct RClass*)mrb_obj_alloc(mrb, k->tt, k); c->super = k; obj = mrb_obj_value(c); - mrb_funcall_with_block(mrb, obj, "initialize", argc, argv, blk); + mrb_funcall_with_block(mrb, obj, mrb_intern(mrb, "initialize"), argc, argv, blk); return obj; } @@ -801,11 +979,39 @@ mrb_instance_new(mrb_state *mrb, mrb_value cv) o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c); obj = mrb_obj_value(o); mrb_get_args(mrb, "*&", &argv, &argc, &blk); - mrb_funcall_with_block(mrb, obj, "initialize", argc, argv, blk); + mrb_funcall_with_block(mrb, obj, mrb_intern(mrb, "initialize"), argc, argv, blk); return obj; } +mrb_value +mrb_class_new_class(mrb_state *mrb, mrb_value cv) +{ + mrb_value super; + struct RClass *new_class; + + if (mrb_get_args(mrb, "|o", &super) == 0) { + super = mrb_obj_value(mrb->object_class); + } + new_class = mrb_class_new(mrb, mrb_class_ptr(super)); + return mrb_obj_value(new_class); +} + +mrb_value +mrb_class_superclass(mrb_state *mrb, mrb_value klass) +{ + struct RClass *c; + mrb_value superclass; + + c = mrb_class_ptr(klass); + if (c->super) + superclass = mrb_obj_value(mrb_class_real(c->super)); + else + superclass = mrb_nil_value(); + + return superclass; +} + static mrb_value mrb_bob_init(mrb_state *mrb, mrb_value cv) { @@ -878,8 +1084,14 @@ mrb_obj_respond_to(struct RClass* c, mrb_sym mid) if (h) { k = kh_get(mt, h, mid); - if (k != kh_end(h)) - return 1; /* exist method */ + if (k != kh_end(h)) { + if (kh_value(h, k)) { + return 1; /* exist method */ + } + else { + return 0; + } + } } c = c->super; } @@ -896,6 +1108,8 @@ mrb_value mrb_class_path(mrb_state *mrb, struct RClass *c) { mrb_value path; + const char *name; + int len; path = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__")); if (mrb_nil_p(path)) { @@ -903,14 +1117,16 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) mrb_sym sym = class_sym(mrb, c, outer); if (outer && outer != mrb->object_class) { mrb_value base = mrb_class_path(mrb, outer); - path = mrb_str_plus(mrb, base, mrb_str_new_cstr(mrb, "::")); - mrb_str_concat(mrb, path, mrb_str_new_cstr(mrb, mrb_sym2name(mrb, sym))); + path = mrb_str_plus(mrb, base, mrb_str_new(mrb, "::", 2)); + name = mrb_sym2name_len(mrb, sym, &len); + mrb_str_concat(mrb, path, mrb_str_new(mrb, name, len)); } else if (sym == 0) { return mrb_nil_value(); } else { - path = mrb_str_new_cstr(mrb, mrb_sym2name(mrb, sym)); + name = mrb_sym2name_len(mrb, sym, &len); + path = mrb_str_new(mrb, name, len); } mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__"), path); } @@ -931,7 +1147,7 @@ mrb_class_name(mrb_state *mrb, struct RClass* c) { mrb_value path = mrb_class_path(mrb, c); if (mrb_nil_p(path)) return 0; - return mrb_str_ptr(path)->buf; + return mrb_str_ptr(path)->ptr; } const char* @@ -976,6 +1192,9 @@ mrb_class_new(mrb_state *mrb, struct RClass *super) mrb_check_inheritable(mrb, super); } c = boot_defclass(mrb, super); + if (super){ + MRB_SET_INSTANCE_TT(c, MRB_INSTANCE_TT(super)); + } make_metaclass(mrb, c); return c; @@ -988,6 +1207,7 @@ struct RClass * mrb_module_new(mrb_state *mrb) { struct RClass *m = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_MODULE, mrb->module_class); + m->mt = kh_init(mt, mrb); return m; } @@ -1044,9 +1264,8 @@ mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const static mrb_value mrb_mod_to_s(mrb_state *mrb, mrb_value klass) { - //if (FL_TEST(klass, FL_SINGLETON)) { if (mrb_type(klass) == MRB_TT_SCLASS) { - mrb_value s = mrb_str_new_cstr(mrb, "#<"); + mrb_value s = mrb_str_new(mrb, "#<", 2); mrb_value v = mrb_iv_get(mrb, klass, mrb_intern(mrb, "__attached__")); mrb_str_cat2(mrb, s, "Class:"); @@ -1065,25 +1284,25 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass) } else { struct RClass *c = mrb_class_ptr(klass); - const char *cn = mrb_class_name(mrb, c); + const char *cn = mrb_class_name(mrb, c); if (!cn) { char buf[256]; - + int n = 0; switch (mrb_type(klass)) { case MRB_TT_CLASS: - snprintf(buf, 256, "#<Class:%p>", c); + n = snprintf(buf, sizeof(buf), "#<Class:%p>", c); break; case MRB_TT_MODULE: - snprintf(buf, 256, "#<Module:%p>", c); + n = snprintf(buf, sizeof(buf), "#<Module:%p>", c); break; default: break; } - return mrb_str_dup(mrb, mrb_str_new_cstr(mrb, buf)); + return mrb_str_dup(mrb, mrb_str_new(mrb, buf, n)); } else { return mrb_str_dup(mrb, mrb_str_new_cstr(mrb, cn)); @@ -1119,6 +1338,12 @@ mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name) undef_method(mrb, c, mrb_intern(mrb, name)); } +void +mrb_undef_class_method(mrb_state *mrb, struct RClass *c, const char *name) +{ + mrb_undef_method(mrb, mrb_class_ptr(mrb_singleton_class(mrb, mrb_obj_value(c))), name); +} + mrb_value mrb_mod_undef(mrb_state *mrb, mrb_value mod) { @@ -1134,11 +1359,29 @@ mrb_mod_undef(mrb_state *mrb, mrb_value mod) return mrb_nil_value(); } +static mrb_value +mod_define_method(mrb_state *mrb, mrb_value self) +{ + struct RClass *c = mrb_class_ptr(self); + struct RProc *p; + mrb_sym mid; + mrb_value blk; + + mrb_get_args(mrb, "n&", &mid, &blk); + if (mrb_nil_p(blk)) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); + } + p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class); + mrb_proc_copy(p, mrb_proc_ptr(blk)); + mrb_define_method_raw(mrb, c, mid, p); + return blk; +} + static mrb_sym mrb_sym_value(mrb_state *mrb, mrb_value val) { if(val.tt == MRB_TT_STRING) { - return mrb_intern(mrb, RSTRING_PTR(val)); + return mrb_intern_str(mrb, val); } else if(val.tt != MRB_TT_SYMBOL) { mrb_value obj = mrb_funcall(mrb, val, "inspect", 0); @@ -1225,17 +1468,28 @@ mrb_init_class(mrb_state *mrb) MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS); mrb_define_method(mrb, bob, "initialize", mrb_bob_init, ARGS_NONE()); mrb_define_method(mrb, bob, "!", mrb_bob_not, ARGS_NONE()); - mrb_define_method(mrb, bob, "method_missing", mrb_bob_missing, ARGS_ANY()); /* 15.3.1.3.30 */ - mrb_define_method(mrb, cls, "new", mrb_instance_new, ARGS_ANY()); + mrb_define_method(mrb, bob, "method_missing", mrb_bob_missing, ARGS_ANY()); /* 15.3.1.3.30 */ + mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, ARGS_ANY()); + mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, ARGS_NONE()); /* 15.2.3.3.4 */ + mrb_define_method(mrb, cls, "new", mrb_instance_new, ARGS_ANY()); /* 15.2.3.3.3 */ mrb_define_method(mrb, cls, "inherited", mrb_bob_init, ARGS_REQ(1)); - mrb_define_method(mrb, mod, "include", mrb_mod_include, ARGS_REQ(1)); + mrb_define_method(mrb, mod, "extend_object", mrb_mod_extend_object, ARGS_REQ(1)); /* 15.2.2.4.25 */ + mrb_define_method(mrb, mod, "extended", mrb_bob_init, ARGS_REQ(1)); /* 15.2.2.4.26 */ + mrb_define_method(mrb, mod, "include", mrb_mod_include, ARGS_ANY()); /* 15.2.2.4.27 */ + mrb_define_method(mrb, mod, "append_features", mrb_mod_append_features, ARGS_REQ(1)); /* 15.2.2.4.10 */ + mrb_define_method(mrb, mod, "included", mrb_bob_init, ARGS_REQ(1)); /* 15.2.2.4.29 */ + mrb_define_method(mrb, mod, "included_modules", mrb_mod_included_modules, ARGS_NONE()); /* 15.2.2.4.30 */ mrb_define_method(mrb, mod, "to_s", mrb_mod_to_s, ARGS_NONE()); - mrb_define_method(mrb, mod, "alias_method", mrb_mod_alias, ARGS_ANY()); - mrb_define_method(mrb, mod, "undef_method", mrb_mod_undef, ARGS_ANY()); - mrb_define_method(mrb, mod, "const_defined?", mrb_mod_const_defined, ARGS_REQ(1)); - mrb_define_method(mrb, mod, "const_get", mrb_mod_const_get, ARGS_REQ(1)); - mrb_define_method(mrb, mod, "const_set", mrb_mod_const_set, ARGS_REQ(2)); + mrb_define_method(mrb, mod, "alias_method", mrb_mod_alias, ARGS_ANY()); /* 15.2.2.4.8 */ + mrb_define_method(mrb, mod, "ancestors", mrb_mod_ancestors, ARGS_NONE()); /* 15.2.2.4.9 */ + mrb_define_method(mrb, mod, "undef_method", mrb_mod_undef, ARGS_ANY()); /* 15.2.2.4.41 */ + mrb_define_method(mrb, mod, "const_defined?", mrb_mod_const_defined, ARGS_REQ(1)); /* 15.2.2.4.20 */ + mrb_define_method(mrb, mod, "const_get", mrb_mod_const_get, ARGS_REQ(1)); /* 15.2.2.4.21 */ + mrb_define_method(mrb, mod, "const_set", mrb_mod_const_set, ARGS_REQ(2)); /* 15.2.2.4.23 */ + mrb_define_method(mrb, mod, "define_method", mod_define_method, ARGS_REQ(1)); mrb_define_method(mrb, mod, "===", mrb_mod_eqq, ARGS_REQ(1)); + mrb_undef_method(mrb, cls, "append_features"); + mrb_undef_method(mrb, cls, "extend_object"); } diff --git a/src/codegen.c b/src/codegen.c index 505f0ad5b..bf6fd0b3e 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -10,12 +10,13 @@ #include "mruby.h" #include "mruby/string.h" #include "mruby/irep.h" -#include "mruby/proc.h" #include "mruby/compile.h" +#include "mruby/numeric.h" #include "opcode.h" #include "node.h" #include <string.h> #include <stdlib.h> +#include <ctype.h> typedef mrb_ast_node node; typedef struct mrb_parser_state parser_state; @@ -47,7 +48,8 @@ typedef struct scope { int sp; int pc; int lastlabel; - int ainfo; + int ainfo:15; + int mscope:1; struct loopinfo *loop; int ensure_level; @@ -89,7 +91,9 @@ codegen_error(codegen_scope *s, const char *message) s = s->prev; } mrb_pool_close(s->mpool); +#ifdef ENABLE_STDIO fprintf(stderr, "codegen error: %s\n", message); +#endif longjmp(s->jmp, 1); } @@ -132,7 +136,7 @@ genop(codegen_scope *s, mrb_code i) { if (s->pc == s->icapa) { s->icapa *= 2; - s->iseq = codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa); + s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa); } s->iseq[s->pc] = i; s->pc++; @@ -141,7 +145,7 @@ genop(codegen_scope *s, mrb_code i) static void genop_peep(codegen_scope *s, mrb_code i, int val) { - // peephole optimization + /* peephole optimization */ if (!val && s->lastlabel != s->pc && s->pc > 0) { mrb_code i0 = s->iseq[s->pc-1]; int c1 = GET_OPCODE(i); @@ -152,9 +156,13 @@ genop_peep(codegen_scope *s, mrb_code i, int val) switch (c0) { case OP_MOVE: if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i) == GETARG_B(i0) && GETARG_A(i) >= s->nlocals) { - // skip swapping OP_MOVE + /* skip swapping OP_MOVE */ return; } + if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { + s->iseq[s->pc-1] = MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_B(i0)); + return; + } break; case OP_LOADI: if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { @@ -180,7 +188,6 @@ genop_peep(codegen_scope *s, mrb_code i, int val) case OP_GETSPECIAL: case OP_LOADL: case OP_STRING: - case OP_GETMCNST: if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { s->iseq[s->pc-1] = MKOP_ABx(c0, GETARG_A(i), GETARG_Bx(i0)); return; @@ -202,29 +209,27 @@ genop_peep(codegen_scope *s, mrb_code i, int val) return; } break; + default: + break; } break; case OP_SETIV: case OP_SETCV: case OP_SETCONST: case OP_SETMCNST: - switch (c0) { - case OP_MOVE: + if (c0 == OP_MOVE) { if (GETARG_A(i) == GETARG_A(i0)) { s->iseq[s->pc-1] = MKOP_ABx(c1, GETARG_B(i0), GETARG_Bx(i)); return; } - break; } break; case OP_SETUPVAR: - switch (c0) { - case OP_MOVE: + if (c0 == OP_MOVE) { if (GETARG_A(i) == GETARG_A(i0)) { s->iseq[s->pc-1] = MKOP_ABC(c1, GETARG_B(i0), GETARG_B(i), GETARG_C(i)); return; } - break; } break; case OP_EPOP: @@ -239,6 +244,52 @@ genop_peep(codegen_scope *s, mrb_code i, int val) return; } break; + case OP_RETURN: + switch (c0) { + case OP_MOVE: + s->iseq[s->pc-1] = MKOP_AB(OP_RETURN, GETARG_B(i0), OP_R_NORMAL); + return; + case OP_LOADI: + s->iseq[s->pc-1] = MKOP_AsBx(OP_LOADI, 0, GETARG_sBx(i0)); + genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); + return; + case OP_ARRAY: + case OP_HASH: + case OP_RANGE: + case OP_AREF: + case OP_GETUPVAR: + s->iseq[s->pc-1] = MKOP_ABC(c0, 0, GETARG_B(i0), GETARG_C(i0)); + genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); + return; + case OP_LOADSYM: + case OP_GETGLOBAL: + case OP_GETIV: + case OP_GETCV: + case OP_GETCONST: + case OP_GETSPECIAL: + case OP_LOADL: + case OP_STRING: + s->iseq[s->pc-1] = MKOP_ABx(c0, 0, GETARG_Bx(i0)); + genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); + return; + case OP_SCLASS: + s->iseq[s->pc-1] = MKOP_AB(c0, GETARG_A(i), GETARG_B(i0)); + genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); + return; + case OP_LOADNIL: + case OP_LOADSELF: + case OP_LOADT: + case OP_LOADF: + case OP_OCLASS: + s->iseq[s->pc-1] = MKOP_A(c0, 0); + genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); + return; + default: + break; + } + break; + default: + break; } } genop(s, i); @@ -265,7 +316,9 @@ dispatch(codegen_scope *s, int pc) case OP_ONERR: break; default: +#ifdef ENABLE_STDIO fprintf(stderr, "bug: dispatch on non JMP op\n"); +#endif scope_error(s); } s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff); @@ -297,21 +350,10 @@ push_(codegen_scope *s) s->sp++; nregs_update; } -#if 0 -static void -push_n_(codegen_scope *s, int n) -{ - if (s->sp + n > 511) { - codegen_error(s, "too complex expression"); - } - s->sp += n; - nregs_update; -} -#endif #define push() push_(s) -#define push_n(n) push_n_(s, n) -#define pop() (s->sp--) +#define pop_(s) ((s)->sp--) +#define pop() pop_(s) #define pop_n(n) (s->sp-=(n)) #define cursp() (s->sp) @@ -321,11 +363,11 @@ new_lit(codegen_scope *s, mrb_value val) int i; for (i=0; i<s->plen; i++) { - if (memcmp(&s->pool[i], &val, sizeof(mrb_value)) == 0) return i; + if (mrb_obj_equal(s->mrb, s->pool[i], val)) return i; } if (s->plen == s->pcapa) { s->pcapa *= 2; - s->pool = codegen_realloc(s, s->pool, sizeof(mrb_value)*s->pcapa); + s->pool = (mrb_value *)codegen_realloc(s, s->pool, sizeof(mrb_value)*s->pcapa); } s->pool[s->plen] = val; return s->plen++; @@ -359,7 +401,7 @@ new_sym(codegen_scope *s, mrb_sym sym) if (s->syms[i] == sym) return i; } if (s->slen > 125 && s->slen < 256) { - s->syms = codegen_realloc(s, s->syms, sizeof(mrb_sym)*65536); + s->syms = (mrb_sym *)codegen_realloc(s, s->syms, sizeof(mrb_sym)*65536); memset(s->syms+s->slen, 0, sizeof(mrb_sym)*(256-s->slen)); s->slen = 256; } @@ -429,7 +471,7 @@ for_body(codegen_scope *s, node *tree) pop(); c = s->iseq[s->pc-1]; if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) { - genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL)); + genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); } loop_pop(s, NOVAL); scope_finish(s, idx); @@ -448,6 +490,7 @@ lambda_body(codegen_scope *s, node *tree, int blk) s = scope_new(s->mrb, s, tree->car); idx = s->idx; + s->mscope = !blk; if (blk) { struct loopinfo *lp = loop_push(s, LOOP_BLOCK); @@ -484,10 +527,10 @@ lambda_body(codegen_scope *s, node *tree, int blk) pos = new_label(s); for (i=0; i<oa; i++) { new_label(s); - genop(s, MKOP_Ax(OP_JMP, 0)); + genop(s, MKOP_sBx(OP_JMP, 0)); } if (oa > 0) { - genop(s, MKOP_Ax(OP_JMP, 0)); + genop(s, MKOP_sBx(OP_JMP, 0)); } opt = tree->car->cdr->car; i = 0; @@ -510,7 +553,13 @@ lambda_body(codegen_scope *s, node *tree, int blk) pop(); c = s->iseq[s->pc-1]; if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) { - genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL)); + if (s->nregs == 0) { + genop(s, MKOP_A(OP_LOADNIL, 0)); + genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); + } + else { + genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); + } } if (blk) { loop_pop(s, NOVAL); @@ -526,13 +575,19 @@ scope_body(codegen_scope *s, node *tree) codegen_scope *scope = scope_new(s->mrb, s, tree->car); int idx = scope->idx; + codegen(scope, tree->cdr, VAL); if (!s->iseq) { - codegen(scope, tree->cdr, VAL); genop(scope, MKOP_A(OP_STOP, 0)); } else { - codegen(scope, tree->cdr, VAL); - genop(scope, MKOP_AB(OP_RETURN, scope->sp, OP_R_NORMAL)); + pop_(scope); + if (scope->nregs == 0) { + genop(scope, MKOP_A(OP_LOADNIL, 0)); + genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); + } + else { + genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp, OP_R_NORMAL), NOVAL); + } } scope_finish(scope, idx); @@ -552,16 +607,17 @@ nosplat(node *t) static mrb_sym attrsym(codegen_scope *s, mrb_sym a) { - const char *name = mrb_sym2name(s->mrb, a); + const char *name; + int len; char *name2; - size_t len = strlen(name); - name2 = codegen_palloc(s, len+1); - strcpy(name2, name); + name = mrb_sym2name_len(s->mrb, a, &len); + name2 = (char *)codegen_palloc(s, len+1); + memcpy(name2, name, len); name2[len] = '='; name2[len+1] = '\0'; - return mrb_intern(s->mrb, name2); + return mrb_intern2(s->mrb, name2, len+1); } static int @@ -607,7 +663,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val) { mrb_sym sym = name ? name : (mrb_sym)tree->cdr->car; int idx; - int n = 0, noop = 0, sendv = 0; + int n = 0, noop = 0, sendv = 0, blk = 0; codegen(s, tree->car, VAL); /* receiver */ idx = new_msym(s, sym); @@ -637,31 +693,44 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val) pop(); } else { - genop(s, MKOP_A(OP_LOADNIL, cursp())); + blk = cursp(); } pop_n(n+1); { - const char *name = mrb_sym2name(s->mrb, sym); + int len; + const char *name = mrb_sym2name_len(s->mrb, sym, &len); - if (!noop && name[0] == '+' && strlen(name) == 1) { + if (!noop && len == 1 && name[0] == '+') { genop(s, MKOP_ABC(OP_ADD, cursp(), idx, n)); } - else if (!noop && name[0] == '-' && strlen(name) == 1) { + else if (!noop && len == 1 && name[0] == '-') { genop(s, MKOP_ABC(OP_SUB, cursp(), idx, n)); } - else if (!noop && name[0] == '<' && strlen(name) == 1) { + else if (!noop && len == 1 && name[0] == '*') { + genop(s, MKOP_ABC(OP_MUL, cursp(), idx, n)); + } + else if (!noop && len == 1 && name[0] == '/') { + genop(s, MKOP_ABC(OP_DIV, cursp(), idx, n)); + } + else if (!noop && len == 1 && name[0] == '<') { genop(s, MKOP_ABC(OP_LT, cursp(), idx, n)); } - else if (!noop && name[0] == '<' && strlen(name) == 2 && name[1] == '=') { + else if (!noop && len == 2 && name[0] == '<' && name[1] == '=') { genop(s, MKOP_ABC(OP_LE, cursp(), idx, n)); } - else if (!noop && name[0] == '>' && strlen(name) == 1) { + else if (!noop && len == 1 && name[0] == '>') { genop(s, MKOP_ABC(OP_GT, cursp(), idx, n)); } - else if (!noop && name[0] == '>' && strlen(name) == 2 && name[1] == '=') { + else if (!noop && len == 2 && name[0] == '>' && name[1] == '=') { genop(s, MKOP_ABC(OP_GE, cursp(), idx, n)); } + else if (!noop && len == 2 && name[0] == '=' && name[1] == '=') { + genop(s, MKOP_ABC(OP_EQ, cursp(), idx, n)); + } else { + if (blk > 0) { /* no block */ + genop(s, MKOP_A(OP_LOADNIL, blk)); + } if (sendv) n = CALL_MAXARGS; genop(s, MKOP_ABC(OP_SEND, cursp(), idx, n)); } @@ -735,7 +804,9 @@ gen_assignment(codegen_scope *s, node *node, int sp, int val) break; default: +#ifdef ENABLE_STDIO printf("unknown lhs %d\n", type); +#endif break; } if (val) push(); @@ -795,6 +866,32 @@ raise_error(codegen_scope *s, const char *msg) genop(s, MKOP_ABx(OP_ERR, 0, idx)); } +static double +readint_float(codegen_scope *s, const char *p, int base) +{ + const char *e = p + strlen(p); + double f = 0; + int n; + + if (*p == '+') p++; + while (p < e) { + char c = *p; + c = tolower((unsigned char)c); + for (n=0; n<base; n++) { + if (mrb_digitmap[n] == c) { + f *= base; + f += n; + break; + } + } + if (n == base) { + codegen_error(s, "malformed readint input"); + } + p++; + } + return f; +} + static void codegen(codegen_scope *s, node *tree, int val) { @@ -838,28 +935,34 @@ codegen(codegen_scope *s, node *tree, int val) push(); while (n2) { node *n3 = n2->car; + node *n4 = n3->car; if (pos1) dispatch(s, pos1); - if (n3->car) { - node *n4 = n3->car; - - pos2 = 0; - while (n4) { + pos2 = 0; + do { + if (n4) { codegen(s, n4->car, VAL); - genop(s, MKOP_AB(OP_MOVE, cursp(), exc)); + } + else { + genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern(s->mrb, "StandardError")))); push(); - genop(s, MKOP_A(OP_LOADNIL, cursp())); - pop(); pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1)); - tmp = new_label(s); - genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); - pos2 = tmp; + } + genop(s, MKOP_AB(OP_MOVE, cursp(), exc)); + push(); + genop(s, MKOP_A(OP_LOADNIL, cursp())); + pop(); pop(); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1)); + tmp = new_label(s); + genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); + pos2 = tmp; + if (n4) { n4 = n4->cdr; } - pos1 = new_label(s); - genop(s, MKOP_Bx(OP_JMP, 0)); - dispatch_linked(s, pos2); - } + } while (n4); + pos1 = new_label(s); + genop(s, MKOP_sBx(OP_JMP, 0)); + dispatch_linked(s, pos2); + pop(); if (n3->cdr->car) { gen_assignment(s, n3->cdr->car, exc, NOVAL); @@ -868,7 +971,7 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, n3->cdr->cdr->car, val); } tmp = new_label(s); - genop(s, MKOP_AsBx(OP_JMP, cursp(), exend)); + genop(s, MKOP_sBx(OP_JMP, exend)); exend = tmp; n2 = n2->cdr; push(); @@ -878,6 +981,7 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_A(OP_RAISE, exc)); } } + pop(); tree = tree->cdr; dispatch(s, noexc); genop(s, MKOP_A(OP_POPERR, 1)); @@ -983,13 +1087,14 @@ codegen(codegen_scope *s, node *tree, int val) struct loopinfo *lp = loop_push(s, LOOP_NORMAL); lp->pc1 = new_label(s); - codegen(s, tree->car, VAL); - pop(); + genop(s, MKOP_sBx(OP_JMP, 0)); lp->pc2 = new_label(s); - genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0)); codegen(s, tree->cdr, NOVAL); - genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc)); - dispatch(s, lp->pc2); + dispatch(s, lp->pc1); + codegen(s, tree->car, VAL); + pop(); + genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc)); + loop_pop(s, val); } break; @@ -999,13 +1104,14 @@ codegen(codegen_scope *s, node *tree, int val) struct loopinfo *lp = loop_push(s, LOOP_NORMAL); lp->pc1 = new_label(s); - codegen(s, tree->car, VAL); - pop(); + genop(s, MKOP_sBx(OP_JMP, 0)); lp->pc2 = new_label(s); - genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0)); codegen(s, tree->cdr, NOVAL); - genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc)); - dispatch(s, lp->pc2); + dispatch(s, lp->pc1); + codegen(s, tree->car, VAL); + pop(); + genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc)); + loop_pop(s, val); } break; @@ -1046,21 +1152,23 @@ codegen(codegen_scope *s, node *tree, int val) } if (tree->car->car) { pos1 = new_label(s); - genop(s, MKOP_AsBx(OP_JMP, cursp(), 0)); + genop(s, MKOP_sBx(OP_JMP, 0)); dispatch_linked(s, pos2); } - pop(); pop(); + pop(); codegen(s, tree->car->cdr, val); + pop(); tmp = new_label(s); - genop(s, MKOP_AsBx(OP_JMP, cursp(), pos3)); + genop(s, MKOP_sBx(OP_JMP, pos3)); pos3 = tmp; if (pos1) dispatch(s, pos1); tree = tree->cdr; - push(); push(); + push(); } pop(); - if (pos3) dispatch_linked(s, pos3); + genop(s, MKOP_A(OP_LOADNIL, cursp())); if (val) push(); + if (pos3) dispatch_linked(s, pos3); } break; @@ -1227,12 +1335,14 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_OP_ASGN: { mrb_sym sym = (mrb_sym)tree->cdr->car; - const char *name = mrb_sym2name(s->mrb, sym); - int idx; + int len; + const char *name = mrb_sym2name_len(s->mrb, sym, &len); + int idx, blk = 0; codegen(s, tree->car, VAL); - if ((name[0] == '|' && strlen(name) == 2 && name[1] == '|') || - (name[0] == '&' && strlen(name) == 2 && name[1] == '&')) { + if (len == 2 && + ((name[0] == '|' && name[1] == '|') || + (name[0] == '&' && name[1] == '&'))) { int pos; pop(); @@ -1245,29 +1355,32 @@ codegen(codegen_scope *s, node *tree, int val) break; } codegen(s, tree->cdr->cdr->car, VAL); - genop(s, MKOP_A(OP_LOADNIL, cursp())); + blk = cursp(); pop(); pop(); idx = new_msym(s, sym); - if (name[0] == '+' && strlen(name) == 1) { + if (len == 1 && name[0] == '+') { genop(s, MKOP_ABC(OP_ADD, cursp(), idx, 1)); } - else if (name[0] == '-' && strlen(name) == 1) { + else if (len == 1 && name[0] == '-') { genop(s, MKOP_ABC(OP_SUB, cursp(), idx, 1)); } - else if (name[0] == '<' && strlen(name) == 1) { + else if (len == 1 && name[0] == '<') { genop(s, MKOP_ABC(OP_LT, cursp(), idx, 1)); } - else if (name[0] == '<' && strlen(name) == 2 && name[1] == '=') { + else if (len == 2 && name[0] == '<' && name[1] == '=') { genop(s, MKOP_ABC(OP_LE, cursp(), idx, 1)); } - else if (name[0] == '>' && strlen(name) == 1) { + else if (len == 1 && name[0] == '>') { genop(s, MKOP_ABC(OP_GT, cursp(), idx, 1)); } - else if (name[0] == '>' && strlen(name) == 2 && name[1] == '=') { + else if (len == 2 && name[0] == '>' && name[1] == '=') { genop(s, MKOP_ABC(OP_GE, cursp(), idx, 1)); } else { + if (blk > 0) { + genop(s, MKOP_A(OP_LOADNIL, blk)); + } genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1)); } } @@ -1276,16 +1389,18 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_SUPER: { - int n = 0; + int n = 0, noop = 0, sendv = 0; - push(); + push(); /* room for receiver */ if (tree) { node *args = tree->car; - while (args) { - codegen(s, args->car, VAL); - n++; - args = args->cdr; - } + if (args) { + n = gen_values(s, args); + if (n < 0) { + n = noop = sendv = 1; + push(); + } + } } if (tree && tree->cdr) { codegen(s, tree->cdr, VAL); @@ -1295,6 +1410,7 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_A(OP_LOADNIL, cursp())); } pop_n(n+1); + if (sendv) n = CALL_MAXARGS; genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, n)); if (val) push(); } @@ -1305,14 +1421,19 @@ codegen(codegen_scope *s, node *tree, int val) codegen_scope *s2 = s; int lv = 0, ainfo = 0; - while (s2->ainfo < 0) { + push(); /* room for receiver */ + while (!s2->mscope) { lv++; s2 = s2->prev; if (!s2) break; } if (s2) ainfo = s2->ainfo; - push(); genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf))); + if (tree && tree->cdr) { + push(); + codegen(s, tree->cdr, VAL); + pop_n(2); + } pop(); genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS)); if (val) push(); @@ -1326,7 +1447,7 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_RETURN)); } else { - genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL)); + genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); } break; @@ -1336,7 +1457,7 @@ codegen(codegen_scope *s, node *tree, int val) int lv = 0, ainfo = 0; int n = 0, sendv = 0; - while (s2->ainfo < 0) { + while (!s2->mscope) { lv++; s2 = s2->prev; if (!s2) break; @@ -1378,7 +1499,7 @@ codegen(codegen_scope *s, node *tree, int val) else { codegen(s, tree, VAL); pop(); - genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL)); + genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); } if (val) push(); break; @@ -1498,10 +1619,11 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_BACK_REF: { char buf[4]; + int len; int sym; - snprintf(buf, 3, "$%c", (int)(intptr_t)tree); - sym = new_sym(s, mrb_intern(s->mrb, buf)); + len = snprintf(buf, sizeof(buf), "$%c", (int)(intptr_t)tree); + sym = new_sym(s, mrb_intern2(s->mrb, buf, len)); genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); push(); } @@ -1510,10 +1632,11 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_NTH_REF: { char buf[4]; + int len; int sym; - snprintf(buf, 3, "$%d", (int)(intptr_t)tree); - sym = new_sym(s, mrb_intern(s->mrb, buf)); + len = snprintf(buf, sizeof(buf), "$%d", (int)(intptr_t)tree); + sym = new_sym(s, mrb_intern2(s->mrb, buf, len)); genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); push(); } @@ -1531,17 +1654,27 @@ codegen(codegen_scope *s, node *tree, int val) if (val) { char *p = (char*)tree->car; int base = (intptr_t)tree->cdr->car; - int i = readint(p, base); + double f; + mrb_int i; mrb_code co; - if (i < MAXARG_sBx && i > -MAXARG_sBx) { - co = MKOP_AsBx(OP_LOADI, cursp(), i); + f = readint_float(s, p, base); + if (!FIXABLE(f)) { + int off = new_lit(s, mrb_float_value(f)); + + genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); } else { - int off = new_lit(s, mrb_fixnum_value(i)); - co = MKOP_ABx(OP_LOADL, cursp(), off); + i = (mrb_int)f; + if (i < MAXARG_sBx && i > -MAXARG_sBx) { + co = MKOP_AsBx(OP_LOADI, cursp(), i); + } + else { + int off = new_lit(s, mrb_fixnum_value(i)); + co = MKOP_ABx(OP_LOADL, cursp(), off); + } + genop(s, co); } - genop(s, co); push(); } break; @@ -1577,18 +1710,27 @@ codegen(codegen_scope *s, node *tree, int val) { char *p = (char*)tree->car; int base = (intptr_t)tree->cdr->car; - int i = readint(p, base); + mrb_float f; + mrb_int i; mrb_code co; - i = -i; - if (i < MAXARG_sBx && i > -MAXARG_sBx) { - co = MKOP_AsBx(OP_LOADI, cursp(), i); - } - else { - int off = new_lit(s, mrb_fixnum_value(i)); - co = MKOP_ABx(OP_LOADL, cursp(), off); - } - genop(s, co); + f = readint_float(s, p, base); + if (!FIXABLE(f)) { + int off = new_lit(s, mrb_float_value(-f)); + + genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); + } + else { + i = (mrb_int)-f; + if (i < MAXARG_sBx && i > -MAXARG_sBx) { + co = MKOP_AsBx(OP_LOADI, cursp(), i); + } + else { + int off = new_lit(s, mrb_fixnum_value(i)); + co = MKOP_ABx(OP_LOADL, cursp(), off); + } + genop(s, co); + } push(); } break; @@ -1654,6 +1796,15 @@ codegen(codegen_scope *s, node *tree, int val) } break; + case NODE_DSYM: + codegen(s, tree, val); + if (val) { + pop(); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "intern")), 0)); + push(); + } + break; + case NODE_SELF: if (val) { genop(s, MKOP_A(OP_LOADSELF, cursp())); @@ -1843,7 +1994,7 @@ static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) { mrb_pool *pool = mrb_pool_open(mrb); - codegen_scope *p = mrb_pool_alloc(pool, sizeof(codegen_scope)); + codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope)); if (!p) return 0; memset(p, 0, sizeof(codegen_scope)); @@ -1852,15 +2003,16 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) if (!prev) return p; p->prev = prev; p->ainfo = -1; + p->mscope = 0; p->mrb = prev->mrb; p->icapa = 1024; - p->iseq = mrb_malloc(mrb, sizeof(mrb_code)*p->icapa); + p->iseq = (mrb_code *)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa); p->pcapa = 32; - p->pool = mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa); + p->pool = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa); - p->syms = mrb_malloc(mrb, sizeof(mrb_sym)*256); + p->syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym)*256); p->lv = lv; p->sp += node_len(lv)+2; @@ -1879,20 +2031,20 @@ scope_finish(codegen_scope *s, int idx) mrb_irep *irep; mrb_add_irep(mrb, idx); - irep = mrb->irep[idx] = mrb_malloc(mrb, sizeof(mrb_irep)); + irep = mrb->irep[idx] = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep)); irep->idx = idx; irep->flags = 0; if (s->iseq) { - irep->iseq = codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc); + irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc); irep->ilen = s->pc; } if (s->pool) { - irep->pool = codegen_realloc(s, s->pool, sizeof(mrb_value)*s->plen); + irep->pool = (mrb_value *)codegen_realloc(s, s->pool, sizeof(mrb_value)*s->plen); irep->plen = s->plen; } if (s->syms) { - irep->syms = codegen_realloc(s, s->syms, sizeof(mrb_sym)*s->slen); + irep->syms = (mrb_sym *)codegen_realloc(s, s->syms, sizeof(mrb_sym)*s->slen); irep->slen = s->slen; } @@ -1906,7 +2058,7 @@ scope_finish(codegen_scope *s, int idx) static struct loopinfo* loop_push(codegen_scope *s, enum looptype t) { - struct loopinfo *p = codegen_palloc(s, sizeof(struct loopinfo)); + struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo)); p->type = t; p->pc1 = p->pc2 = p->pc3 = 0; @@ -1971,6 +2123,7 @@ loop_pop(codegen_scope *s, int val) static void codedump(mrb_state *mrb, int n) { +#ifdef ENABLE_STDIO mrb_irep *irep = mrb->irep[n]; int i; mrb_code c; @@ -1995,7 +2148,7 @@ codedump(mrb_state *mrb, int n) printf("OP_LOADI\tR%d\t%d\n", GETARG_A(c), GETARG_sBx(c)); break; case OP_LOADSYM: - printf("OP_LOADSYM\tR%d\t'%s'\n", GETARG_A(c), + printf("OP_LOADSYM\tR%d\t:%s\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); break; case OP_LOADNIL: @@ -2011,20 +2164,20 @@ codedump(mrb_state *mrb, int n) printf("OP_LOADF\tR%d\n", GETARG_A(c)); break; case OP_GETGLOBAL: - printf("OP_GETGLOBAL\tR%d\t'%s'\n", GETARG_A(c), + printf("OP_GETGLOBAL\tR%d\t:%s\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); break; case OP_SETGLOBAL: - printf("OP_SETGLOBAL\t'%s'\tR%d\n", + printf("OP_SETGLOBAL\t:%s\tR%d\n", mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), GETARG_A(c)); break; case OP_GETCONST: - printf("OP_GETCONST\tR%d\t'%s'\n", GETARG_A(c), + printf("OP_GETCONST\tR%d\t:%s\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); break; case OP_SETCONST: - printf("OP_SETCONST\t'%s'\tR%d\n", + printf("OP_SETCONST\t:%s\tR%d\n", mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), GETARG_A(c)); break; @@ -2073,7 +2226,12 @@ codedump(mrb_state *mrb, int n) printf("OP_JMPNOT\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c)); break; case OP_SEND: - printf("OP_SEND\tR%d\t'%s'\t%d\n", GETARG_A(c), + printf("OP_SEND\tR%d\t:%s\t%d\n", GETARG_A(c), + mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), + GETARG_C(c)); + break; + case OP_TAILCALL: + printf("OP_TAILCALL\tR%d\t:%s\t%d\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), GETARG_C(c)); break; @@ -2128,37 +2286,52 @@ codedump(mrb_state *mrb, int n) printf("OP_RANGE\tR%d\tR%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c)); break; case OP_METHOD: - printf("OP_METHOD\tR%d\t'%s'\n", GETARG_A(c), + printf("OP_METHOD\tR%d\t:%s\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); break; case OP_ADD: - printf("OP_ADD\tR%d\t'%s'\t%d\n", GETARG_A(c), + printf("OP_ADD\tR%d\t:%s\t%d\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), GETARG_C(c)); break; case OP_SUB: - printf("OP_SUB\tR%d\t'%s'\t%d\n", GETARG_A(c), + printf("OP_SUB\tR%d\t:%s\t%d\n", GETARG_A(c), + mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), + GETARG_C(c)); + break; + case OP_MUL: + printf("OP_MUL\tR%d\t:%s\t%d\n", GETARG_A(c), + mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), + GETARG_C(c)); + break; + case OP_DIV: + printf("OP_DIV\tR%d\t:%s\t%d\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), GETARG_C(c)); break; case OP_LT: - printf("OP_LT\tR%d\t'%s'\t%d\n", GETARG_A(c), + printf("OP_LT\tR%d\t:%s\t%d\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), GETARG_C(c)); break; case OP_LE: - printf("OP_LE\tR%d\t'%s'\t%d\n", GETARG_A(c), + printf("OP_LE\tR%d\t:%s\t%d\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), GETARG_C(c)); break; case OP_GT: - printf("OP_GT\tR%d\t'%s'\t%d\n", GETARG_A(c), + printf("OP_GT\tR%d\t:%s\t%d\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), GETARG_C(c)); break; case OP_GE: - printf("OP_GE\tR%d\t'%s'\t%d\n", GETARG_A(c), + printf("OP_GE\tR%d\t:%s\t%d\n", GETARG_A(c), + mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), + GETARG_C(c)); + break; + case OP_EQ: + printf("OP_EQ\tR%d\t:%s\t%d\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), GETARG_C(c)); break; @@ -2183,7 +2356,12 @@ codedump(mrb_state *mrb, int n) printf("OP_APOST\tR%d\t%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c)); break; case OP_STRING: - printf("OP_STRING\tR%d\t'%s'\n", GETARG_A(c), RSTRING_PTR(irep->pool[GETARG_Bx(c)])); + { + mrb_value s = irep->pool[GETARG_Bx(c)]; + + s = mrb_str_dump(mrb, s); + printf("OP_STRING\tR%d\t%s\n", GETARG_A(c), RSTRING_PTR(s)); + } break; case OP_STRCAT: printf("OP_STRCAT\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c)); @@ -2196,11 +2374,11 @@ codedump(mrb_state *mrb, int n) printf("OP_OCLASS\tR%d\n", GETARG_A(c)); break; case OP_CLASS: - printf("OP_CLASS\tR%d\t'%s'\n", GETARG_A(c), + printf("OP_CLASS\tR%d\t:%s\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); break; case OP_MODULE: - printf("OP_MODULE\tR%d\t'%s'\n", GETARG_A(c), + printf("OP_MODULE\tR%d\t:%s\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); break; case OP_EXEC: @@ -2213,7 +2391,7 @@ codedump(mrb_state *mrb, int n) printf("OP_TCLASS\tR%d\n", GETARG_A(c)); break; case OP_ERR: - printf("OP_ERR\t:L(%d)\n", GETARG_Bx(c)); + printf("OP_ERR\tL(%d)\n", GETARG_Bx(c)); break; case OP_EPUSH: printf("OP_EPUSH\t:I(%d)\n", n+GETARG_Bx(c)); @@ -2241,6 +2419,7 @@ codedump(mrb_state *mrb, int n) } } printf("\n"); +#endif } void diff --git a/src/compar.c b/src/compar.c index 1502d450b..1614d2393 100644 --- a/src/compar.c +++ b/src/compar.c @@ -5,41 +5,6 @@ */ #include "mruby.h" -#include "mruby/string.h" -#include "mruby/numeric.h" - -void -mrb_cmperr(mrb_state *mrb, mrb_value x, mrb_value y) -{ - const char *classname; - - if (SPECIAL_CONST_P(y)) { - y = mrb_inspect(mrb, y); - classname = mrb_string_value_ptr(mrb, y); - } - else { - classname = mrb_obj_classname(mrb, y); - } - mrb_raise(mrb, E_ARGUMENT_ERROR, "comparison of %s with %s failed", - mrb_obj_classname(mrb, x), classname); -} - -int -mrb_cmpint(mrb_state *mrb, mrb_value val, mrb_value a, mrb_value b) -{ - if (mrb_nil_p(val)) { - mrb_cmperr(mrb, a, b); - } - if (FIXNUM_P(val)) { - long l = mrb_fixnum(val); - if (l > 0) return 1; - if (l < 0) return -1; - return 0; - } - if (mrb_test(mrb_funcall(mrb, val, ">", 1, mrb_fixnum_value(0)))) return 1; - if (mrb_test(mrb_funcall(mrb, val, "<", 1, mrb_fixnum_value(0)))) return -1; - return 0; -} void mrb_init_comparable(mrb_state *mrb) diff --git a/src/dump.c b/src/dump.c index f3cbef3a0..230ba9bba 100644 --- a/src/dump.c +++ b/src/dump.c @@ -8,7 +8,7 @@ #include "mruby/dump.h" #include "mruby/string.h" -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP #include "re.h" #endif #include "mruby/irep.h" @@ -222,22 +222,23 @@ get_pool_block_size(mrb_state *mrb, mrb_irep *irep, int type) for (pool_no = 0; pool_no < irep->plen; pool_no++) { uint16_t nlen =0; + int len; switch (irep->pool[pool_no].tt) { case MRB_TT_FIXNUM: - sprintf( buf, "%d", irep->pool[pool_no].value.i); - size += strlen(buf); + len = sprintf( buf, "%d", irep->pool[pool_no].value.i); + size += (uint32_t)len; break; case MRB_TT_FLOAT: - sprintf( buf, "%.16e", irep->pool[pool_no].value.f); - size += strlen(buf); + len = sprintf( buf, "%.16e", irep->pool[pool_no].value.f); + size += (uint32_t)len; break; case MRB_TT_STRING: str = mrb_string_value( mrb, &irep->pool[pool_no]); nlen = str_dump_len(RSTRING_PTR(str), RSTRING_LEN(str), type); size += nlen; break; -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP case MRB_TT_REGEX: str = mrb_reg_to_s(mrb, irep->pool[pool_no]); nlen = str_dump_len(RSTRING_PTR(str), RSTRING_LEN(str), type); @@ -268,8 +269,10 @@ get_syms_block_size(mrb_state *mrb, mrb_irep *irep, int type) size += DUMP_SIZE(MRB_DUMP_SIZE_OF_SHORT, type); /* snl(n) */ if (irep->syms[sym_no] != 0) { - name = mrb_sym2name(mrb, irep->syms[sym_no]); - nlen = str_dump_len((char*)name, strlen(name), type); + int len; + + name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len); + nlen = str_dump_len((char*)name, len, type); size += nlen; /* sn(n) */ } } @@ -329,9 +332,10 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type) char *buf_top = buf; char *char_buf; uint16_t buf_size =0; + int len; buf_size = MRB_DUMP_DEFAULT_STR_LEN; - if ((char_buf = mrb_malloc(mrb, buf_size)) == 0) + if ((char_buf = (char *)mrb_malloc(mrb, buf_size)) == 0) goto error_exit; buf += uint32_dump((uint32_t)irep->plen, buf, type); /* number of pool */ @@ -356,14 +360,14 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type) nlen = str_dump_len(RSTRING_PTR(str), RSTRING_LEN(str), type); if ( nlen > buf_size - 1) { buf_size = nlen + 1; - if ((char_buf = mrb_realloc(mrb, char_buf, buf_size)) == 0) + if ((char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size)) == 0) goto error_exit; memset(char_buf, 0, buf_size); } str_dump(RSTRING_PTR(str), char_buf, RSTRING_LEN(str), type); break; -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP case MRB_TT_REGEX: str = mrb_reg_to_s(mrb, irep->pool[pool_no]); nlen = str_dump_len(RSTRING_PTR(str), RSTRING_LEN(str), type); @@ -382,10 +386,12 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type) continue; } - buf += uint16_dump((uint16_t)strlen(char_buf), buf, type); /* data length */ + len = strlen(char_buf); - memcpy(buf, char_buf, strlen(char_buf)); - buf += strlen(char_buf); + buf += uint16_dump((uint16_t)len, buf, type); /* data length */ + + memcpy(buf, char_buf, len); + buf += len; } error_exit: @@ -403,7 +409,7 @@ write_syms_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type) uint16_t buf_size =0; buf_size = MRB_DUMP_DEFAULT_STR_LEN; - if ((char_buf = mrb_malloc(mrb, buf_size)) == 0) + if ((char_buf = (char *)mrb_malloc(mrb, buf_size)) == 0) goto error_exit; buf += uint32_dump((uint32_t)irep->slen, buf, type); /* number of symbol */ @@ -413,15 +419,17 @@ write_syms_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type) uint16_t nlen =0; if (irep->syms[sym_no] != 0) { - name = mrb_sym2name(mrb, irep->syms[sym_no]); - nlen = str_dump_len((char*)name, strlen(name), type); + int len; + + name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len); + nlen = str_dump_len((char*)name, len, type); if ( nlen > buf_size - 1) { buf_size = nlen + 1; - if ((char_buf = mrb_realloc(mrb, char_buf, buf_size)) == 0) + if ((char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size)) == 0) goto error_exit; } memset(char_buf, 0, buf_size); - str_dump((char*)name, char_buf, strlen(name), type); + str_dump((char*)name, char_buf, len, type); buf += uint16_dump(nlen, buf, type); /* length of symbol name */ memcpy(buf, char_buf, nlen); /* symbol name */ @@ -453,11 +461,10 @@ calc_crc_section(mrb_state *mrb, mrb_irep *irep, uint16_t *crc, int section) default: return MRB_DUMP_GENERAL_FAILURE; } - if ((buf = mrb_malloc(mrb, buf_size)) == 0) + if ((buf = (char *)mrb_calloc(mrb, 1, buf_size)) == 0) return MRB_DUMP_GENERAL_FAILURE; buf_top = buf; - memset(buf, 0, buf_size); switch (section) { case DUMP_IREP_HEADER: buf += write_irep_header(mrb, irep, buf, type); break; @@ -591,13 +598,13 @@ dump_irep_record(mrb_state *mrb, int irep_no, FILE* fp, uint32_t *rlen) if (irep_record_size == 0) return MRB_DUMP_GENERAL_FAILURE; - if ((buf = mrb_malloc(mrb, irep_record_size)) == 0) + if ((buf = (char *)mrb_calloc(mrb, 1, irep_record_size)) == 0) return MRB_DUMP_GENERAL_FAILURE; - memset( buf, 0, irep_record_size); - - if ((rc = write_irep_record(mrb, irep_no, buf, rlen, DUMP_TYPE_HEX)) != MRB_DUMP_OK) + if ((rc = write_irep_record(mrb, irep_no, buf, rlen, DUMP_TYPE_HEX)) != MRB_DUMP_OK) { + rc = MRB_DUMP_GENERAL_FAILURE; goto error_exit; + } if (fwrite(buf, irep_record_size, 1, fp) != 1) @@ -683,7 +690,7 @@ mrb_bdump_irep(mrb_state *mrb, int n, FILE *f,const char *initname) buf_size += get_irep_record_size(mrb, irep_no, DUMP_TYPE_BIN); buf_size += MRB_DUMP_SIZE_OF_LONG; /* end of file */ - if ((buf = mrb_malloc(mrb, buf_size)) == 0) + if ((buf = (char *)mrb_malloc(mrb, buf_size)) == 0) return MRB_DUMP_GENERAL_FAILURE; rc = mrb_write_irep(mrb, n, buf); diff --git a/src/error.c b/src/error.c index ae89541c1..6fe839cb2 100644 --- a/src/error.c +++ b/src/error.c @@ -6,28 +6,15 @@ #include "mruby.h" #include <stdarg.h> -#include <string.h> #include <stdio.h> #include <setjmp.h> #include "error.h" -#include "opcode.h" -#include "mruby/irep.h" -#include "mruby/proc.h" -#include "mruby/numeric.h" #include "mruby/variable.h" #include "mruby/string.h" #include "mruby/class.h" #define warn_printf printf -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - mrb_value mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, long len) { @@ -42,7 +29,6 @@ mrb_exc_new3(mrb_state *mrb, struct RClass* c, mrb_value str) return mrb_funcall(mrb, mrb_obj_value(c), "new", 1, str); } -//mrb_value make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr); /* * call-seq: * Exception.new(msg = nil) -> exception @@ -79,14 +65,14 @@ static mrb_value exc_exception(mrb_state *mrb, mrb_value self) { mrb_value exc; - mrb_value *argv; + mrb_value a; int argc; - mrb_get_args(mrb, "*", &argv, &argc); + argc = mrb_get_args(mrb, "|o", &a); if (argc == 0) return self; - if (argc == 1 && mrb_obj_equal(mrb, self, argv[0])) return self; + if (mrb_obj_equal(mrb, self, a)) return self; exc = mrb_obj_clone(mrb, self); - exc_initialize(mrb, exc); + mrb_iv_set(mrb, exc, mrb_intern(mrb, "mesg"), a); return exc; } @@ -134,20 +120,15 @@ exc_message(mrb_state *mrb, mrb_value exc) static mrb_value exc_inspect(mrb_state *mrb, mrb_value exc) { - mrb_value str, klass; + mrb_value str; - klass = mrb_str_new2(mrb, mrb_obj_classname(mrb, exc)); + str = mrb_str_new2(mrb, mrb_obj_classname(mrb, exc)); exc = mrb_obj_as_string(mrb, exc); - if (RSTRING_LEN(exc) == 0) { - return klass; - } - - str = mrb_str_new2(mrb, "#<"); - mrb_str_append(mrb, str, klass); - mrb_str_cat2(mrb, str, ": "); - mrb_str_append(mrb, str, exc); - mrb_str_cat2(mrb, str, ">"); + if (RSTRING_LEN(exc) > 0) { + mrb_str_cat2(mrb, str, ": "); + mrb_str_append(mrb, str, exc); + } return str; } @@ -163,7 +144,7 @@ exc_equal(mrb_state *mrb, mrb_value exc) if (mrb_obj_equal(mrb, exc, obj)) return mrb_true_value(); if (mrb_obj_class(mrb, exc) != mrb_obj_class(mrb, obj)) { - if ( mrb_respond_to(mrb, obj, mrb_intern(mrb, "message")) ) { + if (mrb_respond_to(mrb, obj, mrb_intern(mrb, "message"))) { mesg = mrb_funcall(mrb, obj, "message", 0); } else @@ -186,24 +167,19 @@ mrb_exc_raise(mrb_state *mrb, mrb_value exc) } void -mrb_raise_va(mrb_state *mrb, struct RClass *c, const char *fmt, va_list args) -{ - char buf[256]; - - vsnprintf(buf, 256, fmt, args); - mrb_exc_raise(mrb, mrb_exc_new(mrb, c, buf, strlen(buf))); -} - -void mrb_raise(mrb_state *mrb, struct RClass *c, const char *fmt, ...) { va_list args; char buf[256]; + int n; va_start(args, fmt); - vsnprintf(buf, 256, fmt, args); + n = vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); - mrb_exc_raise(mrb, mrb_exc_new(mrb, c, buf, strlen(buf))); + if (n < 0) { + n = 0; + } + mrb_exc_raise(mrb, mrb_exc_new(mrb, c, buf, n)); } void @@ -212,51 +188,44 @@ mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...) mrb_value exc, argv[2]; va_list args; char buf[256]; + int n; va_start(args, fmt); - //argv[0] = mrb_vsprintf(fmt, args); - vsnprintf(buf, 256, fmt, args); - argv[0] = mrb_str_new(mrb, buf, strlen(buf)); + n = vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); - - argv[1] = mrb_str_new_cstr(mrb, mrb_sym2name(mrb, id)); - exc = mrb_class_new_instance(mrb, 2, argv, E_NAME_ERROR); + if (n < 0) { + n = 0; + } + argv[0] = mrb_str_new(mrb, buf, n); + argv[1] = mrb_symbol_value(id); /* ignore now */ + exc = mrb_class_new_instance(mrb, 1, argv, E_NAME_ERROR); mrb_exc_raise(mrb, exc); } + mrb_value mrb_sprintf(mrb_state *mrb, const char *fmt, ...) { va_list args; char buf[256]; + int n; va_start(args, fmt); - vsnprintf(buf, 256, fmt, args); + n = vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); - return mrb_str_new(mrb, buf, strlen(buf)); + if (n < 0) { + n = 0; + } + return mrb_str_new(mrb, buf, n); } void mrb_warn(const char *fmt, ...) { va_list args; - char buf[256]; va_start(args, fmt); - snprintf(buf, 256, "warning: %s", fmt); - printf(buf, args); - va_end(args); -} - - -void -mrb_warning(const char *fmt, ...) -{ - va_list args; - char buf[256]; - - va_start(args, fmt); - snprintf(buf, 256, "warning: %s", fmt); - printf(buf, args); + printf("warning: "); + vprintf(fmt, args); va_end(args); } @@ -264,12 +233,12 @@ void mrb_bug(const char *fmt, ...) { va_list args; - char buf[256]; va_start(args, fmt); - snprintf(buf, 256, "bug: %s", fmt); - printf(buf, args); + printf("bug: "); + vprintf(fmt, args); va_end(args); + exit(EXIT_FAILURE); } static const char * @@ -304,28 +273,6 @@ sysexit_status(mrb_state *mrb, mrb_value err) return mrb_fixnum(st); } -void -error_pos(void) -{ -#if 0 - const char *sourcefile = mrb_sourcefile(); - int sourceline = mrb_sourceline(); - - if (sourcefile) { - if (sourceline == 0) { - warn_printf("%s", sourcefile); - } - else if (mrb_frame_callee()) { - warn_printf("%s:%d:in `%s'", sourcefile, sourceline, - mrb_sym2name(mrb, mrb_frame_callee())); - } - else { - warn_printf("%s:%d", sourcefile, sourceline); - } - } -#endif -} - static void set_backtrace(mrb_state *mrb, mrb_value info, mrb_value bt) { @@ -348,7 +295,7 @@ make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr) if (isstr) { mesg = mrb_check_string_type(mrb, argv[0]); if (!mrb_nil_p(mesg)) { - mesg = mrb_exc_new3(mrb, mrb->eRuntimeError_class, mesg); + mesg = mrb_exc_new3(mrb, E_RUNTIME_ERROR, mesg); break; } } @@ -359,20 +306,15 @@ make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr) case 3: n = 1; exception_call: - //if (argv[0] == sysstack_error) return argv[0]; - - //CONST_ID(mrb, exception, "exception"); - //mesg = mrb_check_funcall(mrb, argv[0], exception, n, argv+1); - //if (mrb_nil_p(mesg)) { - // /* undef */ - // mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected"); - //} - if (mrb_respond_to(mrb, argv[0], mrb_intern(mrb, "exception"))) { - mesg = mrb_funcall(mrb, argv[0], "exception", n, argv+1); - } - else { - /* undef */ - mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected"); + { + mrb_sym exc = mrb_intern(mrb, "exception"); + if (mrb_respond_to(mrb, argv[0], exc)) { + mesg = mrb_funcall_argv(mrb, argv[0], exc, n, argv+1); + } + else { + /* undef */ + mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected"); + } } break; @@ -399,16 +341,13 @@ mrb_make_exception(mrb_state *mrb, int argc, mrb_value *argv) void mrb_sys_fail(mrb_state *mrb, const char *mesg) { - mrb_raise(mrb, mrb->eRuntimeError_class, "%s", mesg); + mrb_raise(mrb, E_RUNTIME_ERROR, "%s", mesg); } void mrb_init_exception(mrb_state *mrb) { struct RClass *e; - struct RClass *eIndexError; - struct RClass *eRangeError; - struct RClass *eNameError; mrb->eException_class = e = mrb_define_class(mrb, "Exception", mrb->object_class); /* 15.2.22 */ mrb_define_class_method(mrb, e, "exception", mrb_instance_new, ARGS_ANY()); @@ -419,32 +358,6 @@ mrb_init_exception(mrb_state *mrb) mrb_define_method(mrb, e, "message", exc_message, ARGS_NONE()); mrb_define_method(mrb, e, "inspect", exc_inspect, ARGS_NONE()); - mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */ - mrb->eRuntimeError_class = mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */ - - mrb_define_class(mrb, "TypeError", mrb->eStandardError_class); /* 15.2.29 */ - mrb_define_class(mrb, "ArgumentError", mrb->eStandardError_class); /* 15.2.24 */ - eIndexError = mrb_define_class(mrb, "IndexError", mrb->eStandardError_class); /* 15.2.33 */ - eRangeError = mrb_define_class(mrb, "RangeError", mrb->eStandardError_class); /* 15.2.26 */ - eNameError = mrb_define_class(mrb, "NameError", mrb->eStandardError_class); /* 15.2.31 */ - - mrb_define_class(mrb, "NoMethodError", eNameError); /* 15.2.32 */ - // eScriptError = mrb_define_class(mrb, "ScriptError", mrb->eException_class); /* 15.2.37 */ - // mrb_define_class(mrb, "SyntaxError", eScriptError); /* 15.2.38 */ - // mrb_define_class(mrb, "LoadError", eScriptError); /* 15.2.39 */ - // mrb_define_class(mrb, "NotImplementedError", eScriptError_class); - // mrb_define_class(mrb, "SystemCallError", mrb->eStandardError_class); /* 15.2.36 */ - mrb_define_class(mrb, "LocalJumpError", mrb->eStandardError_class); /* 15.2.25 */ - -#ifdef INCLUDE_REGEX - mrb_define_class(mrb, "RegexpError", mrb->eStandardError_class); /* 15.2.27 */ -#endif - -#ifdef INCLUDE_ENCODING - mrb_define_class(mrb, "EncodingError", mrb->eStandardError_class); -#endif - // mrb_define_class(mrb, "ZeroDivisionError", mrb->eStandardError_class); /* 15.2.30 */ - - mrb_define_class(mrb, "FloatDomainError", eRangeError); - mrb_define_class(mrb, "KeyError", eIndexError); + mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */ + mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */ } diff --git a/src/error.h b/src/error.h index babf93a7d..e4d6acb6c 100644 --- a/src/error.h +++ b/src/error.h @@ -12,13 +12,10 @@ struct RException { }; void mrb_sys_fail(mrb_state *mrb, const char *mesg); -void mrb_exc_raise(mrb_state *mrb, mrb_value mesg); void mrb_bug_errno(const char*, int); int sysexit_status(mrb_state *mrb, mrb_value err); -void error_pos(void); mrb_value mrb_exc_new3(mrb_state *mrb, struct RClass* c, mrb_value str); mrb_value make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr); -mrb_value mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, long len); mrb_value mrb_make_exception(mrb_state *mrb, int argc, mrb_value *argv); mrb_value mrb_sprintf(mrb_state *mrb, const char *fmt, ...); void mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...); @@ -10,14 +10,6 @@ #include "mruby/numeric.h" #include "mruby/data.h" -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - struct RData* mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const struct mrb_data_type *type) { @@ -60,11 +52,6 @@ mrb_check_datatype(mrb_state *mrb, mrb_value obj, const struct mrb_data_type *ty mrb_value mrb_lastline_get(mrb_state *mrb) { - //mrb_value *var = mrb_svar(0); - //if (var) { - // return *var; - //} - //return mrb_nil_value(); mrb_value *argv; int argc; @@ -78,21 +65,6 @@ mrb_lastline_get(mrb_state *mrb) } } -mrb_value -mrb_rescue2(mrb_state *mrb, mrb_value (* b_proc) (ANYARGS), mrb_value *data1, - mrb_value (* r_proc) (ANYARGS), mrb_value *data2, ...) -{ - mrb_value result = (*b_proc) (mrb, data1); - return result; -} - -mrb_value -mrb_rescue(mrb_state *mrb, mrb_value (* b_proc)(ANYARGS), mrb_value *data1, - mrb_value (* r_proc)(ANYARGS), mrb_value *data2) -{ - return mrb_rescue2(mrb, b_proc, data1, r_proc, data2, mrb->eStandardError_class, - mrb_fixnum_value(0)); -} /* ------------------------------------------------ */ /* * Calls func(obj, arg, recursive), where recursive is non-zero if the @@ -111,14 +83,6 @@ mrb_exec_recursive(mrb_state *mrb, mrb_value (*func) (mrb_state *, mrb_value, mr * current method is called recursively on the ordered pair <obj, paired_obj> */ -mrb_value -mrb_exec_recursive_paired(mrb_state *mrb, mrb_value (*func) (mrb_state *, mrb_value, mrb_value, int), - mrb_value obj, mrb_value paired_obj, void* arg) -{ - // return mrb_exec_recursive_paired(mrb, recursive_eql, hash1, hash2, mrb_fixnum_value((int)&data)); - return func(mrb, obj, paired_obj, 0); -} - mrb_sym mrb_to_id(mrb_state *mrb, mrb_value name) { @@ -157,136 +121,64 @@ mrb_block_proc(void) return mrb_nil_value();//proc_new(mrb_cProc, FALSE); } -/* - * Document-method: __id__ - * Document-method: object_id - * - * call-seq: - * obj.__id__ -> fixnum - * obj.object_id -> fixnum - * - * Returns an integer identifier for <i>obj</i>. The same number will - * be returned on all calls to <code>id</code> for a given object, and - * no two active objects will share an id. - * <code>Object#object_id</code> is a different concept from the - * <code>:name</code> notation, which returns the symbol id of - * <code>name</code>. Replaces the deprecated <code>Object#id</code>. - */ +static mrb_int +float_id(mrb_float f) +{ + const char *p = (const char*)&f; + int len = sizeof(f); + mrb_int id = 0; -/* - * call-seq: - * obj.hash -> fixnum - * - * Generates a <code>Fixnum</code> hash value for this object. This - * function must have the property that <code>a.eql?(b)</code> implies - * <code>a.hash == b.hash</code>. The hash value is used by class - * <code>Hash</code>. Any hash value that exceeds the capacity of a - * <code>Fixnum</code> will be truncated before being used. - */ + while (len--) { + id = id*65599 + *p; + p++; + } + id = id + (id>>5); + + return id; +} -int +mrb_int mrb_obj_id(mrb_value obj) { - /* - * 32-bit mrb_value space - * MSB ------------------------ LSB - * false 00000000000000000000000000000000 - * true 00000000000000000000000000000010 - * nil 00000000000000000000000000000100 - * undef 00000000000000000000000000000110 - * symbol ssssssssssssssssssssssss00001110 - * object oooooooooooooooooooooooooooooo00 = 0 (mod sizeof(RVALUE)) - * fixnum fffffffffffffffffffffffffffffff1 - * - * object_id space - * LSB - * false 00000000000000000000000000000000 - * true 00000000000000000000000000000010 - * nil 00000000000000000000000000000100 - * undef 00000000000000000000000000000110 - * symbol 000SSSSSSSSSSSSSSSSSSSSSSSSSSS0 S...S % A = 4 (S...S = s...s * A + 4) - * object oooooooooooooooooooooooooooooo0 o...o % A = 0 - * fixnum fffffffffffffffffffffffffffffff1 bignum if required - * - * where A = sizeof(RVALUE)/4 - * - * sizeof(RVALUE) is - * 20 if 32-bit, double is 4-byte aligned - * 24 if 32-bit, double is 8-byte aligned - * 40 if 64-bit - */ - /* - * 128-bit mrb_value space - * MSB -------- LSB - * x86 [0,1] [2,3] [4,5] [6,7] [8,9] [A,B] [C,D] [E,F] - * 7 6 5 4 3 2 1 0 - * 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF - * FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 - * false 0000000000000000 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000001 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx - * true 0000000000000001 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000010 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx - * nil 0000000000000001 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000001 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx - * undef 0000000000000000 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000101 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx - * symbol ssssssssssssssss ssssssssssssssss xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000100 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx - * object oooooooooooooooo oooooooooooooo00 = 0 (mod sizeof(RVALUE)) - (1)fixnum 0000000000000001 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000011 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx - * float 0000000000000001 0000000000000000 0000000000000000 0000000000000000 xxxxxxxx00000011 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx - * <-- mrb_float --> xxxxxxxx00001101 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx - * - * object_id space - * LSB - * false 0000000000000000 0000000000000000 - * true 0000000000000000 0000000000000010 - * nil 0000000000000000 0000000000000100 - * undef 0000000000000000 0000000000000110 - * symbol 000SSSSSSSSSSSS SSSSSSSSSSSSSSS0 S...S % A = 4 (S...S = s...s * A + 4) - * object ooooooooooooooo ooooooooooooooo0 o...o % A = 0 - * fixnum ffffffffffffffff fffffffffffffff1 bignum if required - * - * where A = sizeof(RVALUE)/4 - * - * sizeof(RVALUE) is - * 20 if 32-bit, double is 4-byte aligned - * 24 if 32-bit, double is 8-byte aligned - * 40 if 64-bit - */ - /* tt:0_27 */ - switch (mrb_type(obj)) { - case MRB_TT_FREE: - return 0; /* not define */ - case MRB_TT_FALSE: - if (mrb_nil_p(obj)) - return 4; - return 0; - case MRB_TT_TRUE: - return 2; - case MRB_TT_FIXNUM: - return mrb_fixnum(obj)*2+1; /* odd number */ - case MRB_TT_SYMBOL: - return SYM2ID(obj) * 2; - case MRB_TT_UNDEF: - return 0; /* not define */ - case MRB_TT_FLOAT: - return (int)mrb_float(obj)*2; /* even number */ - case MRB_TT_OBJECT: - case MRB_TT_CLASS: - case MRB_TT_MODULE: - case MRB_TT_ICLASS: - case MRB_TT_SCLASS: - case MRB_TT_PROC: - case MRB_TT_ARRAY: - case MRB_TT_HASH: - case MRB_TT_STRING: - case MRB_TT_RANGE: - case MRB_TT_REGEX: - case MRB_TT_STRUCT: - case MRB_TT_EXCEPTION: - case MRB_TT_MATCH: - case MRB_TT_FILE: - case MRB_TT_DATA: - case MRB_TT_THREAD: - case MRB_TT_THREADGRP: - default: - return mrb_fixnum(obj); /* even number */ + mrb_int tt = obj.tt; + +#define MakeID2(p,t) (((intptr_t)(p))^(t)) +#define MakeID(p) MakeID2(p,tt) + + switch (tt) { + case MRB_TT_FREE: + case MRB_TT_UNDEF: + return MakeID(0); /* not define */ + case MRB_TT_FALSE: + if (mrb_nil_p(obj)) + return MakeID(1); + return MakeID(0); + case MRB_TT_TRUE: + return MakeID(1); + case MRB_TT_SYMBOL: + return MakeID(SYM2ID(obj)); + case MRB_TT_FIXNUM: + return MakeID2(float_id((mrb_float)mrb_fixnum(obj)), MRB_TT_FLOAT); + case MRB_TT_FLOAT: + return MakeID(float_id(mrb_float(obj))); + case MRB_TT_STRING: + case MRB_TT_OBJECT: + case MRB_TT_CLASS: + case MRB_TT_MODULE: + case MRB_TT_ICLASS: + case MRB_TT_SCLASS: + case MRB_TT_PROC: + case MRB_TT_ARRAY: + case MRB_TT_HASH: + case MRB_TT_RANGE: + case MRB_TT_REGEX: + case MRB_TT_STRUCT: + case MRB_TT_EXCEPTION: + case MRB_TT_MATCH: + case MRB_TT_FILE: + case MRB_TT_DATA: + default: + return MakeID(obj.value.p); } } @@ -11,13 +11,15 @@ #include "mruby/string.h" #include "mruby/hash.h" #include "mruby/range.h" -#include "mruby/khash.h" #include <string.h> -#include <stdio.h> #include "mruby/struct.h" #include "mruby/proc.h" #include "mruby/data.h" -#include "mruby/numeric.h" +#include "mruby/variable.h" + +#ifndef SIZE_MAX +#include <limits.h> // for SIZE_MAX +#endif /* = Tri-color Incremental Garbage Collection @@ -70,13 +72,38 @@ */ -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP #include "re.h" #endif -#include "gc.h" +struct free_obj { + MRUBY_OBJECT_HEADER; + struct RBasic *next; +}; + +typedef struct { + union { + struct free_obj free; + struct RBasic basic; + struct RObject object; + struct RClass klass; + struct RString string; + struct RArray array; + struct RHash hash; + struct RRange range; +#ifdef ENABLE_STRUCT + struct RStruct structdata; +#endif + struct RProc procdata; +#ifdef ENABLE_REGEXP + struct RMatch match; + struct RRegexp regexp; +#endif + } as; +} RVALUE; #ifdef GC_PROFILE +#include <stdio.h> #include <sys/time.h> static double program_invoke_time = 0; @@ -121,25 +148,40 @@ gettimeofday_time(void) #define GC_STEP_SIZE 1024 - void* mrb_realloc(mrb_state *mrb, void *p, size_t len) { - return (mrb->allocf)(mrb, p, len); + void *p2; + + p2 = (mrb->allocf)(mrb, p, len); + + if (!p2 && len > 0 && mrb->heaps) { + mrb_garbage_collect(mrb); + p2 = (mrb->allocf)(mrb, p, len); + } + return p2; } void* mrb_malloc(mrb_state *mrb, size_t len) { - return (mrb->allocf)(mrb, 0, len); + return mrb_realloc(mrb, 0, len); } void* mrb_calloc(mrb_state *mrb, size_t nelem, size_t len) { - void *p = (mrb->allocf)(mrb, 0, nelem*len); + void *p = NULL; + size_t size; + + if (nelem <= SIZE_MAX / len) { + size = nelem * len; + p = mrb_realloc(mrb, 0, size); + + if (p && size > 0) + memset(p, 0, size); + } - memset(p, 0, nelem*len); return p; } @@ -149,7 +191,9 @@ mrb_free(mrb_state *mrb, void *p) return (mrb->allocf)(mrb, p, 0); } -#define HEAP_PAGE_SIZE 1024 +#ifndef MRB_HEAP_PAGE_SIZE +#define MRB_HEAP_PAGE_SIZE 1024 +#endif struct heap_page { struct RBasic *freelist; @@ -157,7 +201,7 @@ struct heap_page { struct heap_page *next; struct heap_page *free_next; struct heap_page *free_prev; - RVALUE objects[HEAP_PAGE_SIZE]; + RVALUE objects[MRB_HEAP_PAGE_SIZE]; }; static void @@ -208,13 +252,11 @@ unlink_free_heap_page(mrb_state *mrb, struct heap_page *page) static void add_heap(mrb_state *mrb) { - struct heap_page *page = mrb_malloc(mrb, sizeof(struct heap_page)); + struct heap_page *page = (struct heap_page *)mrb_calloc(mrb, 1, sizeof(struct heap_page)); RVALUE *p, *e; struct RBasic *prev = NULL; - memset(page, 0, sizeof(struct heap_page)); - - for (p = page->objects, e=p+HEAP_PAGE_SIZE; p<e; p++) { + for (p = page->objects, e=p+MRB_HEAP_PAGE_SIZE; p<e; p++) { p->as.free.tt = MRB_TT_FREE; p->as.free.next = prev; prev = &p->as.basic; @@ -248,7 +290,7 @@ gc_protect(mrb_state *mrb, struct RBasic *p) if (mrb->arena_idx > MRB_ARENA_SIZE) { /* arena overflow error */ mrb->arena_idx = MRB_ARENA_SIZE - 4; /* force room in arena */ - mrb_raise(mrb, mrb->eRuntimeError_class, "arena overflow error"); + mrb_raise(mrb, E_RUNTIME_ERROR, "arena overflow error"); } mrb->arena[mrb->arena_idx++] = p; } @@ -316,8 +358,8 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj) break; case MRB_TT_CLASS: - case MRB_TT_SCLASS: case MRB_TT_MODULE: + case MRB_TT_SCLASS: { struct RClass *c = (struct RClass*)obj; @@ -361,7 +403,7 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj) size_t i, e; for (i=0,e=a->len; i<e; i++) { - mrb_gc_mark_value(mrb, a->buf[i]); + mrb_gc_mark_value(mrb, a->ptr[i]); } } break; @@ -372,13 +414,6 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj) break; case MRB_TT_STRING: - { - struct RString *s = (struct RString*)obj; - - if (s->flags & MRB_STR_SHARED) { - mrb_gc_mark(mrb, (struct RBasic*)s->aux.shared); - } - } break; case MRB_TT_RANGE: @@ -390,7 +425,7 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj) } break; -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP case MRB_TT_MATCH: { struct RMatch *m = (struct RMatch*)obj; @@ -408,6 +443,18 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj) break; #endif +#ifdef ENABLE_STRUCT + case MRB_TT_STRUCT: + { + struct RStruct *s = (struct RStruct*)obj; + long i; + for (i=0; i<s->len; i++){ + mrb_gc_mark_value(mrb, s->ptr[i]); + } + } + break; +#endif + default: break; } @@ -458,7 +505,10 @@ obj_free(mrb_state *mrb, struct RBasic *obj) break; case MRB_TT_ARRAY: - mrb_free(mrb, ((struct RArray*)obj)->buf); + if (obj->flags & MRB_ARY_SHARED) + mrb_ary_decref(mrb, ((struct RArray*)obj)->aux.shared); + else + mrb_free(mrb, ((struct RArray*)obj)->ptr); break; case MRB_TT_HASH: @@ -467,20 +517,29 @@ obj_free(mrb_state *mrb, struct RBasic *obj) break; case MRB_TT_STRING: - if (!(obj->flags & MRB_STR_SHARED)) - mrb_free(mrb, ((struct RString*)obj)->buf); + if (obj->flags & MRB_STR_SHARED) + mrb_str_decref(mrb, ((struct RString*)obj)->aux.shared); + else + mrb_free(mrb, ((struct RString*)obj)->ptr); break; case MRB_TT_RANGE: mrb_free(mrb, ((struct RRange*)obj)->edges); break; +#ifdef ENABLE_STRUCT + case MRB_TT_STRUCT: + mrb_free(mrb, ((struct RStruct*)obj)->ptr); + break; +#endif + case MRB_TT_DATA: { struct RData *d = (struct RData*)obj; if (d->type->dfree) { d->type->dfree(mrb, d->data); } + mrb_gc_free_iv(mrb, (struct RObject*)obj); } break; @@ -504,10 +563,14 @@ root_scan_phase(mrb_state *mrb) for (i=0,e=mrb->arena_idx; i<e; i++) { mrb_gc_mark(mrb, mrb->arena[i]); } + /* mark class hierarchy */ mrb_gc_mark(mrb, (struct RBasic*)mrb->object_class); + /* mark exception */ + mrb_gc_mark(mrb, (struct RBasic*)mrb->exc); /* mark stack */ e = mrb->stack - mrb->stbase; if (mrb->ci) e += mrb->ci->nregs; + if (mrb->stbase + e > mrb->stend) e = mrb->stend - mrb->stbase; for (i=0; i<e; i++) { mrb_gc_mark_value(mrb, mrb->stbase[i]); } @@ -560,6 +623,7 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj) break; case MRB_TT_OBJECT: + case MRB_TT_DATA: children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj); break; @@ -584,7 +648,7 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj) children+=2; break; -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP case MRB_TT_MATCH: children+=2; break; @@ -593,6 +657,15 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj) break; #endif +#ifdef ENABLE_STRUCT + case MRB_TT_STRUCT: + { + struct RStruct *s = (struct RStruct*)obj; + children += s->len; + } + break; +#endif + default: break; } @@ -642,7 +715,7 @@ incremental_sweep_phase(mrb_state *mrb, size_t limit) while (page && (tried_sweep < limit)) { RVALUE *p = page->objects; - RVALUE *e = p + HEAP_PAGE_SIZE; + RVALUE *e = p + MRB_HEAP_PAGE_SIZE; size_t freed = 0; int dead_slot = 1; int full = (page->freelist == NULL); @@ -664,7 +737,7 @@ incremental_sweep_phase(mrb_state *mrb, size_t limit) } /* free dead slot */ - if (dead_slot && freed < HEAP_PAGE_SIZE) { + if (dead_slot && freed < MRB_HEAP_PAGE_SIZE) { struct heap_page *next = page->next; unlink_heap_page(mrb, page); @@ -678,7 +751,7 @@ incremental_sweep_phase(mrb_state *mrb, size_t limit) } page = page->next; } - tried_sweep += HEAP_PAGE_SIZE; + tried_sweep += MRB_HEAP_PAGE_SIZE; mrb->live -= freed; mrb->gc_live_after_mark -= freed; } @@ -1092,7 +1165,7 @@ test_incremental_gc(void) page = mrb->heaps; while (page) { RVALUE *p = page->objects; - RVALUE *e = p + HEAP_PAGE_SIZE; + RVALUE *e = p + MRB_HEAP_PAGE_SIZE; while (p<e) { if (is_black(&p->as.basic)) { live++; @@ -1103,7 +1176,7 @@ test_incremental_gc(void) p++; } page = page->next; - total += HEAP_PAGE_SIZE; + total += MRB_HEAP_PAGE_SIZE; } gc_assert(mrb->gray_list == NULL); @@ -1138,7 +1211,7 @@ test_incremental_sweep_phase(void) gc_assert(mrb->heaps->next->next == NULL); gc_assert(mrb->free_heaps->next->next == NULL); - incremental_sweep_phase(mrb, HEAP_PAGE_SIZE*3); + incremental_sweep_phase(mrb, MRB_HEAP_PAGE_SIZE*3); gc_assert(mrb->heaps->next == NULL); gc_assert(mrb->heaps == mrb->free_heaps); diff --git a/src/gc.h b/src/gc.h deleted file mode 100644 index fea761d1b..000000000 --- a/src/gc.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -** gc.h - garbage collector for RiteVM -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_GC_H -#define MRUBY_GC_H - -#if defined(__cplusplus) -extern "C" { -#endif - -struct free_obj { - MRUBY_OBJECT_HEADER; - struct RBasic *next; -}; - -typedef struct { - union { - struct free_obj free; - struct RBasic basic; - struct RObject object; - struct RClass klass; - struct RString string; - struct RArray array; - struct RHash hash; - struct RRange range; - struct RStruct structdata; - struct RProc procdata; -#ifdef INCLUDE_REGEXP - struct RMatch match; - struct RRegexp regexp; -#endif - } as; -} RVALUE; - -void mrb_gc_mark_gv(mrb_state*); -void mrb_gc_free_gv(mrb_state*); -void mrb_gc_mark_iv(mrb_state*, struct RObject*); -size_t mrb_gc_mark_iv_size(mrb_state*, struct RObject*); -void mrb_gc_free_iv(mrb_state*, struct RObject*); -void mrb_gc_mark_mt(mrb_state*, struct RClass*); -size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*); -void mrb_gc_free_mt(mrb_state*, struct RClass*); -void mrb_gc_mark_ht(mrb_state*, struct RHash*); -size_t mrb_gc_mark_ht_size(mrb_state*, struct RHash*); -void mrb_gc_free_ht(mrb_state*, struct RHash*); - -#if defined(__cplusplus) -} /* extern "C" { */ -#endif - -#endif /* MRUBY_GC_H */ diff --git a/src/hash.c b/src/hash.c index a06becd91..927e40e66 100644 --- a/src/hash.c +++ b/src/hash.c @@ -11,8 +11,6 @@ #include "mruby/array.h" #include "mruby/string.h" #include "mruby/variable.h" -#include <string.h> -#include <stdio.h> static inline khint_t mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key) @@ -31,15 +29,8 @@ mrb_hash_ht_hash_equal(mrb_state *mrb, mrb_value a, mrb_value b) return mrb_eql(mrb, a, b); } -KHASH_INIT(ht, mrb_value, mrb_value, 1, mrb_hash_ht_hash_func, mrb_hash_ht_hash_equal); - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif +KHASH_DECLARE(ht, mrb_value, mrb_value, 1); +KHASH_DEFINE (ht, mrb_value, mrb_value, 1, mrb_hash_ht_hash_func, mrb_hash_ht_hash_equal); static void mrb_hash_modify(mrb_state *mrb, mrb_value hash); @@ -60,6 +51,7 @@ mrb_gc_mark_ht(mrb_state *mrb, struct RHash *hash) khiter_t k; khash_t(ht) *h = hash->ht; + if (!h) return; for (k = kh_begin(h); k != kh_end(h); k++) if (kh_exist(h, k)) { mrb_gc_mark_value(mrb, kh_key(h, k)); @@ -70,43 +62,48 @@ mrb_gc_mark_ht(mrb_state *mrb, struct RHash *hash) size_t mrb_gc_mark_ht_size(mrb_state *mrb, struct RHash *hash) { + if (!hash->ht) return 0; return kh_size(hash->ht)*2; } void mrb_gc_free_ht(mrb_state *mrb, struct RHash *hash) { - kh_destroy(ht, hash->ht); + if (hash->ht) kh_destroy(ht, hash->ht); } mrb_value -mrb_hash_new_capa(mrb_state *mrb, size_t capa) +mrb_hash_new_capa(mrb_state *mrb, int capa) { struct RHash *h; h = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class); h->ht = kh_init(ht, mrb); - kh_resize(ht, h->ht, capa); + if (capa > 0) { + kh_resize(ht, h->ht, capa); + } h->iv = 0; return mrb_obj_value(h); } mrb_value -mrb_hash_new(mrb_state *mrb, int capa) +mrb_hash_new(mrb_state *mrb) { - return mrb_hash_new_capa(mrb, capa); + return mrb_hash_new_capa(mrb, 0); } mrb_value -mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) /* mrb_hash_aref */ /* mrb_hash_lookup */ +mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) { khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; - k = kh_get(ht, h, key); - if (k != kh_end(h)) - return kh_value(h, k); + if (h) { + k = kh_get(ht, h, key); + if (k != kh_end(h)) + return kh_value(h, k); + } /* not found */ if (MRB_RHASH_PROCDEFAULT_P(hash)) { @@ -116,13 +113,13 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) /* mrb_hash_aref */ } mrb_value -mrb_hash_getWithDef(mrb_state *mrb, mrb_value hash, mrb_value vkey, mrb_value def) /* mrb_hash_lookup2 */ +mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def) { khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; if (h) { - k = kh_get(ht, h, vkey); + k = kh_get(ht, h, key); if (k != kh_end(h)) return kh_value(h, k); } @@ -140,6 +137,7 @@ mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val) /* mr mrb_hash_modify(mrb, hash); h = RHASH_TBL(hash); + if (!h) h = RHASH_TBL(hash) = kh_init(ht, mrb); k = kh_get(ht, h, key); if (k == kh_end(h)) { /* expand */ @@ -165,11 +163,11 @@ mrb_hash_dup(mrb_state *mrb, mrb_value hash) khash_t(ht) *h, *ret_h; khiter_t k, ret_k; + h = RHASH_TBL(hash); ret = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class); ret->ht = kh_init(ht, mrb); - if (!RHASH_EMPTY_P(hash)) { - h = RHASH_TBL(hash); + if (kh_size(h) > 0) { ret_h = ret->ht; for (k = kh_begin(h); k != kh_end(h); k++) { @@ -194,7 +192,7 @@ mrb_hash_tbl(mrb_state *mrb, mrb_value hash) { khash_t(ht) *h = RHASH_TBL(hash); - if (!RHASH_TBL(hash)) { + if (!h) { RHASH_TBL(hash) = kh_init(ht, mrb); } return h; @@ -331,15 +329,9 @@ mrb_hash_aget(mrb_state *mrb, mrb_value self) } mrb_value -mrb_hash_lookup2(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def) -{ - return mrb_hash_getWithDef(mrb, hash, key, def); -} - -mrb_value mrb_hash_lookup(mrb_state *mrb, mrb_value hash, mrb_value key) { - return mrb_hash_lookup2(mrb, hash, key, mrb_nil_value()); + return mrb_hash_get(mrb, hash, key); } /* @@ -496,7 +488,7 @@ mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash) return ifnone; } -mrb_value +static mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key) { khash_t(ht) *h = RHASH_TBL(hash); @@ -576,7 +568,9 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash) if (!kh_exist(h,k)) continue; delKey = kh_key(h,k); + mrb_gc_protect(mrb, delKey); delVal = mrb_hash_delete_key(mrb, hash, delKey); + mrb_gc_protect(mrb, delVal); return mrb_assoc_new(mrb, delKey, delVal); } @@ -700,7 +694,7 @@ mrb_hash_clear(mrb_state *mrb, mrb_value hash) { khash_t(ht) *h = RHASH_TBL(hash); - kh_clear(ht, h); + if (h) kh_clear(ht, h); return hash; } @@ -817,13 +811,12 @@ static mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self) { khash_t(ht) *h = RHASH_TBL(self); - khiter_t k; + if (h) { - for (k = kh_begin(h); k != kh_end(h); k++) - if (kh_exist(h, k)) - return mrb_false_value(); + if (kh_size(h) == 0) + return mrb_true_value(); } - return mrb_true_value(); + return mrb_false_value(); } /* 15.2.13.4.11 */ @@ -896,9 +889,9 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur) khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; - if (recur) return mrb_str_new_cstr(mrb, "{...}"); + if (recur) return mrb_str_new(mrb, "{...}", 5); - str = mrb_str_new_cstr(mrb, "{"); + str = mrb_str_new(mrb, "{", 1); if (h && kh_size(h) > 0) { for (k = kh_begin(h); k != kh_end(h); k++) { int ai; @@ -911,14 +904,14 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur) str2 = mrb_inspect(mrb, kh_key(h,k)); mrb_str_append(mrb, str, str2); - mrb_str_buf_cat(mrb, str, "=>", strlen("=>")); + mrb_str_buf_cat(mrb, str, "=>", 2); str2 = mrb_inspect(mrb, kh_value(h,k)); mrb_str_append(mrb, str, str2); mrb_gc_arena_restore(mrb, ai); } } - mrb_str_buf_cat(mrb, str, "}", strlen("}"));//mrb_str_buf_cat2(str, "}"); + mrb_str_buf_cat(mrb, str, "}", 1); return str; } @@ -938,8 +931,10 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur) static mrb_value mrb_hash_inspect(mrb_state *mrb, mrb_value hash) { - if (RHASH_EMPTY_P(hash)) - return mrb_str_new_cstr(mrb, "{}"); + khash_t(ht) *h = RHASH_TBL(hash); + + if (!h || kh_size(h) == 0) + return mrb_str_new(mrb, "{}", 2); return inspect_hash(mrb, hash, 0); } @@ -1106,6 +1101,8 @@ mrb_hash_has_value(mrb_state *mrb, mrb_value hash) static mrb_value hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql) { + khash_t(ht) *h1, *h2; + if (mrb_obj_equal(mrb, hash1, hash2)) return mrb_true_value(); if (mrb_type(hash2) != MRB_TT_HASH) { if (!mrb_respond_to(mrb, hash2, mrb_intern(mrb, "to_hash"))) { @@ -1116,10 +1113,15 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql) else return mrb_fixnum_value(mrb_equal(mrb, hash2, hash1)); } - if (RHASH_SIZE(hash1) != RHASH_SIZE(hash2)) return mrb_false_value(); + h1 = RHASH_TBL(hash1); + h2 = RHASH_TBL(hash2); + if (!h2) { + if (!h2) return mrb_true_value(); + return mrb_false_value(); + } + if (!h2) return mrb_false_value(); + if (kh_size(h1) != kh_size(h2)) return mrb_false_value(); else { - khash_t(ht) *h1 = RHASH_TBL(hash1); - khash_t(ht) *h2 = RHASH_TBL(hash2); khiter_t k1, k2; mrb_value key; @@ -1337,9 +1339,9 @@ mrb_init_hash(mrb_state *mrb) mrb_define_method(mrb, h, "default_proc", mrb_hash_default_proc,ARGS_NONE()); /* 15.2.13.4.7 */ mrb_define_method(mrb, h, "default_proc=", mrb_hash_set_default_proc,ARGS_REQ(1)); /* 15.2.13.4.7 */ mrb_define_method(mrb, h, "__delete", mrb_hash_delete, ARGS_REQ(1)); /* core of 15.2.13.4.8 */ -//mrb_define_method(mrb, h, "each", mrb_hash_each_pair, ARGS_NONE()); /* 15.2.13.4.9 */ /* move to mrblib\hash.rb */ -//mrb_define_method(mrb, h, "each_key", mrb_hash_each_key, ARGS_NONE()); /* 15.2.13.4.10 */ /* move to mrblib\hash.rb */ -//mrb_define_method(mrb, h, "each_value", mrb_hash_each_value, ARGS_NONE()); /* 15.2.13.4.11 */ /* move to mrblib\hash.rb */ +// "each" 15.2.13.4.9 move to mrblib/hash.rb +// "each_key" 15.2.13.4.10 move to mrblib/hash.rb +// "each_value" 15.2.13.4.11 move to mrblib/hash.rb mrb_define_method(mrb, h, "empty?", mrb_hash_empty_p, ARGS_NONE()); /* 15.2.13.4.12 */ mrb_define_method(mrb, h, "has_key?", mrb_hash_has_key, ARGS_REQ(1)); /* 15.2.13.4.13 */ mrb_define_method(mrb, h, "has_value?", mrb_hash_has_value, ARGS_REQ(1)); /* 15.2.13.4.14 */ @@ -1350,7 +1352,7 @@ mrb_init_hash(mrb_state *mrb) mrb_define_method(mrb, h, "keys", mrb_hash_keys, ARGS_NONE()); /* 15.2.13.4.19 */ mrb_define_method(mrb, h, "length", mrb_hash_size_m, ARGS_NONE()); /* 15.2.13.4.20 */ mrb_define_method(mrb, h, "member?", mrb_hash_has_key, ARGS_REQ(1)); /* 15.2.13.4.21 */ -//mrb_define_method(mrb, h, "merge", mrb_hash_merge, ARGS_REQ(1)); /* 15.2.13.4.22 */ /* move to mrblib\hash.rb */ +// "merge" 15.2.13.4.22 move to mrblib/hash.rb mrb_define_method(mrb, h, "replace", mrb_hash_replace, ARGS_REQ(1)); /* 15.2.13.4.23 */ mrb_define_method(mrb, h, "shift", mrb_hash_shift, ARGS_NONE()); /* 15.2.13.4.24 */ mrb_define_method(mrb, h, "size", mrb_hash_size_m, ARGS_NONE()); /* 15.2.13.4.25 */ diff --git a/src/init.c b/src/init.c index 17ce24313..e6af6989b 100644 --- a/src/init.c +++ b/src/init.c @@ -8,7 +8,7 @@ void mrb_init_class(mrb_state*); void mrb_init_symtbl(mrb_state*); -void mrb_init_symbols(mrb_state*); +void mrb_init_symbol(mrb_state*); void mrb_init_object(mrb_state*); void mrb_init_kernel(mrb_state*); void mrb_init_enumerable(mrb_state*); @@ -42,22 +42,30 @@ mrb_init_core(mrb_state *mrb) mrb_init_comparable(mrb); mrb_init_enumerable(mrb); - mrb_init_symbols(mrb); + mrb_init_symbol(mrb); + mrb_init_exception(mrb); mrb_init_proc(mrb); mrb_init_string(mrb); mrb_init_array(mrb); mrb_init_hash(mrb); mrb_init_numeric(mrb); mrb_init_range(mrb); +#ifdef ENABLE_STRUCT mrb_init_struct(mrb); +#endif mrb_init_gc(mrb); -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP mrb_init_regexp(mrb); #endif - mrb_init_exception(mrb); +#ifdef ENABLE_STDIO mrb_init_print(mrb); +#endif +#ifdef ENABLE_TIME mrb_init_time(mrb); +#endif +#ifdef ENABLE_MATH mrb_init_math(mrb); +#endif mrb_init_mrblib(mrb); diff --git a/src/kernel.c b/src/kernel.c index 9092d239d..6327f967d 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -6,18 +6,10 @@ #include "mruby.h" #include "mruby/string.h" -#include <string.h> -#include <stdio.h> -#include <stdlib.h> #include "mruby/proc.h" - -#include "mruby/range.h" #include "mruby/array.h" -#include "mruby/hash.h" #include "mruby/class.h" -#include "mruby/struct.h" #include "mruby/variable.h" -#include "mruby/khash.h" #include "error.h" typedef enum { @@ -34,22 +26,6 @@ typedef enum { NOEX_RESPONDS = 0x80 } mrb_method_flag_t; -#ifdef INCLUDE_REGEXP -#include "re.h" -#include "regint.h" -#endif - -KHASH_MAP_INIT_INT(mt, struct RProc*); -KHASH_MAP_INIT_INT(iv, mrb_value); - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - struct obj_ivar_tag { mrb_value obj; int (*func)(mrb_sym key, mrb_value val, void * arg); @@ -96,9 +72,6 @@ inspect_obj(mrb_state *mrb, mrb_value obj, mrb_value str, int recur) int mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj) { - //const mrb_method_entry_t *me = mrb_method_entry(CLASS_OF(obj), mrb_intern("to_s")); - //if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC && - //me->def->body.cfunc.func == mrb_any_to_s) struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern(mrb, "to_s")); if (me && MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s)) return 1; @@ -135,7 +108,7 @@ mrb_obj_inspect(mrb_state *mrb, mrb_value obj) return mrb_any_to_s(mrb, obj); } else if (mrb_nil_p(obj)) { - return mrb_str_new_cstr(mrb, "nil"); + return mrb_str_new(mrb, "nil", 3); } return mrb_funcall(mrb, obj, "to_s", 0, 0); } @@ -191,7 +164,7 @@ mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self) mrb_value arg; mrb_get_args(mrb, "o", &arg); - if (mrb_obj_equal(mrb, self, arg)) { + if (mrb_equal(mrb, self, arg)) { return mrb_false_value(); } else { @@ -225,14 +198,19 @@ mrb_equal_m(mrb_state *mrb, mrb_value self) /* 15.3.1.3.3 */ /* 15.3.1.3.33 */ /* - * call-seq: - * obj.hash -> fixnum + * Document-method: __id__ + * Document-method: object_id * - * Generates a <code>Fixnum</code> hash value for this object. This - * function must have the property that <code>a.eql?(b)</code> implies - * <code>a.hash == b.hash</code>. The hash value is used by class - * <code>Hash</code>. Any hash value that exceeds the capacity of a - * <code>Fixnum</code> will be truncated before being used. + * call-seq: + * obj.__id__ -> fixnum + * obj.object_id -> fixnum + * + * Returns an integer identifier for <i>obj</i>. The same number will + * be returned on all calls to <code>id</code> for a given object, and + * no two active objects will share an id. + * <code>Object#object_id</code> is a different concept from the + * <code>:name</code> notation, which returns the symbol id of + * <code>name</code>. Replaces the deprecated <code>Object#id</code>. */ static mrb_value mrb_obj_id_m(mrb_state *mrb, mrb_value self) @@ -262,17 +240,12 @@ mrb_obj_id_m(mrb_state *mrb, mrb_value self) static mrb_value mrb_f_send(mrb_state *mrb, mrb_value self) { - mrb_value name, block, *argv; + mrb_sym name; + mrb_value block, *argv; int argc; - mrb_get_args(mrb, "o*&", &name, &argv, &argc, &block); - return mrb_funcall_with_block(mrb,self, mrb_string_value_ptr(mrb, name), argc, argv, block); -} - -static mrb_value -mrb_f_block_given_p(void) -{ - return mrb_false_value(); /* dummy */ + mrb_get_args(mrb, "n*&", &name, &argv, &argc, &block); + return mrb_funcall_with_block(mrb,self, name, argc, argv, block); } /* 15.3.1.2.2 */ @@ -302,7 +275,17 @@ mrb_f_block_given_p(void) static mrb_value mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self) { - return mrb_f_block_given_p(); + mrb_callinfo *ci = mrb->ci; + mrb_value *bp; + + bp = mrb->stbase + ci->stackidx + 1; + ci--; + if (ci <= mrb->cibase) return mrb_false_value(); + if (ci->argc > 0) { + bp += ci->argc; + } + if (mrb_nil_p(*bp)) return mrb_false_value(); + return mrb_true_value(); } /* 15.3.1.3.7 */ @@ -328,56 +311,48 @@ mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj) { struct RClass *klass = RBASIC(obj)->c; - //if (!FL_TEST(klass, FL_SINGLETON)) - //return klass; if (klass->tt != MRB_TT_SCLASS) return klass; else { - //struct clone_method_data data; - /* copy singleton(unnamed) class */ - //VALUE clone = class_alloc(RBASIC(klass)->flags, 0); + /* copy singleton(unnamed) class */ struct RClass *clone = (struct RClass*)mrb_obj_alloc(mrb, klass->tt, mrb->class_class); - //clone->super = objklass->super; - if ((mrb_type(obj) == MRB_TT_CLASS) || - (mrb_type(obj) == MRB_TT_SCLASS)) { /* BUILTIN_TYPE(obj) == T_CLASS */ - clone->c = clone; - } - else { - clone->c = mrb_singleton_class_clone(mrb, mrb_obj_value(klass)); - } + if ((mrb_type(obj) == MRB_TT_CLASS) || + (mrb_type(obj) == MRB_TT_SCLASS)) { /* BUILTIN_TYPE(obj) == T_CLASS */ + clone->c = clone; + } + else { + clone->c = mrb_singleton_class_clone(mrb, mrb_obj_value(klass)); + } - clone->super = klass->super; - if (klass->iv) { - clone->iv = klass->iv; - } - clone->mt = kh_init(mt, mrb); - clone->tt = MRB_TT_SCLASS; - return clone; + clone->super = klass->super; + if (klass->iv) { + clone->iv = klass->iv; + } + if (klass->mt) { + clone->mt = kh_copy(mt, mrb, klass->mt); + } + else { + clone->mt = kh_init(mt, mrb); + } + clone->tt = MRB_TT_SCLASS; + return clone; } } static void init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj) { - //if (OBJ_FROZEN(dest)) { - // rb_raise(rb_eTypeError, "[bug] frozen object (%s) allocated", rb_obj_classname(dest)); - //} - //RBASIC(dest)->flags &= ~(T_MASK|FL_EXIVAR); - //RBASIC(dest)->flags |= RBASIC(obj)->flags & (T_MASK|FL_EXIVAR|FL_TAINT); - //if (FL_TEST(obj, FL_EXIVAR)) { - // mrb_copy_generic_ivar(dest, obj); - //} - //mrb_gc_copy_finalizer(dest, obj); switch (mrb_type(obj)) { case MRB_TT_OBJECT: case MRB_TT_CLASS: case MRB_TT_MODULE: if (ROBJECT(dest)->iv) { + kh_destroy(iv, ROBJECT(dest)->iv); ROBJECT(dest)->iv = 0; } if (ROBJECT(obj)->iv) { - ROBJECT(dest)->iv = ROBJECT(obj)->iv; + ROBJECT(dest)->iv = kh_copy(iv, mrb, ROBJECT(obj)->iv); } break; @@ -424,8 +399,6 @@ mrb_obj_clone(mrb_state *mrb, mrb_value self) clone = (struct RObject*)mrb_obj_alloc(mrb, self.tt, mrb_obj_class(mrb, self)); clone->c = mrb_singleton_class_clone(mrb, self); init_copy(mrb, mrb_obj_value(clone), self); - //1-9-2 no bug mrb_funcall(mrb, clone, "initialize_clone", 1, self); - //RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE; return mrb_obj_value(clone); } @@ -459,47 +432,12 @@ mrb_obj_dup(mrb_state *mrb, mrb_value obj) mrb_raise(mrb, E_TYPE_ERROR, "can't dup %s", mrb_obj_classname(mrb, obj)); } p = mrb_obj_alloc(mrb, mrb_type(obj), mrb_obj_class(mrb, obj)); - //init_copy(dup, obj); dup = mrb_obj_value(p); - mrb_funcall(mrb, dup, "initialize_copy", 1, obj); + init_copy(mrb, dup, obj); return dup; } -/* 15.3.1.2.3 */ -/* 15.3.1.3.12 */ -/* - * call-seq: - * eval(string [, binding [, filename [,lineno]]]) -> obj - * - * Evaluates the Ruby expression(s) in <em>string</em>. If - * <em>binding</em> is given, which must be a <code>Binding</code> - * object, the evaluation is performed in its context. If the - * optional <em>filename</em> and <em>lineno</em> parameters are - * present, they will be used when reporting syntax errors. - * - * def getBinding(str) - * return binding - * end - * str = "hello" - * eval "str + ' Fred'" #=> "hello Fred" - * eval "str + ' Fred'", getBinding("bye") #=> "bye Fred" - */ -mrb_value -mrb_f_eval(int argc, mrb_value *argv, mrb_value self) -{ - return mrb_false_value(); /* dummy */ -} -mrb_value -mrb_f_eval_m(mrb_state *mrb, mrb_value self) -{ - mrb_value *argv; - int argc; - - mrb_get_args(mrb, "*", &argv, &argc); - return mrb_f_eval(argc, argv, self); -} - static mrb_value mrb_obj_extend(mrb_state *mrb, int argc, mrb_value *argv, mrb_value obj) { @@ -509,7 +447,6 @@ mrb_obj_extend(mrb_state *mrb, int argc, mrb_value *argv, mrb_value obj) mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (at least 1)"); } for (i = 0; i < argc; i++) { - //Check_Type(argv[i], T_MODULE); mrb_check_type(mrb, argv[i], MRB_TT_MODULE); } while (argc--) { @@ -554,20 +491,17 @@ mrb_obj_extend_m(mrb_state *mrb, mrb_value self) return mrb_obj_extend(mrb, argc, argv, self); } -/* 15.3.1.2.4 */ -/* 15.3.1.3.14 */ +/* 15.3.1.3.15 */ /* * call-seq: - * global_variables -> array - * - * Returns an array of the names of global variables. + * obj.hash -> fixnum * - * global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr] + * Generates a <code>Fixnum</code> hash value for this object. This + * function must have the property that <code>a.eql?(b)</code> implies + * <code>a.hash == b.hash</code>. The hash value is used by class + * <code>Hash</code>. Any hash value that exceeds the capacity of a + * <code>Fixnum</code> will be truncated before being used. */ -//mrb_value -//mrb_f_global_variables(mrb_state *mrb, mrb_value self) - -/* 15.3.1.3.15 */ mrb_value mrb_obj_hash(mrb_state *mrb, mrb_value self) { @@ -588,15 +522,15 @@ mrb_obj_init_copy(mrb_state *mrb, mrb_value self) return self; } +mrb_value mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self, struct RClass *c); + /* 15.3.1.3.18 */ /* * call-seq: - * obj.instance_eval(string [, filename [, lineno]] ) -> obj * obj.instance_eval {| | block } -> obj * - * Evaluates a string containing Ruby source code, or the given block, - * within the context of the receiver (_obj_). In order to set the - * context, the variable +self+ is set to _obj_ while + * Evaluates the given block,within the context of the receiver (_obj_). + * In order to set the context, the variable +self+ is set to _obj_ while * the code is executing, giving the code access to _obj_'s * instance variables. In the version of <code>instance_eval</code> * that takes a +String+, the optional second and third @@ -614,10 +548,24 @@ mrb_obj_init_copy(mrb_state *mrb, mrb_value self) mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self) { - mrb_value b; + mrb_value a, b; + mrb_value cv; + struct RClass *c; - mrb_get_args(mrb, "&", &b); - return mrb_yield_with_self(mrb, b, 0, 0, self); + if (mrb_get_args(mrb, "|S&", &a, &b) == 1) { + mrb_raise(mrb, E_NOTIMP_ERROR, "instance_eval with string not implemented"); + } + switch (mrb_type(self)) { + case MRB_TT_SYMBOL: + case MRB_TT_FIXNUM: + case MRB_TT_FLOAT: + c = 0; + break; + default: + cv = mrb_singleton_class(mrb, self); + c = mrb_class_ptr(cv); + } + return mrb_yield_internal(mrb, b, 0, 0, self, c); } int @@ -755,46 +703,6 @@ mrb_obj_ivar_set(mrb_state *mrb, mrb_value self) return val; } -/* 15.3.1.3.23 */ -/* - * call-seq: - * obj.instance_variables -> array - * - * Returns an array of instance variable names for the receiver. Note - * that simply defining an accessor does not create the corresponding - * instance variable. - * - * class Fred - * attr_accessor :a1 - * def initialize - * @iv = 3 - * end - * end - * Fred.new.instance_variables #=> [:@iv] - */ -mrb_value -mrb_obj_instance_variables(mrb_state *mrb, mrb_value self) -{ - mrb_value ary; - kh_iv_t *h = RCLASS_IV_TBL(self); - khint_t i; - const char* p; - - ary = mrb_ary_new(mrb); - if (h) { - for (i=0;i<kh_end(h);i++) { - if (kh_exist(h, i)) { - p = mrb_sym2name(mrb, kh_key(h,i)); - if (*p == '@') { - if (mrb_type(kh_value(h, i)) != MRB_TT_UNDEF) - mrb_ary_push(mrb, ary, mrb_str_new_cstr(mrb, p)); - } - } - } - } - return ary; -} - /* 15.3.1.3.24 */ /* 15.3.1.3.26 */ /* @@ -836,71 +744,6 @@ mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self) } } -/* 15.3.1.2.6 */ -/* 15.3.1.3.27 */ -/* - * call-seq: - * lambda { |...| block } -> a_proc - * - * Equivalent to <code>Proc.new</code>, except the resulting Proc objects - * check the number of parameters passed when called. - */ -mrb_value -proc_lambda(mrb_state *mrb, mrb_value self) -{ - //return mrb_block_lambda(); - return mrb_nil_value(); /* dummy */ -} - -/* 15.3.1.2.7 */ -/* 15.3.1.3.28 */ -/* - * call-seq: - * local_variables -> array - * - * Returns the names of the current local variables. - * - * fred = 1 - * for i in 1..10 - * # ... - * end - * local_variables #=> [:fred, :i] - */ -mrb_value -mrb_f_local_variables(mrb_state *mrb, mrb_value self) -{ - mrb_value ary; - - ary = mrb_ary_new(mrb); - return ary; /* dummy */ -} - -/* 15.3.1.2.8 */ -/* 15.3.1.3.29 */ -/* - * call-seq: - * loop { block } - * loop -> an_enumerator - * - * Repeatedly executes the block. - * - * If no block is given, an enumerator is returned instead. - * - * loop do - * print "Input: " - * line = gets - * break if !line or line =~ /^qQ/ - * # ... - * end - * - * StopIteration raised in the block breaks the loop. - */ -mrb_value -mrb_f_loop(mrb_state *mrb, mrb_value self) -{ - return mrb_nil_value(); /* dummy */ -} - static void method_entry_loop(mrb_state *mrb, struct RClass* klass, mrb_value ary) { @@ -958,7 +801,6 @@ mrb_obj_singleton_methods(mrb_state *mrb, int argc, mrb_value *argv, mrb_value o recur = mrb_true_value(); } else { - //mrb_scan_args(argc, argv, "01", &recur); recur = argv[0]; } klass = mrb_class(mrb, obj); @@ -987,7 +829,6 @@ retry: else { mrb_value recur; - //mrb_scan_args(argc, argv, "1", &recur); recur = argv[0]; if (mrb_test(recur)) { argc = 0; @@ -1022,7 +863,7 @@ mrb_obj_methods_m(mrb_state *mrb, mrb_value self) int argc; mrb_get_args(mrb, "*", &argv, &argc); - return mrb_obj_methods(mrb, argc, argv, self, 0); /* everything but private */ + return mrb_obj_methods(mrb, argc, argv, self, (mrb_method_flag_t)0); /* everything but private */ } /* 15.3.1.3.32 */ @@ -1039,31 +880,6 @@ mrb_false(mrb_state *mrb, mrb_value self) return mrb_false_value(); } -/* 15.3.1.2.10 */ -/* 15.3.1.3.35 */ -/* - * call-seq: - * print(obj, ...) -> nil - * - * Prints each object in turn to <code>$stdout</code>. If the output - * field separator (<code>$,</code>) is not +nil+, its - * contents will appear between each field. If the output record - * separator (<code>$\\</code>) is not +nil+, it will be - * appended to the output. If no arguments are given, prints - * <code>$_</code>. Objects that aren't strings will be converted by - * calling their <code>to_s</code> method. - * - * print "cat", [1,2,3], 99, "\n" - * $, = ", " - * $\ = "\n" - * print "cat", [1,2,3], 99 - * - * <em>produces:</em> - * - * cat12399 - * cat, 1, 2, 3, 99 - */ - /* 15.3.1.3.36 */ /* * call-seq: @@ -1121,37 +937,15 @@ mrb_obj_public_methods(mrb_state *mrb, mrb_value self) return mrb_obj_methods(mrb, argc, argv, self, NOEX_PUBLIC); /* public attribute not define */ } -/* 15.3.1.2.11 */ -/* 15.3.1.3.39 */ -/* - * call-seq: - * puts(obj, ...) -> nil - * - * Equivalent to - * - * $stdout.puts(obj, ...) - */ - -static mrb_value -get_errinfo(mrb_state *mrb) -{ - //return get_thread_errinfo(GET_THREAD()); - return mrb_str_new_cstr(mrb, "error!!"); /* dummy */ -} - /* 15.3.1.2.12 */ /* 15.3.1.3.40 */ /* * call-seq: * raise * raise(string) - * raise(exception [, string [, array]]) - * fail - * fail(string) - * fail(exception [, string [, array]]) + * raise(exception [, string]) * - * With no arguments, raises the exception in <code>$!</code> or raises - * a <code>RuntimeError</code> if <code>$!</code> is +nil+. + * With no arguments, raises a <code>RuntimeError</code> * With a single +String+ argument, raises a * +RuntimeError+ with the string as a message. Otherwise, * the first parameter should be the name of an +Exception+ @@ -1167,19 +961,24 @@ get_errinfo(mrb_state *mrb) mrb_value mrb_f_raise(mrb_state *mrb, mrb_value self) { - mrb_value err; - mrb_value *argv; + mrb_value a[2]; int argc; - mrb_get_args(mrb, "*", &argv, &argc); - if (argc == 0) { - err = get_errinfo(mrb); - if (!mrb_nil_p(err)) { - argc = 1; - argv[0] = err; - } + argc = mrb_get_args(mrb, "|oo", &a[0], &a[1]); + switch (argc) { + case 0: + mrb_raise(mrb, E_RUNTIME_ERROR, ""); + break; + case 1: + a[1] = mrb_check_string_type(mrb, a[0]); + if (!mrb_nil_p(a[1])) { + argc = 2; + a[0] = mrb_obj_value(E_RUNTIME_ERROR); + } + /* fall through */ + default: + mrb_exc_raise(mrb, mrb_make_exception(mrb, argc, a)); } - mrb_exc_raise(mrb, mrb_make_exception(mrb, argc, argv)); return mrb_nil_value(); /* not reached */ } @@ -1209,79 +1008,20 @@ mrb_value mrb_obj_remove_instance_variable(mrb_state *mrb, mrb_value self) { mrb_sym sym; - mrb_value name; - khash_t(iv) *h; - khiter_t k; mrb_value val; - mrb_value Qundef = mrb_undef_value(); - mrb_get_args(mrb, "o", &name); - sym = mrb_to_id(mrb, name); - //if (OBJ_FROZEN(obj)) mrb_error_frozen("object"); - //if (!mrb_is_instance_id(id)) { - // mrb_name_error(mrb, id, "`%s' is not allowed as an instance variable name", mrb_sym2name(mrb, id)); - //} - switch (mrb_type(self)) { - case MRB_TT_OBJECT: - case MRB_TT_CLASS: - case MRB_TT_MODULE: - if (!mrb_obj_ptr(self)->iv) break; - h = mrb_obj_ptr(self)->iv; - if (!h) break; - k = kh_get(iv, h, sym); - if (k != kh_end(h)) { - val = kh_value(h, k); - if (!mrb_obj_equal(mrb, val, Qundef)) { - kh_value(h, k) = Qundef; - return val; - } - } - break; - default: - break; + mrb_get_args(mrb, "n", &sym); + val = mrb_iv_remove(mrb, self, sym); + if (mrb_undef_p(val)) { + mrb_name_error(mrb, sym, "instance variable %s not defined", mrb_sym2name(mrb, sym)); } - mrb_name_error(mrb, sym, "instance variable %s not defined", mrb_sym2name(mrb, sym)); - return mrb_nil_value(); /* not reached */ -} - -/* 15.3.1.2.13 */ -/* 15.3.1.3.42 */ -/* - * call-seq: - * require(string) -> true or false - * - * Ruby tries to load the library named _string_, returning - * +true+ if successful. If the filename does not resolve to - * an absolute path, it will be searched for in the directories listed - * in <code>$:</code>. If the file has the extension ``.rb'', it is - * loaded as a source file; if the extension is ``.so'', ``.o'', or - * ``.dll'', or whatever the default shared library extension is on - * the current platform, Ruby loads the shared library as a Ruby - * extension. Otherwise, Ruby tries adding ``.rb'', ``.so'', and so on - * to the name. The name of the loaded feature is added to the array in - * <code>$"</code>. A feature will not be loaded if its name already - * appears in <code>$"</code>. The file name is converted to an absolute - * path, so ``<code>require 'a'; require './a'</code>'' will not load - * <code>a.rb</code> twice. - * - * require "my-library.rb" - * require "db-driver" - */ -mrb_value -mrb_f_require(mrb_state *mrb, mrb_value self) -{ - mrb_value fname; - - mrb_get_args(mrb, "o", &fname); - return mrb_nil_value(); /* dummy */ + return val; } - static inline int basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub) { return mrb_respond_to(mrb, obj, id); - //return TRUE; } /* 15.3.1.3.43 */ /* @@ -1308,7 +1048,6 @@ obj_respond_to(mrb_state *mrb, mrb_value self) mrb_sym id; mrb_get_args(mrb, "*", &argv, &argc); - //mrb_scan_args(argc, argv, "11", &mid, &priv); mid = argv[0]; if (argc > 1) priv = argv[1]; else priv = mrb_nil_value(); @@ -1370,15 +1109,10 @@ mrb_init_kernel(mrb_state *mrb) krn = mrb->kernel_module = mrb_define_module(mrb, "Kernel"); mrb_define_class_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, ARGS_NONE()); /* 15.3.1.2.2 */ - mrb_define_class_method(mrb, krn, "eval", mrb_f_eval_m, ARGS_ANY()); /* 15.3.1.2.3 */ mrb_define_class_method(mrb, krn, "global_variables", mrb_f_global_variables, ARGS_NONE()); /* 15.3.1.2.4 */ mrb_define_class_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, ARGS_NONE()); /* 15.3.1.2.5 */ - mrb_define_class_method(mrb, krn, "lambda", proc_lambda, ARGS_NONE()); /* 15.3.1.2.6 */ - mrb_define_class_method(mrb, krn, "local_variables", mrb_f_local_variables, ARGS_NONE()); /* 15.3.1.2.7 */ - mrb_define_class_method(mrb, krn, "loop", mrb_f_loop, ARGS_NONE()); /* 15.3.1.2.8 */ ; /* 15.3.1.2.11 */ mrb_define_class_method(mrb, krn, "raise", mrb_f_raise, ARGS_ANY()); /* 15.3.1.2.12 */ - mrb_define_class_method(mrb, krn, "require", mrb_f_require, ARGS_REQ(1)); /* 15.3.1.2.13 */ mrb_define_method(mrb, krn, "singleton_class", mrb_singleton_class, ARGS_NONE()); @@ -1393,7 +1127,6 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "dup", mrb_obj_dup, ARGS_NONE()); /* 15.3.1.3.9 */ mrb_define_method(mrb, krn, "eql?", mrb_obj_equal_m, ARGS_REQ(1)); /* 15.3.1.3.10 */ mrb_define_method(mrb, krn, "equal?", mrb_obj_equal_m, ARGS_REQ(1)); /* 15.3.1.3.11 */ - mrb_define_method(mrb, krn, "eval", mrb_f_eval_m, ARGS_ANY()); /* 15.3.1.3.12 */ mrb_define_method(mrb, krn, "extend", mrb_obj_extend_m, ARGS_ANY()); /* 15.3.1.3.13 */ mrb_define_method(mrb, krn, "global_variables", mrb_f_global_variables, ARGS_NONE()); /* 15.3.1.3.14 */ mrb_define_method(mrb, krn, "hash", mrb_obj_hash, ARGS_NONE()); /* 15.3.1.3.15 */ @@ -1408,9 +1141,6 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "is_a?", mrb_obj_is_kind_of_m, ARGS_REQ(1)); /* 15.3.1.3.24 */ mrb_define_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, ARGS_NONE()); /* 15.3.1.3.25 */ mrb_define_method(mrb, krn, "kind_of?", mrb_obj_is_kind_of_m, ARGS_REQ(1)); /* 15.3.1.3.26 */ - mrb_define_method(mrb, krn, "lambda", proc_lambda, ARGS_NONE()); /* 15.3.1.3.27 */ - mrb_define_method(mrb, krn, "local_variables", mrb_f_local_variables, ARGS_NONE()); /* 15.3.1.3.28 */ - mrb_define_method(mrb, krn, "loop", mrb_f_loop, ARGS_NONE()); /* 15.3.1.3.29 */ mrb_define_method(mrb, krn, "methods", mrb_obj_methods_m, ARGS_ANY()); /* 15.3.1.3.31 */ mrb_define_method(mrb, krn, "nil?", mrb_false, ARGS_NONE()); /* 15.3.1.3.32 */ mrb_define_method(mrb, krn, "object_id", mrb_obj_id_m, ARGS_NONE()); /* 15.3.1.3.33 */ @@ -1419,14 +1149,16 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "public_methods", mrb_obj_public_methods, ARGS_ANY()); /* 15.3.1.3.38 */ mrb_define_method(mrb, krn, "raise", mrb_f_raise, ARGS_ANY()); /* 15.3.1.3.40 */ mrb_define_method(mrb, krn, "remove_instance_variable", mrb_obj_remove_instance_variable,ARGS_REQ(1)); /* 15.3.1.3.41 */ - mrb_define_method(mrb, krn, "require", mrb_f_require, ARGS_REQ(1)); /* 15.3.1.3.42 */ mrb_define_method(mrb, krn, "respond_to?", obj_respond_to, ARGS_ANY()); /* 15.3.1.3.43 */ mrb_define_method(mrb, krn, "send", mrb_f_send, ARGS_ANY()); /* 15.3.1.3.44 */ + mrb_define_method(mrb, krn, "__send__", mrb_f_send, ARGS_ANY()); /* 15.3.1.3.4 */ mrb_define_method(mrb, krn, "singleton_methods", mrb_obj_singleton_methods_m, ARGS_ANY()); /* 15.3.1.3.45 */ mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, ARGS_NONE()); /* 15.3.1.3.46 */ +#ifdef ENABLE_SPRINTF mrb_define_method(mrb, krn, "sprintf", mrb_f_sprintf, ARGS_ANY()); /* in sprintf.c */ mrb_define_method(mrb, krn, "format", mrb_f_sprintf, ARGS_ANY()); /* in sprintf.c */ +#endif mrb_include_module(mrb, mrb->object_class, mrb->kernel_module); } diff --git a/src/load.c b/src/load.c index c0684f1aa..cee985f43 100644 --- a/src/load.c +++ b/src/load.c @@ -8,19 +8,11 @@ #include "mruby/dump.h" #include "mruby/string.h" -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP #include "re.h" #endif #include "mruby/irep.h" -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - typedef struct _RiteFILE { FILE* fp; @@ -151,7 +143,7 @@ load_rite_irep_record(mrb_state *mrb, RiteFILE* rfp, unsigned char* dst, uint32_ uint16_t buf_size =0; buf_size = MRB_DUMP_DEFAULT_STR_LEN; - if ((char_buf = mrb_malloc(mrb, buf_size)) == 0) + if ((char_buf = (char *)mrb_malloc(mrb, buf_size)) == 0) goto error_exit; pStart = dst; @@ -200,7 +192,7 @@ load_rite_irep_record(mrb_state *mrb, RiteFILE* rfp, unsigned char* dst, uint32_ if ( pdl > buf_size - 1) { buf_size = pdl + 1; - if ((char_buf = mrb_realloc(mrb, char_buf, buf_size)) == 0) + if ((char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size)) == 0) goto error_exit; } memset(char_buf, '\0', buf_size); @@ -227,7 +219,7 @@ load_rite_irep_record(mrb_state *mrb, RiteFILE* rfp, unsigned char* dst, uint32_ if ( snl > buf_size - 1) { buf_size = snl + 1; - if ((char_buf = mrb_realloc(mrb, char_buf, buf_size)) == 0) + if ((char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size)) == 0) goto error_exit; } memset(char_buf, '\0', buf_size); @@ -256,12 +248,12 @@ mrb_load_irep(mrb_state *mrb, FILE* fp) unsigned char hex8[8], hcrc[4]; unsigned char *dst, *rite_dst = NULL; rite_binary_header bin_header; - RiteFILE ritefp, *rfp; + RiteFILE ritefp = { 0 }; + RiteFILE *rfp; if ((mrb == NULL) || (fp == NULL)) { return MRB_DUMP_INVALID_ARGUMENT; } - memset(&ritefp, 0, sizeof(ritefp)); ritefp.fp = fp; rfp = &ritefp; @@ -270,7 +262,7 @@ mrb_load_irep(mrb_state *mrb, FILE* fp) return ret; len = sizeof(rite_binary_header) + bin_to_uint32(bin_header.rbds); - if ((rite_dst = mrb_malloc(mrb, len)) == NULL) + if ((rite_dst = (unsigned char *)mrb_malloc(mrb, len)) == NULL) return MRB_DUMP_GENERAL_FAILURE; dst = rite_dst; @@ -339,7 +331,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32 int ai = mrb_gc_arena_save(mrb); recordStart = src; - buf = mrb_malloc(mrb, bufsize); + buf = (char *)mrb_malloc(mrb, bufsize); if (buf == NULL) { ret = MRB_DUMP_INVALID_IREP; goto error_exit; @@ -367,7 +359,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32 irep->ilen = bin_to_uint32(src); //iseq length src += MRB_DUMP_SIZE_OF_LONG; if (irep->ilen > 0) { - if ((irep->iseq = mrb_malloc(mrb, sizeof(mrb_code) * irep->ilen)) == NULL) { + if ((irep->iseq = (mrb_code *)mrb_malloc(mrb, sizeof(mrb_code) * irep->ilen)) == NULL) { ret = MRB_DUMP_GENERAL_FAILURE; goto error_exit; } @@ -388,7 +380,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32 irep->plen = bin_to_uint32(src); //pool length src += MRB_DUMP_SIZE_OF_LONG; if (irep->plen > 0) { - irep->pool = mrb_malloc(mrb, sizeof(mrb_value) * irep->plen); + irep->pool = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value) * irep->plen); if (irep->pool == NULL) { ret = MRB_DUMP_INVALID_IREP; goto error_exit; @@ -402,7 +394,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32 if (pdl > bufsize - 1) { mrb_free(mrb, buf); bufsize = pdl + 1; - if ((buf = mrb_malloc(mrb, bufsize)) == NULL) { + if ((buf = (char *)mrb_malloc(mrb, bufsize)) == NULL) { ret = MRB_DUMP_GENERAL_FAILURE; goto error_exit; } @@ -413,7 +405,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32 switch (tt) { //pool data case MRB_TT_FIXNUM: - fix_num = readint(buf, 10); + fix_num = strtol(buf, NULL, 10); irep->pool[i] = mrb_fixnum_value(fix_num); break; @@ -426,7 +418,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32 irep->pool[i] = mrb_str_new(mrb, buf, pdl); break; -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP case MRB_TT_REGEX: str = mrb_str_new(mrb, buf, pdl); irep->pool[i] = mrb_reg_quote(mrb, str); @@ -451,7 +443,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32 irep->slen = bin_to_uint32(src); //syms length src += MRB_DUMP_SIZE_OF_LONG; if (irep->slen > 0) { - if ((irep->syms = mrb_malloc(mrb, sizeof(mrb_sym) * irep->slen)) == NULL) { + if ((irep->syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym) * irep->slen)) == NULL) { ret = MRB_DUMP_INVALID_IREP; goto error_exit; } @@ -469,7 +461,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32 if (snl > bufsize - 1) { mrb_free(mrb, buf); bufsize = snl + 1; - if ((buf = mrb_malloc(mrb, bufsize)) == NULL) { + if ((buf = (char *)mrb_malloc(mrb, bufsize)) == NULL) { ret = MRB_DUMP_GENERAL_FAILURE; goto error_exit; } @@ -477,7 +469,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32 memcpy(buf, src, snl); //symbol name src += snl; buf[snl] = '\0'; - irep->syms[i] = mrb_intern(mrb, buf); + irep->syms[i] = mrb_intern2(mrb, buf, snl); } } crc = calc_crc_16_ccitt((unsigned char*)pStart, src - pStart); //Calculate CRC @@ -517,7 +509,7 @@ mrb_read_irep(mrb_state *mrb, const char *bin) mrb_add_irep(mrb, sirep + nirep); for (n=0,i=sirep; n<nirep; n++,i++) { - if ((mrb->irep[i] = mrb_malloc(mrb, sizeof(mrb_irep))) == NULL) { + if ((mrb->irep[i] = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep))) == NULL) { ret = MRB_DUMP_GENERAL_FAILURE; goto error_exit; } @@ -616,13 +608,11 @@ static char* hex_to_str(char *hex, char *str, uint16_t *str_len) { char *src, *dst; - uint16_t hex_len = strlen(hex); + int escape = 0; *str_len = 0; - - for (src = hex, dst = str; hex_len > 0; (*str_len)++, hex_len--) { - if (*src == '\\' && hex_len > 1) { - src++; hex_len--; + for (src = hex, dst = str; *src != '\0'; src++) { + if (escape) { switch(*src) { case 'a': *dst++ = '\a'/* BEL */; break; case 'b': *dst++ = '\b'/* BS */; break; @@ -637,12 +627,18 @@ hex_to_str(char *hex, char *str, uint16_t *str_len) case '\\': *dst++ = *src; break; default:break; } - src++; + escape = 0; } else { - *dst++ = *src++; + if (*src == '\\') { + escape = 1; + } else { + escape = 0; + *dst++ = *src; + } + } + if (!escape) { + (*str_len)++; } } - return str; } - diff --git a/src/math.c b/src/math.c index b0d911573..9aae87acd 100644 --- a/src/math.c +++ b/src/math.c @@ -5,15 +5,19 @@ */ #include "mruby.h" +#include "mruby/array.h" + +#ifdef ENABLE_MATH #include <math.h> #define domain_error(msg) \ mrb_raise(mrb, E_RANGE_ERROR, "Numerical argument is out of domain - " #msg); -#define MATH_TOLERANCE 1E-12 - /* math functions not provided under Microsoft Visual C++ */ #ifdef _MSC_VER + +#define MATH_TOLERANCE 1E-12 + #define asinh(x) log(x + sqrt(pow(x,2.0) + 1)) #define acosh(x) log(x + sqrt(pow(x,2.0) - 1)) #define atanh(x) (log(1+x) - log(1-x))/2.0 @@ -85,10 +89,6 @@ erfc(double x) #endif - -mrb_value -mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr); - /* TRIGONOMETRIC FUNCTIONS */ @@ -410,11 +410,14 @@ math_exp(mrb_state *mrb, mrb_value obj) static mrb_value math_log(mrb_state *mrb, mrb_value obj) { - mrb_float x; + mrb_float x, base; + int argc; - mrb_get_args(mrb, "f", &x); + argc = mrb_get_args(mrb, "f|f", &x, &base); x = log(x); - + if (argc == 2) { + x /= log(base); + } return mrb_float_value(x); } @@ -465,6 +468,25 @@ math_log10(mrb_state *mrb, mrb_value obj) /* * call-seq: + * Math.sqrt(numeric) -> float + * + * Returns the square root of <i>numeric</i>. + * + */ +static mrb_value +math_sqrt(mrb_state *mrb, mrb_value obj) +{ + mrb_float x; + + mrb_get_args(mrb, "f", &x); + x = sqrt(x); + + return mrb_float_value(x); +} + + +/* + * call-seq: * Math.cbrt(numeric) -> float * * Returns the cube root of <i>numeric</i>. @@ -612,47 +634,54 @@ mrb_init_math(mrb_state *mrb) struct RClass *mrb_math; mrb_math = mrb_define_module(mrb, "Math"); - mrb_define_const(mrb, mrb_math, "TOLERANCE", mrb_float_value(MATH_TOLERANCE)); - #ifdef M_PI - mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(M_PI)); - #else - mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(atan(1.0)*4.0)); - #endif - - #ifdef M_E - mrb_define_const(mrb, mrb_math, "E", mrb_float_value(M_E)); - #else - mrb_define_const(mrb, mrb_math, "E", mrb_float_value(exp(1.0))); - #endif +#ifdef M_PI + mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(M_PI)); +#else + mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(atan(1.0)*4.0)); +#endif - mrb_define_module_function(mrb, mrb_math, "sin", math_sin, 1); - mrb_define_module_function(mrb, mrb_math, "cos", math_cos, 1); - mrb_define_module_function(mrb, mrb_math, "tan", math_tan, 1); - - mrb_define_module_function(mrb, mrb_math, "asin", math_asin, 1); - mrb_define_module_function(mrb, mrb_math, "acos", math_acos, 1); - mrb_define_module_function(mrb, mrb_math, "atan", math_atan, 1); - mrb_define_module_function(mrb, mrb_math, "atan2", math_atan2, 2); +#ifdef M_E + mrb_define_const(mrb, mrb_math, "E", mrb_float_value(M_E)); +#else + mrb_define_const(mrb, mrb_math, "E", mrb_float_value(exp(1.0))); +#endif + +#ifdef MRB_USE_FLOAT + mrb_define_const(mrb, mrb_math, "TOLERANCE", mrb_float_value(1e-5)); +#else + mrb_define_const(mrb, mrb_math, "TOLERANCE", mrb_float_value(1e-12)); +#endif + + mrb_define_module_function(mrb, mrb_math, "sin", math_sin, ARGS_REQ(1)); + mrb_define_module_function(mrb, mrb_math, "cos", math_cos, ARGS_REQ(1)); + mrb_define_module_function(mrb, mrb_math, "tan", math_tan, ARGS_REQ(1)); + + mrb_define_module_function(mrb, mrb_math, "asin", math_asin, ARGS_REQ(1)); + mrb_define_module_function(mrb, mrb_math, "acos", math_acos, ARGS_REQ(1)); + mrb_define_module_function(mrb, mrb_math, "atan", math_atan, ARGS_REQ(1)); + mrb_define_module_function(mrb, mrb_math, "atan2", math_atan2, ARGS_REQ(2)); - mrb_define_module_function(mrb, mrb_math, "sinh", math_sinh, 1); - mrb_define_module_function(mrb, mrb_math, "cosh", math_cosh, 1); - mrb_define_module_function(mrb, mrb_math, "tanh", math_tanh, 1); + mrb_define_module_function(mrb, mrb_math, "sinh", math_sinh, ARGS_REQ(1)); + mrb_define_module_function(mrb, mrb_math, "cosh", math_cosh, ARGS_REQ(1)); + mrb_define_module_function(mrb, mrb_math, "tanh", math_tanh, ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "asinh", math_asinh, 1); - mrb_define_module_function(mrb, mrb_math, "acosh", math_acosh, 1); - mrb_define_module_function(mrb, mrb_math, "atanh", math_atanh, 1); + mrb_define_module_function(mrb, mrb_math, "asinh", math_asinh, ARGS_REQ(1)); + mrb_define_module_function(mrb, mrb_math, "acosh", math_acosh, ARGS_REQ(1)); + mrb_define_module_function(mrb, mrb_math, "atanh", math_atanh, ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "exp", math_exp, 1); - mrb_define_module_function(mrb, mrb_math, "log", math_log, -1); - mrb_define_module_function(mrb, mrb_math, "log2", math_log2, 1); - mrb_define_module_function(mrb, mrb_math, "log10", math_log10, 1); - mrb_define_module_function(mrb, mrb_math, "cbrt", math_cbrt, 1); + mrb_define_module_function(mrb, mrb_math, "exp", math_exp, ARGS_REQ(1)); + mrb_define_module_function(mrb, mrb_math, "log", math_log, ARGS_REQ(1)|ARGS_OPT(1)); + mrb_define_module_function(mrb, mrb_math, "log2", math_log2, ARGS_REQ(1)); + mrb_define_module_function(mrb, mrb_math, "log10", math_log10, ARGS_REQ(1)); + mrb_define_module_function(mrb, mrb_math, "sqrt", math_sqrt, ARGS_REQ(1)); + mrb_define_module_function(mrb, mrb_math, "cbrt", math_cbrt, ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "frexp", math_frexp, 1); - mrb_define_module_function(mrb, mrb_math, "ldexp", math_ldexp, 2); + mrb_define_module_function(mrb, mrb_math, "frexp", math_frexp, ARGS_REQ(1)); + mrb_define_module_function(mrb, mrb_math, "ldexp", math_ldexp, ARGS_REQ(2)); - mrb_define_module_function(mrb, mrb_math, "hypot", math_hypot, 2); + mrb_define_module_function(mrb, mrb_math, "hypot", math_hypot, ARGS_REQ(2)); - mrb_define_module_function(mrb, mrb_math, "erf", math_erf, 1); - mrb_define_module_function(mrb, mrb_math, "erfc", math_erfc, 1); + mrb_define_module_function(mrb, mrb_math, "erf", math_erf, ARGS_REQ(1)); + mrb_define_module_function(mrb, mrb_math, "erfc", math_erfc, ARGS_REQ(1)); } +#endif /* ENABLE_MATH */ diff --git a/src/node.h b/src/node.h index 8ae0301ba..29edd6cc5 100644 --- a/src/node.h +++ b/src/node.h @@ -103,29 +103,3 @@ enum node_type { NODE_ATTRASGN, NODE_LAST }; - -typedef struct RNode { - unsigned long flags; - char *nd_file; - union { - struct RNode *node; - mrb_sym id; - mrb_value value; - //mrb_value (*cfunc)((ARGS_ANY())); - mrb_sym *tbl; - } u1; - union { - struct RNode *node; - mrb_sym id; - long argc; - mrb_value value; - } u2; - union { - struct RNode *node; - mrb_sym id; - long state; - struct global_entry *entry; - long cnt; - mrb_value value; - } u3; -} NODE; diff --git a/src/numeric.c b/src/numeric.c index e1f711478..8280921c7 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -8,13 +8,10 @@ #include "mruby/numeric.h" #include "mruby/string.h" #include "mruby/array.h" -#include <string.h> -#include "mruby/class.h" -#include "mruby/variable.h" -#include <ctype.h> #include <math.h> #include <stdio.h> +#include <assert.h> #if defined(__FreeBSD__) && __FreeBSD__ < 4 #include <floatingpoint.h> @@ -28,7 +25,7 @@ #include <ieeefp.h> #endif -#define SIGNED_VALUE intptr_t +#define RSHIFT(x,y) ((x)>>(int)(y)) #ifdef MRB_USE_FLOAT #define floor(f) floorf(f) @@ -118,6 +115,12 @@ num_pow(mrb_state *mrb, mrb_value x) * result. */ +mrb_value +mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y) +{ + return mrb_float_value(mrb_to_flo(mrb, x) / mrb_to_flo(mrb, y)); +} + /* 15.2.9.3.19(x) */ /* * call-seq: @@ -180,29 +183,25 @@ static mrb_value flo_to_s(mrb_state *mrb, mrb_value flt) { char buf[32]; + int n; mrb_float value = mrb_float(flt); - char *p, *e; - if (isinf(value)) - return mrb_str_new2(mrb, value < 0 ? "-Infinity" : "Infinity"); - else if(isnan(value)) - return mrb_str_new2(mrb, "NaN"); + if (isinf(value)) { + static const char s[2][5] = { "-inf", "inf" }; + static const int n[] = { 4, 3 }; + int idx; + idx = (value < 0) ? 0 : 1; + return mrb_str_new(mrb, s[idx], n[idx]); + } else if(isnan(value)) + return mrb_str_new(mrb, "NaN", 3); - sprintf(buf, "%#.15g", value); /* ensure to print decimal point */ - if (!(e = strchr(buf, 'e'))) { - e = buf + strlen(buf); - } - if (!ISDIGIT(e[-1])) { /* reformat if ended with decimal point (ex 111111111111111.) */ - sprintf(buf, "%#.14e", value); - if (!(e = strchr(buf, 'e'))) { - e = buf + strlen(buf); - } - } - p = e; - while (p[-1]=='0' && ISDIGIT(p[-2])) - p--; - memmove(p, e, strlen(e)+1); - return mrb_str_new2(mrb, buf); +#ifdef MRB_USE_FLOAT + n = sprintf(buf, "%.7g", value); +#else + n = sprintf(buf, "%.14g", value); +#endif + assert(n >= 0); + return mrb_str_new(mrb, buf, n); } /* 15.2.9.3.2 */ @@ -404,7 +403,7 @@ flo_to_f(mrb_state *mrb, mrb_value num) */ static mrb_value -flo_is_infinite_p(mrb_state *mrb, mrb_value num) +flo_infinite_p(mrb_state *mrb, mrb_value num) { mrb_float value = mrb_float(num); @@ -426,7 +425,7 @@ flo_is_infinite_p(mrb_state *mrb, mrb_value num) */ static mrb_value -flo_is_finite_p(mrb_state *mrb, mrb_value num) +flo_finite_p(mrb_state *mrb, mrb_value num) { mrb_float value = mrb_float(num); @@ -516,21 +515,13 @@ flo_ceil(mrb_state *mrb, mrb_value num) */ static mrb_value -flo_round(mrb_state *mrb, /*int argc, mrb_value *argv,*/ mrb_value num) +flo_round(mrb_state *mrb, mrb_value num) { - mrb_value nd; - mrb_float number, f; + double number, f; int ndigits = 0, i; - mrb_value *argv; - int argc; - - mrb_get_args(mrb, "*", &argv, &argc); - if (argc == 1) { - nd = argv[0]; - ndigits = mrb_fixnum(nd); - } - number = mrb_float(num); + mrb_get_args(mrb, "|i", &ndigits); + number = mrb_float(num); f = 1.0; i = abs(ndigits); while (--i >= 0) @@ -540,7 +531,7 @@ flo_round(mrb_state *mrb, /*int argc, mrb_value *argv,*/ mrb_value num) if (ndigits < 0) number = 0; } else { - mrb_float d; + double d; if (ndigits < 0) number /= f; else number *= f; @@ -558,7 +549,6 @@ flo_round(mrb_state *mrb, /*int argc, mrb_value *argv,*/ mrb_value num) if (ndigits < 0) number *= f; else number /= f; } - if (ndigits > 0) return mrb_float_value(number); return mrb_fixnum_value((mrb_int)number); } @@ -691,9 +681,31 @@ int_succ(mrb_state *mrb, mrb_value num) return mrb_funcall(mrb, num, "+", 1, mrb_fixnum_value(1)); } -#define SQRT_LONG_MAX ((SIGNED_VALUE)1<<((sizeof(mrb_int)*CHAR_BIT-1)/2)) +#define SQRT_INT_MAX ((mrb_int)1<<((sizeof(mrb_int)*CHAR_BIT-1)/2)) /*tests if N*N would overflow*/ -#define FIT_SQRT_LONG(n) (((n)<SQRT_LONG_MAX)&&((n)>=-SQRT_LONG_MAX)) +#define FIT_SQRT_INT(n) (((n)<SQRT_INT_MAX)&&((n)>=-SQRT_INT_MAX)) + +mrb_value +mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y) +{ + mrb_int a; + + a = mrb_fixnum(x); + if (a == 0) return x; + if (FIXNUM_P(y)) { + mrb_int b, c; + + b = mrb_fixnum(y); + if (FIT_SQRT_INT(a) && FIT_SQRT_INT(b)) + return mrb_fixnum_value(a*b); + c = a * b; + if (c/a != b) { + return mrb_float_value((mrb_float)a*(mrb_float)b); + } + return mrb_fixnum_value(c);; + } + return mrb_float_value((mrb_float)a * mrb_to_flo(mrb, y)); +} /* 15.2.8.3.3 */ /* @@ -709,27 +721,8 @@ static mrb_value fix_mul(mrb_state *mrb, mrb_value x) { mrb_value y; - mrb_int a; mrb_get_args(mrb, "o", &y); - - a = mrb_fixnum(x); - if (FIXNUM_P(y)) { - mrb_int b, c; - mrb_value r; - - b = mrb_fixnum(y); - if (FIT_SQRT_LONG(a) && FIT_SQRT_LONG(b)) - return mrb_fixnum_value(a*b); - c = a * b; - r = mrb_fixnum_value(c); - - if (a == 0) return x; - if (mrb_fixnum(r) != c || c/a != b) { - r = mrb_float_value((mrb_float)a*(mrb_float)b); - } - return r; - } - return mrb_float_value((mrb_float)a * mrb_to_flo(mrb, y)); + return mrb_fixnum_mul(mrb, x, y); } static void @@ -772,12 +765,11 @@ static mrb_value fix_mod(mrb_state *mrb, mrb_value x) { mrb_value y; - mrb_int a; + mrb_int a, b; mrb_get_args(mrb, "o", &y); - a = mrb_fixnum(x); - if (FIXNUM_P(y)) { + if (FIXNUM_P(y) && (b=mrb_fixnum(y)) != 0) { mrb_int mod; fixdivmod(mrb, a, mrb_fixnum(y), 0, &mod); @@ -942,8 +934,28 @@ fix_xor(mrb_state *mrb, mrb_value x) return mrb_fixnum_value(val); } -static mrb_value fix_lshift(mrb_state *mrb, mrb_int, unsigned long); -static mrb_value fix_rshift(mrb_int, unsigned long); +static mrb_value +lshift(mrb_state *mrb, mrb_int val, unsigned long width) +{ + if (width > (sizeof(mrb_int)*CHAR_BIT-1) + || ((unsigned long)abs(val))>>(sizeof(mrb_int)*CHAR_BIT-1-width) > 0) { + mrb_raise(mrb, E_RANGE_ERROR, "width(%d) > (%d:sizeof(mrb_int)*CHAR_BIT-1)", width, + sizeof(mrb_int)*CHAR_BIT-1); + } + val = val << width; + return mrb_fixnum_value(val); +} + +static mrb_value +rshift(mrb_int val, unsigned long i) +{ + if (i >= sizeof(mrb_int)*CHAR_BIT-1) { + if (val < 0) return mrb_fixnum_value(-1); + return mrb_fixnum_value(0); + } + val = RSHIFT(val, i); + return mrb_fixnum_value(val); +} /* 15.2.8.3.12 */ /* @@ -954,7 +966,7 @@ static mrb_value fix_rshift(mrb_int, unsigned long); */ static mrb_value -mrb_fix_lshift(mrb_state *mrb, mrb_value x) +fix_lshift(mrb_state *mrb, mrb_value x) { mrb_value y; mrb_int val, width; @@ -964,20 +976,8 @@ mrb_fix_lshift(mrb_state *mrb, mrb_value x) y = bit_coerce(mrb, y); width = mrb_fixnum(y); if (width < 0) - return fix_rshift(val, (unsigned long)-width); - return fix_lshift(mrb, val, width); -} - -static mrb_value -fix_lshift(mrb_state *mrb, mrb_int val, unsigned long width) -{ - if (width > (sizeof(mrb_int)*CHAR_BIT-1) - || ((unsigned long)abs(val))>>(sizeof(mrb_int)*CHAR_BIT-1-width) > 0) { - mrb_raise(mrb, E_RANGE_ERROR, "width(%d) > (%d:sizeof(mrb_int)*CHAR_BIT-1)", width, - sizeof(mrb_int)*CHAR_BIT-1); - } - val = val << width; - return mrb_fixnum_value(val); + return rshift(val, (unsigned long)-width); + return lshift(mrb, val, width); } /* 15.2.8.3.13 */ @@ -989,7 +989,7 @@ fix_lshift(mrb_state *mrb, mrb_int val, unsigned long width) */ static mrb_value -mrb_fix_rshift(mrb_state *mrb, mrb_value x) +fix_rshift(mrb_state *mrb, mrb_value x) { mrb_value y; mrb_int i, val; @@ -1000,19 +1000,8 @@ mrb_fix_rshift(mrb_state *mrb, mrb_value x) i = mrb_fixnum(y); if (i == 0) return x; if (i < 0) - return fix_lshift(mrb, val, (unsigned long)-i); - return fix_rshift(val, i); -} - -static mrb_value -fix_rshift(mrb_int val, unsigned long i) -{ - if (i >= sizeof(mrb_int)*CHAR_BIT-1) { - if (val < 0) return mrb_fixnum_value(-1); - return mrb_fixnum_value(0); - } - val = RSHIFT(val, i); - return mrb_fixnum_value(val); + return lshift(mrb, val, (unsigned long)-i); + return rshift(val, i); } /* 15.2.8.3.23 */ @@ -1066,7 +1055,28 @@ flt2big(mrb_state *mrb, mrb_float d) mrb_value mrb_flt2big(mrb_state *mrb, mrb_float d) { - return mrb_fixnum_value(flt2big(mrb, d)); + return mrb_fixnum_value(flt2big(mrb, d)); +} + +mrb_value +mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y) +{ + mrb_int a; + + a = mrb_fixnum(x); + if (a == 0) return y; + if (FIXNUM_P(y)) { + mrb_int b, c; + + b = mrb_fixnum(y); + c = a + b; + if (((a < 0) ^ (b < 0)) == 0 && (a < 0) != (c < 0)) { + /* integer overflow */ + return mrb_float_value((mrb_float)a + (mrb_float)b); + } + return mrb_fixnum_value(c); + } + return mrb_float_value((mrb_float)a + mrb_to_flo(mrb, y)); } /* 15.2.8.3.1 */ @@ -1079,15 +1089,32 @@ mrb_flt2big(mrb_state *mrb, mrb_float d) * result. */ static mrb_value -mrb_fixnum_plus(mrb_state *mrb, mrb_value self) +fix_plus(mrb_state *mrb, mrb_value self) { - mrb_int x, y; + mrb_value other; + + mrb_get_args(mrb, "o", &other); + return mrb_fixnum_plus(mrb, self, other); +} - x = mrb_fixnum(self); - mrb_get_args(mrb, "i", &y); +mrb_value +mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y) +{ + mrb_int a; + + a = mrb_fixnum(x); + if (FIXNUM_P(y)) { + mrb_int b, c; - DEBUG(printf("%d + %d = %d\n", x, y, x+y)); - return mrb_fixnum_value(x + y); + b = mrb_fixnum(y); + c = a - b; + if (((a < 0) ^ (b < 0)) != 0 && (a < 0) != (c < 0)) { + /* integer overflow */ + return mrb_float_value((mrb_float)a - (mrb_float)b); + } + return mrb_fixnum_value(c); + } + return mrb_float_value((mrb_float)a - mrb_to_flo(mrb, y)); } /* 15.2.8.3.2 */ @@ -1101,15 +1128,12 @@ mrb_fixnum_plus(mrb_state *mrb, mrb_value self) * result. */ static mrb_value -mrb_fixnum_minus(mrb_state *mrb, mrb_value self) +fix_minus(mrb_state *mrb, mrb_value self) { - mrb_int x, y; - - x = mrb_fixnum(self); - mrb_get_args(mrb, "i", &y); + mrb_value other; - DEBUG(printf("%d - %d = %d\n", x, y, x-y)); - return mrb_fixnum_value(x - y); + mrb_get_args(mrb, "o", &other); + return mrb_fixnum_minus(mrb, self, other); } /* 15.2.8.3.29 (x) */ @@ -1132,16 +1156,23 @@ mrb_fix2str(mrb_state *mrb, mrb_value x, int base) mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid radix %d", base); } if (val == 0) { - return mrb_str_new2(mrb, "0"); + return mrb_str_new(mrb, "0", 1); } if (val < 0) { val = -val; neg = 1; } *--b = '\0'; - do { - *--b = mrb_digitmap[(int)(val % base)]; - } while (val /= base); + if (neg && val < 0) { + do { + *--b = mrb_digitmap[abs(val % base)]; + } while (val /= base); + } + else { + do { + *--b = mrb_digitmap[(int)(val % base)]; + } while (val /= base); + } if (neg) { *--b = '-'; } @@ -1149,19 +1180,6 @@ mrb_fix2str(mrb_state *mrb, mrb_value x, int base) return mrb_str_new2(mrb, b); } -mrb_value -mrb_fix_to_s(mrb_state *mrb, mrb_value self, int argc, mrb_value *argv) -{ - int base; - - if (argc == 0) base = 10; - else { - mrb_get_args(mrb, "i", &base); - } - - return mrb_fix2str(mrb, self, base); -} - /* 15.2.8.3.25 */ /* * call-seq: @@ -1179,13 +1197,12 @@ mrb_fix_to_s(mrb_state *mrb, mrb_value self, int argc, mrb_value *argv) * */ static mrb_value -mrb_fixnum_to_s(mrb_state *mrb, mrb_value self) /* fix_to_s */ +fix_to_s(mrb_state *mrb, mrb_value self) { - mrb_value *argv; - int argc; + mrb_int base = 10; - mrb_get_args(mrb, "*", &argv, &argc); - return mrb_fix_to_s(mrb, self, argc, argv); + mrb_get_args(mrb, "|i", &base); + return mrb_fix2str(mrb, self, base); } /* 15.2.9.3.6 */ @@ -1236,7 +1253,7 @@ num_cmp(mrb_state *mrb, mrb_value self) * and <code>other</code>. */ static mrb_value -mrb_float_plus(mrb_state *mrb, mrb_value self) +flo_plus(mrb_state *mrb, mrb_value self) { mrb_float x, y; @@ -1266,9 +1283,9 @@ mrb_init_numeric(mrb_state *mrb) integer = mrb_define_class(mrb, "Integer", numeric); fixnum = mrb->fixnum_class = mrb_define_class(mrb, "Fixnum", integer); - mrb_undef_method(mrb, fixnum, "new"); - mrb_define_method(mrb, fixnum, "+", mrb_fixnum_plus, ARGS_REQ(1)); /* 15.2.8.3.1 */ - mrb_define_method(mrb, fixnum, "-", mrb_fixnum_minus, ARGS_REQ(1)); /* 15.2.8.3.2 */ + mrb_undef_class_method(mrb, fixnum, "new"); + mrb_define_method(mrb, fixnum, "+", fix_plus, ARGS_REQ(1)); /* 15.2.8.3.1 */ + mrb_define_method(mrb, fixnum, "-", fix_minus, ARGS_REQ(1)); /* 15.2.8.3.2 */ mrb_define_method(mrb, fixnum, "-@", fix_uminus, ARGS_REQ(1)); /* 15.2.7.4.2 */ mrb_define_method(mrb, fixnum, "*", fix_mul, ARGS_REQ(1)); /* 15.2.8.3.3 */ mrb_define_method(mrb, fixnum, "%", fix_mod, ARGS_REQ(1)); /* 15.2.8.3.5 */ @@ -1277,8 +1294,8 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, fixnum, "&", fix_and, ARGS_REQ(1)); /* 15.2.8.3.9 */ mrb_define_method(mrb, fixnum, "|", fix_or, ARGS_REQ(1)); /* 15.2.8.3.10 */ mrb_define_method(mrb, fixnum, "^", fix_xor, ARGS_REQ(1)); /* 15.2.8.3.11 */ - mrb_define_method(mrb, fixnum, "<<", mrb_fix_lshift, ARGS_REQ(1)); /* 15.2.8.3.12 */ - mrb_define_method(mrb, fixnum, ">>", mrb_fix_rshift, ARGS_REQ(1)); /* 15.2.8.3.13 */ + mrb_define_method(mrb, fixnum, "<<", fix_lshift, ARGS_REQ(1)); /* 15.2.8.3.12 */ + mrb_define_method(mrb, fixnum, ">>", fix_rshift, ARGS_REQ(1)); /* 15.2.8.3.13 */ mrb_define_method(mrb, fixnum, "ceil", int_to_i, ARGS_NONE()); /* 15.2.8.3.14 */ mrb_define_method(mrb, fixnum, "eql?", num_eql, ARGS_REQ(1)); /* 15.2.8.3.16 */ mrb_define_method(mrb, fixnum, "floor", num_floor, ARGS_NONE()); /* 15.2.8.3.17 */ @@ -1288,22 +1305,22 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, fixnum, "succ", fix_succ, ARGS_NONE()); /* 15.2.8.3.21 */ mrb_define_method(mrb, fixnum, "to_f", fix_to_f, ARGS_NONE()); /* 15.2.8.3.23 */ mrb_define_method(mrb, fixnum, "to_i", int_to_i, ARGS_NONE()); /* 15.2.8.3.24 */ - mrb_define_method(mrb, fixnum, "to_s", mrb_fixnum_to_s, ARGS_NONE()); /* 15.2.8.3.25 */ + mrb_define_method(mrb, fixnum, "to_s", fix_to_s, ARGS_NONE()); /* 15.2.8.3.25 */ mrb_define_method(mrb, fixnum, "truncate", int_to_i, ARGS_NONE()); /* 15.2.8.3.26 */ mrb_define_method(mrb, fixnum, "divmod", fix_divmod, ARGS_REQ(1)); /* 15.2.8.3.30 (x) */ /* Float Class */ fl = mrb->float_class = mrb_define_class(mrb, "Float", numeric); - mrb_undef_method(mrb, fl, "new"); - mrb_define_method(mrb, fl, "+", mrb_float_plus, ARGS_REQ(1)); /* 15.2.9.3.1 */ + mrb_undef_class_method(mrb, fl, "new"); + mrb_define_method(mrb, fl, "+", flo_plus, ARGS_REQ(1)); /* 15.2.9.3.1 */ mrb_define_method(mrb, fl, "-", flo_minus, ARGS_REQ(1)); /* 15.2.9.3.2 */ mrb_define_method(mrb, fl, "*", flo_mul, ARGS_REQ(1)); /* 15.2.9.3.3 */ mrb_define_method(mrb, fl, "%", flo_mod, ARGS_REQ(1)); /* 15.2.9.3.5 */ mrb_define_method(mrb, fl, "==", flo_eq, ARGS_REQ(1)); /* 15.2.9.3.7 */ mrb_define_method(mrb, fl, "ceil", flo_ceil, ARGS_NONE()); /* 15.2.9.3.8 */ - mrb_define_method(mrb, fl, "finite?", flo_is_finite_p, ARGS_NONE()); /* 15.2.9.3.9 */ + mrb_define_method(mrb, fl, "finite?", flo_finite_p, ARGS_NONE()); /* 15.2.9.3.9 */ mrb_define_method(mrb, fl, "floor", flo_floor, ARGS_NONE()); /* 15.2.9.3.10 */ - mrb_define_method(mrb, fl, "infinite?", flo_is_infinite_p,ARGS_NONE()); /* 15.2.9.3.11 */ + mrb_define_method(mrb, fl, "infinite?", flo_infinite_p, ARGS_NONE()); /* 15.2.9.3.11 */ mrb_define_method(mrb, fl, "round", flo_round, ARGS_ANY()); /* 15.2.9.3.12 */ mrb_define_method(mrb, fl, "to_f", flo_to_f, ARGS_NONE()); /* 15.2.9.3.13 */ mrb_define_method(mrb, fl, "to_i", flo_truncate, ARGS_NONE()); /* 15.2.9.3.14 */ diff --git a/src/object.c b/src/object.c index 81e3867a7..26df48afd 100644 --- a/src/object.c +++ b/src/object.c @@ -11,14 +11,6 @@ #include "mruby/class.h" #include "mruby/numeric.h" -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - int mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2) { @@ -159,7 +151,7 @@ true_xor(mrb_state *mrb, mrb_value obj) static mrb_value true_to_s(mrb_state *mrb, mrb_value obj) { - return mrb_str_new_cstr(mrb, "true"); + return mrb_str_new(mrb, "true", 4); } /* 15.2.5.3.4 */ @@ -272,7 +264,7 @@ false_or(mrb_state *mrb, mrb_value obj) static mrb_value false_to_s(mrb_state *mrb, mrb_value obj) { - return mrb_str_new_cstr(mrb, "false"); + return mrb_str_new(mrb, "false", 5); } void @@ -283,7 +275,7 @@ mrb_init_object(mrb_state *mrb) struct RClass *f; n = mrb->nil_class = mrb_define_class(mrb, "NilClass", mrb->object_class); - mrb_undef_method(mrb, n, "new"); + mrb_undef_class_method(mrb, n, "new"); mrb_define_method(mrb, n, "&", false_and, ARGS_REQ(1)); /* 15.2.4.3.1 */ mrb_define_method(mrb, n, "^", false_xor, ARGS_REQ(1)); /* 15.2.4.3.2 */ mrb_define_method(mrb, n, "|", false_or, ARGS_REQ(1)); /* 15.2.4.3.3 */ @@ -291,14 +283,14 @@ mrb_init_object(mrb_state *mrb) mrb_define_method(mrb, n, "to_s", nil_to_s, ARGS_NONE()); /* 15.2.4.3.5 */ t = mrb->true_class = mrb_define_class(mrb, "TrueClass", mrb->object_class); - mrb_undef_method(mrb, n, "new"); + mrb_undef_class_method(mrb, t, "new"); mrb_define_method(mrb, t, "&", true_and, ARGS_REQ(1)); /* 15.2.5.3.1 */ mrb_define_method(mrb, t, "^", true_xor, ARGS_REQ(1)); /* 15.2.5.3.2 */ mrb_define_method(mrb, t, "to_s", true_to_s, ARGS_NONE()); /* 15.2.5.3.3 */ mrb_define_method(mrb, t, "|", true_or, ARGS_REQ(1)); /* 15.2.5.3.4 */ f = mrb->false_class = mrb_define_class(mrb, "FalseClass", mrb->object_class); - mrb_undef_method(mrb, n, "new"); + mrb_undef_class_method(mrb, f, "new"); mrb_define_method(mrb, f, "&", false_and, ARGS_REQ(1)); /* 15.2.6.3.1 */ mrb_define_method(mrb, f, "^", false_xor, ARGS_REQ(1)); /* 15.2.6.3.2 */ mrb_define_method(mrb, f, "to_s", false_to_s, ARGS_NONE()); /* 15.2.6.3.3 */ @@ -325,7 +317,7 @@ convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *metho return mrb_nil_value(); } } - return mrb_funcall(mrb, val, method, 0); + return mrb_funcall_argv(mrb, val, m, 0, 0); } mrb_value @@ -335,8 +327,7 @@ mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method) if (mrb_type(val) == MRB_TT_FIXNUM) return val; v = convert_type(mrb, val, "Integer", method, FALSE); - if (mrb_nil_p(v)) return (v); - if (!mrb_obj_is_kind_of(mrb, v, mrb_obj_class(mrb, v))) { + if (mrb_nil_p(v) || mrb_type(v) != MRB_TT_FIXNUM) { return mrb_nil_value(); } return v; @@ -350,8 +341,8 @@ mrb_convert_type(mrb_state *mrb, mrb_value val, mrb_int type, const char *tname, if (mrb_type(val) == type) return val; v = convert_type(mrb, val, tname, method, 1/*Qtrue*/); if (mrb_type(v) != type) { - mrb_raise(mrb, E_TYPE_ERROR, "%s#%s should return %s", - mrb_obj_classname(mrb, val), method, tname); + mrb_raise(mrb, E_TYPE_ERROR, "%s cannot be converted to %s by #%s", + mrb_obj_classname(mrb, val), tname, method); } return v; } @@ -361,14 +352,9 @@ mrb_check_convert_type(mrb_state *mrb, mrb_value val, mrb_int type, const char * { mrb_value v; - /* always convert T_DATA */ if (mrb_type(val) == type && type != MRB_TT_DATA) return val; v = convert_type(mrb, val, tname, method, 0/*Qfalse*/); - if (mrb_nil_p(v)) return mrb_nil_value(); - if (mrb_type(v) != type) { - mrb_raise(mrb, E_TYPE_ERROR, "%s#%s should return %s", - mrb_obj_classname(mrb, val), method, tname); - } + if (mrb_nil_p(v) || mrb_type(v) != type) return mrb_nil_value(); return v; } @@ -411,11 +397,6 @@ mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t) struct RString *s; int xt; - /*if (x == Qundef) { - //mrb_bug("undef leaked to the Ruby space"); - printf ("undef leaked to the Ruby space\n"); - }*/ - xt = mrb_type(x); if ((xt != t) || (xt == MRB_TT_DATA)) { while (type->type < MRB_TT_MAXDEFINE) { @@ -433,18 +414,17 @@ mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t) } else if (mrb_special_const_p(x)) { s = mrb_str_ptr(mrb_obj_as_string(mrb, x)); - etype = s->buf; + etype = s->ptr; } else { etype = mrb_obj_classname(mrb, x); } mrb_raise(mrb, E_TYPE_ERROR, "wrong argument type %s (expected %s)", - etype, type->name); + etype, type->name); } type++; } - /*mrb_bug("unknown type 0x%x", t);*/ - printf ("unknown type 0x%x (0x%x given)", t, mrb_type(x)); + mrb_raise(mrb, E_TYPE_ERROR, "unknown type 0x%x (0x%x given)", t, mrb_type(x)); } } @@ -470,9 +450,7 @@ mrb_any_to_s(mrb_state *mrb, mrb_value obj) len = strlen(cname)+6+16; str = mrb_str_new(mrb, 0, len); /* 6:tags 16:addr */ s = mrb_str_ptr(str); - // snprintf(RSTRING(str)->ptr, len+1, "#<%s:0x%lx>", cname, obj); - sprintf(s->buf, "#<%s:0x%lx>", cname, (unsigned long)(obj.value.p)); - s->len = strlen(s->buf); + s->len = sprintf(s->ptr, "#<%s:0x%lx>", cname, (unsigned long)(obj.value.p)); return str; } @@ -532,7 +510,6 @@ mrb_to_integer(mrb_state *mrb, mrb_value val, const char *method) mrb_value v; if (FIXNUM_P(val)) return val; - //if (TYPE(val) == T_BIGNUM) return val; v = convert_type(mrb, val, "Integer", method, TRUE); if (!mrb_obj_is_kind_of(mrb, v, mrb->fixnum_class)) { const char *cname = mrb_obj_classname(mrb, val); diff --git a/src/opcode.h b/src/opcode.h index 9e7cf7f34..40ba9d126 100644 --- a/src/opcode.h +++ b/src/opcode.h @@ -14,15 +14,15 @@ /* OP:A:Bx = 7:9:16 */ /* OP:Ax = 7:25 */ -#define GET_OPCODE(i) (((mrb_code)(i)) & 0x7f) -#define GETARG_A(i) ((((mrb_code)(i)) >> 23) & 0x1ff) -#define GETARG_B(i) ((((mrb_code)(i)) >> 14) & 0x1ff) -#define GETARG_C(i) ((((mrb_code)(i)) >> 7) & 0x7f) -#define GETARG_Bx(i) ((((mrb_code)(i)) >> 7) & 0xffff) -#define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx) -#define GETARG_Ax(i) ((((mrb_code)(i)) >> 7) & 0x1ffffff) -#define GETARG_UNPACK_b(i,n1,n2) ((((mrb_code)(i)) >> (7+n2)) & (((1<<n1)-1))) -#define GETARG_UNPACK_c(i,n1,n2) ((((mrb_code)(i)) >> 7) & (((1<<n2)-1))) +#define GET_OPCODE(i) ((int)(((mrb_code)(i)) & 0x7f)) +#define GETARG_A(i) ((int)((((mrb_code)(i)) >> 23) & 0x1ff)) +#define GETARG_B(i) ((int)((((mrb_code)(i)) >> 14) & 0x1ff)) +#define GETARG_C(i) ((int)((((mrb_code)(i)) >> 7) & 0x7f)) +#define GETARG_Bx(i) ((int)((((mrb_code)(i)) >> 7) & 0xffff)) +#define GETARG_sBx(i) ((int)(GETARG_Bx(i)-MAXARG_sBx)) +#define GETARG_Ax(i) ((int)((((mrb_code)(i)) >> 7) & 0x1ffffff)) +#define GETARG_UNPACK_b(i,n1,n2) ((int)((((mrb_code)(i)) >> (7+n2)) & (((1<<n1)-1)))) +#define GETARG_UNPACK_c(i,n1,n2) ((int)((((mrb_code)(i)) >> 7) & (((1<<n2)-1)))) #define GETARG_b(i) GETARG_UNPACK_b(i,14,2) #define GETARG_c(i) GETARG_UNPACK_c(i,14,2) diff --git a/src/parse.y b/src/parse.y index eae9fb373..50f55bf7b 100644 --- a/src/parse.y +++ b/src/parse.y @@ -20,8 +20,8 @@ #include "mruby.h" #include "mruby/compile.h" +#include "mruby/proc.h" #include "node.h" -#include "st.h" #include <stdio.h> #include <errno.h> @@ -41,30 +41,22 @@ static void backref_error(parser_state *p, node *n); #define identchar(c) (isalnum(c) || (c) == '_' || !isascii(c)) -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - typedef unsigned int stack_type; -#define BITSTACK_PUSH(stack, n) ((stack) = ((stack)<<1)|((n)&1)) -#define BITSTACK_POP(stack) ((stack) = (stack) >> 1) -#define BITSTACK_LEXPOP(stack) ((stack) = ((stack) >> 1) | ((stack) & 1)) -#define BITSTACK_SET_P(stack) ((stack)&1) +#define BITSTACK_PUSH(stack, n) ((stack) = ((stack)<<1)|((n)&1)) +#define BITSTACK_POP(stack) ((stack) = (stack) >> 1) +#define BITSTACK_LEXPOP(stack) ((stack) = ((stack) >> 1) | ((stack) & 1)) +#define BITSTACK_SET_P(stack) ((stack)&1) -#define COND_PUSH(n) BITSTACK_PUSH(p->cond_stack, (n)) -#define COND_POP() BITSTACK_POP(p->cond_stack) -#define COND_LEXPOP() BITSTACK_LEXPOP(p->cond_stack) -#define COND_P() BITSTACK_SET_P(p->cond_stack) +#define COND_PUSH(n) BITSTACK_PUSH(p->cond_stack, (n)) +#define COND_POP() BITSTACK_POP(p->cond_stack) +#define COND_LEXPOP() BITSTACK_LEXPOP(p->cond_stack) +#define COND_P() BITSTACK_SET_P(p->cond_stack) -#define CMDARG_PUSH(n) BITSTACK_PUSH(p->cmdarg_stack, (n)) -#define CMDARG_POP() BITSTACK_POP(p->cmdarg_stack) -#define CMDARG_LEXPOP() BITSTACK_LEXPOP(p->cmdarg_stack) -#define CMDARG_P() BITSTACK_SET_P(p->cmdarg_stack) +#define CMDARG_PUSH(n) BITSTACK_PUSH(p->cmdarg_stack, (n)) +#define CMDARG_POP() BITSTACK_POP(p->cmdarg_stack) +#define CMDARG_LEXPOP() BITSTACK_LEXPOP(p->cmdarg_stack) +#define CMDARG_P() BITSTACK_SET_P(p->cmdarg_stack) static mrb_sym intern_gen(parser_state *p, const char *s) @@ -102,7 +94,7 @@ cons_gen(parser_state *p, node *car, node *cdr) p->cells = p->cells->cdr; } else { - c = parser_palloc(p, sizeof(mrb_ast_node)); + c = (node *)parser_palloc(p, sizeof(mrb_ast_node)); } c->car = car; @@ -173,7 +165,7 @@ append_gen(parser_state *p, node *a, node *b) static char* parser_strndup(parser_state *p, const char *s, size_t len) { - char *b = parser_palloc(p, len+1); + char *b = (char *)parser_palloc(p, len+1); memcpy(b, s, len); b[len] = '\0'; @@ -526,6 +518,15 @@ new_sym(parser_state *p, mrb_sym sym) return cons((node*)NODE_SYM, (node*)sym); } +static mrb_sym +new_strsym(parser_state *p, node* str) +{ + const char *s = (const char*)str->cdr->car; + size_t len = (size_t)str->cdr->cdr; + + return mrb_intern2(p->mrb, s, len); +} + // (:lvar . a) static node* new_lvar(parser_state *p, mrb_sym sym) @@ -685,9 +686,9 @@ new_float(parser_state *p, const char *s) // (:str . (s . len)) static node* -new_str(parser_state *p, const char *s, size_t len) +new_str(parser_state *p, const char *s, int len) { - return cons((node*)NODE_STR, cons((node*)strndup(s, len), (node*)len)); + return cons((node*)NODE_STR, cons((node*)strndup(s, len), (node*)(intptr_t)len)); } // (:dstr . a) @@ -697,6 +698,13 @@ new_dstr(parser_state *p, node *a) return cons((node*)NODE_DSTR, a); } +// (:dsym . a) +static node* +new_dsym(parser_state *p, node *a) +{ + return cons((node*)NODE_DSYM, new_dstr(p, a)); +} + // (:backref . n) static node* new_back_ref(parser_state *p, int n) @@ -754,11 +762,21 @@ args_with_block(parser_state *p, node *a, node *b) static void call_with_block(parser_state *p, node *a, node *b) { - node *n = a->cdr->cdr->cdr; + node *n; - if (!n->car) n->car = cons(0, b); + if (a->car == (node*)NODE_SUPER || + a->car == (node*)NODE_ZSUPER) { + if (!a->cdr) a->cdr = cons(0, b); + else { + args_with_block(p, a->cdr, b); + } + } else { - args_with_block(p, n->car, b); + n = a->cdr->cdr->cdr; + if (!n->car) n->car = cons(0, b); + else { + args_with_block(p, n->car, b); + } } } @@ -787,12 +805,8 @@ ret_args(parser_state *p, node *n) static void assignable(parser_state *p, node *lhs) { - switch ((int)(intptr_t)lhs->car) { - case NODE_LVAR: + if ((int)(intptr_t)lhs->car == NODE_LVAR) { local_add(p, (mrb_sym)lhs->cdr); - break; - default: - break; } } @@ -801,17 +815,14 @@ var_reference(parser_state *p, node *lhs) { node *n; - switch ((int)(intptr_t)lhs->car) { - case NODE_LVAR: + if ((int)(intptr_t)lhs->car == NODE_LVAR) { if (!local_var_p(p, (mrb_sym)lhs->cdr)) { n = new_fcall(p, (mrb_sym)lhs->cdr, 0); cons_free(lhs); return n; } - break; - default: - break; } + return lhs; } @@ -888,7 +899,7 @@ var_reference(parser_state *p, node *lhs) %token <num> tREGEXP_END %type <nd> singleton string string_interp regexp -%type <nd> literal numeric cpath +%type <nd> literal numeric cpath symbol %type <nd> top_compstmt top_stmts top_stmt %type <nd> bodystmt compstmt stmts stmt expr arg primary command command_call method_call %type <nd> expr_value arg_value primary_value @@ -904,8 +915,8 @@ var_reference(parser_state *p, node *lhs) %type <nd> bv_decls opt_bv_decl bvar f_larglist lambda_body %type <nd> brace_block cmd_brace_block do_block lhs none fitem f_bad_arg %type <nd> mlhs mlhs_list mlhs_post mlhs_basic mlhs_item mlhs_node mlhs_inner -%type <id> fsym sym symbol operation operation2 operation3 -%type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg +%type <id> fsym sym basic_symbol operation operation2 operation3 +%type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg %token tUPLUS /* unary+ */ %token tUMINUS /* unary- */ @@ -1472,7 +1483,7 @@ fname : tIDENTIFIER ; fsym : fname - | symbol + | basic_symbol ; fitem : fsym @@ -1502,7 +1513,7 @@ op : '|' { $$ = intern("|"); } | '>' { $$ = intern(">"); } | tGEQ { $$ = intern(">="); } | '<' { $$ = intern("<"); } - | tLEQ { $$ = intern(">="); } + | tLEQ { $$ = intern("<="); } | tNEQ { $$ = intern("!="); } | tLSHFT { $$ = intern("<<"); } | tRSHFT { $$ = intern(">>"); } @@ -2456,9 +2467,6 @@ opt_ensure : keyword_ensure compstmt literal : numeric | symbol - { - $$ = new_sym(p, $1); - } ; string : tCHAR @@ -2501,7 +2509,18 @@ string_interp : tSTRING_PART regexp : tREGEXP ; -symbol : tSYMBEG sym +symbol : basic_symbol + { + $$ = new_sym(p, $1); + } + | tSYMBEG tSTRING_BEG string_interp tSTRING + { + p->lstate = EXPR_END; + $$ = new_dsym(p, push($3, $4)); + } + ; + +basic_symbol : tSYMBEG sym { p->lstate = EXPR_END; $$ = $2; @@ -2512,6 +2531,14 @@ sym : fname | tIVAR | tGVAR | tCVAR + | tSTRING + { + $$ = new_strsym(p, $1); + } + | tSTRING_BEG tSTRING + { + $$ = new_strsym(p, $2); + } ; numeric : tINTEGER @@ -2585,7 +2612,7 @@ var_ref : variable { char buf[16]; - snprintf(buf, 16, "%d", p->lineno); + snprintf(buf, sizeof(buf), "%d", p->lineno); $$ = new_int(p, buf, 10); } ; @@ -2787,7 +2814,8 @@ f_rest_arg : restarg_mark tIDENTIFIER } | restarg_mark { - $$ = 0; + local_add_f(p, 0); + $$ = -1; } ; @@ -2824,7 +2852,7 @@ singleton : var_ref yyerror(p, "can't define singleton method for ()."); } else { - switch ((enum node_type)$3->car) { + switch ((enum node_type)(int)(intptr_t)$3->car) { case NODE_STR: case NODE_DSTR: case NODE_DREGX: @@ -2926,19 +2954,21 @@ static void yyerror(parser_state *p, const char *s) { char* c; - size_t n; + int n; if (! p->capture_errors) { +#ifdef ENABLE_STDIO if (p->filename) { fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s); } else { fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s); } +#endif } else if (p->nerr < sizeof(p->error_buffer) / sizeof(p->error_buffer[0])) { n = strlen(s); - c = parser_palloc(p, n + 1); + c = (char *)parser_palloc(p, n + 1); memcpy(c, s, n + 1); p->error_buffer[p->nerr].message = c; p->error_buffer[p->nerr].lineno = p->lineno; @@ -2952,7 +2982,7 @@ yyerror_i(parser_state *p, const char *fmt, int i) { char buf[256]; - snprintf(buf, 256, fmt, i); + snprintf(buf, sizeof(buf), fmt, i); yyerror(p, buf); } @@ -2960,19 +2990,21 @@ static void yywarn(parser_state *p, const char *s) { char* c; - size_t n; + int n; if (! p->capture_errors) { +#ifdef ENABLE_STDIO if (p->filename) { fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s); } else { fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s); } +#endif } else if (p->nerr < sizeof(p->warn_buffer) / sizeof(p->warn_buffer[0])) { n = strlen(s); - c = parser_palloc(p, n + 1); + c = (char *)parser_palloc(p, n + 1); memcpy(c, s, n + 1); p->warn_buffer[p->nwarn].message = c; p->warn_buffer[p->nwarn].lineno = p->lineno; @@ -2992,20 +3024,23 @@ yywarning_s(parser_state *p, const char *fmt, const char *s) { char buf[256]; - snprintf(buf, 256, fmt, s); + snprintf(buf, sizeof(buf), fmt, s); yywarning(p, buf); } static void backref_error(parser_state *p, node *n) { - switch ((int)(intptr_t)n->car) { - case NODE_NTH_REF: + int c; + + c = (int)(intptr_t)n->car; + + if (c == NODE_NTH_REF) { yyerror_i(p, "can't set variable $%d", (int)(intptr_t)n->cdr); - break; - case NODE_BACK_REF: + } else if (c == NODE_BACK_REF) { yyerror_i(p, "can't set variable $%c", (int)(intptr_t)n->cdr); - break; + } else { + mrb_bug("Internal error in backref_error() : n=>car == %d", c); } } @@ -3198,9 +3233,9 @@ toklen(parser_state *p) #define IS_LABEL_SUFFIX(n) (peek_n(p, ':',(n)) && !peek_n(p, ':', (n)+1)) static unsigned long -scan_oct(const char *start, int len, int *retlen) +scan_oct(const int *start, int len, int *retlen) { - const char *s = start; + const int *s = start; unsigned long retval = 0; while (len-- && *s >= '0' && *s <= '7') { @@ -3212,14 +3247,14 @@ scan_oct(const char *start, int len, int *retlen) } static unsigned long -scan_hex(const char *start, int len, int *retlen) +scan_hex(const int *start, int len, int *retlen) { static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF"; - register const char *s = start; + register const int *s = start; register unsigned long retval = 0; char *tmp; - while (len-- && *s && (tmp = strchr(hexdigit, *s))) { + while (len-- && *s && (tmp = (char *)strchr(hexdigit, *s))) { retval <<= 4; retval |= (tmp - hexdigit) & 15; s++; @@ -3261,7 +3296,7 @@ read_escape(parser_state *p) case '0': case '1': case '2': case '3': /* octal constant */ case '4': case '5': case '6': case '7': { - char buf[3]; + int buf[3]; int i; for (i=0; i<3; i++) { @@ -3278,7 +3313,7 @@ read_escape(parser_state *p) case 'x': /* hex constant */ { - char buf[2]; + int buf[2]; int i; for (i=0; i<2; i++) { @@ -3389,8 +3424,8 @@ parse_string(parser_state *p, int term) return tSTRING; } -static int -parse_qstring(parser_state *p, int term) +static node* +qstring_node(parser_state *p, int term) { int c; @@ -3426,9 +3461,20 @@ parse_qstring(parser_state *p, int term) } tokfix(p); - yylval.nd = new_str(p, tok(p), toklen(p)); p->lstate = EXPR_END; - return tSTRING; + return new_str(p, tok(p), toklen(p)); +} + +static int +parse_qstring(parser_state *p, int term) +{ + node *nd = qstring_node(p, term); + + if (nd) { + yylval.nd = new_str(p, tok(p), toklen(p)); + return tSTRING; + } + return 0; } static int @@ -3537,11 +3583,10 @@ parser_yylex(parser_state *p) c = '*'; } } - switch (p->lstate) { - case EXPR_FNAME: case EXPR_DOT: - p->lstate = EXPR_ARG; break; - default: - p->lstate = EXPR_BEG; break; + if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { + p->lstate = EXPR_ARG; + } else { + p->lstate = EXPR_BEG; } return c; @@ -3572,11 +3617,10 @@ parser_yylex(parser_state *p) goto retry; } } - switch (p->lstate) { - case EXPR_FNAME: case EXPR_DOT: - p->lstate = EXPR_ARG; break; - default: - p->lstate = EXPR_BEG; break; + if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { + p->lstate = EXPR_ARG; + } else { + p->lstate = EXPR_BEG; } if ((c = nextc(p)) == '=') { if ((c = nextc(p)) == '=') { @@ -3608,13 +3652,13 @@ parser_yylex(parser_state *p) if (token) return token; } #endif - switch (p->lstate) { - case EXPR_FNAME: case EXPR_DOT: - p->lstate = EXPR_ARG; break; - case EXPR_CLASS: - p->cmd_start = TRUE; - default: - p->lstate = EXPR_BEG; break; + if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { + p->lstate = EXPR_ARG; + } else { + p->lstate = EXPR_BEG; + if (p->lstate == EXPR_CLASS) { + p->cmd_start = TRUE; + } } if (c == '=') { if ((c = nextc(p)) == '>') { @@ -3636,11 +3680,10 @@ parser_yylex(parser_state *p) return '<'; case '>': - switch (p->lstate) { - case EXPR_FNAME: case EXPR_DOT: - p->lstate = EXPR_ARG; break; - default: - p->lstate = EXPR_BEG; break; + if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { + p->lstate = EXPR_ARG; + } else { + p->lstate = EXPR_BEG; } if ((c = nextc(p)) == '=') { return tGEQ; @@ -3676,7 +3719,7 @@ parser_yylex(parser_state *p) } if (isspace(c)) { if (!IS_ARG()) { - int c2 = 0; + int c2; switch (c) { case ' ': c2 = 's'; @@ -3696,10 +3739,13 @@ parser_yylex(parser_state *p) case '\f': c2 = 'f'; break; + default: + c2 = 0; + break; } if (c2) { char buf[256]; - snprintf(buf, 256, "invalid character syntax; use ?\\%c", c2); + snprintf(buf, sizeof(buf), "invalid character syntax; use ?\\%c", c2); yyerror(p, buf); } } @@ -3765,10 +3811,9 @@ parser_yylex(parser_state *p) else { c = '&'; } - switch (p->lstate) { - case EXPR_FNAME: case EXPR_DOT: - p->lstate = EXPR_ARG; break; - default: + if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { + p->lstate = EXPR_ARG; + } else { p->lstate = EXPR_BEG; } return c; @@ -3902,7 +3947,7 @@ parser_yylex(parser_state *p) } if (!ISXDIGIT(c)) break; nondigit = 0; - tokadd(p, c); + tokadd(p, tolower(c)); } while ((c = nextc(p)) != -1); } pushback(p, c); @@ -4081,8 +4126,15 @@ parser_yylex(parser_state *p) } tokfix(p); if (is_float) { - (void)strtod(tok(p), 0); /* just check if float is within range */ - if (errno == ERANGE) { + double d; + char *endp; + + errno = 0; + d = strtod(tok(p), &endp); + if (d == 0 && endp == tok(p)) { + yywarning_s(p, "corrupted float value %s", tok(p)); + } + else if (errno == ERANGE) { yywarning_s(p, "float %s out of range", tok(p)); errno = 0; } @@ -4120,21 +4172,7 @@ parser_yylex(parser_state *p) p->lstate = EXPR_BEG; return ':'; } - switch (c) { - case '\'': -#if 0 - p->lex_strterm = new_strterm(p, str_ssym, c, 0); -#endif - break; - case '"': -#if 0 - p->lex_strterm = new_strterm(p, str_dsym, c, 0); -#endif - break; - default: - pushback(p, c); - break; - } + pushback(p, c); p->lstate = EXPR_FNAME; return tSYMBEG; @@ -4158,11 +4196,10 @@ parser_yylex(parser_state *p) #endif return tREGEXP_BEG; } - switch (p->lstate) { - case EXPR_FNAME: case EXPR_DOT: - p->lstate = EXPR_ARG; break; - default: - p->lstate = EXPR_BEG; break; + if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { + p->lstate = EXPR_ARG; + } else { + p->lstate = EXPR_BEG; } return '/'; @@ -4172,11 +4209,10 @@ parser_yylex(parser_state *p) p->lstate = EXPR_BEG; return tOP_ASGN; } - switch (p->lstate) { - case EXPR_FNAME: case EXPR_DOT: - p->lstate = EXPR_ARG; break; - default: - p->lstate = EXPR_BEG; break; + if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { + p->lstate = EXPR_ARG; + } else { + p->lstate = EXPR_BEG; } pushback(p, c); return '^'; @@ -4361,11 +4397,10 @@ parser_yylex(parser_state *p) if (IS_SPCARG(c)) { goto quotation; } - switch (p->lstate) { - case EXPR_FNAME: case EXPR_DOT: - p->lstate = EXPR_ARG; break; - default: - p->lstate = EXPR_BEG; break; + if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { + p->lstate = EXPR_ARG; + } else { + p->lstate = EXPR_BEG; } pushback(p, c); return '%'; @@ -4539,7 +4574,7 @@ parser_yylex(parser_state *p) pushback(p, c); } } - if (result == 0 && isupper(tok(p)[0])) { + if (result == 0 && isupper((int)tok(p)[0])) { result = tCONSTANT; } else { @@ -4636,8 +4671,48 @@ yylex(void *lval, parser_state *p) return t; } +static void +parser_init_cxt(parser_state *p, mrbc_context *cxt) +{ + if (!cxt) return; + if (cxt->lineno) p->lineno = cxt->lineno; + if (cxt->filename) p->filename = cxt->filename; + if (cxt->syms) { + int i; + + p->locals = cons(0,0); + for (i=0; i<cxt->slen; i++) { + local_add_f(p, cxt->syms[i]); + } + } + p->capture_errors = cxt->capture_errors; +} + +static void +parser_update_cxt(parser_state *p, mrbc_context *cxt) +{ + node *n, *n0; + int i = 0; + + if (!cxt) return; + if ((int)(intptr_t)p->tree->car != NODE_SCOPE) return; + n0 = n = p->tree->cdr->car; + while (n) { + i++; + n = n->cdr; + } + cxt->syms = (mrb_sym *)mrb_realloc(p->mrb, cxt->syms, i*sizeof(mrb_sym)); + cxt->slen = i; + for (i=0, n=n0; n; i++,n=n->cdr) { + cxt->syms[i] = (mrb_sym)n->car; + } +} + +void codedump_all(mrb_state*, int); +void parser_dump(mrb_state *mrb, node *tree, int offset); + void -mrb_parser_parse(parser_state *p) +mrb_parser_parse(parser_state *p, mrbc_context *c) { node *tree; @@ -4653,6 +4728,7 @@ mrb_parser_parse(parser_state *p) p->nerr = p->nwarn = 0; p->sterm = 0; + parser_init_cxt(p, c); yyparse(p); tree = p->tree; if (!tree) { @@ -4664,14 +4740,15 @@ mrb_parser_parse(parser_state *p) } } else { - if ((intptr_t)tree->car == NODE_SCOPE) { - p->locals = cons(tree->cdr->car, 0); - } + parser_update_cxt(p, c); if (p->begin_tree) { tree = new_begin(p, p->begin_tree); append(tree, p->tree); } } + if (c && c->dump_result) { + parser_dump(p->mrb, p->tree, 0); + } } parser_state* @@ -4682,7 +4759,7 @@ mrb_parser_new(mrb_state *mrb) pool = mrb_pool_open(mrb); if (!pool) return 0; - p = mrb_pool_alloc(pool, sizeof(parser_state)); + p = (parser_state *)mrb_pool_alloc(pool, sizeof(parser_state)); if (!p) return 0; memset(p, 0, sizeof(parser_state)); @@ -4697,7 +4774,6 @@ mrb_parser_new(mrb_state *mrb) p->in_def = p->in_single = FALSE; p->capture_errors = 0; - p->lineno = 1; p->column = 0; #if defined(PARSER_TEST) || defined(PARSER_DEBUG) @@ -4707,28 +4783,45 @@ mrb_parser_new(mrb_state *mrb) return p; } -const char* -mrb_parser_filename(parser_state *p, const char *s) +void +mrb_parser_free(parser_state *p) { + mrb_pool_close(p->pool); +} + +mrbc_context* +mrbc_context_new(mrb_state *mrb) { - if (s) { - p->filename = strdup(s); - } - return p->filename; + mrbc_context *c; + + c = (mrbc_context *)mrb_calloc(mrb, 1, sizeof(mrbc_context)); + return c; } -int -mrb_parser_lineno(struct mrb_parser_state *p, int n) +void +mrbc_context_free(mrb_state *mrb, mrbc_context *cxt) +{ + mrb_free(mrb, cxt->syms); + mrb_free(mrb, cxt->filename); + mrb_free(mrb, cxt); +} + +const char* +mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s) { - if (n <= 0) { - return p->lineno; + if (s) { + int len = strlen(s); + char *p = (char *)mrb_malloc(mrb, len); + + memcpy(p, s, len); + if (c->filename) mrb_free(mrb, c->filename); + c->filename = p; + c->lineno = 1; } - p->column = 0; - p->lineno = n; - return n; + return c->filename; } parser_state* -mrb_parse_file(mrb_state *mrb, FILE *f) +mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c) { parser_state *p; @@ -4737,12 +4830,12 @@ mrb_parse_file(mrb_state *mrb, FILE *f) p->s = p->send = NULL; p->f = f; - mrb_parser_parse(p); + mrb_parser_parse(p, c); return p; } parser_state* -mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len) +mrb_parse_nstring(mrb_state *mrb, const char *s, int len, mrbc_context *c) { parser_state *p; @@ -4751,64 +4844,97 @@ mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len) p->s = s; p->send = s + len; - mrb_parser_parse(p); + mrb_parser_parse(p, c); return p; } parser_state* -mrb_parse_string(mrb_state *mrb, const char *s) +mrb_parse_string(mrb_state *mrb, const char *s, mrbc_context *c) { - return mrb_parse_nstring(mrb, s, strlen(s)); + return mrb_parse_nstring(mrb, s, strlen(s), c); } -#define PARSER_DUMP - -void parser_dump(mrb_state *mrb, node *tree, int offset); - -int -mrb_compile_file(mrb_state * mrb, FILE *f) +static mrb_value +load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c) { - parser_state *p; int n; + mrb_value v; - p = mrb_parse_file(mrb, f); - if (!p) return -1; - if (!p->tree) return -1; - if (p->nerr) return -1; -#ifdef PARSER_DUMP - parser_dump(mrb, p->tree, 0); -#endif + if (!p) { + mrb_parser_free(p); + return mrb_undef_value(); + } + if (!p->tree || p->nerr) { + if (p->capture_errors) { + char buf[256]; + + n = snprintf(buf, sizeof(buf), "line %d: %s\n", + p->error_buffer[0].lineno, p->error_buffer[0].message); + mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n)); + mrb_parser_free(p); + return mrb_undef_value(); + } + else { + static const char msg[] = "syntax error"; + mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SYNTAX_ERROR, msg, sizeof(msg) - 1)); + mrb_parser_free(p); + return mrb_nil_value(); + } + } n = mrb_generate_code(mrb, p->tree); - mrb_pool_close(p->pool); + mrb_parser_free(p); + if (n < 0) { + static const char msg[] = "codegen error"; + mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1)); + return mrb_nil_value(); + } + if (c) { + if (c->dump_result) codedump_all(mrb, n); + if (c->no_exec) return mrb_fixnum_value(n); + } + v = mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb)); + if (mrb->exc) return mrb_nil_value(); + return v; +} - return n; +mrb_value +mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c) +{ + return load_exec(mrb, mrb_parse_file(mrb, f, c), c); } -int -mrb_compile_nstring(mrb_state *mrb, char *s, size_t len) +mrb_value +mrb_load_file(mrb_state *mrb, FILE *f) { - parser_state *p; - int n; + return mrb_load_file_cxt(mrb, f, NULL); +} - p = mrb_parse_nstring(mrb, s, len); - if (!p) return -1; - if (!p->tree) return -1; - if (p->nerr) return -1; -#ifdef PARSER_DUMP - parser_dump(mrb, p->tree, 0); -#endif - n = mrb_generate_code(mrb, p->tree); - mrb_pool_close(p->pool); +mrb_value +mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *c) +{ + return load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c); +} - return n; +mrb_value +mrb_load_nstring(mrb_state *mrb, const char *s, int len) +{ + return mrb_load_nstring_cxt(mrb, s, len, NULL); } -int -mrb_compile_string(mrb_state *mrb, char *s) +mrb_value +mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *c) +{ + return mrb_load_nstring_cxt(mrb, s, strlen(s), c); +} + +mrb_value +mrb_load_string(mrb_state *mrb, const char *s) { - return mrb_compile_nstring(mrb, s, strlen(s)); + return mrb_load_string_cxt(mrb, s, NULL); } +#ifdef ENABLE_STDIO + static void dump_prefix(int offset) { @@ -4827,9 +4953,12 @@ dump_recur(mrb_state *mrb, node *tree, int offset) } } +#endif + void parser_dump(mrb_state *mrb, node *tree, int offset) { +#ifdef ENABLE_STDIO int n; if (!tree) return; @@ -4891,7 +5020,7 @@ parser_dump(mrb_state *mrb, node *tree, int offset) parser_dump(mrb, tree->car, offset+2); dump_prefix(offset+1); printf("ensure:\n"); - parser_dump(mrb, tree->cdr, offset+2); + parser_dump(mrb, tree->cdr->cdr, offset+2); break; case NODE_LAMBDA: @@ -5052,15 +5181,20 @@ parser_dump(mrb_state *mrb, node *tree, int offset) case NODE_SCOPE: printf("NODE_SCOPE:\n"); - dump_prefix(offset+1); - printf("local variables:\n"); { node *n2 = tree->car; - while (n2) { - dump_prefix(offset+2); - printf("%s\n", mrb_sym2name(mrb, (mrb_sym)n2->car)); - n2 = n2->cdr; + if (n2 && (n2->car || n2->cdr)) { + dump_prefix(offset+1); + printf("local variables:\n"); + while (n2) { + if (n2->car) { + dump_prefix(offset+2); + printf("%s ", mrb_sym2name(mrb, (mrb_sym)n2->car)); + } + n2 = n2->cdr; + } + printf("\n"); } } tree = tree->cdr; @@ -5392,16 +5526,21 @@ parser_dump(mrb_state *mrb, node *tree, int offset) dump_prefix(offset+1); printf("%s\n", mrb_sym2name(mrb, (mrb_sym)tree->car)); tree = tree->cdr; - dump_prefix(offset+1); - printf("local variables:\n"); { node *n2 = tree->car; - while (n2) { - dump_prefix(offset+2); - if (n2->car) - printf("%s\n", mrb_sym2name(mrb, (mrb_sym)n2->car)); - n2 = n2->cdr; + if (n2 && (n2->car || n2->cdr)) { + dump_prefix(offset+1); + printf("local variables:\n"); + + while (n2) { + if (n2->car) { + dump_prefix(offset+2); + printf("%s ", mrb_sym2name(mrb, (mrb_sym)n2->car)); + } + n2 = n2->cdr; + } + printf("\n"); } } tree = tree->cdr; @@ -5508,7 +5647,7 @@ parser_dump(mrb_state *mrb, node *tree, int offset) printf("node type: %d (0x%x)\n", (int)n, (int)n); break; } - return; +#endif } #ifdef PARSER_TEST diff --git a/src/pool.c b/src/pool.c index 3cbb2b163..daa6d0f69 100644 --- a/src/pool.c +++ b/src/pool.c @@ -8,6 +8,18 @@ #include <stddef.h> #include <string.h> +/* configuration section */ +/* allocated memory address should be multiple of POOL_ALIGNMENT */ +/* or undef it if alignment does not matter */ +#ifndef POOL_ALIGNMENT +#define POOL_ALIGNMENT 4 +#endif +/* page size of memory pool */ +#ifndef POOL_PAGE_SIZE +#define POOL_PAGE_SIZE 16000 +#endif +/* end of configuration section */ + struct mrb_pool_page { struct mrb_pool_page *next; size_t offset; @@ -23,16 +35,13 @@ struct mrb_pool { #undef TEST_POOL #ifdef TEST_POOL -#include <stdio.h> #define mrb_malloc(m,s) malloc(s) #define mrb_free(m,p) free(p) #endif -#define POOL_PAGE_SIZE 16000 - -#ifdef ALLOC_ALIGN -# define ALIGN_PADDING(x) ((x % ALLOC_ALIGN) ? ALLOC_ALIGN - (x % ALLOC_ALIGN) : 0) +#ifdef POOL_ALIGNMENT +# define ALIGN_PADDING(x) ((-x) & (POOL_ALIGNMENT - 1)) #else # define ALIGN_PADDING(x) (0) #endif @@ -40,7 +49,7 @@ struct mrb_pool { mrb_pool* mrb_pool_open(mrb_state *mrb) { - mrb_pool *pool = mrb_malloc(mrb, sizeof(mrb_pool)); + mrb_pool *pool = (mrb_pool *)mrb_malloc(mrb, sizeof(mrb_pool)); if (pool) { pool->mrb = mrb; @@ -72,7 +81,7 @@ page_alloc(mrb_pool *pool, size_t len) if (len < POOL_PAGE_SIZE) len = POOL_PAGE_SIZE; - page = mrb_malloc(pool->mrb, sizeof(struct mrb_pool_page)+len-1); + page = (struct mrb_pool_page *)mrb_malloc(pool->mrb, sizeof(struct mrb_pool_page)+len-1); if (page) { page->offset = 0; page->len = len; diff --git a/src/print.c b/src/print.c index 505597935..e6805edbf 100644 --- a/src/print.c +++ b/src/print.c @@ -5,35 +5,31 @@ */ #include "mruby.h" +#ifdef ENABLE_STDIO #include "mruby/string.h" #include <stdio.h> -mrb_value +static void printstr(mrb_state *mrb, mrb_value obj) { struct RString *str; char *s; - size_t len; + int len; if (mrb_type(obj) == MRB_TT_STRING) { str = mrb_str_ptr(obj); - s = str->buf; + s = str->ptr; len = str->len; - while (len--) { - putc(*s, stdout); - s++; - } + fwrite(s, len, 1, stdout); } - return obj; } -mrb_value +void mrb_p(mrb_state *mrb, mrb_value obj) { obj = mrb_funcall(mrb, obj, "inspect", 0); printstr(mrb, obj); putc('\n', stdout); - return obj; } /* 15.3.1.2.9 */ @@ -71,3 +67,19 @@ mrb_show_copyright(mrb_state *mrb) { printf("mruby - Copyright (c) 2010-2012 mruby developers\n"); } +#else +void +mrb_p(mrb_state *mrb, mrb_value obj) +{ +} + +void +mrb_show_version(mrb_state *mrb) +{ +} + +void +mrb_show_copyright(mrb_state *mrb) +{ +} +#endif diff --git a/src/proc.c b/src/proc.c index 21c462493..e5c233e1b 100644 --- a/src/proc.c +++ b/src/proc.c @@ -6,7 +6,6 @@ #include "mruby.h" #include "mruby/proc.h" -#include "mruby/array.h" #include "mruby/class.h" #include "opcode.h" @@ -16,8 +15,8 @@ mrb_proc_new(mrb_state *mrb, mrb_irep *irep) struct RProc *p; p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class); - p->body.irep = irep; p->target_class = (mrb->ci) ? mrb->ci->target_class : 0; + p->body.irep = irep; p->env = 0; return p; @@ -56,20 +55,41 @@ mrb_proc_new_cfunc(mrb_state *mrb, mrb_func_t func) return p; } +void +mrb_proc_copy(struct RProc *a, struct RProc *b) +{ + a->flags = b->flags; + a->body = b->body; + a->target_class = b->target_class; + a->env = b->env; +} + static mrb_value mrb_proc_initialize(mrb_state *mrb, mrb_value self) { mrb_value blk; mrb_get_args(mrb, "&", &blk); - if (!mrb_nil_p(blk)) { - *mrb_proc_ptr(self) = *mrb_proc_ptr(blk); - } - else { + if (mrb_nil_p(blk)) { /* Calling Proc.new without a block is not implemented yet */ mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block"); } + else { + mrb_proc_copy(mrb_proc_ptr(self), mrb_proc_ptr(blk)); + } + return self; +} + +static mrb_value +mrb_proc_init_copy(mrb_state *mrb, mrb_value self) +{ + mrb_value proc; + mrb_get_args(mrb, "o", &proc); + if (mrb_type(proc) != MRB_TT_PROC) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc"); + } + mrb_proc_copy(mrb_proc_ptr(self), mrb_proc_ptr(proc)); return self; } @@ -91,12 +111,41 @@ mrb_proc_iseq(mrb_state *mrb, struct RProc *p) return p->body.irep->iseq; } +/* 15.3.1.2.6 */ +/* 15.3.1.3.27 */ +/* + * call-seq: + * lambda { |...| block } -> a_proc + * + * Equivalent to <code>Proc.new</code>, except the resulting Proc objects + * check the number of parameters passed when called. + */ +static mrb_value +proc_lambda(mrb_state *mrb, mrb_value self) +{ + mrb_value blk; + struct RProc *p; + + mrb_get_args(mrb, "&", &blk); + if (mrb_nil_p(blk)) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block"); + } + p = mrb_proc_ptr(blk); + if (!MRB_PROC_STRICT_P(p)) { + struct RProc *p2 = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, p->c); + mrb_proc_copy(p2, p); + p2->flags |= MRB_PROC_STRICT; + return mrb_obj_value(p2); + } + return blk; +} + void mrb_init_proc(mrb_state *mrb) { struct RProc *m; - mrb_code *call_iseq = mrb_malloc(mrb, sizeof(mrb_code)); - mrb_irep *call_irep = mrb_calloc(mrb, sizeof(mrb_irep), 1); + mrb_code *call_iseq = (mrb_code *)mrb_malloc(mrb, sizeof(mrb_code)); + mrb_irep *call_irep = (mrb_irep *)mrb_calloc(mrb, sizeof(mrb_irep), 1); if ( call_iseq == NULL || call_irep == NULL ) return; @@ -108,10 +157,15 @@ mrb_init_proc(mrb_state *mrb) call_irep->ilen = 1; mrb->proc_class = mrb_define_class(mrb, "Proc", mrb->object_class); + MRB_SET_INSTANCE_TT(mrb->proc_class, MRB_TT_PROC); mrb_define_method(mrb, mrb->proc_class, "initialize", mrb_proc_initialize, ARGS_NONE()); + mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, ARGS_REQ(1)); m = mrb_proc_new(mrb, call_irep); mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern(mrb, "call"), m); mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern(mrb, "[]"), m); + + mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, ARGS_NONE()); /* 15.3.1.2.6 */ + mrb_define_method(mrb, mrb->kernel_module, "lambda", proc_lambda, ARGS_NONE()); /* 15.3.1.3.27 */ } diff --git a/src/range.c b/src/range.c index c1fb580b5..db17c7d40 100644 --- a/src/range.c +++ b/src/range.c @@ -7,30 +7,35 @@ #include "mruby.h" #include "mruby/class.h" #include "mruby/range.h" -#include "mruby/variable.h" -#include "error.h" -#include "mruby/numeric.h" #include "mruby/string.h" - -#include <stdio.h> #include <string.h> -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - #ifndef OTHER #define OTHER 2 #endif #define RANGE_CLASS (mrb_class_obj_get(mrb, "Range")) -mrb_value mrb_exec_recursive_paired(mrb_state *mrb, mrb_value (*func) (mrb_state *, mrb_value, mrb_value, int), - mrb_value obj, mrb_value paired_obj, void* arg); +static void +range_check(mrb_state *mrb, mrb_value a, mrb_value b) +{ + mrb_value ans; + int ta; + int tb; + + ta = mrb_type(a); + tb = mrb_type(b); + if ((ta == MRB_TT_FIXNUM || ta == MRB_TT_FLOAT) && + (tb == MRB_TT_FIXNUM || tb == MRB_TT_FLOAT)) { + return; + } + + ans = mrb_funcall(mrb, a, "<=>", 1, b); + if (mrb_nil_p(ans)) { + /* can not be compared */ + mrb_raise(mrb, E_ARGUMENT_ERROR, "bad value for range"); + } +} mrb_value mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, int excl) @@ -38,7 +43,8 @@ mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, int excl) struct RRange *r; r = (struct RRange*)mrb_obj_alloc(mrb, MRB_TT_RANGE, RANGE_CLASS); - r->edges = mrb_malloc(mrb, sizeof(struct mrb_range_edges)); + r->edges = (struct mrb_range_edges *)mrb_malloc(mrb, sizeof(struct mrb_range_edges)); + range_check(mrb, beg, end); r->edges->beg = beg; r->edges->end = end; r->excl = excl; @@ -93,41 +99,12 @@ mrb_range_excl(mrb_state *mrb, mrb_value range) return r->excl ? mrb_true_value() : mrb_false_value(); } -/* - * call-seq: - * beg end - * args[0] <= args[1] => true - * args[0] > args[1] => false - */ -static int -range_check(mrb_state *mrb, mrb_value *args) -{ - mrb_value ans = mrb_funcall(mrb, args[0], "<=>", 1, args[1]); - /* beg end - ans :args[0] < args[1] => -1 - args[0] = args[1] => 0 - args[0] > args[1] => +1 */ - if (mrb_nil_p(ans)) return FALSE; - //if (mrb_obj_equal(mrb, ans, mrb_fixnum_value(1))) return FALSE; - if (mrb_fixnum(ans) == 1) return FALSE; - return TRUE; -} - static void range_init(mrb_state *mrb, mrb_value range, mrb_value beg, mrb_value end, mrb_int exclude_end) { - mrb_value args[2]; struct RRange *r = mrb_range_ptr(range); - if ((mrb_type(beg) != MRB_TT_FIXNUM) || (mrb_type(end) != MRB_TT_FIXNUM)) { - args[0] = beg; - args[1] = end; - /* eroor.c v = mrb_rescue(range_check, (mrb_value)args, range_failed, 0); - if (mrb_nil_p(v)) range_failed(); */ - if (!range_check(mrb, args)) { - printf("range_failed()\n"); - } - } + range_check(mrb, beg, end); r->excl = exclude_end; r->edges->beg = beg; r->edges->end = end; @@ -179,7 +156,6 @@ mrb_range_eq(mrb_state *mrb, mrb_value range) if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value(); /* same class? */ - // if (!rb_obj_is_instance_of(obj, rb_obj_class(range))) if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) return mrb_false_value(); @@ -198,55 +174,41 @@ mrb_range_eq(mrb_state *mrb, mrb_value range) static int r_le(mrb_state *mrb, mrb_value a, mrb_value b) { - //int c; mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */ /* output :a < b => -1, a = b => 0, a > b => +1 */ - if (mrb_nil_p(r)) return FALSE; + if (mrb_type(r) == MRB_TT_FIXNUM) { + int c = mrb_fixnum(r); + if (c == 0 || c == -1) return TRUE; + } - /* mrb_value -> int */ - //c = mrb_cmpint(mrb, r, a, b); - //if (c == 0) return TRUE; - //if (c < 0) return TRUE; - //return FALSE; - if (mrb_obj_equal(mrb, r, mrb_fixnum_value(0))) return TRUE; - if (mrb_obj_equal(mrb, r, mrb_fixnum_value(-1))) return TRUE; return FALSE; } static int r_gt(mrb_state *mrb, mrb_value a, mrb_value b) { - //int c; mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* output :a < b => -1, a = b => 0, a > b => +1 */ - if (mrb_nil_p(r)) return FALSE; + if (mrb_type(r) == MRB_TT_FIXNUM) { + if (mrb_fixnum(r) == 1) return TRUE; + } - /* mrb_value -> int */ - //c = mrb_cmpint(mrb, r); - //if (c > 0) return TRUE; - //return FALSE; - if (mrb_obj_equal(mrb, r, mrb_fixnum_value(1))) return TRUE; return FALSE; } static int r_ge(mrb_state *mrb, mrb_value a, mrb_value b) { - //int c; mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */ /* output :a < b => -1, a = b => 0, a > b => +1 */ - if (mrb_nil_p(r)) return FALSE; + if (mrb_type(r) == MRB_TT_FIXNUM) { + int c = mrb_fixnum(r); + if (c == 0 || c == 1) return TRUE; + } - /* mrb_value -> int */ - //c = mrb_cmpint(mrb, r); - //if (c == 0) return TRUE; - //if (c > 0) return TRUE; - //return FALSE; - if (mrb_obj_equal(mrb, r, mrb_fixnum_value(0))) return TRUE; - if (mrb_obj_equal(mrb, r, mrb_fixnum_value(1))) return TRUE; return FALSE; } @@ -370,7 +332,12 @@ inspect_range(mrb_state *mrb, mrb_value range, mrb_value dummy, int recur) struct RRange *r = mrb_range_ptr(range); if (recur) { - return mrb_str_new2(mrb, r->excl ? "(... ... ...)" : "(... .. ...)"); + static const char s[2][14] = { "(... ... ...)", "(... .. ...)" }; + static const int n[] = { 13, 12 }; + int idx; + + idx = (r->excl) ? 0 : 1; + return mrb_str_new(mrb, s[idx], n[idx]); } str = mrb_inspect(mrb, r->edges->beg); str2 = mrb_inspect(mrb, r->edges->end); @@ -397,23 +364,6 @@ range_inspect(mrb_state *mrb, mrb_value range) return inspect_range(mrb, range, range, 0); } -static mrb_value -recursive_eql(mrb_state *mrb, mrb_value range, mrb_value obj, int recur) -{ - struct RRange *r = mrb_range_ptr(range); - struct RRange *o = mrb_range_ptr(obj); - - if (recur) return mrb_true_value(); /* Subtle! */ - if (!mrb_eql(mrb, r->edges->beg, o->edges->beg)) - return mrb_false_value(); - if (!mrb_eql(mrb, r->edges->end, o->edges->end)) - return mrb_false_value(); - - if (r->excl != o->excl) - return mrb_false_value(); - return mrb_true_value(); -} - /* 15.2.14.4.14(x) */ /* * call-seq: @@ -433,13 +383,24 @@ static mrb_value range_eql(mrb_state *mrb, mrb_value range) { mrb_value obj; + struct RRange *r, *o; mrb_get_args(mrb, "o", &obj); if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value(); if (!mrb_obj_is_kind_of(mrb, obj, RANGE_CLASS)) return mrb_false_value(); - return mrb_exec_recursive_paired(mrb, recursive_eql, range, obj, &obj); + + r = mrb_range_ptr(range); + if (obj.tt != MRB_TT_RANGE) return mrb_false_value(); + o = mrb_range_ptr(obj); + if (!mrb_eql(mrb, r->edges->beg, o->edges->beg)) + return mrb_false_value(); + if (!mrb_eql(mrb, r->edges->end, o->edges->end)) + return mrb_false_value(); + if (r->excl != o->excl) + return mrb_false_value(); + return mrb_true_value(); } /* 15.2.14.4.15(x) */ @@ -451,7 +412,6 @@ range_initialize_copy(mrb_state *mrb, mrb_value copy) mrb_get_args(mrb, "o", &src); if (mrb_obj_equal(mrb, copy, src)) return copy; - //mrb_check_frozen(copy); if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) { mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class"); } @@ -13,7 +13,7 @@ #include "regint.h" #include "mruby/class.h" #include "error.h" -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP #define REGEX_CLASS (mrb_class_obj_get(mrb, "Regexp")) #define MATCH_CLASS (mrb_class_obj_get(mrb, "MatchData")) @@ -26,14 +26,6 @@ #define MKARG_B(c) (((c) & 0xff) << 16) #define MKARG_C(c) (((c) & 0xff) << 8) -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - #define ARG_REG_OPTION_MASK \ (ONIG_OPTION_IGNORECASE|ONIG_OPTION_MULTILINE|ONIG_OPTION_EXTEND) #define ARG_ENCODING_FIXED 16 @@ -84,7 +76,7 @@ mrb_reg_s_new_instance(mrb_state *mrb, /*int argc, mrb_value *argv, */mrb_value re->ptr = 0; re->src = 0; re->usecnt = 0; - return mrb_funcall_argv(mrb, mrb_obj_value(re), "initialize", argc, argv); + return mrb_funcall_argv(mrb, mrb_obj_value(re), mrb_intern(mrb, "initialize"), argc, argv); } mrb_value @@ -362,17 +354,17 @@ mrb_reg_options(mrb_state *mrb, mrb_value re) static mrb_value mrb_reg_desc(mrb_state *mrb, const char *s, long len, mrb_value re) { - mrb_value str = mrb_str_new_cstr(mrb, "/");//mrb_str_buf_new2("/"); + mrb_value str = mrb_str_new(mrb, "/", 1); mrb_reg_expr_str(mrb, str, s, len); - mrb_str_buf_cat(mrb, str, "/", strlen("/")); + mrb_str_buf_cat(mrb, str, "/", 1); if (re.tt) { char opts[4]; mrb_reg_check(mrb, re); if (*option_to_str(opts, RREGEXP(re)->ptr->options)) mrb_str_buf_cat(mrb, str, opts, strlen(opts));//mrb_str_buf_cat2(str, opts); if (RBASIC(re)->flags & REG_ENCODING_NONE) - mrb_str_buf_cat(mrb, str, "n", strlen("n"));//mrb_str_buf_cat2(str, "n"); + mrb_str_buf_cat(mrb, str, "n", 1); } return str; @@ -1696,9 +1688,10 @@ mrb_reg_expr_str(mrb_state *mrb, mrb_value str, const char *s, long len) } else if (!ISSPACE(c)) { char b[8]; + int n; - snprintf(b, sizeof(b), "\\x%02X", c); - mrb_str_buf_cat(mrb, str, b, 4); + n = snprintf(b, sizeof(b), "\\x%02X", c); + mrb_str_buf_cat(mrb, str, b, n); } else { mrb_str_buf_cat(mrb, str, p, 1); @@ -1736,7 +1729,7 @@ mrb_reg_to_s(mrb_state *mrb, mrb_value re) const int embeddable = ONIG_OPTION_MULTILINE|ONIG_OPTION_IGNORECASE|ONIG_OPTION_EXTEND; long len; const UChar* ptr; - mrb_value str = mrb_str_new_cstr(mrb, "(?"); + mrb_value str = mrb_str_new(mrb, "(?", 2); char optbuf[5]; mrb_encoding *enc = mrb_enc_get(mrb, re); @@ -1804,9 +1797,9 @@ again: mrb_str_buf_cat(mrb, str, optbuf, strlen(optbuf)); } - mrb_str_buf_cat(mrb, str, ":", strlen(":")); + mrb_str_buf_cat(mrb, str, ":", 1); mrb_reg_expr_str(mrb, str, (char*)ptr, len); - mrb_str_buf_cat(mrb, str, ")", strlen(")")); + mrb_str_buf_cat(mrb, str, ")", 1); return str; } @@ -1926,30 +1919,29 @@ mrb_match_inspect(mrb_state *mrb, mrb_value match) onig_foreach_name(regexp->ptr, match_inspect_name_iter, names); - str = mrb_str_new_cstr(mrb, "#<");//mrb_str_buf_new2("#<"); - mrb_str_buf_cat(mrb, str, cname, strlen(cname));//mrb_str_buf_cat2(str, cname); + str = mrb_str_new(mrb, "#<", 2); + mrb_str_buf_cat(mrb, str, cname, strlen(cname)); for (i = 0; i < num_regs; i++) { char buf[sizeof(num_regs)*3+1]; mrb_value v; - mrb_str_buf_cat(mrb, str, " ", strlen(" "));//mrb_str_buf_cat2(str, " "); + mrb_str_buf_cat(mrb, str, " ", 1); if (0 < i) { if (names[i].name) mrb_str_buf_cat(mrb, str, (const char*)names[i].name, names[i].len); else { - //mrb_str_catf(mrb, str, "%d", i); - sprintf(buf, "%d", i); - mrb_str_buf_cat(mrb, str, (const char*)buf, strlen(buf)); + int n = sprintf(buf, "%d", i); + mrb_str_buf_cat(mrb, str, (const char*)buf, n); } - mrb_str_buf_cat(mrb, str, ":", strlen(":"));//mrb_str_buf_cat2(str, ":"); + mrb_str_buf_cat(mrb, str, ":", 1); } v = mrb_reg_nth_match(mrb, i, match); if (mrb_nil_p(v)) - mrb_str_buf_cat(mrb, str, "nil", strlen("nil"));//mrb_str_buf_cat2(str, "nil"); + mrb_str_buf_cat(mrb, str, "nil", 3); else mrb_str_buf_append(mrb, str, mrb_str_inspect(mrb, v)); } - mrb_str_buf_cat(mrb, str, ">", strlen(">"));//mrb_str_buf_cat2(str, ">"); + mrb_str_buf_cat(mrb, str, ">", 1); return str; } @@ -2049,7 +2041,7 @@ mrb_init_regexp(mrb_state *mrb) mrb_define_const(mrb, s, "FIXEDENCODING", mrb_fixnum_value(ARG_ENCODING_FIXED)); s = mrb_define_class(mrb, "MatchData", mrb->object_class); - //mrb_undef_method(CLASS_OF(rb_cMatch), "new"); + //mrb_undef_class_method(CLASS_OF(rb_cMatch), "new"); mrb_define_method(mrb, s, "[]", mrb_match_aref, ARGS_ANY()); /* 15.2.16.3.1 */ mrb_define_method(mrb, s, "begin", mrb_match_begin, ARGS_REQ(1)); /* 15.2.16.3.2 */ @@ -2151,7 +2143,7 @@ mrb_reg_regsub(mrb_state *mrb, mrb_value str, mrb_value src, struct re_registers break; } else { - mrb_raise(mrb, mrb->eRuntimeError_class, "invalid group name reference format"); + mrb_raise(mrb, E_RUNTIME_ERROR, "invalid group name reference format"); } } @@ -2318,7 +2310,7 @@ mrb_backref_set(mrb_state *mrb, mrb_value val) { vm_svar_set(mrb, 1, val); } -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP #ifdef INCLUDE_ENCODING static inline long @@ -2421,7 +2413,7 @@ mrb_memsearch(mrb_state *mrb, const void *x0, int m, const void *y0, int n, mrb_ } #endif //INCLUDE_ENCODING -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP mrb_value mrb_reg_init_str(mrb_state *mrb, mrb_value re, mrb_value s, int options) { @@ -2469,7 +2461,7 @@ re_adjust_startpos(struct re_pattern_buffer *bufp, const char *string, int size, }*/ return startpos; } -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP #ifdef INCLUDE_ENCODING static const unsigned char mbctab_ascii[] = { @@ -13,6 +13,7 @@ #include "node.h" #include "regex.h" #include "encoding.h" +#include "st.h" #define BEG(no) regs->beg[no] #define END(no) regs->end[no] diff --git a/src/regcomp.c b/src/regcomp.c index 523124b26..b8c652999 100644 --- a/src/regcomp.c +++ b/src/regcomp.c @@ -30,7 +30,7 @@ #include "mruby.h" #include <string.h> #include "regparse.h" -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP OnigCaseFoldType OnigDefaultCaseFoldFlag = ONIGENC_CASE_FOLD_MIN; @@ -5628,7 +5628,7 @@ onig_end(void) THREAD_SYSTEM_END; return 0; } -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP #ifdef INCLUDE_ENCODING extern int @@ -5653,7 +5653,7 @@ onig_is_in_code_range(const UChar* p, OnigCodePoint code) } #endif //INCLUDE_ENCODING -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP extern int onig_is_code_in_cc_len(int elen, OnigCodePoint code, CClassNode* cc) { @@ -6285,4 +6285,4 @@ print_tree(FILE* f, Node* node) print_indent_tree(f, node, 0); } #endif -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP diff --git a/src/regenc.c b/src/regenc.c index 3764a694f..4cc496782 100644 --- a/src/regenc.c +++ b/src/regenc.c @@ -32,14 +32,6 @@ #include <string.h> #include "regint.h" -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - OnigEncoding OnigEncDefaultCharEncoding = ONIG_ENCODING_INIT_DEFAULT; extern int diff --git a/src/regerror.c b/src/regerror.c index 2ba879f78..df60b49cc 100644 --- a/src/regerror.c +++ b/src/regerror.c @@ -28,7 +28,7 @@ */ #include "mruby.h" -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP #include <string.h> #include "regint.h" #include <stdio.h> /* for vsnprintf() */ @@ -372,4 +372,4 @@ onig_snprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc, pat, pat_end, fmt, args); va_end(args); } -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP diff --git a/src/regexec.c b/src/regexec.c index 4d8950b73..d265cc803 100644 --- a/src/regexec.c +++ b/src/regexec.c @@ -28,7 +28,7 @@ */ #include "mruby.h" -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP #include <string.h> #include "regint.h" @@ -3754,4 +3754,4 @@ onig_copy_encoding(OnigEncoding to, OnigEncoding from) { *to = *from; } -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP diff --git a/src/regparse.c b/src/regparse.c index 509740ac3..f7bb23306 100644 --- a/src/regparse.c +++ b/src/regparse.c @@ -32,7 +32,7 @@ #include <string.h> #include "regparse.h" #include <stdarg.h> -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP #define WARN_BUFSIZE 256 @@ -298,7 +298,7 @@ strcat_capa_from_static(UChar* dest, UChar* dest_end, onig_strcpy(r + (dest_end - dest), src, src_end); return r; } -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP #ifdef INCLUDE_ENCODING #ifdef USE_ST_LIBRARY @@ -393,7 +393,7 @@ onig_st_insert_strend(hash_table_type* table, const UChar* str_key, #endif /* USE_ST_LIBRARY */ #endif //INCLUDE_ENCODING -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP #ifdef USE_NAMED_GROUP #define INIT_NAME_BACKREFS_ALLOC_NUM 8 @@ -5597,4 +5597,4 @@ onig_scan_env_set_error_string(ScanEnv* env, int ecode ARG_UNUSED, env->error = arg; env->error_end = arg_end; } -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP diff --git a/src/sprintf.c b/src/sprintf.c index 79bd101ad..519e40b4b 100644 --- a/src/sprintf.c +++ b/src/sprintf.c @@ -5,6 +5,9 @@ */ #include "mruby.h" + +#ifdef ENABLE_SPRINTF + #include <stdio.h> #include <string.h> #include "encoding.h" @@ -12,7 +15,6 @@ #include "mruby/hash.h" #include "mruby/numeric.h" #include <math.h> -#include <stdarg.h> #include <ctype.h> #ifdef HAVE_IEEEFP_H @@ -86,7 +88,7 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base) val &= 0x3ff; if (val == 0) { - return mrb_str_new2(mrb, "0"); + return mrb_str_new(mrb, "0", 1); } *--b = '\0'; do { @@ -142,7 +144,7 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base) blen += (l);\ } while (0) -#define GETARG() (!UNDEF_P(nextvalue) ? nextvalue : \ +#define GETARG() (!mrb_undef_p(nextvalue) ? nextvalue : \ posarg == -1 ? \ (mrb_raise(mrb, E_ARGUMENT_ERROR, "unnumbered(%d) mixed with numbered", nextarg), mrb_undef_value()) : \ posarg == -2 ? \ @@ -165,7 +167,7 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base) (mrb_raise(mrb, E_ARGUMENT_ERROR, "named%.*s after unnumbered(%d)", (len), (name), posarg), mrb_undef_value()) : \ posarg == -1 ? \ (mrb_raise(mrb, E_ARGUMENT_ERROR, "named%.*s after numbered", (len), (name)), mrb_undef_value()) : \ - (posarg = -2, mrb_hash_getWithDef(mrb, get_hash(mrb, &hash, argc, argv), id, mrb_undef_value()))) + (posarg = -2, mrb_hash_fetch(mrb, get_hash(mrb, &hash, argc, argv), id, mrb_undef_value()))) #define GETNUM(n, val) \ for (; p < end && ISDIGIT(*p); p++) {\ @@ -198,7 +200,7 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv) { mrb_value tmp; - if (!UNDEF_P(*hash)) return *hash; + if (!mrb_undef_p(*hash)) return *hash; if (argc != 2) { mrb_raise(mrb, E_ARGUMENT_ERROR, "one hash required"); } @@ -493,7 +495,7 @@ mrb_str_format(mrb_state *mrb, int argc, const mrb_value *argv, mrb_value fmt) char *buf; long blen, bsiz; mrb_value result; - + int n; int width, prec, flags = FNONE; int nextarg = 1; int posarg = 0; @@ -530,7 +532,6 @@ mrb_str_format(mrb_state *mrb, int argc, const mrb_value *argv, mrb_value fmt) for (; p < end; p++) { const char *t; - int n; mrb_sym id = 0; for (t = p; t < end && *t != '%'; t++) ; @@ -584,7 +585,7 @@ retry: n = 0; GETNUM(n, width); if (*p == '$') { - if (!UNDEF_P(nextvalue)) { + if (!mrb_undef_p(nextvalue)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "value given twice - %d$", n); } nextvalue = GETPOSARG(n); @@ -610,9 +611,9 @@ retry: (int)(p - start + 1), start, mrb_sym2name(mrb, id)); } symname = mrb_str_new(mrb, start + 1, p - start - 1); - id = mrb_intern(mrb, RSTRING_PTR(symname)); + id = mrb_intern_str(mrb, symname); nextvalue = GETNAMEARG(mrb_symbol_value(id), start, (int)(p - start + 1)); - if (UNDEF_P(nextvalue)) { + if (mrb_undef_p(nextvalue)) { mrb_raise(mrb, E_KEY_ERROR, "key%.*s not found", (int)(p - start + 1), start); } if (term == '}') goto format_s; @@ -666,7 +667,6 @@ retry: mrb_value val = GETARG(); mrb_value tmp; unsigned int c; - int n; tmp = mrb_check_string_type(mrb, val); if (!mrb_nil_p(tmp)) { @@ -981,6 +981,7 @@ bin_retry: fval = mrb_float(mrb_Float(mrb, val)); if (isnan(fval) || isinf(fval)) { const char *expr; + const int elen = 3; if (isnan(fval)) { expr = "NaN"; @@ -988,14 +989,14 @@ bin_retry: else { expr = "Inf"; } - need = (int)strlen(expr); + need = elen; if ((!isnan(fval) && fval < 0.0) || (flags & FPLUS)) need++; if ((flags & FWIDTH) && need < width) need = width; CHECK(need + 1); - snprintf(&buf[blen], need + 1, "%*s", need, ""); + n = snprintf(&buf[blen], need + 1, "%*s", need, ""); if (flags & FMINUS) { if (!isnan(fval) && fval < 0.0) buf[blen++] = '-'; @@ -1003,17 +1004,16 @@ bin_retry: buf[blen++] = '+'; else if (flags & FSPACE) blen++; - memcpy(&buf[blen], expr, strlen(expr)); + memcpy(&buf[blen], expr, elen); } else { if (!isnan(fval) && fval < 0.0) - buf[blen + need - strlen(expr) - 1] = '-'; + buf[blen + need - elen - 1] = '-'; else if (flags & FPLUS) - buf[blen + need - strlen(expr) - 1] = '+'; + buf[blen + need - elen - 1] = '+'; else if ((flags & FSPACE) && need > width) blen++; - memcpy(&buf[blen + need - strlen(expr)], expr, - strlen(expr)); + memcpy(&buf[blen + need - elen], expr, elen); } blen += strlen(&buf[blen]); break; @@ -1033,8 +1033,8 @@ bin_retry: need += 20; CHECK(need); - snprintf(&buf[blen], need, fbuf, fval); - blen += strlen(&buf[blen]); + n = snprintf(&buf[blen], need, fbuf, fval); + blen += n; } break; } @@ -1058,6 +1058,8 @@ static void fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec) { char *end = buf + size; + int n; + *buf++ = '%'; if (flags & FSHARP) *buf++ = '#'; if (flags & FPLUS) *buf++ = '+'; @@ -1066,15 +1068,17 @@ fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec) if (flags & FSPACE) *buf++ = ' '; if (flags & FWIDTH) { - snprintf(buf, end - buf, "%d", width); - buf += strlen(buf); + n = snprintf(buf, end - buf, "%d", width); + buf += n; } if (flags & FPREC) { - snprintf(buf, end - buf, ".%d", prec); - buf += strlen(buf); + n = snprintf(buf, end - buf, ".%d", prec); + buf += n; } *buf++ = c; *buf = '\0'; } + +#endif /* ENABLE_SPRINTF */ @@ -24,21 +24,21 @@ static int numcmp(long, long); static st_index_t numhash(long); static struct st_hash_type type_numhash = { - numcmp, - numhash, + (int (*)(ANYARGS))numcmp, + (st_index_t (*)(ANYARGS))numhash, }; /* extern int strcmp(const char *, const char *); */ static st_index_t strhash(const char*); static struct st_hash_type type_strhash = { - strcmp, - strhash, + (int (*)(ANYARGS))strcmp, + (st_index_t (*)(ANYARGS))strhash, }; static st_index_t strcasehash(st_data_t); static const struct st_hash_type type_strcasehash = { - st_strcasecmp, - strcasehash, + (int (*)(ANYARGS))st_strcasecmp, + (st_index_t (*)(ANYARGS))strcasehash, }; static void rehash(st_table*); diff --git a/src/state.c b/src/state.c index b3946bad9..26e7dff4a 100644 --- a/src/state.c +++ b/src/state.c @@ -15,7 +15,8 @@ void mrb_init_ext(mrb_state*); mrb_state* mrb_open_allocf(mrb_allocf f) { - mrb_state *mrb = (f)(NULL, NULL, sizeof(mrb_state)); + mrb_state *mrb = (mrb_state *)(f)(NULL, NULL, sizeof(mrb_state)); + if (mrb == NULL) return NULL; memset(mrb, 0, sizeof(mrb_state)); mrb->allocf = f; @@ -75,14 +76,14 @@ mrb_add_irep(mrb_state *mrb, int idx) int max = 256; if (idx > max) max = idx+1; - mrb->irep = mrb_malloc(mrb, sizeof(mrb_irep*)*max); + mrb->irep = (mrb_irep **)mrb_calloc(mrb, max, sizeof(mrb_irep*)); mrb->irep_capa = max; } else if (mrb->irep_capa <= idx) { while (mrb->irep_capa <= idx) { mrb->irep_capa *= 2; } - mrb->irep = mrb_realloc(mrb, mrb->irep, sizeof(mrb_irep)*mrb->irep_capa); + mrb->irep = (mrb_irep **)mrb_realloc(mrb, mrb->irep, sizeof(mrb_irep*)*mrb->irep_capa); } } diff --git a/src/string.c b/src/string.c index 26ed7b052..aef0ac88f 100644 --- a/src/string.c +++ b/src/string.c @@ -10,56 +10,65 @@ #include <string.h> #include "mruby/string.h" #include <ctype.h> -#include "mruby/numeric.h" +#include <limits.h> #include "mruby/range.h" #include "mruby/array.h" #include "mruby/class.h" -#include "mruby/variable.h" #include <stdio.h> +#ifdef ENABLE_REGEXP #include "re.h" -#ifdef INCLUDE_REGEXP #include "regex.h" -#include "st.h" -#endif //INCLUDE_REGEXP - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif +#endif //ENABLE_REGEXP const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz"; -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP static mrb_value get_pat(mrb_state *mrb, mrb_value pat, mrb_int quote); -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP static mrb_value str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2); -static mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, long beg, long len); +static mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, int beg, int len); #define RESIZE_CAPA(s,capacity) do {\ - s->buf = mrb_realloc(mrb, s->buf, (capacity)+1);\ + s->ptr = (char *)mrb_realloc(mrb, s->ptr, (capacity)+1);\ s->aux.capa = capacity;\ } while (0) +void +mrb_str_decref(mrb_state *mrb, struct mrb_shared_string *shared) +{ + shared->refcnt--; + if (shared->refcnt == 0) { + mrb_free(mrb, shared->ptr); + mrb_free(mrb, shared); + } +} + static void str_modify(mrb_state *mrb, struct RString *s) { if (s->flags & MRB_STR_SHARED) { - char *ptr, *p; - long len; + struct mrb_shared_string *shared = s->aux.shared; - p = s->buf; - len = s->len; - ptr = mrb_malloc(mrb, sizeof(char)*(len+1)); - if (p) { - memcpy(ptr, p, len); + if (shared->refcnt == 1 && s->ptr == shared->ptr) { + s->ptr = shared->ptr; + s->aux.capa = shared->len; + mrb_free(mrb, shared); + } + else { + char *ptr, *p; + long len; + + p = s->ptr; + len = s->len; + ptr = (char *)mrb_malloc(mrb, len+1); + if (p) { + memcpy(ptr, p, len); + } + ptr[len] = 0; + s->ptr = ptr; + s->aux.capa = len; + mrb_str_decref(mrb, shared); } - ptr[len] = 0; - s->buf = ptr; - s->len = len; - s->aux.capa = len; s->flags &= ~MRB_STR_SHARED; } } @@ -74,13 +83,11 @@ mrb_str_resize(mrb_state *mrb, mrb_value str, int len) slen = s->len; if (len != slen) { if (slen < len || slen -len > 1024) { - s->buf = mrb_realloc(mrb, s->buf, len+1); - } - if (!(s->flags & MRB_STR_SHARED)) { - s->aux.capa = len; + s->ptr = (char *)mrb_realloc(mrb, s->ptr, len+1); } + s->aux.capa = len; s->len = len; - s->buf[len] = '\0'; /* sentinel */ + s->ptr[len] = '\0'; /* sentinel */ } return str; } @@ -90,8 +97,8 @@ str_mod_check(mrb_state *mrb, mrb_value str, char *p, mrb_int len) { struct RString *s = mrb_str_ptr(str); - if (s->buf != p || s->len != len) { - mrb_raise(mrb, mrb->eRuntimeError_class, "string modified"); + if (s->ptr != p || s->len != len) { + mrb_raise(mrb, E_RUNTIME_ERROR, "string modified"); } } @@ -105,7 +112,7 @@ str_alloc(mrb_state *mrb, struct RClass *c) s = mrb_obj_alloc_string(mrb); s->c = c; - s->buf = 0; + s->ptr = 0; s->len = 0; s->aux.capa = 0; @@ -126,11 +133,11 @@ str_new(mrb_state *mrb, const char *p, int len) s->len = len; s->aux.capa = len; - s->buf = mrb_malloc(mrb, len+1); + s->ptr = (char *)mrb_malloc(mrb, len+1); if (p) { - memcpy(s->buf, p, len); + memcpy(s->ptr, p, len); } - s->buf[len] = '\0'; + s->ptr[len] = '\0'; return s; } @@ -161,8 +168,8 @@ mrb_str_buf_new(mrb_state *mrb, int capa) } s->len = 0; s->aux.capa = capa; - s->buf = mrb_malloc(mrb, capa+1); - s->buf[0] = '\0'; + s->ptr = (char *)mrb_malloc(mrb, capa+1); + s->ptr[0] = '\0'; return mrb_obj_value(s); } @@ -173,18 +180,18 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, int len) long capa, total, off = -1; str_modify(mrb, s); - if (ptr >= s->buf && ptr <= s->buf + s->len) { - off = ptr - s->buf; + if (ptr >= s->ptr && ptr <= s->ptr + s->len) { + off = ptr - s->ptr; } if (len == 0) return; capa = s->aux.capa; - if (s->len >= LONG_MAX - len) { + if (s->len >= INT_MAX - len) { mrb_raise(mrb, E_ARGUMENT_ERROR, "string sizes too big"); } total = s->len+len; if (capa <= total) { while (total > capa) { - if (capa + 1 >= LONG_MAX / 2) { + if (capa + 1 >= INT_MAX / 2) { capa = (total + 4095) / 4096; break; } @@ -193,11 +200,11 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, int len) RESIZE_CAPA(s, capa); } if (off != -1) { - ptr = s->buf + off; + ptr = s->ptr + off; } - memcpy(s->buf + s->len, ptr, len); + memcpy(s->ptr + s->len, ptr, len); s->len = total; - s->buf[total] = '\0'; /* sentinel */ + s->ptr[total] = '\0'; /* sentinel */ } mrb_value @@ -211,7 +218,9 @@ mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, int len) mrb_value mrb_str_new(mrb_state *mrb, const char *p, int len) { - struct RString *s = str_new(mrb, p, len); + struct RString *s; + + s = str_new(mrb, p, len); return mrb_obj_value(s); } @@ -240,39 +249,32 @@ mrb_str_new_cstr(mrb_state *mrb, const char *p) int len = strlen(p); s = mrb_obj_alloc_string(mrb); - s->buf = mrb_malloc(mrb, len+1); - memcpy(s->buf, p, len); - s->buf[len] = 0; + s->ptr = (char *)mrb_malloc(mrb, len+1); + memcpy(s->ptr, p, len); + s->ptr[len] = 0; s->len = len; s->aux.capa = len; return mrb_obj_value(s); } -static struct RString* -str_make_shared(mrb_state *mrb, mrb_value str) +static void +str_make_shared(mrb_state *mrb, struct RString *s) { - struct RString *orig, *s; + if (!(s->flags & MRB_STR_SHARED)) { + struct mrb_shared_string *shared = (struct mrb_shared_string *)mrb_malloc(mrb, sizeof(struct mrb_shared_string)); - s = str_new(mrb, 0, 0); - str_with_class(mrb, s, str); - orig = mrb_str_ptr(str); - if (!(orig->flags & MRB_STR_SHARED)) { - struct RString *shared = mrb_obj_alloc_string(mrb); - - shared->buf = orig->buf; - shared->len = orig->len; - shared->aux.capa = orig->aux.capa; - - orig->aux.shared = shared; - orig->flags |= MRB_STR_SHARED; + shared->refcnt = 1; + if (s->aux.capa > s->len) { + s->ptr = shared->ptr = (char *)mrb_realloc(mrb, s->ptr, s->len+1); + } + else { + shared->ptr = s->ptr; + } + shared->len = s->len; + s->aux.shared = shared; + s->flags |= MRB_STR_SHARED; } - s->buf = orig->buf; - s->len = orig->len; - s->aux.shared = orig->aux.shared; - s->flags |= MRB_STR_SHARED; - - return s; } /* @@ -285,16 +287,19 @@ str_make_shared(mrb_state *mrb, mrb_value str) mrb_value mrb_str_literal(mrb_state *mrb, mrb_value str) { - struct RString *orig, *s; + struct RString *s, *orig; + struct mrb_shared_string *shared; - s = str_new(mrb, 0, 0); + s = str_alloc(mrb, mrb->string_class); orig = mrb_str_ptr(str); - while (orig->flags & MRB_STR_SHARED) { - orig = orig->aux.shared; + if (!(orig->flags & MRB_STR_SHARED)) { + str_make_shared(mrb, mrb_str_ptr(str)); } - s->buf = orig->buf; - s->len = orig->len; - s->aux.shared = orig; + shared = orig->aux.shared; + shared->refcnt++; + s->ptr = shared->ptr; + s->len = shared->len; + s->aux.shared = shared; s->flags |= MRB_STR_SHARED; return mrb_obj_value(s); @@ -312,7 +317,7 @@ mrb_str_body(mrb_value str, int *len_p) struct RString *s = mrb_str_ptr(str); *len_p = s->len; - return s->buf; + return s->ptr; } /* @@ -336,11 +341,11 @@ mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other) if (s1->aux.capa < len) { s1->aux.capa = len; - s1->buf = mrb_realloc(mrb, s1->buf, len+1); + s1->ptr = (char *)mrb_realloc(mrb, s1->ptr, len+1); } - memcpy(s1->buf+s1->len, s2->buf, s2->len); + memcpy(s1->ptr+s1->len, s2->ptr, s2->len); s1->len = len; - s1->buf[len] = 0; + s1->ptr[len] = 0; } /* @@ -357,8 +362,8 @@ mrb_str_plus(mrb_state *mrb, mrb_value a, mrb_value b) struct RString *t; t = str_new(mrb, 0, s->len + s2->len); - memcpy(t->buf, s->buf, s->len); - memcpy(t->buf + s->len, s2->buf, s2->len); + memcpy(t->ptr, s->ptr, s->len); + memcpy(t->ptr + s->len, s2->ptr, s2->len); return mrb_obj_value(t); } @@ -426,14 +431,14 @@ mrb_str_times(mrb_state *mrb, mrb_value self) if (times < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argument"); } - if (times && INT32_MAX/times < RSTRING_LEN(self)) { + if (times && INT_MAX/times < RSTRING_LEN(self)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "argument too big"); } len = RSTRING_LEN(self)*times; str2 = str_new(mrb, 0, len); str_with_class(mrb, str2, self); - p = str2->buf; + p = str2->ptr; if (len > 0) { n = RSTRING_LEN(self); memcpy(p, RSTRING_PTR(self), n); @@ -468,7 +473,7 @@ mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2) struct RString *s2 = mrb_str_ptr(str2); len = lesser(s1->len, s2->len); - retval = memcmp(s1->buf, s2->buf, len); + retval = memcmp(s1->ptr, s2->ptr, len); if (retval == 0) { if (s1->len == s2->len) return 0; if (s1->len > s2->len) return 1; @@ -659,7 +664,7 @@ mrb_memsearch_qs(const unsigned char *xs, long m, const unsigned char *ys, long static int mrb_memsearch(const void *x0, int m, const void *y0, int n) { - const unsigned char *x = x0, *y = y0; + const unsigned char *x = (const unsigned char *)x0, *y = (const unsigned char *)y0; if (m > n) return -1; else if (m == n) { @@ -676,7 +681,7 @@ mrb_memsearch(const void *x0, int m, const void *y0, int n) } return -1; } - return mrb_memsearch_qs(x0, m, y0, n); + return mrb_memsearch_qs((const unsigned char *)x0, m, (const unsigned char *)y0, n); } static mrb_int @@ -712,7 +717,7 @@ mrb_str_dup(mrb_state *mrb, mrb_value str) /* should return shared string */ struct RString *s = mrb_str_ptr(str); - return mrb_str_new(mrb, s->buf, s->len); + return mrb_str_new(mrb, s->ptr, s->len); } static mrb_value @@ -730,12 +735,12 @@ num_index: return str; case MRB_TT_REGEX: -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP return mrb_str_subpat(mrb, str, indx, 0); //mrb_str_subpat(str, indx, INT2FIX(0)); #else mrb_raise(mrb, E_TYPE_ERROR, "Regexp Class not supported"); return mrb_nil_value(); -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP case MRB_TT_STRING: if (mrb_str_index(mrb, str, indx, 0) != -1) @@ -750,7 +755,7 @@ num_index: len = RSTRING_LEN(str); switch (mrb_range_beg_len(mrb, indx, &beg, &len, len, 0)) { - case 0/*FLASE*/: + case FALSE: break; case 2/*OTHER*/: return mrb_nil_value(); @@ -822,12 +827,12 @@ mrb_str_aref_m(mrb_state *mrb, mrb_value str) argc = mrb_get_args(mrb, "o|o", &a1, &a2); if (argc == 2) { if (mrb_type(a1) == MRB_TT_REGEX) { -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP return mrb_str_subpat(mrb, str, argv[0], mrb_fixnum(argv[1])); #else mrb_raise(mrb, E_TYPE_ERROR, "Regexp Class not supported"); return mrb_nil_value(); -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP } return mrb_str_substr(mrb, str, mrb_fixnum(a1), mrb_fixnum(a2)); } @@ -858,8 +863,8 @@ mrb_str_capitalize_bang(mrb_state *mrb, mrb_value str) struct RString *s = mrb_str_ptr(str); str_modify(mrb, s); - if (s->len == 0 || !s->buf) return mrb_nil_value(); - p = s->buf; pend = s->buf + s->len; + if (s->len == 0 || !s->ptr) return mrb_nil_value(); + p = s->ptr; pend = s->ptr + s->len; if (ISLOWER(*p)) { *p = toupper(*p); modify = 1; @@ -918,14 +923,14 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str) if (mrb_get_args(mrb, "|S", &rs) == 0) { if (len == 0) return mrb_nil_value(); smart_chomp: - if (s->buf[len-1] == '\n') { + if (s->ptr[len-1] == '\n') { s->len--; if (s->len > 0 && - s->buf[s->len-1] == '\r') { + s->ptr[s->len-1] == '\r') { s->len--; } } - else if (s->buf[len-1] == '\r') { + else if (s->ptr[len-1] == '\r') { s->len--; } else { @@ -935,7 +940,7 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str) } if (len == 0 || mrb_nil_p(rs)) return mrb_nil_value(); - p = s->buf; + p = s->ptr; rslen = RSTRING_LEN(rs); if (rslen == 0) { while (len>0 && p[len-1] == '\n') { @@ -1015,14 +1020,14 @@ mrb_str_chop_bang(mrb_state *mrb, mrb_value str) if (s->len > 0) { int len; len = s->len - 1; - if (s->buf[len] == '\n') { + if (s->ptr[len] == '\n') { if (len > 0 && - s->buf[len-1] == '\r') { + s->ptr[len-1] == '\r') { len--; } } s->len = len; - s->buf[len] = '\0'; + s->ptr[len] = '\0'; return str; } return mrb_nil_value(); @@ -1070,8 +1075,8 @@ mrb_str_downcase_bang(mrb_state *mrb, mrb_value str) struct RString *s = mrb_str_ptr(str); str_modify(mrb, s); - p = s->buf; - pend = s->buf + s->len; + p = s->ptr; + pend = s->ptr + s->len; while (p < pend) { if (ISUPPER(*p)) { *p = tolower(*p); @@ -1184,13 +1189,20 @@ mrb_str_eql(mrb_state *mrb, mrb_value self) } static mrb_value -mrb_str_subseq(mrb_state *mrb, mrb_value str, long beg, long len) +mrb_str_subseq(mrb_state *mrb, mrb_value str, int beg, int len) { - struct RString *s; + struct RString *orig, *s; + struct mrb_shared_string *shared; - s = str_make_shared(mrb, str); - s->buf += beg; + orig = mrb_str_ptr(str); + str_make_shared(mrb, orig); + shared = orig->aux.shared; + s = mrb_obj_alloc_string(mrb); + s->ptr = orig->ptr + beg; s->len = len; + s->aux.shared = shared; + s->flags |= MRB_STR_SHARED; + shared->refcnt++; return mrb_obj_value(s); } @@ -1226,7 +1238,7 @@ mrb_str_buf_append(mrb_state *mrb, mrb_value str, mrb_value str2) return str; } -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP static mrb_value str_gsub(mrb_state *mrb, mrb_value str, mrb_int bang) { @@ -1342,7 +1354,6 @@ str_gsub(mrb_state *mrb, mrb_value str, mrb_int bang) static mrb_value mrb_str_gsub(mrb_state *mrb, mrb_value self) { - //return str_gsub(argc, argv, self, 0); return str_gsub(mrb, self, 0); } @@ -1363,7 +1374,7 @@ mrb_str_gsub_bang(mrb_state *mrb, mrb_value self) str_modify(mrb, s); return str_gsub(mrb, s, 1); } -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP mrb_int mrb_str_hash(mrb_state *mrb, mrb_value str) @@ -1371,7 +1382,7 @@ mrb_str_hash(mrb_state *mrb, mrb_value str) /* 1-8-7 */ struct RString *s = mrb_str_ptr(str); long len = s->len; - char *p = s->buf; + char *p = s->ptr; mrb_int key = 0; while (len--) { @@ -1457,10 +1468,8 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str) int argc; mrb_value sub; - //mrb_value initpos; mrb_int pos; - //if (mrb_scan_args(argc, argv, "11", &sub, &initpos) == 2) { mrb_get_args(mrb, "*", &argv, &argc); if (argc == 2) { pos = mrb_fixnum(argv[1]); @@ -1486,7 +1495,7 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str) switch (mrb_type(sub)) { case MRB_TT_REGEX: -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP if (pos > RSTRING_LEN(str)) return mrb_nil_value(); pos = mrb_str_offset(mrb, str, pos); @@ -1494,7 +1503,7 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str) pos = mrb_str_sublen(mrb, str, pos); #else mrb_raise(mrb, E_TYPE_ERROR, "Regexp Class not supported"); -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP break; case MRB_TT_FIXNUM: { @@ -1528,16 +1537,43 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str) return mrb_fixnum_value(pos); } +#define STR_REPLACE_SHARED_MIN 10 + static mrb_value str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2) { - int len = s2->len; - - str_modify(mrb, s1); - s1->buf = mrb_realloc(mrb, s1->buf, len); - memcpy(s1->buf, s2->buf, len); - s1->len = s2->len; - s2->aux.capa = s2->len; + if (s2->flags & MRB_STR_SHARED) { + L_SHARE: + if (s1->flags & MRB_STR_SHARED){ + mrb_str_decref(mrb, s1->aux.shared); + } + else { + mrb_free(mrb, s1->ptr); + } + s1->ptr = s2->ptr; + s1->len = s2->len; + s1->aux.shared = s2->aux.shared; + s1->flags |= MRB_STR_SHARED; + s1->aux.shared->refcnt++; + } + else if (s2->len > STR_REPLACE_SHARED_MIN) { + str_make_shared(mrb, s2); + goto L_SHARE; + } + else { + if (s1->flags & MRB_STR_SHARED) { + mrb_str_decref(mrb, s1->aux.shared); + s1->flags &= ~MRB_STR_SHARED; + s1->ptr = (char *)mrb_malloc(mrb, s2->len+1); + } + else { + s1->ptr = (char *)mrb_realloc(mrb, s1->ptr, s2->len+1); + } + memcpy(s1->ptr, s2->ptr, s2->len); + s1->ptr[s2->len] = 0; + s1->len = s2->len; + s1->aux.capa = s2->len; + } return mrb_obj_value(s1); } @@ -1577,12 +1613,6 @@ mrb_str_init(mrb_state *mrb, mrb_value self) return self; } -mrb_sym -mrb_intern_str(mrb_state *mrb, mrb_value str) -{ - return mrb_intern(mrb, RSTRING_PTR(str)); -} - /* 15.2.10.5.25 */ /* 15.2.10.5.41 */ /* @@ -1635,7 +1665,7 @@ mrb_check_string_type(mrb_state *mrb, mrb_value str) return mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str"); } -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP static mrb_value get_pat(mrb_state *mrb, mrb_value pat, mrb_int quote) { @@ -1663,7 +1693,7 @@ get_pat(mrb_state *mrb, mrb_value pat, mrb_int quote) return mrb_reg_regcomp(mrb, pat); } -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP /* 15.2.10.5.27 */ /* @@ -1678,7 +1708,7 @@ get_pat(mrb_state *mrb, mrb_value pat, mrb_int quote) * 'hello'.match(/(.)\1/)[0] #=> "ll" * 'hello'.match('xx') #=> nil */ -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP static mrb_value mrb_str_match_m(mrb_state *mrb, mrb_value self) { @@ -1698,7 +1728,7 @@ mrb_str_match_m(mrb_state *mrb, mrb_value self) } return result; } -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP /* ---------------------------------- */ /* 15.2.10.5.29 */ @@ -1721,7 +1751,7 @@ mrb_str_reverse(mrb_state *mrb, mrb_value str) s2 = str_new(mrb, 0, RSTRING(str)->len); str_with_class(mrb, s2, str); s = RSTRING_PTR(str); e = RSTRING_END(str) - 1; - p = s2->buf; + p = s2->ptr; while (e >= s) { *p++ = *e--; @@ -1745,7 +1775,7 @@ mrb_str_reverse_bang(mrb_state *mrb, mrb_value str) str_modify(mrb, s); if (s->len > 1) { - p = s->buf; + p = s->ptr; e = p + s->len - 1; while (p < e) { c = *p; @@ -1787,13 +1817,13 @@ mrb_str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos) if (ps->len - pos < len) { pos = ps->len - len; } - sbeg = ps->buf; - s = ps->buf + pos; - t = psub->buf; + sbeg = ps->ptr; + s = ps->ptr + pos; + t = psub->ptr; if (len) { while (sbeg <= s) { if (memcmp(s, t, len) == 0) { - return s - ps->buf; + return s - ps->ptr; } s--; } @@ -1850,11 +1880,11 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str) pos += len; if (pos < 0) { if (mrb_type(sub) == MRB_TT_REGEX) { -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP mrb_backref_set(mrb, mrb_nil_value()); #else mrb_raise(mrb, E_TYPE_ERROR, "Regexp Class not supported"); -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP } return mrb_nil_value(); } @@ -1871,7 +1901,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str) switch (mrb_type(sub)) { case MRB_TT_REGEX: -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP pos = mrb_str_offset(mrb, str, pos); if (!RREGEXP(sub)->ptr || RREGEXP_SRC_LEN(sub)) { pos = mrb_reg_search(mrb, sub, str, pos, 1); @@ -1880,7 +1910,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str) if (pos >= 0) return mrb_fixnum_value(pos); #else mrb_raise(mrb, E_TYPE_ERROR, "Regexp Class not supported"); -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP break; case MRB_TT_FIXNUM: { @@ -1914,7 +1944,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str) return mrb_nil_value(); } -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP static mrb_value scan_once(mrb_state *mrb, mrb_value str, mrb_value pat, mrb_int *start) { @@ -1926,7 +1956,6 @@ scan_once(mrb_state *mrb, mrb_value str, mrb_value pat, mrb_int *start) if (mrb_reg_search(mrb, pat, str, *start, 0) >= 0) { match = mrb_backref_get(mrb); - //regs = RMATCH(match)->regs; pmatch = mrb_match_ptr(match); regs = &pmatch->rmatch->regs; if (regs->beg[0] == regs->end[0]) { @@ -1944,7 +1973,7 @@ scan_once(mrb_state *mrb, mrb_value str, mrb_value pat, mrb_int *start) if (regs->num_regs == 1) { return mrb_reg_nth_match(mrb, 0, match); } - result = mrb_ary_new_capa(mrb, regs->num_regs);//mrb_ary_new2(regs->num_regs); + result = mrb_ary_new_capa(mrb, regs->num_regs); for (i=1; i < regs->num_regs; i++) { mrb_ary_push(mrb, result, mrb_reg_nth_match(mrb, i, match)); } @@ -1953,7 +1982,7 @@ scan_once(mrb_state *mrb, mrb_value str, mrb_value pat, mrb_int *start) } return mrb_nil_value(); } -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP /* 15.2.10.5.32 */ /* @@ -1986,7 +2015,7 @@ scan_once(mrb_state *mrb, mrb_value str, mrb_value pat, mrb_int *start) * <<cruel>> <<world>> * rceu lowlr */ -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP static mrb_value mrb_str_scan(mrb_state *mrb, mrb_value str) { @@ -1995,7 +2024,7 @@ mrb_str_scan(mrb_state *mrb, mrb_value str) mrb_int start = 0; mrb_value match = mrb_nil_value(); struct RString *ps = mrb_str_ptr(str); - char *p = ps->buf; + char *p = ps->ptr; long len = ps->len; mrb_get_args(mrb, "o&", &pat, &b); @@ -2020,7 +2049,7 @@ mrb_str_scan(mrb_state *mrb, mrb_value str) mrb_backref_set(mrb, match); return str; } -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP static const char isspacetable[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, @@ -2089,27 +2118,16 @@ static const char isspacetable[256] = { static mrb_value mrb_str_split_m(mrb_state *mrb, mrb_value str) { - mrb_value *argv; int argc; mrb_value spat = mrb_nil_value(); - mrb_value limit; enum {awk, string, regexp} split_type = string; long beg, end, i = 0; - int lim = 0; + int lim = -1; mrb_value result, tmp; - mrb_get_args(mrb, "*", &argv, &argc); - if (argc > 0) - spat = argv[0]; - if (argc > 1) - limit = argv[1]; - else - limit = mrb_nil_value(); - + argc = mrb_get_args(mrb, "|oi", &spat, &lim); if (argc == 2) { - lim = mrb_fixnum(limit); - if (lim <= 0) limit = mrb_nil_value(); - else if (lim == 1) { + if (lim == 1) { if (RSTRING_LEN(str) == 0) return mrb_ary_new_capa(mrb, 0); return mrb_ary_new_from_values(mrb, 1, &str); @@ -2117,35 +2135,34 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) i = 1; } - if (argc == 0) { + if (argc == 0 || mrb_nil_p(spat)) { split_type = awk; } else { -//fs_set: if (mrb_type(spat) == MRB_TT_STRING) { split_type = string; -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP if (RSTRING_LEN(spat) == 0) { /* Special case - split into chars */ spat = mrb_reg_regcomp(mrb, spat); split_type = regexp; } else { -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' '){ split_type = awk; } -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP } -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP } else { -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP spat = get_pat(mrb, spat, 1); split_type = regexp; #else mrb_raise(mrb, E_TYPE_ERROR, "Regexp Class not supported"); -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP } } @@ -2168,22 +2185,47 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) else { end = ptr - bptr; skip = 0; - if (!mrb_nil_p(limit) && lim <= i) break; + if (lim >= 0 && lim <= i) break; } } else if (ascii_isspace(c)) { mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, beg, end-beg)); skip = 1; beg = ptr - bptr; - if (!mrb_nil_p(limit)) ++i; + if (lim >= 0) ++i; } else { end = ptr - bptr; } } } + else if (split_type == string) { + char *ptr = RSTRING_PTR(str); + char *temp = ptr; + char *eptr = RSTRING_END(str); + long slen = RSTRING_LEN(spat); + + if (slen == 0) { + while (ptr < eptr) { + mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, ptr-temp, 1)); + ptr++; + if (lim >= 0 && lim <= ++i) break; + } + } + else { + char *sptr = RSTRING_PTR(spat); + + while (ptr < eptr && + (end = mrb_memsearch(sptr, slen, ptr, eptr - ptr)) >= 0) { + mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, ptr - temp, end)); + ptr += end + slen; + if (lim >= 0 && lim <= ++i) break; + } + } + beg = ptr - temp; + } else { -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP char *ptr = RSTRING_PTR(str); long len = RSTRING_LEN(str); long start = beg; @@ -2225,20 +2267,20 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) tmp = mrb_str_subseq(mrb, str, BEG(idx), END(idx)-BEG(idx)); mrb_ary_push(mrb, result, tmp); } - if (!mrb_nil_p(limit) && lim <= ++i) break; + if (lim >= 0 && lim <= ++i) break; } #else mrb_raise(mrb, E_TYPE_ERROR, "Regexp Class not supported"); -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP } - if (RSTRING_LEN(str) > 0 && (!mrb_nil_p(limit) || RSTRING_LEN(str) > beg || lim < 0)) { + if (RSTRING_LEN(str) > 0 && (lim >= 0 || RSTRING_LEN(str) > beg || lim < 0)) { if (RSTRING_LEN(str) == beg) tmp = mrb_str_new_empty(mrb, str); else tmp = mrb_str_subseq(mrb, str, beg, RSTRING_LEN(str)-beg); mrb_ary_push(mrb, result, tmp); } - if (mrb_nil_p(limit) && lim == 0) { + if (lim < 0) { long len; while ((len = RARRAY_LEN(result)) > 0 && (tmp = RARRAY_PTR(result)[len-1], RSTRING_LEN(tmp) == 0)) @@ -2267,14 +2309,14 @@ mrb_block_given_p() * returning <i>str</i>, or <code>nil</code> if no substitutions were * performed. */ -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP static mrb_value mrb_str_sub_bang(mrb_state *mrb, mrb_value str) { str_modify(mrb, str); return mrb_nil_value(); } -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP /* 15.2.10.5.36 */ @@ -2315,7 +2357,7 @@ mrb_str_sub_bang(mrb_state *mrb, mrb_value str) * #=> "Is /bin/bash your preferred shell?" */ -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP static mrb_value mrb_str_sub(mrb_state *mrb, mrb_value self) { @@ -2324,7 +2366,7 @@ mrb_str_sub(mrb_state *mrb, mrb_value self) mrb_str_sub_bang(mrb, str); return str; } -#endif //INCLUDE_REGEXP +#endif //ENABLE_REGEXP mrb_value mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck) @@ -2332,17 +2374,10 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck) #define BDIGIT unsigned int #define BDIGIT_DBL unsigned long -// const char *s = str; char *end; char sign = 1; -// char nondigit = 0; int c; -// BDIGIT_DBL num; long len; -// long blen = 1; -// long i; -// mrb_value z; -// BDIGIT *zds; unsigned long val; #undef ISDIGIT @@ -2459,28 +2494,30 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck) } len *= strlen(str)*sizeof(char); - val = strtoul((char*)str, &end, base); + val = strtoul((char*)str, &end, base); - if (badcheck) { - if (end == str) goto bad; /* no number */ - while (*end && ISSPACE(*end)) end++; - if (*end) goto bad; /* trailing garbage */ - } + if (badcheck) { + if (end == str) goto bad; /* no number */ + while (*end && ISSPACE(*end)) end++; + if (*end) goto bad; /* trailing garbage */ + } - if (sign) return mrb_fixnum_value(val); - else { - long result = -(long)val; - return mrb_fixnum_value(result); - } + if (sign) return mrb_fixnum_value(val); + else { + long result = -(long)val; + return mrb_fixnum_value(result); + } bad: - printf("Integer"); + mrb_raise(mrb, E_ARGUMENT_ERROR, "invalide string for number(%s)", str); + /* not reached */ return mrb_fixnum_value(0); } + char * mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr) { struct RString *ps = mrb_str_ptr(*ptr); - char *s = ps->buf; + char *s = ps->ptr; if (!s || ps->len != strlen(s)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte"); @@ -2494,10 +2531,8 @@ mrb_str_to_inum(mrb_state *mrb, mrb_value str, int base, int badcheck) char *s; int len; - //StringValue(str); mrb_string_value(mrb, &str); if (badcheck) { - //s = StringValueCStr(str); s = mrb_string_value_cstr(mrb, &str); } else { @@ -2506,8 +2541,7 @@ mrb_str_to_inum(mrb_state *mrb, mrb_value str, int base, int badcheck) if (s) { len = RSTRING_LEN(str); if (s[len]) { /* no sentinel somehow */ - //char *p = ALLOCA_N(char, len+1); - char *p = mrb_malloc(mrb, len+1); + char *p = (char *)mrb_malloc(mrb, len+1); //MEMCPY(p, s, char, len); memcpy(p, s, sizeof(char)*len); @@ -2544,10 +2578,8 @@ mrb_str_to_i(mrb_state *mrb, mrb_value self) { mrb_value *argv; int argc; - //mrb_value b; int base; - //mrb_scan_args(argc, *argv, "01", &b); mrb_get_args(mrb, "*", &argv, &argc); if (argc == 0) base = 10; @@ -2583,8 +2615,8 @@ mrb_cstr_to_dbl(mrb_state *mrb, const char * p, int badcheck) if (p == end) { if (badcheck) { bad: - //mrb_invalid_str(q, "Float()"); - printf("Float()\n"); + mrb_raise(mrb, E_ARGUMENT_ERROR, "invalide string for float(%s)", p); + /* not reached */ } return d; } @@ -2643,7 +2675,7 @@ mrb_str_to_dbl(mrb_state *mrb, mrb_value str, int badcheck) mrb_raise(mrb, E_ARGUMENT_ERROR, "string for Float contains null byte"); } if (s[len]) { /* no sentinel somehow */ - char *p = mrb_malloc(mrb, len+1); + char *p = (char *)mrb_malloc(mrb, len+1); memcpy(p, s, sizeof(char)*len); p[len] = '\0'; @@ -2670,7 +2702,6 @@ mrb_str_to_dbl(mrb_state *mrb, mrb_value str, int badcheck) static mrb_value mrb_str_to_f(mrb_state *mrb, mrb_value self) { - //return mrb_float_new(mrb_str_to_dbl(self, 0/*Qfalse*/)); return mrb_float_value(mrb_str_to_dbl(mrb, self, 0/*Qfalse*/)); } @@ -2778,7 +2809,7 @@ mrb_str_dump(mrb_state *mrb, mrb_value str) len++; } else { - len += 4; /* \xNN */ + len += 4; /* \NNN */ } break; } @@ -2787,7 +2818,7 @@ mrb_str_dump(mrb_state *mrb, mrb_value str) result = str_new(mrb, 0, len); str_with_class(mrb, result, str); p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str); - q = result->buf; + q = result->ptr; *q++ = '"'; while (p < pend) { @@ -2849,19 +2880,10 @@ mrb_str_dump(mrb_state *mrb, mrb_value str) mrb_value mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, long len) { - struct RString *s = mrb_str_ptr(str); - if (len < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "negative string size (or size too big)"); } - if (0/*STR_ASSOC_P(str)*/) { - mrb_realloc(mrb, s->buf, s->len+len+1); - memcpy(s->buf + s->len, ptr, len); - s->len += len; - s->buf[s->len] = '\0'; /* sentinel */ - return str; - } - str_buf_cat(mrb, s, ptr, len); + str_buf_cat(mrb, mrb_str_ptr(str), ptr, len); return str; } @@ -2915,18 +2937,15 @@ mrb_str_append(mrb_state *mrb, mrb_value str, mrb_value str2) mrb_value mrb_str_inspect(mrb_state *mrb, mrb_value str) { - const char *p, *pend, *prev; + const char *p, *pend; char buf[CHAR_ESC_LEN + 1]; - mrb_value result = mrb_str_new_cstr(mrb, "\""); + mrb_value result = mrb_str_new(mrb, "\"", 1); p = RSTRING_PTR(str); pend = RSTRING_END(str); - prev = p; - while (p < pend) { + for (;p < pend; p++) { unsigned int c, cc; - int n; - c = *p++; - n = 1; + c = *p; if (c == '"'|| c == '\\' || (c == '#' && IS_EVSTR(p, pend))) { buf[0] = '\\'; buf[1] = c; mrb_str_buf_cat(mrb, result, buf, 2); @@ -2949,25 +2968,18 @@ mrb_str_inspect(mrb_state *mrb, mrb_value str) default: cc = 0; break; } if (cc) { - if (p - n > prev) mrb_str_buf_cat(mrb, result, prev, p - n - prev); buf[0] = '\\'; buf[1] = (char)cc; mrb_str_buf_cat(mrb, result, buf, 2); - prev = p; continue; } else { - if (p - n > prev) mrb_str_buf_cat(mrb, result, prev, p - n - prev); - sprintf(buf, "\\%03o", c & 0377); - mrb_str_buf_cat(mrb, result, buf, strlen(buf)); - prev = p; + int n = sprintf(buf, "\\%03o", c & 0377); + mrb_str_buf_cat(mrb, result, buf, n); continue; } } -#ifdef INCLUDE_ENCODING - if (p > prev) mrb_str_buf_cat(mrb, result, prev, p - prev); -#endif - mrb_str_buf_cat(mrb, result, "\"", strlen("\"")); + mrb_str_buf_cat(mrb, result, "\"", 1); return result; } @@ -3002,7 +3014,7 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "each_line", mrb_str_each_line, ARGS_REQ(1)); /* 15.2.10.5.15 */ mrb_define_method(mrb, s, "empty?", mrb_str_empty_p, ARGS_NONE()); /* 15.2.10.5.16 */ mrb_define_method(mrb, s, "eql?", mrb_str_eql, ARGS_REQ(1)); /* 15.2.10.5.17 */ -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP mrb_define_method(mrb, s, "gsub", mrb_str_gsub, ARGS_REQ(1)); /* 15.2.10.5.18 */ mrb_define_method(mrb, s, "gsub!", mrb_str_gsub_bang, ARGS_REQ(1)); /* 15.2.10.5.19 */ #endif @@ -3012,19 +3024,19 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "initialize", mrb_str_init, ARGS_REQ(1)); /* 15.2.10.5.23 */ mrb_define_method(mrb, s, "initialize_copy", mrb_str_replace, ARGS_REQ(1)); /* 15.2.10.5.24 */ mrb_define_method(mrb, s, "intern", mrb_str_intern, ARGS_NONE()); /* 15.2.10.5.25 */ -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP mrb_define_method(mrb, s, "match", mrb_str_match_m, ARGS_REQ(1)); /* 15.2.10.5.27 */ #endif mrb_define_method(mrb, s, "replace", mrb_str_replace, ARGS_REQ(1)); /* 15.2.10.5.28 */ mrb_define_method(mrb, s, "reverse", mrb_str_reverse, ARGS_NONE()); /* 15.2.10.5.29 */ mrb_define_method(mrb, s, "reverse!", mrb_str_reverse_bang, ARGS_NONE()); /* 15.2.10.5.30 */ mrb_define_method(mrb, s, "rindex", mrb_str_rindex_m, ARGS_ANY()); /* 15.2.10.5.31 */ -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP mrb_define_method(mrb, s, "scan", mrb_str_scan, ARGS_REQ(1)); /* 15.2.10.5.32 */ #endif mrb_define_method(mrb, s, "slice", mrb_str_aref_m, ARGS_ANY()); /* 15.2.10.5.34 */ mrb_define_method(mrb, s, "split", mrb_str_split_m, ARGS_ANY()); /* 15.2.10.5.35 */ -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP mrb_define_method(mrb, s, "sub", mrb_str_sub, ARGS_REQ(1)); /* 15.2.10.5.36 */ mrb_define_method(mrb, s, "sub!", mrb_str_sub_bang, ARGS_REQ(1)); /* 15.2.10.5.37 */ #endif diff --git a/src/struct.c b/src/struct.c index d06124b50..beb7c2f46 100644 --- a/src/struct.c +++ b/src/struct.c @@ -5,6 +5,7 @@ */ #include "mruby.h" +#ifdef ENABLE_STRUCT #include <string.h> #include "error.h" #include "mruby/struct.h" @@ -12,21 +13,13 @@ #include <stdarg.h> //#include "defines.h" -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP #include "encoding.h" #endif -mrb_sym rb_frame_this_func(mrb_state *mrb); -mrb_sym mrb_frame_callee(mrb_state *mrb); -mrb_value mrb_exec_recursive_paired(mrb_state *mrb, mrb_value (*func) (mrb_state *, mrb_value, mrb_value, int), - mrb_value obj, mrb_value paired_obj, void* arg); -#include "mruby/numeric.h" -#include "mruby/hash.h" #include "mruby/string.h" #include "mruby/class.h" #include "mruby/variable.h" -#include "mruby/range.h" -#include "error.h" //#include "defines.h" #define mrb_long2int(n) ((int)(n)) @@ -45,8 +38,6 @@ struct_ivar_get(mrb_state *mrb, mrb_value c, mrb_sym id) mrb_value ans; for (;;) { - //if (mrb_ivar_defined(c, id)) - // return mrb_iv_get(mrb, c, id); ans = mrb_iv_get(mrb, c, id); if (!mrb_nil_p(ans)) return ans; kclass = RCLASS_SUPER(c); @@ -96,7 +87,7 @@ mrb_struct_s_members_m(mrb_state *mrb, mrb_value klass) mrb_value *p, *pend; members = mrb_struct_s_members(mrb, klass); - ary = mrb_ary_new_capa(mrb, RARRAY_LEN(members));//mrb_ary_new2(RARRAY_LEN(members)); + ary = mrb_ary_new_capa(mrb, RARRAY_LEN(members)); p = RARRAY_PTR(members); pend = p + RARRAY_LEN(members); while (p < pend) { mrb_ary_push(mrb, ary, *p); @@ -134,7 +125,7 @@ mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id) ptr = RSTRUCT_PTR(obj); members = mrb_struct_members(mrb, obj); ptr_members = RARRAY_PTR(members); - slot = mrb_str_new_cstr(mrb, mrb_sym2name(mrb, id)); + slot = mrb_symbol_value(id); len = RARRAY_LEN(members); for (i=0; i<len; i++) { if (mrb_obj_equal(mrb, ptr_members[i], slot)) { @@ -148,8 +139,7 @@ mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id) static mrb_value mrb_struct_ref(mrb_state *mrb, mrb_value obj) { - //return mrb_struct_getmember(mrb, obj, rb_frame_this_func(mrb)); - return mrb_nil_value(); + return mrb_struct_getmember(mrb, obj, mrb->ci->mid); } static mrb_value mrb_struct_ref0(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[0];} @@ -186,33 +176,60 @@ mrb_struct_modify(mrb_value s) } mrb_sym -mrb_id_attrset(mrb_sym id) +mrb_id_attrset(mrb_state *mrb, mrb_sym id) { - //id &= ~ID_SCOPE_MASK; - //id |= ID_ATTRSET; - return id; + const char *name; + char *buf; + int len; + mrb_sym mid; + + name = mrb_sym2name_len(mrb, id, &len); + buf = (char *)mrb_malloc(mrb, len+2); + memcpy(buf, name, len); + buf[len] = '='; + buf[len+1] = '\0'; + + mid = mrb_intern2(mrb, buf, len+1); + mrb_free(mrb, buf); + return mid; } static mrb_value mrb_struct_set(mrb_state *mrb, mrb_value obj, mrb_value val) { - mrb_value members, slot, *ptr, *ptr_members; - long i, len; - - members = mrb_struct_members(mrb, obj); - ptr_members = RARRAY_PTR(members); - len = RARRAY_LEN(members); - mrb_struct_modify(obj); - ptr = RSTRUCT_PTR(obj); - for (i=0; i<len; i++) { - slot = ptr_members[i]; - if (mrb_id_attrset(SYM2ID(slot)) == 0/*rb_frame_this_func(mrb)*/) { - return ptr[i] = val; - } + const char *name; + int i, len; + mrb_sym mid; + mrb_value members, slot, *ptr, *ptr_members; + + /* get base id */ + name = mrb_sym2name_len(mrb, mrb->ci->mid, &len); + mid = mrb_intern2(mrb, name, len-1); /* omit last "=" */ + + members = mrb_struct_members(mrb, obj); + ptr_members = RARRAY_PTR(members); + len = RARRAY_LEN(members); + mrb_struct_modify(obj); + ptr = RSTRUCT_PTR(obj); + for (i=0; i<len; i++) { + slot = ptr_members[i]; + if (SYM2ID(slot) == mid) { + return ptr[i] = val; } - mrb_name_error(mrb, 0/*rb_frame_this_func(mrb)*/, "`%s' is not a struct member", - mrb_sym2name(mrb, 0/*rb_frame_this_func(mrb)*/)); - return mrb_nil_value(); /* not reached */ + } + + mrb_name_error(mrb, mid, "`%s' is not a struct member", + mrb_sym2name(mrb, mid)); + return mrb_nil_value(); /* not reached */ +} + +static mrb_value +mrb_struct_set_m(mrb_state *mrb, mrb_value obj) +{ + mrb_value val; + + mrb_get_args(mrb, "o", &val); + return mrb_struct_set(mrb, obj, val); } #define is_notop_id(id) (id)//((id)>tLAST_TOKEN) @@ -241,19 +258,15 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k //OBJ_FREEZE(members); if (mrb_nil_p(name)) { c = mrb_class_new(mrb, klass); - //mrb_make_metaclass(nstr, RBASIC(klass)->c); - //mrb_class_inherited(klass, nstr); } else { /* old style: should we warn? */ name = mrb_str_to_str(mrb, name); id = mrb_to_id(mrb, name); if (!mrb_is_const_id(id)) { - //mrb_name_error(id, "identifier %s needs to be constant", StringValuePtr(name)); mrb_name_error(mrb, id, "identifier %s needs to be constant", mrb_string_value_ptr(mrb, name)); } if (mrb_const_defined_at(mrb, klass, id)) { - //mrb_warn("redefining constant Struct::%s", StringValuePtr(name)); mrb_warn("redefining constant Struct::%s", mrb_string_value_ptr(mrb, name)); //?rb_mod_remove_const(klass, mrb_sym2name(mrb, id)); } @@ -263,8 +276,8 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k nstr = mrb_obj_value(c); mrb_iv_set(mrb, nstr, mrb_intern(mrb, "__members__"), members); - mrb_define_class_method(mrb, c, "new", mrb_class_new_instance_m, ARGS_ANY()); - mrb_define_class_method(mrb, c, "[]", mrb_class_new_instance_m, ARGS_ANY()); + mrb_define_class_method(mrb, c, "new", mrb_instance_new, ARGS_ANY()); + mrb_define_class_method(mrb, c, "[]", mrb_instance_new, ARGS_ANY()); mrb_define_class_method(mrb, c, "members", mrb_struct_s_members_m, ARGS_NONE()); //RSTRUCT(nstr)->basic.c->super = c->c; ptr_members = RARRAY_PTR(members); @@ -273,12 +286,12 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k mrb_sym id = SYM2ID(ptr_members[i]); if (mrb_is_local_id(id) || mrb_is_const_id(id)) { if (i < N_REF_FUNC) { - mrb_define_method_id(mrb, c, id, (mrb_func_t)ref_func[i], 0); + mrb_define_method_id(mrb, c, id, ref_func[i], ARGS_NONE()); } else { - mrb_define_method_id(mrb, c, id, mrb_struct_ref, 0); + mrb_define_method_id(mrb, c, id, mrb_struct_ref, ARGS_NONE()); } - mrb_define_method_id(mrb, c, mrb_id_attrset(id), (mrb_func_t)mrb_struct_set, 1); + mrb_define_method_id(mrb, c, mrb_id_attrset(mrb, id), mrb_struct_set_m, ARGS_REQ(1)); } } @@ -299,7 +312,7 @@ mrb_struct_define(mrb_state *mrb, const char *name, ...) va_start(ar, name); while ((mem = va_arg(ar, char*)) != 0) { mrb_sym slot = mrb_intern(mrb, mem); - mrb_ary_push(mrb, ary, mrb_str_new_cstr(mrb, mrb_sym2name(mrb, slot))); + mrb_ary_push(mrb, ary, mrb_symbol_value(slot)); } va_end(ar); @@ -354,33 +367,31 @@ mrb_struct_s_def(mrb_state *mrb, mrb_value klass) name = mrb_nil_value(); rest = mrb_nil_value(); - mrb_get_args(mrb, "&*", &b, &argv, &argc); + mrb_get_args(mrb, "*&", &argv, &argc, &b); if (argc > 0) name = argv[0]; if (argc > 1) rest = argv[1]; - //mrb_scan_args(argc, argv, "1*", &name, &rest); if (mrb_type(rest) == MRB_TT_ARRAY) { if (!mrb_nil_p(name) && SYMBOL_P(name)) { /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */ mrb_ary_unshift(mrb, rest, name); name = mrb_nil_value(); } - for (i=0; i<RARRAY_LEN(rest); i++) { - id = mrb_to_id(mrb, RARRAY_PTR(rest)[i]); - RARRAY_PTR(rest)[i] = mrb_str_new_cstr(mrb, mrb_sym2name(mrb, id)); - } } else { pargv = &argv[1]; argcnt = argc-1; if (!mrb_nil_p(name) && SYMBOL_P(name)) { /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */ - //mrb_ary_unshift(mrb, rest, name); name = mrb_nil_value(); pargv = &argv[0]; argcnt++; } rest = mrb_ary_new_from_values(mrb, argcnt, pargv); } + for (i=0; i<RARRAY_LEN(rest); i++) { + id = mrb_to_id(mrb, RARRAY_PTR(rest)[i]); + RARRAY_PTR(rest)[i] = mrb_symbol_value(id); + } st = make_struct(mrb, name, rest, struct_class(mrb)); if (!mrb_nil_p(b)) { mrb_funcall(mrb, b, "call", 1, &st); @@ -389,7 +400,7 @@ mrb_struct_s_def(mrb_state *mrb, mrb_value klass) return st; } -static long +static int num_members(mrb_state *mrb, struct RClass *klass) { mrb_value members; @@ -407,7 +418,7 @@ static mrb_value mrb_struct_initialize_withArg(mrb_state *mrb, int argc, mrb_value *argv, mrb_value self) { struct RClass *klass = mrb_obj_class(mrb, self); - long n; + int n; struct RStruct *st; mrb_struct_modify(self); @@ -416,12 +427,10 @@ mrb_struct_initialize_withArg(mrb_state *mrb, int argc, mrb_value *argv, mrb_val mrb_raise(mrb, E_ARGUMENT_ERROR, "struct size differs"); } st = RSTRUCT(self); - st->ptr = malloc(sizeof(mrb_value)*argc); + st->ptr = (mrb_value *)mrb_calloc(mrb, sizeof(mrb_value), n); st->len = n; memcpy(st->ptr, argv, sizeof(mrb_value)*argc); - //if (n > argc) { - // mrb_mem_clear(RSTRUCT_PTR(self)+argc, n-argc); - //} + return self; } @@ -438,41 +447,14 @@ mrb_struct_initialize_m(mrb_state *mrb, /*int argc, mrb_value *argv,*/ mrb_value mrb_value mrb_struct_initialize(mrb_state *mrb, mrb_value self, mrb_value values) { - return mrb_struct_initialize_withArg(mrb, RARRAY_LEN/*INT*/(values), RARRAY_PTR(values), self); -} - -mrb_value -mrb_struct_alloc(mrb_state *mrb, mrb_value klass, mrb_value values) -{ - return mrb_class_new_instance(mrb, RARRAY_LEN(values), RARRAY_PTR(values), mrb_class(mrb, klass)); -} - -mrb_value -mrb_struct_new(mrb_state *mrb, struct RClass *klass, ...) -{ - mrb_value tmpargs[N_REF_FUNC], *mem = tmpargs; - int size, i; - va_list args; - - size = mrb_long2int(num_members(mrb, klass)); - if (size > numberof(tmpargs)) { - tmpargs[0] = mrb_ary_tmp_new(mrb, size); - mem = RARRAY_PTR(tmpargs[0]); - } - va_start(args, klass); - for (i=0; i<size; i++) { - mem[i] = va_arg(args, mrb_value); - } - va_end(args); - - return mrb_class_new_instance(mrb, size, mem, klass); + return mrb_struct_initialize_withArg(mrb, RARRAY_LEN(values), RARRAY_PTR(values), self); } static mrb_value inspect_struct(mrb_state *mrb, mrb_value s, mrb_value dummy, int recur) { const char *cn = mrb_class_name(mrb, mrb_obj_class(mrb, s)); - mrb_value members, str = mrb_str_new2(mrb, "#<struct "); + mrb_value members, str = mrb_str_new(mrb, "#<struct ", 9); mrb_value *ptr, *ptr_members; long i, len; @@ -500,8 +482,11 @@ inspect_struct(mrb_state *mrb, mrb_value s, mrb_value dummy, int recur) slot = ptr_members[i]; id = SYM2ID(slot); if (mrb_is_local_id(id) || mrb_is_const_id(id)) { - //mrb_str_append(str, mrb_id2str(id)); - mrb_str_append(mrb, str, mrb_str_new_cstr(mrb, mrb_sym2name(mrb, id))); + const char *name; + int len; + + name = mrb_sym2name_len(mrb, id, &len); + mrb_str_append(mrb, str, mrb_str_new(mrb, name, len)); } else { mrb_str_append(mrb, str, mrb_inspect(mrb, slot)); @@ -537,7 +522,6 @@ mrb_struct_init_copy(mrb_state *mrb, mrb_value copy) mrb_get_args(mrb, "o", &s); if (mrb_obj_equal(mrb, copy, s)) return copy; - //mrb_check_frozen(copy); if (!mrb_obj_is_instance_of(mrb, s, mrb_obj_class(mrb, copy))) { mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class"); } @@ -690,22 +674,6 @@ mrb_struct_aset(mrb_state *mrb, mrb_value s) return RSTRUCT_PTR(s)[i] = val; } -static mrb_value -recursive_equal(mrb_state *mrb, mrb_value s, mrb_value s2, int recur) -{ - mrb_value *ptr, *ptr2; - long i, len; - - if (recur) return mrb_true_value(); /* Subtle! */ - ptr = RSTRUCT_PTR(s); - ptr2 = RSTRUCT_PTR(s2); - len = RSTRUCT_LEN(s); - for (i=0; i<len; i++) { - if (!mrb_equal(mrb, ptr[i], ptr2[i])) return mrb_false_value(); - } - return mrb_true_value(); -} - /* 15.2.18.4.1 */ /* * call-seq: @@ -728,6 +696,8 @@ static mrb_value mrb_struct_equal(mrb_state *mrb, mrb_value s) { mrb_value s2; + mrb_value *ptr, *ptr2; + long i, len; mrb_get_args(mrb, "o", &s2); if (mrb_obj_equal(mrb, s, s2)) return mrb_true_value(); @@ -736,24 +706,13 @@ mrb_struct_equal(mrb_state *mrb, mrb_value s) if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) { mrb_bug("inconsistent struct"); /* should never happen */ } - - return mrb_exec_recursive_paired(mrb, recursive_equal, s, s2, (void*)0); -} - -static mrb_value -recursive_eql(mrb_state *mrb, mrb_value s, mrb_value s2, int recur) -{ - mrb_value *ptr, *ptr2; - long i, len; - - if (recur) return mrb_true_value(); /* Subtle! */ - ptr = RSTRUCT_PTR(s); - ptr2 = RSTRUCT_PTR(s2); - len = RSTRUCT_LEN(s); - for (i=0; i<len; i++) { - if (!mrb_eql(mrb, ptr[i], ptr2[i])) return mrb_false_value(); - } - return mrb_true_value(); + ptr = RSTRUCT_PTR(s); + ptr2 = RSTRUCT_PTR(s2); + len = RSTRUCT_LEN(s); + for (i=0; i<len; i++) { + if (!mrb_equal(mrb, ptr[i], ptr2[i])) return mrb_false_value(); + } + return mrb_true_value(); } /* 15.2.18.4.12(x) */ @@ -768,6 +727,8 @@ static mrb_value mrb_struct_eql(mrb_state *mrb, mrb_value s) { mrb_value s2; + mrb_value *ptr, *ptr2; + long i, len; mrb_get_args(mrb, "o", &s2); if (mrb_obj_equal(mrb, s, s2)) return mrb_true_value(); @@ -777,7 +738,13 @@ mrb_struct_eql(mrb_state *mrb, mrb_value s) mrb_bug("inconsistent struct"); /* should never happen */ } - return mrb_exec_recursive_paired(mrb, recursive_eql, s, s2, (void*)0); + ptr = RSTRUCT_PTR(s); + ptr2 = RSTRUCT_PTR(s2); + len = RSTRUCT_LEN(s); + for (i=0; i<len; i++) { + if (!mrb_eql(mrb, ptr[i], ptr2[i])) return mrb_false_value(); + } + return mrb_true_value(); } /* @@ -800,9 +767,7 @@ mrb_init_struct(mrb_state *mrb) { struct RClass *st; st = mrb_define_class(mrb, "Struct", mrb->object_class); - //mrb_include_module(mrb_cStruct, rb_mEnumerable); - //mrb_undef_alloc_func(mrb_cStruct); mrb_define_class_method(mrb, st, "new", mrb_struct_s_def, ARGS_ANY()); /* 15.2.18.3.1 */ mrb_define_method(mrb, st, "==", mrb_struct_equal, ARGS_REQ(1)); /* 15.2.18.4.1 */ @@ -816,3 +781,4 @@ mrb_init_struct(mrb_state *mrb) mrb_define_method(mrb, st, "eql?", mrb_struct_eql, ARGS_REQ(1)); /* 15.2.18.4.12(x) */ } +#endif /* ENABLE_STRUCT */ diff --git a/src/symbol.c b/src/symbol.c index aa5b659fa..b81296929 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -8,68 +8,99 @@ #include "mruby/khash.h" #include <string.h> -#include <stdarg.h> -#include <string.h> #include "mruby/string.h" #include <ctype.h> -#include "mruby/class.h" -#include "mruby/variable.h" -#include <stdio.h> /* ------------------------------------------------------ */ -KHASH_INIT(s2n, mrb_sym, const char*, 1, kh_int_hash_func, kh_int_hash_equal) -KHASH_MAP_INIT_STR(n2s, mrb_sym); +typedef struct symbol_name { + int len; + const char *name; +} symbol_name; + +static inline khint_t +sym_hash_func(mrb_state *mrb, const symbol_name s) +{ + khint_t h = 0; + size_t i; + const char *p = s.name; + + for (i=0; i<s.len; i++) { + h = (h << 5) - h + *p++; + } + return h; +} +#define sym_hash_equal(mrb,a, b) (a.len == b.len && memcmp(a.name, b.name, a.len) == 0) + +KHASH_DECLARE(n2s, symbol_name, mrb_sym, 1) +KHASH_DEFINE (n2s, symbol_name, mrb_sym, 1, sym_hash_func, sym_hash_equal) /* ------------------------------------------------------ */ mrb_sym -mrb_intern(mrb_state *mrb, const char *name) +mrb_intern2(mrb_state *mrb, const char *name, int len) { khash_t(n2s) *h = mrb->name2sym; - khash_t(s2n) *rh = mrb->sym2name; + symbol_name sname; khiter_t k; - size_t len; - char *p; mrb_sym sym; + char *p; - k = kh_get(n2s, h, name); + sname.len = len; + sname.name = name; + k = kh_get(n2s, h, sname); if (k != kh_end(h)) return kh_value(h, k); sym = ++mrb->symidx; - len = strlen(name); - p = mrb_malloc(mrb, len+1); + p = (char *)mrb_malloc(mrb, len+1); memcpy(p, name, len); p[len] = 0; - k = kh_put(n2s, h, p); + sname.name = (const char*)p; + k = kh_put(n2s, h, sname); kh_value(h, k) = sym; - k = kh_put(s2n, rh, sym); - kh_value(rh, k) = p; - return sym; } +mrb_sym +mrb_intern(mrb_state *mrb, const char *name) +{ + return mrb_intern2(mrb, name, strlen(name)); +} + +mrb_sym +mrb_intern_str(mrb_state *mrb, mrb_value str) +{ + return mrb_intern2(mrb, RSTRING_PTR(str), RSTRING_LEN(str)); +} + const char* -mrb_sym2name(mrb_state *mrb, mrb_sym sym) +mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, int *lenp) { - khash_t(s2n) *h = mrb->sym2name; + khash_t(n2s) *h = mrb->name2sym; khiter_t k; + symbol_name sname; - k = kh_get(s2n, h, sym); + for (k = kh_begin(h); k != kh_end(h); k++) { + if (kh_exist(h, k)) { + if (kh_value(h, k) == sym) break; + } + } if (k == kh_end(h)) { - return NULL; /* missing */ + *lenp = 0; + return NULL; /* missing */ } - return kh_value(h, k); + sname = kh_key(h, k); + *lenp = sname.len; + return sname.name; } void mrb_free_symtbls(mrb_state *mrb) { - khash_t(s2n) *h = mrb->sym2name; + khash_t(n2s) *h = mrb->name2sym; khiter_t k; - for (k = kh_begin(h); k != kh_end(h); ++k) - if (kh_exist(h, k)) mrb_free(mrb, (char*)kh_value(h, k)); - kh_destroy(s2n,mrb->sym2name); + for (k = kh_begin(h); k != kh_end(h); k++) + if (kh_exist(h, k)) mrb_free(mrb, (char*)kh_key(h, k).name); kh_destroy(n2s,mrb->name2sym); } @@ -77,7 +108,6 @@ void mrb_init_symtbl(mrb_state *mrb) { mrb->name2sym = kh_init(n2s, mrb); - mrb->sym2name = kh_init(s2n, mrb); } /********************************************************************** @@ -148,8 +178,11 @@ mrb_value mrb_sym_to_s(mrb_state *mrb, mrb_value sym) { mrb_sym id = SYM2ID(sym); + const char *p; + int len; - return mrb_str_new_cstr(mrb, mrb_sym2name(mrb, id)); + p = mrb_sym2name_len(mrb, id, &len); + return mrb_str_new(mrb, p, len); } /* 15.2.11.3.4 */ @@ -188,8 +221,7 @@ sym_to_sym(mrb_state *mrb, mrb_value sym) #define is_identchar(c) (SIGN_EXTEND_CHAR(c)!=-1&&(ISALNUM(c) || (c) == '_')) static int -is_special_global_name(m) - const char *m; +is_special_global_name(const char* m) { switch (*m) { case '~': case '*': case '$': case '?': case '!': case '@': @@ -240,6 +272,7 @@ symname_p(const char *name) case '>': switch (*++m) { case '>': case '=': ++m; break; + default: break; } break; @@ -254,12 +287,20 @@ symname_p(const char *name) case '*': if (*++m == '*') ++m; break; - + case '!': + if (*++m == '=') ++m; + break; case '+': case '-': if (*++m == '@') ++m; break; + case '|': + if (*++m == '|') ++m; + break; + case '&': + if (*++m == '&') ++m; + break; - case '|': case '^': case '&': case '/': case '%': case '~': case '`': + case '^': case '/': case '%': case '~': case '`': ++m; break; @@ -275,7 +316,8 @@ id: while (is_identchar(*m)) m += 1; if (localid) { switch (*m) { - case '!': case '?': case '=': ++m; + case '!': case '?': case '=': ++m; + default: break; } } break; @@ -288,22 +330,69 @@ sym_inspect(mrb_state *mrb, mrb_value sym) { mrb_value str; const char *name; + int len; mrb_sym id = SYM2ID(sym); - name = mrb_sym2name(mrb, id); //mrb_id2name(id); - str = mrb_str_new(mrb, 0, strlen(name)+1); - RSTRING(str)->buf[0] = ':'; - strcpy(RSTRING(str)->buf+1, name); - if (!symname_p(name)) { + name = mrb_sym2name_len(mrb, id, &len); + str = mrb_str_new(mrb, 0, len+1); + RSTRING(str)->ptr[0] = ':'; + memcpy(RSTRING(str)->ptr+1, name, len); + if (!symname_p(name) || strlen(name) != len) { str = mrb_str_dump(mrb, str); - strncpy(RSTRING(str)->buf, ":\"", 2); + memcpy(RSTRING(str)->ptr, ":\"", 2); } return str; } +const char* +mrb_sym2name(mrb_state *mrb, mrb_sym sym) +{ + int len; + const char *name = mrb_sym2name_len(mrb, sym, &len); + + if (!name) return NULL; + if (symname_p(name) && strlen(name) == len) { + return name; + } + else { + mrb_value str = mrb_str_dump(mrb, mrb_str_new(mrb, name, len)); + return RSTRING(str)->ptr; + } +} + +#define lesser(a,b) (((a)>(b))?(b):(a)) + +static mrb_value +sym_cmp(mrb_state *mrb, mrb_value s1) +{ + mrb_value s2; + mrb_sym sym1, sym2; + + mrb_get_args(mrb, "o", &s2); + if (mrb_type(s2) != MRB_TT_SYMBOL) return mrb_nil_value(); + sym1 = mrb_symbol(s1); + sym2 = mrb_symbol(s2); + if (sym1 == sym2) return mrb_fixnum_value(0); + else { + const char *p1, *p2; + int len, len1, len2, retval; + + p1 = mrb_sym2name_len(mrb, sym1, &len1); + p2 = mrb_sym2name_len(mrb, sym2, &len2); + len = lesser(len1, len2); + retval = memcmp(p1, p2, len); + if (retval == 0) { + if (len1 == len2) return mrb_fixnum_value(0); + if (len1 > len2) return mrb_fixnum_value(1); + return mrb_fixnum_value(-1); + } + if (retval > 0) return mrb_fixnum_value(1); + return mrb_fixnum_value(-1); + } +} void -mrb_init_symbols(mrb_state *mrb) +mrb_init_symbol(mrb_state *mrb) { struct RClass *sym; @@ -313,6 +402,6 @@ mrb_init_symbols(mrb_state *mrb) mrb_define_method(mrb, sym, "id2name", mrb_sym_to_s, ARGS_NONE()); /* 15.2.11.3.2 */ mrb_define_method(mrb, sym, "to_s", mrb_sym_to_s, ARGS_NONE()); /* 15.2.11.3.3 */ mrb_define_method(mrb, sym, "to_sym", sym_to_sym, ARGS_NONE()); /* 15.2.11.3.4 */ - mrb_define_method(mrb, sym, "inspect", sym_inspect, ARGS_NONE()); /* 15.2.11.3.5(x) */ + mrb_define_method(mrb, sym, "<=>", sym_cmp, ARGS_REQ(1)); } diff --git a/src/time.c b/src/time.c index 63b763a08..ac04745e5 100644 --- a/src/time.c +++ b/src/time.c @@ -6,6 +6,7 @@ #include "mruby.h" +#ifdef ENABLE_TIME #include <string.h> #include <stdio.h> #include <time.h> @@ -136,13 +137,13 @@ mrb_time_update_datetime(struct mrb_time *self) { struct tm *aid; - if(self->timezone == MRB_TIMEZONE_UTC) { + if (self->timezone == MRB_TIMEZONE_UTC) { aid = gmtime_r(&self->sec, &self->datetime); } else { aid = localtime_r(&self->sec, &self->datetime); } - if(!aid) return NULL; + if (!aid) return NULL; #ifdef NO_GMTIME_R self->datetime = *aid; // copy data #endif @@ -159,13 +160,21 @@ mrb_time_wrap(mrb_state *mrb, struct RClass *tc, struct mrb_time *tm) /* Allocates a mrb_time object and initializes it. */ static struct mrb_time* -mrb_time_alloc(mrb_state *mrb, mrb_float seconds, enum mrb_timezone timezone) +mrb_time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone) { struct mrb_time *tm; - tm = mrb_malloc(mrb, sizeof(struct mrb_time)); - tm->sec = (time_t)seconds; - tm->usec = (seconds - tm->sec) * 1.0e6; + tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(struct mrb_time)); + tm->sec = (time_t)sec; + tm->usec = (sec - tm->sec) * 1.0e6 + usec; + while (tm->usec < 0) { + tm->sec--; + tm->usec += 1.0e6; + } + while (tm->usec > 1.0e6) { + tm->sec++; + tm->usec -= 1.0e6; + } tm->timezone = timezone; mrb_time_update_datetime(tm); @@ -173,9 +182,9 @@ mrb_time_alloc(mrb_state *mrb, mrb_float seconds, enum mrb_timezone timezone) } static mrb_value -mrb_time_make(mrb_state *mrb, struct RClass *c, mrb_float seconds, enum mrb_timezone timezone) +mrb_time_make(mrb_state *mrb, struct RClass *c, double sec, double usec, enum mrb_timezone timezone) { - return mrb_time_wrap(mrb, c, mrb_time_alloc(mrb, seconds, timezone)); + return mrb_time_wrap(mrb, c, mrb_time_alloc(mrb, sec, usec, timezone)); } static struct mrb_time* @@ -183,7 +192,7 @@ current_mrb_time(mrb_state *mrb) { struct mrb_time *tm; - tm = mrb_malloc(mrb, sizeof(*tm)); + tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm)); #ifdef NO_GETTIMEOFDAY { static time_t last_sec = 0, last_usec = 0; @@ -226,10 +235,10 @@ mrb_time_now(mrb_state *mrb, mrb_value self) static mrb_value mrb_time_at(mrb_state *mrb, mrb_value self) { - mrb_float f; + mrb_float f, f2 = 0; - mrb_get_args(mrb, "f", &f); - return mrb_time_make(mrb, mrb_class_ptr(self), f, MRB_TIMEZONE_LOCAL); + mrb_get_args(mrb, "f|f", &f, &f2); + return mrb_time_make(mrb, mrb_class_ptr(self), f, f2, MRB_TIMEZONE_LOCAL); } static struct mrb_time* @@ -238,9 +247,8 @@ time_mktime(mrb_state *mrb, mrb_int ayear, mrb_int amonth, mrb_int aday, enum mrb_timezone timezone) { time_t nowsecs; - struct tm nowtime; + struct tm nowtime = { 0 }; - memset(&nowtime, 0, sizeof(struct tm)); nowtime.tm_year = (int)ayear - 1900; nowtime.tm_mon = (int)amonth - 1; nowtime.tm_mday = (int)aday; @@ -258,7 +266,7 @@ time_mktime(mrb_state *mrb, mrb_int ayear, mrb_int amonth, mrb_int aday, mrb_raise(mrb, E_ARGUMENT_ERROR, "Not a valid time."); } - return mrb_time_alloc(mrb, nowsecs+ausec/10e6, timezone); + return mrb_time_alloc(mrb, nowsecs, ausec, timezone); } /* 15.2.19.6.2 */ @@ -296,8 +304,8 @@ mrb_time_eq(mrb_state *mrb, mrb_value self) struct mrb_time *tm1, *tm2; mrb_get_args(mrb, "o", &other); - tm1 = mrb_get_datatype(mrb, self, &mrb_time_type); - tm2 = mrb_get_datatype(mrb, other, &mrb_time_type); + tm1 = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm2 = (struct mrb_time *)mrb_get_datatype(mrb, other, &mrb_time_type); if (!tm1 || !tm2) return mrb_false_value(); if (tm1->sec == tm2->sec && tm1->usec == tm2->usec) { return mrb_true_value(); @@ -312,8 +320,8 @@ mrb_time_cmp(mrb_state *mrb, mrb_value self) struct mrb_time *tm1, *tm2; mrb_get_args(mrb, "o", &other); - tm1 = mrb_get_datatype(mrb, self, &mrb_time_type); - tm2 = mrb_get_datatype(mrb, other, &mrb_time_type); + tm1 = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm2 = (struct mrb_time *)mrb_get_datatype(mrb, other, &mrb_time_type); if (!tm1 || !tm2) return mrb_nil_value(); if (tm1->sec > tm2->sec) { return mrb_fixnum_value(1); @@ -338,25 +346,32 @@ mrb_time_plus(mrb_state *mrb, mrb_value self) struct mrb_time *tm; mrb_get_args(mrb, "f", &f); - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); - f += tm->sec; - f += (mrb_float)tm->usec / 1.0e6; - return mrb_time_make(mrb, mrb_obj_class(mrb, self), f, tm->timezone); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); + return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec+f, tm->usec, tm->timezone); } static mrb_value mrb_time_minus(mrb_state *mrb, mrb_value self) { mrb_float f; - struct mrb_time *tm; + mrb_value other; + struct mrb_time *tm, *tm2; - mrb_get_args(mrb, "f", &f); - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); - f -= tm->sec; - f -= (mrb_float)tm->usec / 1.0e6; - return mrb_time_make(mrb, mrb_obj_class(mrb, self), f, tm->timezone); + mrb_get_args(mrb, "o", &other); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); + + tm2 = (struct mrb_time *)mrb_get_datatype(mrb, other, &mrb_time_type); + if (tm2) { + f = (mrb_float)(tm->sec - tm2->sec) + + (mrb_float)(tm->usec - tm2->usec) / 1.0e6; + return mrb_float_value(f); + } + else { + mrb_get_args(mrb, "f", &f); + return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec-f, tm->usec, tm->timezone); + } } /* 15.2.19.7.30 */ @@ -366,8 +381,8 @@ mrb_time_wday(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_wday); } @@ -378,8 +393,8 @@ mrb_time_yday(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = mrb_check_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); + tm = (struct mrb_time *)mrb_check_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_yday); } @@ -390,8 +405,8 @@ mrb_time_year(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_year + 1900); } @@ -402,10 +417,10 @@ mrb_time_zone(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); - if(tm->timezone <= MRB_TIMEZONE_NONE) return mrb_nil_value(); - if(tm->timezone >= MRB_TIMEZONE_LAST) return mrb_nil_value(); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); + if (tm->timezone <= MRB_TIMEZONE_NONE) return mrb_nil_value(); + if (tm->timezone >= MRB_TIMEZONE_LAST) return mrb_nil_value(); return mrb_str_new_cstr(mrb, timezone_names[tm->timezone]); } @@ -417,16 +432,17 @@ mrb_time_asctime(mrb_state *mrb, mrb_value self) struct mrb_time *tm; struct tm *d; char buf[256]; + int len; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); d = &tm->datetime; - snprintf(buf, 256, "%s %s %02d %02d:%02d:%02d %s%d", - wday_names[d->tm_wday], mon_names[d->tm_mon], d->tm_mday, - d->tm_hour, d->tm_min, d->tm_sec, - tm->timezone == MRB_TIMEZONE_UTC ? "UTC " : "", - d->tm_year + 1900); - return mrb_str_new_cstr(mrb, buf); + len = snprintf(buf, sizeof(buf), "%s %s %02d %02d:%02d:%02d %s%d", + wday_names[d->tm_wday], mon_names[d->tm_mon], d->tm_mday, + d->tm_hour, d->tm_min, d->tm_sec, + tm->timezone == MRB_TIMEZONE_UTC ? "UTC " : "", + d->tm_year + 1900); + return mrb_str_new(mrb, buf, len); } /* 15.2.19.7.6 */ @@ -436,8 +452,8 @@ mrb_time_day(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_mday); } @@ -449,11 +465,44 @@ mrb_time_dstp(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); return mrb_bool_value(tm->datetime.tm_isdst); } +/* 15.2.19.7.8 */ +/* 15.2.19.7.10 */ +/* Returns the Time object of the UTC(GMT) timezone. */ +static mrb_value +mrb_time_getutc(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm, *tm2; + + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return self; + tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm)); + *tm2 = *tm; + tm2->timezone = MRB_TIMEZONE_UTC; + mrb_time_update_datetime(tm2); + return mrb_time_wrap(mrb, mrb_obj_class(mrb, self), tm2); +} + +/* 15.2.19.7.9 */ +/* Returns the Time object of the LOCAL timezone. */ +static mrb_value +mrb_time_getlocal(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm, *tm2; + + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return self; + tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm)); + *tm2 = *tm; + tm2->timezone = MRB_TIMEZONE_LOCAL; + mrb_time_update_datetime(tm2); + return mrb_time_wrap(mrb, mrb_obj_class(mrb, self), tm2); +} + /* 15.2.19.7.15 */ /* Returns hour of time. */ static mrb_value @@ -461,8 +510,8 @@ mrb_time_hour(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_hour); } @@ -473,18 +522,20 @@ mrb_time_initialize(mrb_state *mrb, mrb_value self) { mrb_int ayear = 0, amonth = 1, aday = 1, ahour = 0, amin = 0, asec = 0, ausec = 0; + int n; struct mrb_time *tm; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); if (tm) { mrb_time_free(mrb, tm); } - if (mrb->ci->argc == 0) { + + n = mrb_get_args(mrb, "|iiiiiii", + &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec); + if (n == 0) { tm = current_mrb_time(mrb); } else { - mrb_get_args(mrb, "iiiiiii", - &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec); tm = time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL); } DATA_PTR(self) = tm; @@ -519,8 +570,8 @@ mrb_time_localtime(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return self; + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return self; tm->timezone = MRB_TIMEZONE_LOCAL; mrb_time_update_datetime(tm); return self; @@ -533,8 +584,8 @@ mrb_time_mday(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_mday); } @@ -545,8 +596,8 @@ mrb_time_min(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_min); } @@ -557,8 +608,8 @@ mrb_time_mon(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_mon + 1); } @@ -569,8 +620,8 @@ mrb_time_sec(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_sec); } @@ -582,8 +633,8 @@ mrb_time_to_f(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); return mrb_float_value((mrb_float)tm->sec + (mrb_float)tm->usec/1.0e6); } @@ -594,8 +645,8 @@ mrb_time_to_i(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->sec); } @@ -606,8 +657,8 @@ mrb_time_usec(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->usec); } @@ -618,7 +669,7 @@ mrb_time_utc(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); if (tm) { tm->timezone = MRB_TIMEZONE_UTC; mrb_time_update_datetime(tm); @@ -632,8 +683,8 @@ static mrb_value mrb_time_utcp(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = mrb_get_datatype(mrb, self, &mrb_time_type); - if(!tm) return mrb_nil_value(); + tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + if (!tm) return mrb_nil_value(); return mrb_bool_value(tm->timezone == MRB_TIMEZONE_UTC); } @@ -647,41 +698,54 @@ mrb_init_time(mrb_state *mrb) tc = mrb_define_class(mrb, "Time", mrb->object_class); MRB_SET_INSTANCE_TT(tc, MRB_TT_DATA); mrb_include_module(mrb, tc, mrb_class_get(mrb, "Comparable")); - mrb_define_class_method(mrb, tc, "now", mrb_time_now, ARGS_NONE()); - mrb_define_class_method(mrb, tc, "at", mrb_time_at, ARGS_ANY()); - mrb_define_class_method(mrb, tc, "gm", mrb_time_gm, ARGS_REQ(1)|ARGS_OPT(6)); - mrb_define_class_method(mrb, tc, "local", mrb_time_local, ARGS_REQ(1)|ARGS_OPT(6)); + mrb_define_class_method(mrb, tc, "at", mrb_time_at, ARGS_ANY()); /* 15.2.19.6.1 */ + mrb_define_class_method(mrb, tc, "gm", mrb_time_gm, ARGS_REQ(1)|ARGS_OPT(6)); /* 15.2.19.6.2 */ + mrb_define_class_method(mrb, tc, "local", mrb_time_local, ARGS_REQ(1)|ARGS_OPT(6)); /* 15.2.19.6.3 */ + mrb_define_class_method(mrb, tc, "mktime", mrb_time_local, ARGS_REQ(1)|ARGS_OPT(6));/* 15.2.19.6.4 */ + mrb_define_class_method(mrb, tc, "now", mrb_time_now, ARGS_NONE()); /* 15.2.19.6.5 */ + mrb_define_class_method(mrb, tc, "utc", mrb_time_gm, ARGS_REQ(1)|ARGS_OPT(6)); /* 15.2.19.6.6 */ mrb_define_method(mrb, tc, "==" , mrb_time_eq , ARGS_REQ(1)); - mrb_define_method(mrb, tc, "<=>" , mrb_time_cmp , ARGS_REQ(1)); - mrb_define_method(mrb, tc, "+" , mrb_time_plus , ARGS_REQ(1)); - mrb_define_method(mrb, tc, "-" , mrb_time_minus , ARGS_REQ(1)); + mrb_define_method(mrb, tc, "<=>" , mrb_time_cmp , ARGS_REQ(1)); /* 15.2.19.7.1 */ + mrb_define_method(mrb, tc, "+" , mrb_time_plus , ARGS_REQ(1)); /* 15.2.19.7.2 */ + mrb_define_method(mrb, tc, "-" , mrb_time_minus , ARGS_REQ(1)); /* 15.2.19.7.3 */ mrb_define_method(mrb, tc, "to_s" , mrb_time_asctime, ARGS_NONE()); - mrb_define_method(mrb, tc, "asctime", mrb_time_asctime, ARGS_NONE()); - mrb_define_method(mrb, tc, "ctime" , mrb_time_asctime, ARGS_NONE()); - mrb_define_method(mrb, tc, "day" , mrb_time_day , ARGS_NONE()); - mrb_define_method(mrb, tc, "dst?" , mrb_time_dstp , ARGS_NONE()); - mrb_define_method(mrb, tc, "gmt?" , mrb_time_utcp , ARGS_NONE()); - mrb_define_method(mrb, tc, "gmtime" , mrb_time_utc , ARGS_NONE()); - mrb_define_method(mrb, tc, "hour" , mrb_time_hour, ARGS_NONE()); - mrb_define_method(mrb, tc, "localtime", mrb_time_localtime, ARGS_NONE()); - mrb_define_method(mrb, tc, "mday" , mrb_time_mday, ARGS_NONE()); - mrb_define_method(mrb, tc, "min" , mrb_time_min, ARGS_NONE()); + mrb_define_method(mrb, tc, "asctime", mrb_time_asctime, ARGS_NONE()); /* 15.2.19.7.4 */ + mrb_define_method(mrb, tc, "ctime" , mrb_time_asctime, ARGS_NONE()); /* 15.2.19.7.5 */ + mrb_define_method(mrb, tc, "day" , mrb_time_day , ARGS_NONE()); /* 15.2.19.7.6 */ + mrb_define_method(mrb, tc, "dst?" , mrb_time_dstp , ARGS_NONE()); /* 15.2.19.7.7 */ + mrb_define_method(mrb, tc, "getgm" , mrb_time_getutc , ARGS_NONE()); /* 15.2.19.7.8 */ + mrb_define_method(mrb, tc, "getlocal",mrb_time_getlocal,ARGS_NONE()); /* 15.2.19.7.9 */ + mrb_define_method(mrb, tc, "getutc" , mrb_time_getutc , ARGS_NONE()); /* 15.2.19.7.10 */ + mrb_define_method(mrb, tc, "gmt?" , mrb_time_utcp , ARGS_NONE()); /* 15.2.19.7.11 */ + mrb_define_method(mrb, tc, "gmtime" , mrb_time_utc , ARGS_NONE()); /* 15.2.19.7.13 */ + mrb_define_method(mrb, tc, "hour" , mrb_time_hour, ARGS_NONE()); /* 15.2.19.7.15 */ + mrb_define_method(mrb, tc, "localtime", mrb_time_localtime, ARGS_NONE()); /* 15.2.19.7.18 */ + mrb_define_method(mrb, tc, "mday" , mrb_time_mday, ARGS_NONE()); /* 15.2.19.7.19 */ + mrb_define_method(mrb, tc, "min" , mrb_time_min, ARGS_NONE()); /* 15.2.19.7.20 */ - mrb_define_method(mrb, tc, "mon" , mrb_time_mon, ARGS_NONE()); - mrb_define_method(mrb, tc, "month", mrb_time_mon, ARGS_NONE()); + mrb_define_method(mrb, tc, "mon" , mrb_time_mon, ARGS_NONE()); /* 15.2.19.7.21 */ + mrb_define_method(mrb, tc, "month", mrb_time_mon, ARGS_NONE()); /* 15.2.19.7.22 */ - mrb_define_method(mrb, tc, "sec" , mrb_time_sec, ARGS_NONE()); - mrb_define_method(mrb, tc, "to_i", mrb_time_to_i, ARGS_NONE()); - mrb_define_method(mrb, tc, "to_f", mrb_time_to_f, ARGS_NONE()); - mrb_define_method(mrb, tc, "usec", mrb_time_usec, ARGS_NONE()); - mrb_define_method(mrb, tc, "utc" , mrb_time_utc, ARGS_NONE()); - mrb_define_method(mrb, tc, "utc?", mrb_time_utcp, ARGS_NONE()); - mrb_define_method(mrb, tc, "wday", mrb_time_wday, ARGS_NONE()); - mrb_define_method(mrb, tc, "yday", mrb_time_yday, ARGS_NONE()); - mrb_define_method(mrb, tc, "year", mrb_time_year, ARGS_NONE()); - mrb_define_method(mrb, tc, "zone", mrb_time_zone, ARGS_NONE()); + mrb_define_method(mrb, tc, "sec" , mrb_time_sec, ARGS_NONE()); /* 15.2.19.7.23 */ + mrb_define_method(mrb, tc, "to_i", mrb_time_to_i, ARGS_NONE()); /* 15.2.19.7.25 */ + mrb_define_method(mrb, tc, "to_f", mrb_time_to_f, ARGS_NONE()); /* 15.2.19.7.24 */ + mrb_define_method(mrb, tc, "usec", mrb_time_usec, ARGS_NONE()); /* 15.2.19.7.26 */ + mrb_define_method(mrb, tc, "utc" , mrb_time_utc, ARGS_NONE()); /* 15.2.19.7.27 */ + mrb_define_method(mrb, tc, "utc?", mrb_time_utcp, ARGS_NONE()); /* 15.2.19.7.28 */ + mrb_define_method(mrb, tc, "wday", mrb_time_wday, ARGS_NONE()); /* 15.2.19.7.30 */ + mrb_define_method(mrb, tc, "yday", mrb_time_yday, ARGS_NONE()); /* 15.2.19.7.31 */ + mrb_define_method(mrb, tc, "year", mrb_time_year, ARGS_NONE()); /* 15.2.19.7.32 */ + mrb_define_method(mrb, tc, "zone", mrb_time_zone, ARGS_NONE()); /* 15.2.19.7.33 */ - mrb_define_method(mrb, tc, "initialize", mrb_time_initialize, ARGS_REQ(1)); - mrb_define_method(mrb, tc, "initialize_copy", mrb_time_initialize_copy, ARGS_REQ(1)); + mrb_define_method(mrb, tc, "initialize", mrb_time_initialize, ARGS_REQ(1)); /* 15.2.19.7.16 */ + mrb_define_method(mrb, tc, "initialize_copy", mrb_time_initialize_copy, ARGS_REQ(1)); /* 15.2.19.7.17 */ + + /* + methods not available: + gmt_offset(15.2.19.7.12) + gmtoff(15.2.19.7.14) + utc_offset(15.2.19.7.29) + */ } +#endif diff --git a/src/variable.c b/src/variable.c index 82ab7bef3..8b94f5bbb 100644 --- a/src/variable.c +++ b/src/variable.c @@ -4,29 +4,20 @@ ** See Copyright Notice in mruby.h */ -#include <stdio.h> #include "mruby.h" #include "mruby/class.h" #include "mruby/khash.h" #include "mruby/variable.h" -#include "mruby/string.h" -#include "mruby/range.h" #include "error.h" #include "mruby/array.h" +#include "mruby/proc.h" -#ifdef INCLUDE_REGEXP +#ifdef ENABLE_REGEXP #include "re.h" -#include "st.h" #endif -KHASH_MAP_INIT_INT(iv, mrb_value); - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 +#ifndef MRB_IV_INITIAL_SIZE +#define MRB_IV_INITIAL_SIZE 8 #endif static void @@ -104,10 +95,28 @@ mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym) return ivget(mrb, obj->iv, sym); } +static int +obj_iv_p(mrb_value obj) +{ + switch (mrb_type(obj)) { + case MRB_TT_OBJECT: + case MRB_TT_CLASS: + case MRB_TT_MODULE: + case MRB_TT_HASH: + case MRB_TT_DATA: + return TRUE; + default: + return FALSE; + } +} + mrb_value mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym) { - return mrb_obj_iv_get(mrb, mrb_obj_ptr(obj), sym); + if (obj_iv_p(obj)) { + return mrb_obj_iv_get(mrb, mrb_obj_ptr(obj), sym); + } + return mrb_nil_value(); } static void @@ -125,7 +134,7 @@ mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v) khash_t(iv) *h; if (!obj->iv) { - h = obj->iv = kh_init(iv, mrb); + h = obj->iv = kh_init_size(iv, mrb, MRB_IV_INITIAL_SIZE); } else { h = obj->iv; @@ -137,7 +146,30 @@ mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v) void mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v) /* mrb_ivar_set */ { - mrb_obj_iv_set(mrb, mrb_obj_ptr(obj), sym, v); + if (obj_iv_p(obj)) { + mrb_obj_iv_set(mrb, mrb_obj_ptr(obj), sym, v); + } +} + +mrb_value +mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym) +{ + mrb_value val; + + if (obj_iv_p(obj)) { + khash_t(iv) *h = mrb_obj_ptr(obj)->iv; + khiter_t k; + + if (h) { + k = kh_get(iv, h, sym); + if (k != kh_end(h)) { + val = kh_value(h, k); + kh_del(iv, h, k); + return val; + } + } + } + return mrb_undef_value(); } mrb_value @@ -154,11 +186,56 @@ mrb_vm_iv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) mrb_iv_set(mrb, mrb->stack[0], sym, v); } +/* 15.3.1.3.23 */ +/* + * call-seq: + * obj.instance_variables -> array + * + * Returns an array of instance variable names for the receiver. Note + * that simply defining an accessor does not create the corresponding + * instance variable. + * + * class Fred + * attr_accessor :a1 + * def initialize + * @iv = 3 + * end + * end + * Fred.new.instance_variables #=> [:@iv] + */ +mrb_value +mrb_obj_instance_variables(mrb_state *mrb, mrb_value self) +{ + mrb_value ary; + kh_iv_t *h; + khint_t i; + int len; + const char* p; + + ary = mrb_ary_new(mrb); + if (obj_iv_p(self)) { + h = ROBJECT_IVPTR(self); + if (h) { + for (i=0;i<kh_end(h);i++) { + if (kh_exist(h, i)) { + p = mrb_sym2name_len(mrb, kh_key(h,i), &len); + if (len > 1 && *p == '@') { + if (mrb_type(kh_value(h, i)) != MRB_TT_UNDEF) + mrb_ary_push(mrb, ary, mrb_str_new(mrb, p, len)); + } + } + } + } + } + return ary; +} + mrb_value mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym) { - struct RClass *c = mrb->ci->target_class; + struct RClass *c = mrb->ci->proc->target_class; + if (!c) c = mrb->ci->target_class; while (c) { if (c->iv) { khash_t(iv) *h = c->iv; @@ -175,10 +252,11 @@ mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym) void mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) { - struct RClass *c = mrb->ci->target_class; + struct RClass *c = mrb->ci->proc->target_class; khash_t(iv) *h; khiter_t k; + if (!c) c = mrb->ci->target_class; while (c) { if (c->iv) { h = c->iv; @@ -186,7 +264,7 @@ mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) if (k != kh_end(h)) { k = kh_put(iv, h, sym); kh_value(h, k) = v; - return; + return; } } c = c->super; @@ -194,7 +272,7 @@ mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) c = mrb->ci->target_class; h = c->iv; if (!h) { - c->iv = h = kh_init(iv, mrb); + c->iv = h = kh_init_size(iv, mrb, MRB_IV_INITIAL_SIZE); } k = kh_put(iv, h, sym); kh_value(h, k) = v; @@ -233,26 +311,10 @@ const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym) struct RClass *c = base; khash_t(iv) *h; khiter_t k; + int retry = 0; + mrb_sym cm; - if (c->iv) { - h = c->iv; - k = kh_get(iv, h, sym); - if (k != kh_end(h)) { - return kh_value(h, k); - } - } - for (;;) { - c = mrb_class_outer_module(mrb, c); - if (!c) break; - if (c->iv) { - h = c->iv; - k = kh_get(iv, h, sym); - if (k != kh_end(h)) { - return kh_value(h, k); - } - } - } - c = base->super; + L_RETRY: while (c) { if (c->iv) { h = c->iv; @@ -263,16 +325,20 @@ const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym) } c = c->super; } - - if (!c) { + if (!retry && base->tt == MRB_TT_MODULE) { c = mrb->object_class; + retry = 1; + goto L_RETRY; } - - if (mrb_respond_to(mrb, mrb_obj_value(c), mrb_intern(mrb, "const_missing"))) { - mrb_value argv = mrb_symbol_value(sym); - return mrb_funcall_argv(mrb, mrb_obj_value(c), "const_missing", 1, &argv); + c = base; + cm = mrb_intern(mrb, "const_missing"); + while (c) { + if (mrb_respond_to(mrb, mrb_obj_value(c), cm)) { + mrb_value name = mrb_symbol_value(sym); + return mrb_funcall(mrb, mrb_obj_value(c), "const_missing", 1, name); + } + c = c->super; } - mrb_raise(mrb, E_NAME_ERROR, "uninitialized constant %s", mrb_sym2name(mrb, sym)); /* not reached */ @@ -289,7 +355,10 @@ mrb_const_get(mrb_state *mrb, mrb_value mod, mrb_sym sym) mrb_value mrb_vm_const_get(mrb_state *mrb, mrb_sym sym) { - return const_get(mrb, mrb->ci->target_class, sym); + struct RClass *c = mrb->ci->proc->target_class; + + if (!c) c = mrb->ci->target_class; + return const_get(mrb, c, sym); } void @@ -302,7 +371,10 @@ mrb_const_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v) void mrb_vm_const_set(mrb_state *mrb, mrb_sym sym, mrb_value v) { - mrb_obj_iv_set(mrb, (struct RObject*)mrb->ci->target_class, sym, v); + struct RClass *c = mrb->ci->proc->target_class; + + if (!c) c = mrb->ci->target_class; + mrb_obj_iv_set(mrb, (struct RObject*)c, sym, v); } void @@ -394,16 +466,12 @@ mrb_st_lookup(struct kh_iv *table, mrb_sym id, khiter_t *value) } } -int +static int kiv_lookup(khash_t(iv)* table, mrb_sym key, mrb_value *value) { khash_t(iv) *h=table; khiter_t k; - // you must check(iv==0), before you call this function. - //if (!obj->iv) { - // return 0; - //} k = kh_get(iv, h, key); if (k != kh_end(h)) { *value = kh_value(h, k); @@ -442,23 +510,9 @@ mrb_const_defined_at(mrb_state *mrb, struct RClass *klass, mrb_sym id) return mrb_const_defined_0(mrb, klass, id, TRUE, FALSE); } -struct RClass * -mrb_class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id) -{ - mrb_value c = const_get(mrb, klass, id); - return mrb_class_ptr(c); -} - -struct RClass * -mrb_class_get(mrb_state *mrb, const char *name) -{ - return mrb_class_from_sym(mrb, mrb->object_class, mrb_intern(mrb, name)); -} - mrb_value mrb_attr_get(mrb_state *mrb, mrb_value obj, mrb_sym id) { - //return ivar_get(obj, id, FALSE); return mrb_iv_get(mrb, obj, id); } @@ -28,25 +28,41 @@ static void stack_init(mrb_state *mrb) { /* assert(mrb->stack == NULL); */ - mrb->stbase = mrb_malloc(mrb, sizeof(mrb_value) * STACK_INIT_SIZE); - memset(mrb->stbase, 0, sizeof(mrb_value) * STACK_INIT_SIZE); + mrb->stbase = (mrb_value *)mrb_calloc(mrb, STACK_INIT_SIZE, sizeof(mrb_value)); mrb->stend = mrb->stbase + STACK_INIT_SIZE; mrb->stack = mrb->stbase; /* assert(mrb->ci == NULL); */ - mrb->cibase = mrb_malloc(mrb, sizeof(mrb_callinfo)*CALLINFO_INIT_SIZE); + mrb->cibase = (mrb_callinfo *)mrb_calloc(mrb, CALLINFO_INIT_SIZE, sizeof(mrb_callinfo)); mrb->ciend = mrb->cibase + CALLINFO_INIT_SIZE; mrb->ci = mrb->cibase; - memset(mrb->ci, 0, sizeof(mrb_callinfo)); mrb->ci->target_class = mrb->object_class; } static void +envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase) +{ + mrb_callinfo *ci = mrb->cibase; + + while (ci <= mrb->ci) { + struct REnv *e = ci->env; + if (e && e->cioff >= 0) { + int off = e->stack - oldbase; + + e->stack = newbase + off; + } + ci++; + } +} + +static void stack_extend(mrb_state *mrb, int room, int keep) { int size, off; - if (mrb->stack + room > mrb->stend) { + if (mrb->stack + room >= mrb->stend) { + mrb_value *oldbase = mrb->stbase; + size = mrb->stend - mrb->stbase; off = mrb->stack - mrb->stbase; @@ -54,9 +70,10 @@ stack_extend(mrb_state *mrb, int room, int keep) size *= 2; else size += room; - mrb->stbase = mrb_realloc(mrb, mrb->stbase, sizeof(mrb_value) * size); + mrb->stbase = (mrb_value *)mrb_realloc(mrb, mrb->stbase, sizeof(mrb_value) * size); mrb->stack = mrb->stbase + off; mrb->stend = mrb->stbase + size; + envadjust(mrb, oldbase, mrb->stbase); } if (room > keep) { memset(mrb->stack+keep, 0, sizeof(mrb_value) * (room-keep)); @@ -75,8 +92,8 @@ uvenv(mrb_state *mrb, int up) { struct REnv *e = mrb->ci->proc->env; - if (!e) return 0; while (up--) { + if (!e) return 0; e = (struct REnv*)e->c; } return e; @@ -104,19 +121,18 @@ uvset(mrb_state *mrb, int up, int idx, mrb_value v) static mrb_callinfo* cipush(mrb_state *mrb) { - size_t nregs = mrb->ci->nregs; int eidx = mrb->ci->eidx; int ridx = mrb->ci->ridx; if (mrb->ci + 1 == mrb->ciend) { size_t size = mrb->ci - mrb->cibase; - mrb->cibase = mrb_realloc(mrb, mrb->cibase, sizeof(mrb_callinfo)*size*2); + mrb->cibase = (mrb_callinfo *)mrb_realloc(mrb, mrb->cibase, sizeof(mrb_callinfo)*size*2); mrb->ci = mrb->cibase + size; mrb->ciend = mrb->cibase + size * 2; } mrb->ci++; - mrb->ci->nregs = nregs; + mrb->ci->nregs = 2; mrb->ci->eidx = eidx; mrb->ci->ridx = ridx; mrb->ci->env = 0; @@ -129,7 +145,7 @@ cipop(mrb_state *mrb) if (mrb->ci->env) { struct REnv *e = mrb->ci->env; int len = (int)e->flags; - mrb_value *p = mrb_malloc(mrb, sizeof(mrb_value)*len); + mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len); e->cioff = -1; memcpy(p, e->stack, sizeof(mrb_value)*len); @@ -145,6 +161,7 @@ ecall(mrb_state *mrb, int i) struct RProc *p; mrb_callinfo *ci; mrb_value *self = mrb->stack; + struct RObject *exc; p = mrb->ensure[i]; ci = cipush(mrb); @@ -156,20 +173,24 @@ ecall(mrb_state *mrb, int i) ci->nregs = p->body.irep->nregs; ci->target_class = p->target_class; mrb->stack = mrb->stack + ci[-1].nregs; + exc = mrb->exc; mrb->exc = 0; mrb_run(mrb, p, *self); + if (!mrb->exc) mrb->exc = exc; } mrb_value -mrb_funcall_with_block(mrb_state *mrb, mrb_value self, const char *name, int argc, mrb_value *argv, mrb_value blk) +mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mrb_value *argv, mrb_value blk) { struct RProc *p; struct RClass *c; - mrb_sym mid = mrb_intern(mrb, name); mrb_sym undef = 0; mrb_callinfo *ci; int n = mrb->ci->nregs; mrb_value val; + if (argc < 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%d)", argc); + } c = mrb_class(mrb, self); p = mrb_method_search_vm(mrb, &c, mid); if (!p) { @@ -200,7 +221,10 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, const char *name, int arg mrb->stack[argc+1] = blk; if (MRB_PROC_CFUNC_P(p)) { + int ai = mrb->arena_idx; val = p->body.func(mrb, self); + mrb->arena_idx = ai; + mrb_gc_protect(mrb, val); mrb->stack = mrb->stbase + ci->stackidx; cipop(mrb); } @@ -211,13 +235,13 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, const char *name, int arg } mrb_value -mrb_funcall_argv(mrb_state *mrb, mrb_value self, const char *name, int argc, mrb_value *argv) +mrb_funcall_argv(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mrb_value *argv) { - return mrb_funcall_with_block(mrb, self, name, argc, argv, mrb_nil_value()); + return mrb_funcall_with_block(mrb, self, mid, argc, argv, mrb_nil_value()); } mrb_value -mrb_yield_with_self(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self) +mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self, struct RClass *c) { struct RProc *p; mrb_sym mid = mrb->ci->mid; @@ -231,7 +255,7 @@ mrb_yield_with_self(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_ ci->proc = p; ci->stackidx = mrb->stack - mrb->stbase; ci->argc = argc; - ci->target_class = p->target_class; + ci->target_class = c; ci->nregs = argc + 2; ci->acc = -1; mrb->stack = mrb->stack + n; @@ -257,23 +281,28 @@ mrb_yield_with_self(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_ mrb_value mrb_yield_argv(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv) { - return mrb_yield_with_self(mrb, b, argc, argv, mrb->stack[0]); + struct RProc *p = mrb_proc_ptr(b); + + return mrb_yield_internal(mrb, b, argc, argv, mrb->stack[0], p->target_class); } mrb_value mrb_yield(mrb_state *mrb, mrb_value b, mrb_value v) { - return mrb_yield_with_self(mrb, b, 1, &v, mrb->stack[0]); + struct RProc *p = mrb_proc_ptr(b); + + return mrb_yield_internal(mrb, b, 1, &v, mrb->stack[0], p->target_class); } static void localjump_error(mrb_state *mrb, const char *kind) { char buf[256]; + int len; mrb_value exc; - snprintf(buf, 256, "unexpected %s", kind); - exc = mrb_exc_new(mrb, E_LOCALJUMP_ERROR, buf, strlen(buf)); + len = snprintf(buf, sizeof(buf), "unexpected %s", kind); + exc = mrb_exc_new(mrb, E_LOCALJUMP_ERROR, buf, len); mrb->exc = (struct RObject*)mrb_object(exc); } @@ -281,18 +310,19 @@ static void argnum_error(mrb_state *mrb, int num) { char buf[256]; + int len; mrb_value exc; if (mrb->ci->mid) { - snprintf(buf, 256, "'%s': wrong number of arguments (%d for %d)", - mrb_sym2name(mrb, mrb->ci->mid), - mrb->ci->argc, num); + len = snprintf(buf, sizeof(buf), "'%s': wrong number of arguments (%d for %d)", + mrb_sym2name(mrb, mrb->ci->mid), + mrb->ci->argc, num); } else { - snprintf(buf, 256, "wrong number of arguments (%d for %d)", - mrb->ci->argc, num); + len = snprintf(buf, sizeof(buf), "wrong number of arguments (%d for %d)", + mrb->ci->argc, num); } - exc = mrb_exc_new(mrb, E_ARGUMENT_ERROR, buf, strlen(buf)); + exc = mrb_exc_new(mrb, E_ARGUMENT_ERROR, buf, len); mrb->exc = (struct RObject*)mrb_object(exc); } @@ -337,20 +367,20 @@ argnum_error(mrb_state *mrb, int num) #ifndef DIRECT_THREADED -#define INIT_DISPACTH for (;;) { i = *pc; switch (GET_OPCODE(i)) { +#define INIT_DISPATCH for (;;) { i = *pc; switch (GET_OPCODE(i)) { #define CASE(op) case op: -#define NEXT mrb->arena_idx = ai; pc++; break +#define NEXT pc++; break #define JUMP break -#define END_DISPACTH }} +#define END_DISPATCH }} #else -#define INIT_DISPACTH JUMP; return mrb_nil_value(); +#define INIT_DISPATCH JUMP; return mrb_nil_value(); #define CASE(op) L_ ## op: -#define NEXT mrb->arena_idx = ai; i=*++pc; goto *optable[GET_OPCODE(i)] +#define NEXT i=*++pc; goto *optable[GET_OPCODE(i)] #define JUMP i=*pc; goto *optable[GET_OPCODE(i)] -#define END_DISPACTH +#define END_DISPATCH #endif @@ -370,8 +400,8 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) mrb_value *regs = NULL; mrb_code i; int ai = mrb->arena_idx; + jmp_buf *prev_jmp = (jmp_buf *)mrb->jmp; jmp_buf c_jmp; - jmp_buf *prev_jmp = NULL; #ifdef DIRECT_THREADED static void *optable[] = { @@ -400,7 +430,6 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) if (setjmp(c_jmp) == 0) { - prev_jmp = mrb->jmp; mrb->jmp = &c_jmp; } else { @@ -413,7 +442,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) mrb->ci->nregs = irep->nregs + 2; regs = mrb->stack; - INIT_DISPACTH { + INIT_DISPATCH { CASE(OP_NOP) { /* do nothing */ NEXT; @@ -453,14 +482,6 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) NEXT; } - CASE(OP_LOADNIL) { - /* A B R(A) := nil */ - int a = GETARG_A(i); - - SET_NIL_VALUE(regs[a]); - NEXT; - } - CASE(OP_LOADSELF) { /* A R(A) := self */ regs[GETARG_A(i)] = mrb->stack[0]; @@ -596,7 +617,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) if (mrb->rsize <= mrb->ci->ridx) { if (mrb->rsize == 0) mrb->rsize = 16; else mrb->rsize *= 2; - mrb->rescue = mrb_realloc(mrb, mrb->rescue, sizeof(mrb_code*) * mrb->rsize); + mrb->rescue = (mrb_code **)mrb_realloc(mrb, mrb->rescue, sizeof(mrb_code*) * mrb->rsize); } mrb->rescue[mrb->ci->ridx++] = pc + GETARG_sBx(i); NEXT; @@ -633,9 +654,10 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) if (mrb->esize <= mrb->ci->eidx) { if (mrb->esize == 0) mrb->esize = 16; else mrb->esize *= 2; - mrb->ensure = mrb_realloc(mrb, mrb->ensure, sizeof(struct RProc*) * mrb->esize); + mrb->ensure = (struct RProc **)mrb_realloc(mrb, mrb->ensure, sizeof(struct RProc*) * mrb->esize); } mrb->ensure[mrb->ci->eidx++] = p; + mrb->arena_idx = ai; NEXT; } @@ -647,6 +669,15 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) for (n=0; n<a; n++) { ecall(mrb, --mrb->ci->eidx); } + mrb->arena_idx = ai; + NEXT; + } + + CASE(OP_LOADNIL) { + /* A B R(A) := nil */ + int a = GETARG_A(i); + + SET_NIL_VALUE(regs[a]); NEXT; } @@ -686,25 +717,29 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) ci->stackidx = mrb->stack - mrb->stbase; ci->argc = n; if (ci->argc == CALL_MAXARGS) ci->argc = -1; - ci->target_class = m->target_class; + ci->target_class = c; ci->pc = pc + 1; + ci->acc = a; /* prepare stack */ mrb->stack += a; if (MRB_PROC_CFUNC_P(m)) { + if (n == CALL_MAXARGS) { + ci->nregs = 3; + } + else { + ci->nregs = n + 2; + } mrb->stack[0] = m->body.func(mrb, recv); mrb->arena_idx = ai; if (mrb->exc) goto L_RAISE; /* pop stackpos */ - mrb->stack = mrb->stbase + ci->stackidx; + regs = mrb->stack = mrb->stbase + ci->stackidx; cipop(mrb); NEXT; } else { - /* fill callinfo */ - ci->acc = a; - /* setup environment for calling method */ proc = mrb->ci->proc = m; irep = m->body.irep; @@ -766,6 +801,10 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) /* setup environment for calling method */ proc = m; irep = m->body.irep; + if (!irep) { + mrb->stack[0] = mrb_nil_value(); + goto L_RETURN; + } pool = irep->pool; syms = irep->syms; ci->nregs = irep->nregs; @@ -793,10 +832,9 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) int n = GETARG_C(i); recv = regs[0]; - c = mrb->ci->proc->target_class->super; + c = mrb->ci->target_class->super; m = mrb_method_search_vm(mrb, &c, mid); if (!m) { - c = mrb->ci->proc->target_class; mid = mrb_intern(mrb, "method_missing"); m = mrb_method_search_vm(mrb, &c, mid); if (n == CALL_MAXARGS) { @@ -828,7 +866,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) mrb->arena_idx = ai; if (mrb->exc) goto L_RAISE; /* pop stackpos */ - mrb->stack = mrb->stbase + ci->stackidx; + regs = mrb->stack = mrb->stbase + ci->stackidx; cipop(mrb); NEXT; } @@ -867,6 +905,13 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) if (lv == 0) stack = regs + 1; else { struct REnv *e = uvenv(mrb, lv-1); + if (!e) { + mrb_value exc; + static const char m[] = "super called outside of method"; + exc = mrb_exc_new(mrb, E_NOMETHOD_ERROR, m, sizeof(m) - 1); + mrb->exc = (struct RObject*)mrb_object(exc); + goto L_RAISE; + } stack = e->stack + 1; } if (r == 0) { @@ -880,21 +925,22 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) if (stack[m1].tt == MRB_TT_ARRAY) { struct RArray *ary = mrb_ary_ptr(stack[m1]); - pp = ary->buf; + pp = ary->ptr; len = ary->len; } regs[a] = mrb_ary_new_capa(mrb, m1+len+m2); rest = mrb_ary_ptr(regs[a]); - memcpy(rest->buf, stack, sizeof(mrb_value)*m1); + memcpy(rest->ptr, stack, sizeof(mrb_value)*m1); if (len > 0) { - memcpy(rest->buf+m1, pp, sizeof(mrb_value)*len); + memcpy(rest->ptr+m1, pp, sizeof(mrb_value)*len); } if (m2 > 0) { - memcpy(rest->buf+m1+len, stack+m1+1, sizeof(mrb_value)*m2); + memcpy(rest->ptr+m1+len, stack+m1+1, sizeof(mrb_value)*m2); } rest->len = m1+len+m2; } regs[a+1] = stack[m1+r+m2]; + mrb->arena_idx = ai; NEXT; } @@ -914,12 +960,13 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) int argc = mrb->ci->argc; mrb_value *argv = regs+1; int len = m1 + o + r + m2; + mrb_value *blk = &argv[argc < 0 ? 1 : argc]; if (argc < 0) { struct RArray *ary = mrb_ary_ptr(regs[1]); - argv = ary->buf; + argv = ary->ptr; argc = ary->len; - regs[len+2] = regs[1]; /* save argary in register */ + mrb_gc_protect(mrb, regs[1]); } if (mrb->ci->proc && MRB_PROC_STRICT_P(mrb->ci->proc)) { if (argc >= 0) { @@ -931,17 +978,19 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) } else if (len > 1 && argc == 1 && argv[0].tt == MRB_TT_ARRAY) { argc = mrb_ary_ptr(argv[0])->len; - argv = mrb_ary_ptr(argv[0])->buf; + argv = mrb_ary_ptr(argv[0])->ptr; } mrb->ci->argc = len; if (argc < len) { - regs[len+1] = argv[argc]; /* move block */ + regs[len+1] = *blk; /* move block */ memmove(®s[1], argv, sizeof(mrb_value)*(argc-m2)); /* m1 + o */ memmove(®s[len-m2+1], &argv[argc-m2], sizeof(mrb_value)*m2); /* m2 */ if (r) { /* r */ regs[m1+o+1] = mrb_ary_new_capa(mrb, 0); } - pc += argc - m1 - m2 + 1; + if (o == 0) pc++; + else + pc += argc - m1 - m2 + 1; } else { memmove(®s[1], argv, sizeof(mrb_value)*(m1+o)); /* m1 + o */ @@ -949,7 +998,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) regs[m1+o+1] = mrb_ary_new_elts(mrb, argc-m1-o-m2, argv+m1+o); } memmove(®s[m1+o+r+1], &argv[argc-m2], sizeof(mrb_value)*m2); - regs[len+1] = argv[argc]; /* move block */ + regs[len+1] = *blk; /* move block */ pc += o + 1; } JUMP; @@ -972,16 +1021,25 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) L_RETURN: if (mrb->exc) { mrb_callinfo *ci; + int eidx; L_RAISE: ci = mrb->ci; + eidx = mrb->ci->eidx; if (ci == mrb->cibase) goto L_STOP; while (ci[0].ridx == ci[-1].ridx) { cipop(mrb); ci = mrb->ci; + if (ci->acc < 0) { + mrb->jmp = prev_jmp; + longjmp(*(jmp_buf*)mrb->jmp, 1); + } + while (eidx > mrb->ci->eidx) { + ecall(mrb, --eidx); + } if (ci == mrb->cibase) { if (ci->ridx == 0) { - mrb->stack = mrb->stbase; + regs = mrb->stack = mrb->stbase; goto L_STOP; } break; @@ -1076,7 +1134,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) /* replace callinfo */ - mrb->ci = ci = &mrb->ci[-1]; + ci = mrb->ci; ci->mid = mid; ci->target_class = m->target_class; ci->argc = n; @@ -1120,6 +1178,10 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) if (lv == 0) stack = regs + 1; else { struct REnv *e = uvenv(mrb, lv-1); + if (!e) { + localjump_error(mrb, "yield"); + goto L_RAISE; + } stack = e->stack + 1; } regs[a] = stack[m1+r+m2]; @@ -1131,12 +1193,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) regs[a].value.v1 = regs[a].value.v1 op regs[a+1].value.v2;\ } while(0) -#define OP_MATH(op) do {\ +#define OP_MATH(op,iop,s) do {\ int a = GETARG_A(i);\ - /* need to check if - is overridden */\ + /* need to check if op is overridden */\ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\ - OP_MATH_BODY(op,i,i); \ + regs[a] = iop(mrb, regs[a], regs[a+1]);\ break;\ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):\ {\ @@ -1151,7 +1213,9 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):\ OP_MATH_BODY(op,f,f);\ break;\ + s\ default:\ + SET_NIL_VALUE(regs[a+2]);\ i = MKOP_ABC(OP_SEND, a, GETARG_B(i), GETARG_C(i));\ goto L_SEND;\ }\ @@ -1159,50 +1223,29 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) CASE(OP_ADD) { /* A B C R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1)*/ - int a = GETARG_A(i); - - switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { - case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): - OP_MATH_BODY(+,i,i); - break; - case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): - { - mrb_int x = regs[a].value.i; - mrb_float y = regs[a+1].value.f; - SET_FLOAT_VALUE(regs[a], (mrb_float)x + y); - } - break; - case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): - OP_MATH_BODY(+,f,i); - break; - case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): - OP_MATH_BODY(+,f,f); - break; + OP_MATH(+,mrb_fixnum_plus, case TYPES2(MRB_TT_STRING,MRB_TT_STRING): regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]); - break; - default: - i = MKOP_ABC(OP_SEND, a, GETARG_B(i), GETARG_C(i)); - goto L_SEND; - } + break;); + mrb->arena_idx = ai; NEXT; } CASE(OP_SUB) { /* A B C R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1)*/ - OP_MATH(-); + OP_MATH(-,mrb_fixnum_minus,;); NEXT; } CASE(OP_MUL) { /* A B C R(A) := R(A)*R(A+1) (Syms[B]=:*,C=1)*/ - OP_MATH(*); + OP_MATH(*,mrb_fixnum_mul,;); NEXT; } CASE(OP_DIV) { /* A B C R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1)*/ - OP_MATH(/); + OP_MATH(/,mrb_num_div,;); NEXT; } @@ -1219,6 +1262,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) regs[a].value.f += GETARG_C(i); break; default: + SET_NIL_VALUE(regs[a+2]); SET_INT_VALUE(regs[a+1], GETARG_C(i)); i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1); goto L_SEND; @@ -1239,6 +1283,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) regs[a].value.f -= GETARG_C(i); break; default: + SET_NIL_VALUE(regs[a+2]); SET_INT_VALUE(regs[a+1], GETARG_C(i)); i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1); goto L_SEND; @@ -1272,6 +1317,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) OP_CMP_BODY(op,f,f);\ break;\ default:\ + SET_NIL_VALUE(regs[a+2]);\ i = MKOP_ABC(OP_SEND, a, GETARG_B(i), GETARG_C(i));\ goto L_SEND;\ }\ @@ -1317,6 +1363,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) mrb_ary_push(mrb, ary, regs[b++]); } regs[GETARG_A(i)] = ary; + mrb->arena_idx = ai; NEXT; } @@ -1324,6 +1371,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) /* A B mrb_ary_concat(R(A),R(B)) */ mrb_ary_concat(mrb, regs[GETARG_A(i)], mrb_ary_splat(mrb, regs[GETARG_B(i)])); + mrb->arena_idx = ai; NEXT; } @@ -1379,15 +1427,15 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) int i; if (len > pre + post) { - regs[a++] = mrb_ary_new_elts(mrb, len - pre - post, ary->buf+pre); + regs[a++] = mrb_ary_new_elts(mrb, len - pre - post, ary->ptr+pre); while (post--) { - regs[a++] = ary->buf[len-post-1]; + regs[a++] = ary->ptr[len-post-1]; } } else { regs[a++] = mrb_ary_new_capa(mrb, 0); for (i=0; i+pre<len; i++) { - regs[a+i] = ary->buf[pre+i]; + regs[a+i] = ary->ptr[pre+i]; } while (i < post) { SET_NIL_VALUE(regs[a+i]); @@ -1395,12 +1443,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) } } } + mrb->arena_idx = ai; NEXT; } CASE(OP_STRING) { /* A Bx R(A) := str_new(Lit(Bx)) */ regs[GETARG_A(i)] = mrb_str_literal(mrb, pool[GETARG_Bx(i)]); + mrb->arena_idx = ai; NEXT; } @@ -1422,6 +1472,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) b+=2; } regs[GETARG_A(i)] = hash; + mrb->arena_idx = ai; NEXT; } @@ -1438,6 +1489,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) } if (c & OP_L_STRICT) p->flags |= MRB_PROC_STRICT; regs[GETARG_A(i)] = mrb_obj_value(p); + mrb->arena_idx = ai; NEXT; } @@ -1461,6 +1513,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) } c = mrb_vm_define_class(mrb, base, super, id); regs[a] = mrb_obj_value(c); + mrb->arena_idx = ai; NEXT; } @@ -1477,6 +1530,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) } c = mrb_vm_define_module(mrb, base, id); regs[a] = mrb_obj_value(c); + mrb->arena_idx = ai; NEXT; } @@ -1494,7 +1548,10 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) ci->mid = 0; ci->stackidx = mrb->stack - mrb->stbase; ci->argc = 0; - ci->target_class = mrb_class_ptr(regs[GETARG_A(i)]); + ci->target_class = mrb_class_ptr(recv); + + /* prepare stack */ + mrb->stack += a; p = mrb_proc_new(mrb, mrb->irep[irep->idx+GETARG_Bx(i)]); p->target_class = ci->target_class; @@ -1510,12 +1567,11 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) NEXT; } else { - /* setup environment for calling method */ irep = p->body.irep; pool = irep->pool; syms = irep->syms; - mrb->stack += a; stack_extend(mrb, irep->nregs, 1); + ci->nregs = irep->nregs; regs = mrb->stack; pc = irep->iseq; JUMP; @@ -1528,17 +1584,25 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) struct RClass *c = mrb_class_ptr(regs[a]); mrb_define_method_vm(mrb, c, syms[GETARG_B(i)], regs[a+1]); + mrb->arena_idx = ai; NEXT; } CASE(OP_SCLASS) { /* A B R(A) := R(B).singleton_class */ regs[GETARG_A(i)] = mrb_singleton_class(mrb, regs[GETARG_B(i)]); + mrb->arena_idx = ai; NEXT; } CASE(OP_TCLASS) { /* A B R(A) := target_class */ + if (!mrb->ci->target_class) { + static const char msg[] = "no target class or module"; + mrb_value exc = mrb_exc_new(mrb, E_TYPE_ERROR, msg, sizeof(msg) - 1); + mrb->exc = (struct RObject*)mrb_object(exc); + goto L_RAISE; + } regs[GETARG_A(i)] = mrb_obj_value(mrb->ci->target_class); NEXT; } @@ -1547,18 +1611,30 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) /* A B C R(A) := range_new(R(B),R(B+1),C) */ int b = GETARG_B(i); regs[GETARG_A(i)] = mrb_range_new(mrb, regs[b], regs[b+1], GETARG_C(i)); + mrb->arena_idx = ai; NEXT; } CASE(OP_DEBUG) { /* A debug print R(A),R(B),R(C) */ +#ifdef ENABLE_STDIO printf("OP_DEBUG %d %d %d\n", GETARG_A(i), GETARG_B(i), GETARG_C(i)); +#else + abort(); +#endif NEXT; } CASE(OP_STOP) { /* stop VM */ L_STOP: + { + int n = mrb->ci->eidx; + + while (n--) { + ecall(mrb, n); + } + } mrb->jmp = prev_jmp; if (mrb->exc) { return mrb_obj_value(mrb->exc); @@ -1569,11 +1645,11 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) CASE(OP_ERR) { /* Bx raise RuntimeError with message Lit(Bx) */ mrb_value msg = pool[GETARG_Bx(i)]; - mrb_value exc = mrb_exc_new3(mrb, mrb->eRuntimeError_class, msg); + mrb_value exc = mrb_exc_new3(mrb, E_RUNTIME_ERROR, msg); mrb->exc = (struct RObject*)mrb_object(exc); goto L_RAISE; } } - END_DISPACTH; + END_DISPATCH; } |
