* 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:
matz 2001-05-22 08:28:11 +00:00
Родитель ed6a2bd29f
Коммит 315cd83418
6 изменённых файлов: 88 добавлений и 48 удалений

Просмотреть файл

@ -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
Просмотреть файл

@ -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
Просмотреть файл

@ -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
Просмотреть файл

@ -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