diff options
Diffstat (limited to 'internal/class.h')
-rw-r--r-- | internal/class.h | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/internal/class.h b/internal/class.h new file mode 100644 index 0000000000..8ba64a094b --- /dev/null +++ b/internal/class.h @@ -0,0 +1,143 @@ +#ifndef INTERNAL_CLASS_H /* -*- C -*- */ +#define INTERNAL_CLASS_H +/** + * @file + * @brief Internal header for Class. + * @author \@shyouhei + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + */ + +struct rb_deprecated_classext_struct { + char conflict[sizeof(VALUE) * 3]; +}; + +struct rb_subclass_entry; +typedef struct rb_subclass_entry rb_subclass_entry_t; + +struct rb_subclass_entry { + VALUE klass; + rb_subclass_entry_t *next; +}; + +struct rb_classext_struct { + struct st_table *iv_index_tbl; + struct st_table *iv_tbl; +#if SIZEOF_SERIAL_T == SIZEOF_VALUE /* otherwise m_tbl is in struct RClass */ + struct rb_id_table *m_tbl; +#endif + struct rb_id_table *const_tbl; + struct rb_id_table *callable_m_tbl; + rb_subclass_entry_t *subclasses; + rb_subclass_entry_t **parent_subclasses; + /** + * In the case that this is an `ICLASS`, `module_subclasses` points to the link + * in the module's `subclasses` list that indicates that the klass has been + * included. Hopefully that makes sense. + */ + rb_subclass_entry_t **module_subclasses; +#if SIZEOF_SERIAL_T != SIZEOF_VALUE /* otherwise class_serial is in struct RClass */ + rb_serial_t class_serial; +#endif + const VALUE origin_; + const VALUE refined_class; + rb_alloc_func_t allocator; + const VALUE includer; +}; + +typedef struct rb_classext_struct rb_classext_t; + +#undef RClass +struct RClass { + struct RBasic basic; + VALUE super; + rb_classext_t *ptr; +#if SIZEOF_SERIAL_T == SIZEOF_VALUE + /* Class serial is as wide as VALUE. Place it here. */ + rb_serial_t class_serial; +#else + /* Class serial does not fit into struct RClass. Place m_tbl instead. */ + struct rb_id_table *m_tbl; +#endif +}; + +void rb_class_subclass_add(VALUE super, VALUE klass); +void rb_class_remove_from_super_subclasses(VALUE); +int rb_singleton_class_internal_p(VALUE sklass); +/* class.c */ +VALUE rb_class_boot(VALUE); +VALUE rb_class_inherited(VALUE, VALUE); +VALUE rb_make_metaclass(VALUE, VALUE); +VALUE rb_include_class_new(VALUE, VALUE); +void rb_class_foreach_subclass(VALUE klass, void (*f)(VALUE, VALUE), VALUE); +void rb_class_detach_subclasses(VALUE); +void rb_class_detach_module_subclasses(VALUE); +void rb_class_remove_from_module_subclasses(VALUE); +VALUE rb_obj_methods(int argc, const VALUE *argv, VALUE obj); +VALUE rb_obj_protected_methods(int argc, const VALUE *argv, VALUE obj); +VALUE rb_obj_private_methods(int argc, const VALUE *argv, VALUE obj); +VALUE rb_obj_public_methods(int argc, const VALUE *argv, VALUE obj); +VALUE rb_special_singleton_class(VALUE); +VALUE rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach); +VALUE rb_singleton_class_get(VALUE obj); + +int rb_class_has_methods(VALUE c); +void rb_undef_methods_from(VALUE klass, VALUE super); + +#define RCLASS_EXT(c) (RCLASS(c)->ptr) +#define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl) +#define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl) +#if SIZEOF_SERIAL_T == SIZEOF_VALUE +# define RCLASS_M_TBL(c) (RCLASS_EXT(c)->m_tbl) +#else +# define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl) +#endif +#define RCLASS_CALLABLE_M_TBL(c) (RCLASS_EXT(c)->callable_m_tbl) +#define RCLASS_IV_INDEX_TBL(c) (RCLASS_EXT(c)->iv_index_tbl) +#define RCLASS_ORIGIN(c) (RCLASS_EXT(c)->origin_) +#define RCLASS_REFINED_CLASS(c) (RCLASS_EXT(c)->refined_class) +#if SIZEOF_SERIAL_T == SIZEOF_VALUE +# define RCLASS_SERIAL(c) (RCLASS(c)->class_serial) +#else +# define RCLASS_SERIAL(c) (RCLASS_EXT(c)->class_serial) +#endif +#define RCLASS_INCLUDER(c) (RCLASS_EXT(c)->includer) + +#define RCLASS_CLONED FL_USER6 +#define RICLASS_IS_ORIGIN FL_USER5 +#define RCLASS_REFINED_BY_ANY FL_USER7 + +static inline void +RCLASS_SET_ORIGIN(VALUE klass, VALUE origin) +{ + RB_OBJ_WRITE(klass, &RCLASS_ORIGIN(klass), origin); + if (klass != origin) FL_SET(origin, RICLASS_IS_ORIGIN); +} + +static inline void +RCLASS_SET_INCLUDER(VALUE iclass, VALUE klass) +{ + RB_OBJ_WRITE(iclass, &RCLASS_INCLUDER(iclass), klass); +} + +#undef RCLASS_SUPER +static inline VALUE +RCLASS_SUPER(VALUE klass) +{ + return RCLASS(klass)->super; +} + +static inline VALUE +RCLASS_SET_SUPER(VALUE klass, VALUE super) +{ + if (super) { + rb_class_remove_from_super_subclasses(klass); + rb_class_subclass_add(super, klass); + } + RB_OBJ_WRITE(klass, &RCLASS(klass)->super, super); + return super; +} + +#endif /* INTERNAL_CLASS_H */ |