From: nobu@... Date: 2006-09-03T14:20:00+09:00 Subject: [ruby-dev:29431] Re: method_missing in Ruby 1.9.0 なかだです。 At Sun, 3 Sep 2006 09:55:59 +0900, Masaki Suketa wrote in [ruby-dev:29420]: > 次のスクリプトが、ruby 1.9.0 (2006-09-03)で falseと出力されます。 > class Foo > def method_missing(id, *arg) > p id # => false > end > end > > foo = Foo.new > foo.visible = true たまたまfalse(== 0)になっただけで、実際には不定値ですね。 Index: gc.c =================================================================== RCS file: /cvs/ruby/src/ruby/gc.c,v retrieving revision 1.248 diff -p -U 2 -r1.248 gc.c --- gc.c 2 Sep 2006 15:05:27 -0000 1.248 +++ gc.c 3 Sep 2006 01:12:58 -0000 @@ -1382,5 +1382,5 @@ garbage_collect(void) #endif rb_gc_mark_threads(); - rb_gc_mark_symbols(); + rb_gc_mark_symbols(0); /* mark protected global variables */ Index: intern.h =================================================================== RCS file: /cvs/ruby/src/ruby/intern.h,v retrieving revision 1.199 diff -p -U 2 -r1.199 intern.h --- intern.h 31 Aug 2006 08:24:36 -0000 1.199 +++ intern.h 3 Sep 2006 01:12:33 -0000 @@ -259,4 +259,5 @@ int ruby_cleanup(int); int ruby_exec(void); void rb_gc_mark_threads(void); +void rb_gc_mark_symbols(int); void rb_thread_start_timer(void); void rb_thread_stop_timer(void); Index: parse.y =================================================================== RCS file: /cvs/ruby/src/ruby/parse.y,v retrieving revision 1.456 diff -p -U 2 -r1.456 parse.y --- parse.y 2 Sep 2006 15:05:27 -0000 1.456 +++ parse.y 3 Sep 2006 05:10:38 -0000 @@ -6030,5 +6030,4 @@ parser_yylex(struct parser_params *parse } if (c == '>') { - enum lex_state_e state = lex_state; lex_state = EXPR_ARG; return tLAMBDA; @@ -8379,4 +8378,13 @@ rb_symname_p(const char *name) } +static void +register_symid(VALUE sym, ID id) +{ + RBASIC(sym)->klass = rb_cSymbol; + OBJ_FREEZE(sym); + st_add_direct(global_symbols.sym_id, (st_data_t)sym, id); + st_add_direct(global_symbols.id_sym, id, (st_data_t)sym); +} + ID rb_intern2(const char *name, long len) @@ -8451,8 +8459,5 @@ rb_intern2(const char *name, long len) id |= ++global_symbols.last_id << ID_SCOPE_SHIFT; id_register: - RBASIC(sym)->klass = rb_cSymbol; - OBJ_FREEZE(sym); - st_add_direct(global_symbols.sym_id, (st_data_t)sym, id); - st_add_direct(global_symbols.id_sym, id, (st_data_t)sym); + register_symid(sym, id); return id; } @@ -8467,12 +8472,25 @@ VALUE rb_id2sym(ID id) { - VALUE data; + VALUE sym; + st_data_t data; if (st_lookup(global_symbols.id_sym, id, &data)) { - if (!RBASIC(data)->klass) { - RBASIC(data)->klass = rb_cSymbol; + sym = (VALUE)data; + if (!RBASIC(sym)->klass) { + RBASIC(sym)->klass = rb_cSymbol; } - return data; } + else { + if (!is_attrset_id(id)) return Qnil; + id &= ~ID_SCOPE_MASK; + if (!st_lookup(global_symbols.id_sym, (id | ID_LOCAL), &data) && + !st_lookup(global_symbols.id_sym, (id | ID_CONST), &data)) { + return Qnil; + } + sym = rb_str_dup((VALUE)data); + rb_str_cat(sym, "=", 1); + register_symid(sym, (id | ID_ATTRSET)); + } + return sym; } @@ -8490,6 +8508,5 @@ const char * rb_id2name(ID id) { - const char *name; - st_data_t data; + VALUE sym; if (id < tLAST_TOKEN) { @@ -8502,24 +8519,7 @@ rb_id2name(ID id) } - if (st_lookup(global_symbols.id_sym, id, &data)) - return RSTRING_PTR(data); - - if (is_attrset_id(id)) { - ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL; - - again: - name = rb_id2name(id2); - if (name) { - char *buf = ALLOCA_N(char, strlen(name)+2); - - strcpy(buf, name); - strcat(buf, "="); - rb_intern(buf); - return rb_id2name(id); - } - if (is_local_id(id2)) { - id2 = (id & ~ID_SCOPE_MASK) | ID_CONST; - goto again; - } + sym = rb_id2sym(id); + if (!NIL_P(sym)) { + return RSTRING_PTR(sym); } return 0; -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