2000-05-01 13:42:38 +04:00
|
|
|
/**********************************************************************
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
class.c -
|
|
|
|
|
|
|
|
$Author$
|
|
|
|
created at: Tue Aug 10 15:05:44 JST 1993
|
|
|
|
|
* encoding.c: provide basic features for M17N.
* parse.y: encoding aware parsing.
* parse.y (pragma_encoding): encoding specification pragma.
* parse.y (rb_intern3): encoding specified symbols.
* string.c (rb_str_length): length based on characters.
for older behavior, bytesize method added.
* string.c (rb_str_index_m): index based on characters. rindex as
well.
* string.c (succ_char): encoding aware succeeding string.
* string.c (rb_str_reverse): reverse based on characters.
* string.c (rb_str_inspect): encoding aware string description.
* string.c (rb_str_upcase_bang): encoding aware case conversion.
downcase, capitalize, swapcase as well.
* string.c (rb_str_tr_bang): tr based on characters. delete,
squeeze, tr_s, count as well.
* string.c (rb_str_split_m): split based on characters.
* string.c (rb_str_each_line): encoding aware each_line.
* string.c (rb_str_each_char): added. iteration based on
characters.
* string.c (rb_str_strip_bang): encoding aware whitespace
stripping. lstrip, rstrip as well.
* string.c (rb_str_justify): encoding aware justifying (ljust,
rjust, center).
* string.c (str_encoding): get encoding attribute from a string.
* re.c (rb_reg_initialize): encoding aware regular expression
* sprintf.c (rb_str_format): formatting (i.e. length count) based
on characters.
* io.c (rb_io_getc): getc to return one-character string.
for older behavior, getbyte method added.
* ext/stringio/stringio.c (strio_getc): ditto.
* io.c (rb_io_ungetc): allow pushing arbitrary string at the
current reading point.
* ext/stringio/stringio.c (strio_ungetc): ditto.
* ext/strscan/strscan.c: encoding support.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13261 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-08-25 07:29:39 +04:00
|
|
|
Copyright (C) 1993-2007 Yukihiro Matsumoto
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2000-05-01 13:42:38 +04:00
|
|
|
**********************************************************************/
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2009-06-29 20:39:28 +04:00
|
|
|
/*!
|
|
|
|
* \defgroup class Classes and their hierarchy.
|
|
|
|
* \par Terminology
|
|
|
|
* - class: same as in Ruby.
|
|
|
|
* - singleton class: class for a particular object
|
|
|
|
* - eigenclass: = singleton class
|
|
|
|
* - metaclass: class of a class. metaclass is a kind of singleton class.
|
|
|
|
* - metametaclass: class of a metaclass.
|
|
|
|
* - meta^(n)-class: class of a meta^(n-1)-class.
|
|
|
|
* - attached object: A singleton class knows its unique instance.
|
|
|
|
* The instance is called the attached object for the singleton class.
|
|
|
|
* \{
|
|
|
|
*/
|
|
|
|
|
2014-11-15 14:49:06 +03:00
|
|
|
#include "internal.h"
|
2007-06-10 07:06:15 +04:00
|
|
|
#include "ruby/st.h"
|
2010-10-26 21:27:32 +04:00
|
|
|
#include "constant.h"
|
2009-07-15 18:59:41 +04:00
|
|
|
#include "vm_core.h"
|
2015-08-12 11:43:55 +03:00
|
|
|
#include "id_table.h"
|
1999-01-20 07:59:39 +03:00
|
|
|
#include <ctype.h>
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2013-05-02 11:54:17 +04:00
|
|
|
#define id_attached id__attached__
|
1998-01-16 15:13:05 +03:00
|
|
|
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
|
|
|
void
|
|
|
|
rb_class_subclass_add(VALUE super, VALUE klass)
|
|
|
|
{
|
|
|
|
rb_subclass_entry_t *entry, *head;
|
|
|
|
|
|
|
|
if (super && super != Qundef) {
|
2014-09-13 10:17:58 +04:00
|
|
|
entry = ALLOC(rb_subclass_entry_t);
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
|
|
|
entry->klass = klass;
|
|
|
|
entry->next = NULL;
|
|
|
|
|
|
|
|
head = RCLASS_EXT(super)->subclasses;
|
|
|
|
if (head) {
|
|
|
|
entry->next = head;
|
|
|
|
RCLASS_EXT(head->klass)->parent_subclasses = &entry->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
RCLASS_EXT(super)->subclasses = entry;
|
|
|
|
RCLASS_EXT(klass)->parent_subclasses = &RCLASS_EXT(super)->subclasses;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rb_module_add_to_subclasses_list(VALUE module, VALUE iclass)
|
|
|
|
{
|
|
|
|
rb_subclass_entry_t *entry, *head;
|
|
|
|
|
2014-09-13 10:17:58 +04:00
|
|
|
entry = ALLOC(rb_subclass_entry_t);
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
|
|
|
entry->klass = iclass;
|
|
|
|
entry->next = NULL;
|
|
|
|
|
|
|
|
head = RCLASS_EXT(module)->subclasses;
|
|
|
|
if (head) {
|
|
|
|
entry->next = head;
|
|
|
|
RCLASS_EXT(head->klass)->module_subclasses = &entry->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
RCLASS_EXT(module)->subclasses = entry;
|
|
|
|
RCLASS_EXT(iclass)->module_subclasses = &RCLASS_EXT(module)->subclasses;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_class_remove_from_super_subclasses(VALUE klass)
|
|
|
|
{
|
|
|
|
rb_subclass_entry_t *entry;
|
|
|
|
|
|
|
|
if (RCLASS_EXT(klass)->parent_subclasses) {
|
|
|
|
entry = *RCLASS_EXT(klass)->parent_subclasses;
|
|
|
|
|
|
|
|
*RCLASS_EXT(klass)->parent_subclasses = entry->next;
|
|
|
|
if (entry->next) {
|
|
|
|
RCLASS_EXT(entry->next->klass)->parent_subclasses = RCLASS_EXT(klass)->parent_subclasses;
|
|
|
|
}
|
2014-03-09 09:22:01 +04:00
|
|
|
xfree(entry);
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
RCLASS_EXT(klass)->parent_subclasses = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_class_remove_from_module_subclasses(VALUE klass)
|
|
|
|
{
|
|
|
|
rb_subclass_entry_t *entry;
|
|
|
|
|
|
|
|
if (RCLASS_EXT(klass)->module_subclasses) {
|
|
|
|
entry = *RCLASS_EXT(klass)->module_subclasses;
|
|
|
|
*RCLASS_EXT(klass)->module_subclasses = entry->next;
|
|
|
|
|
|
|
|
if (entry->next) {
|
|
|
|
RCLASS_EXT(entry->next->klass)->module_subclasses = RCLASS_EXT(klass)->module_subclasses;
|
|
|
|
}
|
|
|
|
|
2014-03-09 09:22:01 +04:00
|
|
|
xfree(entry);
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
RCLASS_EXT(klass)->module_subclasses = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-01-19 17:09:20 +03:00
|
|
|
rb_class_foreach_subclass(VALUE klass, void (*f)(VALUE, VALUE), VALUE arg)
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
|
|
|
{
|
|
|
|
rb_subclass_entry_t *cur = RCLASS_EXT(klass)->subclasses;
|
|
|
|
|
|
|
|
/* do not be tempted to simplify this loop into a for loop, the order of
|
|
|
|
operations is important here if `f` modifies the linked list */
|
|
|
|
while (cur) {
|
|
|
|
VALUE curklass = cur->klass;
|
|
|
|
cur = cur->next;
|
2015-01-19 17:09:20 +03:00
|
|
|
f(curklass, arg);
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-19 17:09:20 +03:00
|
|
|
static void
|
|
|
|
class_detach_subclasses(VALUE klass, VALUE arg)
|
|
|
|
{
|
|
|
|
rb_class_remove_from_super_subclasses(klass);
|
|
|
|
}
|
|
|
|
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
|
|
|
void
|
|
|
|
rb_class_detach_subclasses(VALUE klass)
|
|
|
|
{
|
2015-01-19 17:09:20 +03:00
|
|
|
rb_class_foreach_subclass(klass, class_detach_subclasses, Qnil);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
class_detach_module_subclasses(VALUE klass, VALUE arg)
|
|
|
|
{
|
|
|
|
rb_class_remove_from_module_subclasses(klass);
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_class_detach_module_subclasses(VALUE klass)
|
|
|
|
{
|
2015-01-19 17:09:20 +03:00
|
|
|
rb_class_foreach_subclass(klass, class_detach_module_subclasses, Qnil);
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
|
|
|
}
|
|
|
|
|
2009-06-29 20:39:28 +04:00
|
|
|
/**
|
|
|
|
* Allocates a struct RClass for a new class.
|
|
|
|
*
|
|
|
|
* \param flags initial value for basic.flags of the returned class.
|
|
|
|
* \param klass the class of the returned class.
|
|
|
|
* \return an uninitialized Class object.
|
|
|
|
* \pre \p klass must refer \c Class class or an ancestor of Class.
|
|
|
|
* \pre \code (flags | T_CLASS) != 0 \endcode
|
|
|
|
* \post the returned class can safely be \c #initialize 'd.
|
|
|
|
*
|
|
|
|
* \note this function is not Class#allocate.
|
|
|
|
*/
|
2007-09-28 10:21:46 +04:00
|
|
|
static VALUE
|
|
|
|
class_alloc(VALUE flags, VALUE klass)
|
|
|
|
{
|
2014-12-11 13:15:30 +03:00
|
|
|
NEWOBJ_OF(obj, struct RClass, klass, (flags & T_MASK) | FL_PROMOTED1 /* start from age == 2 */ | (RGENGC_WB_PROTECTED_CLASS ? FL_WB_PROTECTED : 0));
|
2015-03-11 12:15:20 +03:00
|
|
|
obj->ptr = ZALLOC(rb_classext_t);
|
|
|
|
/* ZALLOC
|
|
|
|
RCLASS_IV_TBL(obj) = 0;
|
|
|
|
RCLASS_CONST_TBL(obj) = 0;
|
|
|
|
RCLASS_M_TBL(obj) = 0;
|
|
|
|
RCLASS_IV_INDEX_TBL(obj) = 0;
|
|
|
|
RCLASS_SET_SUPER((VALUE)obj, 0);
|
|
|
|
RCLASS_EXT(obj)->subclasses = NULL;
|
|
|
|
RCLASS_EXT(obj)->parent_subclasses = NULL;
|
|
|
|
RCLASS_EXT(obj)->module_subclasses = NULL;
|
|
|
|
*/
|
|
|
|
RCLASS_SET_ORIGIN((VALUE)obj, (VALUE)obj);
|
2013-12-09 15:00:23 +04:00
|
|
|
RCLASS_SERIAL(obj) = rb_next_class_serial();
|
2012-08-06 11:00:19 +04:00
|
|
|
RCLASS_REFINED_CLASS(obj) = Qnil;
|
2012-09-08 13:52:26 +04:00
|
|
|
RCLASS_EXT(obj)->allocator = 0;
|
2015-03-11 12:15:20 +03:00
|
|
|
|
2007-09-28 10:21:46 +04:00
|
|
|
return (VALUE)obj;
|
|
|
|
}
|
|
|
|
|
2015-08-12 11:43:55 +03:00
|
|
|
static void
|
|
|
|
RCLASS_M_TBL_INIT(VALUE c)
|
|
|
|
{
|
|
|
|
RCLASS_M_TBL(c) = rb_id_table_create(0);
|
|
|
|
}
|
2009-06-29 20:39:28 +04:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* A utility function that wraps class_alloc.
|
|
|
|
*
|
|
|
|
* allocates a class and initializes safely.
|
|
|
|
* \param super a class from which the new class derives.
|
|
|
|
* \return a class object.
|
|
|
|
* \pre \a super must be a class.
|
|
|
|
* \post the metaclass of the new class is Class.
|
|
|
|
*/
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_class_boot(VALUE super)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2007-09-28 10:21:46 +04:00
|
|
|
VALUE klass = class_alloc(T_CLASS, rb_cClass);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RCLASS_SET_SUPER(klass, super);
|
2013-12-03 12:11:07 +04:00
|
|
|
RCLASS_M_TBL_INIT(klass);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2001-08-14 12:13:31 +04:00
|
|
|
OBJ_INFECT(klass, super);
|
1998-01-16 15:19:22 +03:00
|
|
|
return (VALUE)klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2009-06-29 20:39:28 +04:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* Ensures a class can be derived from super.
|
|
|
|
*
|
|
|
|
* \param super a reference to an object.
|
|
|
|
* \exception TypeError if \a super is not a Class or \a super is a singleton class.
|
|
|
|
*/
|
2004-11-16 07:55:14 +03:00
|
|
|
void
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_check_inheritable(VALUE super)
|
2004-11-16 07:55:14 +03:00
|
|
|
{
|
2011-09-29 15:07:45 +04:00
|
|
|
if (!RB_TYPE_P(super, T_CLASS)) {
|
2015-06-28 06:28:50 +03:00
|
|
|
rb_raise(rb_eTypeError, "superclass must be a Class (%"PRIsVALUE" given)",
|
|
|
|
rb_obj_class(super));
|
2004-11-16 07:55:14 +03:00
|
|
|
}
|
|
|
|
if (RBASIC(super)->flags & FL_SINGLETON) {
|
|
|
|
rb_raise(rb_eTypeError, "can't make subclass of singleton class");
|
|
|
|
}
|
2009-10-24 03:37:14 +04:00
|
|
|
if (super == rb_cClass) {
|
|
|
|
rb_raise(rb_eTypeError, "can't make subclass of Class");
|
|
|
|
}
|
2004-11-16 07:55:14 +03:00
|
|
|
}
|
|
|
|
|
2009-06-29 20:39:28 +04:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* Creates a new class.
|
|
|
|
* \param super a class from which the new class derives.
|
|
|
|
* \exception TypeError \a super is not inheritable.
|
|
|
|
* \exception TypeError \a super is the Class class.
|
|
|
|
*/
|
2001-07-18 09:56:05 +04:00
|
|
|
VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_class_new(VALUE super)
|
2001-07-18 09:56:05 +04:00
|
|
|
{
|
|
|
|
Check_Type(super, T_CLASS);
|
2004-11-16 07:55:14 +03:00
|
|
|
rb_check_inheritable(super);
|
2001-07-18 09:56:05 +04:00
|
|
|
return rb_class_boot(super);
|
|
|
|
}
|
|
|
|
|
2011-05-31 20:16:06 +04:00
|
|
|
static void
|
2015-06-03 22:36:52 +03:00
|
|
|
clone_method(VALUE old_klass, VALUE new_klass, ID mid, const rb_method_entry_t *me)
|
2009-07-15 18:59:41 +04:00
|
|
|
{
|
2015-06-03 14:10:16 +03:00
|
|
|
if (me->def->type == VM_METHOD_TYPE_ISEQ) {
|
|
|
|
rb_cref_t *new_cref;
|
2015-06-03 22:36:52 +03:00
|
|
|
rb_vm_rewrite_cref(me->def->body.iseq.cref, old_klass, new_klass, &new_cref);
|
2015-07-22 01:52:59 +03:00
|
|
|
rb_add_method_iseq(new_klass, mid, me->def->body.iseq.iseqptr, new_cref, METHOD_ENTRY_VISI(me));
|
2009-08-28 06:45:41 +04:00
|
|
|
}
|
|
|
|
else {
|
2015-06-06 13:19:48 +03:00
|
|
|
rb_method_entry_set(new_klass, mid, me, METHOD_ENTRY_VISI(me));
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
2011-05-31 20:16:06 +04:00
|
|
|
}
|
|
|
|
|
2015-06-03 22:36:52 +03:00
|
|
|
struct clone_method_arg {
|
|
|
|
VALUE new_klass;
|
|
|
|
VALUE old_klass;
|
|
|
|
};
|
|
|
|
|
2015-08-12 11:43:55 +03:00
|
|
|
static enum rb_id_table_iterator_result
|
|
|
|
clone_method_i(ID key, VALUE value, void *data)
|
2011-05-31 20:16:06 +04:00
|
|
|
{
|
2015-06-03 22:36:52 +03:00
|
|
|
const struct clone_method_arg *arg = (struct clone_method_arg *)data;
|
2015-08-12 11:43:55 +03:00
|
|
|
clone_method(arg->old_klass, arg->new_klass, key, (const rb_method_entry_t *)value);
|
2015-08-12 11:59:27 +03:00
|
|
|
return ID_TABLE_CONTINUE;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2013-06-14 13:23:54 +04:00
|
|
|
struct clone_const_arg {
|
|
|
|
VALUE klass;
|
|
|
|
st_table *tbl;
|
|
|
|
};
|
|
|
|
|
2010-10-26 21:27:32 +04:00
|
|
|
static int
|
2013-06-14 13:23:54 +04:00
|
|
|
clone_const(ID key, const rb_const_entry_t *ce, struct clone_const_arg *arg)
|
2010-10-26 21:27:32 +04:00
|
|
|
{
|
|
|
|
rb_const_entry_t *nce = ALLOC(rb_const_entry_t);
|
2013-06-14 13:23:54 +04:00
|
|
|
MEMCPY(nce, ce, rb_const_entry_t, 1);
|
* include/ruby/ruby.h: rename OBJ_WRITE and OBJ_WRITTEN into
RB_OBJ_WRITE and RB_OBJ_WRITTEN.
* array.c, class.c, compile.c, hash.c, internal.h, iseq.c,
proc.c, process.c, re.c, string.c, variable.c, vm.c,
vm_eval.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: catch up this change.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44299 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-12-20 12:07:47 +04:00
|
|
|
RB_OBJ_WRITTEN(arg->klass, Qundef, ce->value);
|
|
|
|
RB_OBJ_WRITTEN(arg->klass, Qundef, ce->file);
|
2013-06-14 13:23:54 +04:00
|
|
|
|
|
|
|
st_insert(arg->tbl, key, (st_data_t)nce);
|
2010-10-27 07:06:27 +04:00
|
|
|
return ST_CONTINUE;
|
2010-10-26 21:27:32 +04:00
|
|
|
}
|
|
|
|
|
2011-06-04 07:49:50 +04:00
|
|
|
static int
|
|
|
|
clone_const_i(st_data_t key, st_data_t value, st_data_t data)
|
|
|
|
{
|
2013-06-14 13:23:54 +04:00
|
|
|
return clone_const((ID)key, (const rb_const_entry_t *)value, (struct clone_const_arg *)data);
|
2011-06-04 07:49:50 +04:00
|
|
|
}
|
|
|
|
|
2012-12-13 18:11:01 +04:00
|
|
|
static void
|
|
|
|
class_init_copy_check(VALUE clone, VALUE orig)
|
|
|
|
{
|
|
|
|
if (orig == rb_cBasicObject) {
|
|
|
|
rb_raise(rb_eTypeError, "can't copy the root class");
|
|
|
|
}
|
|
|
|
if (RCLASS_SUPER(clone) != 0 || clone == rb_cBasicObject) {
|
|
|
|
rb_raise(rb_eTypeError, "already initialized class");
|
|
|
|
}
|
|
|
|
if (FL_TEST(orig, FL_SINGLETON)) {
|
|
|
|
rb_raise(rb_eTypeError, "can't copy singleton class");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-01-18 17:16:47 +03:00
|
|
|
/* :nodoc: */
|
2001-05-02 08:22:21 +04:00
|
|
|
VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_mod_init_copy(VALUE clone, VALUE orig)
|
2001-05-02 08:22:21 +04:00
|
|
|
{
|
2012-12-13 18:32:40 +04:00
|
|
|
if (RB_TYPE_P(clone, T_CLASS)) {
|
2012-12-13 18:11:01 +04:00
|
|
|
class_init_copy_check(clone, orig);
|
|
|
|
}
|
2014-02-21 15:42:03 +04:00
|
|
|
if (!OBJ_INIT_COPY(clone, orig)) return clone;
|
2003-12-22 15:15:34 +03:00
|
|
|
if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RBASIC_SET_CLASS(clone, rb_singleton_class_clone(orig));
|
2010-06-27 21:47:21 +04:00
|
|
|
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
|
2003-12-22 15:15:34 +03:00
|
|
|
}
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RCLASS_SET_SUPER(clone, RCLASS_SUPER(orig));
|
2012-09-08 13:52:26 +04:00
|
|
|
RCLASS_EXT(clone)->allocator = RCLASS_EXT(orig)->allocator;
|
2014-05-08 09:34:31 +04:00
|
|
|
if (RCLASS_IV_TBL(clone)) {
|
|
|
|
st_free_table(RCLASS_IV_TBL(clone));
|
|
|
|
RCLASS_IV_TBL(clone) = 0;
|
|
|
|
}
|
|
|
|
if (RCLASS_CONST_TBL(clone)) {
|
|
|
|
rb_free_const_table(RCLASS_CONST_TBL(clone));
|
|
|
|
RCLASS_CONST_TBL(clone) = 0;
|
|
|
|
}
|
2015-03-06 01:20:14 +03:00
|
|
|
RCLASS_M_TBL(clone) = 0;
|
2007-09-28 10:21:46 +04:00
|
|
|
if (RCLASS_IV_TBL(orig)) {
|
2010-10-14 02:22:18 +04:00
|
|
|
st_data_t id;
|
2001-10-22 10:48:18 +04:00
|
|
|
|
2013-06-14 13:23:54 +04:00
|
|
|
RCLASS_IV_TBL(clone) = rb_st_copy(clone, RCLASS_IV_TBL(orig));
|
2012-05-23 00:15:28 +04:00
|
|
|
CONST_ID(id, "__tmp_classpath__");
|
|
|
|
st_delete(RCLASS_IV_TBL(clone), &id, 0);
|
2008-06-09 13:25:32 +04:00
|
|
|
CONST_ID(id, "__classpath__");
|
2010-10-14 02:22:18 +04:00
|
|
|
st_delete(RCLASS_IV_TBL(clone), &id, 0);
|
2008-06-09 13:25:32 +04:00
|
|
|
CONST_ID(id, "__classid__");
|
2010-10-14 02:22:18 +04:00
|
|
|
st_delete(RCLASS_IV_TBL(clone), &id, 0);
|
2001-05-02 08:22:21 +04:00
|
|
|
}
|
2010-10-26 21:27:21 +04:00
|
|
|
if (RCLASS_CONST_TBL(orig)) {
|
2013-06-14 13:23:54 +04:00
|
|
|
struct clone_const_arg arg;
|
2014-05-08 09:34:31 +04:00
|
|
|
|
2010-10-26 21:27:32 +04:00
|
|
|
RCLASS_CONST_TBL(clone) = st_init_numtable();
|
2013-06-14 13:23:54 +04:00
|
|
|
arg.klass = clone;
|
|
|
|
arg.tbl = RCLASS_CONST_TBL(clone);
|
|
|
|
st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)&arg);
|
2010-10-26 21:27:21 +04:00
|
|
|
}
|
2007-09-28 10:21:46 +04:00
|
|
|
if (RCLASS_M_TBL(orig)) {
|
2015-06-03 22:36:52 +03:00
|
|
|
struct clone_method_arg arg;
|
|
|
|
arg.old_klass = orig;
|
|
|
|
arg.new_klass = clone;
|
2013-12-03 12:11:07 +04:00
|
|
|
RCLASS_M_TBL_INIT(clone);
|
2015-08-12 11:43:55 +03:00
|
|
|
rb_id_table_foreach(RCLASS_M_TBL(orig), clone_method_i, &arg);
|
2001-05-02 08:22:21 +04:00
|
|
|
}
|
|
|
|
|
2003-08-07 01:50:06 +04:00
|
|
|
return clone;
|
2001-05-02 08:22:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_singleton_class_clone(VALUE obj)
|
2012-12-29 06:37:47 +04:00
|
|
|
{
|
|
|
|
return rb_singleton_class_clone_and_attach(obj, Qundef);
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach)
|
2001-05-02 08:22:21 +04:00
|
|
|
{
|
2015-06-03 22:36:52 +03:00
|
|
|
const VALUE klass = RBASIC(obj)->klass;
|
2001-05-02 08:22:21 +04:00
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
if (!FL_TEST(klass, FL_SINGLETON))
|
|
|
|
return klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
else {
|
|
|
|
/* copy singleton(unnamed) class */
|
2012-01-07 18:02:23 +04:00
|
|
|
VALUE clone = class_alloc(RBASIC(klass)->flags, 0);
|
2002-09-03 09:20:14 +04:00
|
|
|
|
|
|
|
if (BUILTIN_TYPE(obj) == T_CLASS) {
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RBASIC_SET_CLASS(clone, clone);
|
2002-09-03 09:20:14 +04:00
|
|
|
}
|
|
|
|
else {
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RBASIC_SET_CLASS(clone, rb_singleton_class_clone(klass));
|
2002-09-03 09:20:14 +04:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RCLASS_SET_SUPER(clone, RCLASS_SUPER(klass));
|
2012-09-08 13:52:26 +04:00
|
|
|
RCLASS_EXT(clone)->allocator = RCLASS_EXT(klass)->allocator;
|
2007-09-28 10:21:46 +04:00
|
|
|
if (RCLASS_IV_TBL(klass)) {
|
2013-06-14 13:23:54 +04:00
|
|
|
RCLASS_IV_TBL(clone) = rb_st_copy(clone, RCLASS_IV_TBL(klass));
|
2001-03-28 12:43:25 +04:00
|
|
|
}
|
2010-10-26 21:27:21 +04:00
|
|
|
if (RCLASS_CONST_TBL(klass)) {
|
2013-06-14 13:23:54 +04:00
|
|
|
struct clone_const_arg arg;
|
2010-10-26 21:27:32 +04:00
|
|
|
RCLASS_CONST_TBL(clone) = st_init_numtable();
|
2013-06-14 13:23:54 +04:00
|
|
|
arg.klass = clone;
|
|
|
|
arg.tbl = RCLASS_CONST_TBL(clone);
|
|
|
|
st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)&arg);
|
2010-10-26 21:27:21 +04:00
|
|
|
}
|
2012-12-29 06:37:47 +04:00
|
|
|
if (attach != Qundef) {
|
|
|
|
rb_singleton_class_attached(clone, attach);
|
|
|
|
}
|
2013-12-03 12:11:07 +04:00
|
|
|
RCLASS_M_TBL_INIT(clone);
|
2015-06-03 22:36:52 +03:00
|
|
|
{
|
|
|
|
struct clone_method_arg arg;
|
|
|
|
arg.old_klass = klass;
|
|
|
|
arg.new_klass = clone;
|
2015-08-12 11:43:55 +03:00
|
|
|
rb_id_table_foreach(RCLASS_M_TBL(klass), clone_method_i, &arg);
|
2015-06-03 22:36:52 +03:00
|
|
|
}
|
2011-05-31 20:16:06 +04:00
|
|
|
rb_singleton_class_attached(RBASIC(clone)->klass, clone);
|
1998-01-16 15:13:05 +03:00
|
|
|
FL_SET(clone, FL_SINGLETON);
|
2013-06-14 13:23:54 +04:00
|
|
|
|
2011-05-31 20:16:06 +04:00
|
|
|
return clone;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-31 09:55:57 +04:00
|
|
|
/*!
|
|
|
|
* Attach a object to a singleton class.
|
|
|
|
* @pre \a klass is the singleton class of \a obj.
|
|
|
|
*/
|
1998-01-16 15:19:22 +03:00
|
|
|
void
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_singleton_class_attached(VALUE klass, VALUE obj)
|
1998-01-16 15:19:22 +03:00
|
|
|
{
|
2001-05-02 08:22:21 +04:00
|
|
|
if (FL_TEST(klass, FL_SINGLETON)) {
|
2007-09-28 10:21:46 +04:00
|
|
|
if (!RCLASS_IV_TBL(klass)) {
|
|
|
|
RCLASS_IV_TBL(klass) = st_init_numtable();
|
2001-05-02 08:22:21 +04:00
|
|
|
}
|
2013-06-14 13:23:54 +04:00
|
|
|
rb_st_insert_id_and_value(klass, RCLASS_IV_TBL(klass), id_attached, obj);
|
2001-05-02 08:22:21 +04:00
|
|
|
}
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
|
|
|
|
* test/ruby/test_metaclass.rb: new test case for metaclass hierarchy.
* class.c (make_metametaclass): new function. extracted from
rb_make_metaclass.
* class.c (rb_make_metaclass): uses make_metametaclass when called for a
metaclass.
* class.c (rb_singleton_class): creates a meta^(n+2)-class in
addition to a meta^(n+1)-class when called for a meta^(n)-class.
This is because the returned meta^(n+1) class must acts as an instance of
Class, metaclass of Class, ..., meta^(n+1)-class of Class,
Module, metaclass of Module, ..., meta^(n+1)-class of Module,
Object, metaclass of Object, ..., meta^(n+2)-class of Object,
BasicObject, metaclass of BasicObject, ..., meta^(n+2)-class of
and BasicObject even when Class, Module, Object or BasicObject has
not have its meta^(i)-class yet.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20747 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-12-15 09:23:43 +03:00
|
|
|
|
2009-08-31 09:55:57 +04:00
|
|
|
|
2010-05-29 22:51:39 +04:00
|
|
|
#define METACLASS_OF(k) RBASIC(k)->klass
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
#define SET_METACLASS_OF(k, cls) RBASIC_SET_CLASS(k, cls)
|
2009-08-31 09:55:57 +04:00
|
|
|
|
2009-06-29 20:39:28 +04:00
|
|
|
/*!
|
2009-08-31 09:55:57 +04:00
|
|
|
* whether k is a meta^(n)-class of Class class
|
|
|
|
* @retval 1 if \a k is a meta^(n)-class of Class class (n >= 0)
|
|
|
|
* @retval 0 otherwise
|
2009-06-29 20:39:28 +04:00
|
|
|
*/
|
2010-12-04 05:18:42 +03:00
|
|
|
#define META_CLASS_OF_CLASS_CLASS_P(k) (METACLASS_OF(k) == (k))
|
2009-08-31 09:55:57 +04:00
|
|
|
|
2013-03-31 01:27:27 +04:00
|
|
|
/*!
|
|
|
|
* whether k has a metaclass
|
|
|
|
* @retval 1 if \a k has a metaclass
|
|
|
|
* @retval 0 otherwise
|
|
|
|
*/
|
|
|
|
#define HAVE_METACLASS_P(k) \
|
|
|
|
(FL_TEST(METACLASS_OF(k), FL_SINGLETON) && \
|
|
|
|
rb_ivar_get(METACLASS_OF(k), id_attached) == (k))
|
2009-08-31 09:55:57 +04:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* ensures \a klass belongs to its own eigenclass.
|
|
|
|
* @return the eigenclass of \a klass
|
|
|
|
* @post \a klass belongs to the returned eigenclass.
|
|
|
|
* i.e. the attached object of the eigenclass is \a klass.
|
|
|
|
* @note this macro creates a new eigenclass if necessary.
|
|
|
|
*/
|
|
|
|
#define ENSURE_EIGENCLASS(klass) \
|
2013-03-31 01:27:27 +04:00
|
|
|
(HAVE_METACLASS_P(klass) ? METACLASS_OF(klass) : make_metaclass(klass))
|
2009-08-31 09:55:57 +04:00
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* Creates a metaclass of \a klass
|
|
|
|
* \param klass a class
|
|
|
|
* \return created metaclass for the class
|
|
|
|
* \pre \a klass is a Class object
|
|
|
|
* \pre \a klass has no singleton class.
|
|
|
|
* \post the class of \a klass is the returned class.
|
|
|
|
* \post the returned class is meta^(n+1)-class when \a klass is a meta^(n)-klass for n >= 0
|
|
|
|
*/
|
|
|
|
static inline VALUE
|
|
|
|
make_metaclass(VALUE klass)
|
* test/ruby/test_metaclass.rb: new test case for metaclass hierarchy.
* class.c (make_metametaclass): new function. extracted from
rb_make_metaclass.
* class.c (rb_make_metaclass): uses make_metametaclass when called for a
metaclass.
* class.c (rb_singleton_class): creates a meta^(n+2)-class in
addition to a meta^(n+1)-class when called for a meta^(n)-class.
This is because the returned meta^(n+1) class must acts as an instance of
Class, metaclass of Class, ..., meta^(n+1)-class of Class,
Module, metaclass of Module, ..., meta^(n+1)-class of Module,
Object, metaclass of Object, ..., meta^(n+2)-class of Object,
BasicObject, metaclass of BasicObject, ..., meta^(n+2)-class of
and BasicObject even when Class, Module, Object or BasicObject has
not have its meta^(i)-class yet.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20747 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-12-15 09:23:43 +03:00
|
|
|
{
|
2009-08-31 09:55:57 +04:00
|
|
|
VALUE super;
|
|
|
|
VALUE metaclass = rb_class_boot(Qundef);
|
* test/ruby/test_metaclass.rb: new test case for metaclass hierarchy.
* class.c (make_metametaclass): new function. extracted from
rb_make_metaclass.
* class.c (rb_make_metaclass): uses make_metametaclass when called for a
metaclass.
* class.c (rb_singleton_class): creates a meta^(n+2)-class in
addition to a meta^(n+1)-class when called for a meta^(n)-class.
This is because the returned meta^(n+1) class must acts as an instance of
Class, metaclass of Class, ..., meta^(n+1)-class of Class,
Module, metaclass of Module, ..., meta^(n+1)-class of Module,
Object, metaclass of Object, ..., meta^(n+2)-class of Object,
BasicObject, metaclass of BasicObject, ..., meta^(n+2)-class of
and BasicObject even when Class, Module, Object or BasicObject has
not have its meta^(i)-class yet.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20747 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-12-15 09:23:43 +03:00
|
|
|
|
2009-08-31 09:55:57 +04:00
|
|
|
FL_SET(metaclass, FL_SINGLETON);
|
|
|
|
rb_singleton_class_attached(metaclass, klass);
|
|
|
|
|
|
|
|
if (META_CLASS_OF_CLASS_CLASS_P(klass)) {
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
SET_METACLASS_OF(klass, metaclass);
|
|
|
|
SET_METACLASS_OF(metaclass, metaclass);
|
* test/ruby/test_metaclass.rb: new test case for metaclass hierarchy.
* class.c (make_metametaclass): new function. extracted from
rb_make_metaclass.
* class.c (rb_make_metaclass): uses make_metametaclass when called for a
metaclass.
* class.c (rb_singleton_class): creates a meta^(n+2)-class in
addition to a meta^(n+1)-class when called for a meta^(n)-class.
This is because the returned meta^(n+1) class must acts as an instance of
Class, metaclass of Class, ..., meta^(n+1)-class of Class,
Module, metaclass of Module, ..., meta^(n+1)-class of Module,
Object, metaclass of Object, ..., meta^(n+2)-class of Object,
BasicObject, metaclass of BasicObject, ..., meta^(n+2)-class of
and BasicObject even when Class, Module, Object or BasicObject has
not have its meta^(i)-class yet.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20747 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-12-15 09:23:43 +03:00
|
|
|
}
|
|
|
|
else {
|
2009-08-31 09:55:57 +04:00
|
|
|
VALUE tmp = METACLASS_OF(klass); /* for a meta^(n)-class klass, tmp is meta^(n)-class of Class class */
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
SET_METACLASS_OF(klass, metaclass);
|
|
|
|
SET_METACLASS_OF(metaclass, ENSURE_EIGENCLASS(tmp));
|
* test/ruby/test_metaclass.rb: new test case for metaclass hierarchy.
* class.c (make_metametaclass): new function. extracted from
rb_make_metaclass.
* class.c (rb_make_metaclass): uses make_metametaclass when called for a
metaclass.
* class.c (rb_singleton_class): creates a meta^(n+2)-class in
addition to a meta^(n+1)-class when called for a meta^(n)-class.
This is because the returned meta^(n+1) class must acts as an instance of
Class, metaclass of Class, ..., meta^(n+1)-class of Class,
Module, metaclass of Module, ..., meta^(n+1)-class of Module,
Object, metaclass of Object, ..., meta^(n+2)-class of Object,
BasicObject, metaclass of BasicObject, ..., meta^(n+2)-class of
and BasicObject even when Class, Module, Object or BasicObject has
not have its meta^(i)-class yet.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20747 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-12-15 09:23:43 +03:00
|
|
|
}
|
|
|
|
|
2009-08-31 09:55:57 +04:00
|
|
|
super = RCLASS_SUPER(klass);
|
2010-12-05 11:56:42 +03:00
|
|
|
while (RB_TYPE_P(super, T_ICLASS)) super = RCLASS_SUPER(super);
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RCLASS_SET_SUPER(metaclass, super ? ENSURE_EIGENCLASS(super) : rb_cClass);
|
2009-08-31 09:55:57 +04:00
|
|
|
|
|
|
|
OBJ_INFECT(metaclass, RCLASS_SUPER(metaclass));
|
|
|
|
|
|
|
|
return metaclass;
|
|
|
|
}
|
* test/ruby/test_metaclass.rb: new test case for metaclass hierarchy.
* class.c (make_metametaclass): new function. extracted from
rb_make_metaclass.
* class.c (rb_make_metaclass): uses make_metametaclass when called for a
metaclass.
* class.c (rb_singleton_class): creates a meta^(n+2)-class in
addition to a meta^(n+1)-class when called for a meta^(n)-class.
This is because the returned meta^(n+1) class must acts as an instance of
Class, metaclass of Class, ..., meta^(n+1)-class of Class,
Module, metaclass of Module, ..., meta^(n+1)-class of Module,
Object, metaclass of Object, ..., meta^(n+2)-class of Object,
BasicObject, metaclass of BasicObject, ..., meta^(n+2)-class of
and BasicObject even when Class, Module, Object or BasicObject has
not have its meta^(i)-class yet.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20747 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-12-15 09:23:43 +03:00
|
|
|
|
2009-08-31 09:55:57 +04:00
|
|
|
/*!
|
|
|
|
* Creates a singleton class for \a obj.
|
|
|
|
* \pre \a obj must not a immediate nor a special const.
|
|
|
|
* \pre \a obj must not a Class object.
|
|
|
|
* \pre \a obj has no singleton class.
|
|
|
|
*/
|
|
|
|
static inline VALUE
|
|
|
|
make_singleton_class(VALUE obj)
|
|
|
|
{
|
2009-08-31 11:21:54 +04:00
|
|
|
VALUE orig_class = RBASIC(obj)->klass;
|
|
|
|
VALUE klass = rb_class_boot(orig_class);
|
2009-08-31 09:55:57 +04:00
|
|
|
|
|
|
|
FL_SET(klass, FL_SINGLETON);
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RBASIC_SET_CLASS(obj, klass);
|
2009-08-31 09:55:57 +04:00
|
|
|
rb_singleton_class_attached(klass, obj);
|
|
|
|
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
SET_METACLASS_OF(klass, METACLASS_OF(rb_class_real(orig_class)));
|
2009-08-31 09:55:57 +04:00
|
|
|
return klass;
|
|
|
|
}
|
* test/ruby/test_metaclass.rb: new test case for metaclass hierarchy.
* class.c (make_metametaclass): new function. extracted from
rb_make_metaclass.
* class.c (rb_make_metaclass): uses make_metametaclass when called for a
metaclass.
* class.c (rb_singleton_class): creates a meta^(n+2)-class in
addition to a meta^(n+1)-class when called for a meta^(n)-class.
This is because the returned meta^(n+1) class must acts as an instance of
Class, metaclass of Class, ..., meta^(n+1)-class of Class,
Module, metaclass of Module, ..., meta^(n+1)-class of Module,
Object, metaclass of Object, ..., meta^(n+2)-class of Object,
BasicObject, metaclass of BasicObject, ..., meta^(n+2)-class of
and BasicObject even when Class, Module, Object or BasicObject has
not have its meta^(i)-class yet.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20747 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-12-15 09:23:43 +03:00
|
|
|
|
2009-08-31 09:55:57 +04:00
|
|
|
|
|
|
|
static VALUE
|
|
|
|
boot_defclass(const char *name, VALUE super)
|
|
|
|
{
|
|
|
|
VALUE obj = rb_class_boot(super);
|
|
|
|
ID id = rb_intern(name);
|
|
|
|
|
|
|
|
rb_name_class(obj, id);
|
|
|
|
rb_const_set((rb_cObject ? rb_cObject : obj), id, obj);
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Init_class_hierarchy(void)
|
|
|
|
{
|
|
|
|
rb_cBasicObject = boot_defclass("BasicObject", 0);
|
|
|
|
rb_cObject = boot_defclass("Object", rb_cBasicObject);
|
|
|
|
rb_cModule = boot_defclass("Module", rb_cObject);
|
|
|
|
rb_cClass = boot_defclass("Class", rb_cModule);
|
|
|
|
|
2014-07-03 07:38:10 +04:00
|
|
|
rb_const_set(rb_cObject, rb_intern_const("BasicObject"), rb_cBasicObject);
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RBASIC_SET_CLASS(rb_cClass, rb_cClass);
|
|
|
|
RBASIC_SET_CLASS(rb_cModule, rb_cClass);
|
|
|
|
RBASIC_SET_CLASS(rb_cObject, rb_cClass);
|
|
|
|
RBASIC_SET_CLASS(rb_cBasicObject, rb_cClass);
|
* test/ruby/test_metaclass.rb: new test case for metaclass hierarchy.
* class.c (make_metametaclass): new function. extracted from
rb_make_metaclass.
* class.c (rb_make_metaclass): uses make_metametaclass when called for a
metaclass.
* class.c (rb_singleton_class): creates a meta^(n+2)-class in
addition to a meta^(n+1)-class when called for a meta^(n)-class.
This is because the returned meta^(n+1) class must acts as an instance of
Class, metaclass of Class, ..., meta^(n+1)-class of Class,
Module, metaclass of Module, ..., meta^(n+1)-class of Module,
Object, metaclass of Object, ..., meta^(n+2)-class of Object,
BasicObject, metaclass of BasicObject, ..., meta^(n+2)-class of
and BasicObject even when Class, Module, Object or BasicObject has
not have its meta^(i)-class yet.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20747 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-12-15 09:23:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-29 20:39:28 +04:00
|
|
|
/*!
|
|
|
|
* \internal
|
2009-08-31 09:55:57 +04:00
|
|
|
* Creates a new *singleton class* for an object.
|
2009-06-29 20:39:28 +04:00
|
|
|
*
|
2009-08-31 09:55:57 +04:00
|
|
|
* \pre \a obj has no singleton class.
|
|
|
|
* \note DO NOT USE the function in an extension libraries. Use \ref rb_singleton_class.
|
|
|
|
* \param obj An object.
|
|
|
|
* \param unused ignored.
|
|
|
|
* \return The singleton class of the object.
|
2009-06-29 20:39:28 +04:00
|
|
|
*/
|
2002-01-10 23:18:39 +03:00
|
|
|
VALUE
|
2009-08-31 09:55:57 +04:00
|
|
|
rb_make_metaclass(VALUE obj, VALUE unused)
|
2002-01-10 23:18:39 +03:00
|
|
|
{
|
2009-08-31 09:55:57 +04:00
|
|
|
if (BUILTIN_TYPE(obj) == T_CLASS) {
|
|
|
|
return make_metaclass(obj);
|
2002-09-25 11:03:05 +04:00
|
|
|
}
|
|
|
|
else {
|
2009-08-31 09:55:57 +04:00
|
|
|
return make_singleton_class(obj);
|
2002-09-03 09:20:14 +04:00
|
|
|
}
|
2002-01-10 23:18:39 +03:00
|
|
|
}
|
|
|
|
|
2009-08-29 17:39:44 +04:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* Defines a new class.
|
|
|
|
* \param id ignored
|
|
|
|
* \param super A class from which the new class will derive. NULL means \c Object class.
|
|
|
|
* \return the created class
|
|
|
|
* \throw TypeError if super is not a \c Class object.
|
|
|
|
*
|
|
|
|
* \note the returned class will not be associated with \a id.
|
|
|
|
* You must explicitly set a class name if necessary.
|
|
|
|
*/
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_define_class_id(ID id, VALUE super)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
if (!super) super = rb_cObject;
|
|
|
|
klass = rb_class_new(super);
|
2002-01-10 23:18:39 +03:00
|
|
|
rb_make_metaclass(klass, RBASIC(super)->klass);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
return klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2009-08-29 17:39:44 +04:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* Calls Class#inherited.
|
|
|
|
* \param super A class which will be called #inherited.
|
|
|
|
* NULL means Object class.
|
|
|
|
* \param klass A Class object which derived from \a super
|
|
|
|
* \return the value \c Class#inherited's returns
|
|
|
|
* \pre Each of \a super and \a klass must be a \c Class object.
|
|
|
|
*/
|
2002-01-10 23:18:39 +03:00
|
|
|
VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_class_inherited(VALUE super, VALUE klass)
|
2002-01-10 23:18:39 +03:00
|
|
|
{
|
2008-06-09 13:25:32 +04:00
|
|
|
ID inherited;
|
2002-01-16 05:20:25 +03:00
|
|
|
if (!super) super = rb_cObject;
|
2008-06-09 13:25:32 +04:00
|
|
|
CONST_ID(inherited, "inherited");
|
|
|
|
return rb_funcall(super, inherited, 1, klass);
|
2002-01-10 23:18:39 +03:00
|
|
|
}
|
|
|
|
|
2009-08-29 17:39:44 +04:00
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* Defines a top-level class.
|
|
|
|
* \param name name of the class
|
2010-05-29 22:51:39 +04:00
|
|
|
* \param super a class from which the new class will derive.
|
2009-08-29 17:39:44 +04:00
|
|
|
* NULL means \c Object class.
|
|
|
|
* \return the created class
|
2010-05-29 22:51:39 +04:00
|
|
|
* \throw TypeError if the constant name \a name is already taken but
|
2009-08-29 17:39:44 +04:00
|
|
|
* the constant is not a \c Class.
|
|
|
|
* \throw NameError if the class is already defined but the class can not
|
|
|
|
* be reopened because its superclass is not \a super.
|
|
|
|
* \post top-level constant named \a name refers the returned class.
|
|
|
|
*
|
|
|
|
* \note if a class named \a name is already defined and its superclass is
|
|
|
|
* \a super, the function just returns the defined class.
|
|
|
|
*/
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_define_class(const char *name, VALUE super)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
ID id;
|
|
|
|
|
|
|
|
id = rb_intern(name);
|
2001-05-02 08:22:21 +04:00
|
|
|
if (rb_const_defined(rb_cObject, id)) {
|
|
|
|
klass = rb_const_get(rb_cObject, id);
|
2011-09-29 15:07:45 +04:00
|
|
|
if (!RB_TYPE_P(klass, T_CLASS)) {
|
2001-12-18 11:47:06 +03:00
|
|
|
rb_raise(rb_eTypeError, "%s is not a class", name);
|
|
|
|
}
|
2007-09-28 10:21:46 +04:00
|
|
|
if (rb_class_real(RCLASS_SUPER(klass)) != super) {
|
2010-01-09 22:54:38 +03:00
|
|
|
rb_raise(rb_eTypeError, "superclass mismatch for class %s", name);
|
2001-12-18 11:47:06 +03:00
|
|
|
}
|
|
|
|
return klass;
|
2001-05-02 08:22:21 +04:00
|
|
|
}
|
2002-02-17 17:44:14 +03:00
|
|
|
if (!super) {
|
|
|
|
rb_warn("no super class for `%s', Object assumed", name);
|
|
|
|
}
|
1998-01-16 15:19:22 +03:00
|
|
|
klass = rb_define_class_id(id, super);
|
2013-10-11 22:27:18 +04:00
|
|
|
rb_vm_add_root_module(id, klass);
|
2004-01-19 12:19:31 +03:00
|
|
|
rb_name_class(klass, id);
|
2003-07-01 05:36:25 +04:00
|
|
|
rb_const_set(rb_cObject, id, klass);
|
2003-01-07 10:36:40 +03:00
|
|
|
rb_class_inherited(super, klass);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
return klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2009-08-29 17:39:44 +04:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* Defines a class under the namespace of \a outer.
|
|
|
|
* \param outer a class which contains the new class.
|
|
|
|
* \param name name of the new class
|
2010-05-29 22:51:39 +04:00
|
|
|
* \param super a class from which the new class will derive.
|
2009-08-29 17:39:44 +04:00
|
|
|
* NULL means \c Object class.
|
|
|
|
* \return the created class
|
2010-05-29 22:51:39 +04:00
|
|
|
* \throw TypeError if the constant name \a name is already taken but
|
2009-08-29 17:39:44 +04:00
|
|
|
* the constant is not a \c Class.
|
|
|
|
* \throw NameError if the class is already defined but the class can not
|
|
|
|
* be reopened because its superclass is not \a super.
|
|
|
|
* \post top-level constant named \a name refers the returned class.
|
|
|
|
*
|
|
|
|
* \note if a class named \a name is already defined and its superclass is
|
|
|
|
* \a super, the function just returns the defined class.
|
|
|
|
*/
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_define_class_under(VALUE outer, const char *name, VALUE super)
|
2009-08-12 10:32:21 +04:00
|
|
|
{
|
|
|
|
return rb_define_class_id_under(outer, rb_intern(name), super);
|
|
|
|
}
|
|
|
|
|
2009-08-29 17:39:44 +04:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* Defines a class under the namespace of \a outer.
|
|
|
|
* \param outer a class which contains the new class.
|
|
|
|
* \param id name of the new class
|
2010-05-29 22:51:39 +04:00
|
|
|
* \param super a class from which the new class will derive.
|
2009-08-29 17:39:44 +04:00
|
|
|
* NULL means \c Object class.
|
|
|
|
* \return the created class
|
2010-05-29 22:51:39 +04:00
|
|
|
* \throw TypeError if the constant name \a name is already taken but
|
2009-08-29 17:39:44 +04:00
|
|
|
* the constant is not a \c Class.
|
|
|
|
* \throw NameError if the class is already defined but the class can not
|
|
|
|
* be reopened because its superclass is not \a super.
|
|
|
|
* \post top-level constant named \a name refers the returned class.
|
|
|
|
*
|
|
|
|
* \note if a class named \a name is already defined and its superclass is
|
|
|
|
* \a super, the function just returns the defined class.
|
|
|
|
*/
|
2009-08-12 10:32:21 +04:00
|
|
|
VALUE
|
|
|
|
rb_define_class_id_under(VALUE outer, ID id, VALUE super)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2001-05-02 08:22:21 +04:00
|
|
|
if (rb_const_defined_at(outer, id)) {
|
2003-06-20 11:11:44 +04:00
|
|
|
klass = rb_const_get_at(outer, id);
|
2011-09-29 15:07:45 +04:00
|
|
|
if (!RB_TYPE_P(klass, T_CLASS)) {
|
2014-11-25 21:44:22 +03:00
|
|
|
rb_raise(rb_eTypeError, "%"PRIsVALUE" is not a class", rb_id2str(id));
|
2001-12-18 11:47:06 +03:00
|
|
|
}
|
2007-09-28 10:21:46 +04:00
|
|
|
if (rb_class_real(RCLASS_SUPER(klass)) != super) {
|
2015-06-28 06:07:37 +03:00
|
|
|
rb_raise(rb_eTypeError, "superclass mismatch for class %"PRIsVALUE"",
|
|
|
|
rb_id2str(id));
|
2001-12-18 11:47:06 +03:00
|
|
|
}
|
|
|
|
return klass;
|
2001-05-02 08:22:21 +04:00
|
|
|
}
|
2002-02-17 17:44:14 +03:00
|
|
|
if (!super) {
|
2014-11-25 21:44:22 +03:00
|
|
|
rb_warn("no super class for `%"PRIsVALUE"::%"PRIsVALUE"', Object assumed",
|
|
|
|
rb_class_path(outer), rb_id2str(id));
|
2002-02-17 17:44:14 +03:00
|
|
|
}
|
1998-01-16 15:19:22 +03:00
|
|
|
klass = rb_define_class_id(id, super);
|
2009-08-12 10:32:21 +04:00
|
|
|
rb_set_class_path_string(klass, outer, rb_id2str(id));
|
2002-01-10 23:18:39 +03:00
|
|
|
rb_const_set(outer, id, klass);
|
2003-01-07 10:36:40 +03:00
|
|
|
rb_class_inherited(super, klass);
|
2010-10-17 05:40:22 +04:00
|
|
|
rb_gc_register_mark_object(klass);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
return klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_module_new(void)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2007-09-28 10:21:46 +04:00
|
|
|
VALUE mdl = class_alloc(T_MODULE, rb_cModule);
|
2013-12-03 12:11:07 +04:00
|
|
|
RCLASS_M_TBL_INIT(mdl);
|
1998-01-16 15:13:05 +03:00
|
|
|
return (VALUE)mdl;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_define_module_id(ID id)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
1999-01-20 07:59:39 +03:00
|
|
|
VALUE mdl;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
mdl = rb_module_new();
|
1998-01-16 15:13:05 +03:00
|
|
|
rb_name_class(mdl, id);
|
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
return mdl;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_define_module(const char *name)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
VALUE module;
|
|
|
|
ID id;
|
|
|
|
|
|
|
|
id = rb_intern(name);
|
2001-05-02 08:22:21 +04:00
|
|
|
if (rb_const_defined(rb_cObject, id)) {
|
|
|
|
module = rb_const_get(rb_cObject, id);
|
2011-09-29 15:07:45 +04:00
|
|
|
if (RB_TYPE_P(module, T_MODULE))
|
2001-05-02 08:22:21 +04:00
|
|
|
return module;
|
2003-01-31 07:00:17 +03:00
|
|
|
rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module));
|
2001-05-02 08:22:21 +04:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
module = rb_define_module_id(id);
|
2013-10-11 22:27:18 +04:00
|
|
|
rb_vm_add_root_module(id, module);
|
2003-07-01 05:36:25 +04:00
|
|
|
rb_const_set(rb_cObject, id, module);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
return module;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_define_module_under(VALUE outer, const char *name)
|
2009-08-12 10:32:21 +04:00
|
|
|
{
|
|
|
|
return rb_define_module_id_under(outer, rb_intern(name));
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
2009-08-12 10:54:45 +04:00
|
|
|
rb_define_module_id_under(VALUE outer, ID id)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
VALUE module;
|
|
|
|
|
2002-01-07 08:27:01 +03:00
|
|
|
if (rb_const_defined_at(outer, id)) {
|
2003-06-20 11:11:44 +04:00
|
|
|
module = rb_const_get_at(outer, id);
|
2011-09-29 15:07:45 +04:00
|
|
|
if (RB_TYPE_P(module, T_MODULE))
|
2001-05-02 08:22:21 +04:00
|
|
|
return module;
|
|
|
|
rb_raise(rb_eTypeError, "%s::%s is not a module",
|
2003-01-31 07:00:17 +03:00
|
|
|
rb_class2name(outer), rb_obj_classname(module));
|
2001-05-02 08:22:21 +04:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
module = rb_define_module_id(id);
|
1999-12-14 09:50:43 +03:00
|
|
|
rb_const_set(outer, id, module);
|
2009-08-12 10:54:45 +04:00
|
|
|
rb_set_class_path_string(module, outer, rb_id2str(id));
|
2010-10-17 05:40:22 +04:00
|
|
|
rb_gc_register_mark_object(module);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
return module;
|
|
|
|
}
|
|
|
|
|
2012-08-02 15:34:19 +04:00
|
|
|
VALUE
|
|
|
|
rb_include_class_new(VALUE module, VALUE super)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2007-09-28 10:21:46 +04:00
|
|
|
VALUE klass = class_alloc(T_ICLASS, rb_cClass);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2002-07-11 12:22:18 +04:00
|
|
|
if (BUILTIN_TYPE(module) == T_ICLASS) {
|
|
|
|
module = RBASIC(module)->klass;
|
|
|
|
}
|
2007-09-28 10:21:46 +04:00
|
|
|
if (!RCLASS_IV_TBL(module)) {
|
|
|
|
RCLASS_IV_TBL(module) = st_init_numtable();
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
2010-10-26 21:27:21 +04:00
|
|
|
if (!RCLASS_CONST_TBL(module)) {
|
|
|
|
RCLASS_CONST_TBL(module) = st_init_numtable();
|
|
|
|
}
|
2007-09-28 10:21:46 +04:00
|
|
|
RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
|
2010-10-26 21:27:21 +04:00
|
|
|
RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module);
|
2013-06-23 00:48:35 +04:00
|
|
|
|
2015-03-06 01:20:14 +03:00
|
|
|
RCLASS_M_TBL(OBJ_WB_UNPROTECT(klass)) =
|
|
|
|
RCLASS_M_TBL(OBJ_WB_UNPROTECT(RCLASS_ORIGIN(module))); /* TODO: unprotected? */
|
2013-06-23 00:48:35 +04:00
|
|
|
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RCLASS_SET_SUPER(klass, super);
|
2011-09-29 15:07:45 +04:00
|
|
|
if (RB_TYPE_P(module, T_ICLASS)) {
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RBASIC_SET_CLASS(klass, RBASIC(module)->klass);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
else {
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RBASIC_SET_CLASS(klass, module);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2001-08-14 12:13:31 +04:00
|
|
|
OBJ_INFECT(klass, module);
|
|
|
|
OBJ_INFECT(klass, super);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
return (VALUE)klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2015-01-19 16:08:28 +03:00
|
|
|
static int include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super);
|
2012-06-27 16:31:17 +04:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
void
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_include_module(VALUE klass, VALUE module)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2001-03-28 12:43:25 +04:00
|
|
|
int changed = 0;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2001-05-02 08:22:21 +04:00
|
|
|
rb_frozen_class_p(klass);
|
2009-02-22 17:23:33 +03:00
|
|
|
|
2011-09-29 15:07:45 +04:00
|
|
|
if (!RB_TYPE_P(module, T_MODULE)) {
|
1998-01-16 15:13:05 +03:00
|
|
|
Check_Type(module, T_MODULE);
|
|
|
|
}
|
|
|
|
|
2001-08-14 12:13:31 +04:00
|
|
|
OBJ_INFECT(klass, module);
|
2012-06-27 16:31:17 +04:00
|
|
|
|
2015-01-19 16:08:28 +03:00
|
|
|
changed = include_modules_at(klass, RCLASS_ORIGIN(klass), module, TRUE);
|
2012-07-02 12:06:37 +04:00
|
|
|
if (changed < 0)
|
|
|
|
rb_raise(rb_eArgError, "cyclic include detected");
|
2012-06-27 16:31:17 +04:00
|
|
|
}
|
|
|
|
|
2015-08-12 11:43:55 +03:00
|
|
|
static enum rb_id_table_iterator_result
|
|
|
|
add_refined_method_entry_i(ID key, VALUE value, void *data)
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 17:08:41 +04:00
|
|
|
{
|
2015-08-12 11:43:55 +03:00
|
|
|
rb_add_refined_method_entry((VALUE)data, key);
|
2015-08-12 11:59:27 +03:00
|
|
|
return ID_TABLE_CONTINUE;
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 17:08:41 +04:00
|
|
|
}
|
|
|
|
|
2012-06-27 16:31:17 +04:00
|
|
|
static int
|
2015-01-19 16:08:28 +03:00
|
|
|
include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super)
|
2012-06-27 16:31:17 +04:00
|
|
|
{
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
|
|
|
VALUE p, iclass;
|
|
|
|
int method_changed = 0, constant_changed = 0;
|
2015-08-12 11:43:55 +03:00
|
|
|
struct rb_id_table *const klass_m_tbl = RCLASS_M_TBL(RCLASS_ORIGIN(klass));
|
2012-06-27 16:31:17 +04:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
while (module) {
|
2009-07-18 12:05:32 +04:00
|
|
|
int superclass_seen = FALSE;
|
2006-11-07 11:56:18 +03:00
|
|
|
|
2012-07-02 12:06:37 +04:00
|
|
|
if (RCLASS_ORIGIN(module) != module)
|
|
|
|
goto skip;
|
2013-02-14 06:08:31 +04:00
|
|
|
if (klass_m_tbl && klass_m_tbl == RCLASS_M_TBL(module))
|
2012-07-02 12:06:37 +04:00
|
|
|
return -1;
|
2009-03-13 08:55:13 +03:00
|
|
|
/* ignore if the module included already in superclasses */
|
|
|
|
for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) {
|
2015-01-19 16:08:28 +03:00
|
|
|
int type = BUILTIN_TYPE(p);
|
|
|
|
if (type == T_ICLASS) {
|
2015-03-06 01:20:14 +03:00
|
|
|
if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) {
|
2009-03-13 08:55:13 +03:00
|
|
|
if (!superclass_seen) {
|
|
|
|
c = p; /* move insertion point */
|
|
|
|
}
|
|
|
|
goto skip;
|
|
|
|
}
|
2015-01-19 16:08:28 +03:00
|
|
|
}
|
|
|
|
else if (type == T_CLASS) {
|
|
|
|
if (!search_super) break;
|
2009-07-18 12:05:32 +04:00
|
|
|
superclass_seen = TRUE;
|
2009-03-13 08:55:13 +03:00
|
|
|
}
|
|
|
|
}
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
|
|
|
iclass = rb_include_class_new(module, RCLASS_SUPER(c));
|
|
|
|
c = RCLASS_SET_SUPER(c, iclass);
|
|
|
|
|
2015-01-19 16:08:28 +03:00
|
|
|
{
|
|
|
|
VALUE m = module;
|
|
|
|
if (BUILTIN_TYPE(m) == T_ICLASS) m = RBASIC(m)->klass;
|
|
|
|
rb_module_add_to_subclasses_list(m, iclass);
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
|
|
|
}
|
|
|
|
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 17:08:41 +04:00
|
|
|
if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
|
|
|
|
VALUE refined_class =
|
|
|
|
rb_refinement_module_get_refined_class(klass);
|
|
|
|
|
2015-08-12 11:43:55 +03:00
|
|
|
rb_id_table_foreach(RMODULE_M_TBL(module), add_refined_method_entry_i, (void *)refined_class);
|
* fix the behavior when a module is included into a refinement.
This change is a little tricky, so it might be better to prohibit
module inclusion to refinements.
* include/ruby/ruby.h (RMODULE_INCLUDED_INTO_REFINEMENT): new flag
to represent that a module (iclass) is included into a refinement.
* class.c (include_modules_at): set RMODULE_INCLUDED_INTO_REFINEMENT
if klass is a refinement.
* eval.c (rb_mod_refine): set the superclass of a refinement to the
refined class for super.
* eval.c (rb_using_refinement): skip the above superclass (the
refined class) when creating iclasses for refinements. Otherwise,
`using Refinement1; using Refinement2' creates iclasses:
<Refinement2> -> <RefinedClass> -> <Refinement1> -> RefinedClass,
where <Module> is an iclass for Module, so RefinedClass is
searched before Refinement1. The correct iclasses should be
<Refinement2> -> <Refinement1> -> RefinedClass.
* vm_insnhelper.c (vm_search_normal_superclass): if klass is an
iclass for a refinement, use the refinement's superclass instead
of the iclass's superclass. Otherwise, multiple refinements are
searched by super. For example, if a refinement Refinement2
includes a module M (i.e., Refinement2 -> <M> -> RefinedClass,
and if refinements iclasses are <Refinement2> -> <M>' ->
<Refinement1> -> RefinedClass, then super in <Refinement2> should
use Refinement2's superclass <M> instead of <Refinement2>'s
superclass <M>'.
* vm_insnhelper.c (vm_search_super_method): do not raise a
NotImplementError if current_defind_class is a module included
into a refinement. Because of the change of
vm_search_normal_superclass(), the receiver might not be an
instance of the module('s iclass).
* test/ruby/test_refinement.rb: related test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38298 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-10 20:05:45 +04:00
|
|
|
FL_SET(c, RMODULE_INCLUDED_INTO_REFINEMENT);
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 17:08:41 +04:00
|
|
|
}
|
2015-08-12 11:43:55 +03:00
|
|
|
if (RMODULE_M_TBL(module) && rb_id_table_size(RMODULE_M_TBL(module))) method_changed = 1;
|
|
|
|
if (RMODULE_CONST_TBL(module) && RMODULE_CONST_TBL(module)->num_entries) constant_changed = 1;
|
2006-11-07 11:56:18 +03:00
|
|
|
skip:
|
2007-09-28 10:21:46 +04:00
|
|
|
module = RCLASS_SUPER(module);
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
2012-06-27 16:31:17 +04:00
|
|
|
|
* insns.def, vm.c, vm_insnhelper.c, vm_insnhelper.h, vm_method.c: split
ruby_vm_global_state_version into two separate counters - one for the
global method state and one for the global constant state. This means
changes to constants do not affect method caches, and changes to
methods do not affect constant caches. In particular, this means
inclusions of modules containing constants no longer globally
invalidate the method cache.
* class.c, eval.c, include/ruby/intern.h, insns.def, vm.c, vm_method.c:
rename rb_clear_cache_by_class to rb_clear_method_cache_by_class
* class.c, include/ruby/intern.h, variable.c, vm_method.c: add
rb_clear_constant_cache
* compile.c, vm_core.h, vm_insnhelper.c: rename vmstat field in
rb_call_info_struct to method_state
* vm_method.c: rename vmstat field in struct cache_entry to method_state
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43455 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-10-29 04:52:38 +04:00
|
|
|
if (method_changed) rb_clear_method_cache_by_class(klass);
|
|
|
|
if (constant_changed) rb_clear_constant_cache();
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
|
|
|
|
|
|
|
return method_changed;
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
|
|
|
|
2015-08-12 11:43:55 +03:00
|
|
|
static enum rb_id_table_iterator_result
|
|
|
|
move_refined_method(ID key, VALUE value, void *data)
|
2012-12-12 13:35:50 +04:00
|
|
|
{
|
|
|
|
rb_method_entry_t *me = (rb_method_entry_t *) value;
|
2015-08-12 11:43:55 +03:00
|
|
|
struct rb_id_table *tbl = (struct rb_id_table *) data;
|
2012-12-12 13:35:50 +04:00
|
|
|
|
|
|
|
if (me->def->type == VM_METHOD_TYPE_REFINED) {
|
2015-06-04 01:27:51 +03:00
|
|
|
if (me->def->body.refined.orig_me) {
|
2015-06-04 19:02:01 +03:00
|
|
|
const rb_method_entry_t *orig_me = me->def->body.refined.orig_me, *new_me;
|
2015-06-18 11:01:13 +03:00
|
|
|
RB_OBJ_WRITE(me, &me->def->body.refined.orig_me, NULL);
|
2015-06-02 07:20:30 +03:00
|
|
|
new_me = rb_method_entry_clone(me);
|
2015-08-12 11:43:55 +03:00
|
|
|
rb_id_table_insert(tbl, key, (VALUE)new_me);
|
2015-06-02 07:20:30 +03:00
|
|
|
rb_method_entry_copy(me, orig_me);
|
2012-12-12 13:35:50 +04:00
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
else {
|
2015-08-12 11:43:55 +03:00
|
|
|
rb_id_table_insert(tbl, key, (VALUE)me);
|
2015-08-12 11:59:27 +03:00
|
|
|
return ID_TABLE_DELETE;
|
2012-12-12 13:35:50 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2015-08-12 11:59:27 +03:00
|
|
|
return ID_TABLE_CONTINUE;
|
2012-12-12 13:35:50 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-27 11:48:50 +04:00
|
|
|
void
|
|
|
|
rb_prepend_module(VALUE klass, VALUE module)
|
|
|
|
{
|
2012-07-02 12:06:37 +04:00
|
|
|
VALUE origin;
|
2012-06-27 16:31:17 +04:00
|
|
|
int changed = 0;
|
2012-06-27 11:48:50 +04:00
|
|
|
|
|
|
|
rb_frozen_class_p(klass);
|
|
|
|
|
|
|
|
Check_Type(module, T_MODULE);
|
|
|
|
|
|
|
|
OBJ_INFECT(klass, module);
|
2012-07-02 12:06:37 +04:00
|
|
|
|
2012-06-27 11:48:50 +04:00
|
|
|
origin = RCLASS_ORIGIN(klass);
|
|
|
|
if (origin == klass) {
|
2012-07-02 12:06:37 +04:00
|
|
|
origin = class_alloc(T_ICLASS, klass);
|
2014-09-11 21:16:45 +04:00
|
|
|
OBJ_WB_UNPROTECT(origin); /* TODO: conservative shading. Need more survey. */
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RCLASS_SET_SUPER(origin, RCLASS_SUPER(klass));
|
|
|
|
RCLASS_SET_SUPER(klass, origin);
|
2015-03-11 12:15:20 +03:00
|
|
|
RCLASS_SET_ORIGIN(klass, origin);
|
2015-03-06 01:20:14 +03:00
|
|
|
RCLASS_M_TBL(origin) = RCLASS_M_TBL(klass);
|
2013-12-03 12:11:07 +04:00
|
|
|
RCLASS_M_TBL_INIT(klass);
|
2015-08-12 11:43:55 +03:00
|
|
|
rb_id_table_foreach(RCLASS_M_TBL(origin), move_refined_method, (void *)RCLASS_M_TBL(klass));
|
2012-06-27 11:48:50 +04:00
|
|
|
}
|
2015-01-19 16:08:28 +03:00
|
|
|
changed = include_modules_at(klass, klass, module, FALSE);
|
2012-07-02 12:06:37 +04:00
|
|
|
if (changed < 0)
|
|
|
|
rb_raise(rb_eArgError, "cyclic prepend detected");
|
2013-03-05 16:36:45 +04:00
|
|
|
if (changed) {
|
|
|
|
rb_vm_check_redefinition_by_prepend(klass);
|
|
|
|
}
|
2012-06-27 11:48:50 +04:00
|
|
|
}
|
|
|
|
|
2003-12-28 09:33:07 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* mod.included_modules -> array
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* Returns the list of modules included in <i>mod</i>.
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* module Mixin
|
|
|
|
* end
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* module Outer
|
|
|
|
* include Mixin
|
|
|
|
* end
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* Mixin.included_modules #=> []
|
|
|
|
* Outer.included_modules #=> [Mixin]
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_mod_included_modules(VALUE mod)
|
1998-01-16 15:19:22 +03:00
|
|
|
{
|
1999-01-20 07:59:39 +03:00
|
|
|
VALUE ary = rb_ary_new();
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE p;
|
2013-05-08 17:47:11 +04:00
|
|
|
VALUE origin = RCLASS_ORIGIN(mod);
|
1998-01-16 15:19:22 +03:00
|
|
|
|
2007-09-28 10:21:46 +04:00
|
|
|
for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
|
2013-05-08 17:47:11 +04:00
|
|
|
if (p != origin && BUILTIN_TYPE(p) == T_ICLASS) {
|
2013-05-08 20:05:50 +04:00
|
|
|
VALUE m = RBASIC(p)->klass;
|
|
|
|
if (RB_TYPE_P(m, T_MODULE))
|
|
|
|
rb_ary_push(ary, m);
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
|
2003-12-28 09:33:07 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:07:33 +04:00
|
|
|
* mod.include?(module) -> true or false
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* Returns <code>true</code> if <i>module</i> is included in
|
|
|
|
* <i>mod</i> or one of <i>mod</i>'s ancestors.
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* module A
|
|
|
|
* end
|
|
|
|
* class B
|
|
|
|
* include A
|
|
|
|
* end
|
|
|
|
* class C < B
|
|
|
|
* end
|
|
|
|
* B.include?(A) #=> true
|
|
|
|
* C.include?(A) #=> true
|
|
|
|
* A.include?(A) #=> false
|
|
|
|
*/
|
|
|
|
|
2001-07-24 13:07:33 +04:00
|
|
|
VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_mod_include_p(VALUE mod, VALUE mod2)
|
2001-07-24 13:07:33 +04:00
|
|
|
{
|
|
|
|
VALUE p;
|
|
|
|
|
|
|
|
Check_Type(mod2, T_MODULE);
|
2007-09-28 10:21:46 +04:00
|
|
|
for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
|
2001-07-24 13:07:33 +04:00
|
|
|
if (BUILTIN_TYPE(p) == T_ICLASS) {
|
|
|
|
if (RBASIC(p)->klass == mod2) return Qtrue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2003-12-28 09:33:07 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* mod.ancestors -> array
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2014-07-05 09:13:28 +04:00
|
|
|
* Returns a list of modules included/prepended in <i>mod</i>
|
|
|
|
* (including <i>mod</i> itself).
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* module Mod
|
|
|
|
* include Math
|
|
|
|
* include Comparable
|
2014-07-05 09:13:28 +04:00
|
|
|
* prepend Enumerable
|
2003-12-28 09:33:07 +03:00
|
|
|
* end
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2014-07-05 09:13:28 +04:00
|
|
|
* Mod.ancestors #=> [Enumerable, Mod, Comparable, Math]
|
|
|
|
* Math.ancestors #=> [Math]
|
|
|
|
* Enumerable.ancestors #=> [Enumerable]
|
2003-12-28 09:33:07 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_mod_ancestors(VALUE mod)
|
1998-01-16 15:19:22 +03:00
|
|
|
{
|
2003-08-07 01:50:06 +04:00
|
|
|
VALUE p, ary = rb_ary_new();
|
1998-01-16 15:19:22 +03:00
|
|
|
|
2012-07-02 12:06:37 +04:00
|
|
|
for (p = mod; p; p = RCLASS_SUPER(p)) {
|
|
|
|
if (BUILTIN_TYPE(p) == T_ICLASS) {
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_ary_push(ary, RBASIC(p)->klass);
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
2012-07-02 12:06:37 +04:00
|
|
|
else if (p == RCLASS_ORIGIN(p)) {
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_ary_push(ary, p);
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2015-06-06 09:07:06 +03:00
|
|
|
ins_methods_push(ID name, rb_method_visibility_t visi, VALUE ary, rb_method_visibility_t expected_visi)
|
2003-05-02 12:24:43 +04:00
|
|
|
{
|
2015-06-06 09:07:06 +03:00
|
|
|
if (visi == METHOD_VISI_UNDEF) return ST_CONTINUE;
|
2006-12-31 18:02:22 +03:00
|
|
|
|
2015-06-06 09:07:06 +03:00
|
|
|
switch (expected_visi) {
|
2015-06-03 04:39:16 +03:00
|
|
|
case METHOD_VISI_UNDEF:
|
2015-06-06 09:07:06 +03:00
|
|
|
if (visi != METHOD_VISI_PRIVATE) rb_ary_push(ary, ID2SYM(name));
|
|
|
|
break;
|
2015-06-03 04:39:16 +03:00
|
|
|
case METHOD_VISI_PRIVATE:
|
|
|
|
case METHOD_VISI_PROTECTED:
|
|
|
|
case METHOD_VISI_PUBLIC:
|
2015-06-06 09:07:06 +03:00
|
|
|
if (visi == expected_visi) rb_ary_push(ary, ID2SYM(name));
|
2003-05-02 12:24:43 +04:00
|
|
|
break;
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2011-06-04 07:49:50 +04:00
|
|
|
ins_methods_i(st_data_t name, st_data_t type, st_data_t ary)
|
1999-01-20 07:59:39 +03:00
|
|
|
{
|
2015-06-06 09:07:06 +03:00
|
|
|
return ins_methods_push((ID)name, (rb_method_visibility_t)type, (VALUE)ary, METHOD_VISI_UNDEF); /* everything but private */
|
2003-05-02 12:24:43 +04:00
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2003-05-02 12:24:43 +04:00
|
|
|
static int
|
2011-06-04 07:49:50 +04:00
|
|
|
ins_methods_prot_i(st_data_t name, st_data_t type, st_data_t ary)
|
2003-05-02 12:24:43 +04:00
|
|
|
{
|
2015-06-06 10:01:21 +03:00
|
|
|
return ins_methods_push((ID)name, (rb_method_visibility_t)type, (VALUE)ary, METHOD_VISI_PROTECTED);
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2011-06-04 07:49:50 +04:00
|
|
|
ins_methods_priv_i(st_data_t name, st_data_t type, st_data_t ary)
|
1998-01-16 15:19:22 +03:00
|
|
|
{
|
2015-06-06 10:01:21 +03:00
|
|
|
return ins_methods_push((ID)name, (rb_method_visibility_t)type, (VALUE)ary, METHOD_VISI_PRIVATE);
|
2003-05-02 12:24:43 +04:00
|
|
|
}
|
2002-10-30 11:04:32 +03:00
|
|
|
|
2003-05-02 12:24:43 +04:00
|
|
|
static int
|
2011-06-04 07:49:50 +04:00
|
|
|
ins_methods_pub_i(st_data_t name, st_data_t type, st_data_t ary)
|
2003-05-02 12:24:43 +04:00
|
|
|
{
|
2015-06-06 10:01:21 +03:00
|
|
|
return ins_methods_push((ID)name, (rb_method_visibility_t)type, (VALUE)ary, METHOD_VISI_PUBLIC);
|
2002-10-30 11:04:32 +03:00
|
|
|
}
|
|
|
|
|
2015-02-04 10:45:29 +03:00
|
|
|
struct method_entry_arg {
|
|
|
|
st_table *list;
|
|
|
|
int recur;
|
|
|
|
};
|
|
|
|
|
2015-08-12 11:43:55 +03:00
|
|
|
static enum rb_id_table_iterator_result
|
|
|
|
method_entry_i(ID key, VALUE value, void *data)
|
2002-10-30 11:04:32 +03:00
|
|
|
{
|
2011-06-04 07:49:50 +04:00
|
|
|
const rb_method_entry_t *me = (const rb_method_entry_t *)value;
|
2015-02-04 10:45:29 +03:00
|
|
|
struct method_entry_arg *arg = (struct method_entry_arg *)data;
|
2015-06-03 04:39:16 +03:00
|
|
|
rb_method_visibility_t type;
|
1998-01-16 15:19:22 +03:00
|
|
|
|
2015-06-03 22:51:38 +03:00
|
|
|
if (me->def->type == VM_METHOD_TYPE_REFINED) {
|
* method.h: introduce rb_callable_method_entry_t to remove
rb_control_frame_t::klass.
[Bug #11278], [Bug #11279]
rb_method_entry_t data belong to modules/classes.
rb_method_entry_t::owner points defined module or class.
module M
def foo; end
end
In this case, owner is M.
rb_callable_method_entry_t data belong to only classes.
For modules, MRI creates corresponding T_ICLASS internally.
rb_callable_method_entry_t can also belong to T_ICLASS.
rb_callable_method_entry_t::defined_class points T_CLASS or
T_ICLASS.
rb_method_entry_t data for classes (not for modules) are also
rb_callable_method_entry_t data because it is completely same data.
In this case, rb_method_entry_t::owner == rb_method_entry_t::defined_class.
For example, there are classes C and D, and incldues M,
class C; include M; end
class D; include M; end
then, two T_ICLASS objects for C's super class and D's super class
will be created.
When C.new.foo is called, then M#foo is searcheed and
rb_callable_method_t data is used by VM to invoke M#foo.
rb_method_entry_t data is only one for M#foo.
However, rb_callable_method_entry_t data are two (and can be more).
It is proportional to the number of including (and prepending)
classes (the number of T_ICLASS which point to the module).
Now, created rb_callable_method_entry_t are collected when
the original module M was modified. We can think it is a cache.
We need to select what kind of method entry data is needed.
To operate definition, then you need to use rb_method_entry_t.
You can access them by the following functions.
* rb_method_entry(VALUE klass, ID id);
* rb_method_entry_with_refinements(VALUE klass, ID id);
* rb_method_entry_without_refinements(VALUE klass, ID id);
* rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me);
To invoke methods, then you need to use rb_callable_method_entry_t
which you can get by the following APIs corresponding to the
above listed functions.
* rb_callable_method_entry(VALUE klass, ID id);
* rb_callable_method_entry_with_refinements(VALUE klass, ID id);
* rb_callable_method_entry_without_refinements(VALUE klass, ID id);
* rb_resolve_refined_method_callable(VALUE refinements, const rb_callable_method_entry_t *me);
VM pushes rb_callable_method_entry_t, so that rb_vm_frame_method_entry()
returns rb_callable_method_entry_t.
You can check a super class of current method by
rb_callable_method_entry_t::defined_class.
* method.h: renamed from rb_method_entry_t::klass to
rb_method_entry_t::owner.
* internal.h: add rb_classext_struct::callable_m_tbl to cache
rb_callable_method_entry_t data.
We need to consider abotu this field again because it is only
active for T_ICLASS.
* class.c (method_entry_i): ditto.
* class.c (rb_define_attr): rb_method_entry() does not takes
defiend_class_ptr.
* gc.c (mark_method_entry): mark RCLASS_CALLABLE_M_TBL() for T_ICLASS.
* cont.c (fiber_init): rb_control_frame_t::klass is removed.
* proc.c: fix `struct METHOD' data structure because
rb_callable_method_t has all information.
* vm_core.h: remove several fields.
* rb_control_frame_t::klass.
* rb_block_t::klass.
And catch up changes.
* eval.c: catch up changes.
* gc.c: ditto.
* insns.def: ditto.
* vm.c: ditto.
* vm_args.c: ditto.
* vm_backtrace.c: ditto.
* vm_dump.c: ditto.
* vm_eval.c: ditto.
* vm_insnhelper.c: ditto.
* vm_method.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-07-03 14:24:50 +03:00
|
|
|
VALUE owner = me->owner;
|
|
|
|
me = rb_resolve_refined_method(Qnil, me);
|
2015-08-12 11:59:27 +03:00
|
|
|
if (!me) return ID_TABLE_CONTINUE;
|
|
|
|
if (!arg->recur && me->owner != owner) return ID_TABLE_CONTINUE;
|
2013-09-10 07:39:31 +04:00
|
|
|
}
|
2015-02-04 10:45:29 +03:00
|
|
|
if (!st_lookup(arg->list, key, 0)) {
|
2009-08-28 06:45:41 +04:00
|
|
|
if (UNDEFINED_METHOD_ENTRY_P(me)) {
|
2015-06-03 04:39:16 +03:00
|
|
|
type = METHOD_VISI_UNDEF; /* none */
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
|
|
|
else {
|
2015-06-06 13:19:48 +03:00
|
|
|
type = METHOD_ENTRY_VISI(me);
|
2006-12-31 18:02:22 +03:00
|
|
|
}
|
2015-06-05 16:39:59 +03:00
|
|
|
st_add_direct(arg->list, key, (st_data_t)type);
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
2015-08-12 11:59:27 +03:00
|
|
|
return ID_TABLE_CONTINUE;
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
|
|
|
|
2003-06-25 11:12:10 +04:00
|
|
|
static VALUE
|
2014-06-18 10:16:39 +04:00
|
|
|
class_instance_method_list(int argc, const VALUE *argv, VALUE mod, int obj, int (*func) (st_data_t, st_data_t, st_data_t))
|
1998-01-16 15:19:22 +03:00
|
|
|
{
|
2003-06-26 16:34:51 +04:00
|
|
|
VALUE ary;
|
2012-06-28 04:39:52 +04:00
|
|
|
int recur, prepended = 0;
|
2015-02-04 10:45:29 +03:00
|
|
|
struct method_entry_arg me_arg;
|
1998-01-16 15:19:22 +03:00
|
|
|
|
2003-05-02 20:11:48 +04:00
|
|
|
if (argc == 0) {
|
2009-07-18 12:05:32 +04:00
|
|
|
recur = TRUE;
|
2003-05-02 20:11:48 +04:00
|
|
|
}
|
2003-06-26 16:34:51 +04:00
|
|
|
else {
|
|
|
|
VALUE r;
|
|
|
|
rb_scan_args(argc, argv, "01", &r);
|
|
|
|
recur = RTEST(r);
|
|
|
|
}
|
|
|
|
|
2012-06-28 04:39:52 +04:00
|
|
|
if (!recur && RCLASS_ORIGIN(mod) != mod) {
|
|
|
|
mod = RCLASS_ORIGIN(mod);
|
|
|
|
prepended = 1;
|
|
|
|
}
|
|
|
|
|
2015-02-04 10:45:29 +03:00
|
|
|
me_arg.list = st_init_numtable();
|
|
|
|
me_arg.recur = recur;
|
2007-09-28 10:21:46 +04:00
|
|
|
for (; mod; mod = RCLASS_SUPER(mod)) {
|
2015-08-12 11:43:55 +03:00
|
|
|
if (RCLASS_M_TBL(mod)) rb_id_table_foreach(RCLASS_M_TBL(mod), method_entry_i, &me_arg);
|
2012-06-28 04:39:52 +04:00
|
|
|
if (BUILTIN_TYPE(mod) == T_ICLASS && !prepended) continue;
|
2010-06-17 20:58:25 +04:00
|
|
|
if (obj && FL_TEST(mod, FL_SINGLETON)) continue;
|
2003-06-26 16:34:51 +04:00
|
|
|
if (!recur) break;
|
|
|
|
}
|
|
|
|
ary = rb_ary_new();
|
2015-02-04 10:45:29 +03:00
|
|
|
st_foreach(me_arg.list, func, ary);
|
|
|
|
st_free_table(me_arg.list);
|
2003-06-26 16:34:51 +04:00
|
|
|
|
|
|
|
return ary;
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
|
|
|
|
2003-12-28 09:33:07 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:07:33 +04:00
|
|
|
* mod.instance_methods(include_super=true) -> array
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2010-06-22 08:52:03 +04:00
|
|
|
* Returns an array containing the names of the public and protected instance
|
|
|
|
* methods in the receiver. For a module, these are the public and protected methods;
|
2014-05-25 04:43:14 +04:00
|
|
|
* for a class, they are the instance (not singleton) methods. If the optional
|
|
|
|
* parameter is <code>false</code>, the methods of any ancestors are not included.
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* module A
|
|
|
|
* def method1() end
|
|
|
|
* end
|
|
|
|
* class B
|
2014-05-25 04:43:14 +04:00
|
|
|
* include A
|
2003-12-28 09:33:07 +03:00
|
|
|
* def method2() end
|
|
|
|
* end
|
|
|
|
* class C < B
|
|
|
|
* def method3() end
|
|
|
|
* end
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2014-05-25 04:43:14 +04:00
|
|
|
* A.instance_methods(false) #=> [:method1]
|
|
|
|
* B.instance_methods(false) #=> [:method2]
|
|
|
|
* B.instance_methods(true).include?(:method1) #=> true
|
|
|
|
* C.instance_methods(false) #=> [:method3]
|
|
|
|
* C.instance_methods.include?(:method2) #=> true
|
2003-12-28 09:33:07 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE
|
2014-06-18 10:16:39 +04:00
|
|
|
rb_class_instance_methods(int argc, const VALUE *argv, VALUE mod)
|
1999-01-20 07:59:39 +03:00
|
|
|
{
|
2010-06-17 20:58:25 +04:00
|
|
|
return class_instance_method_list(argc, argv, mod, 0, ins_methods_i);
|
2003-06-25 11:12:10 +04:00
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2003-12-28 09:33:07 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:07:33 +04:00
|
|
|
* mod.protected_instance_methods(include_super=true) -> array
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* Returns a list of the protected instance methods defined in
|
2014-05-25 04:43:14 +04:00
|
|
|
* <i>mod</i>. If the optional parameter is <code>false</code>, the
|
|
|
|
* methods of any ancestors are not included.
|
2003-12-28 09:33:07 +03:00
|
|
|
*/
|
|
|
|
|
2003-06-25 11:12:10 +04:00
|
|
|
VALUE
|
2014-06-18 10:16:39 +04:00
|
|
|
rb_class_protected_instance_methods(int argc, const VALUE *argv, VALUE mod)
|
2003-06-25 11:12:10 +04:00
|
|
|
{
|
2010-06-17 20:58:25 +04:00
|
|
|
return class_instance_method_list(argc, argv, mod, 0, ins_methods_prot_i);
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
|
|
|
|
2003-12-28 09:33:07 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:07:33 +04:00
|
|
|
* mod.private_instance_methods(include_super=true) -> array
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* Returns a list of the private instance methods defined in
|
2014-05-25 04:43:14 +04:00
|
|
|
* <i>mod</i>. If the optional parameter is <code>false</code>, the
|
|
|
|
* methods of any ancestors are not included.
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* module Mod
|
|
|
|
* def method1() end
|
|
|
|
* private :method1
|
|
|
|
* def method2() end
|
|
|
|
* end
|
2008-03-09 04:04:46 +03:00
|
|
|
* Mod.instance_methods #=> [:method2]
|
|
|
|
* Mod.private_instance_methods #=> [:method1]
|
2003-12-28 09:33:07 +03:00
|
|
|
*/
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
VALUE
|
2014-06-18 10:16:39 +04:00
|
|
|
rb_class_private_instance_methods(int argc, const VALUE *argv, VALUE mod)
|
1998-01-16 15:19:22 +03:00
|
|
|
{
|
2010-06-17 20:58:25 +04:00
|
|
|
return class_instance_method_list(argc, argv, mod, 0, ins_methods_priv_i);
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
|
|
|
|
2003-12-28 09:33:07 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:07:33 +04:00
|
|
|
* mod.public_instance_methods(include_super=true) -> array
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* Returns a list of the public instance methods defined in <i>mod</i>.
|
2014-05-25 04:43:14 +04:00
|
|
|
* If the optional parameter is <code>false</code>, the methods of
|
|
|
|
* any ancestors are not included.
|
2003-12-28 09:33:07 +03:00
|
|
|
*/
|
|
|
|
|
2002-10-30 11:04:32 +03:00
|
|
|
VALUE
|
2014-06-18 10:16:39 +04:00
|
|
|
rb_class_public_instance_methods(int argc, const VALUE *argv, VALUE mod)
|
2002-10-30 11:04:32 +03:00
|
|
|
{
|
2010-06-17 20:58:25 +04:00
|
|
|
return class_instance_method_list(argc, argv, mod, 0, ins_methods_pub_i);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2013-04-24 08:47:31 +04:00
|
|
|
* obj.methods(regular=true) -> array
|
2010-06-17 20:58:25 +04:00
|
|
|
*
|
2010-06-22 08:52:03 +04:00
|
|
|
* Returns a list of the names of public and protected methods of
|
2010-06-17 20:58:25 +04:00
|
|
|
* <i>obj</i>. This will include all the methods accessible in
|
|
|
|
* <i>obj</i>'s ancestors.
|
2014-05-25 04:43:14 +04:00
|
|
|
* If the optional parameter is <code>false</code>, it
|
|
|
|
* returns an array of <i>obj<i>'s public and protected singleton methods,
|
2013-04-24 08:47:31 +04:00
|
|
|
* the array will not include methods in modules included in <i>obj</i>.
|
2010-06-17 20:58:25 +04:00
|
|
|
*
|
|
|
|
* class Klass
|
2011-03-07 11:44:45 +03:00
|
|
|
* def klass_method()
|
2010-06-17 20:58:25 +04:00
|
|
|
* end
|
|
|
|
* end
|
|
|
|
* k = Klass.new
|
2011-03-07 11:44:45 +03:00
|
|
|
* k.methods[0..9] #=> [:klass_method, :nil?, :===,
|
|
|
|
* # :==~, :!, :eql?
|
|
|
|
* # :hash, :<=>, :class, :singleton_class]
|
2014-05-25 04:43:14 +04:00
|
|
|
* k.methods.length #=> 56
|
2013-04-24 08:47:31 +04:00
|
|
|
*
|
|
|
|
* k.methods(false) #=> []
|
|
|
|
* def k.singleton_method; end
|
|
|
|
* k.methods(false) #=> [:singleton_method]
|
|
|
|
*
|
|
|
|
* module M123; def m123; end end
|
|
|
|
* k.extend M123
|
|
|
|
* k.methods(false) #=> [:singleton_method]
|
2010-06-17 20:58:25 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
VALUE
|
2014-06-18 10:16:39 +04:00
|
|
|
rb_obj_methods(int argc, const VALUE *argv, VALUE obj)
|
2010-06-17 20:58:25 +04:00
|
|
|
{
|
2014-01-25 05:55:44 +04:00
|
|
|
rb_check_arity(argc, 0, 1);
|
|
|
|
if (argc > 0 && !RTEST(argv[0])) {
|
2010-06-17 20:58:25 +04:00
|
|
|
return rb_obj_singleton_methods(argc, argv, obj);
|
|
|
|
}
|
2014-01-25 05:55:44 +04:00
|
|
|
return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_i);
|
2010-06-17 20:58:25 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* obj.protected_methods(all=true) -> array
|
|
|
|
*
|
|
|
|
* Returns the list of protected methods accessible to <i>obj</i>. If
|
|
|
|
* the <i>all</i> parameter is set to <code>false</code>, only those methods
|
|
|
|
* in the receiver will be listed.
|
|
|
|
*/
|
|
|
|
|
|
|
|
VALUE
|
2014-06-18 10:16:39 +04:00
|
|
|
rb_obj_protected_methods(int argc, const VALUE *argv, VALUE obj)
|
2010-06-17 20:58:25 +04:00
|
|
|
{
|
|
|
|
return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_prot_i);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* obj.private_methods(all=true) -> array
|
|
|
|
*
|
|
|
|
* Returns the list of private methods accessible to <i>obj</i>. If
|
|
|
|
* the <i>all</i> parameter is set to <code>false</code>, only those methods
|
|
|
|
* in the receiver will be listed.
|
|
|
|
*/
|
|
|
|
|
|
|
|
VALUE
|
2014-06-18 10:16:39 +04:00
|
|
|
rb_obj_private_methods(int argc, const VALUE *argv, VALUE obj)
|
2010-06-17 20:58:25 +04:00
|
|
|
{
|
|
|
|
return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_priv_i);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* obj.public_methods(all=true) -> array
|
|
|
|
*
|
|
|
|
* Returns the list of public methods accessible to <i>obj</i>. If
|
|
|
|
* the <i>all</i> parameter is set to <code>false</code>, only those methods
|
|
|
|
* in the receiver will be listed.
|
|
|
|
*/
|
|
|
|
|
|
|
|
VALUE
|
2014-06-18 10:16:39 +04:00
|
|
|
rb_obj_public_methods(int argc, const VALUE *argv, VALUE obj)
|
2010-06-17 20:58:25 +04:00
|
|
|
{
|
|
|
|
return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_pub_i);
|
2002-10-30 11:04:32 +03:00
|
|
|
}
|
|
|
|
|
2003-12-28 09:33:07 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:07:33 +04:00
|
|
|
* obj.singleton_methods(all=true) -> array
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* Returns an array of the names of singleton methods for <i>obj</i>.
|
|
|
|
* If the optional <i>all</i> parameter is true, the list will include
|
|
|
|
* methods in modules included in <i>obj</i>.
|
2010-06-22 08:52:03 +04:00
|
|
|
* Only public and protected singleton methods are returned.
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* module Other
|
|
|
|
* def three() end
|
|
|
|
* end
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* class Single
|
|
|
|
* def Single.four() end
|
|
|
|
* end
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* a = Single.new
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* def a.one()
|
2004-05-12 06:51:54 +04:00
|
|
|
* end
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2003-12-28 09:33:07 +03:00
|
|
|
* class << a
|
|
|
|
* include Other
|
|
|
|
* def two()
|
2004-05-12 06:51:54 +04:00
|
|
|
* end
|
2003-12-28 09:33:07 +03:00
|
|
|
* end
|
2009-02-22 17:23:33 +03:00
|
|
|
*
|
2008-03-09 04:04:46 +03:00
|
|
|
* Single.singleton_methods #=> [:four]
|
|
|
|
* a.singleton_methods(false) #=> [:two, :one]
|
|
|
|
* a.singleton_methods #=> [:two, :one, :three]
|
2003-12-28 09:33:07 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE
|
2014-06-18 10:16:39 +04:00
|
|
|
rb_obj_singleton_methods(int argc, const VALUE *argv, VALUE obj)
|
1998-01-16 15:19:22 +03:00
|
|
|
{
|
2013-03-13 10:13:08 +04:00
|
|
|
VALUE recur, ary, klass, origin;
|
2015-02-04 10:45:29 +03:00
|
|
|
struct method_entry_arg me_arg;
|
2015-08-12 11:43:55 +03:00
|
|
|
struct rb_id_table *mtbl;
|
1998-01-16 15:19:22 +03:00
|
|
|
|
2003-05-02 20:11:48 +04:00
|
|
|
if (argc == 0) {
|
2003-05-04 20:03:24 +04:00
|
|
|
recur = Qtrue;
|
2003-05-02 20:11:48 +04:00
|
|
|
}
|
2008-03-05 08:22:17 +03:00
|
|
|
else {
|
|
|
|
rb_scan_args(argc, argv, "01", &recur);
|
|
|
|
}
|
1998-01-16 15:19:22 +03:00
|
|
|
klass = CLASS_OF(obj);
|
2013-03-13 10:13:08 +04:00
|
|
|
origin = RCLASS_ORIGIN(klass);
|
2015-02-04 10:45:29 +03:00
|
|
|
me_arg.list = st_init_numtable();
|
2015-02-05 04:34:01 +03:00
|
|
|
me_arg.recur = RTEST(recur);
|
2003-08-02 00:16:53 +04:00
|
|
|
if (klass && FL_TEST(klass, FL_SINGLETON)) {
|
2015-08-12 11:43:55 +03:00
|
|
|
if ((mtbl = RCLASS_M_TBL(origin)) != 0) rb_id_table_foreach(mtbl, method_entry_i, &me_arg);
|
2007-09-28 10:21:46 +04:00
|
|
|
klass = RCLASS_SUPER(klass);
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
2003-05-06 10:51:31 +04:00
|
|
|
if (RTEST(recur)) {
|
2011-09-29 15:07:45 +04:00
|
|
|
while (klass && (FL_TEST(klass, FL_SINGLETON) || RB_TYPE_P(klass, T_ICLASS))) {
|
2015-08-12 11:43:55 +03:00
|
|
|
if (klass != origin && (mtbl = RCLASS_M_TBL(klass)) != 0) rb_id_table_foreach(mtbl, method_entry_i, &me_arg);
|
2007-09-28 10:21:46 +04:00
|
|
|
klass = RCLASS_SUPER(klass);
|
2001-05-30 13:12:34 +04:00
|
|
|
}
|
|
|
|
}
|
2003-05-02 12:24:43 +04:00
|
|
|
ary = rb_ary_new();
|
2015-02-04 10:45:29 +03:00
|
|
|
st_foreach(me_arg.list, ins_methods_i, ary);
|
|
|
|
st_free_table(me_arg.list);
|
1998-01-16 15:19:22 +03:00
|
|
|
|
|
|
|
return ary;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2009-08-29 17:39:44 +04:00
|
|
|
/*!
|
|
|
|
* \}
|
|
|
|
*/
|
|
|
|
/*!
|
|
|
|
* \defgroup defmethod Defining methods
|
|
|
|
* There are some APIs to define a method from C.
|
|
|
|
* These API takes a C function as a method body.
|
|
|
|
*
|
|
|
|
* \par Method body functions
|
2010-05-29 22:51:39 +04:00
|
|
|
* Method body functions must return a VALUE and
|
2009-08-29 17:39:44 +04:00
|
|
|
* can be one of the following form:
|
|
|
|
* <dl>
|
|
|
|
* <dt>Fixed number of parameters</dt>
|
|
|
|
* <dd>
|
2010-05-29 22:51:39 +04:00
|
|
|
* This form is a normal C function, excepting it takes
|
2009-08-29 17:39:44 +04:00
|
|
|
* a receiver object as the first argument.
|
|
|
|
*
|
|
|
|
* \code
|
|
|
|
* static VALUE my_method(VALUE self, VALUE x, VALUE y);
|
|
|
|
* \endcode
|
|
|
|
* </dd>
|
|
|
|
* <dt>argc and argv style</dt>
|
|
|
|
* <dd>
|
|
|
|
* This form takes three parameters: \a argc, \a argv and \a self.
|
|
|
|
* \a self is the receiver. \a argc is the number of arguments.
|
|
|
|
* \a argv is a pointer to an array of the arguments.
|
|
|
|
*
|
|
|
|
* \code
|
|
|
|
* static VALUE my_method(int argc, VALUE *argv, VALUE self);
|
|
|
|
* \endcode
|
|
|
|
* </dd>
|
|
|
|
* <dt>Ruby array style</dt>
|
|
|
|
* <dd>
|
|
|
|
* This form takes two parameters: self and args.
|
2010-05-29 22:51:39 +04:00
|
|
|
* \a self is the receiver. \a args is an Array object which
|
2009-11-03 20:46:28 +03:00
|
|
|
* contains the arguments.
|
2009-08-29 17:39:44 +04:00
|
|
|
*
|
|
|
|
* \code
|
|
|
|
* static VALUE my_method(VALUE self, VALUE args);
|
|
|
|
* \endcode
|
|
|
|
* </dd>
|
|
|
|
*
|
|
|
|
* \par Number of parameters
|
|
|
|
* Method defining APIs takes the number of parameters which the
|
|
|
|
* method will takes. This number is called \a argc.
|
|
|
|
* \a argc can be:
|
|
|
|
* <dl>
|
|
|
|
* <dt>zero or positive number</dt>
|
|
|
|
* <dd>This means the method body function takes a fixed number of parameters</dd>
|
|
|
|
* <dt>-1</dt>
|
|
|
|
* <dd>This means the method body function is "argc and argv" style.</dd>
|
|
|
|
* <dt>-2</dt>
|
|
|
|
* <dd>This means the method body function is "self and args" style.</dd>
|
|
|
|
* </dl>
|
|
|
|
* \{
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
void
|
2009-07-15 18:59:41 +04:00
|
|
|
rb_define_method_id(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2015-06-03 04:39:16 +03:00
|
|
|
rb_add_method_cfunc(klass, mid, func, argc, METHOD_VISI_PUBLIC);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-10-20 06:56:22 +04:00
|
|
|
rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2015-06-03 04:39:16 +03:00
|
|
|
rb_add_method_cfunc(klass, rb_intern(name), func, argc, METHOD_VISI_PUBLIC);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-10-20 06:56:22 +04:00
|
|
|
rb_define_protected_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2015-06-03 04:39:16 +03:00
|
|
|
rb_add_method_cfunc(klass, rb_intern(name), func, argc, METHOD_VISI_PROTECTED);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-10-20 06:56:22 +04:00
|
|
|
rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2015-06-03 04:39:16 +03:00
|
|
|
rb_add_method_cfunc(klass, rb_intern(name), func, argc, METHOD_VISI_PRIVATE);
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_undef_method(VALUE klass, const char *name)
|
1999-01-20 07:59:39 +03:00
|
|
|
{
|
2015-06-03 04:39:16 +03:00
|
|
|
rb_add_method(klass, rb_intern(name), VM_METHOD_TYPE_UNDEF, 0, METHOD_VISI_UNDEF);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2009-08-29 17:39:44 +04:00
|
|
|
/*!
|
|
|
|
* \}
|
|
|
|
*/
|
|
|
|
/*!
|
|
|
|
* \addtogroup class
|
|
|
|
* \{
|
|
|
|
*/
|
|
|
|
|
2002-04-25 17:57:01 +04:00
|
|
|
#define SPECIAL_SINGLETON(x,c) do {\
|
|
|
|
if (obj == (x)) {\
|
2010-12-04 05:18:42 +03:00
|
|
|
return (c);\
|
2002-04-25 17:57:01 +04:00
|
|
|
}\
|
|
|
|
} while (0)
|
2002-03-08 10:03:09 +03:00
|
|
|
|
2012-08-06 19:31:13 +04:00
|
|
|
static inline VALUE
|
|
|
|
special_singleton_class_of(VALUE obj)
|
|
|
|
{
|
|
|
|
SPECIAL_SINGLETON(Qnil, rb_cNilClass);
|
|
|
|
SPECIAL_SINGLETON(Qfalse, rb_cFalseClass);
|
|
|
|
SPECIAL_SINGLETON(Qtrue, rb_cTrueClass);
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_special_singleton_class(VALUE obj)
|
|
|
|
{
|
|
|
|
return special_singleton_class_of(obj);
|
|
|
|
}
|
2009-08-29 17:39:44 +04:00
|
|
|
|
|
|
|
/*!
|
2009-08-31 09:55:57 +04:00
|
|
|
* \internal
|
|
|
|
* Returns the singleton class of \a obj. Creates it if necessary.
|
2009-08-29 17:39:44 +04:00
|
|
|
*
|
2009-08-31 09:55:57 +04:00
|
|
|
* \note DO NOT expose the returned singleton class to
|
|
|
|
* outside of class.c.
|
2010-05-29 22:51:39 +04:00
|
|
|
* Use \ref rb_singleton_class instead for
|
2009-08-31 09:55:57 +04:00
|
|
|
* consistency of the metaclass hierarchy.
|
2009-08-29 17:39:44 +04:00
|
|
|
*/
|
2009-08-31 09:55:57 +04:00
|
|
|
static VALUE
|
|
|
|
singleton_class_of(VALUE obj)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
1999-12-14 09:50:43 +03:00
|
|
|
VALUE klass;
|
2000-03-07 11:37:59 +03:00
|
|
|
|
2015-04-23 05:35:58 +03:00
|
|
|
if (FIXNUM_P(obj) || FLONUM_P(obj) || STATIC_SYM_P(obj)) {
|
|
|
|
no_singleton:
|
1999-08-13 09:45:20 +04:00
|
|
|
rb_raise(rb_eTypeError, "can't define singleton");
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2012-08-06 19:31:13 +04:00
|
|
|
if (SPECIAL_CONST_P(obj)) {
|
|
|
|
klass = special_singleton_class_of(obj);
|
|
|
|
if (NIL_P(klass))
|
|
|
|
rb_bug("unknown immediate %p", (void *)obj);
|
|
|
|
return klass;
|
2000-05-01 13:42:38 +04:00
|
|
|
}
|
2012-10-27 06:10:53 +04:00
|
|
|
else {
|
2015-04-23 05:35:58 +03:00
|
|
|
switch (BUILTIN_TYPE(obj)) {
|
|
|
|
case T_FLOAT: case T_BIGNUM: case T_SYMBOL:
|
|
|
|
goto no_singleton;
|
2012-10-28 04:03:20 +04:00
|
|
|
}
|
2012-10-27 06:10:53 +04:00
|
|
|
}
|
2000-05-01 13:42:38 +04:00
|
|
|
|
2014-09-13 17:07:04 +04:00
|
|
|
klass = RBASIC(obj)->klass;
|
|
|
|
if (!(FL_TEST(klass, FL_SINGLETON) &&
|
|
|
|
rb_ivar_get(klass, id_attached) == obj)) {
|
|
|
|
klass = rb_make_metaclass(obj, klass);
|
1999-12-14 09:50:43 +03:00
|
|
|
}
|
* test/ruby/test_metaclass.rb: new test case for metaclass hierarchy.
* class.c (make_metametaclass): new function. extracted from
rb_make_metaclass.
* class.c (rb_make_metaclass): uses make_metametaclass when called for a
metaclass.
* class.c (rb_singleton_class): creates a meta^(n+2)-class in
addition to a meta^(n+1)-class when called for a meta^(n)-class.
This is because the returned meta^(n+1) class must acts as an instance of
Class, metaclass of Class, ..., meta^(n+1)-class of Class,
Module, metaclass of Module, ..., meta^(n+1)-class of Module,
Object, metaclass of Object, ..., meta^(n+2)-class of Object,
BasicObject, metaclass of BasicObject, ..., meta^(n+2)-class of
and BasicObject even when Class, Module, Object or BasicObject has
not have its meta^(i)-class yet.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20747 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-12-15 09:23:43 +03:00
|
|
|
|
1999-12-14 09:50:43 +03:00
|
|
|
if (OBJ_TAINTED(obj)) {
|
|
|
|
OBJ_TAINT(klass);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
1999-12-14 09:50:43 +03:00
|
|
|
else {
|
|
|
|
FL_UNSET(klass, FL_TAINT);
|
|
|
|
}
|
2014-09-13 17:03:46 +04:00
|
|
|
if (OBJ_FROZEN(obj)) OBJ_FREEZE_RAW(klass);
|
1999-12-14 09:50:43 +03:00
|
|
|
|
|
|
|
return klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2014-09-19 05:45:45 +04:00
|
|
|
void
|
|
|
|
rb_freeze_singleton_class(VALUE x)
|
|
|
|
{
|
|
|
|
/* should not propagate to meta-meta-class, and so on */
|
|
|
|
if (!(RBASIC(x)->flags & FL_SINGLETON)) {
|
|
|
|
VALUE klass = RBASIC_CLASS(x);
|
2014-09-19 06:40:58 +04:00
|
|
|
if (klass && (klass = RCLASS_ORIGIN(klass)) != 0 &&
|
|
|
|
FL_TEST(klass, (FL_SINGLETON|FL_FREEZE)) == FL_SINGLETON) {
|
2014-09-19 05:45:45 +04:00
|
|
|
OBJ_FREEZE_RAW(klass);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-13 09:50:38 +04:00
|
|
|
/*!
|
|
|
|
* Returns the singleton class of \a obj, or nil if obj is not a
|
|
|
|
* singleton object.
|
|
|
|
*
|
|
|
|
* \param obj an arbitrary object.
|
|
|
|
* \return the singleton class or nil.
|
|
|
|
*/
|
|
|
|
VALUE
|
|
|
|
rb_singleton_class_get(VALUE obj)
|
|
|
|
{
|
|
|
|
VALUE klass;
|
|
|
|
|
|
|
|
if (SPECIAL_CONST_P(obj)) {
|
|
|
|
return rb_special_singleton_class(obj);
|
|
|
|
}
|
|
|
|
klass = RBASIC(obj)->klass;
|
|
|
|
if (!FL_TEST(klass, FL_SINGLETON)) return Qnil;
|
|
|
|
if (rb_ivar_get(klass, id_attached) != obj) return Qnil;
|
|
|
|
return klass;
|
|
|
|
}
|
2009-08-31 09:55:57 +04:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* Returns the singleton class of \a obj. Creates it if necessary.
|
|
|
|
*
|
|
|
|
* \param obj an arbitrary object.
|
|
|
|
* \throw TypeError if \a obj is a Fixnum or a Symbol.
|
|
|
|
* \return the singleton class.
|
|
|
|
*
|
|
|
|
* \post \a obj has its own singleton class.
|
2010-05-29 22:51:39 +04:00
|
|
|
* \post if \a obj is a class,
|
|
|
|
* the returned singleton class also has its own
|
2009-08-31 09:55:57 +04:00
|
|
|
* singleton class in order to keep consistency of the
|
|
|
|
* inheritance structure of metaclasses.
|
2010-05-29 22:51:39 +04:00
|
|
|
* \note a new singleton class will be created
|
2009-08-31 09:55:57 +04:00
|
|
|
* if \a obj does not have it.
|
|
|
|
* \note the singleton classes for nil, true and false are:
|
|
|
|
* NilClass, TrueClass and FalseClass.
|
|
|
|
*/
|
|
|
|
VALUE
|
|
|
|
rb_singleton_class(VALUE obj)
|
|
|
|
{
|
|
|
|
VALUE klass = singleton_class_of(obj);
|
|
|
|
|
|
|
|
/* ensures an exposed class belongs to its own eigenclass */
|
2011-09-29 15:07:45 +04:00
|
|
|
if (RB_TYPE_P(obj, T_CLASS)) (void)ENSURE_EIGENCLASS(klass);
|
2009-08-31 09:55:57 +04:00
|
|
|
|
|
|
|
return klass;
|
|
|
|
}
|
|
|
|
|
2009-08-29 17:39:44 +04:00
|
|
|
/*!
|
|
|
|
* \}
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \addtogroup defmethod
|
|
|
|
* \{
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* Defines a singleton method for \a obj.
|
|
|
|
* \param obj an arbitrary object
|
|
|
|
* \param name name of the singleton method
|
|
|
|
* \param func the method body
|
|
|
|
* \param argc the number of parameters, or -1 or -2. see \ref defmethod.
|
|
|
|
*/
|
1998-01-16 15:13:05 +03:00
|
|
|
void
|
2005-10-20 06:56:22 +04:00
|
|
|
rb_define_singleton_method(VALUE obj, const char *name, VALUE (*func)(ANYARGS), int argc)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2009-08-31 09:55:57 +04:00
|
|
|
rb_define_method(singleton_class_of(obj), name, func, argc);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2009-08-29 17:39:44 +04:00
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* Defines a module function for \a module.
|
|
|
|
* \param module an module or a class.
|
|
|
|
* \param name name of the function
|
|
|
|
* \param func the method body
|
|
|
|
* \param argc the number of parameters, or -1 or -2. see \ref defmethod.
|
|
|
|
*/
|
1998-01-16 15:13:05 +03:00
|
|
|
void
|
2005-10-20 06:56:22 +04:00
|
|
|
rb_define_module_function(VALUE module, const char *name, VALUE (*func)(ANYARGS), int argc)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
rb_define_private_method(module, name, func, argc);
|
|
|
|
rb_define_singleton_method(module, name, func, argc);
|
|
|
|
}
|
|
|
|
|
2009-08-29 17:39:44 +04:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* Defines a global function
|
|
|
|
* \param name name of the function
|
|
|
|
* \param func the method body
|
|
|
|
* \param argc the number of parameters, or -1 or -2. see \ref defmethod.
|
|
|
|
*/
|
1998-01-16 15:13:05 +03:00
|
|
|
void
|
2005-10-20 06:56:22 +04:00
|
|
|
rb_define_global_function(const char *name, VALUE (*func)(ANYARGS), int argc)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_define_module_function(rb_mKernel, name, func, argc);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2009-08-29 17:39:44 +04:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* Defines an alias of a method.
|
|
|
|
* \param klass the class which the original method belongs to
|
|
|
|
* \param name1 a new name for the method
|
|
|
|
* \param name2 the original name of the method
|
|
|
|
*/
|
1998-01-16 15:13:05 +03:00
|
|
|
void
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_define_alias(VALUE klass, const char *name1, const char *name2)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
1998-01-16 15:19:22 +03:00
|
|
|
rb_alias(klass, rb_intern(name1), rb_intern(name2));
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2009-08-29 17:39:44 +04:00
|
|
|
/*!
|
|
|
|
* Defines (a) public accessor method(s) for an attribute.
|
|
|
|
* \param klass the class which the attribute will belongs to
|
|
|
|
* \param name name of the attribute
|
|
|
|
* \param read a getter method for the attribute will be defined if \a read is non-zero.
|
|
|
|
* \param write a setter method for the attribute will be defined if \a write is non-zero.
|
|
|
|
*/
|
1998-01-16 15:13:05 +03:00
|
|
|
void
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_define_attr(VALUE klass, const char *name, int read, int write)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2009-07-18 12:05:32 +04:00
|
|
|
rb_attr(klass, rb_intern(name), read, write, FALSE);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2009-10-22 00:17:27 +04:00
|
|
|
int
|
2009-10-22 16:12:24 +04:00
|
|
|
rb_obj_basic_to_s_p(VALUE obj)
|
2009-10-22 00:17:27 +04:00
|
|
|
{
|
* method.h: introduce rb_callable_method_entry_t to remove
rb_control_frame_t::klass.
[Bug #11278], [Bug #11279]
rb_method_entry_t data belong to modules/classes.
rb_method_entry_t::owner points defined module or class.
module M
def foo; end
end
In this case, owner is M.
rb_callable_method_entry_t data belong to only classes.
For modules, MRI creates corresponding T_ICLASS internally.
rb_callable_method_entry_t can also belong to T_ICLASS.
rb_callable_method_entry_t::defined_class points T_CLASS or
T_ICLASS.
rb_method_entry_t data for classes (not for modules) are also
rb_callable_method_entry_t data because it is completely same data.
In this case, rb_method_entry_t::owner == rb_method_entry_t::defined_class.
For example, there are classes C and D, and incldues M,
class C; include M; end
class D; include M; end
then, two T_ICLASS objects for C's super class and D's super class
will be created.
When C.new.foo is called, then M#foo is searcheed and
rb_callable_method_t data is used by VM to invoke M#foo.
rb_method_entry_t data is only one for M#foo.
However, rb_callable_method_entry_t data are two (and can be more).
It is proportional to the number of including (and prepending)
classes (the number of T_ICLASS which point to the module).
Now, created rb_callable_method_entry_t are collected when
the original module M was modified. We can think it is a cache.
We need to select what kind of method entry data is needed.
To operate definition, then you need to use rb_method_entry_t.
You can access them by the following functions.
* rb_method_entry(VALUE klass, ID id);
* rb_method_entry_with_refinements(VALUE klass, ID id);
* rb_method_entry_without_refinements(VALUE klass, ID id);
* rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me);
To invoke methods, then you need to use rb_callable_method_entry_t
which you can get by the following APIs corresponding to the
above listed functions.
* rb_callable_method_entry(VALUE klass, ID id);
* rb_callable_method_entry_with_refinements(VALUE klass, ID id);
* rb_callable_method_entry_without_refinements(VALUE klass, ID id);
* rb_resolve_refined_method_callable(VALUE refinements, const rb_callable_method_entry_t *me);
VM pushes rb_callable_method_entry_t, so that rb_vm_frame_method_entry()
returns rb_callable_method_entry_t.
You can check a super class of current method by
rb_callable_method_entry_t::defined_class.
* method.h: renamed from rb_method_entry_t::klass to
rb_method_entry_t::owner.
* internal.h: add rb_classext_struct::callable_m_tbl to cache
rb_callable_method_entry_t data.
We need to consider abotu this field again because it is only
active for T_ICLASS.
* class.c (method_entry_i): ditto.
* class.c (rb_define_attr): rb_method_entry() does not takes
defiend_class_ptr.
* gc.c (mark_method_entry): mark RCLASS_CALLABLE_M_TBL() for T_ICLASS.
* cont.c (fiber_init): rb_control_frame_t::klass is removed.
* proc.c: fix `struct METHOD' data structure because
rb_callable_method_t has all information.
* vm_core.h: remove several fields.
* rb_control_frame_t::klass.
* rb_block_t::klass.
And catch up changes.
* eval.c: catch up changes.
* gc.c: ditto.
* insns.def: ditto.
* vm.c: ditto.
* vm_args.c: ditto.
* vm_backtrace.c: ditto.
* vm_dump.c: ditto.
* vm_eval.c: ditto.
* vm_insnhelper.c: ditto.
* vm_method.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-07-03 14:24:50 +03:00
|
|
|
const rb_method_entry_t *me = rb_method_entry(CLASS_OF(obj), rb_intern("to_s"));
|
2009-10-22 00:17:27 +04:00
|
|
|
if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC &&
|
|
|
|
me->def->body.cfunc.func == rb_any_to_s)
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
#include <stdarg.h>
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
int
|
2002-04-18 12:46:18 +04:00
|
|
|
rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2009-02-24 18:15:25 +03:00
|
|
|
int i;
|
|
|
|
const char *p = fmt;
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE *var;
|
|
|
|
va_list vargs;
|
2010-09-10 11:51:58 +04:00
|
|
|
int f_var = 0, f_hash = 0, f_block = 0;
|
2009-02-24 18:15:25 +03:00
|
|
|
int n_lead = 0, n_opt = 0, n_trail = 0, n_mand;
|
|
|
|
int argi = 0;
|
2010-09-10 11:51:58 +04:00
|
|
|
VALUE hash = Qnil;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2009-02-24 18:15:25 +03:00
|
|
|
if (ISDIGIT(*p)) {
|
|
|
|
n_lead = *p - '0';
|
|
|
|
p++;
|
|
|
|
if (ISDIGIT(*p)) {
|
|
|
|
n_opt = *p - '0';
|
|
|
|
p++;
|
2009-02-24 18:41:39 +03:00
|
|
|
if (ISDIGIT(*p)) {
|
|
|
|
n_trail = *p - '0';
|
|
|
|
p++;
|
|
|
|
goto block_arg;
|
|
|
|
}
|
2009-02-24 18:15:25 +03:00
|
|
|
}
|
2009-02-16 11:04:56 +03:00
|
|
|
}
|
|
|
|
if (*p == '*') {
|
2009-02-24 18:15:25 +03:00
|
|
|
f_var = 1;
|
|
|
|
p++;
|
|
|
|
if (ISDIGIT(*p)) {
|
|
|
|
n_trail = *p - '0';
|
|
|
|
p++;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2009-02-24 18:15:25 +03:00
|
|
|
}
|
2009-02-24 18:41:39 +03:00
|
|
|
block_arg:
|
2010-09-10 11:51:58 +04:00
|
|
|
if (*p == ':') {
|
|
|
|
f_hash = 1;
|
|
|
|
p++;
|
|
|
|
}
|
2009-02-24 18:15:25 +03:00
|
|
|
if (*p == '&') {
|
|
|
|
f_block = 1;
|
1998-01-16 15:13:05 +03:00
|
|
|
p++;
|
|
|
|
}
|
2009-02-24 18:15:25 +03:00
|
|
|
if (*p != '\0') {
|
|
|
|
rb_fatal("bad scan arg format: %s", fmt);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2009-02-24 18:15:25 +03:00
|
|
|
n_mand = n_lead + n_trail;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2009-02-24 18:15:25 +03:00
|
|
|
if (argc < n_mand)
|
|
|
|
goto argc_error;
|
|
|
|
|
|
|
|
va_start(vargs, fmt);
|
|
|
|
|
2010-09-10 11:51:58 +04:00
|
|
|
/* capture an option hash - phase 1: pop */
|
|
|
|
if (f_hash && n_mand < argc) {
|
|
|
|
VALUE last = argv[argc - 1];
|
|
|
|
|
|
|
|
if (NIL_P(last)) {
|
|
|
|
/* nil is taken as an empty option hash only if it is not
|
|
|
|
ambiguous; i.e. '*' is not specified and arguments are
|
|
|
|
given more than sufficient */
|
|
|
|
if (!f_var && n_mand + n_opt < argc)
|
|
|
|
argc--;
|
|
|
|
}
|
|
|
|
else {
|
2012-06-26 11:46:24 +04:00
|
|
|
hash = rb_check_hash_type(last);
|
2013-11-30 16:22:17 +04:00
|
|
|
if (!NIL_P(hash)) {
|
|
|
|
VALUE opts = rb_extract_keywords(&hash);
|
|
|
|
if (!hash) argc--;
|
2013-12-16 14:25:21 +04:00
|
|
|
hash = opts ? opts : Qnil;
|
2013-11-30 16:22:17 +04:00
|
|
|
}
|
2010-09-10 11:51:58 +04:00
|
|
|
}
|
|
|
|
}
|
2009-02-24 18:15:25 +03:00
|
|
|
/* capture leading mandatory arguments */
|
|
|
|
for (i = n_lead; i-- > 0; ) {
|
|
|
|
var = va_arg(vargs, VALUE *);
|
|
|
|
if (var) *var = argv[argi];
|
|
|
|
argi++;
|
|
|
|
}
|
|
|
|
/* capture optional arguments */
|
|
|
|
for (i = n_opt; i-- > 0; ) {
|
|
|
|
var = va_arg(vargs, VALUE *);
|
|
|
|
if (argi < argc - n_trail) {
|
|
|
|
if (var) *var = argv[argi];
|
|
|
|
argi++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (var) *var = Qnil;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
}
|
2009-02-24 18:15:25 +03:00
|
|
|
/* capture variable length arguments */
|
|
|
|
if (f_var) {
|
|
|
|
int n_var = argc - argi - n_trail;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2009-02-24 18:15:25 +03:00
|
|
|
var = va_arg(vargs, VALUE *);
|
|
|
|
if (0 < n_var) {
|
|
|
|
if (var) *var = rb_ary_new4(n_var, &argv[argi]);
|
|
|
|
argi += n_var;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
else {
|
1999-08-13 09:45:20 +04:00
|
|
|
if (var) *var = rb_ary_new();
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
}
|
2009-02-24 18:15:25 +03:00
|
|
|
/* capture trailing mandatory arguments */
|
|
|
|
for (i = n_trail; i-- > 0; ) {
|
|
|
|
var = va_arg(vargs, VALUE *);
|
|
|
|
if (var) *var = argv[argi];
|
|
|
|
argi++;
|
|
|
|
}
|
2010-09-10 11:51:58 +04:00
|
|
|
/* capture an option hash - phase 2: assignment */
|
|
|
|
if (f_hash) {
|
|
|
|
var = va_arg(vargs, VALUE *);
|
|
|
|
if (var) *var = hash;
|
|
|
|
}
|
2009-02-24 18:15:25 +03:00
|
|
|
/* capture iterator block */
|
|
|
|
if (f_block) {
|
|
|
|
var = va_arg(vargs, VALUE *);
|
2000-05-24 08:34:26 +04:00
|
|
|
if (rb_block_given_p()) {
|
2003-06-16 11:14:50 +04:00
|
|
|
*var = rb_block_proc();
|
2000-02-18 09:59:36 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
*var = Qnil;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
}
|
2000-02-18 09:59:36 +03:00
|
|
|
va_end(vargs);
|
|
|
|
|
2012-04-15 04:06:13 +04:00
|
|
|
if (argi < argc) {
|
|
|
|
argc_error:
|
|
|
|
rb_error_arity(argc, n_mand, f_var ? UNLIMITED_ARGUMENTS : n_mand + n_opt);
|
|
|
|
}
|
2000-02-18 09:59:36 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
return argc;
|
|
|
|
}
|
2009-06-29 20:39:28 +04:00
|
|
|
|
2014-11-27 13:15:47 +03:00
|
|
|
VALUE
|
|
|
|
rb_keyword_error_new(const char *error, VALUE keys)
|
2013-12-06 14:33:42 +04:00
|
|
|
{
|
2013-12-08 11:17:21 +04:00
|
|
|
const char *msg = "";
|
2014-11-27 13:15:47 +03:00
|
|
|
VALUE error_message;
|
|
|
|
|
2013-12-08 11:17:21 +04:00
|
|
|
if (RARRAY_LEN(keys) == 1) {
|
|
|
|
keys = RARRAY_AREF(keys, 0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
keys = rb_ary_join(keys, rb_usascii_str_new2(", "));
|
|
|
|
msg = "s";
|
|
|
|
}
|
2014-11-27 13:15:47 +03:00
|
|
|
|
|
|
|
error_message = rb_sprintf("%s keyword%s: %"PRIsVALUE, error, msg, keys);
|
|
|
|
|
|
|
|
return rb_exc_new_str(rb_eArgError, error_message);
|
|
|
|
}
|
|
|
|
|
|
|
|
NORETURN(static void rb_keyword_error(const char *error, VALUE keys));
|
|
|
|
static void
|
|
|
|
rb_keyword_error(const char *error, VALUE keys)
|
|
|
|
{
|
|
|
|
rb_exc_raise(rb_keyword_error_new(error, keys));
|
2013-12-06 14:33:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NORETURN(static void unknown_keyword_error(VALUE hash, const ID *table, int keywords));
|
|
|
|
static void
|
|
|
|
unknown_keyword_error(VALUE hash, const ID *table, int keywords)
|
|
|
|
{
|
2014-10-22 22:41:54 +04:00
|
|
|
st_table *tbl = rb_hash_tbl_raw(hash);
|
2013-12-06 14:33:42 +04:00
|
|
|
VALUE keys;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < keywords; i++) {
|
2014-10-22 22:41:54 +04:00
|
|
|
st_data_t key = ID2SYM(table[i]);
|
|
|
|
st_delete(tbl, &key, NULL);
|
2013-12-06 14:33:42 +04:00
|
|
|
}
|
2015-02-16 07:08:52 +03:00
|
|
|
keys = rb_funcallv(hash, rb_intern("keys"), 0, 0);
|
2013-12-06 14:33:42 +04:00
|
|
|
if (!RB_TYPE_P(keys, T_ARRAY)) rb_raise(rb_eArgError, "unknown keyword");
|
* rewrite method/block parameter fitting logic to optimize
keyword arguments/parameters and a splat argument.
[Feature #10440] (Details are described in this ticket)
Most of complex part is moved to vm_args.c.
Now, ISeq#to_a does not catch up new instruction format.
* vm_core.h: change iseq data structures.
* introduce rb_call_info_kw_arg_t to represent keyword arguments.
* add rb_call_info_t::kw_arg.
* rename rb_iseq_t::arg_post_len to rb_iseq_t::arg_post_num.
* rename rb_iseq_t::arg_keywords to arg_keyword_num.
* rename rb_iseq_t::arg_keyword to rb_iseq_t::arg_keyword_bits.
to represent keyword bitmap parameter index.
This bitmap parameter shows that which keyword parameters are given
or not given (0 for given).
It is refered by `checkkeyword' instruction described bellow.
* rename rb_iseq_t::arg_keyword_check to rb_iseq_t::arg_keyword_rest
to represent keyword rest parameter index.
* add rb_iseq_t::arg_keyword_default_values to represent default
keyword values.
* rename VM_CALL_ARGS_SKIP_SETUP to VM_CALL_ARGS_SIMPLE
to represent
(ci->flag & (SPLAT|BLOCKARG)) &&
ci->blockiseq == NULL &&
ci->kw_arg == NULL.
* vm_insnhelper.c, vm_args.c: rewrite with refactoring.
* rewrite splat argument code.
* rewrite keyword arguments/parameters code.
* merge method and block parameter fitting code into one code base.
* vm.c, vm_eval.c: catch up these changes.
* compile.c (new_callinfo): callinfo requires kw_arg parameter.
* compile.c (compile_array_): check the last argument Hash object or
not. If Hash object and all keys are Symbol literals, they are
compiled to keyword arguments.
* insns.def (checkkeyword): add new instruction.
This instruction check the availability of corresponding keyword.
For example, a method "def foo k1: 'v1'; end" is cimpiled to the
following instructions.
0000 checkkeyword 2, 0 # check k1 is given.
0003 branchif 9 # if given, jump to address #9
0005 putstring "v1"
0007 setlocal_OP__WC__0 3 # k1 = 'v1'
0009 trace 8
0011 putnil
0012 trace 16
0014 leave
* insns.def (opt_send_simple): removed and add new instruction
"opt_send_without_block".
* parse.y (new_args_tail_gen): reorder variables.
Before this patch, a method "def foo(k1: 1, kr1:, k2: 2, **krest, &b)"
has parameter variables "k1, kr1, k2, &b, internal_id, krest",
but this patch reorders to "kr1, k1, k2, internal_id, krest, &b".
(locate a block variable at last)
* parse.y (vtable_pop): added.
This function remove latest `n' variables from vtable.
* iseq.c: catch up iseq data changes.
* proc.c: ditto.
* class.c (keyword_error): export as rb_keyword_error().
* common.mk: depend vm_args.c for vm.o.
* hash.c (rb_hash_has_key): export.
* internal.h: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@48239 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2014-11-02 21:02:55 +03:00
|
|
|
rb_keyword_error("unknown", keys);
|
2013-12-06 14:33:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
separate_symbol(st_data_t key, st_data_t value, st_data_t arg)
|
|
|
|
{
|
|
|
|
VALUE *kwdhash = (VALUE *)arg;
|
|
|
|
|
|
|
|
if (!SYMBOL_P(key)) kwdhash++;
|
|
|
|
if (!*kwdhash) *kwdhash = rb_hash_new();
|
|
|
|
rb_hash_aset(*kwdhash, (VALUE)key, (VALUE)value);
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_extract_keywords(VALUE *orighash)
|
|
|
|
{
|
|
|
|
VALUE parthash[2] = {0, 0};
|
|
|
|
VALUE hash = *orighash;
|
|
|
|
|
|
|
|
if (RHASH_EMPTY_P(hash)) {
|
|
|
|
*orighash = 0;
|
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
st_foreach(rb_hash_tbl_raw(hash), separate_symbol, (st_data_t)&parthash);
|
|
|
|
*orighash = parthash[1];
|
|
|
|
return parthash[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
|
|
|
|
{
|
|
|
|
int i = 0, j;
|
2013-12-08 11:19:30 +04:00
|
|
|
int rest = 0;
|
2013-12-06 14:33:42 +04:00
|
|
|
VALUE missing = Qnil;
|
2013-12-08 15:47:39 +04:00
|
|
|
st_data_t key;
|
|
|
|
|
|
|
|
#define extract_kwarg(keyword, val) \
|
|
|
|
(key = (st_data_t)(keyword), values ? \
|
|
|
|
st_delete(rb_hash_tbl_raw(keyword_hash), &key, (val)) : \
|
|
|
|
st_lookup(rb_hash_tbl_raw(keyword_hash), key, (val)))
|
2013-12-06 14:33:42 +04:00
|
|
|
|
2014-01-25 06:16:20 +04:00
|
|
|
if (NIL_P(keyword_hash)) keyword_hash = 0;
|
|
|
|
|
2013-12-08 11:19:30 +04:00
|
|
|
if (optional < 0) {
|
|
|
|
rest = 1;
|
|
|
|
optional = -1-optional;
|
|
|
|
}
|
2013-12-06 14:33:42 +04:00
|
|
|
if (values) {
|
|
|
|
for (j = 0; j < required + optional; j++) {
|
|
|
|
values[j] = Qundef;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (required) {
|
|
|
|
for (; i < required; i++) {
|
|
|
|
VALUE keyword = ID2SYM(table[i]);
|
|
|
|
if (keyword_hash) {
|
|
|
|
st_data_t val;
|
2013-12-08 15:47:39 +04:00
|
|
|
if (extract_kwarg(keyword, &val)) {
|
2013-12-06 14:33:42 +04:00
|
|
|
if (values) values[i] = (VALUE)val;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (NIL_P(missing)) missing = rb_ary_tmp_new(1);
|
|
|
|
rb_ary_push(missing, keyword);
|
|
|
|
}
|
|
|
|
if (!NIL_P(missing)) {
|
* rewrite method/block parameter fitting logic to optimize
keyword arguments/parameters and a splat argument.
[Feature #10440] (Details are described in this ticket)
Most of complex part is moved to vm_args.c.
Now, ISeq#to_a does not catch up new instruction format.
* vm_core.h: change iseq data structures.
* introduce rb_call_info_kw_arg_t to represent keyword arguments.
* add rb_call_info_t::kw_arg.
* rename rb_iseq_t::arg_post_len to rb_iseq_t::arg_post_num.
* rename rb_iseq_t::arg_keywords to arg_keyword_num.
* rename rb_iseq_t::arg_keyword to rb_iseq_t::arg_keyword_bits.
to represent keyword bitmap parameter index.
This bitmap parameter shows that which keyword parameters are given
or not given (0 for given).
It is refered by `checkkeyword' instruction described bellow.
* rename rb_iseq_t::arg_keyword_check to rb_iseq_t::arg_keyword_rest
to represent keyword rest parameter index.
* add rb_iseq_t::arg_keyword_default_values to represent default
keyword values.
* rename VM_CALL_ARGS_SKIP_SETUP to VM_CALL_ARGS_SIMPLE
to represent
(ci->flag & (SPLAT|BLOCKARG)) &&
ci->blockiseq == NULL &&
ci->kw_arg == NULL.
* vm_insnhelper.c, vm_args.c: rewrite with refactoring.
* rewrite splat argument code.
* rewrite keyword arguments/parameters code.
* merge method and block parameter fitting code into one code base.
* vm.c, vm_eval.c: catch up these changes.
* compile.c (new_callinfo): callinfo requires kw_arg parameter.
* compile.c (compile_array_): check the last argument Hash object or
not. If Hash object and all keys are Symbol literals, they are
compiled to keyword arguments.
* insns.def (checkkeyword): add new instruction.
This instruction check the availability of corresponding keyword.
For example, a method "def foo k1: 'v1'; end" is cimpiled to the
following instructions.
0000 checkkeyword 2, 0 # check k1 is given.
0003 branchif 9 # if given, jump to address #9
0005 putstring "v1"
0007 setlocal_OP__WC__0 3 # k1 = 'v1'
0009 trace 8
0011 putnil
0012 trace 16
0014 leave
* insns.def (opt_send_simple): removed and add new instruction
"opt_send_without_block".
* parse.y (new_args_tail_gen): reorder variables.
Before this patch, a method "def foo(k1: 1, kr1:, k2: 2, **krest, &b)"
has parameter variables "k1, kr1, k2, &b, internal_id, krest",
but this patch reorders to "kr1, k1, k2, internal_id, krest, &b".
(locate a block variable at last)
* parse.y (vtable_pop): added.
This function remove latest `n' variables from vtable.
* iseq.c: catch up iseq data changes.
* proc.c: ditto.
* class.c (keyword_error): export as rb_keyword_error().
* common.mk: depend vm_args.c for vm.o.
* hash.c (rb_hash_has_key): export.
* internal.h: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@48239 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2014-11-02 21:02:55 +03:00
|
|
|
rb_keyword_error("missing", missing);
|
2013-12-06 14:33:42 +04:00
|
|
|
}
|
|
|
|
}
|
2013-12-08 05:32:07 +04:00
|
|
|
j = i;
|
2013-12-06 14:33:42 +04:00
|
|
|
if (optional && keyword_hash) {
|
2013-12-08 05:32:07 +04:00
|
|
|
for (i = 0; i < optional; i++) {
|
2013-12-06 14:33:42 +04:00
|
|
|
st_data_t val;
|
2013-12-08 15:47:39 +04:00
|
|
|
if (extract_kwarg(ID2SYM(table[required+i]), &val)) {
|
2013-12-06 14:33:42 +04:00
|
|
|
if (values) values[required+i] = (VALUE)val;
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
2013-12-08 11:19:30 +04:00
|
|
|
}
|
|
|
|
if (!rest && keyword_hash) {
|
2013-12-06 14:33:42 +04:00
|
|
|
if (RHASH_SIZE(keyword_hash) > (unsigned int)j) {
|
|
|
|
unknown_keyword_error(keyword_hash, table, required+optional);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return j;
|
2013-12-08 15:47:39 +04:00
|
|
|
#undef extract_kwarg
|
2013-12-06 14:33:42 +04:00
|
|
|
}
|
|
|
|
|
2015-05-31 22:17:18 +03:00
|
|
|
int
|
|
|
|
rb_class_has_methods(VALUE c)
|
|
|
|
{
|
2015-08-12 11:43:55 +03:00
|
|
|
return rb_id_table_size(RCLASS_M_TBL(c)) == 0 ? FALSE : TRUE;
|
2015-05-31 22:17:18 +03:00
|
|
|
}
|
|
|
|
|
2009-06-29 20:39:28 +04:00
|
|
|
/*!
|
|
|
|
* \}
|
|
|
|
*/
|