Permalink
Browse files

Implement rb_block_call

Fixes #1787
  • Loading branch information...
1 parent bf12361 commit ff2d84cf88a7f4146d3d2cfaf2c75197719fb654 @dbussink dbussink committed Sep 27, 2012
Showing with 49 additions and 6 deletions.
  1. +26 −6 vm/builtin/nativemethod.cpp
  2. +1 −0 vm/builtin/nativemethod.hpp
  3. +3 −0 vm/capi/18/include/ruby.h
  4. +5 −0 vm/capi/19/include/ruby/ruby.h
  5. +14 −0 vm/capi/capi.cpp
@@ -551,7 +551,7 @@ namespace rubinius {
/* A C function being used as a block */
case ITERATE_BLOCK: {
- VALUE cb = env->get_handle(nm->get_ivar(state, state->symbol("cb_data")));
+ VALUE cb_data = env->get_handle(nm->get_ivar(state, state->symbol("cb_data")));
Object* ob = nm->get_ivar(state, state->symbol("original_block"));
if(!ob->nil_p()) {
@@ -572,21 +572,41 @@ namespace rubinius {
break;
}
- VALUE ret = nm->func()(val, cb, receiver);
+ VALUE ret = nm->func()(val, cb_data, receiver);
+ return env->get_object(ret);
+ }
+
+ case C_BLOCK_CALL: {
+ VALUE val;
+ VALUE* ary = (VALUE*)alloca(sizeof(VALUE) * args.total());
+ VALUE cb_data = env->get_handle(nm->get_ivar(state, state->symbol("cb_data")));
+
+ if(args.total() > 0) {
+ val = env->get_handle(args.get_argument(0));
+ } else {
+ val = env->get_handle(cNil);
+ }
+
+ for (std::size_t i = 0; i < args.total(); ++i) {
+ ary[i] = env->get_handle(args.get_argument(i));
+ }
+
+ VALUE ret = nm->func()(val, cb_data, args.total(), ary);
+
return env->get_object(ret);
}
case C_LAMBDA: {
- VALUE cb = env->get_handle(nm->get_ivar(state, state->symbol("cb_data")));
+ VALUE cb_data = env->get_handle(nm->get_ivar(state, state->symbol("cb_data")));
VALUE val = env->get_handle(args.as_array(state));
- VALUE ret = nm->func()(val, cb);
+ VALUE ret = nm->func()(val, cb_data);
return env->get_object(ret);
}
case C_CALLBACK: {
- VALUE cb = env->get_handle(nm->get_ivar(state, state->symbol("cb_data")));
+ VALUE cb_data = env->get_handle(nm->get_ivar(state, state->symbol("cb_data")));
- nm->func()(cb);
+ nm->func()(cb_data);
return cNil;
}
@@ -261,6 +261,7 @@ namespace rubinius {
ITERATE_BLOCK = -98,
C_CALLBACK = -97,
C_LAMBDA = -96,
+ C_BLOCK_CALL = -95,
ARGS_IN_RUBY_ARRAY = -3,
RECEIVER_PLUS_ARGS_IN_RUBY_ARRAY = -2,
ARG_COUNT_ARGS_IN_C_ARRAY_PLUS_RECEIVER = -1
@@ -827,6 +827,9 @@ VALUE rb_uint2big(unsigned long number);
/* Converts implicit block into a new Proc. */
VALUE rb_block_proc();
+ typedef VALUE rb_block_call_func _((VALUE, VALUE));
+ VALUE rb_block_call(VALUE, ID, int, VALUE*, VALUE (*)(ANYARGS), VALUE);
+
VALUE rb_each(VALUE);
VALUE rb_iterate(VALUE (*ifunc)(VALUE), VALUE ary, VALUE(*cb)(ANYARGS), VALUE cb_data);
@@ -415,6 +415,8 @@ struct RFile {
// MRI checks also that it's not closed...
#define GetOpenFile(val, ptr) (ptr) = (capi_rio_struct(val))
#define rb_stdin rb_const_get(rb_cObject, rb_intern("STDIN"))
+#define rb_stdout rb_const_get(rb_cObject, rb_intern("STDOUT"))
+#define rb_stderr rb_const_get(rb_cObject, rb_intern("STDERR"))
#define GetReadFile(ptr) (ptr->f)
#define GetWriteFile(ptr) (ptr->f)
@@ -917,6 +919,9 @@ VALUE rb_uint2big(unsigned long number);
/* Converts implicit block into a new Proc. */
VALUE rb_block_proc();
+ typedef VALUE rb_block_call_func(VALUE, VALUE, int, VALUE*);
+ VALUE rb_block_call(VALUE,ID,int,VALUE*,VALUE(*)(ANYARGS),VALUE);
+
VALUE rb_each(VALUE);
VALUE rb_iterate(VALUE (*ifunc)(VALUE), VALUE ary, VALUE(*cb)(ANYARGS), VALUE cb_data);
View
@@ -630,6 +630,20 @@ extern "C" {
}
}
+ VALUE rb_block_call(VALUE obj, ID meth, int argc, VALUE* argv,
+ VALUE(*cb)(ANYARGS), VALUE cb_data) {
+ NativeMethodEnvironment* env = NativeMethodEnvironment::get();
+
+ if(cb) {
+ Proc* prc = capi::wrap_c_function((void*)cb, cb_data, C_BLOCK_CALL);
+ env->set_outgoing_block(env->get_handle(prc));
+ } else {
+ env->set_outgoing_block(env->get_handle(env->block()));
+ }
+
+ return rb_funcall2(obj, meth, argc, argv);
+ }
+
VALUE rb_apply(VALUE recv, ID mid, VALUE args) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
env->flush_cached_data();

0 comments on commit ff2d84c

Please sign in to comment.