summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/array.c16
-rw-r--r--src/backtrace.c29
-rw-r--r--src/class.c135
-rw-r--r--src/codedump.c32
-rw-r--r--src/debug.c15
-rw-r--r--src/dump.c21
-rw-r--r--src/error.c12
-rw-r--r--src/etc.c19
-rw-r--r--src/ext/.gitkeep0
-rw-r--r--src/fmt_fp.c6
-rw-r--r--src/gc.c30
-rw-r--r--src/hash.c53
-rw-r--r--src/kernel.c59
-rw-r--r--src/load.c25
-rw-r--r--src/mruby_core.rake1
-rw-r--r--src/numeric.c95
-rw-r--r--src/object.c6
-rw-r--r--src/proc.c81
-rw-r--r--src/range.c363
-rw-r--r--src/state.c1
-rw-r--r--src/string.c146
-rw-r--r--src/symbol.c256
-rw-r--r--src/variable.c68
-rw-r--r--src/vm.c365
24 files changed, 866 insertions, 968 deletions
diff --git a/src/array.c b/src/array.c
index 084b48dc0..d4302cb22 100644
--- a/src/array.c
+++ b/src/array.c
@@ -120,9 +120,7 @@ ary_fill_with_nil(mrb_value *ptr, mrb_int size)
static void
ary_modify_check(mrb_state *mrb, struct RArray *a)
{
- if (MRB_FROZEN_P(a)) {
- mrb_raise(mrb, E_FROZEN_ERROR, "can't modify frozen array");
- }
+ mrb_check_frozen(mrb, a);
}
static void
@@ -1089,7 +1087,6 @@ mrb_ary_clear(mrb_state *mrb, mrb_value self)
{
struct RArray *a = mrb_ary_ptr(self);
- mrb_get_args(mrb, "");
ary_modify(mrb, a);
if (ARY_SHARED_P(a)) {
mrb_ary_decref(mrb, a->as.heap.aux.shared);
@@ -1104,6 +1101,13 @@ mrb_ary_clear(mrb_state *mrb, mrb_value self)
}
static mrb_value
+mrb_ary_clear_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_get_args(mrb, "");
+ return mrb_ary_clear(mrb, self);
+}
+
+static mrb_value
mrb_ary_empty_p(mrb_state *mrb, mrb_value self)
{
struct RArray *a = mrb_ary_ptr(self);
@@ -1268,7 +1272,7 @@ mrb_init_array(mrb_state *mrb)
mrb_define_method(mrb, a, "<<", mrb_ary_push_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.3 */
mrb_define_method(mrb, a, "[]", mrb_ary_aget, MRB_ARGS_ANY()); /* 15.2.12.5.4 */
mrb_define_method(mrb, a, "[]=", mrb_ary_aset, MRB_ARGS_ANY()); /* 15.2.12.5.5 */
- mrb_define_method(mrb, a, "clear", mrb_ary_clear, MRB_ARGS_NONE()); /* 15.2.12.5.6 */
+ mrb_define_method(mrb, a, "clear", mrb_ary_clear_m, MRB_ARGS_NONE()); /* 15.2.12.5.6 */
mrb_define_method(mrb, a, "concat", mrb_ary_concat_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.8 */
mrb_define_method(mrb, a, "delete_at", mrb_ary_delete_at, MRB_ARGS_REQ(1)); /* 15.2.12.5.9 */
mrb_define_method(mrb, a, "empty?", mrb_ary_empty_p, MRB_ARGS_NONE()); /* 15.2.12.5.12 */
@@ -1280,7 +1284,6 @@ mrb_init_array(mrb_state *mrb)
mrb_define_method(mrb, a, "length", mrb_ary_size, MRB_ARGS_NONE()); /* 15.2.12.5.19 */
mrb_define_method(mrb, a, "pop", mrb_ary_pop, MRB_ARGS_NONE()); /* 15.2.12.5.21 */
mrb_define_method(mrb, a, "push", mrb_ary_push_m, MRB_ARGS_ANY()); /* 15.2.12.5.22 */
- mrb_define_method(mrb, a, "append", mrb_ary_push_m, MRB_ARGS_ANY());
mrb_define_method(mrb, a, "replace", mrb_ary_replace_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.23 */
mrb_define_method(mrb, a, "reverse", mrb_ary_reverse, MRB_ARGS_NONE()); /* 15.2.12.5.24 */
mrb_define_method(mrb, a, "reverse!", mrb_ary_reverse_bang, MRB_ARGS_NONE()); /* 15.2.12.5.25 */
@@ -1289,7 +1292,6 @@ mrb_init_array(mrb_state *mrb)
mrb_define_method(mrb, a, "size", mrb_ary_size, MRB_ARGS_NONE()); /* 15.2.12.5.28 */
mrb_define_method(mrb, a, "slice", mrb_ary_aget, MRB_ARGS_ANY()); /* 15.2.12.5.29 */
mrb_define_method(mrb, a, "unshift", mrb_ary_unshift_m, MRB_ARGS_ANY()); /* 15.2.12.5.30 */
- mrb_define_method(mrb, a, "prepend", mrb_ary_unshift_m, MRB_ARGS_ANY());
mrb_define_method(mrb, a, "__ary_eq", mrb_ary_eq, MRB_ARGS_REQ(1));
mrb_define_method(mrb, a, "__ary_cmp", mrb_ary_cmp, MRB_ARGS_REQ(1));
diff --git a/src/backtrace.c b/src/backtrace.c
index 57ae7fd7f..e4f5a3064 100644
--- a/src/backtrace.c
+++ b/src/backtrace.c
@@ -17,23 +17,23 @@
struct backtrace_location {
int lineno;
- const char *filename;
mrb_sym method_id;
+ const char *filename;
};
-typedef void (*each_backtrace_func)(mrb_state*, struct backtrace_location*, void*);
+typedef void (*each_backtrace_func)(mrb_state*, const struct backtrace_location*, void*);
static const mrb_data_type bt_type = { "Backtrace", mrb_free };
static void
each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, mrb_code *pc0, each_backtrace_func func, void *data)
{
- ptrdiff_t i, j;
+ ptrdiff_t i;
if (ciidx >= mrb->c->ciend - mrb->c->cibase)
ciidx = 10; /* ciidx is broken... */
- for (i=ciidx, j=0; i >= 0; i--,j++) {
+ for (i=ciidx; i >= 0; i--) {
struct backtrace_location loc;
mrb_callinfo *ci;
mrb_irep *irep;
@@ -57,11 +57,11 @@ each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, mrb_code *pc0, each_backtrace_fu
else {
pc = pc0;
}
- loc.filename = mrb_debug_get_filename(irep, pc - irep->iseq);
- loc.lineno = mrb_debug_get_line(irep, pc - irep->iseq);
+ loc.lineno = mrb_debug_get_line(mrb, irep, pc - irep->iseq);
if (loc.lineno == -1) continue;
+ loc.filename = mrb_debug_get_filename(mrb, irep, pc - irep->iseq);
if (!loc.filename) {
loc.filename = "(unknown)";
}
@@ -80,8 +80,6 @@ print_backtrace(mrb_state *mrb, mrb_value backtrace)
mrb_int n;
FILE *stream = stderr;
- if (!mrb_array_p(backtrace)) return;
-
n = RARRAY_LEN(backtrace) - 1;
if (n == 0) return;
@@ -96,7 +94,7 @@ print_backtrace(mrb_state *mrb, mrb_value backtrace)
}
static int
-packed_bt_len(struct backtrace_location *bt, int n)
+packed_bt_len(const struct backtrace_location *bt, int n)
{
int len = 0;
int i;
@@ -113,7 +111,7 @@ static void
print_packed_backtrace(mrb_state *mrb, mrb_value packed)
{
FILE *stream = stderr;
- struct backtrace_location *bt;
+ const struct backtrace_location *bt;
int n, i;
int ai = mrb_gc_arena_save(mrb);
@@ -124,7 +122,7 @@ print_packed_backtrace(mrb_state *mrb, mrb_value packed)
if (packed_bt_len(bt, n) == 0) return;
fprintf(stream, "trace (most recent call last):\n");
for (i = 0; i<n; i++) {
- struct backtrace_location *entry = &bt[n-i-1];
+ const struct backtrace_location *entry = &bt[n-i-1];
if (entry->filename == NULL) continue;
fprintf(stream, "\t[%d] %s:%d", i, entry->filename, entry->lineno);
if (entry->method_id != 0) {
@@ -172,7 +170,7 @@ mrb_print_backtrace(mrb_state *mrb)
static void
count_backtrace_i(mrb_state *mrb,
- struct backtrace_location *loc,
+ const struct backtrace_location *loc,
void *data)
{
int *lenp = (int*)data;
@@ -183,7 +181,7 @@ count_backtrace_i(mrb_state *mrb,
static void
pack_backtrace_i(mrb_state *mrb,
- struct backtrace_location *loc,
+ const struct backtrace_location *loc,
void *data)
{
struct backtrace_location **pptr = (struct backtrace_location**)data;
@@ -206,7 +204,6 @@ packed_backtrace(mrb_state *mrb)
each_backtrace(mrb, ciidx, mrb->c->ci->pc, count_backtrace_i, &len);
size = len * sizeof(struct backtrace_location);
ptr = mrb_malloc(mrb, size);
- if (ptr) memset(ptr, 0, size);
backtrace = mrb_data_object_alloc(mrb, NULL, ptr, &bt_type);
backtrace->flags = (unsigned int)len;
each_backtrace(mrb, ciidx, mrb->c->ci->pc, pack_backtrace_i, &ptr);
@@ -230,7 +227,7 @@ mrb_keep_backtrace(mrb_state *mrb, mrb_value exc)
mrb_value
mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace)
{
- struct backtrace_location *bt;
+ const struct backtrace_location *bt;
mrb_int n, i;
int ai;
@@ -245,7 +242,7 @@ mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace)
backtrace = mrb_ary_new_capa(mrb, n);
ai = mrb_gc_arena_save(mrb);
for (i = 0; i < n; i++) {
- struct backtrace_location *entry = &bt[i];
+ const struct backtrace_location *entry = &bt[i];
mrb_value btline;
if (entry->filename == NULL) continue;
diff --git a/src/class.c b/src/class.c
index dd5b65cc3..2cabc820e 100644
--- a/src/class.c
+++ b/src/class.c
@@ -120,6 +120,20 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o)
mrb_field_write_barrier(mrb, (struct RBasic*)o, (struct RBasic*)sc);
mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)o);
mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern_lit(mrb, "__attached__"), mrb_obj_value(o));
+ sc->flags |= o->flags & MRB_FL_OBJ_IS_FROZEN;
+}
+
+static mrb_value
+class_name_str(mrb_state *mrb, struct RClass* c)
+{
+ mrb_value path = mrb_class_path(mrb, c);
+ if (mrb_nil_p(path)) {
+ path = c->tt == MRB_TT_MODULE ? mrb_str_new_lit(mrb, "#<Module:") :
+ mrb_str_new_lit(mrb, "#<Class:");
+ mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, c));
+ mrb_str_cat_lit(mrb, path, ">");
+ }
+ return path;
}
static struct RClass*
@@ -428,12 +442,7 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_method_
MRB_CLASS_ORIGIN(c);
h = c->mt;
- if (MRB_FROZEN_P(c)) {
- if (c->tt == MRB_TT_MODULE)
- mrb_raise(mrb, E_FROZEN_ERROR, "can't modify frozen module");
- else
- mrb_raise(mrb, E_FROZEN_ERROR, "can't modify frozen class");
- }
+ mrb_check_frozen(mrb, c);
if (!h) h = c->mt = kh_init(mt, mrb);
k = kh_put(mt, mrb, h, mid);
kh_value(h, k) = m;
@@ -471,15 +480,11 @@ mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t
MRB_API void
mrb_notimplement(mrb_state *mrb)
{
- const char *str;
- mrb_int len;
mrb_callinfo *ci = mrb->c->ci;
if (ci->mid) {
- str = mrb_sym2name_len(mrb, ci->mid, &len);
- mrb_raisef(mrb, E_NOTIMP_ERROR,
- "%S() function is unimplemented on this machine",
- mrb_str_new_static(mrb, str, (size_t)len));
+ mrb_value str = mrb_sym2str(mrb, ci->mid);
+ mrb_raisef(mrb, E_NOTIMP_ERROR, "%S() function is unimplemented on this machine", str);
}
}
@@ -833,29 +838,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
p = va_arg(ap, mrb_int*);
if (i < argc) {
- switch (mrb_type(ARGV[arg_i])) {
- case MRB_TT_FIXNUM:
- *p = mrb_fixnum(ARGV[arg_i]);
- break;
-#ifndef MRB_WITHOUT_FLOAT
- case MRB_TT_FLOAT:
- {
- mrb_float f = mrb_float(ARGV[arg_i]);
-
- if (!FIXABLE_FLOAT(f)) {
- mrb_raise(mrb, E_RANGE_ERROR, "float too big for int");
- }
- *p = (mrb_int)f;
- }
- break;
-#endif
- case MRB_TT_STRING:
- mrb_raise(mrb, E_TYPE_ERROR, "no implicit conversion of String into Integer");
- break;
- default:
- *p = mrb_fixnum(mrb_Integer(mrb, ARGV[arg_i]));
- break;
- }
+ *p = mrb_fixnum(mrb_to_int(mrb, ARGV[arg_i]));
arg_i++;
i++;
}
@@ -1494,29 +1477,20 @@ mrb_instance_alloc(mrb_state *mrb, mrb_value cv)
*
*/
-MRB_API mrb_value
+mrb_value
mrb_instance_new(mrb_state *mrb, mrb_value cv)
{
mrb_value obj, blk;
mrb_value *argv;
mrb_int argc;
mrb_sym init;
- mrb_method_t m;
mrb_get_args(mrb, "*&", &argv, &argc, &blk);
obj = mrb_instance_alloc(mrb, cv);
init = mrb_intern_lit(mrb, "initialize");
- m = mrb_method_search(mrb, mrb_class(mrb, obj), init);
- if (MRB_METHOD_CFUNC_P(m)) {
- mrb_func_t f = MRB_METHOD_CFUNC(m);
- if (f != mrb_bob_init) {
- f(mrb, obj);
- }
- }
- else {
+ if (!mrb_func_basic_p(mrb, obj, init, mrb_bob_init)) {
mrb_funcall_with_block(mrb, obj, init, argc, argv, blk);
}
-
return obj;
}
@@ -1673,11 +1647,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c)
}
else if (mrb_symbol_p(path)) {
/* toplevel class/module */
- const char *str;
- mrb_int len;
-
- str = mrb_sym2name_len(mrb, mrb_symbol(path), &len);
- return mrb_str_new(mrb, str, len);
+ return mrb_sym2str(mrb, mrb_symbol(path));
}
return mrb_str_dup(mrb, path);
}
@@ -1696,14 +1666,8 @@ mrb_class_real(struct RClass* cl)
MRB_API const char*
mrb_class_name(mrb_state *mrb, struct RClass* c)
{
- mrb_value path = mrb_class_path(mrb, c);
- if (mrb_nil_p(path)) {
- path = c->tt == MRB_TT_MODULE ? mrb_str_new_lit(mrb, "#<Module:") :
- mrb_str_new_lit(mrb, "#<Class:");
- mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, c));
- mrb_str_cat_lit(mrb, path, ">");
- }
- return RSTRING_PTR(path);
+ mrb_value name = class_name_str(mrb, c);
+ return RSTRING_PTR(name);
}
MRB_API const char*
@@ -1815,15 +1779,13 @@ mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const
* show information on the thing we're attached to as well.
*/
-static mrb_value
+mrb_value
mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
{
- mrb_value str;
if (mrb_type(klass) == MRB_TT_SCLASS) {
mrb_value v = mrb_iv_get(mrb, klass, mrb_intern_lit(mrb, "__attached__"));
-
- str = mrb_str_new_lit(mrb, "#<Class:");
+ mrb_value str = mrb_str_new_lit(mrb, "#<Class:");
if (class_ptr_p(v)) {
mrb_str_cat_str(mrb, str, mrb_inspect(mrb, v));
@@ -1834,34 +1796,7 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
return mrb_str_cat_lit(mrb, str, ">");
}
else {
- struct RClass *c;
- mrb_value path;
-
- str = mrb_str_new_capa(mrb, 32);
- c = mrb_class_ptr(klass);
- path = mrb_class_path(mrb, c);
-
- if (mrb_nil_p(path)) {
- switch (mrb_type(klass)) {
- case MRB_TT_CLASS:
- mrb_str_cat_lit(mrb, str, "#<Class:");
- break;
-
- case MRB_TT_MODULE:
- mrb_str_cat_lit(mrb, str, "#<Module:");
- break;
-
- default:
- /* Shouldn't be happened? */
- mrb_str_cat_lit(mrb, str, "#<??????:");
- break;
- }
- mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, c));
- return mrb_str_cat_lit(mrb, str, ">");
- }
- else {
- return path;
- }
+ return class_name_str(mrb, mrb_class_ptr(klass));
}
}
@@ -1873,7 +1808,7 @@ mrb_mod_alias(mrb_state *mrb, mrb_value mod)
mrb_get_args(mrb, "nn", &new_name, &old_name);
mrb_alias_method(mrb, c, new_name, old_name);
- return mrb_nil_value();
+ return mod;
}
void
@@ -1917,18 +1852,20 @@ mrb_mod_undef(mrb_state *mrb, mrb_value mod)
return mrb_nil_value();
}
-static void
-check_const_name_str(mrb_state *mrb, mrb_value str)
+static mrb_bool
+const_name_p(mrb_state *mrb, const char *name, mrb_int len)
{
- if (RSTRING_LEN(str) < 1 || !ISUPPER(*RSTRING_PTR(str))) {
- mrb_name_error(mrb, mrb_intern_str(mrb, str), "wrong constant name %S", str);
- }
+ return len > 0 && ISUPPER(name[0]) && mrb_ident_p(name+1, len-1);
}
static void
check_const_name_sym(mrb_state *mrb, mrb_sym id)
{
- check_const_name_str(mrb, mrb_sym2str(mrb, id));
+ mrb_int len;
+ const char *name = mrb_sym2name_len(mrb, id, &len);
+ if (!const_name_p(mrb, name, len)) {
+ mrb_name_error(mrb, id, "wrong constant name %S", mrb_sym2str(mrb, id));
+ }
}
static mrb_value
@@ -2126,7 +2063,7 @@ mrb_mod_eqq(mrb_state *mrb, mrb_value mod)
return mrb_bool_value(eqq);
}
-MRB_API mrb_value
+static mrb_value
mrb_mod_module_function(mrb_state *mrb, mrb_value mod)
{
mrb_value *argv;
diff --git a/src/codedump.c b/src/codedump.c
index 4d56fd427..12d609075 100644
--- a/src/codedump.c
+++ b/src/codedump.c
@@ -48,11 +48,11 @@ print_lv_ab(mrb_state *mrb, mrb_irep *irep, uint16_t a, uint16_t b)
}
static void
-print_header(mrb_irep *irep, ptrdiff_t i)
+print_header(mrb_state *mrb, mrb_irep *irep, ptrdiff_t i)
{
int32_t line;
- line = mrb_debug_get_line(irep, i);
+ line = mrb_debug_get_line(mrb, irep, i);
if (line < 0) {
printf(" ");
}
@@ -74,8 +74,8 @@ codedump(mrb_state *mrb, mrb_irep *irep)
const char *file = NULL, *next_file;
if (!irep) return;
- printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d\n", (void*)irep,
- irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen);
+ printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d iseq=%d\n", (void*)irep,
+ irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen, (int)irep->ilen);
if (irep->lv) {
int i;
@@ -99,12 +99,12 @@ codedump(mrb_state *mrb, mrb_irep *irep)
ai = mrb_gc_arena_save(mrb);
i = pc - irep->iseq;
- next_file = mrb_debug_get_filename(irep, i);
+ next_file = mrb_debug_get_filename(mrb, irep, i);
if (next_file && file != next_file) {
printf("file: %s\n", next_file);
file = next_file;
}
- print_header(irep, i);
+ print_header(mrb, irep, i);
ins = READ_B();
switch (ins) {
CASE(OP_NOP, Z):
@@ -266,13 +266,13 @@ codedump(mrb_state *mrb, mrb_irep *irep)
break;
CASE(OP_ENTER, W):
printf("OP_ENTER\t%d:%d:%d:%d:%d:%d:%d\n",
- (a>>18)&0x1f,
- (a>>13)&0x1f,
- (a>>12)&0x1,
- (a>>7)&0x1f,
- (a>>2)&0x1f,
- (a>>1)&0x1,
- a & 0x1);
+ MRB_ASPEC_REQ(a),
+ MRB_ASPEC_OPT(a),
+ MRB_ASPEC_REST(a),
+ MRB_ASPEC_POST(a),
+ MRB_ASPEC_KEY(a),
+ MRB_ASPEC_KDICT(a),
+ MRB_ASPEC_BLOCK(a));
break;
CASE(OP_KEY_P, BB):
printf("OP_KEY_P\tR%d\t:%s\t", a, mrb_sym2name(mrb, irep->syms[b]));
@@ -491,7 +491,7 @@ codedump(mrb_state *mrb, mrb_irep *irep)
CASE(OP_EXT1, Z):
ins = READ_B();
printf("OP_EXT1\n");
- print_header(irep, pc-irep->iseq-2);
+ print_header(mrb, irep, pc-irep->iseq-2);
switch (ins) {
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); goto L_OP_ ## i;
#include "mruby/ops.h"
@@ -501,7 +501,7 @@ codedump(mrb_state *mrb, mrb_irep *irep)
CASE(OP_EXT2, Z):
ins = READ_B();
printf("OP_EXT2\n");
- print_header(irep, pc-irep->iseq-2);
+ print_header(mrb, irep, pc-irep->iseq-2);
switch (ins) {
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); goto L_OP_ ## i;
#include "mruby/ops.h"
@@ -511,7 +511,7 @@ codedump(mrb_state *mrb, mrb_irep *irep)
CASE(OP_EXT3, Z):
ins = READ_B();
printf("OP_EXT3\n");
- print_header(irep, pc-irep->iseq-2);
+ print_header(mrb, irep, pc-irep->iseq-2);
switch (ins) {
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); goto L_OP_ ## i;
#include "mruby/ops.h"
diff --git a/src/debug.c b/src/debug.c
index 2949131e4..0dc02a1e3 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -51,20 +51,20 @@ select_line_type(const uint16_t *lines, size_t lines_len)
}
MRB_API char const*
-mrb_debug_get_filename(mrb_irep *irep, ptrdiff_t pc)
+mrb_debug_get_filename(mrb_state *mrb, mrb_irep *irep, ptrdiff_t pc)
{
if (irep && pc >= 0 && pc < irep->ilen) {
mrb_irep_debug_info_file* f = NULL;
if (!irep->debug_info) return NULL;
else if ((f = get_file(irep->debug_info, (uint32_t)pc))) {
- return f->filename;
+ return mrb_sym2name_len(mrb, f->filename_sym, NULL);
}
}
return NULL;
}
MRB_API int32_t
-mrb_debug_get_line(mrb_irep *irep, ptrdiff_t pc)
+mrb_debug_get_line(mrb_state *mrb, mrb_irep *irep, ptrdiff_t pc)
{
if (irep && pc >= 0 && pc < irep->ilen) {
mrb_irep_debug_info_file* f = NULL;
@@ -129,7 +129,6 @@ mrb_debug_info_append_file(mrb_state *mrb, mrb_irep_debug_info *d,
mrb_irep_debug_info_file *f;
uint32_t file_pc_count;
size_t fn_len;
- mrb_int len;
uint32_t i;
if (!d) return NULL;
@@ -138,8 +137,10 @@ mrb_debug_info_append_file(mrb_state *mrb, mrb_irep_debug_info *d,
mrb_assert(filename);
mrb_assert(lines);
- if (d->flen > 0 && strcmp(filename, d->files[d->flen - 1]->filename) == 0) {
- return NULL;
+ if (d->flen > 0) {
+ const char *fn = mrb_sym2name_len(mrb, d->files[d->flen - 1]->filename_sym, NULL);
+ if (strcmp(filename, fn) == 0)
+ return NULL;
}
f = (mrb_irep_debug_info_file*)mrb_malloc(mrb, sizeof(*f));
@@ -156,8 +157,6 @@ mrb_debug_info_append_file(mrb_state *mrb, mrb_irep_debug_info *d,
fn_len = strlen(filename);
f->filename_sym = mrb_intern(mrb, filename, fn_len);
- len = 0;
- f->filename = mrb_sym2name_len(mrb, f->filename_sym, &len);
f->line_type = select_line_type(lines + start_pos, end_pos - start_pos);
f->lines.ptr = NULL;
diff --git a/src/dump.c b/src/dump.c
index 6ce9c4eb9..f1e167e35 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -6,6 +6,7 @@
#include <string.h>
#include <limits.h>
+#include <math.h>
#include <mruby/dump.h>
#include <mruby/string.h>
#include <mruby/irep.h>
@@ -17,9 +18,9 @@
#ifndef MRB_WITHOUT_FLOAT
#ifdef MRB_USE_FLOAT
-#define MRB_FLOAT_FMT "%.8e"
+#define MRB_FLOAT_FMT "%.9g"
#else
-#define MRB_FLOAT_FMT "%.16e"
+#define MRB_FLOAT_FMT "%.17g"
#endif
#endif
@@ -90,6 +91,18 @@ write_iseq_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf, uint8_t flags)
return cur - buf;
}
+#ifndef MRB_WITHOUT_FLOAT
+static mrb_value
+float_to_str(mrb_state *mrb, mrb_value flt)
+{
+ mrb_float f = mrb_float(flt);
+
+ if (isinf(f)) {
+ return f < 0 ? mrb_str_new_lit(mrb, "I") : mrb_str_new_lit(mrb, "i");
+ }
+ return mrb_float_to_str(mrb, flt, MRB_FLOAT_FMT);
+}
+#endif
static size_t
get_pool_block_size(mrb_state *mrb, mrb_irep *irep)
@@ -116,7 +129,7 @@ get_pool_block_size(mrb_state *mrb, mrb_irep *irep)
#ifndef MRB_WITHOUT_FLOAT
case MRB_TT_FLOAT:
- str = mrb_float_to_str(mrb, irep->pool[pool_no], MRB_FLOAT_FMT);
+ str = float_to_str(mrb, irep->pool[pool_no]);
{
mrb_int len = RSTRING_LEN(str);
mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
@@ -165,7 +178,7 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
#ifndef MRB_WITHOUT_FLOAT
case MRB_TT_FLOAT:
cur += uint8_to_bin(IREP_TT_FLOAT, cur); /* data type */
- str = mrb_float_to_str(mrb, irep->pool[pool_no], MRB_FLOAT_FMT);
+ str = float_to_str(mrb, irep->pool[pool_no]);
break;
#endif
diff --git a/src/error.c b/src/error.c
index 57cdfcfe1..4c1b67c99 100644
--- a/src/error.c
+++ b/src/error.c
@@ -208,8 +208,8 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc)
if (err && ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) {
mrb_irep *irep = ci->proc->body.irep;
- int32_t const line = mrb_debug_get_line(irep, err - irep->iseq);
- char const* file = mrb_debug_get_filename(irep, err - irep->iseq);
+ int32_t const line = mrb_debug_get_line(mrb, irep, err - irep->iseq);
+ char const* file = mrb_debug_get_filename(mrb, irep, err - irep->iseq);
if (line != -1 && file) {
mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "file"), mrb_str_new_cstr(mrb, file));
mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "line"), mrb_fixnum_value(line));
@@ -376,6 +376,7 @@ mrb_warn(mrb_state *mrb, const char *fmt, ...)
str = mrb_vformat(mrb, fmt, ap);
fputs("warning: ", stderr);
fwrite(RSTRING_PTR(str), RSTRING_LEN(str), 1, stderr);
+ putc('\n', stderr);
va_end(ap);
#endif
}
@@ -483,6 +484,13 @@ mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, char const* fmt,
mrb_exc_raise(mrb, exc);
}
+MRB_API mrb_noreturn void
+mrb_frozen_error(mrb_state *mrb, void *frozen_obj)
+{
+ mrb_raisef(mrb, E_FROZEN_ERROR, "can't modify frozen %S",
+ mrb_obj_value(mrb_class(mrb, mrb_obj_value(frozen_obj))));
+}
+
void
mrb_init_exception(mrb_state *mrb)
{
diff --git a/src/etc.c b/src/etc.c
index 12d948a55..ac1540f92 100644
--- a/src/etc.c
+++ b/src/etc.c
@@ -167,6 +167,7 @@ mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f)
v.value.p = mrb_obj_alloc(mrb, MRB_TT_FLOAT, mrb->float_class);
v.value.fp->f = f;
+ MRB_SET_FROZEN_FLAG(v.value.bp);
return v;
}
@@ -177,6 +178,7 @@ mrb_word_boxing_float_pool(mrb_state *mrb, mrb_float f)
nf->tt = MRB_TT_FLOAT;
nf->c = mrb->float_class;
nf->f = f;
+ MRB_SET_FROZEN_FLAG(nf);
return mrb_obj_value(nf);
}
#endif /* MRB_WITHOUT_FLOAT */
@@ -192,23 +194,6 @@ mrb_word_boxing_cptr_value(mrb_state *mrb, void *p)
}
#endif /* MRB_WORD_BOXING */
-MRB_API mrb_bool
-mrb_regexp_p(mrb_state *mrb, mrb_value v)
-{
- if (mrb->flags & MRB_STATE_NO_REGEXP) {
- return FALSE;
- }
- if ((mrb->flags & MRB_STATE_REGEXP) || mrb_class_defined(mrb, REGEXP_CLASS)) {
- mrb->flags |= MRB_STATE_REGEXP;
- return mrb_obj_is_kind_of(mrb, v, mrb_class_get(mrb, REGEXP_CLASS));
- }
- else {
- mrb->flags |= MRB_STATE_REGEXP;
- mrb->flags |= MRB_STATE_NO_REGEXP;
- }
- return FALSE;
-}
-
#if defined _MSC_VER && _MSC_VER < 1900
#ifndef va_copy
diff --git a/src/ext/.gitkeep b/src/ext/.gitkeep
deleted file mode 100644
index e69de29bb..000000000
--- a/src/ext/.gitkeep
+++ /dev/null
diff --git a/src/fmt_fp.c b/src/fmt_fp.c
index 7028d3aac..1f1af6764 100644
--- a/src/fmt_fp.c
+++ b/src/fmt_fp.c
@@ -1,5 +1,5 @@
#ifndef MRB_WITHOUT_FLOAT
-#ifdef MRB_DISABLE_STDIO
+#if defined(MRB_DISABLE_STDIO) || defined(_WIN32) || defined(_WIN64)
/*
Most code in this file originates from musl (src/stdio/vfprintf.c)
@@ -372,7 +372,7 @@ mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt)
}
return f.str;
}
-#else /* MRB_DISABLE_STDIO */
+#else /* MRB_DISABLE_STDIO || _WIN32 || _WIN64 */
#include <mruby.h>
#include <stdio.h>
@@ -384,5 +384,5 @@ mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt)
snprintf(buf, sizeof(buf), fmt, mrb_float(flo));
return mrb_str_new_cstr(mrb, buf);
}
-#endif /* MRB_DISABLE_STDIO */
+#endif /* MRB_DISABLE_STDIO || _WIN32 || _WIN64 */
#endif
diff --git a/src/gc.c b/src/gc.c
index a52c64bfa..5e7440d50 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -10,6 +10,7 @@
#include <mruby/array.h>
#include <mruby/class.h>
#include <mruby/data.h>
+#include <mruby/istruct.h>
#include <mruby/hash.h>
#include <mruby/proc.h>
#include <mruby/range.h>
@@ -109,8 +110,10 @@ typedef struct {
struct RHash hash;
struct RRange range;
struct RData data;
+ struct RIstruct istruct;
struct RProc proc;
struct REnv env;
+ struct RFiber fiber;
struct RException exc;
struct RBreak brk;
#ifdef MRB_WORD_BOXING
@@ -396,7 +399,7 @@ mrb_gc_init(mrb_state *mrb, mrb_gc *gc)
static void obj_free(mrb_state *mrb, struct RBasic *obj, int end);
-void
+static void
free_heap(mrb_state *mrb, mrb_gc *gc)
{
mrb_heap_page *page = gc->heaps;
@@ -463,9 +466,12 @@ mrb_gc_protect(mrb_state *mrb, mrb_value obj)
MRB_API void
mrb_gc_register(mrb_state *mrb, mrb_value obj)
{
- mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME);
- mrb_value table = mrb_gv_get(mrb, root);
+ mrb_sym root;
+ mrb_value table;
+ if (mrb_immediate_p(obj)) return;
+ root = mrb_intern_lit(mrb, GC_ROOT_NAME);
+ table = mrb_gv_get(mrb, root);
if (mrb_nil_p(table) || mrb_type(table) != MRB_TT_ARRAY) {
table = mrb_ary_new(mrb);
mrb_gv_set(mrb, root, table);
@@ -477,11 +483,14 @@ mrb_gc_register(mrb_state *mrb, mrb_value obj)
MRB_API void
mrb_gc_unregister(mrb_state *mrb, mrb_value obj)
{
- mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME);
- mrb_value table = mrb_gv_get(mrb, root);
+ mrb_sym root;
+ mrb_value table;
struct RArray *a;
mrb_int i;
+ if (mrb_immediate_p(obj)) return;
+ root = mrb_intern_lit(mrb, GC_ROOT_NAME);
+ table = mrb_gv_get(mrb, root);
if (mrb_nil_p(table)) return;
if (mrb_type(table) != MRB_TT_ARRAY) {
mrb_gv_set(mrb, root, mrb_nil_value());
@@ -739,14 +748,7 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
break;
case MRB_TT_RANGE:
- {
- struct RRange *r = (struct RRange*)obj;
-
- if (r->edges) {
- mrb_gc_mark_value(mrb, r->edges->beg);
- mrb_gc_mark_value(mrb, r->edges->end);
- }
- }
+ mrb_gc_mark_range(mrb, (struct RRange*)obj);
break;
default:
@@ -870,7 +872,7 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end)
break;
case MRB_TT_RANGE:
- mrb_free(mrb, ((struct RRange*)obj)->edges);
+ mrb_gc_free_range(mrb, ((struct RRange*)obj));
break;
case MRB_TT_DATA:
diff --git a/src/hash.c b/src/hash.c
index 467b20a51..a9367a426 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -16,13 +16,10 @@
mrb_int mrb_float_id(mrb_float f);
#endif
-/* return non zero to break the loop */
-typedef int (ht_foreach_func)(mrb_state *mrb,mrb_value key, mrb_value val, void *data);
-
#ifndef MRB_HT_INIT_SIZE
#define MRB_HT_INIT_SIZE 4
#endif
-#define HT_SEG_INCREASE_RATIO 1.2
+#define HT_SEG_INCREASE_RATIO 6 / 5
struct segkv {
mrb_value key;
@@ -41,7 +38,7 @@ typedef struct segindex {
struct segkv *table[];
} segindex;
-/* Instance variable table structure */
+/* hash table structure */
typedef struct htable {
segment *rootseg;
segment *lastseg;
@@ -135,7 +132,7 @@ ht_hash_equal(mrb_state *mrb, htable *t, mrb_value a, mrb_value b)
}
}
-/* Creates the instance variable table. */
+/* Creates the hash table. */
static htable*
ht_new(mrb_state *mrb)
{
@@ -185,7 +182,7 @@ ht_index(mrb_state *mrb, htable *t)
if (!index || index->capa < size) {
index = (segindex*)mrb_realloc_simple(mrb, index, sizeof(segindex)+sizeof(struct segkv*)*size);
if (index == NULL) {
- mrb_free(mrb, index);
+ mrb_free(mrb, t->index);
t->index = NULL;
return;
}
@@ -349,7 +346,7 @@ ht_index_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val)
t->size++;
}
-/* Set the value for the key in the table. */
+/* Set the value for the key in the hash table. */
static void
ht_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val)
{
@@ -468,7 +465,7 @@ ht_get(mrb_state *mrb, htable *t, mrb_value key, mrb_value *vp)
return FALSE;
}
-/* Deletes the value for the symbol from the instance variable table. */
+/* Deletes the value for the symbol from the hash table. */
/* Deletion is done by overwriting keys by `undef`. */
static mrb_bool
ht_del(mrb_state *mrb, htable *t, mrb_value key, mrb_value *vp)
@@ -499,9 +496,9 @@ ht_del(mrb_state *mrb, htable *t, mrb_value key, mrb_value *vp)
return FALSE;
}
-/* Iterates over the instance variable table. */
+/* Iterates over the hash table. */
static void
-ht_foreach(mrb_state *mrb, htable *t, ht_foreach_func *func, void *p)
+ht_foreach(mrb_state *mrb, htable *t, mrb_hash_foreach_func *func, void *p)
{
segment *seg;
mrb_int i;
@@ -522,7 +519,14 @@ ht_foreach(mrb_state *mrb, htable *t, ht_foreach_func *func, void *p)
}
}
-/* Copy the instance variable table. */
+/* Iterates over the hash table. */
+MRB_API void
+mrb_hash_foreach(mrb_state *mrb, struct RHash *hash, mrb_hash_foreach_func *func, void *p)
+{
+ ht_foreach(mrb, hash->ht, func, p);
+}
+
+/* Copy the hash table. */
static htable*
ht_copy(mrb_state *mrb, htable *t)
{
@@ -532,6 +536,7 @@ ht_copy(mrb_state *mrb, htable *t)
seg = t->rootseg;
t2 = ht_new(mrb);
+ if (t->size == 0) return t2;
while (seg) {
for (i=0; i<seg->size; i++) {
@@ -548,7 +553,7 @@ ht_copy(mrb_state *mrb, htable *t)
return t2;
}
-/* Free memory of the instance variable table. */
+/* Free memory of the hash table. */
static void
ht_free(mrb_state *mrb, htable *t)
{
@@ -741,10 +746,7 @@ mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val)
static void
mrb_hash_modify(mrb_state *mrb, mrb_value hash)
{
- if (MRB_FROZEN_P(mrb_hash_ptr(hash))) {
- mrb_raise(mrb, E_FROZEN_ERROR, "can't modify frozen hash");
- }
-
+ mrb_check_frozen(mrb, mrb_hash_ptr(hash));
if (!RHASH_TBL(hash)) {
RHASH_TBL(hash) = ht_new(mrb);
}
@@ -1008,7 +1010,7 @@ mrb_hash_delete(mrb_state *mrb, mrb_value self)
return mrb_hash_delete_key(mrb, self, key);
}
-/* find first element in a hash table, and remove it. */
+/* find first element in the hash table, and remove it. */
static void
ht_shift(mrb_state *mrb, htable *t, mrb_value *kp, mrb_value *vp)
{
@@ -1129,6 +1131,15 @@ mrb_hash_aset(mrb_state *mrb, mrb_value self)
return val;
}
+MRB_API mrb_int
+mrb_hash_size(mrb_state *mrb, mrb_value hash)
+{
+ htable *t = RHASH_TBL(hash);
+
+ if (!t) return 0;
+ return t->size;
+}
+
/* 15.2.13.4.20 */
/* 15.2.13.4.25 */
/*
@@ -1146,10 +1157,8 @@ mrb_hash_aset(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_hash_size_m(mrb_state *mrb, mrb_value self)
{
- htable *t = RHASH_TBL(self);
-
- if (!t) return mrb_fixnum_value(0);
- return mrb_fixnum_value(t->size);
+ mrb_int size = mrb_hash_size(mrb, self);
+ return mrb_fixnum_value(size);
}
MRB_API mrb_bool
diff --git a/src/kernel.c b/src/kernel.c
index ce9cd1d44..45bca7558 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -434,24 +434,12 @@ mrb_obj_extend_m(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_obj_freeze(mrb_state *mrb, mrb_value self)
{
- struct RBasic *b;
-
- switch (mrb_type(self)) {
- case MRB_TT_FALSE:
- case MRB_TT_TRUE:
- case MRB_TT_FIXNUM:
- case MRB_TT_SYMBOL:
-#ifndef MRB_WITHOUT_FLOAT
- case MRB_TT_FLOAT:
-#endif
- return self;
- default:
- break;
- }
-
- b = mrb_basic_ptr(self);
- if (!MRB_FROZEN_P(b)) {
- MRB_SET_FROZEN_FLAG(b);
+ if (!mrb_immediate_p(self)) {
+ struct RBasic *b = mrb_basic_ptr(self);
+ if (!MRB_FROZEN_P(b)) {
+ MRB_SET_FROZEN_FLAG(b);
+ if (b->c->tt == MRB_TT_SCLASS) MRB_SET_FROZEN_FLAG(b->c);
+ }
}
return self;
}
@@ -459,26 +447,7 @@ mrb_obj_freeze(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_obj_frozen(mrb_state *mrb, mrb_value self)
{
- struct RBasic *b;
-
- switch (mrb_type(self)) {
- case MRB_TT_FALSE:
- case MRB_TT_TRUE:
- case MRB_TT_FIXNUM:
- case MRB_TT_SYMBOL:
-#ifndef MRB_WITHOUT_FLOAT
- case MRB_TT_FLOAT:
-#endif
- return mrb_true_value();
- default:
- break;
- }
-
- b = mrb_basic_ptr(self);
- if (!MRB_FROZEN_P(b)) {
- return mrb_false_value();
- }
- return mrb_true_value();
+ return mrb_bool_value(mrb_immediate_p(self) || MRB_FROZEN_P(mrb_basic_ptr(self)));
}
/* 15.3.1.3.15 */
@@ -492,7 +461,7 @@ mrb_obj_frozen(mrb_state *mrb, mrb_value self)
* <code>Hash</code>. Any hash value that exceeds the capacity of a
* <code>Fixnum</code> will be truncated before being used.
*/
-MRB_API mrb_value
+static mrb_value
mrb_obj_hash(mrb_state *mrb, mrb_value self)
{
return mrb_fixnum_value(mrb_obj_id(self));
@@ -640,16 +609,6 @@ mrb_f_raise(mrb_state *mrb, mrb_value self)
return mrb_nil_value(); /* not reached */
}
-static mrb_value
-mrb_krn_class_defined(mrb_state *mrb, mrb_value self)
-{
- mrb_value str;
-
- mrb_get_args(mrb, "S", &str);
- return mrb_bool_value(mrb_class_defined(mrb, RSTRING_PTR(str)));
-}
-
-
/* 15.3.1.3.41 */
/*
* call-seq:
@@ -847,8 +806,6 @@ mrb_init_kernel(mrb_state *mrb)
mrb_define_method(mrb, krn, "__to_int", mrb_to_int, MRB_ARGS_NONE()); /* internal */
mrb_define_method(mrb, krn, "__to_str", mrb_to_str, MRB_ARGS_NONE()); /* internal */
- mrb_define_method(mrb, krn, "class_defined?", mrb_krn_class_defined, MRB_ARGS_REQ(1));
-
mrb_include_module(mrb, mrb->object_class, mrb->kernel_module);
mrb_define_alias(mrb, mrb->module_class, "dup", "clone"); /* XXX */
}
diff --git a/src/load.c b/src/load.c
index 559fff1d4..70f18da31 100644
--- a/src/load.c
+++ b/src/load.c
@@ -7,6 +7,7 @@
#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#include <math.h>
#include <mruby/dump.h>
#include <mruby/irep.h>
#include <mruby/proc.h>
@@ -40,6 +41,23 @@ offset_crc_body(void)
return ((uint8_t *)header.binary_crc - (uint8_t *)&header) + sizeof(header.binary_crc);
}
+#ifndef MRB_WITHOUT_FLOAT
+static double
+str_to_double(mrb_state *mrb, mrb_value str)
+{
+ const char *p = RSTRING_PTR(str);
+ mrb_int len = RSTRING_LEN(str);
+
+ /* `i`, `inf`, `infinity` */
+ if (len > 0 && p[0] == 'i') return INFINITY;
+
+ /* `I`, `-inf`, `-infinity` */
+ if (p[0] == 'I' || (len > 1 && p[0] == '-' && p[1] == 'i')) return -INFINITY;
+
+ return mrb_str_to_dbl(mrb, str, TRUE);
+}
+#endif
+
static mrb_irep*
read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags)
{
@@ -125,7 +143,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
#ifndef MRB_WITHOUT_FLOAT
case IREP_TT_FLOAT:
- irep->pool[i] = mrb_float_pool(mrb, mrb_str_to_dbl(mrb, s, FALSE));
+ irep->pool[i] = mrb_float_pool(mrb, str_to_double(mrb, s));
break;
#endif
@@ -299,7 +317,6 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *
for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
mrb_irep_debug_info_file *file;
uint16_t filename_idx;
- mrb_int len;
file = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*file));
irep->debug_info->files[f_idx] = file;
@@ -312,8 +329,6 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *
bin += sizeof(uint16_t);
mrb_assert(filename_idx < filenames_len);
file->filename_sym = filenames[filename_idx];
- len = 0;
- file->filename = mrb_sym2name_len(mrb, file->filename_sym, &len);
file->line_entry_count = bin_to_uint32(bin);
bin += sizeof(uint32_t);
@@ -593,7 +608,7 @@ read_irep(mrb_state *mrb, const uint8_t *bin, uint8_t flags)
mrb_irep*
mrb_read_irep(mrb_state *mrb, const uint8_t *bin)
{
-#ifdef MRB_USE_ETEXT_EDATA
+#if defined(MRB_USE_ETEXT_EDATA) || defined(MRB_USE_CUSTOM_RO_DATA_P)
uint8_t flags = mrb_ro_data_p((char*)bin) ? FLAG_SRC_STATIC : FLAG_SRC_MALLOC;
#else
uint8_t flags = FLAG_SRC_STATIC;
diff --git a/src/mruby_core.rake b/src/mruby_core.rake
index 3024c8544..73fddb220 100644
--- a/src/mruby_core.rake
+++ b/src/mruby_core.rake
@@ -5,7 +5,6 @@ MRuby.each_target do
objs = Dir.glob("#{current_dir}/*.c").map { |f|
next nil if cxx_exception_enabled? and f =~ /(error|vm).c$/
- next nil if self.cc.defines.flatten.include?("MRB_WITHOUT_FLOAT") and f =~ /fmt_fp.c$/
objfile(f.pathmap("#{current_build_dir}/%n"))
}.compact
diff --git a/src/numeric.c b/src/numeric.c
index 3624831cc..101b338de 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -10,6 +10,7 @@
#endif
#include <limits.h>
#include <stdlib.h>
+#include <string.h>
#include <mruby.h>
#include <mruby/array.h>
@@ -23,9 +24,9 @@
#define floor(f) floorf(f)
#define ceil(f) ceilf(f)
#define fmod(x,y) fmodf(x,y)
-#define MRB_FLO_TO_STR_FMT "%.8g"
+#define FLO_TO_STR_PREC 8
#else
-#define MRB_FLO_TO_STR_FMT "%.16g"
+#define FLO_TO_STR_PREC 16
#endif
#endif
@@ -153,6 +154,22 @@ num_div(mrb_state *mrb, mrb_value x)
#endif
}
+static mrb_value
+num_coerce_step_counter(mrb_state *mrb, mrb_value self)
+{
+ mrb_value counter = self, num, step;
+
+ mrb_get_args(mrb, "oo", &num, &step);
+
+#ifndef MRB_WITHOUT_FLOAT
+ if (mrb_float_p(self) || mrb_float_p(num) || mrb_float_p(step)) {
+ counter = mrb_funcall(mrb, counter, "to_f", 0);
+ }
+#endif
+
+ return counter;
+}
+
#ifndef MRB_WITHOUT_FLOAT
/********************************************************************
*
@@ -177,10 +194,49 @@ num_div(mrb_state *mrb, mrb_value x)
static mrb_value
flo_to_s(mrb_state *mrb, mrb_value flt)
{
- if (isnan(mrb_float(flt))) {
+ mrb_float f = mrb_float(flt);
+
+ if (isinf(f)) {
+ return f < 0 ? mrb_str_new_lit(mrb, "-Infinity")
+ : mrb_str_new_lit(mrb, "Infinity");
+ }
+ else if (isnan(f)) {
return mrb_str_new_lit(mrb, "NaN");
}
- return mrb_float_to_str(mrb, flt, MRB_FLO_TO_STR_FMT);
+ else {
+ char fmt[] = "%." MRB_STRINGIZE(FLO_TO_STR_PREC) "g";
+ mrb_value str = mrb_float_to_str(mrb, flt, fmt);
+ mrb_int len;
+ char *begp, *p, *endp;
+
+ insert_dot_zero:
+ begp = RSTRING_PTR(str);
+ len = RSTRING_LEN(str);
+ for (p = begp, endp = p + len; p < endp; ++p) {
+ if (*p == '.') {
+ return str;
+ }
+ else if (*p == 'e') {
+ ptrdiff_t e_pos = p - begp;
+ mrb_str_cat(mrb, str, ".0", 2);
+ p = RSTRING_PTR(str) + e_pos;
+ memmove(p + 2, p, len - e_pos);
+ memcpy(p, ".0", 2);
+ return str;
+ }
+ }
+
+ if (FLO_TO_STR_PREC + (begp[0] == '-') <= len) {
+ --fmt[sizeof(fmt) - 3]; /* %.16g(%.8g) -> %.15g(%.7g) */
+ str = mrb_float_to_str(mrb, flt, fmt);
+ goto insert_dot_zero;
+ }
+ else {
+ mrb_str_cat(mrb, str, ".0", 2);
+ }
+
+ return str;
+ }
}
/* 15.2.9.3.2 */
@@ -313,7 +369,7 @@ flo_eql(mrb_state *mrb, mrb_value x)
mrb_get_args(mrb, "o", &y);
if (!mrb_float_p(y)) return mrb_false_value();
- return mrb_bool_value(mrb_float(x) == (mrb_float)mrb_fixnum(y));
+ return mrb_bool_value(mrb_float(x) == mrb_float(y));
}
/* 15.2.9.3.7 */
@@ -454,7 +510,7 @@ flo_shift(mrb_state *mrb, mrb_value x, mrb_int width)
}
static mrb_value
-flo_lshift(mrb_state *mrb, mrb_value x)
+flo_rshift(mrb_state *mrb, mrb_value x)
{
mrb_int width;
@@ -463,7 +519,7 @@ flo_lshift(mrb_state *mrb, mrb_value x)
}
static mrb_value
-flo_rshift(mrb_state *mrb, mrb_value x)
+flo_lshift(mrb_state *mrb, mrb_value x)
{
mrb_int width;
@@ -1150,7 +1206,7 @@ fix_to_f(mrb_state *mrb, mrb_value num)
* (in particular infinite or NaN)
* to numerical classes which don't support them.
*
- * Float::INFINITY.to_r
+ * Float::INFINITY.to_i
*
* <em>raises the exception:</em>
*
@@ -1169,17 +1225,12 @@ mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x)
else {
mrb_float d = mrb_float(x);
- if (isinf(d)) {
- mrb_raise(mrb, E_FLOATDOMAIN_ERROR, d < 0 ? "-Infinity" : "Infinity");
- }
- if (isnan(d)) {
- mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN");
- }
+ mrb_check_num_exact(mrb, d);
if (FIXABLE_FLOAT(d)) {
z = (mrb_int)d;
}
else {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "number (%S) too big for integer", x);
+ mrb_raisef(mrb, E_RANGE_ERROR, "number (%S) too big for integer", x);
}
}
return mrb_fixnum_value(z);
@@ -1487,11 +1538,13 @@ flo_plus(mrb_state *mrb, mrb_value x)
void
mrb_init_numeric(mrb_state *mrb)
{
- struct RClass *numeric, *integer, *fixnum;
+ struct RClass *numeric, *integer, *fixnum, *integral;
#ifndef MRB_WITHOUT_FLOAT
struct RClass *fl;
#endif
+ integral = mrb_define_module(mrb, "Integral");
+
/* Numeric Class */
numeric = mrb_define_class(mrb, "Numeric", mrb->object_class); /* 15.2.7 */
@@ -1505,12 +1558,14 @@ mrb_init_numeric(mrb_state *mrb)
mrb_define_method(mrb, numeric, ">=", num_ge, MRB_ARGS_REQ(1));
mrb_define_method(mrb, numeric, "finite?", num_finite_p, MRB_ARGS_NONE());
mrb_define_method(mrb, numeric, "infinite?",num_infinite_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, numeric, "__coerce_step_counter", num_coerce_step_counter, MRB_ARGS_REQ(2));
/* Integer Class */
integer = mrb_define_class(mrb, "Integer", numeric); /* 15.2.8 */
MRB_SET_INSTANCE_TT(integer, MRB_TT_FIXNUM);
mrb_undef_class_method(mrb, integer, "new");
mrb_define_method(mrb, integer, "to_i", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.24 */
+ mrb_define_method(mrb, integer, "to_int", int_to_i, MRB_ARGS_NONE());
#ifndef MRB_WITHOUT_FLOAT
mrb_define_method(mrb, integer, "ceil", int_to_i, MRB_ARGS_REQ(1)); /* 15.2.8.3.8 (x) */
mrb_define_method(mrb, integer, "floor", int_to_i, MRB_ARGS_REQ(1)); /* 15.2.8.3.10 (x) */
@@ -1553,8 +1608,8 @@ mrb_init_numeric(mrb_state *mrb)
mrb_define_method(mrb, fl, "&", flo_and, MRB_ARGS_REQ(1));
mrb_define_method(mrb, fl, "|", flo_or, MRB_ARGS_REQ(1));
mrb_define_method(mrb, fl, "^", flo_xor, MRB_ARGS_REQ(1));
- mrb_define_method(mrb, fl, ">>", flo_lshift, MRB_ARGS_REQ(1));
- mrb_define_method(mrb, fl, "<<", flo_rshift, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, fl, ">>", flo_rshift, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, fl, "<<", flo_lshift, MRB_ARGS_REQ(1));
mrb_define_method(mrb, fl, "ceil", flo_ceil, MRB_ARGS_NONE()); /* 15.2.9.3.8 */
mrb_define_method(mrb, fl, "finite?", flo_finite_p, MRB_ARGS_NONE()); /* 15.2.9.3.9 */
mrb_define_method(mrb, fl, "floor", flo_floor, MRB_ARGS_NONE()); /* 15.2.9.3.10 */
@@ -1562,6 +1617,7 @@ mrb_init_numeric(mrb_state *mrb)
mrb_define_method(mrb, fl, "round", flo_round, MRB_ARGS_OPT(1)); /* 15.2.9.3.12 */
mrb_define_method(mrb, fl, "to_f", flo_to_f, MRB_ARGS_NONE()); /* 15.2.9.3.13 */
mrb_define_method(mrb, fl, "to_i", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.14 */
+ mrb_define_method(mrb, fl, "to_int", flo_truncate, MRB_ARGS_NONE());
mrb_define_method(mrb, fl, "truncate", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.15 */
mrb_define_method(mrb, fl, "divmod", flo_divmod, MRB_ARGS_REQ(1));
mrb_define_method(mrb, fl, "eql?", flo_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */
@@ -1576,6 +1632,7 @@ mrb_init_numeric(mrb_state *mrb)
#ifdef NAN
mrb_define_const(mrb, fl, "NAN", mrb_float_value(mrb, NAN));
#endif
+
+ mrb_include_module(mrb, fl, integral);
#endif
- mrb_define_module(mrb, "Integral");
}
diff --git a/src/object.c b/src/object.c
index b764fc8ef..d45ab27c7 100644
--- a/src/object.c
+++ b/src/object.c
@@ -434,8 +434,10 @@ mrb_any_to_s(mrb_state *mrb, mrb_value obj)
mrb_str_cat_lit(mrb, str, "#<");
mrb_str_cat_cstr(mrb, str, cname);
- mrb_str_cat_lit(mrb, str, ":");
- mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_ptr(obj)));
+ if (!mrb_immediate_p(obj)) {
+ mrb_str_cat_lit(mrb, str, ":");
+ mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_ptr(obj)));
+ }
mrb_str_cat_lit(mrb, str, ">");
return str;
diff --git a/src/proc.c b/src/proc.c
index dcbeb4f62..094fff816 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -213,46 +213,11 @@ mrb_proc_init_copy(mrb_state *mrb, mrb_value self)
return self;
}
-int
-mrb_proc_cfunc_p(struct RProc *p)
-{
- return MRB_PROC_CFUNC_P(p);
-}
-
/* 15.2.17.4.2 */
static mrb_value
-mrb_proc_arity(mrb_state *mrb, mrb_value self)
+proc_arity(mrb_state *mrb, mrb_value self)
{
- struct RProc *p = mrb_proc_ptr(self);
- struct mrb_irep *irep;
- mrb_code *pc;
- mrb_aspec aspec;
- int ma, op, ra, pa, arity;
-
- if (MRB_PROC_CFUNC_P(p)) {
- /* TODO cfunc aspec not implemented yet */
- return mrb_fixnum_value(-1);
- }
-
- irep = p->body.irep;
- if (!irep) {
- return mrb_fixnum_value(0);
- }
-
- pc = irep->iseq;
- /* arity is depend on OP_ENTER */
- if (*pc != OP_ENTER) {
- return mrb_fixnum_value(0);
- }
-
- aspec = PEEK_W(pc+1);
- ma = MRB_ASPEC_REQ(aspec);
- op = MRB_ASPEC_OPT(aspec);
- ra = MRB_ASPEC_REST(aspec);
- pa = MRB_ASPEC_POST(aspec);
- arity = ra || (MRB_PROC_STRICT_P(p) && op) ? -(ma + pa + 1) : ma + pa;
-
- return mrb_fixnum_value(arity);
+ return mrb_fixnum_value(mrb_proc_arity(mrb_proc_ptr(self)));
}
/* 15.3.1.2.6 */
@@ -287,6 +252,40 @@ proc_lambda(mrb_state *mrb, mrb_value self)
return blk;
}
+mrb_int
+mrb_proc_arity(const struct RProc *p)
+{
+ struct mrb_irep *irep;
+ mrb_code *pc;
+ mrb_aspec aspec;
+ int ma, op, ra, pa, arity;
+
+ if (MRB_PROC_CFUNC_P(p)) {
+ /* TODO cfunc aspec not implemented yet */
+ return -1;
+ }
+
+ irep = p->body.irep;
+ if (!irep) {
+ return 0;
+ }
+
+ pc = irep->iseq;
+ /* arity is depend on OP_ENTER */
+ if (*pc != OP_ENTER) {
+ return 0;
+ }
+
+ aspec = PEEK_W(pc+1);
+ ma = MRB_ASPEC_REQ(aspec);
+ op = MRB_ASPEC_OPT(aspec);
+ ra = MRB_ASPEC_REST(aspec);
+ pa = MRB_ASPEC_POST(aspec);
+ arity = ra || (MRB_PROC_STRICT_P(p) && op) ? -(ma + pa + 1) : ma + pa;
+
+ return arity;
+}
+
void
mrb_init_proc(mrb_state *mrb)
{
@@ -301,15 +300,15 @@ mrb_init_proc(mrb_state *mrb)
call_irep->ilen = 1;
call_irep->nregs = 2; /* receiver and block */
- mrb_define_class_method(mrb, mrb->proc_class, "new", mrb_proc_s_new, MRB_ARGS_ANY());
+ mrb_define_class_method(mrb, mrb->proc_class, "new", mrb_proc_s_new, MRB_ARGS_NONE()|MRB_ARGS_BLOCK());
mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1));
- mrb_define_method(mrb, mrb->proc_class, "arity", mrb_proc_arity, MRB_ARGS_NONE());
+ mrb_define_method(mrb, mrb->proc_class, "arity", proc_arity, MRB_ARGS_NONE());
p = mrb_proc_new(mrb, call_irep);
MRB_METHOD_FROM_PROC(m, p);
mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "call"), m);
mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "[]"), m);
- mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.2.6 */
- mrb_define_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.3.27 */
+ mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()|MRB_ARGS_BLOCK()); /* 15.3.1.2.6 */
+ mrb_define_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()|MRB_ARGS_BLOCK()); /* 15.3.1.3.27 */
}
diff --git a/src/range.c b/src/range.c
index e45308d35..21771c8ec 100644
--- a/src/range.c
+++ b/src/range.c
@@ -10,19 +10,12 @@
#include <mruby/string.h>
#include <mruby/array.h>
-MRB_API struct RRange*
-mrb_range_ptr(mrb_state *mrb, mrb_value v)
-{
- struct RRange *r = (struct RRange*)mrb_ptr(v);
-
- if (r->edges == NULL) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized range");
- }
- return r;
-}
+#define RANGE_INITIALIZED_MASK 1
+#define RANGE_INITIALIZED(p) ((p)->flags |= RANGE_INITIALIZED_MASK)
+#define RANGE_INITIALIZED_P(p) ((p)->flags & RANGE_INITIALIZED_MASK)
static void
-range_check(mrb_state *mrb, mrb_value a, mrb_value b)
+r_check(mrb_state *mrb, mrb_value a, mrb_value b)
{
mrb_value ans;
enum mrb_vtype ta;
@@ -46,18 +39,83 @@ range_check(mrb_state *mrb, mrb_value a, mrb_value b)
}
}
-MRB_API mrb_value
-mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, mrb_bool excl)
+static mrb_bool
+r_le(mrb_state *mrb, mrb_value a, mrb_value b)
{
- struct RRange *r;
+ mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
+ /* output :a < b => -1, a = b => 0, a > b => +1 */
+
+ if (mrb_fixnum_p(r)) {
+ mrb_int c = mrb_fixnum(r);
+ if (c == 0 || c == -1) return TRUE;
+ }
+
+ return FALSE;
+}
+
+static mrb_bool
+r_gt(mrb_state *mrb, mrb_value a, mrb_value b)
+{
+ mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b);
+ /* output :a < b => -1, a = b => 0, a > b => +1 */
- range_check(mrb, beg, end);
- r = (struct RRange*)mrb_obj_alloc(mrb, MRB_TT_RANGE, mrb->range_class);
+ return mrb_fixnum_p(r) && mrb_fixnum(r) == 1;
+}
+
+static mrb_bool
+r_ge(mrb_state *mrb, mrb_value a, mrb_value b)
+{
+ mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
+ /* output :a < b => -1, a = b => 0, a > b => +1 */
+
+ if (mrb_fixnum_p(r)) {
+ mrb_int c = mrb_fixnum(r);
+ if (c == 0 || c == 1) return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+range_ptr_alloc_edges(mrb_state *mrb, struct RRange *r)
+{
+#ifndef MRB_RANGE_EMBED
r->edges = (mrb_range_edges *)mrb_malloc(mrb, sizeof(mrb_range_edges));
- r->edges->beg = beg;
- r->edges->end = end;
- r->excl = excl;
- return mrb_range_value(r);
+#endif
+}
+
+static struct RRange *
+range_ptr_init(mrb_state *mrb, struct RRange *r, mrb_value beg, mrb_value end, mrb_bool excl)
+{
+ r_check(mrb, beg, end);
+
+ if (r) {
+ if (RANGE_INITIALIZED_P(r)) {
+ /* Ranges are immutable, so that they should be initialized only once. */
+ mrb_name_error(mrb, mrb_intern_lit(mrb, "initialize"), "`initialize' called twice");
+ }
+ else {
+ range_ptr_alloc_edges(mrb, r);
+ }
+ }
+ else {
+ r = (struct RRange*)mrb_obj_alloc(mrb, MRB_TT_RANGE, mrb->range_class);
+ range_ptr_alloc_edges(mrb, r);
+ }
+
+ RANGE_BEG(r) = beg;
+ RANGE_END(r) = end;
+ RANGE_EXCL(r) = excl;
+ RANGE_INITIALIZED(r);
+
+ return r;
+}
+
+static void
+range_ptr_replace(mrb_state *mrb, struct RRange *r, mrb_value beg, mrb_value end, mrb_bool excl)
+{
+ range_ptr_init(mrb, r, beg, end, excl);
+ mrb_write_barrier(mrb, (struct RBasic*)r);
}
/*
@@ -67,12 +125,10 @@ mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, mrb_bool excl)
*
* Returns the first object in <i>rng</i>.
*/
-mrb_value
-mrb_range_beg(mrb_state *mrb, mrb_value range)
+static mrb_value
+range_beg(mrb_state *mrb, mrb_value range)
{
- struct RRange *r = mrb_range_ptr(mrb, range);
-
- return r->edges->beg;
+ return mrb_range_beg(mrb, range);
}
/*
@@ -85,13 +141,10 @@ mrb_range_beg(mrb_state *mrb, mrb_value range)
* (1..10).end #=> 10
* (1...10).end #=> 10
*/
-
-mrb_value
-mrb_range_end(mrb_state *mrb, mrb_value range)
+static mrb_value
+range_end(mrb_state *mrb, mrb_value range)
{
- struct RRange *r = mrb_range_ptr(mrb, range);
-
- return r->edges->end;
+ return mrb_range_end(mrb, range);
}
/*
@@ -100,28 +153,12 @@ mrb_range_end(mrb_state *mrb, mrb_value range)
*
* Returns <code>true</code> if <i>range</i> excludes its end value.
*/
-mrb_value
-mrb_range_excl(mrb_state *mrb, mrb_value range)
+static mrb_value
+range_excl(mrb_state *mrb, mrb_value range)
{
- struct RRange *r = mrb_range_ptr(mrb, range);
-
- return mrb_bool_value(r->excl);
+ return mrb_bool_value(mrb_range_excl_p(mrb, range));
}
-static void
-range_init(mrb_state *mrb, mrb_value range, mrb_value beg, mrb_value end, mrb_bool exclude_end)
-{
- struct RRange *r = mrb_range_raw_ptr(range);
-
- range_check(mrb, beg, end);
- r->excl = exclude_end;
- if (!r->edges) {
- r->edges = (mrb_range_edges *)mrb_malloc(mrb, sizeof(mrb_range_edges));
- }
- r->edges->beg = beg;
- r->edges->end = end;
- mrb_write_barrier(mrb, (struct RBasic*)r);
-}
/*
* call-seq:
* Range.new(start, end, exclusive=false) => range
@@ -130,25 +167,17 @@ range_init(mrb_state *mrb, mrb_value range, mrb_value beg, mrb_value end, mrb_bo
* parameter is omitted or is <code>false</code>, the <i>range</i> will include
* the end object; otherwise, it will be excluded.
*/
-
-mrb_value
-mrb_range_initialize(mrb_state *mrb, mrb_value range)
+static mrb_value
+range_initialize(mrb_state *mrb, mrb_value range)
{
mrb_value beg, end;
- mrb_bool exclusive;
- mrb_int n;
+ mrb_bool exclusive = FALSE;
- n = mrb_get_args(mrb, "oo|b", &beg, &end, &exclusive);
- if (n != 3) {
- exclusive = FALSE;
- }
- /* Ranges are immutable, so that they should be initialized only once. */
- if (mrb_range_raw_ptr(range)->edges) {
- mrb_name_error(mrb, mrb_intern_lit(mrb, "initialize"), "`initialize' called twice");
- }
- range_init(mrb, range, beg, end, exclusive);
+ mrb_get_args(mrb, "oo|b", &beg, &end, &exclusive);
+ range_ptr_replace(mrb, mrb_range_raw_ptr(range), beg, end, exclusive);
return range;
}
+
/*
* call-seq:
* range == obj => true or false
@@ -161,11 +190,9 @@ mrb_range_initialize(mrb_state *mrb, mrb_value range)
* (0..2) == (0..2) #=> true
* (0..2) == Range.new(0,2) #=> true
* (0..2) == (0...2) #=> false
- *
*/
-
-mrb_value
-mrb_range_eq(mrb_state *mrb, mrb_value range)
+static mrb_value
+range_eq(mrb_state *mrb, mrb_value range)
{
struct RRange *rr;
struct RRange *ro;
@@ -180,60 +207,22 @@ mrb_range_eq(mrb_state *mrb, mrb_value range)
rr = mrb_range_ptr(mrb, range);
ro = mrb_range_ptr(mrb, obj);
- v1 = mrb_funcall(mrb, rr->edges->beg, "==", 1, ro->edges->beg);
- v2 = mrb_funcall(mrb, rr->edges->end, "==", 1, ro->edges->end);
- if (!mrb_bool(v1) || !mrb_bool(v2) || rr->excl != ro->excl) {
+ v1 = mrb_funcall(mrb, RANGE_BEG(rr), "==", 1, RANGE_BEG(ro));
+ v2 = mrb_funcall(mrb, RANGE_END(rr), "==", 1, RANGE_END(ro));
+ if (!mrb_bool(v1) || !mrb_bool(v2) || RANGE_EXCL(rr) != RANGE_EXCL(ro)) {
return mrb_false_value();
}
return mrb_true_value();
}
-static mrb_bool
-r_le(mrb_state *mrb, mrb_value a, mrb_value b)
-{
- mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
- /* output :a < b => -1, a = b => 0, a > b => +1 */
-
- if (mrb_fixnum_p(r)) {
- mrb_int c = mrb_fixnum(r);
- if (c == 0 || c == -1) return TRUE;
- }
-
- return FALSE;
-}
-
-static mrb_bool
-r_gt(mrb_state *mrb, mrb_value a, mrb_value b)
-{
- mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b);
- /* output :a < b => -1, a = b => 0, a > b => +1 */
-
- return mrb_fixnum_p(r) && mrb_fixnum(r) == 1;
-}
-
-static mrb_bool
-r_ge(mrb_state *mrb, mrb_value a, mrb_value b)
-{
- mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
- /* output :a < b => -1, a = b => 0, a > b => +1 */
-
- if (mrb_fixnum_p(r)) {
- mrb_int c = mrb_fixnum(r);
- if (c == 0 || c == 1) return TRUE;
- }
-
- return FALSE;
-}
-
/*
* call-seq:
* range === obj => true or false
* range.member?(val) => true or false
* range.include?(val) => true or false
- *
*/
-mrb_value
-mrb_range_include(mrb_state *mrb, mrb_value range)
+static mrb_value
+range_include(mrb_state *mrb, mrb_value range)
{
mrb_value val;
struct RRange *r = mrb_range_ptr(mrb, range);
@@ -242,48 +231,15 @@ mrb_range_include(mrb_state *mrb, mrb_value range)
mrb_get_args(mrb, "o", &val);
- beg = r->edges->beg;
- end = r->edges->end;
- include_p = r_le(mrb, beg, val) && /* beg <= val */
- (r->excl ? r_gt(mrb, end, val) /* end > val */
- : r_ge(mrb, end, val)); /* end >= val */
+ beg = RANGE_BEG(r);
+ end = RANGE_END(r);
+ include_p = r_le(mrb, beg, val) && /* beg <= val */
+ (RANGE_EXCL(r) ? r_gt(mrb, end, val) /* end > val */
+ : r_ge(mrb, end, val)); /* end >= val */
return mrb_bool_value(include_p);
}
-MRB_API mrb_int
-mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc)
-{
- mrb_int beg, end;
- struct RRange *r;
-
- if (mrb_type(range) != MRB_TT_RANGE) return 0;
- r = mrb_range_ptr(mrb, range);
-
- beg = mrb_int(mrb, r->edges->beg);
- end = mrb_int(mrb, r->edges->end);
-
- if (beg < 0) {
- beg += len;
- if (beg < 0) return 2;
- }
-
- if (trunc) {
- if (beg > len) return 2;
- if (end > len) end = len;
- }
-
- if (end < 0) end += len;
- if (!r->excl && (!trunc || end < len))
- end++; /* include end point */
- len = end - beg;
- if (len < 0) len = 0;
-
- *begp = beg;
- *lenp = len;
- return 1;
-}
-
/* 15.2.14.4.12(x) */
/*
* call-seq:
@@ -291,17 +247,16 @@ mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp,
*
* Convert this range object to a printable form.
*/
-
static mrb_value
range_to_s(mrb_state *mrb, mrb_value range)
{
mrb_value str, str2;
struct RRange *r = mrb_range_ptr(mrb, range);
- str = mrb_obj_as_string(mrb, r->edges->beg);
- str2 = mrb_obj_as_string(mrb, r->edges->end);
+ str = mrb_obj_as_string(mrb, RANGE_BEG(r));
+ str2 = mrb_obj_as_string(mrb, RANGE_END(r));
str = mrb_str_dup(mrb, str);
- mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2);
+ mrb_str_cat(mrb, str, "...", RANGE_EXCL(r) ? 3 : 2);
mrb_str_cat_str(mrb, str, str2);
return str;
@@ -316,17 +271,16 @@ range_to_s(mrb_state *mrb, mrb_value range)
* <code>inspect</code> to convert the start and end
* objects).
*/
-
static mrb_value
range_inspect(mrb_state *mrb, mrb_value range)
{
mrb_value str, str2;
struct RRange *r = mrb_range_ptr(mrb, range);
- str = mrb_inspect(mrb, r->edges->beg);
- str2 = mrb_inspect(mrb, r->edges->end);
+ str = mrb_inspect(mrb, RANGE_BEG(r));
+ str2 = mrb_inspect(mrb, RANGE_END(r));
str = mrb_str_dup(mrb, str);
- mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2);
+ mrb_str_cat(mrb, str, "...", RANGE_EXCL(r) ? 3 : 2);
mrb_str_cat_str(mrb, str, str2);
return str;
@@ -344,9 +298,7 @@ range_inspect(mrb_state *mrb, mrb_value range)
* (0..2).eql?(0..2) #=> true
* (0..2).eql?(Range.new(0,2)) #=> true
* (0..2).eql?(0...2) #=> false
- *
*/
-
static mrb_value
range_eql(mrb_state *mrb, mrb_value range)
{
@@ -356,16 +308,14 @@ range_eql(mrb_state *mrb, mrb_value range)
mrb_get_args(mrb, "o", &obj);
if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
- if (!mrb_obj_is_kind_of(mrb, obj, mrb->range_class)) {
- return mrb_false_value();
- }
+ if (!mrb_obj_is_kind_of(mrb, obj, mrb->range_class)) return mrb_false_value();
if (mrb_type(obj) != MRB_TT_RANGE) return mrb_false_value();
r = mrb_range_ptr(mrb, range);
o = mrb_range_ptr(mrb, obj);
- if (!mrb_eql(mrb, r->edges->beg, o->edges->beg) ||
- !mrb_eql(mrb, r->edges->end, o->edges->end) ||
- (r->excl != o->excl)) {
+ if (!mrb_eql(mrb, RANGE_BEG(r), RANGE_BEG(o)) ||
+ !mrb_eql(mrb, RANGE_END(r), RANGE_END(o)) ||
+ (RANGE_EXCL(r) != RANGE_EXCL(o))) {
return mrb_false_value();
}
return mrb_true_value();
@@ -386,7 +336,7 @@ range_initialize_copy(mrb_state *mrb, mrb_value copy)
}
r = mrb_range_ptr(mrb, src);
- range_init(mrb, copy, r->edges->beg, r->edges->end, r->excl);
+ range_ptr_replace(mrb, mrb_range_raw_ptr(copy), RANGE_BEG(r), RANGE_END(r), RANGE_EXCL(r));
return copy;
}
@@ -421,6 +371,66 @@ mrb_get_values_at(mrb_state *mrb, mrb_value obj, mrb_int olen, mrb_int argc, con
}
void
+mrb_gc_mark_range(mrb_state *mrb, struct RRange *r)
+{
+ if (RANGE_INITIALIZED_P(r)) {
+ mrb_gc_mark_value(mrb, RANGE_BEG(r));
+ mrb_gc_mark_value(mrb, RANGE_END(r));
+ }
+}
+
+MRB_API struct RRange*
+mrb_range_ptr(mrb_state *mrb, mrb_value range)
+{
+ struct RRange *r = mrb_range_raw_ptr(range);
+
+ /* check for if #initialize_copy was removed [#3320] */
+ if (!RANGE_INITIALIZED_P(r)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized range");
+ }
+ return r;
+}
+
+MRB_API mrb_value
+mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, mrb_bool excl)
+{
+ struct RRange *r = range_ptr_init(mrb, NULL, beg, end, excl);
+ return mrb_range_value(r);
+}
+
+MRB_API mrb_int
+mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc)
+{
+ mrb_int beg, end;
+ struct RRange *r;
+
+ if (mrb_type(range) != MRB_TT_RANGE) return 0;
+ r = mrb_range_ptr(mrb, range);
+
+ beg = mrb_int(mrb, RANGE_BEG(r));
+ end = mrb_int(mrb, RANGE_END(r));
+
+ if (beg < 0) {
+ beg += len;
+ if (beg < 0) return 2;
+ }
+
+ if (trunc) {
+ if (beg > len) return 2;
+ if (end > len) end = len;
+ }
+
+ if (end < 0) end += len;
+ if (!RANGE_EXCL(r) && (!trunc || end < len)) end++; /* include end point */
+ len = end - beg;
+ if (len < 0) len = 0;
+
+ *begp = beg;
+ *lenp = len;
+ return 1;
+}
+
+void
mrb_init_range(mrb_state *mrb)
{
struct RClass *r;
@@ -429,17 +439,16 @@ mrb_init_range(mrb_state *mrb)
mrb->range_class = r;
MRB_SET_INSTANCE_TT(r, MRB_TT_RANGE);
- mrb_define_method(mrb, r, "begin", mrb_range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.3 */
- mrb_define_method(mrb, r, "end", mrb_range_end, MRB_ARGS_NONE()); /* 15.2.14.4.5 */
- mrb_define_method(mrb, r, "==", mrb_range_eq, MRB_ARGS_REQ(1)); /* 15.2.14.4.1 */
- mrb_define_method(mrb, r, "===", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.2 */
- mrb_define_method(mrb, r, "exclude_end?", mrb_range_excl, MRB_ARGS_NONE()); /* 15.2.14.4.6 */
- mrb_define_method(mrb, r, "first", mrb_range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.7 */
- mrb_define_method(mrb, r, "include?", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.8 */
- mrb_define_method(mrb, r, "initialize", mrb_range_initialize, MRB_ARGS_ANY()); /* 15.2.14.4.9 */
- mrb_define_method(mrb, r, "last", mrb_range_end, MRB_ARGS_NONE()); /* 15.2.14.4.10 */
- mrb_define_method(mrb, r, "member?", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.11 */
-
+ mrb_define_method(mrb, r, "begin", range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.3 */
+ mrb_define_method(mrb, r, "end", range_end, MRB_ARGS_NONE()); /* 15.2.14.4.5 */
+ mrb_define_method(mrb, r, "==", range_eq, MRB_ARGS_REQ(1)); /* 15.2.14.4.1 */
+ mrb_define_method(mrb, r, "===", range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.2 */
+ mrb_define_method(mrb, r, "exclude_end?", range_excl, MRB_ARGS_NONE()); /* 15.2.14.4.6 */
+ mrb_define_method(mrb, r, "first", range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.7 */
+ mrb_define_method(mrb, r, "include?", range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.8 */
+ mrb_define_method(mrb, r, "initialize", range_initialize, MRB_ARGS_ANY()); /* 15.2.14.4.9 */
+ mrb_define_method(mrb, r, "last", range_end, MRB_ARGS_NONE()); /* 15.2.14.4.10 */
+ mrb_define_method(mrb, r, "member?", range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.11 */
mrb_define_method(mrb, r, "to_s", range_to_s, MRB_ARGS_NONE()); /* 15.2.14.4.12(x) */
mrb_define_method(mrb, r, "inspect", range_inspect, MRB_ARGS_NONE()); /* 15.2.14.4.13(x) */
mrb_define_method(mrb, r, "eql?", range_eql, MRB_ARGS_REQ(1)); /* 15.2.14.4.14(x) */
diff --git a/src/state.c b/src/state.c
index 5583a77e5..08d7ba906 100644
--- a/src/state.c
+++ b/src/state.c
@@ -26,6 +26,7 @@ mrb_open_core(mrb_allocf f, void *ud)
static const struct mrb_context mrb_context_zero = { 0 };
mrb_state *mrb;
+ if (f == NULL) f = mrb_default_allocf;
mrb = (mrb_state *)(f)(NULL, NULL, sizeof(mrb_state), ud);
if (mrb == NULL) return NULL;
diff --git a/src/string.c b/src/string.c
index 2668a2c85..f043bfd5a 100644
--- a/src/string.c
+++ b/src/string.c
@@ -20,6 +20,7 @@
#include <mruby/class.h>
#include <mruby/range.h>
#include <mruby/string.h>
+#include <mruby/numeric.h>
#include <mruby/re.h>
typedef struct mrb_shared_string {
@@ -156,13 +157,6 @@ mrb_str_new(mrb_state *mrb, const char *p, size_t len)
return mrb_obj_value(str_new(mrb, p, len));
}
-/*
- * call-seq: (Caution! NULL string)
- * String.new(str="") => new_str
- *
- * Returns a new string object containing a copy of <i>str</i>.
- */
-
MRB_API mrb_value
mrb_str_new_cstr(mrb_state *mrb, const char *p)
{
@@ -238,27 +232,36 @@ utf8len(const char* p, const char* e)
return len;
}
-static mrb_int
-utf8_strlen(mrb_value str, mrb_int len)
+mrb_int
+mrb_utf8_len(const char *str, mrb_int byte_len)
{
mrb_int total = 0;
- char* p = RSTRING_PTR(str);
- char* e = p;
- if (RSTRING(str)->flags & MRB_STR_NO_UTF) {
- return RSTRING_LEN(str);
- }
- e += len < 0 ? RSTRING_LEN(str) : len;
- while (p<e) {
+ const char *p = str;
+ const char *e = p + byte_len;
+
+ while (p < e) {
p += utf8len(p, e);
total++;
}
- if (RSTRING_LEN(str) == total) {
- RSTRING(str)->flags |= MRB_STR_NO_UTF;
- }
return total;
}
-#define RSTRING_CHAR_LEN(s) utf8_strlen(s, -1)
+static mrb_int
+utf8_strlen(mrb_value str)
+{
+ mrb_int byte_len = RSTRING_LEN(str);
+
+ if (RSTRING(str)->flags & MRB_STR_NO_UTF) {
+ return byte_len;
+ }
+ else {
+ mrb_int utf8_len = mrb_utf8_len(RSTRING_PTR(str), byte_len);
+ if (byte_len == utf8_len) RSTRING(str)->flags |= MRB_STR_NO_UTF;
+ return utf8_len;
+ }
+}
+
+#define RSTRING_CHAR_LEN(s) utf8_strlen(s)
/* map character index to byte offset index */
static mrb_int
@@ -490,20 +493,12 @@ str_index_str(mrb_state *mrb, mrb_value str, mrb_value str2, mrb_int offset)
return mrb_str_index(mrb, str, ptr, len, offset);
}
-static void
-check_frozen(mrb_state *mrb, struct RString *s)
-{
- if (MRB_FROZEN_P(s)) {
- mrb_raise(mrb, E_FROZEN_ERROR, "can't modify frozen string");
- }
-}
-
static mrb_value
str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
{
mrb_int len;
- check_frozen(mrb, s1);
+ mrb_check_frozen(mrb, s1);
if (s1 == s2) return mrb_obj_value(s1);
s1->flags &= ~MRB_STR_NO_UTF;
s1->flags |= s2->flags&MRB_STR_NO_UTF;
@@ -643,7 +638,7 @@ mrb_locale_from_utf8(const char *utf8, int len)
MRB_API void
mrb_str_modify(mrb_state *mrb, struct RString *s)
{
- check_frozen(mrb, s);
+ mrb_check_frozen(mrb, s);
s->flags &= ~MRB_STR_NO_UTF;
if (RSTR_SHARED_P(s)) {
mrb_shared_string *shared = s->as.heap.aux.shared;
@@ -739,12 +734,6 @@ mrb_str_to_cstr(mrb_state *mrb, mrb_value str0)
return RSTR_PTR(s);
}
-/*
- * call-seq: (Caution! String("abcd") change)
- * String("abcdefg") = String("abcd") + String("efg")
- *
- * Returns a new string object containing a copy of <i>str</i>.
- */
MRB_API void
mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other)
{
@@ -752,12 +741,6 @@ mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other)
mrb_str_cat_str(mrb, self, other);
}
-/*
- * call-seq: (Caution! String("abcd") remain)
- * String("abcdefg") = String("abcd") + String("efg")
- *
- * Returns a new string object containing a copy of <i>str</i>.
- */
MRB_API mrb_value
mrb_str_plus(mrb_state *mrb, mrb_value a, mrb_value b)
{
@@ -775,10 +758,13 @@ mrb_str_plus(mrb_state *mrb, mrb_value a, mrb_value b)
/* 15.2.10.5.2 */
/*
- * call-seq: (Caution! String("abcd") remain) for stack_argument
- * String("abcdefg") = String("abcd") + String("efg")
+ * call-seq:
+ * str + other_str -> new_str
*
- * Returns a new string object containing a copy of <i>str</i>.
+ * Concatenation---Returns a new <code>String</code> containing
+ * <i>other_str</i> concatenated to <i>str</i>.
+ *
+ * "Hello from " + self.to_s #=> "Hello from main"
*/
static mrb_value
mrb_str_plus_m(mrb_state *mrb, mrb_value self)
@@ -979,13 +965,22 @@ mrb_str_equal_m(mrb_state *mrb, mrb_value str1)
return mrb_bool_value(mrb_str_equal(mrb, str1, str2));
}
/* ---------------------------------- */
+mrb_value mrb_mod_to_s(mrb_state *mrb, mrb_value klass);
+
MRB_API mrb_value
mrb_str_to_str(mrb_state *mrb, mrb_value str)
{
- if (!mrb_string_p(str)) {
+ switch (mrb_type(str)) {
+ case MRB_TT_STRING:
+ return str;
+ case MRB_TT_FIXNUM:
+ return mrb_fixnum_to_str(mrb, str, 10);
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ return mrb_mod_to_s(mrb, str);
+ default:
return mrb_convert_type(mrb, str, MRB_TT_STRING, "String", "to_s");
}
- return str;
}
MRB_API const char*
@@ -1002,20 +997,6 @@ mrb_string_value_len(mrb_state *mrb, mrb_value ptr)
return RSTRING_LEN(ptr);
}
-void
-mrb_noregexp(mrb_state *mrb, mrb_value self)
-{
- mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp class not implemented");
-}
-
-void
-mrb_regexp_check(mrb_state *mrb, mrb_value obj)
-{
- if (mrb_regexp_p(mrb, obj)) {
- mrb_noregexp(mrb, obj);
- }
-}
-
MRB_API mrb_value
mrb_str_dup(mrb_state *mrb, mrb_value str)
{
@@ -1031,7 +1012,6 @@ mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value indx)
{
mrb_int idx;
- mrb_regexp_check(mrb, indx);
switch (mrb_type(indx)) {
case MRB_TT_FIXNUM:
idx = mrb_fixnum(indx);
@@ -1124,13 +1104,9 @@ mrb_str_aref_m(mrb_state *mrb, mrb_value str)
if (argc == 2) {
mrb_int n1, n2;
- mrb_regexp_check(mrb, a1);
mrb_get_args(mrb, "ii", &n1, &n2);
return str_substr(mrb, str, n1, n2);
}
- if (argc != 1) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 1)", mrb_fixnum_value(argc));
- }
return mrb_str_aref(mrb, str, a1);
}
@@ -1554,7 +1530,6 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str)
else
sub = mrb_nil_value();
}
- mrb_regexp_check(mrb, sub);
clen = RSTRING_CHAR_LEN(str);
if (pos < 0) {
pos += clen;
@@ -1587,8 +1562,6 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str)
return mrb_fixnum_value(pos);
}
-#define STR_REPLACE_SHARED_MIN 10
-
/* 15.2.10.5.24 */
/* 15.2.10.5.28 */
/*
@@ -1808,7 +1781,6 @@ mrb_str_rindex(mrb_state *mrb, mrb_value str)
if (pos < 0) {
pos += len;
if (pos < 0) {
- mrb_regexp_check(mrb, sub);
return mrb_nil_value();
}
}
@@ -1822,7 +1794,6 @@ mrb_str_rindex(mrb_state *mrb, mrb_value str)
sub = mrb_nil_value();
}
pos = chars2bytes(str, 0, pos);
- mrb_regexp_check(mrb, sub);
switch (mrb_type(sub)) {
default: {
@@ -1916,16 +1887,11 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
if (argc == 0 || mrb_nil_p(spat)) {
split_type = awk;
}
- else {
- if (mrb_string_p(spat)) {
- split_type = string;
- if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' ') {
- split_type = awk;
- }
- }
- else {
- mrb_noregexp(mrb, str);
- }
+ else if (!mrb_string_p(spat)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "expected String");
+ }
+ else if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' ') {
+ split_type = awk;
}
result = mrb_ary_new(mrb);
@@ -1962,7 +1928,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
}
}
}
- else if (split_type == string) {
+ else { /* split_type == string */
mrb_int str_len = RSTRING_LEN(str);
mrb_int pat_len = RSTRING_LEN(spat);
mrb_int idx = 0;
@@ -1983,9 +1949,6 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
}
beg = idx;
}
- else {
- mrb_noregexp(mrb, str);
- }
if (RSTRING_LEN(str) > 0 && (lim_p || RSTRING_LEN(str) > beg || lim < 0)) {
if (RSTRING_LEN(str) == beg) {
tmp = mrb_str_new_empty(mrb, str);
@@ -2005,7 +1968,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
return result;
}
-MRB_API mrb_value
+static mrb_value
mrb_str_len_to_inum(mrb_state *mrb, const char *str, mrb_int len, mrb_int base, int badcheck)
{
const char *p = str;
@@ -2149,7 +2112,7 @@ mrb_str_len_to_inum(mrb_state *mrb, const char *str, mrb_int len, mrb_int base,
else
#endif
{
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%S) too big for integer",
+ mrb_raisef(mrb, E_RANGE_ERROR, "string (%S) too big for integer",
mrb_str_new(mrb, str, pend-str));
}
}
@@ -2173,7 +2136,7 @@ mrb_str_len_to_inum(mrb_state *mrb, const char *str, mrb_int len, mrb_int base,
}
MRB_API mrb_value
-mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
+mrb_cstr_to_inum(mrb_state *mrb, const char *str, mrb_int base, mrb_bool badcheck)
{
return mrb_str_len_to_inum(mrb, str, strlen(str), base, badcheck);
}
@@ -2754,6 +2717,7 @@ mrb_init_string(mrb_state *mrb)
#endif
mrb_define_method(mrb, s, "to_i", mrb_str_to_i, MRB_ARGS_ANY()); /* 15.2.10.5.39 */
mrb_define_method(mrb, s, "to_s", mrb_str_to_s, MRB_ARGS_NONE()); /* 15.2.10.5.40 */
+ mrb_define_method(mrb, s, "to_str", mrb_str_to_s, MRB_ARGS_NONE());
mrb_define_method(mrb, s, "to_sym", mrb_str_intern, MRB_ARGS_NONE()); /* 15.2.10.5.41 */
mrb_define_method(mrb, s, "upcase", mrb_str_upcase, MRB_ARGS_NONE()); /* 15.2.10.5.42 */
mrb_define_method(mrb, s, "upcase!", mrb_str_upcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.43 */
@@ -2842,7 +2806,7 @@ mrb_float_read(const char *string, char **endPtr)
*/
p = string;
- while (isspace(*p)) {
+ while (ISSPACE(*p)) {
p += 1;
}
if (*p == '-') {
@@ -2865,7 +2829,7 @@ mrb_float_read(const char *string, char **endPtr)
for (mantSize = 0; ; mantSize += 1)
{
c = *p;
- if (!isdigit(c)) {
+ if (!ISDIGIT(c)) {
if ((c != '.') || (decPt >= 0)) {
break;
}
@@ -2950,7 +2914,7 @@ mrb_float_read(const char *string, char **endPtr)
}
expSign = FALSE;
}
- while (isdigit(*p)) {
+ while (ISDIGIT(*p)) {
exp = exp * 10 + (*p - '0');
if (exp > 19999) {
exp = 19999;
diff --git a/src/symbol.c b/src/symbol.c
index 6b4c7200c..b26f2b1fd 100644
--- a/src/symbol.c
+++ b/src/symbol.c
@@ -15,54 +15,144 @@
/* ------------------------------------------------------ */
typedef struct symbol_name {
mrb_bool lit : 1;
+ uint8_t prev;
uint16_t len;
const char *name;
} symbol_name;
-static inline khint_t
-sym_hash_func(mrb_state *mrb, mrb_sym s)
+static void
+sym_validate_len(mrb_state *mrb, size_t len)
+{
+ if (len >= RITE_LV_NULL_MARK) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "symbol length too long");
+ }
+}
+
+#ifndef MRB_ENABLE_ALL_SYMBOLS
+static const char pack_table[] = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+static mrb_sym
+sym_inline_pack(const char *name, uint16_t len)
{
- khint_t h = 0;
- size_t i, len = mrb->symtbl[s].len;
- const char *p = mrb->symtbl[s].name;
+ const int lower_length_max = (MRB_SYMBOL_BITSIZE - 2) / 5;
+ const int mix_length_max = (MRB_SYMBOL_BITSIZE - 2) / 6;
+ char c;
+ const char *p;
+ int i;
+ mrb_sym sym = 0;
+ int lower = 1;
+
+ if (len > lower_length_max) return 0; /* too long */
for (i=0; i<len; i++) {
- h = (h << 5) - h + *p++;
+ uint32_t bits;
+
+ c = name[i];
+ if (c == 0) return 0; /* NUL in name */
+ p = strchr(pack_table, (int)c);
+ if (p == 0) return 0; /* non alnum char */
+ bits = (uint32_t)(p - pack_table)+1;
+ if (bits > 27) lower = 0;
+ if (i >= mix_length_max) break;
+ sym |= bits<<(i*6+2);
}
- return h;
+ if (lower) {
+ sym = 0;
+ for (i=0; i<len; i++) {
+ uint32_t bits;
+
+ c = name[i];
+ p = strchr(pack_table, (int)c);
+ bits = (uint32_t)(p - pack_table)+1;
+ sym |= bits<<(i*5+2);
+ }
+ return sym | 3;
+ }
+ if (len > mix_length_max) return 0;
+ return sym | 1;
}
-#define sym_hash_equal(mrb,a, b) (mrb->symtbl[a].len == mrb->symtbl[b].len && memcmp(mrb->symtbl[a].name, mrb->symtbl[b].name, mrb->symtbl[a].len) == 0)
-
-KHASH_DECLARE(n2s, mrb_sym, mrb_sym, FALSE)
-KHASH_DEFINE (n2s, mrb_sym, mrb_sym, FALSE, sym_hash_func, sym_hash_equal)
-/* ------------------------------------------------------ */
-static void
-sym_validate_len(mrb_state *mrb, size_t len)
+static const char*
+sym_inline_unpack(mrb_sym sym, char *buf, mrb_int *lenp)
{
- if (len >= RITE_LV_NULL_MARK) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "symbol length too long");
+ int bit_per_char = sym&2 ? 5 : 6; /* all lower case if `sym&2` is true */
+ int i;
+
+ mrb_assert(sym&1);
+
+ for (i=0; i<30/bit_per_char; i++) {
+ uint32_t bits = sym>>(i*bit_per_char+2) & ((1<<bit_per_char)-1);
+ if (bits == 0) break;
+ buf[i] = pack_table[bits-1];;
}
+ buf[i] = '\0';
+ if (lenp) *lenp = i;
+ return buf;
+}
+#endif
+
+static uint8_t
+symhash(const char *key, size_t len)
+{
+ uint32_t hash, i;
+
+ for(hash = i = 0; i < len; ++i) {
+ hash += key[i];
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ }
+ hash += (hash << 3);
+ hash ^= (hash >> 11);
+ hash += (hash << 15);
+ return hash & 0xff;
+}
+
+static mrb_sym
+find_symbol(mrb_state *mrb, const char *name, uint16_t len, uint8_t hash)
+{
+ mrb_sym i;
+ symbol_name *sname;
+
+#ifndef MRB_ENABLE_ALL_SYMBOLS
+ /* inline symbol */
+ i = sym_inline_pack(name, len);
+ if (i > 0) return i;
+#endif
+
+ i = mrb->symhash[hash];
+ if (i == 0) return 0;
+ do {
+ sname = &mrb->symtbl[i];
+ if (sname->len == len && memcmp(sname->name, name, len) == 0) {
+ return i<<1;
+ }
+ if (sname->prev == 0xff) {
+ i -= 0xff;
+ sname = &mrb->symtbl[i];
+ while (mrb->symtbl < sname) {
+ if (sname->len == len && memcmp(sname->name, name, len) == 0) {
+ return (mrb_sym)(sname - mrb->symtbl)<<1;
+ }
+ sname--;
+ }
+ return 0;
+ }
+ i -= sname->prev;
+ } while (sname->prev > 0);
+ return 0;
}
static mrb_sym
sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit)
{
- khash_t(n2s) *h = mrb->name2sym;
- symbol_name *sname = mrb->symtbl; /* symtbl[0] for working memory */
- khiter_t k;
mrb_sym sym;
- char *p;
+ symbol_name *sname;
+ uint8_t hash;
sym_validate_len(mrb, len);
- if (sname) {
- sname->lit = lit;
- sname->len = (uint16_t)len;
- sname->name = name;
- k = kh_get(n2s, mrb, h, 0);
- if (k != kh_end(h))
- return kh_key(h, k);
- }
+ hash = symhash(name, len);
+ sym = find_symbol(mrb, name, len, hash);
+ if (sym > 0) return sym;
/* registering a new symbol */
sym = ++mrb->symidx;
@@ -78,15 +168,25 @@ sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit)
sname->lit = TRUE;
}
else {
- p = (char *)mrb_malloc(mrb, len+1);
+ char *p = (char *)mrb_malloc(mrb, len+1);
memcpy(p, name, len);
p[len] = 0;
sname->name = (const char*)p;
sname->lit = FALSE;
}
- kh_put(n2s, mrb, h, sym);
+ if (mrb->symhash[hash]) {
+ mrb_sym i = sym - mrb->symhash[hash];
+ if (i > 0xff)
+ sname->prev = 0xff;
+ else
+ sname->prev = i;
+ }
+ else {
+ sname->prev = 0;
+ }
+ mrb->symhash[hash] = sym;
- return sym;
+ return sym<<1;
}
MRB_API mrb_sym
@@ -116,25 +216,18 @@ mrb_intern_str(mrb_state *mrb, mrb_value str)
MRB_API mrb_value
mrb_check_intern(mrb_state *mrb, const char *name, size_t len)
{
- khash_t(n2s) *h = mrb->name2sym;
- symbol_name *sname = mrb->symtbl;
- khiter_t k;
+ mrb_sym sym;
sym_validate_len(mrb, len);
- sname->len = (uint16_t)len;
- sname->name = name;
-
- k = kh_get(n2s, mrb, h, 0);
- if (k != kh_end(h)) {
- return mrb_symbol_value(kh_key(h, k));
- }
+ sym = find_symbol(mrb, name, len, symhash(name, len));
+ if (sym > 0) return mrb_symbol_value(sym);
return mrb_nil_value();
}
MRB_API mrb_value
mrb_check_intern_cstr(mrb_state *mrb, const char *name)
{
- return mrb_check_intern(mrb, name, (mrb_int)strlen(name));
+ return mrb_check_intern(mrb, name, strlen(name));
}
MRB_API mrb_value
@@ -143,10 +236,16 @@ mrb_check_intern_str(mrb_state *mrb, mrb_value str)
return mrb_check_intern(mrb, RSTRING_PTR(str), RSTRING_LEN(str));
}
-/* lenp must be a pointer to a size_t variable */
-MRB_API const char*
-mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp)
+static const char*
+sym2name_len(mrb_state *mrb, mrb_sym sym, char *buf, mrb_int *lenp)
{
+#ifndef MRB_ENABLE_ALL_SYMBOLS
+ if (sym & 1) { /* inline packed symbol */
+ return sym_inline_unpack(sym, buf, lenp);
+ }
+#endif
+
+ sym >>= 1;
if (sym == 0 || mrb->symidx < sym) {
if (lenp) *lenp = 0;
return NULL;
@@ -156,6 +255,12 @@ mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp)
return mrb->symtbl[sym].name;
}
+MRB_API const char*
+mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp)
+{
+ return sym2name_len(mrb, sym, mrb->symbuf, lenp);
+}
+
void
mrb_free_symtbl(mrb_state *mrb)
{
@@ -167,13 +272,11 @@ mrb_free_symtbl(mrb_state *mrb)
}
}
mrb_free(mrb, mrb->symtbl);
- kh_destroy(n2s, mrb, mrb->name2sym);
}
void
mrb_init_symtbl(mrb_state *mrb)
{
- mrb->name2sym = kh_init(n2s, mrb);
}
/**********************************************************************
@@ -209,26 +312,6 @@ mrb_init_symtbl(mrb_state *mrb)
*
*/
-
-/* 15.2.11.3.1 */
-/*
- * call-seq:
- * sym == obj -> true or false
- *
- * Equality---If <i>sym</i> and <i>obj</i> are exactly the same
- * symbol, returns <code>true</code>.
- */
-
-static mrb_value
-sym_equal(mrb_state *mrb, mrb_value sym1)
-{
- mrb_value sym2;
-
- mrb_get_args(mrb, "o", &sym2);
-
- return mrb_bool_value(mrb_obj_equal(mrb, sym1, sym2));
-}
-
/* 15.2.11.3.2 */
/* 15.2.11.3.3 */
/*
@@ -241,14 +324,9 @@ sym_equal(mrb_state *mrb, mrb_value sym1)
* :fred.id2name #=> "fred"
*/
static mrb_value
-mrb_sym_to_s(mrb_state *mrb, mrb_value sym)
+sym_to_s(mrb_state *mrb, mrb_value sym)
{
- mrb_sym id = mrb_symbol(sym);
- const char *p;
- mrb_int len;
-
- p = mrb_sym2name_len(mrb, id, &len);
- return mrb_str_new_static(mrb, p, len);
+ return mrb_sym2str(mrb, mrb_symbol(sym));
}
/* 15.2.11.3.4 */
@@ -425,6 +503,9 @@ mrb_sym2str(mrb_state *mrb, mrb_sym sym)
const char *name = mrb_sym2name_len(mrb, sym, &len);
if (!name) return mrb_undef_value(); /* can't happen */
+ if (sym&1) { /* inline symbol */
+ return mrb_str_new(mrb, name, len);
+ }
return mrb_str_new_static(mrb, name, len);
}
@@ -439,7 +520,14 @@ mrb_sym2name(mrb_state *mrb, mrb_sym sym)
return name;
}
else {
- mrb_value str = mrb_str_dump(mrb, mrb_str_new_static(mrb, name, len));
+ mrb_value str;
+ if (sym&1) { /* inline symbol */
+ str = mrb_str_new(mrb, name, len);
+ }
+ else {
+ str = mrb_str_new_static(mrb, name, len);
+ }
+ str = mrb_str_dump(mrb, str);
return RSTRING_PTR(str);
}
}
@@ -461,9 +549,10 @@ sym_cmp(mrb_state *mrb, mrb_value s1)
const char *p1, *p2;
int retval;
mrb_int len, len1, len2;
+ char buf1[8], buf2[8];
- p1 = mrb_sym2name_len(mrb, sym1, &len1);
- p2 = mrb_sym2name_len(mrb, sym2, &len2);
+ p1 = sym2name_len(mrb, sym1, buf1, &len1);
+ p2 = sym2name_len(mrb, sym2, buf2, &len2);
len = lesser(len1, len2);
retval = memcmp(p1, p2, len);
if (retval == 0) {
@@ -481,14 +570,13 @@ mrb_init_symbol(mrb_state *mrb)
{
struct RClass *sym;
- mrb->symbol_class = sym = mrb_define_class(mrb, "Symbol", mrb->object_class); /* 15.2.11 */
+ mrb->symbol_class = sym = mrb_define_class(mrb, "Symbol", mrb->object_class); /* 15.2.11 */
MRB_SET_INSTANCE_TT(sym, MRB_TT_SYMBOL);
mrb_undef_class_method(mrb, sym, "new");
- mrb_define_method(mrb, sym, "===", sym_equal, MRB_ARGS_REQ(1)); /* 15.2.11.3.1 */
- mrb_define_method(mrb, sym, "id2name", mrb_sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.2 */
- mrb_define_method(mrb, sym, "to_s", mrb_sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.3 */
- mrb_define_method(mrb, sym, "to_sym", sym_to_sym, MRB_ARGS_NONE()); /* 15.2.11.3.4 */
- mrb_define_method(mrb, sym, "inspect", sym_inspect, MRB_ARGS_NONE()); /* 15.2.11.3.5(x) */
- mrb_define_method(mrb, sym, "<=>", sym_cmp, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, sym, "id2name", sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.2 */
+ mrb_define_method(mrb, sym, "to_s", sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.3 */
+ mrb_define_method(mrb, sym, "to_sym", sym_to_sym, MRB_ARGS_NONE()); /* 15.2.11.3.4 */
+ mrb_define_method(mrb, sym, "inspect", sym_inspect, MRB_ARGS_NONE()); /* 15.2.11.3.5(x) */
+ mrb_define_method(mrb, sym, "<=>", sym_cmp, MRB_ARGS_REQ(1));
}
diff --git a/src/variable.c b/src/variable.c
index 72c13aa1f..c4c9d369f 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -9,8 +9,7 @@
#include <mruby/class.h>
#include <mruby/proc.h>
#include <mruby/string.h>
-
-typedef int (iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*);
+#include <mruby/variable.h>
#ifndef MRB_IV_SEGMENT_SIZE
#define MRB_IV_SEGMENT_SIZE 4
@@ -80,19 +79,19 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
}
/* Not found */
- t->size++;
if (matched_seg) {
matched_seg->key[matched_idx] = sym;
matched_seg->val[matched_idx] = val;
+ t->size++;
return;
}
seg = (segment*)mrb_malloc(mrb, sizeof(segment));
- if (!seg) return;
seg->next = NULL;
seg->key[0] = sym;
seg->val[0] = val;
t->last_len = 1;
+ t->size++;
if (prev) {
prev->next = seg;
}
@@ -156,14 +155,13 @@ iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
}
/* Iterates over the instance variable table. */
-static mrb_bool
-iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
+static void
+iv_foreach(mrb_state *mrb, iv_tbl *t, mrb_iv_foreach_func *func, void *p)
{
segment *seg;
size_t i;
- int n;
- if (t == NULL) return TRUE;
+ if (t == NULL) return;
seg = t->rootseg;
while (seg) {
for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) {
@@ -171,20 +169,17 @@ iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
/* no value in last segment after last_len */
if (!seg->next && i >= t->last_len) {
- return FALSE;
+ return;
}
if (key != 0) {
- n =(*func)(mrb, key, seg->val[i], p);
- if (n > 0) return FALSE;
- if (n < 0) {
- t->size--;
- seg->key[i] = 0;
+ if ((*func)(mrb, key, seg->val[i], p) != 0) {
+ return;
}
}
}
seg = seg->next;
}
- return TRUE;
+ return;
}
/* Get the size of the instance variable table. */
@@ -351,9 +346,7 @@ mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
{
iv_tbl *t;
- if (MRB_FROZEN_P(obj)) {
- mrb_raisef(mrb, E_FROZEN_ERROR, "can't modify frozen %S", mrb_obj_value(obj));
- }
+ mrb_check_frozen(mrb, obj);
assign_class_name(mrb, obj, sym, v);
if (!obj->iv) {
obj->iv = iv_new(mrb);
@@ -363,6 +356,14 @@ mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
mrb_write_barrier(mrb, (struct RBasic*)obj);
}
+/* Iterates over the instance variable table. */
+MRB_API void
+mrb_iv_foreach(mrb_state *mrb, mrb_value obj, mrb_iv_foreach_func *func, void *p)
+{
+ if (!obj_iv_p(obj)) return;
+ iv_foreach(mrb, mrb_obj_ptr(obj)->iv, func, p);
+}
+
static inline mrb_bool
namespace_p(enum mrb_vtype tt)
{
@@ -425,22 +426,17 @@ mrb_iv_defined(mrb_state *mrb, mrb_value obj, mrb_sym sym)
return mrb_obj_iv_defined(mrb, mrb_obj_ptr(obj), sym);
}
-#define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c))
-
MRB_API mrb_bool
mrb_iv_name_sym_p(mrb_state *mrb, mrb_sym iv_name)
{
const char *s;
- mrb_int i, len;
+ mrb_int len;
s = mrb_sym2name_len(mrb, iv_name, &len);
if (len < 2) return FALSE;
if (s[0] != '@') return FALSE;
- if (s[1] == '@') return FALSE;
- for (i=1; i<len; i++) {
- if (!identchar(s[i])) return FALSE;
- }
- return TRUE;
+ if (ISDIGIT(s[1])) return FALSE;
+ return mrb_ident_p(s+1, len-1);
}
MRB_API void
@@ -623,7 +619,7 @@ mrb_mod_class_variables(mrb_state *mrb, mrb_value mod)
return ary;
}
-MRB_API mrb_value
+mrb_value
mrb_mod_cv_get(mrb_state *mrb, struct RClass *c, mrb_sym sym)
{
struct RClass * cls = c;
@@ -675,6 +671,7 @@ mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v)
iv_tbl *t = c->iv;
if (iv_get(mrb, t, sym, NULL)) {
+ mrb_check_frozen(mrb, c);
iv_put(mrb, t, sym, v);
mrb_write_barrier(mrb, (struct RBasic*)c);
return;
@@ -702,6 +699,7 @@ mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v)
c = cls;
}
+ mrb_check_frozen(mrb, c);
if (!c->iv) {
c->iv = iv_new(mrb);
}
@@ -716,7 +714,7 @@ mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v)
mrb_mod_cv_set(mrb, mrb_class_ptr(mod), sym, v);
}
-MRB_API mrb_bool
+mrb_bool
mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym)
{
while (c) {
@@ -1108,6 +1106,20 @@ mrb_class_find_path(mrb_state *mrb, struct RClass *c)
iv_del(mrb, c->iv, mrb_intern_lit(mrb, "__outer__"), NULL);
iv_put(mrb, c->iv, mrb_intern_lit(mrb, "__classname__"), path);
mrb_field_write_barrier_value(mrb, (struct RBasic*)c, path);
+ path = mrb_str_dup(mrb, path);
}
return path;
}
+
+#define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c))
+
+mrb_bool
+mrb_ident_p(const char *s, mrb_int len)
+{
+ mrb_int i;
+
+ for (i = 0; i < len; i++) {
+ if (!identchar(s[i])) return FALSE;
+ }
+ return TRUE;
+}
diff --git a/src/vm.c b/src/vm.c
index 84e076ee8..8dc6623d1 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -101,7 +101,7 @@ static inline void
stack_clear(mrb_value *from, size_t count)
{
#ifndef MRB_NAN_BOXING
- const mrb_value mrb_value_zero = { 0 };
+ const mrb_value mrb_value_zero = { { 0 } };
while (count-- > 0) {
*from++ = mrb_value_zero;
@@ -486,26 +486,25 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
ci->argc = (int)argc;
ci->target_class = c;
mrb->c->stack = mrb->c->stack + n;
+ if (argc < 0) argc = 1;
if (mrb->c->stbase <= argv && argv < mrb->c->stend) {
voff = argv - mrb->c->stbase;
}
- if (MRB_METHOD_CFUNC_P(m)) {
- mrb_stack_extend(mrb, argc + 2);
- }
- else if (argc >= CALL_MAXARGS) {
+ if (argc >= CALL_MAXARGS) {
mrb_value args = mrb_ary_new_from_values(mrb, argc, argv);
- mrb_stack_extend(mrb, 3);
mrb->c->stack[1] = args;
ci->argc = -1;
argc = 1;
}
- else {
+ mrb_stack_extend(mrb, argc + 2);
+ if (MRB_METHOD_PROC_P(m)) {
struct RProc *p = MRB_METHOD_PROC(m);
ci->proc = p;
- if (argc < 0) argc = 1;
- mrb_stack_extend(mrb, p->body.irep->nregs + argc);
+ if (!MRB_PROC_CFUNC_P(p)) {
+ mrb_stack_extend(mrb, p->body.irep->nregs + argc);
+ }
}
if (voff >= 0) {
argv = mrb->c->stbase + voff;
@@ -520,9 +519,6 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
int ai = mrb_gc_arena_save(mrb);
ci->acc = CI_ACC_DIRECT;
- if (MRB_METHOD_PROC_P(m)) {
- ci->proc = MRB_METHOD_PROC(m);
- }
val = MRB_METHOD_CFUNC(m)(mrb, self);
mrb->c->stack = mrb->c->ci->stackent;
cipop(mrb);
@@ -593,7 +589,7 @@ mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p)
* k = Klass.new
* k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
*/
-MRB_API mrb_value
+mrb_value
mrb_f_send(mrb_state *mrb, mrb_value self)
{
mrb_sym name;
@@ -667,10 +663,11 @@ eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c)
return MRB_PROC_CFUNC(p)(mrb, self);
}
nregs = p->body.irep->nregs;
- mrb_stack_extend(mrb, (nregs < 3) ? 3 : nregs);
+ if (nregs < 3) nregs = 3;
+ mrb_stack_extend(mrb, nregs);
mrb->c->stack[0] = self;
mrb->c->stack[1] = self;
- mrb->c->stack[2] = mrb_nil_value();
+ stack_clear(mrb->c->stack+2, nregs-2);
ci = cipush(mrb);
ci->target_class = 0;
ci->pc = p->body.irep->iseq;
@@ -1003,7 +1000,7 @@ void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self);
MRB_API mrb_value
mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
{
- /* mrb_assert(mrb_proc_cfunc_p(proc)) */
+ /* mrb_assert(MRB_PROC_CFUNC_P(proc)) */
mrb_code *pc0 = pc;
mrb_irep *irep = proc->body.irep;
mrb_value *pool = irep->pool;
@@ -1809,7 +1806,8 @@ RETRY_TRY_BLOCK:
kdict = argv[argc-1];
mrb_hash_check_kdict(mrb, kdict);
}
- else if (r || argc <= m1+m2+o) {
+ else if (r || argc <= m1+m2+o
+ || !(mrb->c->ci->proc && MRB_PROC_STRICT_P(mrb->c->ci->proc))) {
kdict = mrb_hash_new(mrb);
kargs = 0;
}
@@ -2215,184 +2213,67 @@ RETRY_TRY_BLOCK:
}
#define TYPES2(a,b) ((((uint16_t)(a))<<8)|(((uint16_t)(b))&0xff))
-#define OP_MATH_BODY(op,v1,v2) do {\
- v1(regs[a]) = v1(regs[a]) op v2(regs[a+1]);\
-} while(0)
-
- CASE(OP_ADD, B) {
- /* need to check if op is overridden */
- switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
- case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
- {
- mrb_int x, y, z;
- mrb_value *regs_a = regs + a;
-
- x = mrb_fixnum(regs_a[0]);
- y = mrb_fixnum(regs_a[1]);
- if (mrb_int_add_overflow(x, y, &z)) {
-#ifndef MRB_WITHOUT_FLOAT
- SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x + (mrb_float)y);
- break;
-#endif
- }
- SET_INT_VALUE(regs[a], z);
- }
- break;
-#ifndef MRB_WITHOUT_FLOAT
- case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
- {
- mrb_int x = mrb_fixnum(regs[a]);
- mrb_float y = mrb_float(regs[a+1]);
- SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + y);
- }
- break;
- case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
-#ifdef MRB_WORD_BOXING
- {
- mrb_float x = mrb_float(regs[a]);
- mrb_int y = mrb_fixnum(regs[a+1]);
- SET_FLOAT_VALUE(mrb, regs[a], x + y);
- }
-#else
- OP_MATH_BODY(+,mrb_float,mrb_fixnum);
-#endif
- break;
- case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
-#ifdef MRB_WORD_BOXING
- {
- mrb_float x = mrb_float(regs[a]);
- mrb_float y = mrb_float(regs[a+1]);
- SET_FLOAT_VALUE(mrb, regs[a], x + y);
- }
+#define OP_MATH(op_name) \
+ /* need to check if op is overridden */ \
+ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { \
+ OP_MATH_CASE_FIXNUM(op_name); \
+ OP_MATH_CASE_FLOAT(op_name, fixnum, float); \
+ OP_MATH_CASE_FLOAT(op_name, float, fixnum); \
+ OP_MATH_CASE_FLOAT(op_name, float, float); \
+ OP_MATH_CASE_STRING_##op_name(); \
+ default: \
+ c = 1; \
+ mid = mrb_intern_lit(mrb, MRB_STRINGIZE(OP_MATH_OP_##op_name)); \
+ goto L_SEND_SYM; \
+ } \
+ NEXT;
+#define OP_MATH_CASE_FIXNUM(op_name) \
+ case TYPES2(MRB_TT_FIXNUM, MRB_TT_FIXNUM): \
+ { \
+ mrb_int x = mrb_fixnum(regs[a]), y = mrb_fixnum(regs[a+1]), z; \
+ if (mrb_int_##op_name##_overflow(x, y, &z)) \
+ OP_MATH_OVERFLOW_INT(op_name, x, y, z); \
+ else \
+ SET_INT_VALUE(regs[a], z); \
+ } \
+ break
+#ifdef MRB_WITHOUT_FLOAT
+#define OP_MATH_CASE_FLOAT(op_name, t1, t2) (void)0
+#define OP_MATH_OVERFLOW_INT(op_name, x, y, z) SET_INT_VALUE(regs[a], z)
#else
- OP_MATH_BODY(+,mrb_float,mrb_float);
-#endif
- break;
+#define OP_MATH_CASE_FLOAT(op_name, t1, t2) \
+ case TYPES2(OP_MATH_TT_##t1, OP_MATH_TT_##t2): \
+ { \
+ mrb_float z = mrb_##t1(regs[a]) OP_MATH_OP_##op_name mrb_##t2(regs[a+1]); \
+ SET_FLOAT_VALUE(mrb, regs[a], z); \
+ } \
+ break
+#define OP_MATH_OVERFLOW_INT(op_name, x, y, z) \
+ SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x OP_MATH_OP_##op_name (mrb_float)y)
#endif
- case TYPES2(MRB_TT_STRING,MRB_TT_STRING):
- regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]);
- break;
- default:
- c = 1;
- mid = mrb_intern_lit(mrb, "+");
- goto L_SEND_SYM;
- }
- mrb_gc_arena_restore(mrb, ai);
- NEXT;
+#define OP_MATH_CASE_STRING_add() \
+ case TYPES2(MRB_TT_STRING, MRB_TT_STRING): \
+ regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]); \
+ mrb_gc_arena_restore(mrb, ai); \
+ break
+#define OP_MATH_CASE_STRING_sub() (void)0
+#define OP_MATH_CASE_STRING_mul() (void)0
+#define OP_MATH_OP_add +
+#define OP_MATH_OP_sub -
+#define OP_MATH_OP_mul *
+#define OP_MATH_TT_fixnum MRB_TT_FIXNUM
+#define OP_MATH_TT_float MRB_TT_FLOAT
+
+ CASE(OP_ADD, B) {
+ OP_MATH(add);
}
CASE(OP_SUB, B) {
- /* need to check if op is overridden */
- switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
- case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
- {
- mrb_int x, y, z;
-
- x = mrb_fixnum(regs[a]);
- y = mrb_fixnum(regs[a+1]);
- if (mrb_int_sub_overflow(x, y, &z)) {
-#ifndef MRB_WITHOUT_FLOAT
- SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - (mrb_float)y);
- break;
-#endif
- }
- SET_INT_VALUE(regs[a], z);
- }
- break;
-#ifndef MRB_WITHOUT_FLOAT
- case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
- {
- mrb_int x = mrb_fixnum(regs[a]);
- mrb_float y = mrb_float(regs[a+1]);
- SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - y);
- }
- break;
- case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
-#ifdef MRB_WORD_BOXING
- {
- mrb_float x = mrb_float(regs[a]);
- mrb_int y = mrb_fixnum(regs[a+1]);
- SET_FLOAT_VALUE(mrb, regs[a], x - y);
- }
-#else
- OP_MATH_BODY(-,mrb_float,mrb_fixnum);
-#endif
- break;
- case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
-#ifdef MRB_WORD_BOXING
- {
- mrb_float x = mrb_float(regs[a]);
- mrb_float y = mrb_float(regs[a+1]);
- SET_FLOAT_VALUE(mrb, regs[a], x - y);
- }
-#else
- OP_MATH_BODY(-,mrb_float,mrb_float);
-#endif
- break;
-#endif
- default:
- c = 1;
- mid = mrb_intern_lit(mrb, "-");
- goto L_SEND_SYM;
- }
- NEXT;
+ OP_MATH(sub);
}
CASE(OP_MUL, B) {
- /* need to check if op is overridden */
- switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
- case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
- {
- mrb_int x, y, z;
-
- x = mrb_fixnum(regs[a]);
- y = mrb_fixnum(regs[a+1]);
- if (mrb_int_mul_overflow(x, y, &z)) {
-#ifndef MRB_WITHOUT_FLOAT
- SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x * (mrb_float)y);
- break;
-#endif
- }
- SET_INT_VALUE(regs[a], z);
- }
- break;
-#ifndef MRB_WITHOUT_FLOAT
- case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
- {
- mrb_int x = mrb_fixnum(regs[a]);
- mrb_float y = mrb_float(regs[a+1]);
- SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x * y);
- }
- break;
- case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
-#ifdef MRB_WORD_BOXING
- {
- mrb_float x = mrb_float(regs[a]);
- mrb_int y = mrb_fixnum(regs[a+1]);
- SET_FLOAT_VALUE(mrb, regs[a], x * y);
- }
-#else
- OP_MATH_BODY(*,mrb_float,mrb_fixnum);
-#endif
- break;
- case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
-#ifdef MRB_WORD_BOXING
- {
- mrb_float x = mrb_float(regs[a]);
- mrb_float y = mrb_float(regs[a+1]);
- SET_FLOAT_VALUE(mrb, regs[a], x * y);
- }
-#else
- OP_MATH_BODY(*,mrb_float,mrb_float);
-#endif
- break;
-#endif
- default:
- c = 1;
- mid = mrb_intern_lit(mrb, "*");
- goto L_SEND_SYM;
- }
- NEXT;
+ OP_MATH(mul);
}
CASE(OP_DIV, B) {
@@ -2447,84 +2328,46 @@ RETRY_TRY_BLOCK:
NEXT;
}
- CASE(OP_ADDI, BB) {
- /* need to check if + is overridden */
- switch (mrb_type(regs[a])) {
- case MRB_TT_FIXNUM:
- {
- mrb_int x = mrb_fixnum(regs[a]);
- mrb_int y = (mrb_int)b;
- mrb_int z;
-
- if (mrb_int_add_overflow(x, y, &z)) {
-#ifndef MRB_WITHOUT_FLOAT
- SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + (mrb_float)y);
- break;
-#endif
- }
- SET_INT_VALUE(regs[a], z);
- }
- break;
-#ifndef MRB_WITHOUT_FLOAT
- case MRB_TT_FLOAT:
-#ifdef MRB_WORD_BOXING
- {
- mrb_float x = mrb_float(regs[a]);
- SET_FLOAT_VALUE(mrb, regs[a], x + b);
- }
+#define OP_MATHI(op_name) \
+ /* need to check if op is overridden */ \
+ switch (mrb_type(regs[a])) { \
+ OP_MATHI_CASE_FIXNUM(op_name); \
+ OP_MATHI_CASE_FLOAT(op_name); \
+ default: \
+ SET_INT_VALUE(regs[a+1], b); \
+ c = 1; \
+ mid = mrb_intern_lit(mrb, MRB_STRINGIZE(OP_MATH_OP_##op_name)); \
+ goto L_SEND_SYM; \
+ } \
+ NEXT;
+#define OP_MATHI_CASE_FIXNUM(op_name) \
+ case MRB_TT_FIXNUM: \
+ { \
+ mrb_int x = mrb_fixnum(regs[a]), y = (mrb_int)b, z; \
+ if (mrb_int_##op_name##_overflow(x, y, &z)) \
+ OP_MATH_OVERFLOW_INT(op_name, x, y, z); \
+ else \
+ SET_INT_VALUE(regs[a], z); \
+ } \
+ break
+#ifdef MRB_WITHOUT_FLOAT
+#define OP_MATHI_CASE_FLOAT(op_name) (void)0
#else
- mrb_float(regs[a]) += b;
+#define OP_MATHI_CASE_FLOAT(op_name) \
+ case MRB_TT_FLOAT: \
+ { \
+ mrb_float z = mrb_float(regs[a]) OP_MATH_OP_##op_name b; \
+ SET_FLOAT_VALUE(mrb, regs[a], z); \
+ } \
+ break
#endif
- break;
-#endif
- default:
- SET_INT_VALUE(regs[a+1], b);
- c = 1;
- mid = mrb_intern_lit(mrb, "+");
- goto L_SEND_SYM;
- }
- NEXT;
+
+ CASE(OP_ADDI, BB) {
+ OP_MATHI(add);
}
CASE(OP_SUBI, BB) {
- mrb_value *regs_a = regs + a;
-
- /* need to check if + is overridden */
- switch (mrb_type(regs_a[0])) {
- case MRB_TT_FIXNUM:
- {
- mrb_int x = mrb_fixnum(regs_a[0]);
- mrb_int y = (mrb_int)b;
- mrb_int z;
-
- if (mrb_int_sub_overflow(x, y, &z)) {
-#ifndef MRB_WITHOUT_FLOAT
- SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x - (mrb_float)y);
- break;
-#endif
- }
- SET_INT_VALUE(regs_a[0], z);
- }
- break;
-#ifndef MRB_WITHOUT_FLOAT
- case MRB_TT_FLOAT:
-#ifdef MRB_WORD_BOXING
- {
- mrb_float x = mrb_float(regs[a]);
- SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - (mrb_float)b);
- }
-#else
- mrb_float(regs_a[0]) -= b;
-#endif
- break;
-#endif
- default:
- SET_INT_VALUE(regs_a[1], b);
- c = 1;
- mid = mrb_intern_lit(mrb, "-");
- goto L_SEND_SYM;
- }
- NEXT;
+ OP_MATHI(sub);
}
#define OP_CMP_BODY(op,v1,v2) (v1(regs[a]) op v2(regs[a+1]))
@@ -3019,11 +2862,11 @@ mrb_top_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int sta
return mrb_vm_run(mrb, proc, self, stack_keep);
}
ci = cipush(mrb);
+ ci->stackent = mrb->c->stack;
ci->mid = 0;
ci->acc = CI_ACC_SKIP;
ci->target_class = mrb->object_class;
v = mrb_vm_run(mrb, proc, self, stack_keep);
- cipop(mrb);
return v;
}