From e36e2760f2c168c179a35cc8bf7a4103ce523f61 Mon Sep 17 00:00:00 2001 From: Rob Lyman Date: Sat, 20 Jan 2018 13:52:04 -0600 Subject: [PATCH 1/2] Updated support for integer division behavior This adds an adapted fix to give conditional integer division support, based on the environment variable MRB_INTEGER_DIVISION. This adapts from the previous fix to the latest stable mRuby branch, taking into account their new MRB_WITHOUT_FLOAT environment variable. Note that MRB_WITHOUT_FLOAT and MRB_INTEGER_DIVISION are not compatible and should not be used together. With the former unset and the latter set, we can build an mRuby that supports native floating point values, but still gives an integer quotient result for dividing two integers (non-integer dividend or divisor give float results, as usual). This fix is adapted from the fix in this open PR on the mRuby project: https://github.com/mruby/mruby/pull/3123 --- src/vm.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/vm.c b/src/vm.c index 0848114999..59646ed6cc 100644 --- a/src/vm.c +++ b/src/vm.c @@ -2416,6 +2416,9 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc) CASE(OP_DIV) { /* A B C R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1)*/ int a = GETARG_A(i); +#ifdef MRB_INTEGER_DIVISION + int integer_div = FALSE; +#endif #ifndef MRB_WITHOUT_FLOAT double x, y, f; #endif @@ -2433,6 +2436,9 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc) #else x = (mrb_float)mrb_fixnum(regs[a]); y = (mrb_float)mrb_fixnum(regs[a+1]); +#ifdef MRB_INTEGER_DIVISION + integer_div = TRUE; +#endif break; case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): x = (mrb_float)mrb_fixnum(regs[a]); @@ -2452,6 +2458,35 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc) } #ifndef MRB_WITHOUT_FLOAT +#ifdef MRB_INTEGER_DIVISION + if (integer_div) + { + if (y == 0 || (x == MRB_INT_MIN && y == -1)) { + SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x / (mrb_float)y); + } + else { + mrb_int div, mod; + if (y < 0) { + if (x < 0) + div = -x / -y; + else + div = - (x / -y); + } + else { + if (x < 0) + div = - (-x / y); + else + div = x / y; + } + mod = x - div*y; + if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) { + div -= 1; + } + SET_INT_VALUE(regs[a], div); + } + } + else { +#endif if (y == 0) { if (x > 0) f = INFINITY; else if (x < 0) f = -INFINITY; @@ -2461,7 +2496,10 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc) f = x / y; } SET_FLOAT_VALUE(mrb, regs[a], f); +#ifdef MRB_INTEGER_DIVISION + } #endif +#endif /* #ifndef MRB_WITHOUT_FLOAT */ NEXT; } From 116c6373e188109e27f00012f8ed3a965c75ad53 Mon Sep 17 00:00:00 2001 From: Rob Lyman Date: Sat, 20 Jan 2018 13:52:38 -0600 Subject: [PATCH 2/2] Add explanation of integer division support to README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This explains the raison d'ĂȘtre for this fork of mRuby. --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 196cc2ef70..6ba0b4c42e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,13 @@ [![Build Status][build-status-img]][travis-ci] +## mruby with Integer Division Support + +This is a fork of the mruby project that includes support for integer division compatible with that in other Rubys, so that + +`(1 / 2) => 0` + +This is enabled with the compiler variable `MRB_INTEGER_DIVISION`: when set during compilation, it will enable integer division behavior. This mruby is otherwise compatible with mruby 1.4.0. + ## What is mruby mruby is the lightweight implementation of the Ruby language complying to (part