From 69bf6d5e17c3a58b183861b77e3d45fcd058904e Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Wed, 26 Jul 2017 13:02:36 -0700
Subject: [PATCH] [GR-5338] Fixes for cranlogs package.

---
 .../r/engine/TruffleRLanguageImpl.java        |  1 -
 .../ffi/impl/common/JavaUpCallsRFFIImpl.java  |  6 ++
 .../impl/common/TracingUpCallsRFFIImpl.java   |  6 ++
 .../r/ffi/impl/upcalls/StdUpCallsRFFI.java    |  2 +
 .../fficall/src/common/rffi_upcallsindex.h    | 91 ++++++++---------
 .../fficall/src/jni/Rinternals.c              | 11 ++-
 com.oracle.truffle.r.native/version.source    |  2 +-
 .../builtin/base/ConnectionFunctions.java     | 44 ++++++++-
 .../r/nodes/builtin/base/LocaleFunctions.java | 97 ++++++++++++++-----
 .../truffle/r/runtime/RErrorHandling.java     | 17 ++++
 .../truffle/r/test/ExpectedTestOutput.test    | 44 ++++++---
 .../builtins/TestBuiltin_Syssetlocale.java    |  9 +-
 mx.fastr/mx_fastr.py                          |  2 +-
 13 files changed, 239 insertions(+), 93 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguageImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguageImpl.java
