* gc.c (os_live_obj): do not list terminated object.

* gc.c (os_obj_of): ditto.

* gc.c (rb_gc_mark): support new T_BLKTAG tag.

* gc.c (obj_free): ditto.

* eval.c (new_blktag): creation of new block tag, which holds
  destination of global jump and orphan status.

* eval.c (block_pass): break from orphan Proc object will raise a
  LocalJumpError exception.

* eval.c (block_pass): behavior consistency with proc_call(). do
  not propagate `break'.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1145 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2001-01-23 08:08:59 +00:00
parent 9d0bba43bb
commit 7635ff6a05
5 changed files with 122 additions and 91 deletions

View File

@ -1,7 +1,28 @@
Tue Jan 23 16:10:12 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
* gc.c (os_live_obj): do not list terminated object.
* gc.c (os_obj_of): ditto.
* gc.c (rb_gc_mark): support new T_BLKTAG tag.
* gc.c (obj_free): ditto.
* eval.c (new_blktag): creation of new block tag, which holds
destination of global jump and orphan status.
* eval.c (block_pass): break from orphan Proc object will raise a
LocalJumpError exception.
Mon Jan 22 16:33:16 2001 WATANABE Hirofumi <eban@ruby-lang.org> Mon Jan 22 16:33:16 2001 WATANABE Hirofumi <eban@ruby-lang.org>
* mkconfig.rb: autoconf 2.49 support. * mkconfig.rb: autoconf 2.49 support.
Mon Jan 22 00:32:44 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
* eval.c (block_pass): behavior consistency with proc_call(). do
not propagate `break'.
Sat Jan 20 03:54:00 2001 Yukihiro Matsumoto <matz@ruby-lang.org> Sat Jan 20 03:54:00 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
* parse.y (yylex): fixed serious syntax misbehavior. do's * parse.y (yylex): fixed serious syntax misbehavior. do's

94
eval.c
View File

