diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
index 70e3f59befe6762be709e18a834ab931dee2261f..905fb5e0d0e90b19380f9fc56fe0ee2f68a8d9fc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java
index 3e159554532b967dda4eecd7b7db016bf5a478ea..d6e7259a25514429a9b088b7ee6f21662c796196 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java
@@ -22,9 +22,12 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
+import java.util.function.Function;
+
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
@@ -39,15 +42,19 @@ import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 /**
  * The {@code} .Internal part of the {@code array} function. The R code may alter the arguments
@@ -73,9 +80,20 @@ public abstract class Array extends RBuiltinNode {
         updateDimNames.executeRAbstractContainer(container, o);
     }
 
+    private String argType(Object arg) {
+        return ((RTypedValue) arg).getRType().getName();
+    }
+
     @Override
     protected void createCasts(CastBuilder casts) {
-        casts.toInteger(1);
+        Function<Object, Object> argType = this::argType;
+        casts.arg("data").mustBe(instanceOf(RAbstractListVector.class).or(numericValue()).or(stringValue()).or(complexValue().or(rawValue())),
+                        RError.SHOW_CALLER, RError.Message.MUST_BE_VECTOR_BUT_WAS, "data",
+                        argType);
+        casts.arg("dim").asIntegerVector().mustBe(notEmpty(), RError.SHOW_CALLER, RError.Message.CANNOT_BE_LENGTH, "dims", 0);
+        casts.arg("dimnames").shouldBe(instanceOf(RList.class).or(nullValue()), RError.SHOW_CALLER,
+                        RError.Message.GENERIC, "non-list dimnames are disregarded; will be an error in R 3.3.0").mapIf(
+                                        instanceOf(RList.class).not(), nullConstant());
     }
 
     private int dimDataHelper(RAbstractIntVector dim, int[] dimData) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
index 472924e29227c82b5cd414f819e16e56996531c7..c4fb5330bdcd0ac41c253c49b64fe851285cf1ac 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
@@ -22,107 +22,48 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*;
 import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
-import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.nodes.unary.CastStringNode;
-import com.oracle.truffle.r.nodes.unary.CastStringNodeGen;
 import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.RSymbol;
-import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "as.character", kind = PRIMITIVE, parameterNames = {"x", "..."}, dispatch = INTERNAL_GENERIC, behavior = PURE)
 public abstract class AsCharacter extends RBuiltinNode {
 
-    @Child private CastStringNode castStringNode;
-
-    public abstract Object execute(Object obj);
-
     public static AsCharacter create() {
         return AsCharacterNodeGen.create(null);
     }
 
-    private void initCast() {
-        if (castStringNode == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            castStringNode = insert(CastStringNodeGen.create(false, false, false, false));
-        }
-    }
-
-    private String castString(int o) {
-        initCast();
-        return (String) castStringNode.executeString(o);
-    }
-
-    private String castString(double o) {
-        initCast();
-        return (String) castStringNode.executeString(o);
-    }
-
-    private String castString(byte o) {
-        initCast();
-        return (String) castStringNode.executeString(o);
-    }
-
-    private RStringVector castStringVector(Object o) {
-        initCast();
-        return (RStringVector) ((RStringVector) castStringNode.executeString(o)).copyDropAttributes();
-    }
-
-    @Specialization
-    protected String doInt(int value) {
-        return castString(value);
-    }
-
-    @Specialization
-    protected String doDouble(double value) {
-        return castString(value);
-    }
-
-    @Specialization
-    protected String doLogical(byte value) {
-        return castString(value);
-    }
-
-    @Specialization
-    protected String doRaw(RRaw value) {
-        initCast();
-        return (String) castStringNode.executeString(value);
+    @Override
+    protected void createCasts(CastBuilder casts) {
+        casts.arg("x").mapIf(instanceOf(RList.class).not(), asStringVector());
     }
 
     @Specialization
-    protected String doString(String value) {
-        return value;
+    protected RAbstractStringVector asCharacter(@SuppressWarnings("unused") RNull n) {
+        return RDataFactory.createEmptyStringVector();
     }
 
     @Specialization
-    protected String doSymbol(RSymbol value) {
-        return value.getName();
+    protected RAbstractStringVector asCharacter(RAbstractStringVector v) {
+        return v;
     }
 
     @Specialization
-    protected RStringVector doNull(@SuppressWarnings("unused") RNull value) {
-        return RDataFactory.createStringVector(0);
-    }
-
-    @Specialization
-    protected RStringVector doStringVector(RStringVector vector) {
-        return RDataFactory.createStringVector(vector.getDataCopy(), vector.isComplete());
-    }
-
-    @Specialization
-    protected RStringVector doList(RList list) {
+    protected RStringVector asCharacter(Object l) {
+        RList list = (RList) l;
         int len = list.getLength();
         boolean complete = RDataFactory.COMPLETE_VECTOR;
         String[] data = new String[len];
@@ -142,8 +83,4 @@ public abstract class AsCharacter extends RBuiltinNode {
         return RDataFactory.createStringVector(data, complete);
     }
 
-    @Specialization(guards = "!isRList(container)")
-    protected RStringVector doVector(RAbstractContainer container) {
-        return castStringVector(container);
-    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
index e651355cac72294ece64a866aab8351da1d9bfcc..77e3ff3f897bc2a370e4ddbfe8e3e31757d91254 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
@@ -50,6 +50,7 @@ import com.oracle.truffle.r.nodes.unary.CastListNode;
 import com.oracle.truffle.r.nodes.unary.CastListNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastLogicalNode;
 import com.oracle.truffle.r.nodes.unary.CastRawNode;
+import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.nodes.unary.CastSymbolNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
@@ -120,8 +121,8 @@ public abstract class AsVector extends RBuiltinNode {
 
         @Specialization(guards = "castToString(mode)")
         protected Object asVectorString(Object x, @SuppressWarnings("unused") String mode, //
-                        @Cached("create()") AsCharacter asCharacter) {
-            return asCharacter.execute(x);
+                        @Cached("createNonPreserving()") CastStringNode cast) {
+            return cast.execute(x);
         }
 
         @Specialization(guards = "castToInt(x, mode)")
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index 38a7bd4917aef4325160db1aa500e089ee3e1b9c..5fac94e66ef29c643cd766fce9b3679d705b430e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -625,8 +625,8 @@ public class BasePackage extends RBuiltinPackage {
         add(Vector.class, VectorNodeGen::create);
         add(Warning.class, WarningNodeGen::create);
         add(WhichFunctions.Which.class, WhichFunctionsFactory.WhichNodeGen::create);
-        add(WhichFunctions.WhichMax.class, WhichFunctionsFactory.WhichMaxNodeGen::create);
-        add(WhichFunctions.WhichMin.class, WhichFunctionsFactory.WhichMinNodeGen::create);
+        add(WhichFunctions.WhichMax.class, WhichFunctions.WhichMax::create);
+        add(WhichFunctions.WhichMin.class, WhichFunctions.WhichMin::create);
         add(Xtfrm.class, XtfrmNodeGen::create);
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
index 812b2b7ebc0eb1ca2fd8f8808434ac585010357c..aa454c0002d8a29000c90055b468fb1ee87c8f77 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
@@ -362,7 +362,7 @@ public abstract class Combine extends RBuiltinNode {
             case LOGICAL_PRECEDENCE:
                 return CastLogicalNodeGen.create(true, false, false);
             case STRING_PRECEDENCE:
-                return CastStringNodeGen.create(false, true, false, false);
+                return CastStringNodeGen.create(true, false, false);
             case RAW_PRECEDENCE:
                 return CastRawNodeGen.create(true, false, false);
             case EXPRESSION_PRECEDENCE:
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java
index 177768859206b1c9efe5fd9e697239ff55fffd5c..bd48e8980243abb1d75214c3cc5b599653657019 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java
@@ -52,7 +52,7 @@ public abstract class Crossprod extends RBuiltinNode {
         return matMult.executeObject(op1, op2);
     }
 
-    private Object transpose(Object value) {
+    private Object transpose(RAbstractVector value) {
         if (transpose == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             transpose = insert(TransposeNodeGen.create(null));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
index 9d902b5d481e52d677b754eee866fc0df6b3bf84..33546b1db6d04b2303b66e91a9fca9b7f9e497f7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
@@ -741,7 +741,7 @@ public class FileFunctions {
         private CastStringNode initCastStringNode() {
             if (castStringNode == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                castStringNode = insert(CastStringNodeGen.create(false, false, false, false));
+                castStringNode = insert(CastStringNodeGen.create(false, false, false));
             }
             return castStringNode;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java
index c929d73972986ea4b0ac31e5336b72524325dac2..fa762a0a2f9e0fa7a67d30cc5a43595aaac4c592 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java
@@ -35,7 +35,7 @@ public abstract class FormatC extends RBuiltinNode {
     private RStringVector castStringVector(Object o) {
         if (castStringNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castStringNode = insert(CastStringNodeGen.create(true, true, true, false));
+            castStringNode = insert(CastStringNodeGen.create(true, true, true));
         }
         return (RStringVector) ((RStringVector) castStringNode.executeString(o)).copyDropAttributes();
     }
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 81d4ba97e495193b6a14d90228fa3747042825ba..19d0acc4b7f43f8d331e226fccf24349f207d157 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
@@ -56,7 +56,6 @@ import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
index cf527e00fb408b7a65f378b1031ff47245ac7122..bbb1f2bc9bffa1cc9b8065a6ac566e44bb48c950 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
@@ -80,7 +80,7 @@ public abstract class Match extends RBuiltinNode {
     private RAbstractStringVector castString(RAbstractVector operand) {
         if (castString == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castString = insert(CastStringNodeGen.create(false, false, false, false));
+            castString = insert(CastStringNodeGen.create(false, false, false));
         }
         return (RAbstractStringVector) castString.execute(operand);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
index 1caab4877cdf457dc6a95aaa1290494718b26f32..2400bc8fe76c7070f0f6fd940073e6772e22f7af 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
@@ -45,7 +45,7 @@ public abstract class NZChar extends RBuiltinNode {
     private String coerceContent(Object content) {
         if (convertString == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            convertString = insert(CastStringNodeGen.create(false, true, false, false));
+            convertString = insert(CastStringNodeGen.create(false, false, false));
         }
         return (String) convertString.execute(content);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java
index 7bac15ba3eaccd6e53b97eb63747a32f459cf338..9c70a9bdcc45b919cfb1bdf2a8e00c786eeaba86 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java
@@ -28,6 +28,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -108,6 +109,11 @@ public class NamespaceFunctions {
 
     @RBuiltin(name = "registerNamespace", kind = INTERNAL, parameterNames = {"name", "env"}, behavior = MODIFIES_STATE)
     public abstract static class RegisterNamespace extends RBuiltinNode {
+        @Override
+        protected void createCasts(CastBuilder casts) {
+            casts.arg("name").asStringVector().findFirst();
+        }
+
         @Specialization
         protected RNull registerNamespace(String name, REnvironment env) {
             if (REnvironment.registerNamespace(name, env) == null) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
index a64a2900dbbed90e93852da8d52b9ade8aaee138..78b39957ba995d6bbf24687ff2a1f96a8f0cb11f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
@@ -118,7 +118,7 @@ public abstract class PMinMax extends RBuiltinNode {
     private CastNode getStringCastNode() {
         if (castString == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castString = insert(CastStringNodeGen.create(true, true, true, false));
+            castString = insert(CastStringNodeGen.create(true, true, true));
         }
         return castString;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
index 4f61514f592b76207e3b56bf3f37b2172a344b72..10550c3ed5be05f2679fb47d7740b92f74fa5c80 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
@@ -113,7 +113,7 @@ public abstract class Parse extends RBuiltinNode {
         if (castStringNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castVectorNode = insert(CastToVectorNodeGen.create(false));
-            castStringNode = insert(CastStringNodeGen.create(false, false, false, false));
+            castStringNode = insert(CastStringNodeGen.create(false, false, false));
         }
         return (RStringVector) castStringNode.executeString(castVectorNode.execute(s));
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
index 2cb7f66bef9630cdd904f654fde6b68595e6cdfa..699b9fe4219a49ab2dd8e3b8977e5dacf4125e7f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
@@ -40,9 +40,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RSequence;
 import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "paste", kind = INTERNAL, parameterNames = {"", "sep", "collapse"}, behavior = PURE)
@@ -59,24 +57,10 @@ public abstract class Paste extends RBuiltinNode {
     @Child private CastStringNode castCharacterNode;
 
     private final ValueProfile lengthProfile = PrimitiveValueProfile.createEqualityProfile();
-    private final ConditionProfile vectorOrSequence = ConditionProfile.createBinaryProfile();
     private final ConditionProfile reusedResultProfile = ConditionProfile.createBinaryProfile();
     private final BranchProfile nonNullElementsProfile = BranchProfile.create();
     private final BranchProfile onlyNullElementsProfile = BranchProfile.create();
 
-    private RStringVector castCharacter(Object o) {
-        if (asCharacterNode == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            asCharacterNode = insert(AsCharacterNodeGen.create(null));
-        }
-        Object ret = asCharacterNode.execute(o);
-        if (ret instanceof String) {
-            return RDataFactory.createStringVector((String) ret);
-        } else {
-            return (RStringVector) ret;
-        }
-    }
-
     /**
      * FIXME The exact semantics needs checking regarding the use of {@code as.character}. Currently
      * there are problem using it here, so we retain the previous implementation that just uses
@@ -85,11 +69,13 @@ public abstract class Paste extends RBuiltinNode {
     private RStringVector castCharacterVector(Object o) {
         if (castCharacterNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castCharacterNode = insert(CastStringNodeGen.create(false, true, false, false));
+            castCharacterNode = insert(CastStringNodeGen.create(false, false, false));
         }
         Object ret = castCharacterNode.executeString(o);
         if (ret instanceof String) {
             return RDataFactory.createStringVector((String) ret);
+        } else if (ret == RNull.instance) {
+            return RDataFactory.createEmptyStringVector();
         } else {
             return (RStringVector) ret;
         }
@@ -142,12 +128,7 @@ public abstract class Paste extends RBuiltinNode {
         int maxLength = 1;
         for (int i = 0; i < length; i++) {
             Object element = values.getDataAt(i);
-            String[] array;
-            if (vectorOrSequence.profile(element instanceof RVector || element instanceof RSequence)) {
-                array = castCharacterVector(element).getDataWithoutCopying();
-            } else {
-                array = castCharacter(element).getDataWithoutCopying();
-            }
+            String[] array = castCharacterVector(element).getDataWithoutCopying();
             maxLength = Math.max(maxLength, array.length);
             converted[i] = array.length == 0 ? ONE_EMPTY_STRING : array;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java
index db9729cdf6736b4720305df90f902393d8cb17e4..fdcad6132cc24b5119b071873ca097ca83765435 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java
@@ -22,14 +22,19 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+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.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
-import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 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;
@@ -37,24 +42,34 @@ import com.oracle.truffle.r.runtime.data.RFunction;
 
 @RBuiltin(name = ".Primitive", kind = PRIMITIVE, parameterNames = "name", behavior = PURE)
 public abstract class Primitive extends RBuiltinNode {
+
     private final BranchProfile errorProfile = BranchProfile.create();
 
-    // TODO: implement inline caching
+    @Override
+    protected void createCasts(CastBuilder casts) {
+        casts.arg("name").defaultError(Message.STRING_ARGUMENT_REQUIRED).mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
+    }
+
+    @Specialization(guards = "name == cachedName")
+    protected RFunction primitiveCached(@SuppressWarnings("unused") String name,
+                    @Cached("name") @SuppressWarnings("unused") String cachedName,
+                    @Cached("lookup(name)") RFunction function) {
+        return function;
+    }
 
-    @Specialization
+    @Specialization(contains = "primitiveCached")
     protected RFunction primitive(String name) {
+        RFunction function = lookup(name);
+        return function;
+    }
+
+    @TruffleBoundary
+    protected RFunction lookup(String name) {
         RFunction function = RContext.lookupBuiltin(name);
         if (function == null || function.getRBuiltin() != null && function.getRBuiltin().getKind() != RBuiltinKind.PRIMITIVE) {
             errorProfile.enter();
             throw RError.error(this, RError.Message.NO_SUCH_PRIMITIVE, name);
         }
-
-        // .Primitive function is validated
         return function;
     }
-
-    @Fallback
-    protected RFunction primitive(@SuppressWarnings("unused") Object name) {
-        throw RError.error(this, RError.Message.STRING_ARGUMENT_REQUIRED);
-    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
index 304af5f57e8333b6ea11b5a962f98d9607d0ca77..049375ae56f6834addf7f3827751016107526c6f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
@@ -12,7 +12,16 @@
 
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.charAt0;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.length;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lengthLte;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lt;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+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;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
@@ -30,7 +39,6 @@ import com.oracle.truffle.r.nodes.unary.CastToVectorNodeGen;
 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.RBehavior;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.conn.StdConnections;
@@ -45,14 +53,11 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RString;
 import com.oracle.truffle.r.runtime.data.RVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
-import com.sun.org.apache.bcel.internal.generic.INSTANCEOF;
 
-@SuppressWarnings("unused")
 @RBuiltin(name = "scan", kind = INTERNAL, parameterNames = {"file", "what", "nmax", "sep", "dec", "quote", "skip", "nlines", "na.strings", "flush", "fill", "strip.white", "quiet", "blank.lines.skip",
                 "multi.line", "comment.char", "allowEscapes", "encoding", "skipNull"}, behavior = IO)
 public abstract class Scan extends RBuiltinNode {
@@ -74,6 +79,7 @@ public abstract class Scan extends RBuiltinNode {
         return ((RAbstractVector) castVector.execute(value)).materialize();
     }
 
+    @SuppressWarnings("unused")
     private static class LocalData {
         RAbstractStringVector naStrings = null;
         boolean quiet = false;
@@ -181,7 +187,6 @@ public abstract class Scan extends RBuiltinNode {
         // TODO: quite a few more things happen in GNU R around connections
         data.con = file;
 
-        Object result = RNull.instance;
         data.save = 0;
 
         try (RConnection openConn = data.con.forceOpen("r")) {
@@ -199,14 +204,6 @@ public abstract class Scan extends RBuiltinNode {
         }
     }
 
-    private static int firstElementOrNA(RAbstractIntVector nmaxVec) {
-        return nmaxVec.getLength() == 0 ? RRuntime.INT_NA : nmaxVec.getDataAt(0);
-    }
-
-    private static byte firstElementOrNA(RAbstractLogicalVector flushVec) {
-        return flushVec.getLength() == 0 ? RRuntime.LOGICAL_NA : flushVec.getDataAt(0);
-    }
-
     private static int getFirstQuoteInd(String str, char sepChar) {
         int quoteInd = str.indexOf(sepChar);
         if (quoteInd >= 0) {
@@ -320,7 +317,8 @@ public abstract class Scan extends RBuiltinNode {
         }
     }
 
-    private RVector scanFrame(RList what, int maxRecords, int maxLines, boolean flush, boolean fill, boolean stripWhite, boolean blSkip, boolean multiLine, LocalData data) throws IOException {
+    private RVector scanFrame(RList what, int maxRecords, int maxLines, boolean flush, boolean fill, @SuppressWarnings("unused") boolean stripWhite, boolean blSkip, boolean multiLine, LocalData data)
+                    throws IOException {
 
         int nc = what.getLength();
         if (nc == 0) {
@@ -442,7 +440,8 @@ public abstract class Scan extends RBuiltinNode {
     }
 
     @TruffleBoundary
-    private RVector scanVector(RAbstractVector what, int maxItems, int maxLines, boolean flush, boolean stripWhite, boolean blSkip, LocalData data) throws IOException {
+    private RVector scanVector(RAbstractVector what, int maxItems, int maxLines, @SuppressWarnings("unused") boolean flush, @SuppressWarnings("unused") boolean stripWhite, boolean blSkip,
+                    LocalData data) throws IOException {
         int blockSize = maxItems > 0 ? maxItems : SCAN_BLOCKSIZE;
         RVector vec = what.createEmptySameType(blockSize, RDataFactory.COMPLETE_VECTOR);
         naCheck.enable(true);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
index c1a394c20d9e60501af8df2d9a4d7e1e24272140..e9088eeb636daa0ba882e7913ceef4134f86132b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
@@ -13,88 +13,86 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
-import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.SUBSTITUTE;
+import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.profiles.LoopConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNodeGen;
 import com.oracle.truffle.r.nodes.attributes.InitAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.PutAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.PutAttributeNodeGen;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
+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.data.RAttributeProfiles;
+import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
-import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 
-@RBuiltin(name = "t.default", kind = SUBSTITUTE, parameterNames = {"x"}, behavior = PURE)
-// TODO INTERNAL
+@RBuiltin(name = "t.default", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
 public abstract class Transpose extends RBuiltinNode {
 
     private final RAttributeProfiles attrProfiles = RAttributeProfiles.create();
     private final BranchProfile hasDimNamesProfile = BranchProfile.create();
     private final ConditionProfile isMatrixProfile = ConditionProfile.createBinaryProfile();
 
+    private final VectorLengthProfile lengthProfile = VectorLengthProfile.create();
+    private final LoopConditionProfile loopProfile = LoopConditionProfile.createCountingProfile();
+
     @Child private CopyOfRegAttributesNode copyRegAttributes = CopyOfRegAttributesNodeGen.create();
     @Child private InitAttributesNode initAttributes = InitAttributesNode.create();
     @Child private PutAttributeNode putDimensions = PutAttributeNodeGen.createDim();
     @Child private PutAttributeNode putDimNames = PutAttributeNodeGen.createDimNames();
 
-    public abstract Object execute(Object o);
-
-    @Specialization
-    protected RNull transpose(RNull value) {
-        return value;
-    }
-
-    @Specialization
-    protected int transpose(int value) {
-        return value;
-    }
-
-    @Specialization
-    protected double transpose(double value) {
-        return value;
-    }
-
-    @Specialization
-    protected byte transpose(byte value) {
-        return value;
-    }
-
-    @Specialization(guards = "isEmpty2D(vector)")
-    protected RAbstractVector transpose(RAbstractVector vector) {
-        int[] dim = vector.getDimensions();
-        return vector.copyWithNewDimensions(new int[]{dim[1], dim[0]});
-    }
+    public abstract Object execute(RAbstractVector o);
 
     @FunctionalInterface
-    private interface InnerLoop<T extends RAbstractVector> {
-        RVector apply(T vector, int firstDim);
+    private interface WriteArray<T extends RAbstractVector, A> {
+        void apply(A array, T vector, int i, int j);
     }
 
-    protected <T extends RAbstractVector> RVector transposeInternal(T vector, InnerLoop<T> innerLoop) {
+    protected <T extends RAbstractVector, A> RVector transposeInternal(T vector, Function<Integer, A> createArray, WriteArray<T, A> writeArray, BiFunction<A, Boolean, RVector> createResult) {
+        int length = lengthProfile.profile(vector.getLength());
         int firstDim;
         int secondDim;
         if (isMatrixProfile.profile(vector.isMatrix())) {
             firstDim = vector.getDimensions()[0];
             secondDim = vector.getDimensions()[1];
         } else {
-            firstDim = vector.getLength();
+            firstDim = length;
             secondDim = 1;
         }
-        RNode.reportWork(this, vector.getLength());
+        RNode.reportWork(this, length);
 
-        RVector r = innerLoop.apply(vector, firstDim);
+        A array = createArray.apply(length);
+        int j = 0;
+        loopProfile.profileCounted(length);
+        for (int i = 0; loopProfile.inject(i < length); i++, j += firstDim) {
+            if (j > (length - 1)) {
+                j -= (length - 1);
+            }
+            writeArray.apply(array, vector, i, j);
+        }
+        RVector r = createResult.apply(array, vector.isComplete());
         // copy attributes
         copyRegAttributes.execute(vector, r);
         // set new dimensions
@@ -113,61 +111,47 @@ public abstract class Transpose extends RBuiltinNode {
         return r;
     }
 
-    private static RVector innerLoopInt(RAbstractIntVector vector, int firstDim) {
-        int[] result = new int[vector.getLength()];
-        int j = 0;
-        for (int i = 0; i < result.length; i++, j += firstDim) {
-            if (j > (result.length - 1)) {
-                j -= (result.length - 1);
-            }
-            result[i] = vector.getDataAt(j);
-        }
-        return RDataFactory.createIntVector(result, vector.isComplete());
+    @Specialization
+    protected RVector transpose(RAbstractIntVector x) {
+        return transposeInternal(x, l -> new int[l], (a, v, i, j) -> a[i] = v.getDataAt(j), RDataFactory::createIntVector);
     }
 
-    private static RVector innerLoopDouble(RAbstractDoubleVector vector, int firstDim) {
-        double[] result = new double[vector.getLength()];
-        int j = 0;
-        for (int i = 0; i < result.length; i++, j += firstDim) {
-            if (j > (result.length - 1)) {
-                j -= (result.length - 1);
-            }
-            result[i] = vector.getDataAt(j);
-        }
-        return RDataFactory.createDoubleVector(result, vector.isComplete());
+    @Specialization
+    protected RVector transpose(RAbstractLogicalVector x) {
+        return transposeInternal(x, l -> new byte[l], (a, v, i, j) -> a[i] = v.getDataAt(j), RDataFactory::createLogicalVector);
     }
 
-    private static RVector innerLoopString(RAbstractStringVector vector, int firstDim) {
-        String[] result = new String[vector.getLength()];
-        int j = 0;
-        for (int i = 0; i < result.length; i++, j += firstDim) {
-            if (j > (result.length - 1)) {
-                j -= (result.length - 1);
-            }
-            result[i] = vector.getDataAt(j);
-        }
-        return RDataFactory.createStringVector(result, vector.isComplete());
+    @Specialization
+    protected RVector transpose(RAbstractDoubleVector x) {
+        return transposeInternal(x, l -> new double[l], (a, v, i, j) -> a[i] = v.getDataAt(j), RDataFactory::createDoubleVector);
     }
 
-    @Specialization(guards = "!isEmpty2D(vector)")
-    protected RVector transpose(RAbstractIntVector vector) {
-        return transposeInternal(vector, Transpose::innerLoopInt);
+    @Specialization
+    protected RVector transpose(RAbstractComplexVector x) {
+        return transposeInternal(x, l -> new double[l * 2], (a, v, i, j) -> {
+            RComplex d = v.getDataAt(j);
+            a[i * 2] = d.getRealPart();
+            a[i * 2 + 1] = d.getImaginaryPart();
+        }, RDataFactory::createComplexVector);
     }
 
-    @Specialization(guards = "!isEmpty2D(vector)")
-    protected RVector transpose(RAbstractDoubleVector vector) {
-        return transposeInternal(vector, Transpose::innerLoopDouble);
+    @Specialization
+    protected RVector transpose(RAbstractStringVector x) {
+        return transposeInternal(x, l -> new String[l], (a, v, i, j) -> a[i] = v.getDataAt(j), RDataFactory::createStringVector);
     }
 
-    @Specialization(guards = "!isEmpty2D(vector)")
-    protected RVector transpose(RAbstractStringVector vector) {
-        return transposeInternal(vector, Transpose::innerLoopString);
+    @Specialization
+    protected RVector transpose(RAbstractListVector x) {
+        return transposeInternal(x, l -> new Object[l], (a, v, i, j) -> a[i] = v.getDataAt(j), (a, c) -> RDataFactory.createList(a));
     }
 
-    protected static boolean isEmpty2D(RAbstractVector vector) {
-        if (!vector.hasDimensions()) {
-            return false;
-        }
-        return vector.getDimensions().length == 2 && vector.getLength() == 0;
+    @Specialization
+    protected RVector transpose(RAbstractRawVector x) {
+        return transposeInternal(x, l -> new byte[l], (a, v, i, j) -> a[i] = v.getRawDataAt(j), (a, c) -> RDataFactory.createRawVector(a));
+    }
+
+    @Fallback
+    protected RVector transpose(@SuppressWarnings("unused") Object x) {
+        throw RError.error(RError.SHOW_CALLER, Message.ARGUMENT_NOT_MATRIX);
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
index 49b6186f09b7f8ab61fbc1868916c3f2d2efe425..6c526dfbe848ae3c3c51154e9537e514280c4c98 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
@@ -63,20 +63,20 @@ public abstract class UpdateAttributes extends RBuiltinNode {
     // it's OK for the following two methods to update attributes in-place as the container has been
     // already materialized to non-shared
 
-    private void updateNames(RAbstractContainer container, Object o) {
+    private RAbstractContainer updateNames(RAbstractContainer container, Object o) {
         if (updateNames == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             updateNames = insert(UpdateNamesNodeGen.create(null));
         }
-        updateNames.executeStringVector(container, o);
+        return (RAbstractContainer) updateNames.executeStringVector(container, o);
     }
 
-    private void updateDimNames(RAbstractContainer container, Object o) {
+    private RAbstractContainer updateDimNames(RAbstractContainer container, Object o) {
         if (updateDimNames == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             updateDimNames = insert(UpdateDimNamesNodeGen.create(null));
         }
-        updateDimNames.executeRAbstractContainer(container, o);
+        return updateDimNames.executeRAbstractContainer(container, o);
     }
 
     private RAbstractIntVector castInteger(RAbstractVector vector) {
@@ -176,9 +176,9 @@ public abstract class UpdateAttributes extends RBuiltinNode {
             if (attrName.equals(RRuntime.DIM_ATTR_KEY)) {
                 continue;
             } else if (attrName.equals(RRuntime.NAMES_ATTR_KEY)) {
-                updateNames(res, value);
+                res = updateNames(res, value);
             } else if (attrName.equals(RRuntime.DIMNAMES_ATTR_KEY)) {
-                updateDimNames(res, value);
+                res = updateDimNames(res, value);
             } else if (attrName.equals(RRuntime.CLASS_ATTR_KEY)) {
                 if (value == RNull.instance) {
                     res = (RAbstractContainer) result.setClassAttr(null);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
index 25207ed80eabb2649f34aff15ec6b84215f3dc85..bba597a2585760808ef85fadaae692cb3156482f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
@@ -67,7 +67,7 @@ public abstract class UpdateClass extends RBuiltinNode {
     private void initCastStringNode() {
         if (castStringNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castStringNode = insert(CastStringNodeGen.create(false, false, false, false));
+            castStringNode = insert(CastStringNodeGen.create(false, false, false));
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
index 8bcaa7f8a2d2eef9878df405320ca0610db4bf39..9b49702aa2fcc30d926f3fde4b21f6213c0cc8ba 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
@@ -61,7 +61,7 @@ public abstract class UpdateDimNames extends RBuiltinNode {
     private Object castString(Object o) {
         if (castStringNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castStringNode = insert(CastStringNodeGen.create(true, true, false, false));
+            castStringNode = insert(CastStringNodeGen.create(true, true, true));
         }
         return castStringNode.execute(o);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
index f19d251da239e99870eb9e1bef37b34bbfc0a428..fd9b979a7964a6a0b0532c753bfff0a6e8d5c3f4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
@@ -48,7 +48,7 @@ public abstract class UpdateNames extends RBuiltinNode {
     private Object castString(Object o) {
         if (castStringNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castStringNode = insert(CastStringNodeGen.create(false, true, false, false));
+            castStringNode = insert(CastStringNodeGen.create(false, false, false));
         }
         return castStringNode.executeString(o);
     }
@@ -76,9 +76,13 @@ public abstract class UpdateNames extends RBuiltinNode {
             stringVector = (RStringVector) stringVector.copyResized(result.getLength(), true);
         } else if (stringVector.getLength() > result.getLength()) {
             throw RError.error(this, Message.NAMES_LONGER, stringVector.getLength(), result.getLength());
-        } else if (stringVector == container) {
+        } else if (stringVector == names) {
             stringVector = (RStringVector) stringVector.copy();
         }
+        if (stringVector.isTemporary()) {
+            stringVector.incRefCount();
+
+        }
         result.setNames(stringVector);
         return result;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
index 963fb48e49d9bc006ffb8007ca700d4a03560932..f05261a585f42113af69f41576f5a2897eddc6df 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
@@ -59,7 +59,7 @@ public abstract class UpdateOldClass extends RBuiltinNode {
     private void initCastStringNode() {
         if (castStringNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castStringNode = insert(CastStringNodeGen.create(false, false, false, false));
+            castStringNode = insert(CastStringNodeGen.create(false, false, false));
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
index 2ca786f9606fe2ece085ae40a0f5552564e46999..b878565580cb566b94d9b2728004d11527840110 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
@@ -126,7 +126,7 @@ public abstract class VApply extends RBuiltinNode {
     private Object castString(Object operand, boolean preserveAllAttr) {
         if (castString == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castString = insert(CastStringNodeGen.create(false, true, preserveAllAttr, preserveAllAttr));
+            castString = insert(CastStringNodeGen.create(true, preserveAllAttr, preserveAllAttr));
         }
         return castString.execute(operand);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Warning.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Warning.java
index c507722d2142f8f4c7f7af14015a6fff56d4c620..6ee52996d3b615a84c3bc978430ab84f9962f23d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Warning.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Warning.java
@@ -47,7 +47,7 @@ public abstract class Warning extends RBuiltinNode {
     private Object castString(Object operand) {
         if (castString == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castString = insert(CastStringNodeGen.create(false, true, false, false));
+            castString = insert(CastStringNodeGen.create(false, false, false));
         }
         return castString.execute(operand);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java
index ffa0cc5c29b71e409b06dadc9080542cfd02c7cb..17662ce966d830026fbd35be2cfbb5ba69a8f6b2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java
@@ -22,23 +22,28 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
-import java.util.ArrayList;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.profiles.LoopConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.base.WhichFunctionsFactory.WhichMinMaxNodeGen;
+import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RAttributeProfiles;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 /**
@@ -49,94 +54,125 @@ public class WhichFunctions {
     @RBuiltin(name = "which", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
     public abstract static class Which extends RBuiltinNode {
 
-        private final NACheck naCheck = NACheck.create();
-        private final RAttributeProfiles attrProfiles = RAttributeProfiles.create();
+        @Override
+        protected void createCasts(CastBuilder casts) {
+            casts.arg("x").mustBe(logicalValue()).asLogicalVector();
+        }
 
-        @Specialization(guards = "!hasNames(x)")
-        @TruffleBoundary
-        protected RIntVector which(RAbstractLogicalVector x) {
-            ArrayList<Integer> w = new ArrayList<>();
-            for (int i = 0; i < x.getLength(); i++) {
+        @Specialization
+        protected RIntVector which(RAbstractLogicalVector x,
+                        @Cached("create()") VectorLengthProfile lengthProfile,
+                        @Cached("createCountingProfile()") LoopConditionProfile loopProfile,
+                        @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile,
+                        @Cached("create()") RAttributeProfiles attrProfiles,
+                        @Cached("create()") NACheck naCheck) {
+            int length = lengthProfile.profile(x.getLength());
+            loopProfile.profileCounted(length);
+            // determine the length of the result
+            int resultLength = 0;
+            for (int i = 0; loopProfile.inject(i < length); i++) {
                 if (x.getDataAt(i) == RRuntime.LOGICAL_TRUE) {
-                    w.add(i);
+                    resultLength++;
                 }
             }
-            int[] result = new int[w.size()];
-            for (int i = 0; i < result.length; i++) {
-                result[i] = w.get(i) + 1;
-            }
-            return RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR);
-        }
-
-        @Specialization(guards = "hasNames(x)")
-        @TruffleBoundary
-        protected RIntVector whichNames(RAbstractLogicalVector x) {
-            ArrayList<Integer> w = new ArrayList<>();
-            ArrayList<String> n = new ArrayList<>();
-            RStringVector oldNames = x.getNames(attrProfiles);
-            naCheck.enable(oldNames);
-            for (int i = 0; i < x.getLength(); i++) {
+            // collect result indexes
+            int[] result = new int[resultLength];
+            int pos = 0;
+            for (int i = 0; loopProfile.inject(i < length); i++) {
                 if (x.getDataAt(i) == RRuntime.LOGICAL_TRUE) {
-                    w.add(i);
-                    String s = oldNames.getDataAt(i);
-                    naCheck.check(s);
-                    n.add(s);
+                    result[pos++] = i + 1;
                 }
             }
-            int[] result = new int[w.size()];
-            for (int i = 0; i < result.length; i++) {
-                result[i] = w.get(i) + 1;
+            RStringVector names = x.getNames(attrProfiles);
+            if (hasNamesProfile.profile(names != null)) {
+                // collect result names
+                String[] resultNames = new String[resultLength];
+                naCheck.enable(names);
+                pos = 0;
+                for (int i = 0; i < x.getLength(); i++) {
+                    if (x.getDataAt(i) == RRuntime.LOGICAL_TRUE) {
+                        String name = names.getDataAt(i);
+                        naCheck.check(name);
+                        resultNames[pos++] = name;
+                    }
+                }
+                return RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR, RDataFactory.createStringVector(resultNames, naCheck.neverSeenNA()));
+            } else {
+                return RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR);
             }
-            String[] names = new String[n.size()];
-            return RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR, RDataFactory.createStringVector(n.toArray(names), naCheck.neverSeenNA()));
-        }
-
-        protected boolean hasNames(RAbstractLogicalVector x) {
-            return x.getNames(attrProfiles) != null;
         }
     }
 
     @RBuiltin(name = "which.max", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
-    public abstract static class WhichMax extends RBuiltinNode {
-
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            casts.toDouble(0);
+    public abstract static class WhichMax {
+        private WhichMax() {
+            // private
         }
 
-        @Specialization
-        protected int which(RAbstractDoubleVector x) {
-            double max = x.getDataAt(0);
-            int maxIndex = 0;
-            for (int i = 0; i < x.getLength(); i++) {
-                if (x.getDataAt(i) > max) {
-                    max = x.getDataAt(i);
-                    maxIndex = i;
-                }
-            }
-            return maxIndex + 1;
+        public static WhichMinMax create(RNode[] arguments) {
+            return WhichMinMaxNodeGen.create(true, arguments);
         }
     }
 
     @RBuiltin(name = "which.min", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
-    public abstract static class WhichMin extends RBuiltinNode {
+    public abstract static class WhichMin {
+        private WhichMin() {
+            // private
+        }
+
+        public static WhichMinMax create(RNode[] arguments) {
+            return WhichMinMaxNodeGen.create(false, arguments);
+        }
+    }
+
+    public abstract static class WhichMinMax extends RBuiltinNode {
+
+        private final boolean isMax;
+
+        protected WhichMinMax(boolean isMax) {
+            this.isMax = isMax;
+        }
 
         @Override
         protected void createCasts(CastBuilder casts) {
-            casts.toDouble(0);
+            casts.arg(0, "x").asDoubleVector(true, false, false);
         }
 
         @Specialization
-        protected int which(RAbstractDoubleVector x) {
-            double minimum = x.getDataAt(0);
-            int minIndex = 0;
-            for (int i = 0; i < x.getLength(); i++) {
-                if (x.getDataAt(i) < minimum) {
-                    minimum = x.getDataAt(i);
-                    minIndex = i;
+        protected RIntVector which(RAbstractDoubleVector x,
+                        @Cached("create()") VectorLengthProfile lengthProfile,
+                        @Cached("createCountingProfile()") LoopConditionProfile loopProfile,
+                        @Cached("createBinaryProfile()") ConditionProfile isNaNProfile,
+                        @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile,
+                        @Cached("create()") RAttributeProfiles attrProfiles) {
+            int length = lengthProfile.profile(x.getLength());
+            loopProfile.profileCounted(length);
+            double extreme = Double.NaN;
+            int extremeIndex = -1;
+            for (int i = 0; loopProfile.inject(i < length); i++) {
+                double d = x.getDataAt(i);
+                // inverted comparison to pass when extreme is NaN
+                if (!Double.isNaN(d) && (isMax ? !(d <= extreme) : !(d >= extreme))) {
+                    extreme = x.getDataAt(i);
+                    extremeIndex = i;
                 }
             }
-            return minIndex + 1;
+            if (isNaNProfile.profile(extremeIndex == -1)) {
+                return RDataFactory.createEmptyIntVector();
+            }
+            RStringVector names = x.getNames(attrProfiles);
+            if (hasNamesProfile.profile(names != null)) {
+                // collect result names
+                RStringVector resultNames = RDataFactory.createStringVectorFromScalar(names.getDataAt(extremeIndex));
+                return RDataFactory.createIntVector(new int[]{extremeIndex + 1}, true, resultNames);
+            } else {
+                return RDataFactory.createIntVectorFromScalar(extremeIndex + 1);
+            }
+        }
+
+        @Specialization
+        protected RIntVector which(@SuppressWarnings("unused") RNull x) {
+            return RDataFactory.createEmptyIntVector();
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java
index 457b1c404ba589315ba895b2bb3173381b463041..b75899478f34a0c3723eae0c6498afa13336a72e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java
@@ -157,9 +157,9 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> {
         /*
          * F Format: use "F" format WHENEVER we use not more space than 'E' and still satisfy
          * 'R_print.digits' {but as if nsmall==0 !}
-         * 
+         *
          * E Format has the form [S]X[.XXX]E+XX[X]
-         * 
+         *
          * This is indicated by setting *e to non-zero (usually 1) If the additional exponent digit
          * is required *e is set to 2
          */
