Project

General

Profile

Feature #12093 ยป 0002-Update-iseq.eval-to-accept-optional-binding-FIXES-Bu.patch

dalehamel (Dale Hamel), 07/23/2019 04:35 AM

View differences:

iseq.c
1332 1332

  
1333 1333
/*
1334 1334
 *  call-seq:
1335
 *     iseq.eval -> obj
1335
 *     iseq.eval([binding]) -> obj
1336 1336
 *
1337 1337
 *  Evaluates the instruction sequence and returns the result.
1338 1338
 *
1339 1339
 *      RubyVM::InstructionSequence.compile("1 + 2").eval #=> 3
1340
 */
1341
static VALUE
1342
iseqw_eval(VALUE self)
1343
{
1344
    rb_secure(1);
1345
    return rb_iseq_eval(iseqw_check(self));
1346
}
1347

  
1348
/*
1349
 *  call-seq:
1350
 *     iseq.eval_with(binding) -> obj
1351 1340
 *
1352
 *  Evaluates the instruction sequence and returns the result.
1341
 *  If binding is given, which must be a Binding object, the evaluation is performed in its context.
1353 1342
 *
1354 1343
 *      obj = Struct.new(:a, :b).new(1, 2)
1355 1344
 *      bind = obj.instance_eval {binding}
1356
 *      RubyVM::InstructionSequence.compile("a + b").eval_with(bind) #=> 3
1345
 *      RubyVM::InstructionSequence.compile("a + b").eval(bind) #=> 3
1357 1346
 */
1358 1347
static VALUE
1359
iseq_eval_with(VALUE self, VALUE scope)
1348
iseqw_eval(int argc, const VALUE *argv, VALUE self)
1360 1349
{
1361
    rb_secure(1);
1362
    return rb_iseq_eval_in_scope(iseqw_check(self), scope);
1350
    VALUE scope;
1351

  
1352
    if (argc == 0) {
1353
        rb_secure(1);
1354
        return rb_iseq_eval(iseqw_check(self));
1355
    }
1356
    else {
1357
        rb_scan_args(argc, argv, "01", &scope);
1358
        rb_secure(1);
1359
        return rb_iseq_eval_in_scope(iseqw_check(self), scope);
1360
    }
1363 1361
}
1364 1362

  
1365 1363
/*
......
3499 3497
    rb_define_method(rb_cISeq, "disasm", iseqw_disasm, 0);
3500 3498
    rb_define_method(rb_cISeq, "disassemble", iseqw_disasm, 0);
3501 3499
    rb_define_method(rb_cISeq, "to_a", iseqw_to_a, 0);
3502
    rb_define_method(rb_cISeq, "eval", iseqw_eval, 0);
3503
    rb_define_method(rb_cISeq, "eval_with", iseq_eval_with, 1);
3500
    rb_define_method(rb_cISeq, "eval", iseqw_eval, -1);
3504 3501

  
3505 3502
    rb_define_method(rb_cISeq, "to_binary", iseqw_to_binary, -1);
3506 3503
    rb_define_singleton_method(rb_cISeq, "load_from_binary", iseqw_s_load_from_binary, 1);
test/ruby/test_iseq.rb
281 281
    end;
282 282
  end
283 283

  
284
  def test_eval_with_binding
285
    obj = Struct.new(:a, :b).new(1, 2)
286
    bind = obj.instance_eval {binding}
287
    val = RubyVM::InstructionSequence.compile("a + b").eval(bind)
288
    assert_equal(3, val)
289
  end
290

  
284 291
  def test_inspect
285 292
    %W[foo \u{30d1 30b9}].each do |name|
286 293
      assert_match(/@#{name}/, ISeq.compile("", name).inspect, name)
vm.c
2141 2141
VALUE
2142 2142
rb_iseq_eval_in_scope(const rb_iseq_t *iseq, VALUE scope)
2143 2143
{
2144
    rb_thread_t *th = GET_THREAD();
2145
    rb_binding_t *bind = rb_check_typeddata(scope, &ruby_binding_data_type);
2146
    struct rb_block *base_block = &bind->block;
2144
    rb_execution_context_t *ec = GET_EC();
2145
    rb_binding_t *bind = Check_TypedStruct(scope, &ruby_binding_data_type);
2146

  
2147
    vm_set_eval_stack(ec, iseq, NULL, &bind->block);
2147 2148

  
2149
    /* save new env */
2148 2150
    if (iseq->body->local_table_size > 0) {
2149
	vm_bind_update_env(bind, vm_make_env_object(th, th->cfp));
2151
      vm_bind_update_env(scope, bind, vm_make_env_object(ec, ec->cfp));
2150 2152
    }
2151
#if 0
2152
    iseq_set_parent_block(iseq, base_block);
2153
    iseq_set_local_table(iseq, rb_vm_cref()->nd_tbl);
2154
#endif
2155
    vm_set_eval_stack(th, iseq, 0, base_block);
2156 2153

  
2157
    return vm_exec(th);
2154
    return vm_exec(ec, TRUE);
2158 2155
}
2159 2156

  
2160 2157
VALUE
2161
-