From 6847f591ffddd55fad47a40fe08caca22669f49a Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 28 Sep 2017 15:22:46 +0200
Subject: [PATCH] Fix: Did not properly report missing values from active
 bindings.

---
 .../r/nodes/builtin/base/GetFunctions.java    |  4 +--
 .../variables/LocalReadVariableNode.java      |  6 ++++-
 .../access/variables/ReadVariableNode.java    |  6 ++++-
 .../truffle/r/test/ExpectedTestOutput.test    | 26 +++++++++++++++++++
 .../stats/TestRandGenerationFunctions.java    | 10 +++++++
 5 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
index e8547dc985..c1c66e7f6d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
@@ -112,7 +112,7 @@ public class GetFunctions {
 
         protected Object getAndCheck(VirtualFrame frame, String x, REnvironment env, RType modeType, String modeString, boolean fail) throws RError {
             Object obj = checkPromise(frame, env.get(x), x);
-            if (obj != null && RRuntime.checkType(obj, modeType)) {
+            if (obj != null && obj != RMissing.instance && RRuntime.checkType(obj, modeType)) {
                 return obj;
             } else {
                 if (fail) {
@@ -136,7 +136,7 @@ public class GetFunctions {
                         }
                     }
                 }
-                if (r == null && fail) {
+                if ((r == null || r == RMissing.instance) && fail) {
                     unknownObject(x, modeType, modeString);
                 }
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
index 809ee9face..12cbdee576 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
@@ -120,7 +120,11 @@ public final class LocalReadVariableNode extends Node {
         }
         // special treatment for active binding: call bound function
         if (!containsNoActiveBindingAssumption.isValid() && ActiveBinding.isActiveBinding(result)) {
-            return ((ActiveBinding) result).readValue();
+            Object readValue = ((ActiveBinding) result).readValue();
+            if (readValue == RMissing.instance) {
+                return null;
+            }
+            return readValue;
         }
 
         if (forceResult) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
index 7ba6b410c2..7fe705bfcb 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
@@ -262,7 +262,11 @@ public final class ReadVariableNode extends RBaseNode {
             result = promiseHelper.evaluate(frame, (RPromise) result);
         }
         if (isActiveBindingProfile.profile(ActiveBinding.isActiveBinding(result))) {
-            return ((ActiveBinding) result).readValue();
+            Object readValue = ((ActiveBinding) result).readValue();
+            if (readValue == RMissing.instance) {
+                throw error(mode == RType.Function ? RError.Message.UNKNOWN_FUNCTION : RError.Message.UNKNOWN_OBJECT, identifier);
+            }
+            return readValue;
         }
         return result;
     }
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 3a2a1dc162..f0f5839ca9 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
@@ -153818,6 +153818,32 @@ $variables
 list(k, y, z)
 
 
+##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testDotRandomSeed#Output.IgnoreErrorContext#
+#{ .Random.seed }
+Error: object '.Random.seed' not found
+
+##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testDotRandomSeed#Output.IgnoreErrorContext#
+#{ get('.Random.seed', envir = .GlobalEnv, inherits = FALSE) }
+Error in get(".Random.seed", envir = .GlobalEnv, inherits = FALSE) :
+  object '.Random.seed' not found
+
+##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testDotRandomSeed#Output.IgnoreErrorContext#
+#{ get('.Random.seed', envir = .GlobalEnv, inherits = TRUE) }
+Error in get(".Random.seed", envir = .GlobalEnv, inherits = TRUE) :
+  object '.Random.seed' not found
+
+##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testDotRandomSeed#
+#{ get0('.Random.seed', envir = .GlobalEnv, inherits = FALSE) }
+NULL
+
+##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testDotRandomSeed#
+#{ get0('.Random.seed', envir = .GlobalEnv, inherits = TRUE) }
+NULL
+
+##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testDotRandomSeed#Output.IgnoreErrorContext#
+#{ print(.Random.seed) }
+Error in print(.Random.seed) : object '.Random.seed' not found
+
 ##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testFunctions1#Output.IgnoreWhitespace#
 #set.seed(10); rsignrank(12, c(NA, NaN, 1/0, -1/0, -1, 1, 0.3, -0.6, 0.0653, 0.000123, 32e-80, 10))
  [1] NA NA  0 NA NA  1  0 NA  0  0  0 21
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
index 56ff6bd83d..7eb611414d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
@@ -101,4 +101,14 @@ public class TestRandGenerationFunctions extends TestBase {
     public void testGenerators() {
         assertEval("for(gen in c(\"Buggy Kinderman-Ramage\", \"Ahrens-Dieter\", \"Box-Muller\", \"Inversion\", \"Kinderman-Ramage\", \"default\")) { print(paste0(gen, \":\")); RNGkind(NULL,gen); set.seed(42); print(rnorm(30)); }");
     }
+
+    @Test
+    public void testDotRandomSeed() {
+        assertEval(Output.IgnoreErrorContext, "{ .Random.seed }");
+        assertEval(Output.IgnoreErrorContext, "{ print(.Random.seed) }");
+        assertEval(Output.IgnoreErrorContext, "{ get('.Random.seed', envir = .GlobalEnv, inherits = FALSE) }");
+        assertEval("{ get0('.Random.seed', envir = .GlobalEnv, inherits = FALSE) }");
+        assertEval(Output.IgnoreErrorContext, "{ get('.Random.seed', envir = .GlobalEnv, inherits = TRUE) }");
+        assertEval("{ get0('.Random.seed', envir = .GlobalEnv, inherits = TRUE) }");
+    }
 }
-- 
GitLab