Created
November 12, 2009 22:58
-
-
Save takaokouji/233397 to your computer and use it in GitHub Desktop.
This is the patch for MacRuby that is implemented rb_define_method. But not support to call method with blocks.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/class.c b/class.c | |
| index ed7ccaf..e4bdceb 100644 | |
| --- a/class.c | |
| +++ b/class.c | |
| @@ -1003,7 +1003,7 @@ name_to_sel(const char *name, const int arity) | |
| return sel_registerName(name); | |
| } | |
| -static void | |
| +static rb_vm_method_node_t * | |
| rb_objc_add_method(VALUE klass, const char *name, void *imp, const int arity, | |
| const int noex, bool direct) | |
| { | |
| @@ -1014,8 +1014,8 @@ rb_objc_add_method(VALUE klass, const char *name, void *imp, const int arity, | |
| NODE *body = rb_vm_cfunc_node_from_imp((Class)klass, arity, (IMP)imp, noex); | |
| rb_objc_retain(body); | |
| - rb_vm_define_method((Class)klass, name_to_sel(name, arity), (IMP)imp, | |
| - body, direct); | |
| + return rb_vm_define_method((Class)klass, name_to_sel(name, arity), (IMP)imp, | |
| + body, direct); | |
| } | |
| void | |
| @@ -1046,28 +1046,38 @@ rb_objc_define_module_function(VALUE module, const char *name, void *imp, | |
| rb_objc_define_method(*(VALUE *)module, name, imp, arity); | |
| } | |
| +static rb_vm_method_node_t * | |
| +rb_mri_add_method(VALUE klass, const char *name, void *imp, const int arity, | |
| + const int noex, bool direct) | |
| +{ | |
| + rb_vm_method_node_t *node = | |
| + rb_objc_add_method(klass, name, imp, arity, noex, direct); | |
| + node->flags |= VM_METHOD_MRI; | |
| + return node; | |
| +} | |
| + | |
| void | |
| rb_define_method_id(VALUE klass, ID name, VALUE (*func)(ANYARGS), int argc) | |
| { | |
| - rb_add_method(klass, name, NEW_CFUNC(func,argc), NOEX_PUBLIC); | |
| + rb_mri_add_method(klass, rb_id2name(name), func, argc, NOEX_PUBLIC, false); | |
| } | |
| void | |
| rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc) | |
| { | |
| - rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PUBLIC); | |
| + rb_mri_add_method(klass, name, func, argc, NOEX_PUBLIC, false); | |
| } | |
| void | |
| rb_define_protected_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc) | |
| { | |
| - rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PROTECTED); | |
| + rb_mri_add_method(klass, name, func, argc, NOEX_PROTECTED, false); | |
| } | |
| void | |
| rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc) | |
| { | |
| - rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PRIVATE); | |
| + rb_mri_add_method(klass, name, func, argc, NOEX_PRIVATE, false); | |
| } | |
| void | |
| diff --git a/dispatcher.cpp b/dispatcher.cpp | |
| index 0a9202f..cd346c8 100644 | |
| --- a/dispatcher.cpp | |
| +++ b/dispatcher.cpp | |
| @@ -156,6 +156,51 @@ __rb_vm_rcall(VALUE self, SEL sel, IMP pimp, const rb_vm_arity_t &arity, | |
| abort(); | |
| } | |
| +static force_inline VALUE | |
| +__rb_vm_rcall_nosel(VALUE self, SEL sel, IMP pimp, const rb_vm_arity_t &arity, | |
| + int argc, const VALUE *argv) | |
| +{ | |
| + if ((arity.real != argc) || (arity.max == -1)) { | |
| + VALUE *new_argv = (VALUE *)alloca(sizeof(VALUE) * arity.real); | |
| + __rb_vm_fix_args(argv, new_argv, arity, argc); | |
| + argv = new_argv; | |
| + argc = arity.real; | |
| + } | |
| + | |
| + assert(pimp != NULL); | |
| + | |
| + VALUE (*imp)(VALUE, ...) = (VALUE (*)(VALUE, ...))pimp; | |
| + | |
| + switch (argc) { | |
| + case 0: | |
| + return (*imp)(self); | |
| + case 1: | |
| + return (*imp)(self, argv[0]); | |
| + case 2: | |
| + return (*imp)(self, argv[0], argv[1]); | |
| + case 3: | |
| + return (*imp)(self, argv[0], argv[1], argv[2]); | |
| + case 4: | |
| + return (*imp)(self, argv[0], argv[1], argv[2], argv[3]); | |
| + case 5: | |
| + return (*imp)(self, argv[0], argv[1], argv[2], argv[3], argv[4]); | |
| + case 6: | |
| + return (*imp)(self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); | |
| + case 7: | |
| + return (*imp)(self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); | |
| + case 8: | |
| + return (*imp)(self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]); | |
| + case 9: | |
| + return (*imp)(self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]); | |
| + case 10: | |
| + return (*imp)(self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]); | |
| + case 11: | |
| + return (*imp)(self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]); | |
| + } | |
| + printf("invalid argc %d\n", argc); | |
| + abort(); | |
| +} | |
| + | |
| static void | |
| vm_gen_bs_func_types(int argc, const VALUE *argv, | |
| bs_element_function_t *bs_func, std::string &types) | |
| @@ -407,6 +452,28 @@ __rb_vm_ruby_dispatch(VALUE top, VALUE self, SEL sel, | |
| return Qnil; | |
| } | |
| + if (node->flags & VM_METHOD_MRI) { | |
| + if ((node->flags & VM_METHOD_FBODY) && arity.max != arity.min) { | |
| + // Calling a function defined with rb_objc_define_method with | |
| + // a negative arity, which means a different calling convention. | |
| + if (arity.real == 2) { | |
| + return ((VALUE (*)(int, const VALUE *, VALUE))node->ruby_imp) | |
| + (argc, argv, self); | |
| + } | |
| + else if (arity.real == 1) { | |
| + return ((VALUE (*)(VALUE, ...))node->ruby_imp) | |
| + (rb_ary_new4(argc, argv), self); | |
| + } | |
| + else { | |
| + printf("invalid negative arity for C function %d\n", | |
| + arity.real); | |
| + abort(); | |
| + } | |
| + } | |
| + | |
| + return __rb_vm_rcall_nosel(self, sel, node->ruby_imp, arity, argc, argv); | |
| + } | |
| + | |
| if ((node->flags & VM_METHOD_FBODY) && arity.max != arity.min) { | |
| // Calling a function defined with rb_objc_define_method with | |
| // a negative arity, which means a different calling convention. | |
| diff --git a/ext/readline/extconf.rb b/ext/readline/extconf.rb | |
| index 4e4c45d..24a4485 100644 | |
| --- a/vm.h | |
| +++ b/vm.h | |
| @@ -61,6 +61,7 @@ typedef struct { | |
| #define VM_METHOD_PRIVATE 2 // method is private (runtime) | |
| #define VM_METHOD_PROTECTED 4 // method is protected (runtime) | |
| #define VM_METHOD_FBODY 8 // method has a MRI C prototype (compilation) | |
| +#define VM_METHOD_MRI 16 // method has a MRI C arguments (compilation) | |
| static inline int | |
| rb_vm_noex_flag(const int noex) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment