Feature #14914 ยป 0001-Add-BasicObject-instance_exec_with_block.patch
test/ruby/test_object.rb | ||
---|---|---|
end
|
||
end
|
||
def test_instance_exec_with_block
|
||
x = 1.instance_exec_with_block(42, 2, proc{|x| self * x}) {|a, b, &blk| (self + a).instance_exec(b, &blk) }
|
||
assert_equal(86, x)
|
||
assert_raise(ArgumentError) do
|
||
x.instance_exec_with_block{}
|
||
end
|
||
assert_raise(TypeError) do
|
||
x.instance_exec_with_block(1){}
|
||
end
|
||
assert_raise(LocalJumpError) do
|
||
x.instance_exec_with_block(proc{})
|
||
end
|
||
end
|
||
def test_extend
|
||
assert_raise(ArgumentError) do
|
||
1.extend
|
vm.c | ||
---|---|---|
return block_handler;
|
||
}
|
||
static VALUE
|
||
vm_yield_with_cref_and_block(rb_execution_context_t *ec, int argc, const VALUE *argv, const rb_cref_t *cref, int is_lambda, VALUE block_handler)
|
||
{
|
||
vm_block_handler_verify(block_handler);
|
||
return invoke_block_from_c_bh(ec, check_block_handler(ec),
|
||
argc, argv, block_handler,
|
||
cref, is_lambda, FALSE);
|
||
}
|
||
static VALUE
|
||
vm_yield_with_cref(rb_execution_context_t *ec, int argc, const VALUE *argv, const rb_cref_t *cref, int is_lambda)
|
||
{
|
vm_eval.c | ||
---|---|---|
static inline VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv, enum method_missing_reason call_status);
|
||
static inline VALUE vm_yield_with_cref(rb_execution_context_t *ec, int argc, const VALUE *argv, const rb_cref_t *cref, int is_lambda);
|
||
static inline VALUE vm_yield_with_cref_and_block(rb_execution_context_t *ec, int argc, const VALUE *argv, const rb_cref_t *cref, int is_lambda, VALUE block_handler);
|
||
static inline VALUE vm_yield(rb_execution_context_t *ec, int argc, const VALUE *argv);
|
||
static inline VALUE vm_yield_with_block(rb_execution_context_t *ec, int argc, const VALUE *argv, VALUE block_handler);
|
||
static inline VALUE vm_yield_force_blockarg(rb_execution_context_t *ec, VALUE args);
|
||
... | ... | |
/* block eval under the class/module context */
|
||
static VALUE
|
||
yield_under(VALUE under, VALUE self, int argc, const VALUE *argv)
|
||
yield_under(VALUE under, VALUE self, int argc, const VALUE *argv, VALUE passed_block)
|
||
{
|
||
rb_execution_context_t *ec = GET_EC();
|
||
rb_control_frame_t *cfp = ec->cfp;
|
||
... | ... | |
}
|
||
cref = vm_cref_push(ec, under, ep, TRUE);
|
||
return vm_yield_with_cref(ec, argc, argv, cref, is_lambda);
|
||
return vm_yield_with_cref_and_block(ec, argc, argv, cref, is_lambda, passed_block);
|
||
}
|
||
VALUE
|
||
... | ... | |
{
|
||
if (rb_block_given_p()) {
|
||
rb_check_arity(argc, 0, 0);
|
||
return yield_under(klass, self, 1, &self);
|
||
return yield_under(klass, self, 1, &self, VM_BLOCK_HANDLER_NONE);
|
||
}
|
||
else {
|
||
VALUE file = Qundef;
|
||
... | ... | |
rb_obj_instance_exec(int argc, const VALUE *argv, VALUE self)
|
||
{
|
||
VALUE klass = singleton_class_for_eval(self);
|
||
return yield_under(klass, self, argc, argv);
|
||
return yield_under(klass, self, argc, argv, VM_BLOCK_HANDLER_NONE);
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* obj.instance_exec_with_block(arg..., proc) {|var..., &proc| block } -> obj
|
||
*
|
||
* Executes the given block within the context of the receiver
|
||
* (_obj_). In order to set the context, the variable +self+ is set
|
||
* to _obj_ while the code is executing, giving the code access to
|
||
* _obj_'s instance variables. The final argument is the proc to pass
|
||
* as the block argument to the block. Remaining arguments are passed
|
||
* as block parameters.
|
||
*
|
||
* class KlassWithSecret
|
||
* def initialize
|
||
* @secret = "a"
|
||
* end
|
||
* end
|
||
* k = KlassWithSecret.new
|
||
* k.instance_exec_with_block("b", 2, proc{|s| capitalize * 2}) do |x, y, &blk|
|
||
* @secret << x
|
||
* @secret.instance_exec(y, &blk)
|
||
* end #=> "AbAb"
|
||
*/
|
||
VALUE
|
||
rb_obj_instance_exec_with_block(int argc, const VALUE *argv, VALUE self)
|
||
{
|
||
VALUE block;
|
||
VALUE klass;
|
||
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
||
block = argv[--argc];
|
||
if (!rb_obj_is_proc(block)) {
|
||
rb_raise(rb_eTypeError, "last argument to instance_exec_with_block must be a Proc");
|
||
}
|
||
klass = singleton_class_for_eval(self);
|
||
return yield_under(klass, self, argc, argv, block);
|
||
}
|
||
/*
|
||
... | ... | |
VALUE
|
||
rb_mod_module_exec(int argc, const VALUE *argv, VALUE mod)
|
||
{
|
||
return yield_under(mod, mod, argc, argv);
|
||
return yield_under(mod, mod, argc, argv, VM_BLOCK_HANDLER_NONE);
|
||
}
|
||
/*
|
||
... | ... | |
rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
|
||
rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
|
||
rb_define_method(rb_cBasicObject, "instance_exec_with_block", rb_obj_instance_exec_with_block, -1);
|
||
rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
|
||
#if 1
|