diff options
| author | Yukihiro Matsumoto <[email protected]> | 2012-08-13 21:03:08 +0900 |
|---|---|---|
| committer | Yukihiro Matsumoto <[email protected]> | 2012-08-13 21:03:08 +0900 |
| commit | cda1709a35ad7d495ec1a08793cd88b78e20c444 (patch) | |
| tree | 8934fa5e65c5be86f2adcbe5bf9f7282bb137204 | |
| parent | 59bf47e7f887ee987477d3c926d46dde87c1e15f (diff) | |
| download | mruby-cda1709a35ad7d495ec1a08793cd88b78e20c444.tar.gz mruby-cda1709a35ad7d495ec1a08793cd88b78e20c444.zip | |
setjmp in mrb_funcall_with_block if mrb->jmp is empty
| -rw-r--r-- | src/class.c | 38 | ||||
| -rw-r--r-- | src/vm.c | 53 |
2 files changed, 53 insertions, 38 deletions
diff --git a/src/class.c b/src/class.c index d6bb85a58..795527263 100644 --- a/src/class.c +++ b/src/class.c @@ -855,44 +855,6 @@ mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid) return m; } -#ifndef MRB_FUNCALL_ARGC_MAX -#define MRB_FUNCALL_ARGC_MAX 16 -#endif - -mrb_value -mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...) -{ - mrb_sym mid = mrb_intern(mrb, name); - va_list ap; - int i; - - if (argc == 0) { - return mrb_funcall_argv(mrb, self, mid, 0, 0); - } - else if (argc == 1) { - mrb_value v; - - va_start(ap, argc); - v = va_arg(ap, mrb_value); - va_end(ap); - return mrb_funcall_argv(mrb, self, mid, 1, &v); - } - else { - mrb_value argv[MRB_FUNCALL_ARGC_MAX]; - - if (argc > MRB_FUNCALL_ARGC_MAX) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%d)", MRB_FUNCALL_ARGC_MAX); - } - - va_start(ap, argc); - for (i = 0; i < argc; i++) { - argv[i] = va_arg(ap, mrb_value); - } - va_end(ap); - return mrb_funcall_argv(mrb, self, mid, argc, argv); - } -} - void mrb_obj_call_init(mrb_state *mrb, mrb_value obj, int argc, mrb_value *argv) { @@ -21,6 +21,7 @@ #include <string.h> #include <setjmp.h> #include <stddef.h> +#include <stdarg.h> #define STACK_INIT_SIZE 128 #define CALLINFO_INIT_SIZE 32 @@ -179,6 +180,44 @@ ecall(mrb_state *mrb, int i) if (!mrb->exc) mrb->exc = exc; } +#ifndef MRB_FUNCALL_ARGC_MAX +#define MRB_FUNCALL_ARGC_MAX 16 +#endif + +mrb_value +mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...) +{ + mrb_sym mid = mrb_intern(mrb, name); + va_list ap; + int i; + + if (argc == 0) { + return mrb_funcall_argv(mrb, self, mid, 0, 0); + } + else if (argc == 1) { + mrb_value v; + + va_start(ap, argc); + v = va_arg(ap, mrb_value); + va_end(ap); + return mrb_funcall_argv(mrb, self, mid, 1, &v); + } + else { + mrb_value argv[MRB_FUNCALL_ARGC_MAX]; + + if (argc > MRB_FUNCALL_ARGC_MAX) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%d)", MRB_FUNCALL_ARGC_MAX); + } + + va_start(ap, argc); + for (i = 0; i < argc; i++) { + argv[i] = va_arg(ap, mrb_value); + } + va_end(ap); + return mrb_funcall_argv(mrb, self, mid, argc, argv); + } +} + mrb_value mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mrb_value *argv, mrb_value blk) { @@ -189,6 +228,20 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr int n = mrb->ci->nregs; mrb_value val; + if (!mrb->jmp) { + jmp_buf c_jmp; + + if (setjmp(c_jmp) != 0) { /* error */ + mrb->jmp = 0; + return mrb_nil_value(); + } + mrb->jmp = &c_jmp; + /* recursive call */ + val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk); + mrb->jmp = 0; + return val; + } + if (argc < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%d)", argc); } |
