diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-08-18 22:12:28 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-10-12 16:21:48 +0900 |
| commit | 2a92fb2516251fb0ddfa2d1026930a2c7465e528 (patch) | |
| tree | 99fe336ea04b8aec484cb27baf13ae3c261d26b1 | |
| parent | 18e3d39ee23389d9a7955149c09b6de026804ca3 (diff) | |
| download | mruby-2a92fb2516251fb0ddfa2d1026930a2c7465e528.tar.gz mruby-2a92fb2516251fb0ddfa2d1026930a2c7465e528.zip | |
Make division by zero cause `ZeroDivisionError`.
As described in ISO 15.2.30.
| -rw-r--r-- | doc/limitations.md | 9 | ||||
| -rw-r--r-- | include/mruby.h | 1 | ||||
| -rw-r--r-- | mrblib/10error.rb | 4 | ||||
| -rw-r--r-- | src/numeric.c | 20 | ||||
| -rw-r--r-- | src/vm.c | 13 | ||||
| -rw-r--r-- | test/t/superclass.rb | 2 |
6 files changed, 24 insertions, 25 deletions
diff --git a/doc/limitations.md b/doc/limitations.md index 7e58ca420..8ac959b98 100644 --- a/doc/limitations.md +++ b/doc/limitations.md @@ -63,8 +63,15 @@ end #### mruby [2.1.2 (2020-08-06)] -No exception is raised. +No exception is raised. Instead you have to do: +```ruby +begin + 1 / 0 +rescue => e + raise e +end +``` ## Fiber execution can't cross C function boundary mruby's `Fiber` is implemented in a similar way to Lua's co-routine. This diff --git a/include/mruby.h b/include/mruby.h index f07adbb13..959d1ac6d 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -1292,6 +1292,7 @@ MRB_API mrb_value mrb_vformat(mrb_state *mrb, const char *format, va_list ap); */ #define E_RUNTIME_ERROR (mrb_exc_get_id(mrb, MRB_SYM(RuntimeError))) #define E_TYPE_ERROR (mrb_exc_get_id(mrb, MRB_SYM(TypeError))) +#define E_ZERODIV_ERROR (mrb_exc_get_id(mrb, MRB_SYM(ZeroDivisionError))) #define E_ARGUMENT_ERROR (mrb_exc_get_id(mrb, MRB_SYM(ArgumentError))) #define E_INDEX_ERROR (mrb_exc_get_id(mrb, MRB_SYM(IndexError))) #define E_RANGE_ERROR (mrb_exc_get_id(mrb, MRB_SYM(RangeError))) diff --git a/mrblib/10error.rb b/mrblib/10error.rb index 0d9f38d58..054603514 100644 --- a/mrblib/10error.rb +++ b/mrblib/10error.rb @@ -21,6 +21,10 @@ end class TypeError < StandardError end +# ISO 15.2.30 +class ZeroDivisionError < StandardError +end + # ISO 15.2.31 class NameError < StandardError attr_accessor :name diff --git a/src/numeric.c b/src/numeric.c index 99d32f919..0cc7958e6 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -156,7 +156,7 @@ integral_div(mrb_state *mrb, mrb_value xv) mrb_get_args(mrb, "i", &y); if (y == 0) { - mrb_raise(mrb, E_RUNTIME_ERROR, "devided by zero"); + mrb_raise(mrb, E_ZERODIV_ERROR, "devided by zero"); } return mrb_fixnum_value(mrb_fixnum(xv) / y); #else @@ -932,14 +932,7 @@ int_mod(mrb_state *mrb, mrb_value x) mrb_int mod; if (b == 0) { -#ifdef MRB_NO_FLOAT - /* ZeroDivisionError */ - return mrb_fixnum_value(0); -#else - if (a > 0) return mrb_float_value(mrb, INFINITY); - if (a < 0) return mrb_float_value(mrb, INFINITY); - return mrb_float_value(mrb, NAN); -#endif + mrb_raise(mrb, E_ZERODIV_ERROR, "divided by 0"); } fixdivmod(mrb, a, b, NULL, &mod); return mrb_fixnum_value(mod); @@ -971,14 +964,7 @@ int_divmod(mrb_state *mrb, mrb_value x) mrb_int div, mod; if (mrb_fixnum(y) == 0) { -#ifdef MRB_NO_FLOAT - return mrb_assoc_new(mrb, mrb_fixnum_value(0), mrb_fixnum_value(0)); -#else - return mrb_assoc_new(mrb, ((mrb_fixnum(x) == 0) ? - mrb_float_value(mrb, NAN): - mrb_float_value(mrb, INFINITY)), - mrb_float_value(mrb, NAN)); -#endif + mrb_raise(mrb, E_ZERODIV_ERROR, "divided by 0"); } fixdivmod(mrb, mrb_fixnum(x), mrb_fixnum(y), &div, &mod); return mrb_assoc_new(mrb, mrb_fixnum_value(div), mrb_fixnum_value(mod)); @@ -2315,12 +2315,13 @@ RETRY_TRY_BLOCK: { mrb_int x = mrb_fixnum(regs[a]); mrb_int y = mrb_fixnum(regs[a+1]); - if (y == 0 || (x == MRB_INT_MIN && y == -1)) { -#ifdef MRB_NO_FLOAT - SET_INT_VALUE(regs[a], y ? x / y : 0); -#else - SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x / (mrb_float)y); -#endif + + + if (y == 0) { + mrb_raise(mrb, E_ZERODIV_ERROR, "divided by 0"); + } + else if(x == MRB_INT_MIN && y == -1) { + mrb_raise(mrb, E_RANGE_ERROR, "integer overflow in division"); } else { mrb_int div, mod; diff --git a/test/t/superclass.rb b/test/t/superclass.rb index 10b6438d3..70d5c24d9 100644 --- a/test/t/superclass.rb +++ b/test/t/superclass.rb @@ -29,7 +29,7 @@ [:RegexpError, :StandardError, '12.2.27.2'], [:RuntimeError, :StandardError, '12.2.28.2'], [:TypeError, :StandardError, '12.2.29.2'], -# [:ZeroDivisionError, :StandardError, '12.2.30.2'], # No ZeroDivisionError in mruby + [:ZeroDivisionError, :StandardError, '12.2.30.2'], [:NameError, :StandardError, '15.2.31.2'], [:NoMethodError, :NameError, '15.2.32.2'], [:IndexError, :StandardError, '15.2.33.2'], |
