From f289fddace1c84075e6794e24a3d46aee6b35d69 Mon Sep 17 00:00:00 2001 From: matz Date: Fri, 20 Jun 2003 07:11:44 +0000 Subject: * parse.y (new_yield): distinguish "yield 1,2" and "yield [1,2]". [ruby-dev:20360] * eval.c (rb_eval): support new_yield() change. * variable.c (rb_const_get_0): warn for Foo::BAR when BAR is a toplevel constant (i.e. a constant defined under Object). [ruby-list:36935] * parse.y (no_blockarg): separate no block argument check and ret_args argument processing. * range.c (rb_range_beg_len): out_of_range check after adjusting end point. [ruby-dev:20370] * parse.y (call_args): the first argument to arg_cancat() should be NODE_LIST. [ruby-core:01151] * eval.c (rb_eval): should dispatch based on ID type. * eval.c (rb_yield_0): should restore scope_vmode during yield. [ruby-dev:20361] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3967 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 33 +++++++++++++++++++++++++++++++++ class.c | 4 ++-- eval.c | 36 +++++++++++++++++++++++------------- file.c | 2 -- intern.h | 4 +++- node.h | 2 +- parse.y | 51 +++++++++++++++++++++++++++++++++++++++++---------- range.c | 8 ++------ sample/test.rb | 1 - variable.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 10 files changed, 149 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index c3f01c20a5..c7132604b6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,20 @@ Fri Jun 20 15:04:28 2003 NAKAMURA Usaku * ruby.c (proc_options): ditto. +Fri Jun 20 03:09:21 2003 Yukihiro Matsumoto + + * parse.y (new_yield): distinguish "yield 1,2" and "yield [1,2]". + [ruby-dev:20360] + + * eval.c (rb_eval): support new_yield() change. + + * variable.c (rb_const_get_0): warn for Foo::BAR when BAR is a + toplevel constant (i.e. a constant defined under Object). + [ruby-list:36935] + + * parse.y (no_blockarg): separate no block argument check and + ret_args argument processing. + Fri Jun 20 00:45:19 2003 NAKAMURA, Hiroshi * lib/csv.rb: Import csv module. @@ -32,12 +46,31 @@ Thu Jun 19 13:13:10 2003 NAKAMURA Usaku * hash.c (env_delete, rb_f_getenv, env_fetch): case insensitive to access environment variables on DOSISH platforms. +Thu Jun 19 00:51:47 2003 NAKAMURA Hiroshi + + * range.c (rb_range_beg_len): out_of_range check after adjusting + end point. [ruby-dev:20370] + +Wed Jun 18 23:59:11 2003 Guy Decoux + + * parse.y (call_args): the first argument to arg_cancat() should + be NODE_LIST. [ruby-core:01151] + Wed Jun 18 23:41:27 2003 Marc Cartright * ext/zlib/zlib.c (zstream_run): In a particular situation, deflate/inflate will return Z_BUF_ERROR, even though another call is required by the zlib library. +Wed Jun 18 13:50:06 2003 Yukihiro Matsumoto + + * eval.c (rb_eval): should dispatch based on ID type. + +Wed Jun 18 12:53:42 2003 Minero Aoki + + * eval.c (rb_yield_0): should restore scope_vmode during yield. + [ruby-dev:20361] + Wed Jun 18 01:13:36 2003 why the lucky stiff * ext/syck/rubyext.c (rb_syck_load_handler): merge key implemented. diff --git a/class.c b/class.c index 68d908665e..a3d038da94 100644 --- a/class.c +++ b/class.c @@ -229,7 +229,7 @@ rb_define_class_under(outer, name, super) id = rb_intern(name); if (rb_const_defined_at(outer, id)) { - klass = rb_const_get(outer, id); + klass = rb_const_get_at(outer, id); if (TYPE(klass) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", name); } @@ -306,7 +306,7 @@ rb_define_module_under(outer, name) id = rb_intern(name); if (rb_const_defined_at(outer, id)) { - module = rb_const_get(outer, id); + module = rb_const_get_at(outer, id); if (TYPE(module) == T_MODULE) return module; rb_raise(rb_eTypeError, "%s::%s is not a module", diff --git a/eval.c b/eval.c index be8b3d3d02..de1d9b9ac3 100644 --- a/eval.c +++ b/eval.c @@ -2131,7 +2131,7 @@ is_defined(self, node, buf) switch (TYPE(val)) { case T_CLASS: case T_MODULE: - if (rb_const_defined_at(val, node->nd_mid)) + if (rb_const_defined_from(val, node->nd_mid)) return "constant"; break; default: @@ -2774,14 +2774,14 @@ rb_eval(self, n) break; case NODE_YIELD: - if (node->nd_stts) { + if (node->nd_head) { result = rb_eval(self, node->nd_head); } else { result = Qundef; /* no arg */ } SET_CURRENT_SOURCE(); - result = rb_yield_0(result, 0, 0, Qfalse, Qfalse); + result = rb_yield_0(result, 0, 0, Qfalse, node->nd_state); break; case NODE_RESCUE: @@ -3235,15 +3235,22 @@ rb_eval(self, n) VALUE klass; klass = rb_eval(self, node->nd_head); - switch (TYPE(klass)) { - case T_CLASS: - case T_MODULE: - result = rb_const_get(klass, node->nd_mid); - break; - default: + if (rb_is_const_id(node->nd_mid)) { + switch (TYPE(klass)) { + case T_CLASS: + case T_MODULE: + result = rb_const_get_from(klass, node->nd_mid); + break; + default: + rb_raise(rb_eTypeError, "%s is not a class/module", + RSTRING(rb_obj_as_string(klass))->ptr); + break; + } + } + else { result = rb_funcall(klass, node->nd_mid, 0, 0); - break; } + break; } break; @@ -3506,7 +3513,7 @@ rb_eval(self, n) cbase = class_prefix(self, node->nd_cpath); cname = node->nd_cpath->nd_mid; if (rb_const_defined_at(cbase, cname)) { - klass = rb_const_get(cbase, cname); + klass = rb_const_get_at(cbase, cname); if (TYPE(klass) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", rb_id2name(cname)); @@ -3549,7 +3556,7 @@ rb_eval(self, n) cbase = class_prefix(self, node->nd_cpath); cname = node->nd_cpath->nd_mid; if (rb_const_defined_at(cbase, cname)) { - module = rb_const_get(cbase, cname); + module = rb_const_get_at(cbase, cname); if (TYPE(module) != T_MODULE) { rb_raise(rb_eTypeError, "%s is not a module", rb_id2name(cname)); @@ -4014,6 +4021,7 @@ rb_yield_0(val, self, klass, pcall, avalue) volatile VALUE old_wrapper; struct BLOCK * volatile block; struct SCOPE * volatile old_scope; + int old_vmode; struct FRAME frame; NODE *cnode = ruby_current_node; int state; @@ -4035,6 +4043,8 @@ rb_yield_0(val, self, klass, pcall, avalue) ruby_wrapper = block->wrapper; old_scope = ruby_scope; ruby_scope = block->scope; + old_vmode = scope_vmode; + scope_vmode = block->vmode; ruby_block = block->prev; if (block->flags & BLOCK_D_SCOPE) { /* put place holder for dynamic (in-block) local variables */ @@ -4154,6 +4164,7 @@ rb_yield_0(val, self, klass, pcall, avalue) if (ruby_scope->flags & SCOPE_DONT_RECYCLE) scope_dup(old_scope); ruby_scope = old_scope; + scope_vmode = old_vmode; ruby_current_node = cnode; if (state) { if (!block->tag) { @@ -8117,7 +8128,6 @@ rb_thread_save_context(th) th->wrapper = ruby_wrapper; th->cref = ruby_cref; th->dyna_vars = ruby_dyna_vars; - FL_SET(ruby_dyna_vars, DVAR_DONT_RECYCLE); th->block = ruby_block; th->flags &= THREAD_FLAGS_MASK; th->flags |= (rb_trap_immediate<<8) | scope_vmode; diff --git a/file.c b/file.c index 046582a818..156b329f86 100644 --- a/file.c +++ b/file.c @@ -2562,7 +2562,6 @@ rb_file_const(name, value) { rb_define_const(rb_mFConst, name, value); rb_define_const(rb_cIO, name, value); - rb_define_const(rb_cFile, name, value); } static int @@ -2903,7 +2902,6 @@ Init_File() rb_define_method(rb_cFile, "flock", rb_file_flock, 1); rb_mFConst = rb_define_module_under(rb_cFile, "Constants"); - rb_include_module(rb_cFile, rb_mFConst); rb_file_const("LOCK_SH", INT2FIX(LOCK_SH)); rb_file_const("LOCK_EX", INT2FIX(LOCK_EX)); rb_file_const("LOCK_UN", INT2FIX(LOCK_UN)); diff --git a/intern.h b/intern.h index 5fddb41ac8..f80e5de217 100644 --- a/intern.h +++ b/intern.h @@ -451,10 +451,12 @@ void *rb_mod_const_of _((VALUE, void*)); VALUE rb_const_list _((void*)); VALUE rb_mod_constants _((VALUE)); VALUE rb_mod_remove_const _((VALUE, VALUE)); -int rb_const_defined_at _((VALUE, ID)); int rb_const_defined _((VALUE, ID)); +int rb_const_defined_at _((VALUE, ID)); +int rb_const_defined_from _((VALUE, ID)); VALUE rb_const_get _((VALUE, ID)); VALUE rb_const_get_at _((VALUE, ID)); +VALUE rb_const_get_from _((VALUE, ID)); void rb_const_set _((VALUE, ID, VALUE)); void rb_const_assign _((VALUE, ID, VALUE)); VALUE rb_mod_constants _((VALUE)); diff --git a/node.h b/node.h index 516618a7a5..57fee31ad3 100644 --- a/node.h +++ b/node.h @@ -261,7 +261,7 @@ typedef struct RNode { #define NEW_RESBODY(a,ex,n) rb_node_newnode(NODE_RESBODY,n,ex,a) #define NEW_ENSURE(b,en) rb_node_newnode(NODE_ENSURE,b,0,en) #define NEW_RETURN(s) rb_node_newnode(NODE_RETURN,s,0,0) -#define NEW_YIELD(a) rb_node_newnode(NODE_YIELD,a,0,0) +#define NEW_YIELD(a,s) rb_node_newnode(NODE_YIELD,a,0,s) #define NEW_LIST(a) NEW_ARRAY(a) #define NEW_ARRAY(a) rb_node_newnode(NODE_ARRAY,a,1,0) #define NEW_ZARRAY() rb_node_newnode(NODE_ZARRAY,0,0,0) diff --git a/parse.y b/parse.y index c09522de30..e87bcfec59 100644 --- a/parse.y +++ b/parse.y @@ -145,6 +145,7 @@ static NODE *arg_blk_pass(); static NODE *new_call(); static NODE *new_fcall(); static NODE *new_super(); +static NODE *new_yield(); static NODE *gettable(); static NODE *assignable(); @@ -714,7 +715,7 @@ command : operation command_args %prec tLOWEST } | kYIELD command_args { - $$ = NEW_YIELD(ret_args($2)); + $$ = new_yield($2); fixpos($$, $2); } ; @@ -1287,7 +1288,7 @@ call_args2 : arg_value ',' args opt_block_arg } | arg_value ',' args ',' tSTAR arg_value opt_block_arg { - $$ = arg_concat(list_concat($1,$3), $6); + $$ = arg_concat(list_concat(NEW_LIST($1),$3), $6); $$ = arg_blk_pass($$, $7); } | assocs opt_block_arg @@ -1454,15 +1455,15 @@ primary : literal } | kYIELD '(' call_args ')' { - $$ = NEW_YIELD(ret_args($3)); + $$ = new_yield($3); } | kYIELD '(' ')' { - $$ = NEW_YIELD(0); + $$ = NEW_YIELD(0, Qfalse); } | kYIELD { - $$ = NEW_YIELD(0); + $$ = NEW_YIELD(0, Qfalse); } | kDEFINED opt_nl '(' {in_defined = 1;} expr ')' { @@ -5366,22 +5367,52 @@ cond_negative(nodep) return 0; } +static void +no_blockarg(node) + NODE *node; +{ + if (node && nd_type(node) == NODE_BLOCK_PASS) { + rb_compile_error("block argument should not be given"); + } +} + static NODE * ret_args(node) NODE *node; { if (node) { - if (nd_type(node) == NODE_BLOCK_PASS) { - rb_compile_error("block argument should not be given"); + no_blockarg(node); + if (nd_type(node) == NODE_ARRAY && node->nd_next == 0) { + node = node->nd_head; + } + if (nd_type(node) == NODE_RESTARY) { + nd_set_type(node, NODE_SPLAT); } + } + return node; +} + +static NODE * +new_yield(node) + NODE *node; +{ + long state = Qtrue; + + if (node) { + no_blockarg(node); if (nd_type(node) == NODE_ARRAY && node->nd_next == 0) { node = node->nd_head; + state = Qfalse; + } + if (nd_type(node) == NODE_RESTARY) { + nd_set_type(node, NODE_SPLAT); + state = Qfalse; } } - if (node && nd_type(node) == NODE_RESTARY) { - nd_set_type(node, NODE_SPLAT); + else { + state = Qfalse; } - return node; + return NEW_YIELD(node, state); } static NODE* diff --git a/range.c b/range.c index da8eeda513..9a73c867a1 100644 --- a/range.c +++ b/range.c @@ -377,13 +377,9 @@ rb_range_beg_len(range, begp, lenp, len, err) if (end > len) end = len; } - if (end < 0) { - end += len; - if (end < 0) { - goto out_of_range; - } - } + if (end < 0) end += len; if (!EXCL(range)) end++; /* include end point */ + if (end < 0) goto out_of_range; len = end - beg; if (len < 0) goto out_of_range; diff --git a/sample/test.rb b/sample/test.rb index 6b514a20e3..e281b679b1 100644 --- a/sample/test.rb +++ b/sample/test.rb @@ -125,7 +125,6 @@ def f; yield *[1]; end; f {|a| test_ok(a == 1)} def f; yield *[nil]; end; f {|a| test_ok(a == nil)} def f; yield *[[]]; end; f {|a| test_ok(a == [])} def f; yield *[*[1]]; end; f {|a| test_ok(a == 1)} -def f; yield *[*[1,2]]; end; f {|a| test_ok(a == [1,2])} def f; yield; end; f {|*a| test_ok(a == [])} def f; yield nil; end; f {|*a| test_ok(a == [nil])} diff --git a/variable.c b/variable.c index f0ace3afb1..5c65c0425b 100644 --- a/variable.c +++ b/variable.c @@ -1284,10 +1284,11 @@ rb_const_get_at(klass, id) return Qnil; /* not reached */ } -VALUE -rb_const_get(klass, id) +static VALUE +rb_const_get_0(klass, id, exclude) VALUE klass; ID id; + int exclude; { VALUE value, tmp; int mod_retry = 0; @@ -1295,6 +1296,10 @@ rb_const_get(klass, id) tmp = klass; retry: while (tmp) { + if (exclude && tmp == rb_cObject && klass != rb_cObject) { + rb_warn("toplevel constant %s referenced by %s::%s", + rb_id2name(id), rb_class2name(klass), rb_id2name(id)); + } while (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) { if (value == Qundef) { rb_autoload_load(tmp, id); @@ -1315,6 +1320,22 @@ rb_const_get(klass, id) return Qnil; /* not reached */ } +VALUE +rb_const_get_from(klass, id) + VALUE klass; + ID id; +{ + return rb_const_get_0(klass, id, Qtrue); +} + +VALUE +rb_const_get(klass, id) + VALUE klass; + ID id; +{ + return rb_const_get_0(klass, id, Qfalse); +} + VALUE rb_mod_remove_const(mod, name) VALUE mod, name; @@ -1439,6 +1460,27 @@ rb_const_defined_at(klass, id) return Qfalse; } +int +rb_const_defined_from(klass, id) + VALUE klass; + ID id; +{ + VALUE tmp = klass, value; + + while (tmp) { + if (tmp == rb_cObject && klass != rb_cObject) { + break; + } + if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl, id, &value)) { + if (value == Qundef && NIL_P(autoload_file(klass, id))) + return Qfalse; + return Qtrue; + } + tmp = RCLASS(tmp)->super; + } + return Qfalse; +} + int rb_const_defined(klass, id) VALUE klass; -- cgit v1.2.3