Skip to content

Commit 41d5d7a

Browse files
committed
[GR-16210] Fix parsing of doubles and update CHANGELOG.
PullRequest: fastr/2048
2 parents 5211008 + 1440849 commit 41d5d7a

File tree

6 files changed

+96
-18
lines changed

6 files changed

+96
-18
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,4 @@ install.tmp.gnur
156156
lib.install.packages.fastr
157157
lib.install.packages.gnur
158158
/com.oracle.truffle.r.release/doc/
159+
.Rproj.user

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
# 20.0.0-beta1
2+
3+
New features:
4+
5+
* `is.function` returns `true` for foreign executables
6+
* better error message when FastR cannot find its home directory
7+
8+
Bug fixes:
9+
10+
* strings '-Inf', '+NaN', and '-NaN' are correctly parsed to doubles including ignoring leading and trailing whitespace
11+
* avoid unhandled exceptions in `dev.set` #76
12+
* `for` loop creates and initializes the control variable even if there are no iterations #77
13+
* update the output of the `capabilities` builtin #78
14+
115
# 19.0.0
216

317
New features:

com.oracle.truffle.r.pkgs/refcmp/R/snapshot.R

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ refcmpEnv$snapshot_dir <- 'snapshots'
2626
refcmpEnv$snapshot_id <- 0L
2727
refcmpEnv$equals <- all.equal
2828

