diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/class.c | 37 | ||||
| -rw-r--r-- | src/etc.c | 19 | ||||
| -rw-r--r-- | src/gc.c | 7 | ||||
| -rw-r--r-- | src/gc.h | 12 | ||||
| -rw-r--r-- | src/hash.c | 116 | ||||
| -rw-r--r-- | src/init.c | 1 | ||||
| -rw-r--r-- | src/kernel.c | 13 | ||||
| -rw-r--r-- | src/object.c | 2 | ||||
| -rw-r--r-- | src/range.c | 17 | ||||
| -rw-r--r-- | src/time.c | 600 | ||||
| -rw-r--r-- | src/vm.c | 31 |
11 files changed, 750 insertions, 105 deletions
diff --git a/src/class.c b/src/class.c index f517cc19a..1e2ac7aa0 100644 --- a/src/class.c +++ b/src/class.c @@ -309,9 +309,9 @@ mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t f } void -mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int apec) +mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec) { - return mrb_define_method_id(mrb, c, mrb_intern(mrb, name), func, apec); + return mrb_define_method_id(mrb, c, mrb_intern(mrb, name), func, aspec); } void @@ -348,7 +348,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) { mrb_value *p; p = va_arg(ap, mrb_value*); - *p = (argc > i) ? *sp : mrb_nil_value(); + *p = *sp; i++; sp++; } break; @@ -357,7 +357,22 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_int *p; p = va_arg(ap, mrb_int*); - *p = (argc > i) ? mrb_fixnum(*sp) : 0; + switch (sp->tt) { + case MRB_TT_FIXNUM: + *p = mrb_fixnum(*sp); + break; + case MRB_TT_FLOAT: + *p = (mrb_int)mrb_float(*sp); + break; + default: + { + mrb_value tmp; + + tmp = mrb_convert_type(mrb, *sp, MRB_TT_FIXNUM, "Integer", "to_int"); + *p = mrb_fixnum(tmp); + } + break; + } i++; sp++; } break; @@ -368,13 +383,18 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) p = va_arg(ap, mrb_float*); switch (sp->tt) { case MRB_TT_FLOAT: - *p = (argc > i) ? mrb_float(*sp) : 0; + *p = mrb_float(*sp); break; case MRB_TT_FIXNUM: - *p = (argc > i) ? (mrb_float)mrb_fixnum(*sp) : 0; + *p = (mrb_float)mrb_fixnum(*sp); break; default: - // error + { + mrb_value tmp; + + tmp = mrb_convert_type(mrb, *sp, MRB_TT_FLOAT, "Float", "to_f"); + *p = mrb_float(tmp); + } break; } i++; sp++; @@ -836,7 +856,8 @@ mrb_check_inheritable(mrb_state *mrb, struct RClass *super) * \param super a class from which the new class derives. * \exception TypeError \a super is not inheritable. * \exception TypeError \a super is the Class class. - */struct RClass * + */ +struct RClass * mrb_class_new(mrb_state *mrb, struct RClass *super) { struct RClass *c; @@ -18,13 +18,6 @@ #define TRUE 1 #endif -void -ruby_xfree(void *x) -{ - //if (x) - // vm_xfree(&mrb_objspace, x); -} - struct RData* mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const struct mrb_data_type *type) { @@ -38,6 +31,18 @@ mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const str } void * +mrb_get_datatype(mrb_state *mrb, mrb_value obj, const struct mrb_data_type *type) +{ + if (SPECIAL_CONST_P(obj) || (mrb_type(obj) != MRB_TT_DATA)) { + return NULL; + } + if (DATA_TYPE(obj) != type) { + return NULL; + } + return DATA_PTR(obj); +} + +void * mrb_check_datatype(mrb_state *mrb, mrb_value obj, const struct mrb_data_type *type) { static const char mesg[] = "wrong argument type %s (expected %s)"; @@ -345,7 +345,8 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj) break; case MRB_TT_HASH: - mrb_gc_mark_ht(mrb, (struct RClass*)obj); + mrb_gc_mark_iv(mrb, (struct RObject*)obj); + mrb_gc_mark_ht(mrb, (struct RHash*)obj); break; case MRB_TT_STRING: @@ -422,6 +423,7 @@ obj_free(mrb_state *mrb, struct RBasic *obj) break; case MRB_TT_HASH: + mrb_gc_free_iv(mrb, (struct RObject*)obj); mrb_gc_free_ht(mrb, (struct RClass*)obj); break; @@ -530,7 +532,8 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj) break; case MRB_TT_HASH: - children += mrb_gc_mark_ht_size(mrb, (struct RClass*)obj); + children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj); + children += mrb_gc_mark_ht_size(mrb, (struct RHash*)obj); break; case MRB_TT_PROC: @@ -29,4 +29,16 @@ typedef struct { } as; } RVALUE; +void mrb_gc_mark_gv(mrb_state*); +void mrb_gc_free_gv(mrb_state*); +void mrb_gc_mark_iv(mrb_state*, struct RObject*); +size_t mrb_gc_mark_iv_size(mrb_state*, struct RObject*); +void mrb_gc_free_iv(mrb_state*, struct RObject*); +void mrb_gc_mark_mt(mrb_state*, struct RClass*); +size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*); +void mrb_gc_free_mt(mrb_state*, struct RClass*); +void mrb_gc_mark_ht(mrb_state*, struct RHash*); +size_t mrb_gc_mark_ht_size(mrb_state*, struct RHash*); +void mrb_gc_free_ht(mrb_state*, struct RHash*); + #endif /* MRUBY_GC_H */ diff --git a/src/hash.c b/src/hash.c index 078faf1d3..cb34dae75 100644 --- a/src/hash.c +++ b/src/hash.c @@ -9,10 +9,8 @@ #include "mruby/khash.h" #include "mruby/class.h" #include "mruby/array.h" -#include "error.h" #include "mruby/string.h" -#include "mruby/numeric.h" -#include "mruby/struct.h" +#include "mruby/variable.h" #include "st.h" #include <errno.h> #include <string.h> @@ -66,12 +64,11 @@ mrb_hash_ht_key(mrb_state *mrb, mrb_value key) #define KEY(key) mrb_hash_ht_key(mrb, key) void -mrb_gc_mark_ht(mrb_state *mrb, struct RClass *c) +mrb_gc_mark_ht(mrb_state *mrb, struct RHash *c) { khiter_t k; khash_t(ht) *h = ((struct RHash*)c)->ht; - mrb_gc_mark_value(mrb, ((struct RHash*)c)->ifnone); if (!h) return; for (k = kh_begin(h); k != kh_end(h); k++) if (kh_exist(h, k)) { @@ -86,9 +83,6 @@ mrb_gc_mark_ht_size(mrb_state *mrb, struct RClass *c) size_t ht_size = 0; khash_t(ht) *h = ((struct RHash*)c)->ht; - /* ((struct RHash*)c)->ifnone */ - ht_size++; - /* ((struct RHash*)c)->ht */ if (h) ht_size += kh_size(h)*2; @@ -112,7 +106,7 @@ mrb_hash_new_capa(mrb_state *mrb, size_t capa) h = mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class); h->ht = kh_init(ht, mrb); kh_resize(ht, h->ht, capa); - h->ifnone = mrb_nil_value(); + h->iv = 0; return mrb_obj_value(h); } @@ -125,7 +119,7 @@ mrb_hash_new(mrb_state *mrb, int capa) mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) /* mrb_hash_aref */ /* mrb_hash_lookup */ { - khash_t(ht) *h = RHASH_H_TBL(hash); + khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; if (h) { @@ -138,15 +132,13 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) /* mrb_hash_aref */ if (MRB_RHASH_PROCDEFAULT_P(hash)) { return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key); } - else { - return RHASH_IFNONE(hash); - } + return RHASH_IFNONE(hash); } mrb_value mrb_hash_getWithDef(mrb_state *mrb, mrb_value hash, mrb_value vkey, mrb_value def) /* mrb_hash_lookup2 */ { - khash_t(ht) *h = RHASH_H_TBL(hash); + khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; if (h) { @@ -166,7 +158,7 @@ mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val) /* mr khiter_t k; mrb_hash_modify(mrb, hash); - h = RHASH_H_TBL(hash); + h = RHASH_TBL(hash); k = kh_get(ht, h, key); if (k == kh_end(h)) { @@ -201,18 +193,6 @@ retry: } } -static mrb_value -hash_s_new(mrb_state *mrb, mrb_value klass) -{ - mrb_value *argv; - int argc; - - mrb_get_args(mrb, "*", &argv, &argc); - mrb_value hash = mrb_hash_new_capa(mrb, 0); - mrb_obj_call_init(mrb, hash, argc, argv); - return hash; -} - mrb_value mrb_hash_dup(mrb_state *mrb, mrb_value hash) { @@ -224,7 +204,7 @@ mrb_hash_dup(mrb_state *mrb, mrb_value hash) ret->ht = kh_init(ht, mrb); if (!RHASH_EMPTY_P(hash)) { - h = RHASH_H_TBL(hash); + h = RHASH_TBL(hash); ret_h = ret->ht; for (k = kh_begin(h); k != kh_end(h); k++) { @@ -247,10 +227,10 @@ mrb_hash_modify_check(mrb_state *mrb, mrb_value hash) khash_t(ht) * mrb_hash_tbl(mrb_state *mrb, mrb_value hash) { - khash_t(ht) *h = RHASH_H_TBL(hash); + khash_t(ht) *h = RHASH_TBL(hash); - if (!RHASH_H_TBL(hash)) { - RHASH_H_TBL(hash) = kh_init(ht, mrb); + if (!RHASH_TBL(hash)) { + RHASH_TBL(hash) = kh_init(ht, mrb); } return h; } @@ -301,21 +281,20 @@ mrb_hash_modify(mrb_state *mrb, mrb_value hash) static mrb_value mrb_hash_init_core(mrb_state *mrb, mrb_value hash) { - mrb_value block; + mrb_value block, ifnone; mrb_value *argv; int argc; mrb_get_args(mrb, "o*", &block, &argv, &argc); mrb_hash_modify(mrb, hash); - if (mrb_nil_p(block)) { if (argc > 0) { if (argc != 1) mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); - RHASH_IFNONE(hash) = argv[0]; + ifnone = argv[0]; } else { - RHASH_IFNONE(hash) = mrb_nil_value(); + ifnone = mrb_nil_value(); } } else { @@ -323,9 +302,9 @@ mrb_hash_init_core(mrb_state *mrb, mrb_value hash) mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); } RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT; - RHASH_PROCDEFAULT(hash) = block; + ifnone = block; } - + mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone); return hash; } @@ -497,7 +476,7 @@ mrb_hash_set_default(mrb_state *mrb, mrb_value hash) mrb_get_args(mrb, "o", &ifnone); mrb_hash_modify(mrb, hash); - RHASH_IFNONE(hash) = ifnone; + mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone); RHASH(hash)->flags &= ~(MRB_HASH_PROC_DEFAULT); return ifnone; @@ -541,10 +520,23 @@ mrb_hash_default_proc(mrb_state *mrb, mrb_value hash) * h["cat"] #=> "catcat" */ +static mrb_value +mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash) +{ + mrb_value ifnone; + mrb_get_args(mrb, "o", &ifnone); + + mrb_hash_modify(mrb, hash); + mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone); + RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT; + + return ifnone; +} + mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key) { - khash_t(ht) *h = RHASH_H_TBL(hash); + khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; mrb_value delVal; @@ -610,7 +602,7 @@ struct shift_var { static mrb_value mrb_hash_shift(mrb_state *mrb, mrb_value hash) { - khash_t(ht) *h = RHASH_H_TBL(hash); + khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; mrb_value delKey, delVal; mrb_value result; @@ -625,8 +617,8 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash) delVal = mrb_hash_delete_key(mrb, hash, delKey); result = mrb_hash_new(mrb, 1); - k = kh_put(ht, RHASH_H_TBL(result), KEY(delKey)); - kh_value(RHASH_H_TBL(result), k) = delVal; + k = kh_put(ht, RHASH_TBL(result), KEY(delKey)); + kh_value(RHASH_TBL(result), k) = delVal; return result; } } @@ -688,7 +680,7 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash) mrb_value mrb_hash_values_at(mrb_state *mrb, int argc, mrb_value *argv, mrb_value hash) { - mrb_value result = mrb_ary_new_capa(mrb, argc);//mrb_ary_new2(argc); + mrb_value result = mrb_ary_new_capa(mrb, argc); long i; for (i=0; i<argc; i++) { @@ -747,7 +739,7 @@ mrb_hash_values_at(mrb_state *mrb, int argc, mrb_value *argv, mrb_value hash) static mrb_value mrb_hash_clear(mrb_state *mrb, mrb_value hash) { - khash_t(ht) *h = RHASH_H_TBL(hash); + khash_t(ht) *h = RHASH_TBL(hash); kh_clear(ht, h); return hash; @@ -799,7 +791,7 @@ mrb_hash_aset(mrb_state *mrb, mrb_value self) static mrb_value mrb_hash_replace(mrb_state *mrb, mrb_value hash) { - mrb_value hash2; + mrb_value hash2, ifnone; khash_t(ht) *h2; khiter_t k; @@ -810,7 +802,7 @@ mrb_hash_replace(mrb_state *mrb, mrb_value hash) if (mrb_obj_equal(mrb, hash, hash2)) return hash; mrb_hash_clear(mrb, hash); - h2 = RHASH_H_TBL(hash2); + h2 = RHASH_TBL(hash2); if (h2) { for (k = kh_begin(h2); k != kh_end(h2); k++) { if (kh_exist(h2, k)) @@ -820,11 +812,13 @@ mrb_hash_replace(mrb_state *mrb, mrb_value hash) if (MRB_RHASH_PROCDEFAULT_P(hash2)) { RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT; - RHASH_PROCDEFAULT(hash) = RHASH_PROCDEFAULT(hash2); + ifnone = RHASH_PROCDEFAULT(hash2); } else { - RHASH_IFNONE(hash) = RHASH_IFNONE(hash2); + ifnone = RHASH_IFNONE(hash2); } + mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone); + return hash; } @@ -845,7 +839,7 @@ mrb_hash_replace(mrb_state *mrb, mrb_value hash) static mrb_value mrb_hash_size_m(mrb_state *mrb, mrb_value self) { - khash_t(ht) *h = RHASH_H_TBL(self); + khash_t(ht) *h = RHASH_TBL(self); if (!h) return mrb_fixnum_value(0); return mrb_fixnum_value(kh_size(h)); @@ -864,7 +858,7 @@ mrb_hash_size_m(mrb_state *mrb, mrb_value self) static mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self) { - khash_t(ht) *h = RHASH_H_TBL(self); + khash_t(ht) *h = RHASH_TBL(self); khiter_t k; if (h) { for (k = kh_begin(h); k != kh_end(h); k++) @@ -941,12 +935,12 @@ static mrb_value inspect_hash(mrb_state *mrb, mrb_value hash, int recur) { mrb_value str, str2; - khash_t(ht) *h = RHASH_H_TBL(hash); + khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; - if (recur) return mrb_str_new2(mrb, "{...}"); + if (recur) return mrb_str_new_cstr(mrb, "{...}"); - str = mrb_str_new2(mrb, "{"); + str = mrb_str_new_cstr(mrb, "{"); if (h && kh_size(h) > 0) { for (k = kh_begin(h); k != kh_end(h); k++) { int ai; @@ -987,7 +981,7 @@ static mrb_value mrb_hash_inspect(mrb_state *mrb, mrb_value hash) { if (RHASH_EMPTY_P(hash)) - return mrb_str_new2(mrb, "{}"); + return mrb_str_new_cstr(mrb, "{}"); return inspect_hash(mrb, hash, 0); } @@ -1021,7 +1015,7 @@ mrb_hash_to_hash(mrb_state *mrb, mrb_value hash) static mrb_value mrb_hash_keys(mrb_state *mrb, mrb_value hash) { - khash_t(ht) *h = RHASH_H_TBL(hash); + khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; mrb_value ary = mrb_ary_new(mrb); @@ -1053,7 +1047,7 @@ mrb_hash_keys(mrb_state *mrb, mrb_value hash) static mrb_value mrb_hash_values(mrb_state *mrb, mrb_value hash) { - khash_t(ht) *h = RHASH_H_TBL(hash); + khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; mrb_value ary = mrb_ary_new(mrb); @@ -1072,7 +1066,7 @@ mrb_hash_values(mrb_state *mrb, mrb_value hash) static mrb_value mrb_hash_has_keyWithKey(mrb_state *mrb, mrb_value hash, mrb_value key) { - khash_t(ht) *h = RHASH_H_TBL(hash); + khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; if (h) { @@ -1115,7 +1109,7 @@ mrb_hash_has_key(mrb_state *mrb, mrb_value hash) static mrb_value mrb_hash_has_valueWithvalue(mrb_state *mrb, mrb_value hash, mrb_value value) { - khash_t(ht) *h = RHASH_H_TBL(hash); + khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; if (h) { @@ -1158,8 +1152,8 @@ mrb_hash_has_value(mrb_state *mrb, mrb_value hash) static mrb_value recursive_eql(mrb_state *mrb, mrb_value hash, mrb_value dt, int recur) { - khash_t(ht) *h1 = RHASH_H_TBL(hash); - khash_t(ht) *h2 = RHASH_H_TBL(dt); + khash_t(ht) *h1 = RHASH_TBL(hash); + khash_t(ht) *h2 = RHASH_TBL(dt); khiter_t k1, k2; mrb_value key1; @@ -1388,7 +1382,6 @@ mrb_init_hash(mrb_state *mrb) h = mrb->hash_class = mrb_define_class(mrb, "Hash", mrb->object_class); MRB_SET_INSTANCE_TT(h, MRB_TT_HASH); - //mrb_define_class_method(mrb, h, "new", hash_s_new, ARGS_ANY()); mrb_include_module(mrb, h, mrb_class_get(mrb, "Enumerable")); mrb_define_method(mrb, h, "==", mrb_hash_equal, ARGS_REQ(1)); /* 15.2.13.4.1 */ mrb_define_method(mrb, h, "[]", mrb_hash_aget, ARGS_REQ(1)); /* 15.2.13.4.2 */ @@ -1397,6 +1390,7 @@ mrb_init_hash(mrb_state *mrb) mrb_define_method(mrb, h, "default", mrb_hash_default, ARGS_ANY()); /* 15.2.13.4.5 */ mrb_define_method(mrb, h, "default=", mrb_hash_set_default, ARGS_REQ(1)); /* 15.2.13.4.6 */ mrb_define_method(mrb, h, "default_proc", mrb_hash_default_proc,ARGS_NONE()); /* 15.2.13.4.7 */ + mrb_define_method(mrb, h, "default_proc=", mrb_hash_set_default_proc,ARGS_REQ(1)); /* 15.2.13.4.7 */ mrb_define_method(mrb, h, "__delete", mrb_hash_delete, ARGS_REQ(1)); /* core of 15.2.13.4.8 */ //mrb_define_method(mrb, h, "each", mrb_hash_each_pair, ARGS_NONE()); /* 15.2.13.4.9 */ /* move to mrblib\hash.rb */ //mrb_define_method(mrb, h, "each_key", mrb_hash_each_key, ARGS_NONE()); /* 15.2.13.4.10 */ /* move to mrblib\hash.rb */ diff --git a/src/init.c b/src/init.c index 9dbdc44d1..347c6919f 100644 --- a/src/init.c +++ b/src/init.c @@ -98,6 +98,7 @@ mrb_init_core(mrb_state *mrb) #endif mrb_init_exception(mrb); mrb_init_print(mrb); + mrb_init_time(mrb); #ifdef MANDEL mrb_define_method(mrb, mrb->kernel_module, "pow", mpow, ARGS_REQ(2)); diff --git a/src/kernel.c b/src/kernel.c index 8d7b38880..76ef9fa69 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -638,6 +638,13 @@ mrb_obj_instance_eval(mrb_state *mrb, mrb_value self) return mrb_yield_with_self(mrb, b, 0, 0, self); } +int +mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c) +{ + if (mrb_obj_class(mrb, obj) == c) return TRUE; + return FALSE; +} + /* 15.3.1.3.19 */ /* * call-seq: @@ -646,8 +653,8 @@ mrb_obj_instance_eval(mrb_state *mrb, mrb_value self) * Returns <code>true</code> if <i>obj</i> is an instance of the given * class. See also <code>Object#kind_of?</code>. */ -mrb_value -rb_obj_is_instance_of(mrb_state *mrb, mrb_value self) +static mrb_value +obj_is_instance_of(mrb_state *mrb, mrb_value self) { mrb_value arg; @@ -1417,7 +1424,7 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "initialize_copy", mrb_obj_init_copy, ARGS_REQ(1)); /* 15.3.1.3.16 */ mrb_define_method(mrb, krn, "inspect", mrb_obj_inspect, ARGS_NONE()); /* 15.3.1.3.17 */ mrb_define_method(mrb, krn, "instance_eval", mrb_obj_instance_eval, ARGS_ANY()); /* 15.3.1.3.18 */ - mrb_define_method(mrb, krn, "instance_of?", rb_obj_is_instance_of, ARGS_REQ(1)); /* 15.3.1.3.19 */ + mrb_define_method(mrb, krn, "instance_of?", obj_is_instance_of, ARGS_REQ(1)); /* 15.3.1.3.19 */ mrb_define_method(mrb, krn, "instance_variable_defined?", mrb_obj_ivar_defined, ARGS_REQ(1)); /* 15.3.1.3.20 */ mrb_define_method(mrb, krn, "instance_variable_get", mrb_obj_ivar_get, ARGS_REQ(1)); /* 15.3.1.3.21 */ mrb_define_method(mrb, krn, "instance_variable_set", mrb_obj_ivar_set, ARGS_REQ(2)); /* 15.3.1.3.22 */ diff --git a/src/object.c b/src/object.c index 6c0e944a8..4e479a119 100644 --- a/src/object.c +++ b/src/object.c @@ -310,7 +310,7 @@ mrb_init_object(mrb_state *mrb) mrb_define_method(mrb, f, "|", false_or, ARGS_REQ(1)); /* 15.2.6.3.4 */ } -mrb_value +static mrb_value convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *method, int raise) { mrb_sym m = 0; diff --git a/src/range.c b/src/range.c index 020ae7ec0..f298d336e 100644 --- a/src/range.c +++ b/src/range.c @@ -31,23 +31,6 @@ mrb_value mrb_exec_recursive_paired(mrb_state *mrb, mrb_value (*func) (mrb_state mrb_value obj, mrb_value paired_obj, void* arg); int printf (const char*, ...); -/*--------- <1.8.7>object.c ---------> */ - -/* - * call-seq: - * obj.instance_of?(class) => true or false - * - * Returns <code>true</code> if <i>obj</i> is an instance of the given - * class. See also <code>Object#kind_of?</code>. - */ - -int -mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c) -{ - if (mrb_obj_class(mrb, obj) == c) return TRUE; - return FALSE; -} -/*--------- <1.8.7>object.c ---------< */ mrb_value mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, int excl) diff --git a/src/time.c b/src/time.c new file mode 100644 index 000000000..a71d83058 --- /dev/null +++ b/src/time.c @@ -0,0 +1,600 @@ +/* +** time.c - Time class +** +** See Copyright Notice in mruby.h +*/ + + +#include "mruby.h" +#include <string.h> +#include <stdio.h> +#include <time.h> +#include "mruby/class.h" +#include "mruby/data.h" + +/* Time class configuration */ +#undef USE_GETTIMEOFDAY /* C99 does not have gettimeofday */ +#define USE_GETTIMEOFDAY /* need gettimeofday to retrieve microseconds */ +#undef USE_GMTIME_R /* C99 does not have reentrant gmtime_r */ +#define USE_GMTIME_R /* use reentrant gmtime_r */ + +#ifdef USE_GETTIMEOFDAY +#include <sys/time.h> +#endif +#ifndef USE_GMTIME_R +#define gmtime_r(t,r) gmtime(t) +#define localtime_r(t,r) localtime(t) +#endif + +/* Since we are limited to using ISO C89, this implementation is based +* on time_t. That means the resolution of time is only precise to the +* second level. Also, there are only 2 timezones, namely UTC and LOCAL. +*/ + +#ifndef mrb_bool_value +#define mrb_bool_value(val) ((val) ? mrb_true_value() : mrb_false_value()) +#endif + + +enum mrb_timezone { + MRB_TIMEZONE_NONE = 0, + MRB_TIMEZONE_UTC = 1, + MRB_TIMEZONE_LOCAL = 2, + MRB_TIMEZONE_LAST = 3 +}; + +static const char *timezone_names[] = { + "none", + "UTC", + "LOCAL", + NULL +}; + +static const char *mon_names[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", +}; + +static const char *wday_names[] = { + "Sun", "Mon", "Tus", "Wed", "Thu", "Fri", "Sat", +}; + +struct mrb_time { + time_t sec; + time_t usec; + enum mrb_timezone timezone; + struct tm datetime; +}; + +static void +mrb_time_free(mrb_state *mrb, void *ptr) +{ + mrb_free(mrb, ptr); +} + +static struct mrb_data_type mrb_time_type = { "Time", mrb_time_free }; + +/** Updates the datetime of a mrb_time based on it's timezone and +seconds setting. Returns self on cussess, NULL of failure. */ +struct mrb_time* +mrb_time_update_datetime(struct mrb_time *self) +{ + struct tm *aid; + + if(self->timezone == MRB_TIMEZONE_UTC) { + aid = gmtime_r(&self->sec, &self->datetime); + } + else { + aid = localtime_r(&self->sec, &self->datetime); + } + if(!aid) return NULL; +#ifndef USE_GMTIME_R + self->datetime = *aid; // copy data +#endif + + return self; +} + +static mrb_value +mrb_time_wrap(mrb_state *mrb, struct RClass *tc, struct mrb_time *tm) +{ + return mrb_obj_value(Data_Wrap_Struct(mrb, tc, &mrb_time_type, tm)); +} + + +/* Allocates a mrb_time object and initializes it. */ +static struct mrb_time* +mrb_time_alloc(mrb_state *mrb, mrb_float seconds, enum mrb_timezone timezone) +{ + struct mrb_time *tm; + + tm = mrb_malloc(mrb, sizeof(struct mrb_time)); + tm->sec = (time_t)seconds; + tm->usec = (seconds - tm->sec) * 1.0e6; + tm->timezone = timezone; + mrb_time_update_datetime(tm); + + return tm; +} + +static mrb_value +mrb_time_make(mrb_state *mrb, struct RClass *c, mrb_float seconds, enum mrb_timezone timezone) +{ + return mrb_time_wrap(mrb, c, mrb_time_alloc(mrb, seconds, timezone)); +} + +/* Allocates a new Time object with given millis value. */ +static mrb_value +mrb_time_now(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + + tm = mrb_malloc(mrb, sizeof(*tm)); +#ifdef USE_GETTIMEOFDAY + { + struct timeval tv; + + gettimeofday(&tv, NULL); + tm->sec = tv.tv_sec; + tm->usec = tv.tv_usec; + } +#else + tm->sec = time(NULL); + tm->usec = 0; +#endif + tm->timezone = MRB_TIMEZONE_LOCAL; + mrb_time_update_datetime(tm); + return mrb_time_wrap(mrb, mrb_class_ptr(self), tm); +} + +/* 15.2.19.6.1 */ +/* Creates an instance of time at the given time in seconds, etc. */ +static mrb_value +mrb_time_at(mrb_state *mrb, mrb_value self) +{ + mrb_float f; + + mrb_get_args(mrb, "f", &f); + return mrb_time_make(mrb, mrb_class_ptr(self), f, MRB_TIMEZONE_LOCAL); +} + +static struct mrb_time* +time_mktime(mrb_state *mrb, int ayear, int amonth, int aday, + int ahour, int amin, int asec, int ausec, + enum mrb_timezone timezone) +{ + time_t nowsecs; + struct tm nowtime; + + nowtime.tm_year = (int)ayear - 1900; + nowtime.tm_mon = (int)amonth - 1; + nowtime.tm_mday = (int)aday; + nowtime.tm_hour = (int)ahour; + nowtime.tm_min = (int)amin; + nowtime.tm_sec = (int)asec; + nowtime.tm_isdst = -1; + nowsecs = mktime(&nowtime); + if (nowsecs < 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "Not a valid time."); + } + + return mrb_time_alloc(mrb, nowsecs+ausec/10e6, timezone); +} + +/* 15.2.19.6.2 */ +/* Creates an instance of time at the given time in UTC. */ +static mrb_value +mrb_time_gm(mrb_state *mrb, mrb_value self) +{ + mrb_float ayear = 0.0, amonth = 1.0, aday = 1.0, ahour = 0.0, + amin = 0.0, asec = 0.0, ausec = 0.0; + + mrb_get_args(mrb, "fffffff", + &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec); + return mrb_time_wrap(mrb, mrb_class_ptr(self), + time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_UTC)); +} + + +/* 15.2.19.6.3 */ +/* Creates an instance of time at the given time in local time zone. */ +static mrb_value +mrb_time_local(mrb_state *mrb, mrb_value self) +{ + mrb_float ayear = 0.0, amonth = 1.0, aday = 1.0, ahour = 0.0, + amin = 0.0, asec = 0.0, ausec = 0.0; + + mrb_get_args(mrb, "fffffff", + &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec); + return mrb_time_wrap(mrb, mrb_class_ptr(self), + time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL)); +} + + +static mrb_value +mrb_time_eq(mrb_state *mrb, mrb_value self) +{ + mrb_value other; + struct mrb_time *tm1, *tm2; + + mrb_get_args(mrb, "o", &other); + tm1 = mrb_get_datatype(mrb, self, &mrb_time_type); + tm2 = mrb_get_datatype(mrb, other, &mrb_time_type); + if (!tm1 || !tm2) return mrb_false_value(); + if (tm1->sec == tm2->sec && tm1->usec == tm2->usec) { + return mrb_true_value(); + } + return mrb_false_value(); +} + +static mrb_value +mrb_time_cmp(mrb_state *mrb, mrb_value self) +{ + mrb_value other; + struct mrb_time *tm1, *tm2; + + mrb_get_args(mrb, "o", &other); + tm1 = mrb_get_datatype(mrb, self, &mrb_time_type); + tm2 = mrb_get_datatype(mrb, other, &mrb_time_type); + if (!tm1 || !tm2) return mrb_nil_value(); + if (tm1->sec > tm2->sec) { + return mrb_fixnum_value(1); + } + else if (tm1->sec < tm2->sec) { + return mrb_fixnum_value(-1); + } + /* tm1->sec == tm2->sec */ + if (tm1->usec > tm2->usec) { + return mrb_fixnum_value(1); + } + else if (tm1->usec < tm2->usec) { + return mrb_fixnum_value(-1); + } + return mrb_fixnum_value(0); +} + +static mrb_value +mrb_time_plus(mrb_state *mrb, mrb_value self) +{ + mrb_float f; + struct mrb_time *tm; + + mrb_get_args(mrb, "f", &f); + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + f += tm->sec; + f += (mrb_float)tm->usec / 1.0e6; + return mrb_time_make(mrb, mrb_obj_class(mrb, self), f, tm->timezone); +} + +static mrb_value +mrb_time_minus(mrb_state *mrb, mrb_value self) +{ + mrb_float f; + struct mrb_time *tm; + + mrb_get_args(mrb, "f", &f); + + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + f -= tm->sec; + f -= (mrb_float)tm->usec / 1.0e6; + return mrb_time_make(mrb, mrb_obj_class(mrb, self), f, tm->timezone); +} + +/* 15.2.19.7.30 */ +/* Returns week day number of time. */ +static mrb_value +mrb_time_wday(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + return mrb_fixnum_value(tm->datetime.tm_wday); +} + +/* 15.2.19.7.31 */ +/* Returns year day number of time. */ +static mrb_value +mrb_time_yday(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + + tm = mrb_check_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + return mrb_fixnum_value(tm->datetime.tm_yday); +} + +/* 15.2.19.7.32 */ +/* Returns year of time. */ +static mrb_value +mrb_time_year(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + return mrb_fixnum_value(tm->datetime.tm_year + 1900); +} + +/* 15.2.19.7.33 */ +/* Returns name of time's timezone. */ +static mrb_value +mrb_time_zone(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + if(tm->timezone <= MRB_TIMEZONE_NONE) return mrb_nil_value(); + if(tm->timezone >= MRB_TIMEZONE_LAST) return mrb_nil_value(); + return mrb_str_new_cstr(mrb, timezone_names[tm->timezone]); +} + +/* 15.2.19.7.4 */ +/* Returns a string that describes the time. */ +static mrb_value +mrb_time_asctime(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + struct tm *d; + char buf[256]; + + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + d = &tm->datetime; + snprintf(buf, 256, "%s %s %02d %02d:%02d:%02d %s%d", + wday_names[d->tm_wday], mon_names[d->tm_mon], d->tm_mday, + d->tm_hour, d->tm_min, d->tm_sec, + tm->timezone == MRB_TIMEZONE_UTC ? "UTC " : "", + d->tm_year + 1900); + return mrb_str_new_cstr(mrb, buf); +} + +/* 15.2.19.7.6 */ +/* Returns the day in the month of the time. */ +static mrb_value +mrb_time_day(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + return mrb_fixnum_value(tm->datetime.tm_mday); +} + + +/* 15.2.19.7.7 */ +/* Returns true if daylight saving was applied for this time. */ +static mrb_value +mrb_time_dstp(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + return mrb_bool_value(tm->datetime.tm_isdst); +} + +/* 15.2.19.7.15 */ +/* Returns hour of time. */ +static mrb_value +mrb_time_hour(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + return mrb_fixnum_value(tm->datetime.tm_hour); +} + +/* 15.2.19.7.16 */ +/* Initializes a time by setting the amount of milliseconds since the epoch.*/ +static mrb_value +mrb_time_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_float ayear = 0.0, amonth = 1.0, aday = 1.0, ahour = 0.0, + amin = 0.0, asec = 0.0, ausec = 0.0; + struct mrb_time *tm; + + printf("init\n"); + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if (tm) { + mrb_time_free(mrb, tm); + } + mrb_get_args(mrb, "fffffff", + &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec); + DATA_PTR(self) = time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL); + DATA_TYPE(self) = &mrb_time_type; + return self; +} + +/* 15.2.19.7.17(x) */ +/* Initializes a copy of this time object. */ +static mrb_value +mrb_time_initialize_copy(mrb_state *mrb, mrb_value copy) +{ + mrb_value src; + mrb_get_args(mrb, "o", &src); + + if (mrb_obj_equal(mrb, copy, src)) return copy; + if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) { + mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class"); + } + memcpy(DATA_PTR(copy), DATA_PTR(src), sizeof(struct mrb_time)); + return copy; +} + +/* 15.2.19.7.18 */ +/* Sets the timezone attribute of the Time object to LOCAL. */ +static mrb_value +mrb_time_localtime(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return self; + tm->timezone = MRB_TIMEZONE_LOCAL; + mrb_time_update_datetime(tm); + return self; +} + +/* 15.2.19.7.19 */ +/* Returns day of month of time. */ +static mrb_value +mrb_time_mday(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + return mrb_fixnum_value(tm->datetime.tm_mday); +} + +/* 15.2.19.7.20 */ +/* Returns minutes of time. */ +static mrb_value +mrb_time_min(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + return mrb_fixnum_value(tm->datetime.tm_min); +} + +/* 15.2.19.7.21 and 15.2.19.7.22 */ +/* Returns month of time. */ +static mrb_value +mrb_time_mon(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + return mrb_fixnum_value(tm->datetime.tm_mon + 1); +} + +/* 15.2.19.7.23 */ +/* Returns seconds in minute of time. */ +static mrb_value +mrb_time_sec(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + return mrb_fixnum_value(tm->datetime.tm_sec); +} + + +/* 15.2.19.7.24 */ +/* Returns a Float with the time since the epoch in seconds. */ +static mrb_value +mrb_time_to_f(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + return mrb_float_value((mrb_float)tm->sec + (mrb_float)tm->usec/1.0e6); +} + +/* 15.2.19.7.25 */ +/* Returns a Fixnum with the time since the epoch in seconds. */ +static mrb_value +mrb_time_to_i(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + return mrb_fixnum_value(tm->sec); +} + +/* 15.2.19.7.26 */ +/* Returns a Float with the time since the epoch in microseconds. */ +static mrb_value +mrb_time_usec(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + return mrb_fixnum_value(tm->usec); +} + +/* 15.2.19.7.27 */ +/* Sets the timzeone attribute of the Time object to UTC. */ +static mrb_value +mrb_time_utc(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(tm) { + tm->timezone = MRB_TIMEZONE_UTC; + mrb_time_update_datetime(tm); + } + return self; +} + +/* 15.2.19.7.28 */ +/* Returns true if this time is in the UTC timze zone false if not. */ +static mrb_value +mrb_time_utcp(mrb_state *mrb, mrb_value self) +{ + struct mrb_time *tm; + tm = mrb_get_datatype(mrb, self, &mrb_time_type); + if(!tm) return mrb_nil_value(); + return mrb_bool_value(tm->timezone == MRB_TIMEZONE_UTC); +} + + + +void +mrb_init_time(mrb_state *mrb) +{ + struct RClass *tc; + /* ISO 15.2.19.2 */ + tc = mrb_define_class(mrb, "Time", mrb->object_class); + MRB_SET_INSTANCE_TT(tc, MRB_TT_DATA); + mrb_include_module(mrb, tc, mrb_class_get(mrb, "Comparable")); + mrb_define_class_method(mrb, tc, "now", mrb_time_now, ARGS_NONE()); + mrb_define_class_method(mrb, tc, "at", mrb_time_at, ARGS_ANY()); + mrb_define_class_method(mrb, tc, "gm", mrb_time_gm, ARGS_REQ(1)|ARGS_OPT(6)); + mrb_define_class_method(mrb, tc, "local", mrb_time_local, ARGS_REQ(1)|ARGS_OPT(6)); + + mrb_define_method(mrb, tc, "==" , mrb_time_eq , ARGS_REQ(1)); + mrb_define_method(mrb, tc, "<=>" , mrb_time_cmp , ARGS_REQ(1)); + mrb_define_method(mrb, tc, "+" , mrb_time_plus , ARGS_REQ(1)); + mrb_define_method(mrb, tc, "-" , mrb_time_minus , ARGS_REQ(1)); + mrb_define_method(mrb, tc, "to_s" , mrb_time_asctime, ARGS_NONE()); + mrb_define_method(mrb, tc, "asctime", mrb_time_asctime, ARGS_NONE()); + mrb_define_method(mrb, tc, "ctime" , mrb_time_asctime, ARGS_NONE()); + mrb_define_method(mrb, tc, "day" , mrb_time_day , ARGS_NONE()); + mrb_define_method(mrb, tc, "dst?" , mrb_time_dstp , ARGS_NONE()); + mrb_define_method(mrb, tc, "gmt?" , mrb_time_utcp , ARGS_NONE()); + mrb_define_method(mrb, tc, "gmtime" , mrb_time_utc , ARGS_NONE()); + mrb_define_method(mrb, tc, "hour" , mrb_time_hour, ARGS_NONE()); + mrb_define_method(mrb, tc, "localtime", mrb_time_localtime, ARGS_NONE()); + mrb_define_method(mrb, tc, "mday" , mrb_time_mday, ARGS_NONE()); + mrb_define_method(mrb, tc, "min" , mrb_time_min, ARGS_NONE()); + + mrb_define_method(mrb, tc, "mon" , mrb_time_mon, ARGS_NONE()); + mrb_define_method(mrb, tc, "month", mrb_time_mon, ARGS_NONE()); + + mrb_define_method(mrb, tc, "sec" , mrb_time_sec, ARGS_NONE()); + mrb_define_method(mrb, tc, "to_i", mrb_time_to_i, ARGS_NONE()); + mrb_define_method(mrb, tc, "to_f", mrb_time_to_f, ARGS_NONE()); + mrb_define_method(mrb, tc, "usec", mrb_time_usec, ARGS_NONE()); + mrb_define_method(mrb, tc, "utc" , mrb_time_utc, ARGS_NONE()); + mrb_define_method(mrb, tc, "utc?", mrb_time_utcp, ARGS_NONE()); + mrb_define_method(mrb, tc, "wday", mrb_time_wday, ARGS_NONE()); + mrb_define_method(mrb, tc, "yday", mrb_time_yday, ARGS_NONE()); + mrb_define_method(mrb, tc, "year", mrb_time_year, ARGS_NONE()); + mrb_define_method(mrb, tc, "zone", mrb_time_zone, ARGS_NONE()); + + mrb_define_method(mrb, tc, "initialize", mrb_time_initialize, ARGS_REQ(1)); + mrb_define_method(mrb, tc, "initialize_copy", mrb_time_initialize_copy, ARGS_REQ(1)); +} @@ -261,7 +261,7 @@ mrb_yield(mrb_state *mrb, mrb_value b, mrb_value v) return mrb_yield_with_self(mrb, b, 1, &v, mrb->stack[0]); } -void +static void localjump_error(mrb_state *mrb, const char *kind) { char buf[256]; @@ -272,6 +272,25 @@ localjump_error(mrb_state *mrb, const char *kind) mrb->exc = mrb_object(exc); } +static void +argnum_error(mrb_state *mrb, int num) +{ + char buf[256]; + mrb_value exc; + + if (mrb->ci->mid) { + snprintf(buf, 256, "'%s': wrong number of arguments (%d for %d)", + mrb_sym2name(mrb, mrb->ci->mid), + mrb->ci->argc, num); + } + else { + snprintf(buf, 256, "wrong number of arguments (%d for %d)", + mrb->ci->argc, num); + } + exc = mrb_exc_new(mrb, E_ARGUMENT_ERROR, buf, strlen(buf)); + mrb->exc = mrb_object(exc); +} + #define SET_TRUE_VALUE(r) {\ (r).tt = MRB_TT_TRUE;\ (r).value.i = 1;\ @@ -717,7 +736,9 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) ci->target_class = m->target_class; ci->proc = m; if (m->env) { - ci->mid = m->env->mid; + if (m->env->mid) { + ci->mid = m->env->mid; + } if (!m->env->stack) { m->env->stack = mrb->stack; } @@ -895,10 +916,8 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) if (mrb->ci->proc && MRB_PROC_STRICT_P(mrb->ci->proc)) { if (argc >= 0) { if (argc < m1 + m2 || (r == 0 && argc > len)) { - fprintf(stderr, "'%s': wrong number of arguments (%d for %d)\n", - mrb_sym2name(mrb, mrb->ci->mid), - mrb->ci->argc, m1+m2); - exit(1); + argnum_error(mrb, m1+m2); + goto L_RAISE; } } } |
