summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--doc/language/Core.md12
-rw-r--r--doc/language/mrbdoc/lib/mrbdoc_docu.rb8
-rw-r--r--examples/targets/build_config_ArduinoDue.rb (renamed from examples/targets/ArduinoDue.rb)18
-rw-r--r--examples/targets/build_config_IntelGalileo.rb (renamed from examples/targets/IntelGalileo.rb)18
-rw-r--r--examples/targets/build_config_chipKITMax32.rb (renamed from examples/targets/chipKitMax32.rb)21
-rw-r--r--include/mruby/error.h3
-rw-r--r--include/mruby/numeric.h35
-rw-r--r--mrbgems/default.gembox3
-rw-r--r--mrbgems/mruby-bin-mirb/mrbgem.rake3
-rw-r--r--mrbgems/mruby-bin-mirb/tools/mirb/mirb.c25
-rw-r--r--mrbgems/mruby-enum-lazy/mrbgem.rake3
-rw-r--r--mrbgems/mruby-enumerator/mrbgem.rake2
-rw-r--r--mrbgems/mruby-enumerator/mrblib/enumerator.rb10
-rw-r--r--mrbgems/mruby-hash-ext/mrblib/hash.rb66
-rw-r--r--mrbgems/mruby-hash-ext/test/hash.rb33
-rw-r--r--mrbgems/mruby-kernel-ext/mrbgem.rake5
-rw-r--r--mrbgems/mruby-kernel-ext/src/kernel.c36
-rw-r--r--mrbgems/mruby-kernel-ext/test/kernel.rb18
-rw-r--r--mrbgems/mruby-objectspace/src/mruby_objectspace.c22
-rw-r--r--mrbgems/mruby-random/src/random.c2
-rw-r--r--mrbgems/mruby-time/mrblib/time.rb9
-rw-r--r--mrbgems/mruby-time/src/time.c22
-rw-r--r--mrbgems/mruby-time/test/time.rb302
-rw-r--r--mrblib/error.rb4
-rw-r--r--mrblib/hash.rb56
-rw-r--r--src/array.c15
-rw-r--r--src/error.c26
-rw-r--r--src/hash.c2
-rw-r--r--src/kernel.c88
-rw-r--r--src/load.c4
-rw-r--r--src/numeric.c18
-rw-r--r--src/parse.y2
-rw-r--r--src/string.c117
-rw-r--r--src/vm.c51
-rw-r--r--tasks/mrbgems_test.rake2
-rw-r--r--test/t/array.rb5
-rw-r--r--test/t/bs_block.rb7
-rw-r--r--test/t/exception.rb66
-rw-r--r--test/t/hash.rb6
-rw-r--r--test/t/integer.rb2
-rw-r--r--test/t/kernel.rb14
-rw-r--r--test/t/proc.rb57
-rw-r--r--test/t/range.rb16
-rw-r--r--test/t/string.rb14
44 files changed, 817 insertions, 431 deletions
diff --git a/doc/language/Core.md b/doc/language/Core.md
index 6b4103a99..033939865 100644
--- a/doc/language/Core.md
+++ b/doc/language/Core.md
@@ -806,12 +806,6 @@ ISO Code | Source File | C Function
--- | --- | ---
15.2.14.4.3 | src/range.c | mrb_range_beg
-#### each
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.14.4.4 | src/range.c | mrb_range_each
-
#### end
ISO Code | Source File | C Function
@@ -1372,12 +1366,6 @@ ISO Code | Source File | C Function
--- | --- | ---
15.3.1.3.3 | src/kernel.c | mrb_obj_id_m
-#### __method__
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/kernel.c | mrb_f_method
-
#### __send__
ISO Code | Source File | C Function
diff --git a/doc/language/mrbdoc/lib/mrbdoc_docu.rb b/doc/language/mrbdoc/lib/mrbdoc_docu.rb
index 0e942e0f2..f6f327804 100644
--- a/doc/language/mrbdoc/lib/mrbdoc_docu.rb
+++ b/doc/language/mrbdoc/lib/mrbdoc_docu.rb
@@ -96,8 +96,8 @@ CLASS
def print_method(io, met_name, met_hsh, cfg)
if cfg[:print_line_no]
- line_no_head = '| Line'
- line_no = "| #{find_c_func(met_hsh[:c_func])[:line_no]}"
+ line_no_head = ' | Line'
+ line_no = " | #{find_c_func(met_hsh[:c_func])[:line_no]}"
else
line_no, line_no_head = '', ''
end
@@ -109,9 +109,9 @@ CLASS
io.puts <<METHOD
#### #{met_name}
-ISO Code | Source File | C Function #{line_no_head}
+ISO Code | Source File | C Function#{line_no_head}
--- | --- | ---
-#{iso} | #{file} | #{met_hsh[:c_func]} #{line_no}
+#{iso} | #{file} | #{met_hsh[:c_func]}#{line_no}
METHOD
end
diff --git a/examples/targets/ArduinoDue.rb b/examples/targets/build_config_ArduinoDue.rb
index a850eabb6..eadcfdd43 100644
--- a/examples/targets/ArduinoDue.rb
+++ b/examples/targets/build_config_ArduinoDue.rb
@@ -1,8 +1,24 @@
+MRuby::Build.new do |conf|
+
+ # Gets set by the VS command prompts.
+ if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
+ toolchain :visualcpp
+ else
+ toolchain :gcc
+ end
+
+ enable_debug
+
+ # include the default GEMs
+ conf.gembox 'default'
+
+end
+
# Cross Compiling configuration for Arduino Due
# http://arduino.cc/en/Main/ArduinoBoardDue
#
# Requires Arduino IDE >= 1.5
-MRuby::CrossBuild.new("Arduino Due") do |conf|
+MRuby::CrossBuild.new("ArduinoDue") do |conf|
toolchain :gcc
# Mac OS X
diff --git a/examples/targets/IntelGalileo.rb b/examples/targets/build_config_IntelGalileo.rb
index 185b6e71e..42f800d9f 100644
--- a/examples/targets/IntelGalileo.rb
+++ b/examples/targets/build_config_IntelGalileo.rb
@@ -1,8 +1,24 @@
+MRuby::Build.new do |conf|
+
+ # Gets set by the VS command prompts.
+ if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
+ toolchain :visualcpp
+ else
+ toolchain :gcc
+ end
+
+ enable_debug
+
+ # include the default GEMs
+ conf.gembox 'default'
+
+end
+
+
# Cross Compiling configuration for Intel Galileo on Arduino environment
# http://arduino.cc/en/ArduinoCertified/IntelGalileo
#
# Requires Arduino IDE for Intel Galileo
-
MRuby::CrossBuild.new("Galileo") do |conf|
toolchain :gcc
diff --git a/examples/targets/chipKitMax32.rb b/examples/targets/build_config_chipKITMax32.rb
index b3a7c7c7d..e3a122f43 100644
--- a/examples/targets/chipKitMax32.rb
+++ b/examples/targets/build_config_chipKITMax32.rb
@@ -1,3 +1,19 @@
+MRuby::Build.new do |conf|
+
+ # Gets set by the VS command prompts.
+ if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
+ toolchain :visualcpp
+ else
+ toolchain :gcc
+ end
+
+ enable_debug
+
+ # include the default GEMs
+ conf.gembox 'default'
+
+end
+
# Cross Compiling configuration for Digilent chipKIT Max32
# http://www.digilentinc.com/Products/Detail.cfm?Prod=CHIPKIT-MAX32
#
@@ -5,7 +21,7 @@
#
# This configuration is based on @kyab's version
# http://d.hatena.ne.jp/kyab/20130201
-MRuby::CrossBuild.new("chipKitMax32") do |conf|
+MRuby::CrossBuild.new("chipKITMax32") do |conf|
toolchain :gcc
# Mac OS X
@@ -54,6 +70,9 @@ MRuby::CrossBuild.new("chipKitMax32") do |conf|
#do not build test executable
conf.build_mrbtest_lib_only
+ #disable C++ exception
+ conf.disable_cxx_exception
+
#gems from core
conf.gem :core => "mruby-print"
conf.gem :core => "mruby-math"
diff --git a/include/mruby/error.h b/include/mruby/error.h
index 689cf4b8f..9dd4260c2 100644
--- a/include/mruby/error.h
+++ b/include/mruby/error.h
@@ -21,6 +21,9 @@ 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);
+/* declaration for fail method */
+mrb_value mrb_f_raise(mrb_state*, mrb_value);
+
#if defined(__cplusplus)
} /* extern "C" { */
#endif
diff --git a/include/mruby/numeric.h b/include/mruby/numeric.h
index 17291c2f2..fe4f3b264 100644
--- a/include/mruby/numeric.h
+++ b/include/mruby/numeric.h
@@ -25,6 +25,41 @@ mrb_value mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x);
+#define MRB_UINT_MAKE2(n) uint ## n ## _t
+#define MRB_UINT_MAKE(n) MRB_UINT_MAKE2(n)
+#define mrb_uint MRB_UINT_MAKE(MRB_INT_BIT)
+
+#ifdef MRB_WORD_BOXING
+# define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1 - MRB_FIXNUM_SHIFT))
+#else
+# define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1))
+#endif
+
+static inline mrb_bool
+mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum)
+{
+ mrb_uint x = (mrb_uint)augend;
+ mrb_uint y = (mrb_uint)addend;
+ mrb_uint z = (mrb_uint)(x + y);
+ *sum = (mrb_int)z;
+ return !!(((x ^ z) & (y ^ z)) & MRB_INT_OVERFLOW_MASK);
+}
+
+static inline mrb_bool
+mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference)
+{
+ mrb_uint x = (mrb_uint)minuend;
+ mrb_uint y = (mrb_uint)subtrahend;
+ mrb_uint z = (mrb_uint)(x - y);
+ *difference = (mrb_int)z;
+ return !!(((x ^ z) & (~y ^ z)) & MRB_INT_OVERFLOW_MASK);
+}
+
+#undef MRB_INT_OVERFLOW_MASK
+#undef mrb_uint
+#undef MRB_UINT_MAKE
+#undef MRB_UINT_MAKE2
+
#if defined(__cplusplus)
} /* extern "C" { */
#endif
diff --git a/mrbgems/default.gembox b/mrbgems/default.gembox
index 1bba7be26..8729593de 100644
--- a/mrbgems/default.gembox
+++ b/mrbgems/default.gembox
@@ -64,4 +64,7 @@ MRuby::GemBox.new do |conf|
# Generate mruby command
conf.gem :core => "mruby-bin-mruby"
+
+ # Use extensional Kernel module
+ conf.gem :core => "mruby-kernel-ext"
end
diff --git a/mrbgems/mruby-bin-mirb/mrbgem.rake b/mrbgems/mruby-bin-mirb/mrbgem.rake
index 4c9cdf29e..c4374b47e 100644
--- a/mrbgems/mruby-bin-mirb/mrbgem.rake
+++ b/mrbgems/mruby-bin-mirb/mrbgem.rake
@@ -5,6 +5,9 @@ MRuby::Gem::Specification.new('mruby-bin-mirb') do |spec|
if spec.build.cc.search_header_path 'readline/readline.h'
spec.cc.defines << "ENABLE_READLINE"
+ if spec.build.cc.search_header_path 'termcap.h'
+ spec.linker.libraries << 'termcap'
+ end
spec.linker.libraries << 'readline'
elsif spec.build.cc.search_header_path 'linenoise.h'
spec.cc.defines << "ENABLE_LINENOISE"
diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c
index c8ea0a055..b389db7bc 100644
--- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c
+++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c
@@ -100,9 +100,9 @@ is_code_block_open(struct mrb_parser_state *parser)
/* all states which need more code */
case EXPR_BEG:
- /* an expression was just started, */
- /* we can't end it like this */
- code_block_open = TRUE;
+ /* beginning of a statement, */
+ /* that means previous line ended */
+ ;;code_block_open = FALSE;
break;
case EXPR_DOT:
/* a message dot was the last token, */
@@ -319,6 +319,10 @@ main(int argc, char **argv)
char_index = 0;
while ((last_char = getchar()) != '\n') {
if (last_char == EOF) break;
+ if (char_index > sizeof(last_code_line)-2) {
+ fputs("input string too long\n", stderr);
+ continue;
+ }
last_code_line[char_index++] = last_char;
}
if (last_char == EOF) {
@@ -326,6 +330,7 @@ main(int argc, char **argv)
break;
}
+ last_code_line[char_index++] = '\n';
last_code_line[char_index] = '\0';
#else
char* line = MIRB_READLINE(code_block_open ? "* " : "> ");
@@ -333,14 +338,22 @@ main(int argc, char **argv)
printf("\n");
break;
}
- strncpy(last_code_line, line, sizeof(last_code_line)-1);
+ if (strlen(line) > sizeof(last_code_line)-2) {
+ fputs("input string too long\n", stderr);
+ continue;
+ }
+ strcpy(last_code_line, line);
+ strcat(last_code_line, "\n");
MIRB_ADD_HISTORY(line);
free(line);
#endif
if (code_block_open) {
- strcat(ruby_code, "\n");
- strcat(ruby_code, last_code_line);
+ if (strlen(ruby_code)+strlen(last_code_line) > sizeof(ruby_code)-1) {
+ fputs("concatenated input string too long\n", stderr);
+ continue;
+ }
+ strcat(ruby_code, last_code_line);
}
else {
if ((strcmp(last_code_line, "quit") == 0) || (strcmp(last_code_line, "exit") == 0)) {
diff --git a/mrbgems/mruby-enum-lazy/mrbgem.rake b/mrbgems/mruby-enum-lazy/mrbgem.rake
index 45dda4054..219141e98 100644
--- a/mrbgems/mruby-enum-lazy/mrbgem.rake
+++ b/mrbgems/mruby-enum-lazy/mrbgem.rake
@@ -2,5 +2,6 @@ MRuby::Gem::Specification.new('mruby-enum-lazy') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'Enumerable::Lazy class'
- spec.add_dependency('mruby-enumerator')
+ spec.add_dependency('mruby-enumerator', :core => 'mruby-enumerator')
+ spec.add_dependency('mruby-enum-ext', :core => 'mruby-enum-ext')
end
diff --git a/mrbgems/mruby-enumerator/mrbgem.rake b/mrbgems/mruby-enumerator/mrbgem.rake
index 2d5fd35ac..abcc54e7a 100644
--- a/mrbgems/mruby-enumerator/mrbgem.rake
+++ b/mrbgems/mruby-enumerator/mrbgem.rake
@@ -1,6 +1,6 @@
MRuby::Gem::Specification.new('mruby-enumerator') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
- spec.add_dependency('mruby-fiber')
+ spec.add_dependency('mruby-fiber', :core => 'mruby-fiber')
spec.summary = 'Enumerator class'
end
diff --git a/mrbgems/mruby-enumerator/mrblib/enumerator.rb b/mrbgems/mruby-enumerator/mrblib/enumerator.rb
index 0257d8bf0..58996adc8 100644
--- a/mrbgems/mruby-enumerator/mrblib/enumerator.rb
+++ b/mrbgems/mruby-enumerator/mrblib/enumerator.rb
@@ -217,14 +217,12 @@ class Enumerator
def inspect
return "#<#{self.class}: uninitialized>" unless @obj
- args = ""
if @args && @args.size > 0
- args = "("
- @args.each {|arg| args << "#{arg}, " }
- args = args[0, args.size-2]
- args << ")"
+ args = @args.join(", ")
+ "#<#{self.class}: #{@obj}:#{@meth}(#{args})>"
+ else
+ "#<#{self.class}: #{@obj}:#{@meth}>"
end
- "#<#{self.class}: #{@obj}:#{@meth}#{args}>"
end
##
diff --git a/mrbgems/mruby-hash-ext/mrblib/hash.rb b/mrbgems/mruby-hash-ext/mrblib/hash.rb
index 1ebc540e8..504848a74 100644
--- a/mrbgems/mruby-hash-ext/mrblib/hash.rb
+++ b/mrbgems/mruby-hash-ext/mrblib/hash.rb
@@ -1,5 +1,8 @@
class Hash
+ # ISO does not define Hash#each_pair, so each_pair is defined in gem.
+ alias each_pair each
+
##
# call-seq:
# hsh.merge!(other_hash) -> hsh
@@ -22,7 +25,7 @@ class Hash
#
def merge!(other, &block)
- raise "can't convert argument into Hash" unless other.respond_to?(:to_hash)
+ raise TypeError, "can't convert argument into Hash" unless other.respond_to?(:to_hash)
if block
other.each_key{|k|
self[k] = (self.has_key?(k))? block.call(k, self[k], other[k]): other[k]
@@ -33,7 +36,6 @@ class Hash
self
end
- alias each_pair each
alias update merge!
##
@@ -120,4 +122,64 @@ class Hash
def flatten(level=1)
self.to_a.flatten(level)
end
+
+ ##
+ # call-seq:
+ # hsh.invert -> new_hash
+ #
+ # Returns a new hash created by using <i>hsh</i>'s values as keys, and
+ # the keys as values.
+ #
+ # h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 }
+ # h.invert #=> {0=>"a", 100=>"m", 200=>"d", 300=>"y"}
+ #
+
+ def invert
+ h = Hash.new
+ self.each {|k, v| h[v] = k }
+ h
+ end
+
+ ##
+ # call-seq:
+ # hsh.keep_if {| key, value | block } -> hsh
+ # hsh.keep_if -> an_enumerator
+ #
+ # Deletes every key-value pair from <i>hsh</i> for which <i>block</i>
+ # evaluates to false.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+
+ def keep_if(&block)
+ return to_enum :keep_if unless block_given?
+
+ keys = []
+ self.each do |k, v|
+ unless block.call([k, v])
+ self.delete(k)
+ end
+ end
+ self
+ end
+
+ ##
+ # call-seq:
+ # hsh.key(value) -> key
+ #
+ # Returns the key of an occurrence of a given value. If the value is
+ # not found, returns <code>nil</code>.
+ #
+ # h = { "a" => 100, "b" => 200, "c" => 300, "d" => 300 }
+ # h.key(200) #=> "b"
+ # h.key(300) #=> "c"
+ # h.key(999) #=> nil
+ #
+
+ def key(val)
+ self.each do |k, v|
+ return k if v == val
+ end
+ nil
+ end
end
diff --git a/mrbgems/mruby-hash-ext/test/hash.rb b/mrbgems/mruby-hash-ext/test/hash.rb
index 7d8d66b4e..62cfc8856 100644
--- a/mrbgems/mruby-hash-ext/test/hash.rb
+++ b/mrbgems/mruby-hash-ext/test/hash.rb
@@ -16,6 +16,10 @@ assert('Hash#merge!') do
'xyz_key' => 'xyz_value' }, result_1)
assert_equal({'abc_key' => 'abc_value', 'cba_key' => 'cba_value',
'xyz_key' => 'xyz_value' }, result_2)
+
+ assert_raise(TypeError) do
+ { 'abc_key' => 'abc_value' }.merge! "a"
+ end
end
assert('Hash#values_at') do
@@ -82,3 +86,32 @@ assert("Hash#flatten") do
assert_equal [1, "one", 2, 2, "two", 3, 3, ["three"]], a.flatten(2)
assert_equal [1, "one", 2, 2, "two", 3, 3, "three"], a.flatten(3)
end
+
+assert("Hash#invert") do
+ h = { 1 => 'one', 2 => 'two', 3 => 'three',
+ true => 'true', nil => 'nil' }.invert
+ assert_equal 1, h['one']
+ assert_equal true, h['true']
+ assert_equal nil, h['nil']
+
+ h = { 'a' => 1, 'b' => 2, 'c' => 1 }.invert
+ assert_equal(2, h.length)
+ assert_include(%w[a c], h[1])
+ assert_equal('b', h[2])
+end
+
+assert("Hash#keep_if") do
+ h = { 1 => 2, 3 => 4, 5 => 6 }
+ assert_equal({3=>4,5=>6}, h.keep_if {|k, v| k + v >= 7 })
+ h = { 1 => 2, 3 => 4, 5 => 6 }
+ assert_equal({ 1 => 2, 3=> 4, 5 =>6} , h.keep_if { true })
+end
+
+assert("Hash#key") do
+ h = { "a" => 100, "b" => 200, "c" => 300, "d" => 300, nil => 'nil', 'nil' => nil }
+ assert_equal "b", h.key(200)
+ assert_equal "c", h.key(300)
+ assert_nil h.key(999)
+ assert_nil h.key('nil')
+ assert_equal 'nil', h.key(nil)
+end
diff --git a/mrbgems/mruby-kernel-ext/mrbgem.rake b/mrbgems/mruby-kernel-ext/mrbgem.rake
new file mode 100644
index 000000000..ab610c02b
--- /dev/null
+++ b/mrbgems/mruby-kernel-ext/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-kernel-ext') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'extensional Kernel module'
+end
diff --git a/mrbgems/mruby-kernel-ext/src/kernel.c b/mrbgems/mruby-kernel-ext/src/kernel.c
new file mode 100644
index 000000000..1ce63ac94
--- /dev/null
+++ b/mrbgems/mruby-kernel-ext/src/kernel.c
@@ -0,0 +1,36 @@
+#include "mruby.h"
+#include "mruby/error.h"
+
+/*
+ * call-seq:
+ * __method__ -> symbol
+ *
+ * Returns the name at the definition of the current method as a
+ * Symbol.
+ * If called outside of a method, it returns <code>nil</code>.
+ *
+ */
+static mrb_value
+mrb_f_method(mrb_state *mrb, mrb_value self)
+{
+ mrb_callinfo *ci = mrb->c->ci;
+ ci--;
+ if (ci->mid)
+ return mrb_symbol_value(ci->mid);
+ else
+ return mrb_nil_value();
+}
+
+void
+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_NONE());
+ mrb_define_method(mrb, krn, "__method__", mrb_f_method, MRB_ARGS_NONE());
+}
+
+void
+mrb_mruby_kernel_ext_gem_final(mrb_state *mrb)
+{
+}
diff --git a/mrbgems/mruby-kernel-ext/test/kernel.rb b/mrbgems/mruby-kernel-ext/test/kernel.rb
new file mode 100644
index 000000000..0e47e3b57
--- /dev/null
+++ b/mrbgems/mruby-kernel-ext/test/kernel.rb
@@ -0,0 +1,18 @@
+assert('Kernel.fail, Kernel#fail') do
+ assert_raise(RuntimeError) { fail }
+ assert_raise(RuntimeError) { Kernel.fail }
+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
+ end
+ assert_equal(:m1, c.new.m1)
+ assert_equal(:m2, c.new.m2)
+end
diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c
index 7d3b0b74e..ba22fc990 100644
--- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c
+++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c
@@ -1,7 +1,7 @@
-#include <mruby.h>
-#include <mruby/gc.h>
-#include <mruby/hash.h>
-#include <mruby/class.h>
+#include "mruby.h"
+#include "mruby/gc.h"
+#include "mruby/hash.h"
+#include "mruby/class.h"
struct os_count_struct {
mrb_int total;
@@ -128,6 +128,20 @@ os_each_object_cb(mrb_state *mrb, struct RBasic *obj, void *ud)
++d->count;
}
+/*
+ * call-seq:
+ * ObjectSpace.each_object([module]) {|obj| ... } -> fixnum
+ *
+ * Calls the block once for each object in this Ruby process.
+ * Returns the number of objects found.
+ * If the optional argument +module+ is given,
+ * calls the block for only those classes or modules
+ * that match (or are a subclass of) +module+.
+ *
+ * If no block is given, ArgumentError is raised.
+ *
+ */
+
static mrb_value
os_each_object(mrb_state *mrb, mrb_value self)
{
diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c
index 7756bc7c9..391336493 100644
--- a/mrbgems/mruby-random/src/random.c
+++ b/mrbgems/mruby-random/src/random.c
@@ -44,7 +44,7 @@ static mrb_value
mrb_random_mt_srand(mrb_state *mrb, mt_state *t, mrb_value seed)
{
if (mrb_nil_p(seed)) {
- seed = mrb_fixnum_value(time(NULL) + mt_rand(t));
+ seed = mrb_fixnum_value((mrb_int)(time(NULL) + mt_rand(t)));
if (mrb_fixnum(seed) < 0) {
seed = mrb_fixnum_value( 0 - mrb_fixnum(seed));
}
diff --git a/mrbgems/mruby-time/mrblib/time.rb b/mrbgems/mruby-time/mrblib/time.rb
new file mode 100644
index 000000000..df0d8ca82
--- /dev/null
+++ b/mrbgems/mruby-time/mrblib/time.rb
@@ -0,0 +1,9 @@
+class Time
+ def sunday?; wday == 0 end
+ def monday?; wday == 1 end
+ def tuesday?; wday == 2 end
+ def wednesday?; wday == 3 end
+ def thursday?; wday == 4 end
+ def friday?; wday == 5 end
+ def saturday?; wday == 6 end
+end
diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c
index 0427fe3c0..3f8ffabef 100644
--- a/mrbgems/mruby-time/src/time.c
+++ b/mrbgems/mruby-time/src/time.c
@@ -10,6 +10,10 @@
#include "mruby/class.h"
#include "mruby/data.h"
+#if defined(__MINGW64__) || defined(__MINGW32__)
+# include <sys/time.h>
+#endif
+
/** Time class configuration */
/* gettimeofday(2) */
@@ -197,14 +201,14 @@ time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone)
tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(struct mrb_time));
tm->sec = (time_t)sec;
- tm->usec = (sec - tm->sec) * 1.0e6 + usec;
+ tm->usec = (time_t)((sec - tm->sec) * 1.0e6 + usec);
while (tm->usec < 0) {
tm->sec--;
- tm->usec += 1.0e6;
+ tm->usec += 1000000;
}
- while (tm->usec > 1.0e6) {
+ while (tm->usec > 1000000) {
tm->sec++;
- tm->usec -= 1.0e6;
+ tm->usec -= 1000000;
}
tm->timezone = timezone;
mrb_time_update_datetime(tm);
@@ -297,7 +301,7 @@ time_mktime(mrb_state *mrb, mrb_int ayear, mrb_int amonth, mrb_int aday,
mrb_raise(mrb, E_ARGUMENT_ERROR, "Not a valid time.");
}
- return time_alloc(mrb, nowsecs, ausec, timezone);
+ return time_alloc(mrb, (double)nowsecs, ausec, timezone);
}
/* 15.2.19.6.2 */
@@ -377,7 +381,7 @@ mrb_time_plus(mrb_state *mrb, mrb_value self)
mrb_get_args(mrb, "f", &f);
tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
- return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec+f, tm->usec, tm->timezone);
+ return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec+f, (double)tm->usec, tm->timezone);
}
static mrb_value
@@ -398,7 +402,7 @@ mrb_time_minus(mrb_state *mrb, mrb_value self)
}
else {
mrb_get_args(mrb, "f", &f);
- return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec-f, tm->usec, tm->timezone);
+ return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec-f, (double)tm->usec, tm->timezone);
}
}
@@ -662,7 +666,7 @@ mrb_time_to_i(mrb_state *mrb, mrb_value self)
struct mrb_time *tm;
tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
- return mrb_fixnum_value(tm->sec);
+ return mrb_fixnum_value((mrb_int)tm->sec);
}
/* 15.2.19.7.26 */
@@ -673,7 +677,7 @@ mrb_time_usec(mrb_state *mrb, mrb_value self)
struct mrb_time *tm;
tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
- return mrb_fixnum_value(tm->usec);
+ return mrb_fixnum_value((mrb_int)tm->usec);
}
/* 15.2.19.7.27 */
diff --git a/mrbgems/mruby-time/test/time.rb b/mrbgems/mruby-time/test/time.rb
index f92459d5e..450d87b43 100644
--- a/mrbgems/mruby-time/test/time.rb
+++ b/mrbgems/mruby-time/test/time.rb
@@ -1,201 +1,209 @@
##
# Time ISO Test
-if Object.const_defined?(:Time)
- assert('Time.new', '15.2.3.3.3') do
- Time.new.class == Time
- end
+assert('Time.new', '15.2.3.3.3') do
+ Time.new.class == Time
+end
- assert('Time', '15.2.19') do
- Time.class == Class
- end
+assert('Time', '15.2.19') do
+ Time.class == Class
+end
- assert('Time superclass', '15.2.19.2') do
- Time.superclass == Object
- end
+assert('Time superclass', '15.2.19.2') do
+ Time.superclass == Object
+end
- assert('Time.at', '15.2.19.6.1') do
- Time.at(1300000000.0)
- end
+assert('Time.at', '15.2.19.6.1') do
+ Time.at(1300000000.0)
+end
- assert('Time.gm', '15.2.19.6.2') do
- Time.gm(2012, 12, 23)
- end
+assert('Time.gm', '15.2.19.6.2') do
+ Time.gm(2012, 12, 23)
+end
- assert('Time.local', '15.2.19.6.3') do
- Time.local(2012, 12, 23)
- end
+assert('Time.local', '15.2.19.6.3') do
+ Time.local(2012, 12, 23)
+end
- assert('Time.mktime', '15.2.19.6.4') do
- Time.mktime(2012, 12, 23)
- end
+assert('Time.mktime', '15.2.19.6.4') do
+ Time.mktime(2012, 12, 23)
+end
- assert('Time.now', '15.2.19.6.5') do
- Time.now.class == Time
- end
+assert('Time.now', '15.2.19.6.5') do
+ Time.now.class == Time
+end
- assert('Time.utc', '15.2.19.6.6') do
- Time.utc(2012, 12, 23)
- end
+assert('Time.utc', '15.2.19.6.6') do
+ Time.utc(2012, 12, 23)
+end
- assert('Time#+', '15.2.19.7.1') do
- t1 = Time.at(1300000000.0)
- t2 = t1.+(60)
+assert('Time#+', '15.2.19.7.1') do
+ t1 = Time.at(1300000000.0)
+ t2 = t1.+(60)
- t2.utc.asctime == "Sun Mar 13 07:07:40 UTC 2011"
- end
+ t2.utc.asctime == "Sun Mar 13 07:07:40 UTC 2011"
+end
- assert('Time#-', '15.2.19.7.2') do
- t1 = Time.at(1300000000.0)
- t2 = t1.-(60)
+assert('Time#-', '15.2.19.7.2') do
+ t1 = Time.at(1300000000.0)
+ t2 = t1.-(60)
- t2.utc.asctime == "Sun Mar 13 07:05:40 UTC 2011"
- end
+ t2.utc.asctime == "Sun Mar 13 07:05:40 UTC 2011"
+end
- assert('Time#<=>', '15.2.19.7.3') do
- t1 = Time.at(1300000000.0)
- t2 = Time.at(1400000000.0)
- t3 = Time.at(1500000000.0)
+assert('Time#<=>', '15.2.19.7.3') do
+ t1 = Time.at(1300000000.0)
+ t2 = Time.at(1400000000.0)
+ t3 = Time.at(1500000000.0)
- t2.<=>(t1) == 1 and
- t2.<=>(t2) == 0 and
- t2.<=>(t3) == -1 and
- t2.<=>(nil) == nil
- end
+ t2.<=>(t1) == 1 and
+ t2.<=>(t2) == 0 and
+ t2.<=>(t3) == -1 and
+ t2.<=>(nil) == nil
+end
- assert('Time#asctime', '15.2.19.7.4') do
- Time.at(1300000000.0).utc.asctime == "Sun Mar 13 07:06:40 UTC 2011"
- end
+assert('Time#asctime', '15.2.19.7.4') do
+ Time.at(1300000000.0).utc.asctime == "Sun Mar 13 07:06:40 UTC 2011"
+end
- assert('Time#ctime', '15.2.19.7.5') do
- Time.at(1300000000.0).utc.ctime == "Sun Mar 13 07:06:40 UTC 2011"
- end
+assert('Time#ctime', '15.2.19.7.5') do
+ Time.at(1300000000.0).utc.ctime == "Sun Mar 13 07:06:40 UTC 2011"
+end
- assert('Time#day', '15.2.19.7.6') do
- Time.gm(2012, 12, 23).day == 23
- end
+assert('Time#day', '15.2.19.7.6') do
+ Time.gm(2012, 12, 23).day == 23
+end
- assert('Time#dst?', '15.2.19.7.7') do
- not Time.gm(2012, 12, 23).utc.dst?
- end
+assert('Time#dst?', '15.2.19.7.7') do
+ not Time.gm(2012, 12, 23).utc.dst?
+end
- assert('Time#getgm', '15.2.19.7.8') do
- Time.at(1300000000.0).getgm.asctime == "Sun Mar 13 07:06:40 UTC 2011"
- end
+assert('Time#getgm', '15.2.19.7.8') do
+ Time.at(1300000000.0).getgm.asctime == "Sun Mar 13 07:06:40 UTC 2011"
+end
- assert('Time#getlocal', '15.2.19.7.9') do
- t1 = Time.at(1300000000.0)
- t2 = Time.at(1300000000.0)
- t3 = t1.getlocal
+assert('Time#getlocal', '15.2.19.7.9') do
+ t1 = Time.at(1300000000.0)
+ t2 = Time.at(1300000000.0)
+ t3 = t1.getlocal
- t1 == t3 and t3 == t2.getlocal
- end
+ t1 == t3 and t3 == t2.getlocal
+end
- assert('Time#getutc', '15.2.19.7.10') do
- Time.at(1300000000.0).getutc.asctime == "Sun Mar 13 07:06:40 UTC 2011"
- end
+assert('Time#getutc', '15.2.19.7.10') do
+ Time.at(1300000000.0).getutc.asctime == "Sun Mar 13 07:06:40 UTC 2011"
+end
- assert('Time#gmt?', '15.2.19.7.11') do
- Time.at(1300000000.0).utc.gmt?
- end
+assert('Time#gmt?', '15.2.19.7.11') do
+ Time.at(1300000000.0).utc.gmt?
+end
- # ATM not implemented
- # assert('Time#gmt_offset', '15.2.19.7.12') do
+# ATM not implemented
+# assert('Time#gmt_offset', '15.2.19.7.12') do
- assert('Time#gmtime', '15.2.19.7.13') do
- Time.at(1300000000.0).gmtime
- end
+assert('Time#gmtime', '15.2.19.7.13') do
+ Time.at(1300000000.0).gmtime
+end
- # ATM not implemented
- # assert('Time#gmtoff', '15.2.19.7.14') do
+# ATM not implemented
+# assert('Time#gmtoff', '15.2.19.7.14') do
- assert('Time#hour', '15.2.19.7.15') do
- Time.gm(2012, 12, 23, 7, 6).hour == 7
- end
+assert('Time#hour', '15.2.19.7.15') do
+ Time.gm(2012, 12, 23, 7, 6).hour == 7
+end
- # ATM doesn't really work
- # assert('Time#initialize', '15.2.19.7.16') do
+# ATM doesn't really work
+# assert('Time#initialize', '15.2.19.7.16') do
- assert('Time#initialize_copy', '15.2.19.7.17') do
- time_tmp_2 = Time.at(7.0e6)
- time_tmp_2.clone == time_tmp_2
- end
+assert('Time#initialize_copy', '15.2.19.7.17') do
+ time_tmp_2 = Time.at(7.0e6)
+ time_tmp_2.clone == time_tmp_2
+end
- assert('Time#localtime', '15.2.19.7.18') do
- t1 = Time.at(1300000000.0)
- t2 = Time.at(1300000000.0)
+assert('Time#localtime', '15.2.19.7.18') do
+ t1 = Time.at(1300000000.0)
+ t2 = Time.at(1300000000.0)
- t1.localtime
- t1 == t2.getlocal
- end
+ t1.localtime
+ t1 == t2.getlocal
+end
- assert('Time#mday', '15.2.19.7.19') do
- Time.gm(2012, 12, 23).mday == 23
- end
+assert('Time#mday', '15.2.19.7.19') do
+ Time.gm(2012, 12, 23).mday == 23
+end
- assert('Time#min', '15.2.19.7.20') do
- Time.gm(2012, 12, 23, 7, 6).min == 6
- end
+assert('Time#min', '15.2.19.7.20') do
+ Time.gm(2012, 12, 23, 7, 6).min == 6
+end
- assert('Time#mon', '15.2.19.7.21') do
- Time.gm(2012, 12, 23).mon == 12
- end
+assert('Time#mon', '15.2.19.7.21') do
+ Time.gm(2012, 12, 23).mon == 12
+end
- assert('Time#month', '15.2.19.7.22') do
- Time.gm(2012, 12, 23).month == 12
- end
+assert('Time#month', '15.2.19.7.22') do
+ Time.gm(2012, 12, 23).month == 12
+end
- assert('Times#sec', '15.2.19.7.23') do
- Time.gm(2012, 12, 23, 7, 6, 40).sec == 40
- end
+assert('Times#sec', '15.2.19.7.23') do
+ Time.gm(2012, 12, 23, 7, 6, 40).sec == 40
+end
- assert('Time#to_f', '15.2.19.7.24') do
- Time.at(1300000000.0).to_f == 1300000000.0
- end
+assert('Time#to_f', '15.2.19.7.24') do
+ Time.at(1300000000.0).to_f == 1300000000.0
+end
- assert('Time#to_i', '15.2.19.7.25') do
- Time.at(1300000000.0).to_i == 1300000000
- end
+assert('Time#to_i', '15.2.19.7.25') do
+ Time.at(1300000000.0).to_i == 1300000000
+end
- assert('Time#usec', '15.2.19.7.26') do
- Time.at(1300000000.0).usec == 0
- end
+assert('Time#usec', '15.2.19.7.26') do
+ Time.at(1300000000.0).usec == 0
+end
- assert('Time#utc', '15.2.19.7.27') do
- Time.at(1300000000.0).utc
- end
+assert('Time#utc', '15.2.19.7.27') do
+ Time.at(1300000000.0).utc
+end
- assert('Time#utc?', '15.2.19.7.28') do
- Time.at(1300000000.0).utc.utc?
- end
+assert('Time#utc?', '15.2.19.7.28') do
+ Time.at(1300000000.0).utc.utc?
+end
- # ATM not implemented
- # assert('Time#utc_offset', '15.2.19.7.29') do
+# ATM not implemented
+# assert('Time#utc_offset', '15.2.19.7.29') do
- assert('Time#wday', '15.2.19.7.30') do
- Time.gm(2012, 12, 23).wday == 0
- end
+assert('Time#wday', '15.2.19.7.30') do
+ Time.gm(2012, 12, 23).wday == 0
+end
- assert('Time#yday', '15.2.19.7.31') do
- Time.gm(2012, 12, 23).yday == 358
- end
+assert('Time#yday', '15.2.19.7.31') do
+ Time.gm(2012, 12, 23).yday == 358
+end
- assert('Time#year', '15.2.19.7.32') do
- Time.gm(2012, 12, 23).year == 2012
- end
+assert('Time#year', '15.2.19.7.32') do
+ Time.gm(2012, 12, 23).year == 2012
+end
- assert('Time#zone', '15.2.19.7.33') do
- Time.at(1300000000.0).utc.zone == 'UTC'
- end
+assert('Time#zone', '15.2.19.7.33') do
+ Time.at(1300000000.0).utc.zone == 'UTC'
+end
- # Not ISO specified
+# Not ISO specified
- assert('Time#to_s') do
- Time.at(1300000000.0).utc.to_s == "Sun Mar 13 07:06:40 UTC 2011"
- end
+assert('Time#to_s') do
+ Time.at(1300000000.0).utc.to_s == "Sun Mar 13 07:06:40 UTC 2011"
+end
- assert('Time#inspect') do
- Time.at(1300000000.0).utc.inspect == "Sun Mar 13 07:06:40 UTC 2011"
- end
+assert('Time#inspect') do
+ Time.at(1300000000.0).utc.inspect == "Sun Mar 13 07:06:40 UTC 2011"
end
+assert('day of week methods') do
+ t = Time.gm(2012, 12, 24)
+ assert_false t.sunday?
+ assert_true t.monday?
+ assert_false t.tuesday?
+ assert_false t.wednesday?
+ assert_false t.thursday?
+ assert_false t.friday?
+ assert_false t.saturday?
+end
diff --git a/mrblib/error.rb b/mrblib/error.rb
index 9e5a3daeb..6e8181e9d 100644
--- a/mrblib/error.rb
+++ b/mrblib/error.rb
@@ -40,10 +40,6 @@ end
class NameError < StandardError
attr_accessor :name
- def new(message="NameError", name=nil)
- initialize(message, name)
- end
-
def initialize(message=nil, name=nil)
@name = name
super(message)
diff --git a/mrblib/hash.rb b/mrblib/hash.rb
index 5828a13eb..9bb146b27 100644
--- a/mrblib/hash.rb
+++ b/mrblib/hash.rb
@@ -179,7 +179,7 @@ class Hash
# ISO 15.2.13.4.22
def merge(other, &block)
h = {}
- raise "can't convert argument into Hash" unless other.respond_to?(:to_hash)
+ raise TypeError, "can't convert argument into Hash" unless other.respond_to?(:to_hash)
other = other.to_hash
self.each_key{|k| h[k] = self[k]}
if block
@@ -205,7 +205,16 @@ class Hash
# ISO 15.2.13.4.31 (x)
alias to_s inspect
- # 1.8/1.9 Hash#reject! returns Hash; ISO says nothing.
+ ##
+ # call-seq:
+ # hsh.reject! {| key, value | block } -> hsh or nil
+ # hsh.reject! -> an_enumerator
+ #
+ # Equivalent to <code>Hash#delete_if</code>, but returns
+ # <code>nil</code> if no changes were made.
+ #
+ # 1.8/1.9 Hash#reject! returns Hash; ISO says nothing.
+ #
def reject!(&b)
return to_enum :reject! unless block_given?
@@ -222,7 +231,21 @@ class Hash
self
end
- # 1.8/1.9 Hash#reject returns Hash; ISO says nothing.
+ ##
+ # call-seq:
+ # hsh.reject {|key, value| block} -> a_hash
+ # hsh.reject -> an_enumerator
+ #
+ # Returns a new hash consisting of entries for which the block returns false.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ # h = { "a" => 100, "b" => 200, "c" => 300 }
+ # h.reject {|k,v| k < "b"} #=> {"b" => 200, "c" => 300}
+ # h.reject {|k,v| v > 100} #=> {"a" => 100}
+ #
+ # 1.8/1.9 Hash#reject returns Hash; ISO says nothing.
+ #
def reject(&b)
return to_enum :reject unless block_given?
@@ -235,7 +258,16 @@ class Hash
h
end
- # 1.9 Hash#select! returns Hash; ISO says nothing.
+ ##
+ # call-seq:
+ # hsh.select! {| key, value | block } -> hsh or nil
+ # hsh.select! -> an_enumerator
+ #
+ # Equivalent to <code>Hash#keep_if</code>, but returns
+ # <code>nil</code> if no changes were made.
+ #
+ # 1.9 Hash#select! returns Hash; ISO says nothing.
+ #
def select!(&b)
return to_enum :select! unless block_given?
@@ -252,7 +284,21 @@ class Hash
self
end
- # 1.9 Hash#select returns Hash; ISO says nothing.
+ ##
+ # call-seq:
+ # hsh.select {|key, value| block} -> a_hash
+ # hsh.select -> an_enumerator
+ #
+ # Returns a new hash consisting of entries for which the block returns true.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ # h = { "a" => 100, "b" => 200, "c" => 300 }
+ # h.select {|k,v| k > "a"} #=> {"b" => 200, "c" => 300}
+ # h.select {|k,v| v < 200} #=> {"a" => 100}
+ #
+ # 1.9 Hash#select returns Hash; ISO says nothing
+ #
def select(&b)
return to_enum :select unless block_given?
diff --git a/src/array.c b/src/array.c
index febc3a7a8..d008e52cf 100644
--- a/src/array.c
+++ b/src/array.c
@@ -401,7 +401,7 @@ mrb_ary_push(mrb_state *mrb, mrb_value ary, mrb_value elem)
if (a->len == a->aux.capa)
ary_expand_capa(mrb, a, a->len + 1);
a->ptr[a->len++] = elem;
- mrb_write_barrier(mrb, (struct RBasic*)a);
+ mrb_field_write_barrier_value(mrb, (struct RBasic*)a, elem);
}
static mrb_value
@@ -484,7 +484,7 @@ mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item)
a->ptr[0] = item;
}
a->len++;
- mrb_write_barrier(mrb, (struct RBasic*)a);
+ mrb_field_write_barrier_value(mrb, (struct RBasic*)a, item);
return self;
}
@@ -511,7 +511,9 @@ mrb_ary_unshift_m(mrb_state *mrb, mrb_value self)
}
array_copy(a->ptr, vals, len);
a->len += len;
- mrb_write_barrier(mrb, (struct RBasic*)a);
+ while (len--) {
+ mrb_field_write_barrier_value(mrb, (struct RBasic*)a, vals[len]);
+ }
return self;
}
@@ -549,7 +551,7 @@ mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val)
}
a->ptr[n] = val;
- mrb_write_barrier(mrb, (struct RBasic*)a);
+ mrb_field_write_barrier_value(mrb, (struct RBasic*)a, val);
}
mrb_value
@@ -561,6 +563,10 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val
mrb_int i, argc;
ary_modify(mrb, a);
+
+ /* len check */
+ if (len < 0) mrb_raisef(mrb, E_INDEX_ERROR, "negative length (%S)", mrb_fixnum_value(len));
+
/* range check */
if (head < 0) {
head += a->len;
@@ -597,6 +603,7 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val
for (i = 0; i < argc; i++) {
*(a->ptr + head + i) = *(argv + i);
+ mrb_field_write_barrier_value(mrb, (struct RBasic*)a, argv[i]);
}
a->len = size;
diff --git a/src/error.c b/src/error.c
index 6f7641cf1..b4fac2097 100644
--- a/src/error.c
+++ b/src/error.c
@@ -445,20 +445,20 @@ mrb_sys_fail(mrb_state *mrb, const char *mesg)
void
mrb_init_exception(mrb_state *mrb)
{
- struct RClass *e;
-
- mrb->eException_class = e = mrb_define_class(mrb, "Exception", mrb->object_class); /* 15.2.22 */
- mrb_define_class_method(mrb, e, "exception", mrb_instance_new, MRB_ARGS_ANY());
- mrb_define_method(mrb, e, "exception", exc_exception, MRB_ARGS_ANY());
- mrb_define_method(mrb, e, "initialize", exc_initialize, MRB_ARGS_ANY());
- mrb_define_method(mrb, e, "==", exc_equal, MRB_ARGS_REQ(1));
- mrb_define_method(mrb, e, "to_s", exc_to_s, MRB_ARGS_NONE());
- mrb_define_method(mrb, e, "message", exc_message, MRB_ARGS_NONE());
- mrb_define_method(mrb, e, "inspect", exc_inspect, MRB_ARGS_NONE());
- mrb_define_method(mrb, e, "backtrace", mrb_exc_backtrace, MRB_ARGS_NONE());
+ struct RClass *exception, *script_error;
+
+ mrb->eException_class = exception = mrb_define_class(mrb, "Exception", mrb->object_class); /* 15.2.22 */
+ mrb_define_class_method(mrb, exception, "exception", mrb_instance_new, MRB_ARGS_ANY());
+ mrb_define_method(mrb, exception, "exception", exc_exception, MRB_ARGS_ANY());
+ mrb_define_method(mrb, exception, "initialize", exc_initialize, MRB_ARGS_ANY());
+ mrb_define_method(mrb, exception, "==", exc_equal, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, exception, "to_s", exc_to_s, MRB_ARGS_NONE());
+ mrb_define_method(mrb, exception, "message", exc_message, MRB_ARGS_NONE());
+ mrb_define_method(mrb, exception, "inspect", exc_inspect, MRB_ARGS_NONE());
+ mrb_define_method(mrb, exception, "backtrace", mrb_exc_backtrace, MRB_ARGS_NONE());
mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */
mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */
- e = mrb_define_class(mrb, "ScriptError", mrb->eException_class); /* 15.2.37 */
- mrb_define_class(mrb, "SyntaxError", e); /* 15.2.38 */
+ script_error = mrb_define_class(mrb, "ScriptError", mrb->eException_class); /* 15.2.37 */
+ mrb_define_class(mrb, "SyntaxError", script_error); /* 15.2.38 */
}
diff --git a/src/hash.c b/src/hash.c
index c39560d5c..8e6be2214 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -221,7 +221,7 @@ mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val)
kh_value(h, k).n = kh_size(h)-1;
}
- mrb_write_barrier(mrb, (struct RBasic*)RHASH(hash));
+ mrb_field_write_barrier_value(mrb, (struct RBasic*)RHASH(hash), val);
return;
}
diff --git a/src/kernel.c b/src/kernel.c
index 4db8ad7ee..7bcbd6518 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -93,24 +93,18 @@ static mrb_value
mrb_obj_equal_m(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
- mrb_bool eql_p;
mrb_get_args(mrb, "o", &arg);
- eql_p = mrb_obj_equal(mrb, self, arg);
-
- return mrb_bool_value(eql_p);
+ return mrb_bool_value(mrb_obj_equal(mrb, self, arg));
}
static mrb_value
mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
- mrb_bool eql_p;
mrb_get_args(mrb, "o", &arg);
- eql_p = mrb_equal(mrb, self, arg);
-
- return mrb_bool_value(!eql_p);
+ return mrb_bool_value(!mrb_equal(mrb, self, arg));
}
/* 15.3.1.3.2 */
@@ -126,12 +120,9 @@ static mrb_value
mrb_equal_m(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
- mrb_bool equal_p;
mrb_get_args(mrb, "o", &arg);
- equal_p = mrb_equal(mrb, self, arg);
-
- return mrb_bool_value(equal_p);
+ return mrb_bool_value(mrb_equal(mrb, self, arg));
}
/* 15.3.1.3.3 */
@@ -210,26 +201,6 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
return mrb_bool_value(given_p);
}
-/*
- * call-seq:
- * __method__ -> symbol
- *
- * Returns the name at the definition of the current method as a
- * Symbol.
- * If called outside of a method, it returns <code>nil</code>.
- *
- */
-static mrb_value
-mrb_f_method(mrb_state *mrb, mrb_value self)
-{
- mrb_callinfo *ci = mrb->c->ci;
- ci--;
- if (ci->mid)
- return mrb_symbol_value(ci->mid);
- else
- return mrb_nil_value();
-}
-
/* 15.3.1.3.7 */
/*
* call-seq:
@@ -296,21 +267,21 @@ static void
init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj)
{
switch (mrb_type(obj)) {
- case MRB_TT_CLASS:
- case MRB_TT_MODULE:
- copy_class(mrb, dest, obj);
- /* fall through */
- case MRB_TT_OBJECT:
- case MRB_TT_SCLASS:
- case MRB_TT_HASH:
- case MRB_TT_DATA:
- mrb_iv_copy(mrb, dest, obj);
- break;
-
- default:
- break;
- }
- mrb_funcall(mrb, dest, "initialize_copy", 1, obj);
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ copy_class(mrb, dest, obj);
+ /* fall through */
+ case MRB_TT_OBJECT:
+ case MRB_TT_SCLASS:
+ case MRB_TT_HASH:
+ case MRB_TT_DATA:
+ mrb_iv_copy(mrb, dest, obj);
+ break;
+
+ default:
+ break;
+ }
+ mrb_funcall(mrb, dest, "initialize_copy", 1, obj);
}
/* 15.3.1.3.8 */
@@ -346,7 +317,7 @@ mrb_obj_clone(mrb_state *mrb, mrb_value self)
mrb_value clone;
if (mrb_special_const_p(self)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %S", self);
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %S", self);
}
p = (struct RObject*)mrb_obj_alloc(mrb, mrb_type(self), mrb_obj_class(mrb, self));
p->c = mrb_singleton_class_clone(mrb, self);
@@ -378,17 +349,17 @@ mrb_obj_clone(mrb_state *mrb, mrb_value self)
mrb_value
mrb_obj_dup(mrb_state *mrb, mrb_value obj)
{
- struct RBasic *p;
- mrb_value dup;
+ struct RBasic *p;
+ mrb_value dup;
- if (mrb_special_const_p(obj)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "can't dup %S", obj);
- }
- p = mrb_obj_alloc(mrb, mrb_type(obj), mrb_obj_class(mrb, obj));
- dup = mrb_obj_value(p);
- init_copy(mrb, dup, obj);
+ if (mrb_special_const_p(obj)) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't dup %S", obj);
+ }
+ p = mrb_obj_alloc(mrb, mrb_type(obj), mrb_obj_class(mrb, obj));
+ dup = mrb_obj_value(p);
+ init_copy(mrb, dup, obj);
- return dup;
+ return dup;
}
static mrb_value
@@ -924,7 +895,7 @@ mrb_obj_public_methods(mrb_state *mrb, mrb_value self)
* raise "Failed to create socket"
* raise ArgumentError, "No parameters", caller
*/
-static mrb_value
+mrb_value
mrb_f_raise(mrb_state *mrb, mrb_value self)
{
mrb_value a[2], exc;
@@ -1153,7 +1124,6 @@ mrb_init_kernel(mrb_state *mrb)
mrb_define_method(mrb, krn, "===", mrb_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.2 */
mrb_define_method(mrb, krn, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.3 */
mrb_define_method(mrb, krn, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.4 */
- mrb_define_method(mrb, krn, "__method__", mrb_f_method, MRB_ARGS_NONE());
mrb_define_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.6 */
mrb_define_method(mrb, krn, "class", mrb_obj_class_m, MRB_ARGS_NONE()); /* 15.3.1.3.7 */
mrb_define_method(mrb, krn, "clone", mrb_obj_clone, MRB_ARGS_NONE()); /* 15.3.1.3.8 */
diff --git a/src/load.c b/src/load.c
index c6aff4f9c..1142a6eaf 100644
--- a/src/load.c
+++ b/src/load.c
@@ -191,12 +191,10 @@ read_section_irep(mrb_state *mrb, const uint8_t *bin, mrb_bool alloc)
static int
read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t *len)
{
- int ret;
size_t i, fname_len, niseq;
char *fname;
uint16_t *lines;
- ret = MRB_DUMP_OK;
*len = 0;
bin += sizeof(uint32_t); /* record size */
*len += sizeof(uint32_t);
@@ -228,7 +226,7 @@ read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t
irep->filename = fname;
irep->lines = lines;
- return ret;
+ return MRB_DUMP_OK;
}
static int
diff --git a/src/numeric.c b/src/numeric.c
index 56835edbf..357e9438e 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -774,17 +774,17 @@ static mrb_value
fix_mod(mrb_state *mrb, mrb_value x)
{
mrb_value y;
- mrb_int a, b;
+ mrb_int a;
mrb_get_args(mrb, "o", &y);
a = mrb_fixnum(x);
- if (mrb_fixnum_p(y) && (b=mrb_fixnum(y)) != 0) {
- mrb_int mod;
+ if (mrb_fixnum_p(y)) {
+ mrb_int b, mod;
- if (mrb_fixnum(y) == 0) {
+ if ((b=mrb_fixnum(y)) == 0) {
return mrb_float_value(mrb, NAN);
}
- fixdivmod(mrb, a, mrb_fixnum(y), 0, &mod);
+ fixdivmod(mrb, a, b, 0, &mod);
return mrb_fixnum_value(mod);
}
else {
@@ -1109,9 +1109,7 @@ mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y)
if (a == 0) return y;
b = mrb_fixnum(y);
- c = a + b;
- if (((a < 0) ^ (b < 0)) == 0 && (a < 0) != (c < 0)) {
- /* integer overflow */
+ if (mrb_int_add_overflow(a, b, &c)) {
return mrb_float_value(mrb, (mrb_float)a + (mrb_float)b);
}
return mrb_fixnum_value(c);
@@ -1147,9 +1145,7 @@ mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y)
mrb_int b, c;
b = mrb_fixnum(y);
- c = a - b;
- if (((a < 0) ^ (b < 0)) != 0 && (a < 0) != (c < 0)) {
- /* integer overflow */
+ if (mrb_int_sub_overflow(a, b, &c)) {
return mrb_float_value(mrb, (mrb_float)a - (mrb_float)b);
}
return mrb_fixnum_value(c);
diff --git a/src/parse.y b/src/parse.y
index 230d7659e..205405065 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -5466,7 +5466,7 @@ mrb_parser_set_filename(struct mrb_parser_state *p, const char *f)
new_table = (mrb_sym*)parser_palloc(p, sizeof(mrb_sym) * p->filename_table_length);
if (p->filename_table) {
- memcpy(new_table, p->filename_table, sizeof(mrb_sym) * p->filename_table_length);
+ memmove(new_table, p->filename_table, sizeof(mrb_sym) * p->filename_table_length);
}
p->filename_table = new_table;
p->filename_table[p->filename_table_length - 1] = sym;
diff --git a/src/string.c b/src/string.c
index aa4f6bed5..d5a849cec 100644
--- a/src/string.c
+++ b/src/string.c
@@ -914,7 +914,7 @@ static mrb_value
mrb_str_capitalize_bang(mrb_state *mrb, mrb_value str)
{
char *p, *pend;
- int modify = 0;
+ mrb_bool modify = FALSE;
struct RString *s = mrb_str_ptr(str);
mrb_str_modify(mrb, s);
@@ -922,12 +922,12 @@ mrb_str_capitalize_bang(mrb_state *mrb, mrb_value str)
p = STR_PTR(s); pend = STR_PTR(s) + STR_LEN(s);
if (ISLOWER(*p)) {
*p = TOUPPER(*p);
- modify = 1;
+ modify = TRUE;
}
while (++p < pend) {
if (ISUPPER(*p)) {
*p = TOLOWER(*p);
- modify = 1;
+ modify = TRUE;
}
}
if (modify) return str;
@@ -1128,7 +1128,7 @@ static mrb_value
mrb_str_downcase_bang(mrb_state *mrb, mrb_value str)
{
char *p, *pend;
- int modify = 0;
+ mrb_bool modify = FALSE;
struct RString *s = mrb_str_ptr(str);
mrb_str_modify(mrb, s);
@@ -1137,7 +1137,7 @@ mrb_str_downcase_bang(mrb_state *mrb, mrb_value str)
while (p < pend) {
if (ISUPPER(*p)) {
*p = TOLOWER(*p);
- modify = 1;
+ modify = TRUE;
}
p++;
}
@@ -1230,8 +1230,6 @@ mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
mrb_value
mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
{
- mrb_value str2;
-
if (len < 0) return mrb_nil_value();
if (!RSTRING_LEN(str)) {
len = 0;
@@ -1246,9 +1244,7 @@ mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
if (len <= 0) {
len = 0;
}
- str2 = mrb_str_subseq(mrb, str, beg, len);
-
- return str2;
+ return mrb_str_subseq(mrb, str, beg, len);
}
mrb_int
@@ -1264,8 +1260,7 @@ mrb_str_hash(mrb_state *mrb, mrb_value str)
key = key*65599 + *p;
p++;
}
- key = key + (key>>5);
- return key;
+ return key + (key>>5);
}
/* 15.2.10.5.20 */
@@ -1851,7 +1846,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
char *ptr = RSTRING_PTR(str);
char *eptr = RSTRING_END(str);
char *bptr = ptr;
- int skip = 1;
+ mrb_bool skip = TRUE;
unsigned int c;
end = beg;
@@ -1864,14 +1859,14 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
}
else {
end = ptr - bptr;
- skip = 0;
+ skip = FALSE;
if (lim_p && lim <= i) break;
}
}
else if (ascii_isspace(c)) {
mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, beg, end-beg));
mrb_gc_arena_restore(mrb, ai);
- skip = 1;
+ skip = TRUE;
beg = ptr - bptr;
if (lim_p) ++i;
}
@@ -2285,7 +2280,7 @@ mrb_str_upcase_bang(mrb_state *mrb, mrb_value str)
{
struct RString *s = mrb_str_ptr(str);
char *p, *pend;
- int modify = 0;
+ mrb_bool modify = FALSE;
mrb_str_modify(mrb, s);
p = RSTRING_PTR(str);
@@ -2293,7 +2288,7 @@ mrb_str_upcase_bang(mrb_state *mrb, mrb_value str)
while (p < pend) {
if (ISLOWER(*p)) {
*p = TOUPPER(*p);
- modify = 1;
+ modify = TRUE;
}
p++;
}
@@ -2484,54 +2479,54 @@ mrb_str_append(mrb_state *mrb, mrb_value str, mrb_value str2)
mrb_value
mrb_str_inspect(mrb_state *mrb, mrb_value str)
{
- const char *p, *pend;
- char buf[CHAR_ESC_LEN + 1];
- mrb_value result = mrb_str_new_lit(mrb, "\"");
+ const char *p, *pend;
+ char buf[CHAR_ESC_LEN + 1];
+ mrb_value result = mrb_str_new_lit(mrb, "\"");
- p = RSTRING_PTR(str); pend = RSTRING_END(str);
- for (;p < pend; p++) {
- unsigned char c, cc;
+ p = RSTRING_PTR(str); pend = RSTRING_END(str);
+ for (;p < pend; p++) {
+ unsigned char c, cc;
- c = *p;
- if (c == '"'|| c == '\\' || (c == '#' && IS_EVSTR(p, pend))) {
- buf[0] = '\\'; buf[1] = c;
- mrb_str_cat(mrb, result, buf, 2);
- continue;
- }
- if (ISPRINT(c)) {
- buf[0] = c;
- mrb_str_cat(mrb, result, buf, 1);
- continue;
- }
- switch (c) {
- case '\n': cc = 'n'; break;
- case '\r': cc = 'r'; break;
- case '\t': cc = 't'; break;
- case '\f': cc = 'f'; break;
- case '\013': cc = 'v'; break;
- case '\010': cc = 'b'; break;
- case '\007': cc = 'a'; break;
- case 033: cc = 'e'; break;
- default: cc = 0; break;
- }
- if (cc) {
- buf[0] = '\\';
- buf[1] = (char)cc;
- mrb_str_cat(mrb, result, buf, 2);
- continue;
- }
- else {
- buf[0] = '\\';
- buf[3] = '0' + c % 8; c /= 8;
- buf[2] = '0' + c % 8; c /= 8;
- buf[1] = '0' + c % 8;
- mrb_str_cat(mrb, result, buf, 4);
- continue;
- }
+ c = *p;
+ if (c == '"'|| c == '\\' || (c == '#' && IS_EVSTR(p, pend))) {
+ buf[0] = '\\'; buf[1] = c;
+ mrb_str_cat(mrb, result, buf, 2);
+ continue;
+ }
+ if (ISPRINT(c)) {
+ buf[0] = c;
+ mrb_str_cat(mrb, result, buf, 1);
+ continue;
}
- mrb_str_cat_lit(mrb, result, "\"");
+ switch (c) {
+ case '\n': cc = 'n'; break;
+ case '\r': cc = 'r'; break;
+ case '\t': cc = 't'; break;
+ case '\f': cc = 'f'; break;
+ case '\013': cc = 'v'; break;
+ case '\010': cc = 'b'; break;
+ case '\007': cc = 'a'; break;
+ case 033: cc = 'e'; break;
+ default: cc = 0; break;
+ }
+ if (cc) {
+ buf[0] = '\\';
+ buf[1] = (char)cc;
+ mrb_str_cat(mrb, result, buf, 2);
+ continue;
+ }
+ else {
+ buf[0] = '\\';
+ buf[3] = '0' + c % 8; c /= 8;
+ buf[2] = '0' + c % 8; c /= 8;
+ buf[1] = '0' + c % 8;
+ mrb_str_cat(mrb, result, buf, 4);
+ continue;
+ }
+ }
+ mrb_str_cat_lit(mrb, result, "\"");
- return result;
+ return result;
}
/*
diff --git a/src/vm.c b/src/vm.c
index 0e3c0a81e..6e30eab72 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -12,6 +12,7 @@
#include "mruby/class.h"
#include "mruby/hash.h"
#include "mruby/irep.h"
+#include "mruby/numeric.h"
#include "mruby/proc.h"
#include "mruby/range.h"
#include "mruby/string.h"
@@ -1285,6 +1286,9 @@ RETRY_TRY_BLOCK:
int len = m1 + o + r + m2;
mrb_value *blk = &argv[argc < 0 ? 1 : argc];
+ if (!mrb_nil_p(*blk) && mrb_type(*blk) != MRB_TT_PROC) {
+ *blk = mrb_convert_type(mrb, *blk, MRB_TT_PROC, "Proc", "to_proc");
+ }
if (argc < 0) {
struct RArray *ary = mrb_ary_ptr(regs[1]);
argv = ary->ptr;
@@ -1300,20 +1304,25 @@ RETRY_TRY_BLOCK:
}
}
else if (len > 1 && argc == 1 && mrb_array_p(argv[0])) {
+ mrb_gc_protect(mrb, argv[0]);
argc = mrb_ary_ptr(argv[0])->len;
argv = mrb_ary_ptr(argv[0])->ptr;
}
mrb->c->ci->argc = len;
if (argc < len) {
+ int mlen = m2;
+ if (argc < m1+m2) {
+ if (m1 < argc)
+ mlen = argc - m1;
+ else
+ mlen = 0;
+ }
regs[len+1] = *blk; /* move block */
+ SET_NIL_VALUE(regs[argc+1]);
if (argv0 != argv) {
- value_move(&regs[1], argv, argc-m2); /* m1 + o */
+ value_move(&regs[1], argv, argc-mlen); /* m1 + o */
}
- if (m2) {
- int mlen = m2;
- if (argc-m2 <= m1) {
- mlen = argc - m1;
- }
+ if (mlen) {
value_move(&regs[len-m2+1], &argv[argc-mlen], mlen);
}
if (r) {
@@ -1324,16 +1333,18 @@ RETRY_TRY_BLOCK:
pc += argc - m1 - m2 + 1;
}
else {
+ int rnum = 0;
if (argv0 != argv) {
regs[len+1] = *blk; /* move block */
value_move(&regs[1], argv, m1+o);
}
if (r) {
- regs[m1+o+1] = mrb_ary_new_from_values(mrb, argc-m1-o-m2, argv+m1+o);
+ rnum = argc-m1-o-m2;
+ regs[m1+o+1] = mrb_ary_new_from_values(mrb, rnum, argv+m1+o);
}
if (m2) {
if (argc-m2 > m1) {
- value_move(&regs[m1+o+r+1], &argv[argc-m2], m2);
+ value_move(&regs[m1+o+r+1], &argv[m1+o+rnum], m2);
}
}
if (argv0 == argv) {
@@ -1610,12 +1621,7 @@ RETRY_TRY_BLOCK:
x = mrb_fixnum(regs_a[0]);
y = mrb_fixnum(regs_a[1]);
- z = x + y;
-#ifdef MRB_WORD_BOXING
- z = (z << MRB_FIXNUM_SHIFT) / (1 << MRB_FIXNUM_SHIFT);
-#endif
- if ((x < 0) != (z < 0) && ((x < 0) ^ (y < 0)) == 0) {
- /* integer overflow */
+ if (mrb_int_add_overflow(x, y, &z)) {
SET_FLT_VALUE(mrb, regs_a[0], (mrb_float)x + (mrb_float)y);
break;
}
@@ -1673,12 +1679,7 @@ RETRY_TRY_BLOCK:
x = mrb_fixnum(regs[a]);
y = mrb_fixnum(regs[a+1]);
- z = x - y;
-#ifdef MRB_WORD_BOXING
- z = (z << MRB_FIXNUM_SHIFT) / (1 << MRB_FIXNUM_SHIFT);
-#endif
- if (((x < 0) ^ (y < 0)) != 0 && (x < 0) != (z < 0)) {
- /* integer overflow */
+ if (mrb_int_sub_overflow(x, y, &z)) {
SET_FLT_VALUE(mrb, regs[a], (mrb_float)x - (mrb_float)y);
break;
}
@@ -1842,10 +1843,9 @@ RETRY_TRY_BLOCK:
{
mrb_int x = regs[a].attr_i;
mrb_int y = GETARG_C(i);
- mrb_int z = x + y;
+ mrb_int z;
- if (((x < 0) ^ (y < 0)) == 0 && (x < 0) != (z < 0)) {
- /* integer overflow */
+ if (mrb_int_add_overflow(x, y, &z)) {
SET_FLT_VALUE(mrb, regs[a], (mrb_float)x + (mrb_float)y);
break;
}
@@ -1881,10 +1881,9 @@ RETRY_TRY_BLOCK:
{
mrb_int x = regs_a[0].attr_i;
mrb_int y = GETARG_C(i);
- mrb_int z = x - y;
+ mrb_int z;
- if ((x < 0) != (z < 0) && ((x < 0) ^ (y < 0)) != 0) {
- /* integer overflow */
+ if (mrb_int_sub_overflow(x, y, &z)) {
SET_FLT_VALUE(mrb, regs_a[0], (mrb_float)x - (mrb_float)y);
}
else {
diff --git a/tasks/mrbgems_test.rake b/tasks/mrbgems_test.rake
index d5e115f86..d06b7a24c 100644
--- a/tasks/mrbgems_test.rake
+++ b/tasks/mrbgems_test.rake
@@ -117,7 +117,7 @@ MRuby.each_target do
no_mrb_open_test_lib = no_mrb_open_test.ext(exts.object)
file no_mrb_open_test_lib => "#{no_mrb_open_test}.c"
- file "#{no_mrb_open_test}.c" => no_mrb_open_test_rbfiles do |t|
+ file "#{no_mrb_open_test}.c" => no_mrb_open_test_rbfiles + [MRUBY_CONFIG] do |t|
open(t.name, 'w') do |f|
f.puts %Q[/*]
f.puts %Q[ * This file contains a test code for following gems:]
diff --git a/test/t/array.rb b/test/t/array.rb
index 48f2fe0c4..56daf0b01 100644
--- a/test/t/array.rb
+++ b/test/t/array.rb
@@ -66,6 +66,11 @@ assert('Array#[]=', '15.2.12.5.5') do
# this will cause an exception due to the wrong arguments
a.[]=(1,2,3,4)
end
+ assert_raise(IndexError) do
+ # this will cause an exception due to the wrong arguments
+ a = [1,2,3,4,5]
+ a[1, -1] = 10
+ end
assert_equal(4, [1,2,3].[]=(1,4))
assert_equal(3, [1,2,3].[]=(1,2,3))
diff --git a/test/t/bs_block.rb b/test/t/bs_block.rb
index 0a58741e3..04a4a15ba 100644
--- a/test/t/bs_block.rb
+++ b/test/t/bs_block.rb
@@ -512,3 +512,10 @@ assert('BS Block 37') do
end
end
+assert('BS Block 38') do
+ def iter
+ yield 1,2,3,4,5,6
+ end
+
+ assert_equal [1,2,3,4,5], iter{|a,b,c=:c,d,e| [a,b,c,d,e]}
+end
diff --git a/test/t/exception.rb b/test/t/exception.rb
index 8099e911f..186ac2892 100644
--- a/test/t/exception.rb
+++ b/test/t/exception.rb
@@ -42,6 +42,16 @@ assert('Exception.exception', '15.2.22.4.1') do
assert_equal 'a', e.message
end
+assert('NameError', '15.2.31') do
+ assert_raise(NameError) do
+ raise NameError.new
+ end
+
+ e = NameError.new "msg", "name"
+ assert_equal "msg", e.message
+ assert_equal "name", e.name
+end
+
assert('ScriptError', '15.2.37') do
assert_raise(ScriptError) do
raise ScriptError.new
@@ -57,15 +67,16 @@ end
# Not ISO specified
assert('Exception 1') do
- begin
+r=begin
1+1
ensure
2+2
- end == 2
+ end
+ assert_equal 2, r
end
assert('Exception 2') do
- begin
+r=begin
1+1
begin
2+2
@@ -74,11 +85,12 @@ assert('Exception 2') do
end
ensure
4+4
- end == 4
+ end
+ assert_equal 4, r
end
assert('Exception 3') do
- begin
+r=begin
1+1
begin
2+2
@@ -92,7 +104,8 @@ assert('Exception 3') do
ensure
6+6
end
- end == 4
+ end
+ assert_equal 4, r
end
assert('Exception 4') do
@@ -171,17 +184,18 @@ assert('Exception 7') do
end
assert('Exception 8') do
- begin
+r=begin
1
rescue
2
else
3
- end == 3
+ end
+ assert_equal 3, r
end
assert('Exception 9') do
- begin
+r=begin
1+1
rescue
2+2
@@ -189,11 +203,12 @@ assert('Exception 9') do
3+3
ensure
4+4
- end == 6
+ end
+ assert_equal 6, r
end
assert('Exception 10') do
- begin
+r=begin
1+1
begin
2+2
@@ -208,7 +223,8 @@ assert('Exception 10') do
6+6
ensure
7+7
- end == 12
+ end
+ assert_equal 12, r
end
assert('Exception 11') do
@@ -273,12 +289,12 @@ assert('Exception 16') do
raise "foo"
false
rescue => e
- e.message == "foo"
+ assert_equal "foo", e.message
end
end
assert('Exception 17') do
- begin
+r=begin
raise "a" # StandardError
rescue ArgumentError
1
@@ -288,11 +304,12 @@ assert('Exception 17') do
3
ensure
4
- end == 2
+ end
+ assert_equal 2, r
end
assert('Exception 18') do
- begin
+r=begin
0
rescue ArgumentError
1
@@ -302,7 +319,8 @@ assert('Exception 18') do
3
ensure
4
- end == 3
+ end
+ assert_equal 3, r
end
assert('Exception 19') do
@@ -333,17 +351,17 @@ assert('Exception 19') do
end
assert('Exception#inspect without message') do
- Exception.new.inspect
+ assert_equal "Exception: Exception", Exception.new.inspect
end
assert('Exception#backtrace') do
- begin
- raise "get backtrace"
- rescue => e
- e.backtrace
+ assert_nothing_raised do
+ begin
+ raise "get backtrace"
+ rescue => e
+ e.backtrace
+ end
end
-
- true
end
assert('Raise in ensure') do
diff --git a/test/t/hash.rb b/test/t/hash.rb
index 2ddd33316..0d8d137c4 100644
--- a/test/t/hash.rb
+++ b/test/t/hash.rb
@@ -40,7 +40,7 @@ assert('Hash#dup') do
a = { 'a' => 1 }
b = a.dup
a['a'] = 2
- assert_equal(b, {'a' => 1})
+ assert_equal({'a' => 1}, b)
end
assert('Hash#default', '15.2.13.4.5') do
@@ -223,6 +223,10 @@ assert('Hash#merge', '15.2.13.4.22') do
'xyz_key' => 'xyz_value' }, result_1)
assert_equal({'abc_key' => 'abc_value', 'cba_key' => 'cba_value',
'xyz_key' => 'xyz_value' }, result_2)
+
+ assert_raise(TypeError) do
+ { 'abc_key' => 'abc_value' }.merge "a"
+ end
end
assert('Hash#replace', '15.2.13.4.23') do
diff --git a/test/t/integer.rb b/test/t/integer.rb
index 58a102943..b15d4645d 100644
--- a/test/t/integer.rb
+++ b/test/t/integer.rb
@@ -81,7 +81,7 @@ assert('Integer#%', '15.2.8.3.5') do
assert_equal 2, c
end
-assert('Integer#<=>', '15.2.8.3.6') do
+assert('Integer#<=>', '15.2.9.3.6') do
a = 1<=>0
b = 1<=>1
c = 1<=>2
diff --git a/test/t/kernel.rb b/test/t/kernel.rb
index c6b65ddf7..17f776683 100644
--- a/test/t/kernel.rb
+++ b/test/t/kernel.rb
@@ -528,20 +528,6 @@ assert('Kernel#global_variables') do
end
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
- end
- assert_equal(:m1, c.new.m1)
- assert_equal(:m2, c.new.m2)
-end
-
assert('Kernel#define_singleton_method') do
o = Object.new
ret = o.define_singleton_method(:test_method) do
diff --git a/test/t/proc.rb b/test/t/proc.rb
index 151e1df86..e871e637e 100644
--- a/test/t/proc.rb
+++ b/test/t/proc.rb
@@ -55,6 +55,46 @@ assert('Proc#call', '15.2.17.4.3') do
assert_equal 5, a2
end
+assert('Proc#call proc args pos block') do
+ pr = Proc.new {|a,b,&c|
+ [a, b, c.class, c&&c.call(:x)]
+ }
+ assert_equal [nil, nil, Proc, :proc], (pr.call(){ :proc })
+ assert_equal [1, nil, Proc, :proc], (pr.call(1){ :proc })
+ assert_equal [1, 2, Proc, :proc], (pr.call(1, 2){ :proc })
+ assert_equal [1, 2, Proc, :proc], (pr.call(1, 2, 3){ :proc })
+ assert_equal [1, 2, Proc, :proc], (pr.call(1, 2, 3, 4){ :proc })
+
+ assert_equal [nil, nil, Proc, :x], (pr.call(){|x| x})
+ assert_equal [1, nil, Proc, :x], (pr.call(1){|x| x})
+ assert_equal [1, 2, Proc, :x], (pr.call(1, 2){|x| x})
+ assert_equal [1, 2, Proc, :x], (pr.call(1, 2, 3){|x| x})
+ assert_equal [1, 2, Proc, :x], (pr.call(1, 2, 3, 4){|x| x})
+end
+
+assert('Proc#call proc args pos rest post') do
+ pr = Proc.new {|a,b,*c,d,e|
+ [a,b,c,d,e]
+ }
+ assert_equal [nil, nil, [], nil, nil], pr.call()
+ assert_equal [1, nil, [], nil, nil], pr.call(1)
+ assert_equal [1, 2, [], nil, nil], pr.call(1,2)
+ assert_equal [1, 2, [], 3, nil], pr.call(1,2,3)
+ assert_equal [1, 2, [], 3, 4], pr.call(1,2,3,4)
+ assert_equal [1, 2, [3], 4, 5], pr.call(1,2,3,4,5)
+ assert_equal [1, 2, [3, 4], 5, 6], pr.call(1,2,3,4,5,6)
+ assert_equal [1, 2, [3, 4, 5], 6,7], pr.call(1,2,3,4,5,6,7)
+
+ assert_equal [nil, nil, [], nil, nil], pr.call([])
+ assert_equal [1, nil, [], nil, nil], pr.call([1])
+ assert_equal [1, 2, [], nil, nil], pr.call([1,2])
+ assert_equal [1, 2, [], 3, nil], pr.call([1,2,3])
+ assert_equal [1, 2, [], 3, 4], pr.call([1,2,3,4])
+ assert_equal [1, 2, [3], 4, 5], pr.call([1,2,3,4,5])
+ assert_equal [1, 2, [3, 4], 5, 6], pr.call([1,2,3,4,5,6])
+ assert_equal [1, 2, [3, 4, 5], 6,7], pr.call([1,2,3,4,5,6,7])
+end
+
assert('Proc#return_does_not_break_self') do
class TestClass
attr_accessor :block
@@ -91,3 +131,20 @@ assert('Proc#return_does_not_break_self') do
assert_equal nil, c.return_nil
assert_equal c, c.block.call
end
+
+assert('&obj call to_proc if defined') do
+ pr = Proc.new{}
+ def mock(&b)
+ b
+ end
+ assert_equal pr.object_id, mock(&pr).object_id
+ assert_equal pr, mock(&pr)
+
+ obj = Object.new
+ def obj.to_proc
+ Proc.new{ :from_to_proc }
+ end
+ assert_equal :from_to_proc, mock(&obj).call
+
+ assert_raise(TypeError){ mock(&(Object.new)) }
+end
diff --git a/test/t/range.rb b/test/t/range.rb
index d7294cc1b..b35da40ab 100644
--- a/test/t/range.rb
+++ b/test/t/range.rb
@@ -46,7 +46,7 @@ assert('Range#first', '15.2.14.4.7') do
assert_equal 1, (1..10).first
end
-assert('Range#include', '15.2.14.4.8') do
+assert('Range#include?', '15.2.14.4.8') do
a = (1..10)
assert_true a.include?(5)
@@ -74,6 +74,20 @@ assert('Range#member?', '15.2.14.4.11') do
assert_false a.member?(20)
end
+assert('Range#to_s', '15.2.14.4.12') do
+ assert_equal "0..1", (0..1).to_s
+ assert_equal "0...1", (0...1).to_s
+ assert_equal "a..b", ("a".."b").to_s
+ assert_equal "a...b", ("a"..."b").to_s
+end
+
+assert('Range#inspect', '15.2.14.4.13') do
+ assert_equal "0..1", (0..1).inspect
+ assert_equal "0...1", (0...1).inspect
+ assert_equal "\"a\"..\"b\"", ("a".."b").inspect
+ assert_equal "\"a\"...\"b\"", ("a"..."b").inspect
+end
+
assert('Range#eql?', '15.2.14.4.14') do
assert_true (1..10).eql? (1..10)
assert_false (1..10).eql? (1..100)
diff --git a/test/t/string.rb b/test/t/string.rb
index 04f90fb45..5ecb51530 100644
--- a/test/t/string.rb
+++ b/test/t/string.rb
@@ -475,6 +475,15 @@ assert('String#upcase!', '15.2.10.5.43') do
assert_equal 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', b
end
+assert('String#inspect', '15.2.10.5.46') do
+ # should not raise an exception - regress #1210
+ assert_nothing_raised do
+ ("\1" * 100).inspect
+ end
+
+ assert_equal "\"\\000\"", "\0".inspect
+end
+
# Not ISO specified
assert('String interpolation (mrb_str_concat for shared strings)') do
@@ -506,8 +515,3 @@ assert('String#each_byte') do
assert_equal bytes1, bytes2
end
-
-assert('String#inspect') do
- ("\1" * 100).inspect # should not raise an exception - regress #1210
- assert_equal "\"\\000\"", "\0".inspect
-end