diff options
| author | ksss <[email protected]> | 2017-01-14 10:15:40 +0900 |
|---|---|---|
| committer | ksss <[email protected]> | 2017-01-14 22:01:20 +0900 |
| commit | 6f9cb7406aed5f06dffdb64356d2891aba4a15b1 (patch) | |
| tree | 540a77996f115716d42d366fddb94ddc6c83a95a /mrbgems/mruby-kernel-ext/src | |
| parent | c4491e477b40adc842ef76e524647607780c8f25 (diff) | |
| download | mruby-6f9cb7406aed5f06dffdb64356d2891aba4a15b1.tar.gz mruby-6f9cb7406aed5f06dffdb64356d2891aba4a15b1.zip | |
Implement Kernel.#caller
Diffstat (limited to 'mrbgems/mruby-kernel-ext/src')
| -rw-r--r-- | mrbgems/mruby-kernel-ext/src/kernel.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/mrbgems/mruby-kernel-ext/src/kernel.c b/mrbgems/mruby-kernel-ext/src/kernel.c index d2153be4a..1aa40260e 100644 --- a/mrbgems/mruby-kernel-ext/src/kernel.c +++ b/mrbgems/mruby-kernel-ext/src/kernel.c @@ -2,6 +2,64 @@ #include <mruby/error.h> #include <mruby/array.h> #include <mruby/hash.h> +#include <mruby/range.h> + +static mrb_value +mrb_f_caller(mrb_state *mrb, mrb_value self) +{ + mrb_value bt, v, length; + mrb_int bt_len, argc, lev, n; + + bt = mrb_get_backtrace(mrb); + bt_len = RARRAY_LEN(bt); + argc = mrb_get_args(mrb, "|oo", &v, &length); + + switch (argc) { + case 0: + lev = 1; + n = bt_len - lev; + break; + case 1: + if (mrb_type(v) == MRB_TT_RANGE) { + mrb_int beg, len; + if (mrb_range_beg_len(mrb, v, &beg, &len, bt_len)) { + lev = beg; + n = len; + } + else { + return mrb_nil_value(); + } + } + else { + v = mrb_to_int(mrb, v); + lev = mrb_fixnum(v); + if (lev < 0) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative level (%S)", v); + } + n = bt_len - lev; + } + break; + case 2: + lev = mrb_fixnum(mrb_to_int(mrb, v)); + n = mrb_fixnum(mrb_to_int(mrb, length)); + if (lev < 0) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative level (%S)", v); + } + if (n < 0) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative size (%S)", length); + } + break; + default: + lev = n = 0; + break; + } + + if (n == 0) { + return mrb_ary_new(mrb); + } + + return mrb_funcall(mrb, bt, "[]", 2, mrb_fixnum_value(lev), mrb_fixnum_value(n)); +} /* * call-seq: @@ -170,6 +228,7 @@ mrb_mruby_kernel_ext_gem_init(mrb_state *mrb) struct RClass *krn = mrb->kernel_module; mrb_define_module_function(mrb, krn, "fail", mrb_f_raise, MRB_ARGS_OPT(2)); + mrb_define_module_function(mrb, krn, "caller", mrb_f_caller, MRB_ARGS_NONE()); mrb_define_method(mrb, krn, "__method__", mrb_f_method, MRB_ARGS_NONE()); mrb_define_module_function(mrb, krn, "Integer", mrb_f_integer, MRB_ARGS_ANY()); mrb_define_module_function(mrb, krn, "Float", mrb_f_float, MRB_ARGS_REQ(1)); |
