Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rubinius/rubinius
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 24b4b64efced
Choose a base ref
...
head repository: rubinius/rubinius
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: af5b2edfa2d1
Choose a head ref
  • 2 commits
  • 6 files changed
  • 1 contributor

Commits on Sep 18, 2014

  1. Copy the full SHA
    de6cc7d View commit details
  2. Copy the full SHA
    af5b2ed View commit details
Showing with 68 additions and 0 deletions.
  1. +15 −0 kernel/common/capi.rb
  2. +21 −0 spec/ruby/optional/capi/ext/kernel_spec.c
  3. +1 −0 spec/ruby/optional/capi/ext/rubyspec.h
  4. +17 −0 spec/ruby/optional/capi/kernel_spec.rb
  5. +11 −0 vm/capi/kernel.cpp
  6. +3 −0 vm/include/capi/ruby.h
15 changes: 15 additions & 0 deletions kernel/common/capi.rb
Original file line number Diff line number Diff line change
@@ -87,5 +87,20 @@ def self.rb_str_conv_enc_opts(str, from, to, flags, opts)

return status == :finished ? result : str
end

def self.rb_eval_string_wrap(str)
vs = clean_binding
cs = Rubinius::ConstantScope.new(Object)
cs = Rubinius::ConstantScope.new(Module.new, cs)
binding = Binding.setup(vs, nil, cs)

[eval(str, binding), true]
rescue
[nil, false]
end

def self.clean_binding
return Rubinius::VariableScope.current
end
end
end
21 changes: 21 additions & 0 deletions spec/ruby/optional/capi/ext/kernel_spec.c
Original file line number Diff line number Diff line change
@@ -111,6 +111,23 @@ VALUE kernel_spec_rb_eval_string(VALUE self, VALUE str) {
}
#endif

#ifdef HAVE_RB_EVAL_STRING_WRAP
VALUE kernel_spec_rb_eval_string_wrap(VALUE self, VALUE str) {
VALUE ary = rb_ary_new();

int state;
VALUE result = rb_eval_string_wrap(RSTRING_PTR(str), &state);

rb_ary_store(ary, 0, result);
rb_ary_store(ary, 1, INT2FIX(state));

// return a 2-element array
// ary[0]: the result of the eval
// ary[1]: state
return ary;
}
#endif

#ifdef HAVE_RB_RAISE
VALUE kernel_spec_rb_raise(VALUE self, VALUE hash) {
rb_hash_aset(hash, ID2SYM(rb_intern("stage")), ID2SYM(rb_intern("before")));
@@ -309,6 +326,10 @@ void Init_kernel_spec() {
rb_define_method(cls, "rb_eval_string", kernel_spec_rb_eval_string, 1);
#endif

#ifdef HAVE_RB_EVAL_STRING_WRAP
rb_define_method(cls, "rb_eval_string_wrap", kernel_spec_rb_eval_string_wrap, 1);
#endif

#ifdef HAVE_RB_RAISE
rb_define_method(cls, "rb_raise", kernel_spec_rb_raise, 1);
#endif
1 change: 1 addition & 0 deletions spec/ruby/optional/capi/ext/rubyspec.h
Original file line number Diff line number Diff line change
@@ -347,6 +347,7 @@
#define HAVE_RB_BLOCK_CALL 1
#define HAVE_RB_ENSURE 1
#define HAVE_RB_EVAL_STRING 1
#define HAVE_RB_EVAL_STRING_WRAP 1
#define HAVE_RB_EXEC_RECURSIVE 1
#define HAVE_RB_F_SPRINTF 1
#define HAVE_RB_NEED_BLOCK 1
17 changes: 17 additions & 0 deletions spec/ruby/optional/capi/kernel_spec.rb
Original file line number Diff line number Diff line change
@@ -388,6 +388,23 @@
end
end

describe "rb_eval_string_wrap" do
it "evaluates a string of ruby code" do
eval_result = @s.rb_eval_string_wrap("1+1")[0]
eval_result.should == 2
end

it "sets state to 0 on success" do
state = @s.rb_eval_string_wrap("1+1")[1]
state.should == 0
end

it "sets state to nonzero on failure" do
state = @s.rb_eval_string_wrap("5.sort")[1]
state.should_not == 0
end
end

describe "rb_block_proc" do
it "converts the implicit block into a proc" do
proc = @s.rb_block_proc() { 1+1 }
11 changes: 11 additions & 0 deletions vm/capi/kernel.cpp
Original file line number Diff line number Diff line change
@@ -248,6 +248,17 @@ extern "C" {
return rb_funcall(rb_mKernel, rb_intern("eval"), 1, rb_str_new2(str));
}

VALUE rb_eval_string_wrap(const char* str, int* state) {
// ary[0]: the result of the eval
// ary[1]: 'true' if the eval succeeds, 'false' otherwise
VALUE* ary = RARRAY_PTR(rb_funcall(rb_mCAPI, rb_intern("rb_eval_string_wrap"), 1, rb_str_new2(str)));

// 6 is an arbitrary value. if the eval fails, state just needs to be set to an nonzero value
*state = (ary[1] == Qtrue) ? 0 : 6;

return ary[0];
}

VALUE rb_block_proc() {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
return rb_funcall(rb_cProc, rb_intern("__from_block__"), 1, env->get_handle(env->block()));
3 changes: 3 additions & 0 deletions vm/include/capi/ruby.h
Original file line number Diff line number Diff line change
@@ -1594,6 +1594,9 @@ VALUE rb_uint2big(unsigned long number);
/** Evaluate the given string. */
VALUE rb_eval_string(const char* string);

/** Evaluate the given string in an isolated binding. */
VALUE rb_eval_string_wrap(const char* string, int* state);

/** Create a String from the C string. */
VALUE rb_tainted_str_new2(const char* string);