summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xbenchmark/fib39.rb8
-rw-r--r--include/mruby.h1
-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-sprintf/src/sprintf.c4
-rw-r--r--mrblib/numeric.rb32
-rw-r--r--src/array.c4
-rw-r--r--src/class.c1
-rw-r--r--src/codegen.c2
-rw-r--r--src/dump.c7
-rw-r--r--src/gc.c14
-rw-r--r--src/kernel.c2
-rw-r--r--src/load.c2
-rw-r--r--src/numeric.c100
-rw-r--r--src/object.c3
-rw-r--r--src/string.c4
-rw-r--r--src/variable.c40
-rw-r--r--src/vm.c12
-rw-r--r--tasks/mruby_build_commands.rake4
-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/string.rb10
29 files changed, 253 insertions, 107 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..5272d0400 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;
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-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/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..57cfae78f 100644
--- a/src/class.c
+++ b/src/class.c
@@ -1829,6 +1829,7 @@ 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 */
diff --git a/src/codegen.c b/src/codegen.c
index e5b1802a1..b8909e809 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -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 578a22202..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;
@@ -166,7 +166,7 @@ get_syms_block_size(mrb_state *mrb, mrb_irep *irep)
size += sizeof(uint16_t); /* snl(n) */
if (irep->syms[sym_no] != 0) {
mrb_sym2name_len(mrb, irep->syms[sym_no], &len);
- size += len; /* sn(n) */
+ size += len + 1; /* sn(n) + null char */
}
}
@@ -194,6 +194,7 @@ write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
cur += uint16_to_bin((uint16_t)len, cur); /* length of symbol name */
memcpy(cur, name, len); /* symbol name */
cur += (uint16_t)len;
+ *cur++ = '\0';
}
else {
cur += uint16_to_bin(MRB_DUMP_NULL_SYM_LEN, cur); /* length of symbol name */
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/load.c b/src/load.c
index a2f685742..c350cb1a3 100644
--- a/src/load.c
+++ b/src/load.c
@@ -131,7 +131,7 @@ read_rite_irep_record(mrb_state *mrb, const uint8_t *bin, uint32_t *len)
}
irep->syms[i] = mrb_intern2(mrb, (char *)src, snl);
- src += snl;
+ src += snl + 1;
mrb_gc_arena_restore(mrb, ai);
}
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/string.c b/src/string.c
index 5b6a44abd..c4074a64f 100644
--- a/src/string.c
+++ b/src/string.c
@@ -2537,7 +2537,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 +2629,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);
diff --git a/src/variable.c b/src/variable.c
index 941aaf83e..a9570db02 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*);
@@ -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 d81abd8a6..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);
@@ -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/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/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/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')