From: Nobuyoshi Nakada Date: 2007-06-20T14:44:57+09:00 Subject: [ruby-dev:31028] rb_get_interned なかだです。 以前追加されたrb_sym_interned_p()は結局、intern.hに宣言だけ残し て消されてしまったようですが、変数や定数が定義されているかを調 べようとするだけで新しい名前が登録されてしまうのは無駄のような 気がします。 ID rb_get_interned(const char *name, long len); のような形で既存の名前だけを探すというのはどうでしょうか。 とりあえずvariable.c:rb_path2class()を例に。 Index: parse.y =================================================================== --- parse.y (revision 12575) +++ parse.y (working copy) @@ -8418,17 +8418,57 @@ rb_symname_p(const char *name) } +static ID +id_register(VALUE str, ID id) +{ + OBJ_FREEZE(str); + st_add_direct(global_symbols.sym_id, (st_data_t)str, id); + st_add_direct(global_symbols.id_str, id, (st_data_t)str); + return id; +} + +static ID +get_interned(VALUE str) +{ + st_data_t id; + + if (st_lookup(global_symbols.sym_id, (st_data_t)str, &id)) + return (ID)id; + + if (RSTRING_LEN(str) > 0) { + const char *name = RSTRING_PTR(str); + char c = *name; + + if (c != '_' && c != '$' && c != '@' && ISASCII(c) && !ISALNUM(c)) { + /* operators */ + int i; + + for (i = 0; op_tbl[i].token; i++) { + if (*op_tbl[i].name == *name && + strcmp(op_tbl[i].name, name) == 0) { + return id_register(str, op_tbl[i].token); + } + } + } + } + + return 0; +} + +ID +rb_get_interned(const char *name, long len) +{ + return get_interned(rb_str_new(name, len)); +} + ID rb_intern2(const char *name, long len) { const char *m = name; - VALUE str = rb_str_new(name, len); - ID id; int last; + VALUE str = rb_str_new(name, len); + ID id = get_interned(str); - if (st_lookup(global_symbols.sym_id, (st_data_t)str, (st_data_t *)&id)) - return id; - + if (id) return id; last = len-1; - id = 0; switch (*name) { case '$': @@ -8447,23 +8487,9 @@ rb_intern2(const char *name, long len) break; default: - if (name[0] != '_' && ISASCII(name[0]) && !ISALNUM(name[0])) { - /* operators */ - int i; - - for (i=0; op_tbl[i].token; i++) { - if (*op_tbl[i].name == *name && - strcmp(op_tbl[i].name, name) == 0) { - id = op_tbl[i].token; - goto id_register; - } - } - } - - if (name[last] == '=') { + if (name[last] == '=' && last > 1 && name[last-1] != '=') { /* attribute assignment */ id = rb_intern2(name, last); if (id > tLAST_TOKEN && !is_attrset_id(id)) { - id = rb_id_attrset(id); - goto id_register; + return id_register(str, rb_id_attrset(id)); } id = ID_ATTRSET; @@ -8485,9 +8511,5 @@ rb_intern2(const char *name, long len) new_id: id |= ++global_symbols.last_id << ID_SCOPE_SHIFT; - id_register: - OBJ_FREEZE(str); - st_add_direct(global_symbols.sym_id, (st_data_t)str, id); - st_add_direct(global_symbols.id_str, id, (st_data_t)str); - return id; + return id_register(str, id); } Index: variable.c =================================================================== --- variable.c (revision 12575) +++ variable.c (working copy) @@ -237,5 +237,6 @@ rb_path2class(const char *path) while (*p) { while (*p && *p != ':') p++; - id = rb_intern2(pbeg, p-pbeg); + id = rb_get_interned(pbeg, p-pbeg); + if (!id) goto undefined_class; if (p[0] == ':') { if (p[1] != ':') goto undefined_class; Index: include/ruby/intern.h =================================================================== --- include/ruby/intern.h (revision 12575) +++ include/ruby/intern.h (working copy) @@ -408,5 +409,4 @@ int rb_is_local_id(ID); int rb_is_junk_id(ID); int rb_symname_p(const char*); -int rb_sym_interned_p(VALUE); void rb_gc_mark_symbols(void); VALUE rb_backref_get(void); Index: include/ruby/ruby.h =================================================================== --- include/ruby/ruby.h (revision 12575) +++ include/ruby/ruby.h (working copy) @@ -614,4 +614,5 @@ void rb_gc_unregister_address(VALUE*); ID rb_intern(const char*); ID rb_intern2(const char*, long); +ID rb_get_interned(const char*, long); const char *rb_id2name(ID); ID rb_to_id(VALUE); -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