diff options
46 files changed, 425 insertions, 424 deletions
diff --git a/benchmark/fib39.rb b/benchmark/fib39.rb new file mode 100755 index 000000000..d5565b779 --- /dev/null +++ b/benchmark/fib39.rb @@ -0,0 +1,8 @@ +# Fib 39 + +def fib n + return n if n < 2 + fib(n-2) + fib(n-1) +end + +puts fib(39) diff --git a/include/mruby.h b/include/mruby.h index e204820a3..1336d34d8 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -125,6 +125,7 @@ typedef struct mrb_state { mrb_bool gc_disabled:1; mrb_bool gc_full:1; mrb_bool is_generational_gc_mode:1; + mrb_bool out_of_memory:1; size_t majorgc_old_threshold; struct alloca_header *mems; @@ -281,9 +282,15 @@ void mrb_exc_raise(mrb_state *mrb, mrb_value exc); void mrb_raise(mrb_state *mrb, struct RClass *c, const char *msg); void mrb_raisef(mrb_state *mrb, struct RClass *c, const char *fmt, ...); +void mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...); void mrb_warn(const char *fmt, ...); void mrb_bug(const char *fmt, ...); +/* macros to get typical exception objects + note: + + those E_* macros requires mrb_state* variable named mrb. + + exception objects obtained from those macros are local to mrb +*/ #define E_RUNTIME_ERROR (mrb_class_obj_get(mrb, "RuntimeError")) #define E_TYPE_ERROR (mrb_class_obj_get(mrb, "TypeError")) #define E_ARGUMENT_ERROR (mrb_class_obj_get(mrb, "ArgumentError")) diff --git a/include/mruby/data.h b/include/mruby/data.h index 6ddaebfaa..c6b380f28 100644 --- a/include/mruby/data.h +++ b/include/mruby/data.h @@ -28,19 +28,22 @@ struct RData *mrb_data_object_alloc(mrb_state *mrb, struct RClass* klass, void * #define Data_Wrap_Struct(mrb,klass,type,ptr)\ mrb_data_object_alloc(mrb,klass,ptr,type) -#define Data_Make_Struct(mrb,klass,strct,type,sval,data) (\ - sval = mrb_malloc(mrb, sizeof(strct)),\ - { static const strct zero = { 0 }; *sval = zero; },\ - data = Data_Wrap_Struct(mrb,klass,type,sval)\ -) +#define Data_Make_Struct(mrb,klass,strct,type,sval,data) do { \ + sval = mrb_malloc(mrb, sizeof(strct)); \ + { static const strct zero = { 0 }; *sval = zero; };\ + data = Data_Wrap_Struct(mrb,klass,type,sval);\ +} while (0) #define RDATA(obj) ((struct RData *)((obj).value.p)) #define DATA_PTR(d) (RDATA(d)->data) #define DATA_TYPE(d) (RDATA(d)->type) -void *mrb_get_datatype(mrb_state *mrb, mrb_value, const mrb_data_type*); -void *mrb_check_datatype(mrb_state *mrb, mrb_value, const mrb_data_type*); +void mrb_data_check_type(mrb_state *mrb, mrb_value, const mrb_data_type*); +void *mrb_data_get_ptr(mrb_state *mrb, mrb_value, const mrb_data_type*); +void *mrb_data_check_and_get(mrb_state *mrb, mrb_value, const mrb_data_type*); +#define mrb_get_datatype(mrb,val,type) mrb_data_get_ptr(mrb, val, type) +#define mrb_check_datatype(mrb,val,type) mrb_data_check_and_get(mrb, val, type) #define Data_Get_Struct(mrb,obj,type,sval) do {\ - *(void**)&sval = mrb_check_datatype(mrb, obj, type); \ + *(void**)&sval = mrb_data_check_and_get(mrb, obj, type); \ } while (0) #if defined(__cplusplus) diff --git a/include/mruby/dump.h b/include/mruby/dump.h index 2533a4c93..d1d097cd2 100644 --- a/include/mruby/dump.h +++ b/include/mruby/dump.h @@ -141,9 +141,8 @@ bin_to_uint8(const uint8_t *bin) } /* crc.c */ -uint32_t -calc_crc_16_ccitt(const uint8_t *src, uint32_t nbytes, uint16_t crcwk); - +uint16_t +calc_crc_16_ccitt(const uint8_t *src, size_t nbytes, uint16_t crc); #if defined(__cplusplus) } /* extern "C" { */ #endif diff --git a/include/mruby/numeric.h b/include/mruby/numeric.h index 4bcb43966..aac7b9920 100644 --- a/include/mruby/numeric.h +++ b/include/mruby/numeric.h @@ -15,8 +15,10 @@ extern "C" { #define NEGFIXABLE(f) ((f) >= MRB_INT_MIN) #define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f)) -mrb_value mrb_flt2big(mrb_state *mrb, mrb_float d); -mrb_value mrb_fix2str(mrb_state *mrb, mrb_value x, int base); +mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val); +mrb_value mrb_flo_to_str(mrb_state *mrb, mrb_value flo, int max_digit); + +mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base); mrb_value mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y); mrb_value mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y); diff --git a/include/mruby/value.h b/include/mruby/value.h index 1815f0562..1cc5263ad 100644 --- a/include/mruby/value.h +++ b/include/mruby/value.h @@ -42,7 +42,7 @@ typedef struct mrb_value { mrb_int i; mrb_sym sym; } value; - enum mrb_vtype tt:8; + enum mrb_vtype tt; } mrb_value; #define mrb_type(o) (o).tt diff --git a/include/mruby/variable.h b/include/mruby/variable.h index f699f5dfd..2845e0daa 100644 --- a/include/mruby/variable.h +++ b/include/mruby/variable.h @@ -49,6 +49,7 @@ mrb_bool mrb_iv_defined(mrb_state*, mrb_value, mrb_sym); mrb_value mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym); void mrb_iv_copy(mrb_state *mrb, mrb_value dst, mrb_value src); int mrb_const_defined_at(mrb_state *mrb, struct RClass *klass, mrb_sym id); +mrb_value mrb_mod_constants(mrb_state *mrb, mrb_value mod); mrb_value mrb_f_global_variables(mrb_state *mrb, mrb_value self); mrb_value mrb_gv_get(mrb_state *mrb, mrb_sym sym); void mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value val); diff --git a/mrbgems/mruby-numeric-ext/src/numeric_ext.c b/mrbgems/mruby-numeric-ext/src/numeric_ext.c index 09904c1a9..f193fb531 100644 --- a/mrbgems/mruby-numeric-ext/src/numeric_ext.c +++ b/mrbgems/mruby-numeric-ext/src/numeric_ext.c @@ -10,7 +10,7 @@ mrb_int_chr(mrb_state *mrb, mrb_value x) chr = mrb_fixnum(x); if (chr >= (1 << CHAR_BIT)) { - mrb_raisef(mrb, E_RANGE_ERROR, "%" PRIdMRB_INT " out of char range", chr); + mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", x); } c = (char)chr; diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index 6500b3f84..ba90d664e 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -29,7 +29,7 @@ static mt_state *mrb_mt_get_context(mrb_state *mrb, mrb_value self) mrb_value context; context = mrb_iv_get(mrb, self, mrb_intern(mrb, MT_STATE_KEY)); - t = (mt_state *)mrb_check_datatype(mrb, context, &mt_state_type); + t = (mt_state*)mrb_data_get_ptr(mrb, context, &mt_state_type); if (!t) mrb_raise(mrb, E_RUNTIME_ERROR, "mt_state get from mrb_iv_get failed"); diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index d2ea4c321..fed730c74 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -806,7 +806,7 @@ retry: val = mrb_fixnum_value((mrb_int)mrb_float(val)); goto bin_retry; } - val = mrb_flt2big(mrb, mrb_float(val)); + val = mrb_flo_to_fixnum(mrb, val); if (mrb_fixnum_p(val)) goto bin_retry; break; case MRB_TT_STRING: @@ -843,7 +843,7 @@ retry: dots = 1; } else { - val = mrb_fix2str(mrb, mrb_fixnum_value(v), base); + val = mrb_fixnum_to_str(mrb, mrb_fixnum_value(v), base); } v = mrb_fixnum(mrb_str_to_inum(mrb, val, 10, 0/*Qfalse*/)); } diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index 20ea8b5c5..bd902db7d 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -125,7 +125,7 @@ mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id) return ptr[i]; } } - mrb_raisef(mrb, E_NAME_ERROR, "%S is not struct member", mrb_sym2str(mrb, id)); + mrb_name_error(mrb, id, "%S is not struct member", mrb_sym2str(mrb, id)); return mrb_nil_value(); /* not reached */ } @@ -204,7 +204,7 @@ mrb_struct_set(mrb_state *mrb, mrb_value obj, mrb_value val) return ptr[i] = val; } } - mrb_raisef(mrb, E_NAME_ERROR, "`%S' is not a struct member", + mrb_name_error(mrb, mid, "`%S' is not a struct member", mrb_sym2str(mrb, mid)); return mrb_nil_value(); /* not reached */ } @@ -249,7 +249,7 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k name = mrb_str_to_str(mrb, name); id = mrb_to_id(mrb, name); if (!mrb_is_const_id(id)) { - mrb_raisef(mrb, E_NAME_ERROR, "identifier %S needs to be constant", name); + mrb_name_error(mrb, id, "identifier %S needs to be constant", name); } if (mrb_const_defined_at(mrb, klass, id)) { mrb_warn("redefining constant Struct::%s", mrb_string_value_ptr(mrb, name)); @@ -544,7 +544,7 @@ mrb_struct_aref_id(mrb_state *mrb, mrb_value s, mrb_sym id) return ptr[i]; } } - mrb_raisef(mrb, E_NAME_ERROR, "no member '%S' in struct", mrb_sym2str(mrb, id)); + mrb_name_error(mrb, id, "no member '%S' in struct", mrb_sym2str(mrb, id)); return mrb_nil_value(); /* not reached */ } @@ -619,7 +619,7 @@ mrb_struct_aset_id(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val) return val; } } - mrb_raisef(mrb, E_NAME_ERROR, "no member '%S' in struct", mrb_sym2str(mrb, id)); + mrb_name_error(mrb, id, "no member '%S' in struct", mrb_sym2str(mrb, id)); return val; /* not reach */ } diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index 0ffc0e6f8..200eed0a0 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -298,8 +298,8 @@ mrb_time_eq(mrb_state *mrb, mrb_value self) mrb_bool eq_p; mrb_get_args(mrb, "o", &other); - tm1 = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); - tm2 = (struct mrb_time *)mrb_get_datatype(mrb, other, &mrb_time_type); + tm1 = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); + tm2 = (struct mrb_time*)mrb_data_get_ptr(mrb, other, &mrb_time_type); eq_p = tm1 && tm2 && tm1->sec == tm2->sec && tm1->usec == tm2->usec; return mrb_bool_value(eq_p); @@ -312,8 +312,8 @@ mrb_time_cmp(mrb_state *mrb, mrb_value self) struct mrb_time *tm1, *tm2; mrb_get_args(mrb, "o", &other); - tm1 = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); - tm2 = (struct mrb_time *)mrb_get_datatype(mrb, other, &mrb_time_type); + tm1 = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); + tm2 = (struct mrb_time*)mrb_data_get_ptr(mrb, other, &mrb_time_type); if (!tm1 || !tm2) return mrb_nil_value(); if (tm1->sec > tm2->sec) { return mrb_fixnum_value(1); @@ -338,7 +338,7 @@ mrb_time_plus(mrb_state *mrb, mrb_value self) struct mrb_time *tm; mrb_get_args(mrb, "f", &f); - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(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); } @@ -351,10 +351,10 @@ mrb_time_minus(mrb_state *mrb, mrb_value self) struct mrb_time *tm, *tm2; mrb_get_args(mrb, "o", &other); - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return mrb_nil_value(); - tm2 = (struct mrb_time *)mrb_get_datatype(mrb, other, &mrb_time_type); + tm2 = (struct mrb_time*)mrb_data_get_ptr(mrb, other, &mrb_time_type); if (tm2) { f = (mrb_float)(tm->sec - tm2->sec) + (mrb_float)(tm->usec - tm2->usec) / 1.0e6; @@ -373,7 +373,7 @@ mrb_time_wday(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_wday); } @@ -385,7 +385,7 @@ mrb_time_yday(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = (struct mrb_time *)mrb_check_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_yday + 1); } @@ -397,7 +397,7 @@ mrb_time_year(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_year + 1900); } @@ -409,7 +409,7 @@ mrb_time_zone(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(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(); @@ -426,7 +426,7 @@ mrb_time_asctime(mrb_state *mrb, mrb_value self) char buf[256]; int len; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return mrb_nil_value(); d = &tm->datetime; len = snprintf(buf, sizeof(buf), "%s %s %02d %02d:%02d:%02d %s%d", @@ -444,7 +444,7 @@ mrb_time_day(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_mday); } @@ -457,7 +457,7 @@ mrb_time_dstp(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return mrb_nil_value(); return mrb_bool_value(tm->datetime.tm_isdst); } @@ -470,7 +470,7 @@ 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); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return self; tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm)); *tm2 = *tm; @@ -486,7 +486,7 @@ 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); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return self; tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm)); *tm2 = *tm; @@ -502,7 +502,7 @@ mrb_time_hour(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_hour); } @@ -517,7 +517,7 @@ mrb_time_initialize(mrb_state *mrb, mrb_value self) int n; struct mrb_time *tm; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)DATA_PTR(self); if (tm) { mrb_time_free(mrb, tm); } @@ -563,7 +563,7 @@ mrb_time_localtime(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return self; tm->timezone = MRB_TIMEZONE_LOCAL; mrb_time_update_datetime(tm); @@ -577,7 +577,7 @@ mrb_time_mday(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_mday); } @@ -589,7 +589,7 @@ mrb_time_min(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_min); } @@ -601,7 +601,7 @@ mrb_time_mon(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_mon + 1); } @@ -613,7 +613,7 @@ mrb_time_sec(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->datetime.tm_sec); } @@ -626,7 +626,7 @@ mrb_time_to_f(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(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); } @@ -638,7 +638,7 @@ mrb_time_to_i(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->sec); } @@ -650,7 +650,7 @@ mrb_time_usec(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return mrb_nil_value(); return mrb_fixnum_value(tm->usec); } @@ -662,7 +662,7 @@ mrb_time_utc(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (tm) { tm->timezone = MRB_TIMEZONE_UTC; mrb_time_update_datetime(tm); @@ -676,7 +676,7 @@ static mrb_value mrb_time_utcp(mrb_state *mrb, mrb_value self) { struct mrb_time *tm; - tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); + tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); if (!tm) return mrb_nil_value(); return mrb_bool_value(tm->timezone == MRB_TIMEZONE_UTC); } diff --git a/mrblib/error.rb b/mrblib/error.rb index 32b50da92..9e5a3daeb 100644 --- a/mrblib/error.rb +++ b/mrblib/error.rb @@ -38,6 +38,16 @@ end # ISO 15.2.31 class NameError < StandardError + attr_accessor :name + + def new(message="NameError", name=nil) + initialize(message, name) + end + + def initialize(message=nil, name=nil) + @name = name + super(message) + end end # ISO 15.2.32 diff --git a/mrblib/mrblib.rake b/mrblib/mrblib.rake index 3cd66d0d5..db70842bf 100644 --- a/mrblib/mrblib.rake +++ b/mrblib/mrblib.rake @@ -6,7 +6,7 @@ MRuby.each_target do self.libmruby << objfile("#{current_build_dir}/mrblib") file objfile("#{current_build_dir}/mrblib") => "#{current_build_dir}/mrblib.c" - file "#{current_build_dir}/mrblib.c" => [mrbcfile] + Dir.glob("#{current_dir}/*.rb") do |t| + file "#{current_build_dir}/mrblib.c" => [mrbcfile] + Dir.glob("#{current_dir}/*.rb").sort do |t| mrbc_, *rbfiles = t.prerequisites FileUtils.mkdir_p File.dirname(t.name) open(t.name, 'w') do |f| diff --git a/mrblib/numeric.rb b/mrblib/numeric.rb index 1d701b1fc..daa35c5d6 100644 --- a/mrblib/numeric.rb +++ b/mrblib/numeric.rb @@ -5,6 +5,14 @@ class Integer ## + # Returns the receiver simply. + # + # ISO 15.2.8.3.14 + def ceil + self + end + + ## # Calls the given block once for each Integer # from +self+ downto +num+. # @@ -19,6 +27,14 @@ class Integer end ## + # Returns the receiver simply. + # + # ISO 15.2.8.3.17 + def floor + self + end + + ## # Calls the given block +self+ times. # # ISO 15.2.8.3.22 @@ -32,6 +48,22 @@ class Integer end ## + # Returns the receiver simply. + # + # ISO 15.2.8.3.24 + def round + self + end + + ## + # Returns the receiver simply. + # + # ISO 15.2.8.3.26 + def truncate + self + end + + ## # Calls the given block once for each Integer # from +self+ upto +num+. # diff --git a/src/array.c b/src/array.c index 88f56f6b4..b1f05b450 100644 --- a/src/array.c +++ b/src/array.c @@ -38,11 +38,11 @@ ary_new_capa(mrb_state *mrb, mrb_int capa) mrb_int blen; if (capa > ARY_MAX_SIZE) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "ary size too big"); + mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } blen = capa * sizeof(mrb_value) ; if (blen < capa) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "ary size too big"); + mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } a = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class); diff --git a/src/class.c b/src/class.c index 9dc7b46d6..99dc9cda0 100644 --- a/src/class.c +++ b/src/class.c @@ -979,7 +979,7 @@ mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid) if (RSTRING_LEN(inspect) > 64) { inspect = mrb_any_to_s(mrb, mrb_obj_value(c)); } - mrb_raisef(mrb, E_NAME_ERROR, "undefined method '%S' for class %S", + mrb_name_error(mrb, mid, "undefined method '%S' for class %S", mrb_sym2str(mrb, mid), inspect); } return m; @@ -1748,6 +1748,13 @@ mrb_mod_remove_const(mrb_state *mrb, mrb_value mod) } static mrb_value +mrb_mod_s_constants(mrb_state *mrb, mrb_value mod) +{ + mrb_raise(mrb, E_NOTIMP_ERROR, "Module.constants not implemented"); + return mrb_nil_value(); /* not reached */ +} + +static mrb_value mrb_mod_eqq(mrb_state *mrb, mrb_value mod) { mrb_value obj; @@ -1829,10 +1836,12 @@ mrb_init_class(mrb_state *mrb) 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, "constants", mrb_mod_constants, ARGS_NONE()); /* 15.2.2.4.24 */ mrb_define_method(mrb, mod, "remove_const", mrb_mod_remove_const, ARGS_REQ(1)); /* 15.2.2.4.40 */ mrb_define_method(mrb, mod, "define_method", mod_define_method, ARGS_REQ(1)); mrb_define_method(mrb, mod, "class_variables", mrb_mod_class_variables, ARGS_NONE()); /* 15.2.2.4.19 */ mrb_define_method(mrb, mod, "===", mrb_mod_eqq, ARGS_REQ(1)); + mrb_define_class_method(mrb, mod, "constants", mrb_mod_s_constants, ARGS_ANY()); /* 15.2.2.3.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 e5b1802a1..83d0136ef 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -355,7 +355,7 @@ genop_peep(codegen_scope *s, mrb_code i, int val) static void scope_error(codegen_scope *s) { - exit(1); + exit(EXIT_FAILURE); } static inline void @@ -1868,7 +1868,7 @@ codegen(codegen_scope *s, node *tree, int val) mrb_value str = mrb_str_buf_new(mrb, 4); mrb_str_buf_cat(mrb, str, "$", 1); - mrb_str_buf_append(mrb, str, mrb_fix2str(mrb, fix, 10)); + mrb_str_buf_append(mrb, str, mrb_fixnum_to_str(mrb, fix, 10)); sym = new_sym(s, mrb_intern_str(mrb, str)); genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); push(); diff --git a/src/dump.c b/src/dump.c index 57fa7f612..4714278b0 100644 --- a/src/dump.c +++ b/src/dump.c @@ -80,7 +80,7 @@ get_pool_block_size(mrb_state *mrb, mrb_irep *irep) switch (mrb_type(irep->pool[pool_no])) { case MRB_TT_FIXNUM: - str = mrb_fix2str(mrb, irep->pool[pool_no], 10); + str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); size += RSTRING_LEN(str); break; @@ -123,7 +123,7 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) switch (mrb_type(irep->pool[pool_no])) { case MRB_TT_FIXNUM: - str = mrb_fix2str(mrb, irep->pool[pool_no], 10); + str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); char_ptr = RSTRING_PTR(str); len = RSTRING_LEN(str); break; diff --git a/src/error.c b/src/error.c index 5f1476115..522901ff7 100644 --- a/src/error.c +++ b/src/error.c @@ -306,8 +306,8 @@ mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...) argv[0] = mrb_vformat(mrb, fmt, args); va_end(args); - argv[1] = mrb_symbol_value(id); /* ignore now */ - exc = mrb_class_new_instance(mrb, 1, argv, E_NAME_ERROR); + argv[1] = mrb_symbol_value(id); + exc = mrb_class_new_instance(mrb, 2, argv, E_NAME_ERROR); mrb_exc_raise(mrb, exc); } diff --git a/src/error.h b/src/error.h index 83d0938aa..3726cb4c4 100644 --- a/src/error.h +++ b/src/error.h @@ -13,7 +13,6 @@ 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_make_exception(mrb_state *mrb, int argc, mrb_value *argv); mrb_value mrb_format(mrb_state *mrb, const char *format, ...); -void mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...); void mrb_exc_print(mrb_state *mrb, struct RObject *exc); #endif /* MRUBY_ERROR_H */ @@ -22,28 +22,37 @@ mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const mrb return data; } -void * -mrb_get_datatype(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) +void +mrb_data_check_type(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) { if (mrb_special_const_p(obj) || (mrb_type(obj) != MRB_TT_DATA)) { - return NULL; + mrb_check_type(mrb, obj, MRB_TT_DATA); } if (DATA_TYPE(obj) != type) { - return NULL; + const mrb_data_type *t2 = DATA_TYPE(obj); + + if (t2) { + mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected %S)", + mrb_str_new_cstr(mrb, t2->struct_name), mrb_str_new_cstr(mrb, type->struct_name)); + } } +} + +void * +mrb_data_check_and_get(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) +{ + mrb_data_check_type(mrb, obj, type); return DATA_PTR(obj); } void * -mrb_check_datatype(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) +mrb_data_get_ptr(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) { if (mrb_special_const_p(obj) || (mrb_type(obj) != MRB_TT_DATA)) { - mrb_check_type(mrb, obj, MRB_TT_DATA); + return NULL; } if (DATA_TYPE(obj) != type) { - const char *etype = DATA_TYPE(obj)->struct_name; - mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected %S)", - mrb_str_new_cstr(mrb, etype), mrb_str_new_cstr(mrb, type->struct_name)); + return NULL; } return DATA_PTR(obj); } @@ -157,6 +157,20 @@ mrb_realloc(mrb_state *mrb, void *p, size_t len) mrb_garbage_collect(mrb); p2 = (mrb->allocf)(mrb, p, len, mrb->ud); } + + if (!p2 && len) { + if (mrb->out_of_memory) { + /* mrb_panic(mrb); */ + } + else { + mrb->out_of_memory = 1; + mrb_raise(mrb, E_RUNTIME_ERROR, "Out of memory"); + } + } + else { + mrb->out_of_memory = 0; + } + return p2; } diff --git a/src/kernel.c b/src/kernel.c index f14a94b3a..54c90dfc0 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -108,7 +108,7 @@ mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self) mrb_bool eql_p; mrb_get_args(mrb, "o", &arg); - eql_p = mrb_obj_equal(mrb, self, arg); + eql_p = mrb_equal(mrb, self, arg); return mrb_bool_value(!eql_p); } diff --git a/src/numeric.c b/src/numeric.c index 084243291..aacaed9ee 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -163,13 +163,19 @@ num_abs(mrb_state *mrb, mrb_value num) */ mrb_value -mrb_flo_to_str(mrb_state *mrb, mrb_float n, int max_digit) +mrb_flo_to_str(mrb_state *mrb, mrb_value flo, int max_digit) { mrb_value result; + mrb_float n; if (max_digit > 40) { mrb_raise(mrb, E_RANGE_ERROR, "Too large max_digit."); } + else if (!mrb_float_p(flo)) { + mrb_raise(mrb, E_TYPE_ERROR, "non float value"); + } + + n = mrb_float(flo); if (isnan(n)) { result = mrb_str_new(mrb, "NaN", 3); @@ -270,9 +276,9 @@ static mrb_value flo_to_s(mrb_state *mrb, mrb_value flt) { #ifdef MRB_USE_FLOAT - return mrb_flo_to_str(mrb, mrb_float(flt), 7); + return mrb_flo_to_str(mrb, flt, 7); #else - return mrb_flo_to_str(mrb, mrb_float(flt), 14); + return mrb_flo_to_str(mrb, flt, 14); #endif } @@ -665,42 +671,6 @@ flo_truncate(mrb_state *mrb, mrb_value num) return mrb_fixnum_value((mrb_int)f); } -/* 15.2.8.3.17 */ -/* - * call-seq: - * num.floor -> integer - * - * Returns the largest integer less than or equal to <i>num</i>. - * <code>Numeric</code> implements this by converting <i>anInteger</i> - * to a <code>Float</code> and invoking <code>Float#floor</code>. - * - * 1.floor #=> 1 - * (-1).floor #=> -1 - */ - -static mrb_value -num_floor(mrb_state *mrb, mrb_value num) -{ - return flo_floor(mrb, mrb_Float(mrb, num)); -} - -/* 15.2.8.3.20 */ -/* - * call-seq: - * num.round([ndigits]) -> integer or float - * - * Rounds <i>num</i> to a given precision in decimal digits (default 0 digits). - * Precision may be negative. Returns a floating point number when ndigits - * is more than zero. <code>Numeric</code> implements this by converting itself - * to a <code>Float</code> and invoking <code>Float#round</code>. - */ - -static mrb_value -num_round(mrb_state *mrb, mrb_value num) -{ - return flo_round(mrb, mrb_Float(mrb, num)); -} - /* * Document-class: Integer * @@ -710,17 +680,10 @@ num_round(mrb_state *mrb, mrb_value num) */ -/* 15.2.8.3.14 */ -/* 15.2.8.3.24 */ -/* 15.2.8.3.26 */ /* * call-seq: * int.to_i -> integer * int.to_int -> integer - * int.floor -> integer - * int.ceil -> integer - * int.round -> integer - * int.truncate -> integer * * As <i>int</i> is already an <code>Integer</code>, all these * methods simply return the receiver. @@ -1175,25 +1138,27 @@ fix_to_f(mrb_state *mrb, mrb_value num) * FloatDomainError: Infinity */ /* ------------------------------------------------------------------------*/ -static mrb_int -flt2big(mrb_state *mrb, mrb_float d) +mrb_value +mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x) { mrb_int z; - if (isinf(d)) { - mrb_raise(mrb, E_FLOATDOMAIN_ERROR, d < 0 ? "-Infinity" : "Infinity"); + if (mrb_float_p(x)) { + mrb_raise(mrb, E_TYPE_ERROR, "non float value"); + z = 0; /* not reached. just supress warnings. */ } - if (isnan(d)) { - mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN"); - } - z = (mrb_int)d; - return z; -} + else { + mrb_float d = mrb_float(x); -mrb_value -mrb_flt2big(mrb_state *mrb, mrb_float d) -{ - return mrb_fixnum_value(flt2big(mrb, d)); + if (isinf(d)) { + mrb_raise(mrb, E_FLOATDOMAIN_ERROR, d < 0 ? "-Infinity" : "Infinity"); + } + if (isnan(d)) { + mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN"); + } + z = (mrb_int)d; + } + return mrb_fixnum_value(z); } mrb_value @@ -1276,7 +1241,7 @@ fix_minus(mrb_state *mrb, mrb_value self) mrb_value -mrb_fix2str(mrb_state *mrb, mrb_value x, int base) +mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base) { char buf[sizeof(mrb_int)*CHAR_BIT+1]; char *b = buf + sizeof buf; @@ -1324,7 +1289,7 @@ fix_to_s(mrb_state *mrb, mrb_value self) mrb_int base = 10; mrb_get_args(mrb, "|i", &base); - return mrb_fix2str(mrb, self, base); + return mrb_fixnum_to_str(mrb, self, base); } /* 15.2.9.3.6 */ @@ -1404,6 +1369,9 @@ mrb_init_numeric(mrb_state *mrb) /* Integer Class */ integer = mrb_define_class(mrb, "Integer", numeric); + mrb_undef_class_method(mrb, integer, "new"); + mrb_define_method(mrb, integer, "to_i", int_to_i, ARGS_NONE()); /* 15.2.8.3.24 */ + mrb_define_method(mrb, integer, "to_int", int_to_i, ARGS_NONE()); fixnum = mrb->fixnum_class = mrb_define_class(mrb, "Fixnum", integer); mrb_undef_class_method(mrb, fixnum, "new"); @@ -1419,18 +1387,13 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, fixnum, "^", fix_xor, ARGS_REQ(1)); /* 15.2.8.3.11 */ 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 */ mrb_define_method(mrb, fixnum, "hash", flo_hash, ARGS_NONE()); /* 15.2.8.3.18 */ mrb_define_method(mrb, fixnum, "next", int_succ, ARGS_NONE()); /* 15.2.8.3.19 */ - mrb_define_method(mrb, fixnum, "round", num_round, ARGS_ANY()); /* 15.2.8.3.20 */ 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", fix_to_s, ARGS_NONE()); /* 15.2.8.3.25 */ mrb_define_method(mrb, fixnum, "inspect", fix_to_s, ARGS_NONE()); - 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 */ @@ -1445,9 +1408,10 @@ mrb_init_numeric(mrb_state *mrb) 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_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, "round", flo_round, ARGS_NONE()); /* 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 */ + mrb_define_method(mrb, fl, "to_int", flo_truncate, ARGS_NONE()); mrb_define_method(mrb, fl, "truncate", flo_truncate, ARGS_NONE()); /* 15.2.9.3.15 */ mrb_define_method(mrb, fl, "to_s", flo_to_s, ARGS_NONE()); /* 15.2.9.3.16(x) */ diff --git a/src/object.c b/src/object.c index bd88459ae..23786e859 100644 --- a/src/object.c +++ b/src/object.c @@ -440,6 +440,7 @@ mrb_any_to_s(mrb_state *mrb, mrb_value obj) mrb_str_buf_cat(mrb, str, "#<", 2); mrb_str_cat2(mrb, str, cname); + mrb_str_cat(mrb, str, ":", 1); mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_voidp(obj))); mrb_str_buf_cat(mrb, str, ">", 1); @@ -530,7 +531,7 @@ mrb_convert_to_integer(mrb_state *mrb, mrb_value val, int base) if (FIXABLE(mrb_float(val))) { break; } - return mrb_flt2big(mrb, mrb_float(val)); + return mrb_flo_to_fixnum(mrb, val); case MRB_TT_FIXNUM: if (base != 0) goto arg_error; diff --git a/src/parse.y b/src/parse.y index 1c0170ac9..35bc18cd5 100644 --- a/src/parse.y +++ b/src/parse.y @@ -4726,6 +4726,10 @@ parser_yylex(parser_state *p) p->lstate = EXPR_END; token_column = newtok(p); c = nextc(p); + if (c == -1) { + yyerror(p, "incomplete global variable syntax"); + return 0; + } switch (c) { case '_': /* $_: last read line string */ c = nextc(p); @@ -4812,7 +4816,16 @@ parser_yylex(parser_state *p) tokadd(p, '@'); c = nextc(p); } - if (c != -1 && isdigit(c)) { + if (c == -1) { + if (p->bidx == 1) { + yyerror(p, "incomplete instance variable syntax"); + } + else { + yyerror(p, "incomplete class variable syntax"); + } + return 0; + } + else if (isdigit(c)) { if (p->bidx == 1) { yyerror_i(p, "`@%c' is not allowed as an instance variable name", c); } diff --git a/src/string.c b/src/string.c index 5b6a44abd..329a3da9d 100644 --- a/src/string.c +++ b/src/string.c @@ -622,29 +622,22 @@ mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr) mrb_value str = mrb_str_to_str(mrb, ptr); return RSTRING_PTR(str); } -/* 15.2.10.5.5 */ - -/* - * call-seq: - * str =~ obj -> fixnum or nil - * - * Match---If <i>obj</i> is a <code>Regexp</code>, use it as a pattern to match - * against <i>str</i>,and returns the position the match starts, or - * <code>nil</code> if there is no match. Otherwise, invokes - * <i>obj.=~</i>, passing <i>str</i> as an argument. The default - * <code>=~</code> in <code>Object</code> returns <code>nil</code>. - * - * "cat o' 9 tails" =~ /\d/ #=> 7 - * "cat o' 9 tails" =~ 9 #=> nil - */ static mrb_value -mrb_str_match(mrb_state *mrb, mrb_value self/* x */) +noregexp(mrb_state *mrb, mrb_value self) { - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); + mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp class not implemented"); return mrb_nil_value(); } +static void +regexp_check(mrb_state *mrb, mrb_value obj) +{ + if (!strcmp(mrb_obj_classname(mrb, obj), REGEXP_CLASS)) { + noregexp(mrb, obj); + } +} + static inline mrb_int mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n) { @@ -730,9 +723,7 @@ mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value indx) { mrb_int idx; - if (!strcmp(mrb_obj_classname(mrb, indx), REGEXP_CLASS)) { - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - } + regexp_check(mrb, indx); switch (mrb_type(indx)) { case MRB_TT_FIXNUM: idx = mrb_fixnum(indx); @@ -825,9 +816,7 @@ mrb_str_aref_m(mrb_state *mrb, mrb_value str) argc = mrb_get_args(mrb, "o|o", &a1, &a2); if (argc == 2) { - if (!strcmp(mrb_obj_classname(mrb, a1), REGEXP_CLASS)) { - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - } + regexp_check(mrb, a1); return mrb_str_substr(mrb, str, mrb_fixnum(a1), mrb_fixnum(a2)); } if (argc != 1) { @@ -1193,62 +1182,6 @@ mrb_str_buf_append(mrb_state *mrb, mrb_value str, mrb_value str2) return str; } -/* 15.2.10.5.18 */ -/* - * call-seq: - * str.gsub(pattern, replacement) => new_str - * str.gsub(pattern) {|match| block } => new_str - * - * Returns a copy of <i>str</i> with <em>all</em> occurrences of <i>pattern</i> - * replaced with either <i>replacement</i> or the value of the block. The - * <i>pattern</i> will typically be a <code>Regexp</code>; if it is a - * <code>String</code> then no regular expression metacharacters will be - * interpreted (that is <code>/\d/</code> will match a digit, but - * <code>'\d'</code> will match a backslash followed by a 'd'). - * - * If a string is used as the replacement, special variables from the match - * (such as <code>$&</code> and <code>$1</code>) cannot be substituted into it, - * as substitution into the string occurs before the pattern match - * starts. However, the sequences <code>\1</code>, <code>\2</code>, and so on - * may be used to interpolate successive groups in the match. - * - * In the block form, the current match string is passed in as a parameter, and - * variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>, - * <code>$&</code>, and <code>$'</code> will be set appropriately. The value - * returned by the block will be substituted for the match on each call. - * - * When neither a block nor a second argument is supplied, an - * <code>Enumerator</code> is returned. - * - * "hello".gsub(/[aeiou]/, '*') #=> "h*ll*" - * "hello".gsub(/([aeiou])/, '<\1>') #=> "h<e>ll<o>" - * "hello".gsub(/./) {|s| s.ord.to_s + ' '} #=> "104 101 108 108 111 " - * "hello".gsub(/(?<foo>[aeiou])/, '{\k<foo>}') #=> "h{e}ll{o}" - * 'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*') #=> "h3ll*" - */ -static mrb_value -mrb_str_gsub(mrb_state *mrb, mrb_value self) -{ - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - return mrb_nil_value(); -} - -/* 15.2.10.5.19 */ -/* - * call-seq: - * str.gsub!(pattern, replacement) => str or nil - * str.gsub!(pattern) {|match| block } => str or nil - * - * Performs the substitutions of <code>String#gsub</code> in place, returning - * <i>str</i>, or <code>nil</code> if no substitutions were performed. - */ -static mrb_value -mrb_str_gsub_bang(mrb_state *mrb, mrb_value self) -{ - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - return mrb_nil_value(); -} - mrb_int mrb_str_hash(mrb_state *mrb, mrb_value str) { @@ -1357,9 +1290,7 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str) sub = mrb_nil_value(); } - if (!strcmp(mrb_obj_classname(mrb, sub), REGEXP_CLASS)) { - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - } + regexp_check(mrb, sub); if (pos < 0) { pos += RSTRING_LEN(str); if (pos < 0) { @@ -1555,26 +1486,6 @@ mrb_check_string_type(mrb_state *mrb, mrb_value str) return mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str"); } -/* 15.2.10.5.27 */ -/* - * call-seq: - * str.match(pattern) => matchdata or nil - * - * Converts <i>pattern</i> to a <code>Regexp</code> (if it isn't already one), - * then invokes its <code>match</code> method on <i>str</i>. - * - * 'hello'.match('(.)\1') #=> #<MatchData:0x401b3d30> - * 'hello'.match('(.)\1')[0] #=> "ll" - * 'hello'.match(/(.)\1/)[0] #=> "ll" - * 'hello'.match('xx') #=> nil - */ -static mrb_value -mrb_str_match_m(mrb_state *mrb, mrb_value self) -{ - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - return mrb_nil_value(); -} - /* ---------------------------------- */ /* 15.2.10.5.29 */ /* @@ -1715,9 +1626,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str) if (pos < 0) { pos += len; if (pos < 0) { - if (!strcmp(mrb_obj_classname(mrb, sub), REGEXP_CLASS)) { - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - } + regexp_check(mrb, sub); return mrb_nil_value(); } } @@ -1730,9 +1639,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str) else sub = mrb_nil_value(); } - if (!strcmp(mrb_obj_classname(mrb, sub), REGEXP_CLASS)) { - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - } + regexp_check(mrb, sub); switch (mrb_type(sub)) { case MRB_TT_FIXNUM: { @@ -1765,44 +1672,6 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str) return mrb_nil_value(); } -/* 15.2.10.5.32 */ -/* - * call-seq: - * str.scan(pattern) => array - * str.scan(pattern) {|match, ...| block } => str - * - * Both forms iterate through <i>str</i>, matching the pattern (which may be a - * <code>Regexp</code> or a <code>String</code>). For each match, a result is - * generated and either added to the result array or passed to the block. If - * the pattern contains no groups, each individual result consists of the - * matched string, <code>$&</code>. If the pattern contains groups, each - * individual result is itself an array containing one entry per group. - * - * a = "cruel world" - * a.scan(/\w+/) #=> ["cruel", "world"] - * a.scan(/.../) #=> ["cru", "el ", "wor"] - * a.scan(/(...)/) #=> [["cru"], ["el "], ["wor"]] - * a.scan(/(..)(..)/) #=> [["cr", "ue"], ["l ", "wo"]] - * - * And the block form: - * - * a.scan(/\w+/) {|w| print "<<#{w}>> " } - * print "\n" - * a.scan(/(.)(.)/) {|x,y| print y, x } - * print "\n" - * - * <em>produces:</em> - * - * <<cruel>> <<world>> - * rceu lowlr - */ -static mrb_value -mrb_str_scan(mrb_state *mrb, mrb_value str) -{ - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - return mrb_nil_value(); -} - static const char isspacetable[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1901,7 +1770,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) } } else { - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); + noregexp(mrb, str); } } @@ -1970,7 +1839,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) beg = ptr - temp; } else { - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); + noregexp(mrb, str); } if (RSTRING_LEN(str) > 0 && (lim_p || RSTRING_LEN(str) > beg || lim < 0)) { if (RSTRING_LEN(str) == beg) { @@ -1991,70 +1860,6 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) return result; } - -/* 15.2.10.5.37 */ -/* - * call-seq: - * str.sub!(pattern, replacement) => str or nil - * str.sub!(pattern) {|match| block } => str or nil - * - * Performs the substitutions of <code>String#sub</code> in place, - * returning <i>str</i>, or <code>nil</code> if no substitutions were - * performed. - */ -static mrb_value -mrb_str_sub_bang(mrb_state *mrb, mrb_value str) -{ - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - return mrb_nil_value(); -} - -/* 15.2.10.5.36 */ - -/* - * call-seq: - * str.sub(pattern, replacement) -> new_str - * str.sub(pattern, hash) -> new_str - * str.sub(pattern) {|match| block } -> new_str - * - * Returns a copy of <i>str</i> with the <em>first</em> occurrence of - * <i>pattern</i> substituted for the second argument. The <i>pattern</i> is - * typically a <code>Regexp</code>; if given as a <code>String</code>, any - * regular expression metacharacters it contains will be interpreted - * literally, e.g. <code>'\\\d'</code> will match a backlash followed by 'd', - * instead of a digit. - * - * If <i>replacement</i> is a <code>String</code> it will be substituted for - * the matched text. It may contain back-references to the pattern's capture - * groups of the form <code>\\\d</code>, where <i>d</i> is a group number, or - * <code>\\\k<n></code>, where <i>n</i> is a group name. If it is a - * double-quoted string, both back-references must be preceded by an - * additional backslash. However, within <i>replacement</i> the special match - * variables, such as <code>&$</code>, will not refer to the current match. - * - * If the second argument is a <code>Hash</code>, and the matched text is one - * of its keys, the corresponding value is the replacement string. - * - * In the block form, the current match string is passed in as a parameter, - * and variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>, - * <code>$&</code>, and <code>$'</code> will be set appropriately. The value - * returned by the block will be substituted for the match on each call. - * - * "hello".sub(/[aeiou]/, '*') #=> "h*llo" - * "hello".sub(/([aeiou])/, '<\1>') #=> "h<e>llo" - * "hello".sub(/./) {|s| s.ord.to_s + ' ' } #=> "104 ello" - * "hello".sub(/(?<foo>[aeiou])/, '*\k<foo>*') #=> "h*e*llo" - * 'Is SHELL your preferred shell?'.sub(/[[:upper:]]{2,}/, ENV) - * #=> "Is /bin/bash your preferred shell?" - */ - -static mrb_value -mrb_str_sub(mrb_state *mrb, mrb_value self) -{ - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - return mrb_nil_value(); -} - mrb_value mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck) { @@ -2537,7 +2342,7 @@ mrb_str_dump(mrb_state *mrb, mrb_value str) const char *ptr; int len; chr = mrb_fixnum_value(c & 0xff); - octstr = mrb_fix2str(mrb, chr, 8); + octstr = mrb_fixnum_to_str(mrb, chr, 8); ptr = mrb_str_body(octstr, &len); memcpy(q, "\\000", 4); memcpy(q + 4 - len, ptr, len); @@ -2629,7 +2434,7 @@ mrb_str_inspect(mrb_state *mrb, mrb_value str) const char *ptr; int len; chr = mrb_fixnum_value(c & 0xff); - octstr = mrb_fix2str(mrb, chr, 8); + octstr = mrb_fixnum_to_str(mrb, chr, 8); ptr = mrb_str_body(octstr, &len); memcpy(buf, "\\000", 4); memcpy(buf + 4 - len, ptr, len); @@ -2682,7 +2487,7 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "*", mrb_str_times, ARGS_REQ(1)); /* 15.2.10.5.1 */ mrb_define_method(mrb, s, "<=>", mrb_str_cmp_m, ARGS_REQ(1)); /* 15.2.10.5.3 */ mrb_define_method(mrb, s, "==", mrb_str_equal_m, ARGS_REQ(1)); /* 15.2.10.5.4 */ - mrb_define_method(mrb, s, "=~", mrb_str_match, ARGS_REQ(1)); /* 15.2.10.5.5 */ + mrb_define_method(mrb, s, "=~", noregexp, ARGS_REQ(1)); /* 15.2.10.5.5 */ mrb_define_method(mrb, s, "[]", mrb_str_aref_m, ARGS_ANY()); /* 15.2.10.5.6 */ mrb_define_method(mrb, s, "capitalize", mrb_str_capitalize, ARGS_NONE()); /* 15.2.10.5.7 */ mrb_define_method(mrb, s, "capitalize!", mrb_str_capitalize_bang, ARGS_REQ(1)); /* 15.2.10.5.8 */ @@ -2696,8 +2501,8 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "eql?", mrb_str_eql, ARGS_REQ(1)); /* 15.2.10.5.17 */ // NOTE: Regexp not implemented - 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 */ + mrb_define_method(mrb, s, "gsub", noregexp, ARGS_REQ(1)); /* 15.2.10.5.18 */ + mrb_define_method(mrb, s, "gsub!", noregexp, ARGS_REQ(1)); /* 15.2.10.5.19 */ mrb_define_method(mrb, s, "hash", mrb_str_hash_m, ARGS_REQ(1)); /* 15.2.10.5.20 */ mrb_define_method(mrb, s, "include?", mrb_str_include, ARGS_REQ(1)); /* 15.2.10.5.21 */ @@ -2705,24 +2510,16 @@ 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 */ - - // NOTE: Regexp not implemented - mrb_define_method(mrb, s, "match", mrb_str_match_m, ARGS_REQ(1)); /* 15.2.10.5.27 */ - + mrb_define_method(mrb, s, "match", noregexp, ARGS_REQ(1)); /* 15.2.10.5.27 */ 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 */ - - // NOTE: Regexp not implemented - mrb_define_method(mrb, s, "scan", mrb_str_scan, ARGS_REQ(1)); /* 15.2.10.5.32 */ - + mrb_define_method(mrb, s, "scan", noregexp, ARGS_REQ(1)); /* 15.2.10.5.32 */ 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 */ - - // NOTE: Regexp not implemented - 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 */ + mrb_define_method(mrb, s, "sub", noregexp, ARGS_REQ(1)); /* 15.2.10.5.36 */ + mrb_define_method(mrb, s, "sub!", noregexp, ARGS_REQ(1)); /* 15.2.10.5.37 */ mrb_define_method(mrb, s, "to_i", mrb_str_to_i, ARGS_ANY()); /* 15.2.10.5.38 */ mrb_define_method(mrb, s, "to_f", mrb_str_to_f, ARGS_NONE()); /* 15.2.10.5.39 */ diff --git a/src/variable.c b/src/variable.c index 941aaf83e..2057b69ef 100644 --- a/src/variable.c +++ b/src/variable.c @@ -11,6 +11,7 @@ #include "mruby/string.h" #include "mruby/variable.h" #include "error.h" +#include <ctype.h> typedef int (iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*); @@ -690,7 +691,7 @@ mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym) } c = c->super; } - mrb_raisef(mrb, E_NAME_ERROR, "uninitialized class variable %S in %S", + mrb_name_error(mrb, sym, "uninitialized class variable %S in %S", mrb_sym2str(mrb, sym), cls); /* not reached */ return mrb_nil_value(); @@ -846,7 +847,7 @@ L_RETRY: } c = c->super; } - mrb_raisef(mrb, E_NAME_ERROR, "uninitialized constant %S", + mrb_name_error(mrb, sym, "uninitialized constant %S", mrb_sym2str(mrb, sym)); /* not reached */ return mrb_nil_value(); @@ -919,6 +920,45 @@ mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val) mrb_define_const(mrb, mrb->object_class, name, val); } +static int +const_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) +{ + mrb_value ary; + const char* s; + size_t len; + + ary = *(mrb_value*)p; + s = mrb_sym2name_len(mrb, sym, &len); + if (len > 1 && ISUPPER(s[0])) { + mrb_ary_push(mrb, ary, mrb_symbol_value(sym)); + } + return 0; +} + +/* 15.2.2.4.24 */ +/* + * call-seq: + * mod.constants -> array + * + * Returns an array of all names of contants defined in the receiver. + */ +mrb_value +mrb_mod_constants(mrb_state *mrb, mrb_value mod) +{ + mrb_value ary; + struct RClass *c = mrb_class_ptr(mod); + + ary = mrb_ary_new(mrb); + while (c) { + if (c->iv) { + iv_foreach(mrb, c->iv, const_i, &ary); + } + c = c->super; + if (c == mrb->object_class) break; + } + return ary; +} + mrb_value mrb_gv_get(mrb_state *mrb, mrb_sym sym) { @@ -55,6 +55,9 @@ The value below allows about 60000 recursive calls in the simplest case. */ # define DEBUG(x) #endif +#define TO_STR(x) TO_STR_(x) +#define TO_STR_(x) #x + static inline void stack_clear(mrb_value *from, size_t count) { @@ -133,9 +136,9 @@ stack_extend(mrb_state *mrb, int room, int keep) mrb->stend = mrb->stbase + size; envadjust(mrb, oldbase, mrb->stbase); /* Raise an exception if the new stack size will be too large, - to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raisef has stack space to work with. */ + to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raise has stack space to work with. */ if (size > MRB_STACK_MAX) { - mrb_raisef(mrb, E_RUNTIME_ERROR, "stack level too deep. (limit=%S)", mrb_fixnum_value(MRB_STACK_MAX)); + mrb_raise(mrb, E_RUNTIME_ERROR, "stack level too deep. (limit=" TO_STR(MRB_STACK_MAX) ")"); } } @@ -275,7 +278,7 @@ mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...) int i; if (argc > MRB_FUNCALL_ARGC_MAX) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%S)", mrb_fixnum_value(MRB_FUNCALL_ARGC_MAX)); + mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=" TO_STR(MRB_FUNCALL_ARGC_MAX) ")"); } va_start(ap, argc); @@ -302,7 +305,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr cipop(mrb); } mrb->jmp = 0; - val = mrb_nil_value(); + val = mrb_obj_value(mrb->exc); } else { mrb->jmp = &c_jmp; @@ -343,7 +346,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr ci->nregs = argc + 2; } else { - ci->nregs = p->body.irep->nregs + 2; + ci->nregs = p->body.irep->nregs + n; } ci->acc = -1; mrb->stack = mrb->stack + n; @@ -1207,6 +1210,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) ci = mrb->ci; if (ci[1].acc < 0 && prev_jmp) { mrb->jmp = prev_jmp; + mrb->stack = mrb->stbase + ci[1].stackidx; longjmp(*(jmp_buf*)mrb->jmp, 1); } while (eidx > mrb->ci->eidx) { diff --git a/tasks/mrbgem_spec.rake b/tasks/mrbgem_spec.rake index 4b2ce6499..564836630 100644 --- a/tasks/mrbgem_spec.rake +++ b/tasks/mrbgem_spec.rake @@ -124,7 +124,7 @@ module MRuby f.puts %Q[ mrb_load_irep(mrb, gem_mrblib_irep_#{funcname});] f.puts %Q[ if (mrb->exc) {] f.puts %Q[ mrb_p(mrb, mrb_obj_value(mrb->exc));] - f.puts %Q[ exit(0);] + f.puts %Q[ exit(EXIT_FAILURE);] f.puts %Q[ }] end f.puts %Q[ mrb_gc_arena_restore(mrb, ai);] diff --git a/tasks/mrbgems_test.rake b/tasks/mrbgems_test.rake index 7b78c9878..48acdcf53 100644 --- a/tasks/mrbgems_test.rake +++ b/tasks/mrbgems_test.rake @@ -34,7 +34,7 @@ MRuby.each_target do f.puts %Q[ mrb_load_irep(mrb2, gem_test_irep_#{g.funcname}_preload);] f.puts %Q[ if (mrb2->exc) {] f.puts %Q[ mrb_p(mrb2, mrb_obj_value(mrb2->exc));] - f.puts %Q[ exit(0);] + f.puts %Q[ exit(EXIT_FAILURE);] f.puts %Q[ }] f.puts %Q[ mrb_const_set(mrb2, mrb_obj_value(mrb2->object_class), mrb_intern(mrb2, "GEMNAME"), mrb_str_new(mrb2, "#{g.name}", #{g.name.length}));] @@ -53,7 +53,7 @@ MRuby.each_target do f.puts %Q[ mrb_load_irep(mrb2, gem_test_irep_#{g.funcname}_#{i});] f.puts %Q[ if (mrb2->exc) {] f.puts %Q[ mrb_p(mrb2, mrb_obj_value(mrb2->exc));] - f.puts %Q[ exit(0);] + f.puts %Q[ exit(EXIT_FAILURE);] f.puts %Q[ }] f.puts %Q[ ] diff --git a/tasks/mruby_build_commands.rake b/tasks/mruby_build_commands.rake index 0effa648b..b647ccf98 100644 --- a/tasks/mruby_build_commands.rake +++ b/tasks/mruby_build_commands.rake @@ -249,11 +249,9 @@ module MRuby def run(out, infiles, funcname) @command ||= @build.mrbcfile - commandline = "#{filename @command} #{@compile_options % {:funcname => funcname}}" - IO.popen(commandline, 'r+') do |io| + IO.popen("#{filename @command} #{@compile_options % {:funcname => funcname}}", 'r+') do |io| [infiles].flatten.each do |f| _pp "MRBC", f.relative_path, nil, :indent => 2 - log "#{commandline} ## #{f}" io.write IO.read(f) end io.close_write diff --git a/tasks/ruby_ext.rake b/tasks/ruby_ext.rake index a0fbe7b72..0a0883e02 100644 --- a/tasks/ruby_ext.rake +++ b/tasks/ruby_ext.rake @@ -45,7 +45,7 @@ end $pp_show = true if $verbose.nil? - unless Rake.verbose.nil? + if Rake.respond_to?(:verbose) && !Rake.verbose.nil? if Rake.verbose.class == TrueClass # verbose message logging $pp_show = false diff --git a/test/init_mrbtest.c b/test/init_mrbtest.c index 5c80c6e91..3b8f9129e 100644 --- a/test/init_mrbtest.c +++ b/test/init_mrbtest.c @@ -18,7 +18,7 @@ mrb_init_mrbtest(mrb_state *mrb) #endif if (mrb->exc) { mrb_p(mrb, mrb_obj_value(mrb->exc)); - exit(0); + exit(EXIT_FAILURE); } } diff --git a/test/t/array.rb b/test/t/array.rb index 90fa85c7f..47259c268 100644 --- a/test/t/array.rb +++ b/test/t/array.rb @@ -272,7 +272,7 @@ assert('Array#unshift', '15.2.12.5.30') do a == [1,2,3] and b == [1,2,3] and c == [0,1,2,3] and d == [0,1,2,3] end -assert('Array#to_s', '15.2.12.5.31') do +assert('Array#to_s', '15.2.12.5.31 / 15.2.12.5.32') do a = [2, 3, 4, 5] r1 = a.to_s r2 = a.inspect @@ -288,6 +288,20 @@ assert('Array#==', '15.2.12.5.33') do r1 == false and r2 == true and r3 == false end +assert('Array#eql?', '15.2.12.5.34') do + a1 = [ 1, 2, 3 ] + a2 = [ 1, 2, 3 ] + a3 = [ 1.0, 2.0, 3.0 ] + + (a1.eql? a2) and (not a1.eql? a3) +end + +assert('Array#hash', '15.2.12.5.35') do + a = [ 1, 2, 3 ] + + a.hash.is_a? Integer +end + assert('Array#<=>', '15.2.12.5.36') do r1 = [ "a", "a", "c" ] <=> [ "a", "b", "c" ] #=> -1 r2 = [ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ] #=> +1 diff --git a/test/t/class.rb b/test/t/class.rb index 1c50853dc..72214a2fc 100644 --- a/test/t/class.rb +++ b/test/t/class.rb @@ -9,6 +9,26 @@ assert('Class superclass', '15.2.3.2') do Class.superclass == Module end +# Class#initialize '15.2.3.3.1' is tested in Class#new + +assert('Class#initialize_copy', '15.2.3.3.2') do + class TestClass + attr_accessor :n + def initialize(n) + @n = n + end + def initialize_copy(obj) + @n = n + end + end + + c1 = TestClass.new('Foo') + c2 = c1.dup + c3 = TestClass.new('Bar') + + c1.n == c2.n and c1.n != c3.n +end + assert('Class#new', '15.2.3.3.3') do # at the moment no exception on singleton class #e1 = nil diff --git a/test/t/comparable.rb b/test/t/comparable.rb index f3c03a9b5..c95134246 100644 --- a/test/t/comparable.rb +++ b/test/t/comparable.rb @@ -1,5 +1,5 @@ -assert('<', '15.3.3.2.1') do +assert('Comparable#<', '15.3.3.2.1') do class Foo include Comparable def <=>(x) @@ -10,7 +10,7 @@ assert('<', '15.3.3.2.1') do (Foo.new < Foo.new) == false end -assert('<=', '15.3.3.2.2') do +assert('Comparable#<=', '15.3.3.2.2') do class Foo include Comparable def <=>(x) @@ -21,7 +21,7 @@ assert('<=', '15.3.3.2.2') do (Foo.new <= Foo.new) == true end -assert('==', '15.3.3.2.3') do +assert('Comparable#==', '15.3.3.2.3') do class Foo include Comparable def <=>(x) @@ -32,7 +32,7 @@ assert('==', '15.3.3.2.3') do (Foo.new == Foo.new) == true end -assert('>', '15.3.3.2.4') do +assert('Comparable#>', '15.3.3.2.4') do class Foo include Comparable def <=>(x) @@ -43,7 +43,7 @@ assert('>', '15.3.3.2.4') do (Foo.new > Foo.new) == false end -assert('>=', '15.3.3.2.5') do +assert('Comparable#>=', '15.3.3.2.5') do class Foo include Comparable def <=>(x) diff --git a/test/t/hash.rb b/test/t/hash.rb index 04a9a1c24..5ba476e40 100644 --- a/test/t/hash.rb +++ b/test/t/hash.rb @@ -138,7 +138,18 @@ assert('Hash#include?', '15.2.13.4.15') do a.include?('abc_key') and not b.include?('cba') end -assert('Hash#initialize copy', '15.2.13.4.17') do +assert('Hash#initialize', '15.2.13.4.16') do + # Testing initialize by new. + h = Hash.new + h2 = Hash.new(:not_found) + + h.is_a? Hash and + h == { } and + h["hello"] == nil and + h2["hello"] == :not_found +end + +assert('Hash#initialize_copy', '15.2.13.4.17') do a = { 'abc_key' => 'abc_value' } b = Hash.new.initialize_copy(a) diff --git a/test/t/kernel.rb b/test/t/kernel.rb index 5caa3d7ac..835834359 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -23,6 +23,8 @@ assert('Kernel.block_given?', '15.3.1.2.2') do ((bg_try do "block" end) == "block") end +# Kernel.eval is provided by the mruby-gem mrbgem. '15.3.1.2.3' + assert('Kernel.global_variables', '15.3.1.2.4') do Kernel.global_variables.class == Array end @@ -189,6 +191,8 @@ assert('Kernel#dup', '15.3.1.3.9') do c.respond_to?(:test) == false end +# Kernel#eval is provided by mruby-eval mrbgem '15.3.1.3.12' + assert('Kernel#extend', '15.3.1.3.13') do class Test4ExtendClass end @@ -287,6 +291,10 @@ assert('Kernel#object_id', '15.3.1.3.33') do object_id.class == Fixnum end +# Kernel#p is defined in mruby-print mrbgem. '15.3.1.3.34' + +# Kernel#print is defined in mruby-print mrbgem. '15.3.1.3.35' + assert('Kernel#private_methods', '15.3.1.3.36') do private_methods.class == Array end @@ -299,6 +307,8 @@ assert('Kernel#public_methods', '15.3.1.3.38') do public_methods.class == Array end +# Kernel#puts is defined in mruby-print mrbgem. '15.3.1.3.39' + assert('Kernel#raise', '15.3.1.3.40') do e_list = [] @@ -349,3 +359,13 @@ end assert('Kernel#to_s', '15.3.1.3.46') do to_s.class == String end + +assert('Kernel#!=') do + str1 = "hello" + str2 = str1 + str3 = "world" + + (str1[1] != 'e') == false and + (str1 != str3) == true and + (str2 != str1) == false +end diff --git a/test/t/module.rb b/test/t/module.rb index 6c1c1acda..1ff9d3aea 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -129,6 +129,21 @@ assert('Module#const_get', '15.2.2.4.23') do Test4ConstSet.const_get(:Const4Test4ConstSet) == 23 end +assert('Module.constants', '15.2.2.4.24') do + $n = [] + module TestA + Const = 1 + end + class TestB + include TestA + Const2 = 1 + $n = constants.sort + end + + TestA.constants == [ :Const ] and + $n == [ :Const, :Const2 ] +end + assert('Module#include', '15.2.2.4.27') do module Test4Include Const4Include = 42 diff --git a/test/t/nameerror.rb b/test/t/nameerror.rb index 8e57ac18b..30da74a15 100644 --- a/test/t/nameerror.rb +++ b/test/t/nameerror.rb @@ -9,10 +9,24 @@ assert('NameError superclass', '15.2.31.2') do NameError.superclass == StandardError end -# TODO 15.2.31.2.1 NameError#name +assert('NameError#name', '15.2.31.2.1') do + + # This check is not duplicate with 15.2.31.2.2 check. + # Because the NameError in this test is generated in + # C API. + class TestDummy + alias foo bar + rescue NameError => e + $test_dummy_result = e.name + end + + $test_dummy_result == :bar +end assert('NameError#initialize', '15.2.31.2.2') do - e = NameError.new.initialize('a') + e = NameError.new('a', :foo) - e.class == NameError and e.message == 'a' + e.class == NameError and + e.message == 'a' and + e.name == :foo end diff --git a/test/t/string.rb b/test/t/string.rb index ef6b6fae0..5f5f664cf 100644 --- a/test/t/string.rb +++ b/test/t/string.rb @@ -32,7 +32,7 @@ assert('String#==', '15.2.10.5.4') do 'abc' == 'abc' and not 'abc' == 'cba' end -# TODO: SEGFAULT ATM assert('String#=~', '15.2.10.5.5') +# 'String#=~', '15.2.10.5.5' will be tested in mrbgems. assert('String#[]', '15.2.10.5.6') do # length of args is 1 @@ -49,7 +49,7 @@ assert('String#[]', '15.2.10.5.6') do e1 = 'abc'[1, 2] # args is RegExp - # TODO SEGFAULT ATM + # It will be tested in mrbgems. # args is String a3 = 'abc'['bc'] @@ -251,7 +251,7 @@ assert('String#length', '15.2.10.5.26') do 'abc'.length == 3 end -# TODO Broken ATM assert('String#match', '15.2.10.5.27') do +# 'String#match', '15.2.10.5.27' will be tested in mrbgems. assert('String#replace', '15.2.10.5.28') do a = '' @@ -279,7 +279,7 @@ assert('String#rindex', '15.2.10.5.31') do 'abcabc'.rindex('a', 1) == 0 and 'abcabc'.rindex('a', 4) == 3 end -# TODO Broken ATM assert('String#scan', '15.2.10.5.32') do +# 'String#scan', '15.2.10.5.32' will be tested in mrbgems. assert('String#size', '15.2.10.5.33') do 'abc'.size == 3 @@ -303,7 +303,7 @@ assert('String#slice', '15.2.10.5.34') do e11 = e1.slice(0) # args is RegExp - # TODO SEGFAULT ATM + # It will be tested in mrbgems. # args is String a3 = 'abc'.slice('bc') diff --git a/tools/mirb/mirb.c b/tools/mirb/mirb.c index 3f96696a7..ed3b105b6 100644 --- a/tools/mirb/mirb.c +++ b/tools/mirb/mirb.c @@ -172,19 +172,17 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args) case '-': if (strcmp((*argv) + 2, "version") == 0) { mrb_show_version(mrb); - exit(0); + exit(EXIT_SUCCESS); } else if (strcmp((*argv) + 2, "copyright") == 0) { mrb_show_copyright(mrb); - exit(0); + exit(EXIT_SUCCESS); } - else return -3; default: - return -4; + return EXIT_FAILURE; } } - - return 0; + return EXIT_SUCCESS; } static void @@ -240,7 +238,7 @@ main(int argc, char **argv) } n = parse_args(mrb, argc, argv, &args); - if (n < 0) { + if (n == EXIT_FAILURE) { cleanup(mrb, &args); usage(argv[0]); return n; diff --git a/tools/mrbc/mrbc.c b/tools/mrbc/mrbc.c index b8c1cf286..8698086ff 100644 --- a/tools/mrbc/mrbc.c +++ b/tools/mrbc/mrbc.c @@ -69,7 +69,7 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args) char *infile = NULL; char *outfile = NULL; char **origargv = argv; - int result = 0; + int result = EXIT_SUCCESS; static const struct _args args_zero = { 0 }; *args = args_zero; @@ -88,7 +88,7 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args) if (outfile) { printf("%s: An output file is already specified. (%s)\n", *origargv, outfile); - result = -5; + result = EXIT_FAILURE; goto exit; } outfile = get_outfilename((*argv) + 2, ""); @@ -98,7 +98,7 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args) args->initname = (*argv) + 2; if (*args->initname == '\0') { printf("%s: Function name is not specified.\n", *origargv); - result = -2; + result = EXIT_FAILURE; goto exit; } break; @@ -115,7 +115,7 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args) case '-': if (strcmp((*argv) + 2, "version") == 0) { mrb_show_version(mrb); - exit(0); + exit(EXIT_SUCCESS); } else if (strcmp((*argv) + 2, "verbose") == 0) { args->verbose = 1; @@ -123,9 +123,9 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args) } else if (strcmp((*argv) + 2, "copyright") == 0) { mrb_show_copyright(mrb); - exit(0); + exit(EXIT_SUCCESS); } - result = -3; + result = EXIT_FAILURE; goto exit; default: break; @@ -141,7 +141,7 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args) } if (infile == NULL) { - result = -4; + result = EXIT_FAILURE; goto exit; } if (!args->check_syntax) { @@ -158,7 +158,7 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args) } else if ((args->wfp = fopen(outfile, "wb")) == NULL) { printf("%s: Cannot open output file. (%s)\n", *origargv, outfile); - result = -1; + result = EXIT_FAILURE; goto exit; } } @@ -192,7 +192,7 @@ main(int argc, char **argv) } n = parse_args(mrb, argc, argv, &args); - if (n < 0 || args.rfp == NULL) { + if (n == EXIT_FAILURE || args.rfp == NULL) { cleanup(mrb, &args); usage(argv[0]); return n; diff --git a/tools/mruby/mruby.c b/tools/mruby/mruby.c index 47727e67b..c52eb5e7b 100644 --- a/tools/mruby/mruby.c +++ b/tools/mruby/mruby.c @@ -105,7 +105,7 @@ append_cmdline: } else { printf("%s: No code specified for -e\n", *origargv); - return 0; + return EXIT_SUCCESS; } break; case 'v': @@ -115,7 +115,7 @@ append_cmdline: case '-': if (strcmp((*argv) + 2, "version") == 0) { mrb_show_version(mrb); - exit(0); + exit(EXIT_SUCCESS); } else if (strcmp((*argv) + 2, "verbose") == 0) { args->verbose = 1; @@ -123,11 +123,10 @@ append_cmdline: } else if (strcmp((*argv) + 2, "copyright") == 0) { mrb_show_copyright(mrb); - exit(0); + exit(EXIT_SUCCESS); } - else return -3; default: - return -4; + return EXIT_FAILURE; } } @@ -148,7 +147,7 @@ append_cmdline: memcpy(args->argv, argv, (argc+1) * sizeof(char*)); args->argc = argc; - return 0; + return EXIT_SUCCESS; } static void @@ -240,7 +239,7 @@ main(int argc, char **argv) } n = parse_args(mrb, argc, argv, &args); - if (n < 0 || (args.cmdline == NULL && args.rfp == NULL)) { + if (n == EXIT_FAILURE || (args.cmdline == NULL && args.rfp == NULL)) { cleanup(mrb, &args); usage(argv[0]); return n; |
