Skip to content

Commit

Permalink
Symbol#to_proc now generates a Proc that can accept a variable number…
Browse files Browse the repository at this point in the history
… of arguments

git-svn-id: http://svn.macosforge.org/repository/ruby/MacRuby/trunk@4048 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information
lrz committed May 8, 2010
1 parent 4b9b95e commit dfec2d3
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 10 deletions.
4 changes: 2 additions & 2 deletions symbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -557,8 +557,8 @@ rsym_inspect(VALUE sym, SEL sel)
static VALUE
rsym_to_proc(VALUE sym, SEL sel)
{
SEL msel = sel_registerName(rb_id2name(SYM2ID(sym)));
rb_vm_block_t *b = rb_vm_create_block_calling_sel(msel);
ID mid = SYM2ID(sym);
rb_vm_block_t *b = rb_vm_create_block_calling_mid(mid);
return rb_proc_alloc_with_block(rb_cProc, b);
}

Expand Down
32 changes: 25 additions & 7 deletions vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3339,27 +3339,45 @@ rb_vm_create_block_from_method(rb_vm_method_t *method)

static VALUE
rb_vm_block_call_sel(VALUE rcv, SEL sel, VALUE **dvars, rb_vm_block_t *b,
VALUE x)
VALUE args)
{
if (x == Qnil) {
const VALUE *argv = RARRAY_PTR(args);
const long argc = RARRAY_LEN(args);
if (argc == 0) {
rb_raise(rb_eArgError, "no receiver given");
}
return rb_vm_call(x, (SEL)dvars[0], 0, NULL, false);
SEL msel = argc - 1 == 0 ? (SEL)dvars[0] : (SEL)dvars[1];
return rb_vm_call(argv[0], msel, argc - 1, &argv[1], false);
}

extern "C"
rb_vm_block_t *
rb_vm_create_block_calling_sel(SEL sel)
rb_vm_create_block_calling_mid(ID mid)
{
rb_vm_block_t *b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t)
+ sizeof(VALUE *));
+ (2 * sizeof(VALUE *)));

b->klass = 0;
b->proc = Qnil;
b->arity = rb_vm_arity(1);
b->flags = VM_BLOCK_PROC;
b->imp = (IMP)rb_vm_block_call_sel;
b->dvars[0] = (VALUE *)sel;

// Arity is -1.
b->arity.min = 0;
b->arity.max = -1;
b->arity.left_req = 0;
b->arity.real = 1;

// Prepare 2 selectors for the dispatcher later. One for 0 arity, one for
// 1 or more arity.
const char *midstr = rb_id2name(mid);
if (midstr[strlen(midstr) - 1] == ':') {
rb_raise(rb_eArgError, "invalid method name `%s'", midstr);
}
char buf[100];
snprintf(buf, sizeof buf, "%s:", midstr);
b->dvars[0] = (VALUE *)sel_registerName(midstr);
b->dvars[1] = (VALUE *)sel_registerName(buf);

return b;
}
Expand Down
2 changes: 1 addition & 1 deletion vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ VALUE rb_proc_alloc_with_block(VALUE klass, rb_vm_block_t *proc);

rb_vm_method_t *rb_vm_get_method(VALUE klass, VALUE obj, ID mid, int scope);
rb_vm_block_t *rb_vm_create_block_from_method(rb_vm_method_t *method);
rb_vm_block_t *rb_vm_create_block_calling_sel(SEL sel);
rb_vm_block_t *rb_vm_create_block_calling_mid(ID mid);
VALUE rb_vm_make_curry_proc(VALUE proc, VALUE passed, VALUE arity);

static inline rb_vm_block_t *
Expand Down

0 comments on commit dfec2d3

Please sign in to comment.