diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/array.c | 4 | ||||
| -rw-r--r-- | src/class.c | 11 | ||||
| -rw-r--r-- | src/codegen.c | 4 | ||||
| -rw-r--r-- | src/dump.c | 4 | ||||
| -rw-r--r-- | src/error.c | 4 | ||||
| -rw-r--r-- | src/error.h | 1 | ||||
| -rw-r--r-- | src/etc.c | 27 | ||||
| -rw-r--r-- | src/gc.c | 14 | ||||
| -rw-r--r-- | src/kernel.c | 2 | ||||
| -rw-r--r-- | src/numeric.c | 100 | ||||
| -rw-r--r-- | src/object.c | 3 | ||||
| -rw-r--r-- | src/parse.y | 15 | ||||
| -rw-r--r-- | src/string.c | 255 | ||||
| -rw-r--r-- | src/variable.c | 44 | ||||
| -rw-r--r-- | src/vm.c | 14 |
15 files changed, 176 insertions, 326 deletions
diff --git a/src/array.c b/src/array.c index 88f56f6b4..b1f05b450 100644 --- a/src/array.c +++ b/src/array.c @@ -38,11 +38,11 @@ ary_new_capa(mrb_state *mrb, mrb_int capa) mrb_int blen; if (capa > ARY_MAX_SIZE) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "ary size too big"); + mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } blen = capa * sizeof(mrb_value) ; if (blen < capa) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "ary size too big"); + mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } a = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class); diff --git a/src/class.c b/src/class.c index 9dc7b46d6..99dc9cda0 100644 --- a/src/class.c +++ b/src/class.c @@ -979,7 +979,7 @@ mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid) if (RSTRING_LEN(inspect) > 64) { inspect = mrb_any_to_s(mrb, mrb_obj_value(c)); } - mrb_raisef(mrb, E_NAME_ERROR, "undefined method '%S' for class %S", + mrb_name_error(mrb, mid, "undefined method '%S' for class %S", mrb_sym2str(mrb, mid), inspect); } return m; @@ -1748,6 +1748,13 @@ mrb_mod_remove_const(mrb_state *mrb, mrb_value mod) } static mrb_value +mrb_mod_s_constants(mrb_state *mrb, mrb_value mod) +{ + mrb_raise(mrb, E_NOTIMP_ERROR, "Module.constants not implemented"); + return mrb_nil_value(); /* not reached */ +} + +static mrb_value mrb_mod_eqq(mrb_state *mrb, mrb_value mod) { mrb_value obj; @@ -1829,10 +1836,12 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, mod, "const_defined?", mrb_mod_const_defined, ARGS_REQ(1)); /* 15.2.2.4.20 */ mrb_define_method(mrb, mod, "const_get", mrb_mod_const_get, ARGS_REQ(1)); /* 15.2.2.4.21 */ mrb_define_method(mrb, mod, "const_set", mrb_mod_const_set, ARGS_REQ(2)); /* 15.2.2.4.23 */ + mrb_define_method(mrb, mod, "constants", mrb_mod_constants, ARGS_NONE()); /* 15.2.2.4.24 */ mrb_define_method(mrb, mod, "remove_const", mrb_mod_remove_const, ARGS_REQ(1)); /* 15.2.2.4.40 */ mrb_define_method(mrb, mod, "define_method", mod_define_method, ARGS_REQ(1)); mrb_define_method(mrb, mod, "class_variables", mrb_mod_class_variables, ARGS_NONE()); /* 15.2.2.4.19 */ mrb_define_method(mrb, mod, "===", mrb_mod_eqq, ARGS_REQ(1)); + mrb_define_class_method(mrb, mod, "constants", mrb_mod_s_constants, ARGS_ANY()); /* 15.2.2.3.1 */ mrb_undef_method(mrb, cls, "append_features"); mrb_undef_method(mrb, cls, "extend_object"); diff --git a/src/codegen.c b/src/codegen.c index e5b1802a1..83d0136ef 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -355,7 +355,7 @@ genop_peep(codegen_scope *s, mrb_code i, int val) static void scope_error(codegen_scope *s) { - exit(1); + exit(EXIT_FAILURE); } static inline void @@ -1868,7 +1868,7 @@ codegen(codegen_scope *s, node *tree, int val) mrb_value str = mrb_str_buf_new(mrb, 4); mrb_str_buf_cat(mrb, str, "$", 1); - mrb_str_buf_append(mrb, str, mrb_fix2str(mrb, fix, 10)); + mrb_str_buf_append(mrb, str, mrb_fixnum_to_str(mrb, fix, 10)); sym = new_sym(s, mrb_intern_str(mrb, str)); genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); push(); diff --git a/src/dump.c b/src/dump.c index 57fa7f612..4714278b0 100644 --- a/src/dump.c +++ b/src/dump.c @@ -80,7 +80,7 @@ get_pool_block_size(mrb_state *mrb, mrb_irep *irep) switch (mrb_type(irep->pool[pool_no])) { case MRB_TT_FIXNUM: - str = mrb_fix2str(mrb, irep->pool[pool_no], 10); + str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); size += RSTRING_LEN(str); break; @@ -123,7 +123,7 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) switch (mrb_type(irep->pool[pool_no])) { case MRB_TT_FIXNUM: - str = mrb_fix2str(mrb, irep->pool[pool_no], 10); + str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); char_ptr = RSTRING_PTR(str); len = RSTRING_LEN(str); break; diff --git a/src/error.c b/src/error.c index 5f1476115..522901ff7 100644 --- a/src/error.c +++ b/src/error.c @@ -306,8 +306,8 @@ mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...) argv[0] = mrb_vformat(mrb, fmt, args); va_end(args); - argv[1] = mrb_symbol_value(id); /* ignore now */ - exc = mrb_class_new_instance(mrb, 1, argv, E_NAME_ERROR); + argv[1] = mrb_symbol_value(id); + exc = mrb_class_new_instance(mrb, 2, argv, E_NAME_ERROR); mrb_exc_raise(mrb, exc); } diff --git a/src/error.h b/src/error.h index 83d0938aa..3726cb4c4 100644 --- a/src/error.h +++ b/src/error.h @@ -13,7 +13,6 @@ mrb_value mrb_exc_new3(mrb_state *mrb, struct RClass* c, mrb_value str); mrb_value make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr); mrb_value mrb_make_exception(mrb_state *mrb, int argc, mrb_value *argv); mrb_value mrb_format(mrb_state *mrb, const char *format, ...); -void mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...); void mrb_exc_print(mrb_state *mrb, struct RObject *exc); #endif /* MRUBY_ERROR_H */ @@ -22,28 +22,37 @@ mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const mrb return data; } -void * -mrb_get_datatype(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) +void +mrb_data_check_type(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) { if (mrb_special_const_p(obj) || (mrb_type(obj) != MRB_TT_DATA)) { - return NULL; + mrb_check_type(mrb, obj, MRB_TT_DATA); } if (DATA_TYPE(obj) != type) { - return NULL; + const mrb_data_type *t2 = DATA_TYPE(obj); + + if (t2) { + mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected %S)", + mrb_str_new_cstr(mrb, t2->struct_name), mrb_str_new_cstr(mrb, type->struct_name)); + } } +} + +void * +mrb_data_check_and_get(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) +{ + mrb_data_check_type(mrb, obj, type); return DATA_PTR(obj); } void * -mrb_check_datatype(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) +mrb_data_get_ptr(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) { if (mrb_special_const_p(obj) || (mrb_type(obj) != MRB_TT_DATA)) { - mrb_check_type(mrb, obj, MRB_TT_DATA); + return NULL; } if (DATA_TYPE(obj) != type) { - const char *etype = DATA_TYPE(obj)->struct_name; - mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected %S)", - mrb_str_new_cstr(mrb, etype), mrb_str_new_cstr(mrb, type->struct_name)); + return NULL; } return DATA_PTR(obj); } @@ -157,6 +157,20 @@ mrb_realloc(mrb_state *mrb, void *p, size_t len) mrb_garbage_collect(mrb); p2 = (mrb->allocf)(mrb, p, len, mrb->ud); } + + if (!p2 && len) { + if (mrb->out_of_memory) { + /* mrb_panic(mrb); */ + } + else { + mrb->out_of_memory = 1; + mrb_raise(mrb, E_RUNTIME_ERROR, "Out of memory"); + } + } + else { + mrb->out_of_memory = 0; + } + return p2; } diff --git a/src/kernel.c b/src/kernel.c index f14a94b3a..54c90dfc0 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -108,7 +108,7 @@ mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self) mrb_bool eql_p; mrb_get_args(mrb, "o", &arg); - eql_p = mrb_obj_equal(mrb, self, arg); + eql_p = mrb_equal(mrb, self, arg); return mrb_bool_value(!eql_p); } diff --git a/src/numeric.c b/src/numeric.c index 084243291..aacaed9ee 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -163,13 +163,19 @@ num_abs(mrb_state *mrb, mrb_value num) */ mrb_value -mrb_flo_to_str(mrb_state *mrb, mrb_float n, int max_digit) +mrb_flo_to_str(mrb_state *mrb, mrb_value flo, int max_digit) { mrb_value result; + mrb_float n; if (max_digit > 40) { mrb_raise(mrb, E_RANGE_ERROR, "Too large max_digit."); } + else if (!mrb_float_p(flo)) { + mrb_raise(mrb, E_TYPE_ERROR, "non float value"); + } + + n = mrb_float(flo); if (isnan(n)) { result = mrb_str_new(mrb, "NaN", 3); @@ -270,9 +276,9 @@ static mrb_value flo_to_s(mrb_state *mrb, mrb_value flt) { #ifdef MRB_USE_FLOAT - return mrb_flo_to_str(mrb, mrb_float(flt), 7); + return mrb_flo_to_str(mrb, flt, 7); #else - return mrb_flo_to_str(mrb, mrb_float(flt), 14); + return mrb_flo_to_str(mrb, flt, 14); #endif } @@ -665,42 +671,6 @@ flo_truncate(mrb_state *mrb, mrb_value num) return mrb_fixnum_value((mrb_int)f); } -/* 15.2.8.3.17 */ -/* - * call-seq: - * num.floor -> integer - * - * Returns the largest integer less than or equal to <i>num</i>. - * <code>Numeric</code> implements this by converting <i>anInteger</i> - * to a <code>Float</code> and invoking <code>Float#floor</code>. - * - * 1.floor #=> 1 - * (-1).floor #=> -1 - */ - -static mrb_value -num_floor(mrb_state *mrb, mrb_value num) -{ - return flo_floor(mrb, mrb_Float(mrb, num)); -} - -/* 15.2.8.3.20 */ -/* - * call-seq: - * num.round([ndigits]) -> integer or float - * - * Rounds <i>num</i> to a given precision in decimal digits (default 0 digits). - * Precision may be negative. Returns a floating point number when ndigits - * is more than zero. <code>Numeric</code> implements this by converting itself - * to a <code>Float</code> and invoking <code>Float#round</code>. - */ - -static mrb_value -num_round(mrb_state *mrb, mrb_value num) -{ - return flo_round(mrb, mrb_Float(mrb, num)); -} - /* * Document-class: Integer * @@ -710,17 +680,10 @@ num_round(mrb_state *mrb, mrb_value num) */ -/* 15.2.8.3.14 */ -/* 15.2.8.3.24 */ -/* 15.2.8.3.26 */ /* * call-seq: * int.to_i -> integer * int.to_int -> integer - * int.floor -> integer - * int.ceil -> integer - * int.round -> integer - * int.truncate -> integer * * As <i>int</i> is already an <code>Integer</code>, all these * methods simply return the receiver. @@ -1175,25 +1138,27 @@ fix_to_f(mrb_state *mrb, mrb_value num) * FloatDomainError: Infinity */ /* ------------------------------------------------------------------------*/ -static mrb_int -flt2big(mrb_state *mrb, mrb_float d) +mrb_value +mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x) { mrb_int z; - if (isinf(d)) { - mrb_raise(mrb, E_FLOATDOMAIN_ERROR, d < 0 ? "-Infinity" : "Infinity"); + if (mrb_float_p(x)) { + mrb_raise(mrb, E_TYPE_ERROR, "non float value"); + z = 0; /* not reached. just supress warnings. */ } - if (isnan(d)) { - mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN"); - } - z = (mrb_int)d; - return z; -} + else { + mrb_float d = mrb_float(x); -mrb_value -mrb_flt2big(mrb_state *mrb, mrb_float d) -{ - return mrb_fixnum_value(flt2big(mrb, d)); + if (isinf(d)) { + mrb_raise(mrb, E_FLOATDOMAIN_ERROR, d < 0 ? "-Infinity" : "Infinity"); + } + if (isnan(d)) { + mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN"); + } + z = (mrb_int)d; + } + return mrb_fixnum_value(z); } mrb_value @@ -1276,7 +1241,7 @@ fix_minus(mrb_state *mrb, mrb_value self) mrb_value -mrb_fix2str(mrb_state *mrb, mrb_value x, int base) +mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base) { char buf[sizeof(mrb_int)*CHAR_BIT+1]; char *b = buf + sizeof buf; @@ -1324,7 +1289,7 @@ fix_to_s(mrb_state *mrb, mrb_value self) mrb_int base = 10; mrb_get_args(mrb, "|i", &base); - return mrb_fix2str(mrb, self, base); + return mrb_fixnum_to_str(mrb, self, base); } /* 15.2.9.3.6 */ @@ -1404,6 +1369,9 @@ mrb_init_numeric(mrb_state *mrb) /* Integer Class */ integer = mrb_define_class(mrb, "Integer", numeric); + mrb_undef_class_method(mrb, integer, "new"); + mrb_define_method(mrb, integer, "to_i", int_to_i, ARGS_NONE()); /* 15.2.8.3.24 */ + mrb_define_method(mrb, integer, "to_int", int_to_i, ARGS_NONE()); fixnum = mrb->fixnum_class = mrb_define_class(mrb, "Fixnum", integer); mrb_undef_class_method(mrb, fixnum, "new"); @@ -1419,18 +1387,13 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, fixnum, "^", fix_xor, ARGS_REQ(1)); /* 15.2.8.3.11 */ mrb_define_method(mrb, fixnum, "<<", fix_lshift, ARGS_REQ(1)); /* 15.2.8.3.12 */ mrb_define_method(mrb, fixnum, ">>", fix_rshift, ARGS_REQ(1)); /* 15.2.8.3.13 */ - mrb_define_method(mrb, fixnum, "ceil", int_to_i, ARGS_NONE()); /* 15.2.8.3.14 */ mrb_define_method(mrb, fixnum, "eql?", num_eql, ARGS_REQ(1)); /* 15.2.8.3.16 */ - mrb_define_method(mrb, fixnum, "floor", num_floor, ARGS_NONE()); /* 15.2.8.3.17 */ mrb_define_method(mrb, fixnum, "hash", flo_hash, ARGS_NONE()); /* 15.2.8.3.18 */ mrb_define_method(mrb, fixnum, "next", int_succ, ARGS_NONE()); /* 15.2.8.3.19 */ - mrb_define_method(mrb, fixnum, "round", num_round, ARGS_ANY()); /* 15.2.8.3.20 */ mrb_define_method(mrb, fixnum, "succ", fix_succ, ARGS_NONE()); /* 15.2.8.3.21 */ mrb_define_method(mrb, fixnum, "to_f", fix_to_f, ARGS_NONE()); /* 15.2.8.3.23 */ - mrb_define_method(mrb, fixnum, "to_i", int_to_i, ARGS_NONE()); /* 15.2.8.3.24 */ mrb_define_method(mrb, fixnum, "to_s", fix_to_s, ARGS_NONE()); /* 15.2.8.3.25 */ mrb_define_method(mrb, fixnum, "inspect", fix_to_s, ARGS_NONE()); - mrb_define_method(mrb, fixnum, "truncate", int_to_i, ARGS_NONE()); /* 15.2.8.3.26 */ mrb_define_method(mrb, fixnum, "divmod", fix_divmod, ARGS_REQ(1)); /* 15.2.8.3.30 (x) */ /* Float Class */ @@ -1445,9 +1408,10 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, fl, "finite?", flo_finite_p, ARGS_NONE()); /* 15.2.9.3.9 */ mrb_define_method(mrb, fl, "floor", flo_floor, ARGS_NONE()); /* 15.2.9.3.10 */ mrb_define_method(mrb, fl, "infinite?", flo_infinite_p, ARGS_NONE()); /* 15.2.9.3.11 */ - mrb_define_method(mrb, fl, "round", flo_round, ARGS_ANY()); /* 15.2.9.3.12 */ + mrb_define_method(mrb, fl, "round", flo_round, ARGS_NONE()); /* 15.2.9.3.12 */ mrb_define_method(mrb, fl, "to_f", flo_to_f, ARGS_NONE()); /* 15.2.9.3.13 */ mrb_define_method(mrb, fl, "to_i", flo_truncate, ARGS_NONE()); /* 15.2.9.3.14 */ + mrb_define_method(mrb, fl, "to_int", flo_truncate, ARGS_NONE()); mrb_define_method(mrb, fl, "truncate", flo_truncate, ARGS_NONE()); /* 15.2.9.3.15 */ mrb_define_method(mrb, fl, "to_s", flo_to_s, ARGS_NONE()); /* 15.2.9.3.16(x) */ diff --git a/src/object.c b/src/object.c index bd88459ae..23786e859 100644 --- a/src/object.c +++ b/src/object.c @@ -440,6 +440,7 @@ mrb_any_to_s(mrb_state *mrb, mrb_value obj) mrb_str_buf_cat(mrb, str, "#<", 2); mrb_str_cat2(mrb, str, cname); + mrb_str_cat(mrb, str, ":", 1); mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_voidp(obj))); mrb_str_buf_cat(mrb, str, ">", 1); @@ -530,7 +531,7 @@ mrb_convert_to_integer(mrb_state *mrb, mrb_value val, int base) if (FIXABLE(mrb_float(val))) { break; } - return mrb_flt2big(mrb, mrb_float(val)); + return mrb_flo_to_fixnum(mrb, val); case MRB_TT_FIXNUM: if (base != 0) goto arg_error; diff --git a/src/parse.y b/src/parse.y index 1c0170ac9..35bc18cd5 100644 --- a/src/parse.y +++ b/src/parse.y @@ -4726,6 +4726,10 @@ parser_yylex(parser_state *p) p->lstate = EXPR_END; token_column = newtok(p); c = nextc(p); + if (c == -1) { + yyerror(p, "incomplete global variable syntax"); + return 0; + } switch (c) { case '_': /* $_: last read line string */ c = nextc(p); @@ -4812,7 +4816,16 @@ parser_yylex(parser_state *p) tokadd(p, '@'); c = nextc(p); } - if (c != -1 && isdigit(c)) { + if (c == -1) { + if (p->bidx == 1) { + yyerror(p, "incomplete instance variable syntax"); + } + else { + yyerror(p, "incomplete class variable syntax"); + } + return 0; + } + else if (isdigit(c)) { if (p->bidx == 1) { yyerror_i(p, "`@%c' is not allowed as an instance variable name", c); } diff --git a/src/string.c b/src/string.c index 5b6a44abd..329a3da9d 100644 --- a/src/string.c +++ b/src/string.c @@ -622,29 +622,22 @@ mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr) mrb_value str = mrb_str_to_str(mrb, ptr); return RSTRING_PTR(str); } -/* 15.2.10.5.5 */ - -/* - * call-seq: - * str =~ obj -> fixnum or nil - * - * Match---If <i>obj</i> is a <code>Regexp</code>, use it as a pattern to match - * against <i>str</i>,and returns the position the match starts, or - * <code>nil</code> if there is no match. Otherwise, invokes - * <i>obj.=~</i>, passing <i>str</i> as an argument. The default - * <code>=~</code> in <code>Object</code> returns <code>nil</code>. - * - * "cat o' 9 tails" =~ /\d/ #=> 7 - * "cat o' 9 tails" =~ 9 #=> nil - */ static mrb_value -mrb_str_match(mrb_state *mrb, mrb_value self/* x */) +noregexp(mrb_state *mrb, mrb_value self) { - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); + mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp class not implemented"); return mrb_nil_value(); } +static void +regexp_check(mrb_state *mrb, mrb_value obj) +{ + if (!strcmp(mrb_obj_classname(mrb, obj), REGEXP_CLASS)) { + noregexp(mrb, obj); + } +} + static inline mrb_int mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n) { @@ -730,9 +723,7 @@ mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value indx) { mrb_int idx; - if (!strcmp(mrb_obj_classname(mrb, indx), REGEXP_CLASS)) { - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - } + regexp_check(mrb, indx); switch (mrb_type(indx)) { case MRB_TT_FIXNUM: idx = mrb_fixnum(indx); @@ -825,9 +816,7 @@ mrb_str_aref_m(mrb_state *mrb, mrb_value str) argc = mrb_get_args(mrb, "o|o", &a1, &a2); if (argc == 2) { - if (!strcmp(mrb_obj_classname(mrb, a1), REGEXP_CLASS)) { - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - } + regexp_check(mrb, a1); return mrb_str_substr(mrb, str, mrb_fixnum(a1), mrb_fixnum(a2)); } if (argc != 1) { @@ -1193,62 +1182,6 @@ mrb_str_buf_append(mrb_state *mrb, mrb_value str, mrb_value str2) return str; } -/* 15.2.10.5.18 */ -/* - * call-seq: - * str.gsub(pattern, replacement) => new_str - * str.gsub(pattern) {|match| block } => new_str - * - * Returns a copy of <i>str</i> with <em>all</em> occurrences of <i>pattern</i> - * replaced with either <i>replacement</i> or the value of the block. The - * <i>pattern</i> will typically be a <code>Regexp</code>; if it is a - * <code>String</code> then no regular expression metacharacters will be - * interpreted (that is <code>/\d/</code> will match a digit, but - * <code>'\d'</code> will match a backslash followed by a 'd'). - * - * If a string is used as the replacement, special variables from the match - * (such as <code>$&</code> and <code>$1</code>) cannot be substituted into it, - * as substitution into the string occurs before the pattern match - * starts. However, the sequences <code>\1</code>, <code>\2</code>, and so on - * may be used to interpolate successive groups in the match. - * - * In the block form, the current match string is passed in as a parameter, and - * variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>, - * <code>$&</code>, and <code>$'</code> will be set appropriately. The value - * returned by the block will be substituted for the match on each call. - * - * When neither a block nor a second argument is supplied, an - * <code>Enumerator</code> is returned. - * - * "hello".gsub(/[aeiou]/, '*') #=> "h*ll*" - * "hello".gsub(/([aeiou])/, '<\1>') #=> "h<e>ll<o>" - * "hello".gsub(/./) {|s| s.ord.to_s + ' '} #=> "104 101 108 108 111 " - * "hello".gsub(/(?<foo>[aeiou])/, '{\k<foo>}') #=> "h{e}ll{o}" - * 'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*') #=> "h3ll*" - */ -static mrb_value -mrb_str_gsub(mrb_state *mrb, mrb_value self) -{ - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - return mrb_nil_value(); -} - -/* 15.2.10.5.19 */ -/* - * call-seq: - * str.gsub!(pattern, replacement) => str or nil - * str.gsub!(pattern) {|match| block } => str or nil - * - * Performs the substitutions of <code>String#gsub</code> in place, returning - * <i>str</i>, or <code>nil</code> if no substitutions were performed. - */ -static mrb_value -mrb_str_gsub_bang(mrb_state *mrb, mrb_value self) -{ - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - return mrb_nil_value(); -} - mrb_int mrb_str_hash(mrb_state *mrb, mrb_value str) { @@ -1357,9 +1290,7 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str) sub = mrb_nil_value(); } - if (!strcmp(mrb_obj_classname(mrb, sub), REGEXP_CLASS)) { - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - } + regexp_check(mrb, sub); if (pos < 0) { pos += RSTRING_LEN(str); if (pos < 0) { @@ -1555,26 +1486,6 @@ mrb_check_string_type(mrb_state *mrb, mrb_value str) return mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str"); } -/* 15.2.10.5.27 */ -/* - * call-seq: - * str.match(pattern) => matchdata or nil - * - * Converts <i>pattern</i> to a <code>Regexp</code> (if it isn't already one), - * then invokes its <code>match</code> method on <i>str</i>. - * - * 'hello'.match('(.)\1') #=> #<MatchData:0x401b3d30> - * 'hello'.match('(.)\1')[0] #=> "ll" - * 'hello'.match(/(.)\1/)[0] #=> "ll" - * 'hello'.match('xx') #=> nil - */ -static mrb_value -mrb_str_match_m(mrb_state *mrb, mrb_value self) -{ - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - return mrb_nil_value(); -} - /* ---------------------------------- */ /* 15.2.10.5.29 */ /* @@ -1715,9 +1626,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str) if (pos < 0) { pos += len; if (pos < 0) { - if (!strcmp(mrb_obj_classname(mrb, sub), REGEXP_CLASS)) { - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - } + regexp_check(mrb, sub); return mrb_nil_value(); } } @@ -1730,9 +1639,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str) else sub = mrb_nil_value(); } - if (!strcmp(mrb_obj_classname(mrb, sub), REGEXP_CLASS)) { - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - } + regexp_check(mrb, sub); switch (mrb_type(sub)) { case MRB_TT_FIXNUM: { @@ -1765,44 +1672,6 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str) return mrb_nil_value(); } -/* 15.2.10.5.32 */ -/* - * call-seq: - * str.scan(pattern) => array - * str.scan(pattern) {|match, ...| block } => str - * - * Both forms iterate through <i>str</i>, matching the pattern (which may be a - * <code>Regexp</code> or a <code>String</code>). For each match, a result is - * generated and either added to the result array or passed to the block. If - * the pattern contains no groups, each individual result consists of the - * matched string, <code>$&</code>. If the pattern contains groups, each - * individual result is itself an array containing one entry per group. - * - * a = "cruel world" - * a.scan(/\w+/) #=> ["cruel", "world"] - * a.scan(/.../) #=> ["cru", "el ", "wor"] - * a.scan(/(...)/) #=> [["cru"], ["el "], ["wor"]] - * a.scan(/(..)(..)/) #=> [["cr", "ue"], ["l ", "wo"]] - * - * And the block form: - * - * a.scan(/\w+/) {|w| print "<<#{w}>> " } - * print "\n" - * a.scan(/(.)(.)/) {|x,y| print y, x } - * print "\n" - * - * <em>produces:</em> - * - * <<cruel>> <<world>> - * rceu lowlr - */ -static mrb_value -mrb_str_scan(mrb_state *mrb, mrb_value str) -{ - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - return mrb_nil_value(); -} - static const char isspacetable[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1901,7 +1770,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) } } else { - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); + noregexp(mrb, str); } } @@ -1970,7 +1839,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) beg = ptr - temp; } else { - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); + noregexp(mrb, str); } if (RSTRING_LEN(str) > 0 && (lim_p || RSTRING_LEN(str) > beg || lim < 0)) { if (RSTRING_LEN(str) == beg) { @@ -1991,70 +1860,6 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) return result; } - -/* 15.2.10.5.37 */ -/* - * call-seq: - * str.sub!(pattern, replacement) => str or nil - * str.sub!(pattern) {|match| block } => str or nil - * - * Performs the substitutions of <code>String#sub</code> in place, - * returning <i>str</i>, or <code>nil</code> if no substitutions were - * performed. - */ -static mrb_value -mrb_str_sub_bang(mrb_state *mrb, mrb_value str) -{ - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - return mrb_nil_value(); -} - -/* 15.2.10.5.36 */ - -/* - * call-seq: - * str.sub(pattern, replacement) -> new_str - * str.sub(pattern, hash) -> new_str - * str.sub(pattern) {|match| block } -> new_str - * - * Returns a copy of <i>str</i> with the <em>first</em> occurrence of - * <i>pattern</i> substituted for the second argument. The <i>pattern</i> is - * typically a <code>Regexp</code>; if given as a <code>String</code>, any - * regular expression metacharacters it contains will be interpreted - * literally, e.g. <code>'\\\d'</code> will match a backlash followed by 'd', - * instead of a digit. - * - * If <i>replacement</i> is a <code>String</code> it will be substituted for - * the matched text. It may contain back-references to the pattern's capture - * groups of the form <code>\\\d</code>, where <i>d</i> is a group number, or - * <code>\\\k<n></code>, where <i>n</i> is a group name. If it is a - * double-quoted string, both back-references must be preceded by an - * additional backslash. However, within <i>replacement</i> the special match - * variables, such as <code>&$</code>, will not refer to the current match. - * - * If the second argument is a <code>Hash</code>, and the matched text is one - * of its keys, the corresponding value is the replacement string. - * - * In the block form, the current match string is passed in as a parameter, - * and variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>, - * <code>$&</code>, and <code>$'</code> will be set appropriately. The value - * returned by the block will be substituted for the match on each call. - * - * "hello".sub(/[aeiou]/, '*') #=> "h*llo" - * "hello".sub(/([aeiou])/, '<\1>') #=> "h<e>llo" - * "hello".sub(/./) {|s| s.ord.to_s + ' ' } #=> "104 ello" - * "hello".sub(/(?<foo>[aeiou])/, '*\k<foo>*') #=> "h*e*llo" - * 'Is SHELL your preferred shell?'.sub(/[[:upper:]]{2,}/, ENV) - * #=> "Is /bin/bash your preferred shell?" - */ - -static mrb_value -mrb_str_sub(mrb_state *mrb, mrb_value self) -{ - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); - return mrb_nil_value(); -} - mrb_value mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck) { @@ -2537,7 +2342,7 @@ mrb_str_dump(mrb_state *mrb, mrb_value str) const char *ptr; int len; chr = mrb_fixnum_value(c & 0xff); - octstr = mrb_fix2str(mrb, chr, 8); + octstr = mrb_fixnum_to_str(mrb, chr, 8); ptr = mrb_str_body(octstr, &len); memcpy(q, "\\000", 4); memcpy(q + 4 - len, ptr, len); @@ -2629,7 +2434,7 @@ mrb_str_inspect(mrb_state *mrb, mrb_value str) const char *ptr; int len; chr = mrb_fixnum_value(c & 0xff); - octstr = mrb_fix2str(mrb, chr, 8); + octstr = mrb_fixnum_to_str(mrb, chr, 8); ptr = mrb_str_body(octstr, &len); memcpy(buf, "\\000", 4); memcpy(buf + 4 - len, ptr, len); @@ -2682,7 +2487,7 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "*", mrb_str_times, ARGS_REQ(1)); /* 15.2.10.5.1 */ mrb_define_method(mrb, s, "<=>", mrb_str_cmp_m, ARGS_REQ(1)); /* 15.2.10.5.3 */ mrb_define_method(mrb, s, "==", mrb_str_equal_m, ARGS_REQ(1)); /* 15.2.10.5.4 */ - mrb_define_method(mrb, s, "=~", mrb_str_match, ARGS_REQ(1)); /* 15.2.10.5.5 */ + mrb_define_method(mrb, s, "=~", noregexp, ARGS_REQ(1)); /* 15.2.10.5.5 */ mrb_define_method(mrb, s, "[]", mrb_str_aref_m, ARGS_ANY()); /* 15.2.10.5.6 */ mrb_define_method(mrb, s, "capitalize", mrb_str_capitalize, ARGS_NONE()); /* 15.2.10.5.7 */ mrb_define_method(mrb, s, "capitalize!", mrb_str_capitalize_bang, ARGS_REQ(1)); /* 15.2.10.5.8 */ @@ -2696,8 +2501,8 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "eql?", mrb_str_eql, ARGS_REQ(1)); /* 15.2.10.5.17 */ // NOTE: Regexp not implemented - mrb_define_method(mrb, s, "gsub", mrb_str_gsub, ARGS_REQ(1)); /* 15.2.10.5.18 */ - mrb_define_method(mrb, s, "gsub!", mrb_str_gsub_bang, ARGS_REQ(1)); /* 15.2.10.5.19 */ + mrb_define_method(mrb, s, "gsub", noregexp, ARGS_REQ(1)); /* 15.2.10.5.18 */ + mrb_define_method(mrb, s, "gsub!", noregexp, ARGS_REQ(1)); /* 15.2.10.5.19 */ mrb_define_method(mrb, s, "hash", mrb_str_hash_m, ARGS_REQ(1)); /* 15.2.10.5.20 */ mrb_define_method(mrb, s, "include?", mrb_str_include, ARGS_REQ(1)); /* 15.2.10.5.21 */ @@ -2705,24 +2510,16 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "initialize", mrb_str_init, ARGS_REQ(1)); /* 15.2.10.5.23 */ mrb_define_method(mrb, s, "initialize_copy", mrb_str_replace, ARGS_REQ(1)); /* 15.2.10.5.24 */ mrb_define_method(mrb, s, "intern", mrb_str_intern, ARGS_NONE()); /* 15.2.10.5.25 */ - - // NOTE: Regexp not implemented - mrb_define_method(mrb, s, "match", mrb_str_match_m, ARGS_REQ(1)); /* 15.2.10.5.27 */ - + mrb_define_method(mrb, s, "match", noregexp, ARGS_REQ(1)); /* 15.2.10.5.27 */ mrb_define_method(mrb, s, "replace", mrb_str_replace, ARGS_REQ(1)); /* 15.2.10.5.28 */ mrb_define_method(mrb, s, "reverse", mrb_str_reverse, ARGS_NONE()); /* 15.2.10.5.29 */ mrb_define_method(mrb, s, "reverse!", mrb_str_reverse_bang, ARGS_NONE()); /* 15.2.10.5.30 */ mrb_define_method(mrb, s, "rindex", mrb_str_rindex_m, ARGS_ANY()); /* 15.2.10.5.31 */ - - // NOTE: Regexp not implemented - mrb_define_method(mrb, s, "scan", mrb_str_scan, ARGS_REQ(1)); /* 15.2.10.5.32 */ - + mrb_define_method(mrb, s, "scan", noregexp, ARGS_REQ(1)); /* 15.2.10.5.32 */ mrb_define_method(mrb, s, "slice", mrb_str_aref_m, ARGS_ANY()); /* 15.2.10.5.34 */ mrb_define_method(mrb, s, "split", mrb_str_split_m, ARGS_ANY()); /* 15.2.10.5.35 */ - - // NOTE: Regexp not implemented - mrb_define_method(mrb, s, "sub", mrb_str_sub, ARGS_REQ(1)); /* 15.2.10.5.36 */ - mrb_define_method(mrb, s, "sub!", mrb_str_sub_bang, ARGS_REQ(1)); /* 15.2.10.5.37 */ + mrb_define_method(mrb, s, "sub", noregexp, ARGS_REQ(1)); /* 15.2.10.5.36 */ + mrb_define_method(mrb, s, "sub!", noregexp, ARGS_REQ(1)); /* 15.2.10.5.37 */ mrb_define_method(mrb, s, "to_i", mrb_str_to_i, ARGS_ANY()); /* 15.2.10.5.38 */ mrb_define_method(mrb, s, "to_f", mrb_str_to_f, ARGS_NONE()); /* 15.2.10.5.39 */ diff --git a/src/variable.c b/src/variable.c index 941aaf83e..2057b69ef 100644 --- a/src/variable.c +++ b/src/variable.c @@ -11,6 +11,7 @@ #include "mruby/string.h" #include "mruby/variable.h" #include "error.h" +#include <ctype.h> typedef int (iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*); @@ -690,7 +691,7 @@ mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym) } c = c->super; } - mrb_raisef(mrb, E_NAME_ERROR, "uninitialized class variable %S in %S", + mrb_name_error(mrb, sym, "uninitialized class variable %S in %S", mrb_sym2str(mrb, sym), cls); /* not reached */ return mrb_nil_value(); @@ -846,7 +847,7 @@ L_RETRY: } c = c->super; } - mrb_raisef(mrb, E_NAME_ERROR, "uninitialized constant %S", + mrb_name_error(mrb, sym, "uninitialized constant %S", mrb_sym2str(mrb, sym)); /* not reached */ return mrb_nil_value(); @@ -919,6 +920,45 @@ mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val) mrb_define_const(mrb, mrb->object_class, name, val); } +static int +const_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) +{ + mrb_value ary; + const char* s; + size_t len; + + ary = *(mrb_value*)p; + s = mrb_sym2name_len(mrb, sym, &len); + if (len > 1 && ISUPPER(s[0])) { + mrb_ary_push(mrb, ary, mrb_symbol_value(sym)); + } + return 0; +} + +/* 15.2.2.4.24 */ +/* + * call-seq: + * mod.constants -> array + * + * Returns an array of all names of contants defined in the receiver. + */ +mrb_value +mrb_mod_constants(mrb_state *mrb, mrb_value mod) +{ + mrb_value ary; + struct RClass *c = mrb_class_ptr(mod); + + ary = mrb_ary_new(mrb); + while (c) { + if (c->iv) { + iv_foreach(mrb, c->iv, const_i, &ary); + } + c = c->super; + if (c == mrb->object_class) break; + } + return ary; +} + mrb_value mrb_gv_get(mrb_state *mrb, mrb_sym sym) { @@ -55,6 +55,9 @@ The value below allows about 60000 recursive calls in the simplest case. */ # define DEBUG(x) #endif +#define TO_STR(x) TO_STR_(x) +#define TO_STR_(x) #x + static inline void stack_clear(mrb_value *from, size_t count) { @@ -133,9 +136,9 @@ stack_extend(mrb_state *mrb, int room, int keep) mrb->stend = mrb->stbase + size; envadjust(mrb, oldbase, mrb->stbase); /* Raise an exception if the new stack size will be too large, - to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raisef has stack space to work with. */ + to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raise has stack space to work with. */ if (size > MRB_STACK_MAX) { - mrb_raisef(mrb, E_RUNTIME_ERROR, "stack level too deep. (limit=%S)", mrb_fixnum_value(MRB_STACK_MAX)); + mrb_raise(mrb, E_RUNTIME_ERROR, "stack level too deep. (limit=" TO_STR(MRB_STACK_MAX) ")"); } } @@ -275,7 +278,7 @@ mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...) int i; if (argc > MRB_FUNCALL_ARGC_MAX) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%S)", mrb_fixnum_value(MRB_FUNCALL_ARGC_MAX)); + mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=" TO_STR(MRB_FUNCALL_ARGC_MAX) ")"); } va_start(ap, argc); @@ -302,7 +305,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr cipop(mrb); } mrb->jmp = 0; - val = mrb_nil_value(); + val = mrb_obj_value(mrb->exc); } else { mrb->jmp = &c_jmp; @@ -343,7 +346,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr ci->nregs = argc + 2; } else { - ci->nregs = p->body.irep->nregs + 2; + ci->nregs = p->body.irep->nregs + n; } ci->acc = -1; mrb->stack = mrb->stack + n; @@ -1207,6 +1210,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) ci = mrb->ci; if (ci[1].acc < 0 && prev_jmp) { mrb->jmp = prev_jmp; + mrb->stack = mrb->stbase + ci[1].stackidx; longjmp(*(jmp_buf*)mrb->jmp, 1); } while (eidx > mrb->ci->eidx) { |
