From c1fb27125841e6c7fae612fff790ef3ea93c40e0 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 20 Jul 2017 17:48:52 +0200
Subject: [PATCH] RFFI fixes: PRENV materializes frame, Rf_eval handles
 RSymbols, NAMED/SET_NAMED, simple CAAR & CDAR implementation

---
 .../ffi/impl/common/JavaUpCallsRFFIImpl.java  | 42 ++++++++++++++++---
 .../fficall/src/jni/Rinternals.c              |  6 +--
 com.oracle.truffle.r.native/version.source    |  2 +-
 3 files changed, 39 insertions(+), 11 deletions(-)

diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
index 3b073fef24..2ddd07504b 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
@@ -47,6 +47,7 @@ import com.oracle.truffle.r.ffi.impl.nodes.FFIUpCallRootNode;
 import com.oracle.truffle.r.ffi.impl.upcalls.RFFIUpCallTable;
 import com.oracle.truffle.r.ffi.impl.upcalls.UpCallsRFFI;
 import com.oracle.truffle.r.nodes.RASTUtils;
+import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RArguments;
@@ -54,6 +55,7 @@ import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RCleanUp;
 import com.oracle.truffle.r.runtime.REnvVars;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RErrorHandling;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -84,6 +86,7 @@ import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
+import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
 import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.data.RSequence;
@@ -576,20 +579,41 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     @Override
     public int NAMED(Object x) {
         if (x instanceof RShareable) {
-            return ((RShareable) x).isShared() ? 1 : 0;
+            return getNamed((RShareable) x);
         } else {
-            throw unimplemented();
+            // Note: it may be that we need to remember this for all types, GNUR does
+            return 2;
         }
     }
 
     @Override
     public Object SET_NAMED_FASTR(Object x, int v) {
+        // Note: In GNUR this is a macro that sets the sxpinfo.named regardless of whether it makes
+        // sense to name the actual value, for compatibilty we simply ignore values that are not
+        // RShareable, e.g. RSymbol. However we ignore and report attemps to decrease the ref-count,
+        // which as it seems GNUR would just let proceede
         if (x instanceof RShareable) {
-            ((RShareable) x).incRefCount();
-            return RNull.instance;
-        } else {
-            throw unimplemented();
+            RShareable r = (RShareable) x;
+            int actual = getNamed(r);
+            if (v < actual) {
+                RError.warning(RError.NO_CALLER, Message.GENERIC, "Native code attempted to decrease the reference count. This operation is ignored.");
+                return RNull.instance;
+            }
+            if (v == 2) {
+                // we play it safe: if the caller wants this instance to be shared, they may expect
+                // it to never become non-shared again, which could happen in FastR
+                r.makeSharedPermanent();
+                return RNull.instance;
+            }
+            if (v == 1 && r.isTemporary()) {
+                r.incRefCount();
+            }
         }
+        return RNull.instance;
+    }
+
+    private static int getNamed(RShareable r) {
+        return r.isTemporary() ? 0 : r.isShared() ? 2 : 1;
     }
 
     @Override
@@ -789,6 +813,9 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
                                 ArgumentsSignature.fromNamesAttribute(argsList.getNames()),
                                 argsList.getDataNonShared());
             }
+        } else if (expr instanceof RSymbol) {
+            ReadVariableNode rvn = ReadVariableNode.create(((RSymbol) expr).getName());
+            result = RContext.getEngine().eval(RDataFactory.createLanguage(rvn), (REnvironment) env, RCaller.topLevel);
         } else {
             // just return value
             result = expr;
@@ -1383,6 +1410,9 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     @Override
     public Object PRENV(Object x) {
         RPromise promise = RFFIUtils.guaranteeInstanceOf(x, RPromise.class);
+        if (promise instanceof EagerPromise) {
+            ((EagerPromise) promise).materialize();
+        }
         final MaterializedFrame frame = promise.getFrame();
         return frame != null ? REnvironment.frameToEnvironment(frame) : RNull.instance;
     }
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
index 710affdd15..6b32be84a1 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -776,13 +776,11 @@ SEXP CDR(SEXP e) {
 }
 
 SEXP CAAR(SEXP e) {
-    unimplemented("CAAR");
-    return NULL;
+    return CAR(CAR(e));
 }
 
 SEXP CDAR(SEXP e) {
-    unimplemented("CDAR");
-    return NULL;
+    return CDR(CAR(e));
 }
 
 SEXP CADR(SEXP e) {
diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source
index f04c001f3f..64bb6b746d 100644
--- a/com.oracle.truffle.r.native/version.source
+++ b/com.oracle.truffle.r.native/version.source
@@ -1 +1 @@
-29
+30
-- 
GitLab