[#3006] CVS repository — "Eugene Scripnik" <hoaz@...>

Hello.

21 messages 2004/06/16
[#3008] Re: CVS repository — ts <decoux@...> 2004/06/16

>>>>> "E" == Eugene Scripnik <hoaz@gala.net> writes:

[#3009] Re: CVS repository — Michal Rokos <michal@...> 2004/06/16

Hi!

[#3057] Ruby 1.8.2 to be released. — matz@... (Yukihiro Matsumoto)

Hi,

20 messages 2004/06/23

class= and type checks when casting

From: "Sean O'Dell" <sean@...>
Date: 2004-06-25 19:51:40 UTC
List: ruby-core #3090
Matz, I'm not sure if you followed the discussion in ruby-talk about having a 
"class=" method.  We were just talking about changing the class of an object, 
and what problems would/would not arise in so doing.  When I tried 
implementing "class=" on my own, Ruby crashed pretty badly in a lot of 
places.  Then I realized the reason was because so much code casts VALUEs to 
RFILE, RHASH, etc. without checking that the types were actually valid.  So I 
changed many of the casts in ruby.h (RHASH, RFILE, RSTRING, etc.) to perform 
a quick type check.  That solved the problem of crashing the built-in types 
when the class was changed.  I ran some tests; 100,000x calling file#read 
with and without checking that the file object's class was truly T_FILE, and 
I noticed no time difference.  I don't think the extra check adds any 
noticable overhead.

The implementation I came up with allows you to do silly things like:

class ClassA
  def initialize
    @var = "hello, world"
  end
end

class ClassB
  def test_method
    p @var
  end
end

a = ClassA.new
a.class = ClassB
a.test_method # ==> "hello, world"


For reference, the changes I made as a patch against the CVS:

Index: object.c
===================================================================
RCS file: /src/ruby/object.c,v
retrieving revision 1.153
diff -r1.153 object.c
201a202,209
> VALUE
> rb_obj_class_set(obj, new_class)
>     VALUE obj, new_class;
> {
>     RBASIC(obj)->klass = new_class;
>     return new_class;
> }
>
2546a2555
>     rb_define_method(rb_mKernel, "class=", rb_obj_class_set, 1);
Index: ruby.h
===================================================================
RCS file: /src/ruby/ruby.h,v
retrieving revision 1.105
diff -r1.105 ruby.h
415,420c415,420
< #define RMODULE(obj) RCLASS(obj)
< #define RFLOAT(obj)  (R_CAST(RFloat)(obj))
< #define RSTRING(obj) (R_CAST(RString)(obj))
< #define RREGEXP(obj) (R_CAST(RRegexp)(obj))
< #define RARRAY(obj)  (R_CAST(RArray)(obj))
< #define RHASH(obj)   (R_CAST(RHash)(obj))
---
> #define RMODULE(obj) (Check_Type(obj, T_MODULE), RCLASS(obj))
> #define RFLOAT(obj)  (Check_Type(obj, T_FLOAT), R_CAST(RFloat)(obj))
> #define RSTRING(obj) (Check_Type(obj, T_STRING), R_CAST(RString)(obj))
> #define RREGEXP(obj) (Check_Type(obj, T_REGEXP), R_CAST(RRegexp)(obj))
> #define RARRAY(obj)  (Check_Type(obj, T_ARRAY), R_CAST(RArray)(obj))
> #define RHASH(obj)   (Check_Type(obj, T_HASH), R_CAST(RHash)(obj))
422,424c422,424
< #define RSTRUCT(obj) (R_CAST(RStruct)(obj))
< #define RBIGNUM(obj) (R_CAST(RBignum)(obj))
< #define RFILE(obj)   (R_CAST(RFile)(obj))
---
> #define RSTRUCT(obj) (Check_Type(obj, T_STRUCT), R_CAST(RStruct)(obj))
> #define RBIGNUM(obj) (Check_Type(obj, T_BIGNUM), R_CAST(RBignum)(obj))
> #define RFILE(obj)   (Check_Type(obj, T_FILE), R_CAST(RFile)(obj))

In This Thread

Prev Next