29+
log <- function(msg) cat("SNAPSHOT: ", msg, "\n")
30+
2931
snapshot.isFastR <- function() {
3032
length(grep('FastR', R.Version()$version.string)) != 0
3133
}
@@ -35,14 +37,17 @@ snapshot.isFastR <- function() {
3537
#' @param dir The directory where to store snapshot to (default: 'snapshots')
3638
#' @param is_reference_run A function returning TRUE if snapshots should be taken and FALSE if values should be compared (default: snapshot dir does not exist)
3739
#' @param equalityFunction The function to use for comparing actual values to snapshotted values (default: 'all.equal')
40+
#' @param browserOnDiff Calls the "browser()" function on each difference to the reference run, this opens the
41+
#' interactive command line debugger where you can further inspect the state.
3842
#' @examples
3943
#' # Only comparing using snapshots in directory "my/snapshot/dir" and using function 'identical' to compare values.
4044
#' snapshot.init(dir = "my/snapshot/dir", referenceRunPredicate = function() FALSE, equalityFunction = identical)
4145
#'
4246
#' # This should do the job in most cases
4347
#' snapshot.init()
4448
#' @export
45-
snapshot.init <- function (dir, is_reference_run, equalityFunction) {
49+
snapshot.init <- function (dir, is_reference_run, equalityFunction, browserOnDiff = T) {
50+
refcmpEnv$browser <- browserOnDiff
4651
if (!missing(dir)) {
4752
refcmpEnv$snaphost_dir <- dir
4853
}
@@ -51,6 +56,11 @@ snapshot.init <- function (dir, is_reference_run, equalityFunction) {
5156
} else {
5257
refcmpEnv$is_reference_run <- !file.exists(refcmpEnv$snapshot_dir)
5358
}
59+
if (refcmpEnv$is_reference_run) {
60+
log(paste0(" Mode is reference run. The data will be saved to ", refcmpEnv$snapshot_dir))
61+
} else {
62+
log(paste0(" Mode is check run. The data will be compared to reference run data from ", refcmpEnv$snapshot_dir))
63+
}
5464
if (!missing(equalityFunction)) {
5565
refcmpEnv$equals <- equalityFunction
5666
}
@@ -73,12 +83,12 @@ snapshot.init <- function (dir, is_reference_run, equalityFunction) {
7383
#'
7484
#' snapshot(x, y, z)
7585
#' @export
76-
snapshot <- function(...) {
86+
snapshot <- function(..., ignore = F) {
7787
# the actual parameter expessions
7888
actParExprs <- as.list(match.call()[-1])
7989
valueList <- actParsToList(actParExprs, parent.frame())
8090
try({
81-
snapshot.id(refcmpEnv$snapshot_id, valueList)
91+
snapshot.id(refcmpEnv$snapshot_id, valueList, ignore)
8292
refcmpEnv$snapshot_id <- refcmpEnv$snapshot_id + 1
8393
})
8494
}
@@ -95,23 +105,27 @@ snapshot <- function(...) {
95105
#' I contrast to function 'snapshot', this function does not try to automatically determine the name of a value.
96106
#' It uses the names as provided in the arguments.
97107
#'
108+
#' The ignore parameter allows to skip snapshots that were examined, but still increments the ID sequence so that following comparisons can work.
109+
#'
98110
#' @examples
99111
#' snapshot.named(a = 10 + 20, b = 30, c = function() print("hello"))
100112
#' @export
101-
snapshot.named <- function (...) {
113+
snapshot.named <- function (..., ignore = F) {
102114
args <- list(...)
103115
valueList <- args[names(args) != ""]
104116
try({
105-
snapshot.id(refcmpEnv$snapshot_id, valueList)
117+
snapshot.id(refcmpEnv$snapshot_id, valueList, ignore)
106118
refcmpEnv$snapshot_id <- refcmpEnv$snapshot_id + 1
107119
})
108120
}
109121

110-
snapshot.id <- function(id, valueList) {
111-
if(refcmpEnv$is_reference_run) {
112-
snapshot.record(id, valueList)
113-
} else {
122+
snapshot.id <- function(id, valueList, ignore = F) {
123+
if(!refcmpEnv$is_reference_run) {
124+
log(paste0(" Checking: id ", id, " values named: ", paste(names(valueList), collapse=",")))
114125
snapshot.check(id, valueList)
126+
} else if (!ignore) {
127+
log(paste0(" Recording: id ", id, " values named: ", paste(names(valueList), collapse=",")))
128+
snapshot.record(id, valueList)
115129
}
116130
}
117131

@@ -142,10 +156,18 @@ snapshot.check <- function(id, valueList) {
142156
expectedVal <- restoredVars[[var_names[[i]]]]
143157
equalsResult <- refcmpEnv$equals(expectedVal, actualVal)
144158
if(!is.logical(equalsResult) || !equalsResult) {
145-
stop(paste0("Value of variable '", var_names[[i]], "' differs. Expected ", expectedVal, " but was ", actualVal))
159+
cat("-------------------------------\n")
160+
cat("ERROR: Value of variable '", var_names[[i]], "' differs.\n")
161+
cat("Expected:\n"); str(expectedVal)
162+
cat("\n---\nActual:\n"); str(actualVal)
163+
cat("\n---\nEquality function result: \n")
164+
print(equalsResult)
165+
cat("-------------------------------\n")
166+
if (refcmpEnv$browser) { browser() }
146167
}
147168
} else {
148-
stop(paste0("Missing variable '", var_names[[i]], "' in recorded variables"))
169+
cat("ERROR: Missing variable '", var_names[[i]], "' in recorded variables\n")
170+
if (refcmpEnv$browser) { browser() }
149171
}
150172
}
151173
}

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -493,15 +493,18 @@ public static int string2int(String s) {
493493
@TruffleBoundary
494494
public static double string2doubleNoCheck(String v, boolean exceptionOnFail) {
495495
// FIXME use R rules
496-
if ("Inf".equals(v)) {
496+
String trimmed = v.trim();
497+
if ("Inf".equals(trimmed) || "+Inf".equals(trimmed)) {
497498
return Double.POSITIVE_INFINITY;
498-
} else if ("NaN".equals(v)) {
499+
} else if ("-Inf".equals(trimmed)) {
500+
return Double.NEGATIVE_INFINITY;
501+
} else if ("NaN".equals(trimmed) || "+NaN".equals(trimmed) || "-NaN".equals(trimmed)) {
499502
return Double.NaN;
500-
} else if ("NA_real_".equals(v)) {
503+
} else if ("NA_real_".equals(trimmed)) {
501504
return DOUBLE_NA;
502505
}
503506
try {
504-
return Double.parseDouble(v);
507+
return Double.parseDouble(trimmed);
505508
} catch (NumberFormatException e) {
506509
if (hasHexPrefix(v)) {
507510
switch (v.charAt(0)) {

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

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6798,6 +6798,36 @@ Time differences in hours
67986798
#if (!any(R.version$engine == "FastR")) { [1] TRUE } else { { x <- c(1, 3.5); .fastr.identity(x) == .fastr.identity(as.double(x)); } }
67996799
Error: unexpected '[' in "if (!any(R.version$engine == "FastR")) { ["
68006800

6801+
##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble#
6802+
#as.double(' <<<NEWLINE>>> +Inf <<<NEWLINE>>> ')
6803+
[1] Inf
6804+
6805+
##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble#
6806+
#as.double(' <<<NEWLINE>>> +NaN <<<NEWLINE>>> ')
6807+
[1] NaN
6808+
6809+
##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble#
6810+
#as.double(' <<<NEWLINE>>> -Inf <<<NEWLINE>>> ')
6811+
[1] -Inf
6812+
6813+
##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble#
6814+
#as.double(' <<<NEWLINE>>> -NaN <<<NEWLINE>>> ')
6815+
[1] NaN
6816+
6817+
##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble#
6818+
#as.double(' <<<NEWLINE>>> Inf <<<NEWLINE>>> ')
6819+
[1] Inf
6820+
6821+
##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble#
6822+
#as.double(' <<<NEWLINE>>> NaN <<<NEWLINE>>> ')
6823+
[1] NaN
6824+
6825+
##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble#
6826+
#as.double('- Inf')
6827+
[1] NA
6828+
Warning message:
6829+
NAs introduced by coercion
6830+
68016831
##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble#
68026832
#{ as.double("1.27") }
68036833
[1] 1.27
@@ -21250,7 +21280,7 @@ Error in f() :
2125021280
#{ f <- function() { delayedAssign("x", y); y <- 10; x } ; f() }
2125121281
[1] 10
2125221282

21253-
##com.oracle.truffle.r.test.builtins.TestBuiltin_delayedAssign.testDelayedAssign#
21283+
##com.oracle.truffle.r.test.builtins.TestBuiltin_delayedAssign.testDelayedAssign#Output.IgnoreErrorContext#
2125421284
#{ f <- function() { delayedAssign("x",y); delayedAssign("y",x); g(x, y)}; g <- function(x, y) { x + y }; f() }
2125521285
Error in g(x, y) :
2125621286
promise already under evaluation: recursive default argument reference or earlier problems?
@@ -21260,7 +21290,7 @@ Error in g(x, y) :
2126021290
Error in f() :
2126121291
promise already under evaluation: recursive default argument reference or earlier problems?
2126221292

21263-
##com.oracle.truffle.r.test.builtins.TestBuiltin_delayedAssign.testDelayedAssign#
21293+
##com.oracle.truffle.r.test.builtins.TestBuiltin_delayedAssign.testDelayedAssign#Output.IgnoreErrorContext#
2126421294
#{ f <- function() { delayedAssign("x",y); delayedAssign("y",x); paste(x, y)}; f() }
2126521295
Error in paste(x, y) :
2126621296
promise already under evaluation: recursive default argument reference or earlier problems?

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1515
*
1616
* Copyright (c) 2012-2014, Purdue University
17-
* Copyright (c) 2013, 2018, Oracle and/or its affiliates
17+
* Copyright (c) 2013, 2019, Oracle and/or its affiliates
1818
*
1919
* All rights reserved.
2020
*/
@@ -201,6 +201,14 @@ public void testAsDouble() {
201201
assertEval("{ f <- function() as.double('aaa'); f() }");
202202
assertEval("{ f <- function() as.numeric('aaa'); f() }");
203203
assertEval("{ f1 <- function() {f<- function() as.double('aaa'); f()}; f1() }");
204+
205+
assertEval("as.double('\t\n Inf\t\n ')");
206+
assertEval("as.double('\t\n +Inf\t\n ')");
207+
assertEval("as.double('\t\n -Inf\t\n ')");
208+
assertEval("as.double('\t\n NaN\t\n ')");
209+
assertEval("as.double('\t\n +NaN\t\n ')");
210+
assertEval("as.double('\t\n -NaN\t\n ')");
211+
assertEval("as.double('- Inf')");
204212
}
205213

206214
@Test

0 commit comments

Comments
 (0)