@@ -247,7 +247,7 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> {
          * for a number x , determine sgn = 1_{x < 0} {0/1} kpower = Exponent of 10; nsig =
          * min(R_print.digits, #{significant digits of alpha}) roundingwidens = 1 if rounding causes
          * x to increase in width, 0 otherwise
-         * 
+         *
          * where |x| = alpha * 10^kpower and 1 <= alpha < 10
          */
         double alpha;
@@ -382,8 +382,7 @@ final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVector> {
                 buff = snprintf(NB, fmt, x);
             }
         } else { /* e = 0 */
-            StringBuilder sb = new StringBuilder("#.#");
-            DecimalFormat df = new DecimalFormat(sb.toString());
+            DecimalFormat df = new DecimalFormat("#.#");
             df.setRoundingMode(RoundingMode.HALF_EVEN);
             df.setDecimalSeparatorAlwaysShown(false);
             df.setMinimumFractionDigits(d);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
index 1dda3508749ac98bfd666025679dccd78199226e..550f3efb3191bf745599764bd3fc6b9f598b0d80 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.r.nodes.builtin.fastr;
 
+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.runtime.RVisibility.OFF;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
@@ -33,6 +35,7 @@ import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.DirectCallNode;
@@ -41,10 +44,10 @@ import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 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.RRuntime;
 import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 
@@ -55,8 +58,8 @@ public class FastRInterop {
 
         @Override
         protected void createCasts(CastBuilder casts) {
-            casts.firstStringWithError(0, Message.INVALID_ARGUMENT, "mimeType");
-            casts.firstStringWithError(1, Message.INVALID_ARGUMENT, "source");
+            casts.arg("mimeType").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
+            casts.arg("source").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
         }
 
         protected CallTarget parse(String mimeType, String source) {
@@ -77,9 +80,9 @@ public class FastRInterop {
 
         @SuppressWarnings("unused")
         @Specialization(guards = {"cachedMimeType != null", "cachedMimeType.equals(mimeType)", "cachedSource != null", "cachedSource.equals(source)"})
-        protected Object evalCached(VirtualFrame frame, String mimeType, String source, //
-                        @Cached("mimeType") String cachedMimeType, //
-                        @Cached("source") String cachedSource, //
+        protected Object evalCached(VirtualFrame frame, String mimeType, String source,
+                        @Cached("mimeType") String cachedMimeType,
+                        @Cached("source") String cachedSource,
                         @Cached("createCall(mimeType, source)") DirectCallNode call) {
             return call.call(frame, EMPTY_OBJECT_ARRAY);
         }
@@ -98,31 +101,49 @@ public class FastRInterop {
     @RBuiltin(name = ".fastr.interop.export", visibility = OFF, kind = PRIMITIVE, parameterNames = {"name", "value"}, behavior = COMPLEX)
     public abstract static class Export extends RBuiltinNode {
 
-        @Specialization
+        @Override
+        protected void createCasts(CastBuilder casts) {
+            casts.arg("name").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
+            casts.boxPrimitive(1);
+        }
+
+        @Specialization(guards = "!isRMissing(value)")
         @TruffleBoundary
-        protected Object exportSymbol(Object name, RTypedValue value) {
-            String stringName = RRuntime.asString(name);
-            if (stringName == null) {
+        protected Object exportSymbol(String name, RTypedValue value) {
+            if (name == null) {
                 throw RError.error(this, RError.Message.INVALID_ARG_TYPE, "name");
             }
-            RContext.getInstance().getExportedSymbols().put(stringName, value);
+            RContext.getInstance().getExportedSymbols().put(name, value);
             return RNull.instance;
         }
+
+        @Specialization
+        @TruffleBoundary
+        protected Object exportSymbol(@SuppressWarnings("unused") String name, @SuppressWarnings("unused") RMissing value) {
+            throw RError.error(this, Message.ARGUMENT_MISSING, "value");
+        }
+
+        @Fallback
+        @TruffleBoundary
+        protected Object exportSymbol(@SuppressWarnings("unused") Object name, @SuppressWarnings("unused") Object value) {
+            throw RError.error(this, Message.GENERIC, "only R language objects can be exported");
+        }
     }
 
     @RBuiltin(name = ".fastr.interop.import", visibility = OFF, kind = PRIMITIVE, parameterNames = {"name"}, behavior = COMPLEX)
     public abstract static class Import extends RBuiltinNode {
 
+        @Override
+        protected void createCasts(CastBuilder casts) {
+            casts.arg("name").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
+        }
+
         @Specialization
         @TruffleBoundary
-        protected Object importSymbol(Object name) {
-            String stringName = RRuntime.asString(name);
-            if (stringName == null) {
-                throw RError.error(this, RError.Message.INVALID_ARG_TYPE, "name");
-            }
-            Object object = RContext.getInstance().getEnv().importSymbol(stringName);
+        protected Object importSymbol(String name) {
+            Object object = RContext.getInstance().getEnv().importSymbol(name);
             if (object == null) {
-                throw RError.error(this, RError.Message.NO_IMPORT_OBJECT, stringName);
+                throw RError.error(this, RError.Message.NO_IMPORT_OBJECT, name);
             }
             return object;
         }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
index a7835b6c048720307b08440201cdf3df53c1bcc9..681a49131af2005f5d4f01561a6c8388dd4fad56 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
@@ -22,14 +22,14 @@
  */
 package com.oracle.truffle.r.nodes.builtin;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.elementAt;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asStringVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asLogicalVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asStringVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.defaultValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.elementAt;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.equalTo;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte;
@@ -69,8 +69,6 @@ import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen;
 import com.oracle.truffle.r.nodes.builtin.ArgumentFilter.ArgumentTypeFilter;
 import com.oracle.truffle.r.nodes.builtin.ArgumentFilter.ArgumentValueFilter;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.InitialPhaseBuilder;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
-import com.oracle.truffle.r.nodes.builtin.base.IsNA;
 import com.oracle.truffle.r.nodes.casts.ArgumentFilterSampler;
 import com.oracle.truffle.r.nodes.casts.CastNodeSampler;
 import com.oracle.truffle.r.nodes.casts.PredefFiltersSamplers;
@@ -85,7 +83,6 @@ import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RInteger;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RLogical;
@@ -634,7 +631,7 @@ public class CastBuilderTest {
         }
     }
 
-    private String argType(Object arg) {
+    private static String argType(Object arg) {
         return arg.getClass().getSimpleName();
     }
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastNodeSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastNodeSampler.java
index f90d1ec73c701252e434c56b4e9a4e3e4b6703dd..0e64e2c2cd775661cf03bad5498dce8dcaecad4a 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastNodeSampler.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastNodeSampler.java
@@ -23,11 +23,6 @@
 package com.oracle.truffle.r.nodes.casts;
 
 import java.lang.reflect.Constructor;
-import java.lang.reflect.Type;
-import java.util.Collections;
-import java.util.Set;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
 
 import com.oracle.truffle.r.nodes.unary.CastNode;
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java
index 9981b36e9248af9aa982861c06f101a588f6aef0..a59861970ff7893d9ee0e84082e813a27e9d793f 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java
@@ -52,8 +52,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
-import sun.java2d.xr.XRCompositeManager;
-
 public class CastUtils {
 
     public static final class Cast {
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/PredefFiltersSamplers.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/PredefFiltersSamplers.java
index 19994502bba6cd768faea9f7f04a4583419c3295..abc1459de7be218498b49f1b4396e6f6784716f2 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/PredefFiltersSamplers.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/PredefFiltersSamplers.java
@@ -34,10 +34,12 @@ import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
@@ -249,6 +251,12 @@ public final class PredefFiltersSamplers implements PredefFilters {
                         x instanceof RAbstractComplexVector, RAbstractComplexVector.class, RComplex.class);
     }
 
+    @Override
+    public <R extends RAbstractRawVector> TypePredicateArgumentFilterSampler<Object, R> rawValue() {
+        return TypePredicateArgumentFilterSampler.fromLambda(x -> x instanceof RRaw ||
+                        x instanceof RAbstractRawVector, RAbstractRawVector.class, RRaw.class);
+    }
+
     @Override
     public TypePredicateArgumentFilterSampler<Object, String> scalarStringValue() {
         return TypePredicateArgumentFilterSampler.fromLambda(x -> x instanceof String, CastUtils.<String> samples(), CastUtils.<Object> samples(null), String.class);
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
index 05d7c3b1e78cd10130300c569de72aa7be04bf51..494f5e2116c721d4c45615faa7f51a370d209f15 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
@@ -45,9 +45,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.scalarLogica
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 
-import java.io.IOException;
-import java.io.OutputStream;
-
 import org.junit.Test;
 
 import com.oracle.truffle.api.CompilerAsserts;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentFilterSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentFilterSampler.java
index cf17d773155e154ea3d74f9b6bee05caf07661b0..1b29123007f6ee8a4fc2d0ddef798fc84de3efdc 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentFilterSampler.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentFilterSampler.java
@@ -30,7 +30,6 @@ import java.util.stream.Collectors;
 
 import com.oracle.truffle.r.nodes.builtin.ValuePredicateArgumentFilter;
 import com.oracle.truffle.r.nodes.casts.ArgumentFilterSampler.ArgumentValueFilterSampler;
-import com.sun.source.doctree.AttributeTree.ValueKind;
 
 public class ValuePredicateArgumentFilterSampler<T> extends ValuePredicateArgumentFilter<T> implements ArgumentValueFilterSampler<T> {
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/VectorPredicateArgumentFilterSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/VectorPredicateArgumentFilterSampler.java
index 33f3ebe0ea4419c7efe1973399f1bead927710af..92f4853c4918c6be5ecaa85499177ff6292459b1 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/VectorPredicateArgumentFilterSampler.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/VectorPredicateArgumentFilterSampler.java
@@ -28,7 +28,6 @@ import java.util.List;
 import java.util.Set;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 import com.oracle.truffle.r.nodes.builtin.VectorPredicateArgumentFilter;
 import com.oracle.truffle.r.nodes.casts.ArgumentFilterSampler.ArgumentValueFilterSampler;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/CastStringNodeGenSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/CastStringNodeGenSampler.java
deleted file mode 100644
index 777b8e0e05be525d5a074cf03e726f00ac77707a..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/CastStringNodeGenSampler.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.unary;
-
-import com.oracle.truffle.r.nodes.casts.CastNodeSampler;
-import com.oracle.truffle.r.nodes.casts.TypeExpr;
-import com.oracle.truffle.r.runtime.data.RNull;
-
-public class CastStringNodeGenSampler extends CastNodeSampler<CastStringNodeGen> {
-
-    public CastStringNodeGenSampler(CastStringNodeGen castNode) {
-        super(castNode);
-    }
-
-    @Override
-    public TypeExpr resultTypes(TypeExpr inputType) {
-        TypeExpr rt = super.resultTypes(inputType);
-        if (castNode.convertEmptyVectorToNull()) {
-            return rt.or(TypeExpr.union(RNull.class));
-        } else {
-            return rt;
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FilterNodeGenSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FilterNodeGenSampler.java
index 047ced6cff65c7bf52f15672ccd52189a42737da..bfdbdd71f798d6f2b8c4530c5911014aee10cfc5 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FilterNodeGenSampler.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FilterNodeGenSampler.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes.unary;
 
 import com.oracle.truffle.r.nodes.casts.ArgumentFilterSampler;
 import com.oracle.truffle.r.nodes.casts.CastNodeSampler;
-import com.oracle.truffle.r.nodes.casts.CastUtils;
 import com.oracle.truffle.r.nodes.casts.Samples;
 import com.oracle.truffle.r.nodes.casts.TypeExpr;
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FindFirstNodeGenSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FindFirstNodeGenSampler.java
index 3fa48e1f4a8e503607ae54d9135563aa65e32f56..0b92ad8b7dcc6f93b0e971727b1b71ea6bad8ebb 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FindFirstNodeGenSampler.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FindFirstNodeGenSampler.java
@@ -24,9 +24,7 @@ package com.oracle.truffle.r.nodes.unary;
 
 import java.lang.reflect.Type;
 import java.util.HashSet;
-import java.util.Optional;
 import java.util.Set;
-import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
@@ -36,7 +34,6 @@ import com.oracle.truffle.r.nodes.casts.Samples;
 import com.oracle.truffle.r.nodes.casts.TypeExpr;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public class FindFirstNodeGenSampler extends CastNodeSampler<FindFirstNodeGen> {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java
index 6d813c4a45aa5e8d837aa4b520e374ca167f0980..245067ec8469059f34357adc436ef56abbfef8a0 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java
@@ -70,7 +70,7 @@ public abstract class CastTypeNode extends BinaryNode {
     public static CastNode createCast(RType type, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
         switch (type) {
             case Character:
-                return CastStringNodeGen.create(preserveNames, preserveDimensions, preserveAttributes, false);
+                return CastStringNodeGen.create(preserveNames, preserveDimensions, preserveAttributes);
             case Complex:
                 return CastComplexNodeGen.create(preserveNames, preserveDimensions, preserveAttributes);
             case Double:
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
index 7ced392e8699d325fe7d394241114e406f251064..b5ce331f08f10e4dc7964a04fb14f590bfe76997 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
@@ -58,10 +58,12 @@ import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
@@ -127,7 +129,11 @@ public final class CastBuilder {
     }
 
     public CastBuilder toCharacter(int index) {
-        return insert(index, CastStringNodeGen.create(false, false, false, false));
+        return insert(index, CastStringNodeGen.create(false, false, false));
+    }
+
+    public CastBuilder toCharacter(int index, boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) {
+        return insert(index, CastStringNodeGen.create(preserveNames, dimensionsPreservation, attrPreservation));
     }
 
     public CastBuilder boxPrimitive(int index) {
@@ -278,6 +284,8 @@ public final class CastBuilder {
 
         <R extends RAbstractComplexVector> TypePredicateArgumentFilter<Object, R> complexValue();
 
+        <R extends RAbstractRawVector> TypePredicateArgumentFilter<Object, R> rawValue();
+
         TypePredicateArgumentFilter<Object, String> scalarStringValue();
 
         TypePredicateArgumentFilter<Object, Integer> scalarIntegerValue();
@@ -493,6 +501,11 @@ public final class CastBuilder {
             return TypePredicateArgumentFilter.fromLambda(x -> x instanceof RComplex || x instanceof RAbstractComplexVector);
         }
 
+        @Override
+        public <R extends RAbstractRawVector> TypePredicateArgumentFilter<Object, R> rawValue() {
+            return TypePredicateArgumentFilter.fromLambda(x -> x instanceof RRaw || x instanceof RAbstractRawVector);
+        }
+
         @Override
         public TypePredicateArgumentFilter<Object, String> scalarStringValue() {
             return TypePredicateArgumentFilter.fromLambda(x -> x instanceof String);
@@ -691,11 +704,11 @@ public final class CastBuilder {
         }
 
         public static <T> Function<ArgCastBuilder<T, ?>, CastNode> asStringVector() {
-            return phaseBuilder -> CastStringNodeGen.create(false, false, false, false);
+            return phaseBuilder -> CastStringNodeGen.create(false, false, false);
         }
 
         public static <T> Function<ArgCastBuilder<T, ?>, CastNode> asStringVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-            return phaseBuilder -> CastStringNodeGen.create(preserveNames, preserveDimensions, preserveAttributes, false);
+            return phaseBuilder -> CastStringNodeGen.create(preserveNames, preserveDimensions, preserveAttributes);
         }
 
         public static <T> Function<ArgCastBuilder<T, ?>, CastNode> asLogical() {
@@ -950,6 +963,10 @@ public final class CastBuilder {
             return predefFilters().complexValue();
         }
 
+        public static <R extends RAbstractRawVector> TypePredicateArgumentFilter<Object, R> rawValue() {
+            return predefFilters().rawValue();
+        }
+
         public static ArgumentTypeFilter<Object, Object> numericValue() {
             return integerValue().or(doubleValue()).or(logicalValue());
         }
@@ -1357,6 +1374,11 @@ public final class CastBuilder {
             return state().factory.newCoercedPhaseBuilder(this, Byte.class);
         }
 
+        default CoercedPhaseBuilder<RAbstractStringVector, String> asStringVector(boolean preserveNames, boolean dimensionsPreservation, boolean attrPreservation) {
+            state().castBuilder().toCharacter(state().index(), preserveNames, dimensionsPreservation, attrPreservation);
+            return state().factory.newCoercedPhaseBuilder(this, String.class);
+        }
+
         default CoercedPhaseBuilder<RAbstractStringVector, String> asStringVector() {
             state().castBuilder().toCharacter(state().index());
             return state().factory.newCoercedPhaseBuilder(this, String.class);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java
index 2c468c42b1bbd4b6c25dfb88ff3952db68b03e5c..cf65a15c602e85f5eccf5e005c31402e5c68ff30 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java
@@ -101,7 +101,7 @@ public final class RFactorNodes {
             } else {
                 if (castString == null) {
                     CompilerDirectives.transferToInterpreterAndInvalidate();
-                    castString = insert(CastStringNodeGen.create(false, false, false, false));
+                    castString = insert(CastStringNodeGen.create(false, false, false));
                 }
                 RStringVector slevels = (RStringVector) castString.executeString(vec);
                 return RDataFactory.createStringVector(slevels.getDataWithoutCopying(), RDataFactory.COMPLETE_VECTOR);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java
index 9a258c8124fc2ca1f264a0f054dc899b0c89acb0..d416956e4a2689e6f5f1098a9b7a4de604697d56 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java
@@ -30,19 +30,11 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public abstract class CastStringNode extends CastStringBaseNode {
 
-    private final boolean convertEmptyVectorToNull;
-
-    protected CastStringNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean convertEmptyVectorToNull) {
+    protected CastStringNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
         super(preserveNames, preserveDimensions, preserveAttributes);
-        this.convertEmptyVectorToNull = convertEmptyVectorToNull;
-    }
-
-    public boolean convertEmptyVectorToNull() {
-        return convertEmptyVectorToNull;
     }
 
     public abstract Object executeString(int o);
@@ -58,17 +50,25 @@ public abstract class CastStringNode extends CastStringBaseNode {
         return RNull.instance;
     }
 
-    @Specialization(guards = "vector.getLength() == 0")
-    protected Object doEmptyVector(@SuppressWarnings("unused") RAbstractVector vector) {
-        return convertEmptyVectorToNull ? RNull.instance : RDataFactory.createStringVector(0);
+    private RStringVector vectorCopy(RAbstractContainer operand, String[] data) {
+        RStringVector ret = RDataFactory.createStringVector(data, operand.isComplete(), getPreservedDimensions(operand), getPreservedNames(operand));
+        preserveDimensionNames(operand, ret);
+        if (preserveAttributes()) {
+            ret.copyRegAttributesFrom(operand);
+        }
+        return ret;
     }
 
-    @Specialization(guards = "vector.getLength() != 0")
+    @Specialization
     protected RStringVector doStringVector(RStringVector vector) {
-        return vector;
+        if (preserveAttributes() && preserveDimensions() && preserveNames()) {
+            return vector;
+        } else {
+            return vectorCopy(vector, vector.getDataCopy());
+        }
     }
 
-    @Specialization(guards = "operand.getLength() != 0")
+    @Specialization
     protected RStringVector doIntVector(RAbstractContainer operand) {
         String[] sdata = new String[operand.getLength()];
         // conversions to character will not introduce new NAs
@@ -80,12 +80,7 @@ public abstract class CastStringNode extends CastStringBaseNode {
                 sdata[i] = toString(o);
             }
         }
-        RStringVector ret = RDataFactory.createStringVector(sdata, operand.isComplete(), getPreservedDimensions(operand), getPreservedNames(operand));
-        preserveDimensionNames(operand, ret);
-        if (preserveAttributes()) {
-            ret.copyRegAttributesFrom(operand);
-        }
-        return ret;
+        return vectorCopy(operand, sdata);
     }
 
     @Specialization
@@ -94,10 +89,10 @@ public abstract class CastStringNode extends CastStringBaseNode {
     }
 
     public static CastStringNode create() {
-        return CastStringNodeGen.create(false, true, true, true);
+        return CastStringNodeGen.create(true, true, true);
     }
 
     public static CastStringNode createNonPreserving() {
-        return CastStringNodeGen.create(false, false, false, false);
+        return CastStringNodeGen.create(false, false, false);
     }
 }
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java
index c845b089c361007de40e3ea58ee12cfcdc2ed564..a44b8ff62a92abd152f40e7db3f18345c91508fa 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java
@@ -38,11 +38,11 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RErrorHandling;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.RSrcref;
 import com.oracle.truffle.r.runtime.RSource;
+import com.oracle.truffle.r.runtime.RSrcref;
+import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.Utils;
-import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE;
 import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RAttributable;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index d8ffa9fb2fee02f8fc3948e260d9bf0390e783fc..b1e8b8809410ffaade8698147faf38c847b2b085 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -686,7 +686,9 @@ public final class RError extends RuntimeException {
         ROWSUM_NAMES_NOT_CHAR("row names are not character"),
         ROWSUM_NON_NUMERIC("non-numeric matrix in rowsum(): this should not happen"),
         ARGUMENTS_REQUIRED_COUNT("%d arguments to '%s' which requires %d"),
-        ARGUMENT_LENGTH_0("argument of length 0");
+        ARGUMENT_LENGTH_0("argument of length 0"),
+        MUST_BE_VECTOR_BUT_WAS("'%s' must be of a vector type, was '%s'"),
+        CANNOT_BE_LENGTH("'%s' cannot be of length %d");
 
         public final String message;
         final boolean hasArgs;
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 5774cdbc65dcccdf4aaaaafad70e30ee0e9d1813..a24724055e6f850aedb069f9e7dbabecde41a50f 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
@@ -1101,6 +1101,26 @@ character(0)
 #argv <- list(structure(list(sec = c(0, 0, 0, 0, 0), min = c(0L, 0L, 0L, 0L, 0L), hour = c(0L, 0L, 0L, 0L, 0L), mday = 22:26, mon = c(3L, 3L, 3L, 3L, 3L), year = c(108L, 108L, 108L, 108L, 108L), wday = 2:6, yday = 112:116, isdst = c(-1L, -1L, -1L, -1L, -1L)), .Names = c('sec', 'min', 'hour', 'mday', 'mon', 'year', 'wday', 'yday', 'isdst'), class = c('POSIXlt', 'POSIXt'), tzone = 'GMT')); .Internal(POSIXlt2Date(argv[[1]]))
 [1] "2008-04-22" "2008-04-23" "2008-04-24" "2008-04-25" "2008-04-26"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Primitive.testPrimitive1
+#.Primitive('any')
+function (..., na.rm = FALSE)  .Primitive("any")
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Primitive.testPrimitive1
+#.Primitive('complex')
+Error in .Primitive("complex") : no such primitive function
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Primitive.testPrimitive1
+#.Primitive('foo')
+Error in .Primitive("foo") : no such primitive function
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Primitive.testPrimitive1
+#.Primitive(1)
+Error in .Primitive(1) : string argument required
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Primitive.testPrimitive1
+#.Primitive(c('c', 'b'))
+Error in .Primitive(c("c", "b")) : string argument required
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Primitive.testPrimitive1
 #argv <- list('c');.Primitive(argv[[1]]);
 function (..., recursive = FALSE)  .Primitive("c")
@@ -3894,6 +3914,58 @@ NULL
 #argv <- list(structure(numeric(0), .Dim = c(0L, 0L))); .Internal(args(argv[[1]]))
 NULL
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray
+#{ .Internal(array(1:4, NULL, NULL)) }
+Error: 'dims' cannot be of length 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray
+#{ .Internal(array(NA, 1, NULL)) }
+[1] NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray
+#{ .Internal(array(NULL, 1, NULL)) }
+Error: 'data' must be of a vector type, was 'NULL'
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray
+#{ array(1:4, 1:2, 4) }
+     [,1] [,2]
+[1,]    1    2
+Warning message:
+In array(1:4, 1:2, 4) :
+  non-list dimnames are disregarded; will be an error in R 3.3.0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray
+#{ array(1:4, NULL) }
+Error in array(1:4, NULL) : 'dims' cannot be of length 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray
+#{ array(1:4, c(1+2i, 2+2i)) }
+     [,1] [,2]
+[1,]    1    2
+Warning message:
+In array(1:4, c(1 + (0+2i), 2 + (0+2i))) :
+  imaginary parts discarded in coercion
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray
+#{ array(1:4, integer()) }
+Error in array(1:4, integer()) : 'dims' cannot be of length 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray
+#{ array(NA) }
+[1] NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray
+#{ array(NULL) }
+Error in array(NULL) : 'data' must be of a vector type, was 'NULL'
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray
+#{ array(as.raw(1:4)) }
+[1] 01 02 03 04
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray
+#{ f<-function() 42; .Internal(array(f, 1, NULL)) }
+Error: 'data' must be of a vector type, was 'closure'
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testarray1
 #argv <- list(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L), 59L, structure(list(dr = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59.5')), .Names = 'dr')); .Internal(array(argv[[1]], argv[[2]], argv[[3]]))
 dr
@@ -30762,6 +30834,10 @@ NULL
 #{ x<-c(1,2,3); dim(x)<-3; dimnames(x)<-list(c(11,12,13)); names(x) }
 [1] "11" "12" "13"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testNames
+#{ y<-c(d="e"); attr(y, "foo")<-"foo"; x<-c(42); names(x)<-y; attributes(names(x)) }
+NULL
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testnames1
 #argv <- list(structure(list(size = 113, isdir = FALSE, mode = structure(436L, class = 'octmode'), mtime = structure(1395082088.72988, class = c('POSIXct', 'POSIXt')), ctime = structure(1395082088.72988, class = c('POSIXct', 'POSIXt')), atime = structure(1395082088.77388, class = c('POSIXct', 'POSIXt')), uid = 1001L, gid = 1001L, uname = 'roman', grname = 'roman'), .Names = c('size', 'isdir', 'mode', 'mtime', 'ctime', 'atime', 'uid', 'gid', 'uname', 'grname'), class = 'data.frame', row.names = '/tmp/RtmptPgrXI/file55711ba85492'));names(argv[[1]]);
  [1] "size"   "isdir"  "mode"   "mtime"  "ctime"  "atime"  "uid"    "gid"
@@ -47952,6 +48028,39 @@ integer(0)
 #{ u <- function() sys.parents() ; f <- function(x) x ; g <- function(y) f(y) ; h <- function(z=u()) g(z) ; h() }
 [1] 0 1 2 1
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTranspose
+#t(1)
+     [,1]
+[1,]    1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTranspose
+#t(TRUE)
+     [,1]
+[1,] TRUE
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTranspose
+#t(as.raw(c(1,2,3,4)))
+     [,1] [,2] [,3] [,4]
+[1,]   01   02   03   04
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTranspose
+#t(new.env())
+Error in t.default(new.env()) : argument is not a matrix
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTranspose
+#v <- as.complex(1:50); dim(v) <- c(5,10); dimnames(v) <- list(as.character(40:44), as.character(10:19)); t(v)
+      40    41    42    43    44
+10  1+0i  2+0i  3+0i  4+0i  5+0i
+11  6+0i  7+0i  8+0i  9+0i 10+0i
+12 11+0i 12+0i 13+0i 14+0i 15+0i
+13 16+0i 17+0i 18+0i 19+0i 20+0i
+14 21+0i 22+0i 23+0i 24+0i 25+0i
+15 26+0i 27+0i 28+0i 29+0i 30+0i
+16 31+0i 32+0i 33+0i 34+0i 35+0i
+17 36+0i 37+0i 38+0i 39+0i 40+0i
+18 41+0i 42+0i 43+0i 44+0i 45+0i
+19 46+0i 47+0i 48+0i 49+0i 50+0i
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTranspose
 #{ m <- double() ; dim(m) <- c(0,4) ; t(m) }
 
@@ -107035,26 +107144,38 @@ a b c d
 a b c d e
 1 2 3 4 5
 
-##com.oracle.truffle.r.test.library.fastr.TestInteropEval.testInteropEval
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEval
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { .fastr.interop.eval('application/x-r', '1') }
 [1] 1
 
-##com.oracle.truffle.r.test.library.fastr.TestInteropEval.testInteropEval
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEval
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 16 } else { .fastr.interop.eval('application/x-r', '14 + 2') }
 [1] 16
 
-##com.oracle.truffle.r.test.library.fastr.TestInteropEval.testInteropEval
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEval
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 1L } else { .fastr.interop.eval('application/x-r', '1L') }
 [1] 1
 
-##com.oracle.truffle.r.test.library.fastr.TestInteropEval.testInteropEval
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEval
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { .fastr.interop.eval('application/x-r', 'TRUE') }
 [1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestInteropEval.testInteropEval
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEval
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { as.character(123) } else { .fastr.interop.eval('application/x-r', 'as.character(123)') }
 [1] "123"
 
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropExport
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { invisible() } else { .fastr.interop.export('foo', 'foo') }
+
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropExport
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { invisible() } else { .fastr.interop.export('foo', 14 + 2) }
+
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropExport
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { invisible() } else { .fastr.interop.export('foo', 1:100) }
+
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropExport
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { invisible() } else { .fastr.interop.export('foo', new.env()) }
+
 ##com.oracle.truffle.r.test.library.fastr.TestStateTrans.testTransitions
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { { f<-function(x) .fastr.refcountinfo(x); f(c(1,2)) } }
 [1] 1
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Primitive.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Primitive.java
index dd1cb83bac27a21d515b2dbc9d66231d545b9f4b..0a5be54776f6d0366f142b7175f1fc4fb3284c57 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Primitive.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Primitive.java
@@ -19,6 +19,13 @@ public class TestBuiltin_Primitive extends TestBase {
 
     @Test
     public void testPrimitive1() {
-        assertEval(Ignored.Unknown, "argv <- list('c');.Primitive(argv[[1]]);");
+        // our c() primitive is missing an argument
+        assertEval(Ignored.ImplementationError, "argv <- list('c');.Primitive(argv[[1]]);");
+
+        assertEval(".Primitive(c('c', 'b'))");
+        assertEval(".Primitive('any')");
+        assertEval(".Primitive('foo')");
+        assertEval(".Primitive('complex')");
+        assertEval(".Primitive(1)");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_array.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_array.java
index 7afc488e9daa4c76a19ed3b9c2f78091522d3791..f3bbee15bd4d1f428380499e223d8e54256cb5c0 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_array.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_array.java
@@ -154,4 +154,20 @@ public class TestBuiltin_array extends TestBase {
     public void testarray27() {
         assertEval("argv <- list(-1, c(3L, 2L), list(c('a', 'b', 'c'), NULL)); .Internal(array(argv[[1]], argv[[2]], argv[[3]]))");
     }
+
+    @Test
+    public void testArray() {
+        assertEval(Output.IgnoreWarningContext, "{ array(1:4, 1:2, 4) }");
+        assertEval(Output.IgnoreWarningContext, "{ array(1:4, c(1+2i, 2+2i)) }");
+        assertEval("{ array(as.raw(1:4)) }");
+        assertEval("{ array(1:4, integer()) }");
+        assertEval("{ array(NULL) }");
+        assertEval("{ array(NA) }");
+        assertEval("{ array(1:4, NULL) }");
+        assertEval("{ .Internal(array(1:4, NULL, NULL)) }");
+        assertEval("{ .Internal(array(NULL, 1, NULL)) }");
+        assertEval("{ .Internal(array(NA, 1, NULL)) }");
+        assertEval("{ f<-function() 42; .Internal(array(f, 1, NULL)) }");
+    }
+
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java
index 7a1ba027b7e2836032a9fc06232474901b940c51..cd568a219dfdb357ab3e656147f43c3f6ef9d095 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java
@@ -203,6 +203,7 @@ public class TestBuiltin_names extends TestBase {
         assertEval("v <- parse(text=\"useDynLib(digest, digest_impl=digest)\"); names(v[[1]][[3]])");
         assertEval("{ x<-c(1,2,3); dim(x)<-3; dimnames(x)<-list(c(11,12,13)); names(x) }");
         assertEval("{ symNames <- c(\"foobar\", \"bar\"); names(symNames) = symNames; names(names(symNames)); }");
+        assertEval("{ y<-c(d=\"e\"); attr(y, \"foo\")<-\"foo\"; x<-c(42); names(x)<-y; attributes(names(x)) }");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_t.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_t.java
index 3d851f24c7e6da980f8521ef2ff438e066cf4420..693cde32eb6e252583908b569377a1a8b142a8c2 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_t.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_t.java
@@ -40,5 +40,11 @@ public class TestBuiltin_t extends TestBase {
         assertEval("{ t(t(matrix(1:4, nrow=2))) }");
 
         assertEval("{ x<-matrix(1:2, ncol=2, dimnames=list(\"a\", c(\"b\", \"c\"))); t(x) }");
+
+        assertEval("t(new.env())");
+        assertEval("v <- as.complex(1:50); dim(v) <- c(5,10); dimnames(v) <- list(as.character(40:44), as.character(10:19)); t(v)");
+        assertEval("t(1)");
+        assertEval("t(TRUE)");
+        assertEval("t(as.raw(c(1,2,3,4)))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_whichmax.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_whichmax.java
index 2fe9d80df244312a224515e494fa1fc7ced6783c..ddf4c669f82f8a705cacddb8ba2f8b227097aad2 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_whichmax.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_whichmax.java
@@ -24,7 +24,7 @@ public class TestBuiltin_whichmax extends TestBase {
 
     @Test
     public void testwhichmax2() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(c(TRUE, FALSE), .Names = c('d', 'I(as.numeric(d)^2)'))); .Internal(which.max(argv[[1]]))");
+        assertEval("argv <- list(structure(c(TRUE, FALSE), .Names = c('d', 'I(as.numeric(d)^2)'))); .Internal(which.max(argv[[1]]))");
     }
 
     @Test
@@ -34,23 +34,22 @@ public class TestBuiltin_whichmax extends TestBase {
 
     @Test
     public void testwhichmax4() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(NA, 87, 82, 75, 63, 50, 43, 32, 35, 60, 54, 55, 36, 39, NA, NA, 69, 57, 57, 51, 45, 37, 46, 39, 36, 24, 32, 23, 25, 32, NA, 32, 59, 74, 75, 60, 71, 61, 71, 57, 71, 68, 79, 73, 76, 71, 67, 75, 79, 62, 63, 57, 60, 49, 48, 52, 57, 62, 61, 66, 71, 62, 61, 57, 72, 83, 71, 78, 79, 71, 62, 74, 76, 64, 62, 57, 80, 73, 69, 69, 71, 64, 69, 62, 63, 46, 56, 44, 44, 52, 38, 46, 36, 49, 35, 44, 59, 65, 65, 56, 66, 53, 61, 52, 51, 48, 54, 49, 49, 61, NA, NA, 68, 44, 40, 27, 28, 25, 24, 24), .Tsp = c(1945, 1974.75, 4), class = 'ts')); .Internal(which.max(argv[[1]]))");
+        assertEval("argv <- list(structure(c(NA, 87, 82, 75, 63, 50, 43, 32, 35, 60, 54, 55, 36, 39, NA, NA, 69, 57, 57, 51, 45, 37, 46, 39, 36, 24, 32, 23, 25, 32, NA, 32, 59, 74, 75, 60, 71, 61, 71, 57, 71, 68, 79, 73, 76, 71, 67, 75, 79, 62, 63, 57, 60, 49, 48, 52, 57, 62, 61, 66, 71, 62, 61, 57, 72, 83, 71, 78, 79, 71, 62, 74, 76, 64, 62, 57, 80, 73, 69, 69, 71, 64, 69, 62, 63, 46, 56, 44, 44, 52, 38, 46, 36, 49, 35, 44, 59, 65, 65, 56, 66, 53, 61, 52, 51, 48, 54, 49, 49, 61, NA, NA, 68, 44, 40, 27, 28, 25, 24, 24), .Tsp = c(1945, 1974.75, 4), class = 'ts')); .Internal(which.max(argv[[1]]))");
     }
 
     @Test
     public void testwhichmax5() {
-        assertEval(Ignored.Unknown, "argv <- list(NULL); .Internal(which.max(argv[[1]]))");
+        assertEval("argv <- list(NULL); .Internal(which.max(argv[[1]]))");
     }
 
     @Test
     public void testwhichmax6() {
-        assertEval(Ignored.Unknown, "argv <- list(list()); .Internal(which.max(argv[[1]]))");
+        assertEval("argv <- list(list()); .Internal(which.max(argv[[1]]))");
     }
 
     @Test
     public void testwhichmax8() {
-        assertEval(Ignored.Unknown, "argv <- structure(list(x = c(NA, NA)), .Names = 'x');do.call('which.max', argv)");
+        assertEval("argv <- structure(list(x = c(NA, NA)), .Names = 'x');do.call('which.max', argv)");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_whichmin.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_whichmin.java
index c68a12f92aeb6613580324898e4074e1212331ef..8dbadd6a6face7e01fb9f1830fe277a4b5186edd 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_whichmin.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_whichmin.java
@@ -19,41 +19,37 @@ public class TestBuiltin_whichmin extends TestBase {
 
     @Test
     public void testwhichmin1() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(345595, 172795, 69115, 34555, 23035, 11515, 5755, 2875, 1147, 571, 379, 187, 91, 27, 11, 3, 1, 3, 4.42857142857143, 4.73716632443532, 4.86858316221766, 4.95619438740589, 4.97809719370294, 4.98904859685147, 4.99452429842574, 4.99780971937029, 4.99890485968515, 4.99945242984257, 4.99978097193703, 4.99989048596851, 4.99994524298426, 4.9999780971937, 4.99998904859685), .Names = c('1 sec', '2 secs', '5 secs', '10 secs', '15 secs', '30 secs', '1 min', '2 mins', '5 mins', '10 mins', '15 mins', '30 mins', '1 hour', '3 hours', '6 hours', '12 hours', '1 DSTday', '2 DSTdays', '1 week', 'halfmonth', '1 month', '3 months', '6 months', '1 year', '2 years', '5 years', '10 years', '20 years', '50 years', '100 years', '200 years', '500 years', '1000 years'))); .Internal(which.min(argv[[1]]))");
+        assertEval("argv <- list(structure(c(345595, 172795, 69115, 34555, 23035, 11515, 5755, 2875, 1147, 571, 379, 187, 91, 27, 11, 3, 1, 3, 4.42857142857143, 4.73716632443532, 4.86858316221766, 4.95619438740589, 4.97809719370294, 4.98904859685147, 4.99452429842574, 4.99780971937029, 4.99890485968515, 4.99945242984257, 4.99978097193703, 4.99989048596851, 4.99994524298426, 4.9999780971937, 4.99998904859685), .Names = c('1 sec', '2 secs', '5 secs', '10 secs', '15 secs', '30 secs', '1 min', '2 mins', '5 mins', '10 mins', '15 mins', '30 mins', '1 hour', '3 hours', '6 hours', '12 hours', '1 DSTday', '2 DSTdays', '1 week', 'halfmonth', '1 month', '3 months', '6 months', '1 year', '2 years', '5 years', '10 years', '20 years', '50 years', '100 years', '200 years', '500 years', '1000 years'))); .Internal(which.min(argv[[1]]))");
     }
 
     @Test
     public void testwhichmin2() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(295, 145, 55, 25, 15, 5, 0, 2.5, 4, 4.5, 4.66666666666667, 4.83333333333333, 4.91666666666667, 4.97222222222222, 4.98611111111111, 4.99305555555556, 4.99652777777778, 4.99826388888889, 4.99950396825397, 4.99977184576774, 4.99988592288387, 4.99996197429462, 4.99998098714731, 4.99999049357366, 4.99999524678683, 4.99999809871473, 4.99999904935737, 4.99999952467868, 4.99999980987147, 4.99999990493574, 4.99999995246787, 4.99999998098715, 4.99999999049357), .Names = c('1 sec', '2 secs', '5 secs', '10 secs', '15 secs', '30 secs', '1 min', '2 mins', '5 mins', '10 mins', '15 mins', '30 mins', '1 hour', '3 hours', '6 hours', '12 hours', '1 DSTday', '2 DSTdays', '1 week', 'halfmonth', '1 month', '3 months', '6 months', '1 year', '2 years', '5 years', '10 years', '20 years', '50 years', '100 years', '200 years', '500 years', '1000 years'))); .Internal(which.min(argv[[1]]))");
+        assertEval("argv <- list(structure(c(295, 145, 55, 25, 15, 5, 0, 2.5, 4, 4.5, 4.66666666666667, 4.83333333333333, 4.91666666666667, 4.97222222222222, 4.98611111111111, 4.99305555555556, 4.99652777777778, 4.99826388888889, 4.99950396825397, 4.99977184576774, 4.99988592288387, 4.99996197429462, 4.99998098714731, 4.99999049357366, 4.99999524678683, 4.99999809871473, 4.99999904935737, 4.99999952467868, 4.99999980987147, 4.99999990493574, 4.99999995246787, 4.99999998098715, 4.99999999049357), .Names = c('1 sec', '2 secs', '5 secs', '10 secs', '15 secs', '30 secs', '1 min', '2 mins', '5 mins', '10 mins', '15 mins', '30 mins', '1 hour', '3 hours', '6 hours', '12 hours', '1 DSTday', '2 DSTdays', '1 week', 'halfmonth', '1 month', '3 months', '6 months', '1 year', '2 years', '5 years', '10 years', '20 years', '50 years', '100 years', '200 years', '500 years', '1000 years'))); .Internal(which.min(argv[[1]]))");
     }
 
     @Test
     public void testwhichmin3() {
-        assertEval(Ignored.Unknown, "argv <- list(NULL); .Internal(which.min(argv[[1]]))");
+        assertEval("argv <- list(NULL); .Internal(which.min(argv[[1]]))");
     }
 
     @Test
     public void testwhichmin4() {
-        assertEval(Ignored.Unknown, "argv <- list(list()); .Internal(which.min(argv[[1]]))");
+        assertEval("argv <- list(list()); .Internal(which.min(argv[[1]]))");
     }
 
     @Test
     public void testwhichmin5() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c(NA, 0.951840581382975, 0.805577027554469, 0.663985017923499, 0.53717416750558, 0.496765449963868, 0.472038350505409, 0.463306413812878, 0.485896454097402, 0.520777596351646, 0.524391122960607, 0.492063804965834, 0.513821989320989, 0.521702559081969, 0.533525525673351)); .Internal(which.min(argv[[1]]))");
+        assertEval("argv <- list(c(NA, 0.951840581382975, 0.805577027554469, 0.663985017923499, 0.53717416750558, 0.496765449963868, 0.472038350505409, 0.463306413812878, 0.485896454097402, 0.520777596351646, 0.524391122960607, 0.492063804965834, 0.513821989320989, 0.521702559081969, 0.533525525673351)); .Internal(which.min(argv[[1]]))");
     }
 
     @Test
     public void testwhichmin6() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(NA, 87, 82, 75, 63, 50, 43, 32, 35, 60, 54, 55, 36, 39, NA, NA, 69, 57, 57, 51, 45, 37, 46, 39, 36, 24, 32, 23, 25, 32, NA, 32, 59, 74, 75, 60, 71, 61, 71, 57, 71, 68, 79, 73, 76, 71, 67, 75, 79, 62, 63, 57, 60, 49, 48, 52, 57, 62, 61, 66, 71, 62, 61, 57, 72, 83, 71, 78, 79, 71, 62, 74, 76, 64, 62, 57, 80, 73, 69, 69, 71, 64, 69, 62, 63, 46, 56, 44, 44, 52, 38, 46, 36, 49, 35, 44, 59, 65, 65, 56, 66, 53, 61, 52, 51, 48, 54, 49, 49, 61, NA, NA, 68, 44, 40, 27, 28, 25, 24, 24), .Tsp = c(1945, 1974.75, 4), class = 'ts')); .Internal(which.min(argv[[1]]))");
+        assertEval("argv <- list(structure(c(NA, 87, 82, 75, 63, 50, 43, 32, 35, 60, 54, 55, 36, 39, NA, NA, 69, 57, 57, 51, 45, 37, 46, 39, 36, 24, 32, 23, 25, 32, NA, 32, 59, 74, 75, 60, 71, 61, 71, 57, 71, 68, 79, 73, 76, 71, 67, 75, 79, 62, 63, 57, 60, 49, 48, 52, 57, 62, 61, 66, 71, 62, 61, 57, 72, 83, 71, 78, 79, 71, 62, 74, 76, 64, 62, 57, 80, 73, 69, 69, 71, 64, 69, 62, 63, 46, 56, 44, 44, 52, 38, 46, 36, 49, 35, 44, 59, 65, 65, 56, 66, 53, 61, 52, 51, 48, 54, 49, 49, 61, NA, NA, 68, 44, 40, 27, 28, 25, 24, 24), .Tsp = c(1945, 1974.75, 4), class = 'ts')); .Internal(which.min(argv[[1]]))");
     }
 
     @Test
     public void testwhichmin8() {
-        assertEval(Ignored.Unknown, "argv <- structure(list(x = c(NA, NA, Inf)), .Names = 'x');do.call('which.min', argv)");
+        assertEval("argv <- structure(list(x = c(NA, NA, Inf)), .Names = 'x');do.call('which.min', argv)");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInteropEval.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
similarity index 79%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInteropEval.java
rename to com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
index f866e6f2e6f40e52d0b39934bb32c6aeef5dc77e..0f8ad2f8dd8531ed611b23c3a89d9173f3f1d0fe 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInteropEval.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
@@ -26,7 +26,7 @@ import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
 
-public class TestInteropEval extends TestBase {
+public class TestInterop extends TestBase {
 
     @Test
     public void testInteropEval() {
@@ -36,4 +36,12 @@ public class TestInteropEval extends TestBase {
         assertEvalFastR(".fastr.interop.eval('application/x-r', 'TRUE')", "TRUE");
         assertEvalFastR(".fastr.interop.eval('application/x-r', 'as.character(123)')", "as.character(123)");
     }
+
+    @Test
+    public void testInteropExport() {
+        assertEvalFastR(".fastr.interop.export('foo', 14 + 2)", "invisible()");
+        assertEvalFastR(".fastr.interop.export('foo', 'foo')", "invisible()");
+        assertEvalFastR(".fastr.interop.export('foo', 1:100)", "invisible()");
+        assertEvalFastR(".fastr.interop.export('foo', new.env())", "invisible()");
+    }
 }
diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index f5867b36f50d72a883a4fe216ca940ba998521ca..bd1837a79e77c0bce1b99dd90e6a170a69d8f94d 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -21,7 +21,7 @@
 # questions.
 #
 suite = {
-  "mxversion" : "5.31.0",
+  "mxversion" : "5.34.4",
   "name" : "fastr",
   "versionConflictResolution" : "latest",
   "imports" : {