support builtin for Kernel#clone
This commit is contained in:
parent
d514ba8e17
commit
290d608637
Notes:
git
2020-03-17 19:37:40 +09:00
Merged: https://github.com/ruby/ruby/pull/2954 Merged-By: nobu <nobu@ruby-lang.org>
@ -14,6 +14,7 @@ array.rb
|
|||||||
ast.rb
|
ast.rb
|
||||||
gc.rb
|
gc.rb
|
||||||
io.rb
|
io.rb
|
||||||
|
kernel.rb
|
||||||
pack.rb
|
pack.rb
|
||||||
trace_point.rb
|
trace_point.rb
|
||||||
warning.rb
|
warning.rb
|
||||||
|
6
benchmark/kernel_clone.yml
Normal file
6
benchmark/kernel_clone.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
prelude: "object = Object.new"
|
||||||
|
benchmark:
|
||||||
|
clone: "object.clone"
|
||||||
|
clone_true: "object.clone(freeze: true)"
|
||||||
|
clone_false: "object.clone(freeze: false)"
|
||||||
|
loop_count: 10000
|
@ -1003,6 +1003,7 @@ BUILTIN_RB_SRCS = \
|
|||||||
$(srcdir)/trace_point.rb \
|
$(srcdir)/trace_point.rb \
|
||||||
$(srcdir)/warning.rb \
|
$(srcdir)/warning.rb \
|
||||||
$(srcdir)/array.rb \
|
$(srcdir)/array.rb \
|
||||||
|
$(srcdir)/kernel.rb \
|
||||||
$(srcdir)/prelude.rb \
|
$(srcdir)/prelude.rb \
|
||||||
$(srcdir)/gem_prelude.rb \
|
$(srcdir)/gem_prelude.rb \
|
||||||
$(empty)
|
$(empty)
|
||||||
@ -2848,6 +2849,7 @@ miniinit.$(OBJEXT): {$(VPATH)}intern.h
|
|||||||
miniinit.$(OBJEXT): {$(VPATH)}internal.h
|
miniinit.$(OBJEXT): {$(VPATH)}internal.h
|
||||||
miniinit.$(OBJEXT): {$(VPATH)}io.rb
|
miniinit.$(OBJEXT): {$(VPATH)}io.rb
|
||||||
miniinit.$(OBJEXT): {$(VPATH)}iseq.h
|
miniinit.$(OBJEXT): {$(VPATH)}iseq.h
|
||||||
|
miniinit.$(OBJEXT): {$(VPATH)}kernel.rb
|
||||||
miniinit.$(OBJEXT): {$(VPATH)}method.h
|
miniinit.$(OBJEXT): {$(VPATH)}method.h
|
||||||
miniinit.$(OBJEXT): {$(VPATH)}mini_builtin.c
|
miniinit.$(OBJEXT): {$(VPATH)}mini_builtin.c
|
||||||
miniinit.$(OBJEXT): {$(VPATH)}miniinit.c
|
miniinit.$(OBJEXT): {$(VPATH)}miniinit.c
|
||||||
@ -3101,6 +3103,7 @@ object.$(OBJEXT): $(top_srcdir)/internal/variable.h
|
|||||||
object.$(OBJEXT): $(top_srcdir)/internal/vm.h
|
object.$(OBJEXT): $(top_srcdir)/internal/vm.h
|
||||||
object.$(OBJEXT): $(top_srcdir)/internal/warnings.h
|
object.$(OBJEXT): $(top_srcdir)/internal/warnings.h
|
||||||
object.$(OBJEXT): {$(VPATH)}assert.h
|
object.$(OBJEXT): {$(VPATH)}assert.h
|
||||||
|
object.$(OBJEXT): {$(VPATH)}builtin.h
|
||||||
object.$(OBJEXT): {$(VPATH)}config.h
|
object.$(OBJEXT): {$(VPATH)}config.h
|
||||||
object.$(OBJEXT): {$(VPATH)}constant.h
|
object.$(OBJEXT): {$(VPATH)}constant.h
|
||||||
object.$(OBJEXT): {$(VPATH)}defines.h
|
object.$(OBJEXT): {$(VPATH)}defines.h
|
||||||
@ -3109,6 +3112,7 @@ object.$(OBJEXT): {$(VPATH)}id.h
|
|||||||
object.$(OBJEXT): {$(VPATH)}id_table.h
|
object.$(OBJEXT): {$(VPATH)}id_table.h
|
||||||
object.$(OBJEXT): {$(VPATH)}intern.h
|
object.$(OBJEXT): {$(VPATH)}intern.h
|
||||||
object.$(OBJEXT): {$(VPATH)}internal.h
|
object.$(OBJEXT): {$(VPATH)}internal.h
|
||||||
|
object.$(OBJEXT): {$(VPATH)}kernel.rbinc
|
||||||
object.$(OBJEXT): {$(VPATH)}missing.h
|
object.$(OBJEXT): {$(VPATH)}missing.h
|
||||||
object.$(OBJEXT): {$(VPATH)}object.c
|
object.$(OBJEXT): {$(VPATH)}object.c
|
||||||
object.$(OBJEXT): {$(VPATH)}onigmo.h
|
object.$(OBJEXT): {$(VPATH)}onigmo.h
|
||||||
|
1
inits.c
1
inits.c
@ -84,6 +84,7 @@ rb_call_inits(void)
|
|||||||
BUILTIN(pack);
|
BUILTIN(pack);
|
||||||
BUILTIN(warning);
|
BUILTIN(warning);
|
||||||
BUILTIN(array);
|
BUILTIN(array);
|
||||||
|
BUILTIN(kernel);
|
||||||
Init_builtin_prelude();
|
Init_builtin_prelude();
|
||||||
}
|
}
|
||||||
#undef CALL
|
#undef CALL
|
||||||
|
29
kernel.rb
Normal file
29
kernel.rb
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
module Kernel
|
||||||
|
#
|
||||||
|
# call-seq:
|
||||||
|
# obj.clone(freeze: true) -> an_object
|
||||||
|
#
|
||||||
|
# Produces a shallow copy of <i>obj</i>---the instance variables of
|
||||||
|
# <i>obj</i> are copied, but not the objects they reference.
|
||||||
|
# #clone copies the frozen (unless +:freeze+ keyword argument is
|
||||||
|
# given with a false value) state of <i>obj</i>. See
|
||||||
|
# also the discussion under Object#dup.
|
||||||
|
#
|
||||||
|
# class Klass
|
||||||
|
# attr_accessor :str
|
||||||
|
# end
|
||||||
|
# s1 = Klass.new #=> #<Klass:0x401b3a38>
|
||||||
|
# s1.str = "Hello" #=> "Hello"
|
||||||
|
# s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello">
|
||||||
|
# s2.str[1,4] = "i" #=> "i"
|
||||||
|
# s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">"
|
||||||
|
# s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">"
|
||||||
|
#
|
||||||
|
# This method may have class-specific behavior. If so, that
|
||||||
|
# behavior will be documented under the #+initialize_copy+ method of
|
||||||
|
# the class.
|
||||||
|
#
|
||||||
|
def clone(freeze: true)
|
||||||
|
__builtin_rb_obj_clone2(freeze)
|
||||||
|
end
|
||||||
|
end
|
51
object.c
51
object.c
@ -36,6 +36,7 @@
|
|||||||
#include "ruby/encoding.h"
|
#include "ruby/encoding.h"
|
||||||
#include "ruby/st.h"
|
#include "ruby/st.h"
|
||||||
#include "ruby/util.h"
|
#include "ruby/util.h"
|
||||||
|
#include "builtin.h"
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \defgroup object Core objects and their operations
|
* \defgroup object Core objects and their operations
|
||||||
@ -389,35 +390,21 @@ special_object_p(VALUE obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static int
|
||||||
* call-seq:
|
obj_freeze_opt(VALUE freeze)
|
||||||
* obj.clone(freeze: true) -> an_object
|
{
|
||||||
*
|
if (freeze == Qfalse) return FALSE;
|
||||||
* Produces a shallow copy of <i>obj</i>---the instance variables of
|
|
||||||
* <i>obj</i> are copied, but not the objects they reference.
|
if (freeze != Qtrue)
|
||||||
* #clone copies the frozen (unless +:freeze+ keyword argument is
|
rb_raise(rb_eArgError, "unexpected value for freeze: %"PRIsVALUE, rb_obj_class(freeze));
|
||||||
* given with a false value) state of <i>obj</i>. See
|
|
||||||
* also the discussion under Object#dup.
|
return TRUE;
|
||||||
*
|
}
|
||||||
* class Klass
|
|
||||||
* attr_accessor :str
|
|
||||||
* end
|
|
||||||
* s1 = Klass.new #=> #<Klass:0x401b3a38>
|
|
||||||
* s1.str = "Hello" #=> "Hello"
|
|
||||||
* s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello">
|
|
||||||
* s2.str[1,4] = "i" #=> "i"
|
|
||||||
* s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">"
|
|
||||||
* s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">"
|
|
||||||
*
|
|
||||||
* This method may have class-specific behavior. If so, that
|
|
||||||
* behavior will be documented under the #+initialize_copy+ method of
|
|
||||||
* the class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_obj_clone2(int argc, VALUE *argv, VALUE obj)
|
rb_obj_clone2(rb_execution_context_t *ec, VALUE obj, VALUE freeze)
|
||||||
{
|
{
|
||||||
int kwfreeze = freeze_opt(argc, argv);
|
int kwfreeze = obj_freeze_opt(freeze);
|
||||||
if (!special_object_p(obj))
|
if (!special_object_p(obj))
|
||||||
return mutable_obj_clone(obj, kwfreeze);
|
return mutable_obj_clone(obj, kwfreeze);
|
||||||
return immutable_obj_clone(obj, kwfreeze);
|
return immutable_obj_clone(obj, kwfreeze);
|
||||||
@ -437,6 +424,7 @@ freeze_opt(int argc, VALUE *argv)
|
|||||||
static ID keyword_ids[1];
|
static ID keyword_ids[1];
|
||||||
VALUE opt;
|
VALUE opt;
|
||||||
VALUE kwfreeze;
|
VALUE kwfreeze;
|
||||||
|
int ret = 1;
|
||||||
|
|
||||||
if (!keyword_ids[0]) {
|
if (!keyword_ids[0]) {
|
||||||
CONST_ID(keyword_ids[0], "freeze");
|
CONST_ID(keyword_ids[0], "freeze");
|
||||||
@ -444,13 +432,9 @@ freeze_opt(int argc, VALUE *argv)
|
|||||||
rb_scan_args(argc, argv, "0:", &opt);
|
rb_scan_args(argc, argv, "0:", &opt);
|
||||||
if (!NIL_P(opt)) {
|
if (!NIL_P(opt)) {
|
||||||
rb_get_kwargs(opt, keyword_ids, 0, 1, &kwfreeze);
|
rb_get_kwargs(opt, keyword_ids, 0, 1, &kwfreeze);
|
||||||
if (kwfreeze == Qfalse) return FALSE;
|
ret = obj_freeze_opt(kwfreeze);
|
||||||
if (kwfreeze != Qundef && kwfreeze != Qtrue) {
|
|
||||||
rb_raise(rb_eArgError, "unexpected value for freeze: %"PRIsVALUE,
|
|
||||||
rb_obj_class(kwfreeze));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return TRUE;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
@ -4612,7 +4596,6 @@ InitVM_Object(void)
|
|||||||
|
|
||||||
rb_define_method(rb_mKernel, "class", rb_obj_class, 0);
|
rb_define_method(rb_mKernel, "class", rb_obj_class, 0);
|
||||||
rb_define_method(rb_mKernel, "singleton_class", rb_obj_singleton_class, 0);
|
rb_define_method(rb_mKernel, "singleton_class", rb_obj_singleton_class, 0);
|
||||||
rb_define_method(rb_mKernel, "clone", rb_obj_clone2, -1);
|
|
||||||
rb_define_method(rb_mKernel, "dup", rb_obj_dup, 0);
|
rb_define_method(rb_mKernel, "dup", rb_obj_dup, 0);
|
||||||
rb_define_method(rb_mKernel, "itself", rb_obj_itself, 0);
|
rb_define_method(rb_mKernel, "itself", rb_obj_itself, 0);
|
||||||
rb_define_method(rb_mKernel, "yield_self", rb_obj_yield_self, 0);
|
rb_define_method(rb_mKernel, "yield_self", rb_obj_yield_self, 0);
|
||||||
@ -4790,6 +4773,8 @@ InitVM_Object(void)
|
|||||||
rb_deprecate_constant(rb_cObject, "FALSE");
|
rb_deprecate_constant(rb_cObject, "FALSE");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "kernel.rbinc"
|
||||||
|
|
||||||
void
|
void
|
||||||
Init_Object(void)
|
Init_Object(void)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user