Commit 427ea605 authored by Yukihiro "Matz" Matsumoto's avatar Yukihiro "Matz" Matsumoto

Merge branch 'master' of github.com:mruby/mruby

parents b81f0d0f 037a1d70
......@@ -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);
......
......@@ -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
......
......@@ -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
......@@ -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
......
......@@ -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
......
......@@ -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();
}
......
......@@ -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)
{
......
......@@ -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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment