1 #ifndef RBX_VM_OBJECT_UTILS_HPP
2 #define RBX_VM_OBJECT_UTILS_HPP
4 #include "class/object.hpp"
5 #include "exception.hpp"
8 * @file object_utils.hpp
10 * Defines all the most common operations for dealing with
11 * objects, such as type checking and casting.
14 #define SPECIALIZATION_STORAGE
19 * Ruby type system subtype check.
21 * Given builtin-class +T+, return true if +obj+ is of class +T+
24 static bool kind_of(const MemoryHeader
* obj
) {
25 if(obj
->reference_p()) {
26 return obj
->type_id() == T::type
;
32 static bool kind_of(const Object
* obj
) {
33 if(obj
->reference_p()) {
34 return obj
->type_id() == T::type
;
40 * A specialized version for completeness.
43 bool kind_of
<Object
>(const Object
* obj
) {
48 * Ruby type system class check.
50 * Another version of kind_of that shouldn't be specialized for subtype
51 * compatibility. I.e., only whether object's class is this specific
55 static bool instance_of(const Object
* obj
) {
56 if(obj
->reference_p()) {
57 return obj
->type_id() == T::type
;
63 * A specialized version for completeness.
66 bool instance_of
<Object
>(const Object
* obj
) {
67 return obj
->reference_p() && (obj
->type_id() == ObjectType
);
71 * There is NO reason why as() or try_as() should be getting
72 * NULL arguments. That means something has not been properly
73 * initialised (to cNil if nothing else.)
77 * Cast Object* into builtin T*.
79 * Given builtin class +T+, return +obj+ cast as type +T*+. If
80 * +obj+ is not of type +T+, throw's a TypeError exception.
82 * @see builtin/object.cpp has specialised versions.
85 static T
* as(Object
* obj
) {
86 if(!kind_of
<T
>(obj
)) {
87 TypeError::raise(T::type
, obj
);
90 return static_cast<T
*>(obj
);
94 * Cast const Object* into builtin const T*.
96 * Given builtin class +T+, return +obj+ cast as type +T*+. If
97 * +obj+ is not of type +T+, throw's a TypeError exception.
99 * @see builtin/object.cpp has specialised versions.
102 static const T
* as(const Object
* obj
) {
103 if(!kind_of
<T
>(obj
)) {
104 TypeError::raise(T::type
, obj
);
107 return static_cast<const T
*>(obj
);
111 * A specialized version for completeness.
114 Object
* as
<Object
>(Object
* obj
) {
119 * A specialized version for completeness.
122 const Object
* as
<Object
>(const Object
* obj
) {
127 * Cast Object* into builtin T*.
129 * Given builtin class +T+, return +obj+ cast as type +T*+. If
130 * +obj+ is not exactly of type +T+, throw's a TypeError exception.
132 * @see builtin/object.cpp has specialised versions.
135 static T
* as_instance(Object
* obj
) {
136 if(!instance_of
<T
>(obj
)) {
137 TypeError::raise(T::type
, obj
);
140 return static_cast<T
*>(obj
);
144 * Cast const Object* into builtin const T*.
146 * Given builtin class +T+, return +obj+ cast as type +T*+. If
147 * +obj+ is not exactly of type +T+, throw's a TypeError exception.
149 * @see builtin/object.cpp has specialised versions.
152 static const T
* as_instance(const Object
* obj
) {
153 if(!instance_of
<T
>(obj
)) {
154 TypeError::raise(T::type
, obj
);
157 return static_cast<const T
*>(obj
);
161 * Non-raising version of as().
163 * Similar to as<>, but returns NULL if the type is invalid. ONLY
164 * use this when doing a conditional cast.
166 * @see builtin/object.cpp has specialised versions.
169 static T
* try_as(MemoryHeader
* obj
) {
170 if(!kind_of
<T
>(obj
)) {
174 return static_cast<T
*>(obj
);
178 static T
* try_as(Object
* obj
) {
179 if(!kind_of
<T
>(obj
)) {
183 return static_cast<T
*>(obj
);
187 * Non-raising version of as(), for const objects.
189 * Similar to as<>, but returns NULL if the type is invalid. ONLY
190 * use this when doing a conditional cast.
192 * @see builtin/object.cpp has specialised versions.
195 static const T
* try_as(const MemoryHeader
* obj
) {
196 if(!kind_of
<T
>(obj
)) {
200 return static_cast<const T
*>(obj
);
204 static const T
* try_as(const Object
* obj
) {
205 if(!kind_of
<T
>(obj
)) {
209 return static_cast<const T
*>(obj
);
213 * Non-raising version of as_instance().
215 * Similar to as_instance<>, but returns NULL if the type is invalid. ONLY
216 * use this when doing a conditional cast.
218 * @see builtin/object.cpp has specialised versions.
221 static T
* try_as_instance(Object
* obj
) {
222 if(!instance_of
<T
>(obj
)) {
226 return static_cast<T
*>(obj
);
230 * Non-raising version of as(), for const objects.
232 * Similar to as<>, but returns NULL if the type is invalid. ONLY
233 * use this when doing a conditional cast.
235 * @see builtin/object.cpp has specialised versions.
238 static const T
* try_as_instance(const Object
* obj
) {
239 if(!instance_of
<T
>(obj
)) {
243 return static_cast<const T
*>(obj
);
247 * Returns cNil cast to another type of rubinius::Object. Useful in
248 * cases where e.g. a String* would be returned but cNil is returned
249 * as an exceptional value.
253 static T
* nil() { return static_cast<T
*>(cNil
); }
256 * Converts one type into another without a type check. This is
257 * like reinterprete_cast<>(), but we use it so we can easily
258 * find where we're doing explicit force casts.
261 static T
* force_as(ObjectHeader
* obj
) {
262 return reinterpret_cast<T
*>(obj
);
266 static const T
* force_as(const ObjectHeader
* obj
) {
267 return reinterpret_cast<const T
*>(obj
);
270 void type_assert(STATE
, Object
* obj
, object_type type
, const char* reason
);
272 #include "kind_of.hpp"