diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java index 49f536b7eeefd197ee064f91445ece6f6ad4345d..56bb231456813d173e3755fea8891b5c7a0fdef0 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java @@ -57,6 +57,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import java.time.LocalTime; // from GnuR datatime.c @@ -427,7 +428,14 @@ public class DatePOSIXFunctions { continue; } try { - LocalDateTime time = LocalDateTime.from(parse); + LocalDateTime time; + try { + time = LocalDateTime.from(parse); + } catch (DateTimeException e) { + // Try just time and use current date + LocalTime tm = LocalTime.from(parse); + time = LocalDateTime.of(LocalDate.now(), tm); + } builder.setEntry(i, time.getSecond(), time.getMinute(), time.getHour(), time.getDayOfMonth(), time.getMonthValue() - 1, time.getYear() - 1900, time.getDayOfWeek().ordinal(), time.getDayOfYear(), 0); continue; @@ -455,6 +463,10 @@ public class DatePOSIXFunctions { private static DateTimeFormatterBuilder createFormatter(String format, boolean forInput) { DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder(); + if (forInput) { + // Opposite of STRICT mode; allows to parse single-digit hour and minute like '0:3:22'. + builder.parseLenient(); + } boolean escaped = false; int i = 0; while (i < format.length()) { @@ -540,9 +552,10 @@ public class DatePOSIXFunctions { case 'H': /* * Hours as decimal number (00–23). As a special exception strings such as - * 24:00:00 are accepted for input, since ISO 8601 allows these. + * 24:00:00 are accepted for input, since ISO 8601 allows these. For output + * 00-23 is required thus using HOUR_OF_DAY. */ - builder.appendValue(ChronoField.CLOCK_HOUR_OF_DAY, 2); + builder.appendValue(forInput ? ChronoField.CLOCK_HOUR_OF_DAY : ChronoField.HOUR_OF_DAY, 2); break; case 'I': // Hours as decimal number (01–12). diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java index 21a2d7a25883d40f06bb172a52bbf556762fad41..3edade53d5551c2e2d3b3892a9cbaa94f07f356f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java @@ -17,6 +17,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; @@ -32,6 +33,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; +import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "prod", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE_SUMMARY) public abstract class Prod extends RBuiltinNode.Arg2 { @@ -84,12 +86,18 @@ public abstract class Prod extends RBuiltinNode.Arg2 { double aProdImg; if (aProd instanceof RComplex) { RComplex c = (RComplex) aProd; + if (RRuntime.isNA(c)) { + return c; + } aProdReal = c.getRealPart(); aProdImg = c.getImaginaryPart(); complex = true; } else { aProdReal = (Double) aProd; aProdImg = 0d; + if (RRuntime.isNA(aProdReal)) { + return aProd; + } } if (complex) { RComplex c = prod.op(prodReal, prodImg, aProdReal, aProdImg); @@ -105,13 +113,19 @@ public abstract class Prod extends RBuiltinNode.Arg2 { } private final ValueProfile intVecProfile = ValueProfile.createClassProfile(); + private final NACheck naCheck = NACheck.create(); @Specialization protected double prod(RAbstractDoubleVector x) { RAbstractDoubleVector profiledVec = intVecProfile.profile(x); double product = 1; + naCheck.enable(x); for (int k = 0; k < profiledVec.getLength(); k++) { - product = prod.op(product, profiledVec.getDataAt(k)); + double value = profiledVec.getDataAt(k); + if (naCheck.check(value)) { + return RRuntime.DOUBLE_NA; + } + product = prod.op(product, value); } return product; } @@ -120,8 +134,13 @@ public abstract class Prod extends RBuiltinNode.Arg2 { protected double prod(RAbstractIntVector x) { RAbstractIntVector profiledVec = intVecProfile.profile(x); double product = 1; + naCheck.enable(x); for (int k = 0; k < profiledVec.getLength(); k++) { - product = prod.op(product, profiledVec.getDataAt(k)); + int data = profiledVec.getDataAt(k); + if (naCheck.check(data)) { + return RRuntime.DOUBLE_NA; + } + product = prod.op(product, data); } return product; } @@ -130,8 +149,13 @@ public abstract class Prod extends RBuiltinNode.Arg2 { protected double prod(RAbstractLogicalVector x) { RAbstractLogicalVector profiledVec = intVecProfile.profile(x); double product = 1; + naCheck.enable(x); for (int k = 0; k < profiledVec.getLength(); k++) { - product = prod.op(product, profiledVec.getDataAt(k)); + byte value = profiledVec.getDataAt(k); + if (naCheck.check(value)) { + return RRuntime.DOUBLE_NA; + } + product = prod.op(product, value); } return product; } @@ -140,8 +164,12 @@ public abstract class Prod extends RBuiltinNode.Arg2 { protected RComplex prod(RAbstractComplexVector x) { RAbstractComplexVector profiledVec = intVecProfile.profile(x); RComplex product = RDataFactory.createComplexRealOne(); + naCheck.enable(x); for (int k = 0; k < profiledVec.getLength(); k++) { RComplex a = profiledVec.getDataAt(k); + if (naCheck.check(a)) { + return a; + } product = prod.op(product.getRealPart(), product.getImaginaryPart(), a.getRealPart(), a.getImaginaryPart()); } return product; diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test index ff7cb7b48b5e5e9b5c5434b6bd4a9223e4aba6ec..08d6daef45a8ecb94e68c6469daf582240abd79b 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test @@ -6353,12 +6353,12 @@ q3.csv 0.3333333 0.6666667 0.5000000 [1] Freq <0 rows> (or 0-length row.names) -##com.oracle.truffle.r.test.builtins.TestBuiltin_asdifftime.testasdifftime1#Ignored.ImplementationError# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asdifftime.testasdifftime1# #argv <- structure(list(tim = c('0:3:20', '11:23:15')), .Names = 'tim');do.call('as.difftime', argv) Time differences in mins [1] 3.333333 683.250000 -##com.oracle.truffle.r.test.builtins.TestBuiltin_asdifftime.testasdifftime2#Ignored.ImplementationError# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asdifftime.testasdifftime2# #argv <- structure(list(tim = c('3:20', '23:15', '2:'), format = '%H:%M'), .Names = c('tim', 'format'));do.call('as.difftime', argv) Time differences in hours [1] 3.333333 23.250000 NA @@ -45463,15 +45463,15 @@ Error in prod("a") : invalid 'type' (character) of argument #{prod(list())} Error in prod(list()) : invalid 'type' (list) of argument -##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProdNa#Ignored.ImplementationError# +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProdNa# #{prod(c(1,2,3,4,5,NA),FALSE)} [1] NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProdNa#Ignored.ImplementationError# +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProdNa# #{prod(c(2,4,3,NA),TRUE)} [1] NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProdNa#Ignored.ImplementationError# +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProdNa# #{prod(c(2,4,NA))} [1] NA @@ -45515,7 +45515,7 @@ Error in prod(list()) : invalid 'type' (list) of argument #argv <- list(c(0.138260298853371, 0.000636169906925458));prod(argv[[1]]); [1] 8.795704e-05 -##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testprod9#Ignored.ImplementationError# +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testprod9# #argv <- list(NA_integer_);prod(argv[[1]]); [1] NA @@ -66140,17 +66140,21 @@ B FALSE TRUE [2,] 1 [3,] 2 -##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts# -#{ .Internal(strptime('','',) } -Error: unexpected '}' in "{ .Internal(strptime('','',) }" +##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts#Output.IgnoreErrorContext# +#{ .Internal(strptime('','',)); } +Error in .Internal(strptime("", "", )) : argument 3 is empty -##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts# -#{ .Internal(strptime('',,'') } -Error: unexpected '}' in "{ .Internal(strptime('',,'') }" +##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts#Output.IgnoreErrorContext# +#{ .Internal(strptime('',,'')); } +Error in .Internal(strptime("", , "")) : argument 2 is empty ##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts# -#{ .Internal(strptime(,'','') } -Error: unexpected '}' in "{ .Internal(strptime(,'','') }" +#{ .Internal(strptime('1970-01-01 0:3:22', '%H:%M:%S', 'UTC')); } +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts#Output.IgnoreErrorContext# +#{ .Internal(strptime(,'','')); } +Error in .Internal(strptime(, "", "")) : argument 1 is empty ##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.teststrptime1# #argv <- list('2008-04-22 09:45', '%Y-%m-%d', ''); .Internal(strptime(argv[[1]], argv[[2]], argv[[3]])) diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdifftime.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdifftime.java index a39cfdb313564626ebc3c07980bd738a3e2c475a..6a24ff3af08e423d50743a0e677886b945ba4c5c 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdifftime.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdifftime.java @@ -20,13 +20,11 @@ public class TestBuiltin_asdifftime extends TestBase { @Test public void testasdifftime1() { - // FIXME RInternalError: should not reach here - assertEval(Ignored.ImplementationError, "argv <- structure(list(tim = c('0:3:20', '11:23:15')), .Names = 'tim');do.call('as.difftime', argv)"); + assertEval("argv <- structure(list(tim = c('0:3:20', '11:23:15')), .Names = 'tim');do.call('as.difftime', argv)"); } @Test public void testasdifftime2() { - // FIXME RInternalError: should not reach here - assertEval(Ignored.ImplementationError, "argv <- structure(list(tim = c('3:20', '23:15', '2:'), format = '%H:%M'), .Names = c('tim', 'format'));do.call('as.difftime', argv)"); + assertEval("argv <- structure(list(tim = c('3:20', '23:15', '2:'), format = '%H:%M'), .Names = c('tim', 'format'));do.call('as.difftime', argv)"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java index 26d8221b69e8d54e9c7dd56a299611135679105f..42a9f0ef49eb81f41d325bbc09fcefceac17ba45 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java @@ -59,8 +59,7 @@ public class TestBuiltin_prod extends TestBase { @Test public void testprod9() { - // FIXME -2147483648 returned instead of NA - assertEval(Ignored.ImplementationError, "argv <- list(NA_integer_);prod(argv[[1]]);"); + assertEval("argv <- list(NA_integer_);prod(argv[[1]]);"); } @Test @@ -101,11 +100,8 @@ public class TestBuiltin_prod extends TestBase { @Test public void testProdNa() { - // FIXME NaN returned instead of expected NA - assertEval(Ignored.ImplementationError, "{prod(c(2,4,NA))}"); - // FIXME NaN returned instead of expected NA - assertEval(Ignored.ImplementationError, "{prod(c(2,4,3,NA),TRUE)}"); - // FIXME NaN returned instead of expected NA - assertEval(Ignored.ImplementationError, "{prod(c(1,2,3,4,5,NA),FALSE)}"); + assertEval("{prod(c(2,4,NA))}"); + assertEval("{prod(c(2,4,3,NA),TRUE)}"); + assertEval("{prod(c(1,2,3,4,5,NA),FALSE)}"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strptime.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strptime.java index 78be45ee5f2769ec53eef4d60c4bbf9623635282..363f4cfe0f04b6ee6f01525d61023aef9d5f2fe4 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strptime.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strptime.java @@ -69,8 +69,11 @@ public class TestBuiltin_strptime extends TestBase { @Test public void testArgsCasts() { - assertEval("{ .Internal(strptime(,'','') }"); - assertEval("{ .Internal(strptime('',,'') }"); - assertEval("{ .Internal(strptime('','',) }"); + assertEval("{ .Internal(strptime('1970-01-01 0:3:22', '%H:%M:%S', 'UTC')); }"); + // Ingoring error context since changing casts has no effect + // due to hitting InternalNode:152 first that throws the resulting RError + assertEval(Output.IgnoreErrorContext, "{ .Internal(strptime(,'','')); }"); + assertEval(Output.IgnoreErrorContext, "{ .Internal(strptime('',,'')); }"); + assertEval(Output.IgnoreErrorContext, "{ .Internal(strptime('','',)); }"); } }