@ -527,14 +527,20 @@ static struct SCOPE *top_scope;
ruby_sourceline = _frame.line; \ ruby_sourceline = _frame.line; \
ruby_frame = _frame.prev; } ruby_frame = _frame.prev; }
struct BLOCKTAG {
struct RBasic super;
long dst;
long flags;
};
struct BLOCK { struct BLOCK {
NODE *var; NODE *var;
NODE *body; NODE *body;
VALUE self; VALUE self;
struct FRAME frame; struct FRAME frame;
struct SCOPE *scope; struct SCOPE *scope;
struct BLOCKTAG *tag;
VALUE klass; VALUE klass;
struct tag *tag;
int iter; int iter;
int vmode; int vmode;
int flags; int flags;
@ -545,12 +551,23 @@ struct BLOCK {
#define BLOCK_D_SCOPE 1 #define BLOCK_D_SCOPE 1
#define BLOCK_DYNAMIC 2 #define BLOCK_DYNAMIC 2
#define BLOCK_ORPHAN 4
static struct BLOCK *ruby_block; static struct BLOCK *ruby_block;
static struct BLOCKTAG*
new_blktag()
{
NEWOBJ(blktag, struct BLOCKTAG);
OBJSETUP(blktag, 0, T_BLKTAG);
blktag->dst = 0;
blktag->flags = 0;
return blktag;
}
#define PUSH_BLOCK(v,b) { \ #define PUSH_BLOCK(v,b) { \
struct BLOCK _block; \ struct BLOCK _block; \
_block.tag = prot_tag; \ _block.tag = new_blktag(); \
_block.var = v; \ _block.var = v; \
_block.body = b; \ _block.body = b; \
_block.self = self; \ _block.self = self; \
@ -567,6 +584,7 @@ static struct BLOCK *ruby_block;
ruby_block = &_block; ruby_block = &_block;
#define POP_BLOCK() \ #define POP_BLOCK() \
_block.tag->flags |= BLOCK_ORPHAN; \
ruby_block = _block.prev; \ ruby_block = _block.prev; \
} }
@ -576,6 +594,7 @@ static struct BLOCK *ruby_block;
ruby_block = b; ruby_block = b;
#define POP_BLOCK2() \ #define POP_BLOCK2() \
_block.tag->flags |= BLOCK_ORPHAN; \
ruby_block = _old; \ ruby_block = _old; \
} }
@ -1051,7 +1070,7 @@ static int
error_handle(ex) error_handle(ex)
int ex; int ex;
{ {
switch (ex & 0xf) { switch (ex & TAG_MASK) {
case 0: case 0:
ex = 0; ex = 0;
break; break;
@ -2213,8 +2232,8 @@ rb_eval(self, n)
case NODE_FOR: case NODE_FOR:
{ {
iter_retry: iter_retry:
PUSH_BLOCK(node->nd_var, node->nd_body);
PUSH_TAG(PROT_FUNC); PUSH_TAG(PROT_FUNC);
PUSH_BLOCK(node->nd_var, node->nd_body);
state = EXEC_TAG(); state = EXEC_TAG();
if (state == 0) { if (state == 0) {
@ -2243,8 +2262,8 @@ rb_eval(self, n)
result = prot_tag->retval; result = prot_tag->retval;
} }
} }
POP_TAG();
POP_BLOCK(); POP_BLOCK();
POP_TAG();
switch (state) { switch (state) {
case 0: case 0:
break; break;
@ -3554,7 +3573,7 @@ rb_yield_0(val, self, klass, acheck)
case TAG_RETURN: case TAG_RETURN:
state |= (serial++ << 8); state |= (serial++ << 8);
state |= 0x10; state |= 0x10;
block->tag->dst = state; block->tag->dst = state;
break; break;
default: default:
break; break;
@ -3584,7 +3603,19 @@ rb_yield_0(val, self, klass, acheck)
if (ruby_scope->flag & SCOPE_DONT_RECYCLE) if (ruby_scope->flag & SCOPE_DONT_RECYCLE)
scope_dup(old_scope); scope_dup(old_scope);
ruby_scope = old_scope; ruby_scope = old_scope;
if (state) JUMP_TAG(state); if (state) {
if (!block->tag) {
switch (state & TAG_MASK) {
case TAG_BREAK:
rb_raise(rb_eLocalJumpError, "unexpected break");
break;
case TAG_RETURN:
rb_raise(rb_eLocalJumpError, "unexpected return");
break;
}
}
JUMP_TAG(state);
}
return result; return result;
} }
@ -6087,7 +6118,6 @@ proc_new(klass)
data->orig_thread = rb_thread_current(); data->orig_thread = rb_thread_current();
data->iter = data->prev?Qtrue:Qfalse; data->iter = data->prev?Qtrue:Qfalse;
data->tag = 0; /* should not point into stack */
frame_dup(&data->frame); frame_dup(&data->frame);
if (data->iter) { if (data->iter) {
blk_copy_prev(data); blk_copy_prev(data);
@ -6131,8 +6161,10 @@ static int
blk_orphan(data) blk_orphan(data)
struct BLOCK *data; struct BLOCK *data;
{ {
if (data->scope && data->scope != top_scope && if (!(data->scope->flag & SCOPE_NOSTACK)) {
(data->scope->flag & SCOPE_NOSTACK)) { return 0;
}
if ((data->tag->flags & BLOCK_ORPHAN)) {
return 1; return 1;
} }
if (data->orig_thread != rb_thread_current()) { if (data->orig_thread != rb_thread_current()) {
@ -6196,7 +6228,6 @@ proc_call(proc, args)
} }
PUSH_TAG(PROT_NONE); PUSH_TAG(PROT_NONE);
_block.tag = prot_tag;
state = EXEC_TAG(); state = EXEC_TAG();
if (state == 0) { if (state == 0) {
proc_set_safe_level(proc); proc_set_safe_level(proc);
@ -6292,7 +6323,6 @@ block_pass(self, node)
ruby_frame->iter = ITER_PRE; ruby_frame->iter = ITER_PRE;
PUSH_TAG(PROT_NONE); PUSH_TAG(PROT_NONE);
_block.tag = prot_tag;
state = EXEC_TAG(); state = EXEC_TAG();
if (state == 0) { if (state == 0) {
proc_set_safe_level(block); proc_set_safe_level(block);
@ -6301,38 +6331,30 @@ block_pass(self, node)
POP_TAG(); POP_TAG();
POP_ITER(); POP_ITER();
if (_block.tag->dst == state) { if (_block.tag->dst == state) {
if (orphan) { state &= TAG_MASK;
state &= TAG_MASK;
}
else {
struct BLOCK *ptr = old_block;
while (ptr) {
if (ptr->scope == _block.scope) {
ptr->tag->dst = state;
break;
}
ptr = ptr->prev;
}
}
} }
ruby_block = old_block; ruby_block = old_block;
ruby_safe_level = safe; ruby_safe_level = safe;
if (state) { switch (state) {/* escape from orphan procedure */
switch (state) {/* escape from orphan procedure */ case 0:
case TAG_BREAK: break;
rb_raise(rb_eLocalJumpError, "break from proc-closure"); case TAG_BREAK:
break; if (orphan) {
case TAG_RETRY:
rb_raise(rb_eLocalJumpError, "retry from proc-closure"); rb_raise(rb_eLocalJumpError, "retry from proc-closure");
break;
case TAG_RETURN:
rb_raise(rb_eLocalJumpError, "return from proc-closure");
break;
} }
break;
case TAG_RETRY:
rb_raise(rb_eLocalJumpError, "retry from proc-closure");
break;
case TAG_RETURN:
if (orphan) {
rb_raise(rb_eLocalJumpError, "return from proc-closure");
}
default:
JUMP_TAG(state); JUMP_TAG(state);
} }
return result; return result;
} }

4
gc.c
View File

@ -610,6 +610,7 @@ rb_gc_mark(ptr)
case T_REGEXP: case T_REGEXP:
case T_FLOAT: case T_FLOAT:
case T_BIGNUM: case T_BIGNUM:
case T_BLKTAG:
break; break;
case T_MATCH: case T_MATCH:
@ -826,6 +827,7 @@ obj_free(obj)
case T_FLOAT: case T_FLOAT:
case T_VARMAP: case T_VARMAP:
case T_BLKTAG:
break; break;
case T_BIGNUM: case T_BIGNUM:
@ -1048,6 +1050,7 @@ os_live_obj()
case T_CLASS: case T_CLASS:
if (FL_TEST(p, FL_SINGLETON)) continue; if (FL_TEST(p, FL_SINGLETON)) continue;
default: default:
if (!p->as.basic.klass) continue;
rb_yield((VALUE)p); rb_yield((VALUE)p);
n++; n++;
} }
@ -1080,6 +1083,7 @@ os_obj_of(of)
case T_CLASS: case T_CLASS:
if (FL_TEST(p, FL_SINGLETON)) continue; if (FL_TEST(p, FL_SINGLETON)) continue;
default: default:
if (!p->as.basic.klass) continue;
if (rb_obj_is_kind_of((VALUE)p, of)) { if (rb_obj_is_kind_of((VALUE)p, of)) {
rb_yield((VALUE)p); rb_yield((VALUE)p);
n++; n++;

93
parse.y
View File

@ -49,7 +49,6 @@ static int yyerror();
static enum lex_state { static enum lex_state {
EXPR_BEG, /* ignore newline, +/- is a sign. */ EXPR_BEG, /* ignore newline, +/- is a sign. */
EXPR_END, /* newline significant, +/- is a operator. */ EXPR_END, /* newline significant, +/- is a operator. */
EXPR_PAREN, /* almost like EXPR_END, `do' works as `{'. */
EXPR_ARG, /* newline significant, +/- is a operator. */ EXPR_ARG, /* newline significant, +/- is a operator. */
EXPR_MID, /* newline significant, +/- is a operator. */ EXPR_MID, /* newline significant, +/- is a operator. */
EXPR_FNAME, /* ignore newline, no reserved words. */ EXPR_FNAME, /* ignore newline, no reserved words. */
@ -186,9 +185,9 @@ static void top_local_setup();
%type <val> literal numeric %type <val> literal numeric
%type <node> compstmt stmts stmt expr arg primary command command_call method_call %type <node> compstmt stmts stmt expr arg primary command command_call method_call
%type <node> if_tail opt_else case_body cases rescue exc_list exc_var ensure %type <node> if_tail opt_else case_body cases rescue exc_list exc_var ensure
%type <node> opt_call_args call_args ret_args args when_args %type <node> args ret_args when_args call_args paren_args opt_paren_args
%type <node> aref_args opt_block_arg block_arg var_ref %type <node> aref_args opt_block_arg block_arg var_ref
%type <node> mrhs mrhs_basic superclass generic_call block_call blocklike_call %type <node> mrhs mrhs_basic superclass generic_call block_call call_block
%type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg %type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
%type <node> assoc_list assocs assoc undef_list backref %type <node> assoc_list assocs assoc undef_list backref
%type <node> block_var opt_block_var brace_block do_block lhs none %type <node> block_var opt_block_var brace_block do_block lhs none
@ -445,15 +444,15 @@ expr : mlhs '=' mrhs
| arg | arg
command_call : command command_call : command
| blocklike_call | block_call
blocklike_call : block_call block_call : call_block
| block_call '.' operation2 call_args | call_block '.' operation2 call_args
{ {
value_expr($1); value_expr($1);
$$ = new_call($1, $3, $4); $$ = new_call($1, $3, $4);
} }
| block_call tCOLON2 operation2 call_args | call_block tCOLON2 operation2 call_args
{ {
value_expr($1); value_expr($1);
$$ = new_call($1, $3, $4); $$ = new_call($1, $3, $4);
@ -930,16 +929,25 @@ aref_args : none
$$ = NEW_RESTARGS($2); $$ = NEW_RESTARGS($2);
} }
opt_call_args : none paren_args : '(' none ')'
| call_args opt_nl
| blocklike_call opt_nl
{ {
$$ = NEW_LIST($1); $$ = $2;
} }
| args ',' blocklike_call | '(' call_args opt_nl ')'
{ {
$$ = list_append($1, $3); $$ = $2;
} }
| '(' block_call opt_nl ')'
{
$$ = NEW_LIST($2);
}
| '(' args ',' block_call opt_nl ')'
{
$$ = list_append($2, $4);
}
opt_paren_args : none
| paren_args
call_args : command call_args : command
{ {
@ -1416,7 +1424,7 @@ generic_call : tIDENTIFIER
| command_call | command_call
block_call : generic_call do_block call_block : generic_call do_block
{ {
if ($1 && nd_type($1) == NODE_BLOCK_PASS) { if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
rb_compile_error("both block arg and actual block given"); rb_compile_error("both block arg and actual block given");
@ -1425,48 +1433,32 @@ block_call : generic_call do_block
$$ = $2; $$ = $2;
fixpos($$, $2); fixpos($$, $2);
} }
| block_call '.' operation2 | call_block '.' operation2 opt_paren_args
{ {
value_expr($1); value_expr($1);
$$ = new_call($1, $3, 0); $$ = new_call($1, $3, $4);
} }
| block_call '.' operation2 '(' opt_call_args close_paren | call_block tCOLON2 operation2 opt_paren_args
{ {
value_expr($1); value_expr($1);
$$ = new_call($1, $3, $5); $$ = new_call($1, $3, $4);
}
| block_call tCOLON2 operation2
{
value_expr($1);
$$ = new_call($1, $3, 0);
}
| block_call tCOLON2 operation2 '(' opt_call_args close_paren
{
value_expr($1);
$$ = new_call($1, $3, $5);
} }
method_call : operation '(' opt_call_args close_paren method_call : operation paren_args
{ {
$$ = new_fcall($1, $3); $$ = new_fcall($1, $2);
fixpos($$, $3); fixpos($$, $2);
} }
| primary '.' operation2 '(' opt_call_args close_paren | primary '.' operation2 opt_paren_args
{ {
value_expr($1); value_expr($1);
$$ = new_call($1, $3, $5); $$ = new_call($1, $3, $4);
fixpos($$, $1); fixpos($$, $1);
} }
| primary '.' operation2 | primary tCOLON2 operation2 paren_args
{ {
value_expr($1); value_expr($1);
$$ = new_call($1, $3, 0); $$ = new_call($1, $3, $4);
fixpos($$, $1);
}
| primary tCOLON2 operation2 '(' opt_call_args close_paren
{
value_expr($1);
$$ = new_call($1, $3, $5);
fixpos($$, $1); fixpos($$, $1);
} }
| primary tCOLON2 operation3 | primary tCOLON2 operation3
@ -1474,12 +1466,12 @@ method_call : operation '(' opt_call_args close_paren
value_expr($1); value_expr($1);
$$ = new_call($1, $3, 0); $$ = new_call($1, $3, 0);
} }
| kSUPER '(' opt_call_args close_paren | kSUPER paren_args
{ {
if (!compile_for_eval && !cur_mid && if (!compile_for_eval && !cur_mid &&
!in_single && !in_defined) !in_single && !in_defined)
yyerror("super called outside of method"); yyerror("super called outside of method");
$$ = new_super($3); $$ = new_super($2);
} }
| kSUPER | kSUPER
{ {
@ -1489,11 +1481,6 @@ method_call : operation '(' opt_call_args close_paren
$$ = NEW_ZSUPER(); $$ = NEW_ZSUPER();
} }
close_paren : ')'
{
if (!COND_P()) lex_state = EXPR_PAREN;
}
case_body : kWHEN when_args then case_body : kWHEN when_args then
compstmt compstmt
cases cases
@ -1848,8 +1835,6 @@ none : /* none */
#include "regex.h" #include "regex.h"
#include "util.h" #include "util.h"
#define enc ruby_default_encoding
/* We remove any previous definition of `SIGN_EXTEND_CHAR', /* We remove any previous definition of `SIGN_EXTEND_CHAR',
since ours (we hope) works properly with all combinations of since ours (we hope) works properly with all combinations of
machines, compilers, `char' and `unsigned char' argument types. machines, compilers, `char' and `unsigned char' argument types.
@ -2919,8 +2904,7 @@ yylex()
case '<': case '<':
c = nextc(); c = nextc();
if (c == '<' && if (c == '<' &&
lex_state != EXPR_END && lex_state != EXPR_PAREN && lex_state != EXPR_END && lex_state != EXPR_CLASS &&
lex_state != EXPR_CLASS &&
(lex_state != EXPR_ARG || space_seen)) { (lex_state != EXPR_ARG || space_seen)) {
int c2 = nextc(); int c2 = nextc();
int indent = 0; int indent = 0;
@ -2979,7 +2963,7 @@ yylex()
return parse_qstring(c,0); return parse_qstring(c,0);
case '?': case '?':
if (lex_state == EXPR_END || lex_state == EXPR_PAREN) { if (lex_state == EXPR_END) {
lex_state = EXPR_BEG; lex_state = EXPR_BEG;
return '?'; return '?';
} }
@ -3306,7 +3290,7 @@ yylex()
return tCOLON2; return tCOLON2;
} }
pushback(c); pushback(c);
if (lex_state == EXPR_END || lex_state == EXPR_PAREN || ISSPACE(c)) { if (lex_state == EXPR_END || ISSPACE(c)) {
lex_state = EXPR_BEG; lex_state = EXPR_BEG;
return ':'; return ':';
} }
@ -3391,7 +3375,6 @@ yylex()
case '{': case '{':
if (lex_state != EXPR_END && if (lex_state != EXPR_END &&
lex_state != EXPR_PAREN &&
lex_state != EXPR_ARG) lex_state != EXPR_ARG)
c = tLBRACE; c = tLBRACE;
lex_state = EXPR_BEG; lex_state = EXPR_BEG;

1
ruby.h
View File

@ -162,6 +162,7 @@ VALUE rb_uint2inum _((unsigned long));
#define T_MATCH 0x23 #define T_MATCH 0x23
#define T_SYMBOL 0x24 #define T_SYMBOL 0x24
#define T_BLKTAG 0x3b
#define T_UNDEF 0x3c #define T_UNDEF 0x3c
#define T_VARMAP 0x3d #define T_VARMAP 0x3d
#define T_SCOPE 0x3e #define T_SCOPE 0x3e