diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2001-05-22 08:28:11 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2001-05-22 08:28:11 +0000 |
commit | 315cd8341823e129ba5df0f420443e9d06d62c6f (patch) | |
tree | 2184e205b25e90012772f2ca77d419ed56a61bff /eval.c | |
parent | ed6a2bd29f649369beb1b7935cf2625c60581c04 (diff) |
* variable.c (rb_alias_variable): should not allow variable
aliasing if $SAFE >= 4.
* parse.y (expr): "break" and "next" to take optional expression,
which is used as a value for termination. [new, experimental]
* eval.c (rb_eval): "break" can give value to terminating method.
* eval.c (rb_eval): "break" and "next" to take optional expression.
* eval.c (rb_yield_0): "next" can give value to terminating "yield".
* eval.c (rb_iterate): "break" can give value to terminating method.
* eval.c (proc_call): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1441 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 57 |
1 files changed, 38 insertions, 19 deletions
@@ -2288,7 +2288,7 @@ rb_eval(self, n) } else if (_block.tag->dst == state) { state &= TAG_MASK; - if (state == TAG_RETURN) { + if (state == TAG_RETURN || state == TAG_BREAK) { result = prot_tag->retval; } } @@ -2302,8 +2302,8 @@ rb_eval(self, n) goto iter_retry; case TAG_BREAK: - result = Qnil; break; + case TAG_RETURN: return_value(result); /* fall through */ @@ -2314,10 +2314,22 @@ rb_eval(self, n) break; case NODE_BREAK: + if (node->nd_stts) { + return_value(rb_eval(self, node->nd_stts)); + } + else { + return_value(Qnil); + } JUMP_TAG(TAG_BREAK); break; case NODE_NEXT: + if (node->nd_stts) { + return_value(rb_eval(self, node->nd_stts)); + } + else { + return_value(Qnil); + } JUMP_TAG(TAG_NEXT); break; @@ -3574,6 +3586,12 @@ rb_yield_0(val, self, klass, acheck) RARRAY(val)->len); } } + else if (block->var == (NODE*)2) { + if (val != Qundef && TYPE(val) == T_ARRAY && RARRAY(val)->len != 0) { + rb_raise(rb_eArgError, "wrong # of arguments (%d for 0)", + RARRAY(val)->len); + } + } else { if (nd_type(block->var) == NODE_MASGN) massign(self, block->var, val, acheck); @@ -3614,7 +3632,7 @@ rb_yield_0(val, self, klass, acheck) goto redo; case TAG_NEXT: state = 0; - result = Qnil; + result = prot_tag->retval; break; case TAG_BREAK: case TAG_RETURN: @@ -3842,7 +3860,7 @@ rb_iterate(it_proc, data1, bl_proc, data2) } if (ruby_block->tag->dst == state) { state &= TAG_MASK; - if (state == TAG_RETURN) { + if (state == TAG_RETURN || state == TAG_BREAK) { retval = prot_tag->retval; } } @@ -3858,7 +3876,6 @@ rb_iterate(it_proc, data1, bl_proc, data2) goto iter_retry; case TAG_BREAK: - retval = Qnil; break; case TAG_RETURN: @@ -6343,21 +6360,22 @@ proc_call(proc, args) ruby_block = old_block; ruby_safe_level = safe; - if (state) { - switch (state) { - case TAG_BREAK: - break; - case TAG_RETRY: - rb_raise(rb_eLocalJumpError, "retry from proc-closure"); - break; - case TAG_RETURN: - if (orphan) { /* orphan procedure */ - rb_raise(rb_eLocalJumpError, "return from proc-closure"); - } - /* fall through */ - default: - JUMP_TAG(state); + switch (state) { + case 0: + break; + case TAG_BREAK: + result = prot_tag->retval; + break; + case TAG_RETRY: + rb_raise(rb_eLocalJumpError, "retry from proc-closure"); + break; + case TAG_RETURN: + if (orphan) { /* orphan procedure */ + rb_raise(rb_eLocalJumpError, "return from proc-closure"); } + /* fall through */ + default: + JUMP_TAG(state); } return result; } @@ -6373,6 +6391,7 @@ proc_arity(proc) Data_Get_Struct(proc, struct BLOCK, data); if (data->var == 0) return INT2FIX(-1); if (data->var == (NODE*)1) return INT2FIX(0); + if (data->var == (NODE*)2) return INT2FIX(0); switch (nd_type(data->var)) { default: return INT2FIX(-1); |