diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/array.c | 7 | ||||
| -rw-r--r-- | src/class.c | 119 | ||||
| -rw-r--r-- | src/dump.c | 10 | ||||
| -rw-r--r-- | src/error.c | 9 | ||||
| -rw-r--r-- | src/etc.c | 10 | ||||
| -rw-r--r-- | src/fmt_fp.c | 2 | ||||
| -rw-r--r-- | src/load.c | 2 | ||||
| -rw-r--r-- | src/numeric.c | 15 | ||||
| -rw-r--r-- | src/range.c | 4 | ||||
| -rw-r--r-- | src/string.c | 33 | ||||
| -rw-r--r-- | src/variable.c | 2 | ||||
| -rw-r--r-- | src/version.c | 1 | ||||
| -rw-r--r-- | src/vm.c | 22 |
13 files changed, 164 insertions, 72 deletions
diff --git a/src/array.c b/src/array.c index f48719310..2622ee528 100644 --- a/src/array.c +++ b/src/array.c @@ -19,7 +19,6 @@ static inline mrb_value ary_elt(mrb_value ary, mrb_int offset) { - if (RARRAY_LEN(ary) == 0) return mrb_nil_value(); if (offset < 0 || RARRAY_LEN(ary) <= offset) { return mrb_nil_value(); } @@ -295,7 +294,7 @@ mrb_ary_plus(mrb_state *mrb, mrb_value self) mrb_get_args(mrb, "a", &ptr, &blen); if (ARY_MAX_SIZE - blen < a1->len) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); + mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } a2 = ary_new_capa(mrb, a1->len + blen); array_copy(a2->ptr, a1->ptr, a1->len); @@ -349,7 +348,7 @@ mrb_ary_times(mrb_state *mrb, mrb_value self) } if (times == 0) return mrb_ary_new(mrb); if (ARY_MAX_SIZE / times < a1->len) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); + mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } a2 = ary_new_capa(mrb, a1->len * times); ptr = a2->ptr; @@ -1031,7 +1030,7 @@ mrb_ary_join_m(mrb_state *mrb, mrb_value ary) { mrb_value sep = mrb_nil_value(); - mrb_get_args(mrb, "|S", &sep); + mrb_get_args(mrb, "|S!", &sep); return mrb_ary_join(mrb, ary, sep); } diff --git a/src/class.c b/src/class.c index e9cbc592d..33fb61211 100644 --- a/src/class.c +++ b/src/class.c @@ -435,12 +435,12 @@ to_sym(mrb_state *mrb, mrb_value ss) ---------------------------------------------------------------------------------------------- o: Object [mrb_value] C: class/module [mrb_value] - S: String [mrb_value] - A: Array [mrb_value] - H: Hash [mrb_value] - s: String [char*,mrb_int] Receive two arguments. - z: String [char*] NUL terminated string. - a: Array [mrb_value*,mrb_int] Receive two arguments. + S: String [mrb_value] when ! follows, the value may be nil + A: Array [mrb_value] when ! follows, the value may be nil + H: Hash [mrb_value] when ! follows, the value may be nil + s: String [char*,mrb_int] Receive two arguments; s! gives (NULL,0) for nil + z: String [char*] NUL terminated string; z! gives NULL for nil + a: Array [mrb_value*,mrb_int] Receive two arguments; a! gives (NULL,0) for nil f: Float [mrb_float] i: Integer [mrb_int] b: Boolean [mrb_bool] @@ -525,6 +525,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_value *p; p = va_arg(ap, mrb_value*); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *p = *sp++; + i++; + break; + } + } if (i < argc) { *p = to_str(mrb, *sp++); i++; @@ -536,6 +544,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_value *p; p = va_arg(ap, mrb_value*); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *p = *sp++; + i++; + break; + } + } if (i < argc) { *p = to_ary(mrb, *sp++); i++; @@ -547,6 +563,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_value *p; p = va_arg(ap, mrb_value*); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *p = *sp++; + i++; + break; + } + } if (i < argc) { *p = to_hash(mrb, *sp++); i++; @@ -561,6 +585,15 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) ps = va_arg(ap, char**); pl = va_arg(ap, mrb_int*); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *ps = NULL; + *pl = 0; + i++; + break; + } + } if (i < argc) { ss = to_str(mrb, *sp++); *ps = RSTRING_PTR(ss); @@ -575,6 +608,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) const char **ps; ps = va_arg(ap, const char**); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *ps = NULL; + i++; + break; + } + } if (i < argc) { ss = to_str(mrb, *sp++); *ps = mrb_string_value_cstr(mrb, &ss); @@ -591,6 +632,15 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) pb = va_arg(ap, mrb_value**); pl = va_arg(ap, mrb_int*); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *pb = 0; + *pl = 0; + i++; + break; + } + } if (i < argc) { aa = to_ary(mrb, *sp++); a = mrb_ary_ptr(aa); @@ -676,6 +726,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) datap = va_arg(ap, void**); type = va_arg(ap, struct mrb_data_type const*); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *datap = 0; + i++; + break; + } + } if (i < argc) { *datap = mrb_data_get_ptr(mrb, *sp++, type); ++i; @@ -1262,6 +1320,31 @@ mrb_bob_not(mrb_state *mrb, mrb_value cv) return mrb_bool_value(!mrb_test(cv)); } +void +mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args) +{ + mrb_sym inspect; + mrb_value repr; + + inspect = mrb_intern_lit(mrb, "inspect"); + if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) { + /* method missing in inspect; avoid recursion */ + repr = mrb_any_to_s(mrb, self); + } + else if (mrb_respond_to(mrb, self, inspect) && mrb->c->ci - mrb->c->cibase < 64) { + repr = mrb_funcall_argv(mrb, self, inspect, 0, 0); + if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) { + repr = mrb_any_to_s(mrb, self); + } + } + else { + repr = mrb_any_to_s(mrb, self); + } + + mrb_no_method_error(mrb, name, args, "undefined method '%S' for %S", + mrb_sym2str(mrb, name), repr); +} + /* 15.3.1.3.30 */ /* * call-seq: @@ -1301,27 +1384,9 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod) mrb_sym name; mrb_value *a; mrb_int alen; - mrb_sym inspect; - mrb_value repr; mrb_get_args(mrb, "n*", &name, &a, &alen); - - inspect = mrb_intern_lit(mrb, "inspect"); - if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) { - /* method missing in inspect; avoid recursion */ - repr = mrb_any_to_s(mrb, mod); - } - else if (mrb_respond_to(mrb, mod, inspect) && mrb->c->ci - mrb->c->cibase < 64) { - repr = mrb_funcall_argv(mrb, mod, inspect, 0, 0); - if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) { - repr = mrb_any_to_s(mrb, mod); - } - } - else { - repr = mrb_any_to_s(mrb, mod); - } - - mrb_no_method_error(mrb, name, alen, a, "undefined method '%S' for %S", mrb_sym2str(mrb, name), repr); + mrb_method_missing(mrb, name, mod, mrb_ary_new_from_values(mrb, alen, a)); /* not reached */ return mrb_nil_value(); } @@ -1543,10 +1608,10 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass) case MRB_TT_CLASS: case MRB_TT_MODULE: case MRB_TT_SCLASS: - mrb_str_append(mrb, str, mrb_inspect(mrb, v)); + mrb_str_cat_str(mrb, str, mrb_inspect(mrb, v)); break; default: - mrb_str_append(mrb, str, mrb_any_to_s(mrb, v)); + mrb_str_cat_str(mrb, str, mrb_any_to_s(mrb, v)); break; } return mrb_str_cat_lit(mrb, str, ">"); diff --git a/src/dump.c b/src/dump.c index 2f2e5edcb..734f38043 100644 --- a/src/dump.c +++ b/src/dump.c @@ -16,7 +16,7 @@ #define FLAG_BYTEORDER_NONATIVE 0 #ifdef MRB_USE_FLOAT -#define MRB_FLOAT_FMT "%.9e" +#define MRB_FLOAT_FMT "%.8e" #else #define MRB_FLOAT_FMT "%.16e" #endif @@ -978,12 +978,8 @@ error_exit: mrb_free(mrb, *bin); *bin = NULL; } - if (lv_syms) { - mrb_free(mrb, lv_syms); - } - if (filenames) { - mrb_free(mrb, filenames); - } + mrb_free(mrb, lv_syms); + mrb_free(mrb, filenames); return result; } diff --git a/src/error.c b/src/error.c index a800f77f9..359e5737b 100644 --- a/src/error.c +++ b/src/error.c @@ -152,7 +152,7 @@ exc_inspect(mrb_state *mrb, mrb_value exc) mrb_str_append(mrb, str, line); mrb_str_cat_lit(mrb, str, ": "); if (append_mesg) { - mrb_str_append(mrb, str, mesg); + mrb_str_cat_str(mrb, str, mesg); mrb_str_cat_lit(mrb, str, " ("); } mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc)); @@ -165,7 +165,7 @@ exc_inspect(mrb_state *mrb, mrb_value exc) str = mrb_str_new_cstr(mrb, cname); mrb_str_cat_lit(mrb, str, ": "); if (append_mesg) { - mrb_str_append(mrb, str, mesg); + mrb_str_cat_str(mrb, str, mesg); } else { mrb_str_cat_cstr(mrb, str, cname); @@ -424,15 +424,14 @@ mrb_sys_fail(mrb_state *mrb, const char *mesg) } MRB_API mrb_noreturn void -mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_int argc, const mrb_value *argv, char const* fmt, ...) +mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, char const* fmt, ...) { mrb_value exc; va_list ap; va_start(ap, fmt); exc = mrb_funcall(mrb, mrb_obj_value(E_NOMETHOD_ERROR), "new", 3, - mrb_vformat(mrb, fmt, ap), mrb_symbol_value(id), - mrb_ary_new_from_values(mrb, argc, argv)); + mrb_vformat(mrb, fmt, ap), mrb_symbol_value(id), args); va_end(ap); mrb_exc_raise(mrb, exc); } @@ -67,17 +67,15 @@ mrb_data_get_ptr(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) MRB_API mrb_sym mrb_obj_to_sym(mrb_state *mrb, mrb_value name) { - mrb_value tmp; mrb_sym id; switch (mrb_type(name)) { default: - tmp = mrb_check_string_type(mrb, name); - if (mrb_nil_p(tmp)) { - tmp = mrb_inspect(mrb, name); - mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", tmp); + name = mrb_check_string_type(mrb, name); + if (mrb_nil_p(name)) { + name = mrb_inspect(mrb, name); + mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", name); } - name = tmp; /* fall through */ case MRB_TT_STRING: name = mrb_str_intern(mrb, name); diff --git a/src/fmt_fp.c b/src/fmt_fp.c index b467435a3..b27ebd6e9 100644 --- a/src/fmt_fp.c +++ b/src/fmt_fp.c @@ -90,7 +90,7 @@ fmt_u(uint32_t x, char *s) typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)]; #endif -#if ((defined(__CYGWIN32__) || defined(__NetBSD__) || defined(mips)) && !defined(__linux__)) || defined(__android__) +#if ((defined(__CYGWIN__) || defined(__NetBSD__) || defined(mips)) && !defined(__linux__)) || defined(__android__) #undef frexpl #define frexpl frexp #endif diff --git a/src/load.c b/src/load.c index a9f1641bf..36fae9aee 100644 --- a/src/load.c +++ b/src/load.c @@ -529,7 +529,7 @@ read_binary_header(const uint8_t *bin, size_t *bin_size, uint16_t *crc, uint8_t else if (memcmp(header->binary_ident, RITE_BINARY_IDENT_LIL, sizeof(header->binary_ident)) == 0) { if (bigendian_p()) *flags |= FLAG_BYTEORDER_LIL; - else + else *flags |= FLAG_BYTEORDER_NATIVE; } else { diff --git a/src/numeric.c b/src/numeric.c index b9aef51d9..1a3c903f0 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -55,7 +55,8 @@ num_pow(mrb_state *mrb, mrb_value x) mrb_get_args(mrb, "o", &y); yv = mrb_to_flo(mrb, y); d = pow(mrb_to_flo(mrb, x), yv); - if (mrb_fixnum_p(x) && mrb_fixnum_p(y) && FIXABLE(d) && yv > 0) + if (mrb_fixnum_p(x) && mrb_fixnum_p(y) && FIXABLE(d) && yv > 0 && + (d < 0 || (d > 0 && (mrb_int)d > 0))) return mrb_fixnum_value((mrb_int)d); return mrb_float_value(mrb, d); } @@ -819,11 +820,13 @@ fix_xor(mrb_state *mrb, mrb_value x) static mrb_value lshift(mrb_state *mrb, mrb_int val, mrb_int width) { - mrb_assert(width >= 0); + mrb_assert(width > 0); if (width > NUMERIC_SHIFT_WIDTH_MAX) { - mrb_raisef(mrb, E_RANGE_ERROR, "width(%S) > (%S:MRB_INT_BIT-1)", - mrb_fixnum_value(width), - mrb_fixnum_value(NUMERIC_SHIFT_WIDTH_MAX)); + mrb_float f = (mrb_float)val; + while (width--) { + f *= 2; + } + return mrb_float_value(mrb, f); } return mrb_fixnum_value(val << width); } @@ -831,7 +834,7 @@ lshift(mrb_state *mrb, mrb_int val, mrb_int width) static mrb_value rshift(mrb_int val, mrb_int width) { - mrb_assert(width >= 0); + mrb_assert(width > 0); if (width >= NUMERIC_SHIFT_WIDTH_MAX) { if (val < 0) { return mrb_fixnum_value(-1); diff --git a/src/range.c b/src/range.c index b427dc1b7..b58b6a1c8 100644 --- a/src/range.c +++ b/src/range.c @@ -290,7 +290,7 @@ range_to_s(mrb_state *mrb, mrb_value range) str2 = mrb_obj_as_string(mrb, r->edges->end); str = mrb_str_dup(mrb, str); mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2); - mrb_str_append(mrb, str, str2); + mrb_str_cat_str(mrb, str, str2); return str; } @@ -315,7 +315,7 @@ range_inspect(mrb_state *mrb, mrb_value range) str2 = mrb_inspect(mrb, r->edges->end); str = mrb_str_dup(mrb, str); mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2); - mrb_str_append(mrb, str, str2); + mrb_str_cat_str(mrb, str, str2); return str; } diff --git a/src/string.c b/src/string.c index 45ba38c9d..08caf3bae 100644 --- a/src/string.c +++ b/src/string.c @@ -75,9 +75,18 @@ str_decref(mrb_state *mrb, mrb_shared_string *shared) } } +static void +check_frozen(mrb_state *mrb, struct RString *s) +{ + if (RSTR_FROZEN_P(s)) { + mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen string"); + } +} + MRB_API void mrb_str_modify(mrb_state *mrb, struct RString *s) { + check_frozen(mrb, s); if (RSTR_SHARED_P(s)) { mrb_shared_string *shared = s->as.heap.aux.shared; @@ -119,6 +128,15 @@ mrb_str_modify(mrb_state *mrb, struct RString *s) } } +static mrb_value +mrb_str_freeze(mrb_state *mrb, mrb_value str) +{ + struct RString *s = mrb_str_ptr(str); + + RSTR_SET_FROZEN_FLAG(s); + return str; +} + MRB_API mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len) { @@ -1345,6 +1363,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2) { long len; + check_frozen(mrb, s1); len = RSTR_LEN(s2); if (RSTR_SHARED_P(s1)) { str_decref(mrb, s1->as.heap.aux.shared); @@ -1844,7 +1863,7 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck) const char *p; char sign = 1; int c, uscore; - unsigned long n = 0; + uint64_t n = 0; mrb_int val; #define conv_digit(c) \ @@ -1964,9 +1983,9 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck) } n *= base; n += c; - } - if (n > MRB_INT_MAX) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%S) too big for integer", mrb_str_new_cstr(mrb, str)); + if (n > MRB_INT_MAX) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%S) too big for integer", mrb_str_new_cstr(mrb, str)); + } } val = n; if (badcheck) { @@ -2366,10 +2385,10 @@ mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2) } MRB_API mrb_value -mrb_str_append(mrb_state *mrb, mrb_value str, mrb_value str2) +mrb_str_append(mrb_state *mrb, mrb_value str1, mrb_value str2) { str2 = mrb_str_to_str(mrb, str2); - return mrb_str_cat_str(mrb, str, str2); + return mrb_str_cat_str(mrb, str1, str2); } #define CHAR_ESC_LEN 13 /* sizeof(\x{ hex of 32bit unsigned int } \0) */ @@ -2514,4 +2533,6 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "upcase!", mrb_str_upcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.43 */ mrb_define_method(mrb, s, "inspect", mrb_str_inspect, MRB_ARGS_NONE()); /* 15.2.10.5.46(x) */ mrb_define_method(mrb, s, "bytes", mrb_str_bytes, MRB_ARGS_NONE()); + + mrb_define_method(mrb, s, "freeze", mrb_str_freeze, MRB_ARGS_NONE()); } diff --git a/src/variable.c b/src/variable.c index 1b2ad56a7..efe6fad12 100644 --- a/src/variable.c +++ b/src/variable.c @@ -609,7 +609,7 @@ inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) else { ins = mrb_inspect(mrb, v); } - mrb_str_append(mrb, str, ins); + mrb_str_cat_str(mrb, str, ins); return 0; } diff --git a/src/version.c b/src/version.c index 7aac44d62..fc3b2fc7a 100644 --- a/src/version.c +++ b/src/version.c @@ -7,6 +7,7 @@ mrb_init_version(mrb_state* mrb) mrb_define_global_const(mrb, "RUBY_VERSION", mrb_str_new_lit(mrb, MRUBY_RUBY_VERSION)); mrb_define_global_const(mrb, "RUBY_ENGINE", mrb_str_new_lit(mrb, MRUBY_RUBY_ENGINE)); mrb_define_global_const(mrb, "MRUBY_VERSION", mrb_str_new_lit(mrb, MRUBY_VERSION)); + mrb_define_global_const(mrb, "MRUBY_RELEASE_NO", mrb_fixnum_value(MRUBY_RELEASE_NO)); mrb_define_global_const(mrb, "MRUBY_RELEASE_DATE", mrb_str_new_lit(mrb, MRUBY_RELEASE_DATE)); mrb_define_global_const(mrb, "MRUBY_DESCRIPTION", mrb_str_new_lit(mrb, MRUBY_DESCRIPTION)); mrb_define_global_const(mrb, "MRUBY_COPYRIGHT", mrb_str_new_lit(mrb, MRUBY_COPYRIGHT)); @@ -266,6 +266,7 @@ ecall(mrb_state *mrb, int i) mrb_value *self = mrb->c->stack; struct RObject *exc; + if (i<0) return; p = mrb->c->ensure[i]; if (!p) return; if (mrb->c->ci->eidx > i) @@ -723,6 +724,8 @@ argnum_error(mrb_state *mrb, mrb_int num) #define CALL_MAXARGS 127 +void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args); + MRB_API mrb_value mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep) { @@ -1030,7 +1033,7 @@ RETRY_TRY_BLOCK: mrb_callinfo *ci = mrb->c->ci; int n, eidx = ci->eidx; - for (n=0; n<a && eidx > ci[-1].eidx; n++) { + for (n=0; n<a && (ci == mrb->c->cibase || eidx > ci[-1].eidx); n++) { ecall(mrb, --eidx); ARENA_RESTORE(mrb, ai); } @@ -1078,8 +1081,15 @@ RETRY_TRY_BLOCK: m = mrb_method_search_vm(mrb, &c, missing); if (!m) { - mrb_no_method_error(mrb, mid, n, regs+a+1, - "undefined method '%S' for %S", mrb_sym2str(mrb, mid), recv); + mrb_value args; + + if (n == CALL_MAXARGS) { + args = regs[a+1]; + } + else { + args = mrb_ary_new_from_values(mrb, n, regs+a+1); + } + mrb_method_missing(mrb, mid, recv, args); } mid = missing; if (n == CALL_MAXARGS) { @@ -1476,9 +1486,6 @@ RETRY_TRY_BLOCK: if (ci->ridx == 0) goto L_STOP; goto L_RESCUE; } - while (eidx > ci[-1].eidx) { - ecall(mrb, --eidx); - } while (ci[0].ridx == ci[-1].ridx) { cipop(mrb); ci = mrb->c->ci; @@ -1488,6 +1495,9 @@ RETRY_TRY_BLOCK: MRB_THROW(prev_jmp); } if (ci == mrb->c->cibase) { + while (eidx > 0) { + ecall(mrb, --eidx); + } if (ci->ridx == 0) { if (mrb->c == mrb->root_c) { regs = mrb->c->stack = mrb->c->stbase; |
