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
/*
* call-seq:
* iseq.eval -> obj
* iseq.eval([binding]) -> obj
*
* Evaluates the instruction sequence and returns the result.
*
* RubyVM::InstructionSequence.compile("1 + 2").eval #=> 3
*/
static VALUE
iseqw_eval(VALUE self)
{
rb_secure(1);
return rb_iseq_eval(iseqw_check(self));
}
/*
* call-seq:
* iseq.eval_with(binding) -> obj
*
* Evaluates the instruction sequence and returns the result.
* If binding is given, which must be a Binding object, the evaluation is performed in its context.
*
* obj = Struct.new(:a, :b).new(1, 2)
* bind = obj.instance_eval {binding}
* RubyVM::InstructionSequence.compile("a + b").eval_with(bind) #=> 3
* RubyVM::InstructionSequence.compile("a + b").eval(bind) #=> 3
*/
static VALUE
iseq_eval_with(VALUE self, VALUE scope)
iseqw_eval(int argc, const VALUE *argv, VALUE self)
{
rb_secure(1);
return rb_iseq_eval_in_scope(iseqw_check(self), scope);
VALUE scope;
if (argc == 0) {
rb_secure(1);
return rb_iseq_eval(iseqw_check(self));
}
else {
rb_scan_args(argc, argv, "01", &scope);
rb_secure(1);
return rb_iseq_eval_in_scope(iseqw_check(self), scope);
}
}
/*
......
rb_define_method(rb_cISeq, "disasm", iseqw_disasm, 0);
rb_define_method(rb_cISeq, "disassemble", iseqw_disasm, 0);
rb_define_method(rb_cISeq, "to_a", iseqw_to_a, 0);
rb_define_method(rb_cISeq, "eval", iseqw_eval, 0);
rb_define_method(rb_cISeq, "eval_with", iseq_eval_with, 1);
rb_define_method(rb_cISeq, "eval", iseqw_eval, -1);
rb_define_method(rb_cISeq, "to_binary", iseqw_to_binary, -1);
rb_define_singleton_method(rb_cISeq, "load_from_binary", iseqw_s_load_from_binary, 1);
test/ruby/test_iseq.rb
end;
end
def test_eval_with_binding
obj = Struct.new(:a, :b).new(1, 2)
bind = obj.instance_eval {binding}
val = RubyVM::InstructionSequence.compile("a + b").eval(bind)
assert_equal(3, val)
end
def test_inspect
%W[foo \u{30d1 30b9}].each do |name|
assert_match(/@#{name}/, ISeq.compile("", name).inspect, name)
vm.c
VALUE
rb_iseq_eval_in_scope(const rb_iseq_t *iseq, VALUE scope)
{
rb_thread_t *th = GET_THREAD();
rb_binding_t *bind = rb_check_typeddata(scope, &ruby_binding_data_type);
struct rb_block *base_block = &bind->block;
rb_execution_context_t *ec = GET_EC();
rb_binding_t *bind = Check_TypedStruct(scope, &ruby_binding_data_type);
vm_set_eval_stack(ec, iseq, NULL, &bind->block);
/* save new env */
if (iseq->body->local_table_size > 0) {
vm_bind_update_env(bind, vm_make_env_object(th, th->cfp));
vm_bind_update_env(scope, bind, vm_make_env_object(ec, ec->cfp));
}
#if 0
iseq_set_parent_block(iseq, base_block);
iseq_set_local_table(iseq, rb_vm_cref()->nd_tbl);
#endif
vm_set_eval_stack(th, iseq, 0, base_block);
return vm_exec(th);
return vm_exec(ec, TRUE);
}
VALUE
(1-1/2)