summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2020-08-18 22:12:28 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2020-10-12 16:21:48 +0900
commit2a92fb2516251fb0ddfa2d1026930a2c7465e528 (patch)
tree99fe336ea04b8aec484cb27baf13ae3c261d26b1
parent18e3d39ee23389d9a7955149c09b6de026804ca3 (diff)
downloadmruby-2a92fb2516251fb0ddfa2d1026930a2c7465e528.tar.gz
mruby-2a92fb2516251fb0ddfa2d1026930a2c7465e528.zip
Make division by zero cause `ZeroDivisionError`.
As described in ISO 15.2.30.
-rw-r--r--doc/limitations.md9
-rw-r--r--include/mruby.h1
-rw-r--r--mrblib/10error.rb4
-rw-r--r--src/numeric.c20
-rw-r--r--src/vm.c13
-rw-r--r--test/t/superclass.rb2
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));
diff --git a/src/vm.c b/src/vm.c
index 979c67424..15a38c0e4 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -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'],