summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--ToDo1
-rw-r--r--class.c2
-rw-r--r--marshal.c118
-rw-r--r--variable.c37
5 files changed, 120 insertions, 49 deletions
diff --git a/ChangeLog b/ChangeLog
index ee205f90f9..687c42e72e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,19 @@
+Thu Sep 5 18:32:32 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * variable.c (rb_path2class): should not use rb_eval_string().
+
Thu Sep 5 17:18:22 2002 Michal Rokos <michal@ruby-lang.org>
* dln.c: fix memory leak in dln_load (ruby-core:405) and
in load_1 (ruby-core:407)
+Thu Sep 5 15:43:54 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (w_extended): should allow marshaling of object which
+ is extended by named module.
+
+ * class.c (rb_make_metaclass): super may be T_ICLASS, need to skip.
+
Thu Sep 5 13:09:22 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net>
* eval.c (rb_eval): overriding false constant with class/module
diff --git a/ToDo b/ToDo
index fa7f32daed..9bd0207601 100644
--- a/ToDo
+++ b/ToDo
@@ -106,6 +106,7 @@ Standard Libraries
* deprecate Array#indexes, and Array#indices.
* require "1.6" etc. by /usr/lib/ruby/1.6/1.6.rb ;-)
* save both "feature names" and "normalized path" in $"
+* allow marshaling of extend'ed object.
Extension Libraries
diff --git a/class.c b/class.c
index 65187f50d0..9d9d3660ca 100644
--- a/class.c
+++ b/class.c
@@ -150,7 +150,7 @@ rb_make_metaclass(obj, super)
if (BUILTIN_TYPE(obj) == T_CLASS) {
RBASIC(klass)->klass = klass;
if (FL_TEST(obj, FL_SINGLETON)) {
- RCLASS(klass)->super = RBASIC(RCLASS(obj)->super)->klass;
+ RCLASS(klass)->super = RBASIC(rb_class_real(RCLASS(obj)->super))->klass;
}
}
diff --git a/marshal.c b/marshal.c
index 6a337d208f..e6672d229c 100644
--- a/marshal.c
+++ b/marshal.c
@@ -50,9 +50,10 @@ shortlen(len, ds)
#define TYPE_FALSE 'F'
#define TYPE_FIXNUM 'i'
+#define TYPE_EXTENDED 'e'
#define TYPE_UCLASS 'C'
#define TYPE_OBJECT 'o'
-#define TYPE_DATA 'd'
+#define TYPE_DATA 'd'
#define TYPE_USERDEF 'u'
#define TYPE_USRMARHAL 'U'
#define TYPE_FLOAT 'f'
@@ -250,19 +251,38 @@ obj_each(id, value, arg)
}
static void
-w_class(obj, arg)
- VALUE obj;
+w_extended(klass, arg)
+ VALUE klass;
struct dump_arg *arg;
{
- VALUE klass = CLASS_OF(obj);
char *path;
- while (FL_TEST(klass, FL_SINGLETON) || BUILTIN_TYPE(klass) == T_ICLASS) {
- if (RCLASS(klass)->m_tbl->num_entries > 0 ||
- RCLASS(klass)->iv_tbl->num_entries > 1) {
+ if (FL_TEST(klass, FL_SINGLETON)) {
+ if (RCLASS(klass)->m_tbl->num_entries ||
+ (RCLASS(klass)->iv_tbl && RCLASS(klass)->iv_tbl->num_entries > 1)) {
rb_raise(rb_eTypeError, "singleton can't be dumped");
}
+ klass = RCLASS(klass)->super;
}
+ while (BUILTIN_TYPE(klass) == T_ICLASS) {
+ path = rb_class2name(RBASIC(klass)->klass);
+ w_byte(TYPE_EXTENDED, arg);
+ w_unique(path, arg);
+ klass = RCLASS(klass)->super;
+ }
+}
+
+static void
+w_class(type, obj, arg)
+ int type;
+ VALUE obj;
+ struct dump_arg *arg;
+{
+ char *path;
+
+ VALUE klass = CLASS_OF(obj);
+ w_extended(klass, arg);
+ w_byte(type, arg);
path = rb_class2name(klass);
w_unique(path, arg);
}
@@ -275,14 +295,7 @@ w_uclass(obj, base_klass, arg)
VALUE klass = CLASS_OF(obj);
char *path;
- while (FL_TEST(klass, FL_SINGLETON) || BUILTIN_TYPE(klass) == T_ICLASS) {
- if (RCLASS(klass)->m_tbl->num_entries > 0 ||
- RCLASS(klass)->iv_tbl->num_entries > 1) {
- rb_raise(rb_eTypeError, "singleton can't be dumped");
- }
- klass = RCLASS(klass)->super;
- }
-
+ w_extended(klass, arg);
if (klass != base_klass) {
w_byte(TYPE_UCLASS, arg);
w_unique(rb_class2name(CLASS_OF(obj)), arg);
@@ -504,17 +517,15 @@ w_object(obj, arg, limit)
break;
case T_OBJECT:
- w_byte(TYPE_OBJECT, arg);
- w_class(obj, arg);
+ w_class(TYPE_OBJECT, obj, arg);
w_ivar(ROBJECT(obj)->iv_tbl, &c_arg);
break;
case T_DATA:
- w_byte(TYPE_DATA, arg);
{
VALUE v;
- w_class(obj, arg);
+ w_class(TYPE_DATA, obj, arg);
if (!rb_respond_to(obj, s_dump_data)) {
rb_raise(rb_eTypeError,
"class %s needs to have instance method `_dump_data'",
@@ -805,6 +816,30 @@ r_ivar(obj, arg)
}
static VALUE
+path2class(path)
+ char *path;
+{
+ VALUE v = rb_path2class(path);
+
+ if (TYPE(v) != T_CLASS) {
+ rb_raise(rb_eTypeError, "%s does not refer class", path);
+ }
+ return v;
+}
+
+static VALUE
+path2module(path)
+ char *path;
+{
+ VALUE v = rb_path2class(path);
+
+ if (TYPE(v) != T_MODULE) {
+ rb_raise(rb_eTypeError, "%s does not refer module", path);
+ }
+ return v;
+}
+
+static VALUE
r_object0(arg, proc)
struct load_arg *arg;
VALUE proc;
@@ -827,9 +862,18 @@ r_object0(arg, proc)
r_ivar(v, arg);
break;
+ case TYPE_EXTENDED:
+ {
+ VALUE m = path2module(r_unique(arg));
+
+ v = r_object0(arg, 0);
+ rb_extend_object(v, m);
+ }
+ break;
+
case TYPE_UCLASS:
{
- VALUE c = rb_path2class(r_unique(arg));
+ VALUE c = path2class(r_unique(arg));
v = r_object0(arg, 0);
if (rb_special_const_p(v) || TYPE(v) == T_OBJECT || TYPE(v) == T_CLASS) {
@@ -973,7 +1017,7 @@ r_object0(arg, proc)
long len;
ID slot;
- klass = rb_path2class(r_unique(arg));
+ klass = path2class(r_unique(arg));
mem = rb_struct_iv_get(klass, "__member__");
if (mem == Qnil) {
rb_raise(rb_eTypeError, "uninitialized struct");
@@ -1002,9 +1046,8 @@ r_object0(arg, proc)
case TYPE_USERDEF:
{
- VALUE klass;
+ VALUE klass = path2class(r_unique(arg));
- klass = rb_path2class(r_unique(arg));
if (!rb_respond_to(klass, s_load)) {
rb_raise(rb_eTypeError, "class %s needs to have method `_load'",
rb_class2name(klass));
@@ -1016,9 +1059,8 @@ r_object0(arg, proc)
case TYPE_OBJECT:
{
- VALUE klass;
+ VALUE klass = path2class(r_unique(arg));
- klass = rb_path2class(r_unique(arg));
v = rb_obj_alloc(klass);
if (TYPE(v) != T_OBJECT) {
rb_raise(rb_eArgError, "dump format error");
@@ -1030,9 +1072,7 @@ r_object0(arg, proc)
case TYPE_DATA:
{
- VALUE klass;
-
- klass = rb_path2class(r_unique(arg));
+ VALUE klass = path2class(r_unique(arg));
if (rb_respond_to(klass, s_alloc)) {
static int warn = Qtrue;
if (warn) {
@@ -1059,29 +1099,27 @@ r_object0(arg, proc)
case TYPE_MODULE_OLD:
{
- volatile VALUE str = r_bytes(arg);
- v = r_regist(rb_path2class(RSTRING(str)->ptr), arg);
+ VALUE str = r_bytes(arg);
+
+ v = path2module(RSTRING(str)->ptr);
+ r_regist(v, arg);
}
break;
case TYPE_CLASS:
{
- volatile VALUE str = r_bytes(arg);
- v = rb_path2class(RSTRING(str)->ptr);
- if (TYPE(v) != T_CLASS) {
- rb_raise(rb_eTypeError, "%s is not a class", RSTRING(str)->ptr);
- }
+ VALUE str = r_bytes(arg);
+
+ v = path2class(RSTRING(str)->ptr);
r_regist(v, arg);
}
break;
case TYPE_MODULE:
{
- volatile VALUE str = r_bytes(arg);
- v = rb_path2class(RSTRING(str)->ptr);
- if (TYPE(v) != T_MODULE) {
- rb_raise(rb_eTypeError, "%s is not a module", RSTRING(str)->ptr);
- }
+ VALUE str = r_bytes(arg);
+
+ v = path2module(RSTRING(str)->ptr);
r_regist(v, arg);
}
break;
diff --git a/variable.c b/variable.c
index c37548fb91..18cd0c14ee 100644
--- a/variable.c
+++ b/variable.c
@@ -229,19 +229,40 @@ VALUE
rb_path2class(path)
const char *path;
{
- VALUE c;
+ const char *pbeg, *p;
+ ID id;
+ VALUE c = rb_cObject;
if (path[0] == '#') {
rb_raise(rb_eArgError, "can't retrieve anonymous class %s", path);
}
- c = rb_eval_string(path);
- switch (TYPE(c)) {
- case T_MODULE:
- case T_CLASS:
- break;
- default:
- rb_raise(rb_eTypeError, "class path %s does not point class", path);
+ pbeg = p = path;
+ while (*p) {
+ VALUE str;
+
+ while (*p && *p != ':') p++;
+ str = rb_str_new(pbeg, p-pbeg);
+ id = rb_intern(RSTRING(str)->ptr);
+ if (p[0] == ':') {
+ if (p[1] != ':') goto undefined_class;
+ p += 2;
+ pbeg = p;
+ }
+ if (!rb_const_defined(c, id)) {
+ undefined_class:
+ rb_raise(rb_eArgError, "undefined class/module %s", rb_id2name(id));
+ rb_raise(rb_eArgError, "undefined class/module %s", path);
+ }
+ c = rb_const_get_at(c, id);
+ switch (TYPE(c)) {
+ case T_MODULE:
+ case T_CLASS:
+ break;
+ default:
+ rb_raise(rb_eTypeError, "%s does not refer class/module %d", path, TYPE(c));
+ }
}
+
return c;
}