diff --git a/ChangeLog b/ChangeLog index ee77d16103..af518c6d95 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,20 @@ -2003-04-24 Dave Thomas +Fri Apr 25 02:03:25 2003 Yukihiro Matsumoto + + * eval.c (proc_invoke): Proc#yield should pass through retry and + break like keyword yield. [ruby-talk:70034] + + * eval.c (proc_invoke): orphan Proc now raises LocalJumpError for + break and retry again. + + * eval.c (rb_eval): ARGSCAT should splat the argument. + + * eval.c (splat_value): splat operation function. + +Thu Apr 24 23:37:02 2003 Dave Thomas * lib/matrix.rb (Matrix#minor): Used Range#size, which no longer exists. -2003-04-24 Dave Thomas - * lib/complex.rb (new!): Complex.new had been made private, but Kernel#Complex called it. Re-exposed as new!. @@ -21190,3 +21200,7 @@ Fri Aug 15 19:40:43 1997 WATANABE Hirofumi Wed Aug 13 17:51:46 1997 Yukihiro Matsumoto * version 1.1 alpha0 released. + +Local variables: +add-log-time-format: current-time-string +end: diff --git a/eval.c b/eval.c index f53a1a7b6a..9ce0f1c49f 100644 --- a/eval.c +++ b/eval.c @@ -2244,19 +2244,6 @@ svalue_to_avalue(v) return tmp; } -static VALUE -avalue_splat(v) - VALUE v; -{ - if (RARRAY(v)->len == 0) { - return Qundef; - } - if (RARRAY(v)->len == 1) { - return RARRAY(v)->ptr[0]; - } - return v; -} - static VALUE svalue_to_mrhs(v, lhs) VALUE v; @@ -2276,6 +2263,45 @@ svalue_to_mrhs(v, lhs) return tmp; } +static VALUE +avalue_splat(v) + VALUE v; +{ + if (RARRAY(v)->len == 0) { + return Qundef; + } + if (RARRAY(v)->len == 1) { + return RARRAY(v)->ptr[0]; + } + return v; +} + +static VALUE +splat_value(v) + VALUE v; +{ + if (NIL_P(v)) return rb_ary_new3(1, Qnil); +#if 1 + /* hack to avoid invoke Object#to_a */ + if (TYPE(v) != T_ARRAY) { + VALUE tmp = rb_check_array_type(v); + if (NIL_P(tmp)) { + VALUE origin; + ID id = rb_intern("to_a"); + + if (search_method(CLASS_OF(v), id, &origin) && + origin != RCLASS(rb_cObject)->super) { /* exclude Object#to_a */ + return rb_funcall(v, id, 0); + } + else { + return rb_ary_new3(1, v); + } + } + } +#endif + return avalue_splat(rb_Array(v)); +} + static VALUE class_prefix(self, cpath) VALUE self; @@ -2660,31 +2686,7 @@ rb_eval(self, n) break; case NODE_SPLAT: -#if 0 - /* simplified version after Object#to_a removed */ - result = rb_eval(self, node->nd_head); - if (NIL_P(result)) result = rb_ary_new3(1, Qnil); - result = avalue_splat(rb_Array(result)); -#else - result = rb_eval(self, node->nd_head); - if (NIL_P(result)) result = rb_ary_new3(1, Qnil); - if (TYPE(result) != T_ARRAY) { - VALUE tmp = rb_check_array_type(result); - if (NIL_P(tmp)) { - VALUE origin; - ID id = rb_intern("to_a"); - - if (search_method(CLASS_OF(result), id, &origin) && - origin != RCLASS(rb_cObject)->super) { /* exclude Object#to_a */ - result = rb_funcall(result, id, 0); - } - else { - result = rb_ary_new3(1, result); - } - } - } - result = avalue_splat(rb_Array(result)); -#endif + result = splat_value(rb_eval(self, node->nd_head)); break; case NODE_SVALUE: @@ -2845,7 +2847,7 @@ rb_eval(self, n) case NODE_ARGSCAT: result = rb_ary_concat(rb_eval(self, node->nd_head), - rb_eval(self, node->nd_body)); + splat_value(rb_eval(self, node->nd_body))); break; case NODE_ARGSPUSH: @@ -6736,7 +6738,7 @@ proc_invoke(proc, args, pcall, self) struct BLOCK _block; struct BLOCK *data; volatile VALUE result = Qnil; - int state; + int state, incoming_state; volatile int orphan; volatile int safe = ruby_safe_level; volatile VALUE old_wrapper = ruby_wrapper; @@ -6770,6 +6772,7 @@ proc_invoke(proc, args, pcall, self) POP_TAG(); POP_ITER(); + incoming_state = state; if (ruby_block->tag->dst == state) { state &= TAG_MASK; } @@ -6781,11 +6784,22 @@ proc_invoke(proc, args, pcall, self) switch (state) { case 0: break; - case TAG_BREAK: - result = prot_tag->retval; - break; case TAG_RETRY: - localjump_error("retry from proc-closure", Qnil); + if (pcall || orphan) { + localjump_error("retry from proc-closure", Qnil); + } + /* fall through */ + case TAG_BREAK: + if (pcall) { + result = prot_tag->retval; + } + else if (orphan) { + localjump_error("break from proc-closure", prot_tag->retval); + } + else { + ruby_block->tag->dst = incoming_state; + JUMP_TAG(incoming_state); + } break; case TAG_RETURN: if (orphan) { /* orphan procedure */