diff options
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; } /* @@ -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(®s[1], argv, argc-m2); /* m1 + o */ + value_move(®s[1], argv, argc-mlen); /* m1 + o */ } - if (m2) { - int mlen = m2; - if (argc-m2 <= m1) { - mlen = argc - m1; - } + if (mlen) { value_move(®s[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(®s[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(®s[m1+o+r+1], &argv[argc-m2], m2); + value_move(®s[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 |
