From 7e35911e105409fabe48dc2a6214479b6a6ffa24 Mon Sep 17 00:00:00 2001 From: matz Date: Mon, 19 May 2003 15:45:46 +0000 Subject: * ext/pty/pty.c (pty_finalize_syswait): join (using Thread#value) before detach pid. [ruby-talk:71519] * eval.c (PUSH_FRAME): save outer ruby_block. [ruby-list:37677], [ruby-dev:20202] * eval.c (BEGIN_CALLARGS): restore outer block by using ruby_block->outer. * eval.c (block_pass): do not alter block->prev, but block->outer. * array.c (get_inspect_tbl): warning on wrong condition. * eval.c (localjump_xvalue): renamed exitstatus to exit_value since it's not exit "status" after all. * eval.c (localjump_error): add reason to LocalJumpError. * compar.c (rb_cmpint): raise error via rb_cmperr(), if cmp value is nil. now take new 2 arguments. * time.c (time_cmp): 2003-05-16 fix was incomplete. (ruby-bugs-ja:PR#458) git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3823 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 31 +++++++++++++++++++++++++++++ array.c | 14 +++++++------ compar.c | 19 ++++++++++-------- enum.c | 25 +++++++++++++---------- eval.c | 62 ++++++++++++++++++++++++++++++++++++++++++---------------- ext/pty/pty.c | 3 ++- intern.h | 2 +- range.c | 6 +++--- sample/test.rb | 27 +++++++++++++++++++++++++ time.c | 28 ++++++-------------------- 10 files changed, 149 insertions(+), 68 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1b659eb6a0..cf2ed3a8a6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +Tue May 20 00:09:41 2003 Yukihiro Matsumoto + + * ext/pty/pty.c (pty_finalize_syswait): join (using Thread#value) + before detach pid. [ruby-talk:71519] + +Mon May 19 23:02:10 2003 Yukihiro Matsumoto + + * eval.c (PUSH_FRAME): save outer ruby_block. [ruby-list:37677], + [ruby-dev:20202] + + * eval.c (BEGIN_CALLARGS): restore outer block by using + ruby_block->outer. + + * eval.c (block_pass): do not alter block->prev, but block->outer. + + * array.c (get_inspect_tbl): warning on wrong condition. + Mon May 19 16:13:57 2003 Minero Aoki * class.c: add #include "version.h". @@ -6,6 +23,19 @@ Mon May 19 16:13:57 2003 Minero Aoki * string.c: ditto. +Mon May 19 15:33:27 2003 Yukihiro Matsumoto + + * eval.c (localjump_xvalue): renamed exitstatus to exit_value + since it's not exit "status" after all. + + * eval.c (localjump_error): add reason to LocalJumpError. + + * compar.c (rb_cmpint): raise error via rb_cmperr(), if cmp value + is nil. now take new 2 arguments. + + * time.c (time_cmp): 2003-05-16 fix was incomplete. + (ruby-bugs-ja:PR#458) + Mon May 19 14:42:50 2003 Yukihiro Matsumoto * object.c (rb_mod_cmp): stupid comparison fixed. @@ -76,6 +106,7 @@ Fri May 16 23:55:50 2003 Yukihiro Matsumoto Fri May 16 12:40:40 2003 Yukihiro Matsumoto * eval.c (block_pass): chain previous block to the pushing block. + [ruby-list:37677] * time.c (time_cmp): does not compare with numbers for interchangeability. (ruby-bugs-ja:PR#458) diff --git a/array.c b/array.c index c557ab2d15..d53bf496d2 100644 --- a/array.c +++ b/array.c @@ -935,10 +935,12 @@ get_inspect_tbl(create) { VALUE inspect_tbl = rb_thread_local_aref(rb_thread_current(), inspect_key); - if (create && NIL_P(inspect_tbl)) { - tbl_init: - inspect_tbl = rb_ary_new(); - rb_thread_local_aset(rb_thread_current(), inspect_key, inspect_tbl); + if (NIL_P(inspect_tbl)) { + if (create) { + tbl_init: + inspect_tbl = rb_ary_new(); + rb_thread_local_aset(rb_thread_current(), inspect_key, inspect_tbl); + } } else if (TYPE(inspect_tbl) != T_ARRAY) { rb_warn("invalid inspect_tbl value"); @@ -1084,7 +1086,7 @@ sort_1(a, b) VALUE *a, *b; { VALUE retval = rb_yield(rb_assoc_new(*a, *b)); - return rb_cmpint(retval); + return rb_cmpint(retval, *a, *b); } static int @@ -1104,7 +1106,7 @@ sort_2(ap, bp) } retval = rb_funcall(a, id_cmp, 1, b); - return rb_cmpint(retval); + return rb_cmpint(retval, a, b); } static VALUE diff --git a/compar.c b/compar.c index bb90125bff..d6cca36137 100644 --- a/compar.c +++ b/compar.c @@ -17,9 +17,12 @@ VALUE rb_mComparable; static ID cmp; int -rb_cmpint(val) - VALUE val; +rb_cmpint(val, a, b) + VALUE val, a, b; { + if (NIL_P(val)) { + rb_cmperr(a, b); + } if (FIXNUM_P(val)) return FIX2INT(val); if (TYPE(val) == T_BIGNUM) { if (RBIGNUM(val)->sign) return 1; @@ -43,7 +46,7 @@ rb_cmperr(x, y) else { classname = rb_obj_classname(y); } - rb_raise(rb_eArgError, "comparison of %s to %s failed", + rb_raise(rb_eArgError, "comparison of %s with %s failed", rb_obj_classname(x), classname); } @@ -60,7 +63,7 @@ cmp_equal(x, y) c = rb_funcall(x, cmp, 1, y); if (NIL_P(c)) return Qnil; if (c == INT2FIX(0)) return Qtrue; - if (rb_cmpint(c) == 0) return Qtrue; + if (rb_cmpint(c, x, y) == 0) return Qtrue; return Qfalse; } @@ -71,7 +74,7 @@ cmp_gt(x, y) VALUE c = rb_funcall(x, cmp, 1, y); if (NIL_P(c)) return cmperr(); - if (rb_cmpint(c) > 0) return Qtrue; + if (rb_cmpint(c, x, y) > 0) return Qtrue; return Qfalse; } @@ -82,7 +85,7 @@ cmp_ge(x, y) VALUE c = rb_funcall(x, cmp, 1, y); if (NIL_P(c)) return cmperr(); - if (rb_cmpint(c) >= 0) return Qtrue; + if (rb_cmpint(c, x, y) >= 0) return Qtrue; return Qfalse; } @@ -93,7 +96,7 @@ cmp_lt(x, y) VALUE c = rb_funcall(x, cmp, 1, y); if (NIL_P(c)) return cmperr(); - if (rb_cmpint(c) < 0) return Qtrue; + if (rb_cmpint(c, x, y) < 0) return Qtrue; return Qfalse; } @@ -104,7 +107,7 @@ cmp_le(x, y) VALUE c = rb_funcall(x, cmp, 1, y); if (NIL_P(c)) return cmperr(); - if (rb_cmpint(c) <= 0) return Qtrue; + if (rb_cmpint(c, x, y) <= 0) return Qtrue; return Qfalse; } diff --git a/enum.c b/enum.c index 6b76f4f710..ddefbd6c2c 100644 --- a/enum.c +++ b/enum.c @@ -156,23 +156,23 @@ collect_all(i, ary) } static VALUE -enum_to_a(obj) +enum_collect(obj) VALUE obj; { VALUE ary = rb_ary_new(); - rb_iterate(rb_each, obj, collect_all, ary); + rb_iterate(rb_each, obj, rb_block_given_p() ? collect_i : collect_all, ary); return ary; } static VALUE -enum_collect(obj) +enum_to_a(obj) VALUE obj; { VALUE ary = rb_ary_new(); - rb_iterate(rb_each, obj, rb_block_given_p() ? collect_i : collect_all, ary); + rb_iterate(rb_each, obj, collect_all, ary); return ary; } @@ -264,7 +264,7 @@ sort_by_cmp(a, b) VALUE retval; retval = rb_funcall(RARRAY(*a)->ptr[0], id_cmp, 1, RARRAY(*b)->ptr[0]); - return rb_cmpint(retval); + return rb_cmpint(retval, *a, *b); } static VALUE @@ -274,7 +274,12 @@ enum_sort_by(obj) VALUE ary; long i; - ary = rb_ary_new2((TYPE(obj) == T_ARRAY) ? RARRAY(obj)->len : 2000); + if (TYPE(obj) == T_ARRAY) { + ary = rb_ary_new2(RARRAY(obj)->len); + } + else { + ary = rb_ary_new(); + } rb_iterate(rb_each, obj, sort_by_i, ary); if (RARRAY(ary)->len > 1) { qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE), sort_by_cmp); @@ -374,7 +379,7 @@ min_i(i, memo) } else { cmp = rb_funcall(i, id_cmp, 1, memo->u1.value); - if (rb_cmpint(cmp) < 0) { + if (rb_cmpint(cmp, i, memo->u1.value) < 0) { memo->u1.value = i; } } @@ -393,7 +398,7 @@ min_ii(i, memo) } else { cmp = rb_yield(rb_assoc_new(i, memo->u1.value)); - if (rb_cmpint(cmp) < 0) { + if (rb_cmpint(cmp, i, memo->u1.value) < 0) { memo->u1.value = i; } } @@ -425,7 +430,7 @@ max_i(i, memo) } else { cmp = rb_funcall(i, id_cmp, 1, memo->u1.value); - if (rb_cmpint(cmp) > 0) { + if (rb_cmpint(cmp, i, memo->u1.value) > 0) { memo->u1.value = i; } } @@ -444,7 +449,7 @@ max_ii(i, memo) } else { cmp = rb_yield(rb_assoc_new(i, memo->u1.value)); - if (rb_cmpint(cmp) > 0) { + if (rb_cmpint(cmp, i, memo->u1.value) > 0) { memo->u1.value = i; } } diff --git a/eval.c b/eval.c index c1538301b7..0bc1fea016 100644 --- a/eval.c +++ b/eval.c @@ -628,6 +628,7 @@ struct BLOCK { struct RVarmap *dyna_vars; VALUE orig_thread; VALUE wrapper; + struct BLOCK *outer; struct BLOCK *prev; }; @@ -658,6 +659,7 @@ new_blktag() _block.frame.node = ruby_current_node;\ _block.scope = ruby_scope; \ _block.prev = ruby_block; \ + _block.outer = ruby_block; \ _block.iter = ruby_iter->iter; \ _block.vmode = scope_vmode; \ _block.flags = BLOCK_D_SCOPE; \ @@ -1477,20 +1479,45 @@ rb_eval_string_wrap(str, state) } static void -localjump_error(mesg, status) +localjump_error(mesg, status, reason) const char *mesg; VALUE status; + int reason; { VALUE exc = rb_exc_new2(rb_eLocalJumpError, mesg); - rb_iv_set(exc, "@status", status); + VALUE id; + + rb_iv_set(exc, "@exit_value", status); + switch (reason) { + case TAG_BREAK: + id = rb_intern("break"); break; + case TAG_REDO: + id = rb_intern("redo"); break; + case TAG_RETRY: + id = rb_intern("retry"); break; + case TAG_NEXT: + id = rb_intern("next"); break; + case TAG_RETURN: + id = rb_intern("return"); break; + default: + id = rb_intern("noreason"); break; + } + rb_iv_set(exc, "@reason", ID2SYM(id)); rb_exc_raise(exc); } static VALUE -localjump_exitstatus(exc) +localjump_xvalue(exc) + VALUE exc; +{ + return rb_iv_get(exc, "@exit_value"); +} + +static VALUE +localjump_reason(exc) VALUE exc; { - return rb_iv_get(exc, "@status"); + return rb_iv_get(exc, "@reason"); } static void @@ -1505,19 +1532,19 @@ jump_tag_but_local_jump(state) case 0: break; case TAG_RETURN: - localjump_error("unexpected return", val); + localjump_error("unexpected return", val, state); break; case TAG_NEXT: - localjump_error("unexpected next", val); + localjump_error("unexpected next", val, state); break; case TAG_BREAK: - localjump_error("unexpected break", val); + localjump_error("unexpected break", val, state); break; case TAG_REDO: - localjump_error("unexpected redo", Qnil); + localjump_error("unexpected redo", Qnil, state); break; case TAG_RETRY: - localjump_error("retry outside of rescue clause", Qnil); + localjump_error("retry outside of rescue clause", Qnil, state); break; default: JUMP_TAG(state); @@ -1897,7 +1924,7 @@ copy_node_scope(node, rval) #define BEGIN_CALLARGS do {\ struct BLOCK *tmp_block = ruby_block;\ if (ruby_iter->iter == ITER_PRE) {\ - ruby_block = ruby_block->prev;\ + ruby_block = ruby_block->outer;\ }\ PUSH_ITER(ITER_NOT) @@ -3967,7 +3994,7 @@ rb_yield_0(val, self, klass, pcall, avalue) static unsigned serial = 1; if (!rb_block_given_p()) { - localjump_error("no block given", Qnil); + localjump_error("no block given", Qnil, 0); } PUSH_VARS(); @@ -6805,7 +6832,7 @@ proc_invoke(proc, args, pcall, self) break; case TAG_RETRY: if (pcall || orphan) { - localjump_error("retry from proc-closure", Qnil); + localjump_error("retry from proc-closure", Qnil, state); } /* fall through */ case TAG_BREAK: @@ -6813,7 +6840,7 @@ proc_invoke(proc, args, pcall, self) result = prot_tag->retval; } else if (orphan) { - localjump_error("break from proc-closure", prot_tag->retval); + localjump_error("break from proc-closure", prot_tag->retval, state); } else { ruby_block->tag->dst = incoming_state; @@ -6822,7 +6849,7 @@ proc_invoke(proc, args, pcall, self) break; case TAG_RETURN: if (orphan) { /* orphan procedure */ - localjump_error("return from proc-closure", prot_tag->retval); + localjump_error("return from proc-closure", prot_tag->retval, state); } /* fall through */ default: @@ -6988,7 +7015,7 @@ block_pass(self, node) /* PUSH BLOCK from data */ old_block = ruby_block; _block = *data; - _block.prev = old_block; + _block.outer = ruby_block; ruby_block = &_block; PUSH_ITER(ITER_PRE); ruby_frame->iter = ITER_PRE; @@ -7035,7 +7062,7 @@ block_pass(self, node) goto retry; case TAG_RETURN: if (orphan) { - localjump_error("return from proc-closure", prot_tag->retval); + localjump_error("return from proc-closure", prot_tag->retval, state); } default: JUMP_TAG(state); @@ -7445,7 +7472,8 @@ void Init_Proc() { rb_eLocalJumpError = rb_define_class("LocalJumpError", rb_eStandardError); - rb_define_method(rb_eLocalJumpError, "exitstatus", localjump_exitstatus, 0); + rb_define_method(rb_eLocalJumpError, "exit_value", localjump_xvalue, 0); + rb_define_method(rb_eLocalJumpError, "reason", localjump_reason, 0); rb_eSysStackError = rb_define_class("SystemStackError", rb_eStandardError); diff --git a/ext/pty/pty.c b/ext/pty/pty.c index 3189b9ae65..cea0de50a2 100644 --- a/ext/pty/pty.c +++ b/ext/pty/pty.c @@ -300,6 +300,7 @@ pty_finalize_syswait(info) struct pty_info *info; { rb_thread_kill(info->thread); + rb_funcall(info->thread, rb_intern("value"), 0); rb_detach_process(info->child_pid); return Qnil; } @@ -438,9 +439,9 @@ pty_getpty(argc, argv, self) thinfo.thread = rb_thread_create(pty_syswait, (void*)&info); thinfo.child_pid = info.child_pid; + rb_thread_schedule(); if (rb_block_given_p()) { - rb_ensure(rb_yield, res, pty_finalize_syswait, (VALUE)&thinfo); return Qnil; } diff --git a/intern.h b/intern.h index 6776216c40..0b73d7461d 100644 --- a/intern.h +++ b/intern.h @@ -121,7 +121,7 @@ void rb_define_private_method _((VALUE, const char*, VALUE (*)(ANYARGS), int)); void rb_define_singleton_method _((VALUE, const char*, VALUE(*)(ANYARGS), int)); VALUE rb_singleton_class _((VALUE)); /* compar.c */ -int rb_cmpint _((VALUE)); +int rb_cmpint _((VALUE, VALUE, VALUE)); NORETURN(void rb_cmperr _((VALUE, VALUE))); /* enum.c */ /* error.c */ diff --git a/range.c b/range.c index e0d17f46c2..5d398b5e6b 100644 --- a/range.c +++ b/range.c @@ -126,7 +126,7 @@ r_lt(a, b) VALUE r = rb_funcall(a, id_cmp, 1, b); if (NIL_P(r)) return Qfalse; - if (rb_cmpint(r) < 0) return Qtrue; + if (rb_cmpint(r, a, b) < 0) return Qtrue; return Qfalse; } @@ -137,7 +137,7 @@ r_le(a, b) VALUE r = rb_funcall(a, id_cmp, 1, b); if (NIL_P(r)) return Qfalse; - if (rb_cmpint(r) <= 0) return Qtrue; + if (rb_cmpint(r, a, b) <= 0) return Qtrue; return Qfalse; } @@ -149,7 +149,7 @@ r_gt(a,b) VALUE r = rb_funcall(a, id_cmp, 1, b); if (NIL_P(r)) return Qfalse; - if (rb_cmpint(r) > 0) return Qtrue; + if (rb_cmpint(r, a, b) > 0) return Qtrue; return Qfalse; } diff --git a/sample/test.rb b/sample/test.rb index d49e7a3e28..c2263013d2 100644 --- a/sample/test.rb +++ b/sample/test.rb @@ -962,6 +962,28 @@ IterTest.new([[8]]).each8 {|x| test_ok(x == [8])} IterTest.new([[0,0]]).each0 {|x| test_ok(x == [0,0])} IterTest.new([[8,8]]).each8 {|x| test_ok(x == [8,8])} +def m + test_ok(block_given?) +end +m{p 'test'} + +def m + test_ok(block_given?,&proc) +end +m{p 'test'} + +class C + include Enumerable + def initialize + @a = [1,2,3] + end + def each(&block) + @a.each(&block) + end +end + +test_ok(C.new.collect{|n| n} == [1,2,3]) + test_check "float" test_ok(2.6.floor == 2) test_ok((-2.6).floor == -3) @@ -1526,6 +1548,11 @@ include Const2 STDERR.print "intentionally redefines TEST3, TEST4\n" if $VERBOSE test_ok([TEST1,TEST2,TEST3,TEST4] == [1,2,6,8]) + +test_ok((String <=> Object) == -1) +test_ok((Object <=> String) == 1) +test_ok((Array <=> String) == nil) + test_check "clone" foo = Object.new def foo.test diff --git a/time.c b/time.c index cb5d5088a9..7348906cdb 100644 --- a/time.c +++ b/time.c @@ -704,31 +704,15 @@ time_cmp(time1, time2) long i; GetTimeval(time1, tobj1); - switch (TYPE(time2)) { - case T_FIXNUM: - i = FIX2LONG(time2); - if (tobj1->tv.tv_sec == i) { - if (tobj1->tv.tv_usec == 0) - return INT2FIX(0); - if (tobj1->tv.tv_usec > 0) - return INT2FIX(1); + if (TYPE(time2) == T_DATA && RDATA(time2)->dfree == time_free) { + GetTimeval(time2, tobj2); + if (tobj1->tv.tv_sec == tobj2->tv.tv_sec) { + if (tobj1->tv.tv_usec == tobj2->tv.tv_usec) return INT2FIX(0); + if (tobj1->tv.tv_usec > tobj2->tv.tv_usec) return INT2FIX(1); return INT2FIX(-1); } - if (tobj1->tv.tv_sec > i) return INT2FIX(1); + if (tobj1->tv.tv_sec > tobj2->tv.tv_sec) return INT2FIX(1); return INT2FIX(-1); - - case T_DATA: - if (RDATA(time2)->dfree == time_free) { - GetTimeval(time2, tobj2); - if (tobj1->tv.tv_sec == tobj2->tv.tv_sec) { - if (tobj1->tv.tv_usec == tobj2->tv.tv_usec) return INT2FIX(0); - if (tobj1->tv.tv_usec > tobj2->tv.tv_usec) return INT2FIX(1); - return INT2FIX(-1); - } - if (tobj1->tv.tv_sec > tobj2->tv.tv_sec) return INT2FIX(1); - return INT2FIX(-1); - } - break; } return Qnil; -- cgit v1.2.3