diff options
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | eval.c | 92 | ||||
-rw-r--r-- | gc.c | 4 | ||||
-rw-r--r-- | parse.y | 93 | ||||
-rw-r--r-- | ruby.h | 1 |
5 files changed, 121 insertions, 90 deletions
@@ -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> * 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> * parse.y (yylex): fixed serious syntax misbehavior. do's @@ -527,14 +527,20 @@ static struct SCOPE *top_scope; ruby_sourceline = _frame.line; \ ruby_frame = _frame.prev; } +struct BLOCKTAG { + struct RBasic super; + long dst; + long flags; +}; + struct BLOCK { NODE *var; NODE *body; VALUE self; struct FRAME frame; struct SCOPE *scope; + struct BLOCKTAG *tag; VALUE klass; - struct tag *tag; int iter; int vmode; int flags; @@ -545,12 +551,23 @@ struct BLOCK { #define BLOCK_D_SCOPE 1 #define BLOCK_DYNAMIC 2 +#define BLOCK_ORPHAN 4 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) { \ struct BLOCK _block; \ - _block.tag = prot_tag; \ + _block.tag = new_blktag(); \ _block.var = v; \ _block.body = b; \ _block.self = self; \ @@ -567,6 +584,7 @@ static struct BLOCK *ruby_block; ruby_block = &_block; #define POP_BLOCK() \ + _block.tag->flags |= BLOCK_ORPHAN; \ ruby_block = _block.prev; \ } @@ -576,6 +594,7 @@ static struct BLOCK *ruby_block; ruby_block = b; #define POP_BLOCK2() \ + _block.tag->flags |= BLOCK_ORPHAN; \ ruby_block = _old; \ } @@ -1051,7 +1070,7 @@ static int error_handle(ex) int ex; { - switch (ex & 0xf) { + switch (ex & TAG_MASK) { case 0: ex = 0; break; @@ -2213,8 +2232,8 @@ rb_eval(self, n) case NODE_FOR: { iter_retry: - PUSH_BLOCK(node->nd_var, node->nd_body); PUSH_TAG(PROT_FUNC); + PUSH_BLOCK(node->nd_var, node->nd_body); state = EXEC_TAG(); if (state == 0) { @@ -2243,8 +2262,8 @@ rb_eval(self, n) result = prot_tag->retval; } } - POP_TAG(); POP_BLOCK(); + POP_TAG(); switch (state) { case 0: break; @@ -3554,7 +3573,7 @@ rb_yield_0(val, self, klass, acheck) case TAG_RETURN: state |= (serial++ << 8); state |= 0x10; - block->tag->dst = state; + block->tag->dst = state; break; default: break; @@ -3584,7 +3603,19 @@ rb_yield_0(val, self, klass, acheck) if (ruby_scope->flag & SCOPE_DONT_RECYCLE) scope_dup(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; } @@ -6087,7 +6118,6 @@ proc_new(klass) data->orig_thread = rb_thread_current(); data->iter = data->prev?Qtrue:Qfalse; - data->tag = 0; /* should not point into stack */ frame_dup(&data->frame); if (data->iter) { blk_copy_prev(data); @@ -6131,8 +6161,10 @@ static int blk_orphan(data) struct BLOCK *data; { - if (data->scope && data->scope != top_scope && - (data->scope->flag & SCOPE_NOSTACK)) { + if (!(data->scope->flag & SCOPE_NOSTACK)) { + return 0; + } + if ((data->tag->flags & BLOCK_ORPHAN)) { return 1; } if (data->orig_thread != rb_thread_current()) { @@ -6196,7 +6228,6 @@ proc_call(proc, args) } PUSH_TAG(PROT_NONE); - _block.tag = prot_tag; state = EXEC_TAG(); if (state == 0) { proc_set_safe_level(proc); @@ -6292,7 +6323,6 @@ block_pass(self, node) ruby_frame->iter = ITER_PRE; PUSH_TAG(PROT_NONE); - _block.tag = prot_tag; state = EXEC_TAG(); if (state == 0) { proc_set_safe_level(block); @@ -6301,38 +6331,30 @@ block_pass(self, node) POP_TAG(); POP_ITER(); if (_block.tag->dst == state) { - if (orphan) { - state &= TAG_MASK; - } - else { - struct BLOCK *ptr = old_block; - - while (ptr) { - if (ptr->scope == _block.scope) { - ptr->tag->dst = state; - break; - } - ptr = ptr->prev; - } - } + state &= TAG_MASK; } ruby_block = old_block; ruby_safe_level = safe; - if (state) { - switch (state) {/* escape from orphan procedure */ - case TAG_BREAK: - rb_raise(rb_eLocalJumpError, "break from proc-closure"); - break; - case TAG_RETRY: + switch (state) {/* escape from orphan procedure */ + case 0: + break; + case TAG_BREAK: + if (orphan) { rb_raise(rb_eLocalJumpError, "retry from proc-closure"); - break; - case TAG_RETURN: + } + 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"); - break; } + default: JUMP_TAG(state); } + return result; } @@ -610,6 +610,7 @@ rb_gc_mark(ptr) case T_REGEXP: case T_FLOAT: case T_BIGNUM: + case T_BLKTAG: break; case T_MATCH: @@ -826,6 +827,7 @@ obj_free(obj) case T_FLOAT: case T_VARMAP: + case T_BLKTAG: break; case T_BIGNUM: @@ -1048,6 +1050,7 @@ os_live_obj() case T_CLASS: if (FL_TEST(p, FL_SINGLETON)) continue; default: + if (!p->as.basic.klass) continue; rb_yield((VALUE)p); n++; } @@ -1080,6 +1083,7 @@ os_obj_of(of) case T_CLASS: if (FL_TEST(p, FL_SINGLETON)) continue; default: + if (!p->as.basic.klass) continue; if (rb_obj_is_kind_of((VALUE)p, of)) { rb_yield((VALUE)p); n++; @@ -49,7 +49,6 @@ static int yyerror(); static enum lex_state { EXPR_BEG, /* ignore newline, +/- is a sign. */ EXPR_END, /* newline significant, +/- is a operator. */ - EXPR_PAREN, /* almost like EXPR_END, `do' works as `{'. */ EXPR_ARG, /* newline significant, +/- is a operator. */ EXPR_MID, /* newline significant, +/- is a operator. */ EXPR_FNAME, /* ignore newline, no reserved words. */ @@ -186,9 +185,9 @@ static void top_local_setup(); %type <val> literal numeric %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> 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> 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> assoc_list assocs assoc undef_list backref %type <node> block_var opt_block_var brace_block do_block lhs none @@ -445,15 +444,15 @@ expr : mlhs '=' mrhs | arg command_call : command - | blocklike_call + | block_call -blocklike_call : block_call - | block_call '.' operation2 call_args +block_call : call_block + | call_block '.' operation2 call_args { value_expr($1); $$ = new_call($1, $3, $4); } - | block_call tCOLON2 operation2 call_args + | call_block tCOLON2 operation2 call_args { value_expr($1); $$ = new_call($1, $3, $4); @@ -930,16 +929,25 @@ aref_args : none $$ = NEW_RESTARGS($2); } -opt_call_args : none - | call_args opt_nl - | blocklike_call opt_nl +paren_args : '(' none ')' { - $$ = 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 { @@ -1416,7 +1424,7 @@ generic_call : tIDENTIFIER | command_call -block_call : generic_call do_block +call_block : generic_call do_block { if ($1 && nd_type($1) == NODE_BLOCK_PASS) { rb_compile_error("both block arg and actual block given"); @@ -1425,48 +1433,32 @@ block_call : generic_call do_block $$ = $2; fixpos($$, $2); } - | block_call '.' operation2 + | call_block '.' operation2 opt_paren_args { value_expr($1); - $$ = new_call($1, $3, 0); - } - | block_call '.' operation2 '(' opt_call_args close_paren - { - value_expr($1); - $$ = new_call($1, $3, $5); - } - | block_call tCOLON2 operation2 - { - value_expr($1); - $$ = new_call($1, $3, 0); + $$ = new_call($1, $3, $4); } - | block_call tCOLON2 operation2 '(' opt_call_args close_paren + | call_block tCOLON2 operation2 opt_paren_args { value_expr($1); - $$ = new_call($1, $3, $5); + $$ = new_call($1, $3, $4); } -method_call : operation '(' opt_call_args close_paren - { - $$ = new_fcall($1, $3); - fixpos($$, $3); - } - | primary '.' operation2 '(' opt_call_args close_paren +method_call : operation paren_args { - value_expr($1); - $$ = new_call($1, $3, $5); - fixpos($$, $1); + $$ = new_fcall($1, $2); + fixpos($$, $2); } - | primary '.' operation2 + | primary '.' operation2 opt_paren_args { value_expr($1); - $$ = new_call($1, $3, 0); + $$ = new_call($1, $3, $4); fixpos($$, $1); } - | primary tCOLON2 operation2 '(' opt_call_args close_paren + | primary tCOLON2 operation2 paren_args { value_expr($1); - $$ = new_call($1, $3, $5); + $$ = new_call($1, $3, $4); fixpos($$, $1); } | primary tCOLON2 operation3 @@ -1474,12 +1466,12 @@ method_call : operation '(' opt_call_args close_paren value_expr($1); $$ = new_call($1, $3, 0); } - | kSUPER '(' opt_call_args close_paren + | kSUPER paren_args { if (!compile_for_eval && !cur_mid && !in_single && !in_defined) yyerror("super called outside of method"); - $$ = new_super($3); + $$ = new_super($2); } | kSUPER { @@ -1489,11 +1481,6 @@ method_call : operation '(' opt_call_args close_paren $$ = NEW_ZSUPER(); } -close_paren : ')' - { - if (!COND_P()) lex_state = EXPR_PAREN; - } - case_body : kWHEN when_args then compstmt cases @@ -1848,8 +1835,6 @@ none : /* none */ #include "regex.h" #include "util.h" -#define enc ruby_default_encoding - /* We remove any previous definition of `SIGN_EXTEND_CHAR', since ours (we hope) works properly with all combinations of machines, compilers, `char' and `unsigned char' argument types. @@ -2919,8 +2904,7 @@ yylex() case '<': c = nextc(); if (c == '<' && - lex_state != EXPR_END && lex_state != EXPR_PAREN && - lex_state != EXPR_CLASS && + lex_state != EXPR_END && lex_state != EXPR_CLASS && (lex_state != EXPR_ARG || space_seen)) { int c2 = nextc(); int indent = 0; @@ -2979,7 +2963,7 @@ yylex() return parse_qstring(c,0); case '?': - if (lex_state == EXPR_END || lex_state == EXPR_PAREN) { + if (lex_state == EXPR_END) { lex_state = EXPR_BEG; return '?'; } @@ -3306,7 +3290,7 @@ yylex() return tCOLON2; } pushback(c); - if (lex_state == EXPR_END || lex_state == EXPR_PAREN || ISSPACE(c)) { + if (lex_state == EXPR_END || ISSPACE(c)) { lex_state = EXPR_BEG; return ':'; } @@ -3391,7 +3375,6 @@ yylex() case '{': if (lex_state != EXPR_END && - lex_state != EXPR_PAREN && lex_state != EXPR_ARG) c = tLBRACE; lex_state = EXPR_BEG; @@ -162,6 +162,7 @@ VALUE rb_uint2inum _((unsigned long)); #define T_MATCH 0x23 #define T_SYMBOL 0x24 +#define T_BLKTAG 0x3b #define T_UNDEF 0x3c #define T_VARMAP 0x3d #define T_SCOPE 0x3e |