diff options
| author | Paolo Bosetti <[email protected]> | 2012-08-13 16:26:15 +0200 |
|---|---|---|
| committer | Paolo Bosetti <[email protected]> | 2012-08-13 16:26:15 +0200 |
| commit | 4c56ce2744f4c8640de1b299c4ff4bd749a93345 (patch) | |
| tree | 1286395880c71cd30e0938b020cd154c3317357c /src | |
| parent | 05127776cf0c528b549d723ba2e325332e49ced9 (diff) | |
| parent | cda1709a35ad7d495ec1a08793cd88b78e20c444 (diff) | |
| download | mruby-4c56ce2744f4c8640de1b299c4ff4bd749a93345.tar.gz mruby-4c56ce2744f4c8640de1b299c4ff4bd749a93345.zip | |
Merge branch 'master' into XCode
Diffstat (limited to 'src')
| -rw-r--r-- | src/class.c | 85 | ||||
| -rw-r--r-- | src/codegen.c | 22 | ||||
| -rw-r--r-- | src/error.c | 1 | ||||
| -rw-r--r-- | src/gc.c | 49 | ||||
| -rw-r--r-- | src/kernel.c | 104 | ||||
| -rw-r--r-- | src/object.c | 6 | ||||
| -rw-r--r-- | src/pool.c | 8 | ||||
| -rw-r--r-- | src/state.c | 2 | ||||
| -rw-r--r-- | src/string.c | 2 | ||||
| -rw-r--r-- | src/struct.c | 49 | ||||
| -rw-r--r-- | src/symbol.c | 3 | ||||
| -rw-r--r-- | src/variable.c | 716 | ||||
| -rw-r--r-- | src/vm.c | 68 |
13 files changed, 760 insertions, 355 deletions
diff --git a/src/class.c b/src/class.c index 7802c34bd..795527263 100644 --- a/src/class.c +++ b/src/class.c @@ -15,7 +15,6 @@ #include "mruby/array.h" #include "error.h" -KHASH_DEFINE(iv, mrb_sym, mrb_value, 1, kh_int_hash_func, kh_int_hash_equal); KHASH_DEFINE(mt, mrb_sym, struct RProc*, 1, kh_int_hash_func, kh_int_hash_equal); typedef struct fc_result { @@ -65,30 +64,6 @@ mrb_name_class(mrb_state *mrb, struct RClass *c, mrb_sym name) mrb_intern(mrb, "__classid__"), mrb_symbol_value(name)); } -static mrb_sym -class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer) -{ - mrb_value name; - - name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classid__")); - if (mrb_nil_p(name)) { - khash_t(iv)* h; - khiter_t k; - mrb_value v; - - if (!outer) outer = mrb->object_class; - h = outer->iv; - for (k = kh_begin(h); k != kh_end(h); k++) { - if (!kh_exist(h,k)) continue; - v = kh_value(h,k); - if (mrb_type(v) == c->tt && mrb_class_ptr(v) == c) { - return kh_key(h,k); - } - } - } - return SYM2ID(name); -} - static void make_metaclass(mrb_state *mrb, struct RClass *c) { @@ -880,48 +855,10 @@ mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid) return m; } -#ifndef MRB_FUNCALL_ARGC_MAX -#define MRB_FUNCALL_ARGC_MAX 16 -#endif - -mrb_value -mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...) -{ - mrb_sym mid = mrb_intern(mrb, name); - va_list ap; - int i; - - if (argc == 0) { - return mrb_funcall_argv(mrb, self, mid, 0, 0); - } - else if (argc == 1) { - mrb_value v; - - va_start(ap, argc); - v = va_arg(ap, mrb_value); - va_end(ap); - return mrb_funcall_argv(mrb, self, mid, 1, &v); - } - else { - mrb_value argv[MRB_FUNCALL_ARGC_MAX]; - - if (argc > MRB_FUNCALL_ARGC_MAX) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%d)", MRB_FUNCALL_ARGC_MAX); - } - - va_start(ap, argc); - for (i = 0; i < argc; i++) { - argv[i] = va_arg(ap, mrb_value); - } - va_end(ap); - return mrb_funcall_argv(mrb, self, mid, argc, argv); - } -} - void mrb_obj_call_init(mrb_state *mrb, mrb_value obj, int argc, mrb_value *argv) { - mrb_funcall_argv(mrb, obj, mrb_intern(mrb, "initialize"), argc, argv); + mrb_funcall_argv(mrb, obj, mrb->init_sym, argc, argv); } /* @@ -960,7 +897,7 @@ mrb_class_new_instance_m(mrb_state *mrb, mrb_value klass) c = (struct RClass*)mrb_obj_alloc(mrb, k->tt, k); c->super = k; obj = mrb_obj_value(c); - mrb_funcall_with_block(mrb, obj, mrb_intern(mrb, "initialize"), argc, argv, blk); + mrb_funcall_with_block(mrb, obj, mrb->init_sym, argc, argv, blk); return obj; } @@ -979,7 +916,7 @@ mrb_instance_new(mrb_state *mrb, mrb_value cv) o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c); obj = mrb_obj_value(o); mrb_get_args(mrb, "*&", &argv, &argc, &blk); - mrb_funcall_with_block(mrb, obj, mrb_intern(mrb, "initialize"), argc, argv, blk); + mrb_funcall_with_block(mrb, obj, mrb->init_sym, argc, argv, blk); return obj; } @@ -1086,16 +1023,16 @@ mrb_obj_respond_to(struct RClass* c, mrb_sym mid) k = kh_get(mt, h, mid); if (k != kh_end(h)) { if (kh_value(h, k)) { - return 1; /* exist method */ + return TRUE; /* method exists */ } else { - return 0; + return FALSE; /* undefined method */ } } } c = c->super; } - return 0; /* no method */ + return FALSE; /* no method */ } int @@ -1114,16 +1051,16 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) path = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__")); if (mrb_nil_p(path)) { struct RClass *outer = mrb_class_outer_module(mrb, c); - mrb_sym sym = class_sym(mrb, c, outer); - if (outer && outer != mrb->object_class) { + mrb_sym sym = mrb_class_sym(mrb, c, outer); + if (sym == 0) { + return mrb_nil_value(); + } + else if (outer && outer != mrb->object_class) { mrb_value base = mrb_class_path(mrb, outer); path = mrb_str_plus(mrb, base, mrb_str_new(mrb, "::", 2)); name = mrb_sym2name_len(mrb, sym, &len); mrb_str_concat(mrb, path, mrb_str_new(mrb, name, len)); } - else if (sym == 0) { - return mrb_nil_value(); - } else { name = mrb_sym2name_len(mrb, sym, &len); path = mrb_str_new(mrb, name, len); diff --git a/src/codegen.c b/src/codegen.c index bf6fd0b3e..38d57d581 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -142,6 +142,9 @@ genop(codegen_scope *s, mrb_code i) s->pc++; } +#define NOVAL 0 +#define VAL 1 + static void genop_peep(codegen_scope *s, mrb_code i, int val) { @@ -217,6 +220,7 @@ genop_peep(codegen_scope *s, mrb_code i, int val) case OP_SETCV: case OP_SETCONST: case OP_SETMCNST: + case OP_SETGLOBAL: if (c0 == OP_MOVE) { if (GETARG_A(i) == GETARG_A(i0)) { s->iseq[s->pc-1] = MKOP_ABx(c1, GETARG_B(i0), GETARG_Bx(i)); @@ -261,6 +265,17 @@ genop_peep(codegen_scope *s, mrb_code i, int val) s->iseq[s->pc-1] = MKOP_ABC(c0, 0, GETARG_B(i0), GETARG_C(i0)); genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); return; + case OP_SETIV: + case OP_SETCV: + case OP_SETCONST: + case OP_SETMCNST: + case OP_SETUPVAR: + case OP_SETGLOBAL: + s->pc--; + genop_peep(s, i0, NOVAL); + i0 = s->iseq[s->pc-1]; + genop(s, MKOP_AB(OP_RETURN, GETARG_A(i0), OP_R_NORMAL)); + return; case OP_LOADSYM: case OP_GETGLOBAL: case OP_GETIV: @@ -436,9 +451,6 @@ lv_idx(codegen_scope *s, mrb_sym id) return 0; } -#define NOVAL 0 -#define VAL 1 - static void for_body(codegen_scope *s, node *tree) { @@ -598,10 +610,10 @@ static int nosplat(node *t) { while (t) { - if ((intptr_t)t->car->car == NODE_SPLAT) return 0; + if ((intptr_t)t->car->car == NODE_SPLAT) return FALSE; t = t->cdr; } - return 1; + return TRUE; } static mrb_sym diff --git a/src/error.c b/src/error.c index 6fe839cb2..150524f87 100644 --- a/src/error.c +++ b/src/error.c @@ -8,6 +8,7 @@ #include <stdarg.h> #include <stdio.h> #include <setjmp.h> +#include <string.h> #include "error.h" #include "mruby/variable.h" #include "mruby/string.h" @@ -796,6 +796,7 @@ mrb_incremental_gc(mrb_state *mrb) { size_t limit = 0, result = 0; + if (mrb->gc_disabled) return; GC_INVOKE_TIME_REPORT; GC_TIME_START; @@ -826,6 +827,7 @@ mrb_garbage_collect(mrb_state *mrb) { size_t max_limit = ~0; + if (mrb->gc_disabled) return; GC_INVOKE_TIME_REPORT; GC_TIME_START; @@ -918,6 +920,51 @@ gc_start(mrb_state *mrb, mrb_value obj) /* * call-seq: + * GC.enable -> true or false + * + * Enables garbage collection, returning <code>true</code> if garbage + * collection was previously disabled. + * + * GC.disable #=> false + * GC.enable #=> true + * GC.enable #=> false + * + */ + +static mrb_value +gc_enable(mrb_state *mrb, mrb_value obj) +{ + int old = mrb->gc_disabled; + + mrb->gc_disabled = FALSE; + if (old) return mrb_true_value(); + return mrb_false_value(); +} + +/* + * call-seq: + * GC.disable -> true or false + * + * Disables garbage collection, returning <code>true</code> if garbage + * collection was already disabled. + * + * GC.disable #=> false + * GC.disable #=> true + * + */ + +static mrb_value +gc_disable(mrb_state *mrb, mrb_value obj) +{ + int old = mrb->gc_disabled; + + mrb->gc_disabled = TRUE; + if (old) return mrb_true_value(); + return mrb_false_value(); +} + +/* + * call-seq: * GC.interval_ratio -> fixnum * * Returns ratio of GC interval. Default value is 200(%). @@ -989,6 +1036,8 @@ mrb_init_gc(mrb_state *mrb) gc = mrb_define_module(mrb, "GC"); mrb_define_class_method(mrb, gc, "start", gc_start, ARGS_NONE()); + mrb_define_class_method(mrb, gc, "enable", gc_enable, ARGS_NONE()); + mrb_define_class_method(mrb, gc, "disable", gc_disable, ARGS_NONE()); mrb_define_class_method(mrb, gc, "interval_ratio", gc_interval_ratio_get, ARGS_NONE()); mrb_define_class_method(mrb, gc, "interval_ratio=", gc_interval_ratio_set, ARGS_REQ(1)); mrb_define_class_method(mrb, gc, "step_ratio", gc_step_ratio_get, ARGS_NONE()); diff --git a/src/kernel.c b/src/kernel.c index 6327f967d..1334d8f9f 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -32,50 +32,13 @@ struct obj_ivar_tag { void * arg; }; -static mrb_value -inspect_obj(mrb_state *mrb, mrb_value obj, mrb_value str, int recur) -{ - if (recur) { - mrb_str_cat2(mrb, str, " ..."); - } - else { - khiter_t k; - kh_iv_t *h = RCLASS_IV_TBL(obj); - - if (h) { - for (k = kh_begin(h); k != kh_end(h); k++) { - if (kh_exist(h, k)){ - mrb_sym id = kh_key(h, k); - mrb_value value = kh_value(h, k); - - /* need not to show internal data */ - if (RSTRING_PTR(str)[0] == '-') { /* first element */ - RSTRING_PTR(str)[0] = '#'; - mrb_str_cat2(mrb, str, " "); - } - else { - mrb_str_cat2(mrb, str, ", "); - } - mrb_str_cat2(mrb, str, mrb_sym2name(mrb, id)); - mrb_str_cat2(mrb, str, "="); - mrb_str_append(mrb, str, mrb_inspect(mrb, value)); - } - } - } - } - mrb_str_cat2(mrb, str, ">"); - RSTRING_PTR(str)[0] = '#'; - - return str; -} - int mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj) { struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern(mrb, "to_s")); if (me && MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s)) - return 1; - return 0; + return TRUE; + return FALSE; } /* 15.3.1.3.17 */ @@ -96,16 +59,7 @@ mrb_value mrb_obj_inspect(mrb_state *mrb, mrb_value obj) { if ((mrb_type(obj) == MRB_TT_OBJECT) && mrb_obj_basic_to_s_p(mrb, obj)) { - long len = ROBJECT_NUMIV(obj); - - if (len > 0) { - mrb_value str; - const char *c = mrb_obj_classname(mrb, obj); - - str = mrb_sprintf(mrb, "-<%s:%p", c, (void*)&obj); - return inspect_obj(mrb, obj, str, 0); - } - return mrb_any_to_s(mrb, obj); + return mrb_obj_iv_inspect(mrb, mrb_obj_ptr(obj)); } else if (mrb_nil_p(obj)) { return mrb_str_new(mrb, "nil", 3); @@ -347,13 +301,7 @@ init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj) case MRB_TT_OBJECT: case MRB_TT_CLASS: case MRB_TT_MODULE: - if (ROBJECT(dest)->iv) { - kh_destroy(iv, ROBJECT(dest)->iv); - ROBJECT(dest)->iv = 0; - } - if (ROBJECT(obj)->iv) { - ROBJECT(dest)->iv = kh_copy(iv, mrb, ROBJECT(obj)->iv); - } + mrb_iv_copy(mrb, dest, obj); break; default: @@ -597,6 +545,18 @@ obj_is_instance_of(mrb_state *mrb, mrb_value self) } } +static void +check_iv_name(mrb_state *mrb, mrb_sym id) +{ + const char *s; + int len; + + s = mrb_sym2name_len(mrb, id, &len); + if (len < 2 && s[0] != '@') { + mrb_name_error(mrb, id, "`%s' is not allowed as an instance variable name", s); + } +} + /* 15.3.1.3.20 */ /* * call-seq: @@ -618,20 +578,12 @@ obj_is_instance_of(mrb_state *mrb, mrb_value self) mrb_value mrb_obj_ivar_defined(mrb_state *mrb, mrb_value self) { - mrb_value arg; - khiter_t k; - kh_iv_t *h = RCLASS_IV_TBL(self); mrb_sym mid; - mrb_get_args(mrb, "o", &arg); - mid = mrb_to_id(mrb, arg); - - if (h) { - k = kh_get(iv, h, mid); - if (k != kh_end(h)) { - return mrb_true_value(); - } - } + mrb_get_args(mrb, "n", &mid); + check_iv_name(mrb, mid); + if (mrb_obj_iv_defined(mrb, mrb_obj_ptr(self), mid)) + return mrb_true_value(); return mrb_false_value(); } @@ -658,15 +610,11 @@ mrb_obj_ivar_defined(mrb_state *mrb, mrb_value self) mrb_value mrb_obj_ivar_get(mrb_state *mrb, mrb_value self) { - mrb_value arg; mrb_sym id; - mrb_get_args(mrb, "o", &arg); - id = mrb_to_id(mrb, arg); + mrb_get_args(mrb, "n", &id); - //if (!mrb_is_instance_id(id)) { - // mrb_name_error(mrb, id, "`%s' is not allowed as an instance variable name", mrb_sym2name(mrb, id)); - //} + check_iv_name(mrb, id); return mrb_iv_get(mrb, self, id); } @@ -693,12 +641,11 @@ mrb_obj_ivar_get(mrb_state *mrb, mrb_value self) mrb_value mrb_obj_ivar_set(mrb_state *mrb, mrb_value self) { - mrb_value key; - mrb_value val; mrb_sym id; + mrb_value val; - mrb_get_args(mrb, "oo", &key, &val); - id = mrb_to_id(mrb, key); + mrb_get_args(mrb, "no", &id, &val); + check_iv_name(mrb, id); mrb_iv_set(mrb, self, id, val); return val; } @@ -1011,6 +958,7 @@ mrb_obj_remove_instance_variable(mrb_state *mrb, mrb_value self) mrb_value val; mrb_get_args(mrb, "n", &sym); + check_iv_name(mrb, sym); val = mrb_iv_remove(mrb, self, sym); if (mrb_undef_p(val)) { mrb_name_error(mrb, sym, "instance variable %s not defined", mrb_sym2name(mrb, sym)); diff --git a/src/object.c b/src/object.c index 26df48afd..20310d288 100644 --- a/src/object.c +++ b/src/object.c @@ -14,7 +14,7 @@ int mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2) { - if (v1.tt != v2.tt) return 0; + if (v1.tt != v2.tt) return FALSE; switch (v1.tt) { case MRB_TT_TRUE: return 1; @@ -498,10 +498,10 @@ mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, struct RClass *c) while (cl) { if (cl == c || cl->mt == c->mt) - return 1/* TRUE */; + return TRUE; cl = cl->super; } - return 0/* FALSE */; + return FALSE; } static mrb_value diff --git a/src/pool.c b/src/pool.c index daa6d0f69..71e4b477d 100644 --- a/src/pool.c +++ b/src/pool.c @@ -123,7 +123,7 @@ mrb_pool_can_realloc(mrb_pool *pool, void *p, size_t len) { struct mrb_pool_page *page; - if (!pool) return 0; + if (!pool) return FALSE; len += ALIGN_PADDING(len); page = pool->pages; while (page) { @@ -131,12 +131,12 @@ mrb_pool_can_realloc(mrb_pool *pool, void *p, size_t len) size_t beg; beg = (char*)p - page->page; - if (beg + len > page->len) return 0; - return 1; + if (beg + len > page->len) return FALSE; + return TRUE; } page = page->next; } - return 0; + return FALSE; } void* diff --git a/src/state.c b/src/state.c index 26e7dff4a..181cd00e0 100644 --- a/src/state.c +++ b/src/state.c @@ -6,6 +6,7 @@ #include "mruby.h" #include "mruby/irep.h" +#include "mruby/variable.h" #include <string.h> void mrb_init_heap(mrb_state*); @@ -54,6 +55,7 @@ mrb_close(mrb_state *mrb) int i; /* free */ + mrb_gc_free_gv(mrb); mrb_free(mrb, mrb->stbase); mrb_free(mrb, mrb->cibase); for (i=0; i<mrb->irep_len; i++) { diff --git a/src/string.c b/src/string.c index aef0ac88f..b749614dc 100644 --- a/src/string.c +++ b/src/string.c @@ -2296,7 +2296,7 @@ mrb_block_given_p() { /*if (ruby_frame->iter == ITER_CUR && ruby_block) return 1;*//*Qtrue*/ - return 0/*Qfalse*/; + return FALSE; } /* 15.2.10.5.37 */ diff --git a/src/struct.c b/src/struct.c index beb7c2f46..a5ffe6453 100644 --- a/src/struct.c +++ b/src/struct.c @@ -368,30 +368,35 @@ mrb_struct_s_def(mrb_state *mrb, mrb_value klass) name = mrb_nil_value(); rest = mrb_nil_value(); mrb_get_args(mrb, "*&", &argv, &argc, &b); - if (argc > 0) name = argv[0]; - if (argc > 1) rest = argv[1]; - if (mrb_type(rest) == MRB_TT_ARRAY) { - if (!mrb_nil_p(name) && SYMBOL_P(name)) { - /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */ - mrb_ary_unshift(mrb, rest, name); - name = mrb_nil_value(); + if (argc == 0) { /* special case to avoid crash */ + rest = mrb_ary_new(mrb); + } + else { + if (argc > 0) name = argv[0]; + if (argc > 1) rest = argv[1]; + if (mrb_type(rest) == MRB_TT_ARRAY) { + if (!mrb_nil_p(name) && SYMBOL_P(name)) { + /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */ + mrb_ary_unshift(mrb, rest, name); + name = mrb_nil_value(); + } } - } - else { - pargv = &argv[1]; - argcnt = argc-1; - if (!mrb_nil_p(name) && SYMBOL_P(name)) { - /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */ - name = mrb_nil_value(); - pargv = &argv[0]; - argcnt++; + else { + pargv = &argv[1]; + argcnt = argc-1; + if (!mrb_nil_p(name) && SYMBOL_P(name)) { + /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */ + name = mrb_nil_value(); + pargv = &argv[0]; + argcnt++; + } + rest = mrb_ary_new_from_values(mrb, argcnt, pargv); } - rest = mrb_ary_new_from_values(mrb, argcnt, pargv); - } - for (i=0; i<RARRAY_LEN(rest); i++) { - id = mrb_to_id(mrb, RARRAY_PTR(rest)[i]); - RARRAY_PTR(rest)[i] = mrb_symbol_value(id); - } + for (i=0; i<RARRAY_LEN(rest); i++) { + id = mrb_to_id(mrb, RARRAY_PTR(rest)[i]); + RARRAY_PTR(rest)[i] = mrb_symbol_value(id); + } + } st = make_struct(mrb, name, rest, struct_class(mrb)); if (!mrb_nil_p(b)) { mrb_funcall(mrb, b, "call", 1, &st); diff --git a/src/symbol.c b/src/symbol.c index b81296929..6b29ed350 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -236,7 +236,7 @@ is_special_global_name(const char* m) if (is_identchar(*m)) m += 1; break; default: - if (!ISDIGIT(*m)) return 0; + if (!ISDIGIT(*m)) return FALSE; do ++m; while (ISDIGIT(*m)); } return !*m; @@ -404,4 +404,5 @@ mrb_init_symbol(mrb_state *mrb) mrb_define_method(mrb, sym, "to_sym", sym_to_sym, ARGS_NONE()); /* 15.2.11.3.4 */ mrb_define_method(mrb, sym, "inspect", sym_inspect, ARGS_NONE()); /* 15.2.11.3.5(x) */ mrb_define_method(mrb, sym, "<=>", sym_cmp, ARGS_REQ(1)); + mrb->init_sym = mrb_intern(mrb, "initialize"); } diff --git a/src/variable.c b/src/variable.c index 8b94f5bbb..618e8cb89 100644 --- a/src/variable.c +++ b/src/variable.c @@ -6,29 +6,374 @@ #include "mruby.h" #include "mruby/class.h" -#include "mruby/khash.h" #include "mruby/variable.h" #include "error.h" #include "mruby/array.h" +#include "mruby/string.h" #include "mruby/proc.h" +#ifndef MRB_USE_IV_SEGLIST +#include "mruby/khash.h" +#endif #ifdef ENABLE_REGEXP #include "re.h" #endif +typedef int (iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*); + +#ifdef MRB_USE_IV_SEGLIST + +#ifndef MRB_SEGMENT_SIZE +#define MRB_SEGMENT_SIZE 4 +#endif + +typedef struct segment +{ + mrb_sym key[MRB_SEGMENT_SIZE]; + mrb_value val[MRB_SEGMENT_SIZE]; + struct segment *next; +} segment; + +typedef struct iv_tbl { + segment *rootseg; + int size; + int last_len; +} iv_tbl; + +static iv_tbl* +iv_new(mrb_state *mrb) +{ + iv_tbl *t; + + t = mrb_malloc(mrb, sizeof(iv_tbl)); + if (t) { + t->size = 0; + t->rootseg = NULL; + t->last_len = 0; + } + return t; +} + +static void +iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) +{ + segment *seg = t->rootseg; + segment *prev = NULL; + segment *matched_seg = NULL; + int matched_idx = 0; + int i; + + while (seg) { + for (i=0; i<MRB_SEGMENT_SIZE; i++) { + mrb_sym key = seg->key[i]; + /* found room in last segment after last_len */ + if (!seg->next && i >= t->last_len) { + seg->key[i] = sym; + seg->val[i] = val; + t->last_len = i+1; + t->size++; + return; + } + if (key == 0 && !matched_seg) { + matched_seg = seg; + matched_idx = i; + } + else if (key == sym) { + seg->val[i] = val; + return; + } + } + prev = seg; + seg = seg->next; + } + + /* not found */ + t->size++; + if (matched_seg) { + matched_seg->key[matched_idx] = sym; + matched_seg->val[matched_idx] = val; + return; + } + + seg = mrb_malloc(mrb, sizeof(segment)); + if (!seg) return; + seg->next = NULL; + seg->key[0] = sym; + seg->val[0] = val; + t->last_len = 1; + if (prev) { + prev->next = seg; + } + else { + t->rootseg = seg; + } + return; +} + +static int +iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) +{ + segment *seg; + int i; + + seg = t->rootseg; + while (seg) { + for (i=0; i<MRB_SEGMENT_SIZE; i++) { + mrb_sym key = seg->key[i]; + + if (!seg->next && i >= t->last_len) { + return FALSE; + } + if (key == sym) { + if (vp) *vp = seg->val[i]; + return TRUE; + } + } + seg = seg->next; + } + return FALSE; +} + +static int +iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) +{ + segment *seg; + int i; + + seg = t->rootseg; + while (seg) { + for (i=0; i<MRB_SEGMENT_SIZE; i++) { + mrb_sym key = seg->key[i]; + + if (!seg->next && i >= t->last_len) { + return FALSE; + } + if (key == sym) { + t->size--; + seg->key[i] = 0; + if (vp) *vp = seg->val[i]; + return TRUE; + } + } + seg = seg->next; + } + return FALSE; +} + +static int +iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p) +{ + segment *seg; + int i, n; + + seg = t->rootseg; + while (seg) { + for (i=0; i<MRB_SEGMENT_SIZE; i++) { + mrb_sym key = seg->key[i]; + + /* no value in last segment after last_len */ + if (!seg->next && i >= t->last_len) { + return FALSE; + } + if (key != 0) { + n =(*func)(mrb, key, seg->val[i], p); + if (n > 0) return FALSE; + if (n < 0) { + t->size--; + seg->key[i] = 0; + } + } + } + seg = seg->next; + } + return TRUE; +} + +static int +iv_size(mrb_state *mrb, iv_tbl *t) +{ + segment *seg; + int size = 0; + + if (!t) return 0; + if (t->size > 0) return t->size; + seg = t->rootseg; + while (seg) { + if (seg->next == NULL) { + size += t->last_len; + return size; + } + seg = seg->next; + size += MRB_SEGMENT_SIZE; + } + /* empty iv_tbl */ + return 0; +} + +static iv_tbl* +iv_copy(mrb_state *mrb, iv_tbl *t) +{ + segment *seg; + iv_tbl *t2; + + int i; + + seg = t->rootseg; + t2 = iv_new(mrb); + + while (seg != NULL) { + for (i=0; i<MRB_SEGMENT_SIZE; i++) { + mrb_sym key = seg->key[i]; + mrb_value val = seg->val[i]; + + iv_put(mrb, t2, key, val); + if ((seg->next == NULL) && (i >= t->last_len)) { + return t2; + } + } + seg = seg->next; + } + return t2; +} + +static void +iv_free(mrb_state *mrb, iv_tbl *t) +{ + segment *seg; + + seg = t->rootseg; + while (seg) { + segment *p = seg; + seg = seg->next; + mrb_free(mrb, p); + } + mrb_free(mrb, t); +} + +#else + +#include "mruby/khash.h" + #ifndef MRB_IV_INITIAL_SIZE #define MRB_IV_INITIAL_SIZE 8 #endif +KHASH_DECLARE(iv, mrb_sym, mrb_value, 1) +KHASH_DEFINE(iv, mrb_sym, mrb_value, 1, kh_int_hash_func, kh_int_hash_equal); + +typedef struct iv_tbl { + khash_t(iv) h; +} iv_tbl; + +static iv_tbl* +iv_new(mrb_state *mrb) +{ + return (iv_tbl*)kh_init_size(iv, mrb, MRB_IV_INITIAL_SIZE); +} + static void -mark_tbl(mrb_state *mrb, struct kh_iv *h) +iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) { + khash_t(iv) *h = &t->h; khiter_t k; - if (!h) return; - for (k = kh_begin(h); k != kh_end(h); k++) - if (kh_exist(h, k)) - mrb_gc_mark_value(mrb, kh_value(h, k)); + k = kh_put(iv, h, sym); + kh_value(h, k) = val; +} + +static int +iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) +{ + khash_t(iv) *h = &t->h; + khiter_t k; + + k = kh_get(iv, h, sym); + if (k != kh_end(h)) { + if (vp) *vp = kh_value(h, k); + return TRUE; + } + return FALSE; +} + +static int +iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) +{ + khash_t(iv) *h = &t->h; + khiter_t k; + + if (h) { + k = kh_get(iv, h, sym); + if (k != kh_end(h)) { + mrb_value val = kh_value(h, k); + kh_del(iv, h, k); + if (vp) *vp = val; + return TRUE; + } + } + return FALSE; +} + +static int +iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p) +{ + khash_t(iv) *h = &t->h; + khiter_t k; + int n; + + if (h) { + for (k = kh_begin(h); k != kh_end(h); k++) { + if (kh_exist(h, k)){ + n = (*func)(mrb, kh_key(h, k), kh_value(h, k), p); + if (n > 0) return FALSE; + if (n < 0) { + kh_del(iv, h, k); + } + } + } + } + return TRUE; +} + +static int +iv_size(mrb_state *mrb, iv_tbl *t) +{ + khash_t(iv) *h = &t->h; + + if (!h) return 0; + return kh_size(h); +} + +static iv_tbl* +iv_copy(mrb_state *mrb, iv_tbl *t) +{ + return (iv_tbl*)kh_copy(iv, mrb, &t->h); +} + +static void +iv_free(mrb_state *mrb, iv_tbl *t) +{ + kh_destroy(iv, &t->h); +} + +#endif + +#ifndef MRB_IV_INITIAL_SIZE +#define MRB_IV_INITIAL_SIZE 8 +#endif + +static int +iv_mark_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) +{ + mrb_gc_mark_value(mrb, v); + return 0; +} + +static void +mark_tbl(mrb_state *mrb, iv_tbl *t) +{ + if (t) { + iv_foreach(mrb, t, iv_mark_i, 0); + } } void @@ -40,7 +385,8 @@ mrb_gc_mark_gv(mrb_state *mrb) void mrb_gc_free_gv(mrb_state *mrb) { - kh_destroy(iv, mrb->globals); + if (mrb->globals) + iv_free(mrb, mrb->globals); } void @@ -52,16 +398,15 @@ mrb_gc_mark_iv(mrb_state *mrb, struct RObject *obj) size_t mrb_gc_mark_iv_size(mrb_state *mrb, struct RObject *obj) { - struct kh_iv *h = obj->iv; - - if (!h) return 0; - return kh_size(h); + return iv_size(mrb, obj->iv); } void mrb_gc_free_iv(mrb_state *mrb, struct RObject *obj) { - kh_destroy(iv, obj->iv); + if (obj->iv) { + iv_free(mrb, obj->iv); + } } mrb_value @@ -75,26 +420,6 @@ mrb_vm_special_set(mrb_state *mrb, mrb_sym i, mrb_value v) { } -static mrb_value -ivget(mrb_state *mrb, struct kh_iv *h, mrb_sym sym) -{ - khiter_t k; - - k = kh_get(iv, h, sym); - if (k != kh_end(h)) - return kh_value(h, k); - return mrb_nil_value(); -} - -mrb_value -mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym) -{ - if (!obj->iv) { - return mrb_nil_value(); - } - return ivget(mrb, obj->iv, sym); -} - static int obj_iv_p(mrb_value obj) { @@ -111,6 +436,16 @@ obj_iv_p(mrb_value obj) } mrb_value +mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym) +{ + mrb_value v; + + if (obj->iv && iv_get(mrb, obj->iv, sym, &v)) + return v; + return mrb_nil_value(); +} + +mrb_value mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym) { if (obj_iv_p(obj)) { @@ -119,54 +454,110 @@ mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym) return mrb_nil_value(); } -static void -ivset(mrb_state *mrb, struct kh_iv *h, mrb_sym sym, mrb_value v) +void +mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v) { - khiter_t k; + iv_tbl *t = obj->iv; - k = kh_put(iv, h, sym); - kh_value(h, k) = v; + if (!t) { + t = obj->iv = iv_new(mrb); + } + mrb_write_barrier(mrb, (struct RBasic*)obj); + iv_put(mrb, t, sym, v); } void -mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v) +mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v) { - khash_t(iv) *h; - - if (!obj->iv) { - h = obj->iv = kh_init_size(iv, mrb, MRB_IV_INITIAL_SIZE); + if (obj_iv_p(obj)) { + mrb_obj_iv_set(mrb, mrb_obj_ptr(obj), sym, v); } else { - h = obj->iv; + mrb_raise(mrb, E_ARGUMENT_ERROR, "cannot set instance variable"); } - mrb_write_barrier(mrb, (struct RBasic*)obj); - ivset(mrb, h, sym, v); +} + +int +mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym) +{ + iv_tbl *t; + + t = obj->iv; + if (t) { + return iv_get(mrb, t, sym, NULL); + } + return FALSE; +} + +int +mrb_iv_defined(mrb_state *mrb, mrb_value obj, mrb_sym sym) +{ + if (!obj_iv_p(obj)) return FALSE; + return mrb_obj_iv_defined(mrb, mrb_obj_ptr(obj), sym); } void -mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v) /* mrb_ivar_set */ +mrb_iv_copy(mrb_state *mrb, mrb_value dest, mrb_value src) { - if (obj_iv_p(obj)) { - mrb_obj_iv_set(mrb, mrb_obj_ptr(obj), sym, v); + struct RObject *d = mrb_obj_ptr(dest); + struct RObject *s = mrb_obj_ptr(src); + + if (d->iv) { + iv_free(mrb, d->iv); + d->iv = 0; } + if (s->iv) { + d->iv = iv_copy(mrb, s->iv); + } +} + +static int +inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) +{ + mrb_value str = *(mrb_value*)p; + const char *s; + int len; + + /* need not to show internal data */ + if (RSTRING_PTR(str)[0] == '-') { /* first element */ + RSTRING_PTR(str)[0] = '#'; + mrb_str_cat2(mrb, str, " "); + } + else { + mrb_str_cat2(mrb, str, ", "); + } + s = mrb_sym2name_len(mrb, sym, &len); + mrb_str_cat(mrb, str, s, len); + mrb_str_cat(mrb, str, "=", 1); + mrb_str_append(mrb, str, mrb_inspect(mrb, v)); + return 0; } mrb_value -mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym) +mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj) { - mrb_value val; + iv_tbl *t = obj->iv; + int len = iv_size(mrb, t); + if (len > 0) { + const char *cn = mrb_obj_classname(mrb, mrb_obj_value(obj)); + mrb_value str = mrb_sprintf(mrb, "-<%s:%p", cn, (void*)obj); + + iv_foreach(mrb, t, inspect_i, &str); + return str; + } + return mrb_any_to_s(mrb, mrb_obj_value(obj)); +} + +mrb_value +mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym) +{ if (obj_iv_p(obj)) { - khash_t(iv) *h = mrb_obj_ptr(obj)->iv; - khiter_t k; - - if (h) { - k = kh_get(iv, h, sym); - if (k != kh_end(h)) { - val = kh_value(h, k); - kh_del(iv, h, k); - return val; - } + iv_tbl *t = mrb_obj_ptr(obj)->iv; + mrb_value val; + + if (iv_del(mrb, t, sym, &val)) { + return val; } } return mrb_undef_value(); @@ -186,6 +577,21 @@ mrb_vm_iv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) mrb_iv_set(mrb, mrb->stack[0], sym, v); } +static int +iv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) +{ + mrb_value ary; + const char* s; + int len; + + ary = *(mrb_value*)p; + s = mrb_sym2name_len(mrb, sym, &len); + if (len > 1 && s[0] == '@') { + mrb_ary_push(mrb, ary, mrb_symbol_value(sym)); + } + return 0; +} + /* 15.3.1.3.23 */ /* * call-seq: @@ -207,25 +613,10 @@ mrb_value mrb_obj_instance_variables(mrb_state *mrb, mrb_value self) { mrb_value ary; - kh_iv_t *h; - khint_t i; - int len; - const char* p; ary = mrb_ary_new(mrb); - if (obj_iv_p(self)) { - h = ROBJECT_IVPTR(self); - if (h) { - for (i=0;i<kh_end(h);i++) { - if (kh_exist(h, i)) { - p = mrb_sym2name_len(mrb, kh_key(h,i), &len); - if (len > 1 && *p == '@') { - if (mrb_type(kh_value(h, i)) != MRB_TT_UNDEF) - mrb_ary_push(mrb, ary, mrb_str_new(mrb, p, len)); - } - } - } - } + if (obj_iv_p(self) && mrb_obj_ptr(self)->iv) { + iv_foreach(mrb, mrb_obj_ptr(self)->iv, iv_i, &ary); } return ary; } @@ -238,11 +629,11 @@ mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym) if (!c) c = mrb->ci->target_class; while (c) { if (c->iv) { - khash_t(iv) *h = c->iv; - khiter_t k = kh_get(iv, h, sym); + iv_tbl *t = c->iv; + mrb_value v; - if (k != kh_end(h)) - return kh_value(h, k); + if (iv_get(mrb, t, sym, &v)) + return v; } c = c->super; } @@ -253,43 +644,34 @@ void mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) { struct RClass *c = mrb->ci->proc->target_class; - khash_t(iv) *h; - khiter_t k; if (!c) c = mrb->ci->target_class; while (c) { if (c->iv) { - h = c->iv; - k = kh_get(iv, h, sym); - if (k != kh_end(h)) { - k = kh_put(iv, h, sym); - kh_value(h, k) = v; + iv_tbl *t = c->iv; + + if (iv_get(mrb, t, sym, NULL)) { + iv_put(mrb, t, sym, v); return; } } c = c->super; } c = mrb->ci->target_class; - h = c->iv; - if (!h) { - c->iv = h = kh_init_size(iv, mrb, MRB_IV_INITIAL_SIZE); + if (!c->iv) { + c->iv = iv_new(mrb); } - k = kh_put(iv, h, sym); - kh_value(h, k) = v; + iv_put(mrb, c->iv, sym, v); } int mrb_const_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym) { - khiter_t k; struct RClass *m = mrb_class_ptr(mod); - struct kh_iv *h = m->iv; + iv_tbl *t = m->iv; - if (!h) return 0; - k = kh_get(iv, h, sym); - if (k != kh_end(h)) - return 1; - return 0; + if (!t) return FALSE; + return iv_get(mrb, t, sym, NULL); } static void @@ -309,19 +691,17 @@ static mrb_value const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym) { struct RClass *c = base; - khash_t(iv) *h; - khiter_t k; + mrb_value v; + iv_tbl *t; int retry = 0; mrb_sym cm; L_RETRY: while (c) { if (c->iv) { - h = c->iv; - k = kh_get(iv, h, sym); - if (k != kh_end(h)) { - return kh_value(h, k); - } + t = c->iv; + if (iv_get(mrb, t, sym, &v)) + return v; } c = c->super; } @@ -374,13 +754,13 @@ mrb_vm_const_set(mrb_state *mrb, mrb_sym sym, mrb_value v) struct RClass *c = mrb->ci->proc->target_class; if (!c) c = mrb->ci->target_class; - mrb_obj_iv_set(mrb, (struct RObject*)c, sym, v); + mrb_iv_set(mrb, mrb_obj_value(c), sym, v); } void mrb_define_const(mrb_state *mrb, struct RClass *mod, const char *name, mrb_value v) { - mrb_obj_iv_set(mrb, (struct RObject*)mod, mrb_intern(mrb, name), v); + mrb_iv_set(mrb, mrb_obj_value(mod), mrb_intern(mrb, name), v); } void @@ -392,24 +772,38 @@ mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val) mrb_value mrb_gv_get(mrb_state *mrb, mrb_sym sym) { + mrb_value v; + if (!mrb->globals) { return mrb_nil_value(); } - return ivget(mrb, mrb->globals, sym); + if (iv_get(mrb, mrb->globals, sym, &v)) + return v; + return mrb_nil_value(); } void mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) { - khash_t(iv) *h; + iv_tbl *t; if (!mrb->globals) { - h = mrb->globals = kh_init(iv, mrb); + t = mrb->globals = iv_new(mrb); } else { - h = mrb->globals; + t = mrb->globals; } - ivset(mrb, h, sym, v); + iv_put(mrb, t, sym, v); +} + +static int +gv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) +{ + mrb_value ary; + + ary = *(mrb_value*)p; + mrb_ary_push(mrb, ary, mrb_symbol_value(sym)); + return 0; } /* 15.3.1.2.4 */ @@ -425,73 +819,34 @@ mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) mrb_value mrb_f_global_variables(mrb_state *mrb, mrb_value self) { - char buf[3]; - khint_t i; - struct kh_iv *h = mrb->globals; + iv_tbl *t = mrb->globals; mrb_value ary = mrb_ary_new(mrb); + int i; + char buf[3]; - if (h) { - for (i=0;i < kh_end(h);i++) { - if (kh_exist(h, i)) { - mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(h,i))); - } - } + if (t) { + iv_foreach(mrb, t, gv_i, &ary); } buf[0] = '$'; buf[2] = 0; for (i = 1; i <= 9; ++i) { - buf[1] = (char)(i + '0'); - mrb_ary_push(mrb, ary, mrb_symbol_value(mrb_intern(mrb, buf))); + buf[1] = (char)(i + '0'); + mrb_ary_push(mrb, ary, mrb_symbol_value(mrb_intern2(mrb, buf, 2))); } return ary; } -int -mrb_st_lookup(struct kh_iv *table, mrb_sym id, khiter_t *value) -{ - khash_t(iv) *h; - khiter_t k; - - if (table) { - h = (khash_t(iv)*)table; - k = kh_get(iv, h, id); - if (k != kh_end(h)) { - if (value != 0) *value = k;//kh_value(h, k); - return 1;/* TRUE */ - } - return 0;/* FALSE */ - } - else { - return 0;/* FALSE */ - } -} - -static int -kiv_lookup(khash_t(iv)* table, mrb_sym key, mrb_value *value) -{ - khash_t(iv) *h=table; - khiter_t k; - - k = kh_get(iv, h, key); - if (k != kh_end(h)) { - *value = kh_value(h, k); - return 1; - } - return 0; -} - static int mrb_const_defined_0(mrb_state *mrb, struct RClass *klass, mrb_sym id, int exclude, int recurse) { - mrb_value value; struct RClass * tmp; int mod_retry = 0; tmp = klass; retry: while (tmp) { - if (tmp->iv && kiv_lookup(tmp->iv, id, &value)) { - return (int)1/*Qtrue*/; + if (tmp->iv && iv_get(mrb, tmp->iv, id, NULL)) { + return TRUE; } if (!recurse && (klass != mrb->object_class)) break; tmp = tmp->super; @@ -501,7 +856,7 @@ retry: tmp = mrb->object_class; goto retry; } - return (int)0/*Qfalse*/; + return FALSE; } int @@ -525,3 +880,38 @@ mrb_class_obj_get(mrb_state *mrb, const char *name) return mrb_class_ptr(mrb_const_get(mrb, mod, sym)); } +struct csym_arg { + struct RClass *c; + mrb_sym sym; +}; + +static int +csym_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) +{ + struct csym_arg *a = (struct csym_arg*)p; + struct RClass *c = a->c; + + if (mrb_type(v) == c->tt && mrb_class_ptr(v) == c) { + a->sym = sym; + return 1; /* stop iteration */ + } + return 0; +} + +mrb_sym +mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer) +{ + mrb_value name; + + name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classid__")); + if (mrb_nil_p(name)) { + struct csym_arg arg; + + arg.c = c; + arg.sym = 0; + + iv_foreach(mrb, outer->iv, csym_i, &arg); + return arg.sym; + } + return SYM2ID(name); +} @@ -20,6 +20,8 @@ #include <stdio.h> #include <string.h> #include <setjmp.h> +#include <stddef.h> +#include <stdarg.h> #define STACK_INIT_SIZE 128 #define CALLINFO_INIT_SIZE 32 @@ -178,6 +180,44 @@ ecall(mrb_state *mrb, int i) if (!mrb->exc) mrb->exc = exc; } +#ifndef MRB_FUNCALL_ARGC_MAX +#define MRB_FUNCALL_ARGC_MAX 16 +#endif + +mrb_value +mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...) +{ + mrb_sym mid = mrb_intern(mrb, name); + va_list ap; + int i; + + if (argc == 0) { + return mrb_funcall_argv(mrb, self, mid, 0, 0); + } + else if (argc == 1) { + mrb_value v; + + va_start(ap, argc); + v = va_arg(ap, mrb_value); + va_end(ap); + return mrb_funcall_argv(mrb, self, mid, 1, &v); + } + else { + mrb_value argv[MRB_FUNCALL_ARGC_MAX]; + + if (argc > MRB_FUNCALL_ARGC_MAX) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%d)", MRB_FUNCALL_ARGC_MAX); + } + + va_start(ap, argc); + for (i = 0; i < argc; i++) { + argv[i] = va_arg(ap, mrb_value); + } + va_end(ap); + return mrb_funcall_argv(mrb, self, mid, argc, argv); + } +} + mrb_value mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mrb_value *argv, mrb_value blk) { @@ -188,6 +228,20 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr int n = mrb->ci->nregs; mrb_value val; + if (!mrb->jmp) { + jmp_buf c_jmp; + + if (setjmp(c_jmp) != 0) { /* error */ + mrb->jmp = 0; + return mrb_nil_value(); + } + mrb->jmp = &c_jmp; + /* recursive call */ + val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk); + mrb->jmp = 0; + return val; + } + if (argc < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%d)", argc); } @@ -402,6 +456,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) int ai = mrb->arena_idx; jmp_buf *prev_jmp = (jmp_buf *)mrb->jmp; jmp_buf c_jmp; + ptrdiff_t ciidx = mrb->ci - mrb->cibase; #ifdef DIRECT_THREADED static void *optable[] = { @@ -450,9 +505,9 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) CASE(OP_MOVE) { /* A B R(A) := R(B) */ -#if 0 +#if 1 regs[GETARG_A(i)] = regs[GETARG_B(i)]; -#elif 1 +#elif 0 int a = GETARG_A(i); int b = GETARG_B(i); @@ -689,7 +744,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) struct RProc *m; struct RClass *c; mrb_callinfo *ci; - mrb_value recv; + mrb_value recv, result; mrb_sym mid = syms[GETARG_B(i)]; recv = regs[a]; @@ -731,7 +786,8 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) else { ci->nregs = n + 2; } - mrb->stack[0] = m->body.func(mrb, recv); + result = m->body.func(mrb, recv); + mrb->stack[0] = result; mrb->arena_idx = ai; if (mrb->exc) goto L_RAISE; /* pop stackpos */ @@ -1027,6 +1083,10 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) ci = mrb->ci; eidx = mrb->ci->eidx; if (ci == mrb->cibase) goto L_STOP; + if (ciidx == ci - mrb->cibase){ + mrb->jmp = prev_jmp; + longjmp(*(jmp_buf*)mrb->jmp, 1); + } while (ci[0].ridx == ci[-1].ridx) { cipop(mrb); ci = mrb->ci; |
