diff options
| -rw-r--r-- | include/mruby/class.h | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-bin-debugger/bintest/print.rb | 10 | ||||
| -rw-r--r-- | mrbgems/mruby-complex/mrbgem.rake | 3 | ||||
| -rw-r--r-- | mrbgems/mruby-complex/mrblib/complex.rb | 10 | ||||
| -rw-r--r-- | mrbgems/mruby-io/README.md | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-io/mrbgem.rake | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-io/src/file.c | 5 | ||||
| -rw-r--r-- | mrbgems/mruby-io/src/file_test.c | 5 | ||||
| -rw-r--r-- | mrbgems/mruby-io/src/io.c | 13 | ||||
| -rw-r--r-- | mrbgems/mruby-io/test/mruby_io_test.c | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-metaprog/src/metaprog.c | 33 | ||||
| -rw-r--r-- | mrbgems/mruby-pack/README.md | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-pack/mrbgem.rake | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-sleep/mrbgem.rake | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-sleep/src/mrb_sleep.c | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-socket/README.md | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-socket/mrbgem.rake | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-test/vformat.c | 320 | ||||
| -rw-r--r-- | src/backtrace.c | 85 | ||||
| -rw-r--r-- | src/class.c | 2 | ||||
| -rw-r--r-- | src/error.c | 69 | ||||
| -rw-r--r-- | src/print.c | 1 | ||||
| -rw-r--r-- | src/string.c | 1 | ||||
| -rw-r--r-- | test/t/exception.rb | 4 | ||||
| -rw-r--r-- | test/t/vformat.rb | 130 |
25 files changed, 274 insertions, 432 deletions
diff --git a/include/mruby/class.h b/include/mruby/class.h index 7c925f3b3..c15633e83 100644 --- a/include/mruby/class.h +++ b/include/mruby/class.h @@ -90,6 +90,7 @@ mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv); void mrb_class_name_class(mrb_state*, struct RClass*, struct RClass*, mrb_sym); mrb_bool mrb_const_name_p(mrb_state*, const char*, mrb_int); mrb_value mrb_class_find_path(mrb_state*, struct RClass*); +mrb_value mrb_mod_to_s(mrb_state*, mrb_value); void mrb_gc_mark_mt(mrb_state*, struct RClass*); size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*); void mrb_gc_free_mt(mrb_state*, struct RClass*); diff --git a/mrbgems/mruby-bin-debugger/bintest/print.rb b/mrbgems/mruby-bin-debugger/bintest/print.rb index 6675392b8..314c7041a 100644 --- a/mrbgems/mruby-bin-debugger/bintest/print.rb +++ b/mrbgems/mruby-bin-debugger/bintest/print.rb @@ -90,8 +90,8 @@ assert('mruby-bin-debugger(print) error') do # test case tc = [] - tc << {:cmd=>"p (1+2", :exp=>'$1 = SyntaxError'} - tc << {:cmd=>"p bar", :exp=>'$2 = (eval):2: undefined method'} + tc << {:cmd=>"p (1+2", :exp=>'$1 = line 1: syntax error'} + tc << {:cmd=>"p bar", :exp=>'$2 = undefined method'} BinTest_MrubyBinDebugger.test(src, tc) end @@ -588,7 +588,7 @@ SRC tc << {:cmd=>'p foo=[foo,bar,baz]', :exp=>'$2 = ["foo", "bar", "baz"]'} tc << {:cmd=>'p undefined=-1', :exp=>'$3 = -1'} - tc << {:cmd=>'p "#{undefined}"', :exp=>'$4 = (eval):2: undefined method'} + tc << {:cmd=>'p "#{undefined}"', :exp=>'$4 = undefined method'} BinTest_MrubyBinDebugger.test(src, tc) end @@ -626,7 +626,7 @@ SRC tc << {:cmd=>'p [a,b]', :exp=>'$13 = [20, 10]'} tc << {:cmd=>'p undefined=-1', :exp=>'$14 = -1'} - tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = (eval):2: undefined method'} + tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = undefined method'} BinTest_MrubyBinDebugger.test(src, tc) end @@ -694,7 +694,7 @@ SRC tc << {:cmd=>'p [a,b]', :exp=>'$13 = [20, 10]'} tc << {:cmd=>'p undefined=-1', :exp=>'$14 = -1'} - tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = (eval):2: undefined method'} + tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = undefined method'} BinTest_MrubyBinDebugger.test(src, tc) end diff --git a/mrbgems/mruby-complex/mrbgem.rake b/mrbgems/mruby-complex/mrbgem.rake index 19612e74d..8f782ae18 100644 --- a/mrbgems/mruby-complex/mrbgem.rake +++ b/mrbgems/mruby-complex/mrbgem.rake @@ -3,8 +3,5 @@ MRuby::Gem::Specification.new('mruby-complex') do |spec| spec.author = 'mruby developers' spec.summary = 'Complex class' - spec.add_dependency 'mruby-metaprog', core: 'mruby-metaprog' - spec.add_dependency 'mruby-object-ext', core: 'mruby-object-ext' - spec.add_dependency 'mruby-numeric-ext', core: 'mruby-numeric-ext' spec.add_dependency 'mruby-math', core: 'mruby-math' end diff --git a/mrbgems/mruby-complex/mrblib/complex.rb b/mrbgems/mruby-complex/mrblib/complex.rb index f32b84c8b..ea8530919 100644 --- a/mrbgems/mruby-complex/mrblib/complex.rb +++ b/mrbgems/mruby-complex/mrblib/complex.rb @@ -8,7 +8,7 @@ class Complex < Numeric end def to_s - "#{real}#{'+' unless imaginary.negative?}#{imaginary}i" + "#{real}#{'+' unless imaginary < 0}#{imaginary}i" end def +@ @@ -56,7 +56,7 @@ class Complex < Numeric if rhs.is_a? Complex real == rhs.real && imaginary == rhs.imaginary elsif rhs.is_a? Numeric - imaginary.zero? && real == rhs + imaginary == 0 && real == rhs end end @@ -106,14 +106,14 @@ class Complex < Numeric [Fixnum, Float].each do |cls| [:+, :-, :*, :/, :==].each do |op| - cls.instance_exec do + cls.instance_eval do original_operator_name = "__original_operator_#{op}_complex" alias_method original_operator_name, op define_method op do |rhs| if rhs.is_a? Complex - Complex(self).send(op, rhs) + Complex(self).__send__(op, rhs) else - send(original_operator_name, rhs) + __send__(original_operator_name, rhs) end end end diff --git a/mrbgems/mruby-io/README.md b/mrbgems/mruby-io/README.md index ccf56f970..2c5b762d8 100644 --- a/mrbgems/mruby-io/README.md +++ b/mrbgems/mruby-io/README.md @@ -171,6 +171,7 @@ Add the line below to your `build_config.rb`: ## License Copyright (c) 2013 Internet Initiative Japan Inc. +Copyright (c) 2017 mruby developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/mrbgems/mruby-io/mrbgem.rake b/mrbgems/mruby-io/mrbgem.rake index e4f0b7bb6..bd20f6d20 100644 --- a/mrbgems/mruby-io/mrbgem.rake +++ b/mrbgems/mruby-io/mrbgem.rake @@ -1,6 +1,6 @@ MRuby::Gem::Specification.new('mruby-io') do |spec| spec.license = 'MIT' - spec.authors = 'Internet Initiative Japan Inc.' + spec.authors = ['Internet Initiative Japan Inc.', 'mruby developers'] spec.summary = 'IO and File class' spec.cc.include_paths << "#{build.root}/src" diff --git a/mrbgems/mruby-io/src/file.c b/mrbgems/mruby-io/src/file.c index f9ccb6148..673decc20 100644 --- a/mrbgems/mruby-io/src/file.c +++ b/mrbgems/mruby-io/src/file.c @@ -7,12 +7,7 @@ #include "mruby/data.h" #include "mruby/string.h" #include "mruby/ext/io.h" - -#if MRUBY_RELEASE_NO < 10000 -#include "error.h" -#else #include "mruby/error.h" -#endif #include <sys/types.h> #include <sys/stat.h> diff --git a/mrbgems/mruby-io/src/file_test.c b/mrbgems/mruby-io/src/file_test.c index 445bafde9..aadd1ac1c 100644 --- a/mrbgems/mruby-io/src/file_test.c +++ b/mrbgems/mruby-io/src/file_test.c @@ -7,12 +7,7 @@ #include "mruby/data.h" #include "mruby/string.h" #include "mruby/ext/io.h" - -#if MRUBY_RELEASE_NO < 10000 -#include "error.h" -#else #include "mruby/error.h" -#endif #include <sys/types.h> #include <sys/stat.h> diff --git a/mrbgems/mruby-io/src/io.c b/mrbgems/mruby-io/src/io.c index 5bc88e047..32128fa07 100644 --- a/mrbgems/mruby-io/src/io.c +++ b/mrbgems/mruby-io/src/io.c @@ -10,12 +10,7 @@ #include "mruby/string.h" #include "mruby/variable.h" #include "mruby/ext/io.h" - -#if MRUBY_RELEASE_NO < 10000 -#include "error.h" -#else #include "mruby/error.h" -#endif #include <sys/types.h> #include <sys/stat.h> @@ -66,14 +61,6 @@ static int mrb_io_modestr_to_flags(mrb_state *mrb, const char *modestr); static int mrb_io_flags_to_modenum(mrb_state *mrb, int flags); static void fptr_finalize(mrb_state *mrb, struct mrb_io *fptr, int quiet); -#if MRUBY_RELEASE_NO < 10000 -static struct RClass * -mrb_module_get(mrb_state *mrb, const char *name) -{ - return mrb_class_get(mrb, name); -} -#endif - static struct mrb_io * io_get_open_fptr(mrb_state *mrb, mrb_value self) { diff --git a/mrbgems/mruby-io/test/mruby_io_test.c b/mrbgems/mruby-io/test/mruby_io_test.c index f5c55499b..1c31c5fe0 100644 --- a/mrbgems/mruby-io/test/mruby_io_test.c +++ b/mrbgems/mruby-io/test/mruby_io_test.c @@ -18,7 +18,7 @@ typedef int mode_t; #define open _open #define close _close -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__MINGW32__) #include <sys/stat.h> static int diff --git a/mrbgems/mruby-metaprog/src/metaprog.c b/mrbgems/mruby-metaprog/src/metaprog.c index bca8ab34c..f00c4493b 100644 --- a/mrbgems/mruby-metaprog/src/metaprog.c +++ b/mrbgems/mruby-metaprog/src/metaprog.c @@ -172,7 +172,7 @@ mrb_local_variables(mrb_state *mrb, mrb_value self) KHASH_DECLARE(st, mrb_sym, char, FALSE) static void -method_entry_loop(mrb_state *mrb, struct RClass* klass, khash_t(st)* set) +method_entry_loop(mrb_state *mrb, struct RClass *klass, khash_t(st) *set, khash_t(st) *undef) { khint_t i; @@ -181,20 +181,28 @@ method_entry_loop(mrb_state *mrb, struct RClass* klass, khash_t(st)* set) for (i=0;i<kh_end(h);i++) { if (kh_exist(h, i)) { mrb_method_t m = kh_value(h, i); - if (MRB_METHOD_UNDEF_P(m)) continue; - kh_put(st, mrb, set, kh_key(h, i)); + if (MRB_METHOD_UNDEF_P(m)) { + if (undef) { + kh_put(st, mrb, undef, kh_key(h, i)); + } + } + else if (undef == NULL || + kh_get(st, mrb, undef, kh_key(h, i)) == kh_end(undef)) { + kh_put(st, mrb, set, kh_key(h, i)); + } } } } static mrb_value -mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* klass, int obj) +mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass *klass, int obj) { khint_t i; mrb_value ary; mrb_bool prepended = FALSE; - struct RClass* oldklass; - khash_t(st)* set = kh_init(st, mrb); + struct RClass *oldklass; + khash_t(st) *set = kh_init(st, mrb); + khash_t(st) *undef = (recur ? kh_init(st, mrb) : NULL); if (!recur && (klass->flags & MRB_FL_CLASS_IS_PREPENDED)) { MRB_CLASS_ORIGIN(klass); @@ -203,7 +211,7 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* kl oldklass = 0; while (klass && (klass != oldklass)) { - method_entry_loop(mrb, klass, set); + method_entry_loop(mrb, klass, set, undef); if ((klass->tt == MRB_TT_ICLASS && !prepended) || (klass->tt == MRB_TT_SCLASS)) { } @@ -221,6 +229,7 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* kl } } kh_destroy(st, mrb, set); + if (undef) kh_destroy(st, mrb, undef); return ary; } @@ -313,18 +322,19 @@ mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj) { khint_t i; mrb_value ary; - struct RClass* klass; - khash_t(st)* set = kh_init(st, mrb); + struct RClass *klass; + khash_t(st) *set = kh_init(st, mrb); + khash_t(st) *undef = (recur ? kh_init(st, mrb) : NULL); klass = mrb_class(mrb, obj); if (klass && (klass->tt == MRB_TT_SCLASS)) { - method_entry_loop(mrb, klass, set); + method_entry_loop(mrb, klass, set, undef); klass = klass->super; } if (recur) { while (klass && ((klass->tt == MRB_TT_SCLASS) || (klass->tt == MRB_TT_ICLASS))) { - method_entry_loop(mrb, klass, set); + method_entry_loop(mrb, klass, set, undef); klass = klass->super; } } @@ -336,6 +346,7 @@ mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj) } } kh_destroy(st, mrb, set); + if (undef) kh_destroy(st, mrb, undef); return ary; } diff --git a/mrbgems/mruby-pack/README.md b/mrbgems/mruby-pack/README.md index 95733e2d5..c8a653fba 100644 --- a/mrbgems/mruby-pack/README.md +++ b/mrbgems/mruby-pack/README.md @@ -49,6 +49,7 @@ There is no dependency on other mrbgems. ## License Copyright (c) 2012 Internet Initiative Japan Inc. +Copyright (c) 2017 mruby developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/mrbgems/mruby-pack/mrbgem.rake b/mrbgems/mruby-pack/mrbgem.rake index 6e8375d1e..f1c0306b1 100644 --- a/mrbgems/mruby-pack/mrbgem.rake +++ b/mrbgems/mruby-pack/mrbgem.rake @@ -1,6 +1,6 @@ MRuby::Gem::Specification.new('mruby-pack') do |spec| spec.license = 'MIT' - spec.authors = 'Internet Initiative Japan Inc.' + spec.authors = ['Internet Initiative Japan Inc.', 'mruby developers'] spec.summary = 'Array#pack and String#unpack method' spec.cc.include_paths << "#{build.root}/src" diff --git a/mrbgems/mruby-sleep/mrbgem.rake b/mrbgems/mruby-sleep/mrbgem.rake index 8827b3580..7a303b81c 100644 --- a/mrbgems/mruby-sleep/mrbgem.rake +++ b/mrbgems/mruby-sleep/mrbgem.rake @@ -1,5 +1,5 @@ MRuby::Gem::Specification.new('mruby-sleep') do |spec| spec.license = 'MIT' - spec.authors = 'MATSUMOTO Ryosuke' + spec.authors = ['MATSUMOTO Ryosuke', 'mruby developers'] spec.version = '0.0.1' end diff --git a/mrbgems/mruby-sleep/src/mrb_sleep.c b/mrbgems/mruby-sleep/src/mrb_sleep.c index 3f8ef90cf..ac9b07e85 100644 --- a/mrbgems/mruby-sleep/src/mrb_sleep.c +++ b/mrbgems/mruby-sleep/src/mrb_sleep.c @@ -2,6 +2,7 @@ ** mrb_sleep - sleep methods for mruby ** ** Copyright (c) mod_mruby developers 2012- +** Copyright (c) mruby developers 2018 ** ** Permission is hereby granted, free of charge, to any person obtaining ** a copy of this software and associated documentation files (the diff --git a/mrbgems/mruby-socket/README.md b/mrbgems/mruby-socket/README.md index ceb50c651..947a24e9e 100644 --- a/mrbgems/mruby-socket/README.md +++ b/mrbgems/mruby-socket/README.md @@ -35,6 +35,7 @@ Date: Tue, 21 May 2013 04:31:30 GMT ## License Copyright (c) 2013 Internet Initiative Japan Inc. +Copyright (c) 2017 mruby developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/mrbgems/mruby-socket/mrbgem.rake b/mrbgems/mruby-socket/mrbgem.rake index b0894e095..24d6f953d 100644 --- a/mrbgems/mruby-socket/mrbgem.rake +++ b/mrbgems/mruby-socket/mrbgem.rake @@ -1,6 +1,6 @@ MRuby::Gem::Specification.new('mruby-socket') do |spec| spec.license = 'MIT' - spec.authors = 'Internet Initiative Japan' + spec.authors = ['Internet Initiative Japan', 'mruby developers'] spec.summary = 'standard socket class' spec.cc.include_paths << "#{build.root}/src" diff --git a/mrbgems/mruby-test/vformat.c b/mrbgems/mruby-test/vformat.c index 6984aaeb1..7775e1fd2 100644 --- a/mrbgems/mruby-test/vformat.c +++ b/mrbgems/mruby-test/vformat.c @@ -4,197 +4,177 @@ #include <mruby/data.h> #include <mruby/string.h> -#ifdef MRB_WITHOUT_FLOAT -typedef mrb_int mrb_float; -#define mrb_float(o) mrb_fixnum(o) +/* no argument */ +static mrb_value +vf_s_format_0(mrb_state *mrb, mrb_value klass) +{ + mrb_value fmt_str; + const char *fmt; + + mrb_get_args(mrb, "S", &fmt_str); + fmt = RSTRING_CSTR(mrb, fmt_str); + + return mrb_format(mrb, fmt); +} + +/* c char */ +static mrb_value +vf_s_format_c(mrb_state *mrb, mrb_value klass) +{ + mrb_value fmt_str, arg_str; + const char *fmt; + char c; + + mrb_get_args(mrb, "SS", &fmt_str, &arg_str); + fmt = RSTRING_CSTR(mrb, fmt_str); + c = RSTRING_CSTR(mrb, arg_str)[0]; + + return mrb_format(mrb, fmt, c); +} + +/* d int */ +static mrb_value +vf_s_format_d(mrb_state *mrb, mrb_value klass) +{ + mrb_value fmt_str, arg_int; + const char *fmt; + int d; + + mrb_get_args(mrb, "Si", &fmt_str, &arg_int); + fmt = RSTRING_CSTR(mrb, fmt_str); + d = mrb_fixnum(arg_int); + + return mrb_format(mrb, fmt, d); +} + +#ifndef MRB_WITHOUT_FLOAT +/* f float */ +static mrb_value +vf_s_format_f(mrb_state *mrb, mrb_value klass) +{ + mrb_value fmt_str, arg_flt; + const char *fmt; + mrb_float f; + + mrb_get_args(mrb, "Sf", &fmt_str, &arg_flt); + fmt = RSTRING_CSTR(mrb, fmt_str); + f = mrb_float(arg_flt); + + return mrb_format(mrb, fmt, f); +} #endif -#define NATIVE_TYPES \ - char c; \ - int d; \ - mrb_float f; \ - mrb_int i; \ -/* size_t l; */\ - mrb_sym n; \ - char *s; \ - struct RClass *C - -#define NATIVE_DEFINE_TYPE_FUNC(t) \ - static mrb_value \ - native_s_##t(mrb_state *mrb, mrb_value klass) \ - { \ - mrb_value obj, type = mrb_fixnum_value(ARG_##t); \ - mrb_get_args(mrb, "o", &obj); \ - return mrb_funcall(mrb, klass, "new", 2, type, obj); \ - } - -#define NATIVE_DEFINE_TYPE_METHOD(t) \ - mrb_define_class_method(mrb, n, #t, native_s_##t, MRB_ARGS_REQ(1)) - -typedef enum { - ARG_c, - ARG_d, - ARG_f, - ARG_i, -/* ARG_l,*/ - ARG_n, - ARG_s, - ARG_C, - ARG_v, -} VFArgumentType; - -typedef struct { - VFArgumentType type; - union { NATIVE_TYPES; }; -} VFNative; - -typedef struct { - VFArgumentType type; - union { - NATIVE_TYPES; - mrb_value v; - }; -} VFArgument; - -static void -native_free(mrb_state *mrb, void *data) +/* i fixnum */ +static mrb_value +vf_s_format_i(mrb_state *mrb, mrb_value klass) { - VFNative *native = (VFNative*)data; - if (native->type == ARG_s) mrb_free(mrb, native->s); - mrb_free(mrb, native); + mrb_value fmt_str, arg_int; + const char *fmt; + mrb_int i; + + mrb_get_args(mrb, "Si", &fmt_str, &arg_int); + fmt = RSTRING_CSTR(mrb, fmt_str); + i = mrb_fixnum(arg_int); + + return mrb_format(mrb, fmt, i); } -static const struct mrb_data_type native_data_type = { - "TestVFormat::Native", native_free -}; +/* l char*, size_t */ +static mrb_value +vf_s_format_l(mrb_state *mrb, mrb_value klass) +{ + mrb_value fmt_str, arg_str, arg_int; + const char *fmt; + const char *s; + size_t len; + + mrb_get_args(mrb, "SSi", &fmt_str, &arg_str, &arg_int); + fmt = RSTRING_CSTR(mrb, fmt_str); + s = RSTRING_PTR(arg_str); + len = (size_t)mrb_fixnum(arg_int); + if (len > (size_t)RSTRING_LEN(arg_str)) len = (size_t)RSTRING_LEN(arg_str); + + return mrb_format(mrb, fmt, s, len); +} +/* n symbol */ static mrb_value -native_initialize(mrb_state *mrb, mrb_value self) +vf_s_format_n(mrb_state *mrb, mrb_value klass) { - VFNative data, *datap; - mrb_int type; - mrb_value obj; - - mrb_get_args(mrb, "io", &type, &obj); - data.type = (VFArgumentType)type; - switch (data.type) { - case ARG_c: data.c = RSTRING_PTR(obj)[0]; break; - case ARG_d: data.d = (int)mrb_fixnum(obj); break; - case ARG_f: data.f = mrb_float(obj); break; - case ARG_i: data.i = mrb_fixnum(obj); break; -/* case ARG_l: data.l = (size_t)mrb_fixnum(obj); break;*/ - case ARG_n: data.n = mrb_symbol(obj); break; - case ARG_s: data.s = (char*)mrb_malloc(mrb, RSTRING_LEN(obj) + 1); - memcpy(data.s, RSTRING_PTR(obj), RSTRING_LEN(obj)); - data.s[RSTRING_LEN(obj)] = '\0'; break; - case ARG_C: data.C = mrb_class_ptr(obj); break; - default: mrb_raise(mrb, E_ARGUMENT_ERROR, "unknown type"); - } - datap = (VFNative*)mrb_malloc(mrb, sizeof(VFNative)); - *datap = data; - mrb_data_init(self, datap, &native_data_type); - return self; + mrb_value fmt_str, arg_sym; + const char *fmt; + mrb_sym n; + + mrb_get_args(mrb, "Sn", &fmt_str, &arg_sym); + fmt = RSTRING_CSTR(mrb, fmt_str); + n = mrb_symbol(arg_sym); + + return mrb_format(mrb, fmt, n); } -NATIVE_DEFINE_TYPE_FUNC(c) -NATIVE_DEFINE_TYPE_FUNC(d) -NATIVE_DEFINE_TYPE_FUNC(f) -NATIVE_DEFINE_TYPE_FUNC(i) -/*NATIVE_DEFINE_TYPE_FUNC(l)*/ -NATIVE_DEFINE_TYPE_FUNC(n) -NATIVE_DEFINE_TYPE_FUNC(s) -NATIVE_DEFINE_TYPE_FUNC(C) - -static VFArgument* -arg_from_obj(mrb_state *mrb, mrb_value obj, struct RClass *native_class, - VFArgument *vf_arg) +/* s char* */ +static mrb_value +vf_s_format_s(mrb_state *mrb, mrb_value klass) { - if (mrb_obj_is_instance_of(mrb, obj, native_class)) { - const VFNative *native = (VFNative*)DATA_PTR(obj); - *(VFNative*)vf_arg = *native; - } - else { - vf_arg->v = obj; - vf_arg->type = ARG_v; - } - return vf_arg; + mrb_value fmt_str, arg_str; + const char *fmt; + const char *s; + + mrb_get_args(mrb, "SS", &fmt_str, &arg_str); + fmt = RSTRING_CSTR(mrb, fmt_str); + s = RSTRING_CSTR(mrb, arg_str); + + return mrb_format(mrb, fmt, s); } -#define VF_FORMAT_INIT(klass) \ - struct RClass *vf_native_class = \ - mrb_class_get_under(mrb, mrb_class_ptr(klass), "Native"); \ - VFArgument vf_args[2]; - -#define VF_ARG(args, idx) \ - arg_from_obj(mrb, args[idx], vf_native_class, &vf_args[idx]) - -#define VF_FORMAT0(fmt) mrb_format(mrb, fmt); -#define VF_FORMAT1(fmt, args) \ - (VF_ARG(args, 0), VF_FORMAT_TYPED(fmt, 1, vf_args, NULL)) -#define VF_FORMAT2(fmt, args) ( \ - VF_ARG(args, 0), VF_ARG(args, 1), \ - VF_FORMAT2_COND_EXPR(fmt, vf_args, vf_args+1, c) : \ - VF_FORMAT2_COND_EXPR(fmt, vf_args, vf_args+1, d) : \ - VF_FORMAT2_COND_EXPR(fmt, vf_args, vf_args+1, f) : \ - VF_FORMAT2_COND_EXPR(fmt, vf_args, vf_args+1, i) : \ -/* VF_FORMAT2_COND_EXPR(fmt, vf_args, vf_args+1, l) : */\ - VF_FORMAT2_COND_EXPR(fmt, vf_args, vf_args+1, n) : \ - VF_FORMAT2_COND_EXPR(fmt, vf_args, vf_args+1, s) : \ - VF_FORMAT2_COND_EXPR(fmt, vf_args, vf_args+1, C) : \ - VF_FORMAT2_COND_EXPR(fmt, vf_args, vf_args+1, v) : \ - mrb_nil_value() /* not reached */ \ -) -#define VF_FORMAT2_COND_EXPR(fmt, a1, a2, t) \ - a1->type == ARG_##t ? VF_FORMAT_TYPED(fmt, 2, a2, (a1)->t) -#define VF_FORMAT_TYPED(fmt, n_arg, type_a, v1) \ - VF_FORMAT_TYPED_COND_EXPR(fmt, n_arg, type_a, v1, c) : \ - VF_FORMAT_TYPED_COND_EXPR(fmt, n_arg, type_a, v1, d) : \ - VF_FORMAT_TYPED_COND_EXPR(fmt, n_arg, type_a, v1, f) : \ - VF_FORMAT_TYPED_COND_EXPR(fmt, n_arg, type_a, v1, i) : \ -/* VF_FORMAT_TYPED_COND_EXPR(fmt, n_arg, type_a, v1, l) : */\ - VF_FORMAT_TYPED_COND_EXPR(fmt, n_arg, type_a, v1, n) : \ - VF_FORMAT_TYPED_COND_EXPR(fmt, n_arg, type_a, v1, s) : \ - VF_FORMAT_TYPED_COND_EXPR(fmt, n_arg, type_a, v1, C) : \ - VF_FORMAT_TYPED_COND_EXPR(fmt, n_arg, type_a, v1, v) : \ - mrb_nil_value() /* not reached */ -#define VF_FORMAT_TYPED_COND_EXPR(fmt, n_arg, type_a, v1, t) \ - (type_a)->type == ARG_##t ? n_arg == 1 ? \ - mrb_format(mrb, fmt, (type_a)->t) : mrb_format(mrb, fmt, v1, (type_a)->t) +/* C RClass */ +static mrb_value +vf_s_format_C(mrb_state *mrb, mrb_value klass) +{ + mrb_value fmt_str, arg_cls; + const char *fmt; + struct RClass *c; + + mrb_get_args(mrb, "SC", &fmt_str, &arg_cls); + fmt = RSTRING_CSTR(mrb, fmt_str); + c = mrb_class_ptr(arg_cls); + return mrb_format(mrb, fmt, c); +} + +/* v value */ static mrb_value -vf_s_format(mrb_state *mrb, mrb_value klass) +vf_s_format_v(mrb_state *mrb, mrb_value klass) { - mrb_value fmt_str, args[2]; - mrb_int argc = mrb_get_args(mrb, "S|oo", &fmt_str, args, args+1); - const char *fmt = RSTRING_CSTR(mrb, fmt_str); - - VF_FORMAT_INIT(klass); - - switch (argc) { - case 1: return VF_FORMAT0(fmt); - case 2: return VF_FORMAT1(fmt, args); - case 3: return VF_FORMAT2(fmt, args); - default: return mrb_nil_value(); /* not reached */ - } + mrb_value fmt_str, arg_v; + const char *fmt; + + mrb_get_args(mrb, "So", &fmt_str, &arg_v); + fmt = RSTRING_CSTR(mrb, fmt_str); + + return mrb_format(mrb, fmt, arg_v); } void mrb_init_test_vformat(mrb_state *mrb) { - struct RClass *vf, *n; + struct RClass *vf; vf = mrb_define_module(mrb, "TestVFormat"); - mrb_define_class_method(mrb, vf, "format", vf_s_format, MRB_ARGS_ARG(1,2)); - - n = mrb_define_class_under(mrb, vf, "Native", mrb->object_class); - MRB_SET_INSTANCE_TT(n, MRB_TT_DATA); - NATIVE_DEFINE_TYPE_METHOD(c); - NATIVE_DEFINE_TYPE_METHOD(d); - NATIVE_DEFINE_TYPE_METHOD(f); - NATIVE_DEFINE_TYPE_METHOD(i); -/* NATIVE_DEFINE_TYPE_METHOD(l);*/ - NATIVE_DEFINE_TYPE_METHOD(n); - NATIVE_DEFINE_TYPE_METHOD(s); - NATIVE_DEFINE_TYPE_METHOD(C); - mrb_define_method(mrb, n, "initialize", native_initialize, MRB_ARGS_REQ(2)); + mrb_define_class_method(mrb, vf, "z", vf_s_format_0, MRB_ARGS_REQ(1)); + +#define VF_DEFINE_FORMAT_METHOD(t) VF_DEFINE_FORMAT_METHOD_n(t,2) +#define VF_DEFINE_FORMAT_METHOD_n(t,n) mrb_define_class_method(mrb, vf, #t, vf_s_format_##t, MRB_ARGS_REQ(n)); + + VF_DEFINE_FORMAT_METHOD(c); + VF_DEFINE_FORMAT_METHOD(d); +#ifndef MRB_WITHOUT_FLOAT + VF_DEFINE_FORMAT_METHOD(f); +#endif + VF_DEFINE_FORMAT_METHOD(i); + VF_DEFINE_FORMAT_METHOD_n(l,3); + VF_DEFINE_FORMAT_METHOD(n); + VF_DEFINE_FORMAT_METHOD(s); + VF_DEFINE_FORMAT_METHOD(C); + VF_DEFINE_FORMAT_METHOD(v); } diff --git a/src/backtrace.c b/src/backtrace.c index 803c5e285..186009523 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -25,6 +25,9 @@ typedef void (*each_backtrace_func)(mrb_state*, const struct backtrace_location* static const mrb_data_type bt_type = { "Backtrace", mrb_free }; +mrb_value mrb_exc_inspect(mrb_state *mrb, mrb_value exc); +mrb_value mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace); + static void each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, const mrb_code *pc0, each_backtrace_func func, void *data) { @@ -74,66 +77,27 @@ each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, const mrb_code *pc0, each_backtr #ifndef MRB_DISABLE_STDIO static void -print_backtrace(mrb_state *mrb, mrb_value backtrace) +print_backtrace(mrb_state *mrb, struct RObject *exc, mrb_value backtrace) { int i; - mrb_int n; + mrb_int n = RARRAY_LEN(backtrace); + mrb_value *loc, mesg; FILE *stream = stderr; - n = RARRAY_LEN(backtrace) - 1; - if (n == 0) return; - - fprintf(stream, "trace (most recent call last):\n"); - for (i=0; i<n; i++) { - mrb_value entry = RARRAY_PTR(backtrace)[n-i-1]; - - if (mrb_string_p(entry)) { - fprintf(stream, "\t[%d] %.*s\n", i, (int)RSTRING_LEN(entry), RSTRING_PTR(entry)); + if (n != 0) { + fprintf(stream, "trace (most recent call last):\n"); + for (i=n-1,loc=&RARRAY_PTR(backtrace)[i]; i>0; i--,loc--) { + if (mrb_string_p(*loc)) { + fprintf(stream, "\t[%d] %.*s\n", + i, (int)RSTRING_LEN(*loc), RSTRING_PTR(*loc)); + } } - } -} - -static int -packed_bt_len(const struct backtrace_location *bt, int n) -{ - int len = 0; - int i; - - for (i=0; i<n; i++) { - if (!bt[i].filename && !bt[i].lineno && !bt[i].method_id) - continue; - len++; - } - return len; -} - -static void -print_packed_backtrace(mrb_state *mrb, mrb_value packed) -{ - FILE *stream = stderr; - const struct backtrace_location *bt; - int n, i; - int ai = mrb_gc_arena_save(mrb); - - bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, packed, &bt_type); - if (bt == NULL) return; - n = (mrb_int)RDATA(packed)->flags; - - if (packed_bt_len(bt, n) == 0) return; - fprintf(stream, "trace (most recent call last):\n"); - for (i = 0; i<n; i++) { - const struct backtrace_location *entry = &bt[n-i-1]; - if (entry->filename == NULL) continue; - fprintf(stream, "\t[%d] %s:%d", i, entry->filename, entry->lineno); - if (entry->method_id != 0) { - const char *method_name; - - method_name = mrb_sym_name(mrb, entry->method_id); - fprintf(stream, ":in %s", method_name); - mrb_gc_arena_restore(mrb, ai); + if (mrb_string_p(*loc)) { + fprintf(stream, "%.*s: ", (int)RSTRING_LEN(*loc), RSTRING_PTR(*loc)); } - fprintf(stream, "\n"); } + mesg = mrb_exc_inspect(mrb, mrb_obj_value(exc)); + fprintf(stream, "%.*s\n", (int)RSTRING_LEN(mesg), RSTRING_PTR(mesg)); } /* mrb_print_backtrace @@ -152,12 +116,8 @@ mrb_print_backtrace(mrb_state *mrb) backtrace = mrb_obj_iv_get(mrb, mrb->exc, mrb_intern_lit(mrb, "backtrace")); if (mrb_nil_p(backtrace)) return; - if (mrb_array_p(backtrace)) { - print_backtrace(mrb, backtrace); - } - else { - print_packed_backtrace(mrb, backtrace); - } + if (!mrb_array_p(backtrace)) backtrace = mrb_unpack_backtrace(mrb, backtrace); + print_backtrace(mrb, mrb->exc, backtrace); } #else @@ -175,7 +135,6 @@ count_backtrace_i(mrb_state *mrb, { int *lenp = (int*)data; - if (loc->filename == NULL) return; (*lenp)++; } @@ -187,7 +146,6 @@ pack_backtrace_i(mrb_state *mrb, struct backtrace_location **pptr = (struct backtrace_location**)data; struct backtrace_location *ptr = *pptr; - if (loc->filename == NULL) return; *ptr = *loc; *pptr = ptr+1; } @@ -205,7 +163,7 @@ packed_backtrace(mrb_state *mrb) size = len * sizeof(struct backtrace_location); ptr = mrb_malloc(mrb, size); backtrace = mrb_data_object_alloc(mrb, NULL, ptr, &bt_type); - backtrace->flags = (unsigned int)len; + backtrace->flags = (uint32_t)len; each_backtrace(mrb, ciidx, mrb->c->ci->pc, pack_backtrace_i, &ptr); return mrb_obj_value(backtrace); } @@ -245,8 +203,7 @@ mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace) const struct backtrace_location *entry = &bt[i]; mrb_value btline; - if (entry->filename == NULL) continue; - btline = mrb_format(mrb, "%s:%d", entry->filename, entry->lineno); + btline = mrb_format(mrb, "%s:%d", entry->filename, (int)entry->lineno); if (entry->method_id != 0) { mrb_str_cat_lit(mrb, btline, ":in "); mrb_str_cat_cstr(mrb, btline, mrb_sym_name(mrb, entry->method_id)); diff --git a/src/class.c b/src/class.c index e0196fe0a..0da572b0e 100644 --- a/src/class.c +++ b/src/class.c @@ -2323,7 +2323,9 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, mod, "dup", mrb_mod_dup, MRB_ARGS_NONE()); mrb_undef_method(mrb, cls, "append_features"); + mrb_undef_method(mrb, cls, "prepend_features"); mrb_undef_method(mrb, cls, "extend_object"); + mrb_undef_method(mrb, cls, "module_function"); mrb->top_self = (struct RObject*)mrb_obj_alloc(mrb, MRB_TT_OBJECT, mrb->object_class); mrb_define_singleton_method(mrb, mrb->top_self, "inspect", inspect_main, MRB_ARGS_NONE()); diff --git a/src/error.c b/src/error.c index 43b09ec66..126cd23fb 100644 --- a/src/error.c +++ b/src/error.c @@ -13,7 +13,6 @@ #include <mruby/proc.h> #include <mruby/string.h> #include <mruby/variable.h> -#include <mruby/debug.h> #include <mruby/error.h> #include <mruby/class.h> #include <mruby/throw.h> @@ -88,7 +87,7 @@ exc_exception(mrb_state *mrb, mrb_value self) * no message is set). */ -static mrb_value +mrb_value exc_to_s(mrb_state *mrb, mrb_value exc) { mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg")); @@ -128,37 +127,13 @@ exc_message(mrb_state *mrb, mrb_value exc) * returns message and class name. */ -static mrb_value -exc_inspect(mrb_state *mrb, mrb_value exc) +mrb_value +mrb_exc_inspect(mrb_state *mrb, mrb_value exc) { - mrb_value str, mesg, file, line; - mrb_bool append_mesg; - const char *cname; - - mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg")); - file = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "file")); - line = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "line")); - - append_mesg = !mrb_nil_p(mesg); - if (append_mesg) { - mesg = mrb_obj_as_string(mrb, mesg); - append_mesg = RSTRING_LEN(mesg) > 0; - } - - cname = mrb_obj_classname(mrb, exc); - str = mrb_str_new_cstr(mrb, cname); - if (mrb_string_p(file) && mrb_fixnum_p(line)) { - if (append_mesg) { - str = mrb_format(mrb, "%v:%v: %v (%v)", file, line, mesg, str); - } - else { - str = mrb_format(mrb, "%v:%v: %v", file, line, str); - } - } - else if (append_mesg) { - str = mrb_format(mrb, "%v: %v", str, mesg); - } - return str; + mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg")); + mrb_value cname = mrb_mod_to_s(mrb, mrb_obj_value(mrb_obj_class(mrb, exc))); + mesg = mrb_obj_as_string(mrb, mesg); + return RSTRING_LEN(mesg) == 0 ? cname : mrb_format(mrb, "%v (%v)", mesg, cname); } void mrb_keep_backtrace(mrb_state *mrb, mrb_value exc); @@ -192,33 +167,6 @@ exc_set_backtrace(mrb_state *mrb, mrb_value exc) return backtrace; } -static void -exc_debug_info(mrb_state *mrb, struct RObject *exc) -{ - mrb_callinfo *ci = mrb->c->ci; - const mrb_code *pc = ci->pc; - - if (mrb_obj_iv_defined(mrb, exc, mrb_intern_lit(mrb, "file"))) return; - while (ci >= mrb->c->cibase) { - const mrb_code *err = ci->err; - - if (!err && pc) err = pc - 1; - if (err && ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) { - mrb_irep *irep = ci->proc->body.irep; - - int32_t const line = mrb_debug_get_line(mrb, irep, err - irep->iseq); - char const* file = mrb_debug_get_filename(mrb, irep, err - irep->iseq); - if (line != -1 && file) { - mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "file"), mrb_str_new_cstr(mrb, file)); - mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "line"), mrb_fixnum_value(line)); - return; - } - } - pc = ci->pc; - ci--; - } -} - void mrb_exc_set(mrb_state *mrb, mrb_value exc) { @@ -232,7 +180,6 @@ mrb_exc_set(mrb_state *mrb, mrb_value exc) mrb->gc.arena_idx--; } if (!mrb->gc.out_of_memory && !mrb_frozen_p(mrb->exc)) { - exc_debug_info(mrb, mrb->exc); mrb_keep_backtrace(mrb, exc); } } @@ -598,7 +545,7 @@ mrb_init_exception(mrb_state *mrb) mrb_define_method(mrb, exception, "initialize", exc_initialize, MRB_ARGS_OPT(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, "inspect", mrb_exc_inspect, MRB_ARGS_NONE()); mrb_define_method(mrb, exception, "backtrace", mrb_exc_backtrace, MRB_ARGS_NONE()); mrb_define_method(mrb, exception, "set_backtrace", exc_set_backtrace, MRB_ARGS_REQ(1)); diff --git a/src/print.c b/src/print.c index 03b5eadfa..7d2d16086 100644 --- a/src/print.c +++ b/src/print.c @@ -31,7 +31,6 @@ MRB_API void mrb_print_error(mrb_state *mrb) { mrb_print_backtrace(mrb); - printstr(mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0), stderr); } MRB_API void diff --git a/src/string.c b/src/string.c index 5a0a6a233..b3f07dfb0 100644 --- a/src/string.c +++ b/src/string.c @@ -1095,7 +1095,6 @@ mrb_str_equal_m(mrb_state *mrb, mrb_value str1) return mrb_bool_value(mrb_str_equal(mrb, str1, str2)); } /* ---------------------------------- */ -mrb_value mrb_mod_to_s(mrb_state *mrb, mrb_value klass); MRB_API mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str) diff --git a/test/t/exception.rb b/test/t/exception.rb index bdf277c1e..a6f69eef6 100644 --- a/test/t/exception.rb +++ b/test/t/exception.rb @@ -352,8 +352,10 @@ assert('Exception 19') do assert_equal [true, true], Class4Exception19.new.a end -assert('Exception#inspect without message') do +assert('Exception#inspect') do assert_equal "Exception", Exception.new.inspect + assert_equal "Exception", Exception.new("").inspect + assert_equal "error! (Exception)", Exception.new("error!").inspect end assert('Exception#backtrace') do diff --git a/test/t/vformat.rb b/test/t/vformat.rb index 679f30407..df6950ee6 100644 --- a/test/t/vformat.rb +++ b/test/t/vformat.rb @@ -1,25 +1,4 @@ -def assert_format(exp, args) - assert_equal(exp, TestVFormat.format(*args)) -end - -def assert_format_pattern(exp_pattern, args) - assert_match(exp_pattern, TestVFormat.format(*args)) -end - -# Pass if ArgumentError is raised or return value is +exp+. -def assert_implementation_dependent(exp, args) - begin - ret = TestVFormat.format(*args) - rescue ArgumentError - return pass - end - if ret == exp - pass - else - flunk "", "Expected ArgumentError is raised or #{ret.inspect} to be #{exp}." - end -end - +# coding: utf-8-emacs def sclass(v) class << v self @@ -27,66 +6,53 @@ def sclass(v) end assert('mrb_vformat') do - n = TestVFormat::Native - assert_format '', [''] - assert_format 'No specifier!', ['No specifier!'] - assert_format '`c`: C', ['`c`: %c', n.c(?C)] - assert_format '`d`: 123', ['`d`: %d', n.d(123)] - assert_format '`d`: -79', ['`d`: %d', n.d(-79)] - assert_format '`i`: 514', ['`i`: %i', n.i(514)] - assert_format '`i`: -83', ['`i`: %i', n.i(-83)] - assert_format '`t`: NilClass', ['`t`: %t', nil] - assert_format '`t`: FalseClass', ['`t`: %t', false] - assert_format '`t`: TrueClass', ['`t`: %t', true] - assert_format '`t`: Fixnum', ['`t`: %t', 0] - assert_format '`t`: Hash', ['`t`: %t', k: "value"] - assert_format_pattern '#<Class:#<Class:#<Hash:0x*>>>', ['%t', sclass({})] -# assert_format 'string and length', ['string %l length', n.s('andante'), n.l(3)] - assert_format '`n`: sym', ['`n`: %n', n.n(:sym)] - assert_format '%C文字列%', ['%s', n.s('%C文字列%')] - assert_format '`C`: Kernel module', ['`C`: %C module', n.C(Kernel)] - assert_format '`C`: NilClass', ['`C`: %C', n.C(nil.class)] - assert_format_pattern '#<Class:#<String:0x*>>', ['%C', n.C(sclass(""))] - assert_format '`T`: NilClass', ['`T`: %T', nil] - assert_format '`T`: FalseClass', ['`T`: %T', false] - assert_format '`T`: TrueClass', ['`T`: %T', true] - assert_format '`T`: Fixnum', ['`T`: %T', 0] - assert_format '`T`: Hash', ['`T`: %T', k: "value"] - assert_format_pattern 'Class', ['%T', sclass({})] - assert_format '`Y`: nil', ['`Y`: %Y', nil] - assert_format '`Y`: false', ['`Y`: %Y', false] - assert_format '`Y`: true', ['`Y`: %Y', true] - assert_format '`Y`: Fixnum', ['`Y`: %Y', 0] - assert_format '`Y`: Hash', ['`Y`: %Y', k: "value"] - assert_format 'Class', ['%Y', sclass({})] - assert_format_pattern '#<Class:#<String:0x*>>', ['%v', sclass("")] - assert_format '`v`: 1...3', ['`v`: %v', 1...3] - assert_format '`S`: {:a=>1, "b"=>"c"}', ['`S`: %S', a: 1, "b" => ?c] - assert_format 'percent: %', ['percent: %%'] - assert_format '"I": inspect char', ['%!c: inspect char', n.c(?I)] - assert_format '709: inspect mrb_int', ['%!d: inspect mrb_int', n.i(709)] -# assert_format '"a\x00b\xff"', ['%!l', n.s("a\000b\xFFc\000d"), n.l(4)] - assert_format ':"&.": inspect symbol', ['%!n: inspect symbol', n.n(:'&.')] - assert_format 'inspect "String"', ['inspect %!v', 'String'] - assert_format 'inspect Array: [1, :x, {}]', ['inspect Array: %!v', [1,:x,{}]] - assert_format_pattern '`!C`: #<Class:0x*>', ['`!C`: %!C', n.C(Class.new)] - assert_format 'to_s -> to_s: ab,cd', ['to_s -> to_s: %n,%v', n.n(:ab), 'cd'] - assert_format 'to_s -> inspect: x:y', ['to_s -> inspect: %v%!v', 'x', :y] - assert_format 'inspect -> to_s: "a"b', ['inspect -> to_s: %!v%n', 'a', n.n(:b)] - assert_format 'Y -> to_s: nile', ['Y -> to_s: %Y%v', nil, "e"] - assert_format '"abc":Z', ['%!s%!n', n.s('abc'), n.n('Z'.to_sym)] - assert_format 'escape: \\%a,b,c,d', ['escape: \\\\\%a,b,\c%v', ',d'] - - assert_implementation_dependent 'unknown specifier: %^', - ['unknown specifier: %^'] - assert_implementation_dependent 'unknown specifier with modifier: %!^', - ['unknown specifier with modifier: %!^'] - assert_implementation_dependent 'termination is \\', ['termination is \\'] - assert_implementation_dependent 'termination is %', ['termination is %'] - assert_implementation_dependent 'termination is %!', ['termination is %!'] + vf = TestVFormat + assert_equal '', vf.z('') + assert_equal 'No specifier!', vf.z('No specifier!') + assert_equal '`c`: C', vf.c('`c`: %c', ?C) + assert_equal '`d`: 123', vf.d('`d`: %d', 123) + assert_equal '`d`: -79', vf.d('`d`: %d', -79) + assert_equal '`i`: 514', vf.i('`i`: %i', 514) + assert_equal '`i`: -83', vf.i('`i`: %i', -83) + assert_equal '`t`: NilClass', vf.v('`t`: %t', nil) + assert_equal '`t`: FalseClass', vf.v('`t`: %t', false) + assert_equal '`t`: TrueClass', vf.v('`t`: %t', true) + assert_equal '`t`: Fixnum', vf.v('`t`: %t', 0) + assert_equal '`t`: Hash', vf.v('`t`: %t', {k: "value"}) + assert_match '#<Class:#<Class:#<Hash:0x*>>>', vf.v('%t', sclass({})) + assert_equal 'string and length', vf.l('string %l length', 'andante', 3) + assert_equal '`n`: sym', vf.n('`n`: %n', :sym) + assert_equal '%C文字列����%', vf.s('%s', '%C文字列����%') + assert_equal '`C`: Kernel module', vf.C('`C`: %C module', Kernel) + assert_equal '`C`: NilClass', vf.C('`C`: %C', nil.class) + assert_match '#<Class:#<String:0x*>>', vf.C('%C', sclass("")) + assert_equal '`T`: NilClass', vf.v('`T`: %T', nil) + assert_equal '`T`: FalseClass', vf.v('`T`: %T', false) + assert_equal '`T`: TrueClass', vf.v('`T`: %T', true) + assert_equal '`T`: Fixnum', vf.v('`T`: %T', 0) + assert_equal '`T`: Hash', vf.v('`T`: %T', {k: "value"}) + assert_match 'Class', vf.v('%T', sclass({})) + assert_equal '`Y`: nil', vf.v('`Y`: %Y', nil) + assert_equal '`Y`: false', vf.v('`Y`: %Y', false) + assert_equal '`Y`: true', vf.v('`Y`: %Y', true) + assert_equal '`Y`: Fixnum', vf.v('`Y`: %Y', 0) + assert_equal '`Y`: Hash', vf.v('`Y`: %Y', {k: "value"}) + assert_equal 'Class', vf.v('%Y', sclass({})) + assert_match '#<Class:#<String:0x*>>', vf.v('%v', sclass("")) + assert_equal '`v`: 1...3', vf.v('`v`: %v', 1...3) + assert_equal '`S`: {:a=>1, "b"=>"c"}', vf.v('`S`: %S', {a: 1, "b" => ?c}) + assert_equal 'percent: %', vf.z('percent: %%') + assert_equal '"I": inspect char', vf.c('%!c: inspect char', ?I) + assert_equal '709: inspect mrb_int', vf.i('%!d: inspect mrb_int', 709) + assert_equal '"a\x00b\xff"', vf.l('%!l', "a\000b\xFFc\000d", 4) + assert_equal ':"&.": inspect symbol', vf.n('%!n: inspect symbol', :'&.') + assert_equal 'inspect "String"', vf.v('inspect %!v', 'String') + assert_equal 'inspect Array: [1, :x, {}]', vf.v('inspect Array: %!v', [1,:x,{}]) + assert_match '`!C`: #<Class:0x*>', vf.C('`!C`: %!C', Class.new) + assert_equal 'escape: \\%a,b,c,d', vf.v('escape: \\\\\%a,b,\c%v', ',d') skip unless Object.const_defined?(:Float) - assert_format '`f`: 0.0125', ['`f`: %f', n.f(0.0125)] - assert_format '-Infinity', ['%f', n.f(-Float::INFINITY)] - assert_format 'NaN: Not a Number', ['%f: Not a Number', n.f(Float::NAN)] + assert_equal '`f`: 0.0125', vf.f('`f`: %f', 0.0125) + assert_equal '-Infinity', vf.f('%f', -Float::INFINITY) + assert_equal 'NaN: Not a Number', vf.f('%f: Not a Number', Float::NAN) end |
