diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
index 5d18e8897e307e9ecff69fb34218f40f173292ce..700bc55df30454cf8c7e9694a75d0d10b7182f28 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
@@ -33,6 +33,7 @@ import org.antlr.runtime.RecognitionException;
 import org.antlr.runtime.Token;
 
 import com.oracle.truffle.api.CallTarget;
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
@@ -243,8 +244,8 @@ final class REngine implements Engine, Engine.Timings {
         try {
             Object lastValue = RNull.instance;
             for (RSyntaxNode node : list) {
-                RootCallTarget callTarget = doMakeCallTarget(node.asRNode(), "<repl wrapper>");
-                lastValue = runCall(callTarget, frame, printResult, true);
+                RootCallTarget callTarget = doMakeCallTarget(node.asRNode(), "<repl wrapper>", printResult, true);
+                lastValue = callTarget.call(frame);
             }
             return lastValue;
         } catch (ReturnException ex) {
@@ -322,7 +323,7 @@ final class REngine implements Engine, Engine.Timings {
         return Truffle.getRuntime().createCallTarget(new PolyglotEngineRootNode(statements));
     }
 
-    private static class PolyglotEngineRootNode extends RootNode {
+    private final class PolyglotEngineRootNode extends RootNode {
 
         private final List<RSyntaxNode> statements;
 
@@ -341,13 +342,13 @@ final class REngine implements Engine, Engine.Timings {
         @Override
         public Object execute(VirtualFrame frame) {
             RContext oldContext = RContext.threadLocalContext.get();
-            RContext context = findContext.executeFindContext();
-            RContext.threadLocalContext.set(context);
+            RContext newContext = findContext.executeFindContext();
+            RContext.threadLocalContext.set(newContext);
             try {
                 Object lastValue = RNull.instance;
                 for (RSyntaxNode node : statements) {
-                    RootCallTarget callTarget = doMakeCallTarget(node.asRNode(), "<repl wrapper>");
-                    lastValue = ((REngine) context.getThisEngine()).runCall(callTarget, context.stateREnvironment.getGlobalFrame(), true, true);
+                    RootCallTarget callTarget = doMakeCallTarget(node.asRNode(), "<repl wrapper>", true, true);
+                    lastValue = callTarget.call(newContext.stateREnvironment.getGlobalFrame());
                 }
                 return lastValue;
             } catch (ReturnException ex) {
@@ -401,8 +402,8 @@ final class REngine implements Engine, Engine.Timings {
         if (n instanceof ConstantNode) {
             return ((ConstantNode) n).getValue();
         }
-        RootCallTarget callTarget = doMakeCallTarget(n, EVAL_FUNCTION_NAME);
-        return runCall(callTarget, frame, false, false);
+        RootCallTarget callTarget = doMakeCallTarget(n, EVAL_FUNCTION_NAME, false, false);
+        return callTarget.call(frame);
     }
 
     public Object evalFunction(RFunction func, MaterializedFrame frame, Object... args) {
@@ -414,8 +415,10 @@ final class REngine implements Engine, Engine.Timings {
     }
 
     private Object evalNode(RNode exprRep, REnvironment envir, int depth) {
-        RNode n = exprRep;
-        RootCallTarget callTarget = doMakeCallTarget(n, EVAL_FUNCTION_NAME);
+        // we need to copy the node, otherwise it (and its children) will specialized to a specific
+        // frame descriptor and will fail on subsequent re-executions
+        RNode n = (RNode) exprRep.deepCopy();
+        RootCallTarget callTarget = doMakeCallTarget(n, EVAL_FUNCTION_NAME, false, false);
         RCaller call = RArguments.getCall(envir.getFrame());
         return evalTarget(callTarget, call, envir, depth);
     }
@@ -430,29 +433,30 @@ final class REngine implements Engine, Engine.Timings {
      * inefficient. In particular, in the case where a {@link VirtualFrame} is available, then the
      * {@code eval} methods that take such a {@link VirtualFrame} should be used in preference.
      */
-    private Object evalTarget(RootCallTarget callTarget, RCaller call, REnvironment envir, int depth) {
-        MaterializedFrame envFrame = envir.getFrame();
+    private static Object evalTarget(RootCallTarget callTarget, RCaller call, REnvironment envir, int depth) {
         // Here we create fake frame that wraps the original frame's context and has an only
         // slightly changed arguments array (function and callSrc).
-        MaterializedFrame vFrame = VirtualEvalFrame.create(envFrame, (RFunction) null, call, depth);
-        return runCall(callTarget, vFrame, false, false);
+        MaterializedFrame vFrame = VirtualEvalFrame.create(envir.getFrame(), (RFunction) null, call, depth);
+        return callTarget.call(vFrame);
     }
 
     public Object evalPromise(Closure closure, MaterializedFrame frame) {
-        return runCall(closure.getCallTarget(), frame, false, false);
+        return closure.getCallTarget().call(frame);
     }
 
     @Override
     public RootCallTarget makePromiseCallTarget(RNode body, String funName) {
-        return doMakeCallTarget(body, funName);
+        return doMakeCallTarget(body, funName, false, false);
     }
 
     /**
-     * Creates an anonymous function, with no arguments to evaluate {@code body}.
+     * Creates an anonymous function, with no arguments to evaluate {@code body}, optionally
+     * printing any result. The {@code callTarget} expects exactly one argument: the {@code frame}
+     * that the body should be executed in.
      */
     @TruffleBoundary
-    private static RootCallTarget doMakeCallTarget(RNode body, String description) {
-        return Truffle.getRuntime().createCallTarget(new AnonymousRootNode(body, description));
+    private RootCallTarget doMakeCallTarget(RNode body, String description, boolean printResult, boolean topLevel) {
+        return Truffle.getRuntime().createCallTarget(new AnonymousRootNode(body, description, printResult, topLevel));
     }
 
     /**
@@ -463,24 +467,70 @@ final class REngine implements Engine, Engine.Timings {
      * context of that frame. Note that passing only this one frame argument, strictly spoken,
      * violates the frame layout as set forth in {@link RArguments}. This is for internal use only.
      */
-    private static final class AnonymousRootNode extends RootNode {
+    private final class AnonymousRootNode extends RootNode {
 
         private final ValueProfile frameTypeProfile = ValueProfile.createClassProfile();
 
         private final String description;
+        private final boolean printResult;
+        private final boolean topLevel;
 
         @Child private RNode body;
 
-        protected AnonymousRootNode(RNode body, String description) {
+        protected AnonymousRootNode(RNode body, String description, boolean printResult, boolean topLevel) {
             super(TruffleRLanguage.class, null, new FrameDescriptor());
             this.body = body;
             this.description = description;
+            this.printResult = printResult;
+            this.topLevel = topLevel;
         }
 
         @Override
         public Object execute(VirtualFrame frame) {
+            assert frame.getArguments().length == 1;
             SubstituteVirtualFrame vf = new SubstituteVirtualFrame((MaterializedFrame) frameTypeProfile.profile(frame.getArguments()[0]));
-            return body.execute(vf);
+            Object result = null;
+            try {
+                result = body.execute(vf);
+                assert checkResult(result);
+                if (printResult && result != null) {
+                    assert topLevel;
+                    if (context.isVisible()) {
+                        printResult(result);
+                    }
+                }
+                if (topLevel) {
+                    RErrorHandling.printWarnings(suppressWarnings);
+                }
+            } catch (RError e) {
+                CompilerDirectives.transferToInterpreter();
+                throw e;
+            } catch (ReturnException ex) {
+                CompilerDirectives.transferToInterpreter();
+                // condition handling can cause a "return" that needs to skip over this call
+                throw ex;
+            } catch (BreakException | NextException cfe) {
+                if (topLevel) {
+                    CompilerDirectives.transferToInterpreter();
+                    throw RError.error(RError.SHOW_CALLER2, RError.Message.NO_LOOP_FOR_BREAK_NEXT);
+                } else {
+                    // there can be an outer loop
+                    throw cfe;
+                }
+            } catch (DebugExitException | BrowserQuitException e) {
+                CompilerDirectives.transferToInterpreter();
+                throw e;
+            } catch (Throwable e) {
+                CompilerDirectives.transferToInterpreter();
+                if (e instanceof Error) {
+                    throw (Error) e;
+                } else if (e instanceof RuntimeException) {
+                    throw (RuntimeException) e;
+                } else {
+                    assert false : "unexpected exception: " + e;
+                }
+            }
+            return result;
         }
 
         @Override
@@ -494,55 +544,6 @@ final class REngine implements Engine, Engine.Timings {
         }
     }
 
-    /**
-     * Execute {@code callTarget} in {@code frame}, optionally printing any result. N.B.
-     * {@code callTarget.call} will create a new {@link VirtualFrame} called, say, {@code newFrame},
-     * in which to execute the (anonymous) {@link FunctionDefinitionNode} associated with
-     * {@code callTarget}. When execution reaches {@link FunctionDefinitionNode#execute},
-     * {@code frame} will be accessible via {@code newFrame.getArguments()[0]}, and the execution
-     * will continue using {@code frame}.
-     */
-    private Object runCall(RootCallTarget callTarget, MaterializedFrame frame, boolean printResult, boolean topLevel) {
-        Object result = null;
-        try {
-            result = callTarget.call(frame);
-            assert checkResult(result);
-            if (printResult && result != null) {
-                assert topLevel;
-                if (context.isVisible()) {
-                    printResult(result);
-                }
-            }
-            if (topLevel) {
-                RErrorHandling.printWarnings(suppressWarnings);
-            }
-        } catch (RError e) {
-            throw e;
-        } catch (ReturnException ex) {
-            // condition handling can cause a "return" that needs to skip over this call
-            throw ex;
-        } catch (BreakException | NextException cfe) {
-            if (topLevel) {
-                throw RError.error(RError.SHOW_CALLER2, RError.Message.NO_LOOP_FOR_BREAK_NEXT);
-            } else {
-                // there can be an outer loop
-                throw cfe;
-            }
-        } catch (DebugExitException | BrowserQuitException e) {
-            throw e;
-        } catch (Throwable e) {
-            if (e instanceof Error) {
-                throw (Error) e;
-            } else if (e instanceof RuntimeException) {
-                throw (RuntimeException) e;
-            } else {
-                /* This should never happen given the logic in FunctionDefinitionNode.execute */
-                assert false;
-            }
-        }
-        return result;
-    }
-
     @TruffleBoundary
     private static boolean checkResult(Object result) {
         if (FastROptions.CheckResultCompleteness.getBooleanValue() && result instanceof RAbstractVector && ((RAbstractVector) result).isComplete()) {
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
index f2fbd83221e9080efa322fc5c2d47c5dd34f6b81..6174278a838279a3f60073a514a32ef2b2e2f60e 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
@@ -342,7 +342,7 @@ public class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
             return state.closePairList();
         } else if (obj instanceof RLanguage) {
             RLanguage lang = (RLanguage) obj;
-            RSyntaxNode node = (RSyntaxNode) lang.getRep();
+            RSyntaxNode node = lang.getRep().asRSyntaxNode();
             state.openPairList(SEXPTYPE.LANGSXP);
             node.serializeImpl(state);
             return state.closePairList();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastr/FastRContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastr/FastRContext.java
index 3da6259544ff280fbc41f23644c280681f0c8350..7d290f2181fb5587bd3268b0c89b62494871f84f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastr/FastRContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastr/FastRContext.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -257,4 +257,41 @@ public class FastRContext {
             return wrongChannelArg(this, id, "id");
         }
     }
+
+    public abstract static class ChannelPoll extends RExternalBuiltinNode.Arg1 {
+        @Specialization(guards = "id.getLength() == 1")
+        @TruffleBoundary
+        protected Object poll(RAbstractIntVector id) {
+            return RChannel.poll(id.getDataAt(0));
+        }
+
+        @Fallback
+        protected int error(Object id) {
+            return wrongChannelArg(this, id, "id");
+        }
+    }
+
+    public abstract static class ChannelSelect extends RExternalBuiltinNode.Arg1 {
+        @Specialization
+        @TruffleBoundary
+        protected RList select(RList nodes) {
+            int ind = 0;
+            int length = nodes.getLength();
+            while (true) {
+                Object o = nodes.getDataAt(ind);
+                ind = (ind + 1) % length;
+                int id;
+                if (o instanceof Integer) {
+                    id = (int) o;
+                } else {
+                    id = ((RIntVector) o).getDataAt(0);
+                }
+                Object res = RChannel.poll(id);
+                if (res != null) {
+                    return RDataFactory.createList(new Object[]{id, res});
+                }
+            }
+        }
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/MissingPrinter.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/parallel/ParallelFunctions.java
similarity index 62%
rename from com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/MissingPrinter.java
rename to com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/parallel/ParallelFunctions.java
index cf4a712f9d9f4cd57c34f769f54041975af986f3..4e09a92391428984e0528ec4fd5565e5d1b87313 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/MissingPrinter.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/parallel/ParallelFunctions.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -20,19 +20,22 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.builtin.base.printer;
+package com.oracle.truffle.r.library.parallel;
 
-import java.io.IOException;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.r.nodes.builtin.*;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.context.RContext;
 
-import com.oracle.truffle.r.runtime.data.RExternalPtr;
-
-public final class MissingPrinter extends AbstractValuePrinter<RExternalPtr> {
-
-    public static final MissingPrinter INSTANCE = new MissingPrinter();
-
-    @Override
-    protected void printValue(RExternalPtr value, PrintContext printCtx) throws IOException {
-        printCtx.output().print(String.format("<pointer: %#x>", value.getAddr()));
+/**
+ * The .Call support for the parallel package.
+ */
+public class ParallelFunctions {
+    public abstract static class MCIsChild extends RExternalBuiltinNode.Arg0 {
+        @Specialization
+        protected byte mcIsChild() {
+            return RRuntime.asLogical(RContext.getInstance().getParent() != null);
+        }
     }
 
 }
diff --git a/com.oracle.truffle.r.native/library/fastr/src/R/fastr.R b/com.oracle.truffle.r.native/library/fastr/src/R/fastr.R
index 7a16c7dc9f154638758cb9c9f76804da2dd831da..11019e1c3f1bd4ecdbbd9555b6bbfb2e6f580e90 100644
--- a/com.oracle.truffle.r.native/library/fastr/src/R/fastr.R
+++ b/com.oracle.truffle.r.native/library/fastr/src/R/fastr.R
@@ -146,6 +146,14 @@ fastr.channel.receive <- function(id) {
 	.FastR(.NAME="fastr.channel.receive", id)
 }
 
+fastr.channel.poll <- function(id) {
+	.FastR(.NAME="fastr.channel.poll", id)
+}
+
+fastr.channel.select <- function(ids) {
+	.FastR(.NAME="fastr.channel.select", ids)
+}
+
 fastr.throw <- function(name) {
 	.FastR(.NAME="fastr.throw", name)
 }
diff --git a/com.oracle.truffle.r.native/library/lib.mk b/com.oracle.truffle.r.native/library/lib.mk
index 6384272ca6d3e11eee64a3ea4efbf5864d558c2d..4ca0f7eeaf79f45f52e5abb79efeb1bd1f577d37 100644
--- a/com.oracle.truffle.r.native/library/lib.mk
+++ b/com.oracle.truffle.r.native/library/lib.mk
@@ -69,7 +69,8 @@ LIB_PKG := $(OBJ)/$(PKG).so
 JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/$(JDK_OS_DIR)
 FFI_INCLUDES = -I$(TOPDIR)/include -I$(TOPDIR)/include/R_ext
 
-INCLUDES := $(JNI_INCLUDES) $(FFI_INCLUDES)
+#$(info PKG_INCLUDES=$(PKG_INCLUDES))
+INCLUDES := $(JNI_INCLUDES) $(FFI_INCLUDES) $(PKG_INCLUDES)
 
 PKGDIR := $(FASTR_LIBRARY_DIR)/$(PKG)
 
diff --git a/com.oracle.truffle.r.native/library/methods/src/methods_dummy.c b/com.oracle.truffle.r.native/library/methods/src/methods_dummy.c
index 41655a18adedc7bfbbbbab51ed6657bce3920bb7..b3ec4177a8064af97c1b699ffbb44898113d87f6 100644
--- a/com.oracle.truffle.r.native/library/methods/src/methods_dummy.c
+++ b/com.oracle.truffle.r.native/library/methods/src/methods_dummy.c
@@ -19,35 +19,33 @@
 
 #include <Rinternals.h>
 
-static void unimplemented_methods() {
-	error("unimplemented methods .External");
-}
+#define UNIMPLEMENTED { error("unimplemented function at %s:%d", __FILE__, __LINE__); return NULL; }
 
 
 SEXP R_M_setPrimitiveMethods(SEXP fname, SEXP op, SEXP code_vec,
-			     SEXP fundef, SEXP mlist){ unimplemented_methods(); return NULL; }
-SEXP R_clear_method_selection(){ unimplemented_methods(); return NULL; }
-SEXP R_dummy_extern_place(){ unimplemented_methods(); return NULL; }
-SEXP R_el_named(SEXP object, SEXP what){ unimplemented_methods(); return NULL; }
-SEXP R_externalptr_prototype_object(){ unimplemented_methods(); return NULL; }
-SEXP R_getGeneric(SEXP name, SEXP mustFind, SEXP env, SEXP package){ unimplemented_methods(); return NULL; }
-SEXP R_get_slot(SEXP obj, SEXP name){ unimplemented_methods(); return NULL; }
-SEXP R_getClassFromCache(SEXP class, SEXP table){ unimplemented_methods(); return NULL; }
-SEXP R_hasSlot(SEXP obj, SEXP name){ unimplemented_methods(); return NULL; }
-SEXP R_identC(SEXP e1, SEXP e2){ unimplemented_methods(); return NULL; }
-SEXP R_initMethodDispatch(SEXP envir){ unimplemented_methods(); return NULL; }
-SEXP R_methodsPackageMetaName(SEXP prefix, SEXP name, SEXP pkg){ unimplemented_methods(); return NULL; }
-SEXP R_methods_test_MAKE_CLASS(SEXP className){ unimplemented_methods(); return NULL; }
-SEXP R_methods_test_NEW(SEXP className){ unimplemented_methods(); return NULL; }
-SEXP R_missingArg(SEXP symbol, SEXP ev){ unimplemented_methods(); return NULL; }
-SEXP R_nextMethodCall(SEXP matched_call, SEXP ev){ unimplemented_methods(); return NULL; }
-SEXP R_quick_method_check(SEXP args, SEXP mlist, SEXP fdef){ unimplemented_methods(); return NULL; }
-SEXP R_selectMethod(SEXP fname, SEXP ev, SEXP mlist, SEXP evalArgs){ unimplemented_methods(); return NULL; }
-SEXP R_set_el_named(SEXP object, SEXP what, SEXP value){ unimplemented_methods(); return NULL; }
-SEXP R_set_slot(SEXP obj, SEXP name, SEXP value){ unimplemented_methods(); return NULL; }
-SEXP R_standardGeneric(SEXP fname, SEXP ev, SEXP fdef){ unimplemented_methods(); return NULL; }
-SEXP do_substitute_direct(SEXP f, SEXP env){ unimplemented_methods(); return NULL; }
-SEXP Rf_allocS4Object(){ unimplemented_methods(); return NULL; }
-SEXP R_set_method_dispatch(SEXP onOff){ unimplemented_methods(); return NULL; }
-SEXP R_get_primname(SEXP object){ unimplemented_methods(); return NULL; }
-SEXP new_object(SEXP class_def){ unimplemented_methods(); return NULL; }
+			     SEXP fundef, SEXP mlist) UNIMPLEMENTED
+SEXP R_clear_method_selection() UNIMPLEMENTED
+SEXP R_dummy_extern_place() UNIMPLEMENTED
+SEXP R_el_named(SEXP object, SEXP what) UNIMPLEMENTED
+SEXP R_externalptr_prototype_object() UNIMPLEMENTED
+SEXP R_getGeneric(SEXP name, SEXP mustFind, SEXP env, SEXP package) UNIMPLEMENTED
+SEXP R_get_slot(SEXP obj, SEXP name) UNIMPLEMENTED
+SEXP R_getClassFromCache(SEXP class, SEXP table) UNIMPLEMENTED
+SEXP R_hasSlot(SEXP obj, SEXP name) UNIMPLEMENTED
+SEXP R_identC(SEXP e1, SEXP e2) UNIMPLEMENTED
+SEXP R_initMethodDispatch(SEXP envir) UNIMPLEMENTED
+SEXP R_methodsPackageMetaName(SEXP prefix, SEXP name, SEXP pkg) UNIMPLEMENTED
+SEXP R_methods_test_MAKE_CLASS(SEXP className) UNIMPLEMENTED
+SEXP R_methods_test_NEW(SEXP className) UNIMPLEMENTED
+SEXP R_missingArg(SEXP symbol, SEXP ev) UNIMPLEMENTED
+SEXP R_nextMethodCall(SEXP matched_call, SEXP ev) UNIMPLEMENTED
+SEXP R_quick_method_check(SEXP args, SEXP mlist, SEXP fdef) UNIMPLEMENTED
+SEXP R_selectMethod(SEXP fname, SEXP ev, SEXP mlist, SEXP evalArgs) UNIMPLEMENTED
+SEXP R_set_el_named(SEXP object, SEXP what, SEXP value) UNIMPLEMENTED
+SEXP R_set_slot(SEXP obj, SEXP name, SEXP value) UNIMPLEMENTED
+SEXP R_standardGeneric(SEXP fname, SEXP ev, SEXP fdef) UNIMPLEMENTED
+SEXP do_substitute_direct(SEXP f, SEXP env) UNIMPLEMENTED
+SEXP Rf_allocS4Object() UNIMPLEMENTED
+SEXP R_set_method_dispatch(SEXP onOff) UNIMPLEMENTED
+SEXP R_get_primname(SEXP object) UNIMPLEMENTED
+SEXP new_object(SEXP class_def) UNIMPLEMENTED
diff --git a/com.oracle.truffle.r.native/library/parallel/Makefile b/com.oracle.truffle.r.native/library/parallel/Makefile
index f128fcf8a4ea847d045bd6a86eda6d24ffe6ae27..5d2ca990c9ed3e25fd3ed36f3ac8802d406ca5e2 100644
--- a/com.oracle.truffle.r.native/library/parallel/Makefile
+++ b/com.oracle.truffle.r.native/library/parallel/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 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
@@ -21,4 +21,17 @@
 # questions.
 #
 
+OBJ = lib
+
+GNUR_C_FILES = init.c
+
+GNUR_C_OBJECTS := $(addprefix $(OBJ)/, $(GNUR_C_FILES:.c=.o))
+
+PKG_INCLUDES = -I $(GNUR_SRC)
+
 include ../lib.mk
+
+$(C_OBJECTS): | $(OBJ)
+
+$(OBJ)/%.o: $(GNUR_SRC)/%.c
+	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
diff --git a/com.oracle.truffle.r.native/library/parallel/src/init.c b/com.oracle.truffle.r.native/library/parallel/src/init.c
deleted file mode 100644
index 0d9658a073a83850d67ff7ff987d339fd01d4f3b..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.native/library/parallel/src/init.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *  R : A Computer Language for Statistical Data Analysis
- *  Copyright (C) 2011   The R Core Team.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program 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 for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, a copy is available at
- *  http://www.r-project.org/Licenses/
- */
-
-#include <R.h>
-#include "parallel.h"
-#include <R_ext/Rdynload.h>
-
-static const R_CallMethodDef callMethods[] = {
-    {"nextStream", (DL_FUNC) &nextStream, 1},
-    {"nextSubStream", (DL_FUNC) &nextSubStream, 1},
-#ifndef _WIN32
-#ifndef FASTR
-    {"mc_children", (DL_FUNC) &mc_children, 0},
-    {"mc_close_fds", (DL_FUNC) &mc_close_fds, 1},
-    {"mc_close_stderr", (DL_FUNC) &mc_close_stderr, 1},
-    {"mc_close_stdout", (DL_FUNC) &mc_close_stdout, 1},
-    {"mc_exit", (DL_FUNC) &mc_exit, 1},
-    {"mc_fds", (DL_FUNC) &mc_fds, 1},
-    {"mc_fork", (DL_FUNC) &mc_fork, 1},
-    {"mc_is_child", (DL_FUNC) &mc_is_child, 0},
-    {"mc_kill", (DL_FUNC) &mc_kill, 2},
-    {"mc_master_fd", (DL_FUNC) &mc_master_fd, 0},
-    {"mc_read_child", (DL_FUNC) &mc_read_child, 1},
-    {"mc_read_children", (DL_FUNC) &mc_read_children, 1},
-    {"mc_rm_child", (DL_FUNC) &mc_rm_child, 1},
-    {"mc_send_master", (DL_FUNC) &mc_send_master, 1},
-    {"mc_select_children", (DL_FUNC) &mc_select_children, 2},
-    {"mc_send_child_stdin", (DL_FUNC) &mc_send_child_stdin, 2},
-    {"mc_affinity", (DL_FUNC) &mc_affinity, 1},
-    {"mc_interactive", (DL_FUNC) &mc_interactive, 1},
-#endif
-#else
-    {"ncpus", (DL_FUNC) &ncpus, 1},
-#endif
-    {NULL, NULL, 0}
-};
-
-void
-#ifdef HAVE_VISIBILITY_ATTRIBUTE
-__attribute__ ((visibility ("default")))
-#endif
-R_init_parallel(DllInfo *dll)
-{
-    R_registerRoutines(dll, NULL, callMethods, NULL, NULL);
-    R_useDynamicSymbols(dll, FALSE);
-}
diff --git a/com.oracle.truffle.r.native/library/parallel/src/parallel.h b/com.oracle.truffle.r.native/library/parallel/src/parallel.h
deleted file mode 100644
index d1a6f8ad0bb1bb7b84728302a93867636915f0af..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.native/library/parallel/src/parallel.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *  R : A Computer Language for Statistical Data Analysis
- *  Copyright (C) 2011   The R Core Team.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program 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 for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, a copy is available at
- *  http://www.r-project.org/Licenses/
- */
-
-#ifndef R_PARALLEL_H
-#define R_PARALLEL_H
-
-#include <Rinternals.h>
-#ifdef ENABLE_NLS
-#include <libintl.h>
-#define _(String) dgettext ("parallel", String)
-#else
-#define _(String) (String)
-#endif
-
-SEXP nextStream(SEXP);
-SEXP nextSubStream(SEXP);
-
-#ifndef _WIN32
-SEXP mc_children(void);
-SEXP mc_close_fds(SEXP);
-SEXP mc_close_stderr(SEXP);
-SEXP mc_close_stdout(SEXP);
-SEXP mc_create_list(SEXP);
-SEXP mc_exit(SEXP);
-SEXP mc_fds(SEXP);
-SEXP mc_fork(SEXP);
-SEXP mc_is_child(void);
-SEXP mc_kill(SEXP, SEXP);
-SEXP mc_master_fd(void);
-SEXP mc_read_child(SEXP);
-SEXP mc_read_children(SEXP);
-SEXP mc_rm_child(SEXP);
-SEXP mc_send_master(SEXP);
-SEXP mc_select_children(SEXP, SEXP);
-SEXP mc_send_child_stdin(SEXP, SEXP);
-SEXP mc_affinity(SEXP);
-SEXP mc_interactive(SEXP);
-#else
-SEXP ncpus(SEXP);
-#endif
-
-#endif
diff --git a/com.oracle.truffle.r.native/library/parallel/src/parallel_dummy.c b/com.oracle.truffle.r.native/library/parallel/src/parallel_dummy.c
new file mode 100644
index 0000000000000000000000000000000000000000..71d0a3e628ed0611b767774bdc4cb0bf23d495f3
--- /dev/null
+++ b/com.oracle.truffle.r.native/library/parallel/src/parallel_dummy.c
@@ -0,0 +1,46 @@
+/*
+ *  R : A Computer Language for Statistical Data Analysis
+ *  Copyright (C) 2005-12   The R Core Team.
+ *
+ *  This program is free software{ return NULL UNIMPLEMENTED } you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation{ return NULL UNIMPLEMENTED } either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY{ return NULL UNIMPLEMENTED } without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program{ return NULL UNIMPLEMENTED } if not, a copy is available at
+ *  http://www.r-project.org/Licenses/
+ */
+
+#include <Rinternals.h>
+
+#define UNIMPLEMENTED { error("unimplemented function at %s:%d", __FILE__, __LINE__); return NULL; }
+
+#ifndef _WIN32
+SEXP mc_children() UNIMPLEMENTED
+SEXP mc_close_fds(SEXP a) UNIMPLEMENTED
+SEXP mc_close_stderr(SEXP a) UNIMPLEMENTED
+SEXP mc_close_stdout(SEXP a) UNIMPLEMENTED
+SEXP mc_create_list(SEXP a) UNIMPLEMENTED
+SEXP mc_exit(SEXP a) UNIMPLEMENTED
+SEXP mc_fds(SEXP a) UNIMPLEMENTED
+SEXP mc_fork(SEXP a) UNIMPLEMENTED
+SEXP mc_is_child(void) UNIMPLEMENTED
+SEXP mc_kill(SEXP a, SEXP b) UNIMPLEMENTED
+SEXP mc_master_fd(void) UNIMPLEMENTED
+SEXP mc_read_child(SEXP a) UNIMPLEMENTED
+SEXP mc_read_children(SEXP a) UNIMPLEMENTED
+SEXP mc_rm_child(SEXP a) UNIMPLEMENTED
+SEXP mc_send_master(SEXP a) UNIMPLEMENTED
+SEXP mc_select_children(SEXP a, SEXP b) UNIMPLEMENTED
+SEXP mc_send_child_stdin(SEXP a, SEXP b) UNIMPLEMENTED
+SEXP mc_affinity(SEXP a) UNIMPLEMENTED
+SEXP mc_interactive(SEXP a) UNIMPLEMENTED
+#else
+SEXP ncpus(SEXP a) UNIMPLEMENTED
+#endif
diff --git a/com.oracle.truffle.r.native/library/stats/Makefile b/com.oracle.truffle.r.native/library/stats/Makefile
index b610f2876bf61b7ab9060635286b8606c5f7abc2..338aa50c549ddc1ce803e6099557169b4c5e2d65 100644
--- a/com.oracle.truffle.r.native/library/stats/Makefile
+++ b/com.oracle.truffle.r.native/library/stats/Makefile
@@ -41,6 +41,7 @@ include $(TOPDIR)/platform.mk
 endif
 
 PKG_LIBS := $(LAPACK_LIBS) $(BLAS_LIBS) -L$(FASTR_LIB_DIR) $(FLIBS)
+PKG_INCLUDES = -I $(GNUR_SRC)
 
 OBJ = lib
 
diff --git a/com.oracle.truffle.r.native/library/stats/src/gnur_extracts.c b/com.oracle.truffle.r.native/library/stats/src/gnur_extracts.c
index 4f71911dc6bc4ceff6a1edee4b81b0180917695a..eec34fc49afeb4c9752241400bb714fd7f1d5469 100644
--- a/com.oracle.truffle.r.native/library/stats/src/gnur_extracts.c
+++ b/com.oracle.truffle.r.native/library/stats/src/gnur_extracts.c
@@ -24,7 +24,7 @@
 #include "nls.h"
 #include "port.h"
 #include "stats.h"
-#include "statsR.h"
+#include <statsR.h>
 #include "ts.h"
 #include <R_ext/Rdynload.h>
 #include <R_ext/Visibility.h>
diff --git a/com.oracle.truffle.r.native/library/stats/src/statsR.h b/com.oracle.truffle.r.native/library/stats/src/statsR.h
deleted file mode 100644
index 0a12612ffbeb3f0753dd90371a638293c79ddaf9..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.native/library/stats/src/statsR.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- *  R : A Computer Language for Statistical Data Analysis
- *  Copyright (C) 2012   The R Core Team.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program 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 for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, a copy is available at
- *  http://www.r-project.org/Licenses/
- */
-
-/* auxiliary */
-static void unimplemented_stats() {
-	error("unimplemented stats .External");
-}
-
-SEXP getListElement(SEXP list, char *str) { unimplemented_stats(); return NULL; }
-
-/* Declarations for .Call entry points */
-
-SEXP logit_link(SEXP mu) { unimplemented_stats(); return NULL; }
-SEXP logit_linkinv(SEXP eta) { unimplemented_stats(); return NULL; }
-SEXP logit_mu_eta(SEXP eta) { unimplemented_stats(); return NULL; }
-SEXP binomial_dev_resids(SEXP y, SEXP mu, SEXP wt) { unimplemented_stats(); return NULL; }
-
-SEXP cutree(SEXP merge, SEXP which) { unimplemented_stats(); return NULL; }
-SEXP rWishart(SEXP ns, SEXP nuP, SEXP scal) { unimplemented_stats(); return NULL; }
-SEXP Cdqrls(SEXP x, SEXP y, SEXP tol, SEXP chk) { unimplemented_stats(); return NULL; }
-SEXP Cdist(SEXP x, SEXP method, SEXP attrs, SEXP p) { unimplemented_stats(); return NULL; }
-SEXP r2dtable(SEXP n, SEXP r, SEXP c) { unimplemented_stats(); return NULL; }
-SEXP cor(SEXP x, SEXP y, SEXP na_method, SEXP method) { unimplemented_stats(); return NULL; }
-SEXP cov(SEXP x, SEXP y, SEXP na_method, SEXP method) { unimplemented_stats(); return NULL; }
-SEXP updateform(SEXP old, SEXP new) { unimplemented_stats(); return NULL; }
-SEXP fft(SEXP z, SEXP inverse) { unimplemented_stats(); return NULL; }
-SEXP mvfft(SEXP z, SEXP inverse) { unimplemented_stats(); return NULL; }
-SEXP nextn(SEXP n, SEXP factors) { unimplemented_stats(); return NULL; }
-
-SEXP cfilter(SEXP sx, SEXP sfilter, SEXP ssides, SEXP scircular) { unimplemented_stats(); return NULL; }
-SEXP rfilter(SEXP x, SEXP filter, SEXP out) { unimplemented_stats(); return NULL; }
-SEXP lowess(SEXP x, SEXP y, SEXP sf, SEXP siter, SEXP sdelta) { unimplemented_stats(); return NULL; }
-SEXP DoubleCentre(SEXP A) { unimplemented_stats(); return NULL; }
-SEXP BinDist(SEXP x, SEXP weights, SEXP slo, SEXP sup, SEXP sn) { unimplemented_stats(); return NULL; }
-
-/* Declarations for .External[2] entry points */
-
-SEXP compcases(SEXP args) { unimplemented_stats(); return NULL; }
-SEXP doD(SEXP args) { unimplemented_stats(); return NULL; }
-SEXP deriv(SEXP args) { unimplemented_stats(); return NULL; }
-SEXP modelframe(SEXP call, SEXP op, SEXP args, SEXP rho) { unimplemented_stats(); return NULL; }
-SEXP modelmatrix(SEXP call, SEXP op, SEXP args, SEXP rho) { unimplemented_stats(); return NULL; }
-SEXP termsform(SEXP args) { unimplemented_stats(); return NULL; }
-SEXP do_fmin(SEXP call, SEXP op, SEXP args, SEXP rho) { unimplemented_stats(); return NULL; }
-SEXP nlm(SEXP call, SEXP op, SEXP args, SEXP rho) { unimplemented_stats(); return NULL; }
-SEXP zeroin2(SEXP call, SEXP op, SEXP args, SEXP rho) { unimplemented_stats(); return NULL; }
-SEXP optim(SEXP call, SEXP op, SEXP args, SEXP rho) { unimplemented_stats(); return NULL; }
-SEXP optimhess(SEXP call, SEXP op, SEXP args, SEXP rho) { unimplemented_stats(); return NULL; }
-SEXP Rmultinom(SEXP args) { unimplemented_stats(); return NULL; }
-SEXP call_dqagi(SEXP x) { unimplemented_stats(); return NULL; }
-SEXP call_dqags(SEXP x) { unimplemented_stats(); return NULL; }
-SEXP Random1(SEXP args) { unimplemented_stats(); return NULL; }
-SEXP Random2(SEXP args) { unimplemented_stats(); ; return NULL; }
-SEXP Random3(SEXP args) { unimplemented_stats(); return NULL; }
-SEXP distn2(SEXP args) { unimplemented_stats(); return NULL; }
-SEXP distn3(SEXP args) { unimplemented_stats(); return NULL; }
-SEXP distn4(SEXP args) { unimplemented_stats(); return NULL; }
-
-SEXP Rsm(SEXP x, SEXP stype, SEXP send) { unimplemented_stats(); return NULL; }
-SEXP tukeyline(SEXP x, SEXP y, SEXP call) { unimplemented_stats(); return NULL; }
-SEXP runmed(SEXP x, SEXP stype, SEXP sk, SEXP end, SEXP print_level) { unimplemented_stats(); return NULL; }
-SEXP influence(SEXP mqr, SEXP do_coef, SEXP e, SEXP stol) { unimplemented_stats(); return NULL; }
-
-SEXP pSmirnov2x(SEXP statistic, SEXP snx, SEXP sny) { unimplemented_stats(); return NULL; }
-SEXP pKolmogorov2x(SEXP statistic, SEXP sn) { unimplemented_stats(); return NULL; }
-SEXP pKS2(SEXP sn, SEXP stol) { unimplemented_stats(); return NULL; }
-
-SEXP ksmooth(SEXP x, SEXP y, SEXP snp, SEXP skrn, SEXP sbw) { unimplemented_stats(); return NULL; }
-
-SEXP SplineCoef(SEXP method, SEXP x, SEXP y) { unimplemented_stats(); return NULL; }
-SEXP SplineEval(SEXP xout, SEXP z) { unimplemented_stats(); return NULL; }
-
-SEXP ApproxTest(SEXP x, SEXP y, SEXP method, SEXP sf) { unimplemented_stats(); return NULL; }
-SEXP Approx(SEXP x, SEXP y, SEXP v, SEXP method,
-	    SEXP yleft, SEXP yright, SEXP sf) { unimplemented_stats(); return NULL; }
-
-SEXP LogLin(SEXP dtab, SEXP conf, SEXP table, SEXP start,
-	    SEXP snmar, SEXP eps, SEXP iter) { unimplemented_stats(); return NULL; }
-
-SEXP pAnsari(SEXP q, SEXP sm, SEXP sn) { unimplemented_stats(); return NULL; }
-SEXP qAnsari(SEXP p, SEXP sm, SEXP sn) { unimplemented_stats(); return NULL; }
-SEXP pKendall(SEXP q, SEXP sn) { unimplemented_stats(); return NULL; }
-SEXP pRho(SEXP q, SEXP sn, SEXP lower) { unimplemented_stats(); return NULL; }
-SEXP SWilk(SEXP x) { unimplemented_stats(); return NULL; }
-
-SEXP bw_den(SEXP nbin, SEXP sx) { unimplemented_stats(); return NULL; }
-SEXP bw_ucv(SEXP sn, SEXP sd, SEXP cnt, SEXP sh) { unimplemented_stats(); return NULL; }
-SEXP bw_bcv(SEXP sn, SEXP sd, SEXP cnt, SEXP sh) { unimplemented_stats(); return NULL; }
-SEXP bw_phi4(SEXP sn, SEXP sd, SEXP cnt, SEXP sh) { unimplemented_stats(); return NULL; }
-SEXP bw_phi6(SEXP sn, SEXP sd, SEXP cnt, SEXP sh) { unimplemented_stats(); return NULL; }
-
-SEXP Fexact(SEXP x, SEXP pars, SEXP work, SEXP smult) { unimplemented_stats(); return NULL; }
-SEXP Fisher_sim(SEXP sr, SEXP sc, SEXP sB) { unimplemented_stats(); return NULL; }
-SEXP chisq_sim(SEXP sr, SEXP sc, SEXP sB, SEXP E) { unimplemented_stats(); return NULL; }
-SEXP d2x2xk(SEXP sK, SEXP sm, SEXP sn, SEXP st, SEXP srn) { unimplemented_stats(); return NULL; }
-
-SEXP stats_signrank_free(void) { unimplemented_stats(); return NULL; }
-SEXP stats_wilcox_free(void) { unimplemented_stats(); return NULL; }
diff --git a/com.oracle.truffle.r.native/library/stats/src/statsR_dummy.c b/com.oracle.truffle.r.native/library/stats/src/statsR_dummy.c
new file mode 100644
index 0000000000000000000000000000000000000000..db2d3e5f172dd74ab4a93c2af654ff33fdd69c3d
--- /dev/null
+++ b/com.oracle.truffle.r.native/library/stats/src/statsR_dummy.c
@@ -0,0 +1,113 @@
+/*
+ *  R : A Computer Language for Statistical Data Analysis
+ *  Copyright (C) 2012   The R Core Team.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, a copy is available at
+ *  http://www.r-project.org/Licenses/
+ */
+
+#include <Rinternals.h>
+
+#define UNIMPLEMENTED { error("unimplemented function at %s:%d", __FILE__, __LINE__); return NULL; }
+
+SEXP getListElement(SEXP list, char *str) UNIMPLEMENTED
+
+/* Declarations for .Call entry points */
+
+SEXP logit_link(SEXP mu) UNIMPLEMENTED
+SEXP logit_linkinv(SEXP eta) UNIMPLEMENTED
+SEXP logit_mu_eta(SEXP eta) UNIMPLEMENTED
+SEXP binomial_dev_resids(SEXP y, SEXP mu, SEXP wt) UNIMPLEMENTED
+
+SEXP cutree(SEXP merge, SEXP which) UNIMPLEMENTED
+SEXP rWishart(SEXP ns, SEXP nuP, SEXP scal) UNIMPLEMENTED
+SEXP Cdqrls(SEXP x, SEXP y, SEXP tol, SEXP chk) UNIMPLEMENTED
+SEXP Cdist(SEXP x, SEXP method, SEXP attrs, SEXP p) UNIMPLEMENTED
+SEXP r2dtable(SEXP n, SEXP r, SEXP c) UNIMPLEMENTED
+SEXP cor(SEXP x, SEXP y, SEXP na_method, SEXP method) UNIMPLEMENTED
+SEXP cov(SEXP x, SEXP y, SEXP na_method, SEXP method) UNIMPLEMENTED
+SEXP updateform(SEXP old, SEXP new) UNIMPLEMENTED
+SEXP fft(SEXP z, SEXP inverse) UNIMPLEMENTED
+SEXP mvfft(SEXP z, SEXP inverse) UNIMPLEMENTED
+SEXP nextn(SEXP n, SEXP factors) UNIMPLEMENTED
+
+SEXP cfilter(SEXP sx, SEXP sfilter, SEXP ssides, SEXP scircular) UNIMPLEMENTED
+SEXP rfilter(SEXP x, SEXP filter, SEXP out) UNIMPLEMENTED
+SEXP lowess(SEXP x, SEXP y, SEXP sf, SEXP siter, SEXP sdelta) UNIMPLEMENTED
+SEXP DoubleCentre(SEXP A) UNIMPLEMENTED
+SEXP BinDist(SEXP x, SEXP weights, SEXP slo, SEXP sup, SEXP sn) UNIMPLEMENTED
+
+/* Declarations for .External[2] entry points */
+
+SEXP compcases(SEXP args) UNIMPLEMENTED
+SEXP doD(SEXP args) UNIMPLEMENTED
+SEXP deriv(SEXP args) UNIMPLEMENTED
+SEXP modelframe(SEXP call, SEXP op, SEXP args, SEXP rho) UNIMPLEMENTED
+SEXP modelmatrix(SEXP call, SEXP op, SEXP args, SEXP rho) UNIMPLEMENTED
+SEXP termsform(SEXP args) UNIMPLEMENTED
+SEXP do_fmin(SEXP call, SEXP op, SEXP args, SEXP rho) UNIMPLEMENTED
+SEXP nlm(SEXP call, SEXP op, SEXP args, SEXP rho) UNIMPLEMENTED
+SEXP zeroin2(SEXP call, SEXP op, SEXP args, SEXP rho) UNIMPLEMENTED
+SEXP optim(SEXP call, SEXP op, SEXP args, SEXP rho) UNIMPLEMENTED
+SEXP optimhess(SEXP call, SEXP op, SEXP args, SEXP rho) UNIMPLEMENTED
+SEXP Rmultinom(SEXP args) UNIMPLEMENTED
+SEXP call_dqagi(SEXP x) UNIMPLEMENTED
+SEXP call_dqags(SEXP x) UNIMPLEMENTED
+SEXP Random1(SEXP args) UNIMPLEMENTED
+SEXP Random2(SEXP args) UNIMPLEMENTED
+SEXP Random3(SEXP args) UNIMPLEMENTED
+SEXP distn2(SEXP args) UNIMPLEMENTED
+SEXP distn3(SEXP args) UNIMPLEMENTED
+SEXP distn4(SEXP args) UNIMPLEMENTED
+
+SEXP Rsm(SEXP x, SEXP stype, SEXP send) UNIMPLEMENTED
+SEXP tukeyline(SEXP x, SEXP y, SEXP call) UNIMPLEMENTED
+SEXP runmed(SEXP x, SEXP stype, SEXP sk, SEXP end, SEXP print_level) UNIMPLEMENTED
+SEXP influence(SEXP mqr, SEXP do_coef, SEXP e, SEXP stol) UNIMPLEMENTED
+
+SEXP pSmirnov2x(SEXP statistic, SEXP snx, SEXP sny) UNIMPLEMENTED
+SEXP pKolmogorov2x(SEXP statistic, SEXP sn) UNIMPLEMENTED
+SEXP pKS2(SEXP sn, SEXP stol) UNIMPLEMENTED
+
+SEXP ksmooth(SEXP x, SEXP y, SEXP snp, SEXP skrn, SEXP sbw) UNIMPLEMENTED
+
+SEXP SplineCoef(SEXP method, SEXP x, SEXP y) UNIMPLEMENTED
+SEXP SplineEval(SEXP xout, SEXP z) UNIMPLEMENTED
+
+SEXP ApproxTest(SEXP x, SEXP y, SEXP method, SEXP sf) UNIMPLEMENTED
+SEXP Approx(SEXP x, SEXP y, SEXP v, SEXP method,
+	    SEXP yleft, SEXP yright, SEXP sf) UNIMPLEMENTED
+
+SEXP LogLin(SEXP dtab, SEXP conf, SEXP table, SEXP start,
+	    SEXP snmar, SEXP eps, SEXP iter) UNIMPLEMENTED
+
+SEXP pAnsari(SEXP q, SEXP sm, SEXP sn) UNIMPLEMENTED
+SEXP qAnsari(SEXP p, SEXP sm, SEXP sn) UNIMPLEMENTED
+SEXP pKendall(SEXP q, SEXP sn) UNIMPLEMENTED
+SEXP pRho(SEXP q, SEXP sn, SEXP lower) UNIMPLEMENTED
+SEXP SWilk(SEXP x) UNIMPLEMENTED
+
+SEXP bw_den(SEXP nbin, SEXP sx) UNIMPLEMENTED
+SEXP bw_ucv(SEXP sn, SEXP sd, SEXP cnt, SEXP sh) UNIMPLEMENTED
+SEXP bw_bcv(SEXP sn, SEXP sd, SEXP cnt, SEXP sh) UNIMPLEMENTED
+SEXP bw_phi4(SEXP sn, SEXP sd, SEXP cnt, SEXP sh) UNIMPLEMENTED
+SEXP bw_phi6(SEXP sn, SEXP sd, SEXP cnt, SEXP sh) UNIMPLEMENTED
+
+SEXP Fexact(SEXP x, SEXP pars, SEXP work, SEXP smult) UNIMPLEMENTED
+SEXP Fisher_sim(SEXP sr, SEXP sc, SEXP sB) UNIMPLEMENTED
+SEXP chisq_sim(SEXP sr, SEXP sc, SEXP sB, SEXP E) UNIMPLEMENTED
+SEXP d2x2xk(SEXP sK, SEXP sm, SEXP sn, SEXP st, SEXP srn) UNIMPLEMENTED
+
+SEXP stats_signrank_free(void) UNIMPLEMENTED
+SEXP stats_wilcox_free(void) UNIMPLEMENTED
diff --git a/com.oracle.truffle.r.native/library/tools/src/tools_dummy.c b/com.oracle.truffle.r.native/library/tools/src/tools_dummy.c
index 9f01bde84e3d0c8577f69cfb88c352857a28e349..42e67576e5c0ed1ea7dbacce5bb2f59acddbef99 100644
--- a/com.oracle.truffle.r.native/library/tools/src/tools_dummy.c
+++ b/com.oracle.truffle.r.native/library/tools/src/tools_dummy.c
@@ -19,25 +19,23 @@
 
 #include <Rinternals.h>
 
-static void unimplemented_tools() {
-	error("unimplemented tools .External");
-}
+#define UNIMPLEMENTED { error("unimplemented function at %s:%d", __FILE__, __LINE__); return NULL; }
 
-SEXP delim_match(SEXP x, SEXP delims) { unimplemented_tools(); return NULL; }
-SEXP dirchmod(SEXP dr) { unimplemented_tools(); return NULL; }
-SEXP Rmd5(SEXP files) { unimplemented_tools(); return NULL; }
-SEXP check_nonASCII(SEXP text, SEXP ignore_quotes) { unimplemented_tools(); return NULL; }
-SEXP check_nonASCII2(SEXP text) { unimplemented_tools(); return NULL; }
-SEXP doTabExpand(SEXP strings, SEXP starts) { unimplemented_tools(); return NULL; }
-SEXP ps_kill(SEXP pid, SEXP signal) { unimplemented_tools(); return NULL; }
-SEXP ps_sigs(SEXP pid) { unimplemented_tools(); return NULL; }
-SEXP ps_priority(SEXP pid, SEXP value) { unimplemented_tools(); return NULL; }
-SEXP codeFilesAppend(SEXP f1, SEXP f2) { unimplemented_tools(); return NULL; }
-SEXP getfmts(SEXP format) { unimplemented_tools(); return NULL; }
-SEXP startHTTPD(SEXP sIP, SEXP sPort) { unimplemented_tools(); return NULL; }
-SEXP stopHTTPD(void) { unimplemented_tools(); return NULL; }
+SEXP delim_match(SEXP x, SEXP delims) UNIMPLEMENTED
+SEXP dirchmod(SEXP dr) UNIMPLEMENTED
+SEXP Rmd5(SEXP files) UNIMPLEMENTED
+SEXP check_nonASCII(SEXP text, SEXP ignore_quotes) UNIMPLEMENTED
+SEXP check_nonASCII2(SEXP text) UNIMPLEMENTED
+SEXP doTabExpand(SEXP strings, SEXP starts) UNIMPLEMENTED
+SEXP ps_kill(SEXP pid, SEXP signal) UNIMPLEMENTED
+SEXP ps_sigs(SEXP pid) UNIMPLEMENTED
+SEXP ps_priority(SEXP pid, SEXP value) UNIMPLEMENTED
+SEXP codeFilesAppend(SEXP f1, SEXP f2) UNIMPLEMENTED
+SEXP getfmts(SEXP format) UNIMPLEMENTED
+SEXP startHTTPD(SEXP sIP, SEXP sPort) UNIMPLEMENTED
+SEXP stopHTTPD(void) UNIMPLEMENTED
 
-SEXP C_parseLatex(SEXP call, SEXP op, SEXP args, SEXP env) { unimplemented_tools(); return NULL; }
+SEXP C_parseLatex(SEXP call, SEXP op, SEXP args, SEXP env) UNIMPLEMENTED
 //SEXP C_parseRd(SEXP call, SEXP op, SEXP args, SEXP env);
 SEXP C_parseRd(SEXP con, SEXP source, SEXP verbose, SEXP fragment, SEXP basename, SEXP warningcalls);
-SEXP C_deparseRd(SEXP e, SEXP state) { unimplemented_tools(); return NULL; }
+SEXP C_deparseRd(SEXP e, SEXP state) UNIMPLEMENTED
diff --git a/com.oracle.truffle.r.native/library/utils/src/utils_dummy.c b/com.oracle.truffle.r.native/library/utils/src/utils_dummy.c
index 31e4872eb2b564d1780a81ee8848b8f046e0b688..34baf763e4d8df9e1b4c1854489caeeeed2be6db 100644
--- a/com.oracle.truffle.r.native/library/utils/src/utils_dummy.c
+++ b/com.oracle.truffle.r.native/library/utils/src/utils_dummy.c
@@ -2,59 +2,57 @@
  *  R : A Computer Language for Statistical Data Analysis
  *  Copyright (C) 2005-12   The R Core Team.
  *
- *  This program is free software{ unimplemented_utils(); return NULL; } you can redistribute it and/or modify
+ *  This program is free software UNIMPLEMENTED you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation{ unimplemented_utils(); return NULL; } either version 2 of the License, or
+ *  the Free Software Foundation UNIMPLEMENTED either version 2 of the License, or
  *  (at your option) any later version.
  *
  *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY{ unimplemented_utils(); return NULL; } without even the implied warranty of
+ *  but WITHOUT ANY WARRANTY UNIMPLEMENTED without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
- *  along with this program{ unimplemented_utils(); return NULL; } if not, a copy is available at
+ *  along with this program UNIMPLEMENTED if not, a copy is available at
  *  http://www.r-project.org/Licenses/
  */
 
 #include <Rinternals.h>
 
-static void unimplemented_utils() {
-	error("unimplemented utils .External");
-}
-
-SEXP objectSize(SEXP s) { unimplemented_utils(); return NULL; }
-SEXP unzip(SEXP args) { unimplemented_utils(); return NULL; }
-SEXP Rprof(SEXP args) { unimplemented_utils(); return NULL; }
-SEXP Rprofmem(SEXP args) { unimplemented_utils(); return NULL; }
-
-SEXP countfields(SEXP args) { unimplemented_utils(); return NULL; }
-SEXP flushconsole(void) { unimplemented_utils(); return NULL; }
-SEXP menu(SEXP args) { unimplemented_utils(); return NULL; }
-SEXP readtablehead(SEXP args) { unimplemented_utils(); return NULL; }
-SEXP typeconvert(SEXP call, SEXP op, SEXP args, SEXP env) { unimplemented_utils(); return NULL; }
-SEXP writetable(SEXP call, SEXP op, SEXP args, SEXP env) { unimplemented_utils(); return NULL; }
-
-SEXP crc64(SEXP in) { unimplemented_utils(); return NULL; }
-SEXP nsl(SEXP hostname) { unimplemented_utils(); return NULL; }
-SEXP download(SEXP args) { unimplemented_utils(); return NULL; }
-
-SEXP sockconnect(SEXP sport, SEXP shost) { unimplemented_utils(); return NULL; }
-SEXP sockread(SEXP sport, SEXP smaxlen) { unimplemented_utils(); return NULL; }
-SEXP sockclose(SEXP sport) { unimplemented_utils(); return NULL; }
-SEXP sockopen(SEXP sport) { unimplemented_utils(); return NULL; }
-SEXP socklisten(SEXP sport) { unimplemented_utils(); return NULL; }
-SEXP sockwrite(SEXP sport, SEXP sstring) { unimplemented_utils(); return NULL; }
-
-SEXP addhistory(SEXP call, SEXP op, SEXP args, SEXP rho) { unimplemented_utils(); return NULL; }
-SEXP loadhistory(SEXP call, SEXP op, SEXP args, SEXP rho) { unimplemented_utils(); return NULL; }
-SEXP savehistory(SEXP call, SEXP op, SEXP args, SEXP rho) { unimplemented_utils(); return NULL; }
-SEXP dataentry(SEXP call, SEXP op, SEXP args, SEXP rho) { unimplemented_utils(); return NULL; }
-SEXP dataviewer(SEXP call, SEXP op, SEXP args, SEXP rho) { unimplemented_utils(); return NULL; }
-SEXP edit(SEXP call, SEXP op, SEXP args, SEXP rho) { unimplemented_utils(); return NULL; }
-SEXP fileedit(SEXP call, SEXP op, SEXP args, SEXP rho) { unimplemented_utils(); return NULL; }
-SEXP selectlist(SEXP call, SEXP op, SEXP args, SEXP rho) { unimplemented_utils(); return NULL; }
-
-SEXP processevents(void) { unimplemented_utils(); return NULL; }
-
-SEXP octsize(SEXP s) { unimplemented_utils(); return NULL; }
+#define UNIMPLEMENTED { error("unimplemented function at %s:%d", __FILE__, __LINE__); return NULL; }
+
+SEXP objectSize(SEXP s)  UNIMPLEMENTED
+SEXP unzip(SEXP args)  UNIMPLEMENTED
+SEXP Rprof(SEXP args)  UNIMPLEMENTED
+SEXP Rprofmem(SEXP args)  UNIMPLEMENTED
+
+SEXP countfields(SEXP args)  UNIMPLEMENTED
+SEXP flushconsole(void)  UNIMPLEMENTED
+SEXP menu(SEXP args)  UNIMPLEMENTED
+SEXP readtablehead(SEXP args)  UNIMPLEMENTED
+SEXP typeconvert(SEXP call, SEXP op, SEXP args, SEXP env)  UNIMPLEMENTED
+SEXP writetable(SEXP call, SEXP op, SEXP args, SEXP env)  UNIMPLEMENTED
+
+SEXP crc64(SEXP in)  UNIMPLEMENTED
+SEXP nsl(SEXP hostname)  UNIMPLEMENTED
+SEXP download(SEXP args)  UNIMPLEMENTED
+
+SEXP sockconnect(SEXP sport, SEXP shost)  UNIMPLEMENTED
+SEXP sockread(SEXP sport, SEXP smaxlen)  UNIMPLEMENTED
+SEXP sockclose(SEXP sport)  UNIMPLEMENTED
+SEXP sockopen(SEXP sport)  UNIMPLEMENTED
+SEXP socklisten(SEXP sport)  UNIMPLEMENTED
+SEXP sockwrite(SEXP sport, SEXP sstring)  UNIMPLEMENTED
+
+SEXP addhistory(SEXP call, SEXP op, SEXP args, SEXP rho)  UNIMPLEMENTED
+SEXP loadhistory(SEXP call, SEXP op, SEXP args, SEXP rho)  UNIMPLEMENTED
+SEXP savehistory(SEXP call, SEXP op, SEXP args, SEXP rho)  UNIMPLEMENTED
+SEXP dataentry(SEXP call, SEXP op, SEXP args, SEXP rho)  UNIMPLEMENTED
+SEXP dataviewer(SEXP call, SEXP op, SEXP args, SEXP rho)  UNIMPLEMENTED
+SEXP edit(SEXP call, SEXP op, SEXP args, SEXP rho)  UNIMPLEMENTED
+SEXP fileedit(SEXP call, SEXP op, SEXP args, SEXP rho)  UNIMPLEMENTED
+SEXP selectlist(SEXP call, SEXP op, SEXP args, SEXP rho)  UNIMPLEMENTED
+
+SEXP processevents(void)  UNIMPLEMENTED
+
+SEXP octsize(SEXP s)  UNIMPLEMENTED
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 7a42096411a951170929e210df2eca8e3093057e..dfba6c9b085c400665daca211e38726cf47a332d 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
@@ -412,6 +412,7 @@ public class BasePackage extends RBuiltinPackage {
         add(Quit.class, QuitNodeGen::create);
         add(Quote.class, QuoteNodeGen::create);
         add(Range.class, RangeNodeGen::create);
+        add(Rank.class, RankNodeGen::create);
         add(RNGFunctions.RNGkind.class, RNGFunctionsFactory.RNGkindNodeGen::create);
         add(RNGFunctions.SetSeed.class, RNGFunctionsFactory.SetSeedNodeGen::create);
         add(RVersion.class, RVersionNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
index cdc3849a10373d9ffac263a99a4c06ce4205bd53..a488e579626a2e586509eb07f5a55ffb216e9b65 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
@@ -29,7 +29,6 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.profiles.*;
 import com.oracle.truffle.r.nodes.*;
 import com.oracle.truffle.r.nodes.access.*;
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 751bcf924cde8c085845125662053712a2357693..4bd2e07902e7d5906776a1306ae9d07247e3bd80 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
@@ -58,12 +58,12 @@ public abstract class Match extends RBuiltinNode {
         casts.toInteger(2);
     }
 
-    private String castString(Object operand) {
+    private RAbstractStringVector castString(RAbstractVector operand) {
         if (castString == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castString = insert(CastStringNodeGen.create(false, false, false, false));
         }
-        return (String) castString.execute(operand);
+        return (RAbstractStringVector) castString.execute(operand);
     }
 
     private Object matchRecursive(Object x, Object table, RAbstractIntVector noMatch, Object incomparables) {
@@ -427,9 +427,10 @@ public abstract class Match extends RBuiltinNode {
         int nomatch = nomatchVec.getLength() == 0 ? RRuntime.INT_NA : nomatchVec.getDataAt(0);
         int[] result = initResult(x.getLength(), nomatch);
         boolean matchAll = true;
+        RAbstractStringVector stringTable = castString(table);
         NonRecursiveHashMapCharacter hashTable = new NonRecursiveHashMapCharacter(table.getLength());
         for (int i = table.getLength() - 1; i >= 0; i--) {
-            hashTable.put(castString(table.getDataAtAsObject(i)), i);
+            hashTable.put(stringTable.getDataAt(i), i);
         }
         for (int i = 0; i < result.length; i++) {
             String xx = x.getDataAt(i);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
index a180713320eba54c97b54924956a44abb8641122..812743c6709eae9d23346f86c7f7a7fe5feec10f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
@@ -6,7 +6,7 @@
  * Copyright (c) 1995, 1996, 1997  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1995-2014, The R Core Team
  * Copyright (c) 2002-2008, The R Foundation
- * Copyright (c) 2015, Oracle and/or its affiliates
+ * Copyright (c) 2016, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -14,11 +14,14 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.runtime.RBuiltinKind.*;
 
+import java.text.Collator;
+
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.profiles.*;
 import com.oracle.truffle.r.nodes.builtin.*;
 import com.oracle.truffle.r.nodes.builtin.base.OrderNodeGen.CmpNodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.OrderNodeGen.OrderVector1NodeGen;
 import com.oracle.truffle.r.nodes.unary.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
@@ -31,15 +34,22 @@ public abstract class Order extends RPrecedenceBuiltinNode {
 
     public abstract RIntVector executeRIntVector(byte naLast, byte dec, RArgsValuesAndNames args);
 
+    @Child OrderVector1Node orderVector1Node;
     @Child private CastToVectorNode castVector;
     @Child private CastToVectorNode castVector2;
     @Child private CmpNode cmpNode;
 
     private final BranchProfile error = BranchProfile.create();
-    private final ConditionProfile decProfile = ConditionProfile.createBinaryProfile();
 
     private static final int[] SINCS = {1073790977, 268460033, 67121153, 16783361, 4197377, 1050113, 262913, 65921, 16577, 4193, 1073, 281, 77, 23, 8, 1, 0};
 
+    private OrderVector1Node initOrderVector1() {
+        if (orderVector1Node == null) {
+            orderVector1Node = insert(OrderVector1NodeGen.create(null, null, null, null));
+        }
+        return orderVector1Node;
+    }
+
     private RAbstractVector castVector(Object value) {
         if (castVector == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -76,21 +86,22 @@ public abstract class Order extends RPrecedenceBuiltinNode {
         RAbstractIntVector v = (RAbstractIntVector) castVector(vectors[0]);
         int n = v.getLength();
 
-        boolean naLast = true;
-        boolean dec = true;
+        byte naLastL = RRuntime.LOGICAL_TRUE;
+        byte decL = RRuntime.LOGICAL_TRUE;
 
         if (naLastVec.getLength() == 0 || naLastVec.getDataAt(0) == RRuntime.LOGICAL_FALSE) {
-            naLast = false;
+            naLastL = RRuntime.LOGICAL_FALSE;
         }
         if (decVec.getLength() == 0 || decVec.getDataAt(0) == RRuntime.LOGICAL_FALSE) {
-            dec = false;
+            decL = RRuntime.LOGICAL_FALSE;
         }
 
         int[] indx = new int[n];
         for (int i = 0; i < indx.length; i++) {
             indx[i] = i;
         }
-        orderVector1(indx, v, naLast, dec);
+        RIntVector indxVec = RDataFactory.createIntVector(indx, RDataFactory.COMPLETE_VECTOR);
+        initOrderVector1().execute(indxVec, v, naLastL, decL);
         for (int i = 0; i < indx.length; i++) {
             indx[i] = indx[i] + 1;
         }
@@ -104,21 +115,22 @@ public abstract class Order extends RPrecedenceBuiltinNode {
         RAbstractDoubleVector v = (RAbstractDoubleVector) castVector(vectors[0]);
         int n = v.getLength();
 
-        boolean naLast = true;
-        boolean dec = true;
+        byte naLastL = RRuntime.LOGICAL_TRUE;
+        byte decL = RRuntime.LOGICAL_TRUE;
 
         if (naLastVec.getLength() == 0 || naLastVec.getDataAt(0) == RRuntime.LOGICAL_FALSE) {
-            naLast = false;
+            naLastL = RRuntime.LOGICAL_FALSE;
         }
         if (decVec.getLength() == 0 || decVec.getDataAt(0) == RRuntime.LOGICAL_FALSE) {
-            dec = false;
+            decL = RRuntime.LOGICAL_FALSE;
         }
 
         int[] indx = new int[n];
         for (int i = 0; i < indx.length; i++) {
             indx[i] = i;
         }
-        orderVector1(indx, v, naLast, dec);
+        RIntVector indxVec = RDataFactory.createIntVector(indx, RDataFactory.COMPLETE_VECTOR);
+        initOrderVector1().execute(indxVec, v, naLastL, decL);
         for (int i = 0; i < indx.length; i++) {
             indx[i] = indx[i] + 1;
         }
@@ -139,21 +151,22 @@ public abstract class Order extends RPrecedenceBuiltinNode {
         RAbstractStringVector v = (RAbstractStringVector) castVector(vectors[0]);
         int n = v.getLength();
 
-        boolean naLast = true;
-        boolean dec = true;
+        byte naLastL = RRuntime.LOGICAL_TRUE;
+        byte decL = RRuntime.LOGICAL_TRUE;
 
         if (naLastVec.getLength() == 0 || naLastVec.getDataAt(0) == RRuntime.LOGICAL_FALSE) {
-            naLast = false;
+            naLastL = RRuntime.LOGICAL_FALSE;
         }
         if (decVec.getLength() == 0 || decVec.getDataAt(0) == RRuntime.LOGICAL_FALSE) {
-            dec = false;
+            decL = RRuntime.LOGICAL_FALSE;
         }
 
         int[] indx = new int[n];
         for (int i = 0; i < indx.length; i++) {
             indx[i] = i;
         }
-        orderVector1(indx, v, naLast, dec);
+        RIntVector indxVec = RDataFactory.createIntVector(indx, RDataFactory.COMPLETE_VECTOR);
+        initOrderVector1().execute(indxVec, v, naLastL, decL);
         for (int i = 0; i < indx.length; i++) {
             indx[i] = indx[i] + 1;
         }
@@ -167,21 +180,22 @@ public abstract class Order extends RPrecedenceBuiltinNode {
         RAbstractComplexVector v = (RAbstractComplexVector) castVector(vectors[0]);
         int n = v.getLength();
 
-        boolean naLast = true;
-        boolean dec = true;
+        byte naLastL = RRuntime.LOGICAL_TRUE;
+        byte decL = RRuntime.LOGICAL_TRUE;
 
         if (naLastVec.getLength() == 0 || naLastVec.getDataAt(0) == RRuntime.LOGICAL_FALSE) {
-            naLast = false;
+            naLastL = RRuntime.LOGICAL_FALSE;
         }
         if (decVec.getLength() == 0 || decVec.getDataAt(0) == RRuntime.LOGICAL_FALSE) {
-            dec = false;
+            decL = RRuntime.LOGICAL_FALSE;
         }
 
         int[] indx = new int[n];
         for (int i = 0; i < indx.length; i++) {
             indx[i] = i;
         }
-        orderVector1(indx, v, naLast, dec);
+        RIntVector indxVec = RDataFactory.createIntVector(indx, RDataFactory.COMPLETE_VECTOR);
+        initOrderVector1().execute(indxVec, v, naLastL, decL);
         for (int i = 0; i < indx.length; i++) {
             indx[i] = indx[i] + 1;
         }
@@ -271,74 +285,62 @@ public abstract class Order extends RPrecedenceBuiltinNode {
         }
     }
 
-    private void orderVector1(int[] indx, RAbstractIntVector dv, boolean naLast, boolean dec) {
-        int lo = 0;
-        int hi = indx.length - 1;
-        int numNa = 0;
-        if (!dv.isComplete()) {
-            boolean[] isNa = new boolean[indx.length];
-            for (int i = 0; i < isNa.length; i++) {
-                if (RRuntime.isNA(dv.getDataAt(i))) {
-                    isNa[i] = true;
-                    numNa++;
-                }
-            }
+    /**
+     * Also used by {@link Rank}.
+     */
+    @NodeChildren({@NodeChild("indx"), @NodeChild("dv"), @NodeChild("naLast"), @NodeChild("dec")})
+    abstract static class OrderVector1Node extends RNode {
+        private final ConditionProfile decProfile = ConditionProfile.createBinaryProfile();
 
-            if (numNa > 0) {
-                if (!naLast) {
-                    for (int i = 0; i < isNa.length; i++) {
-                        isNa[i] = !isNa[i];
+        public abstract Object execute(Object v, Object dv, byte naLast, byte dec);
+
+        @Specialization
+        protected Object orderVector1(RIntVector indxVec, RAbstractIntVector dv, byte naLastL, byte decL) {
+            int[] indx = indxVec.getDataWithoutCopying();
+            boolean naLast = RRuntime.fromLogical(naLastL);
+            boolean dec = RRuntime.fromLogical(decL);
+            int lo = 0;
+            int hi = indx.length - 1;
+            int numNa = 0;
+            if (!dv.isComplete()) {
+                boolean[] isNa = new boolean[indx.length];
+                for (int i = 0; i < isNa.length; i++) {
+                    if (RRuntime.isNA(dv.getDataAt(i))) {
+                        isNa[i] = true;
+                        numNa++;
                     }
                 }
-                sortNA(indx, isNa, lo, hi);
-                if (naLast) {
-                    hi -= numNa;
-                } else {
-                    lo += numNa;
-                }
-            }
-        }
 
-        sort(indx, dv, lo, hi, dec);
-    }
-
-    private void orderVector1(int[] indx, RAbstractDoubleVector dv, boolean naLast, boolean dec) {
-        int lo = 0;
-        int hi = indx.length - 1;
-        int numNa = 0;
-        boolean[] isNa = new boolean[indx.length];
-        for (int i = 0; i < isNa.length; i++) {
-            if (RRuntime.isNAorNaN(dv.getDataAt(i))) {
-                isNa[i] = true;
-                numNa++;
-            }
-        }
-
-        if (numNa > 0) {
-            if (!naLast) {
-                for (int i = 0; i < isNa.length; i++) {
-                    isNa[i] = !isNa[i];
+                if (numNa > 0) {
+                    if (!naLast) {
+                        for (int i = 0; i < isNa.length; i++) {
+                            isNa[i] = !isNa[i];
+                        }
+                    }
+                    sortNA(indx, isNa, lo, hi);
+                    if (naLast) {
+                        hi -= numNa;
+                    } else {
+                        lo += numNa;
+                    }
                 }
             }
-            sortNA(indx, isNa, lo, hi);
-            if (naLast) {
-                hi -= numNa;
-            } else {
-                lo += numNa;
-            }
-        }
 
-        sort(indx, dv, lo, hi, dec);
-    }
+            sort(indx, dv, lo, hi, dec);
+            return indxVec;
+        }
 
-    private void orderVector1(int[] indx, RAbstractStringVector dv, boolean naLast, boolean dec) {
-        int lo = 0;
-        int hi = indx.length - 1;
-        int numNa = 0;
-        if (!dv.isComplete()) {
+        @Specialization
+        protected Object orderVector1(RIntVector indxVec, RAbstractDoubleVector dv, byte naLastL, byte decL) {
+            int[] indx = indxVec.getDataWithoutCopying();
+            boolean naLast = RRuntime.fromLogical(naLastL);
+            boolean dec = RRuntime.fromLogical(decL);
+            int lo = 0;
+            int hi = indx.length - 1;
+            int numNa = 0;
             boolean[] isNa = new boolean[indx.length];
             for (int i = 0; i < isNa.length; i++) {
-                if (RRuntime.isNA(dv.getDataAt(i))) {
+                if (RRuntime.isNAorNaN(dv.getDataAt(i))) {
                     isNa[i] = true;
                     numNa++;
                 }
@@ -357,174 +359,224 @@ public abstract class Order extends RPrecedenceBuiltinNode {
                     lo += numNa;
                 }
             }
-        }
 
-        sort(indx, dv, lo, hi, dec);
-    }
+            sort(indx, dv, lo, hi, dec);
+            return indxVec;
+        }
 
-    private void orderVector1(int[] indx, RAbstractComplexVector dv, boolean naLast, boolean dec) {
-        int lo = 0;
-        int hi = indx.length - 1;
-        int numNa = 0;
-        if (!dv.isComplete()) {
-            boolean[] isNa = new boolean[indx.length];
-            for (int i = 0; i < isNa.length; i++) {
-                if (RRuntime.isNA(dv.getDataAt(i))) {
-                    isNa[i] = true;
-                    numNa++;
+        @Specialization
+        protected Object orderVector1(RIntVector indxVec, RAbstractStringVector dv, byte naLastL, byte decL) {
+            int[] indx = indxVec.getDataWithoutCopying();
+            boolean naLast = RRuntime.fromLogical(naLastL);
+            boolean dec = RRuntime.fromLogical(decL);
+            int lo = 0;
+            int hi = indx.length - 1;
+            int numNa = 0;
+            if (!dv.isComplete()) {
+                boolean[] isNa = new boolean[indx.length];
+                for (int i = 0; i < isNa.length; i++) {
+                    if (RRuntime.isNA(dv.getDataAt(i))) {
+                        isNa[i] = true;
+                        numNa++;
+                    }
                 }
-            }
 
-            if (numNa > 0) {
-                if (!naLast) {
-                    for (int i = 0; i < isNa.length; i++) {
-                        isNa[i] = !isNa[i];
+                if (numNa > 0) {
+                    if (!naLast) {
+                        for (int i = 0; i < isNa.length; i++) {
+                            isNa[i] = !isNa[i];
+                        }
+                    }
+                    sortNA(indx, isNa, lo, hi);
+                    if (naLast) {
+                        hi -= numNa;
+                    } else {
+                        lo += numNa;
                     }
-                }
-                sortNA(indx, isNa, lo, hi);
-                if (naLast) {
-                    hi -= numNa;
-                } else {
-                    lo += numNa;
                 }
             }
+
+            sort(indx, dv, lo, hi, dec);
+            return indxVec;
         }
 
-        sort(indx, dv, lo, hi, dec);
-    }
+        @Specialization
+        protected Object orderVector1(RIntVector indxVec, RAbstractComplexVector dv, byte naLastL, byte decL) {
+            int[] indx = indxVec.getDataWithoutCopying();
+            boolean naLast = RRuntime.fromLogical(naLastL);
+            boolean dec = RRuntime.fromLogical(decL);
+            int lo = 0;
+            int hi = indx.length - 1;
+            int numNa = 0;
+            if (!dv.isComplete()) {
+                boolean[] isNa = new boolean[indx.length];
+                for (int i = 0; i < isNa.length; i++) {
+                    if (RRuntime.isNA(dv.getDataAt(i))) {
+                        isNa[i] = true;
+                        numNa++;
+                    }
+                }
 
-    private static void sortNA(int[] indx, boolean[] isNa, int lo, int hi) {
-        int t = 0;
-        for (; SINCS[t] > indx.length; t++) {
-        }
-        for (int h = SINCS[t]; t < 16; h = SINCS[++t]) {
-            for (int i = lo + h; i <= hi; i++) {
-                int itmp = indx[i];
-                int j = i;
-                while (j >= lo + h) {
-                    int a = indx[j - h];
-                    int b = itmp;
-                    if (!((isNa[a] && !isNa[b]) || (isNa[a] == isNa[b] && a > b))) {
-                        break;
+                if (numNa > 0) {
+                    if (!naLast) {
+                        for (int i = 0; i < isNa.length; i++) {
+                            isNa[i] = !isNa[i];
+                        }
+                    }
+                    sortNA(indx, isNa, lo, hi);
+                    if (naLast) {
+                        hi -= numNa;
+                    } else {
+                        lo += numNa;
                     }
-                    indx[j] = indx[j - h];
-                    j -= h;
                 }
-                indx[j] = itmp;
             }
+
+            sort(indx, dv, lo, hi, dec);
+            return indxVec;
         }
 
-    }
+        private void sort(int[] indx, RAbstractDoubleVector dv, int lo, int hi, boolean dec) {
+            int t = 0;
+            for (; SINCS[t] > hi - lo + 1; t++) {
+            }
+            for (int h = SINCS[t]; t < 16; h = SINCS[++t]) {
+                for (int i = lo + h; i <= hi; i++) {
+                    int itmp = indx[i];
+                    int j = i;
+                    while (j >= lo + h) {
+                        int a = indx[j - h];
+                        int b = itmp;
+                        if (decProfile.profile(dec)) {
+                            if (!((dv.getDataAt(a)) < dv.getDataAt(b) || (dv.getDataAt(a) == dv.getDataAt(b) && a > b))) {
+                                break;
+                            }
+                        } else {
+                            if (!((dv.getDataAt(a)) > dv.getDataAt(b) || (dv.getDataAt(a) == dv.getDataAt(b) && a > b))) {
+                                break;
+                            }
 
-    private void sort(int[] indx, RAbstractDoubleVector dv, int lo, int hi, boolean dec) {
-        int t = 0;
-        for (; SINCS[t] > hi - lo + 1; t++) {
-        }
-        for (int h = SINCS[t]; t < 16; h = SINCS[++t]) {
-            for (int i = lo + h; i <= hi; i++) {
-                int itmp = indx[i];
-                int j = i;
-                while (j >= lo + h) {
-                    int a = indx[j - h];
-                    int b = itmp;
-                    if (decProfile.profile(dec)) {
-                        if (!((dv.getDataAt(a)) < dv.getDataAt(b) || (dv.getDataAt(a) == dv.getDataAt(b) && a > b))) {
-                            break;
-                        }
-                    } else {
-                        if (!((dv.getDataAt(a)) > dv.getDataAt(b) || (dv.getDataAt(a) == dv.getDataAt(b) && a > b))) {
-                            break;
                         }
-
+                        indx[j] = indx[j - h];
+                        j -= h;
                     }
-                    indx[j] = indx[j - h];
-                    j -= h;
+                    indx[j] = itmp;
                 }
-                indx[j] = itmp;
             }
         }
-    }
 
-    private void sort(int[] indx, RAbstractIntVector dv, int lo, int hi, boolean dec) {
-        int t = 0;
-        for (; SINCS[t] > hi - lo + 1; t++) {
-        }
-        for (int h = SINCS[t]; t < 16; h = SINCS[++t]) {
-            for (int i = lo + h; i <= hi; i++) {
-                int itmp = indx[i];
-                int j = i;
-                while (j >= lo + h) {
-                    int a = indx[j - h];
-                    int b = itmp;
-                    if (decProfile.profile(dec)) {
-                        if (!((dv.getDataAt(a)) < dv.getDataAt(b) || (dv.getDataAt(a) == dv.getDataAt(b) && a > b))) {
-                            break;
-                        }
-                    } else {
-                        if (!((dv.getDataAt(a)) > dv.getDataAt(b) || (dv.getDataAt(a) == dv.getDataAt(b) && a > b))) {
-                            break;
-                        }
+        private void sort(int[] indx, RAbstractIntVector dv, int lo, int hi, boolean dec) {
+            int t = 0;
+            for (; SINCS[t] > hi - lo + 1; t++) {
+            }
+            for (int h = SINCS[t]; t < 16; h = SINCS[++t]) {
+                for (int i = lo + h; i <= hi; i++) {
+                    int itmp = indx[i];
+                    int j = i;
+                    while (j >= lo + h) {
+                        int a = indx[j - h];
+                        int b = itmp;
+                        if (decProfile.profile(dec)) {
+                            if (!((dv.getDataAt(a)) < dv.getDataAt(b) || (dv.getDataAt(a) == dv.getDataAt(b) && a > b))) {
+                                break;
+                            }
+                        } else {
+                            if (!((dv.getDataAt(a)) > dv.getDataAt(b) || (dv.getDataAt(a) == dv.getDataAt(b) && a > b))) {
+                                break;
+                            }
 
+                        }
+                        indx[j] = indx[j - h];
+                        j -= h;
                     }
-                    indx[j] = indx[j - h];
-                    j -= h;
+                    indx[j] = itmp;
                 }
-                indx[j] = itmp;
             }
         }
-    }
 
-    private void sort(int[] indx, RAbstractStringVector dv, int lo, int hi, boolean dec) {
-        int t = 0;
-        for (; SINCS[t] > hi - lo + 1; t++) {
-        }
-        for (int h = SINCS[t]; t < 16; h = SINCS[++t]) {
-            for (int i = lo + h; i <= hi; i++) {
-                int itmp = indx[i];
-                int j = i;
-                while (j >= lo + h) {
-                    int a = indx[j - h];
-                    int b = itmp;
-                    if (decProfile.profile(dec)) {
-                        if (!(dv.getDataAt(a).compareTo(dv.getDataAt(b)) < 0 || (dv.getDataAt(a).compareTo(dv.getDataAt(b)) == 0 && a > b))) {
-                            break;
-                        }
-                    } else {
-                        if (!(dv.getDataAt(a).compareTo(dv.getDataAt(b)) > 0 || (dv.getDataAt(a).compareTo(dv.getDataAt(b)) == 0 && a > b))) {
-                            break;
+        private void sort(int[] indx, RAbstractStringVector dv, int lo, int hi, boolean dec) {
+            Collator collator = Collator.getInstance();
+            int t = 0;
+            for (; SINCS[t] > hi - lo + 1; t++) {
+            }
+            for (int h = SINCS[t]; t < 16; h = SINCS[++t]) {
+                for (int i = lo + h; i <= hi; i++) {
+                    int itmp = indx[i];
+                    int j = i;
+                    while (j >= lo + h) {
+                        int a = indx[j - h];
+                        int b = itmp;
+                        int c = collator.compare(dv.getDataAt(a), dv.getDataAt(b));
+                        if (decProfile.profile(dec)) {
+                            if (!(c < 0 || (c == 0 && a > b))) {
+                                break;
+                            }
+                        } else {
+                            if (!(c > 0 || (c == 0 && a > b))) {
+                                break;
+                            }
                         }
+                        indx[j] = indx[j - h];
+                        j -= h;
                     }
-                    indx[j] = indx[j - h];
-                    j -= h;
+                    indx[j] = itmp;
                 }
-                indx[j] = itmp;
             }
         }
-    }
 
-    private static boolean lt(RComplex a, RComplex b) {
-        if (a.getRealPart() == b.getRealPart()) {
-            return a.getImaginaryPart() < b.getImaginaryPart();
-        } else {
-            return a.getRealPart() < b.getRealPart();
+        private static boolean lt(RComplex a, RComplex b) {
+            if (a.getRealPart() == b.getRealPart()) {
+                return a.getImaginaryPart() < b.getImaginaryPart();
+            } else {
+                return a.getRealPart() < b.getRealPart();
+            }
         }
-    }
 
-    private static boolean gt(RComplex a, RComplex b) {
-        if (a.getRealPart() == b.getRealPart()) {
-            return a.getImaginaryPart() > b.getImaginaryPart();
-        } else {
-            return a.getRealPart() > b.getRealPart();
+        private static boolean gt(RComplex a, RComplex b) {
+            if (a.getRealPart() == b.getRealPart()) {
+                return a.getImaginaryPart() > b.getImaginaryPart();
+            } else {
+                return a.getRealPart() > b.getRealPart();
+            }
         }
-    }
 
-    private static boolean eq(RComplex a, RComplex b) {
-        return a.getRealPart() == b.getRealPart() && a.getImaginaryPart() == b.getImaginaryPart();
+        private static boolean eq(RComplex a, RComplex b) {
+            return a.getRealPart() == b.getRealPart() && a.getImaginaryPart() == b.getImaginaryPart();
+        }
+
+        private void sort(int[] indx, RAbstractComplexVector dv, int lo, int hi, boolean dec) {
+            int t = 0;
+            for (; SINCS[t] > hi - lo + 1; t++) {
+            }
+            for (int h = SINCS[t]; t < 16; h = SINCS[++t]) {
+                for (int i = lo + h; i <= hi; i++) {
+                    int itmp = indx[i];
+                    int j = i;
+                    while (j >= lo + h) {
+                        int a = indx[j - h];
+                        int b = itmp;
+                        if (decProfile.profile(dec)) {
+                            if (!(lt(dv.getDataAt(a), dv.getDataAt(b)) || (eq(dv.getDataAt(a), dv.getDataAt(b)) && a > b))) {
+                                break;
+                            }
+                        } else {
+                            if (!(gt(dv.getDataAt(a), dv.getDataAt(b)) || (eq(dv.getDataAt(a), dv.getDataAt(b)) && a > b))) {
+                                break;
+                            }
+
+                        }
+                        indx[j] = indx[j - h];
+                        j -= h;
+                    }
+                    indx[j] = itmp;
+                }
+            }
+        }
     }
 
-    private void sort(int[] indx, RAbstractComplexVector dv, int lo, int hi, boolean dec) {
+    private static void sortNA(int[] indx, boolean[] isNa, int lo, int hi) {
         int t = 0;
-        for (; SINCS[t] > hi - lo + 1; t++) {
+        for (; SINCS[t] > indx.length; t++) {
         }
         for (int h = SINCS[t]; t < 16; h = SINCS[++t]) {
             for (int i = lo + h; i <= hi; i++) {
@@ -533,15 +585,8 @@ public abstract class Order extends RPrecedenceBuiltinNode {
                 while (j >= lo + h) {
                     int a = indx[j - h];
                     int b = itmp;
-                    if (decProfile.profile(dec)) {
-                        if (!(lt(dv.getDataAt(a), dv.getDataAt(b)) || (eq(dv.getDataAt(a), dv.getDataAt(b)) && a > b))) {
-                            break;
-                        }
-                    } else {
-                        if (!(gt(dv.getDataAt(a), dv.getDataAt(b)) || (eq(dv.getDataAt(a), dv.getDataAt(b)) && a > b))) {
-                            break;
-                        }
-
+                    if (!((isNa[a] && !isNa[b]) || (isNa[a] == isNa[b] && a > b))) {
+                        break;
                     }
                     indx[j] = indx[j - h];
                     j -= h;
@@ -549,6 +594,7 @@ public abstract class Order extends RPrecedenceBuiltinNode {
                 indx[j] = itmp;
             }
         }
+
     }
 
     protected boolean isFirstIntegerPrecedence(RArgsValuesAndNames args) {
@@ -579,8 +625,11 @@ public abstract class Order extends RPrecedenceBuiltinNode {
         return args.getLength() == 1;
     }
 
+    /**
+     * Also used by {@link Rank}. *
+     */
     @NodeChildren({@NodeChild("v"), @NodeChild("i"), @NodeChild("j"), @NodeChild("naLast")})
-    protected abstract static class CmpNode extends RNode {
+    abstract static class CmpNode extends RNode {
 
         public abstract int executeInt(Object v, int i, int j, byte naLast);
 
@@ -725,4 +774,5 @@ public abstract class Order extends RPrecedenceBuiltinNode {
         }
 
     }
+
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java
index 5c1648c5ce2bbebc781920d4b573c7016bade3fe..5e23fc43c66bd765047f838ae1057cb4e42d189f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.runtime.RBuiltinKind.INTERNAL;
 
 import java.io.IOException;
+
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.dsl.Cached;
@@ -52,8 +53,6 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 public class PrintFunctions {
     public abstract static class PrintAdapter extends RInvisibleBuiltinNode {
-        @Child protected PrettyPrinterNode prettyPrinter = PrettyPrinterNodeGen.create(null, null, null, null, false);
-        // The new pretty-printer
         @Child protected ValuePrinterNode valuePrinter = ValuePrinterNodeGen.create(null, null, null, null, null, null, null, null, null);
 
         @TruffleBoundary
@@ -82,19 +81,8 @@ public class PrintFunctions {
         }
 
         @Specialization(guards = "!isS4(o)")
-        protected Object printDefault(Object o, Object digits, boolean quote, Object naPrint, Object printGap, boolean right, Object max, boolean useSource, boolean noOpt) {
-            try {
-                // Invoking the new pretty-printer. In contrast to the previous one, the new one
-                // does not return the output value and prints directly to the output.
-                valuePrinter.executeString(o, digits, quote, naPrint, printGap, right, max, useSource, noOpt);
-            } catch (UnsupportedOperationException e) {
-                // The original pretty printing code
-                String s = (String) prettyPrinter.executeString(o, null, RRuntime.asLogical(quote), RRuntime.asLogical(right));
-                if (s != null && !s.isEmpty()) {
-                    printHelper(s);
-                }
-            }
-
+        protected Object printDefault(VirtualFrame frame, Object o, Object digits, boolean quote, Object naPrint, Object printGap, boolean right, Object max, boolean useSource, boolean noOpt) {
+            valuePrinter.executeString(frame, o, digits, quote, naPrint, printGap, right, max, useSource, noOpt);
             controlVisibility();
             return o;
         }
@@ -133,17 +121,8 @@ public class PrintFunctions {
         @SuppressWarnings("unused")
         @Specialization
         protected RFunction printFunction(VirtualFrame frame, RFunction x, byte useSource, RArgsValuesAndNames extra) {
-            try {
-                valuePrinter.executeString(x, PrintParameters.DEFAULT_DIGITS, true, RString.valueOf(RRuntime.STRING_NA), 1, false, PrintParameters.getDeafultMaxPrint(),
-                                true, false);
-            } catch (UnsupportedOperationException e) {
-                // The original pretty printing code
-                String s = prettyPrinter.prettyPrintFunction(x, null, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, useSource == RRuntime.LOGICAL_TRUE);
-                if (s != null && !s.isEmpty()) {
-                    printHelper(s);
-                }
-            }
-
+            valuePrinter.executeString(frame, x, PrintParameters.DEFAULT_DIGITS, true, RString.valueOf(RRuntime.STRING_NA), 1, false, PrintParameters.getDeafultMaxPrint(),
+                            true, false);
             controlVisibility();
             return x;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java
new file mode 100644
index 0000000000000000000000000000000000000000..a1d23026cf573e3caf5bcbdd23ef45cc1abc1749
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java
@@ -0,0 +1,131 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
+ * Copyright (c) 1997-2013,  The R Core Team
+ * Copyright (c) 2016, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.nodes.builtin.base;
+
+import static com.oracle.truffle.r.runtime.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.nodes.builtin.base.OrderNodeGen.CmpNodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.OrderNodeGen.OrderVector1NodeGen;
+import com.oracle.truffle.r.runtime.RBuiltin;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RRawVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+@RBuiltin(name = "rank", kind = INTERNAL, parameterNames = {"x", "len", "ties.method"})
+public abstract class Rank extends RBuiltinNode {
+    @Child Order.OrderVector1Node orderVector1Node;
+    @Child Order.CmpNode orderCmpNode;
+
+    private enum TiesKind {
+        AVERAGE,
+        MAX,
+        MIN;
+    }
+
+    @Override
+    protected void createCasts(CastBuilder casts) {
+        casts.toInteger(1);
+    }
+
+    Order.OrderVector1Node initOrderVector1() {
+        if (orderVector1Node == null) {
+            orderVector1Node = insert(OrderVector1NodeGen.create(null, null, null, null));
+        }
+        return orderVector1Node;
+    }
+
+    Order.CmpNode initOrderCmp() {
+        if (orderCmpNode == null) {
+            orderCmpNode = insert(CmpNodeGen.create(null, null, null, null));
+        }
+        return orderCmpNode;
+    }
+
+    @Specialization
+    protected Object rank(RAbstractVector x, int n, RAbstractStringVector tiesMethod) {
+        if (n < 0 || RRuntime.isNA(n)) {
+            throw RError.error(this, RError.Message.INVALID_ARGUMENT, "length(xx)");
+        }
+        if (x instanceof RRawVector) {
+            throw RError.error(this, RError.Message.RAW_SORT);
+        }
+        TiesKind tiesKind;
+        switch (tiesMethod.getDataAt(0)) {
+            case "average":
+                tiesKind = TiesKind.AVERAGE;
+                break;
+
+            case "max":
+                tiesKind = TiesKind.MAX;
+                break;
+
+            case "min":
+                tiesKind = TiesKind.MIN;
+                break;
+            default:
+                throw RError.error(this, RError.Message.GENERIC, "invalid ties.method for rank() [should never happen]");
+
+        }
+        int[] ik = null;
+        double[] rk = null;
+        if (tiesKind == TiesKind.AVERAGE) {
+            rk = new double[n];
+        } else {
+            ik = new int[n];
+        }
+        int[] indx = new int[n];
+        for (int i = 0; i < n; i++) {
+            indx[i] = i;
+        }
+        RIntVector indxVec = RDataFactory.createIntVector(indx, RDataFactory.COMPLETE_VECTOR);
+        initOrderVector1().execute(indxVec, x, RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE);
+        initOrderCmp();
+        int j;
+        for (int i = 0; i < n; i = j + 1) {
+            j = i;
+            while ((j < n - 1) && orderCmpNode.executeInt(x, indx[j], indx[j + 1], RRuntime.LOGICAL_FALSE) == 0) {
+                j++;
+            }
+            switch (tiesKind) {
+                case AVERAGE:
+                    for (int k = i; k <= j; k++) {
+                        rk[indx[k]] = (i + j + 2) / 2.;
+                    }
+                    break;
+                case MAX:
+                    for (int k = i; k <= j; k++) {
+                        ik[indx[k]] = j + 1;
+                    }
+                    break;
+                case MIN:
+                    for (int k = i; k <= j; k++) {
+                        ik[indx[k]] = i + 1;
+                    }
+                    break;
+            }
+        }
+        if (tiesKind == TiesKind.AVERAGE) {
+            return RDataFactory.createDoubleVector(rk, RDataFactory.COMPLETE_VECTOR);
+        } else {
+            return RDataFactory.createIntVector(ik, RDataFactory.COMPLETE_VECTOR);
+        }
+
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FastR.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FastR.java
index 5f3dabd63fbe9b0b12466d1c1ab760f6da2ec7eb..0718f7f04cb157c39df9b788449ebce09e11f7d9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FastR.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FastR.java
@@ -116,6 +116,10 @@ public abstract class FastR extends RBuiltinNode {
                 return FastRContextFactory.ChannelSendNodeGen.create();
             case "fastr.channel.receive":
                 return FastRContextFactory.ChannelReceiveNodeGen.create();
+            case "fastr.channel.poll":
+                return FastRContextFactory.ChannelPollNodeGen.create();
+            case "fastr.channel.select":
+                return FastRContextFactory.ChannelSelectNodeGen.create();
             case "fastr.throw":
                 return FastRThrowItFactory.ThrowItNodeGen.create();
             case "fastr.trace":
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java
index ae8ac7f47887c69fb3db7108b68995a57bde0200..e4f2f954111bb1eecee4a2c01eff084e560187de 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java
@@ -33,6 +33,7 @@ import com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_set_met
 import com.oracle.truffle.r.library.methods.SlotFactory.R_getSlotNodeGen;
 import com.oracle.truffle.r.library.methods.SlotFactory.R_setSlotNodeGen;
 import com.oracle.truffle.r.library.methods.SubstituteDirectNodeGen;
+import com.oracle.truffle.r.library.parallel.ParallelFunctionsFactory.MCIsChildNodeGen;
 import com.oracle.truffle.r.library.stats.*;
 import com.oracle.truffle.r.library.stats.GammaFunctionsFactory.QgammaNodeGen;
 import com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineCoefNodeGen;
@@ -419,6 +420,10 @@ public class ForeignFunctions {
                     // grid
                 case "L_initGrid":
                     return InitGridNodeGen.create();
+
+                    // parallel
+                case "mc_is_child":
+                    return MCIsChildNodeGen.create();
                 default:
                     return null;
             }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AbstractScalarValuePrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AbstractScalarValuePrinter.java
deleted file mode 100644
index 77f8129c24bd40720c2f0bcc0632445f3a5828d4..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AbstractScalarValuePrinter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2014, 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.builtin.base.printer;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-
-public abstract class AbstractScalarValuePrinter<T> extends AbstractValuePrinter<T> {
-
-    @Override
-    protected final void printValue(T value, PrintContext printCtx) throws IOException {
-        PrintWriter out = printCtx.output();
-        if (!printCtx.parameters().getSuppressIndexLabels()) {
-            out.print("[1] ");
-        }
-        printScalarValue(value, printCtx);
-    }
-
-    protected abstract void printScalarValue(T value, PrintContext printCtx) throws IOException;
-
-}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AttributesPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AttributesPrinter.java
index 4e60f5674c32c886a91ea88e3650398598cd97ab..2fb00e7dba66fc64fbebd1f722502a3394d96fa7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AttributesPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AttributesPrinter.java
@@ -86,20 +86,13 @@ public class AttributesPrinter implements ValuePrinter<RAttributable> {
             }
             out.println(tag);
 
-            if (RRuntime.ROWNAMES_ATTR_KEY.equals(a.getName())) {
-                /* need special handling AND protection */
-                Object val = a.getValue();
-                ValuePrinters.INSTANCE.print(val, printCtx);
-                continue;
-            }
-            if (RContext.getInstance().isMethodTableDispatchOn() && utils.isS4(value)) {
-                throw new UnsupportedOperationException("TODO");
-            }
-            if (utils.isObject(value)) {
-                throw new UnsupportedOperationException("TODO");
+            if (RContext.getInstance().isMethodTableDispatchOn() && utils.isS4(a.getValue())) {
+                S4ObjectPrinter.printS4(printCtx, a.getValue());
+                // throw new UnsupportedOperationException("TODO");
+            } else {
+                ValuePrinters.INSTANCE.print(a.getValue(), printCtx);
             }
 
-            ValuePrinters.INSTANCE.print(a.getValue(), printCtx);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java
index 82e8500271470ff0baff681aedc4496612053f06..f53d8e9e280f3c061b4ca4f3d4573ca7c702ade9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java
@@ -11,12 +11,12 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base.printer;
 
-import static com.oracle.truffle.r.nodes.builtin.base.printer.DoublePrinter.NB;
+import static com.oracle.truffle.r.nodes.builtin.base.printer.DoubleVectorPrinter.NB;
 import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.snprintf;
 
 import java.io.IOException;
 
-import com.oracle.truffle.r.nodes.builtin.base.printer.DoublePrinter.ScientificDouble;
+import com.oracle.truffle.r.nodes.builtin.base.printer.DoubleVectorPrinter.ScientificDouble;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
@@ -29,14 +29,14 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
     public static final ComplexVectorPrinter INSTANCE = new ComplexVectorPrinter();
 
     @Override
-    protected VectorPrinter<RAbstractComplexVector>.VectorPrintJob createJob(RAbstractComplexVector vector, int indx, boolean quote, PrintContext printCtx) {
-        return new ComplexVectorPrintJob(vector, indx, quote, printCtx);
+    protected VectorPrinter<RAbstractComplexVector>.VectorPrintJob createJob(RAbstractComplexVector vector, int indx, PrintContext printCtx) {
+        return new ComplexVectorPrintJob(vector, indx, printCtx);
     }
 
     private final class ComplexVectorPrintJob extends VectorPrintJob {
 
-        protected ComplexVectorPrintJob(RAbstractComplexVector vector, int indx, boolean quote, PrintContext printCtx) {
-            super(vector, indx, quote, printCtx);
+        protected ComplexVectorPrintJob(RAbstractComplexVector vector, int indx, PrintContext printCtx) {
+            super(vector, indx, printCtx);
         }
 
         @Override
@@ -158,7 +158,7 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
                     if (xi.getRealPart() != 0) {
                         allReZero = false;
                     }
-                    ScientificDouble sd = DoublePrinter.scientific(tmp.getRealPart(), pp);
+                    ScientificDouble sd = DoubleVectorPrinter.scientific(tmp.getRealPart(), pp);
 
                     left = sd.kpower + 1;
                     if (sd.roundingwidens) {
@@ -202,7 +202,7 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
                     if (xi.getImaginaryPart() != 0) {
                         allImZero = false;
                     }
-                    ScientificDouble sd = DoublePrinter.scientific(tmp.getImaginaryPart(), pp);
+                    ScientificDouble sd = DoubleVectorPrinter.scientific(tmp.getImaginaryPart(), pp);
 
                     left = sd.kpower + 1;
                     if (sd.roundingwidens) {
@@ -365,7 +365,7 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
 
     public static String encodeComplex(RComplex x, ComplexVectorMetrics cvm, PrintParameters pp) {
         if (RRuntime.isNA(x.getRealPart()) || RRuntime.isNA(x.getImaginaryPart())) {
-            return DoublePrinter.encodeReal(RRuntime.DOUBLE_NA, cvm.maxWidth, 0, 0, '.', pp);
+            return DoubleVectorPrinter.encodeReal(RRuntime.DOUBLE_NA, cvm.maxWidth, 0, 0, '.', pp);
         } else {
             String s = encodeComplex(x, cvm.wr, cvm.dr, cvm.er, cvm.wi, cvm.di, cvm.ei, '.', pp);
             int g = cvm.maxWidth - cvm.wr - cvm.wi - 2;
@@ -411,18 +411,18 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
              */
             y = zprecr(x, pp.getDigits());
             if (y.getRealPart() == 0.) {
-                re = DoublePrinter.encodeReal(y.getRealPart(), wr, dr, er, cdec, pp);
+                re = DoubleVectorPrinter.encodeReal(y.getRealPart(), wr, dr, er, cdec, pp);
             } else {
-                re = DoublePrinter.encodeReal(xr, wr, dr, er, cdec, pp);
+                re = DoubleVectorPrinter.encodeReal(xr, wr, dr, er, cdec, pp);
             }
             flagNegIm = xi < 0;
             if (flagNegIm) {
                 xi = -xi;
             }
             if (y.getImaginaryPart() == 0.) {
-                im = DoublePrinter.encodeReal(y.getImaginaryPart(), wi, di, ei, cdec, pp);
+                im = DoubleVectorPrinter.encodeReal(y.getImaginaryPart(), wi, di, ei, cdec, pp);
             } else {
-                im = DoublePrinter.encodeReal(xi, wi, di, ei, cdec, pp);
+                im = DoubleVectorPrinter.encodeReal(xi, wi, di, ei, cdec, pp);
             }
             buff = snprintf(NB, "%s%s%si", re, flagNegIm ? "-" : "+", im);
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoublePrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoublePrinter.java
deleted file mode 100644
index 3da453f0f7e883589dff420a915887cd58b3bb99..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoublePrinter.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (c) 1997-2013,  The R Core Team
- * Copyright (c) 2016, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.nodes.builtin.base.printer;
-
-import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.snprintf;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.math.RoundingMode;
-import java.text.DecimalFormat;
-
-import com.oracle.truffle.r.nodes.builtin.base.printer.DoubleVectorPrinter.DoubleVectorMetrics;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RDouble;
-
-//Transcribed from GnuR, src/main/printutils.c
-
-public final class DoublePrinter extends AbstractScalarValuePrinter<Double> {
-
-    public static final DoublePrinter INSTANCE = new DoublePrinter();
-
-    @Override
-    protected void printScalarValue(Double value, PrintContext printCtx) throws IOException {
-        double x = value;
-
-        PrintWriter out = printCtx.output();
-        DoubleVectorMetrics dm = DoubleVectorPrinter.formatDoubleVector(RDouble.valueOf(x), 0, 1, 0, printCtx.parameters());
-        out.print(encodeReal(x, dm.maxWidth, dm.d, dm.e, '.', printCtx.parameters()));
-    }
-
-    private static final int DBL_DIG = 15;
-
-    private static final double[] tbl = {
-                    1e-1,
-                    1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09,
-                    1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
-                    1e20, 1e21, 1e22
-    };
-    private static final int KP_MAX = 22;
-    private static final int R_dec_min_exponent = -308;
-
-    public static final int NB = 1000;
-
-    public static class ScientificDouble {
-        public final int sgn;
-        public final int kpower;
-        public final int nsig;
-        public final boolean roundingwidens;
-
-        public ScientificDouble(int sgn, int kpower, int nsig, boolean roundingwidens) {
-            super();
-            this.sgn = sgn;
-            this.kpower = kpower;
-            this.nsig = nsig;
-            this.roundingwidens = roundingwidens;
-        }
-
-    }
-
-    public static ScientificDouble scientific(double x, PrintParameters pp) {
-        /*
-         * 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;
-        double r;
-        int kp;
-        int j;
-
-        // output arguments
-        int sgn;
-        int kpower;
-        int nsig;
-        boolean roundingwidens;
-
-        if (x == 0.0) {
-            kpower = 0;
-            nsig = 1;
-            sgn = 0;
-            roundingwidens = false;
-            r = 0.0;
-        } else {
-            if (x < 0.0) {
-                sgn = 1;
-                r = -x;
-            } else {
-                sgn = 0;
-                r = x;
-            }
-
-            if (pp.getDigits() >= DBL_DIG + 1) {
-                // TODO:
-                // format_via_sprintf(r, pp.getDigits(), kpower, nsig);
-                roundingwidens = false;
-                // return;
-                throw new UnsupportedOperationException();
-            }
-
-            kp = (int) Math.floor(Math.log10(r)) - pp.getDigits() + 1; // r = |x|;
-                                                                       // 10^(kp + digits - 1) <= r
-
-            double rPrec = r;
-            /* use exact scaling factor in double precision, if possible */
-            if (Math.abs(kp) <= 22) {
-                if (kp >= 0) {
-                    rPrec /= tbl[kp + 1];
-                } else {
-                    rPrec *= tbl[-kp + 1];
-                }
-            } else if (kp <= R_dec_min_exponent) {
-                /*
-                 * on IEEE 1e-308 is not representable except by gradual underflow. Shifting by 303
-                 * allows for any potential denormalized numbers x, and makes the reasonable
-                 * assumption that R_dec_min_exponent+303 is in range. Representation of 1e+303 has
-                 * low error.
-                 */
-                rPrec = (rPrec * 1e+303) / Math.pow(10, kp + 303);
-            } else {
-                rPrec /= Math.pow(10, kp);
-            }
-            if (rPrec < tbl[pp.getDigits()]) {
-                rPrec *= 10.0;
-                kp--;
-            }
-            /* round alpha to integer, 10^(digits-1) <= alpha <= 10^digits */
-            /*
-             * accuracy limited by double rounding problem, alpha already rounded to 53 bits
-             */
-            alpha = Math.round(rPrec);
-
-            nsig = pp.getDigits();
-            for (j = 1; j <= pp.getDigits(); j++) {
-                alpha /= 10.0;
-                if (alpha == Math.floor(alpha)) {
-                    nsig--;
-                } else {
-                    break;
-                }
-            }
-            if (nsig == 0 && pp.getDigits() > 0) {
-                nsig = 1;
-                kp += 1;
-            }
-            kpower = kp + pp.getDigits() - 1;
-
-            /*
-             * Scientific format may do more rounding than fixed format, e.g. 9996 with 3 digits is
-             * 1e+04 in scientific, but 9996 in fixed. This happens when the true value r is less
-             * than 10^(kpower+1) and would not round up to it in fixed format. Here rgt is the
-             * decimal place that will be cut off by rounding
-             */
-
-            int rgt = pp.getDigits() - kpower;
-            /* bound rgt by 0 and KP_MAX */
-            rgt = rgt < 0 ? 0 : rgt > KP_MAX ? KP_MAX : rgt;
-            double fuzz = 0.5 / tbl[1 + rgt];
-            // kpower can be bigger than the table.
-            roundingwidens = kpower > 0 && kpower <= KP_MAX && r < tbl[kpower + 1] - fuzz;
-
-        }
-
-        return new ScientificDouble(sgn, kpower, nsig, roundingwidens);
-    }
-
-    public static String encodeReal(double x, DoubleVectorMetrics dm, PrintParameters pp) {
-        return encodeReal(x, dm.maxWidth, dm.d, dm.e, '.', pp);
-    }
-
-    public static String encodeReal(double x, int w, int d, int e, char cdec, PrintParameters pp) {
-        final String buff;
-        String fmt;
-
-        /* IEEE allows signed zeros (yuck!) */
-        if (x == 0.0) {
-            x = 0.0;
-        }
-        if (!RRuntime.isFinite(x)) {
-            int numBlanks = Math.min(w, (NB - 1));
-            String naFmt = "%" + Utils.asBlankArg(numBlanks) + "s";
-            if (RRuntime.isNA(x)) {
-                buff = snprintf(NB, naFmt, pp.getNaString());
-            } else if (RRuntime.isNAorNaN(x)) {
-                buff = snprintf(NB, naFmt, "NaN");
-            } else if (x > 0) {
-                buff = snprintf(NB, naFmt, "Inf");
-            } else {
-                buff = snprintf(NB, naFmt, "-Inf");
-            }
-        } else if (e != 0) {
-            if (d != 0) {
-                fmt = String.format("%%#%d.%de", Math.min(w, (NB - 1)), d);
-                buff = snprintf(NB, fmt, x);
-            } else {
-                fmt = String.format("%%%d.%de", Math.min(w, (NB - 1)), d);
-                buff = snprintf(NB, fmt, x);
-            }
-        } else { /* e = 0 */
-            StringBuilder sb = new StringBuilder("#.#");
-            DecimalFormat df = new DecimalFormat(sb.toString());
-            df.setRoundingMode(RoundingMode.HALF_EVEN);
-            df.setDecimalSeparatorAlwaysShown(false);
-            df.setMinimumFractionDigits(d);
-            df.setMaximumFractionDigits(d);
-            String ds = df.format(x);
-            int blanks = w - ds.length();
-            fmt = "%" + Utils.asBlankArg(blanks) + "s%s";
-            buff = String.format(fmt, "", ds);
-        }
-
-        if (cdec != '.') {
-            buff.replace('.', cdec);
-        }
-
-        return buff;
-    }
-
-}
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 2826264d04f9e27cf5f17d787f1ff23835885917..ef5939fe83a6955e673adcb93cb6ab9fdcc4ba12 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
@@ -11,9 +11,12 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base.printer;
 
+import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.snprintf;
+
 import java.io.IOException;
+import java.math.RoundingMode;
+import java.text.DecimalFormat;
 
-import com.oracle.truffle.r.nodes.builtin.base.printer.DoublePrinter.ScientificDouble;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 
@@ -24,14 +27,14 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect
     public static final DoubleVectorPrinter INSTANCE = new DoubleVectorPrinter();
 
     @Override
-    protected VectorPrinter<RAbstractDoubleVector>.VectorPrintJob createJob(RAbstractDoubleVector vector, int indx, boolean quote, PrintContext printCtx) {
-        return new DoubleVectorPrintJob(vector, indx, quote, printCtx);
+    protected VectorPrinter<RAbstractDoubleVector>.VectorPrintJob createJob(RAbstractDoubleVector vector, int indx, PrintContext printCtx) {
+        return new DoubleVectorPrintJob(vector, indx, printCtx);
     }
 
     private final class DoubleVectorPrintJob extends VectorPrintJob {
 
-        protected DoubleVectorPrintJob(RAbstractDoubleVector vector, int indx, boolean quote, PrintContext printCtx) {
-            super(vector, indx, quote, printCtx);
+        protected DoubleVectorPrintJob(RAbstractDoubleVector vector, int indx, PrintContext printCtx) {
+            super(vector, indx, printCtx);
         }
 
         @Override
@@ -42,7 +45,7 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect
         @Override
         protected void printElement(int i, FormatMetrics fm) throws IOException {
             DoubleVectorMetrics dfm = (DoubleVectorMetrics) fm;
-            String v = DoublePrinter.encodeReal(vector.getDataAt(i), dfm.maxWidth, dfm.d, dfm.e, '.', printCtx.parameters());
+            String v = encodeReal(vector.getDataAt(i), dfm.maxWidth, dfm.d, dfm.e, '.', printCtx.parameters());
             out.print(v);
         }
 
@@ -121,7 +124,7 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect
                     neginf = true;
                 }
             } else {
-                ScientificDouble sd = DoublePrinter.scientific(xi, pp);
+                ScientificDouble sd = scientific(xi, pp);
                 sgn = sd.sgn;
                 nsig = sd.nsig;
                 kpower = sd.kpower;
@@ -220,4 +223,193 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect
         return new DoubleVectorMetrics(w, d, e);
     }
 
+    private static final int DBL_DIG = 15;
+
+    private static final double[] tbl = {
+                    1e-1,
+                    1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09,
+                    1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+                    1e20, 1e21, 1e22
+    };
+    private static final int KP_MAX = 22;
+    private static final int R_dec_min_exponent = -308;
+
+    public static final int NB = 1000;
+
+    public static class ScientificDouble {
+        public final int sgn;
+        public final int kpower;
+        public final int nsig;
+        public final boolean roundingwidens;
+
+        public ScientificDouble(int sgn, int kpower, int nsig, boolean roundingwidens) {
+            super();
+            this.sgn = sgn;
+            this.kpower = kpower;
+            this.nsig = nsig;
+            this.roundingwidens = roundingwidens;
+        }
+
+    }
+
+    public static ScientificDouble scientific(double x, PrintParameters pp) {
+        /*
+         * 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;
+        double r;
+        int kp;
+        int j;
+
+        // output arguments
+        int sgn;
+        int kpower;
+        int nsig;
+        boolean roundingwidens;
+
+        if (x == 0.0) {
+            kpower = 0;
+            nsig = 1;
+            sgn = 0;
+            roundingwidens = false;
+            r = 0.0;
+        } else {
+            if (x < 0.0) {
+                sgn = 1;
+                r = -x;
+            } else {
+                sgn = 0;
+                r = x;
+            }
+
+            if (pp.getDigits() >= DBL_DIG + 1) {
+                // TODO:
+                // format_via_sprintf(r, pp.getDigits(), kpower, nsig);
+                roundingwidens = false;
+                // return;
+                throw new UnsupportedOperationException();
+            }
+
+            kp = (int) Math.floor(Math.log10(r)) - pp.getDigits() + 1; // r = |x|;
+                                                                       // 10^(kp + digits - 1) <= r
+
+            double rPrec = r;
+            /* use exact scaling factor in double precision, if possible */
+            if (Math.abs(kp) <= 22) {
+                if (kp >= 0) {
+                    rPrec /= tbl[kp + 1];
+                } else {
+                    rPrec *= tbl[-kp + 1];
+                }
+            } else if (kp <= R_dec_min_exponent) {
+                /*
+                 * on IEEE 1e-308 is not representable except by gradual underflow. Shifting by 303
+                 * allows for any potential denormalized numbers x, and makes the reasonable
+                 * assumption that R_dec_min_exponent+303 is in range. Representation of 1e+303 has
+                 * low error.
+                 */
+                rPrec = (rPrec * 1e+303) / Math.pow(10, kp + 303);
+            } else {
+                rPrec /= Math.pow(10, kp);
+            }
+            if (rPrec < tbl[pp.getDigits()]) {
+                rPrec *= 10.0;
+                kp--;
+            }
+            /* round alpha to integer, 10^(digits-1) <= alpha <= 10^digits */
+            /*
+             * accuracy limited by double rounding problem, alpha already rounded to 53 bits
+             */
+            alpha = Math.round(rPrec);
+
+            nsig = pp.getDigits();
+            for (j = 1; j <= pp.getDigits(); j++) {
+                alpha /= 10.0;
+                if (alpha == Math.floor(alpha)) {
+                    nsig--;
+                } else {
+                    break;
+                }
+            }
+            if (nsig == 0 && pp.getDigits() > 0) {
+                nsig = 1;
+                kp += 1;
+            }
+            kpower = kp + pp.getDigits() - 1;
+
+            /*
+             * Scientific format may do more rounding than fixed format, e.g. 9996 with 3 digits is
+             * 1e+04 in scientific, but 9996 in fixed. This happens when the true value r is less
+             * than 10^(kpower+1) and would not round up to it in fixed format. Here rgt is the
+             * decimal place that will be cut off by rounding
+             */
+
+            int rgt = pp.getDigits() - kpower;
+            /* bound rgt by 0 and KP_MAX */
+            rgt = rgt < 0 ? 0 : rgt > KP_MAX ? KP_MAX : rgt;
+            double fuzz = 0.5 / tbl[1 + rgt];
+            // kpower can be bigger than the table.
+            roundingwidens = kpower > 0 && kpower <= KP_MAX && r < tbl[kpower + 1] - fuzz;
+
+        }
+
+        return new ScientificDouble(sgn, kpower, nsig, roundingwidens);
+    }
+
+    public static String encodeReal(double x, DoubleVectorMetrics dm, PrintParameters pp) {
+        return encodeReal(x, dm.maxWidth, dm.d, dm.e, '.', pp);
+    }
+
+    public static String encodeReal(double x, int w, int d, int e, char cdec, PrintParameters pp) {
+        final String buff;
+        String fmt;
+
+        /* IEEE allows signed zeros (yuck!) */
+        if (x == 0.0) {
+            x = 0.0;
+        }
+        if (!RRuntime.isFinite(x)) {
+            int numBlanks = Math.min(w, (NB - 1));
+            String naFmt = "%" + Utils.asBlankArg(numBlanks) + "s";
+            if (RRuntime.isNA(x)) {
+                buff = snprintf(NB, naFmt, pp.getNaString());
+            } else if (RRuntime.isNAorNaN(x)) {
+                buff = snprintf(NB, naFmt, "NaN");
+            } else if (x > 0) {
+                buff = snprintf(NB, naFmt, "Inf");
+            } else {
+                buff = snprintf(NB, naFmt, "-Inf");
+            }
+        } else if (e != 0) {
+            if (d != 0) {
+                fmt = String.format("%%#%d.%de", Math.min(w, (NB - 1)), d);
+                buff = snprintf(NB, fmt, x);
+            } else {
+                fmt = String.format("%%%d.%de", Math.min(w, (NB - 1)), d);
+                buff = snprintf(NB, fmt, x);
+            }
+        } else { /* e = 0 */
+            StringBuilder sb = new StringBuilder("#.#");
+            DecimalFormat df = new DecimalFormat(sb.toString());
+            df.setRoundingMode(RoundingMode.HALF_EVEN);
+            df.setDecimalSeparatorAlwaysShown(false);
+            df.setMinimumFractionDigits(d);
+            df.setMaximumFractionDigits(d);
+            String ds = df.format(x);
+            int blanks = w - ds.length();
+            fmt = "%" + Utils.asBlankArg(blanks) + "s%s";
+            buff = String.format(fmt, "", ds);
+        }
+
+        if (cdec != '.') {
+            buff.replace('.', cdec);
+        }
+
+        return buff;
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/EnvironmentPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/EnvironmentPrinter.java
index 943b9e34a1be5503c72cc5d31f2bcf7d0b08cf8f..2a536db0961d1bc8c38f2a72d41c9ff220d193d5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/EnvironmentPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/EnvironmentPrinter.java
@@ -32,7 +32,7 @@ public final class EnvironmentPrinter extends AbstractValuePrinter<REnvironment>
 
     @Override
     protected void printValue(REnvironment value, PrintContext printCtx) throws IOException {
-        printCtx.output().print(value.toString());
+        printCtx.output().print(value.getPrintName());
     }
 
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FactorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FactorPrinter.java
new file mode 100644
index 0000000000000000000000000000000000000000..5c0d609a5d7ece1846a687f41442f183c040a920
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FactorPrinter.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, 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.builtin.base.printer;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import com.oracle.truffle.r.runtime.data.RAttributeProfiles;
+import com.oracle.truffle.r.runtime.data.RFactor;
+import com.oracle.truffle.r.runtime.data.RVector;
+import com.oracle.truffle.r.runtime.data.closures.RClosures;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+public final class FactorPrinter extends AbstractValuePrinter<RFactor> {
+
+    public static final FactorPrinter INSTANCE = new FactorPrinter();
+
+    private static RAttributeProfiles dummyAttrProfiles = RAttributeProfiles.create();
+
+    @Override
+    protected void printValue(RFactor operand, PrintContext printCtx) throws IOException {
+        // TODO: this should be handled by an S3 function
+        RVector vec = operand.getLevels(dummyAttrProfiles);
+        String[] strings;
+        if (vec == null) {
+            strings = new String[0];
+        } else {
+            strings = new String[vec.getLength()];
+            for (int i = 0; i < vec.getLength(); i++) {
+                strings[i] = printCtx.printerNode().castString(vec.getDataAtAsObject(i));
+            }
+        }
+
+        RAbstractVector v = RClosures.createFactorToVector(operand, true, dummyAttrProfiles);
+        PrintContext vectorPrintCtx = printCtx.cloneContext();
+        vectorPrintCtx.parameters().setQuote(false);
+        ValuePrinters.INSTANCE.println(v, vectorPrintCtx);
+
+        final PrintWriter out = printCtx.output();
+        out.print("Levels:");
+        if (vec != null) {
+            for (int i = 0; i < vec.getLength(); i++) {
+                out.print(" ");
+                out.print(strings[i]);
+            }
+        }
+
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerPrinter.java
deleted file mode 100644
index 18e7418776621f27e3ec31f1a39bc963698a6ba7..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerPrinter.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (c) 1997-2013,  The R Core Team
- * Copyright (c) 2016, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.nodes.builtin.base.printer;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-
-import com.oracle.truffle.r.nodes.builtin.base.printer.VectorPrinter.FormatMetrics;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RInteger;
-
-//Transcribed from GnuR, src/main/printutils.c
-
-public final class IntegerPrinter extends AbstractScalarValuePrinter<Integer> {
-
-    public static final IntegerPrinter INSTANCE = new IntegerPrinter();
-
-    @Override
-    protected void printScalarValue(Integer value, PrintContext printCtx) throws IOException {
-        FormatMetrics fm = IntegerVectorPrinter.formatIntVector(RInteger.valueOf(value),
-                        0, 1, printCtx.parameters().getNaWidth());
-        String s = encodeInteger(value, fm.maxWidth, printCtx.parameters());
-        PrintWriter out = printCtx.output();
-        out.print(s);
-    }
-
-    /*
-     * There is no documented (or enforced) limit on 'w' here, so use snprintf
-     */
-    public static int NB = 1000;
-
-    public static String encodeInteger(int x, int w, PrintParameters pp) {
-        if (x == RRuntime.INT_NA) {
-            return Utils.snprintf(NB, "%" + Utils.asBlankArg(Math.min(w, (NB - 1))) + "s", pp.getNaString());
-        } else {
-            return Utils.snprintf(NB, "%" + Utils.asBlankArg(Math.min(w, (NB - 1))) + "d", x);
-        }
-    }
-
-}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java
index 497fbcd9f80b8c8f39ddf10118de7b2f0b69bb2d..f80a140f61bab2937fafed4d9078f274291747c6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java
@@ -25,14 +25,14 @@ public final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector
     public static final IntegerVectorPrinter INSTANCE = new IntegerVectorPrinter();
 
     @Override
-    protected IntegerVectorPrintJob createJob(RAbstractIntVector vector, int indx, boolean quote, PrintContext printCtx) {
-        return new IntegerVectorPrintJob(vector, indx, quote, printCtx);
+    protected IntegerVectorPrintJob createJob(RAbstractIntVector vector, int indx, PrintContext printCtx) {
+        return new IntegerVectorPrintJob(vector, indx, printCtx);
     }
 
     private final class IntegerVectorPrintJob extends VectorPrintJob {
 
-        protected IntegerVectorPrintJob(RAbstractIntVector vector, int indx, boolean quote, PrintContext printCtx) {
-            super(vector, indx, quote, printCtx);
+        protected IntegerVectorPrintJob(RAbstractIntVector vector, int indx, PrintContext printCtx) {
+            super(vector, indx, printCtx);
         }
 
         @Override
@@ -47,7 +47,7 @@ public final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector
 
         @Override
         protected void printElement(int i, FormatMetrics fm) throws IOException {
-            String v = IntegerPrinter.encodeInteger(vector.getDataAt(i), fm.maxWidth, printCtx.parameters());
+            String v = encodeInteger(vector.getDataAt(i), fm.maxWidth, printCtx.parameters());
             out.print(v);
         }
 
@@ -106,4 +106,17 @@ public final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector
         return new FormatMetrics(fieldwidth);
     }
 
+    /*
+     * There is no documented (or enforced) limit on 'w' here, so use snprintf
+     */
+    public static int NB = 1000;
+
+    public static String encodeInteger(int x, int w, PrintParameters pp) {
+        if (x == RRuntime.INT_NA) {
+            return Utils.snprintf(NB, "%" + Utils.asBlankArg(Math.min(w, (NB - 1))) + "s", pp.getNaString());
+        } else {
+            return Utils.snprintf(NB, "%" + Utils.asBlankArg(Math.min(w, (NB - 1))) + "d", x);
+        }
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
index 9765e090faf6851c58113bd83edeb0f1cfecdac5..352c7344d3338f4ff1471bf260541bbdd121f572 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
@@ -20,25 +20,32 @@ import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.canBeStringV
 import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.indexWidth;
 import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.isValidName;
 import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.snprintf;
+import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.toComplexVector;
 import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.toDoubleVector;
 import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.toIntVector;
+import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.toLogicalVector;
 import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.toStringVector;
 
 import java.io.IOException;
 import java.io.PrintWriter;
 
+import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
+import com.oracle.truffle.r.nodes.builtin.base.printer.ComplexVectorPrinter.ComplexVectorMetrics;
 import com.oracle.truffle.r.nodes.builtin.base.printer.DoubleVectorPrinter.DoubleVectorMetrics;
 import com.oracle.truffle.r.nodes.builtin.base.printer.VectorPrinter.FormatMetrics;
 import com.oracle.truffle.r.runtime.RRuntime;
 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.RLanguage;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 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;
 
@@ -52,6 +59,113 @@ public final class ListPrinter extends AbstractValuePrinter<RAbstractListVector>
 
     @Override
     protected void printValue(RAbstractListVector s, PrintContext printCtx) throws IOException {
+        RAbstractIntVector dims = Utils.<RAbstractIntVector> castTo(
+                        s.getAttr(dummyAttrProfiles, RRuntime.DIM_ATTR_KEY));
+
+        if (dims != null && dims.getLength() > 1) {
+            printDimList(s, printCtx);
+        } else {
+            // no dim()
+            printNoDimList(s, printCtx);
+        }
+
+    }
+
+    private static void printDimList(RAbstractListVector s, PrintContext printCtx) throws IOException {
+        final PrintParameters pp = printCtx.parameters();
+
+        int ns = s.getLength();
+        String[] t = new String[ns];
+        for (int i = 0; i < ns; i++) {
+            Object tmp = s.getDataAtAsObject(i);
+            final String pbuf;
+            if (tmp == null || tmp == RNull.instance) {
+                pbuf = RRuntime.NULL;
+            } else if (canBeLogicalVector(tmp)) {
+                RAbstractLogicalVector lv = toLogicalVector(tmp);
+                if (lv.getLength() == 1) {
+                    FormatMetrics fm = LogicalVectorPrinter.formatLogicalVector(lv, 0, 1, pp.getNaWidth());
+                    pbuf = snprintf(115, "%s",
+                                    LogicalVectorPrinter.encodeLogical(lv.getDataAt(0), fm.maxWidth, pp));
+                } else {
+                    pbuf = snprintf(115, "Logical,%d", lv.getLength());
+                }
+            } else if (canBeIntVector(tmp)) {
+                RAbstractIntVector iv = toIntVector(tmp);
+                if (printCtx.printerNode().inherits(iv, "factor", RRuntime.LOGICAL_FALSE)) {
+                    /* factors are stored as integers */
+                    pbuf = snprintf(115, "factor,%d", iv.getLength());
+                } else {
+                    if (iv.getLength() == 1) {
+                        FormatMetrics fm = IntegerVectorPrinter.formatIntVector(iv, 0, 1, pp.getNaWidth());
+                        pbuf = snprintf(115, "%s",
+                                        IntegerVectorPrinter.encodeInteger(iv.getDataAt(0), fm.maxWidth, pp));
+                    } else {
+                        pbuf = snprintf(115, "Integer,%d", iv.getLength());
+                    }
+                }
+            } else if (canBeDoubleVector(tmp)) {
+                RAbstractDoubleVector dv = toDoubleVector(tmp);
+                if (dv.getLength() == 1) {
+                    DoubleVectorMetrics fm = DoubleVectorPrinter.formatDoubleVector(dv, 0, 1, 0, pp);
+                    pbuf = snprintf(115, "%s",
+                                    DoubleVectorPrinter.encodeReal(dv.getDataAt(0), fm, pp));
+                } else {
+                    pbuf = snprintf(115, "Numeric,%d", dv.getLength());
+                }
+            } else if (tmp instanceof RAbstractComplexVector) {
+                RAbstractComplexVector cv = toComplexVector(tmp);
+                if (cv.getLength() == 1) {
+                    RComplex x = cv.getDataAt(0);
+                    if (RRuntime.isNA(x.getRealPart()) || RRuntime.isNA(x.getImaginaryPart())) {
+                        /* formatReal(NA) --> w=R_print.na_width, d=0, e=0 */
+                        pbuf = snprintf(115, "%s",
+                                        DoubleVectorPrinter.encodeReal(RRuntime.DOUBLE_NA, pp.getNaWidth(), 0, 0, '.', pp));
+                    } else {
+                        ComplexVectorMetrics cvm = ComplexVectorPrinter.formatComplexVector(x, 0, 1, 0, pp);
+                        pbuf = snprintf(115, "%s", ComplexVectorPrinter.encodeComplex(x, cvm, pp));
+                    }
+                } else {
+                    pbuf = snprintf(115, "Complex,%d", cv.getLength());
+                }
+            } else if (canBeStringVector(tmp)) {
+                RAbstractStringVector sv = toStringVector(tmp);
+                if (sv.getLength() == 1) {
+                    String ctmp = sv.getDataAt(0);
+                    int len = ctmp.length();
+                    if (len < 100) {
+                        pbuf = snprintf(115, "\"%s\"", ctmp);
+                    } else {
+                        pbuf = snprintf(101, "\"%s", ctmp) + "\" [truncated]";
+                    }
+                } else {
+                    pbuf = snprintf(115, "Character,%d", sv.getLength());
+                }
+            } else if (tmp instanceof RAbstractRawVector) {
+                pbuf = snprintf(115, "Raw,%d", ((RAbstractRawVector) (tmp)).getLength());
+            } else if (tmp instanceof RAbstractListVector) {
+                pbuf = snprintf(115, "List,%d", ((RAbstractListVector) (tmp)).getLength());
+            } else if (tmp instanceof RLanguage) {
+                pbuf = snprintf(115, "Expression");
+            } else {
+                pbuf = snprintf(115, "?");
+            }
+
+            t[i] = pbuf;
+        }
+
+        RStringVector tt = RDataFactory.createStringVector(t, true, s.getDimensions());
+        Object dimNames = s.getAttr(dummyAttrProfiles, RRuntime.DIMNAMES_ATTR_KEY);
+        tt.setAttr(RRuntime.DIMNAMES_ATTR_KEY, dimNames);
+
+        PrintContext cc = printCtx.cloneContext();
+        cc.parameters().setQuote(false);
+        StringVectorPrinter.INSTANCE.print(tt, cc);
+    }
+
+    static void printNoDimList(RAbstractContainer s, PrintContext printCtx) throws IOException {
+        final PrintParameters pp = printCtx.parameters();
+        final PrintWriter out = printCtx.output();
 
         class TagBuf {
             final int tagStartMark = buffer().length();
@@ -84,168 +198,95 @@ public final class ListPrinter extends AbstractValuePrinter<RAbstractListVector>
 
         }
         final TagBuf tagbuf = new TagBuf();
-
-        final PrintParameters pp = printCtx.parameters();
-        final PrintWriter out = printCtx.output();
-
         int taglen = tagbuf.taglen();
-        RAbstractIntVector dims = Utils.<RAbstractIntVector> castTo(
-                        s.getAttr(dummyAttrProfiles, RRuntime.DIM_ATTR_KEY));
-        RAbstractStringVector names;
 
         int ns = s.getLength();
 
-        if (dims != null && dims.getLength() > 1) {
-            // Calculate the size of the array from the dimensions
-            String[] t = new String[ns];
-            for (int i = 0; i < ns; i++) {
-                Object tmp = s.getDataAtAsObject(i);
-                final String pbuf;
-                if (tmp == null || tmp == RNull.instance) {
-                    pbuf = RRuntime.NULL;
-                } else if (canBeLogicalVector(tmp)) {
-                    throw new UnsupportedOperationException("TODO");
-                } else if (canBeIntVector(tmp)) {
-                    RAbstractIntVector iv = toIntVector(tmp);
-                    if (printCtx.printerNode().inherits(iv, "factor", RRuntime.LOGICAL_FALSE)) {
-                        /* factors are stored as integers */
-                        pbuf = snprintf(115, "factor,%d", iv.getLength());
+        RAbstractStringVector names;
+        names = toStringVector(s.getAttr(dummyAttrProfiles, RRuntime.NAMES_ATTR_KEY));
+
+        if (ns > 0) {
+            int npr = (ns <= pp.getMax() + 1) ? ns : pp.getMax();
+            /* '...max +1' ==> will omit at least 2 ==> plural in msg below */
+            for (int i = 0; i < npr; i++) {
+                if (i > 0) {
+                    out.println();
+                }
+                String ss = names == null ? null : Utils.<String> getDataAt(names, i);
+                if (ss != null && !"".equals(ss)) {
+                    /*
+                     * Bug for L <- list(`a\\b` = 1, `a\\c` = 2) : const char *ss =
+                     * translateChar(STRING_ELT(names, i));
+                     */
+                    if (taglen + ss.length() > TAGBUFLEN) {
+                        if (taglen <= TAGBUFLEN) {
+                            tagbuf.appendTag("$...");
+                        }
                     } else {
-                        if (iv.getLength() == 1) {
-                            FormatMetrics fm = IntegerVectorPrinter.formatIntVector(iv, 0, 1, pp.getNaWidth());
-                            pbuf = snprintf(115, "%s",
-                                            IntegerPrinter.encodeInteger(iv.getDataAt(0), fm.maxWidth, pp));
+                        /*
+                         * we need to distinguish character NA from "NA", which is a valid (if
+                         * non-syntactic) name
+                         */
+                        if (ss == RRuntime.STRING_NA) {
+                            tagbuf.appendTag("$<NA>");
+                        } else if (isValidName(ss)) {
+                            tagbuf.appendTag(String.format("$%s", ss));
                         } else {
-                            pbuf = snprintf(115, "Integer,%d", iv.getLength());
+                            tagbuf.appendTag(String.format("$`%s`", ss));
                         }
                     }
-                } else if (canBeDoubleVector(tmp)) {
-                    RAbstractDoubleVector dv = toDoubleVector(tmp);
-                    if (dv.getLength() == 1) {
-                        DoubleVectorMetrics fm = DoubleVectorPrinter.formatDoubleVector(dv, 0, 1, 0, pp);
-                        pbuf = snprintf(115, "%s",
-                                        DoublePrinter.encodeReal(dv.getDataAt(0), fm, pp));
-                    } else {
-                        pbuf = snprintf(115, "Numeric,%d", dv.getLength());
-                    }
-                } else if (tmp instanceof RAbstractComplexVector) {
-                    throw new UnsupportedOperationException("TODO");
-                } else if (canBeStringVector(tmp)) {
-                    RAbstractStringVector sv = toStringVector(tmp);
-                    if (sv.getLength() == 1) {
-                        String ctmp = sv.getDataAt(0);
-                        int len = ctmp.length();
-                        if (len < 100) {
-                            pbuf = snprintf(115, "\"%s\"", ctmp);
-                        } else {
-                            pbuf = snprintf(101, "\"%s", ctmp) + "\" [truncated]";
+
+                } else {
+                    if (taglen + indexWidth(i) > TAGBUFLEN) {
+                        if (taglen <= TAGBUFLEN) {
+                            tagbuf.appendTag("$...");
                         }
                     } else {
-                        pbuf = snprintf(115, "Character,%d", sv.getLength());
+                        tagbuf.appendTag(String.format("[[%d]]", i + 1));
                     }
-                } else if (tmp instanceof RAbstractRawVector) {
-                    pbuf = snprintf(115, "Raw,%d", ((RAbstractRawVector) (tmp)).getLength());
-                } else if (tmp instanceof RAbstractListVector) {
-                    pbuf = snprintf(115, "List,%d", ((RAbstractListVector) (tmp)).getLength());
-                } else if (tmp instanceof RLanguage) {
-                    pbuf = snprintf(115, "Expression");
+                }
+
+                out.println(tagbuf);
+                Object si = s.getDataAtAsObject(i);
+                if (printCtx.printerNode().isObject(si)) {
+                    ValuePrinters.INSTANCE.println(si, printCtx);
                 } else {
-                    pbuf = snprintf(115, "?");
+                    ValuePrinters.INSTANCE.println(si, printCtx);
                 }
 
-                t[i] = pbuf;
+                tagbuf.removeTag();
             }
 
-            RStringVector tt = RDataFactory.createStringVector(t, true, s.getDimensions());
-            Object dimNames = s.getAttr(dummyAttrProfiles, RRuntime.DIMNAMES_ATTR_KEY);
-            tt.setAttr(RRuntime.DIMNAMES_ATTR_KEY, dimNames);
-
-            PrintContext cc = printCtx.cloneContext();
-            cc.parameters().setQuote(false);
-            StringVectorPrinter.INSTANCE.print(tt, cc);
+            if (npr < ns) {
+                out.printf("\n [ reached getOption(\"max.print\") -- omitted %d entries ]",
+                                ns - npr);
+            }
 
         } else {
-            // no dim()
-            names = toStringVector(s.getAttr(dummyAttrProfiles, RRuntime.NAMES_ATTR_KEY));
-
-            if (ns > 0) {
-                int npr = (ns <= pp.getMax() + 1) ? ns : pp.getMax();
-                /* '...max +1' ==> will omit at least 2 ==> plural in msg below */
-                for (int i = 0; i < npr; i++) {
-                    if (i > 0) {
-                        out.println();
-                    }
-                    String ss = names == null ? null : Utils.<String> getDataAt(names, i);
-                    if (ss != null && !"".equals(ss)) {
-                        /*
-                         * Bug for L <- list(`a\\b` = 1, `a\\c` = 2) : const char *ss =
-                         * translateChar(STRING_ELT(names, i));
-                         */
-                        if (taglen + ss.length() > TAGBUFLEN) {
-                            if (taglen <= TAGBUFLEN) {
-                                tagbuf.appendTag("$...");
-                            }
-                        } else {
-                            /*
-                             * we need to distinguish character NA from "NA", which is a valid (if
-                             * non-syntactic) name
-                             */
-                            if (ss == RRuntime.STRING_NA) {
-                                tagbuf.appendTag("$<NA>");
-                            } else if (isValidName(ss)) {
-                                tagbuf.appendTag(String.format("$%s", ss));
-                            } else {
-                                tagbuf.appendTag(String.format("$`%s`", ss));
-                            }
-                        }
-
-                    } else {
-                        if (taglen + indexWidth(i) > TAGBUFLEN) {
-                            if (taglen <= TAGBUFLEN) {
-                                tagbuf.appendTag("$...");
-                            }
-                        } else {
-                            tagbuf.appendTag(String.format("[[%d]]", i + 1));
-                        }
+            /* ns = length(s) == 0 */
+
+            /* Formal classes are represented as empty lists */
+            String className = null;
+            if (printCtx.printerNode().isObject(s) && printCtx.printerNode().isMethodDispatchOn()) {
+                RAbstractStringVector klass = toStringVector(s.getAttr(dummyAttrProfiles, RRuntime.CLASS_ATTR_KEY));
+                if (klass != null && klass.getLength() == 1) {
+                    String ss = klass.getDataAt(0);
+                    String str = snprintf(200, ".__C__%s", ss);
+                    if (ReadVariableNode.lookupAny(str, printCtx.frame(), false) != null) {
+                        className = ss;
                     }
-
-                    out.println(tagbuf);
-                    Object si = s.getDataAtAsObject(i);
-                    if (printCtx.printerNode().isObject(si)) {
-                        throw new UnsupportedOperationException("TODO");
-                    } else {
-                        ValuePrinters.INSTANCE.println(si, printCtx);
-                    }
-
-                    tagbuf.removeTag();
                 }
-
-                if (npr < ns) {
-                    out.printf("\n [ reached getOption(\"max.print\") -- omitted %d entries ]",
-                                    ns - npr);
-                }
-
+            }
+            if (className != null) {
+                out.printf("An object of class \"%s\"", className);
             } else {
-                /* ns = length(s) == 0 */
-
-                /* Formal classes are represented as empty lists */
-                String className = null;
-                RAbstractStringVector klass;
-                if (printCtx.printerNode().isObject(s) && printCtx.printerNode().isMethodDispatchOn()) {
-                    throw new UnsupportedOperationException("TODO");
+                if (names != null) {
+                    out.print("named ");
                 }
-                if (className != null) {
-                    out.printf("An object of class \"%s\"", className);
-                } else {
-                    if (names != null) {
-                        out.print("named ");
-                    }
-                    out.print("list()");
-                }
-
+                out.print("list()");
             }
-        }
 
+        }
     }
 
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalPrinter.java
deleted file mode 100644
index cb1e3ede3d6a1b87b32eb368ec86896b048d0229..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalPrinter.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (c) 1997-2013,  The R Core Team
- * Copyright (c) 2016, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.nodes.builtin.base.printer;
-
-import static com.oracle.truffle.r.nodes.builtin.base.printer.IntegerPrinter.NB;
-import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.snprintf;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-
-import com.oracle.truffle.r.nodes.builtin.base.printer.VectorPrinter.FormatMetrics;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RLogical;
-
-//Transcribed from GnuR, src/main/printutils.c
-
-public final class LogicalPrinter extends AbstractScalarValuePrinter<Byte> {
-
-    public static final LogicalPrinter INSTANCE = new LogicalPrinter();
-
-    @Override
-    protected void printScalarValue(Byte value, PrintContext printCtx) throws IOException {
-        FormatMetrics fm = LogicalVectorPrinter.formatLogicalVector(RLogical.valueOf(value),
-                        0, 1, printCtx.parameters().getNaWidth());
-        String s = encodeLogical(value, fm.maxWidth, printCtx.parameters());
-        PrintWriter out = printCtx.output();
-        out.print(s);
-    }
-
-    public static String encodeLogical(byte x, int w, PrintParameters pp) {
-        final String fmt = "%" + Utils.asBlankArg(Math.min(w, (NB - 1))) + "s";
-        if (x == RRuntime.LOGICAL_NA) {
-            return snprintf(NB, fmt, pp.getNaString());
-        } else if (x != 0) {
-            return snprintf(NB, fmt, "TRUE");
-        } else {
-            return snprintf(NB, fmt, "FALSE");
-        }
-    }
-
-}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java
index 295de7288947b607c6c4a263c0fc05e7f2cf6739..9d84e4b571e57919228d1dabd01a0fc7a004402d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java
@@ -11,6 +11,9 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base.printer;
 
+import static com.oracle.truffle.r.nodes.builtin.base.printer.IntegerVectorPrinter.NB;
+import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.snprintf;
+
 import java.io.IOException;
 
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -23,14 +26,14 @@ public final class LogicalVectorPrinter extends VectorPrinter<RAbstractLogicalVe
     public static final LogicalVectorPrinter INSTANCE = new LogicalVectorPrinter();
 
     @Override
-    protected VectorPrinter<RAbstractLogicalVector>.VectorPrintJob createJob(RAbstractLogicalVector vector, int indx, boolean quote, PrintContext printCtx) {
-        return new LogicalVectorPrintJob(vector, indx, quote, printCtx);
+    protected VectorPrinter<RAbstractLogicalVector>.VectorPrintJob createJob(RAbstractLogicalVector vector, int indx, PrintContext printCtx) {
+        return new LogicalVectorPrintJob(vector, indx, printCtx);
     }
 
     private final class LogicalVectorPrintJob extends VectorPrintJob {
 
-        protected LogicalVectorPrintJob(RAbstractLogicalVector vector, int indx, boolean quote, PrintContext printCtx) {
-            super(vector, indx, quote, printCtx);
+        protected LogicalVectorPrintJob(RAbstractLogicalVector vector, int indx, PrintContext printCtx) {
+            super(vector, indx, printCtx);
         }
 
         @Override
@@ -45,7 +48,7 @@ public final class LogicalVectorPrinter extends VectorPrinter<RAbstractLogicalVe
 
         @Override
         protected void printElement(int i, FormatMetrics fm) throws IOException {
-            String v = LogicalPrinter.encodeLogical(vector.getDataAt(i), fm.maxWidth, printCtx.parameters());
+            String v = encodeLogical(vector.getDataAt(i), fm.maxWidth, printCtx.parameters());
             out.print(v);
         }
 
@@ -78,4 +81,16 @@ public final class LogicalVectorPrinter extends VectorPrinter<RAbstractLogicalVe
         }
         return new FormatMetrics(fieldwidth);
     }
+
+    public static String encodeLogical(byte x, int w, PrintParameters pp) {
+        final String fmt = "%" + Utils.asBlankArg(Math.min(w, (NB - 1))) + "s";
+        if (x == RRuntime.LOGICAL_NA) {
+            return snprintf(NB, fmt, pp.getNaString());
+        } else if (x != 0) {
+            return snprintf(NB, fmt, "TRUE");
+        } else {
+            return snprintf(NB, fmt, "FALSE");
+        }
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/NullPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/NullPrinter.java
index 191975291b88e342ed68bd2da039be3d57487838..0cfdb5d0cfab144d3e8c34dc4bb4a9f1b17fedac 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/NullPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/NullPrinter.java
@@ -23,12 +23,13 @@
 package com.oracle.truffle.r.nodes.builtin.base.printer;
 
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RNull;
 
-public final class NullPrinter implements ValuePrinter<Object> {
+public final class NullPrinter implements ValuePrinter<RNull> {
 
     public static NullPrinter INSTANCE = new NullPrinter();
 
-    public void print(Object value, PrintContext printCtx) {
+    public void print(RNull value, PrintContext printCtx) {
         printCtx.output().print(RRuntime.NULL);
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java
new file mode 100644
index 0000000000000000000000000000000000000000..5cc0332ee6905e268f37bc0ff583e3ca1e3231a6
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java
@@ -0,0 +1,96 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
+ * Copyright (c) 1997-2013,  The R Core Team
+ * Copyright (c) 2016, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.nodes.builtin.base.printer;
+
+import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.canBeDoubleVector;
+import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.canBeIntVector;
+import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.canBeLogicalVector;
+import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.canBeStringVector;
+import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.snprintf;
+import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.toComplexVector;
+import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.toDoubleVector;
+import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.toIntVector;
+import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.toLogicalVector;
+import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.toStringVector;
+
+import java.io.IOException;
+
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RAttributeProfiles;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
+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.RAbstractRawVector;
+
+//Transcribed from GnuR, src/main/print.c
+
+public final class PairListPrinter extends AbstractValuePrinter<RPairList> {
+
+    public static final PairListPrinter INSTANCE = new PairListPrinter();
+
+    private static RAttributeProfiles dummyAttrProfiles = RAttributeProfiles.create();
+
+    @Override
+    protected void printValue(RPairList s, PrintContext printCtx) throws IOException {
+        final RAbstractIntVector dims = Utils.<RAbstractIntVector> castTo(
+                        s.getAttr(dummyAttrProfiles, RRuntime.DIM_ATTR_KEY));
+
+        final int ns = s.getLength();
+
+        if (dims != null && dims.getLength() > 1) {
+            String[] t = new String[ns];
+            for (int i = 0; i < ns; i++) {
+                Object tmp = s.getDataAtAsObject(i);
+                final String pbuf;
+                if (tmp == null || tmp == RNull.instance) {
+                    pbuf = RRuntime.NULL;
+                } else if (canBeLogicalVector(tmp)) {
+                    pbuf = snprintf(115, "Logical,%d", toLogicalVector(tmp).getLength());
+                } else if (canBeIntVector(tmp)) {
+                    pbuf = snprintf(115, "Integer,%d", toIntVector(tmp).getLength());
+                } else if (canBeDoubleVector(tmp)) {
+                    pbuf = snprintf(115, "Numeric,%d", toDoubleVector(tmp).getLength());
+                } else if (tmp instanceof RAbstractComplexVector) {
+                    pbuf = snprintf(115, "Complex,%d", toComplexVector(tmp).getLength());
+                } else if (canBeStringVector(tmp)) {
+                    pbuf = snprintf(115, "Character,%d", toStringVector(tmp).getLength());
+                } else if (tmp instanceof RAbstractRawVector) {
+                    pbuf = snprintf(115, "Raw,%d", ((RAbstractRawVector) (tmp)).getLength());
+                } else if (tmp instanceof RAbstractListVector) {
+                    pbuf = snprintf(115, "List,%d", ((RAbstractListVector) (tmp)).getLength());
+                } else if (tmp instanceof RLanguage) {
+                    pbuf = snprintf(115, "Expression");
+                } else {
+                    pbuf = snprintf(115, "?");
+                }
+
+                t[i] = pbuf;
+
+                RStringVector tt = RDataFactory.createStringVector(t, true, s.getDimensions());
+                Object dimNames = s.getAttr(dummyAttrProfiles, RRuntime.DIMNAMES_ATTR_KEY);
+                tt.setAttr(RRuntime.DIMNAMES_ATTR_KEY, dimNames);
+
+                PrintContext cc = printCtx.cloneContext();
+                cc.parameters().setQuote(false);
+                StringVectorPrinter.INSTANCE.print(tt, cc);
+            }
+        } else {
+            // no dim()
+            ListPrinter.printNoDimList(s.toRList(), printCtx);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintContext.java
index 85fc30685e738082d2ef794c07b805f3d2dc908b..18a4836f1e9143a4d61506f40830d3bde7e33e97 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintContext.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintContext.java
@@ -23,19 +23,27 @@
 package com.oracle.truffle.r.nodes.builtin.base.printer;
 
 import java.io.PrintWriter;
+import java.util.ArrayDeque;
 import java.util.HashMap;
 import java.util.Map;
 
-public class PrintContext {
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.r.runtime.RInternalError;
+
+public final class PrintContext {
     private final ValuePrinterNode pn;
     private final PrintParameters params;
     private final PrintWriter out;
     private final Map<String, Object> attrs = new HashMap<>();
+    private final VirtualFrame frame;
+
+    private static final ThreadLocal<ArrayDeque<PrintContext>> printCtxTL = new ThreadLocal<>();
 
-    public PrintContext(ValuePrinterNode printerNode, PrintParameters parameters, PrintWriter output) {
+    private PrintContext(ValuePrinterNode printerNode, PrintParameters parameters, PrintWriter output, VirtualFrame frame) {
         this.pn = printerNode;
         this.params = parameters;
         this.out = output;
+        this.frame = frame;
     }
 
     public PrintParameters parameters() {
@@ -46,6 +54,10 @@ public class PrintContext {
         return pn;
     }
 
+    public VirtualFrame frame() {
+        return frame;
+    }
+
     public PrintWriter output() {
         return out;
     }
@@ -59,9 +71,38 @@ public class PrintContext {
     }
 
     public PrintContext cloneContext() {
-        PrintContext cloned = new PrintContext(pn, params.cloneParameters(), out);
+        PrintContext cloned = new PrintContext(pn, params.cloneParameters(), out, frame);
         cloned.attrs.putAll(attrs);
         return cloned;
     }
 
+    public static PrintContext enter(ValuePrinterNode printerNode, PrintParameters parameters, PrintWriter output, VirtualFrame frame) {
+        ArrayDeque<PrintContext> ctxStack = printCtxTL.get();
+        if (ctxStack == null) {
+            ctxStack = new ArrayDeque<>();
+            printCtxTL.set(ctxStack);
+            PrintContext ctx = new PrintContext(printerNode, parameters, output, frame);
+            ctxStack.push(ctx);
+            return ctx;
+        } else {
+            PrintContext parentCtx = ctxStack.peek();
+            PrintContext ctx = new PrintContext(printerNode, parameters, parentCtx.output(), frame);
+            ctx.attrs.putAll(parentCtx.attrs);
+            ctxStack.push(ctx);
+            return ctx;
+        }
+    }
+
+    public static void leave() {
+        ArrayDeque<PrintContext> ctxStack = printCtxTL.get();
+
+        RInternalError.guarantee(ctxStack != null, "No pretty-printer context stack");
+        RInternalError.guarantee(!ctxStack.isEmpty(), "Pretty-printer context stack is empty");
+
+        ctxStack.pop();
+
+        if (ctxStack.isEmpty()) {
+            printCtxTL.remove();
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java
index d99542c34027bc453b3c16115f7a4d56fe830cd9..53fdf8bd4704295b9bf3914df2b8020fd44d190b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java
@@ -19,7 +19,7 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RString;
 
-public class PrintParameters {
+public final class PrintParameters {
     public static final int DEFAULT_DIGITS = RRuntime.asInteger(RContext.getInstance().stateROptions.getValue("digits"));
 
     private int width;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PromisePrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PromisePrinter.java
deleted file mode 100644
index 09ebf2f6cba1ddf224583fcf97b8b197a32ca9ba..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PromisePrinter.java
+++ /dev/null
@@ -1,57 +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.builtin.base.printer;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-
-import com.oracle.truffle.api.source.SourceSection;
-import com.oracle.truffle.r.runtime.data.RPromise;
-import com.oracle.truffle.r.runtime.nodes.RNode;
-
-public final class PromisePrinter extends AbstractValuePrinter<RPromise> {
-
-    public static final PromisePrinter INSTANCE = new PromisePrinter();
-
-    @Override
-    protected void printValue(RPromise promise, PrintContext printCtx) throws IOException {
-        if (promise.isEvaluated()) {
-            ValuePrinters.INSTANCE.print(promise.getValue(), printCtx);
-        } else {
-            printPromise(promise, printCtx);
-        }
-    }
-
-    private static void printPromise(RPromise promise, PrintContext printCtx) {
-        final PrintWriter out = printCtx.output();
-
-        RNode node = (RNode) promise.getRep();
-        SourceSection ss = node.asRSyntaxNode().getSourceSection();
-        if (ss == null) {
-            out.print("<no source available>");
-        } else {
-            out.print(ss.getCode());
-        }
-    }
-
-}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RawPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RawPrinter.java
deleted file mode 100644
index cb4176a775c0c53160070d6a27a1ea82987ca6d1..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RawPrinter.java
+++ /dev/null
@@ -1,38 +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.builtin.base.printer;
-
-import java.io.IOException;
-
-import com.oracle.truffle.r.runtime.data.RRaw;
-
-public final class RawPrinter extends AbstractScalarValuePrinter<RRaw> {
-
-    public static final RawPrinter INSTANCE = new RawPrinter();
-
-    @Override
-    protected void printScalarValue(RRaw value, PrintContext printCtx) throws IOException {
-        printCtx.output().print(value.toString());
-    }
-
-}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RawVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RawVectorPrinter.java
index 3045c3b39d623a34969aab099841edb76fb363b1..1fabfe2b10b8b4e66e0dc4298996a775bb54e83d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RawVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RawVectorPrinter.java
@@ -31,14 +31,14 @@ public final class RawVectorPrinter extends VectorPrinter<RAbstractRawVector> {
     public static final RawVectorPrinter INSTANCE = new RawVectorPrinter();
 
     @Override
-    protected RawVectorPrintJob createJob(RAbstractRawVector vector, int indx, boolean quote, PrintContext printCtx) {
-        return new RawVectorPrintJob(vector, indx, quote, printCtx);
+    protected RawVectorPrintJob createJob(RAbstractRawVector vector, int indx, PrintContext printCtx) {
+        return new RawVectorPrintJob(vector, indx, printCtx);
     }
 
     private final class RawVectorPrintJob extends VectorPrintJob {
 
-        protected RawVectorPrintJob(RAbstractRawVector vector, int indx, boolean quote, PrintContext printCtx) {
-            super(vector, indx, quote, printCtx);
+        protected RawVectorPrintJob(RAbstractRawVector vector, int indx, PrintContext printCtx) {
+            super(vector, indx, printCtx);
         }
 
         @Override
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/S4ObjectPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/S4ObjectPrinter.java
new file mode 100644
index 0000000000000000000000000000000000000000..136b32333bff7ea5b54e2eb5eddfb0e8bc17ca2b
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/S4ObjectPrinter.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014, 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.builtin.base.printer;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RS4Object;
+
+public final class S4ObjectPrinter implements ValuePrinter<RS4Object> {
+
+    public static final S4ObjectPrinter INSTANCE = new S4ObjectPrinter();
+
+    @Override
+    public void print(RS4Object object, PrintContext printCtx) throws IOException {
+        final PrintWriter out = printCtx.output();
+        out.print("<S4 Type Object>");
+        for (RAttribute attr : object.getAttributes()) {
+            printAttribute(attr, printCtx);
+        }
+    }
+
+    private static void printAttribute(RAttribute attr, PrintContext printCtx) throws IOException {
+        final PrintWriter out = printCtx.output();
+        out.println();
+        out.print("attr(,\"");
+        out.print(attr.getName());
+        out.println("\")");
+        ValuePrinters.INSTANCE.print(attr.getValue(), printCtx);
+    }
+
+    public static void printS4(PrintContext printCtx, Object o) {
+        RContext.getEngine().evalFunction(createShowFunction(printCtx.frame(), createShowFind()), null, o);
+        // The show function prints an additional new line character. The following attribute
+        // instructs the ValuePrinter.println method not to print the new line since it was
+        // already printed.
+        printCtx.setAttribute(DONT_PRINT_NL_ATTR, true);
+    }
+
+    private static ReadVariableNode createShowFind() {
+        return ReadVariableNode.createFunctionLookup(RSyntaxNode.INTERNAL, "show");
+    }
+
+    private static RFunction createShowFunction(VirtualFrame frame, ReadVariableNode showFind) {
+        return (RFunction) showFind.execute(frame);
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringPrinter.java
deleted file mode 100644
index 76c89c35017e9c64b138b81cad1eca59a6298e16..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringPrinter.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (c) 1997-2013,  The R Core Team
- * Copyright (c) 2016, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.nodes.builtin.base.printer;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.Arrays;
-
-import com.oracle.truffle.r.runtime.RRuntime;
-
-//Transcribed from GnuR, src/main/printutils.c
-
-public final class StringPrinter extends AbstractScalarValuePrinter<String> {
-
-    public static final StringPrinter INSTANCE = new StringPrinter();
-
-    public static String encode(String value, int w, PrintParameters pp) {
-        final boolean quote = pp.getQuote();
-        final String s;
-        if (quote) {
-            if (RRuntime.isNA(value)) {
-                s = pp.getNaString();
-            } else {
-                s = RRuntime.quoteString(value);
-            }
-        } else {
-            if (RRuntime.isNA(value)) {
-                s = pp.getNaStringNoquote();
-            } else {
-                s = value;
-            }
-        }
-        return encode(s, w, pp.getRight() ? PrintJustification.right : PrintJustification.left);
-    }
-
-    public static String encode(String s, int w, PrintJustification justify) {
-        // justification
-        final int b = w - s.length(); // total amount of blanks
-        int bl = 0; // left blanks
-        int br = 0; // right blanks
-
-        switch (justify) {
-            case left:
-                br = b;
-                break;
-            case center:
-                bl = b / 2;
-                br = b - bl;
-                break;
-            case right:
-                bl = b;
-                break;
-            case none:
-                break;
-        }
-
-        StringBuilder sb = new StringBuilder();
-
-        if (bl > 0) {
-            char[] sp = new char[bl];
-            Arrays.fill(sp, ' ');
-            sb.append(sp);
-        }
-
-        sb.append(s);
-
-        if (br > 0) {
-            char[] sp = new char[br];
-            Arrays.fill(sp, ' ');
-            sb.append(sp);
-        }
-
-        return sb.toString();
-    }
-
-    public static void printString(String s, int w, PrintContext printCtx) {
-        String outS = encode(s, w, printCtx.parameters());
-        printCtx.output().print(outS);
-    }
-
-    @Override
-    protected void printScalarValue(String value, PrintContext printCtx) throws IOException {
-        printString(value, value.length(), printCtx);
-    }
-
-}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java
index deef8711dcbdbc1e80a460b1f082a762df8b33bd..28e400d3751044c44fa36f51fb78de77132cca7a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java
@@ -14,6 +14,7 @@ package com.oracle.truffle.r.nodes.builtin.base.printer;
 import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.asBlankArg;
 
 import java.io.IOException;
+import java.util.Arrays;
 
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
@@ -25,14 +26,14 @@ public final class StringVectorPrinter extends VectorPrinter<RAbstractStringVect
     public static final StringVectorPrinter INSTANCE = new StringVectorPrinter();
 
     @Override
-    protected VectorPrinter<RAbstractStringVector>.VectorPrintJob createJob(RAbstractStringVector vector, int indx, boolean quote, PrintContext printCtx) {
-        return new StringVectorPrintJob(vector, indx, quote, printCtx);
+    protected VectorPrinter<RAbstractStringVector>.VectorPrintJob createJob(RAbstractStringVector vector, int indx, PrintContext printCtx) {
+        return new StringVectorPrintJob(vector, indx, printCtx);
     }
 
     private final class StringVectorPrintJob extends VectorPrintJob {
 
-        protected StringVectorPrintJob(RAbstractStringVector vector, int indx, boolean quote, PrintContext printCtx) {
-            super(vector, indx, quote, printCtx);
+        protected StringVectorPrintJob(RAbstractStringVector vector, int indx, PrintContext printCtx) {
+            super(vector, indx, printCtx);
         }
 
         @Override
@@ -44,13 +45,13 @@ public final class StringVectorPrinter extends VectorPrinter<RAbstractStringVect
         @Override
         protected void printElement(int i, FormatMetrics fm) throws IOException {
             String s = vector.getDataAt(i);
-            StringPrinter.printString(s, fm.maxWidth, printCtx);
+            StringVectorPrinter.printString(s, fm.maxWidth, printCtx);
         }
 
         @Override
         protected void printCell(int i, FormatMetrics fm) throws IOException {
             String s = vector.getDataAt(i);
-            String outS = StringPrinter.encode(s, fm.maxWidth, printCtx.parameters());
+            String outS = StringVectorPrinter.encode(s, fm.maxWidth, printCtx.parameters());
             int g = printCtx.parameters().getGap();
             String fmt = "%" + asBlankArg(g) + "s%s";
             printCtx.output().printf(fmt, "", outS);
@@ -117,4 +118,68 @@ public final class StringVectorPrinter extends VectorPrinter<RAbstractStringVect
         return fieldwidth;
     }
 
+    public static void printString(String s, int w, PrintContext printCtx) {
+        String outS = encode(s, w, printCtx.parameters());
+        printCtx.output().print(outS);
+    }
+
+    public static String encode(String s, int w, PrintJustification justify) {
+        // justification
+        final int b = w - s.length(); // total amount of blanks
+        int bl = 0; // left blanks
+        int br = 0; // right blanks
+
+        switch (justify) {
+            case left:
+                br = b;
+                break;
+            case center:
+                bl = b / 2;
+                br = b - bl;
+                break;
+            case right:
+                bl = b;
+                break;
+            case none:
+                break;
+        }
+
+        StringBuilder sb = new StringBuilder();
+
+        if (bl > 0) {
+            char[] sp = new char[bl];
+            Arrays.fill(sp, ' ');
+            sb.append(sp);
+        }
+
+        sb.append(s);
+
+        if (br > 0) {
+            char[] sp = new char[br];
+            Arrays.fill(sp, ' ');
+            sb.append(sp);
+        }
+
+        return sb.toString();
+    }
+
+    public static String encode(String value, int w, PrintParameters pp) {
+        final boolean quote = pp.getQuote();
+        final String s;
+        if (quote) {
+            if (RRuntime.isNA(value)) {
+                s = pp.getNaString();
+            } else {
+                s = RRuntime.quoteString(value);
+            }
+        } else {
+            if (RRuntime.isNA(value)) {
+                s = pp.getNaStringNoquote();
+            } else {
+                s = value;
+            }
+        }
+        return StringVectorPrinter.encode(s, w, pp.getRight() ? PrintJustification.right : PrintJustification.left);
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/Utils.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/Utils.java
index ab936555cd373686b95860cb28b9427a8350fc8a..e9527a3283477b10c6deb1ada6fe21a2f97deb7d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/Utils.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/Utils.java
@@ -32,6 +32,7 @@ import com.oracle.truffle.r.runtime.data.RInteger;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RString;
+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;
@@ -114,6 +115,14 @@ public class Utils {
         return Utils.<RAbstractDoubleVector> castTo(o);
     }
 
+    public static boolean canBeComplexVector(Object o) {
+        return o instanceof RAbstractComplexVector;
+    }
+
+    public static RAbstractComplexVector toComplexVector(Object o) {
+        return Utils.<RAbstractComplexVector> castTo(o);
+    }
+
     public static <T> T getDataAt(RAbstractVector v, int index) {
         return index < v.getLength() ? Utils.<T> castTo(v.getDataAtAsObject(index)) : null;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinter.java
index 010da6f7cb8fba5a8f70320709b453e7376c1edc..d958868b01041dd7b41906a87418fa68f76e56d1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinter.java
@@ -26,10 +26,23 @@ import java.io.IOException;
 
 public interface ValuePrinter<T> {
 
+    /**
+     * This attribute instructs the <code>println</code> method not to print the new line character
+     * since it has already been printed by an external printing routine, such as the
+     * <code>show</code> R-function.
+     */
+    String DONT_PRINT_NL_ATTR = "no_nl";
+
     void print(T value, PrintContext printCtx) throws IOException;
 
     default void println(T value, PrintContext printCtx) throws IOException {
         print(value, printCtx);
-        printCtx.output().println();
+        //
+        if (!Boolean.TRUE.equals(printCtx.getAttribute(DONT_PRINT_NL_ATTR))) {
+            printCtx.output().println();
+        } else {
+            // Clear the instruction attribute
+            printCtx.setAttribute(DONT_PRINT_NL_ATTR, false);
+        }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
index 7f4b2f01dfe7b01859ca57378e3831285252d4e4..f6329781421392413a05db2cb0c638d5bd8b35ee 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
@@ -24,11 +24,15 @@ package com.oracle.truffle.r.nodes.builtin.base.printer;
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.io.Writer;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.NodeChildren;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.Node.Child;
+import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
 import com.oracle.truffle.r.nodes.builtin.base.Inherits;
 import com.oracle.truffle.r.nodes.builtin.base.InheritsNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.IsMethodsDispatchOn;
@@ -41,6 +45,8 @@ import com.oracle.truffle.r.nodes.builtin.base.IsTypeFunctions.IsObject;
 import com.oracle.truffle.r.nodes.builtin.base.IsTypeFunctionsFactory.IsArrayNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.IsTypeFunctionsFactory.IsListNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.IsTypeFunctionsFactory.IsObjectNodeGen;
+import com.oracle.truffle.r.nodes.unary.CastStringNode;
+import com.oracle.truffle.r.nodes.unary.CastStringNodeGen;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -59,6 +65,8 @@ public abstract class ValuePrinterNode extends RNode {
     @Child IsS4 isS4BuiltIn = IsS4NodeGen.create(null, null, null);
     @Child IsObject isObjectBuiltIn = IsObjectNodeGen.create(null, null, null);
     @Child IsMethodsDispatchOn isMethodDispatchOnBuiltIn = IsMethodsDispatchOnNodeGen.create(null, null, null);
+    @Child CastStringNode castStringNode = CastStringNode.createNonPreserving();
+    @Child BoxPrimitiveNode boxPrimitiveNode = BoxPrimitiveNode.create();
 
     public boolean isArray(Object o) {
         return RRuntime.fromLogical(isArrayBuiltIn.execute(o));
@@ -84,28 +92,50 @@ public abstract class ValuePrinterNode extends RNode {
         return RRuntime.fromLogical(isMethodDispatchOnBuiltIn.execute());
     }
 
-    public abstract Object executeString(Object o, Object digits, boolean quote, Object naPrint, Object printGap, boolean right, Object max, boolean useSource, boolean noOpt);
+    public String castString(Object o) {
+        return (String) castStringNode.executeString(o);
+    }
+
+    public Object boxPrimitive(Object o) {
+        return boxPrimitiveNode.execute(o);
+    }
+
+    public abstract Object executeString(VirtualFrame frame, Object o, Object digits, boolean quote, Object naPrint, Object printGap, boolean right, Object max, boolean useSource, boolean noOpt);
 
     // TODO: More specializations should be added
 
-    @TruffleBoundary
     @Specialization
-    protected String prettyPrint(Object o, Object digits, boolean quote, Object naPrint, Object printGap, boolean right, Object max, boolean useSource, boolean noOpt) {
+    protected String prettyPrint(VirtualFrame frame, Object o, Object digits, boolean quote, Object naPrint, Object printGap, boolean right, Object max, boolean useSource, boolean noOpt) {
         // Until the new code is fully functional we have to use RBufferedWriter. In case
         // an exception is thrown by the new code, the content accumulated in the
         // RBufferedWriter is not printed and the old code is invoked to print the value. When
         // the new code stabilizes the RBufferedWriter will be replaced by RWriter.
-        try (RBufferedWriter rw = new RBufferedWriter(); PrintWriter pw = new PrintWriter(rw)) {
-            // try (RWriter rw = new RWriter(); PrintWriter pw = new PrintWriter(rw)) {
-            PrintContext printCtx = new PrintContext(this, new PrintParameters(digits, quote, naPrint, printGap,
-                            right, max, useSource, noOpt), pw);
-            ValuePrinters.INSTANCE.println(o, printCtx);
-            pw.flush();
-            rw.commit();
+        try (RWriter rw = new RWriter(); PrintWriter out = new PrintWriter(rw)) {
+            prettyPrint(o, new PrintParameters(digits, quote, naPrint, printGap,
+                            right, max, useSource, noOpt), out, frame);
+            out.flush();
+            // rw.commit();
             return null;
         } catch (IOException ex) {
             throw RError.error(this, RError.Message.GENERIC, ex.getMessage());
         }
+
+    }
+
+    private String prettyPrint(Object o, PrintParameters printParams, PrintWriter out, VirtualFrame frame)
+                    throws IOException {
+        PrintContext printCtx = PrintContext.enter(this, printParams, out, frame);
+        try {
+            prettyPrint(o, printCtx);
+            return null;
+        } finally {
+            PrintContext.leave();
+        }
+    }
+
+    @TruffleBoundary
+    private static void prettyPrint(Object o, PrintContext printCtx) throws IOException {
+        ValuePrinters.INSTANCE.println(o, printCtx);
     }
 
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
index 43a1997059fa83f0447d8eee59e2e302583453fd..68147b78d70fd4d0c42fba438fc4ed7411ebeb2e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
@@ -26,13 +26,18 @@ import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 
+import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
+import com.oracle.truffle.r.runtime.data.RFactor;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
-import com.oracle.truffle.r.runtime.data.RRaw;
+import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
@@ -50,26 +55,27 @@ public final class ValuePrinters implements ValuePrinter<Object> {
     public static final ValuePrinters INSTANCE = new ValuePrinters();
 
     private ValuePrinters() {
-        printers.put(String.class, StringPrinter.INSTANCE);
-        printers.put(Double.class, DoublePrinter.INSTANCE);
-        printers.put(Integer.class, IntegerPrinter.INSTANCE);
-        printers.put(Byte.class, LogicalPrinter.INSTANCE);
+        printers.put(RNull.class, NullPrinter.INSTANCE);
         printers.put(RSymbol.class, SymbolPrinter.INSTANCE);
         printers.put(RFunction.class, FunctionPrinter.INSTANCE);
         printers.put(RExpression.class, ExpressionPrinter.INSTANCE);
         printers.put(RLanguage.class, LanguagePrinter.INSTANCE);
-        printers.put(REnvironment.class, EnvironmentPrinter.INSTANCE);
         printers.put(RExternalPtr.class, ExternalPtrPrinter.INSTANCE);
-        printers.put(RPromise.class, PromisePrinter.INSTANCE);
-        printers.put(RMissing.class, MissingPrinter.INSTANCE);
+        printers.put(RS4Object.class, S4ObjectPrinter.INSTANCE);
+        printers.put(RPairList.class, PairListPrinter.INSTANCE);
+        printers.put(RFactor.class, FactorPrinter.INSTANCE);
     }
 
     @SuppressWarnings({"rawtypes", "unchecked"})
     @Override
-    public void print(Object x, PrintContext printCtx) throws IOException {
-        if (x == null) {
+    public void print(Object v, PrintContext printCtx) throws IOException {
+        RInternalError.guarantee(v != null, "Unexpected null value");
+
+        if (v == RNull.instance) {
             NullPrinter.INSTANCE.print(null, printCtx);
         } else {
+            // Try to box a scalar primitive value to the respective vector
+            Object x = printCtx.printerNode().boxPrimitive(v);
             ValuePrinter printer = printers.get(x.getClass());
             if (printer == null) {
                 if (x instanceof RAbstractStringVector) {
@@ -86,8 +92,10 @@ public final class ValuePrinters implements ValuePrinter<Object> {
                     printer = RawVectorPrinter.INSTANCE;
                 } else if (x instanceof RAbstractListVector) {
                     printer = ListPrinter.INSTANCE;
+                } else if (x instanceof REnvironment) {
+                    printer = EnvironmentPrinter.INSTANCE;
                 } else {
-                    throw new UnsupportedOperationException("TODO");
+                    RInternalError.shouldNotReachHere();
                 }
             }
             printer.print(x, printCtx);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java
index 5c9f7113441c1220faa7f47136c4ec2828476f8d..c16fe9a382ec75eeef938586372a32776f011e1e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java
@@ -34,14 +34,14 @@ public abstract class VectorPrinter<T extends RAbstractVector> extends AbstractV
 
     @Override
     protected void printValue(T vector, PrintContext printCtx) throws IOException {
-        printVector(vector, 1, printCtx.parameters().getQuote(), printCtx);
+        printVector(vector, 1, printCtx);
     }
 
-    public void printVector(T vector, int indx, boolean quote, PrintContext printCtx) throws IOException {
-        createJob(vector, indx, quote, printCtx).print();
+    public void printVector(T vector, int indx, PrintContext printCtx) throws IOException {
+        createJob(vector, indx, printCtx).print();
     }
 
-    protected abstract VectorPrintJob createJob(T vector, int indx, boolean quote, PrintContext printCtx);
+    protected abstract VectorPrintJob createJob(T vector, int indx, PrintContext printCtx);
 
     protected enum JobMode {
         nonEmpty,
@@ -79,11 +79,12 @@ public abstract class VectorPrinter<T extends RAbstractVector> extends AbstractV
         protected final String title;
         protected final MatrixDimNames matrixDimNames;
         protected final RAbstractIntVector dims;
+        protected final boolean supressIndexLabels;
 
-        protected VectorPrintJob(T vector, int indx, boolean quote, PrintContext printCtx) {
+        protected VectorPrintJob(T vector, int indx, PrintContext printCtx) {
             this.vector = vector;
             this.indx = indx;
-            this.quote = quote;
+            this.quote = printCtx.parameters().getQuote();
 
             MatrixDimNames mdn = null;
 
@@ -141,7 +142,7 @@ public abstract class VectorPrinter<T extends RAbstractVector> extends AbstractV
             }
 
             this.printCtx = printCtx.cloneContext();
-            this.printCtx.parameters().setQuote(quote);
+            this.supressIndexLabels = printCtx.parameters().getSuppressIndexLabels();
             if (jobMode == JobMode.named) {
                 this.printCtx.parameters().setRight(true);
             }
@@ -181,7 +182,7 @@ public abstract class VectorPrinter<T extends RAbstractVector> extends AbstractV
         }
 
         private void printNonEmptyVector() throws IOException {
-            final int gap = printCtx.parameters().getGap();
+            final int gap = supressIndexLabels ? 0 : printCtx.parameters().getGap();
             final int totalWidth = printCtx.parameters().getWidth();
 
             int width = 0;
@@ -246,7 +247,7 @@ public abstract class VectorPrinter<T extends RAbstractVector> extends AbstractV
                     out.println();
                 }
                 for (j = 0; j < nperline && (k = i * nperline + j) < n; j++) {
-                    StringPrinter.printString(names.getDataAt(k), w, namesPrintCtx);
+                    StringVectorPrinter.printString(names.getDataAt(k), w, namesPrintCtx);
                     out.printf("%" + asBlankArg(gap) + "s", "");
                 }
                 out.println();
@@ -432,7 +433,7 @@ public abstract class VectorPrinter<T extends RAbstractVector> extends AbstractV
                 PrintParameters pp2 = printCtx.parameters().cloneParameters();
                 pp2.setQuote(false);
                 pp2.setRight(false);
-                out.printf(fmt, "", StringPrinter.encode(tmp, l, pp2));
+                out.printf(fmt, "", StringVectorPrinter.encode(tmp, l, pp2));
             } else {
                 int gap = w - indexWidth(j + 1) - 3;
                 String fmt = "%" + asBlankArg(gap) + "s[,%d]";
@@ -456,7 +457,7 @@ public abstract class VectorPrinter<T extends RAbstractVector> extends AbstractV
                 PrintParameters pp2 = printCtx.parameters().cloneParameters();
                 pp2.setQuote(false);
                 pp2.setRight(true);
-                out.printf(fmt, "", StringPrinter.encode(tmp, l, pp2));
+                out.printf(fmt, "", StringVectorPrinter.encode(tmp, l, pp2));
             } else {
                 String g1 = asBlankArg(pp.getGap());
                 String g2 = asBlankArg(w - indexWidth(j + 1) - 3);
@@ -478,7 +479,7 @@ public abstract class VectorPrinter<T extends RAbstractVector> extends AbstractV
                 PrintParameters pp2 = printCtx.parameters().cloneParameters();
                 pp2.setQuote(false);
                 pp2.setRight(false);
-                out.printf(fmt, "", StringPrinter.encode(tmp, l, pp2), "");
+                out.printf(fmt, "", StringVectorPrinter.encode(tmp, l, pp2), "");
             } else {
                 String g1 = asBlankArg(pp.getGap());
                 String g2 = asBlankArg(w - indexWidth(j + 1) - 3);
@@ -499,7 +500,7 @@ public abstract class VectorPrinter<T extends RAbstractVector> extends AbstractV
                 PrintParameters pp2 = printCtx.parameters().cloneParameters();
                 pp2.setQuote(false);
                 pp2.setRight(false);
-                String s = StringPrinter.encode(tmp, l, pp2);
+                String s = StringVectorPrinter.encode(tmp, l, pp2);
                 out.printf(fmt, "", s, "");
             } else {
                 String gap = asBlankArg(rlabw - 3 - indexWidth(i + 1));
@@ -644,7 +645,7 @@ public abstract class VectorPrinter<T extends RAbstractVector> extends AbstractV
         }
 
         private int doLab(int i) {
-            if (indx > 0 && !printCtx.parameters().getSuppressIndexLabels()) {
+            if (indx > 0 && !supressIndexLabels) {
                 printVectorIndex(i + 1, labwidth, out);
                 return labwidth;
             } else {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R
index 73cff8a2ce04520ad2e6dd3291c20a9a69fde1d8..ad71acfce277f2a3e3b7490c2538550c9775c389 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R
@@ -15,18 +15,33 @@
 
 ## Derived from snow and parallel packages
 
+eval(expression(
 closeNode.SHAREDnode <- function(node) {
     fastr:::fastr.channel.close(node$channel)
-}
+}), asNamespace("parallel"))
 
+eval(expression(
 sendData.SHAREDnode <- function(node, data) {
     fastr:::fastr.channel.send(node$channel, data)
-}
+}), asNamespace("parallel"))
 
+eval(expression(
 recvData.SHAREDnode <- function(node) {
     fastr:::fastr.channel.receive(node$channel)
-}
+}), asNamespace("parallel"))
+
+eval(expression(
+recvOneData.SHAREDcluster <- function(cl) {
+	channel_ids = lapply(cl, function(l) l[["channel"]])
+    res <- fastr:::fastr.channel.select(channel_ids)
+	selected_id = res[[1]]
+	# TODO: I am sure there is a better way...
+	indexes = lapply(cl, function(l, id) if (identical(l[["channel"]], id)) id else as.integer(NA), id=selected_id)
+	node_ind = which(as.double(indexes)==as.double(selected_id))
+	list(node = node_ind, value = res[[2]])
+}), asNamespace("parallel"))
 
+eval(expression(
 fastr.newSHAREDnode <- function(rank, options = defaultClusterOptions)
 {
 	# Add the "debug" option defaulted to FALSE, if the user didn't specify
@@ -53,10 +68,9 @@ fastr.newSHAREDnode <- function(rank, options = defaultClusterOptions)
     channel <- fastr:::fastr.channel.create(port)
 	if (isTRUE(debug)) cat(sprintf("Context %d started!\n", rank))
 	structure(list(channel = channel, context=cx, rank = rank), class = "SHAREDnode")
+}), asNamespace("parallel"))
 
-}
-
-eval(expression(
+makeForkClusterExpr <- expression({
 makeForkCluster <- function(nnodes = getOption("mc.cores", 2L), options = defaultClusterOptions, ...)
 {
     nnodes <- as.integer(nnodes)
@@ -67,11 +81,15 @@ makeForkCluster <- function(nnodes = getOption("mc.cores", 2L), options = defaul
     for (i in seq_along(cl)) cl[[i]] <- fastr.newSHAREDnode(rank=i, options=options)
 	class(cl) <- c("SHAREDcluster", "cluster")
 	cl	
-}), asNamespace("parallel"))
+}; environment(makeForkCluster)<-asNamespace("parallel")})
+eval(makeForkClusterExpr, asNamespace("parallel"))
+eval(makeForkClusterExpr, as.environment("package:parallel"))
+
 
+eval(expression(
 stopCluster.SHAREDcluster <- function(cl) {
     for (n in cl) {
         parallel:::postNode(n, "DONE")
         fastr:::fastr.context.join(n$context)
     }
-}
+}), asNamespace("parallel"))
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/mclapply_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/mclapply_overrides.R
new file mode 100644
index 0000000000000000000000000000000000000000..fc2862634c9d173148f52c46098e1f6cfd604010
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/mclapply_overrides.R
@@ -0,0 +1,95 @@
+#  Copyright (C) 1995-2014 The R Core Team
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  This program 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 for more details.
+#
+#  A copy of the GNU General Public License is available at
+#  http://www.r-project.org/Licenses/
+
+## Derived from snow and parallel packages
+
+eval(expression(
+mc.set.children.streams <- function(cl)
+{
+	if (RNGkind()[1L] == "L'Ecuyer-CMRG") {
+		clusterExport(cl, "LEcuyer.seed", envir = RNGenv)
+		clusterCall(cl, mc.set.stream)
+	}
+}), asNamespace("parallel"))
+
+mclapplyExpr <- expression({
+mclapply <- function(X, FUN, ..., mc.preschedule = TRUE, mc.set.seed = TRUE,
+                     mc.silent = FALSE, mc.cores = getOption("mc.cores", 2L),
+                     mc.cleanup = TRUE, mc.allow.recursive = TRUE)
+{
+    # TODO: warning messages are not quite the same as in original mclapply
+	cores <- as.integer(mc.cores)
+    if(is.na(cores) || cores < 1L) stop("'mc.cores' must be >= 1")
+    .check_ncores(cores)
+
+    if (parallel:::isChild() && !isTRUE(mc.allow.recursive))
+        return(lapply(X = X, FUN = FUN, ...))
+
+    if (mc.set.seed) mc.reset.stream()
+
+    cl <- list()
+    jobs <- list()
+    cleanup <- function() {
+		# TODO: forcefully "kill" contexts if mc.cleanup is TRUE
+		if (length(cl) > 0) {
+			# after cluster initialized
+			stopCluster(cl)
+		}
+	}
+    on.exit(cleanup())	
+	## Follow lapply
+    if(!is.vector(X) || is.object(X)) X <- as.list(X)
+
+	if (mc.set.seed) mc.advance.stream();
+		
+    if (!mc.preschedule) {              # sequential (non-scheduled)
+        FUN <- match.fun(FUN)
+        if (length(X) <= cores) { # we can use one-shot parallel
+    		cl <- makeForkCluster(length(X))
+			# there is no actual fork, so we must set seeds explicitly
+			if (mc.set.seed) mc.set.children.streams(cl)	
+			res <- tryCatch(parallel::clusterApply(cl, X, FUN, ...),
+					error=function(e) warning("function(s) calls resulted in an error"))			
+        } else { # more complicated, we have to wait for jobs selectively
+    		cl <- makeForkCluster(cores)
+			# there is no actual fork, so we must set seeds explicitly
+			if (mc.set.seed) mc.set.children.streams(cl)
+			res <- tryCatch(clusterApplyLB(cl, X, FUN, ...),
+					error=function(e) warning("function(s) calls resulted in an error"))
+        }
+        return(res)
+    }
+    ## mc.preschedule = TRUE from here on.
+    if (length(X) < cores) cores <- length(X)
+    if (cores < 2L) return(lapply(X = X, FUN = FUN, ...))
+    sindex <- lapply(seq_len(cores),
+                     function(i) seq(i, length(X), by = cores))
+    schedule <- lapply(seq_len(cores),
+                       function(i) X[seq(i, length(X), by = cores)])
+    res <- vector("list", length(X))
+    cl <- makeForkCluster(cores)
+	# there is no actual fork, so we must set seeds explicitly
+	if (mc.set.seed) mc.set.children.streams(cl)	
+
+	job.res <- tryCatch(parallel::parLapply(cl, unlist(schedule), FUN, ...), 
+			error=function(e) warning("scheduled core(s) encountered errors in user code"))			
+    for (i in seq_len(cores)) {
+		len = length(sindex[[i]])
+        res[sindex[[i]]] <- job.res[seq((i-1)*len+1, i*len)]
+    }
+	res	
+}; environment(mclapply)<-asNamespace("parallel")})
+eval(mclapplyExpr, asNamespace("parallel"))
+eval(mclapplyExpr, as.environment("package:parallel"))
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/InlineCacheNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/InlineCacheNode.java
index 988dbcd90d7977d872596f18855cf09eb4939c9e..bde97701653365a3123e6590c32555fcdd45005c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/InlineCacheNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/InlineCacheNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -27,7 +27,6 @@ import java.util.function.*;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.profiles.*;
 import com.oracle.truffle.r.nodes.function.*;
 import com.oracle.truffle.r.runtime.context.*;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java
index 674e62112192f5cfd75a4113ee6a9c9f00f4410f..00613d34dab18439618911960bca51266c952c2c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * 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
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
index effb4bf752444061e8dc968209a61a32567b50b1..926a8576c2995180a618d7067f9bed9b5a0ca028 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
@@ -41,7 +41,6 @@ import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.nodes.InvalidAssumptionException;
-import com.oracle.truffle.api.nodes.NodeUtil;
 import com.oracle.truffle.api.nodes.SlowPathException;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
@@ -686,6 +685,33 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
         return null;
     }
 
+    @TruffleBoundary
+    public static Object lookupAny(String identifier, Frame variableFrame, boolean localOnly) {
+        Frame current = variableFrame;
+        do {
+            // see if the current frame has a value of the given name
+            FrameSlot frameSlot = current.getFrameDescriptor().findFrameSlot(identifier);
+            if (frameSlot != null) {
+                Object value = current.getValue(frameSlot);
+
+                if (value != null) {
+                    if (value == RMissing.instance) {
+                        throw RError.error(RError.SHOW_CALLER, RError.Message.ARGUMENT_MISSING, identifier);
+                    }
+                    if (value instanceof RPromise) {
+                        return PromiseHelperNode.evaluateSlowPath(null, (RPromise) value);
+                    }
+                    return value;
+                }
+            }
+            if (localOnly) {
+                return null;
+            }
+            current = RArguments.getEnclosingFrame(current);
+        } while (current != null);
+        return null;
+    }
+
     @TruffleBoundary
     public static RArgsValuesAndNames lookupVarArgs(Frame variableFrame) {
         Frame current = variableFrame;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/RLengthNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/RLengthNode.java
index 717cfe89a168bec53fc8a85427e3a1d389ab28be..613afbbd46ac4889fa83716bec6d8b7c5327485e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/RLengthNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/RLengthNode.java
@@ -79,6 +79,12 @@ public abstract class RLengthNode extends RNode {
         return 1;
     }
 
+    @Specialization
+    @SuppressWarnings("unused")
+    protected int doSymbol(RSymbol operand) {
+        return 1;
+    }
+
     @Specialization(guards = {"cachedClass != null", "cachedClass == operand.getClass()"})
     protected int doCachedContainer(Object operand, //
                     @Cached("getContainerClass(operand)") Class<? extends RAbstractContainer> cachedClass, //
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
index be17840af75a9c87650a192e0328b07b8cd23550..5b8106d144444768e14cb852dbbd221c336e1333 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
@@ -32,7 +32,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
-import com.oracle.truffle.api.nodes.NodeUtil;
 import com.oracle.truffle.api.nodes.UnexpectedResultException;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index 929d5dfb98d2b01b4d9f17ce57944aa3b01188d3..302407bc04a70ef05a39b1d6b1d20f4d6fb13d9f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -286,6 +286,14 @@ public final class RCallNode extends RSourceSectionNode implements RSyntaxNode,
         arguments.v[index] = value;
     }
 
+    @Override
+    public Node deepCopy() {
+        RCallNode copy = (RCallNode) super.deepCopy();
+        // execution (frame) specific due to temp identifiers, so reset
+        copy.internalDispatchCall = null;
+        return copy;
+    }
+
     @Override
     public Object execute(VirtualFrame frame) {
         return execute(frame, executeFunctionNode(frame));
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/GetCallerFrameNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/GetCallerFrameNode.java
index 610d158a4f772b16d6f17c762544f30567832b12..c3e934461ddec3069b916a1b20f784eca32271c8 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/GetCallerFrameNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/GetCallerFrameNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -48,9 +48,11 @@ public final class GetCallerFrameNode extends RBaseNode {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 slowPathSeen = true;
             }
-            funFrame = Utils.getCallerFrame(frame, FrameAccess.MATERIALIZE).materialize();
             RError.performanceWarning("slow caller frame access in UseMethod dispatch");
-            if (funFrame == null) {
+            Frame callerFrame = Utils.getCallerFrame(frame, FrameAccess.MATERIALIZE);
+            if (callerFrame != null) {
+                return callerFrame.materialize();
+            } else {
                 topLevelProfile.enter();
                 // S3 method can be dispatched from top-level where there is no caller frame
                 return frame.materialize();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java
index 61bd5269c21680f7e9b443471542a9e736ed7f4e..2256112edf4c70a488ff04d2b60d6da7ce75d4b8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java
@@ -301,6 +301,10 @@ public class RChannel {
             msg = RSerialize.serialize(msg, false, true, RSerialize.DEFAULT_VERSION, null);
         }
         try {
+            int i = 0;
+            if (msg == null) {
+                i++;
+            }
             (id > 0 ? channel.masterToClient : channel.clientToMaster).put(msg);
         } catch (InterruptedException x) {
             throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error sending through the channel");
@@ -348,10 +352,8 @@ public class RChannel {
         }
     }
 
-    public static Object receive(int id) {
-        RChannel channel = getChannelFromId(id);
+    public static Object processedReceivedMessage(Object msg) {
         try {
-            Object msg = (id < 0 ? channel.masterToClient : channel.clientToMaster).take();
             if (msg instanceof SerializedList) {
                 RList list = ((SerializedList) msg).getList();
                 // list and attributes are already private (shallow copies - do the appropriate
@@ -369,10 +371,28 @@ public class RChannel {
                 }
                 return msg;
             }
-        } catch (InterruptedException x) {
-            throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error receiving from the channel");
         } catch (IOException x) {
             throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error unserializing msg from the channel");
         }
     }
+
+    public static Object receive(int id) {
+        RChannel channel = getChannelFromId(id);
+        try {
+            Object msg = (id < 0 ? channel.masterToClient : channel.clientToMaster).take();
+            return processedReceivedMessage(msg);
+        } catch (InterruptedException x) {
+            throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error receiving from the channel");
+        }
+    }
+
+    public static Object poll(int id) {
+        RChannel channel = getChannelFromId(id);
+        Object msg = (id < 0 ? channel.masterToClient : channel.clientToMaster).poll();
+        if (msg != null) {
+            return processedReceivedMessage(msg);
+        }
+        return null;
+    }
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
index 19c1ce78b6fc49bfb1765b656beff86e2cb7ae5f..58f4abe742a82b24182464d36ae87bc5a9de48c4 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
@@ -93,7 +93,7 @@ public class RPairList extends RAttributeStorage implements RAbstractContainer {
         boolean named = false;
         RPairList plt = this;
         while (true) {
-            named = named | !isNullTag();
+            named = named || !plt.isNullTag();
             if (isNull(plt.cdr)) {
                 break;
             }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
index a0427e9cff0b0ae8a35d3e738432c37ac1708be7..79bff3df03bd44f151837ee7ce989f4d8e44f10a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
@@ -11,33 +11,75 @@
  */
 package com.oracle.truffle.r.runtime.gnur;
 
-import java.util.*;
-
-import com.oracle.truffle.api.CompilerDirectives.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.r.runtime.*;
-import com.oracle.truffle.r.runtime.conn.*;
-import com.oracle.truffle.r.runtime.data.*;
-import com.oracle.truffle.r.runtime.env.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.conn.RConnection;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RComplexVector;
+import com.oracle.truffle.r.runtime.data.RDataFrame;
+import com.oracle.truffle.r.runtime.data.RDoubleSequence;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.REmpty;
+import com.oracle.truffle.r.runtime.data.RExpression;
+import com.oracle.truffle.r.runtime.data.RExternalPtr;
+import com.oracle.truffle.r.runtime.data.RFactor;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RIntSequence;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
+import com.oracle.truffle.r.runtime.data.RPromise;
+import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
+import com.oracle.truffle.r.runtime.data.RRaw;
+import com.oracle.truffle.r.runtime.data.RRawVector;
+import com.oracle.truffle.r.runtime.data.RS4Object;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.data.RUnboundValue;
+import com.oracle.truffle.r.runtime.env.REnvironment;
 
 // Transcribed from GnuR src/include/Rinternals.h and src/main/serialize.c
 
 public enum SEXPTYPE {
+
+    /*
+     * FastR scalar variants of GnuR vector types (other than String) These could be removed in a
+     * similar way to String, but there is no pressing need.
+     */
+    FASTR_DOUBLE(300, Double.class),
+    FASTR_INT(301, Integer.class),
+    FASTR_BYTE(302, Byte.class),
+    FASTR_COMPLEX(303, RComplex.class),
+    // FastR special "vector" types
+    FASTR_DATAFRAME(304, RDataFrame.class),
+    FASTR_FACTOR(305, RFactor.class),
+    // very special case
+    FASTR_SOURCESECTION(306, SourceSection.class),
+    FASTR_CONNECTION(307, RConnection.class),
+
     NILSXP(0, RNull.class), /* nil ()NULL */
     SYMSXP(1, RSymbol.class), /* symbols */
     LISTSXP(2, RPairList.class), /* lists of dotted pairs */
     CLOSXP(3, RPairList.class), /* closures */
     ENVSXP(4, REnvironment.class), /* environments */
-    PROMSXP(5, RPromise.class), /* promises: [un]evaluated closure arguments */
+    PROMSXP(5, RPromise.class, EagerPromise.class), /* promises: [un]evaluated closure arguments */
     LANGSXP(6, RLanguage.class), /* language constructs (special lists) */
     SPECIALSXP(7), /* special forms */
     BUILTINSXP(8), /* builtin non-special forms */
     CHARSXP(9), /* "scalar" string type (GnuR internal only) */
     LGLSXP(10, RLogicalVector.class), /* logical vectors */
-    INTSXP(13, new Class<?>[]{RIntVector.class, RIntSequence.class}), /* integer vectors */
-    REALSXP(14, new Class<?>[]{RDoubleVector.class, RDoubleSequence.class}), /* real variables */
+    INTSXP(13, RIntVector.class, RIntSequence.class), /* integer vectors */
+    REALSXP(14, RDoubleVector.class, RDoubleSequence.class), /* real variables */
     CPLXSXP(15, RComplexVector.class), /* complex variables */
-    STRSXP(16, new Class<?>[]{RStringVector.class, String.class}), /* string vectors */
+    STRSXP(16, RStringVector.class, String.class), /* string vectors */
     DOTSXP(17, RArgsValuesAndNames.class), /* dot-dot-dot object */
     ANYSXP(18), /* make "any" args work */
     VECSXP(19, RList.class), /* generic vectors */
@@ -45,7 +87,7 @@ public enum SEXPTYPE {
     BCODESXP(21), /* byte code */
     EXTPTRSXP(22, RExternalPtr.class), /* external pointer */
     WEAKREFSXP(23), /* weak reference */
-    RAWSXP(24, new Class<?>[]{RRawVector.class, RRaw.class}), /* raw bytes */
+    RAWSXP(24, RRawVector.class, RRaw.class), /* raw bytes */
     S4SXP(25, RS4Object.class), /* S4 non-vector */
 
     NEWSXP(30), /* fresh node created in new page */
@@ -70,45 +112,24 @@ public enum SEXPTYPE {
     ATTRLANGSXP(240),
     ATTRLISTSXP(239),
 
-    /*
-     * FastR scalar variants of GnuR vector types (other than String) These could be removed in a
-     * similar way to String, but there is no pressing need.
-     */
-    FASTR_DOUBLE(300, Double.class),
-    FASTR_INT(301, Integer.class),
-    FASTR_BYTE(302, Byte.class),
-    FASTR_COMPLEX(303, RComplex.class),
-    // FastR special "vector" types
-    FASTR_DATAFRAME(304, RDataFrame.class),
-    FASTR_FACTOR(305, RFactor.class),
-    // very special case
-    FASTR_SOURCESECTION(306, SourceSection.class),
-    FASTR_CONNECTION(307, RConnection.class),
-
     EMPTYARG_SXP(500, REmpty.class);
 
     public final int code;
     public final Class<?>[] fastRClasses;
 
-    @CompilationFinal private static final SEXPTYPE[] NON_NULL_VALUES;
-
-    SEXPTYPE(int code) {
-        this.code = code;
-        this.fastRClasses = null;
-    }
-
-    SEXPTYPE(int code, Class<?>[] fastRClasses) {
+    SEXPTYPE(int code, Class<?>... fastRClasses) {
         this.code = code;
         this.fastRClasses = fastRClasses;
-
-    }
-
-    SEXPTYPE(int code, Class<?> fastRClass) {
-        this(code, new Class<?>[]{fastRClass});
     }
 
     private static final Map<Integer, SEXPTYPE> codeMap = new HashMap<>();
 
+    static {
+        for (SEXPTYPE type : SEXPTYPE.values()) {
+            SEXPTYPE.codeMap.put(type.code, type);
+        }
+    }
+
     public static SEXPTYPE mapInt(int type) {
         return codeMap.get(type);
     }
@@ -119,13 +140,9 @@ public enum SEXPTYPE {
      * {@code type} field on the {@link RPairList} has to be consulted.
      */
     public static SEXPTYPE typeForClass(Class<?> fastRClass) {
-        for (SEXPTYPE type : NON_NULL_VALUES) {
-            if (type.fastRClasses.length == 1) {
-                if (fastRClass == type.fastRClasses[0]) {
-                    return type;
-                }
-            } else {
-                if (fastRClass == type.fastRClasses[0] || fastRClass == type.fastRClasses[1]) {
+        for (SEXPTYPE type : values()) {
+            for (Class<?> clazz : type.fastRClasses) {
+                if (fastRClass == clazz) {
                     return type;
                 }
             }
@@ -204,22 +221,4 @@ public enum SEXPTYPE {
                 return null;
         }
     }
-
-    static {
-        int nonNullCount = 0;
-        for (SEXPTYPE type : SEXPTYPE.values()) {
-            SEXPTYPE.codeMap.put(type.code, type);
-            if (type.fastRClasses != null) {
-                nonNullCount++;
-            }
-        }
-        NON_NULL_VALUES = new SEXPTYPE[nonNullCount];
-        nonNullCount = 0;
-        for (SEXPTYPE type : SEXPTYPE.values()) {
-            if (type.fastRClasses != null) {
-                NON_NULL_VALUES[nonNullCount++] = type;
-            }
-        }
-    }
-
 }
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 a2049e1dc9335e08c6352a9dc21d0223c2543b5c..6b5087fcb513526860b96e8f36080762c09f89f5 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
@@ -24368,6 +24368,14 @@ NULL
 [1] -0.6931472 -2.0794415 -2.7725887 -3.2425924 -3.5992673 -3.8869494 -4.1281114
 [8] -4.3357508 -4.5180723
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_length.testLength
+#length(as.symbol('x'))
+[1] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_length.testLength
+#length(quote(x))
+[1] 1
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_length.testLength
 #{ length(1) }
 [1] 1
@@ -24404,32 +24412,6 @@ NULL
 #{ length(d<-dim(1:3)) }
 [1] 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_length.testLength
-#{ x <- 1 ; f <- function() { length(x) <<- 2 } ; f() ; x }
-[1]  1 NA
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_length.testLength
-#{ x <- 1:2 ; length(x) <- 4 ; x }
-[1]  1  2 NA NA
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_length.testLength
-#{ x <- 1:2 ; z <- (length(x) <- 4) ; z }
-[1] 4
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_length.testLength
-#{ x <- 1:4 ; length(x) <- 2 ; x }
-[1] 1 2
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_length.testLength
-#{ x<-c(a=7, b=42); length(x)<-1; x }
-a
-7
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_length.testLength
-#{ x<-c(a=7, b=42); length(x)<-4; x }
- a  b
- 7 42 NA NA
-
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_length.testlength1
 #argv <- list('~ . + Soft+M.user:Temp');length(argv[[1]]);
 [1] 1
@@ -24574,6 +24556,22 @@ Error: unexpected symbol in "argv <- list(list('Residuals vs Fitted', 'Normal Q-
 #argv <- list(c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE));length(argv[[1]]);
 [1] 260
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lengthassign.testLengthUpdate
+#{ x <- 1 ; f <- function() { length(x) <<- 2 } ; f() ; x }
+[1]  1 NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lengthassign.testLengthUpdate
+#{ x <- 1:2 ; length(x) <- 4 ; x }
+[1]  1  2 NA NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lengthassign.testLengthUpdate
+#{ x <- 1:2 ; z <- (length(x) <- 4) ; z }
+[1] 4
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lengthassign.testLengthUpdate
+#{ x <- 1:4 ; length(x) <- 2 ; x }
+[1] 1 2
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_lengthassign.testLengthUpdate
 #{ x<-c(a=1, b=2); length(x)<-1; x }
 a
@@ -24584,6 +24582,16 @@ a
  a  b
  1  2 NA NA
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lengthassign.testLengthUpdate
+#{ x<-c(a=7, b=42); length(x)<-1; x }
+a
+7
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lengthassign.testLengthUpdate
+#{ x<-c(a=7, b=42); length(x)<-4; x }
+ a  b
+ 7 42 NA NA
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_lengthassign.testLengthUpdate
 #{ x<-data.frame(a=1,b=2); length(x)<-1; attributes(x) }
 $names
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_length.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_length.java
index f23608b8b830f266dc56f1477742a8f1992cea79..5c62fe700e604c1d5d29b3ecb5f2f1059c281492 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_length.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_length.java
@@ -204,10 +204,7 @@ public class TestBuiltin_length extends TestBase {
 
     @Test
     public void testLength() {
-        assertEval("{ x <- 1:4 ; length(x) <- 2 ; x }");
-        assertEval("{ x <- 1:2 ; length(x) <- 4 ; x }");
         assertEval("{ length(c(z=1:4)) }");
-        assertEval("{ x <- 1 ; f <- function() { length(x) <<- 2 } ; f() ; x }");
         assertEval("{ length(1) }");
         assertEval("{ length(NULL) }");
         assertEval("{ length(NA) }");
@@ -216,8 +213,7 @@ public class TestBuiltin_length extends TestBase {
         assertEval("{ length(1+1i) }");
         assertEval("{ length(d<-dim(1:3)) }");
         assertEval("{ length(1:3) }");
-        assertEval("{ x <- 1:2 ; z <- (length(x) <- 4) ; z }");
-        assertEval("{ x<-c(a=7, b=42); length(x)<-4; x }");
-        assertEval("{ x<-c(a=7, b=42); length(x)<-1; x }");
+        assertEval("length(quote(x))");
+        assertEval("length(as.symbol('x'))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lengthassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lengthassign.java
index 458096e7fd3c57910495f40dbb658ddebff54096..22243418d493dfa1495bbb13d790819ff85e9afd 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lengthassign.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lengthassign.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -61,5 +61,11 @@ public class TestBuiltin_lengthassign extends TestBase {
         assertEval("{ x<-data.frame(a=1,b=2); length(x)<-4; attributes(x) }");
         assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); length(x)<-1; x }");
         assertEval("{ x<-factor(c(\"a\", \"b\", \"a\")); length(x)<-4; x }");
+        assertEval("{ x <- 1:4 ; length(x) <- 2 ; x }");
+        assertEval("{ x <- 1:2 ; length(x) <- 4 ; x }");
+        assertEval("{ x <- 1 ; f <- function() { length(x) <<- 2 } ; f() ; x }");
+        assertEval("{ x <- 1:2 ; z <- (length(x) <- 4) ; z }");
+        assertEval("{ x<-c(a=7, b=42); length(x)<-4; x }");
+        assertEval("{ x<-c(a=7, b=42); length(x)<-1; x }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rank.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rank.java
index 77078e786d9503be6585968fbf44572f15ffc4af..37808f9d0cb22935abfaaedcc61b6feaa93d9323 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rank.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rank.java
@@ -19,76 +19,70 @@ public class TestBuiltin_rank extends TestBase {
 
     @Test
     public void testrank1() {
-        assertEval(Ignored.Unknown, "argv <- list(c(1, 2, 3), 3L, 'average'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(c(1, 2, 3), 3L, 'average'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testrank2() {
-        assertEval(Ignored.Unknown, "argv <- list(list(), 0L, 'average'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(list(), 0L, 'average'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testrank3() {
-        assertEval(Ignored.Unknown, "argv <- list(c(FALSE, FALSE), 2L, 'average'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(c(FALSE, FALSE), 2L, 'average'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testrank4() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c(2, 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, 60), 60L, 'average'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(c(2, 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, 60), 60L, 'average'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testrank5() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(9.96, 84.84, 93.4, 33.77, 5.16, 90.57, 92.85, 97.16, 97.67, 91.38, 98.61, 8.52, 2.27, 4.43, 2.82, 24.2, 3.3, 12.11, 2.15, 2.84, 5.23, 4.52, 15.14, 4.2, 5.23, 2.56, 7.72, 18.46, 6.1, 99.71, 99.68, 100, 98.96, 98.22, 99.06, 99.46, 96.83, 5.62, 13.79, 11.22, 16.92, 4.97, 8.65, 42.34, 50.43, 58.33), .Names = c('Courtelary', 'Delemont', 'Franches-Mnt', 'Moutier', 'Neuveville', 'Porrentruy', 'Broye', 'Glane', 'Gruyere', 'Sarine', 'Veveyse', 'Aigle', 'Aubonne', 'Avenches', 'Cossonay', 'Echallens', 'Grandson', 'Lausanne', 'La Vallee', 'Lavaux', 'Morges', 'Moudon', 'Nyone', 'Orbe', 'Payerne', 'Paysd'enhaut', 'Rolle', 'Vevey', 'Yverdon', 'Conthey', 'Entremont', 'Herens', 'Martigwy', 'Monthey', 'St Maurice', 'Sierre', 'Sion', 'Boudry', 'La Chauxdfnd', 'Le Locle', 'Neuchatel', 'Val de Ruz', 'ValdeTravers', 'V. De Geneve', 'Rive Droite', 'Rive Gauche')), 46L, 'average'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(c(9.96, 84.84, 93.4, 33.77, 5.16, 90.57, 92.85, 97.16, 97.67, 91.38, 98.61, 8.52, 2.27, 4.43, 2.82, 24.2, 3.3, 12.11, 2.15, 2.84, 5.23, 4.52, 15.14, 4.2, 5.23, 2.56, 7.72, 18.46, 6.1, 99.71, 99.68, 100, 98.96, 98.22, 99.06, 99.46, 96.83, 5.62, 13.79, 11.22, 16.92, 4.97, 8.65, 42.34, 50.43, 58.33), .Names = c('Courtelary', 'Delemont', 'Franches-Mnt', 'Moutier', 'Neuveville', 'Porrentruy', 'Broye', 'Glane', 'Gruyere', 'Sarine', 'Veveyse', 'Aigle', 'Aubonne', 'Avenches', 'Cossonay', 'Echallens', 'Grandson', 'Lausanne', 'La Vallee', 'Lavaux', 'Morges', 'Moudon', 'Nyone', 'Orbe', 'Payerne', 'Paysd'enhaut', 'Rolle', 'Vevey', 'Yverdon', 'Conthey', 'Entremont', 'Herens', 'Martigwy', 'Monthey', 'St Maurice', 'Sierre', 'Sion', 'Boudry', 'La Chauxdfnd', 'Le Locle', 'Neuchatel', 'Val de Ruz', 'ValdeTravers', 'V. De Geneve', 'Rive Droite', 'Rive Gauche')), 46L, 'average'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testrank6() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5), .Names = c('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k')), 11L, 'max'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(c(3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5), .Names = c('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k')), 11L, 'max'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testrank7() {
-        assertEval(Ignored.Unknown, "argv <- list(c('9', '9', '8', '7', '6', '5', '4', '3', '2', '1'), 10L, 'min'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(c('9', '9', '8', '7', '6', '5', '4', '3', '2', '1'), 10L, 'min'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testrank8() {
-        assertEval(Ignored.Unknown, "argv <- list(c(2, 1, 3, 4, 5), 5L, 'average'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(c(2, 1, 3, 4, 5), 5L, 'average'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testrank9() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c('Tukey', 'Venables', 'Tierney', 'Ripley', 'Ripley', 'McNeil', 'R Core'), class = 'AsIs'), 7L, 'min'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(c('Tukey', 'Venables', 'Tierney', 'Ripley', 'Ripley', 'McNeil', 'R Core'), class = 'AsIs'), 7L, 'min'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testrank10() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c(0.0244473121385049, 0.0208069652959635, 0.00198363254553387, -0.0529221973952693, 0.0164890605562422, -0.00149317802331189, -0.00414458668937225, -0.0391260369607497, -0.0127200995448093, 0.0111183888673723, 0.03614459302116, -0.00273443474452932, 0.0103131254237995, -0.00143136127438401, -0.0366335514444555, -0.0110399906877088, -0.0104891914308669, -0.00157789861665007, 0.0292636842429564, 0.0203025627349537, -0.0043767777488601, -0.00674011381520054, 0.0185411324740319, 0.0148087639526725, -0.0183227857094651, -0.018821306675337, 0.00969887758262181, 0.0204450782737623, -0.00298871658962484, 0.0234398759771181, 0.0105907055191967, -0.0162815763859567, 0.00907471699575067, -0.0300441479633801, 0.0381223507996197, 0.0526840550960561, -0.00976909588473167, -0.0277768375074461, 0.0151561006764977, -0.00359282193318711, 0.0638896025542924, -0.0010438914218908, 0.0183489539666666, 0.00074493402929487, -0.0197731007347187, 0.00502239164768132, -0.048016837368221, 0.0389877686476984, 0.00407695805281634, 0.057797414062711, 0.0126498543239424, -0.0188865172686347, 0.0162469917717659, -0.0248495524200794, -0.0333500780212535, 0.00775326717655591, -0.0117927765447241, 2.9405377320478e-05, 0.00197768259858777, -0.0156828699257579, -0.0151281440045609, -0.00359612097150966, 0.0313403370108415, -0.0405310449252812, 0.0158005934542395, 0.00885739072926609, 0.0282813640022565, -0.00809212452705879, 0.00984351260718323, 0.00710555853883393, -0.0144325170007544, 0.0321325880127445, 0.0308698841001781, 0.0186275986571656, 0.0422141110037264, 0.0148572667758066, -0.033960845128472, -0.0152504283054679, -0.0325780457387957, -0.0125937520151832, -0.0165034507562293, 0.00112039744236678, -0.0242330078671155, 0.00420399766652167, -0.0174137422806726, 0.047014676147193, 0.0190663795644171, 0.0242131244754732, 0.0102203815371289, 0.0447504856843389, -0.0169123288643312, -0.0122810127527625, 0.0381026258511537, -0.0173103031132602, -0.00551689511296685, -0.0104497655309428, -0.00851268571043338, -0.00742517743166594, 0.0131467615666842, -0.00471747595278646, -1.01191492422851, 2.68607765034082, -0.429158817093737, -0.359113060086774, -0.200381482427124, 1.42533261410281, -0.147128808252653, -0.0752683429340958, -1.36332095751131, -0.648540544492638, 0.12032088086903, -1.17778897251933, 1.06299238526514, -3.03678816357357, 0.613115721579531, -3.07289964707517, -0.601952253673221, -1.05655980889001, -1.304189561362, -0.113793555694785, -3.82871885136002, 2.35316662403712, -3.32994487242401, -0.927060802944771, -2.23184021008569, -1.5016380023869, 4.17433309125669, 0.0347912393865033, -2.57260106086865, -3.28121106883716, 0.900374202545311, -0.037119665429276, -0.636136749087689, -1.8587242949074, -2.97492062028297, -2.15038459323136, 2.00005760742783, -1.24253338959365, -2.76885369476898, 3.73858124484716, 0.850200754744896, -0.477294201826066, 2.11696609741804, 1.77284530274987, -1.23848609646229, 4.41220492908093, -0.51005406028203, -2.84898930042562, -0.288799203908439, 0.41507667846469, 4.61595679811872, 0.211604735787423, 0.913997610846827, -0.154305870713062, -0.668001684733089, -0.0694520566225524, 1.57527921126032, 4.15049001730457, 2.05478487752754, 2.41581679677341, -2.46264684311609, 1.96779114010676, 0.439849607321303, -2.93450005818449, 1.04204548529628, -0.317509209432032, 2.92917462393959, -1.53216399920933, -0.860423507857093, -1.85221899475487, -0.354207922873081, 0.804023558972676, -1.46349634623921, 1.66074633596335, -2.41616557260893, -2.09596882561548, 2.88231541368856, -2.0316949306093, 0.82394942463503, -0.762152102217839, 0.818803679301868, 3.37774657240809, 3.17317686688394, -0.661815601365533, -4.57047107058493, 4.99532317966833, 1.33413233353099, 1.0826546719274, -0.0267990462918174, 1.02021684590585, -0.328751663539334, 0.841389286509026, -0.800493487955288, -2.74041575509492, 1.97567653490976, 3.03949005099909, -0.617481138451227, -2.50657951121538, 1.28448261135565, -0.0894182737879582), 200L, 'average'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(c(0.0244473121385049, 0.0208069652959635, 0.00198363254553387, -0.0529221973952693, 0.0164890605562422, -0.00149317802331189, -0.00414458668937225, -0.0391260369607497, -0.0127200995448093, 0.0111183888673723, 0.03614459302116, -0.00273443474452932, 0.0103131254237995, -0.00143136127438401, -0.0366335514444555, -0.0110399906877088, -0.0104891914308669, -0.00157789861665007, 0.0292636842429564, 0.0203025627349537, -0.0043767777488601, -0.00674011381520054, 0.0185411324740319, 0.0148087639526725, -0.0183227857094651, -0.018821306675337, 0.00969887758262181, 0.0204450782737623, -0.00298871658962484, 0.0234398759771181, 0.0105907055191967, -0.0162815763859567, 0.00907471699575067, -0.0300441479633801, 0.0381223507996197, 0.0526840550960561, -0.00976909588473167, -0.0277768375074461, 0.0151561006764977, -0.00359282193318711, 0.0638896025542924, -0.0010438914218908, 0.0183489539666666, 0.00074493402929487, -0.0197731007347187, 0.00502239164768132, -0.048016837368221, 0.0389877686476984, 0.00407695805281634, 0.057797414062711, 0.0126498543239424, -0.0188865172686347, 0.0162469917717659, -0.0248495524200794, -0.0333500780212535, 0.00775326717655591, -0.0117927765447241, 2.9405377320478e-05, 0.00197768259858777, -0.0156828699257579, -0.0151281440045609, -0.00359612097150966, 0.0313403370108415, -0.0405310449252812, 0.0158005934542395, 0.00885739072926609, 0.0282813640022565, -0.00809212452705879, 0.00984351260718323, 0.00710555853883393, -0.0144325170007544, 0.0321325880127445, 0.0308698841001781, 0.0186275986571656, 0.0422141110037264, 0.0148572667758066, -0.033960845128472, -0.0152504283054679, -0.0325780457387957, -0.0125937520151832, -0.0165034507562293, 0.00112039744236678, -0.0242330078671155, 0.00420399766652167, -0.0174137422806726, 0.047014676147193, 0.0190663795644171, 0.0242131244754732, 0.0102203815371289, 0.0447504856843389, -0.0169123288643312, -0.0122810127527625, 0.0381026258511537, -0.0173103031132602, -0.00551689511296685, -0.0104497655309428, -0.00851268571043338, -0.00742517743166594, 0.0131467615666842, -0.00471747595278646, -1.01191492422851, 2.68607765034082, -0.429158817093737, -0.359113060086774, -0.200381482427124, 1.42533261410281, -0.147128808252653, -0.0752683429340958, -1.36332095751131, -0.648540544492638, 0.12032088086903, -1.17778897251933, 1.06299238526514, -3.03678816357357, 0.613115721579531, -3.07289964707517, -0.601952253673221, -1.05655980889001, -1.304189561362, -0.113793555694785, -3.82871885136002, 2.35316662403712, -3.32994487242401, -0.927060802944771, -2.23184021008569, -1.5016380023869, 4.17433309125669, 0.0347912393865033, -2.57260106086865, -3.28121106883716, 0.900374202545311, -0.037119665429276, -0.636136749087689, -1.8587242949074, -2.97492062028297, -2.15038459323136, 2.00005760742783, -1.24253338959365, -2.76885369476898, 3.73858124484716, 0.850200754744896, -0.477294201826066, 2.11696609741804, 1.77284530274987, -1.23848609646229, 4.41220492908093, -0.51005406028203, -2.84898930042562, -0.288799203908439, 0.41507667846469, 4.61595679811872, 0.211604735787423, 0.913997610846827, -0.154305870713062, -0.668001684733089, -0.0694520566225524, 1.57527921126032, 4.15049001730457, 2.05478487752754, 2.41581679677341, -2.46264684311609, 1.96779114010676, 0.439849607321303, -2.93450005818449, 1.04204548529628, -0.317509209432032, 2.92917462393959, -1.53216399920933, -0.860423507857093, -1.85221899475487, -0.354207922873081, 0.804023558972676, -1.46349634623921, 1.66074633596335, -2.41616557260893, -2.09596882561548, 2.88231541368856, -2.0316949306093, 0.82394942463503, -0.762152102217839, 0.818803679301868, 3.37774657240809, 3.17317686688394, -0.661815601365533, -4.57047107058493, 4.99532317966833, 1.33413233353099, 1.0826546719274, -0.0267990462918174, 1.02021684590585, -0.328751663539334, 0.841389286509026, -0.800493487955288, -2.74041575509492, 1.97567653490976, 3.03949005099909, -0.617481138451227, -2.50657951121538, 1.28448261135565, -0.0894182737879582), 200L, 'average'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testrank11() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(4, 7, 6, 0, 0, 2, 4, 9, 3, 6, 0, 1, 5.5, 0.5, 4.5, 5.5, 0.5, 2.5, 0.5, 0.5, 2.5, 4.5, 9.5, 3.5, 1.5, 0.5, 5.5, 0.5, 1.5, 0.5, 0.5, 0.5, 1.5, 1.5, 0.5, 2.5, 2, 0, 7, 1, 1, 2, 0, 0, 0, 0, 3, 1, 0, 2, 0, 2, 0, 3, 2, 2, 0, 1, 3, 1, 4, 6, 0, 7, 0, 1, 2, 5, 11, 11, 9, 2), .Dim = 72L, .Dimnames = list(c('A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F'))), 72L, 'average'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(c(4, 7, 6, 0, 0, 2, 4, 9, 3, 6, 0, 1, 5.5, 0.5, 4.5, 5.5, 0.5, 2.5, 0.5, 0.5, 2.5, 4.5, 9.5, 3.5, 1.5, 0.5, 5.5, 0.5, 1.5, 0.5, 0.5, 0.5, 1.5, 1.5, 0.5, 2.5, 2, 0, 7, 1, 1, 2, 0, 0, 0, 0, 3, 1, 0, 2, 0, 2, 0, 3, 2, 2, 0, 1, 3, 1, 4, 6, 0, 7, 0, 1, 2, 5, 11, 11, 9, 2), .Dim = 72L, .Dimnames = list(c('A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F'))), 72L, 'average'); .Internal(rank(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testRank() {
-        assertEval(Ignored.Unknown, "{ rank(c(10,100,100,1000)) }");
-        assertEval(Ignored.Unknown, "{ rank(c(1000,100,100,100, 10)) }");
-        assertEval(Ignored.Unknown, "{ rank(c(a=2,b=1,c=3,40)) }");
-        assertEval(Ignored.Unknown, "{ rank(c(a=2,b=1,c=3,d=NA,e=40), na.last=NA) }");
-        assertEval(Ignored.Unknown, "{ rank(c(a=2,b=1,c=3,d=NA,e=40), na.last=\"keep\") }");
-        assertEval(Ignored.Unknown, "{ rank(c(a=2,b=1,c=3,d=NA,e=40), na.last=TRUE) }");
-        assertEval(Ignored.Unknown, "{ rank(c(a=2,b=1,c=3,d=NA,e=40), na.last=FALSE) }");
-        assertEval(Ignored.Unknown, "{ rank(c(a=1,b=1,c=3,d=NA,e=3), na.last=FALSE, ties.method=\"max\") }");
-        assertEval(Ignored.Unknown, "{ rank(c(a=1,b=1,c=3,d=NA,e=3), na.last=NA, ties.method=\"min\") }");
+        assertEval("{ rank(c(10,100,100,1000)) }");
+        assertEval("{ rank(c(1000,100,100,100, 10)) }");
+        assertEval("{ rank(c(a=2,b=1,c=3,40)) }");
+        assertEval("{ rank(c(a=2,b=1,c=3,d=NA,e=40), na.last=NA) }");
+        assertEval("{ rank(c(a=2,b=1,c=3,d=NA,e=40), na.last=\"keep\") }");
+        assertEval("{ rank(c(a=2,b=1,c=3,d=NA,e=40), na.last=TRUE) }");
+        assertEval("{ rank(c(a=2,b=1,c=3,d=NA,e=40), na.last=FALSE) }");
+        assertEval("{ rank(c(a=1,b=1,c=3,d=NA,e=3), na.last=FALSE, ties.method=\"max\") }");
+        assertEval("{ rank(c(a=1,b=1,c=3,d=NA,e=3), na.last=NA, ties.method=\"min\") }");
         assertEval("{ rank(c(1000, 100, 100, NA, 1, 20), ties.method=\"first\") }");
     }
 }
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 348ccd1bd0297474786cfa4c5147a2699a901b9a..6ae4b8c513320982e323112f4f6f399c82a13436 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -88,18 +88,16 @@ com.oracle.truffle.r.native/library/grid/src/unit.c,no.copyright
 com.oracle.truffle.r.native/library/grid/src/util.c,no.copyright
 com.oracle.truffle.r.native/library/grid/src/viewport.c,no.copyright
 com.oracle.truffle.r.native/library/methods/src/methods_dummy.c,no.copyright
-com.oracle.truffle.r.native/library/methods/src/methods_dummy.c,no.copyright
 com.oracle.truffle.r.native/library/parallel/src/glpi.h,no.copyright
-com.oracle.truffle.r.native/library/parallel/src/init.c,no.copyright
-com.oracle.truffle.r.native/library/parallel/src/parallel.h,no.copyright
 com.oracle.truffle.r.native/library/parallel/src/rngstream.c,no.copyright
+com.oracle.truffle.r.native/library/parallel/src/parallel_dummy.c,no.copyright
 com.oracle.truffle.r.native/library/splines/src/splines.c,no.copyright
 com.oracle.truffle.r.native/library/stats/src/gnur_extracts.c,no.copyright
 com.oracle.truffle.r.native/library/stats/src/modreg.h,no.copyright
 com.oracle.truffle.r.native/library/stats/src/nls.h,no.copyright
 com.oracle.truffle.r.native/library/stats/src/port.h,no.copyright
 com.oracle.truffle.r.native/library/stats/src/stats.h,no.copyright
-com.oracle.truffle.r.native/library/stats/src/statsR.h,no.copyright
+com.oracle.truffle.r.native/library/stats/src/statsR_dummy.c,no.copyright
 com.oracle.truffle.r.native/library/stats/src/ts.h,no.copyright
 com.oracle.truffle.r.native/library/tools/src/gramRd.c,no.copyright
 com.oracle.truffle.r.native/library/tools/src/tools_dummy.c,no.copyright
@@ -145,6 +143,7 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/L
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowMeans.java,purdue.copyright
@@ -678,15 +677,12 @@ com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/data/tree2/incx.r
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/data/tree2/setx.r,no.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AttributesPrinter.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoublePrinter.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringPrinter.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerPrinter.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalPrinter.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java,gnu_r_gentleman_ihaka2.copyright
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index 888cce434136f2dd61c6892258e1feae4938272a..10e6195f4105a90a7f7ece4c3af579e241220b5f 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -437,13 +437,13 @@ def testgen(args):
     if os.getcwd() != _fastr_suite.dir:
         mx.abort('must run rtestgen from FastR home directory')
     # check the version of GnuR against FastR
-#    try:
-#        fastr_version = subprocess.check_output([mx.get_jdk().java, '-cp', mx.classpath('com.oracle.truffle.r.runtime'), 'com.oracle.truffle.r.runtime.RVersionNumber'])
-#        gnur_version = subprocess.check_output(['R', '--version'])
-#        if not gnur_version.startswith(fastr_version):
-#            mx.abort('R version is incompatible with FastR, please update to ' + fastr_version)
-#    except subprocess.CalledProcessError:
-#        mx.abort('RVersionNumber.main failed')
+    try:
+        fastr_version = subprocess.check_output([mx.get_jdk().java, '-cp', mx.classpath('com.oracle.truffle.r.runtime'), 'com.oracle.truffle.r.runtime.RVersionNumber'])
+        gnur_version = subprocess.check_output(['R', '--version'])
+        if not gnur_version.startswith(fastr_version):
+            mx.abort('R version is incompatible with FastR, please update to ' + fastr_version)
+    except subprocess.CalledProcessError:
+        mx.abort('RVersionNumber.main failed')
     # clean the test project to invoke the test analyzer AP
     testOnly = ['--projects', 'com.oracle.truffle.r.test']
     mx.clean(['--no-dist', ] + testOnly)