From ff2d84cf88a7f4146d3d2cfaf2c75197719fb654 Mon Sep 17 00:00:00 2001 From: Dirkjan Bussink Date: Thu, 27 Sep 2012 14:44:20 +0200 Subject: [PATCH] Implement rb_block_call Fixes #1787 --- vm/builtin/nativemethod.cpp | 32 ++++++++++++++++++++++++++------ vm/builtin/nativemethod.hpp | 1 + vm/capi/18/include/ruby.h | 3 +++ vm/capi/19/include/ruby/ruby.h | 5 +++++ vm/capi/capi.cpp | 14 ++++++++++++++ 5 files changed, 49 insertions(+), 6 deletions(-) diff --git a/vm/builtin/nativemethod.cpp b/vm/builtin/nativemethod.cpp index c6a387b9bc..564ceaddb1 100644 --- a/vm/builtin/nativemethod.cpp +++ b/vm/builtin/nativemethod.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; } diff --git a/vm/builtin/nativemethod.hpp b/vm/builtin/nativemethod.hpp index 32895e4c9d..d82b30cc8d 100644 --- a/vm/builtin/nativemethod.hpp +++ b/vm/builtin/nativemethod.hpp @@ -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 diff --git a/vm/capi/18/include/ruby.h b/vm/capi/18/include/ruby.h index a420f40c90..da058a688a 100644 --- a/vm/capi/18/include/ruby.h +++ b/vm/capi/18/include/ruby.h @@ -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); diff --git a/vm/capi/19/include/ruby/ruby.h b/vm/capi/19/include/ruby/ruby.h index 62c3a8bc6f..c8d9cbbecb 100644 --- a/vm/capi/19/include/ruby/ruby.h +++ b/vm/capi/19/include/ruby/ruby.h @@ -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); diff --git a/vm/capi/capi.cpp b/vm/capi/capi.cpp index 26e7276f8c..72b2fe1878 100644 --- a/vm/capi/capi.cpp +++ b/vm/capi/capi.cpp @@ -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();