Skip to content

Commit 26ff8cf

Browse files
author
Pavel Marek
committed
[GR-28147] Fix AssertionError in Sprintf.
PullRequest: fastr/2544
2 parents 10266f0 + 4cb2ffe commit 26ff8cf

File tree

4 files changed

+50
-15
lines changed

4 files changed

+50
-15
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# 21.0.0
2+
3+
Bug fixes:
4+
5+
* Fix `AssertionError` in `sprintf` (#169)
6+
17
# 20.3.0
28

39
Bug fixes:

com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -202,16 +202,11 @@ private static int maxLengthAndConvertToScalar(Object[] values) {
202202
for (int i = 0; i < values.length; i++) {
203203
if (values[i] instanceof RAbstractVector) {
204204
int vecLength = ((RAbstractVector) values[i]).getLength();
205-
if (vecLength == 0) {
206-
// result will be empty character vector in this case, as in:
207-
// sprintf("%d %d", as.integer(c(7,42)), integer())
208-
return 0;
209-
} else {
210-
if (vecLength == 1) {
211-
values[i] = ((RAbstractVector) values[i]).getDataAtAsObject(0);
212-
}
213-
length = Math.max(vecLength, length);
205+
assert vecLength != 0;
206+
if (vecLength == 1) {
207+
values[i] = ((RAbstractVector) values[i]).getDataAtAsObject(0);
214208
}
209+
length = Math.max(vecLength, length);
215210
} else {
216211
length = Math.max(1, length);
217212
}
@@ -231,12 +226,12 @@ private static Object[] createSprintfArgs(Object[] values, int index, int maxLen
231226
return sprintfArgs;
232227
}
233228

234-
@Specialization(guards = {"!oneElement(args)", "hasNull(args)"})
229+
@Specialization(guards = {"!oneElement(args)", "hasNullOrEmptyVec(args)"})
235230
protected RStringVector sprintf(@SuppressWarnings("unused") Object fmt, @SuppressWarnings("unused") RArgsValuesAndNames args) {
236231
return RDataFactory.createEmptyStringVector();
237232
}
238233

239-
@Specialization(guards = {"!oneElement(args)", "!hasNull(args)"})
234+
@Specialization(guards = {"!oneElement(args)", "!hasNullOrEmptyVec(args)"})
240235
@TruffleBoundary
241236
protected RStringVector sprintf(String fmt, RArgsValuesAndNames args) {
242237
Object[] values = args.getArguments();
@@ -267,7 +262,7 @@ protected Object sprintfOneElement(String fmt, RArgsValuesAndNames args) {
267262
return sprintfRecursive.executeObject(fmt, args.getArgument(0));
268263
}
269264

270-
@Specialization(guards = {"!oneElement(args)", "!hasNull(args)"})
265+
@Specialization(guards = {"!oneElement(args)", "!hasNullOrEmptyVec(args)"})
271266
@TruffleBoundary
272267
protected RStringVector sprintf(RStringVector fmt, RArgsValuesAndNames args) {
273268
if (fmt.getLength() == 0) {
@@ -276,8 +271,15 @@ protected RStringVector sprintf(RStringVector fmt, RArgsValuesAndNames args) {
276271
String[] data = new String[fmt.getLength()];
277272
for (int i = 0; i < data.length; i++) {
278273
RStringVector formatted = sprintf(fmt.getDataAt(i), args);
279-
assert formatted.getLength() > 0;
280-
data[i] = formatted.getDataAt(args.getLength() == 0 ? 0 : i % Math.min(args.getLength(), formatted.getLength()));
274+
if (args.getLength() == 0) {
275+
if (formatted.getLength() == 0) {
276+
data[i] = null;
277+
} else {
278+
data[i] = formatted.getDataAt(0);
279+
}
280+
} else {
281+
data[i] = formatted.getDataAt(i % Math.min(args.getLength(), formatted.getLength()));
282+
}
281283
}
282284
return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR);
283285
}
@@ -739,10 +741,15 @@ protected boolean oneElement(RArgsValuesAndNames args) {
739741
return args.getLength() == 1;
740742
}
741743

742-
protected boolean hasNull(RArgsValuesAndNames args) {
744+
protected boolean hasNullOrEmptyVec(RArgsValuesAndNames args) {
743745
for (int i = 0; i < args.getLength(); i++) {
744746
if (args.getArgument(i) == RNull.instance) {
745747
return true;
748+
} else if (args.getArgument(i) instanceof RAbstractVector) {
749+
RAbstractVector vector = (RAbstractVector) args.getArgument(i);
750+
if (vector.getLength() == 0) {
751+
return true;
752+
}
746753
}
747754
}
748755

com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82782,10 +82782,26 @@ character(0)
8278282782
#{ sprintf('%.3i', 4.0) }
8278382783
[1] "004"
8278482784

82785+
##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testSprintf#
82786+
#{ sprintf('%d%s', NULL, 'Hello') }
82787+
character(0)
82788+
8278582789
##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testSprintf#
8278682790
#{ sprintf('%g', 4.3345423) }
8278782791
[1] "4.33454"
8278882792

82793+
##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testSprintf#
82794+
#{ sprintf('%s%d', 'Hello', NULL) }
82795+
character(0)
82796+
82797+
##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testSprintf#
82798+
#{ sprintf('%s%d', 'Hello', c()) }
82799+
character(0)
82800+
82801+
##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testSprintf#
82802+
#{ sprintf('%s%d', 'Hello', seq_along(c())) }
82803+
character(0)
82804+
8278982805
##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testSprintf#
8279082806
#{ sprintf('%s', list('hello world')) }
8279182807
[1] "hello world"

com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sprintf.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,12 @@ public void testSprintf() {
180180
assertEval("{ sprintf('% g', 4.33) }");
181181
assertEval("{ sprintf('%g', 4.3345423) }");
182182

183+
// If one of args is NULL or an empty vector, sprintf should produce character(0).
184+
assertEval("{ sprintf('%s%d', 'Hello', c()) }");
185+
assertEval("{ sprintf('%s%d', 'Hello', NULL) }");
186+
assertEval("{ sprintf('%d%s', NULL, 'Hello') }");
187+
assertEval("{ sprintf('%s%d', 'Hello', seq_along(c())) }");
188+
183189
assertEval(Ignored.ImplementationError, "{ sprintf('%#g', 4.0) }");
184190
}
185191

0 commit comments

Comments
 (0)