summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/array.c4
-rw-r--r--src/class.c11
-rw-r--r--src/codegen.c4
-rw-r--r--src/dump.c4
-rw-r--r--src/error.c4
-rw-r--r--src/error.h1
-rw-r--r--src/etc.c27
-rw-r--r--src/gc.c14
-rw-r--r--src/kernel.c2
-rw-r--r--src/numeric.c100
-rw-r--r--src/object.c3
-rw-r--r--src/parse.y15
-rw-r--r--src/string.c255
-rw-r--r--src/variable.c44
-rw-r--r--src/vm.c14
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 */
diff --git a/src/etc.c b/src/etc.c
index 0b58ad67c..727915145 100644
--- a/src/etc.c
+++ b/src/etc.c
@@ -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);
}
diff --git a/src/gc.c b/src/gc.c
index c90e00c89..07bc23b12 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -157,6 +157,20 @@ mrb_realloc(mrb_state *mrb, void *p, size_t len)
mrb_garbage_collect(mrb);
p2 = (mrb->allocf)(mrb, p, len, mrb->ud);
}
+
+ if (!p2 && len) {
+ if (mrb->out_of_memory) {
+ /* mrb_panic(mrb); */
+ }
+ else {
+ mrb->out_of_memory = 1;
+ mrb_raise(mrb, E_RUNTIME_ERROR, "Out of memory");
+ }
+ }
+ else {
+ mrb->out_of_memory = 0;
+ }
+
return p2;
}
diff --git a/src/kernel.c b/src/kernel.c
index f14a94b3a..54c90dfc0 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -108,7 +108,7 @@ mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self)
mrb_bool eql_p;
mrb_get_args(mrb, "o", &arg);
- eql_p = mrb_obj_equal(mrb, self, arg);
+ eql_p = mrb_equal(mrb, self, arg);
return mrb_bool_value(!eql_p);
}
diff --git a/src/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)
{
diff --git a/src/vm.c b/src/vm.c
index 596e34961..c319e7148 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -55,6 +55,9 @@ The value below allows about 60000 recursive calls in the simplest case. */
# define DEBUG(x)
#endif
+#define TO_STR(x) TO_STR_(x)
+#define TO_STR_(x) #x
+
static inline void
stack_clear(mrb_value *from, size_t count)
{
@@ -133,9 +136,9 @@ stack_extend(mrb_state *mrb, int room, int keep)
mrb->stend = mrb->stbase + size;
envadjust(mrb, oldbase, mrb->stbase);
/* Raise an exception if the new stack size will be too large,
- to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raisef has stack space to work with. */
+ to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raise has stack space to work with. */
if (size > MRB_STACK_MAX) {
- mrb_raisef(mrb, E_RUNTIME_ERROR, "stack level too deep. (limit=%S)", mrb_fixnum_value(MRB_STACK_MAX));
+ mrb_raise(mrb, E_RUNTIME_ERROR, "stack level too deep. (limit=" TO_STR(MRB_STACK_MAX) ")");
}
}
@@ -275,7 +278,7 @@ mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...)
int i;
if (argc > MRB_FUNCALL_ARGC_MAX) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%S)", mrb_fixnum_value(MRB_FUNCALL_ARGC_MAX));
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=" TO_STR(MRB_FUNCALL_ARGC_MAX) ")");
}
va_start(ap, argc);
@@ -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) {