From 7c097dc8914e035dc4e1fb6913064e59fcb3d08c Mon Sep 17 00:00:00 2001 From: matz Date: Wed, 10 Mar 2004 07:05:19 +0000 Subject: * struct.c (rb_struct_s_def): Struct::new executes block with generated struct class. [ruby-talk:02606] * io.c (rb_io_ungetc): raise IOError instead of calling rb_sys_fail(). [ruby-talk:23181] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5934 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 20 +++++ eval.c | 244 +++++++++++++++++++++++++++++++++++--------------- ext/socket/socket.c | 17 ++++ gc.c | 6 +- io.c | 5 +- lib/getoptlong.rb | 14 +-- lib/irb/completion.rb | 2 +- ruby.h | 26 +++--- sample/test.rb | 136 +++++++++++++++++++++++++--- struct.c | 15 +++- 10 files changed, 373 insertions(+), 112 deletions(-) diff --git a/ChangeLog b/ChangeLog index 281c973070..b3db26f8ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Wed Mar 10 16:00:14 2004 Yukihiro Matsumoto + + * struct.c (rb_struct_s_def): Struct::new executes block with + generated struct class. [ruby-talk:02606] + +Wed Mar 10 15:58:43 2004 Ryan Davis + + * eval.c (eval): Only print backtrace if generating the backtrace + doesn't generate an exception. [ruby-core:02621] + Wed Mar 10 10:15:16 2004 NAKAMURA Usaku * ruby.c (opt_W_getter): get rid of warning. @@ -5,6 +15,11 @@ Wed Mar 10 10:15:16 2004 NAKAMURA Usaku * bcc32/Makefile.sub, win32/Makefile.sub, wince/Makefile.sub: fixed dependency. +Tue Mar 9 13:04:26 2004 Yukihiro Matsumoto + + * io.c (rb_io_ungetc): raise IOError instead of calling + rb_sys_fail(). [ruby-talk:23181] + Tue Mar 09 10:03:40 2004 NAKAMURA Usaku * bcc32/Makefile.sub, win32/Makefile.sub, wince/Makefile.sub: @@ -215,6 +230,11 @@ Thu Mar 4 11:46:32 2004 Nobuyoshi Nakada * lib/drb/extservm.rb (DRb::ExtServManager#invoke_service_command): detach server processes to get rid of zombies. +Thu Mar 4 10:41:25 2004 Yukihiro Matsumoto + + * ruby.h (T_MASK): save 1 bit in flags bits by shifting T_xxx + values. + Thu Mar 4 08:08:36 2004 Nobuyoshi Nakada * ext/syck/rubyext.c: get rid of warnings. diff --git a/eval.c b/eval.c index c4b8d463dd..8cca8c68f9 100644 --- a/eval.c +++ b/eval.c @@ -681,6 +681,7 @@ struct BLOCK { int iter; int vmode; int flags; + int uniq; struct RVarmap *dyna_vars; VALUE orig_thread; VALUE wrapper; @@ -693,11 +694,12 @@ struct BLOCK { #define BLOCK_LAMBDA 2 static struct BLOCK *ruby_block; +static unsigned long block_unique = 0; #define PUSH_BLOCK(v,b) do { \ struct BLOCK _block; \ - _block.var = v; \ - _block.body = b; \ + _block.var = (v); \ + _block.body = (b); \ _block.self = self; \ _block.frame = *ruby_frame; \ _block.klass = ruby_class; \ @@ -712,6 +714,10 @@ static struct BLOCK *ruby_block; _block.dyna_vars = ruby_dyna_vars; \ _block.wrapper = ruby_wrapper; \ _block.block_obj = 0; \ + _block.uniq = (b)?block_unique++:0; \ + if (b) { \ + prot_tag->blkid = _block.uniq; \ + } \ ruby_block = &_block #define POP_BLOCK() \ @@ -892,6 +898,7 @@ struct tag { struct SCOPE *scope; VALUE dst; struct tag *prev; + int blkid; }; static struct tag *prot_tag; @@ -904,15 +911,15 @@ static struct tag *prot_tag; _tag.scope = ruby_scope; \ _tag.tag = ptag; \ _tag.dst = 0; \ + _tag.blkid = 0; \ prot_tag = &_tag #define PROT_NONE Qfalse /* 0 */ #define PROT_THREAD Qtrue /* 2 */ #define PROT_FUNC INT2FIX(0) /* 1 */ -#define PROT_ITER INT2FIX(1) /* 3 */ -#define PROT_CALL INT2FIX(2) /* 5 */ -#define PROT_PCALL INT2FIX(3) /* 7 */ -#define PROT_YIELD INT2FIX(4) /* 9 */ +#define PROT_LOOP INT2FIX(1) /* 3 */ +#define PROT_LAMBDA INT2FIX(2) /* 5 */ +#define PROT_YIELD INT2FIX(3) /* 7 */ #define EXEC_TAG() (FLUSH_REGISTER_WINDOWS, setjmp(prot_tag->buf)) @@ -993,11 +1000,11 @@ static NODE *compile _((VALUE, char*, int)); static VALUE rb_yield_0 _((VALUE, VALUE, VALUE, int, int)); -#define YIELD_LAMBDA_CALL 1 -#define YIELD_BLOCK_ORPHAN 2 -#define YIELD_PUBLIC_DEF 4 -#define YIELD_FUNC_AVALUE 1 -#define YIELD_FUNC_SVALUE 2 +#define YIELD_LAMBDA_CALL 1 +#define YIELD_PROC_CALL 2 +#define YIELD_PUBLIC_DEF 4 +#define YIELD_FUNC_AVALUE 1 +#define YIELD_FUNC_SVALUE 2 static VALUE rb_call _((VALUE,VALUE,ID,int,const VALUE*,int)); static VALUE module_setup _((VALUE,NODE*)); @@ -1564,6 +1571,7 @@ rb_eval_string_wrap(str, state) return val; } +NORETURN(static void localjump_error(const char*, VALUE, int)); static void localjump_error(mesg, value, reason) const char *mesg; @@ -1620,15 +1628,14 @@ localjump_reason(exc) return rb_iv_get(exc, "@reason"); } -NORETURN(static void jump_tag_but_local_jump _((int))); +NORETURN(static void jump_tag_but_local_jump _((int,VALUE))); static void -jump_tag_but_local_jump(state) +jump_tag_but_local_jump(state, val) int state; -{ VALUE val; +{ - if (prot_tag) val = prot_tag->retval; - else val = Qnil; + if (val == Qundef) val = prot_tag->retval; switch (state) { case 0: break; @@ -1694,7 +1701,7 @@ rb_eval_cmd(cmd, arg, tcheck) POP_TAG(); POP_FRAME(); - jump_tag_but_local_jump(state); + jump_tag_but_local_jump(state, val); return val; } @@ -2664,7 +2671,8 @@ class_prefix(self, cpath) }\ } while (0) -NORETURN(static void localjump_destination _((int, VALUE))); +NORETURN(static void return_jump _((VALUE))); +NORETURN(static void break_jump _((VALUE))); static VALUE rb_eval(self, n) @@ -2741,7 +2749,7 @@ rb_eval(self, n) /* node for speed-up(top-level loop for -n/-p) */ case NODE_OPT_N: - PUSH_TAG(PROT_ITER); + PUSH_TAG(PROT_LOOP); switch (state = EXEC_TAG()) { case 0: opt_n_next: @@ -2876,7 +2884,7 @@ rb_eval(self, n) RETURN(Qnil); case NODE_WHILE: - PUSH_TAG(PROT_ITER); + PUSH_TAG(PROT_LOOP); result = Qnil; switch (state = EXEC_TAG()) { case 0: @@ -2911,7 +2919,7 @@ rb_eval(self, n) RETURN(result); case NODE_UNTIL: - PUSH_TAG(PROT_ITER); + PUSH_TAG(PROT_LOOP); result = Qnil; switch (state = EXEC_TAG()) { case 0: @@ -2952,7 +2960,7 @@ rb_eval(self, n) case NODE_ITER: case NODE_FOR: { - PUSH_TAG(PROT_ITER); + PUSH_TAG(PROT_LOOP); PUSH_BLOCK(node->nd_var, node->nd_body); state = EXEC_TAG(); @@ -2995,7 +3003,7 @@ rb_eval(self, n) break; case NODE_BREAK: - localjump_destination(TAG_BREAK, rb_eval(self, node->nd_stts)); + break_jump(rb_eval(self, node->nd_stts)); break; case NODE_NEXT: @@ -3184,7 +3192,7 @@ rb_eval(self, n) break; case NODE_RETURN: - localjump_destination(TAG_RETURN, rb_eval(self, node->nd_stts)); + return_jump(rb_eval(self, node->nd_stts)); break; case NODE_ARGSCAT: @@ -3300,14 +3308,13 @@ rb_eval(self, n) { struct FRAME frame; NODE *saved_cref = 0; - int jump_chain = Qfalse; frame = *ruby_frame; frame.tmp = ruby_frame; ruby_frame = &frame; PUSH_SCOPE(); - PUSH_TAG(PROT_PCALL); + PUSH_TAG(PROT_NONE); if (node->nd_rval) { saved_cref = ruby_cref; ruby_cref = (NODE*)node->nd_rval; @@ -3326,24 +3333,12 @@ rb_eval(self, n) if ((state = EXEC_TAG()) == 0) { result = rb_eval(self, node->nd_next); } - else if (TAG_DST()) { - result = prot_tag->retval; - jump_chain = Qtrue; - } POP_TAG(); POP_SCOPE(); ruby_frame = frame.tmp; if (saved_cref) ruby_cref = saved_cref; - switch (state) { - case 0: - break; - case TAG_RETURN: - case TAG_BREAK: - localjump_destination(state, result); - default: - JUMP_TAG(state); - } + if (state) JUMP_TAG(state); } break; @@ -4288,7 +4283,7 @@ rb_f_abort(argc, argv) void rb_iter_break() { - localjump_destination(TAG_BREAK, Qnil); + break_jump(Qnil); } NORETURN(static void rb_longjmp _((int, VALUE))); @@ -4511,12 +4506,12 @@ rb_f_block_given_p() static VALUE rb_eThreadError; static void -localjump_destination(state, retval) +localjump_jump(state, retval) int state; VALUE retval; { struct tag *tt = prot_tag; - VALUE tag = (state == TAG_BREAK) ? PROT_ITER : PROT_FUNC; + VALUE tag = (state == TAG_BREAK) ? PROT_LOOP : PROT_FUNC; int yield = Qfalse; if (retval == Qundef) retval = Qnil; @@ -4526,13 +4521,13 @@ localjump_destination(state, retval) tt = tt->prev; } if ((tt->tag == PROT_THREAD && state == TAG_BREAK) || - ((tt->tag == PROT_CALL || tt->tag == PROT_PCALL || tt->tag == tag) && + ((tt->tag == PROT_LAMBDA || tt->tag == PROT_LOOP) && tt->frame->uniq == ruby_frame->uniq)) { tt->dst = (VALUE)ruby_frame->uniq; tt->retval = retval; JUMP_TAG(state); } - if (tt->tag == PROT_PCALL && !yield) { + if (tt->tag == PROT_LAMBDA && !yield) { tt->dst = (VALUE)tt->frame->uniq; tt->retval = retval; JUMP_TAG(state); @@ -4543,7 +4538,107 @@ localjump_destination(state, retval) } tt = tt->prev; } - jump_tag_but_local_jump(state); + jump_tag_but_local_jump(state, retval); +} + +NORETURN(static void proc_jump_error(int, VALUE)); +static void +proc_jump_error(state, result) + int state; + VALUE result; +{ + char mesg[32]; + char *statement; + + switch (state) { + case TAG_BREAK: + statement = "break"; break; + case TAG_RETURN: + statement = "return"; break; + case TAG_RETRY: + statement = "retry"; break; + default: + statement = "local-jump"; break; /* should not happen */ + } + snprintf(mesg, sizeof mesg, "%s from proc-closure", statement); + localjump_error(mesg, result, state); +} + +static void +return_jump(retval) + VALUE retval; +{ + struct tag *tt = prot_tag; + int yield = Qfalse; + + if (retval == Qundef) retval = Qnil; + while (tt) { + if (tt->tag == PROT_YIELD) { + yield = Qtrue; + tt = tt->prev; + } + if (tt->tag == PROT_FUNC && tt->frame->uniq == ruby_frame->uniq) { + tt->dst = (VALUE)ruby_frame->uniq; + tt->retval = retval; + JUMP_TAG(TAG_RETURN); + } + if (tt->tag == PROT_LAMBDA && !yield) { + tt->dst = (VALUE)tt->frame->uniq; + tt->retval = retval; + JUMP_TAG(TAG_RETURN); + } + if (tt->tag == PROT_THREAD) { + rb_raise(rb_eThreadError, "return jump can't across threads"); + } + tt = tt->prev; + } + proc_jump_error(TAG_RETURN, retval); +} + +static void +break_jump(retval) + VALUE retval; +{ + struct tag *tt = prot_tag; + int yield = Qfalse; + + if (retval == Qundef) retval = Qnil; + while (tt) { + switch (tt->tag) { + case PROT_THREAD: + case PROT_YIELD: + case PROT_LOOP: + case PROT_LAMBDA: + tt->dst = (VALUE)tt->frame->uniq; + tt->retval = retval; + JUMP_TAG(TAG_BREAK); + break; + default: + break; + } + tt = tt->prev; + } + proc_jump_error(TAG_BREAK, retval); +} + +NORETURN(static void break_jump2 _((VALUE))); +static void +break_jump2(retval) + VALUE retval; +{ + struct tag *tt = prot_tag; + int yield = Qfalse; + + if (retval == Qundef) retval = Qnil; + while (tt) { + if (tt->tag == PROT_LOOP && tt->blkid == ruby_block->uniq) { + tt->dst = (VALUE)tt->frame->uniq; + tt->retval = retval; + JUMP_TAG(TAG_BREAK); + } + tt = tt->prev; + } + proc_jump_error(TAG_BREAK, retval); } static VALUE @@ -4654,7 +4749,7 @@ rb_yield_0(val, self, klass, flags, avalue) ruby_current_node = node; PUSH_ITER(block->iter); - PUSH_TAG((flags & YIELD_BLOCK_ORPHAN) ? PROT_NONE : PROT_YIELD); + PUSH_TAG(lambda ? PROT_NONE : PROT_YIELD); if ((state = EXEC_TAG()) == 0) { redo: if (nd_type(node) == NODE_CFUNC || nd_type(node) == NODE_IFUNC) { @@ -4722,7 +4817,18 @@ rb_yield_0(val, self, klass, flags, avalue) scope_dup(old_scope); ruby_scope = old_scope; scope_vmode = old_vmode; - if (state) JUMP_TAG(state); + switch (state) { + case 0: + break; + case TAG_BREAK: + if (!lambda) { + break_jump2(result); + } + /* fall through */ + default: + JUMP_TAG(state); + break; + } ruby_current_node = cnode; return result; } @@ -4955,9 +5061,8 @@ rb_iterate(it_proc, data1, bl_proc, data2) VALUE self = ruby_top_self; PUSH_ITER(ITER_PRE); + PUSH_TAG(PROT_LOOP); PUSH_BLOCK(0, node); - - PUSH_TAG(PROT_ITER); state = EXEC_TAG(); if (state == 0) { iter_retry: @@ -4971,8 +5076,8 @@ rb_iterate(it_proc, data1, bl_proc, data2) state = 0; goto iter_retry; } - POP_TAG(); POP_BLOCK(); + POP_TAG(); POP_ITER(); switch (state) { @@ -5592,7 +5697,7 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper) if (rb_block_given_p()) JUMP_TAG(state); /* fall through */ default: - jump_tag_but_local_jump(state); + jump_tag_but_local_jump(state, result); break; } } @@ -6058,11 +6163,13 @@ eval(self, src, scope, file, line) errat = get_backtrace(ruby_errinfo); mesg = rb_attr_get(ruby_errinfo, rb_intern("mesg")); - if (!NIL_P(mesg) && TYPE(mesg) == T_STRING) { + if (!NIL_P(errat) && TYPE(errat) == T_ARRAY) { + if (!NIL_P(mesg) && TYPE(mesg) == T_STRING) { rb_str_update(mesg, 0, 0, rb_str_new2(": ")); rb_str_update(mesg, 0, 0, RARRAY(errat)->ptr[0]); + } + RARRAY(errat)->ptr[0] = RARRAY(backtrace(-2))->ptr[0]; } - RARRAY(errat)->ptr[0] = RARRAY(backtrace(-2))->ptr[0]; } rb_exc_raise(ruby_errinfo); } @@ -6431,7 +6538,7 @@ rb_load(fname, wrap) ruby_nerrs = 0; rb_exc_raise(ruby_errinfo); } - if (state) jump_tag_but_local_jump(state); + if (state) jump_tag_but_local_jump(state, Qundef); if (!NIL_P(ruby_errinfo)) /* exception during load */ rb_exc_raise(ruby_errinfo); } @@ -7953,6 +8060,8 @@ static int block_orphan(data) struct BLOCK *data; { + struct tag *tt; + if (data->scope->flags & SCOPE_NOSTACK) { return 1; } @@ -7988,8 +8097,7 @@ proc_invoke(proc, args, self, klass) Data_Get_Struct(proc, struct BLOCK, data); pcall = (data->flags & BLOCK_LAMBDA) ? YIELD_LAMBDA_CALL : 0; - orphan = pcall ? 0 : block_orphan(data); - if (orphan || pcall) pcall |= YIELD_BLOCK_ORPHAN; +// orphan = pcall ? 0 : block_orphan(data); if (!pcall && RARRAY(args)->len == 1) { avalue = Qfalse; args = RARRAY(args)->ptr[0]; @@ -8006,7 +8114,7 @@ proc_invoke(proc, args, self, klass) PUSH_ITER(ITER_CUR); ruby_frame->iter = ITER_CUR; - PUSH_TAG((pcall || orphan) ? PROT_PCALL : PROT_CALL); + PUSH_TAG(pcall ? PROT_LAMBDA : PROT_NONE); state = EXEC_TAG(); if (state == 0) { proc_set_safe_level(proc); @@ -8026,21 +8134,17 @@ proc_invoke(proc, args, self, klass) case 0: break; case TAG_RETRY: - if (pcall || orphan) { - localjump_error("retry from proc-closure", Qnil, state); - } - /* fall through */ + proc_jump_error(TAG_RETRY, Qnil); /* xxx */ + JUMP_TAG(state); + break; case TAG_BREAK: - case TAG_RETURN: - if (orphan) { /* orphan block */ - char mesg[32]; - snprintf(mesg, sizeof mesg, "%s from proc-closure", - state == TAG_BREAK ? "break" : "return"); - localjump_error(mesg, result, state); + if (!pcall && result != Qundef) { + proc_jump_error(state, result); } + case TAG_RETURN: if (result != Qundef) { if (pcall) break; - localjump_destination(state, result); + return_jump(result); } default: JUMP_TAG(state); @@ -8344,7 +8448,7 @@ block_pass(self, node) if (ruby_frame->iter == ITER_NOT) ruby_frame->iter = ITER_PRE; - PUSH_TAG(PROT_ITER); + PUSH_TAG(PROT_LOOP); state = EXEC_TAG(); if (state == 0) { retry: @@ -8371,7 +8475,7 @@ block_pass(self, node) break; case TAG_RETURN: if (orphan) { - localjump_error("return from proc-closure", prot_tag->retval, state); + proc_jump_error(state, prot_tag->retval); } default: JUMP_TAG(state); diff --git a/ext/socket/socket.c b/ext/socket/socket.c index dfd65a2672..e62837891b 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -683,6 +683,23 @@ sock_addrinfo(host, port, socktype, flags) rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error)); } +#if defined(__APPLE__) && defined(__MACH__) + { + struct addrinfo *r; + r = res; + while (r) { + if (! r->ai_socktype) r->ai_socktype = hints.ai_socktype; + if (! r->ai_protocol) { + if (r->ai_socktype == SOCK_DGRAM) { + r->ai_protocol = IPPROTO_UDP; + } else if (r->ai_socktype == SOCK_STREAM) { + r->ai_protocol = IPPROTO_TCP; + } + } + r = r->ai_next; + } + } +#endif return res; } diff --git a/gc.c b/gc.c index 9138d235ef..14f0f36c3a 100644 --- a/gc.c +++ b/gc.c @@ -934,7 +934,7 @@ gc_mark_children(ptr, lev) case T_REGEXP: case T_FLOAT: case T_BIGNUM: - case T_BLKTAG: + case T_BLOCK: break; case T_MATCH: @@ -1186,7 +1186,7 @@ obj_free(obj) case T_FLOAT: case T_VARMAP: - case T_BLKTAG: + case T_BLOCK: break; case T_BIGNUM: @@ -1838,7 +1838,7 @@ id2ref(obj, id) } ptr = id ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */ - if (!is_pointer_to_heap((void *)ptr)|| BUILTIN_TYPE(ptr) >= T_BLKTAG) { + if (!is_pointer_to_heap((void *)ptr)|| BUILTIN_TYPE(ptr) >= T_BLOCK) { rb_raise(rb_eRangeError, "0x%lx is not id value", p0); } if (BUILTIN_TYPE(ptr) == 0 || RBASIC(ptr)->klass == 0) { diff --git a/io.c b/io.c index 3785487a88..018c74ce86 100644 --- a/io.c +++ b/io.c @@ -1696,8 +1696,9 @@ rb_io_ungetc(io, c) rb_raise(rb_eIOError, "unread stream"); rb_io_check_readable(fptr); - if (ungetc(cc, fptr->f) == EOF && cc != EOF) - rb_sys_fail(fptr->path); + if (ungetc(cc, fptr->f) == EOF && cc != EOF) { + rb_raise(rb_eIOError, "ungetc failed"); + } return Qnil; } diff --git a/lib/getoptlong.rb b/lib/getoptlong.rb index 7bb9baef2d..979554ad34 100644 --- a/lib/getoptlong.rb +++ b/lib/getoptlong.rb @@ -34,7 +34,7 @@ class GetoptLong # Error types. # class Error < StandardError; end - class AmbigousOption < Error; end + class AmbiguousOption < Error; end class NeedlessArgument < Error; end class MissingArgument < Error; end class InvalidOption < Error; end @@ -208,7 +208,7 @@ class GetoptLong end # - # Set/Unset `quit' mode. + # Set/Unset `quiet' mode. # attr_writer :quiet @@ -351,16 +351,16 @@ class GetoptLong # The option `option_name' is not registered in `@canonical_names'. # It may be an abbreviated. # - match_count = 0 + matches = [] @canonical_names.each_key do |key| if key.index(pattern) == 0 option_name = key - match_count += 1 + matches << key end end - if 2 <= match_count - set_error(AmbigousOption, "option `#{argument}' is ambiguous") - elsif match_count == 0 + if 2 <= matches.length + set_error(AmbiguousOption, "option `#{argument}' is ambiguous between #{matches.join(', ')}") + elsif matches.length == 0 set_error(InvalidOption, "unrecognized option `#{argument}'") end end diff --git a/lib/irb/completion.rb b/lib/irb/completion.rb index 46e6f24f30..e51a92adc1 100644 --- a/lib/irb/completion.rb +++ b/lib/irb/completion.rb @@ -182,7 +182,7 @@ module IRB end if Readline.respond_to?("basic_word_break_characters=") - Readline.basic_word_break_characters= "\t\n\"\\'`><=;|&{(" + Readline.basic_word_break_characters= " \t\n\"\\'`><=;|&{(" end Readline.completion_append_character = nil Readline.completion_proc = IRB::InputCompletor::CompletionProc diff --git a/ruby.h b/ruby.h index dc91588d82..f7e324d9e5 100644 --- a/ruby.h +++ b/ruby.h @@ -193,19 +193,19 @@ VALUE rb_ull2inum _((unsigned LONG_LONG)); #define T_BIGNUM 0x0d #define T_FILE 0x0e -#define T_TRUE 0x20 -#define T_FALSE 0x21 -#define T_DATA 0x22 -#define T_MATCH 0x23 -#define T_SYMBOL 0x24 - -#define T_BLKTAG 0x3b -#define T_UNDEF 0x3c -#define T_VARMAP 0x3d -#define T_SCOPE 0x3e -#define T_NODE 0x3f - -#define T_MASK 0x3f +#define T_TRUE 0x10 +#define T_FALSE 0x11 +#define T_DATA 0x12 +#define T_MATCH 0x13 +#define T_SYMBOL 0x14 + +#define T_BLOCK 0x1b +#define T_UNDEF 0x1c +#define T_VARMAP 0x1d +#define T_SCOPE 0x1e +#define T_NODE 0x1f + +#define T_MASK 0x1f #define BUILTIN_TYPE(x) (((struct RBasic*)(x))->flags & T_MASK) diff --git a/sample/test.rb b/sample/test.rb index fe39fc646f..7e58cd5362 100644 --- a/sample/test.rb +++ b/sample/test.rb @@ -1134,23 +1134,135 @@ test_ok(55, begin $!.exit_value end) -test_ok(block.arity == -1) -test_ok(lambda.arity == -1) -test_ok(lambda{||}.arity == 0) -test_ok(lambda{|a|}.arity == 1) -test_ok(lambda{|a,|}.arity == 1) -test_ok(lambda{|a,b|}.arity == 2) +def block_call(&block) + block.call +end -def yield_in_lambda - lambda{ yield }[] +def block_get(&block) + block end -def return_in_lambda - yield_in_lambda{ return true } - false +def test_b1 + block_call{break 11} +end +test_ok(test_b1() == 11) + +def ljump_rescue(r) + begin + yield + rescue LocalJumpError => e + r if /from proc-closure/ =~ e.message + end +end + +def test_b2 + ljump_rescue(22) do + block_get{break 21}.call + end +end +test_ok(test_b2() == 22) + +def test_b3 + ljump_rescue(33) do + Proc.new{break 31}.call + end +end +test_ok(test_b3() == 33) + +def test_b4 + lambda{break 44}.call +end +test_ok(test_b4() == 44) + +def test_b5 + ljump_rescue(55) do + b = block_get{break 54} + block_call(&b) + end +end +test_ok(test_b5() == 55) + +def test_b6 + b = lambda{break 67} + block_call(&b) + 66 +end +test_ok(test_b6() == 66) + +def util_r7 + block_get{break 78} +end + +def test_b7 + b = util_r7() + ljump_rescue(77) do + block_call(&b) + end end +test_ok(test_b7() == 77) -test_ok(return_in_lambda()) +def util_b8(&block) + block_call(&block) +end + +def test_b8 + util_b8{break 88} +end +test_ok(test_b8() == 88) + +def util_b9(&block) + lambda{block.call}.call +end + +def test_b9 + util_b9{break 99} +end +test_ok(test_b9() == 99) + +def util_b10 + util_b9{break 100} +end + +def test_b10 + util_b10() +end +test_ok(test_b10() == 100) + +def test_b11 + ljump_rescue(111) do + loop do + Proc.new{break 110}.call + break 112 + end + end +end +test_ok(test_b11() == 111) + +def test_b12 + loop do + break lambda{break 122}.call + break 121 + end +end +test_ok(test_b12() == 122) + +def test_b13 + ljump_rescue(133) do + while true + Proc.new{break 130}.call + break 131 + end + end +end +test_ok(test_b13() == 133) + +def test_b14 + while true + break lambda{break 144}.call + break 143 + end +end +test_ok(test_b14() == 144) def marity_test(m) method = method(m) diff --git a/struct.c b/struct.c index fd149e3c75..1a8c44ad02 100644 --- a/struct.c +++ b/struct.c @@ -285,12 +285,19 @@ rb_struct_s_def(argc, argv, klass) id = rb_to_id(RARRAY(rest)->ptr[i]); RARRAY(rest)->ptr[i] = ID2SYM(id); } - if (!NIL_P(name) && TYPE(name) != T_STRING) { - id = rb_to_id(name); - rb_ary_unshift(rest, ID2SYM(id)); - name = Qnil; + if (!NIL_P(name)) { + VALUE tmp = rb_check_string_type(name); + + if (NIL_P(tmp)) { + id = rb_to_id(name); + rb_ary_unshift(rest, ID2SYM(id)); + name = Qnil; + } } st = make_struct(name, rest, klass); + if (rb_block_given_p()) { + rb_mod_module_eval(0, 0, st); + } return st; } -- cgit v1.2.3