index e51cdfd37d..d1fa28a8e7 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguageImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguageImpl.java
@@ -77,7 +77,6 @@ public final class TruffleRLanguageImpl extends TruffleRLanguage implements Scop
      */
     private static void initialize() {
         try {
-            Locale.setDefault(Locale.ROOT);
             RAccuracyInfo.initialize();
         } catch (Throwable t) {
             t.printStackTrace();
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 f58760ece3..7c50bb2d2d 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
@@ -392,6 +392,12 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         return 0;
     }
 
+    @Override
+    public int Rf_errorcall(Object call, Object msg) {
+        RErrorHandling.errorcallRFFI(call, (String) msg);
+        return 0;
+    }
+
     @Override
     public Object Rf_allocVector(int mode, long n) {
         SEXPTYPE type = SEXPTYPE.mapInt(mode);
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TracingUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TracingUpCallsRFFIImpl.java
index 5a483d0457..cf9a072f94 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TracingUpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TracingUpCallsRFFIImpl.java
@@ -218,6 +218,12 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
         return delegate.Rf_warningcall(call, msg);
     }
 
+    @Override
+    public int Rf_errorcall(Object call, Object msg) {
+        RFFIUtils.traceUpCall("Rf_errorcall", call, msg);
+        return delegate.Rf_errorcall(call, msg);
+    }
+
     @Override
     public Object Rf_allocVector(int mode, long n) {
         RFFIUtils.traceUpCall("Rf_allocateVector", mode, n);
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
index 732ca80749..56faae246c 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
@@ -115,6 +115,8 @@ public interface StdUpCallsRFFI {
 
     int /* void */ Rf_warningcall(Object call, @RFFICstring Object msg);
 
+    int /* void */ Rf_errorcall(Object call, @RFFICstring Object msg);
+
     Object Rf_allocVector(int mode, long n);
 
     Object Rf_allocArray(int mode, Object dimsObj);
diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
index 5c4785b6e6..a08f6c2192 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
+++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
@@ -94,51 +94,52 @@
 #define Rf_defineVar_x 89
 #define Rf_duplicate_x 90
 #define Rf_error_x 91
-#define Rf_eval_x 92
-#define Rf_findFun_x 93
-#define Rf_findVar_x 94
-#define Rf_findVarInFrame_x 95
-#define Rf_findVarInFrame3_x 96
-#define Rf_getAttrib_x 97
-#define Rf_gsetVar_x 98
-#define Rf_inherits_x 99
-#define Rf_install_x 100
-#define Rf_installChar_x 101
-#define Rf_isNull_x 102
-#define Rf_isString_x 103
-#define Rf_lengthgets_x 104
-#define Rf_mkCharLenCE_x 105
-#define Rf_ncols_x 106
-#define Rf_nrows_x 107
-#define Rf_setAttrib_x 108
-#define Rf_str2type_x 109
-#define Rf_warning_x 110
-#define Rf_warningcall_x 111
-#define Rprintf_x 112
-#define SETCADR_x 113
-#define SETCAR_x 114
-#define SETCDR_x 115
-#define SET_NAMED_FASTR_x 116
-#define SET_RDEBUG_x 117
-#define SET_RSTEP_x 118
-#define SET_S4_OBJECT_x 119
-#define SET_STRING_ELT_x 120
-#define SET_SYMVALUE_x 121
-#define SET_TAG_x 122
-#define SET_TYPEOF_FASTR_x 123
-#define SET_VECTOR_ELT_x 124
-#define STRING_ELT_x 125
-#define SYMVALUE_x 126
-#define TAG_x 127
-#define TYPEOF_x 128
-#define UNSET_S4_OBJECT_x 129
-#define VECTOR_ELT_x 130
-#define getConnectionClassString_x 131
-#define getOpenModeString_x 132
-#define getSummaryDescription_x 133
-#define isSeekable_x 134
-#define unif_rand_x 135
+#define Rf_errorcall_x 92
+#define Rf_eval_x 93
+#define Rf_findFun_x 94
+#define Rf_findVar_x 95
+#define Rf_findVarInFrame_x 96
+#define Rf_findVarInFrame3_x 97
+#define Rf_getAttrib_x 98
+#define Rf_gsetVar_x 99
+#define Rf_inherits_x 100
+#define Rf_install_x 101
+#define Rf_installChar_x 102
+#define Rf_isNull_x 103
+#define Rf_isString_x 104
+#define Rf_lengthgets_x 105
+#define Rf_mkCharLenCE_x 106
+#define Rf_ncols_x 107
+#define Rf_nrows_x 108
+#define Rf_setAttrib_x 109
+#define Rf_str2type_x 110
+#define Rf_warning_x 111
+#define Rf_warningcall_x 112
+#define Rprintf_x 113
+#define SETCADR_x 114
+#define SETCAR_x 115
+#define SETCDR_x 116
+#define SET_NAMED_FASTR_x 117
+#define SET_RDEBUG_x 118
+#define SET_RSTEP_x 119
+#define SET_S4_OBJECT_x 120
+#define SET_STRING_ELT_x 121
+#define SET_SYMVALUE_x 122
+#define SET_TAG_x 123
+#define SET_TYPEOF_FASTR_x 124
+#define SET_VECTOR_ELT_x 125
+#define STRING_ELT_x 126
+#define SYMVALUE_x 127
+#define TAG_x 128
+#define TYPEOF_x 129
+#define UNSET_S4_OBJECT_x 130
+#define VECTOR_ELT_x 131
+#define getConnectionClassString_x 132
+#define getOpenModeString_x 133
+#define getSummaryDescription_x 134
+#define isSeekable_x 135
+#define unif_rand_x 136
 
-#define UPCALLS_TABLE_SIZE 136
+#define UPCALLS_TABLE_SIZE 137
 
 #endif // RFFI_UPCALLSINDEX_H
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 642fdd7ad1..1858fc85e7 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -57,6 +57,7 @@ static jmethodID Rf_isNullMethodID;
 static jmethodID Rf_installCharMethodID;
 static jmethodID Rf_installMethodID;
 static jmethodID Rf_warningcallMethodID;
+static jmethodID Rf_errorcallMethodID;
 static jmethodID Rf_warningMethodID;
 static jmethodID Rf_errorMethodID;
 static jmethodID R_NewHashedEnvMethodID;
@@ -172,6 +173,7 @@ void init_internals(JNIEnv *env) {
 	Rf_installCharMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_installChar", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_warningMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_warning", "(Ljava/lang/Object;)I", 0);
 	Rf_warningcallMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_warningcall", "(Ljava/lang/Object;Ljava/lang/Object;)I", 0);
+	Rf_errorcallMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_errorcall", "(Ljava/lang/Object;Ljava/lang/Object;)I", 0);
 	Rf_errorMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_error", "(Ljava/lang/Object;)I", 0);
 	Rf_allocVectorMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocVector", "(IJ)Ljava/lang/Object;", 0);
 	Rf_allocMatrixMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocMatrix", "(III)Ljava/lang/Object;", 0);
@@ -604,7 +606,14 @@ void Rf_error(const char *format, ...) {
 }
 
 void Rf_errorcall(SEXP x, const char *format, ...) {
-	unimplemented("Rf_errorcall");
+	char buf[8192];
+	va_list(ap);
+	va_start(ap,format);
+	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
+	va_end(ap);
+	JNIEnv *thisenv = getEnv();
+	jstring string = (*thisenv)->NewStringUTF(thisenv, buf);
+	(*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_errorcallMethodID, x, string);
 }
 
 void Rf_warningcall(SEXP x, const char *format, ...) {
diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source
index f5c89552bd..bb95160cb6 100644
--- a/com.oracle.truffle.r.native/version.source
+++ b/com.oracle.truffle.r.native/version.source
@@ -1 +1 @@
-32
+33
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 272c1ea4e8..fd7198eda7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -34,6 +34,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.rawValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
@@ -827,8 +828,7 @@ public abstract class ConnectionFunctions {
 
         static {
             Casts casts = new Casts(ReadBin.class);
-            // TODO con can be a RAWSXP (not implemented)
-            CastsHelper.connection(casts);
+            casts.arg("con").defaultError(Message.INVALID_CONNECTION).mustNotBeNull().returnIf(rawValue()).asIntegerVector().findFirst();
             casts.arg("what").asStringVector().findFirst();
             CastsHelper.n(casts);
             CastsHelper.size(casts);
@@ -836,6 +836,22 @@ public abstract class ConnectionFunctions {
             CastsHelper.swap(casts);
         }
 
+        @SuppressWarnings("unused")
+        @Specialization
+        @TruffleBoundary
+        protected Object readBin(RAbstractRawVector con, String what, int n, int sizeInput, boolean signed, boolean swap) {
+            Object result;
+            switch (what) {
+                case "character":
+                    result = readString(con, con.getLength());
+                    break;
+
+                default:
+                    throw RInternalError.unimplemented();
+            }
+            return result;
+        }
+
         @Specialization
         @TruffleBoundary
         protected Object readBin(int con, String what, int n, int sizeInput, boolean signed, boolean swap) {
@@ -983,6 +999,23 @@ public abstract class ConnectionFunctions {
             return RDataFactory.createStringVector(stringData, RDataFactory.COMPLETE_VECTOR);
         }
 
+        private static RStringVector readString(RAbstractRawVector vec, int n) {
+            ArrayList<String> strings = new ArrayList<>(n);
+            byte[] chars;
+            if (vec instanceof RRaw) {
+                chars = new byte[1];
+                chars[0] = ((RRaw) vec).getRawDataAt(0);
+            } else {
+                chars = ((RRawVector) vec).getDataWithoutCopying();
+            }
+            strings.add(new String(chars, 0, n));
+
+            // There is no special encoding for NA_character_
+            String[] stringData = new String[1];
+            strings.toArray(stringData);
+            return RDataFactory.createStringVector(stringData, RDataFactory.COMPLETE_VECTOR);
+        }
+
         private static RRawVector readRaw(RConnection con, int n) throws IOException {
             ByteBuffer buffer = ByteBuffer.allocate(n);
             int bytesRead = con.readBin(buffer);
@@ -995,6 +1028,13 @@ public abstract class ConnectionFunctions {
             return RDataFactory.createRawVector(data);
         }
 
+        /*
+         * private static RRawVector readRaw(RAbstractRawVector raw, int n) { ByteBuffer buffer =
+         * ByteBuffer.allocate(n); int bytesRead = con.readBin(buffer); if (bytesRead == 0) { return
+         * RDataFactory.createEmptyRawVector(); } buffer.flip(); byte[] data = new byte[bytesRead];
+         * buffer.get(data); return RDataFactory.createRawVector(data); }
+         */
+
         private static RLogicalVector readLogical(RConnection con, int n, boolean swap) throws IOException {
             ByteBuffer buffer = ByteBuffer.allocate(n * 4);
             int bytesRead = con.readBin(buffer);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java
index aae947e9a6..ddbc3242d7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java
@@ -34,15 +34,16 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import java.nio.charset.Charset;
+import java.util.Locale;
 
 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.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -51,6 +52,46 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public class LocaleFunctions {
 
+    enum LC {
+        COLLATE(stdDefault()),
+        CTYPE(stdDefault()),
+        MONETARY(stdDefault()),
+        NUMERIC("C"),
+        TIME(stdDefault()),
+        MESSAGES(stdDefault()),
+        PAPER(""),
+        MEASUREMENT("");
+
+        private String value;
+        private String defaultValue;
+
+        LC(String defaultValue) {
+            this.defaultValue = defaultValue;
+        }
+
+        static String stdDefault() {
+            String defLocale = Locale.getDefault().toString() + "_";
+            String defCharSet = Charset.defaultCharset().name();
+            return defLocale + defCharSet;
+        }
+
+        private String getLCEnvVar() {
+            if (value != null) {
+                return value;
+            }
+            String val = RContext.getInstance().stateREnvVars.get("LC_" + name());
+            if (val == null) {
+                return defaultValue;
+            } else {
+                return val;
+            }
+        }
+
+        private static int getLCCategory(int category) {
+            return category - 2;
+        }
+    }
+
     @RBuiltin(name = "Sys.getlocale", kind = INTERNAL, parameterNames = {"category"}, behavior = READS_STATE)
     public abstract static class GetLocale extends RBuiltinNode.Arg1 {
 
@@ -59,33 +100,33 @@ public class LocaleFunctions {
             CastsHelper.category(casts);
         }
 
+        private static final int[] ALL_CATEGORIES = new int[]{3, 2, 4, 5, 6, 7, 8, 9};
+
         @Specialization
         @TruffleBoundary
         protected Object getLocale(int category) {
-            // TODO implement all: for now just return not available (NULL)
-            switch (category) {
-                case 3: // "LC_CTYPE",
-                    return RDataFactory.createStringVector(Charset.defaultCharset().name());
-                case 1: // "LC_ALL"
-                    break;
-                case 2: // "LC_COLLATE"
-                    break;
-                case 4: // "LC_MONETARY"
-                    break;
-                case 5: // "LC_NUMERIC"
-                    break;
-                case 6: // "LC_TIME"
-                    break;
-                case 7: // "LC_MESSAGES"
-                    break;
-                case 8: // "LC_PAPER"
-                    return RDataFactory.createStringVectorFromScalar("");
-                case 9: // "LC_MEASUREMENT"
-                    break;
-                default:
-                    throw RInternalError.shouldNotReachHere();
+            return RDataFactory.createStringVector(getLocaleData(category));
+        }
+
+        protected String getLocaleData(int category) {
+            String data = "";
+            if (category == 1) {
+                // "LC_ALL"
+                StringBuilder sb = new StringBuilder();
+                for (int i = 0; i < ALL_CATEGORIES.length; i++) {
+                    String d = getLocaleData(ALL_CATEGORIES[i]);
+                    if (d.length() > 0) {
+                        sb.append(d);
+                        if (i != ALL_CATEGORIES.length - 1) {
+                            sb.append('/');
+                        }
+                    }
+                }
+                data = sb.toString();
+            } else {
+                data = LC.values()[LC.getLCCategory(category)].getLCEnvVar();
             }
-            return RNull.instance;
+            return data;
         }
     }
 
@@ -100,8 +141,8 @@ public class LocaleFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected Object setLocale(@SuppressWarnings("unused") int category, String locale) {
-            // TODO implement properly!!
+        protected Object setLocale(int category, String locale) {
+            LC.values()[LC.getLCCategory(category)].value = locale;
             return locale;
         }
     }
@@ -186,4 +227,8 @@ public class LocaleFunctions {
             casts.arg("category").mustBe(numericValue(), INVALID_ARGUMENT, "category").asIntegerVector().findFirst();
         }
     }
+
+    public static void main(String[] args) {
+        System.out.println(Locale.getDefault());
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
index 9dea6c4d9c..5b78bfd0da 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
@@ -585,12 +585,29 @@ public class RErrorHandling {
         warningCallInvoke(call, RDataFactory.createStringVectorFromScalar(message));
     }
 
+    /**
+     * Entry point for Rf_errorCall from RFFI.
+     */
+    public static void errorcallRFFI(Object call, String message) {
+        errorCallInvoke(call, RDataFactory.createStringVectorFromScalar(message));
+    }
+
+    private static void errorCallInvoke(Object call, RStringVector errorMessage) {
+        errorcallDfltWithCall(null, call, Message.GENERIC, errorMessage, new Object[]{errorMessage});
+    }
+
     static void warningcall(boolean showCall, RBaseNode callObj, Message msg, Object... args) {
         Object call = showCall ? findCaller(callObj) : RNull.instance;
         RStringVector warningMessage = RDataFactory.createStringVectorFromScalar(formatMessage(msg, args));
         warningCallInvoke(call, warningMessage);
     }
 
+    static void errorcall(boolean showCall, RBaseNode callObj, Message msg, Object... args) {
+        Object call = showCall ? findCaller(callObj) : RNull.instance;
+        RStringVector warningMessage = RDataFactory.createStringVectorFromScalar(formatMessage(msg, args));
+        warningCallInvoke(call, warningMessage);
+    }
+
     private static void warningCallInvoke(Object call, RStringVector warningMessage) {
         /*
          * Warnings generally do not prevent results being printed. However, this call into R will
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 8bc62fd9ec..dcb146433d 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
@@ -1847,26 +1847,30 @@ character(0)
 #argv <- structure(list(TZ = 'EST5EDT'), .Names = 'TZ');do.call('Sys.setenv', argv)
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocale1#
-#argv <- list(3L, 'C'); .Internal(Sys.setlocale(argv[[1]], argv[[2]]))
-[1] "C"
+#argv <- list(3L, 'C'); Sys.setlocale(argv[[1]], argv[[2]])
+Error in Sys.setlocale(argv[[1]], argv[[2]]) :
+  invalid 'category' argument
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocale3#
 #argv <- structure(list(category = 'LC_TIME', locale = 'C'), .Names = c('category',     'locale'));do.call('Sys.setlocale', argv)
 [1] "C"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocaleInvalidArgs#Output.IgnoreErrorMessage#
-#.Internal(Sys.setlocale('3L', 'C'))
-Error: invalid 'category' argument
-In addition: Warning message:
-NAs introduced by coercion
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocale3#
+#{ Sys.setenv(LC_CTYPE="en_US.UTF-8"); Sys.getlocale("LC_CTYPE"); }
+[1] "en_US.UTF-8"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocaleInvalidArgs#
+#Sys.setlocale('3L', 'C')
+Error in Sys.setlocale("3L", "C") : invalid 'category' argument
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocaleInvalidArgs#
-#.Internal(Sys.setlocale(4, 42))
-Error: invalid 'locale' argument
+#Sys.setlocale(4, 42)
+Error in Sys.setlocale(4, 42) : invalid 'category' argument
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocaleInvalidArgs#
-#.Internal(Sys.setlocale(4, c('more', 'elements')))
-Error: invalid 'locale' argument
+#Sys.setlocale(4, c('more', 'elements'))
+Error in Sys.setlocale(4, c("more", "elements")) :
+  invalid 'category' argument
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssleep.testSyssleep1#
 #argv <- list(0.5); .Internal(Sys.sleep(argv[[1]]))
@@ -70538,7 +70542,7 @@ tracemem[0x7faf191a98a8 -> 0x7faf191a98e0]:
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.retracemem#Output.ContainsReferences#
 #x<-1:10; retracemem(x, c("first", "second")) 
-tracemem[first -> 0x7fc1dc2ba750]:
+tracemem[first -> 0x7ffe0227b550]:
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.vectors#Output.ContainsReferences#
 #v <- c(1,10,100); tracemem(v); x <- v; y <- v; x[[1]]<-42; untracemem(v); y[[2]] <- 84
@@ -135082,6 +135086,22 @@ In while (c(T, F)) { :
 #if (!any(R.version$engine == "FastR")) { TRUE } else { { x<-rep(1, 100); xi1<-.fastr.identity(x); f<-function(x) { y<-x; y }; f(x); x[1]<-7; xi2<-.fastr.identity(x); xi1 == xi2 } }
 [1] TRUE
 
+##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
+#{ library(grid); 3 * (unit(1, 'mm')); }
+[1] 3*1mm
+
+##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
+#{ library(grid); grid:::unit.list(3 * unit(1, 'mm')); }
+[1] 3*1mm
+
+##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
+#{ library(grid); unit.c(unit(1,'mm'), 42*unit(1,'mm')); }
+[1] 1mm    42*1mm
+
+##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
+#{ library(grid); unit.c(unit(1,'mm'), unit(1,'mm')) }
+[1] 1mm 1mm
+
 ##com.oracle.truffle.r.test.library.methods.TestSubstituteDirect.basicTests#
 #a<-substituteDirect(quote(x+1), NA); a
 Error in substituteDirect(quote(x + 1), NA) :
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java
index b13bdb9886..ea840a2bb0 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java
@@ -19,18 +19,19 @@ public class TestBuiltin_Syssetlocale extends TestBase {
 
     @Test
     public void testSyssetlocale1() {
-        assertEval("argv <- list(3L, 'C'); .Internal(Sys.setlocale(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(3L, 'C'); Sys.setlocale(argv[[1]], argv[[2]])");
     }
 
     @Test
     public void testSyssetlocale3() {
         assertEval("argv <- structure(list(category = 'LC_TIME', locale = 'C'), .Names = c('category',     'locale'));do.call('Sys.setlocale', argv)");
+        assertEval("{ Sys.setenv(LC_CTYPE=\"en_US.UTF-8\"); Sys.getlocale(\"LC_CTYPE\"); }");
     }
 
     @Test
     public void testSyssetlocaleInvalidArgs() {
-        assertEval(".Internal(Sys.setlocale(4, c('more', 'elements')))");
-        assertEval(".Internal(Sys.setlocale(4, 42))");
-        assertEval(Output.IgnoreErrorMessage, ".Internal(Sys.setlocale('3L', 'C'))");
+        assertEval("Sys.setlocale(4, c('more', 'elements'))");
+        assertEval("Sys.setlocale(4, 42)");
+        assertEval("Sys.setlocale('3L', 'C')");
     }
 }
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index efadce495d..1376997ad7 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -313,7 +313,7 @@ def _test_subpackage(name):
     return '.'.join((_test_package(), name))
 
 def _simple_generated_unit_tests():
-    return map(_test_subpackage, ['engine.shell', 'library.base', 'library.fastrGrid', 'library.methods', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'rffi', 'rng', 'runtime.data', 'S4'])
+    return map(_test_subpackage, ['engine.shell', 'library.base', 'library.grid', 'library.fastrGrid', 'library.methods', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'rffi', 'rng', 'runtime.data', 'S4'])
 
 def _simple_unit_tests():
     return _simple_generated_unit_tests() + [_test_subpackage('tck')]
-- 
GitLab