diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2007-01-23 08:03:28 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2007-01-23 08:03:28 +0000 |
commit | 17b99a2ed9651352c69c7abfcfdb284c1db86ed8 (patch) | |
tree | 21966e6d8ef80b64a61c0feecd339a1b60375ae4 | |
parent | 4bccf2123bb86113c5b4a8164bd1d0981490e1ba (diff) | |
download | ruby-17b99a2ed9651352c69c7abfcfdb284c1db86ed8.tar.gz |
* eval.c (ivar2_prepare): prepare ivar2 ID before processing.
* marshal.c (w_symbol): support class local instance variables.
* marshal.c (r_object0): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/matzruby@11561 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | eval.c | 27 | ||||
-rw-r--r-- | gc.c | 26 | ||||
-rw-r--r-- | intern.h | 3 | ||||
-rw-r--r-- | marshal.c | 66 | ||||
-rw-r--r-- | node.h | 4 | ||||
-rw-r--r-- | parse.y | 35 | ||||
-rw-r--r-- | string.c | 55 | ||||
-rw-r--r-- | variable.c | 2 |
9 files changed, 205 insertions, 21 deletions
@@ -372,6 +372,14 @@ Fri Dec 1 16:31:53 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> * ext/tk/tcltklib.c: shouldn't run the killed thread at callback. [ruby-talk: 227408] +Tue Nov 28 17:31:40 2006 Yukihiro Matsumoto <matz@ruby-lang.org> + + * eval.c (ivar2_prepare): prepare ivar2 ID before processing. + + * marshal.c (w_symbol): support class local instance variables. + + * marshal.c (r_object0): ditto. + Tue Nov 28 17:25:11 2006 Yukihiro Matsumoto <matz@ruby-lang.org> * array.c (ary_iter_check): should check modification (size @@ -1861,6 +1861,14 @@ cvar_cbase(int warn) return ruby_cbase; } +static void +ivar2_prepare(NODE *node) +{ + if (node->nd_vid == 0) { + node->nd_vid = rb_intern_ivar2(node->nd_aid, ruby_cbase); + } +} + /* * call-seq: * Module.nesting => array @@ -2326,6 +2334,7 @@ is_defined(VALUE self, NODE *node /* OK */, char *buf, int noeval) case NODE_DASGN_CURR: case NODE_GASGN: case NODE_IASGN: + case NODE_IASGN2: case NODE_CDECL: case NODE_CVDECL: case NODE_CVASGN: @@ -2348,6 +2357,13 @@ is_defined(VALUE self, NODE *node /* OK */, char *buf, int noeval) } break; + case NODE_IVAR2: + ivar2_prepare(node); + if (rb_ivar_defined(self, node->nd_vid)) { + return "instance-variable"; + } + break; + case NODE_CONST: if (ev_const_defined(node->nd_vid, self)) { return "constant"; @@ -3480,6 +3496,8 @@ rb_eval(VALUE self, NODE *n) rb_gvar_set(node->nd_entry, result); break; + case NODE_IASGN2: + ivar2_prepare(node); case NODE_IASGN: result = rb_eval(self, node->nd_value); rb_ivar_set(self, node->nd_vid, result); @@ -3516,6 +3534,9 @@ rb_eval(VALUE self, NODE *n) result = rb_gvar_get(node->nd_entry); break; + case NODE_IVAR2: + ivar2_prepare(node); + /* fall through */ case NODE_IVAR: result = rb_ivar_get(self, node->nd_vid); break; @@ -5034,6 +5055,9 @@ assign(VALUE self, NODE *lhs, VALUE val, int pcall) rb_gvar_set(lhs->nd_entry, val); break; + + case NODE_IASGN2: + ivar2_prepare(lhs); case NODE_IASGN: rb_ivar_set(self, lhs->nd_vid, val); break; @@ -5758,6 +5782,8 @@ rb_call0(VALUE klass, VALUE recv, ID id, ID oid, break; /* for attr get/set */ + case NODE_IVAR2: + ivar2_prepare(body); case NODE_IVAR: if (argc != 0) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc); @@ -9288,6 +9314,7 @@ rb_node_arity(NODE *body) return -1; case NODE_ATTRSET: return 1; + case NODE_IVAR2: case NODE_IVAR: return 0; case NODE_BMETHOD: @@ -1973,6 +1973,32 @@ id2ref(VALUE obj, VALUE objid) return (VALUE)ptr; } +ID +rb_dump_ivar2(ID id, VALUE *klassp) +{ + VALUE sym = ID2SYM(id); + char *ptr = RSTRING_PTR(sym); + long len = strlen(ptr); + ID oid; + VALUE klass; + + if (RSTRING_LEN(sym) == len) return id; + oid = rb_intern2(ptr, len); + + memcpy((char*)&klass, ptr+strlen(ptr)+1, sizeof(VALUE)); + klass = id2ref(0, klass); + switch (TYPE(klass)) { + case T_CLASS: + case T_MODULE: + break; + default: + rb_raise(rb_eTypeError, "corrupted instance variable - %s", ptr); + break; + } + if (klassp) *klassp = klass; + return oid; +} + /* * Document-method: __id__ * Document-method: object_id @@ -313,6 +313,7 @@ void rb_gc_call_finalizer_at_exit(void); VALUE rb_gc_enable(void); VALUE rb_gc_disable(void); VALUE rb_gc_start(void); +ID rb_dump_ivar2(ID, VALUE*); /* hash.c */ void st_foreach_safe(struct st_table *, int (*)(ANYARGS), st_data_t); void rb_hash_foreach(VALUE, int (*)(ANYARGS), VALUE); @@ -395,6 +396,7 @@ ID rb_id_attrset(ID); void rb_gc_mark_parser(void); int rb_is_const_id(ID); int rb_is_instance_id(ID); +int rb_is_instance2_id(ID); int rb_is_class_id(ID); int rb_is_local_id(ID); int rb_is_junk_id(ID); @@ -520,6 +522,7 @@ void rb_str_associate(VALUE, VALUE); VALUE rb_str_associated(VALUE); void rb_str_setter(VALUE, ID, VALUE*); VALUE rb_str_intern(VALUE); +ID rb_intern_ivar2(ID, VALUE); /* struct.c */ VALUE rb_struct_new(VALUE, ...); VALUE rb_struct_define(const char*, ...); @@ -47,7 +47,7 @@ shortlen(long len, BDIGIT *ds) #endif #define MARSHAL_MAJOR 4 -#define MARSHAL_MINOR 8 +#define MARSHAL_MINOR 9 #define TYPE_NIL '0' #define TYPE_TRUE 'T' @@ -73,6 +73,7 @@ shortlen(long len, BDIGIT *ds) #define TYPE_MODULE 'm' #define TYPE_SYMBOL ':' +#define TYPE_SYMBOL2 ',' #define TYPE_SYMLINK ';' #define TYPE_IVAR 'I' @@ -304,7 +305,7 @@ w_float(double d, struct dump_arg *arg) static void w_symbol(ID id, struct dump_arg *arg) { - const char *sym = rb_id2name(id); + const char *sym; st_data_t num; if (st_lookup(arg->symbols, id, &num)) { @@ -312,8 +313,22 @@ w_symbol(ID id, struct dump_arg *arg) w_long((long)num, arg); } else { - w_byte(TYPE_SYMBOL, arg); - w_bytes(sym, strlen(sym), arg); + if (rb_is_instance2_id(id)) { + VALUE klass; + volatile VALUE path; + + id = rb_dump_ivar2(id, &klass); + path = class2path(klass); + w_byte(TYPE_SYMBOL2, arg); + sym = rb_id2name(id); + w_bytes(sym, strlen(sym), arg); + w_bytes(RSTRING_PTR(path), RSTRING_LEN(path), arg); + } + else { + sym = rb_id2name(id); + w_byte(TYPE_SYMBOL, arg); + w_bytes(sym, strlen(sym), arg); + } st_add_direct(arg->symbols, id, arg->symbols->num_entries); } } @@ -360,12 +375,14 @@ w_extended(VALUE klass, struct dump_arg *arg, int check) static void w_class(char type, VALUE obj, struct dump_arg *arg, int check) { + volatile VALUE p; char *path; VALUE klass = CLASS_OF(obj); w_extended(klass, arg, check); w_byte(type, arg); - path = RSTRING_PTR(class2path(rb_class_real(klass))); + p = class2path(rb_class_real(klass)); + path = RSTRING_PTR(p); w_unique(path, arg); } @@ -490,7 +507,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit) } w_byte(TYPE_CLASS, arg); { - VALUE path = class2path(obj); + volatile VALUE path = class2path(obj); w_bytes(RSTRING_PTR(path), RSTRING_LEN(path), arg); } break; @@ -738,7 +755,9 @@ struct load_arg { int taint; }; +static VALUE r_entry(VALUE v, struct load_arg *arg); static VALUE r_object(struct load_arg *arg); +static VALUE path2class(const char *path); static int r_byte(struct load_arg *arg) @@ -855,10 +874,24 @@ r_symlink(struct load_arg *arg) static ID r_symreal(struct load_arg *arg) { - ID id; volatile VALUE s = r_bytes(arg); + ID id = rb_intern(RSTRING_PTR(s)); + + st_insert(arg->symbols, arg->symbols->num_entries, id); + + return id; +} + +static ID +r_symivar2(struct load_arg *arg) +{ + volatile VALUE s = r_bytes(arg); + ID id = rb_intern(RSTRING_PTR(s)); + VALUE klass; - id = rb_intern(RSTRING_PTR(s)); + s = r_bytes(arg); + klass = r_entry(path2class(RSTRING_PTR(s)), arg); + id = rb_intern_ivar2(id, klass); st_insert(arg->symbols, arg->symbols->num_entries, id); return id; @@ -867,10 +900,19 @@ r_symreal(struct load_arg *arg) static ID r_symbol(struct load_arg *arg) { - if (r_byte(arg) == TYPE_SYMLINK) { + int type; + + switch ((type = r_byte(arg))) { + case TYPE_SYMBOL: + return r_symreal(arg); + case TYPE_SYMBOL2: + return r_symivar2(arg); + case TYPE_SYMLINK: return r_symlink(arg); + default: + rb_raise(rb_eArgError, "dump format error(0x%x)", type); + break; } - return r_symreal(arg); } static const char* @@ -1274,6 +1316,10 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) v = ID2SYM(r_symreal(arg)); break; + case TYPE_SYMBOL2: + v = ID2SYM(r_symivar2(arg)); + break; + case TYPE_SYMLINK: v = ID2SYM(r_symlink(arg)); break; @@ -48,6 +48,7 @@ enum node_type { NODE_DASGN_CURR, NODE_GASGN, NODE_IASGN, + NODE_IASGN2, NODE_CDECL, NODE_CVASGN, NODE_CVDECL, @@ -70,6 +71,7 @@ enum node_type { NODE_DVAR, NODE_GVAR, NODE_IVAR, + NODE_IVAR2, NODE_CONST, NODE_CVAR, NODE_NTH_REF, @@ -282,6 +284,7 @@ extern NODE *ruby_top_cref; #define NEW_DASGN(v,val) NEW_NODE(NODE_DASGN,v,val,0) #define NEW_DASGN_CURR(v,val) NEW_NODE(NODE_DASGN_CURR,v,val,0) #define NEW_IASGN(v,val) NEW_NODE(NODE_IASGN,v,val,0) +#define NEW_IASGN2(v,val) NEW_NODE(NODE_IASGN2,0,val,v) #define NEW_CDECL(v,val,path) NEW_NODE(NODE_CDECL,v,val,path) #define NEW_CVASGN(v,val) NEW_NODE(NODE_CVASGN,v,val,0) #define NEW_CVDECL(v,val) NEW_NODE(NODE_CVDECL,v,val,0) @@ -294,6 +297,7 @@ extern NODE *ruby_top_cref; #define NEW_LVAR(v) NEW_NODE(NODE_LVAR,v,0,local_cnt(v)) #define NEW_DVAR(v) NEW_NODE(NODE_DVAR,v,0,0) #define NEW_IVAR(v) NEW_NODE(NODE_IVAR,v,0,0) +#define NEW_IVAR2(v) NEW_NODE(NODE_IVAR2,0,0,v) #define NEW_CONST(v) NEW_NODE(NODE_CONST,v,0,0) #define NEW_CVAR(v) NEW_NODE(NODE_CVAR,v,0,0) #define NEW_NTH_REF(n) NEW_NODE(NODE_NTH_REF,0,n,local_cnt('~')) @@ -36,19 +36,21 @@ #define ID_SCOPE_SHIFT 3 #define ID_SCOPE_MASK 0x07 -#define ID_LOCAL 0x01 -#define ID_INSTANCE 0x02 -#define ID_GLOBAL 0x03 -#define ID_ATTRSET 0x04 -#define ID_CONST 0x05 -#define ID_CLASS 0x06 -#define ID_JUNK 0x07 -#define ID_INTERNAL ID_JUNK +#define ID_LOCAL 0x00 +#define ID_INSTANCE 0x01 +#define ID_INSTANCE2 0x02 +#define ID_GLOBAL 0x03 +#define ID_ATTRSET 0x04 +#define ID_CONST 0x05 +#define ID_CLASS 0x06 +#define ID_JUNK 0x07 +#define ID_INTERNAL ID_JUNK #define is_notop_id(id) ((id)>tLAST_TOKEN) #define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL) #define is_global_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL) #define is_instance_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE) +#define is_instance2_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE2) #define is_attrset_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET) #define is_const_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST) #define is_class_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS) @@ -7174,6 +7176,9 @@ gettable_gen(struct parser_params *parser, ID id) else if (is_instance_id(id)) { return NEW_IVAR(id); } + else if (is_instance2_id(id)) { + return NEW_IVAR2(id); + } else if (is_const_id(id)) { return NEW_CONST(id); } @@ -7227,6 +7232,9 @@ assignable_gen(struct parser_params *parser, ID id, NODE *val) else if (is_instance_id(id)) { return NEW_IASGN(id, val); } + else if (is_instance2_id(id)) { + return NEW_IASGN2(id, val); + } else if (is_const_id(id)) { if (in_def || in_single) yyerror("dynamic constant assignment"); @@ -7361,6 +7369,7 @@ node_assign_gen(struct parser_params *parser, NODE *lhs, NODE *rhs) switch (nd_type(lhs)) { case NODE_GASGN: case NODE_IASGN: + case NODE_IASGN2: case NODE_LASGN: case NODE_DASGN: case NODE_DASGN_CURR: @@ -8408,6 +8417,9 @@ rb_intern2(const char *name, long len) m++; id |= ID_CLASS; } + else if (name[1] == '_') { + id |= ID_INSTANCE2; + } else { id |= ID_INSTANCE; } @@ -8590,6 +8602,13 @@ rb_is_instance_id(ID id) } int +rb_is_instance2_id(ID id) +{ + if (is_instance2_id(id)) return Qtrue; + return Qfalse; +} + +int rb_is_local_id(ID id) { if (is_local_id(id)) return Qtrue; @@ -4227,7 +4227,10 @@ rb_str_intern(VALUE s) volatile VALUE str = s; ID id; - if (OBJ_TAINTED(str) && rb_safe_level() >= 1 && !rb_sym_interned_p(str)) { + if (rb_sym_interned_p(str)) { + return str; + } + if (OBJ_TAINTED(str) && rb_safe_level() >= 1) { rb_raise(rb_eSecurityError, "Insecure: can't intern tainted string"); } id = rb_intern2(RSTRING_PTR(str), RSTRING_LEN(str)); @@ -4688,8 +4691,13 @@ sym_to_i(VALUE sym) static VALUE sym_inspect(VALUE sym) { - VALUE str; + VALUE str, klass = Qundef; + ID id = SYM2ID(sym); + if (rb_is_instance2_id(id)) { + id = rb_dump_ivar2(id, &klass); + sym = ID2SYM(id); + } str = rb_str_new(0, RSTRING_LEN(sym)+1); RSTRING_PTR(str)[0] = ':'; memcpy(RSTRING_PTR(str)+1, RSTRING_PTR(sym), RSTRING_LEN(sym)); @@ -4698,6 +4706,10 @@ sym_inspect(VALUE sym) str = rb_str_dump(str); strncpy(RSTRING_PTR(str), ":\"", 2); } + if (klass != Qundef) { + rb_str_cat2(str, "/"); + rb_str_append(str, rb_inspect(klass)); + } return str; } @@ -4808,6 +4820,44 @@ rb_to_id(VALUE name) return id; } +ID +rb_intern_ivar2(ID id, VALUE klass) +{ + VALUE sym = ID2SYM(id); + long len = RSTRING_LEN(sym); + char *buf = ALLOCA_N(char, len+sizeof(VALUE)+1); + VALUE oid; + + strcpy(buf, RSTRING_PTR(sym)); + oid = rb_obj_id(klass); + memcpy(buf+len+1, (char*)&oid, sizeof(VALUE)); + id = rb_intern2(buf, len+sizeof(VALUE)+1); + sym = ID2SYM(id); +// STR_SET_LEN(sym, len); + return id; +} + +static VALUE +sym_div(VALUE sym, VALUE klass) +{ + ID id = SYM2ID(sym); + + if (!rb_is_instance2_id(id)) { + rb_raise(rb_eArgError, "symbol %s should be local instance variable", + rb_id2name(id)); + } + switch (TYPE(klass)) { + case T_CLASS: + case T_MODULE: + break; + default: + rb_check_type(klass, T_CLASS); + break; + } + id = rb_intern_ivar2(id, klass); + return ID2SYM(id); +} + /* * A <code>String</code> object holds and manipulates an arbitrary sequence of * bytes, typically representing characters. String objects may be created @@ -4948,6 +4998,7 @@ Init_String(void) 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_method(rb_cSymbol, "/", sym_div, 1); rb_define_method(rb_cSymbol, "==", sym_equal, 1); rb_define_method(rb_cSymbol, "to_i", sym_to_i, 0); rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0); diff --git a/variable.c b/variable.c index 63f6ed9474..3786419573 100644 --- a/variable.c +++ b/variable.c @@ -987,7 +987,7 @@ rb_ivar_defined(VALUE obj, ID id) static int ivar_i(ID key, struct global_entry *entry, VALUE ary) { - if (rb_is_instance_id(key)) { + if (rb_is_instance_id(key) || rb_is_instance2_id(key)) { rb_ary_push(ary, ID2SYM(key)); } return ST_CONTINUE; |