summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xbenchmark/fib39.rb8
-rw-r--r--include/mruby.h7
-rw-r--r--include/mruby/data.h19
-rw-r--r--include/mruby/dump.h5
-rw-r--r--include/mruby/numeric.h6
-rw-r--r--include/mruby/value.h2
-rw-r--r--include/mruby/variable.h1
-rw-r--r--mrbgems/mruby-numeric-ext/src/numeric_ext.c2
-rw-r--r--mrbgems/mruby-random/src/random.c2
-rw-r--r--mrbgems/mruby-sprintf/src/sprintf.c4
-rw-r--r--mrbgems/mruby-struct/src/struct.c10
-rw-r--r--mrbgems/mruby-time/src/time.c56
-rw-r--r--mrblib/error.rb10
-rw-r--r--mrblib/mrblib.rake2
-rw-r--r--mrblib/numeric.rb32
-rw-r--r--src/array.c4
-rw-r--r--src/class.c11
-rw-r--r--src/codegen.c4
-rw-r--r--src/dump.c4
-rw-r--r--src/error.c4
-rw-r--r--src/error.h1
-rw-r--r--src/etc.c27
-rw-r--r--src/gc.c14
-rw-r--r--src/kernel.c2
-rw-r--r--src/numeric.c100
-rw-r--r--src/object.c3
-rw-r--r--src/parse.y15
-rw-r--r--src/string.c255
-rw-r--r--src/variable.c44
-rw-r--r--src/vm.c14
-rw-r--r--tasks/mrbgem_spec.rake2
-rw-r--r--tasks/mrbgems_test.rake4
-rw-r--r--tasks/mruby_build_commands.rake4
-rw-r--r--tasks/ruby_ext.rake2
-rw-r--r--test/init_mrbtest.c2
-rw-r--r--test/t/array.rb16
-rw-r--r--test/t/class.rb20
-rw-r--r--test/t/comparable.rb10
-rw-r--r--test/t/hash.rb13
-rw-r--r--test/t/kernel.rb20
-rw-r--r--test/t/module.rb15
-rw-r--r--test/t/nameerror.rb20
-rw-r--r--test/t/string.rb10
-rw-r--r--tools/mirb/mirb.c12
-rw-r--r--tools/mrbc/mrbc.c18
-rw-r--r--tools/mruby/mruby.c13
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 */
diff --git a/src/etc.c b/src/etc.c
index 0b58ad67c..727915145 100644
--- a/src/etc.c
+++ b/src/etc.c
@@ -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);
}
diff --git a/src/gc.c b/src/gc.c
index c90e00c89..07bc23b12 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -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)
{
diff --git a/src/vm.c b/src/vm.c
index 596e34961..c319e7148 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -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;