diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-02-26 17:15:00 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-02-26 17:15:00 +0000 |
commit | aba4666e197331362f4a53b37bc21909144a3494 (patch) | |
tree | 9a59a2a739ca7ddbf1d798c7b5ebf66fd927944f /eval.c | |
parent | 52e0246b61c3eb9871761692704e41687f8437c0 (diff) | |
download | ruby-aba4666e197331362f4a53b37bc21909144a3494.tar.gz |
* eval.c (localjump_destination): lambda should not interfere
return from the yielded block.
* hash.c (delete_if_i): use st_delete_safe() (via
rb_hash_delete()) instead of returning ST_DELETE.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5842 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 14 |
1 files changed, 10 insertions, 4 deletions
@@ -912,6 +912,7 @@ static struct tag *prot_tag; #define PROT_ITER INT2FIX(1) /* 3 */ #define PROT_CALL INT2FIX(2) /* 5 */ #define PROT_PCALL INT2FIX(3) /* 7 */ +#define PROT_YIELD INT2FIX(4) /* 9 */ #define EXEC_TAG() (FLUSH_REGISTER_WINDOWS, setjmp(prot_tag->buf)) @@ -4514,10 +4515,15 @@ localjump_destination(state, retval) { struct tag *tt = prot_tag; VALUE tag = (state == TAG_BREAK) ? PROT_ITER : PROT_FUNC; + int uniq = 0; if (retval == Qundef) retval = Qnil; while (tt) { - if (tt->tag == PROT_PCALL || (tt->tag == PROT_THREAD && state == TAG_BREAK) || + if (tt->tag == PROT_YIELD) { + uniq = tt->frame->uniq; + } + if ((tt->tag == PROT_THREAD && state == TAG_BREAK) || + (tt->tag == PROT_PCALL && uniq == 0) || (tt->tag == PROT_CALL || tt->tag == tag) && tt->frame->uniq == ruby_frame->uniq) { tt->dst = (VALUE)ruby_frame->uniq; tt->retval = retval; @@ -4639,7 +4645,7 @@ rb_yield_0(val, self, klass, flags, avalue) ruby_current_node = node; PUSH_ITER(block->iter); - PUSH_TAG(PROT_NONE); + PUSH_TAG(PROT_YIELD); if ((state = EXEC_TAG()) == 0) { redo: if (nd_type(node) == NODE_CFUNC || nd_type(node) == NODE_IFUNC) { @@ -7988,7 +7994,7 @@ proc_invoke(proc, args, self, klass) proc_set_safe_level(proc); result = rb_yield_0(args, self, (self!=Qundef)?CLASS_OF(self):0, pcall, avalue); } - else if (pcall || orphan || TAG_DST()) { + else if (TAG_DST()) { result = prot_tag->retval; } POP_TAG(); @@ -8008,7 +8014,6 @@ proc_invoke(proc, args, self, klass) /* fall through */ case TAG_BREAK: case TAG_RETURN: - if (pcall) break; if (orphan) { /* orphan block */ char mesg[32]; snprintf(mesg, sizeof mesg, "%s from proc-closure", @@ -8016,6 +8021,7 @@ proc_invoke(proc, args, self, klass) localjump_error(mesg, result, state); } if (result != Qundef) { + if (pcall) break; localjump_destination(state, result); } default: |