Skip to content

Commit 80d9ad9

Browse files
committed
Implement coercion for all BigDecimal operations
* Except for operations that MRI does not support yet like #** and #sqrt.
1 parent 665fdde commit 80d9ad9

File tree

2 files changed

+64
-10
lines changed

2 files changed

+64
-10
lines changed

src/main/java/org/truffleruby/stdlib/bigdecimal/BigDecimalNodes.java

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,7 @@ public Object addSpecial(VirtualFrame frame, DynamicObject a, DynamicObject b) {
8484
return addSpecial(frame, a, b, 0);
8585
}
8686

87-
@Specialization(guards = {
88-
"isRubyBigDecimal(a)",
89-
"!isRubyBigDecimal(b)"
90-
})
87+
@Specialization(guards = "!isRubyBigDecimal(b)")
9188
public Object addCoerced(DynamicObject a, Object b,
9289
@Cached("createPrivate()") CallDispatchHeadNode redoCoerced) {
9390
return redoCoerced.call(a, "redo_coerced", coreStrings().PLUS.getSymbol(), b);
@@ -115,6 +112,12 @@ protected Object add(VirtualFrame frame, DynamicObject a, DynamicObject b, int p
115112
protected Object addSpecial(VirtualFrame frame, DynamicObject a, DynamicObject b, int precision) {
116113
return super.addSpecial(frame, a, b, precision);
117114
}
115+
116+
@Specialization(guards = "!isRubyBigDecimal(b)")
117+
public Object addCoerced(DynamicObject a, Object b, int precision,
118+
@Cached("createPrivate()") CallDispatchHeadNode redoCoerced) {
119+
return redoCoerced.call(a, "redo_coerced", getSymbol("add"), b, precision);
120+
}
118121
}
119122

120123
@CoreMethod(names = "-", required = 1)
@@ -136,10 +139,7 @@ public Object subSpecial(VirtualFrame frame, DynamicObject a, DynamicObject b) {
136139
return subSpecial(frame, a, b, 0);
137140
}
138141

139-
@Specialization(guards = {
140-
"isRubyBigDecimal(a)",
141-
"!isRubyBigDecimal(b)"
142-
})
142+
@Specialization(guards = "!isRubyBigDecimal(b)")
143143
public Object subCoerced(DynamicObject a, Object b,
144144
@Cached("createPrivate()") CallDispatchHeadNode redoCoerced) {
145145
return redoCoerced.call(a, "redo_coerced", coreStrings().MINUS.getSymbol(), b);
@@ -167,6 +167,12 @@ public Object subNormal(VirtualFrame frame, DynamicObject a, DynamicObject b, in
167167
public Object subSpecial(VirtualFrame frame, DynamicObject a, DynamicObject b, int precision) {
168168
return super.subSpecial(frame, a, b, precision);
169169
}
170+
171+
@Specialization(guards = "!isRubyBigDecimal(b)")
172+
public Object subCoerced(DynamicObject a, Object b, int precision,
173+
@Cached("createPrivate()") CallDispatchHeadNode redoCoerced) {
174+
return redoCoerced.call(a, "redo_coerced", getSymbol("sub"), b, precision);
175+
}
170176
}
171177

172178
@CoreMethod(names = "-@")
@@ -252,6 +258,12 @@ public Object multSpecialNormal(VirtualFrame frame, DynamicObject a, DynamicObje
252258
public Object multSpecial(VirtualFrame frame, DynamicObject a, DynamicObject b) {
253259
return multSpecial(frame, a, b, 0);
254260
}
261+
262+
@Specialization(guards = "!isRubyBigDecimal(b)")
263+
public Object multCoerced(DynamicObject a, Object b,
264+
@Cached("createPrivate()") CallDispatchHeadNode redoCoerced) {
265+
return redoCoerced.call(a, "redo_coerced", coreStrings().MULTIPLY.getSymbol(), b);
266+
}
255267
}
256268

257269
@CoreMethod(names = "mult", required = 2, lowerFixnum = 2)
@@ -293,6 +305,12 @@ public Object multSpecialNormal(VirtualFrame frame, DynamicObject a, DynamicObje
293305
public Object multSpecial(VirtualFrame frame, DynamicObject a, DynamicObject b, int precision) {
294306
return super.multSpecial(frame, a, b, precision);
295307
}
308+
309+
@Specialization(guards = "!isRubyBigDecimal(b)")
310+
public Object multCoerced(DynamicObject a, Object b, int precision,
311+
@Cached("createPrivate()") CallDispatchHeadNode redoCoerced) {
312+
return redoCoerced.call(a, "redo_coerced", getSymbol("mult"), b, precision);
313+
}
296314
}
297315

298316
@CoreMethod(names = { "/", "quo" }, required = 1)
@@ -330,6 +348,12 @@ public Object divSpecialNormal(VirtualFrame frame, DynamicObject a, DynamicObjec
330348
public Object divSpecialSpecial(VirtualFrame frame, DynamicObject a, DynamicObject b) {
331349
return divSpecialSpecial(frame, a, b, 0);
332350
}
351+
352+
@Specialization(guards = "!isRubyBigDecimal(b)")
353+
public Object divCoerced(DynamicObject a, Object b,
354+
@Cached("createPrivate()") CallDispatchHeadNode redoCoerced) {
355+
return redoCoerced.call(a, "redo_coerced", coreStrings().DIVIDE.getSymbol(), b);
356+
}
333357
}
334358

335359
@CoreMethod(names = "div", required = 1, optional = 1, lowerFixnum = 2)
@@ -469,6 +493,18 @@ public Object divSpecialSpecial(
469493
public Object divSpecialSpecial(VirtualFrame frame, DynamicObject a, DynamicObject b, int precision) {
470494
return super.divSpecialSpecial(frame, a, b, precision);
471495
}
496+
497+
@Specialization(guards = "!isRubyBigDecimal(b)")
498+
public Object divCoerced(DynamicObject a, Object b, NotProvided precision,
499+
@Cached("createPrivate()") CallDispatchHeadNode redoCoerced) {
500+
return redoCoerced.call(a, "redo_coerced", getSymbol("div"), b);
501+
}
502+
503+
@Specialization(guards = "!isRubyBigDecimal(b)")
504+
public Object divCoerced(DynamicObject a, Object b, int precision,
505+
@Cached("createPrivate()") CallDispatchHeadNode redoCoerced) {
506+
return redoCoerced.call(a, "redo_coerced", getSymbol("div"), b, precision);
507+
}
472508
}
473509

474510
@CoreMethod(names = "divmod", required = 1)
@@ -568,6 +604,12 @@ public Object divmodSpecial(
568604
throw new UnsupportedOperationException("unreachable code branch");
569605
}
570606

607+
@Specialization(guards = "!isRubyBigDecimal(b)")
608+
public Object divmodCoerced(DynamicObject a, Object b,
609+
@Cached("createPrivate()") CallDispatchHeadNode redoCoerced) {
610+
return redoCoerced.call(a, "redo_coerced", getSymbol("divmod"), b);
611+
}
612+
571613
}
572614

573615
@CoreMethod(names = "remainder", required = 1)
@@ -614,6 +656,12 @@ public Object remainderSpecial(
614656
return createBigDecimal(frame, BigDecimalType.NAN);
615657
}
616658
}
659+
660+
@Specialization(guards = "!isRubyBigDecimal(b)")
661+
public Object remainderCoerced(DynamicObject a, Object b,
662+
@Cached("createPrivate()") CallDispatchHeadNode redoCoerced) {
663+
return redoCoerced.call(a, "redo_coerced", getSymbol("remainder"), b);
664+
}
617665
}
618666

619667
@CoreMethod(names = { "modulo", "%" }, required = 1)
@@ -691,6 +739,12 @@ public Object moduloSpecial(
691739

692740
throw new UnsupportedOperationException("unreachable code branch");
693741
}
742+
743+
@Specialization(guards = "!isRubyBigDecimal(b)")
744+
public Object moduloCoerced(DynamicObject a, Object b,
745+
@Cached("createPrivate()") CallDispatchHeadNode redoCoerced) {
746+
return redoCoerced.call(a, "redo_coerced", getSymbol("modulo"), b);
747+
}
694748
}
695749

696750
@CoreMethod(names = { "**", "power" }, required = 1, optional = 1, lowerFixnum = { 1, 2 })

src/main/ruby/core/numeric.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,9 @@ def bit_coerce(other)
278278
end
279279
private :bit_coerce
280280

281-
def redo_coerced(meth, right)
281+
def redo_coerced(meth, right, *extra)
282282
b, a = math_coerce(right)
283-
a.__send__ meth, b
283+
a.__send__ meth, b, *extra
284284
end
285285
private :redo_coerced
286286

0 commit comments

Comments
 (0)