* object.c (Init_Object): move symbol related code to string.c
* string.c (Init_String): Symbol as subclass of String. * parse.y (rb_intern2): handle symbol as strings. * string.c (str_new): substring of symbols are mere strings, not symbols. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10834 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
2156870525
commit
ccf5372b25
18
ChangeLog
18
ChangeLog
@ -1,3 +1,14 @@
|
|||||||
|
Sat Sep 2 23:53:28 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
|
* object.c (Init_Object): move symbol related code to string.c
|
||||||
|
|
||||||
|
* string.c (Init_String): Symbol as subclass of String.
|
||||||
|
|
||||||
|
* parse.y (rb_intern2): handle symbol as strings.
|
||||||
|
|
||||||
|
* string.c (str_new): substring of symbols are mere strings, not
|
||||||
|
symbols.
|
||||||
|
|
||||||
Sat Sep 2 23:37:29 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
|
Sat Sep 2 23:37:29 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
* ruby.h (struct RArray): embed small arrays.
|
* ruby.h (struct RArray): embed small arrays.
|
||||||
@ -17,6 +28,13 @@ Sat Sep 2 12:06:35 2006 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
|
|||||||
XML attribute which value is nil. value "" and nil both were dumped
|
XML attribute which value is nil. value "" and nil both were dumped
|
||||||
as 'attr="value"'. [ruby-dev:29395]
|
as 'attr="value"'. [ruby-dev:29395]
|
||||||
|
|
||||||
|
Sat Sep 2 11:47:58 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
|
* eval.c (rb_eval): should handle when in else clause. a patch
|
||||||
|
from Eric Hodel <drbrain at segment7.net>. [ruby-core:08662]
|
||||||
|
|
||||||
|
* parse.y (primary): wrap with NODE_CASE. [ruby-core:08663]
|
||||||
|
|
||||||
Sat Sep 2 12:00:32 2006 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
|
Sat Sep 2 12:00:32 2006 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
|
||||||
|
|
||||||
* lib/csv.rb (CSV::IOReader#initialize): use String#[](pos, len)
|
* lib/csv.rb (CSV::IOReader#initialize): use String#[](pos, len)
|
||||||
|
2
class.c
2
class.c
@ -489,7 +489,7 @@ ins_methods_push(ID name, long type, VALUE ary, long visi)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (visi) {
|
if (visi) {
|
||||||
rb_ary_push(ary, rb_str_new2(rb_id2name(name)));
|
rb_ary_push(ary, ID2SYM(name));
|
||||||
}
|
}
|
||||||
return ST_CONTINUE;
|
return ST_CONTINUE;
|
||||||
}
|
}
|
||||||
|
1
gc.c
1
gc.c
@ -1381,6 +1381,7 @@ garbage_collect(void)
|
|||||||
(VALUE*)((char*)rb_gc_stack_start + 2));
|
(VALUE*)((char*)rb_gc_stack_start + 2));
|
||||||
#endif
|
#endif
|
||||||
rb_gc_mark_threads();
|
rb_gc_mark_threads();
|
||||||
|
rb_gc_mark_symbols();
|
||||||
|
|
||||||
/* mark protected global variables */
|
/* mark protected global variables */
|
||||||
for (list = global_List; list; list = list->next) {
|
for (list = global_List; list; list = list->next) {
|
||||||
|
198
object.c
198
object.c
@ -30,7 +30,6 @@ VALUE rb_cData;
|
|||||||
VALUE rb_cNilClass;
|
VALUE rb_cNilClass;
|
||||||
VALUE rb_cTrueClass;
|
VALUE rb_cTrueClass;
|
||||||
VALUE rb_cFalseClass;
|
VALUE rb_cFalseClass;
|
||||||
VALUE rb_cSymbol;
|
|
||||||
|
|
||||||
static ID id_eq, id_eql, id_inspect, id_init_copy;
|
static ID id_eq, id_eql, id_inspect, id_init_copy;
|
||||||
|
|
||||||
@ -938,149 +937,6 @@ rb_obj_pattern_match(VALUE obj1, VALUE obj2)
|
|||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************
|
|
||||||
* Document-class: Symbol
|
|
||||||
*
|
|
||||||
* <code>Symbol</code> objects represent names and some strings
|
|
||||||
* inside the Ruby
|
|
||||||
* interpreter. They are generated using the <code>:name</code> and
|
|
||||||
* <code>:"string"</code> literals
|
|
||||||
* syntax, and by the various <code>to_sym</code> methods. The same
|
|
||||||
* <code>Symbol</code> object will be created for a given name or string
|
|
||||||
* for the duration of a program's execution, regardless of the context
|
|
||||||
* or meaning of that name. Thus if <code>Fred</code> is a constant in
|
|
||||||
* one context, a method in another, and a class in a third, the
|
|
||||||
* <code>Symbol</code> <code>:Fred</code> will be the same object in
|
|
||||||
* all three contexts.
|
|
||||||
*
|
|
||||||
* module One
|
|
||||||
* class Fred
|
|
||||||
* end
|
|
||||||
* $f1 = :Fred
|
|
||||||
* end
|
|
||||||
* module Two
|
|
||||||
* Fred = 1
|
|
||||||
* $f2 = :Fred
|
|
||||||
* end
|
|
||||||
* def Fred()
|
|
||||||
* end
|
|
||||||
* $f3 = :Fred
|
|
||||||
* $f1.id #=> 2514190
|
|
||||||
* $f2.id #=> 2514190
|
|
||||||
* $f3.id #=> 2514190
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* call-seq:
|
|
||||||
* sym.to_i => fixnum
|
|
||||||
*
|
|
||||||
* Returns an integer that is unique for each symbol within a
|
|
||||||
* particular execution of a program.
|
|
||||||
*
|
|
||||||
* :fred.to_i #=> 9809
|
|
||||||
* "fred".to_sym.to_i #=> 9809
|
|
||||||
*/
|
|
||||||
|
|
||||||
static VALUE
|
|
||||||
sym_to_i(VALUE sym)
|
|
||||||
{
|
|
||||||
ID id = SYM2ID(sym);
|
|
||||||
|
|
||||||
return LONG2FIX(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* call-seq:
|
|
||||||
* sym.inspect => string
|
|
||||||
*
|
|
||||||
* Returns the representation of <i>sym</i> as a symbol literal.
|
|
||||||
*
|
|
||||||
* :fred.inspect #=> ":fred"
|
|
||||||
*/
|
|
||||||
|
|
||||||
static VALUE
|
|
||||||
sym_inspect(VALUE sym)
|
|
||||||
{
|
|
||||||
VALUE str;
|
|
||||||
const char *name;
|
|
||||||
ID id = SYM2ID(sym);
|
|
||||||
|
|
||||||
name = rb_id2name(id);
|
|
||||||
str = rb_str_new(0, strlen(name)+1);
|
|
||||||
RSTRING_PTR(str)[0] = ':';
|
|
||||||
strcpy(RSTRING_PTR(str)+1, name);
|
|
||||||
if (!rb_symname_p(name)) {
|
|
||||||
str = rb_str_dump(str);
|
|
||||||
strncpy(RSTRING_PTR(str), ":\"", 2);
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* call-seq:
|
|
||||||
* sym.id2name => string
|
|
||||||
* sym.to_s => string
|
|
||||||
*
|
|
||||||
* Returns the name or string corresponding to <i>sym</i>.
|
|
||||||
*
|
|
||||||
* :fred.id2name #=> "fred"
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
static VALUE
|
|
||||||
sym_to_s(VALUE sym)
|
|
||||||
{
|
|
||||||
return rb_str_new2(rb_id2name(SYM2ID(sym)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* call-seq:
|
|
||||||
* sym.to_sym => sym
|
|
||||||
*
|
|
||||||
* In general, <code>to_sym</code> returns the <code>Symbol</code> corresponding
|
|
||||||
* to an object. As <i>sym</i> is already a symbol, <code>self</code> is returned
|
|
||||||
* in this case.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static VALUE
|
|
||||||
sym_to_sym(VALUE sym)
|
|
||||||
{
|
|
||||||
return sym;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VALUE
|
|
||||||
sym_call(VALUE args, VALUE sym)
|
|
||||||
{
|
|
||||||
VALUE obj;
|
|
||||||
|
|
||||||
if (RARRAY_LEN(args) < 1) {
|
|
||||||
rb_raise(rb_eArgError, "no receiver given");
|
|
||||||
}
|
|
||||||
obj = RARRAY_PTR(args)[0];
|
|
||||||
return rb_funcall3(obj, (ID)sym,
|
|
||||||
RARRAY_LEN(args) - 1,
|
|
||||||
RARRAY_PTR(args) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* call-seq:
|
|
||||||
* sym.to_proc
|
|
||||||
*
|
|
||||||
* Returns a _Proc_ object which respond to the given method by _sym_.
|
|
||||||
*
|
|
||||||
* (1..3).collect(&:to_s) #=> ["1", "2", "3"]
|
|
||||||
*/
|
|
||||||
|
|
||||||
static VALUE
|
|
||||||
sym_to_proc(VALUE sym)
|
|
||||||
{
|
|
||||||
return rb_proc_new(sym_call, (VALUE)SYM2ID(sym));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
*
|
*
|
||||||
@ -1473,47 +1329,6 @@ rb_class_superclass(VALUE klass)
|
|||||||
return super;
|
return super;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ID
|
|
||||||
str_to_id(VALUE str)
|
|
||||||
{
|
|
||||||
if (!RSTRING_PTR(str) || RSTRING_LEN(str) == 0) {
|
|
||||||
rb_raise(rb_eArgError, "empty symbol string");
|
|
||||||
}
|
|
||||||
if (RSTRING_LEN(str) != strlen(RSTRING_PTR(str))) {
|
|
||||||
rb_raise(rb_eArgError, "Symbols should not contain NUL (\\0)");
|
|
||||||
}
|
|
||||||
return rb_intern(RSTRING_PTR(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
ID
|
|
||||||
rb_to_id(VALUE name)
|
|
||||||
{
|
|
||||||
VALUE tmp;
|
|
||||||
ID id;
|
|
||||||
|
|
||||||
switch (TYPE(name)) {
|
|
||||||
case T_STRING:
|
|
||||||
return str_to_id(name);
|
|
||||||
case T_FIXNUM:
|
|
||||||
rb_warn("do not use Fixnums as Symbols");
|
|
||||||
id = FIX2LONG(name);
|
|
||||||
if (!rb_id2name(id)) {
|
|
||||||
rb_raise(rb_eArgError, "%ld is not a symbol", id);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case T_SYMBOL:
|
|
||||||
id = SYM2ID(name);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tmp = rb_check_string_type(name);
|
|
||||||
if (!NIL_P(tmp)) {
|
|
||||||
return str_to_id(tmp);
|
|
||||||
}
|
|
||||||
rb_raise(rb_eTypeError, "%s is not a symbol", RSTRING_PTR(rb_inspect(name)));
|
|
||||||
}
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* attr_reader(symbol, ...) => nil
|
* attr_reader(symbol, ...) => nil
|
||||||
@ -2449,19 +2264,6 @@ Init_Object(void)
|
|||||||
rb_undef_method(CLASS_OF(rb_cNilClass), "new");
|
rb_undef_method(CLASS_OF(rb_cNilClass), "new");
|
||||||
rb_define_global_const("NIL", Qnil);
|
rb_define_global_const("NIL", Qnil);
|
||||||
|
|
||||||
rb_cSymbol = rb_define_class("Symbol", rb_cObject);
|
|
||||||
rb_define_singleton_method(rb_cSymbol, "all_symbols", rb_sym_all_symbols, 0); /* in parse.y */
|
|
||||||
rb_undef_alloc_func(rb_cSymbol);
|
|
||||||
rb_undef_method(CLASS_OF(rb_cSymbol), "new");
|
|
||||||
|
|
||||||
rb_define_method(rb_cSymbol, "to_i", sym_to_i, 0);
|
|
||||||
rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0);
|
|
||||||
rb_define_method(rb_cSymbol, "to_s", sym_to_s, 0);
|
|
||||||
rb_define_method(rb_cSymbol, "id2name", sym_to_s, 0);
|
|
||||||
rb_define_method(rb_cSymbol, "to_sym", sym_to_sym, 0);
|
|
||||||
rb_define_method(rb_cSymbol, "to_proc", sym_to_proc, 0);
|
|
||||||
rb_define_method(rb_cSymbol, "===", rb_obj_equal, 1);
|
|
||||||
|
|
||||||
rb_define_method(rb_cModule, "freeze", rb_mod_freeze, 0);
|
rb_define_method(rb_cModule, "freeze", rb_mod_freeze, 0);
|
||||||
rb_define_method(rb_cModule, "===", rb_mod_eqq, 1);
|
rb_define_method(rb_cModule, "===", rb_mod_eqq, 1);
|
||||||
rb_define_method(rb_cModule, "==", rb_obj_equal, 1);
|
rb_define_method(rb_cModule, "==", rb_obj_equal, 1);
|
||||||
|
75
parse.y
75
parse.y
@ -8255,15 +8255,26 @@ static const struct {
|
|||||||
|
|
||||||
static struct symbols {
|
static struct symbols {
|
||||||
ID last_id;
|
ID last_id;
|
||||||
st_table *tbl;
|
st_table *sym_id;
|
||||||
st_table *rev;
|
st_table *id_sym;
|
||||||
} global_symbols = {tLAST_TOKEN};
|
} global_symbols = {tLAST_TOKEN};
|
||||||
|
|
||||||
|
static struct st_hash_type symhash = {
|
||||||
|
rb_str_cmp,
|
||||||
|
rb_str_hash,
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
Init_sym(void)
|
Init_sym(void)
|
||||||
{
|
{
|
||||||
global_symbols.tbl = st_init_strtable_with_size(200);
|
global_symbols.sym_id = st_init_table_with_size(&symhash, 1000);
|
||||||
global_symbols.rev = st_init_numtable_with_size(200);
|
global_symbols.id_sym = st_init_numtable_with_size(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_gc_mark_symbols(int lev)
|
||||||
|
{
|
||||||
|
rb_mark_tbl(global_symbols.id_sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ID
|
static ID
|
||||||
@ -8368,16 +8379,17 @@ rb_symname_p(const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ID
|
ID
|
||||||
rb_intern(const char *name)
|
rb_intern2(const char *name, long len)
|
||||||
{
|
{
|
||||||
const char *m = name;
|
const char *m = name;
|
||||||
|
VALUE sym = rb_str_new(name, len);
|
||||||
ID id;
|
ID id;
|
||||||
int last;
|
int last;
|
||||||
|
|
||||||
if (st_lookup(global_symbols.tbl, (st_data_t)name, (st_data_t *)&id))
|
if (st_lookup(global_symbols.sym_id, (st_data_t)sym, (st_data_t *)&id))
|
||||||
return id;
|
return id;
|
||||||
|
|
||||||
last = strlen(name)-1;
|
last = len-1;
|
||||||
id = 0;
|
id = 0;
|
||||||
switch (*name) {
|
switch (*name) {
|
||||||
case '$':
|
case '$':
|
||||||
@ -8438,12 +8450,42 @@ rb_intern(const char *name)
|
|||||||
new_id:
|
new_id:
|
||||||
id |= ++global_symbols.last_id << ID_SCOPE_SHIFT;
|
id |= ++global_symbols.last_id << ID_SCOPE_SHIFT;
|
||||||
id_register:
|
id_register:
|
||||||
name = strdup(name);
|
RBASIC(sym)->klass = rb_cSymbol;
|
||||||
st_add_direct(global_symbols.tbl, (st_data_t)name, id);
|
OBJ_FREEZE(sym);
|
||||||
st_add_direct(global_symbols.rev, id, (st_data_t)name);
|
st_add_direct(global_symbols.sym_id, (st_data_t)sym, id);
|
||||||
|
st_add_direct(global_symbols.id_sym, id, (st_data_t)sym);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ID
|
||||||
|
rb_intern(const char *name)
|
||||||
|
{
|
||||||
|
return rb_intern2(name, strlen(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_id2sym(ID id)
|
||||||
|
{
|
||||||
|
VALUE data;
|
||||||
|
|
||||||
|
if (st_lookup(global_symbols.id_sym, id, &data)) {
|
||||||
|
if (!RBASIC(data)->klass) {
|
||||||
|
RBASIC(data)->klass = rb_cSymbol;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ID
|
||||||
|
rb_sym2id(VALUE sym)
|
||||||
|
{
|
||||||
|
ID data;
|
||||||
|
|
||||||
|
if (st_lookup(global_symbols.sym_id, sym, &data))
|
||||||
|
return data;
|
||||||
|
return rb_intern2(RSTRING_PTR(sym), RSTRING_LEN(sym));
|
||||||
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
rb_id2name(ID id)
|
rb_id2name(ID id)
|
||||||
{
|
{
|
||||||
@ -8459,8 +8501,8 @@ rb_id2name(ID id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (st_lookup(global_symbols.rev, id, &data))
|
if (st_lookup(global_symbols.id_sym, id, &data))
|
||||||
return (char *)data;
|
return RSTRING_PTR(data);
|
||||||
|
|
||||||
if (is_attrset_id(id)) {
|
if (is_attrset_id(id)) {
|
||||||
ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
|
ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
|
||||||
@ -8484,9 +8526,9 @@ rb_id2name(ID id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
symbols_i(char *key, ID value, VALUE ary)
|
symbols_i(VALUE sym, ID value, VALUE ary)
|
||||||
{
|
{
|
||||||
rb_ary_push(ary, ID2SYM(value));
|
rb_ary_push(ary, sym);
|
||||||
return ST_CONTINUE;
|
return ST_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8509,9 +8551,9 @@ symbols_i(char *key, ID value, VALUE ary)
|
|||||||
VALUE
|
VALUE
|
||||||
rb_sym_all_symbols(void)
|
rb_sym_all_symbols(void)
|
||||||
{
|
{
|
||||||
VALUE ary = rb_ary_new2(global_symbols.tbl->num_entries);
|
VALUE ary = rb_ary_new2(global_symbols.sym_id->num_entries);
|
||||||
|
|
||||||
st_foreach(global_symbols.tbl, symbols_i, ary);
|
st_foreach(global_symbols.sym_id, symbols_i, ary);
|
||||||
return ary;
|
return ary;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9261,3 +9303,4 @@ Init_ripper(void)
|
|||||||
rb_intern("&&");
|
rb_intern("&&");
|
||||||
}
|
}
|
||||||
#endif /* RIPPER */
|
#endif /* RIPPER */
|
||||||
|
|
||||||
|
10
ruby.h
10
ruby.h
@ -195,10 +195,11 @@ VALUE rb_ull2inum(unsigned LONG_LONG);
|
|||||||
#define IMMEDIATE_MASK 0x03
|
#define IMMEDIATE_MASK 0x03
|
||||||
#define IMMEDIATE_P(x) ((VALUE)(x) & IMMEDIATE_MASK)
|
#define IMMEDIATE_P(x) ((VALUE)(x) & IMMEDIATE_MASK)
|
||||||
|
|
||||||
#define SYMBOL_FLAG 0x0e
|
#define SYMBOL_P(x) (!IMMEDIATE_P(x) && RBASIC(x)->klass == rb_cSymbol)
|
||||||
#define SYMBOL_P(x) (((VALUE)(x)&0xff)==SYMBOL_FLAG)
|
VALUE rb_id2sym(ID);
|
||||||
#define ID2SYM(x) ((VALUE)(((long)(x))<<8|SYMBOL_FLAG))
|
ID rb_sym2id(VALUE);
|
||||||
#define SYM2ID(x) RSHIFT((VALUE)x,8)
|
#define ID2SYM(x) rb_id2sym(x)
|
||||||
|
#define SYM2ID(x) rb_sym2id(x)
|
||||||
|
|
||||||
/* special contants - i.e. non-zero and non-fixnum constants */
|
/* special contants - i.e. non-zero and non-fixnum constants */
|
||||||
#define Qfalse ((VALUE)0)
|
#define Qfalse ((VALUE)0)
|
||||||
@ -596,6 +597,7 @@ void rb_gc_register_address(VALUE*);
|
|||||||
void rb_gc_unregister_address(VALUE*);
|
void rb_gc_unregister_address(VALUE*);
|
||||||
|
|
||||||
ID rb_intern(const char*);
|
ID rb_intern(const char*);
|
||||||
|
ID rb_intern2(const char*, long);
|
||||||
const char *rb_id2name(ID);
|
const char *rb_id2name(ID);
|
||||||
ID rb_to_id(VALUE);
|
ID rb_to_id(VALUE);
|
||||||
|
|
||||||
|
216
string.c
216
string.c
@ -26,6 +26,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
VALUE rb_cString;
|
VALUE rb_cString;
|
||||||
|
VALUE rb_cSymbol;
|
||||||
|
|
||||||
#define STR_TMPLOCK FL_USER7
|
#define STR_TMPLOCK FL_USER7
|
||||||
#define STR_NOEMBED FL_USER1
|
#define STR_NOEMBED FL_USER1
|
||||||
@ -134,6 +135,7 @@ str_new(VALUE klass, const char *ptr, long len)
|
|||||||
rb_raise(rb_eArgError, "negative string size (or size too big)");
|
rb_raise(rb_eArgError, "negative string size (or size too big)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (klass == rb_cSymbol) klass = rb_cString;
|
||||||
str = str_alloc(klass);
|
str = str_alloc(klass);
|
||||||
if (len > RSTRING_EMBED_LEN_MAX) {
|
if (len > RSTRING_EMBED_LEN_MAX) {
|
||||||
RSTRING(str)->as.heap.aux.capa = len;
|
RSTRING(str)->as.heap.aux.capa = len;
|
||||||
@ -4369,6 +4371,207 @@ rb_str_setter(VALUE val, ID id, VALUE *var)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Document-class: Symbol
|
||||||
|
*
|
||||||
|
* <code>Symbol</code> objects represent names and some strings
|
||||||
|
* inside the Ruby
|
||||||
|
* interpreter. They are generated using the <code>:name</code> and
|
||||||
|
* <code>:"string"</code> literals
|
||||||
|
* syntax, and by the various <code>to_sym</code> methods. The same
|
||||||
|
* <code>Symbol</code> object will be created for a given name or string
|
||||||
|
* for the duration of a program's execution, regardless of the context
|
||||||
|
* or meaning of that name. Thus if <code>Fred</code> is a constant in
|
||||||
|
* one context, a method in another, and a class in a third, the
|
||||||
|
* <code>Symbol</code> <code>:Fred</code> will be the same object in
|
||||||
|
* all three contexts.
|
||||||
|
*
|
||||||
|
* module One
|
||||||
|
* class Fred
|
||||||
|
* end
|
||||||
|
* $f1 = :Fred
|
||||||
|
* end
|
||||||
|
* module Two
|
||||||
|
* Fred = 1
|
||||||
|
* $f2 = :Fred
|
||||||
|
* end
|
||||||
|
* def Fred()
|
||||||
|
* end
|
||||||
|
* $f3 = :Fred
|
||||||
|
* $f1.id #=> 2514190
|
||||||
|
* $f2.id #=> 2514190
|
||||||
|
* $f3.id #=> 2514190
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* Symbol.new(str) => new_sym
|
||||||
|
* Symbol.intern(str) => new_sym
|
||||||
|
*
|
||||||
|
* Returns a new symbol corresponding to <i>str</i>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
rb_sym_s_intern(VALUE s)
|
||||||
|
{
|
||||||
|
if (rb_class_real(s) == rb_cSymbol) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
StringValue(s);
|
||||||
|
return rb_intern2(RSTRING_PTR(s), RSTRING_LEN(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* sym.to_i => fixnum
|
||||||
|
*
|
||||||
|
* Returns an integer that is unique for each symbol within a
|
||||||
|
* particular execution of a program.
|
||||||
|
*
|
||||||
|
* :fred.to_i #=> 9809
|
||||||
|
* "fred".to_sym.to_i #=> 9809
|
||||||
|
*/
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
sym_to_i(VALUE sym)
|
||||||
|
{
|
||||||
|
ID id = SYM2ID(sym);
|
||||||
|
|
||||||
|
return LONG2FIX(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* sym.inspect => string
|
||||||
|
*
|
||||||
|
* Returns the representation of <i>sym</i> as a symbol literal.
|
||||||
|
*
|
||||||
|
* :fred.inspect #=> ":fred"
|
||||||
|
*/
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
sym_inspect(VALUE sym)
|
||||||
|
{
|
||||||
|
VALUE str;
|
||||||
|
|
||||||
|
str = rb_str_new(0, RSTRING_LEN(sym)+1);
|
||||||
|
RSTRING_PTR(str)[0] = ':';
|
||||||
|
memcpy(RSTRING_PTR(str)+1, RSTRING_PTR(sym), RSTRING_LEN(sym));
|
||||||
|
if (!rb_symname_p(RSTRING_PTR(sym))) {
|
||||||
|
str = rb_str_dump(str);
|
||||||
|
strncpy(RSTRING_PTR(str), ":\"", 2);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* sym.id2name => string
|
||||||
|
* sym.to_s => string
|
||||||
|
*
|
||||||
|
* Returns the name or string corresponding to <i>sym</i>.
|
||||||
|
*
|
||||||
|
* :fred.id2name #=> "fred"
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
sym_to_s(VALUE sym)
|
||||||
|
{
|
||||||
|
return rb_str_new(RSTRING_PTR(sym), RSTRING_LEN(sym));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* sym.to_sym => sym
|
||||||
|
* sym.intern => sym
|
||||||
|
*
|
||||||
|
* In general, <code>to_sym</code> returns the <code>Symbol</code> corresponding
|
||||||
|
* to an object. As <i>sym</i> is already a symbol, <code>self</code> is returned
|
||||||
|
* in this case.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
sym_to_sym(VALUE sym)
|
||||||
|
{
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
sym_call(VALUE args, VALUE sym)
|
||||||
|
{
|
||||||
|
VALUE obj;
|
||||||
|
|
||||||
|
if (RARRAY_LEN(args) < 1) {
|
||||||
|
rb_raise(rb_eArgError, "no receiver given");
|
||||||
|
}
|
||||||
|
obj = RARRAY_PTR(args)[0];
|
||||||
|
return rb_funcall3(obj, (ID)sym,
|
||||||
|
RARRAY_LEN(args) - 1,
|
||||||
|
RARRAY_PTR(args) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* sym.to_proc
|
||||||
|
*
|
||||||
|
* Returns a _Proc_ object which respond to the given method by _sym_.
|
||||||
|
*
|
||||||
|
* (1..3).collect(&:to_s) #=> ["1", "2", "3"]
|
||||||
|
*/
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
sym_to_proc(VALUE sym)
|
||||||
|
{
|
||||||
|
return rb_proc_new(sym_call, (VALUE)SYM2ID(sym));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ID
|
||||||
|
str_to_id(VALUE str)
|
||||||
|
{
|
||||||
|
if (!RSTRING_PTR(str) || RSTRING_LEN(str) == 0) {
|
||||||
|
rb_raise(rb_eArgError, "empty symbol string");
|
||||||
|
}
|
||||||
|
if (RBASIC(str)->klass == rb_cSymbol)
|
||||||
|
return str;
|
||||||
|
return rb_intern2(RSTRING_PTR(str), RSTRING_LEN(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
ID
|
||||||
|
rb_to_id(VALUE name)
|
||||||
|
{
|
||||||
|
VALUE tmp;
|
||||||
|
ID id;
|
||||||
|
|
||||||
|
switch (TYPE(name)) {
|
||||||
|
case T_STRING:
|
||||||
|
return str_to_id(name);
|
||||||
|
case T_FIXNUM:
|
||||||
|
rb_warn("do not use Fixnums as Symbols");
|
||||||
|
id = FIX2LONG(name);
|
||||||
|
if (!rb_id2name(id)) {
|
||||||
|
rb_raise(rb_eArgError, "%ld is not a symbol", id);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case T_SYMBOL:
|
||||||
|
id = SYM2ID(name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tmp = rb_check_string_type(name);
|
||||||
|
if (!NIL_P(tmp)) {
|
||||||
|
return str_to_id(tmp);
|
||||||
|
}
|
||||||
|
rb_raise(rb_eTypeError, "%s is not a symbol", RSTRING_PTR(rb_inspect(name)));
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A <code>String</code> object holds and manipulates an arbitrary sequence of
|
* A <code>String</code> object holds and manipulates an arbitrary sequence of
|
||||||
* bytes, typically representing characters. String objects may be created
|
* bytes, typically representing characters. String objects may be created
|
||||||
@ -4496,4 +4699,17 @@ Init_String(void)
|
|||||||
rb_fs = Qnil;
|
rb_fs = Qnil;
|
||||||
rb_define_variable("$;", &rb_fs);
|
rb_define_variable("$;", &rb_fs);
|
||||||
rb_define_variable("$-F", &rb_fs);
|
rb_define_variable("$-F", &rb_fs);
|
||||||
|
|
||||||
|
rb_cSymbol = rb_define_class("Symbol", rb_cString);
|
||||||
|
rb_define_singleton_method(rb_cSymbol, "all_symbols", rb_sym_all_symbols, 0); /* in parse.y */
|
||||||
|
rb_define_singleton_method(rb_cSymbol, "intern", rb_sym_s_intern, 1);
|
||||||
|
rb_define_singleton_method(rb_cSymbol, "new", rb_sym_s_intern, 1);
|
||||||
|
|
||||||
|
rb_define_method(rb_cSymbol, "to_i", sym_to_i, 0);
|
||||||
|
rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0);
|
||||||
|
rb_define_method(rb_cSymbol, "to_s", sym_to_s, 0);
|
||||||
|
rb_define_method(rb_cSymbol, "id2name", sym_to_s, 0);
|
||||||
|
rb_define_method(rb_cSymbol, "intern", sym_to_sym, 0);
|
||||||
|
rb_define_method(rb_cSymbol, "to_sym", sym_to_sym, 0);
|
||||||
|
rb_define_method(rb_cSymbol, "to_proc", sym_to_proc, 0);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user