summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2014-06-03 16:34:21 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2014-06-03 16:34:21 +0900
commit427ea605e7408fd2ed3b5c97d701c660b8028788 (patch)
tree1914f4d72a56d6ba8969879d3bfcadb1bbb71907
parentb81f0d0ffb7db46507f7b79ccb72cc94428555ce (diff)
parent037a1d70880ecdcfd2d55eb10c234de1001eb654 (diff)
downloadmruby-427ea605e7408fd2ed3b5c97d701c660b8028788.tar.gz
mruby-427ea605e7408fd2ed3b5c97d701c660b8028788.zip
Merge branch 'master' of github.com:mruby/mruby
-rw-r--r--include/mruby/error.h1
-rw-r--r--mrbgems/mruby-array-ext/src/array.c44
-rw-r--r--mrbgems/mruby-array-ext/test/array.rb8
-rw-r--r--mrbgems/mruby-string-ext/mrblib/string.rb21
-rw-r--r--mrblib/error.rb6
-rw-r--r--src/class.c3
-rw-r--r--src/error.c14
-rw-r--r--test/t/nomethoderror.rb13
8 files changed, 98 insertions, 12 deletions
diff --git a/include/mruby/error.h b/include/mruby/error.h
index 7ae2d4348..4d37f1701 100644
--- a/include/mruby/error.h
+++ b/include/mruby/error.h
@@ -19,6 +19,7 @@ void mrb_exc_print(mrb_state *mrb, struct RObject *exc);
void mrb_print_backtrace(mrb_state *mrb);
mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc);
mrb_value mrb_get_backtrace(mrb_state *mrb);
+mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_int argc, const mrb_value *argv, const char *fmt, ...);
/* declaration for fail method */
mrb_value mrb_f_raise(mrb_state*, mrb_value);
diff --git a/mrbgems/mruby-array-ext/src/array.c b/mrbgems/mruby-array-ext/src/array.c
index 014137e99..d69f0ac44 100644
--- a/mrbgems/mruby-array-ext/src/array.c
+++ b/mrbgems/mruby-array-ext/src/array.c
@@ -2,6 +2,7 @@
#include "mruby/value.h"
#include "mruby/array.h"
#include "mruby/range.h"
+#include "mruby/hash.h"
/*
* call-seq:
@@ -105,6 +106,48 @@ mrb_ary_values_at(mrb_state *mrb, mrb_value self)
return mrb_get_values_at(mrb, self, RARRAY_LEN(self), argc, argv, mrb_ary_ref);
}
+/*
+ * call-seq:
+ * ary.to_h -> Hash
+ *
+ * Returns the result of interpreting <i>aray</i> as an array of
+ * <tt>[key, value]</tt> paris.
+ *
+ * [[:foo, :bar], [1, 2]].to_h
+ * # => {:foo => :bar, 1 => 2}
+ */
+
+static mrb_value
+mrb_ary_to_h(mrb_state *mrb, mrb_value ary)
+{
+ mrb_int i;
+ mrb_value v, hash;
+
+ hash = mrb_hash_new_capa(mrb, 0);
+
+ for (i = 0; i < RARRAY_LEN(ary); ++i) {
+ v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]);
+
+ if (mrb_nil_p(v)) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "wrong element type %S at %S (expected array)",
+ mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, RARRAY_PTR(ary)[i])),
+ mrb_fixnum_value(i)
+ );
+ }
+
+ if (RARRAY_LEN(v) != 2) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong array length at %S (expected 2, was %S)",
+ mrb_fixnum_value(i),
+ mrb_fixnum_value(RARRAY_LEN(v))
+ );
+ }
+
+ mrb_hash_set(mrb, hash, RARRAY_PTR(v)[0], RARRAY_PTR(v)[1]);
+ }
+
+ return hash;
+}
+
void
mrb_mruby_array_ext_gem_init(mrb_state* mrb)
{
@@ -114,6 +157,7 @@ mrb_mruby_array_ext_gem_init(mrb_state* mrb)
mrb_define_method(mrb, a, "at", mrb_ary_at, MRB_ARGS_REQ(1));
mrb_define_method(mrb, a, "rassoc", mrb_ary_rassoc, MRB_ARGS_REQ(1));
mrb_define_method(mrb, a, "values_at", mrb_ary_values_at, MRB_ARGS_ANY());
+ mrb_define_method(mrb, a, "to_h", mrb_ary_to_h, MRB_ARGS_REQ(0));
}
void
diff --git a/mrbgems/mruby-array-ext/test/array.rb b/mrbgems/mruby-array-ext/test/array.rb
index cb5652dde..8c919f7e0 100644
--- a/mrbgems/mruby-array-ext/test/array.rb
+++ b/mrbgems/mruby-array-ext/test/array.rb
@@ -285,3 +285,11 @@ assert('Array#values_at') do
assert_equal ['none', nil, nil, 'red', 'green', 'purple'], a.values_at(4..6, 0...3)
assert_raise(TypeError) { a.values_at 'tt' }
end
+
+assert('Array#to_h') do
+ assert_equal({}, [].to_h)
+ assert_equal({a: 1, b:2}, [[:a, 1], [:b, 2]].to_h)
+
+ assert_raise(TypeError) { [1].to_h }
+ assert_raise(ArgumentError) { [[1]].to_h }
+end
diff --git a/mrbgems/mruby-string-ext/mrblib/string.rb b/mrbgems/mruby-string-ext/mrblib/string.rb
index 18a7a62d3..a08fc0f46 100644
--- a/mrbgems/mruby-string-ext/mrblib/string.rb
+++ b/mrbgems/mruby-string-ext/mrblib/string.rb
@@ -94,16 +94,17 @@ class String
(s == self) ? nil : self.replace(s)
end
-# call-seq:
-# str.casecmp(other_str) -> -1, 0, +1 or nil
-#
-# Case-insensitive version of <code>String#<=></code>.
-#
-# "abcdef".casecmp("abcde") #=> 1
-# "aBcDeF".casecmp("abcdef") #=> 0
-# "abcdef".casecmp("abcdefg") #=> -1
-# "abcdef".casecmp("ABCDEF") #=> 0
-#
+ ##
+ # call-seq:
+ # str.casecmp(other_str) -> -1, 0, +1 or nil
+ #
+ # Case-insensitive version of <code>String#<=></code>.
+ #
+ # "abcdef".casecmp("abcde") #=> 1
+ # "aBcDeF".casecmp("abcdef") #=> 0
+ # "abcdef".casecmp("abcdefg") #=> -1
+ # "abcdef".casecmp("ABCDEF") #=> 0
+ #
def casecmp(str)
self.downcase <=> str.to_str.downcase
rescue NoMethodError
diff --git a/mrblib/error.rb b/mrblib/error.rb
index 6e8181e9d..a5b6b3223 100644
--- a/mrblib/error.rb
+++ b/mrblib/error.rb
@@ -48,6 +48,12 @@ end
# ISO 15.2.32
class NoMethodError < NameError
+ attr_reader :args
+
+ def initialize(message=nil, name=nil, args=nil)
+ @args = args
+ super message, name
+ end
end
# ISO 15.2.33
diff --git a/src/class.c b/src/class.c
index db9a8ac26..ba078911b 100644
--- a/src/class.c
+++ b/src/class.c
@@ -1216,8 +1216,7 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod)
repr = mrb_any_to_s(mrb, mod);
}
- mrb_raisef(mrb, E_NOMETHOD_ERROR, "undefined method '%S' for %S",
- mrb_sym2str(mrb, name), repr);
+ mrb_no_method_error(mrb, name, alen, a, "undefined method '%S' for %S", mrb_sym2str(mrb, name), repr);
/* not reached */
return mrb_nil_value();
}
diff --git a/src/error.c b/src/error.c
index 360df8f2e..c60fff10d 100644
--- a/src/error.c
+++ b/src/error.c
@@ -442,6 +442,20 @@ mrb_sys_fail(mrb_state *mrb, const char *mesg)
}
}
+mrb_noreturn void
+mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_int argc, const mrb_value *argv, char const* fmt, ...)
+{
+ mrb_value exc;
+ va_list ap;
+
+ va_start(ap, fmt);
+ exc = mrb_funcall(mrb, mrb_obj_value(E_NOMETHOD_ERROR), "new", 3,
+ mrb_vformat(mrb, fmt, ap), mrb_symbol_value(id),
+ mrb_ary_new_from_values(mrb, argc, argv));
+ va_end(ap);
+ mrb_exc_raise(mrb, exc);
+}
+
void
mrb_init_exception(mrb_state *mrb)
{
diff --git a/test/t/nomethoderror.rb b/test/t/nomethoderror.rb
index 561e545f9..709d31165 100644
--- a/test/t/nomethoderror.rb
+++ b/test/t/nomethoderror.rb
@@ -11,3 +11,16 @@ end
assert('NoMethodError superclass', '15.2.32.2') do
assert_equal NameError, NoMethodError.superclass
end
+
+assert('NoMethodError#args', '15.2.32.2.1') do
+ a = NoMethodError.new 'test', :test, [1, 2]
+ assert_equal [1, 2], a.args
+
+ assert_nothing_raised do
+ begin
+ doesNotExistAsAMethodNameForVerySure 3, 1, 4
+ rescue NoMethodError => e
+ assert_equal [3, 1, 4], e.args
+ end
+ end
+end