diff --git a/include/ruby/intern.h b/include/ruby/intern.h index 56e2452..d9541ca 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -583,6 +583,7 @@ void rb_backref_set(VALUE); VALUE rb_lastline_get(void); void rb_lastline_set(VALUE); VALUE rb_sym_all_symbols(void); +VALUE rb_sym_lookup(int argc, VALUE *argv); /* process.c */ void rb_last_status_set(int status, rb_pid_t pid); VALUE rb_last_status_get(void); diff --git a/parse.y b/parse.y index 915db67..3931351 100644 --- a/parse.y +++ b/parse.y @@ -10413,6 +10413,38 @@ rb_sym_all_symbols(void) return ary; } +/* + * call-seq: + * Symbol[str] => Symbol or nil + * + * Returns an extant symbol, which is the .to_sym of +str+, or + * nil if no such symbol exists. + * + * Symbol['Object'] #=> :Object + * Symbol['none such'] #=> nil + */ + +VALUE +rb_sym_lookup(int argc, VALUE *argv) +{ + st_data_t id; + VALUE str,tmp; + rb_scan_args(argc, argv, "1", &str); + if (!RB_TYPE_P(str, T_STRING)) { + tmp = rb_check_string_type(str); + if (NIL_P(tmp)) { + tmp = rb_inspect(str); + rb_raise(rb_eTypeError, "%s is not a string", + RSTRING_PTR(tmp)); + } + str = tmp; + } + if (st_lookup(global_symbols.sym_id, (st_data_t)str, &id)) { + return ID2SYM(id); + } + return Qnil; +} + int rb_is_const_id(ID id) { diff --git a/string.c b/string.c index 04984f0..3bae1b7 100644 --- a/string.c +++ b/string.c @@ -8307,6 +8307,7 @@ Init_String(void) rb_undef_alloc_func(rb_cSymbol); rb_undef_method(CLASS_OF(rb_cSymbol), "new"); rb_define_singleton_method(rb_cSymbol, "all_symbols", rb_sym_all_symbols, 0); /* in parse.y */ + rb_define_singleton_method(rb_cSymbol, "[]", rb_sym_lookup, -1); /* in parse.y */ rb_define_method(rb_cSymbol, "==", sym_equal, 1); rb_define_method(rb_cSymbol, "===", sym_equal, 1);