diff options
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 507 |
1 files changed, 303 insertions, 204 deletions
@@ -6,7 +6,7 @@ $Date$ created at: Thu Jun 10 14:22:17 JST 1993 - Copyright (C) 1993-1997 Yukihiro Matsumoto + Copyright (C) 1993-1998 Yukihiro Matsumoto ************************************************/ @@ -43,6 +43,7 @@ static VALUE f_binding _((VALUE)); static void f_END _((void)); #define SCOPE_PRIVATE FL_USER4 +#define SCOPE_MODFUNC FL_USER5 #define CACHE_SIZE 0x200 #define CACHE_MASK 0x1ff @@ -51,7 +52,7 @@ static void f_END _((void)); struct cache_entry { /* method hash table. */ ID mid; /* method's id */ ID mid0; /* method's original id */ - VALUE class; /* receiver's class */ + VALUE klass; /* receiver's class */ VALUE origin; /* where method defined */ NODE *method; int noex; @@ -87,80 +88,80 @@ rb_clear_cache_by_id(id) } void -rb_add_method(class, mid, node, noex) - VALUE class; +rb_add_method(klass, mid, node, noex) + VALUE klass; ID mid; NODE *node; int noex; { NODE *body; - if (NIL_P(class)) class = cObject; + if (NIL_P(klass)) klass = cObject; body = NEW_METHOD(node, noex); - st_insert(RCLASS(class)->m_tbl, mid, body); + st_insert(RCLASS(klass)->m_tbl, mid, body); } void -rb_remove_method(class, mid) - VALUE class; +rb_remove_method(klass, mid) + VALUE klass; ID mid; { NODE *body; - if (!st_delete(RCLASS(class)->m_tbl, &mid, &body)) { + if (!st_delete(RCLASS(klass)->m_tbl, &mid, &body)) { NameError("method `%s' not defined in %s", - rb_id2name(mid), rb_class2name(class)); + rb_id2name(mid), rb_class2name(klass)); } rb_clear_cache_by_id(mid); } static NODE* -search_method(class, id, origin) - VALUE class, *origin; +search_method(klass, id, origin) + VALUE klass, *origin; ID id; { NODE *body; - while (!st_lookup(RCLASS(class)->m_tbl, id, &body)) { - class = (VALUE)RCLASS(class)->super; - if (!class) return 0; + while (!st_lookup(RCLASS(klass)->m_tbl, id, &body)) { + klass = RCLASS(klass)->super; + if (!klass) return 0; } - if (origin) *origin = class; + if (origin) *origin = klass; return body; } static NODE* -rb_get_method_body(classp, idp, noexp) - VALUE *classp; +rb_get_method_body(klassp, idp, noexp) + VALUE *klassp; ID *idp; int *noexp; { ID id = *idp; - VALUE class = *classp; + VALUE klass = *klassp; VALUE origin; NODE *body; struct cache_entry *ent; - if ((body = search_method(class, id, &origin)) == 0) { + if ((body = search_method(klass, id, &origin)) == 0) { return 0; } if (!body->nd_body) return 0; /* store in cache */ - ent = cache + EXPR1(class, id); - ent->class = class; + ent = cache + EXPR1(klass, id); + ent->klass = klass; ent->noex = body->nd_noex; body = body->nd_body; if (nd_type(body) == NODE_FBODY) { ent->mid = id; - *classp = body->nd_orig; + *klassp = body->nd_orig; ent->origin = body->nd_orig; *idp = ent->mid0 = body->nd_mid; body = ent->method = body->nd_head; } else { - *classp = (VALUE)origin; + *klassp = origin; ent->origin = origin; ent->mid = ent->mid0 = id; ent->method = body; @@ -171,23 +172,23 @@ rb_get_method_body(classp, idp, noexp) } void -rb_alias(class, name, def) - VALUE class; +rb_alias(klass, name, def) + VALUE klass; ID name, def; { VALUE origin; NODE *orig, *body; if (name == def) return; - orig = search_method(class, def, &origin); + orig = search_method(klass, def, &origin); if (!orig || !orig->nd_body) { - if (TYPE(class) == T_MODULE) { + if (TYPE(klass) == T_MODULE) { orig = search_method(cObject, def, &origin); } } if (!orig || !orig->nd_body) { NameError("undefined method `%s' for `%s'", - rb_id2name(def), rb_class2name((VALUE)class)); + rb_id2name(def), rb_class2name(klass)); } body = orig->nd_body; if (nd_type(body) == NODE_FBODY) { /* was alias */ @@ -196,47 +197,47 @@ rb_alias(class, name, def) origin = body->nd_orig; } - st_insert(RCLASS(class)->m_tbl, name, + st_insert(RCLASS(klass)->m_tbl, name, NEW_METHOD(NEW_FBODY(body, def, origin), orig->nd_noex)); } static void -rb_export_method(class, name, noex) - VALUE class; +rb_export_method(klass, name, noex) + VALUE klass; ID name; int noex; { NODE *body; - struct RClass *origin; + VALUE origin; - body = search_method(class, name, &origin); - if (!body && TYPE(class) == T_MODULE) { + body = search_method(klass, name, &origin); + if (!body && TYPE(klass) == T_MODULE) { body = search_method(cObject, name, &origin); } if (!body) { NameError("undefined method `%s' for `%s'", - rb_id2name(name), rb_class2name(class)); + rb_id2name(name), rb_class2name(klass)); } if (body->nd_noex != noex) { - if (class == (VALUE)origin) { + if (klass == origin) { body->nd_noex = noex; } else { rb_clear_cache_by_id(name); - rb_add_method(class, name, NEW_ZSUPER(), noex); + rb_add_method(klass, name, NEW_ZSUPER(), noex); } } } static VALUE -method_boundp(class, id, ex) - VALUE class; +method_boundp(klass, id, ex) + VALUE klass; ID id; int ex; { int noex; - if (rb_get_method_body(&class, &id, &noex)) { + if (rb_get_method_body(&klass, &id, &noex)) { if (ex && noex == NOEX_PRIVATE) return FALSE; return TRUE; @@ -245,12 +246,12 @@ method_boundp(class, id, ex) } int -rb_method_boundp(class, id, ex) - VALUE class; +rb_method_boundp(klass, id, ex) + VALUE klass; ID id; int ex; { - if (method_boundp(class, id, ex)) + if (method_boundp(klass, id, ex)) return TRUE; return FALSE; } @@ -282,15 +283,15 @@ static struct FRAME *top_frame; static struct SCOPE *top_scope; #define PUSH_FRAME() { \ - struct FRAME *_frame = ALLOCA_N(struct FRAME,1);\ - _frame->prev = the_frame; \ - _frame->file = sourcefile; \ - _frame->line = sourceline; \ - _frame->iter = the_iter->iter; \ - _frame->cbase = the_frame->cbase; \ - the_frame = _frame; \ + struct FRAME _frame; \ + _frame.prev = the_frame; \ + _frame.file = sourcefile; \ + _frame.line = sourceline; \ + _frame.iter = the_iter->iter; \ + _frame.cbase = the_frame->cbase; \ + the_frame = &_frame; \ -#define POP_FRAME() the_frame = _frame->prev; } +#define POP_FRAME() the_frame = _frame.prev; } struct BLOCK { NODE *var; @@ -298,7 +299,7 @@ struct BLOCK { VALUE self; struct FRAME frame; struct SCOPE *scope; - VALUE class; + VALUE klass; struct tag *tag; int iter; struct RVarmap *d_vars; @@ -309,29 +310,29 @@ struct BLOCK { } *the_block; #define PUSH_BLOCK(v,b) { \ - struct BLOCK *_block = ALLOCA_N(struct BLOCK,1);\ - _block->tag = prot_tag; \ - _block->var = v; \ - _block->body = b; \ - _block->self = self; \ - _block->frame = *the_frame; \ - _block->class = the_class; \ - _block->frame.file = sourcefile; \ - _block->frame.line = sourceline; \ - _block->scope = the_scope; \ - _block->d_vars = the_dyna_vars; \ - _block->prev = the_block; \ - _block->iter = the_iter->iter; \ - the_block = _block; + struct BLOCK _block; \ + _block.tag = prot_tag; \ + _block.var = v; \ + _block.body = b; \ + _block.self = self; \ + _block.frame = *the_frame; \ + _block.klass = the_class; \ + _block.frame.file = sourcefile; \ + _block.frame.line = sourceline; \ + _block.scope = the_scope; \ + _block.d_vars = the_dyna_vars; \ + _block.prev = the_block; \ + _block.iter = the_iter->iter; \ + the_block = &_block; #define PUSH_BLOCK2(b) { \ - struct BLOCK *_block = ALLOCA_N(struct BLOCK,1);\ - *_block = *b; \ - _block->prev = the_block; \ - the_block = _block; + struct BLOCK _block; \ + _block = *b; \ + _block.prev = the_block; \ + the_block = &_block; #define POP_BLOCK() \ - the_block = the_block->prev; \ + the_block = _block.prev; \ } struct RVarmap *the_dyna_vars; @@ -416,38 +417,26 @@ static struct iter { the_iter = _iter.prev; \ } -#ifdef C_ALLOCA -/* need to protect retval in struct tag from GC. */ -#define tag_retval_dcl VALUE *dd_retval -#define tag_retval_init VALUE _tag_retval = Qnil;\ - _tag->dd_retval = &_tag_retval; -#define tag_retval dd_retval[0] -#else -#define tag_retval_dcl VALUE retval -#define tag_retval_init _tag->retval = Qnil -#define tag_retval retval -#endif - static struct tag { jmp_buf buf; struct FRAME *frame; struct iter *iter; ID tag; - tag_retval_dcl; + VALUE retval; ID dst; struct tag *prev; } *prot_tag; #define PUSH_TAG(ptag) { \ - struct tag *_tag = ALLOCA_N(struct tag,1);\ - tag_retval_init; \ - _tag->frame = the_frame; \ - _tag->iter = the_iter; \ - _tag->prev = prot_tag; \ - _tag->tag_retval = Qnil; \ - _tag->tag = ptag; \ - _tag->dst = 0; \ - prot_tag = _tag; + struct tag _tag; \ + _tag.retval = Qnil; \ + _tag.frame = the_frame; \ + _tag.iter = the_iter; \ + _tag.prev = prot_tag; \ + _tag.retval = Qnil; \ + _tag.tag = ptag; \ + _tag.dst = 0; \ + prot_tag = &_tag; #define PROT_NONE 0 #define PROT_FUNC -1 @@ -462,7 +451,7 @@ static struct tag { } #define POP_TAG() \ - prot_tag = _tag->prev; \ + prot_tag = _tag.prev; \ } #define TAG_RETURN 0x1 @@ -717,6 +706,7 @@ ruby_init() top_scope = the_scope; /* default visibility is private at toplevel */ FL_SET(top_scope, SCOPE_PRIVATE); + FL_UNSET(top_scope, SCOPE_MODFUNC); PUSH_TAG(PROT_NONE) if ((state = EXEC_TAG()) == 0) { @@ -746,11 +736,10 @@ ruby_options(argc, argv) NODE *save; ruby_process_options(argc, argv); + ext_init = 1; /* Init_ext() called in ruby_process_options */ save = eval_tree; eval_tree = 0; - Init_ext(); - ext_init = 1; - rb_require_modules(); + ruby_require_modules(); eval_tree = save; } POP_TAG(); @@ -1024,10 +1013,10 @@ ev_const_defined(cref, id) NODE *cbase = cref; while (cbase && cbase->nd_clss != cObject) { - struct RClass *class = RCLASS(cbase->nd_clss); + struct RClass *klass = RCLASS(cbase->nd_clss); - if (class->iv_tbl && - st_lookup(class->iv_tbl, id, 0)) { + if (klass->iv_tbl && + st_lookup(klass->iv_tbl, id, 0)) { return TRUE; } cbase = cbase->nd_next; @@ -1044,10 +1033,10 @@ ev_const_get(cref, id) VALUE result; while (cbase && cbase->nd_clss != cObject) { - struct RClass *class = RCLASS(cbase->nd_clss); + struct RClass *klass = RCLASS(cbase->nd_clss); - if (class->iv_tbl && - st_lookup(class->iv_tbl, id, &result)) { + if (klass->iv_tbl && + st_lookup(klass->iv_tbl, id, &result)) { return result; } cbase = cbase->nd_next; @@ -1103,16 +1092,27 @@ mod_undef_method(mod, name) } static VALUE -mod_alias_method(mod, new, old) - VALUE mod, new, old; +mod_alias_method(mod, newname, oldname) + VALUE mod, newname, oldname; { - ID id = rb_to_id(new); + ID id = rb_to_id(newname); - rb_alias(mod, id, rb_to_id(old)); + rb_alias(mod, id, rb_to_id(oldname)); rb_clear_cache_by_id(id); return mod; } +#if defined(C_ALLOCA) && defined(THREAD) +# define TMP_PROTECT NODE *__protect_tmp=0 +# define TMP_ALLOC(type,n) \ + (__protect_tmp = node_newnode(NODE_ALLOCA, \ + str_new(0,sizeof(type)*(n)),0,__protect_tmp), \ + (void*)RSTRING(__protect_tmp->nd_head)->ptr) +#else +# define TMP_PROTECT typedef int foobazzz +# define TMP_ALLOC(type,n) ALLOCA_N(type,n) +#endif + #define SETUP_ARGS(anode) {\ NODE *n = anode;\ if (!n) {\ @@ -1126,7 +1126,7 @@ mod_alias_method(mod, new, old) int line = sourceline;\ int i;\ n = anode;\ - argv = ALLOCA_N(VALUE,argc);\ + argv = TMP_ALLOC(VALUE,argc);\ for (i=0;i<argc;i++) {\ argv[i] = rb_eval(self,n->nd_head);\ n=n->nd_next;\ @@ -1371,7 +1371,7 @@ call_trace_func(event, file, line, self, id) prev = the_frame; PUSH_FRAME(); - *the_frame = *_frame->prev; + *the_frame = *_frame.prev; the_frame->prev = prev; the_frame->line = sourceline = line; @@ -1606,7 +1606,7 @@ rb_eval(self, node) else if (the_block->tag->dst == state) { state &= TAG_MASK; if (state == TAG_RETURN) { - result = prot_tag->tag_retval; + result = prot_tag->retval; } } POP_TAG(); @@ -1767,6 +1767,7 @@ rb_eval(self, node) { VALUE recv; int argc; VALUE *argv; /* used in SETUP_ARGS */ + TMP_PROTECT; PUSH_ITER(ITER_NOT); recv = rb_eval(self, node->nd_recv); @@ -1779,6 +1780,7 @@ rb_eval(self, node) case NODE_FCALL: { int argc; VALUE *argv; /* used in SETUP_ARGS */ + TMP_PROTECT; PUSH_ITER(ITER_NOT); SETUP_ARGS(node->nd_args); @@ -1795,6 +1797,7 @@ rb_eval(self, node) case NODE_ZSUPER: { int argc; VALUE *argv; /* used in SETUP_ARGS */ + TMP_PROTECT; if (nd_type(node) == NODE_ZSUPER) { argc = the_frame->argc; @@ -1819,7 +1822,7 @@ rb_eval(self, node) PUSH_SCOPE(); PUSH_TAG(PROT_NONE); - if (node->nd_rval) the_frame->cbase = (VALUE)node->nd_rval; + if (node->nd_rval) the_frame->cbase = node->nd_rval; if (node->nd_tbl) { VALUE *vars = ALLOCA_N(VALUE, node->nd_tbl[0]+1); *vars++ = (VALUE)node; @@ -1846,6 +1849,7 @@ rb_eval(self, node) int argc; VALUE *argv; /* used in SETUP_ARGS */ VALUE recv, val; NODE *rval; + TMP_PROTECT; recv = rb_eval(self, node->nd_recv); rval = node->nd_args->nd_head; @@ -1950,18 +1954,18 @@ rb_eval(self, node) case NODE_COLON2: { - VALUE cls; + VALUE klass; - cls = rb_eval(self, node->nd_head); - switch (TYPE(cls)) { + klass = rb_eval(self, node->nd_head); + switch (TYPE(klass)) { case T_CLASS: case T_MODULE: break; default: - Check_Type(cls, T_CLASS); + Check_Type(klass, T_CLASS); break; } - result = rb_const_get_at(cls, node->nd_mid); + result = rb_const_get_at(klass, node->nd_mid); } break; @@ -2106,19 +2110,25 @@ rb_eval(self, node) body = search_method(the_class, node->nd_mid, &origin); if (body) { - if (origin == (VALUE)the_class) { + if (origin == the_class) { Warning("discarding old %s", rb_id2name(node->nd_mid)); } rb_clear_cache_by_id(node->nd_mid); } - if (FL_TEST(the_scope,SCOPE_PRIVATE)) { + if (FL_TEST(the_scope,SCOPE_PRIVATE) || node->nd_mid == init) { noex = NOEX_PRIVATE; } else { noex = NOEX_PUBLIC; } rb_add_method(the_class, node->nd_mid, node->nd_defn, noex); + if (FL_TEST(the_scope,SCOPE_MODFUNC)) { + rb_add_method(rb_singleton_class(the_class), + node->nd_mid, node->nd_defn, NOEX_PUBLIC); + rb_funcall(the_class, rb_intern("singleton_method_added"), + 1, INT2FIX(node->nd_mid)); + } if (FL_TEST(the_class, FL_SINGLETON)) { VALUE recv = rb_iv_get(the_class, "__attached__"); rb_funcall(recv, rb_intern("singleton_method_added"), @@ -2135,7 +2145,7 @@ rb_eval(self, node) case NODE_DEFS: if (node->nd_defn) { VALUE recv = rb_eval(self, node->nd_recv); - VALUE class; + VALUE klass; NODE *body; if (FIXNUM_P(recv)) { @@ -2151,12 +2161,12 @@ rb_eval(self, node) rb_id2name(node->nd_mid)); } - class = rb_singleton_class(recv); - if (st_lookup(RCLASS(class)->m_tbl, node->nd_mid, &body)) { + klass = rb_singleton_class(recv); + if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, &body)) { Warning("redefine %s", rb_id2name(node->nd_mid)); } rb_clear_cache_by_id(node->nd_mid); - rb_add_method(class, node->nd_mid, node->nd_defn, NOEX_PUBLIC); + rb_add_method(klass, node->nd_mid, node->nd_defn, NOEX_PUBLIC); rb_funcall(recv, rb_intern("singleton_method_added"), 1, INT2FIX(node->nd_mid)); result = Qnil; @@ -2171,7 +2181,7 @@ rb_eval(self, node) body = search_method(the_class, node->nd_mid, &origin); if (!body || !body->nd_body) { NameError("undefined method `%s' for class `%s'", - rb_id2name(node->nd_mid), rb_class2name((VALUE)the_class)); + rb_id2name(node->nd_mid), rb_class2name(the_class)); } rb_clear_cache_by_id(node->nd_mid); rb_add_method(the_class, node->nd_mid, 0, NOEX_PUBLIC); @@ -2193,7 +2203,7 @@ rb_eval(self, node) case NODE_CLASS: { - VALUE super, class, tmp; + VALUE super, klass, tmp; if (node->nd_super) { super = superclass(self, node->nd_super); @@ -2203,15 +2213,15 @@ rb_eval(self, node) } if (rb_const_defined_at(the_class, node->nd_cname) && - ((VALUE)the_class != cObject || + (the_class != cObject || !rb_autoload_defined(node->nd_cname))) { - class = rb_const_get_at(the_class, node->nd_cname); - if (TYPE(class) != T_CLASS) { + klass = rb_const_get_at(the_class, node->nd_cname); + if (TYPE(klass) != T_CLASS) { TypeError("%s is not a class", rb_id2name(node->nd_cname)); } if (super) { - tmp = RCLASS(class)->super; + tmp = RCLASS(klass)->super; if (FL_TEST(tmp, FL_SINGLETON)) { tmp = RCLASS(tmp)->super; } @@ -2230,12 +2240,12 @@ rb_eval(self, node) } else { if (!super) super = cObject; - class = rb_define_class_id(node->nd_cname, super); - rb_const_set(the_class, node->nd_cname, class); - rb_set_class_path(class,the_class,rb_id2name(node->nd_cname)); + klass = rb_define_class_id(node->nd_cname, super); + rb_const_set(the_class, node->nd_cname, klass); + rb_set_class_path(klass,the_class,rb_id2name(node->nd_cname)); } - return module_setup(class, node->nd_body); + return module_setup(klass, node->nd_body); } break; @@ -2244,7 +2254,7 @@ rb_eval(self, node) VALUE module; if (rb_const_defined_at(the_class, node->nd_cname) && - ((VALUE)the_class != cObject || + (the_class != cObject || !rb_autoload_defined(node->nd_cname))) { module = rb_const_get_at(the_class, node->nd_cname); @@ -2267,24 +2277,24 @@ rb_eval(self, node) case NODE_SCLASS: { - VALUE class; + VALUE klass; - class = rb_eval(self, node->nd_recv); - if (FIXNUM_P(class)) { + klass = rb_eval(self, node->nd_recv); + if (FIXNUM_P(klass)) { TypeError("No virtual class for Fixnums"); } - if (NIL_P(class)) { + if (NIL_P(klass)) { TypeError("No virtual class for nil"); } - if (rb_special_const_p(class)) { + if (rb_special_const_p(klass)) { TypeError("No virtual class for special constants"); } - if (FL_TEST(CLASS_OF(class), FL_SINGLETON)) { + if (FL_TEST(CLASS_OF(klass), FL_SINGLETON)) { rb_clear_cache(); - class = rb_singleton_class(class); } - - result = module_setup(class, node->nd_body); + klass = rb_singleton_class(klass); + + result = module_setup(klass, node->nd_body); } break; @@ -2326,6 +2336,7 @@ module_setup(module, node) VALUE result; /* OK */ char *file = sourcefile; int line = sourceline; + TMP_PROTECT; /* fill c-ref */ node->nd_clss = module; @@ -2337,7 +2348,7 @@ module_setup(module, node) if (node->nd_rval) the_frame->cbase = node->nd_rval; if (node->nd_tbl) { - VALUE *vars = ALLOCA_N(VALUE, node->nd_tbl[0]+1); + VALUE *vars = TMP_ALLOC(VALUE, node->nd_tbl[0]+1); *vars++ = (VALUE)node; the_scope->local_vars = vars; memclear(the_scope->local_vars, node->nd_tbl[0]); @@ -2354,7 +2365,7 @@ module_setup(module, node) call_trace_func("class", file, line, the_class, the_frame->last_func); } - result = rb_eval((VALUE)the_class, node->nd_body); + result = rb_eval(the_class, node->nd_body); } POP_TAG(); POP_SCOPE(); @@ -2568,7 +2579,7 @@ f_raise(argc, argv) } PUSH_FRAME(); /* fake frame */ - *the_frame = *_frame->prev->prev; + *the_frame = *_frame.prev->prev; rb_longjmp(TAG_RAISE, mesg, arg3); POP_FRAME(); } @@ -2614,7 +2625,7 @@ rb_yield_0(val, self) the_scope = block->scope; the_block = block->prev; the_dyna_vars = block->d_vars; - the_class = block->class; + the_class = block->klass; if (!self) self = block->self; node = block->body; if (block->var) { @@ -2795,7 +2806,7 @@ rb_iterate(it_proc, data1, bl_proc, data2) if (the_block->tag->dst == state) { state &= TAG_MASK; if (state == TAG_RETURN) { - retval = prot_tag->tag_retval; + retval = prot_tag->retval; } } POP_TAG(); @@ -2828,6 +2839,7 @@ handle_rescue(self, node) NODE *node; { int argc; VALUE *argv; /* used in SETUP_ARGS */ + TMP_PROTECT; if (!node->nd_args) { return obj_is_kind_of(errinfo, eException); @@ -2968,7 +2980,7 @@ f_missing(argc, argv, obj) sourcefile = file; sourceline = line; PUSH_FRAME(); /* fake frame */ - *the_frame = *_frame->prev->prev; + *the_frame = *_frame.prev->prev; NameError(format, rb_id2name(id), @@ -3022,8 +3034,8 @@ stack_length() } static VALUE -rb_call(class, recv, mid, argc, argv, scope) - VALUE class, recv; +rb_call(klass, recv, mid, argc, argv, scope) + VALUE klass, recv; ID mid; int argc; /* OK */ VALUE *argv; /* OK */ @@ -3037,17 +3049,18 @@ rb_call(class, recv, mid, argc, argv, scope) int itr; enum node_type type; static int tick; + TMP_PROTECT; again: /* is it in the method cache? */ - ent = cache + EXPR1(class, mid); - if (ent->mid == mid && ent->class == class) { - class = ent->origin; + ent = cache + EXPR1(klass, mid); + if (ent->mid == mid && ent->klass == klass) { + klass = ent->origin; id = ent->mid0; noex = ent->noex; body = ent->method; } - else if ((body = rb_get_method_body(&class, &id, &noex)) == 0) { + else if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) { return rb_undefined(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0); } @@ -3070,19 +3083,19 @@ rb_call(class, recv, mid, argc, argv, scope) /* for re-scoped/renamed method */ mid = id; if (scope == 0) scope = 1; - if (RCLASS(class)->super == 0) { + if (RCLASS(klass)->super == 0) { /* origin is the Module, so need to scan superclass hierarchy. */ - struct RClass *cl = RCLASS(class); + struct RClass *cl = RCLASS(klass); - class = RBASIC(recv)->class; - while (class) { - if (RCLASS(class)->m_tbl == cl->m_tbl) + klass = RBASIC(recv)->klass; + while (klass) { + if (RCLASS(klass)->m_tbl == cl->m_tbl) break; - class = RCLASS(class)->super; + klass = RCLASS(klass)->super; } } else { - class = RCLASS(class)->super; + klass = RCLASS(klass)->super; } goto again; } @@ -3093,7 +3106,7 @@ rb_call(class, recv, mid, argc, argv, scope) PUSH_ITER(itr); PUSH_FRAME(); the_frame->last_func = id; - the_frame->last_class = class; + the_frame->last_class = klass; the_frame->argc = argc; the_frame->argv = argv; @@ -3200,7 +3213,7 @@ rb_call(class, recv, mid, argc, argv, scope) default: if (len < 0) { Bug("bad argc(%d) specified for `%s(%s)'", - len, rb_class2name((VALUE)class), rb_id2name(mid)); + len, rb_class2name(klass), rb_id2name(mid)); } else { ArgError("too many arguments(%d)", len); @@ -3225,7 +3238,7 @@ rb_call(class, recv, mid, argc, argv, scope) if (body->nd_rval) the_frame->cbase = body->nd_rval; if (body->nd_tbl) { - local_vars = ALLOCA_N(VALUE, body->nd_tbl[0]+1); + local_vars = TMP_ALLOC(VALUE, body->nd_tbl[0]+1); *local_vars++ = (VALUE)body; memclear(local_vars, body->nd_tbl[0]); the_scope->local_tbl = body->nd_tbl; @@ -3301,7 +3314,7 @@ rb_call(class, recv, mid, argc, argv, scope) result = rb_eval(recv, body); } else if (state == TAG_RETURN) { - result = prot_tag->tag_retval; + result = prot_tag->retval; state = 0; } POP_VARS(); @@ -3572,7 +3585,7 @@ eval(self, src, scope) rb_in_eval++; if (TYPE(the_class) == T_ICLASS) { - the_class = RBASIC(the_class)->class; + the_class = RBASIC(the_class)->klass; } PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { @@ -3644,8 +3657,8 @@ eval_under(under, self, src) PUSH_CLASS(); the_class = under; PUSH_FRAME(); - the_frame->last_func = _frame->last_func; - the_frame->last_class = _frame->last_class; + the_frame->last_func = _frame.last_func; + the_frame->last_class = _frame.last_class; the_frame->argc = 1; the_frame->argv = &src; the_frame->cbase = (VALUE)node_newnode(NODE_CREF,under,0,cbase); @@ -3722,6 +3735,7 @@ f_load(obj, fname) int state; char *file; volatile ID last_func; + TMP_PROTECT; Check_SafeStr(fname); if (RSTRING(fname)->ptr[0] == '~') { @@ -3737,7 +3751,7 @@ f_load(obj, fname) if (top_scope->local_tbl) { int len = top_scope->local_tbl[0]+1; ID *tbl = ALLOC_N(ID, len); - VALUE *vars = ALLOCA_N(VALUE, len); + VALUE *vars = TMP_ALLOC(VALUE, len); *vars++ = 0; MEMCPY(tbl, top_scope->local_tbl, ID, len); MEMCPY(vars, top_scope->local_vars, ID, len-1); @@ -3746,6 +3760,7 @@ f_load(obj, fname) } /* default visibility is private at loading toplevel */ FL_SET(the_scope, SCOPE_PRIVATE); + FL_UNSET(top_scope, SCOPE_MODFUNC); state = EXEC_TAG(); last_func = the_frame->last_func; @@ -3938,6 +3953,7 @@ mod_public(argc, argv, module) { if (argc == 0) { FL_UNSET(the_scope, SCOPE_PRIVATE); + FL_UNSET(top_scope, SCOPE_MODFUNC); } else { set_method_visibility(module, argc, argv, NOEX_PUBLIC); @@ -3953,6 +3969,7 @@ mod_private(argc, argv, module) { if (argc == 0) { FL_SET(the_scope, SCOPE_PRIVATE); + FL_UNSET(top_scope, SCOPE_MODFUNC); } else { set_method_visibility(module, argc, argv, NOEX_PRIVATE); @@ -4006,7 +4023,12 @@ mod_modfunc(argc, argv, module) ID id; NODE *body; - rb_clear_cache(); + if (argc == 0) { + FL_SET(the_scope, SCOPE_PRIVATE); + FL_SET(the_scope, SCOPE_MODFUNC); + return module; + } + set_method_visibility(module, argc, argv, NOEX_PRIVATE); for (i=0; i<argc; i++) { id = rb_to_id(argv[i]); @@ -4015,6 +4037,7 @@ mod_modfunc(argc, argv, module) NameError("undefined method `%s' for module `%s'", rb_id2name(id), rb_class2name(module)); } + rb_clear_cache_by_id(id); rb_add_method(rb_singleton_class(module), id, body->nd_body, NOEX_PUBLIC); } return module; @@ -4053,17 +4076,17 @@ mod_include(argc, argv, module) } VALUE -class_new_instance(argc, argv, class) +class_new_instance(argc, argv, klass) int argc; VALUE *argv; - VALUE class; + VALUE klass; { VALUE obj; - if (FL_TEST(class, FL_SINGLETON)) { + if (FL_TEST(klass, FL_SINGLETON)) { TypeError("can't create instance of virtual class"); } - obj = obj_alloc(class); + obj = obj_alloc(klass); PUSH_ITER(iterator_p()?ITER_PRE:ITER_NOT); rb_funcall2(obj, init, argc, argv); POP_ITER(); @@ -4347,8 +4370,8 @@ f_binding(self) #define PROC_TMASK (FL_USER1|FL_USER2) static VALUE -proc_s_new(class) - VALUE class; +proc_s_new(klass) + VALUE klass; { volatile VALUE proc; struct BLOCK *data; @@ -4357,7 +4380,7 @@ proc_s_new(class) ArgError("tryed to create Procedure-Object out of iterator"); } - proc = Data_Make_Struct(class, struct BLOCK, blk_mark, blk_free, data); + proc = Data_Make_Struct(klass, struct BLOCK, blk_mark, blk_free, data); *data = *the_block; #ifdef THREAD @@ -4392,6 +4415,22 @@ f_lambda() return proc_s_new(cProc); } +static int +blk_orphan(data) + struct BLOCK *data; +{ + if (data->scope && data->scope != top_scope && + (data->scope->flag & SCOPE_NOSTACK)) { + return 1; + } +#ifdef THREAD + if (data->orig_thread != thread_current()) { + return 1; + } +#endif + return 0; +} + static VALUE proc_call(proc, args) VALUE proc, args; /* OK */ @@ -4414,32 +4453,22 @@ proc_call(proc, args) } Data_Get_Struct(proc, struct BLOCK, data); + orphan = blk_orphan(data); + + /* PUSH BLOCK from data */ + PUSH_BLOCK2(data); + PUSH_ITER(ITER_CUR); + the_frame->iter = ITER_CUR; - if (data->scope && (data->scope->flag & SCOPE_NOSTACK)) { - orphan = 1; - } - else { -#ifdef THREAD - if (data->orig_thread != thread_current()) { - orphan = 1; - } - else -#endif - orphan = 0; - } if (orphan) {/* orphan procedure */ if (iterator_p()) { - data->frame.iter = ITER_CUR; + the_block->frame.iter = ITER_CUR; } else { - data->frame.iter = ITER_NOT; + the_block->frame.iter = ITER_NOT; } } - /* PUSH BLOCK from data */ - PUSH_BLOCK2(data); - PUSH_ITER(ITER_CUR); - the_frame->iter = ITER_CUR; if (FL_TEST(proc, PROC_TAINT)) { switch (RBASIC(proc)->flags & PROC_TMASK) { case PROC_T3: @@ -4487,6 +4516,76 @@ proc_call(proc, args) return result; } +static VALUE +proc_iterate(proc) + VALUE proc; +{ + VALUE lambda = f_lambda(); + struct BLOCK *data; + volatile VALUE result = Qnil; + int state; + volatile int orphan; + volatile int safe = safe_level; + + Data_Get_Struct(lambda, struct BLOCK, data); + data->frame.iter = ITER_PRE; + data->iter = ITER_PRE; + + Data_Get_Struct(proc, struct BLOCK, data); + orphan = blk_orphan(data); + + /* PUSH BLOCK from data */ + PUSH_BLOCK2(data); + PUSH_ITER(ITER_PRE); + the_frame->iter = ITER_PRE; + if (FL_TEST(proc, PROC_TAINT)) { + switch (RBASIC(proc)->flags & PROC_TMASK) { + case PROC_T3: + safe_level = 3; + break; + case PROC_T4: + safe_level = 4; + break; + case PROC_T5: + safe_level = 5; + break; + } + } + + PUSH_TAG(PROT_NONE); + state = EXEC_TAG(); + if (state == 0) { + result = proc_call(lambda, Qnil); + } + POP_TAG(); + + POP_ITER(); + if (the_block->tag->dst == state) { + state &= TAG_MASK; + orphan = 2; + } + POP_BLOCK(); + safe_level = safe; + + if (state) { + if (orphan == 2) {/* escape from orphan procedure */ + switch (state) { + case TAG_BREAK: + Raise(eLocalJumpError, "break from proc-closure"); + break; + case TAG_RETRY: + Raise(eLocalJumpError, "retry from proc-closure"); + break; + case TAG_RETURN: + Raise(eLocalJumpError, "return from proc-closure"); + break; + } + } + JUMP_TAG(state); + } + return result; +} + void Init_Proc() { @@ -4496,6 +4595,7 @@ Init_Proc() rb_define_singleton_method(cProc, "new", proc_s_new, 0); rb_define_method(cProc, "call", proc_call, -2); + rb_define_method(cProc, "iterate", proc_iterate, 0); rb_define_global_function("proc", f_lambda, 0); rb_define_global_function("lambda", f_lambda, 0); rb_define_global_function("binding", f_binding, 0); @@ -4562,7 +4662,7 @@ struct thread { struct BLOCK *block; struct iter *iter; struct tag *tag; - VALUE class; + VALUE klass; VALUE trace; @@ -4707,7 +4807,7 @@ thread_save_context(th) th->frame = the_frame; th->scope = the_scope; - th->class = the_class; + th->klass = the_class; th->dyna_vars = the_dyna_vars; th->block = the_block; th->iter = the_iter; @@ -4764,12 +4864,11 @@ thread_restore_context(th, exit) the_frame = th->frame; the_scope = th->scope; - the_class = th->class; + the_class = th->klass; the_dyna_vars = th->dyna_vars; the_block = th->block; the_iter = th->iter; prot_tag = th->tag; - the_class = th->class; errat = th->errat; errinfo = th->errinfo; last_status = th->last_status; @@ -5376,7 +5475,7 @@ thread_alloc() th->frame = 0; th->scope = 0; - th->class = 0; + th->klass = 0; th->dyna_vars = 0; th->block = 0; th->iter = 0; @@ -5721,7 +5820,7 @@ f_catch(dmy, tag) val = rb_yield(tag); } else if (state == TAG_THROW && prot_tag->tag == prot_tag->dst) { - val = prot_tag->tag_retval; + val = prot_tag->retval; state = 0; } POP_TAG(); @@ -5745,7 +5844,7 @@ f_throw(argc, argv) while (tt) { if (tt->tag == t) { tt->dst = t; - tt->tag_retval = value; + tt->retval = value; break; } #ifdef THREAD @@ -5773,7 +5872,7 @@ return_value(val) while (tt) { if (tt->tag == PROT_FUNC) { - tt->tag_retval = val; + tt->retval = val; break; } #ifdef THREAD |