From 3718735726d203e0e3638fcbbf658ae0cf5bf5f0 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 17 Aug 2017 17:26:52 +0200
Subject: [PATCH] Initializing active binding for '.Random.seed' in REngine
 programatically.

---
 .../com/oracle/truffle/r/engine/REngine.java  | 16 +++++++++++++
 .../r/nodes/builtin/base/R/base_overrides.R   |  2 --
 .../r/nodes/builtin/base/RNGFunctions.java    | 23 +++++++++++++------
 .../oracle/truffle/r/runtime/rng/RRNG.java    |  9 ++------
 4 files changed, 34 insertions(+), 16 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
index f8d34c7195..4c03ebeafe 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
@@ -36,6 +36,8 @@ import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.TruffleLanguage.ContextReference;
 import com.oracle.truffle.api.dsl.UnsupportedSpecializationException;
 import com.oracle.truffle.api.frame.Frame;
+import com.oracle.truffle.api.frame.FrameSlot;
+import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
@@ -76,6 +78,7 @@ import com.oracle.truffle.r.runtime.RParserFactory;
 import com.oracle.truffle.r.runtime.RProfile;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RSource;
+import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.ReturnException;
 import com.oracle.truffle.r.runtime.RootWithBody;
 import com.oracle.truffle.r.runtime.SubstituteVirtualFrame;
@@ -98,12 +101,15 @@ import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.interop.R2Foreign;
 import com.oracle.truffle.r.runtime.interop.R2ForeignNodeGen;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
+import com.oracle.truffle.r.runtime.rng.RRNG;
 
 /**
  * The engine for the FastR implementation. Handles parsing and evaluation. There is one instance of
@@ -152,6 +158,7 @@ final class REngine implements Engine, Engine.Timings {
         if (context.getKind() == RContext.ContextKind.SHARE_NOTHING) {
             initializeNonShared();
         }
+        initializeRNG();
     }
 
     private void initializeNonShared() {
@@ -201,6 +208,15 @@ final class REngine implements Engine, Engine.Timings {
         }
     }
 
+    private void initializeRNG() {
+        assert REnvironment.globalEnv() != null;
+        RFunction fun = context.lookupBuiltin(".fastr.set.seed");
+        ActiveBinding dotRandomSeed = new ActiveBinding(RType.Any, fun);
+        Frame frame = REnvironment.globalEnv().getFrame();
+        FrameSlot slot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), RRNG.RANDOM_SEED, FrameSlotKind.Object);
+        FrameSlotChangeMonitor.setActiveBinding(frame, slot, dotRandomSeed, false, null);
+    }
+
     @Override
     public void checkAndRunStartupShutdownFunction(String name, String... args) {
         Object func = REnvironment.globalEnv().findFunction(name);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/base_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/base_overrides.R
index 3c6bcb3f79..9b10332922 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/base_overrides.R
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/base_overrides.R
@@ -27,5 +27,3 @@ eval(expression({
     }
 })
 }), asNamespace("base"))
-
-makeActiveBinding(".Random.seed", .fastr.set.seed, .GlobalEnv)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java
index 6971216e19..1078617dec 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java
@@ -39,10 +39,8 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntVector;
@@ -129,15 +127,26 @@ public class RNGFunctions {
             return RNull.instance;
         }
 
+        protected boolean isSetOperation(Object param) {
+            return !(param instanceof RMissing);
+        }
+
+        @Specialization(guards = {"isSetOperation(data)"})
+        @TruffleBoundary
+        protected RNull setSeed(Object data) {
+            RContext.getInstance().stateRNG.currentSeeds = data;
+            return RNull.instance;
+        }
+
         @Specialization
         @TruffleBoundary
         protected Object getSeed(@SuppressWarnings("unused") RMissing data) {
-            int[] seeds = RContext.getInstance().stateRNG.currentSeeds;
-            if (seeds != null) {
-                return RDataFactory.createIntVector(seeds, RDataFactory.INCOMPLETE_VECTOR);
+            Object seeds = RContext.getInstance().stateRNG.currentSeeds;
+            if (seeds instanceof int[]) {
+                int[] seedsArr = (int[]) seeds;
+                return RDataFactory.createIntVector(seedsArr, RDataFactory.INCOMPLETE_VECTOR);
             }
-// throw error(RError.Message.UNKNOWN_OBJECT, ".Random.seed");
-            return RNull.instance;
+            return seeds;
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java
index 61aa34ed69..1b8d000143 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java
@@ -17,16 +17,11 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
-import com.oracle.truffle.r.runtime.env.REnvironment;
-import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
 import com.oracle.truffle.r.runtime.rng.mm.MarsagliaMulticarry;
 import com.oracle.truffle.r.runtime.rng.mt.MersenneTwister;
@@ -102,14 +97,14 @@ public class RRNG {
     public static final Integer SAME_SEED = null;
     private static final Kind DEFAULT_KIND = Kind.MERSENNE_TWISTER;
     private static final NormKind DEFAULT_NORM_KIND = NormKind.INVERSION;
-    private static final String RANDOM_SEED = ".Random.seed";
+    public static final String RANDOM_SEED = ".Random.seed";
     private static final double UINT_MAX = (double) Integer.MAX_VALUE * 2;
 
     public static final class ContextStateImpl implements RContext.ContextState {
         private RandomNumberGenerator currentGenerator;
         private final RandomNumberGenerator[] allGenerators;
         private NormKind currentNormKind;
-        public int[] currentSeeds;
+        public Object currentSeeds;
 
         private ContextStateImpl() {
             this.currentNormKind = DEFAULT_NORM_KIND;
-- 
GitLab