зеркало из https://github.com/github/ruby.git
* 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
This commit is contained in:
Родитель
ed6a2bd29f
Коммит
315cd83418
20
ChangeLog
20
ChangeLog
|
@ -1,3 +1,23 @@
|
|||
Tue May 22 17:10:35 2001 K.Kosako <kosako@sofnec.co.jp>
|
||||
|
||||
* variable.c (rb_alias_variable): should not allow variable
|
||||
aliasing if $SAFE >= 4.
|
||||
|
||||
Tue May 22 02:37:45 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* 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.
|
||||
|
||||
Mon May 21 13:15:25 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* bignum.c (rb_big2str): t should be protected from GC.
|
||||
|
|
57
eval.c
57
eval.c
|
@ -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);
|
||||
|
|
4
node.h
4
node.h
|
@ -248,8 +248,8 @@ typedef struct RNode {
|
|||
#define NEW_UNTIL(c,b,n) rb_node_newnode(NODE_UNTIL,c,b,n)
|
||||
#define NEW_FOR(v,i,b) rb_node_newnode(NODE_FOR,v,b,i)
|
||||
#define NEW_ITER(v,i,b) rb_node_newnode(NODE_ITER,v,b,i)
|
||||
#define NEW_BREAK() rb_node_newnode(NODE_BREAK,0,0,0)
|
||||
#define NEW_NEXT() rb_node_newnode(NODE_NEXT,0,0,0)
|
||||
#define NEW_BREAK(s) rb_node_newnode(NODE_BREAK,s,0,0)
|
||||
#define NEW_NEXT(s) rb_node_newnode(NODE_NEXT,s,0,0)
|
||||
#define NEW_REDO() rb_node_newnode(NODE_REDO,0,0,0)
|
||||
#define NEW_RETRY() rb_node_newnode(NODE_RETRY,0,0,0)
|
||||
#define NEW_BEGIN(b) rb_node_newnode(NODE_BEGIN,0,b,0)
|
||||
|
|
49
parse.y
49
parse.y
|
@ -426,21 +426,13 @@ expr : kRETURN ret_args
|
|||
yyerror("return appeared outside of method");
|
||||
$$ = NEW_RETURN($2);
|
||||
}
|
||||
| kBREAK
|
||||
| kBREAK ret_args
|
||||
{
|
||||
$$ = NEW_BREAK();
|
||||
$$ = NEW_BREAK($2);
|
||||
}
|
||||
| kNEXT
|
||||
| kNEXT ret_args
|
||||
{
|
||||
$$ = NEW_NEXT();
|
||||
}
|
||||
| kREDO
|
||||
{
|
||||
$$ = NEW_REDO();
|
||||
}
|
||||
| kRETRY
|
||||
{
|
||||
$$ = NEW_RETRY();
|
||||
$$ = NEW_NEXT($2);
|
||||
}
|
||||
| command_call
|
||||
| expr kAND expr
|
||||
|
@ -1142,19 +1134,6 @@ primary : literal
|
|||
{
|
||||
$$ = NEW_HASH($2);
|
||||
}
|
||||
| kRETURN '(' ret_args ')'
|
||||
{
|
||||
if (!compile_for_eval && !in_def && !in_single)
|
||||
yyerror("return appeared outside of method");
|
||||
value_expr($3);
|
||||
$$ = NEW_RETURN($3);
|
||||
}
|
||||
| kRETURN '(' ')'
|
||||
{
|
||||
if (!compile_for_eval && !in_def && !in_single)
|
||||
yyerror("return appeared outside of method");
|
||||
$$ = NEW_RETURN(0);
|
||||
}
|
||||
| kRETURN
|
||||
{
|
||||
if (!compile_for_eval && !in_def && !in_single)
|
||||
|
@ -1359,6 +1338,22 @@ primary : literal
|
|||
local_pop();
|
||||
in_single--;
|
||||
}
|
||||
| kBREAK
|
||||
{
|
||||
$$ = NEW_BREAK(0);
|
||||
}
|
||||
| kNEXT
|
||||
{
|
||||
$$ = NEW_NEXT(0);
|
||||
}
|
||||
| kREDO
|
||||
{
|
||||
$$ = NEW_REDO();
|
||||
}
|
||||
| kRETRY
|
||||
{
|
||||
$$ = NEW_RETRY();
|
||||
}
|
||||
|
||||
then : term
|
||||
| kTHEN
|
||||
|
@ -1399,6 +1394,10 @@ opt_block_var : none
|
|||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| '<' f_args '>'
|
||||
{
|
||||
$$ = (NODE*)2;
|
||||
}
|
||||
|
||||
|
||||
do_block : kDO_BLOCK
|
||||
|
|
|
@ -700,6 +700,8 @@ rb_alias_variable(name1, name2)
|
|||
{
|
||||
struct global_entry *entry1, *entry2;
|
||||
|
||||
if (rb_safe_level() >= 4)
|
||||
rb_raise(rb_eSecurityError, "Insecure: can't alias global variable");
|
||||
entry1 = rb_global_entry(name1);
|
||||
entry2 = rb_global_entry(name2);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#define RUBY_VERSION "1.7.0"
|
||||
#define RUBY_RELEASE_DATE "2001-05-21"
|
||||
#define RUBY_RELEASE_DATE "2001-05-22"
|
||||
#define RUBY_VERSION_CODE 170
|
||||
#define RUBY_RELEASE_CODE 20010521
|
||||
#define RUBY_RELEASE_CODE 20010522
|
||||
|
|
Загрузка…
Ссылка в новой задаче