summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/array.c14
-rw-r--r--src/backtrace.c87
-rw-r--r--src/class.c155
-rw-r--r--src/codedump.c4
-rw-r--r--src/dump.c68
-rw-r--r--src/error.c88
-rw-r--r--src/etc.c17
-rw-r--r--src/fmt_fp.c120
-rw-r--r--src/gc.c10
-rw-r--r--src/hash.c13
-rw-r--r--src/kernel.c12
-rw-r--r--src/load.c48
-rw-r--r--src/numeric.c13
-rw-r--r--src/print.c1
-rw-r--r--src/string.c325
-rw-r--r--src/symbol.c32
-rw-r--r--src/variable.c2
-rw-r--r--src/vm.c51
18 files changed, 518 insertions, 542 deletions
diff --git a/src/array.c b/src/array.c
index 85481fe9e..ad0d5b8db 100644
--- a/src/array.c
+++ b/src/array.c
@@ -631,11 +631,13 @@ mrb_ary_unshift_m(mrb_state *mrb, mrb_value self)
ptr = a->as.heap.ptr;
}
else {
+ mrb_bool same = vals == ARY_PTR(a);
ary_modify(mrb, a);
if (ARY_CAPA(a) < len + alen)
ary_expand_capa(mrb, a, len + alen);
ptr = ARY_PTR(a);
value_move(ptr + alen, ptr, len);
+ if (same) vals = ptr;
}
array_copy(ptr, vals, alen);
ARY_SET_LEN(a, len+alen);
@@ -730,6 +732,10 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val
argv = ARY_PTR(r);
}
}
+ else if (mrb_undef_p(rpl)) {
+ argc = 0;
+ argv = NULL;
+ }
else {
argc = 1;
argv = &rpl;
@@ -802,6 +808,13 @@ ary_subseq(mrb_state *mrb, struct RArray *a, mrb_int beg, mrb_int len)
return mrb_obj_value(b);
}
+mrb_value
+mrb_ary_subseq(mrb_state *mrb, mrb_value ary, mrb_int beg, mrb_int len)
+{
+ struct RArray *a = mrb_ary_ptr(ary);
+ return ary_subseq(mrb, a, beg, len);
+}
+
static mrb_int
aget_index(mrb_state *mrb, mrb_value index)
{
@@ -1302,6 +1315,7 @@ init_ary_each(mrb_state *mrb, struct RClass *ary)
each_irep->nregs = 7;
each_irep->nlocals = 3;
p = mrb_proc_new(mrb, each_irep);
+ p->flags |= MRB_PROC_SCOPE | MRB_PROC_STRICT;
MRB_METHOD_FROM_PROC(m, p);
mrb_define_method_raw(mrb, ary, mrb_intern_lit(mrb, "each"), m);
}
diff --git a/src/backtrace.c b/src/backtrace.c
index 803c5e285..591f4ea4b 100644
--- a/src/backtrace.c
+++ b/src/backtrace.c
@@ -25,6 +25,9 @@ typedef void (*each_backtrace_func)(mrb_state*, const struct backtrace_location*
static const mrb_data_type bt_type = { "Backtrace", mrb_free };
+mrb_value mrb_exc_inspect(mrb_state *mrb, mrb_value exc);
+mrb_value mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace);
+
static void
each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, const mrb_code *pc0, each_backtrace_func func, void *data)
{
@@ -74,66 +77,27 @@ each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, const mrb_code *pc0, each_backtr
#ifndef MRB_DISABLE_STDIO
static void
-print_backtrace(mrb_state *mrb, mrb_value backtrace)
+print_backtrace(mrb_state *mrb, struct RObject *exc, mrb_value backtrace)
{
- int i;
- mrb_int n;
+ mrb_int i;
+ mrb_int n = RARRAY_LEN(backtrace);
+ mrb_value *loc, mesg;
FILE *stream = stderr;
- n = RARRAY_LEN(backtrace) - 1;
- if (n == 0) return;
-
- fprintf(stream, "trace (most recent call last):\n");
- for (i=0; i<n; i++) {
- mrb_value entry = RARRAY_PTR(backtrace)[n-i-1];
-
- if (mrb_string_p(entry)) {
- fprintf(stream, "\t[%d] %.*s\n", i, (int)RSTRING_LEN(entry), RSTRING_PTR(entry));
+ if (n != 0) {
+ fprintf(stream, "trace (most recent call last):\n");
+ for (i=n-1,loc=&RARRAY_PTR(backtrace)[i]; i>0; i--,loc--) {
+ if (mrb_string_p(*loc)) {
+ fprintf(stream, "\t[%d] %.*s\n",
+ (int)i, (int)RSTRING_LEN(*loc), RSTRING_PTR(*loc));
+ }
}
- }
-}
-
-static int
-packed_bt_len(const struct backtrace_location *bt, int n)
-{
- int len = 0;
- int i;
-
- for (i=0; i<n; i++) {
- if (!bt[i].filename && !bt[i].lineno && !bt[i].method_id)
- continue;
- len++;
- }
- return len;
-}
-
-static void
-print_packed_backtrace(mrb_state *mrb, mrb_value packed)
-{
- FILE *stream = stderr;
- const struct backtrace_location *bt;
- int n, i;
- int ai = mrb_gc_arena_save(mrb);
-
- bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, packed, &bt_type);
- if (bt == NULL) return;
- n = (mrb_int)RDATA(packed)->flags;
-
- if (packed_bt_len(bt, n) == 0) return;
- fprintf(stream, "trace (most recent call last):\n");
- for (i = 0; i<n; i++) {
- 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) {
- const char *method_name;
-
- method_name = mrb_sym_name(mrb, entry->method_id);
- fprintf(stream, ":in %s", method_name);
- mrb_gc_arena_restore(mrb, ai);
+ if (mrb_string_p(*loc)) {
+ fprintf(stream, "%.*s: ", (int)RSTRING_LEN(*loc), RSTRING_PTR(*loc));
}
- fprintf(stream, "\n");
}
+ mesg = mrb_exc_inspect(mrb, mrb_obj_value(exc));
+ fprintf(stream, "%.*s\n", (int)RSTRING_LEN(mesg), RSTRING_PTR(mesg));
}
/* mrb_print_backtrace
@@ -152,12 +116,8 @@ mrb_print_backtrace(mrb_state *mrb)
backtrace = mrb_obj_iv_get(mrb, mrb->exc, mrb_intern_lit(mrb, "backtrace"));
if (mrb_nil_p(backtrace)) return;
- if (mrb_array_p(backtrace)) {
- print_backtrace(mrb, backtrace);
- }
- else {
- print_packed_backtrace(mrb, backtrace);
- }
+ if (!mrb_array_p(backtrace)) backtrace = mrb_unpack_backtrace(mrb, backtrace);
+ print_backtrace(mrb, mrb->exc, backtrace);
}
#else
@@ -175,7 +135,6 @@ count_backtrace_i(mrb_state *mrb,
{
int *lenp = (int*)data;
- if (loc->filename == NULL) return;
(*lenp)++;
}
@@ -187,7 +146,6 @@ pack_backtrace_i(mrb_state *mrb,
struct backtrace_location **pptr = (struct backtrace_location**)data;
struct backtrace_location *ptr = *pptr;
- if (loc->filename == NULL) return;
*ptr = *loc;
*pptr = ptr+1;
}
@@ -205,7 +163,7 @@ packed_backtrace(mrb_state *mrb)
size = len * sizeof(struct backtrace_location);
ptr = mrb_malloc(mrb, size);
backtrace = mrb_data_object_alloc(mrb, NULL, ptr, &bt_type);
- backtrace->flags = (unsigned int)len;
+ backtrace->flags = (uint32_t)len;
each_backtrace(mrb, ciidx, mrb->c->ci->pc, pack_backtrace_i, &ptr);
return mrb_obj_value(backtrace);
}
@@ -245,8 +203,7 @@ mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace)
const struct backtrace_location *entry = &bt[i];
mrb_value btline;
- if (entry->filename == NULL) continue;
- btline = mrb_format(mrb, "%s:%d", entry->filename, entry->lineno);
+ btline = mrb_format(mrb, "%s:%d", entry->filename, (int)entry->lineno);
if (entry->method_id != 0) {
mrb_str_cat_lit(mrb, btline, ":in ");
mrb_str_cat_cstr(mrb, btline, mrb_sym_name(mrb, entry->method_id));
diff --git a/src/class.c b/src/class.c
index 2656806d2..d30edd41e 100644
--- a/src/class.c
+++ b/src/class.c
@@ -65,23 +65,21 @@ mrb_class_name_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb
name = mrb_symbol_value(id);
}
else {
- const char *n;
- mrb_int len;
- mrb_value outer_name = mrb_class_path(mrb, outer);
-
- if (mrb_nil_p(outer_name)) { /* unnamed outer class */
+ name = mrb_class_path(mrb, outer);
+ if (mrb_nil_p(name)) { /* unnamed outer class */
if (outer != mrb->object_class && outer != c) {
mrb_obj_iv_set_force(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"),
mrb_obj_value(outer));
}
return;
}
- n = mrb_sym_name_len(mrb, id, &len);
- name = mrb_str_new_capa(mrb, RSTRING_LEN(outer_name) + 2 + len);
- mrb_str_cat_str(mrb, name, outer_name);
- mrb_str_cat_lit(mrb, name, "::");
- mrb_str_cat(mrb, name, n, len);
- MRB_SET_FROZEN_FLAG(mrb_obj_ptr(name));
+ else {
+ mrb_int len;
+ const char *n = mrb_sym_name_len(mrb, id, &len);
+
+ mrb_str_cat_lit(mrb, name, "::");
+ mrb_str_cat(mrb, name, n, len);
+ }
}
mrb_obj_iv_set_force(mrb, (struct RObject*)c, nsym, name);
}
@@ -287,11 +285,9 @@ mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super)
static mrb_value mrb_bob_init(mrb_state *mrb, mrb_value);
#ifdef MRB_METHOD_CACHE
static void mc_clear_all(mrb_state *mrb);
-static void mc_clear_by_class(mrb_state *mrb, struct RClass*);
static void mc_clear_by_id(mrb_state *mrb, struct RClass*, mrb_sym);
#else
#define mc_clear_all(mrb)
-#define mc_clear_by_class(mrb,c)
#define mc_clear_by_id(mrb,c,s)
#endif
@@ -305,7 +301,7 @@ mrb_class_inherited(mrb_state *mrb, struct RClass *super, struct RClass *klass)
super = mrb->object_class;
super->flags |= MRB_FL_CLASS_IS_INHERITED;
s = mrb_obj_value(super);
- mc_clear_by_class(mrb, klass);
+ mrb_mc_clear_by_class(mrb, klass);
mid = mrb_intern_lit(mrb, "inherited");
if (!mrb_func_basic_p(mrb, s, mid, mrb_bob_init)) {
mrb_value c = mrb_obj_value(klass);
@@ -544,15 +540,12 @@ MRB_API mrb_value*
mrb_get_argv(mrb_state *mrb)
{
mrb_int argc = mrb->c->ci->argc;
- mrb_value *array_argv;
+ mrb_value *array_argv = mrb->c->stack + 1;
if (argc < 0) {
- struct RArray *a = mrb_ary_ptr(mrb->c->stack[1]);
+ struct RArray *a = mrb_ary_ptr(*array_argv);
array_argv = ARY_PTR(a);
}
- else {
- array_argv = NULL;
- }
return array_argv;
}
@@ -596,9 +589,9 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
char c;
mrb_int i = 0;
va_list ap;
- mrb_int argc = mrb_get_argc(mrb);
- mrb_int arg_i = 0;
- mrb_value *array_argv = mrb_get_argv(mrb);
+ mrb_int argc = mrb->c->ci->argc;
+ mrb_value *array_argv = mrb->c->stack+1;
+ mrb_bool argv_on_stack = argc >= 0;
mrb_bool opt = FALSE;
mrb_bool opt_skip = TRUE;
mrb_bool given = TRUE;
@@ -606,10 +599,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_bool reqkarg = FALSE;
mrb_int needargc = 0;
+ if (!argv_on_stack) {
+ struct RArray *a = mrb_ary_ptr(*array_argv);
+ array_argv = ARY_PTR(a);
+ argc = ARY_LEN(a);
+ }
va_start(ap, format);
-#define ARGV \
- (array_argv ? array_argv : (mrb->c->stack + 1))
+#define ARGV array_argv
while ((c = *fmt++)) {
switch (c) {
@@ -622,11 +619,11 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
goto check_exit;
case '!':
break;
- case '&': case '?':
- if (opt) opt_skip = FALSE;
- break;
case ':':
reqkarg = TRUE;
+ /* fall through */
+ case '&': case '?':
+ if (opt) opt_skip = FALSE;
break;
default:
if (!opt) needargc ++;
@@ -679,8 +676,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
p = va_arg(ap, mrb_value*);
if (i < argc) {
- *p = argv[arg_i++];
- i++;
+ *p = argv[i++];
}
}
break;
@@ -692,12 +688,11 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
if (i < argc) {
mrb_value ss;
- ss = argv[arg_i++];
+ ss = argv[i++];
if (!class_ptr_p(ss)) {
mrb_raisef(mrb, E_TYPE_ERROR, "%v is not class/module", ss);
}
*p = ss;
- i++;
}
}
break;
@@ -707,8 +702,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
p = va_arg(ap, mrb_value*);
if (i < argc) {
- *p = argv[arg_i++];
- i++;
+ *p = argv[i++];
if (!(altmode && mrb_nil_p(*p))) {
mrb_to_str(mrb, *p);
}
@@ -721,8 +715,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
p = va_arg(ap, mrb_value*);
if (i < argc) {
- *p = argv[arg_i++];
- i++;
+ *p = argv[i++];
if (!(altmode && mrb_nil_p(*p))) {
*p = to_ary(mrb, *p);
}
@@ -735,8 +728,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
p = va_arg(ap, mrb_value*);
if (i < argc) {
- *p = argv[arg_i++];
- i++;
+ *p = argv[i++];
if (!(altmode && mrb_nil_p(*p))) {
*p = to_hash(mrb, *p);
}
@@ -752,8 +744,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
ps = va_arg(ap, char**);
pl = va_arg(ap, mrb_int*);
if (i < argc) {
- ss = argv[arg_i++];
- i++;
+ ss = argv[i++];
if (altmode && mrb_nil_p(ss)) {
*ps = NULL;
*pl = 0;
@@ -773,8 +764,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
ps = va_arg(ap, const char**);
if (i < argc) {
- ss = argv[arg_i++];
- i++;
+ ss = argv[i++];
if (altmode && mrb_nil_p(ss)) {
*ps = NULL;
}
@@ -795,8 +785,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
pb = va_arg(ap, mrb_value**);
pl = va_arg(ap, mrb_int*);
if (i < argc) {
- aa = argv[arg_i++];
- i++;
+ aa = argv[i++];
if (altmode && mrb_nil_p(aa)) {
*pb = 0;
*pl = 0;
@@ -817,14 +806,12 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
p = va_arg(ap, void**);
if (i < argc) {
- ss = argv[arg_i];
+ ss = argv[i++];
if (!mrb_istruct_p(ss))
{
mrb_raisef(mrb, E_TYPE_ERROR, "%v is not inline struct", ss);
}
*p = mrb_istruct_ptr(ss);
- arg_i++;
- i++;
}
}
break;
@@ -835,9 +822,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
p = va_arg(ap, mrb_float*);
if (i < argc) {
- *p = mrb_to_flo(mrb, argv[arg_i]);
- arg_i++;
- i++;
+ *p = mrb_to_flo(mrb, argv[i++]);
}
}
break;
@@ -848,9 +833,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
p = va_arg(ap, mrb_int*);
if (i < argc) {
- *p = mrb_fixnum(mrb_to_int(mrb, argv[arg_i]));
- arg_i++;
- i++;
+ *p = mrb_fixnum(mrb_to_int(mrb, argv[i++]));
}
}
break;
@@ -859,9 +842,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_bool *boolp = va_arg(ap, mrb_bool*);
if (i < argc) {
- mrb_value b = argv[arg_i++];
+ mrb_value b = argv[i++];
*boolp = mrb_test(b);
- i++;
}
}
break;
@@ -873,9 +855,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
if (i < argc) {
mrb_value ss;
- ss = argv[arg_i++];
+ ss = argv[i++];
*symp = to_sym(mrb, ss);
- i++;
}
}
break;
@@ -887,8 +868,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
datap = va_arg(ap, void**);
type = va_arg(ap, struct mrb_data_type const*);
if (i < argc) {
- mrb_value dd = argv[arg_i++];
- i++;
+ mrb_value dd = argv[i++];
if (altmode && mrb_nil_p(dd)) {
*datap = 0;
}
@@ -917,7 +897,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
break;
case '|':
- if (opt_skip && i == argc) return argc;
+ if (opt_skip && i == argc) goto finish;
opt = TRUE;
break;
case '?':
@@ -933,7 +913,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
{
mrb_value **var;
mrb_int *pl;
- mrb_bool nocopy = altmode || array_argv ? TRUE : FALSE;
+ mrb_bool nocopy = (altmode || !argv_on_stack) ? TRUE : FALSE;
var = va_arg(ap, mrb_value**);
pl = va_arg(ap, mrb_int*);
@@ -941,16 +921,15 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
*pl = argc-i;
if (*pl > 0) {
if (nocopy) {
- *var = argv+arg_i;
+ *var = argv+i;
}
else {
- mrb_value args = mrb_ary_new_from_values(mrb, *pl, argv+arg_i);
+ mrb_value args = mrb_ary_new_from_values(mrb, *pl, argv+i);
RARRAY(args)->c = NULL;
*var = RARRAY_PTR(args);
}
}
i = argc;
- arg_i += *pl;
}
else {
*pl = 0;
@@ -1025,6 +1004,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
if (!c && argc > i) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
}
+
+finish:
va_end(ap);
return i;
}
@@ -1109,7 +1090,7 @@ include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, stru
m->flags |= MRB_FL_CLASS_IS_INHERITED;
ins_pos->super = ic;
mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ic);
- mc_clear_by_class(mrb, ins_pos);
+ mrb_mc_clear_by_class(mrb, ins_pos);
ins_pos = ic;
skip:
m = m->super;
@@ -1261,33 +1242,45 @@ mrb_mod_dummy_visibility(mrb_state *mrb, mrb_value mod)
return mod;
}
-MRB_API mrb_value
-mrb_singleton_class(mrb_state *mrb, mrb_value v)
+/* returns mrb_class_ptr(mrb_singleton_class()) */
+/* except that it return NULL for immediate values */
+MRB_API struct RClass*
+mrb_singleton_class_ptr(mrb_state *mrb, mrb_value v)
{
struct RBasic *obj;
switch (mrb_type(v)) {
case MRB_TT_FALSE:
if (mrb_nil_p(v))
- return mrb_obj_value(mrb->nil_class);
- return mrb_obj_value(mrb->false_class);
+ return mrb->nil_class;
+ return mrb->false_class;
case MRB_TT_TRUE:
- return mrb_obj_value(mrb->true_class);
+ return mrb->true_class;
case MRB_TT_CPTR:
- return mrb_obj_value(mrb->object_class);
+ return mrb->object_class;
case MRB_TT_SYMBOL:
case MRB_TT_FIXNUM:
#ifndef MRB_WITHOUT_FLOAT
case MRB_TT_FLOAT:
#endif
- mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton");
- return mrb_nil_value(); /* not reached */
+ return NULL;
default:
break;
}
obj = mrb_basic_ptr(v);
prepare_singleton_class(mrb, obj);
- return mrb_obj_value(obj->c);
+ return obj->c;
+}
+
+MRB_API mrb_value
+mrb_singleton_class(mrb_state *mrb, mrb_value v)
+{
+ struct RClass *c = mrb_singleton_class_ptr(mrb, v);
+
+ if (c == NULL) {
+ mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton");
+ }
+ return mrb_obj_value(c);
}
MRB_API void
@@ -1322,8 +1315,8 @@ mc_clear_all(mrb_state *mrb)
}
}
-static void
-mc_clear_by_class(mrb_state *mrb, struct RClass *c)
+void
+mrb_mc_clear_by_class(mrb_state *mrb, struct RClass *c)
{
struct mrb_cache_entry *mc = mrb->cache;
int i;
@@ -1718,7 +1711,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c)
/* toplevel class/module */
return mrb_sym_str(mrb, mrb_symbol(path));
}
- return path;
+ return mrb_str_dup(mrb, path);
}
MRB_API struct RClass*
@@ -1735,7 +1728,10 @@ mrb_class_real(struct RClass* cl)
MRB_API const char*
mrb_class_name(mrb_state *mrb, struct RClass* c)
{
- mrb_value name = class_name_str(mrb, c);
+ mrb_value name;
+
+ if (c == NULL) return NULL;
+ name = class_name_str(mrb, c);
return RSTRING_PTR(name);
}
@@ -1885,8 +1881,7 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
return mrb_str_cat_lit(mrb, str, ">");
}
else {
- mrb_value str = class_name_str(mrb, mrb_class_ptr(klass));
- return mrb_frozen_p(mrb_basic_ptr(str)) ? mrb_str_dup(mrb, str) : str;
+ return class_name_str(mrb, mrb_class_ptr(klass));
}
}
@@ -2324,7 +2319,9 @@ mrb_init_class(mrb_state *mrb)
mrb_define_method(mrb, mod, "dup", mrb_mod_dup, MRB_ARGS_NONE());
mrb_undef_method(mrb, cls, "append_features");
+ mrb_undef_method(mrb, cls, "prepend_features");
mrb_undef_method(mrb, cls, "extend_object");
+ mrb_undef_method(mrb, cls, "module_function");
mrb->top_self = (struct RObject*)mrb_obj_alloc(mrb, MRB_TT_OBJECT, mrb->object_class);
mrb_define_singleton_method(mrb, mrb->top_self, "inspect", inspect_main, MRB_ARGS_NONE());
diff --git a/src/codedump.c b/src/codedump.c
index 7faa39360..649be176b 100644
--- a/src/codedump.c
+++ b/src/codedump.c
@@ -130,6 +130,10 @@ codedump(mrb_state *mrb, mrb_irep *irep)
printf("OP_LOADI\tR%d\t-%d\t", a, b);
print_lv_a(mrb, irep, a);
break;
+ CASE(OP_LOADI16, BS):
+ printf("OP_LOADI16\tR%d\t%d\t", a, (int)(int16_t)b);
+ print_lv_a(mrb, irep, a);
+ break;
CASE(OP_LOADI__1, B):
printf("OP_LOADI__1\tR%d\t\t", a);
print_lv_a(mrb, irep, a);
diff --git a/src/dump.c b/src/dump.c
index 183f3b67d..a6bbe68f3 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -13,9 +13,6 @@
#include <mruby/numeric.h>
#include <mruby/debug.h>
-#define FLAG_BYTEORDER_NATIVE 2
-#define FLAG_BYTEORDER_NONATIVE 0
-
#ifndef MRB_WITHOUT_FLOAT
#ifdef MRB_USE_FLOAT
#define MRB_FLOAT_FMT "%.9g"
@@ -709,22 +706,7 @@ write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t *bin, uint8
uint16_t crc;
uint32_t offset;
- switch (flags & DUMP_ENDIAN_NAT) {
- endian_big:
- case DUMP_ENDIAN_BIG:
- memcpy(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident));
- break;
- endian_little:
- case DUMP_ENDIAN_LIL:
- memcpy(header->binary_ident, RITE_BINARY_IDENT_LIL, sizeof(header->binary_ident));
- break;
-
- case DUMP_ENDIAN_NAT:
- if (bigendian_p()) goto endian_big;
- goto endian_little;
- break;
- }
-
+ memcpy(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident));
memcpy(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version));
memcpy(header->compiler_name, RITE_COMPILER_NAME, sizeof(header->compiler_name));
memcpy(header->compiler_version, RITE_COMPILER_VERSION, sizeof(header->compiler_version));
@@ -764,21 +746,6 @@ lv_defined_p(mrb_irep *irep)
return FALSE;
}
-static uint8_t
-dump_flags(uint8_t flags, uint8_t native)
-{
- if (native == FLAG_BYTEORDER_NATIVE) {
- if ((flags & DUMP_ENDIAN_NAT) == 0) {
- return (flags & DUMP_DEBUG_INFO) | DUMP_ENDIAN_NAT;
- }
- return flags;
- }
- if ((flags & DUMP_ENDIAN_NAT) == 0) {
- return (flags & DUMP_DEBUG_INFO) | DUMP_ENDIAN_BIG;
- }
- return flags;
-}
-
static int
dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size)
{
@@ -870,7 +837,7 @@ error_exit:
int
mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size)
{
- return dump_irep(mrb, irep, dump_flags(flags, FLAG_BYTEORDER_NONATIVE), bin, bin_size);
+ return dump_irep(mrb, irep, flags, bin, bin_size);
}
#ifndef MRB_DISABLE_STDIO
@@ -886,7 +853,7 @@ mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE* fp)
return MRB_DUMP_INVALID_ARGUMENT;
}
- result = dump_irep(mrb, irep, dump_flags(flags, FLAG_BYTEORDER_NONATIVE), &bin, &bin_size);
+ result = dump_irep(mrb, irep, flags, &bin, &bin_size);
if (result == MRB_DUMP_OK) {
if (fwrite(bin, sizeof(bin[0]), bin_size, fp) != bin_size) {
result = MRB_DUMP_WRITE_FAULT;
@@ -897,20 +864,6 @@ mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE* fp)
return result;
}
-static mrb_bool
-dump_bigendian_p(uint8_t flags)
-{
- switch (flags & DUMP_ENDIAN_NAT) {
- case DUMP_ENDIAN_BIG:
- return TRUE;
- case DUMP_ENDIAN_LIL:
- return FALSE;
- default:
- case DUMP_ENDIAN_NAT:
- return bigendian_p();
- }
-}
-
int
mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, const char *initname)
{
@@ -921,23 +874,8 @@ mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, con
if (fp == NULL || initname == NULL || initname[0] == '\0') {
return MRB_DUMP_INVALID_ARGUMENT;
}
- flags = dump_flags(flags, FLAG_BYTEORDER_NATIVE);
result = dump_irep(mrb, irep, flags, &bin, &bin_size);
if (result == MRB_DUMP_OK) {
- if (!dump_bigendian_p(flags)) {
- if (fprintf(fp, "/* dumped in little endian order.\n"
- " use `mrbc -E` option for big endian CPU. */\n") < 0) {
- mrb_free(mrb, bin);
- return MRB_DUMP_WRITE_FAULT;
- }
- }
- else {
- if (fprintf(fp, "/* dumped in big endian order.\n"
- " use `mrbc -e` option for better performance on little endian CPU. */\n") < 0) {
- mrb_free(mrb, bin);
- return MRB_DUMP_WRITE_FAULT;
- }
- }
if (fprintf(fp, "#include <stdint.h>\n") < 0) { /* for uint8_t under at least Darwin */
mrb_free(mrb, bin);
return MRB_DUMP_WRITE_FAULT;
diff --git a/src/error.c b/src/error.c
index 43b09ec66..260ca7a3d 100644
--- a/src/error.c
+++ b/src/error.c
@@ -13,7 +13,6 @@
#include <mruby/proc.h>
#include <mruby/string.h>
#include <mruby/variable.h>
-#include <mruby/debug.h>
#include <mruby/error.h>
#include <mruby/class.h>
#include <mruby/throw.h>
@@ -88,7 +87,7 @@ exc_exception(mrb_state *mrb, mrb_value self)
* no message is set).
*/
-static mrb_value
+mrb_value
exc_to_s(mrb_state *mrb, mrb_value exc)
{
mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg"));
@@ -128,37 +127,13 @@ exc_message(mrb_state *mrb, mrb_value exc)
* returns message and class name.
*/
-static mrb_value
-exc_inspect(mrb_state *mrb, mrb_value exc)
+mrb_value
+mrb_exc_inspect(mrb_state *mrb, mrb_value exc)
{
- mrb_value str, mesg, file, line;
- mrb_bool append_mesg;
- const char *cname;
-
- mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg"));
- file = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "file"));
- line = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "line"));
-
- append_mesg = !mrb_nil_p(mesg);
- if (append_mesg) {
- mesg = mrb_obj_as_string(mrb, mesg);
- append_mesg = RSTRING_LEN(mesg) > 0;
- }
-
- cname = mrb_obj_classname(mrb, exc);
- str = mrb_str_new_cstr(mrb, cname);
- if (mrb_string_p(file) && mrb_fixnum_p(line)) {
- if (append_mesg) {
- str = mrb_format(mrb, "%v:%v: %v (%v)", file, line, mesg, str);
- }
- else {
- str = mrb_format(mrb, "%v:%v: %v", file, line, str);
- }
- }
- else if (append_mesg) {
- str = mrb_format(mrb, "%v: %v", str, mesg);
- }
- return str;
+ mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg"));
+ mrb_value cname = mrb_mod_to_s(mrb, mrb_obj_value(mrb_obj_class(mrb, exc)));
+ mesg = mrb_obj_as_string(mrb, mesg);
+ return RSTRING_LEN(mesg) == 0 ? cname : mrb_format(mrb, "%v (%v)", mesg, cname);
}
void mrb_keep_backtrace(mrb_state *mrb, mrb_value exc);
@@ -192,33 +167,6 @@ exc_set_backtrace(mrb_state *mrb, mrb_value exc)
return backtrace;
}
-static void
-exc_debug_info(mrb_state *mrb, struct RObject *exc)
-{
- mrb_callinfo *ci = mrb->c->ci;
- const mrb_code *pc = ci->pc;
-
- if (mrb_obj_iv_defined(mrb, exc, mrb_intern_lit(mrb, "file"))) return;
- while (ci >= mrb->c->cibase) {
- const mrb_code *err = ci->err;
-
- if (!err && pc) err = pc - 1;
- 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(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));
- return;
- }
- }
- pc = ci->pc;
- ci--;
- }
-}
-
void
mrb_exc_set(mrb_state *mrb, mrb_value exc)
{
@@ -232,7 +180,6 @@ mrb_exc_set(mrb_state *mrb, mrb_value exc)
mrb->gc.arena_idx--;
}
if (!mrb->gc.out_of_memory && !mrb_frozen_p(mrb->exc)) {
- exc_debug_info(mrb, mrb->exc);
mrb_keep_backtrace(mrb, exc);
}
}
@@ -355,7 +302,11 @@ mrb_vformat(mrb_state *mrb, const char *format, va_list ap)
mrb_gc_arena_restore(mrb, ai);
break;
case 'n':
+#if UINT32_MAX < INT_MAX
+ obj = mrb_symbol_value((mrb_sym)va_arg(ap, int));
+#else
obj = mrb_symbol_value(va_arg(ap, mrb_sym));
+#endif
goto L_cat_obj;
case 's':
chars = va_arg(ap, char*);
@@ -530,7 +481,7 @@ exception_call:
break;
default:
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%i for 0..3)", argc);
+ mrb_argnum_error(mrb, argc, 0, 3);
break;
}
if (argc > 0) {
@@ -586,6 +537,19 @@ mrb_frozen_error(mrb_state *mrb, void *frozen_obj)
mrb_raisef(mrb, E_FROZEN_ERROR, "can't modify frozen %t", mrb_obj_value(frozen_obj));
}
+MRB_API mrb_noreturn void
+mrb_argnum_error(mrb_state *mrb, mrb_int argc, int min, int max)
+{
+#define FMT(exp) "wrong number of arguments (given %i, expected " exp ")"
+ if (min == max)
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, FMT("%d"), argc, min);
+ else if (max < 0)
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, FMT("%d+"), argc, min);
+ else
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, FMT("%d..%d"), argc, min, max);
+#undef FMT
+}
+
void
mrb_init_exception(mrb_state *mrb)
{
@@ -598,7 +562,7 @@ mrb_init_exception(mrb_state *mrb)
mrb_define_method(mrb, exception, "initialize", exc_initialize, MRB_ARGS_OPT(1));
mrb_define_method(mrb, exception, "to_s", exc_to_s, MRB_ARGS_NONE());
mrb_define_method(mrb, exception, "message", exc_message, MRB_ARGS_NONE());
- mrb_define_method(mrb, exception, "inspect", exc_inspect, MRB_ARGS_NONE());
+ mrb_define_method(mrb, exception, "inspect", mrb_exc_inspect, MRB_ARGS_NONE());
mrb_define_method(mrb, exception, "backtrace", mrb_exc_backtrace, MRB_ARGS_NONE());
mrb_define_method(mrb, exception, "set_backtrace", exc_set_backtrace, MRB_ARGS_REQ(1));
diff --git a/src/etc.c b/src/etc.c
index 607e82ca1..6e1533e3d 100644
--- a/src/etc.c
+++ b/src/etc.c
@@ -140,7 +140,13 @@ mrb_obj_id(mrb_value obj)
}
}
+#if defined(MRB_NAN_BOXING) && defined(MRB_64BIT)
+#define mrb_xxx_boxing_cptr_value mrb_nan_boxing_cptr_value
+#endif
+
#ifdef MRB_WORD_BOXING
+#define mrb_xxx_boxing_cptr_value mrb_word_boxing_cptr_value
+
#ifndef MRB_WITHOUT_FLOAT
MRB_API mrb_value
mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f)
@@ -164,17 +170,20 @@ mrb_word_boxing_float_pool(mrb_state *mrb, mrb_float f)
return mrb_obj_value(nf);
}
#endif /* MRB_WITHOUT_FLOAT */
+#endif /* MRB_WORD_BOXING */
+#if defined(MRB_WORD_BOXING) || (defined(MRB_NAN_BOXING) && defined(MRB_64BIT))
MRB_API mrb_value
-mrb_word_boxing_cptr_value(mrb_state *mrb, void *p)
+mrb_xxx_boxing_cptr_value(mrb_state *mrb, void *p)
{
mrb_value v;
+ struct RCptr *cptr = (struct RCptr*)mrb_obj_alloc(mrb, MRB_TT_CPTR, mrb->object_class);
- v.value.p = mrb_obj_alloc(mrb, MRB_TT_CPTR, mrb->object_class);
- v.value.vp->p = p;
+ SET_OBJ_VALUE(v, cptr);
+ cptr->p = p;
return v;
}
-#endif /* MRB_WORD_BOXING */
+#endif
#if defined _MSC_VER && _MSC_VER < 1900
diff --git a/src/fmt_fp.c b/src/fmt_fp.c
index 1f1af6764..9ae5dd177 100644
--- a/src/fmt_fp.c
+++ b/src/fmt_fp.c
@@ -30,7 +30,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <limits.h>
#include <string.h>
-#include <stdint.h>
#include <math.h>
#include <float.h>
#include <ctype.h>
@@ -38,9 +37,19 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <mruby.h>
#include <mruby/string.h>
+struct fmt_args;
+
+typedef void output_func(struct fmt_args *f, const char *s, size_t l);
+
struct fmt_args {
mrb_state *mrb;
- mrb_value str;
+ output_func *output;
+ void *opaque;
+};
+
+struct mrb_cstr {
+ char *buf;
+ size_t len;
};
#define MAX(a,b) ((a)>(b) ? (a) : (b))
@@ -55,15 +64,44 @@ struct fmt_args {
#define PAD_POS (1U<<(' '-' '))
#define MARK_POS (1U<<('+'-' '))
+#define FLAGMASK (ALT_FORM|ZERO_PAD|LEFT_ADJ|PAD_POS|MARK_POS)
+
+static output_func strcat_value;
+static output_func strcat_cstr;
+
+static void
+strcat_value(struct fmt_args *f, const char *s, size_t l)
+{
+ mrb_value str = *(mrb_value*)f->opaque;
+ mrb_str_cat(f->mrb, str, s, l);
+}
+
+static void
+strcat_cstr(struct fmt_args *f, const char *s, size_t l)
+{
+ struct mrb_cstr *cstr = (struct mrb_cstr*)f->opaque;
+
+ if (l > cstr->len) {
+ mrb_state *mrb = f->mrb;
+
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "string buffer too small");
+ }
+
+ memcpy(cstr->buf, s, l);
+
+ cstr->buf += l;
+ cstr->len -= l;
+}
+
static void
out(struct fmt_args *f, const char *s, size_t l)
{
- mrb_str_cat(f->mrb, f->str, s, l);
+ f->output(f, s, l);
}
#define PAD_SIZE 256
static void
-pad(struct fmt_args *f, char c, ptrdiff_t w, ptrdiff_t l, uint8_t fl)
+pad(struct fmt_args *f, char c, ptrdiff_t w, ptrdiff_t l, uint32_t fl)
{
char pad[PAD_SIZE];
if (fl & (LEFT_ADJ | ZERO_PAD) || l >= w) return;
@@ -93,7 +131,7 @@ typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)
#endif
static int
-fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
+fmt_fp(struct fmt_args *f, long double y, ptrdiff_t w, ptrdiff_t p, uint32_t fl, int t)
{
uint32_t big[(LDBL_MANT_DIG+28)/29 + 1 // mantissa expansion
+ (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9]; // exponent expansion
@@ -118,11 +156,11 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
if (!isfinite(y)) {
const char *ss = (t&32)?"inf":"INF";
if (y!=y) ss=(t&32)?"nan":"NAN";
- pad(f, ' ', 0, 3+pl, fl&~ZERO_PAD);
+ pad(f, ' ', w, 3+pl, fl&~ZERO_PAD);
out(f, prefix, pl);
out(f, ss, 3);
- pad(f, ' ', 0, 3+pl, fl^LEFT_ADJ);
- return 3+(int)pl;
+ pad(f, ' ', w, 3+pl, fl^LEFT_ADJ);
+ return MAX(w, 3+(int)pl);
}
y = frexp((double)y, &e2) * 2;
@@ -170,14 +208,14 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
else
l = (s-buf) + (ebuf-estr);
- pad(f, ' ', 0, pl+l, fl);
+ pad(f, ' ', w, pl+l, fl);
out(f, prefix, pl);
- pad(f, '0', 0, pl+l, fl^ZERO_PAD);
+ pad(f, '0', w, pl+l, fl^ZERO_PAD);
out(f, buf, s-buf);
pad(f, '0', l-(ebuf-estr)-(s-buf), 0, 0);
out(f, estr, ebuf-estr);
- pad(f, ' ', 0, pl+l, fl^LEFT_ADJ);
- return (int)pl+(int)l;
+ pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
+ return MAX(w, (int)pl+(int)l);
}
if (p<0) p=6;
@@ -289,9 +327,9 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
l += ebuf-estr;
}
- pad(f, ' ', 0, pl+l, fl);
+ pad(f, ' ', w, pl+l, fl);
out(f, prefix, pl);
- pad(f, '0', 0, pl+l, fl^ZERO_PAD);
+ pad(f, '0', w, pl+l, fl^ZERO_PAD);
if ((t|32)=='f') {
if (a>r) a=r;
@@ -326,21 +364,33 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
out(f, estr, ebuf-estr);
}
- pad(f, ' ', 0, pl+l, fl^LEFT_ADJ);
+ pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
- return (int)pl+(int)l;
+ return MAX(w, (int)pl+(int)l);
}
static int
fmt_core(struct fmt_args *f, const char *fmt, mrb_float flo)
{
- ptrdiff_t p;
+ ptrdiff_t w, p;
+ uint32_t fl;
if (*fmt != '%') {
return -1;
}
++fmt;
+ /* Read modifier flags */
+ for (fl=0; (unsigned)*fmt-' '<32 && (FLAGMASK&(1U<<(*fmt-' '))); fmt++)
+ fl |= 1U<<(*fmt-' ');
+
+ /* - and 0 flags are mutually exclusive */
+ if (fl & LEFT_ADJ) fl &= ~ZERO_PAD;
+
+ for (w = 0; ISDIGIT(*fmt); ++fmt) {
+ w = 10 * w + (*fmt - '0');
+ }
+
if (*fmt == '.') {
++fmt;
for (p = 0; ISDIGIT(*fmt); ++fmt) {
@@ -354,29 +404,49 @@ fmt_core(struct fmt_args *f, const char *fmt, mrb_float flo)
switch (*fmt) {
case 'e': case 'f': case 'g': case 'a':
case 'E': case 'F': case 'G': case 'A':
- return fmt_fp(f, flo, p, 0, *fmt);
+ return fmt_fp(f, flo, w, p, fl, *fmt);
default:
return -1;
}
}
-mrb_value
+MRB_API mrb_value
mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt)
{
struct fmt_args f;
+ mrb_value str = mrb_str_new_capa(mrb, 24);
f.mrb = mrb;
- f.str = mrb_str_new_capa(mrb, 24);
+ f.output = strcat_value;
+ f.opaque = (void*)&str;
if (fmt_core(&f, fmt, mrb_float(flo)) < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format string");
}
- return f.str;
+ return str;
+}
+
+MRB_API int
+mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_float fval)
+{
+ struct fmt_args f;
+ struct mrb_cstr cstr;
+
+ cstr.buf = buf;
+ cstr.len = len - 1; /* reserve NUL terminator */
+ f.mrb = mrb;
+ f.output = strcat_cstr;
+ f.opaque = (void*)&cstr;
+ if (fmt_core(&f, fmt, fval) < 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format string");
+ }
+ *cstr.buf = '\0';
+ return cstr.buf - buf;
}
#else /* MRB_DISABLE_STDIO || _WIN32 || _WIN64 */
#include <mruby.h>
#include <stdio.h>
-mrb_value
+MRB_API mrb_value
mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt)
{
char buf[25];
@@ -384,5 +454,11 @@ 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);
}
+
+MRB_API int
+mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_float fval)
+{
+ return snprintf(buf, len, fmt, fval);
+}
#endif /* MRB_DISABLE_STDIO || _WIN32 || _WIN64 */
#endif
diff --git a/src/gc.c b/src/gc.c
index 835d1c61d..8d9a1806c 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -280,8 +280,9 @@ mrb_free(mrb_state *mrb, void *p)
MRB_API void*
mrb_alloca(mrb_state *mrb, size_t size)
{
- mrb_value str = mrb_str_new(mrb, NULL, size);
- return RSTRING_PTR(str);
+ struct RString *s;
+ s = (struct RString*)mrb_obj_alloc(mrb, MRB_TT_STRING, mrb->string_class);
+ return s->as.heap.ptr = (char*)mrb_malloc(mrb, size);
}
static mrb_bool
@@ -806,10 +807,12 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end)
case MRB_TT_SCLASS:
mrb_gc_free_mt(mrb, (struct RClass*)obj);
mrb_gc_free_iv(mrb, (struct RObject*)obj);
+ mrb_mc_clear_by_class(mrb, (struct RClass*)obj);
break;
case MRB_TT_ICLASS:
if (MRB_FLAG_TEST(obj, MRB_FL_CLASS_IS_ORIGIN))
mrb_gc_free_mt(mrb, (struct RClass*)obj);
+ mrb_mc_clear_by_class(mrb, (struct RClass*)obj);
break;
case MRB_TT_ENV:
{
@@ -1609,6 +1612,9 @@ mrb_init_gc(mrb_state *mrb)
{
struct RClass *gc;
+ mrb_static_assert(sizeof(RVALUE) <= sizeof(void*) * 6,
+ "RVALUE size must be within 6 words");
+
gc = mrb_define_module(mrb, "GC");
mrb_define_class_method(mrb, gc, "start", gc_start, MRB_ARGS_NONE());
diff --git a/src/hash.c b/src/hash.c
index 21e34a5ea..ec79a3def 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -222,9 +222,8 @@ static void
ht_compact(mrb_state *mrb, htable *t)
{
segment *seg;
- mrb_int i;
+ uint16_t i, i2;
segment *seg2 = NULL;
- mrb_int i2;
mrb_int size = 0;
if (t == NULL) return;
@@ -374,7 +373,7 @@ ht_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val)
deleted++;
continue;
}
- if (ht_hash_equal(mrb, t, k, key)) {
+ if (ht_hash_equal(mrb, t, key, k)) {
seg->e[i].val = val;
return;
}
@@ -455,7 +454,7 @@ ht_get(mrb_state *mrb, htable *t, mrb_value key, mrb_value *vp)
return FALSE;
}
if (mrb_undef_p(k)) continue;
- if (ht_hash_equal(mrb, t, k, key)) {
+ if (ht_hash_equal(mrb, t, key, k)) {
if (vp) *vp = seg->e[i].val;
return TRUE;
}
@@ -800,7 +799,7 @@ mrb_hash_init(mrb_state *mrb, mrb_value hash)
mrb_hash_modify(mrb, hash);
if (!mrb_nil_p(block)) {
if (ifnone_p) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
+ mrb_argnum_error(mrb, 1, 0, 0);
}
RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT;
ifnone = block;
@@ -1414,7 +1413,7 @@ mrb_init_hash(mrb_state *mrb)
mrb_define_method(mrb, h, "[]", mrb_hash_aget, MRB_ARGS_REQ(1)); /* 15.2.13.4.2 */
mrb_define_method(mrb, h, "[]=", mrb_hash_aset, MRB_ARGS_REQ(2)); /* 15.2.13.4.3 */
mrb_define_method(mrb, h, "clear", mrb_hash_clear, MRB_ARGS_NONE()); /* 15.2.13.4.4 */
- mrb_define_method(mrb, h, "default", mrb_hash_default, MRB_ARGS_ANY()); /* 15.2.13.4.5 */
+ mrb_define_method(mrb, h, "default", mrb_hash_default, MRB_ARGS_OPT(1)); /* 15.2.13.4.5 */
mrb_define_method(mrb, h, "default=", mrb_hash_set_default, MRB_ARGS_REQ(1)); /* 15.2.13.4.6 */
mrb_define_method(mrb, h, "default_proc", mrb_hash_default_proc,MRB_ARGS_NONE()); /* 15.2.13.4.7 */
mrb_define_method(mrb, h, "default_proc=", mrb_hash_set_default_proc,MRB_ARGS_REQ(1)); /* 15.2.13.4.7 */
@@ -1423,7 +1422,7 @@ mrb_init_hash(mrb_state *mrb)
mrb_define_method(mrb, h, "has_key?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.13 */
mrb_define_method(mrb, h, "has_value?", mrb_hash_has_value, MRB_ARGS_REQ(1)); /* 15.2.13.4.14 */
mrb_define_method(mrb, h, "include?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.15 */
- mrb_define_method(mrb, h, "initialize", mrb_hash_init, MRB_ARGS_OPT(1)); /* 15.2.13.4.16 */
+ mrb_define_method(mrb, h, "initialize", mrb_hash_init, MRB_ARGS_OPT(1)|MRB_ARGS_BLOCK()); /* 15.2.13.4.16 */
mrb_define_method(mrb, h, "key?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.18 */
mrb_define_method(mrb, h, "keys", mrb_hash_keys, MRB_ARGS_NONE()); /* 15.2.13.4.19 */
mrb_define_method(mrb, h, "length", mrb_hash_size_m, MRB_ARGS_NONE()); /* 15.2.13.4.20 */
diff --git a/src/kernel.c b/src/kernel.c
index c88a457f0..ae9617686 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -325,7 +325,7 @@ mrb_obj_clone(mrb_state *mrb, mrb_value self)
mrb_value clone;
if (mrb_immediate_p(self)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %v", self);
+ return self;
}
if (mrb_sclass_p(self)) {
mrb_raise(mrb, E_TYPE_ERROR, "can't clone singleton class");
@@ -366,7 +366,7 @@ mrb_obj_dup(mrb_state *mrb, mrb_value obj)
mrb_value dup;
if (mrb_immediate_p(obj)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "can't dup %v", obj);
+ return obj;
}
if (mrb_sclass_p(obj)) {
mrb_raise(mrb, E_TYPE_ERROR, "can't dup singleton class");
@@ -384,7 +384,7 @@ mrb_obj_extend(mrb_state *mrb, mrb_int argc, mrb_value *argv, mrb_value obj)
mrb_int i;
if (argc == 0) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (at least 1)");
+ mrb_argnum_error(mrb, argc, 1, -1);
}
for (i = 0; i < argc; i++) {
mrb_check_type(mrb, argv[i], MRB_TT_MODULE);
@@ -685,7 +685,6 @@ mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args)
* r.xxiii #=> 23
* r.mm #=> 2000
*/
-#ifdef MRB_DEFAULT_METHOD_MISSING
static mrb_value
mrb_obj_missing(mrb_state *mrb, mrb_value mod)
{
@@ -698,7 +697,6 @@ mrb_obj_missing(mrb_state *mrb, mrb_value mod)
/* not reached */
return mrb_nil_value();
}
-#endif
static inline mrb_bool
basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub)
@@ -791,14 +789,12 @@ mrb_init_kernel(mrb_state *mrb)
mrb_define_method(mrb, krn, "is_a?", mrb_obj_is_kind_of_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.24 */
mrb_define_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.25 */
mrb_define_method(mrb, krn, "kind_of?", mrb_obj_is_kind_of_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.26 */
-#ifdef MRB_DEFAULT_METHOD_MISSING
mrb_define_method(mrb, krn, "method_missing", mrb_obj_missing, MRB_ARGS_ANY()); /* 15.3.1.3.30 */
-#endif
mrb_define_method(mrb, krn, "nil?", mrb_false, MRB_ARGS_NONE()); /* 15.3.1.3.32 */
mrb_define_method(mrb, krn, "object_id", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.33 */
mrb_define_method(mrb, krn, "raise", mrb_f_raise, MRB_ARGS_ANY()); /* 15.3.1.3.40 */
mrb_define_method(mrb, krn, "remove_instance_variable", mrb_obj_remove_instance_variable,MRB_ARGS_REQ(1)); /* 15.3.1.3.41 */
- mrb_define_method(mrb, krn, "respond_to?", obj_respond_to, MRB_ARGS_ANY()); /* 15.3.1.3.43 */
+ mrb_define_method(mrb, krn, "respond_to?", obj_respond_to, MRB_ARGS_ARG(1,1)); /* 15.3.1.3.43 */
mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, MRB_ARGS_NONE()); /* 15.3.1.3.46 */
mrb_define_method(mrb, krn, "__case_eqq", mrb_obj_ceqq, MRB_ARGS_REQ(1)); /* internal */
mrb_define_method(mrb, krn, "__to_int", mrb_to_int, MRB_ARGS_NONE()); /* internal */
diff --git a/src/load.c b/src/load.c
index 471ff3841..2a118c922 100644
--- a/src/load.c
+++ b/src/load.c
@@ -19,9 +19,6 @@
# error size_t must be at least 32 bits wide
#endif
-#define FLAG_BYTEORDER_BIG 2
-#define FLAG_BYTEORDER_LIL 4
-#define FLAG_BYTEORDER_NATIVE 8
#define FLAG_SRC_MALLOC 1
#define FLAG_SRC_STATIC 0
@@ -42,22 +39,22 @@ offset_crc_body(void)
}
#ifndef MRB_WITHOUT_FLOAT
+double mrb_str_len_to_dbl(mrb_state *mrb, const char *s, size_t len, mrb_bool badcheck);
+
static double
-str_to_double(mrb_state *mrb, mrb_value str)
+str_to_double(mrb_state *mrb, const char *p, size_t len)
{
- 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);
+ return mrb_str_len_to_dbl(mrb, p, len, TRUE);
}
#endif
+mrb_value mrb_str_len_to_inum(mrb_state *mrb, const char *str, mrb_int len, mrb_int base, int badcheck);
+
static mrb_irep*
read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags)
{
@@ -94,8 +91,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
if (SIZE_ERROR_MUL(irep->ilen, sizeof(mrb_code))) {
return NULL;
}
- if ((flags & FLAG_SRC_MALLOC) == 0 &&
- (flags & FLAG_BYTEORDER_NATIVE)) {
+ if ((flags & FLAG_SRC_MALLOC) == 0) {
irep->iseq = (mrb_code*)src;
src += sizeof(mrb_code) * irep->ilen;
irep->flags |= MRB_ISEQ_NO_FREE;
@@ -119,21 +115,17 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * plen);
for (i = 0; i < plen; i++) {
- mrb_value s;
+ const char *s;
+ mrb_bool st = (flags & FLAG_SRC_MALLOC)==0;
tt = *src++; /* pool TT */
pool_data_len = bin_to_uint16(src); /* pool data length */
src += sizeof(uint16_t);
- if (flags & FLAG_SRC_MALLOC) {
- s = mrb_str_new(mrb, (char *)src, pool_data_len);
- }
- else {
- s = mrb_str_new_static(mrb, (char *)src, pool_data_len);
- }
+ s = (const char*)src;
src += pool_data_len;
switch (tt) { /* pool data */
case IREP_TT_FIXNUM: {
- mrb_value num = mrb_str_to_inum(mrb, s, 10, FALSE);
+ mrb_value num = mrb_str_len_to_inum(mrb, s, pool_data_len, 10, FALSE);
#ifdef MRB_WITHOUT_FLOAT
irep->pool[i] = num;
#else
@@ -144,12 +136,12 @@ 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, str_to_double(mrb, s));
+ irep->pool[i] = mrb_float_pool(mrb, str_to_double(mrb, s, pool_data_len));
break;
#endif
case IREP_TT_STRING:
- irep->pool[i] = mrb_str_pool(mrb, s);
+ irep->pool[i] = mrb_str_pool(mrb, s, pool_data_len, st);
break;
default:
@@ -468,19 +460,7 @@ read_binary_header(const uint8_t *bin, size_t bufsize, size_t *bin_size, uint16_
return MRB_DUMP_READ_FAULT;
}
- if (memcmp(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)) == 0) {
- if (bigendian_p())
- *flags |= FLAG_BYTEORDER_NATIVE;
- else
- *flags |= FLAG_BYTEORDER_BIG;
- }
- else if (memcmp(header->binary_ident, RITE_BINARY_IDENT_LIL, sizeof(header->binary_ident)) == 0) {
- if (bigendian_p())
- *flags |= FLAG_BYTEORDER_LIL;
- else
- *flags |= FLAG_BYTEORDER_NATIVE;
- }
- else {
+ if (memcmp(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)) != 0) {
return MRB_DUMP_INVALID_FILE_HEADER;
}
diff --git a/src/numeric.c b/src/numeric.c
index 306b6ef4d..07a2d20a8 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -1485,13 +1485,14 @@ cmpnum(mrb_state *mrb, mrb_value v1, mrb_value v2)
/* 15.2.9.3.6 */
/*
* call-seq:
- * self.f <=> other.f => -1, 0, +1
+ * self.f <=> other.f => -1, 0, +1, or nil
* < => -1
* = => 0
* > => +1
* Comparison---Returns -1, 0, or +1 depending on whether <i>fix</i> is
* less than, equal to, or greater than <i>numeric</i>. This is the
- * basis for the tests in <code>Comparable</code>.
+ * basis for the tests in <code>Comparable</code>. When the operands are
+ * not comparable, it returns nil instead of raising an exception.
*/
static mrb_value
integral_cmp(mrb_state *mrb, mrb_value self)
@@ -1648,10 +1649,10 @@ mrb_init_numeric(mrb_state *mrb)
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) */
- mrb_define_method(mrb, integer, "round", int_to_i, MRB_ARGS_REQ(1)); /* 15.2.8.3.12 (x) */
- mrb_define_method(mrb, integer, "truncate", int_to_i, MRB_ARGS_REQ(1)); /* 15.2.8.3.15 (x) */
+ mrb_define_method(mrb, integer, "ceil", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.8 (x) */
+ mrb_define_method(mrb, integer, "floor", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.10 (x) */
+ mrb_define_method(mrb, integer, "round", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.12 (x) */
+ mrb_define_method(mrb, integer, "truncate", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.15 (x) */
#endif
/* Fixnum Class */
diff --git a/src/print.c b/src/print.c
index 03b5eadfa..7d2d16086 100644
--- a/src/print.c
+++ b/src/print.c
@@ -31,7 +31,6 @@ MRB_API void
mrb_print_error(mrb_state *mrb)
{
mrb_print_backtrace(mrb);
- printstr(mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0), stderr);
}
MRB_API void
diff --git a/src/string.c b/src/string.c
index b7eef5888..44e3c9069 100644
--- a/src/string.c
+++ b/src/string.c
@@ -10,6 +10,7 @@
#ifndef MRB_WITHOUT_FLOAT
#include <float.h>
+#include <math.h>
#endif
#include <limits.h>
#include <stddef.h>
@@ -24,7 +25,7 @@
typedef struct mrb_shared_string {
int refcnt;
- mrb_int capa;
+ mrb_ssize capa;
char *ptr;
} mrb_shared_string;
@@ -40,8 +41,8 @@ str_init_normal_capa(mrb_state *mrb, struct RString *s,
if (p) memcpy(dst, p, len);
dst[len] = '\0';
s->as.heap.ptr = dst;
- s->as.heap.len = (mrb_int)len;
- s->as.heap.aux.capa = (mrb_int)capa;
+ s->as.heap.len = (mrb_ssize)len;
+ s->as.heap.aux.capa = (mrb_ssize)capa;
RSTR_UNSET_TYPE_FLAG(s);
return s;
}
@@ -66,7 +67,7 @@ static struct RString*
str_init_nofree(struct RString *s, const char *p, size_t len)
{
s->as.heap.ptr = (char *)p;
- s->as.heap.len = (mrb_int)len;
+ s->as.heap.len = (mrb_ssize)len;
s->as.heap.aux.capa = 0; /* nofree */
RSTR_SET_TYPE_FLAG(s, NOFREE);
return s;
@@ -118,7 +119,7 @@ str_new_static(mrb_state *mrb, const char *p, size_t len)
if (RSTR_EMBEDDABLE_P(len)) {
return str_init_embed(mrb_obj_alloc_string(mrb), p, len);
}
- if (len >= MRB_INT_MAX) {
+ if (len >= MRB_SSIZE_MAX) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
}
return str_init_nofree(mrb_obj_alloc_string(mrb), p, len);
@@ -130,7 +131,7 @@ str_new(mrb_state *mrb, const char *p, size_t len)
if (RSTR_EMBEDDABLE_P(len)) {
return str_init_embed(mrb_obj_alloc_string(mrb), p, len);
}
- if (len >= MRB_INT_MAX) {
+ if (len >= MRB_SSIZE_MAX) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
}
if (p && mrb_ro_data_p(p)) {
@@ -162,7 +163,7 @@ mrb_str_new_capa(mrb_state *mrb, size_t capa)
if (RSTR_EMBEDDABLE_P(capa)) {
s = str_init_embed(mrb_obj_alloc_string(mrb), NULL, 0);
}
- else if (capa >= MRB_INT_MAX) {
+ else if (capa >= MRB_SSIZE_MAX) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string capacity size too big");
/* not reached */
s = NULL;
@@ -190,8 +191,8 @@ mrb_str_buf_new(mrb_state *mrb, size_t capa)
static void
resize_capa(mrb_state *mrb, struct RString *s, size_t capacity)
{
-#if SIZE_MAX > MRB_INT_MAX
- mrb_assert(capacity < MRB_INT_MAX);
+#if SIZE_MAX > MRB_SSIZE_MAX
+ mrb_assert(capacity < MRB_SSIZE_MAX);
#endif
if (RSTR_EMBED_P(s)) {
if (!RSTR_EMBEDDABLE_P(capacity)) {
@@ -200,7 +201,7 @@ resize_capa(mrb_state *mrb, struct RString *s, size_t capacity)
}
else {
s->as.heap.ptr = (char*)mrb_realloc(mrb, RSTR_PTR(s), capacity+1);
- s->as.heap.aux.capa = (mrb_int)capacity;
+ s->as.heap.aux.capa = (mrb_ssize)capacity;
}
}
@@ -246,6 +247,28 @@ str_decref(mrb_state *mrb, mrb_shared_string *shared)
}
static void
+str_modify_keep_ascii(mrb_state *mrb, struct RString *s)
+{
+ if (RSTR_SHARED_P(s)) {
+ mrb_shared_string *shared = s->as.heap.aux.shared;
+
+ if (shared->refcnt == 1 && s->as.heap.ptr == shared->ptr) {
+ s->as.heap.aux.capa = shared->capa;
+ s->as.heap.ptr[s->as.heap.len] = '\0';
+ RSTR_UNSET_SHARED_FLAG(s);
+ mrb_free(mrb, shared);
+ }
+ else {
+ str_init_modifiable(mrb, s, s->as.heap.ptr, (size_t)s->as.heap.len);
+ str_decref(mrb, shared);
+ }
+ }
+ else if (RSTR_NOFREE_P(s) || RSTR_FSHARED_P(s)) {
+ str_init_modifiable(mrb, s, s->as.heap.ptr, (size_t)s->as.heap.len);
+ }
+}
+
+static void
check_null_byte(mrb_state *mrb, mrb_value str)
{
mrb_to_str(mrb, str);
@@ -278,8 +301,8 @@ static const char utf8len_codepage[256] =
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,
};
-static mrb_int
-utf8len(const char* p, const char* e)
+mrb_int
+mrb_utf8len(const char* p, const char* e)
{
mrb_int len;
mrb_int i;
@@ -295,14 +318,14 @@ utf8len(const char* p, const char* e)
}
mrb_int
-mrb_utf8_len(const char *str, mrb_int byte_len)
+mrb_utf8_strlen(const char *str, mrb_int byte_len)
{
mrb_int total = 0;
const char *p = str;
const char *e = p + byte_len;
while (p < e) {
- p += utf8len(p, e);
+ p += mrb_utf8len(p, e);
total++;
}
return total;
@@ -318,7 +341,7 @@ utf8_strlen(mrb_value str)
return byte_len;
}
else {
- mrb_int utf8_len = mrb_utf8_len(RSTR_PTR(s), byte_len);
+ mrb_int utf8_len = mrb_utf8_strlen(RSTR_PTR(s), byte_len);
if (byte_len == utf8_len) RSTR_SET_ASCII_FLAG(s);
return utf8_len;
}
@@ -339,7 +362,7 @@ chars2bytes(mrb_value s, mrb_int off, mrb_int idx)
const char *e = RSTRING_END(s);
for (b=i=0; p<e && i<idx; i++) {
- n = utf8len(p, e);
+ n = mrb_utf8len(p, e);
b += n;
p += n;
}
@@ -356,7 +379,7 @@ bytes2chars(char *p, mrb_int len, mrb_int bi)
mrb_int i;
for (i = 0; p < pivot; i ++) {
- p += utf8len(p, e);
+ p += mrb_utf8len(p, e);
}
if (p != pivot) return -1;
return i;
@@ -377,7 +400,7 @@ char_adjust(const char *beg, const char *end, const char *ptr)
while (p > beg) {
p --;
if ((*p & 0xc0) != 0x80) {
- int clen = utf8len(p, end);
+ int clen = mrb_utf8len(p, end);
if (clen > ptr - p) return p;
break;
}
@@ -440,10 +463,10 @@ str_index_str_by_char_search(mrb_state *mrb, const char *p, const char *pend, co
}
pivot = p + qstable[(unsigned char)p[slen - 1]];
- if (pivot > pend || pivot < p /* overflowed */) { return -1; }
+ if (pivot >= pend || pivot < p /* overflowed */) { return -1; }
do {
- p += utf8len(p, pend);
+ p += mrb_utf8len(p, pend);
off ++;
} while (p < pivot);
}
@@ -462,7 +485,7 @@ str_index_str_by_char(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
for (; pos > 0; pos --) {
if (pend - p < 1) { return -1; }
- p += utf8len(p, pend);
+ p += mrb_utf8len(p, pend);
}
if (slen < 1) { return off; }
@@ -481,25 +504,45 @@ str_index_str_by_char(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
#define str_index_str_by_char(mrb, str, sub, pos) str_index_str(mrb, str, sub, pos)
#endif
+#ifndef MRB_QS_SHORT_STRING_LENGTH
+#define MRB_QS_SHORT_STRING_LENGTH 2048
+#endif
+
static inline mrb_int
mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n)
{
- const unsigned char *x = xs, *xe = xs + m;
- const unsigned char *y = ys;
- int i;
- ptrdiff_t qstable[256];
+ if (n + m < MRB_QS_SHORT_STRING_LENGTH) {
+ const unsigned char *y = ys;
+ const unsigned char *ye = ys+n-m+1;
- /* Preprocessing */
- for (i = 0; i < 256; ++i)
- qstable[i] = m + 1;
- for (; x < xe; ++x)
- qstable[*x] = xe - x;
- /* Searching */
- for (; y + m <= ys + n; y += *(qstable + y[m])) {
- if (*xs == *y && memcmp(xs, y, m) == 0)
- return (mrb_int)(y - ys);
+ for (;;) {
+ y = (const unsigned char*)memchr(y, xs[0], (size_t)(ye-y));
+ if (y == NULL) return -1;
+ if (memcmp(xs, y, m) == 0) {
+ return (mrb_int)(y - ys);
+ }
+ y++;
+ }
+ return -1;
+ }
+ else {
+ const unsigned char *x = xs, *xe = xs + m;
+ const unsigned char *y = ys;
+ int i;
+ ptrdiff_t qstable[256];
+
+ /* Preprocessing */
+ for (i = 0; i < 256; ++i)
+ qstable[i] = m + 1;
+ for (; x < xe; ++x)
+ qstable[*x] = xe - x;
+ /* Searching */
+ for (; y + m <= ys + n; y += *(qstable + y[m])) {
+ if (*xs == *y && memcmp(xs, y, m) == 0)
+ return (mrb_int)(y - ys);
+ }
+ return -1;
}
- return -1;
}
static mrb_int
@@ -531,7 +574,7 @@ str_share(mrb_state *mrb, struct RString *orig, struct RString *s)
size_t len = (size_t)orig->as.heap.len;
mrb_assert(!RSTR_EMBED_P(orig));
- if (RSTR_NOFREE_P(orig) || RSTR_POOL_P(orig)) {
+ if (RSTR_NOFREE_P(orig)) {
str_init_nofree(s, orig->as.heap.ptr, len);
}
else if (RSTR_SHARED_P(orig)) {
@@ -540,13 +583,13 @@ str_share(mrb_state *mrb, struct RString *orig, struct RString *s)
else if (RSTR_FSHARED_P(orig)) {
str_init_fshared(orig, s, orig->as.heap.aux.fshared);
}
- else if (mrb_frozen_p(orig)) {
+ else if (mrb_frozen_p(orig) && !RSTR_POOL_P(orig)) {
str_init_fshared(orig, s, orig);
}
else {
if (orig->as.heap.aux.capa > orig->as.heap.len) {
orig->as.heap.ptr = (char *)mrb_realloc(mrb, orig->as.heap.ptr, len+1);
- orig->as.heap.aux.capa = len;
+ orig->as.heap.aux.capa = (mrb_ssize)len;
}
str_init_shared(mrb, orig, s, NULL);
str_init_shared(mrb, orig, orig, s->as.heap.aux.shared);
@@ -554,12 +597,9 @@ str_share(mrb_state *mrb, struct RString *orig, struct RString *s)
}
mrb_value
-mrb_str_pool(mrb_state *mrb, mrb_value str)
+mrb_str_pool(mrb_state *mrb, const char *p, mrb_int len, mrb_bool nofree)
{
struct RString *s = (struct RString *)mrb_malloc(mrb, sizeof(struct RString));
- struct RString *orig = mrb_str_ptr(str);
- const char *p = RSTR_PTR(orig);
- size_t len = (size_t)RSTR_LEN(orig);
s->tt = MRB_TT_STRING;
s->c = mrb->string_class;
@@ -568,7 +608,7 @@ mrb_str_pool(mrb_state *mrb, mrb_value str)
if (RSTR_EMBEDDABLE_P(len)) {
str_init_embed(s, p, len);
}
- else if (RSTR_NOFREE_P(orig)) {
+ else if (nofree) {
str_init_nofree(s, p, len);
}
else {
@@ -591,8 +631,8 @@ mrb_str_byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
}
else {
str_share(mrb, orig, s);
- s->as.heap.ptr += beg;
- s->as.heap.len = len;
+ s->as.heap.ptr += (mrb_ssize)beg;
+ s->as.heap.len = (mrb_ssize)len;
}
RSTR_COPY_ASCII_FLAG(s, orig);
return mrb_obj_value(s);
@@ -814,22 +854,7 @@ MRB_API void
mrb_str_modify_keep_ascii(mrb_state *mrb, struct RString *s)
{
mrb_check_frozen(mrb, s);
- if (RSTR_SHARED_P(s)) {
- mrb_shared_string *shared = s->as.heap.aux.shared;
-
- if (shared->refcnt == 1 && s->as.heap.ptr == shared->ptr) {
- s->as.heap.aux.capa = shared->capa;
- s->as.heap.ptr[s->as.heap.len] = '\0';
- mrb_free(mrb, shared);
- }
- else {
- str_init_modifiable(mrb, s, s->as.heap.ptr, (size_t)s->as.heap.len);
- str_decref(mrb, shared);
- }
- }
- else if (RSTR_NOFREE_P(s) || RSTR_FSHARED_P(s)) {
- str_init_modifiable(mrb, s, s->as.heap.ptr, (size_t)s->as.heap.len);
- }
+ str_modify_keep_ascii(mrb, s);
}
MRB_API void
@@ -954,7 +979,7 @@ mrb_str_times(mrb_state *mrb, mrb_value self)
if (times < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argument");
}
- if (times && MRB_INT_MAX / times < RSTRING_LEN(self)) {
+ if (times && MRB_SSIZE_MAX / times < RSTRING_LEN(self)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "argument too big");
}
@@ -1088,7 +1113,6 @@ 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)
@@ -1295,7 +1319,7 @@ str_replace_partial(mrb_state *mrb, mrb_value src, mrb_int pos, mrb_int end, mrb
replen = (mrb_nil_p(rep) ? 0 : RSTRING_LEN(rep));
newlen = replen + len - (end - pos);
- if (newlen >= MRB_INT_MAX || newlen < replen /* overflowed */) {
+ if (newlen >= MRB_SSIZE_MAX || newlen < replen /* overflowed */) {
mrb_raise(mrb, E_RUNTIME_ERROR, "string size too big");
}
@@ -1338,7 +1362,7 @@ str_escape(mrb_state *mrb, mrb_value str, mrb_bool inspect)
unsigned char c, cc;
#ifdef MRB_UTF8_STRING
if (inspect) {
- mrb_int clen = utf8len(p, pend);
+ mrb_int clen = mrb_utf8len(p, pend);
if (clen > 1) {
mrb_int i;
@@ -1641,7 +1665,7 @@ mrb_str_chop_bang(mrb_state *mrb, mrb_value str)
const char* t = RSTR_PTR(s), *p = t;
const char* e = p + RSTR_LEN(s);
while (p<e) {
- mrb_int clen = utf8len(p, e);
+ mrb_int clen = mrb_utf8len(p, e);
if (p + clen>=e) break;
p += clen;
}
@@ -1942,15 +1966,10 @@ mrb_str_intern(mrb_state *mrb, mrb_value self)
MRB_API mrb_value
mrb_obj_as_string(mrb_state *mrb, mrb_value obj)
{
- mrb_value str;
-
if (mrb_string_p(obj)) {
return obj;
}
- str = mrb_funcall(mrb, obj, "to_s", 0);
- if (!mrb_string_p(str))
- return mrb_any_to_s(mrb, obj);
- return str;
+ return mrb_str_to_str(mrb, obj);
}
MRB_API mrb_value
@@ -2018,7 +2037,7 @@ mrb_str_reverse_bang(mrb_state *mrb, mrb_value str)
p = RSTR_PTR(s);
e = p + RSTR_LEN(s);
while (p<e) {
- mrb_int clen = utf8len(p, e);
+ mrb_int clen = mrb_utf8len(p, e);
str_reverse(p, p + clen - 1);
p += clen;
}
@@ -2241,7 +2260,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
return result;
}
-static mrb_value
+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;
@@ -2352,7 +2371,7 @@ mrb_str_len_to_inum(mrb_state *mrb, const char *str, mrb_int len, mrb_int base,
if (*(p - 1) == '0')
p--;
}
- if (p == pend) {
+ if (p == pend || *p == '_') {
if (badcheck) goto bad;
return mrb_fixnum_value(0);
}
@@ -2391,9 +2410,10 @@ mrb_str_len_to_inum(mrb_state *mrb, const char *str, mrb_int len, mrb_int base,
}
val = (mrb_int)n;
if (badcheck) {
- if (p == str) goto bad; /* no number */
+ if (p == str) goto bad; /* no number */
+ if (*(p - 1) == '_') goto bad; /* trailing '_' */
while (p<pend && ISSPACE(*p)) p++;
- if (p<pend) goto bad; /* trailing garbage */
+ if (p<pend) goto bad; /* trailing garbage */
}
return mrb_fixnum_value(sign ? val : -val);
@@ -2427,15 +2447,12 @@ mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr)
if (p[len] == '\0') {
return p;
}
- if (mrb_frozen_p(ps) || RSTR_CAPA(ps) == len) {
- ps = str_new(mrb, NULL, len+1);
- memcpy(RSTR_PTR(ps), p, len);
- RSTR_SET_LEN(ps, len);
- *ptr = mrb_obj_value(ps);
- }
- else {
- mrb_str_modify(mrb, ps);
- }
+
+ /*
+ * Even after str_modify_keep_ascii(), NULL termination is not ensured if
+ * RSTR_SET_LEN() is used explicitly (e.g. String#delete_suffix!).
+ */
+ str_modify_keep_ascii(mrb, ps);
RSTR_PTR(ps)[len] = '\0';
return RSTR_PTR(ps);
}
@@ -2492,73 +2509,105 @@ mrb_str_to_i(mrb_state *mrb, mrb_value self)
}
#ifndef MRB_WITHOUT_FLOAT
-MRB_API double
-mrb_cstr_to_dbl(mrb_state *mrb, const char * p, mrb_bool badcheck)
+double
+mrb_str_len_to_dbl(mrb_state *mrb, const char *s, size_t len, mrb_bool badcheck)
{
+ char buf[DBL_DIG * 4 + 20];
+ const char *p = s, *p2;
+ const char *pend = p + len;
char *end;
- char buf[DBL_DIG * 4 + 10];
+ char *n;
+ char prev = 0;
double d;
-
- enum {max_width = 20};
+ mrb_bool dot = FALSE;
if (!p) return 0.0;
- while (ISSPACE(*p)) p++;
-
- if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
- return 0.0;
+ while (p<pend && ISSPACE(*p)) p++;
+ p2 = p;
+
+ if (pend - p > 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
+ mrb_value x;
+
+ if (!badcheck) return 0.0;
+ x = mrb_str_len_to_inum(mrb, p, pend-p, 0, badcheck);
+ if (mrb_fixnum_p(x))
+ d = (double)mrb_fixnum(x);
+ else /* if (mrb_float_p(x)) */
+ d = mrb_float(x);
+ return d;
+ }
+ while (p < pend) {
+ if (!*p) {
+ if (badcheck) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "string for Float contains null byte");
+ /* not reached */
+ }
+ pend = p;
+ p = p2;
+ goto nocopy;
+ }
+ if (!badcheck && *p == ' ') {
+ pend = p;
+ p = p2;
+ goto nocopy;
+ }
+ if (*p == '_') break;
+ p++;
}
+ p = p2;
+ n = buf;
+ while (p < pend) {
+ char c = *p++;
+ if (c == '.') dot = TRUE;
+ if (c == '_') {
+ /* remove an underscore between digits */
+ if (n == buf || !ISDIGIT(prev) || p == pend) {
+ if (badcheck) goto bad;
+ break;
+ }
+ }
+ else if (badcheck && prev == '_' && !ISDIGIT(c)) goto bad;
+ else {
+ const char *bend = buf+sizeof(buf)-1;
+ if (n==bend) { /* buffer overflow */
+ if (dot) break; /* cut off remaining fractions */
+ return INFINITY;
+ }
+ *n++ = c;
+ }
+ prev = c;
+ }
+ *n = '\0';
+ p = buf;
+ pend = n;
+nocopy:
d = mrb_float_read(p, &end);
if (p == end) {
if (badcheck) {
bad:
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for float(%s)", p);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for float(%!s)", s);
/* not reached */
}
return d;
}
- if (*end) {
- char *n = buf;
- char *e = buf + sizeof(buf) - 1;
- char prev = 0;
-
- while (p < end && n < e) prev = *n++ = *p++;
- while (*p) {
- if (*p == '_') {
- /* remove underscores between digits */
- if (badcheck) {
- if (n == buf || !ISDIGIT(prev)) goto bad;
- ++p;
- if (!ISDIGIT(*p)) goto bad;
- }
- else {
- while (*++p == '_');
- continue;
- }
- }
- prev = *p++;
- if (n < e) *n++ = prev;
- }
- *n = '\0';
- p = buf;
-
- if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
- return 0.0;
- }
-
- d = mrb_float_read(p, &end);
- if (badcheck) {
- if (!end || p == end) goto bad;
- while (*end && ISSPACE(*end)) end++;
- if (*end) goto bad;
- }
+ if (badcheck) {
+ if (!end || p == end) goto bad;
+ while (end<pend && ISSPACE(*end)) end++;
+ if (end<pend) goto bad;
}
return d;
}
MRB_API double
+mrb_cstr_to_dbl(mrb_state *mrb, const char *s, mrb_bool badcheck)
+{
+ return mrb_str_len_to_dbl(mrb, s, strlen(s), badcheck);
+}
+
+MRB_API double
mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck)
{
- return mrb_cstr_to_dbl(mrb, RSTRING_CSTR(mrb, str), badcheck);
+ return mrb_str_len_to_dbl(mrb, RSTRING_PTR(str), RSTRING_LEN(str), badcheck);
}
/* 15.2.10.5.39 */
@@ -2678,21 +2727,21 @@ mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len)
capa = RSTR_CAPA(s);
total = RSTR_LEN(s)+len;
- if (total >= MRB_INT_MAX) {
+ if (total >= MRB_SSIZE_MAX) {
size_error:
mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
}
if (capa <= total) {
if (capa == 0) capa = 1;
while (capa <= total) {
- if (capa <= MRB_INT_MAX / 2) {
+ if (capa <= MRB_SSIZE_MAX / 2) {
capa *= 2;
}
else {
capa = total+1;
}
}
- if (capa <= total || capa > MRB_INT_MAX) {
+ if (capa <= total || capa > MRB_SSIZE_MAX) {
goto size_error;
}
resize_capa(mrb, s, capa);
@@ -2701,7 +2750,7 @@ mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len)
ptr = RSTR_PTR(s) + off;
}
memcpy(RSTR_PTR(s) + RSTR_LEN(s), ptr, len);
- mrb_assert_int_fit(size_t, total, mrb_int, MRB_INT_MAX);
+ mrb_assert_int_fit(size_t, total, mrb_ssize, MRB_SSIZE_MAX);
RSTR_SET_LEN(s, total);
RSTR_PTR(s)[total] = '\0'; /* sentinel */
return str;
@@ -2710,7 +2759,7 @@ mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len)
MRB_API mrb_value
mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr)
{
- return mrb_str_cat(mrb, str, ptr, strlen(ptr));
+ return mrb_str_cat(mrb, str, ptr, ptr ? strlen(ptr) : 0);
}
MRB_API mrb_value
@@ -2873,7 +2922,7 @@ mrb_init_string(mrb_state *mrb)
{
struct RClass *s;
- mrb_static_assert(RSTRING_EMBED_LEN_MAX < (1 << MRB_STR_EMBED_LEN_BITSIZE),
+ mrb_static_assert(RSTRING_EMBED_LEN_MAX < (1 << MRB_STR_EMBED_LEN_BIT),
"pointer size too big for embedded string");
mrb->string_class = s = mrb_define_class(mrb, "String", mrb->object_class); /* 15.2.10 */
diff --git a/src/symbol.c b/src/symbol.c
index 2696b5210..ad186dce3 100644
--- a/src/symbol.c
+++ b/src/symbol.c
@@ -20,12 +20,12 @@ typedef struct symbol_name {
const char *name;
} symbol_name;
-#define SYMBOL_INLINE_BIT 1
-#define SYMBOL_INLINE_LOWER_BIT 2
-#define SYMBOL_INLINE (1 << (SYMBOL_INLINE_BIT - 1))
-#define SYMBOL_INLINE_LOWER (1 << (SYMBOL_INLINE_LOWER_BIT - 1))
-#define SYMBOL_NORMAL_SHIFT SYMBOL_INLINE_BIT
-#define SYMBOL_INLINE_SHIFT SYMBOL_INLINE_LOWER_BIT
+#define SYMBOL_INLINE_BIT_POS 1
+#define SYMBOL_INLINE_LOWER_BIT_POS 2
+#define SYMBOL_INLINE (1 << (SYMBOL_INLINE_BIT_POS - 1))
+#define SYMBOL_INLINE_LOWER (1 << (SYMBOL_INLINE_LOWER_BIT_POS - 1))
+#define SYMBOL_NORMAL_SHIFT SYMBOL_INLINE_BIT_POS
+#define SYMBOL_INLINE_SHIFT SYMBOL_INLINE_LOWER_BIT_POS
#ifdef MRB_ENABLE_ALL_SYMBOLS
# define SYMBOL_INLINE_P(sym) FALSE
# define SYMBOL_INLINE_LOWER_P(sym) FALSE
@@ -48,14 +48,14 @@ sym_validate_len(mrb_state *mrb, size_t len)
static const char pack_table[] = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static mrb_sym
-sym_inline_pack(const char *name, uint16_t len)
+sym_inline_pack(const char *name, size_t len)
{
- const int lower_length_max = (MRB_SYMBOL_BITSIZE - 2) / 5;
- const int mix_length_max = (MRB_SYMBOL_BITSIZE - 2) / 6;
+ const size_t lower_length_max = (MRB_SYMBOL_BIT - 2) / 5;
+ const size_t mix_length_max = (MRB_SYMBOL_BIT - 2) / 6;
char c;
const char *p;
- int i;
+ size_t i;
mrb_sym sym = 0;
mrb_bool lower = TRUE;
@@ -124,7 +124,7 @@ symhash(const char *key, size_t len)
}
static mrb_sym
-find_symbol(mrb_state *mrb, const char *name, uint16_t len, uint8_t *hashp)
+find_symbol(mrb_state *mrb, const char *name, size_t len, uint8_t *hashp)
{
mrb_sym i;
symbol_name *sname;
@@ -517,18 +517,14 @@ mrb_sym_str(mrb_state *mrb, mrb_sym sym)
{
mrb_int len;
const char *name = mrb_sym_name_len(mrb, sym, &len);
- mrb_value str;
if (!name) return mrb_undef_value(); /* can't happen */
if (SYMBOL_INLINE_P(sym)) {
- str = mrb_str_new(mrb, name, len);
+ mrb_value str = mrb_str_new(mrb, name, len);
RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
+ return str;
}
- else {
- str = mrb_str_new_static(mrb, name, len);
- }
- MRB_SET_FROZEN_FLAG(mrb_str_ptr(str));
- return str;
+ return mrb_str_new_static(mrb, name, len);
}
static const char*
diff --git a/src/variable.c b/src/variable.c
index 8fc01fe2d..030aa7b00 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -1123,7 +1123,7 @@ 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);
- MRB_SET_FROZEN_FLAG(mrb_obj_ptr(path));
+ path = mrb_str_dup(mrb, path);
}
return path;
}
diff --git a/src/vm.c b/src/vm.c
index 54f74907e..a280026f8 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -6,7 +6,9 @@
#include <stddef.h>
#include <stdarg.h>
+#ifndef MRB_WITHOUT_FLOAT
#include <math.h>
+#endif
#include <mruby.h>
#include <mruby/array.h>
#include <mruby/class.h>
@@ -322,6 +324,7 @@ cipop(mrb_state *mrb)
}
void mrb_exc_set(mrb_state *mrb, mrb_value exc);
+static mrb_value mrb_run(mrb_state *mrb, struct RProc* proc, mrb_value self);
static void
ecall(mrb_state *mrb)
@@ -333,10 +336,12 @@ ecall(mrb_state *mrb)
struct REnv *env;
ptrdiff_t cioff;
int ai = mrb_gc_arena_save(mrb);
- uint16_t i = --c->eidx;
+ uint16_t i;
int nregs;
- if (i<0) return;
+ if (c->eidx == 0) return;
+ i = --c->eidx;
+
/* restrict total call depth of ecall() */
if (++mrb->ecall_nest > MRB_ECALL_DEPTH_MAX) {
mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
@@ -428,6 +433,7 @@ MRB_API mrb_value
mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv, mrb_value blk)
{
mrb_value val;
+ int ai = mrb_gc_arena_save(mrb);
if (!mrb->jmp) {
struct mrb_jmpbuf c_jmp;
@@ -516,19 +522,17 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
mrb->c->stack[argc+1] = blk;
if (MRB_METHOD_CFUNC_P(m)) {
- int ai = mrb_gc_arena_save(mrb);
-
ci->acc = CI_ACC_DIRECT;
val = MRB_METHOD_CFUNC(m)(mrb, self);
mrb->c->stack = mrb->c->ci->stackent;
cipop(mrb);
- mrb_gc_arena_restore(mrb, ai);
}
else {
ci->acc = CI_ACC_SKIP;
val = mrb_run(mrb, MRB_METHOD_PROC(m), self);
}
}
+ mrb_gc_arena_restore(mrb, ai);
mrb_gc_protect(mrb, val);
return val;
}
@@ -623,7 +627,7 @@ mrb_f_send(mrb_state *mrb, mrb_value self)
ci->argc--;
}
else { /* variable length arguments */
- mrb_ary_shift(mrb, regs[0]);
+ regs[0] = mrb_ary_subseq(mrb, regs[0], 1, RARRAY_LEN(regs[0]) - 1);
}
if (MRB_METHOD_CFUNC_P(m)) {
@@ -647,8 +651,7 @@ eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c)
}
ci = mrb->c->ci;
if (ci->acc == CI_ACC_DIRECT) {
- ci->target_class = c;
- return mrb_yield_cont(mrb, blk, self, 1, &self);
+ return mrb_yield_with_class(mrb, blk, 1, &self, self, c);
}
ci->target_class = c;
p = mrb_proc_ptr(blk);
@@ -723,26 +726,11 @@ mrb_value
mrb_obj_instance_eval(mrb_state *mrb, mrb_value self)
{
mrb_value a, b;
- mrb_value cv;
- struct RClass *c;
if (mrb_get_args(mrb, "|S&", &a, &b) == 1) {
mrb_raise(mrb, E_NOTIMP_ERROR, "instance_eval with string not implemented");
}
- switch (mrb_type(self)) {
- case MRB_TT_SYMBOL:
- case MRB_TT_FIXNUM:
-#ifndef MRB_WITHOUT_FLOAT
- case MRB_TT_FLOAT:
-#endif
- c = 0;
- break;
- default:
- cv = mrb_singleton_class(mrb, self);
- c = mrb_class_ptr(cv);
- break;
- }
- return eval_under(mrb, self, b, c);
+ return eval_under(mrb, self, b, mrb_singleton_class_ptr(mrb, self));
}
MRB_API mrb_value
@@ -1061,6 +1049,11 @@ RETRY_TRY_BLOCK:
NEXT;
}
+ CASE(OP_LOADI16, BS) {
+ SET_INT_VALUE(regs[a], (mrb_int)(int16_t)b);
+ NEXT;
+ }
+
CASE(OP_LOADSYM, BB) {
SET_SYM_VALUE(regs[a], syms[b]);
NEXT;
@@ -1098,13 +1091,13 @@ RETRY_TRY_BLOCK:
}
CASE(OP_GETSV, BB) {
- mrb_value val = mrb_vm_special_get(mrb, b);
+ mrb_value val = mrb_vm_special_get(mrb, syms[b]);
regs[a] = val;
NEXT;
}
CASE(OP_SETSV, BB) {
- mrb_vm_special_set(mrb, b, regs[a]);
+ mrb_vm_special_set(mrb, syms[b], regs[a]);
NEXT;
}
@@ -1495,11 +1488,9 @@ RETRY_TRY_BLOCK:
ci->target_class = MRB_PROC_TARGET_CLASS(m);
ci->proc = m;
if (MRB_PROC_ENV_P(m)) {
- mrb_sym mid;
struct REnv *e = MRB_PROC_ENV(m);
- mid = e->mid;
- if (mid) ci->mid = mid;
+ ci->mid = e->mid;
if (!e->stack) {
e->stack = mrb->c->stack;
}
@@ -2825,7 +2816,7 @@ RETRY_TRY_BLOCK:
MRB_END_EXC(&c_jmp);
}
-MRB_API mrb_value
+static mrb_value
mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
{
if (mrb->c->ci->argc < 0) {