Project

General

Profile

Feature #14914 ยป 0001-Add-BasicObject-instance_exec_with_block.patch

jeremyevans0 (Jeremy Evans), 07/16/2018 04:04 PM

View differences:

test/ruby/test_object.rb
759 759
    end
760 760
  end
761 761

  
762
  def test_instance_exec_with_block
763
    x = 1.instance_exec_with_block(42, 2, proc{|x| self * x}) {|a, b, &blk| (self + a).instance_exec(b, &blk) }
764
    assert_equal(86, x)
765

  
766
    assert_raise(ArgumentError) do
767
      x.instance_exec_with_block{}
768
    end
769

  
770
    assert_raise(TypeError) do
771
      x.instance_exec_with_block(1){}
772
    end
773

  
774
    assert_raise(LocalJumpError) do
775
      x.instance_exec_with_block(proc{})
776
    end
777
  end
778

  
762 779
  def test_extend
763 780
    assert_raise(ArgumentError) do
764 781
      1.extend
vm.c
1105 1105
    return block_handler;
1106 1106
}
1107 1107

  
1108
static VALUE
1109
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)
1110
{
1111
    vm_block_handler_verify(block_handler);
1112
    return invoke_block_from_c_bh(ec, check_block_handler(ec),
1113
				  argc, argv, block_handler,
1114
				  cref, is_lambda, FALSE);
1115
}
1116

  
1108 1117
static VALUE
1109 1118
vm_yield_with_cref(rb_execution_context_t *ec, int argc, const VALUE *argv, const rb_cref_t *cref, int is_lambda)
1110 1119
{
vm_eval.c
17 17

  
18 18
static inline VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv, enum method_missing_reason call_status);
19 19
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);
20
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);
20 21
static inline VALUE vm_yield(rb_execution_context_t *ec, int argc, const VALUE *argv);
21 22
static inline VALUE vm_yield_with_block(rb_execution_context_t *ec, int argc, const VALUE *argv, VALUE block_handler);
22 23
static inline VALUE vm_yield_force_blockarg(rb_execution_context_t *ec, VALUE args);
......
1526 1527
/* block eval under the class/module context */
1527 1528

  
1528 1529
static VALUE
1529
yield_under(VALUE under, VALUE self, int argc, const VALUE *argv)
1530
yield_under(VALUE under, VALUE self, int argc, const VALUE *argv, VALUE passed_block)
1530 1531
{
1531 1532
    rb_execution_context_t *ec = GET_EC();
1532 1533
    rb_control_frame_t *cfp = ec->cfp;
......
1567 1568
    }
1568 1569

  
1569 1570
    cref = vm_cref_push(ec, under, ep, TRUE);
1570
    return vm_yield_with_cref(ec, argc, argv, cref, is_lambda);
1571
    return vm_yield_with_cref_and_block(ec, argc, argv, cref, is_lambda, passed_block);
1571 1572
}
1572 1573

  
1573 1574
VALUE
......
1606 1607
{
1607 1608
    if (rb_block_given_p()) {
1608 1609
	rb_check_arity(argc, 0, 0);
1609
	return yield_under(klass, self, 1, &self);
1610
	return yield_under(klass, self, 1, &self, VM_BLOCK_HANDLER_NONE);
1610 1611
    }
1611 1612
    else {
1612 1613
	VALUE file = Qundef;
......
1704 1705
rb_obj_instance_exec(int argc, const VALUE *argv, VALUE self)
1705 1706
{
1706 1707
    VALUE klass = singleton_class_for_eval(self);
1707
    return yield_under(klass, self, argc, argv);
1708
    return yield_under(klass, self, argc, argv, VM_BLOCK_HANDLER_NONE);
1709
}
1710

  
1711
/*
1712
 *  call-seq:
1713
 *     obj.instance_exec_with_block(arg..., proc) {|var..., &proc| block }  -> obj
1714
 *
1715
 *  Executes the given block within the context of the receiver
1716
 *  (_obj_). In order to set the context, the variable +self+ is set
1717
 *  to _obj_ while the code is executing, giving the code access to
1718
 *  _obj_'s instance variables. The final argument is the proc to pass
1719
 *  as the block argument to the block. Remaining arguments are passed
1720
 *  as block parameters.
1721
 *
1722
 *     class KlassWithSecret
1723
 *       def initialize
1724
 *         @secret = "a"
1725
 *       end
1726
 *     end
1727
 *     k = KlassWithSecret.new
1728
 *     k.instance_exec_with_block("b", 2, proc{|s| capitalize * 2}) do |x, y, &blk|
1729
 *       @secret << x
1730
 *       @secret.instance_exec(y, &blk)
1731
 *     end #=> "AbAb"
1732
 */
1733

  
1734
VALUE
1735
rb_obj_instance_exec_with_block(int argc, const VALUE *argv, VALUE self)
1736
{
1737
    VALUE block;
1738
    VALUE klass;
1739

  
1740
    rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
1741
    block = argv[--argc];
1742
    if (!rb_obj_is_proc(block)) {
1743
      rb_raise(rb_eTypeError, "last argument to instance_exec_with_block must be a Proc");
1744
    }
1745
    klass = singleton_class_for_eval(self);
1746
    return yield_under(klass, self, argc, argv, block);
1708 1747
}
1709 1748

  
1710 1749
/*
......
1765 1804
VALUE
1766 1805
rb_mod_module_exec(int argc, const VALUE *argv, VALUE mod)
1767 1806
{
1768
    return yield_under(mod, mod, argc, argv);
1807
    return yield_under(mod, mod, argc, argv, VM_BLOCK_HANDLER_NONE);
1769 1808
}
1770 1809

  
1771 1810
/*
......
2155 2194

  
2156 2195
    rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
2157 2196
    rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
2197
    rb_define_method(rb_cBasicObject, "instance_exec_with_block", rb_obj_instance_exec_with_block, -1);
2158 2198
    rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
2159 2199

  
2160 2200
#if 1
2161
-