summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-kernel-ext
diff options
context:
space:
mode:
Diffstat (limited to 'mrbgems/mruby-kernel-ext')
-rw-r--r--mrbgems/mruby-kernel-ext/src/kernel.c144
-rw-r--r--mrbgems/mruby-kernel-ext/test/kernel.rb26
2 files changed, 120 insertions, 50 deletions
diff --git a/mrbgems/mruby-kernel-ext/src/kernel.c b/mrbgems/mruby-kernel-ext/src/kernel.c
index 7afa6fa5f..5b3dd6b35 100644
--- a/mrbgems/mruby-kernel-ext/src/kernel.c
+++ b/mrbgems/mruby-kernel-ext/src/kernel.c
@@ -3,70 +3,73 @@
#include <mruby/array.h>
#include <mruby/hash.h>
#include <mruby/range.h>
+#include <mruby/string.h>
+#include <mruby/numeric.h>
+#include <mruby/proc.h>
#include <mruby/presym.h>
static mrb_value
mrb_f_caller(mrb_state *mrb, mrb_value self)
{
- mrb_value bt, v, length;
+ mrb_value bt, v;
mrb_int bt_len, argc, lev, n;
+ argc = mrb_get_args(mrb, "|oi", &v, &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_range_p(v)) {
- mrb_int beg, len;
- if (mrb_range_beg_len(mrb, v, &beg, &len, bt_len, TRUE) == MRB_RANGE_OK) {
- lev = beg;
- n = len;
- }
- else {
- return mrb_nil_value();
- }
+ case 0:
+ lev = 1;
+ n = bt_len - 1;
+ break;
+ case 1:
+ if (mrb_range_p(v)) {
+ mrb_int beg, len;
+ if (mrb_range_beg_len(mrb, v, &beg, &len, bt_len, TRUE) == MRB_RANGE_OK) {
+ lev = beg;
+ n = len;
}
else {
- lev = mrb_int(mrb, v);
- if (lev < 0) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative level (%v)", v);
- }
- n = bt_len - lev;
+ return mrb_nil_value();
}
- break;
- case 2:
- lev = mrb_int(mrb, v);
- n = mrb_int(mrb, length);
+ }
+ else {
+ lev = mrb_as_int(mrb, v);
if (lev < 0) {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative level (%v)", v);
}
- if (n < 0) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative size (%v)", length);
- }
- break;
- default:
- lev = n = 0;
- break;
+ n = bt_len - lev;
+ }
+ break;
+ case 2:
+ lev = mrb_as_int(mrb, v);
+ break;
+ default:
+ /* not reached */
+ lev = n = 0;
+ break;
}
-
- if (n == 0) {
+ if (lev >= bt_len) return mrb_nil_value();
+ if (lev < 0) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative level (%v)", v);
+ }
+ if (n < 0) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative size (%d)", n);
+ }
+ if (n == 0 || bt_len <= lev) {
return mrb_ary_new(mrb);
}
-
- return mrb_funcall_id(mrb, bt, MRB_OPSYM(aref), 2, mrb_fixnum_value(lev), mrb_fixnum_value(n));
+ if (bt_len <= n + lev) n = bt_len - lev - 1;
+ return mrb_ary_new_from_values(mrb, n, RARRAY_PTR(bt)+lev+1);
}
/*
* call-seq:
* __method__ -> symbol
*
- * Returns the name at the definition of the current method as a
- * Symbol.
+ * Returns the called name of the current method as a Symbol.
* If called outside of a method, it returns <code>nil</code>.
*
*/
@@ -75,6 +78,27 @@ mrb_f_method(mrb_state *mrb, mrb_value self)
{
mrb_callinfo *ci = mrb->c->ci;
ci--;
+ if (ci->proc->e.env->tt == MRB_TT_ENV && ci->proc->e.env->mid)
+ return mrb_symbol_value(ci->proc->e.env->mid);
+ else if (ci->mid)
+ return mrb_symbol_value(ci->mid);
+ else
+ return mrb_nil_value();
+}
+
+/*
+ * call-seq:
+ * __callee__ -> symbol
+ *
+ * Returns the called name of the current method as a Symbol.
+ * If called outside of a method, it returns <code>nil</code>.
+ *
+ */
+static mrb_value
+mrb_f_callee(mrb_state *mrb, mrb_value self)
+{
+ mrb_callinfo *ci = mrb->c->ci;
+ ci--;
if (ci->mid)
return mrb_symbol_value(ci->mid);
else
@@ -106,11 +130,43 @@ mrb_f_method(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_f_integer(mrb_state *mrb, mrb_value self)
{
- mrb_value arg;
+ mrb_value val, tmp;
mrb_int base = 0;
- mrb_get_args(mrb, "o|i", &arg, &base);
- return mrb_convert_to_integer(mrb, arg, base);
+ mrb_get_args(mrb, "o|i", &val, &base);
+ if (mrb_nil_p(val)) {
+ if (base != 0) goto arg_error;
+ mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Integer");
+ }
+ switch (mrb_type(val)) {
+#ifndef MRB_NO_FLOAT
+ case MRB_TT_FLOAT:
+ if (base != 0) goto arg_error;
+ return mrb_float_to_integer(mrb, val);
+#endif
+
+ case MRB_TT_INTEGER:
+ if (base != 0) goto arg_error;
+ return val;
+
+ case MRB_TT_STRING:
+ string_conv:
+ return mrb_str_to_integer(mrb, val, base, TRUE);
+
+ default:
+ break;
+ }
+ if (base != 0) {
+ tmp = mrb_obj_as_string(mrb, val);
+ if (mrb_string_p(tmp)) {
+ val = tmp;
+ goto string_conv;
+ }
+arg_error:
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "base specified for non string value");
+ }
+ /* to raise TypeError */
+ return mrb_to_integer(mrb, val);
}
#ifndef MRB_NO_FLOAT
@@ -131,7 +187,7 @@ mrb_f_float(mrb_state *mrb, mrb_value self)
{
mrb_value arg = mrb_get_arg1(mrb);
- return mrb_Float(mrb, arg);
+ return mrb_to_float(mrb, arg);
}
#endif
@@ -201,7 +257,8 @@ mrb_f_hash(mrb_state *mrb, mrb_value self)
if (mrb_nil_p(arg) || (mrb_array_p(arg) && RARRAY_LEN(arg) == 0)) {
return mrb_hash_new(mrb);
}
- return mrb_ensure_hash_type(mrb, arg);
+ mrb_ensure_hash_type(mrb, arg);
+ return arg;
}
void
@@ -212,6 +269,7 @@ mrb_mruby_kernel_ext_gem_init(mrb_state *mrb)
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_OPT(2));
mrb_define_method(mrb, krn, "__method__", mrb_f_method, MRB_ARGS_NONE());
+ mrb_define_method(mrb, krn, "__callee__", mrb_f_callee, MRB_ARGS_NONE());
mrb_define_module_function(mrb, krn, "Integer", mrb_f_integer, MRB_ARGS_ARG(1,1));
#ifndef MRB_NO_FLOAT
mrb_define_module_function(mrb, krn, "Float", mrb_f_float, MRB_ARGS_REQ(1));
diff --git a/mrbgems/mruby-kernel-ext/test/kernel.rb b/mrbgems/mruby-kernel-ext/test/kernel.rb
index fc4402b3d..e5876f976 100644
--- a/mrbgems/mruby-kernel-ext/test/kernel.rb
+++ b/mrbgems/mruby-kernel-ext/test/kernel.rb
@@ -38,17 +38,29 @@ assert('Kernel.caller, Kernel#caller') do
end
assert('Kernel#__method__') do
- assert_equal(:m, Class.new {def m; __method__; end}.new.m)
- assert_equal(:m, Class.new {define_method(:m) {__method__}}.new.m)
c = Class.new do
- [:m1, :m2].each do |m|
- define_method(m) do
- __method__
- end
- end
+ def m1; __method__ end
+ define_method(:m2) {__method__}
+ alias m3 m1
+ alias_method :m4, :m2
+ end
+ assert_equal(:m1, c.new.m1)
+ assert_equal(:m2, c.new.m2)
+ assert_equal(:m1, c.new.m3)
+ assert_equal(:m2, c.new.m4)
+end
+
+assert('Kernel#__callee__') do
+ c = Class.new do
+ def m1; __callee__ end
+ define_method(:m2) {__callee__}
+ alias m3 m1
+ alias_method :m4, :m2
end
assert_equal(:m1, c.new.m1)
assert_equal(:m2, c.new.m2)
+ assert_equal(:m3, c.new.m3)
+ assert_equal(:m4, c.new.m4)
end
assert('Kernel#Integer') do