mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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
This commit is contained in:
parent
86e988a555
commit
7c097dc891
10 changed files with 372 additions and 111 deletions
20
ChangeLog
20
ChangeLog
|
@ -1,3 +1,13 @@
|
||||||
|
Wed Mar 10 16:00:14 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
|
* 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 <ryand@zenspider.com>
|
||||||
|
|
||||||
|
* 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 <usa@ruby-lang.org>
|
Wed Mar 10 10:15:16 2004 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||||
|
|
||||||
* ruby.c (opt_W_getter): get rid of warning.
|
* ruby.c (opt_W_getter): get rid of warning.
|
||||||
|
@ -5,6 +15,11 @@ Wed Mar 10 10:15:16 2004 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||||
* bcc32/Makefile.sub, win32/Makefile.sub, wince/Makefile.sub:
|
* bcc32/Makefile.sub, win32/Makefile.sub, wince/Makefile.sub:
|
||||||
fixed dependency.
|
fixed dependency.
|
||||||
|
|
||||||
|
Tue Mar 9 13:04:26 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
|
* 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 <usa@ruby-lang.org>
|
Tue Mar 09 10:03:40 2004 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||||
|
|
||||||
* bcc32/Makefile.sub, win32/Makefile.sub, wince/Makefile.sub:
|
* bcc32/Makefile.sub, win32/Makefile.sub, wince/Makefile.sub:
|
||||||
|
@ -215,6 +230,11 @@ Thu Mar 4 11:46:32 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
* lib/drb/extservm.rb (DRb::ExtServManager#invoke_service_command):
|
* lib/drb/extservm.rb (DRb::ExtServManager#invoke_service_command):
|
||||||
detach server processes to get rid of zombies.
|
detach server processes to get rid of zombies.
|
||||||
|
|
||||||
|
Thu Mar 4 10:41:25 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
|
* ruby.h (T_MASK): save 1 bit in flags bits by shifting T_xxx
|
||||||
|
values.
|
||||||
|
|
||||||
Thu Mar 4 08:08:36 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Thu Mar 4 08:08:36 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* ext/syck/rubyext.c: get rid of warnings.
|
* ext/syck/rubyext.c: get rid of warnings.
|
||||||
|
|
244
eval.c
244
eval.c
|
@ -681,6 +681,7 @@ struct BLOCK {
|
||||||
int iter;
|
int iter;
|
||||||
int vmode;
|
int vmode;
|
||||||
int flags;
|
int flags;
|
||||||
|
int uniq;
|
||||||
struct RVarmap *dyna_vars;
|
struct RVarmap *dyna_vars;
|
||||||
VALUE orig_thread;
|
VALUE orig_thread;
|
||||||
VALUE wrapper;
|
VALUE wrapper;
|
||||||
|
@ -693,11 +694,12 @@ struct BLOCK {
|
||||||
#define BLOCK_LAMBDA 2
|
#define BLOCK_LAMBDA 2
|
||||||
|
|
||||||
static struct BLOCK *ruby_block;
|
static struct BLOCK *ruby_block;
|
||||||
|
static unsigned long block_unique = 0;
|
||||||
|
|
||||||
#define PUSH_BLOCK(v,b) do { \
|
#define PUSH_BLOCK(v,b) do { \
|
||||||
struct BLOCK _block; \
|
struct BLOCK _block; \
|
||||||
_block.var = v; \
|
_block.var = (v); \
|
||||||
_block.body = b; \
|
_block.body = (b); \
|
||||||
_block.self = self; \
|
_block.self = self; \
|
||||||
_block.frame = *ruby_frame; \
|
_block.frame = *ruby_frame; \
|
||||||
_block.klass = ruby_class; \
|
_block.klass = ruby_class; \
|
||||||
|
@ -712,6 +714,10 @@ static struct BLOCK *ruby_block;
|
||||||
_block.dyna_vars = ruby_dyna_vars; \
|
_block.dyna_vars = ruby_dyna_vars; \
|
||||||
_block.wrapper = ruby_wrapper; \
|
_block.wrapper = ruby_wrapper; \
|
||||||
_block.block_obj = 0; \
|
_block.block_obj = 0; \
|
||||||
|
_block.uniq = (b)?block_unique++:0; \
|
||||||
|
if (b) { \
|
||||||
|
prot_tag->blkid = _block.uniq; \
|
||||||
|
} \
|
||||||
ruby_block = &_block
|
ruby_block = &_block
|
||||||
|
|
||||||
#define POP_BLOCK() \
|
#define POP_BLOCK() \
|
||||||
|
@ -892,6 +898,7 @@ struct tag {
|
||||||
struct SCOPE *scope;
|
struct SCOPE *scope;
|
||||||
VALUE dst;
|
VALUE dst;
|
||||||
struct tag *prev;
|
struct tag *prev;
|
||||||
|
int blkid;
|
||||||
};
|
};
|
||||||
static struct tag *prot_tag;
|
static struct tag *prot_tag;
|
||||||
|
|
||||||
|
@ -904,15 +911,15 @@ static struct tag *prot_tag;
|
||||||
_tag.scope = ruby_scope; \
|
_tag.scope = ruby_scope; \
|
||||||
_tag.tag = ptag; \
|
_tag.tag = ptag; \
|
||||||
_tag.dst = 0; \
|
_tag.dst = 0; \
|
||||||
|
_tag.blkid = 0; \
|
||||||
prot_tag = &_tag
|
prot_tag = &_tag
|
||||||
|
|
||||||
#define PROT_NONE Qfalse /* 0 */
|
#define PROT_NONE Qfalse /* 0 */
|
||||||
#define PROT_THREAD Qtrue /* 2 */
|
#define PROT_THREAD Qtrue /* 2 */
|
||||||
#define PROT_FUNC INT2FIX(0) /* 1 */
|
#define PROT_FUNC INT2FIX(0) /* 1 */
|
||||||
#define PROT_ITER INT2FIX(1) /* 3 */
|
#define PROT_LOOP INT2FIX(1) /* 3 */
|
||||||
#define PROT_CALL INT2FIX(2) /* 5 */
|
#define PROT_LAMBDA INT2FIX(2) /* 5 */
|
||||||
#define PROT_PCALL INT2FIX(3) /* 7 */
|
#define PROT_YIELD INT2FIX(3) /* 7 */
|
||||||
#define PROT_YIELD INT2FIX(4) /* 9 */
|
|
||||||
|
|
||||||
#define EXEC_TAG() (FLUSH_REGISTER_WINDOWS, setjmp(prot_tag->buf))
|
#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));
|
static VALUE rb_yield_0 _((VALUE, VALUE, VALUE, int, int));
|
||||||
|
|
||||||
#define YIELD_LAMBDA_CALL 1
|
#define YIELD_LAMBDA_CALL 1
|
||||||
#define YIELD_BLOCK_ORPHAN 2
|
#define YIELD_PROC_CALL 2
|
||||||
#define YIELD_PUBLIC_DEF 4
|
#define YIELD_PUBLIC_DEF 4
|
||||||
#define YIELD_FUNC_AVALUE 1
|
#define YIELD_FUNC_AVALUE 1
|
||||||
#define YIELD_FUNC_SVALUE 2
|
#define YIELD_FUNC_SVALUE 2
|
||||||
|
|
||||||
static VALUE rb_call _((VALUE,VALUE,ID,int,const VALUE*,int));
|
static VALUE rb_call _((VALUE,VALUE,ID,int,const VALUE*,int));
|
||||||
static VALUE module_setup _((VALUE,NODE*));
|
static VALUE module_setup _((VALUE,NODE*));
|
||||||
|
@ -1564,6 +1571,7 @@ rb_eval_string_wrap(str, state)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NORETURN(static void localjump_error(const char*, VALUE, int));
|
||||||
static void
|
static void
|
||||||
localjump_error(mesg, value, reason)
|
localjump_error(mesg, value, reason)
|
||||||
const char *mesg;
|
const char *mesg;
|
||||||
|
@ -1620,15 +1628,14 @@ localjump_reason(exc)
|
||||||
return rb_iv_get(exc, "@reason");
|
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
|
static void
|
||||||
jump_tag_but_local_jump(state)
|
jump_tag_but_local_jump(state, val)
|
||||||
int state;
|
int state;
|
||||||
{
|
|
||||||
VALUE val;
|
VALUE val;
|
||||||
|
{
|
||||||
|
|
||||||
if (prot_tag) val = prot_tag->retval;
|
if (val == Qundef) val = prot_tag->retval;
|
||||||
else val = Qnil;
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
|
@ -1694,7 +1701,7 @@ rb_eval_cmd(cmd, arg, tcheck)
|
||||||
POP_TAG();
|
POP_TAG();
|
||||||
POP_FRAME();
|
POP_FRAME();
|
||||||
|
|
||||||
jump_tag_but_local_jump(state);
|
jump_tag_but_local_jump(state, val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2664,7 +2671,8 @@ class_prefix(self, cpath)
|
||||||
}\
|
}\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
NORETURN(static void localjump_destination _((int, VALUE)));
|
NORETURN(static void return_jump _((VALUE)));
|
||||||
|
NORETURN(static void break_jump _((VALUE)));
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_eval(self, n)
|
rb_eval(self, n)
|
||||||
|
@ -2741,7 +2749,7 @@ rb_eval(self, n)
|
||||||
|
|
||||||
/* node for speed-up(top-level loop for -n/-p) */
|
/* node for speed-up(top-level loop for -n/-p) */
|
||||||
case NODE_OPT_N:
|
case NODE_OPT_N:
|
||||||
PUSH_TAG(PROT_ITER);
|
PUSH_TAG(PROT_LOOP);
|
||||||
switch (state = EXEC_TAG()) {
|
switch (state = EXEC_TAG()) {
|
||||||
case 0:
|
case 0:
|
||||||
opt_n_next:
|
opt_n_next:
|
||||||
|
@ -2876,7 +2884,7 @@ rb_eval(self, n)
|
||||||
RETURN(Qnil);
|
RETURN(Qnil);
|
||||||
|
|
||||||
case NODE_WHILE:
|
case NODE_WHILE:
|
||||||
PUSH_TAG(PROT_ITER);
|
PUSH_TAG(PROT_LOOP);
|
||||||
result = Qnil;
|
result = Qnil;
|
||||||
switch (state = EXEC_TAG()) {
|
switch (state = EXEC_TAG()) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -2911,7 +2919,7 @@ rb_eval(self, n)
|
||||||
RETURN(result);
|
RETURN(result);
|
||||||
|
|
||||||
case NODE_UNTIL:
|
case NODE_UNTIL:
|
||||||
PUSH_TAG(PROT_ITER);
|
PUSH_TAG(PROT_LOOP);
|
||||||
result = Qnil;
|
result = Qnil;
|
||||||
switch (state = EXEC_TAG()) {
|
switch (state = EXEC_TAG()) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -2952,7 +2960,7 @@ rb_eval(self, n)
|
||||||
case NODE_ITER:
|
case NODE_ITER:
|
||||||
case NODE_FOR:
|
case NODE_FOR:
|
||||||
{
|
{
|
||||||
PUSH_TAG(PROT_ITER);
|
PUSH_TAG(PROT_LOOP);
|
||||||
PUSH_BLOCK(node->nd_var, node->nd_body);
|
PUSH_BLOCK(node->nd_var, node->nd_body);
|
||||||
|
|
||||||
state = EXEC_TAG();
|
state = EXEC_TAG();
|
||||||
|
@ -2995,7 +3003,7 @@ rb_eval(self, n)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NODE_BREAK:
|
case NODE_BREAK:
|
||||||
localjump_destination(TAG_BREAK, rb_eval(self, node->nd_stts));
|
break_jump(rb_eval(self, node->nd_stts));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NODE_NEXT:
|
case NODE_NEXT:
|
||||||
|
@ -3184,7 +3192,7 @@ rb_eval(self, n)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NODE_RETURN:
|
case NODE_RETURN:
|
||||||
localjump_destination(TAG_RETURN, rb_eval(self, node->nd_stts));
|
return_jump(rb_eval(self, node->nd_stts));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NODE_ARGSCAT:
|
case NODE_ARGSCAT:
|
||||||
|
@ -3300,14 +3308,13 @@ rb_eval(self, n)
|
||||||
{
|
{
|
||||||
struct FRAME frame;
|
struct FRAME frame;
|
||||||
NODE *saved_cref = 0;
|
NODE *saved_cref = 0;
|
||||||
int jump_chain = Qfalse;
|
|
||||||
|
|
||||||
frame = *ruby_frame;
|
frame = *ruby_frame;
|
||||||
frame.tmp = ruby_frame;
|
frame.tmp = ruby_frame;
|
||||||
ruby_frame = &frame;
|
ruby_frame = &frame;
|
||||||
|
|
||||||
PUSH_SCOPE();
|
PUSH_SCOPE();
|
||||||
PUSH_TAG(PROT_PCALL);
|
PUSH_TAG(PROT_NONE);
|
||||||
if (node->nd_rval) {
|
if (node->nd_rval) {
|
||||||
saved_cref = ruby_cref;
|
saved_cref = ruby_cref;
|
||||||
ruby_cref = (NODE*)node->nd_rval;
|
ruby_cref = (NODE*)node->nd_rval;
|
||||||
|
@ -3326,24 +3333,12 @@ rb_eval(self, n)
|
||||||
if ((state = EXEC_TAG()) == 0) {
|
if ((state = EXEC_TAG()) == 0) {
|
||||||
result = rb_eval(self, node->nd_next);
|
result = rb_eval(self, node->nd_next);
|
||||||
}
|
}
|
||||||
else if (TAG_DST()) {
|
|
||||||
result = prot_tag->retval;
|
|
||||||
jump_chain = Qtrue;
|
|
||||||
}
|
|
||||||
POP_TAG();
|
POP_TAG();
|
||||||
POP_SCOPE();
|
POP_SCOPE();
|
||||||
ruby_frame = frame.tmp;
|
ruby_frame = frame.tmp;
|
||||||
if (saved_cref)
|
if (saved_cref)
|
||||||
ruby_cref = saved_cref;
|
ruby_cref = saved_cref;
|
||||||
switch (state) {
|
if (state) JUMP_TAG(state);
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case TAG_RETURN:
|
|
||||||
case TAG_BREAK:
|
|
||||||
localjump_destination(state, result);
|
|
||||||
default:
|
|
||||||
JUMP_TAG(state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -4288,7 +4283,7 @@ rb_f_abort(argc, argv)
|
||||||
void
|
void
|
||||||
rb_iter_break()
|
rb_iter_break()
|
||||||
{
|
{
|
||||||
localjump_destination(TAG_BREAK, Qnil);
|
break_jump(Qnil);
|
||||||
}
|
}
|
||||||
|
|
||||||
NORETURN(static void rb_longjmp _((int, VALUE)));
|
NORETURN(static void rb_longjmp _((int, VALUE)));
|
||||||
|
@ -4511,12 +4506,12 @@ rb_f_block_given_p()
|
||||||
static VALUE rb_eThreadError;
|
static VALUE rb_eThreadError;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
localjump_destination(state, retval)
|
localjump_jump(state, retval)
|
||||||
int state;
|
int state;
|
||||||
VALUE retval;
|
VALUE retval;
|
||||||
{
|
{
|
||||||
struct tag *tt = prot_tag;
|
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;
|
int yield = Qfalse;
|
||||||
|
|
||||||
if (retval == Qundef) retval = Qnil;
|
if (retval == Qundef) retval = Qnil;
|
||||||
|
@ -4526,13 +4521,13 @@ localjump_destination(state, retval)
|
||||||
tt = tt->prev;
|
tt = tt->prev;
|
||||||
}
|
}
|
||||||
if ((tt->tag == PROT_THREAD && state == TAG_BREAK) ||
|
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->frame->uniq == ruby_frame->uniq)) {
|
||||||
tt->dst = (VALUE)ruby_frame->uniq;
|
tt->dst = (VALUE)ruby_frame->uniq;
|
||||||
tt->retval = retval;
|
tt->retval = retval;
|
||||||
JUMP_TAG(state);
|
JUMP_TAG(state);
|
||||||
}
|
}
|
||||||
if (tt->tag == PROT_PCALL && !yield) {
|
if (tt->tag == PROT_LAMBDA && !yield) {
|
||||||
tt->dst = (VALUE)tt->frame->uniq;
|
tt->dst = (VALUE)tt->frame->uniq;
|
||||||
tt->retval = retval;
|
tt->retval = retval;
|
||||||
JUMP_TAG(state);
|
JUMP_TAG(state);
|
||||||
|
@ -4543,7 +4538,107 @@ localjump_destination(state, retval)
|
||||||
}
|
}
|
||||||
tt = tt->prev;
|
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
|
static VALUE
|
||||||
|
@ -4654,7 +4749,7 @@ rb_yield_0(val, self, klass, flags, avalue)
|
||||||
ruby_current_node = node;
|
ruby_current_node = node;
|
||||||
|
|
||||||
PUSH_ITER(block->iter);
|
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) {
|
if ((state = EXEC_TAG()) == 0) {
|
||||||
redo:
|
redo:
|
||||||
if (nd_type(node) == NODE_CFUNC || nd_type(node) == NODE_IFUNC) {
|
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);
|
scope_dup(old_scope);
|
||||||
ruby_scope = old_scope;
|
ruby_scope = old_scope;
|
||||||
scope_vmode = old_vmode;
|
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;
|
ruby_current_node = cnode;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -4955,9 +5061,8 @@ rb_iterate(it_proc, data1, bl_proc, data2)
|
||||||
VALUE self = ruby_top_self;
|
VALUE self = ruby_top_self;
|
||||||
|
|
||||||
PUSH_ITER(ITER_PRE);
|
PUSH_ITER(ITER_PRE);
|
||||||
|
PUSH_TAG(PROT_LOOP);
|
||||||
PUSH_BLOCK(0, node);
|
PUSH_BLOCK(0, node);
|
||||||
|
|
||||||
PUSH_TAG(PROT_ITER);
|
|
||||||
state = EXEC_TAG();
|
state = EXEC_TAG();
|
||||||
if (state == 0) {
|
if (state == 0) {
|
||||||
iter_retry:
|
iter_retry:
|
||||||
|
@ -4971,8 +5076,8 @@ rb_iterate(it_proc, data1, bl_proc, data2)
|
||||||
state = 0;
|
state = 0;
|
||||||
goto iter_retry;
|
goto iter_retry;
|
||||||
}
|
}
|
||||||
POP_TAG();
|
|
||||||
POP_BLOCK();
|
POP_BLOCK();
|
||||||
|
POP_TAG();
|
||||||
POP_ITER();
|
POP_ITER();
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
@ -5592,7 +5697,7 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
|
||||||
if (rb_block_given_p()) JUMP_TAG(state);
|
if (rb_block_given_p()) JUMP_TAG(state);
|
||||||
/* fall through */
|
/* fall through */
|
||||||
default:
|
default:
|
||||||
jump_tag_but_local_jump(state);
|
jump_tag_but_local_jump(state, result);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6058,11 +6163,13 @@ eval(self, src, scope, file, line)
|
||||||
|
|
||||||
errat = get_backtrace(ruby_errinfo);
|
errat = get_backtrace(ruby_errinfo);
|
||||||
mesg = rb_attr_get(ruby_errinfo, rb_intern("mesg"));
|
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, rb_str_new2(": "));
|
||||||
rb_str_update(mesg, 0, 0, RARRAY(errat)->ptr[0]);
|
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);
|
rb_exc_raise(ruby_errinfo);
|
||||||
}
|
}
|
||||||
|
@ -6431,7 +6538,7 @@ rb_load(fname, wrap)
|
||||||
ruby_nerrs = 0;
|
ruby_nerrs = 0;
|
||||||
rb_exc_raise(ruby_errinfo);
|
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 */
|
if (!NIL_P(ruby_errinfo)) /* exception during load */
|
||||||
rb_exc_raise(ruby_errinfo);
|
rb_exc_raise(ruby_errinfo);
|
||||||
}
|
}
|
||||||
|
@ -7953,6 +8060,8 @@ static int
|
||||||
block_orphan(data)
|
block_orphan(data)
|
||||||
struct BLOCK *data;
|
struct BLOCK *data;
|
||||||
{
|
{
|
||||||
|
struct tag *tt;
|
||||||
|
|
||||||
if (data->scope->flags & SCOPE_NOSTACK) {
|
if (data->scope->flags & SCOPE_NOSTACK) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -7988,8 +8097,7 @@ proc_invoke(proc, args, self, klass)
|
||||||
|
|
||||||
Data_Get_Struct(proc, struct BLOCK, data);
|
Data_Get_Struct(proc, struct BLOCK, data);
|
||||||
pcall = (data->flags & BLOCK_LAMBDA) ? YIELD_LAMBDA_CALL : 0;
|
pcall = (data->flags & BLOCK_LAMBDA) ? YIELD_LAMBDA_CALL : 0;
|
||||||
orphan = pcall ? 0 : block_orphan(data);
|
// orphan = pcall ? 0 : block_orphan(data);
|
||||||
if (orphan || pcall) pcall |= YIELD_BLOCK_ORPHAN;
|
|
||||||
if (!pcall && RARRAY(args)->len == 1) {
|
if (!pcall && RARRAY(args)->len == 1) {
|
||||||
avalue = Qfalse;
|
avalue = Qfalse;
|
||||||
args = RARRAY(args)->ptr[0];
|
args = RARRAY(args)->ptr[0];
|
||||||
|
@ -8006,7 +8114,7 @@ proc_invoke(proc, args, self, klass)
|
||||||
|
|
||||||
PUSH_ITER(ITER_CUR);
|
PUSH_ITER(ITER_CUR);
|
||||||
ruby_frame->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();
|
state = EXEC_TAG();
|
||||||
if (state == 0) {
|
if (state == 0) {
|
||||||
proc_set_safe_level(proc);
|
proc_set_safe_level(proc);
|
||||||
|
@ -8026,21 +8134,17 @@ proc_invoke(proc, args, self, klass)
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
case TAG_RETRY:
|
case TAG_RETRY:
|
||||||
if (pcall || orphan) {
|
proc_jump_error(TAG_RETRY, Qnil); /* xxx */
|
||||||
localjump_error("retry from proc-closure", Qnil, state);
|
JUMP_TAG(state);
|
||||||
}
|
break;
|
||||||
/* fall through */
|
|
||||||
case TAG_BREAK:
|
case TAG_BREAK:
|
||||||
case TAG_RETURN:
|
if (!pcall && result != Qundef) {
|
||||||
if (orphan) { /* orphan block */
|
proc_jump_error(state, result);
|
||||||
char mesg[32];
|
|
||||||
snprintf(mesg, sizeof mesg, "%s from proc-closure",
|
|
||||||
state == TAG_BREAK ? "break" : "return");
|
|
||||||
localjump_error(mesg, result, state);
|
|
||||||
}
|
}
|
||||||
|
case TAG_RETURN:
|
||||||
if (result != Qundef) {
|
if (result != Qundef) {
|
||||||
if (pcall) break;
|
if (pcall) break;
|
||||||
localjump_destination(state, result);
|
return_jump(result);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
JUMP_TAG(state);
|
JUMP_TAG(state);
|
||||||
|
@ -8344,7 +8448,7 @@ block_pass(self, node)
|
||||||
if (ruby_frame->iter == ITER_NOT)
|
if (ruby_frame->iter == ITER_NOT)
|
||||||
ruby_frame->iter = ITER_PRE;
|
ruby_frame->iter = ITER_PRE;
|
||||||
|
|
||||||
PUSH_TAG(PROT_ITER);
|
PUSH_TAG(PROT_LOOP);
|
||||||
state = EXEC_TAG();
|
state = EXEC_TAG();
|
||||||
if (state == 0) {
|
if (state == 0) {
|
||||||
retry:
|
retry:
|
||||||
|
@ -8371,7 +8475,7 @@ block_pass(self, node)
|
||||||
break;
|
break;
|
||||||
case TAG_RETURN:
|
case TAG_RETURN:
|
||||||
if (orphan) {
|
if (orphan) {
|
||||||
localjump_error("return from proc-closure", prot_tag->retval, state);
|
proc_jump_error(state, prot_tag->retval);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
JUMP_TAG(state);
|
JUMP_TAG(state);
|
||||||
|
|
|
@ -683,6 +683,23 @@ sock_addrinfo(host, port, socktype, flags)
|
||||||
rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
gc.c
6
gc.c
|
@ -934,7 +934,7 @@ gc_mark_children(ptr, lev)
|
||||||
case T_REGEXP:
|
case T_REGEXP:
|
||||||
case T_FLOAT:
|
case T_FLOAT:
|
||||||
case T_BIGNUM:
|
case T_BIGNUM:
|
||||||
case T_BLKTAG:
|
case T_BLOCK:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_MATCH:
|
case T_MATCH:
|
||||||
|
@ -1186,7 +1186,7 @@ obj_free(obj)
|
||||||
|
|
||||||
case T_FLOAT:
|
case T_FLOAT:
|
||||||
case T_VARMAP:
|
case T_VARMAP:
|
||||||
case T_BLKTAG:
|
case T_BLOCK:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_BIGNUM:
|
case T_BIGNUM:
|
||||||
|
@ -1838,7 +1838,7 @@ id2ref(obj, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = id ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */
|
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);
|
rb_raise(rb_eRangeError, "0x%lx is not id value", p0);
|
||||||
}
|
}
|
||||||
if (BUILTIN_TYPE(ptr) == 0 || RBASIC(ptr)->klass == 0) {
|
if (BUILTIN_TYPE(ptr) == 0 || RBASIC(ptr)->klass == 0) {
|
||||||
|
|
5
io.c
5
io.c
|
@ -1696,8 +1696,9 @@ rb_io_ungetc(io, c)
|
||||||
rb_raise(rb_eIOError, "unread stream");
|
rb_raise(rb_eIOError, "unread stream");
|
||||||
rb_io_check_readable(fptr);
|
rb_io_check_readable(fptr);
|
||||||
|
|
||||||
if (ungetc(cc, fptr->f) == EOF && cc != EOF)
|
if (ungetc(cc, fptr->f) == EOF && cc != EOF) {
|
||||||
rb_sys_fail(fptr->path);
|
rb_raise(rb_eIOError, "ungetc failed");
|
||||||
|
}
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ class GetoptLong
|
||||||
# Error types.
|
# Error types.
|
||||||
#
|
#
|
||||||
class Error < StandardError; end
|
class Error < StandardError; end
|
||||||
class AmbigousOption < Error; end
|
class AmbiguousOption < Error; end
|
||||||
class NeedlessArgument < Error; end
|
class NeedlessArgument < Error; end
|
||||||
class MissingArgument < Error; end
|
class MissingArgument < Error; end
|
||||||
class InvalidOption < Error; end
|
class InvalidOption < Error; end
|
||||||
|
@ -208,7 +208,7 @@ class GetoptLong
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Set/Unset `quit' mode.
|
# Set/Unset `quiet' mode.
|
||||||
#
|
#
|
||||||
attr_writer :quiet
|
attr_writer :quiet
|
||||||
|
|
||||||
|
@ -351,16 +351,16 @@ class GetoptLong
|
||||||
# The option `option_name' is not registered in `@canonical_names'.
|
# The option `option_name' is not registered in `@canonical_names'.
|
||||||
# It may be an abbreviated.
|
# It may be an abbreviated.
|
||||||
#
|
#
|
||||||
match_count = 0
|
matches = []
|
||||||
@canonical_names.each_key do |key|
|
@canonical_names.each_key do |key|
|
||||||
if key.index(pattern) == 0
|
if key.index(pattern) == 0
|
||||||
option_name = key
|
option_name = key
|
||||||
match_count += 1
|
matches << key
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if 2 <= match_count
|
if 2 <= matches.length
|
||||||
set_error(AmbigousOption, "option `#{argument}' is ambiguous")
|
set_error(AmbiguousOption, "option `#{argument}' is ambiguous between #{matches.join(', ')}")
|
||||||
elsif match_count == 0
|
elsif matches.length == 0
|
||||||
set_error(InvalidOption, "unrecognized option `#{argument}'")
|
set_error(InvalidOption, "unrecognized option `#{argument}'")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -182,7 +182,7 @@ module IRB
|
||||||
end
|
end
|
||||||
|
|
||||||
if Readline.respond_to?("basic_word_break_characters=")
|
if Readline.respond_to?("basic_word_break_characters=")
|
||||||
Readline.basic_word_break_characters= "\t\n\"\\'`><=;|&{("
|
Readline.basic_word_break_characters= " \t\n\"\\'`><=;|&{("
|
||||||
end
|
end
|
||||||
Readline.completion_append_character = nil
|
Readline.completion_append_character = nil
|
||||||
Readline.completion_proc = IRB::InputCompletor::CompletionProc
|
Readline.completion_proc = IRB::InputCompletor::CompletionProc
|
||||||
|
|
22
ruby.h
22
ruby.h
|
@ -193,19 +193,19 @@ VALUE rb_ull2inum _((unsigned LONG_LONG));
|
||||||
#define T_BIGNUM 0x0d
|
#define T_BIGNUM 0x0d
|
||||||
#define T_FILE 0x0e
|
#define T_FILE 0x0e
|
||||||
|
|
||||||
#define T_TRUE 0x20
|
#define T_TRUE 0x10
|
||||||
#define T_FALSE 0x21
|
#define T_FALSE 0x11
|
||||||
#define T_DATA 0x22
|
#define T_DATA 0x12
|
||||||
#define T_MATCH 0x23
|
#define T_MATCH 0x13
|
||||||
#define T_SYMBOL 0x24
|
#define T_SYMBOL 0x14
|
||||||
|
|
||||||
#define T_BLKTAG 0x3b
|
#define T_BLOCK 0x1b
|
||||||
#define T_UNDEF 0x3c
|
#define T_UNDEF 0x1c
|
||||||
#define T_VARMAP 0x3d
|
#define T_VARMAP 0x1d
|
||||||
#define T_SCOPE 0x3e
|
#define T_SCOPE 0x1e
|
||||||
#define T_NODE 0x3f
|
#define T_NODE 0x1f
|
||||||
|
|
||||||
#define T_MASK 0x3f
|
#define T_MASK 0x1f
|
||||||
|
|
||||||
#define BUILTIN_TYPE(x) (((struct RBasic*)(x))->flags & T_MASK)
|
#define BUILTIN_TYPE(x) (((struct RBasic*)(x))->flags & T_MASK)
|
||||||
|
|
||||||
|
|
138
sample/test.rb
138
sample/test.rb
|
@ -1134,23 +1134,135 @@ test_ok(55, begin
|
||||||
$!.exit_value
|
$!.exit_value
|
||||||
end)
|
end)
|
||||||
|
|
||||||
test_ok(block.arity == -1)
|
def block_call(&block)
|
||||||
test_ok(lambda.arity == -1)
|
block.call
|
||||||
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 yield_in_lambda
|
|
||||||
lambda{ yield }[]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def return_in_lambda
|
def block_get(&block)
|
||||||
yield_in_lambda{ return true }
|
block
|
||||||
false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test_ok(return_in_lambda())
|
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)
|
||||||
|
|
||||||
|
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)
|
def marity_test(m)
|
||||||
method = method(m)
|
method = method(m)
|
||||||
|
|
15
struct.c
15
struct.c
|
@ -285,12 +285,19 @@ rb_struct_s_def(argc, argv, klass)
|
||||||
id = rb_to_id(RARRAY(rest)->ptr[i]);
|
id = rb_to_id(RARRAY(rest)->ptr[i]);
|
||||||
RARRAY(rest)->ptr[i] = ID2SYM(id);
|
RARRAY(rest)->ptr[i] = ID2SYM(id);
|
||||||
}
|
}
|
||||||
if (!NIL_P(name) && TYPE(name) != T_STRING) {
|
if (!NIL_P(name)) {
|
||||||
id = rb_to_id(name);
|
VALUE tmp = rb_check_string_type(name);
|
||||||
rb_ary_unshift(rest, ID2SYM(id));
|
|
||||||
name = Qnil;
|
if (NIL_P(tmp)) {
|
||||||
|
id = rb_to_id(name);
|
||||||
|
rb_ary_unshift(rest, ID2SYM(id));
|
||||||
|
name = Qnil;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
st = make_struct(name, rest, klass);
|
st = make_struct(name, rest, klass);
|
||||||
|
if (rb_block_given_p()) {
|
||||||
|
rb_mod_module_eval(0, 0, st);
|
||||||
|
}
|
||||||
|
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue