Skip to content

Commit

Permalink
Implement rb_block_call
Browse files Browse the repository at this point in the history
  • Loading branch information
dbussink committed Sep 27, 2012
1 parent bf12361 commit ff2d84c
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 6 deletions.
32 changes: 26 additions & 6 deletions vm/builtin/nativemethod.cpp
Expand Up @@ -551,7 +551,7 @@ namespace rubinius {


/* A C function being used as a block */ /* A C function being used as a block */
case ITERATE_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")); Object* ob = nm->get_ivar(state, state->symbol("original_block"));
if(!ob->nil_p()) { if(!ob->nil_p()) {
Expand All @@ -572,21 +572,41 @@ namespace rubinius {
break; 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); return env->get_object(ret);
} }


case C_LAMBDA: { 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 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); return env->get_object(ret);
} }


case C_CALLBACK: { 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; return cNil;
} }
Expand Down
1 change: 1 addition & 0 deletions vm/builtin/nativemethod.hpp
Expand Up @@ -261,6 +261,7 @@ namespace rubinius {
ITERATE_BLOCK = -98, ITERATE_BLOCK = -98,
C_CALLBACK = -97, C_CALLBACK = -97,
C_LAMBDA = -96, C_LAMBDA = -96,
C_BLOCK_CALL = -95,
ARGS_IN_RUBY_ARRAY = -3, ARGS_IN_RUBY_ARRAY = -3,
RECEIVER_PLUS_ARGS_IN_RUBY_ARRAY = -2, RECEIVER_PLUS_ARGS_IN_RUBY_ARRAY = -2,
ARG_COUNT_ARGS_IN_C_ARRAY_PLUS_RECEIVER = -1 ARG_COUNT_ARGS_IN_C_ARRAY_PLUS_RECEIVER = -1
Expand Down
3 changes: 3 additions & 0 deletions vm/capi/18/include/ruby.h
Expand Up @@ -827,6 +827,9 @@ VALUE rb_uint2big(unsigned long number);
/* Converts implicit block into a new Proc. */ /* Converts implicit block into a new Proc. */
VALUE rb_block_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_each(VALUE);


VALUE rb_iterate(VALUE (*ifunc)(VALUE), VALUE ary, VALUE(*cb)(ANYARGS), VALUE cb_data); VALUE rb_iterate(VALUE (*ifunc)(VALUE), VALUE ary, VALUE(*cb)(ANYARGS), VALUE cb_data);
Expand Down
5 changes: 5 additions & 0 deletions vm/capi/19/include/ruby/ruby.h
Expand Up @@ -415,6 +415,8 @@ struct RFile {
// MRI checks also that it's not closed... // MRI checks also that it's not closed...
#define GetOpenFile(val, ptr) (ptr) = (capi_rio_struct(val)) #define GetOpenFile(val, ptr) (ptr) = (capi_rio_struct(val))
#define rb_stdin rb_const_get(rb_cObject, rb_intern("STDIN")) #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 GetReadFile(ptr) (ptr->f)
#define GetWriteFile(ptr) (ptr->f) #define GetWriteFile(ptr) (ptr->f)
Expand Down Expand Up @@ -917,6 +919,9 @@ VALUE rb_uint2big(unsigned long number);
/* Converts implicit block into a new Proc. */ /* Converts implicit block into a new Proc. */
VALUE rb_block_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_each(VALUE);


VALUE rb_iterate(VALUE (*ifunc)(VALUE), VALUE ary, VALUE(*cb)(ANYARGS), VALUE cb_data); VALUE rb_iterate(VALUE (*ifunc)(VALUE), VALUE ary, VALUE(*cb)(ANYARGS), VALUE cb_data);
Expand Down
14 changes: 14 additions & 0 deletions vm/capi/capi.cpp
Expand Up @@ -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) { VALUE rb_apply(VALUE recv, ID mid, VALUE args) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get(); NativeMethodEnvironment* env = NativeMethodEnvironment::get();
env->flush_cached_data(); env->flush_cached_data();
Expand Down

0 comments on commit ff2d84c

Please sign in to comment.