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 ca2133ea918c645f2efcfcac3ae892d6972d27eb..3df94adeb5f6b2628e155046868fa10f6280a2c3 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
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.engine;
 
-import java.io.File;
 import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -48,6 +47,7 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.launcher.StartupTiming;
 import com.oracle.truffle.r.library.graphics.RGraphics;
 import com.oracle.truffle.r.nodes.RASTBuilder;
 import com.oracle.truffle.r.nodes.RASTUtils;
@@ -76,10 +76,8 @@ import com.oracle.truffle.r.runtime.RParserFactory;
 import com.oracle.truffle.r.runtime.RProfile;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RSource;
-import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE;
 import com.oracle.truffle.r.runtime.ReturnException;
 import com.oracle.truffle.r.runtime.RootWithBody;
-import com.oracle.truffle.r.runtime.StartupTiming;
 import com.oracle.truffle.r.runtime.SubstituteVirtualFrame;
 import com.oracle.truffle.r.runtime.ThreadTimings;
 import com.oracle.truffle.r.runtime.Utils;
@@ -192,10 +190,9 @@ final class REngine implements Engine, Engine.Timings {
                     throw new RInternalError(e, "error while parsing user profile from %s", userProfile.getName());
                 }
             }
-            if (!(context.getStartParams().getRestoreAction() == SA_TYPE.NORESTORE)) {
+            if (context.getStartParams().restore()) {
                 // call sys.load.image(".RData", RCmdOption.QUIET
-                checkAndRunStartupShutdownFunction("sys.load.image", new String[]{"\".RData\"", context.getStartParams().getQuiet() ? "TRUE" : "FALSE"});
-                context.getConsoleHandler().setHistoryFrom(new File("./.Rhistory"));
+                checkAndRunStartupShutdownFunction("sys.load.image", new String[]{"\".RData\"", context.getStartParams().isQuiet() ? "TRUE" : "FALSE"});
             }
             checkAndRunStartupShutdownFunction(".First");
             checkAndRunStartupShutdownFunction(".First.sys");
@@ -273,11 +270,11 @@ final class REngine implements Engine, Engine.Timings {
         } catch (UnsupportedSpecializationException use) {
             String message = "FastR internal error: Unsupported specialization in node " + use.getNode().getClass().getSimpleName() + " - supplied values: " +
                             Arrays.asList(use.getSuppliedValues()).stream().map(v -> v == null ? "null" : v.getClass().getSimpleName()).collect(Collectors.toList());
-            context.getConsoleHandler().printErrorln(message);
+            context.getConsole().printErrorln(message);
             RInternalError.reportError(use);
             return null;
         } catch (Throwable t) {
-            context.getConsoleHandler().printErrorln("FastR internal error: " + t.getMessage());
+            context.getConsole().printErrorln("FastR internal error: " + t.getMessage());
             RInternalError.reportError(t);
             return null;
         }
@@ -668,7 +665,7 @@ final class REngine implements Engine, Engine.Timings {
             } else {
                 str = String.valueOf(result);
             }
-            RContext.getInstance().getConsoleHandler().println(str);
+            RContext.getInstance().getConsole().println(str);
         }
     }
 
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 6739d88e52246eb0acbdf078d66be58c09b8689a..d22caa9aaf12ba0b5d9bc0d0d5a6ac1ffc5d165a 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
@@ -38,8 +38,8 @@ import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.object.DynamicObject;
-import com.oracle.truffle.r.engine.shell.RCommand;
-import com.oracle.truffle.r.engine.shell.RscriptCommand;
+import com.oracle.truffle.r.launcher.RCommand;
+import com.oracle.truffle.r.launcher.RscriptCommand;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
@@ -584,7 +584,7 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
     @Override
     public Object rcommandMain(String[] args, String[] env, boolean intern) {
         IORedirect redirect = handleIORedirect(args, intern);
-        Object result = RCommand.doMain(redirect.args, env, false, redirect.in, redirect.out);
+        Object result = RCommand.doMain(redirect.args, env, redirect.in, redirect.out, redirect.err);
         return redirect.getInternResult(result);
     }
 
@@ -593,19 +593,21 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
         IORedirect redirect = handleIORedirect(args, intern);
         // TODO argument parsing can fail with ExitException, which needs to be handled correctly in
         // nested context
-        Object result = RscriptCommand.doMain(redirect.args, env, false, redirect.in, redirect.out);
+        Object result = RscriptCommand.doMain(redirect.args, env, redirect.in, redirect.out, redirect.err);
         return redirect.getInternResult(result);
     }
 
     private static final class IORedirect {
         private final InputStream in;
+        private final OutputStream err;
         private final OutputStream out;
         private final String[] args;
         private final boolean intern;
 
-        private IORedirect(InputStream in, OutputStream out, String[] args, boolean intern) {
+        private IORedirect(InputStream in, OutputStream out, OutputStream err, String[] args, boolean intern) {
             this.in = in;
             this.out = out;
+            this.err = err;
             this.args = args;
             this.intern = intern;
         }
@@ -645,6 +647,7 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
          */
         InputStream in = System.in;
         OutputStream out = System.out;
+        OutputStream err = System.err;
         ArrayList<String> newArgsList = new ArrayList<>();
         int i = 0;
         while (i < args.length) {
@@ -692,7 +695,7 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
         if (intern) {
             out = new ByteArrayOutputStream();
         }
-        return new IORedirect(in, out, newArgs, intern);
+        return new IORedirect(in, out, err, newArgs, intern);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguageImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguageImpl.java
index 028b9d3795c792ccd513639b3d2174ed98e01957..f5e88edb17a05abf107da58aeada56d121db5845 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguageImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguageImpl.java
@@ -204,7 +204,7 @@ public final class TruffleRLanguageImpl extends TruffleRLanguage implements Scop
             try {
                 return RContext.getEngine().parseToCallTarget(request.getSource(), request.getFrame());
             } catch (IncompleteSourceException e) {
-                throw new com.oracle.truffle.api.vm.IncompleteSourceException(e);
+                throw e;
             } catch (ParseException e) {
                 return Truffle.getRuntime().createCallTarget(new RootNode(this, new FrameDescriptor()) {
                     @Override
@@ -214,11 +214,7 @@ public final class TruffleRLanguageImpl extends TruffleRLanguage implements Scop
 
                     @Override
                     public Object execute(VirtualFrame frame) {
-                        try {
-                            throw e.throwAsRError();
-                        } catch (RError e2) {
-                            return null;
-                        }
+                        throw e.throwAsRError();
                     }
                 });
             } catch (RError e) {
@@ -230,7 +226,7 @@ public final class TruffleRLanguageImpl extends TruffleRLanguage implements Scop
 
                     @Override
                     public Object execute(VirtualFrame frame) {
-                        return null;
+                        throw e;
                     }
                 });
             }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java
index e8104c310ff3334ca899365ce8fd1c27a0a2b6a8..15c38d4b1af3c79cb3e101a46cbb75d6efe584d1 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java
@@ -108,6 +108,7 @@ public class REnvironmentMR {
     @Resolve(message = "KEY_INFO")
     public abstract static class REnvironmentKeyInfoNode extends Node {
 
+        private static final int EXISTS = 1 << 0;
         private static final int READABLE = 1 << 1;
         private static final int WRITABLE = 1 << 2;
 
@@ -117,7 +118,7 @@ public class REnvironmentMR {
                 return 0;
             }
 
-            int info = READABLE;
+            int info = READABLE | EXISTS;
             if (!receiver.isLocked() && !receiver.bindingIsLocked(identifier)) {
                 info += WRITABLE;
             }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
index 0f1c2234efc78592c291c850fbe63bb4355884ea..afe4aa3f7e822ac7f7089dd8521cb300cbbdbcab 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
@@ -114,6 +114,7 @@ public class RListMR {
 
         private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
 
+        private static final int EXISTS = 1 << 0;
         private static final int READABLE = 1 << 1;
         private static final int WRITABLE = 1 << 2;
         private static final int INVOCABLE = 1 << 3;
@@ -126,7 +127,7 @@ public class RListMR {
                 RStringVector names = getNamesNode.getNames(receiver);
                 for (int i = 0; i < names.getLength(); i++) {
                     if (identifier.equals(names.getDataAt(i))) {
-                        info = 1;
+                        info = EXISTS;
                         break;
                     }
                 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java
index 589fd7f8c78e1c4c3c5fbb4cb5bf2721d8832ea0..27ee846c57d1021dde21cbf2b4085c588fd1fcbe 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java
@@ -121,17 +121,18 @@ public class RPromiseMR {
     @Resolve(message = "KEY_INFO")
     public abstract static class RPromiseKeyInfoNode extends Node {
 
+        private static final int EXISTS = 1 << 0;
         private static final int READABLE = 1 << 1;
         private static final int WRITABLE = 1 << 2;
 
         @SuppressWarnings("try")
         protected Object access(@SuppressWarnings("unused") VirtualFrame frame, @SuppressWarnings("unused") RPromise receiver, String identifier) {
             if (PROP_IS_EAGER.equals(identifier) || PROP_VALUE.equals(identifier)) {
-                return READABLE;
+                return EXISTS + READABLE;
             }
 
             if (PROP_IS_EVALUATED.equals(identifier)) {
-                return READABLE + WRITABLE;
+                return EXISTS + READABLE + WRITABLE;
             }
             return 0;
         }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java
index c47155062d8634fd1b9d7b965304af8a6ccc7779..4e503874cb4b2f595b4428fb278c22c747e4131e 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java
@@ -22,11 +22,14 @@
  */
 package com.oracle.truffle.r.engine.shell;
 
+import org.graalvm.polyglot.Engine;
+
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.launcher.ConsoleHandler;
+import com.oracle.truffle.r.launcher.DefaultConsoleHandler;
+import com.oracle.truffle.r.launcher.JLineConsoleHandler;
+import com.oracle.truffle.r.launcher.RStartParams;
 import com.oracle.truffle.r.runtime.RInterfaceCallbacks;
-import com.oracle.truffle.r.runtime.RStartParams;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
-import com.oracle.truffle.r.runtime.context.DefaultConsoleHandler;
 import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 
@@ -57,61 +60,61 @@ public class EmbeddedConsoleHandler extends ConsoleHandler {
         if (rEmbedRFFI == null) {
             rEmbedRFFI = RFFIFactory.getRFFI().getREmbedRFFI();
             if (!(RInterfaceCallbacks.R_WriteConsole.isOverridden() || RInterfaceCallbacks.R_ReadConsole.isOverridden())) {
-                if (startParams.getNoReadline()) {
+                if (startParams.noReadline()) {
                     delegate = new DefaultConsoleHandler(System.in, System.out);
                 } else {
-                    delegate = new JLineConsoleHandler(startParams, System.in, System.out);
+                    delegate = new JLineConsoleHandler(System.in, System.out, startParams.isSlave());
                 }
             }
         }
         return rEmbedRFFI;
     }
 
-    @Override
-    @TruffleBoundary
-    public void println(String s) {
-        getREmbedRFFI();
-        if (delegate == null) {
-            getREmbedRFFI().writeConsole(s);
-            getREmbedRFFI().writeConsole("\n");
-        } else {
-            delegate.println(s);
-        }
-    }
-
-    @Override
-    @TruffleBoundary
-    public void print(String s) {
-        getREmbedRFFI();
-        if (delegate == null) {
-            rEmbedRFFI.writeConsole(s);
-        } else {
-            delegate.print(s);
-        }
-    }
-
-    @Override
-    @TruffleBoundary
-    public void printErrorln(String s) {
-        getREmbedRFFI();
-        if (delegate == null) {
-            rEmbedRFFI.writeErrConsole(s);
-            rEmbedRFFI.writeErrConsole("\n");
-        } else {
-            delegate.printErrorln(s);
-        }
-    }
-
-    @Override
-    @TruffleBoundary
-    public void printError(String s) {
-        getREmbedRFFI();
-        if (delegate == null) {
-            rEmbedRFFI.writeErrConsole(s);
-        } else {
-            delegate.printError(s);
-        }
-    }
+    // @Override
+    // @TruffleBoundary
+    // public void println(String s) {
+    // getREmbedRFFI();
+    // if (delegate == null) {
+    // getREmbedRFFI().writeConsole(s);
+    // getREmbedRFFI().writeConsole("\n");
+    // } else {
+    // delegate.println(s);
+    // }
+    // }
+    //
+    // @Override
+    // @TruffleBoundary
+    // public void print(String s) {
+    // getREmbedRFFI();
+    // if (delegate == null) {
+    // rEmbedRFFI.writeConsole(s);
+    // } else {
+    // delegate.print(s);
+    // }
+    // }
+    //
+    // @Override
+    // @TruffleBoundary
+    // public void printErrorln(String s) {
+    // getREmbedRFFI();
+    // if (delegate == null) {
+    // rEmbedRFFI.writeErrConsole(s);
+    // rEmbedRFFI.writeErrConsole("\n");
+    // } else {
+    // delegate.printErrorln(s);
+    // }
+    // }
+    //
+    // @Override
+    // @TruffleBoundary
+    // public void printError(String s) {
+    // getREmbedRFFI();
+    // if (delegate == null) {
+    // rEmbedRFFI.writeErrConsole(s);
+    // } else {
+    // delegate.printError(s);
+    // }
+    // }
 
     @Override
     @TruffleBoundary
@@ -124,16 +127,6 @@ public class EmbeddedConsoleHandler extends ConsoleHandler {
         }
     }
 
-    @Override
-    public boolean isInteractive() {
-        return startParams.getInteractive();
-    }
-
-    @Override
-    public String getPrompt() {
-        return prompt;
-    }
-
     @Override
     @TruffleBoundary
     public void setPrompt(String prompt) {
@@ -142,9 +135,4 @@ public class EmbeddedConsoleHandler extends ConsoleHandler {
             delegate.setPrompt(prompt);
         }
     }
-
-    @Override
-    public String getInputDescription() {
-        return "<embedded input>";
-    }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java
deleted file mode 100644
index b5e7c8ae1eb3dec0c024c9185b453d5e7ee94507..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2017, 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.engine.shell;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import com.oracle.truffle.api.frame.MaterializedFrame;
-import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
-import com.oracle.truffle.r.runtime.RCaller;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
-import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RList;
-import com.oracle.truffle.r.runtime.data.RPromise;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.oracle.truffle.r.runtime.env.REnvironment;
-
-import jline.console.completer.Completer;
-
-public class JLineConsoleCompleter implements Completer {
-    private final ConsoleHandler console;
-
-    private static boolean isTesting = false;
-
-    public static void testingMode() {
-        isTesting = true;
-    }
-
-    public JLineConsoleCompleter(ConsoleHandler console) {
-        this.console = console;
-    }
-
-    @Override
-    public int complete(String buffer, int cursor, List<CharSequence> candidates) {
-        try {
-            return completeImpl(buffer, cursor, candidates);
-        } catch (Throwable e) {
-            if (isTesting) {
-                throw e;
-            }
-            RInternalError.reportErrorAndConsoleLog(e, console, 0);
-        }
-        return cursor;
-    }
-
-    @SuppressWarnings("try")
-    private int completeImpl(String buffer, int cursor, List<CharSequence> candidates) {
-        if (buffer.isEmpty()) {
-            return cursor;
-        }
-
-        try (RCloseable c = RContext.withinContext(console.getContext())) {
-
-            REnvironment utils = REnvironment.getRegisteredNamespace("utils");
-            Object o = utils.get(".completeToken");
-            if (o instanceof RPromise) {
-                o = PromiseHelperNode.evaluateSlowPath((RPromise) o);
-            }
-            RFunction completeToken;
-            if (o instanceof RFunction) {
-                completeToken = (RFunction) o;
-            } else {
-                return cursor;
-            }
-
-            o = utils.get(".CompletionEnv");
-            if (!(o instanceof RPromise)) {
-                return cursor;
-            }
-            REnvironment env = (REnvironment) PromiseHelperNode.evaluateSlowPath(null, (RPromise) o);
-            int start = getStart(buffer, env, cursor);
-            env.safePut("start", start);
-            env.safePut("end", cursor);
-            env.safePut("linebuffer", buffer);
-            env.safePut("token", buffer.substring(start, cursor));
-
-            MaterializedFrame callingFrame = REnvironment.globalEnv().getFrame();
-            RContext.getEngine().evalFunction(completeToken, callingFrame, RCaller.createInvalid(callingFrame), true, null, new Object[]{});
-
-            o = env.get("comps");
-            if (!(o instanceof RAbstractStringVector)) {
-                return cursor;
-            }
-
-            RAbstractStringVector comps = (RAbstractStringVector) o;
-            List<String> ret = new ArrayList<>(comps.getLength());
-            for (int i = 0; i < comps.getLength(); i++) {
-                ret.add(comps.getDataAt(i));
-            }
-            Collections.sort(ret, String.CASE_INSENSITIVE_ORDER);
-            candidates.addAll(ret);
-            return start;
-        }
-    }
-
-    private static int getStart(String buffer, REnvironment env, int cursor) {
-        int start = 0;
-        Object o = env.get("options");
-        if (o instanceof RList) {
-            RList opt = (RList) o;
-            start = lastIdxOf(buffer, opt, "funarg.suffix", start, cursor);
-            start = lastIdxOf(buffer, opt, "function.suffix", start, cursor);
-        }
-        start = lastIdxOf(buffer, "\"", start, cursor);
-        start = lastIdxOf(buffer, "'", start, cursor);
-        return start;
-    }
-
-    private static int lastIdxOf(String buffer, RList opt, String key, int start, int cursor) {
-        int optIdx = opt.getElementIndexByName(key);
-        if (optIdx > -1) {
-            Object o = opt.getDataAt(optIdx);
-            if (o instanceof RAbstractStringVector) {
-                RAbstractStringVector v = (RAbstractStringVector) o;
-                return lastIdxOf(buffer, v.getLength() > 0 ? v.getDataAt(0) : null, start, cursor);
-            }
-        }
-        return start;
-    }
-
-    private static int lastIdxOf(String buffer, String subs, int start, int cursor) {
-        if (null != subs && !subs.isEmpty()) {
-            int idx = buffer.lastIndexOf(subs, cursor);
-            if (idx == cursor) {
-                idx = buffer.lastIndexOf(subs, cursor - 1);
-            }
-            if (idx > -1) {
-                idx += subs.length();
-                return idx > start ? idx : start;
-            }
-        }
-        return start;
-    }
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java
deleted file mode 100644
index 86fe4c3cb7727c1146b1564b5c2db40ddfa0df85..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, 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.engine.shell;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.runtime.RSource;
-import com.oracle.truffle.r.runtime.RStartParams;
-import com.oracle.truffle.r.runtime.Utils;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
-
-import jline.console.ConsoleReader;
-import jline.console.UserInterruptException;
-import jline.console.completer.CandidateListCompletionHandler;
-import jline.console.completer.CompletionHandler;
-import jline.console.history.FileHistory;
-import jline.console.history.History;
-
-class JLineConsoleHandler extends ConsoleHandler {
-    private final ConsoleReader console;
-    private final boolean isInteractive;
-    private final PrintWriter printWriter;
-
-    JLineConsoleHandler(RStartParams startParams, InputStream inStream, OutputStream outStream) {
-        try {
-            console = new ConsoleReader(inStream, outStream);
-            console.addCompleter(new JLineConsoleCompleter(this));
-            CompletionHandler completionHandler = console.getCompletionHandler();
-            if (completionHandler instanceof CandidateListCompletionHandler) {
-                ((CandidateListCompletionHandler) completionHandler).setPrintSpaceAfterFullCompletion(false);
-            }
-            console.setHandleUserInterrupt(true);
-            console.setExpandEvents(false);
-        } catch (IOException ex) {
-            throw Utils.rSuicide("unexpected error opening console reader");
-        }
-        // long start = System.currentTimeMillis();
-        printWriter = new PrintWriter(console.getOutput());
-        this.isInteractive = startParams.getInteractive();
-    }
-
-    @Override
-    @TruffleBoundary
-    public void println(String s) {
-        printWriter.println(s);
-        printWriter.flush();
-    }
-
-    @Override
-    @TruffleBoundary
-    public void print(String s) {
-        printWriter.print(s);
-        printWriter.flush();
-    }
-
-    @Override
-    @TruffleBoundary
-    public String readLine() {
-        try {
-            console.getTerminal().init();
-            return console.readLine();
-        } catch (UserInterruptException e) {
-            throw e;
-        } catch (Exception ex) {
-            throw Utils.rSuicide("unexpected error reading console input: " + ex);
-        }
-    }
-
-    @Override
-    public boolean isInteractive() {
-        return isInteractive;
-    }
-
-    @Override
-    @TruffleBoundary
-    public void printErrorln(String s) {
-        println(s);
-    }
-
-    @Override
-    @TruffleBoundary
-    public void printError(String s) {
-        print(s);
-    }
-
-    @Override
-    @TruffleBoundary
-    public String getPrompt() {
-        return console.getPrompt();
-    }
-
-    @Override
-    @TruffleBoundary
-    public void setPrompt(String prompt) {
-        console.setPrompt(prompt);
-    }
-
-    @Override
-    public String getInputDescription() {
-        return RSource.Internal.SHELL_INPUT.string;
-    }
-
-    @Override
-    public void setHistoryFrom(File file) {
-        try {
-            console.setHistory(new FileHistory(file));
-        } catch (IOException x) {
-            // silent - there will simply be no history
-        }
-    }
-
-    @Override
-    public void flushHistory() {
-        History history = console.getHistory();
-        if (history instanceof FileHistory) {
-            try {
-                history.removeLast();
-                ((FileHistory) history).flush();
-            } catch (IOException x) {
-                // silent - no history appended
-            }
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
deleted file mode 100644
index 45a37ce645397b21b1f3cc9feaa8a5e72eec9db3..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, 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.engine.shell;
-
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.EXPR;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.FILE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.INTERACTIVE;
-
-import java.io.Console;
-import java.io.EOFException;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.file.Files;
-import java.util.List;
-
-import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.source.Source;
-import com.oracle.truffle.api.vm.PolyglotEngine;
-import com.oracle.truffle.api.vm.PolyglotEngine.Value;
-import com.oracle.truffle.r.nodes.builtin.base.Quit;
-import com.oracle.truffle.r.runtime.ExitException;
-import com.oracle.truffle.r.runtime.FastROptions;
-import com.oracle.truffle.r.runtime.JumpToTopLevelException;
-import com.oracle.truffle.r.runtime.RCmdOptions;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.RSource;
-import com.oracle.truffle.r.runtime.RStartParams;
-import com.oracle.truffle.r.runtime.StartupTiming;
-import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE;
-import com.oracle.truffle.r.runtime.Utils;
-import com.oracle.truffle.r.runtime.Utils.DebugExitException;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
-import com.oracle.truffle.r.runtime.context.ContextInfo;
-import com.oracle.truffle.r.runtime.context.DefaultConsoleHandler;
-import com.oracle.truffle.r.runtime.context.Engine;
-import com.oracle.truffle.r.runtime.context.Engine.IncompleteSourceException;
-import com.oracle.truffle.r.runtime.context.Engine.ParseException;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
-import com.oracle.truffle.r.runtime.data.RLogicalVector;
-import com.oracle.truffle.r.runtime.data.RStringVector;
-
-import jline.console.UserInterruptException;
-
-/**
- * Emulates the (Gnu)R command as precisely as possible.
- */
-public class RCommand {
-
-    // CheckStyle: stop system..print check
-
-    public static void main(String[] args) {
-        doMain(args, null, true, System.in, System.out);
-        // never returns
-        throw RInternalError.shouldNotReachHere();
-    }
-
-    public static int doMain(String[] args, String[] env, boolean initial, InputStream inStream, OutputStream outStream) {
-        FastROptions.initialize();
-        StartupTiming.timestamp("Main Entered");
-        RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.R, args, false);
-        options.printHelpAndVersion();
-        ContextInfo info = createContextInfoFromCommandLine(options, false, initial, inStream, outStream, env);
-        PolyglotEngine vm = info.createVM();
-        StartupTiming.timestamp("VM Created");
-        StartupTiming.printSummary();
-        return readEvalPrint(vm, info);
-    }
-
-    /**
-     * The standard R script escapes spaces to "~+~" in "-e" and "-f" commands.
-     */
-    private static String unescapeSpace(String input) {
-        return input.replace("~+~", " ");
-    }
-
-    static ContextInfo createContextInfoFromCommandLine(RCmdOptions options, boolean embedded, boolean initial, InputStream inStream, OutputStream outStream, String[] env) {
-        RStartParams rsp = new RStartParams(options, embedded);
-
-        String fileArg = options.getString(FILE);
-        if (fileArg != null) {
-            if (options.getStringList(EXPR) != null) {
-                Utils.rSuicide("cannot use -e with -f or --file");
-            }
-            if (!rsp.getSlave()) {
-                rsp.setSaveAction(SA_TYPE.NOSAVE);
-            }
-            if (fileArg.equals("-")) {
-                // means stdin, but still implies NO_SAVE
-                fileArg = null;
-            } else {
-                fileArg = unescapeSpace(fileArg);
-            }
-            // cf GNU R
-            rsp.setInteractive(false);
-        }
-
-        /*
-         * Outputting the welcome message here has the virtue that the VM initialization delay
-         * occurs later. However, it does not work in embedded mode as console redirects have not
-         * been installed at this point. So we do it later in REmbedded.
-         */
-        if (!rsp.getQuiet() && !embedded) {
-            System.out.println(RRuntime.WELCOME_MESSAGE);
-        }
-        /*
-         * Whether the input is from stdin, a file (-f), or an expression on the command line (-e)
-         * it goes through the console. N.B. -f and -e can't be used together and this is already
-         * checked.
-         */
-        ConsoleHandler consoleHandler;
-        if (fileArg != null) {
-            List<String> lines;
-            String filePath;
-            try {
-                /*
-                 * If initial==false, ~ expansion will not have been done and the open will fail.
-                 * It's harmless to always do it.
-                 */
-                File file = new File(Utils.tildeExpand(fileArg));
-                lines = Files.readAllLines(file.toPath());
-                filePath = file.getCanonicalPath();
-            } catch (IOException e) {
-                if (initial) {
-                    throw Utils.rSuicide(String.format(RError.Message.NO_SUCH_FILE.message, fileArg));
-                } else {
-                    throw RError.error(RError.NO_CALLER, RError.Message.NO_SUCH_FILE, fileArg);
-                }
-            }
-            consoleHandler = new StringConsoleHandler(lines, outStream, filePath);
-        } else if (options.getStringList(EXPR) != null) {
-            List<String> exprs = options.getStringList(EXPR);
-            for (int i = 0; i < exprs.size(); i++) {
-                exprs.set(i, unescapeSpace(exprs.get(i)));
-            }
-            if (!rsp.getSlave()) {
-                rsp.setSaveAction(SA_TYPE.NOSAVE);
-            }
-            // cf GNU R
-            rsp.setInteractive(false);
-            consoleHandler = new StringConsoleHandler(exprs, outStream, RSource.Internal.EXPRESSION_INPUT.string);
-        } else {
-            /*
-             * GnuR behavior differs from the manual entry for {@code interactive} in that {@code
-             * --interactive} never applies to {@code -e/-f}, only to console input that has been
-             * redirected from a pipe/file etc.
-             *
-             * If we are in embedded mode, the creation of ConsoleReader and the ConsoleHandler
-             * should be lazy, as these may not be necessary and can cause hangs if stdin has been
-             * redirected.
-             */
-            Console sysConsole = System.console(); // TODO fix for context sessions
-            boolean isInteractive = options.getBoolean(INTERACTIVE) || sysConsole != null;
-            if (!isInteractive && rsp.getSaveAction() != SA_TYPE.SAVE && rsp.getSaveAction() != SA_TYPE.NOSAVE) {
-                String msg = "you must specify '--save', '--no-save' or '--vanilla'";
-                if (initial) {
-                    throw Utils.rSuicide(msg);
-                } else {
-                    throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, msg);
-                }
-            }
-            if (embedded) {
-                consoleHandler = new EmbeddedConsoleHandler(rsp);
-            } else {
-                boolean useReadLine = !rsp.getNoReadline();
-                if (useReadLine) {
-                    consoleHandler = new JLineConsoleHandler(rsp, inStream, outStream);
-                } else {
-                    consoleHandler = new DefaultConsoleHandler(inStream, outStream);
-                }
-            }
-        }
-        return ContextInfo.create(rsp, env, ContextKind.SHARE_NOTHING, initial ? null : RContext.getInstance(), consoleHandler);
-    }
-
-    private static final Source GET_ECHO = RSource.fromTextInternal("invisible(getOption('echo'))", RSource.Internal.GET_ECHO);
-    private static final Source QUIT_EOF = RSource.fromTextInternal("quit(\"default\", 0L, TRUE)", RSource.Internal.QUIT_EOF);
-    private static final Source GET_CONTINUE_PROMPT = RSource.fromTextInternal("invisible(getOption('continue'))", RSource.Internal.GET_CONTINUE_PROMPT);
-
-    /**
-     * The read-eval-print loop, which can take input from a console, command line expression or a
-     * file. There are two ways the repl can terminate:
-     * <ol>
-     * <li>A {@code quit} command is executed successfully, which case the system exits from the
-     * {@link Quit} {@code .Internal} .</li>
-     * <li>EOF on the input.</li>
-     * </ol>
-     * In case 2, we must implicitly execute a {@code quit("default, 0L, TRUE} command before
-     * exiting. So,in either case, we never return.
-     */
-    static int readEvalPrint(PolyglotEngine vm, ContextInfo info) {
-        int lastStatus = 0;
-        ConsoleHandler consoleHandler = info.getConsoleHandler();
-        try {
-            // console.println("initialize time: " + (System.currentTimeMillis() - start));
-            REPL: for (;;) {
-                boolean doEcho = doEcho(vm);
-                consoleHandler.setPrompt(doEcho ? "> " : null);
-                try {
-                    String input = consoleHandler.readLine();
-                    if (input == null) {
-                        throw new EOFException();
-                    }
-                    String trInput = input.trim();
-                    if (trInput.equals("") || trInput.charAt(0) == '#') {
-                        // nothing to parse
-                        continue;
-                    }
-
-                    String continuePrompt = getContinuePrompt(vm);
-                    StringBuilder sb = new StringBuilder(input);
-                    Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.SHELL_INPUT);
-                    boolean hasExecutor = hasExectuor(vm);
-                    while (true) {
-                        lastStatus = 0;
-                        try {
-                            try {
-                                Value val = vm.eval(source);
-                                if (hasExecutor) {
-                                    val.get();
-                                }
-                                // checked exceptions are wrapped in RuntimeExceptions
-                            } catch (RuntimeException e) {
-                                if (e.getCause() instanceof com.oracle.truffle.api.vm.IncompleteSourceException) {
-                                    throw e.getCause().getCause();
-                                }
-                                throw e;
-                            }
-                        } catch (IncompleteSourceException e) {
-                            // read another line of input
-                            consoleHandler.setPrompt(doEcho ? continuePrompt : null);
-                            String additionalInput = consoleHandler.readLine();
-                            if (additionalInput == null) {
-                                throw new EOFException();
-                            }
-                            sb.append('\n');
-                            sb.append(additionalInput);
-                            source = RSource.fromTextInternal(sb.toString(), RSource.Internal.SHELL_INPUT);
-                            // The only continuation in the while loop
-                            continue;
-                        } catch (ParseException e) {
-                            e.report(consoleHandler);
-                            lastStatus = 1;
-                        } catch (RError e) {
-                            // drop through to continue REPL and remember last eval was an error
-                            lastStatus = 1;
-                        } catch (JumpToTopLevelException e) {
-                            // drop through to continue REPL
-                        } catch (DebugExitException e) {
-                            throw (RuntimeException) e.getCause();
-                        } catch (ExitException e) {
-                            // usually from quit
-                            int status = e.getStatus();
-                            if (info.getParent() == null) {
-                                vm.dispose();
-                                Utils.systemExit(status);
-                            } else {
-                                return status;
-                            }
-                        } catch (Throwable e) {
-                            RInternalError.reportErrorAndConsoleLog(e, consoleHandler, 0);
-                            // We continue the repl even though the system may be broken
-                            lastStatus = 1;
-                        }
-                        continue REPL;
-                    }
-                } catch (UserInterruptException e) {
-                    // interrupted by ctrl-c
-                }
-            }
-        } catch (JumpToTopLevelException | EOFException ex) {
-            // JumpToTopLevelException can happen if user profile invokes browser (unlikely but
-            // possible)
-            try {
-                vm.eval(QUIT_EOF).get();
-            } catch (JumpToTopLevelException e) {
-                Utils.systemExit(0);
-            } catch (ExitException e) {
-                // normal quit, but with exit code based on lastStatus
-                if (info.getParent() == null) {
-                    Utils.systemExit(lastStatus);
-                } else {
-                    return lastStatus;
-                }
-            } catch (Throwable e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        } finally {
-            vm.dispose();
-        }
-        return 0;
-    }
-
-    private static boolean doEcho(PolyglotEngine vm) {
-        PolyglotEngine.Value echoValue = vm.eval(GET_ECHO);
-        Object echo = echoValue.get();
-        if (echo instanceof Boolean) {
-            return (boolean) echo;
-        } else if (echo instanceof TruffleObject) {
-            RLogicalVector echoVec = echoValue.as(RLogicalVector.class);
-            return RRuntime.fromLogical(echoVec.getDataAt(0));
-        } else if (echo instanceof Byte) {
-            return RRuntime.fromLogical((Byte) echo);
-        } else {
-            throw RInternalError.shouldNotReachHere();
-        }
-    }
-
-    private static String getContinuePrompt(PolyglotEngine vm) {
-        PolyglotEngine.Value echoValue = vm.eval(GET_CONTINUE_PROMPT);
-        Object echo = echoValue.get();
-        if (echo instanceof String) {
-            return (String) echo;
-        } else if (echo instanceof TruffleObject) {
-            RStringVector promptVec = echoValue.as(RStringVector.class);
-            return promptVec.getDataAt(0);
-        } else {
-            throw RInternalError.shouldNotReachHere();
-        }
-    }
-
-    private static boolean hasExectuor(PolyglotEngine vm) {
-        return vm.eval(Engine.GET_CONTEXT).as(RContext.class).hasExecutor();
-    }
-
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
index d396a37419bbc799889fdca017ec5db3f5e8af88..5b82001fe056f196fd7bb86d9e733580ea4003ee 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
@@ -22,16 +22,21 @@
  */
 package com.oracle.truffle.r.engine.shell;
 
-import com.oracle.truffle.api.source.Source;
+import org.graalvm.polyglot.Engine;
+import org.graalvm.polyglot.PolyglotContext;
+import org.graalvm.polyglot.PolyglotContext.Builder;
+
 import com.oracle.truffle.api.vm.PolyglotEngine;
-import com.oracle.truffle.r.runtime.RCmdOptions;
+import com.oracle.truffle.r.launcher.ConsoleHandler;
+import com.oracle.truffle.r.launcher.RCmdOptions;
+import com.oracle.truffle.r.launcher.RCommand;
+import com.oracle.truffle.r.launcher.RStartParams;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.RSource.Internal;
-import com.oracle.truffle.r.runtime.RStartParams;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.context.ContextInfo;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 
 /**
  * Support for embedding FastR in a C/C++ application according to {@code Rembedded.h}. The
@@ -59,23 +64,35 @@ import com.oracle.truffle.r.runtime.context.RContext;
  */
 public class REmbedded {
 
+    private static ConsoleHandler consoleHandler;
     private static ContextInfo info;
-    private static PolyglotEngine vm;
+    private static Engine engine;
+    private static PolyglotContext context;
 
     /**
-     * Creates the {@link PolyglotEngine} and initializes it. Called from native code when FastR is
+     * Creates the {@link Engine} and initializes it. Called from native code when FastR is
      * embedded. Corresponds to FFI method {@code Rf_initialize_R}. N.B. This does not completely
      * initialize FastR as we cannot do that until the embedding system has had a chance to adjust
      * the {@link RStartParams}, which happens after this call returns.
      */
     private static void initializeR(String[] args) {
-        assert vm == null;
+        assert engine == null;
         assert info == null;
         RContext.setEmbedded();
-        RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.R, args, true);
-        info = RCommand.createContextInfoFromCommandLine(options, true, true, System.in, System.out, null);
-        vm = info.createVM();
-        vm.eval(INIT);
+        RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.R, args, false);
+
+        RStartParams rsp = new RStartParams(options, true);
+        info = ContextInfo.create(rsp, null, ContextKind.SHARE_NOTHING, null, System.in, System.out, System.err);
+
+        engine = info.createEngine();
+        context = engine.createPolyglotContext();
+        consoleHandler = RCommand.createConsoleHandler(options, true, System.in, System.out);
+        Builder builder = engine.newPolyglotContextBuilder();
+        try (PolyglotContext cntx = builder.setArguments("R", options.getArguments()).setIn(consoleHandler.createInputStream()).setOut(System.out).setErr(System.err).build()) {
+            context = cntx;
+            consoleHandler.setPolyglotContext(context);
+            context.eval("R", INIT);
+        }
     }
 
     /**
@@ -83,7 +100,7 @@ public class REmbedded {
      * is evaluated the R builtins have not been installed, see {@link #initializeR}. The
      * suppression of printing is handled a a special case based on {@link Internal#INIT_EMBEDDED}.
      */
-    private static final Source INIT = RSource.fromTextInternal("1", RSource.Internal.INIT_EMBEDDED);
+    private static final String INIT = "1";
 
     /**
      * GnuR distinguishes {@code setup_Rmainloop} and {@code run_Rmainloop}. Currently we don't have
@@ -99,10 +116,13 @@ public class REmbedded {
      */
     private static void runRmainloop() {
         RContext.getInstance().completeEmbeddedInitialization();
-        if (!RContext.getInstance().getStartParams().getQuiet()) {
-            RContext.getInstance().getConsoleHandler().println(RRuntime.WELCOME_MESSAGE);
+        if (!RContext.getInstance().getStartParams().isQuiet()) {
+            System.out.println(RRuntime.WELCOME_MESSAGE);
         }
-        RCommand.readEvalPrint(vm, info);
+        int status = RCommand.readEvalPrint(context, consoleHandler);
+        context.close();
+        engine.close();
+        Utils.systemExit(status);
     }
 
     /**
@@ -110,10 +130,6 @@ public class REmbedded {
      */
     public static void main(String[] args) {
         initializeR(args);
-        RStartParams startParams = info.getStartParams();
-        startParams.setEmbedded();
-        startParams.setLoadInitFile(false);
-        startParams.setNoRenviron(true);
         setupRmainloop();
         runRmainloop();
     }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
index ee6cfa04ba10a06beecd23d466dbb4d6a18914ac..12b2efafc97208aff8087ae8a17f1961cf82d614 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
@@ -59,7 +59,6 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.RSrcref;
-import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
@@ -106,6 +105,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
+import com.oracle.truffle.r.runtime.gnur.SA_TYPE;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 import com.oracle.truffle.r.runtime.nodes.DuplicationHelper;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -1145,7 +1145,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
 
     @Override
     public int Rprintf(Object message) {
-        RContext.getInstance().getConsoleHandler().print((String) message);
+        RContext.getInstance().getConsole().print((String) message);
         return 0;
     }
 
diff --git a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/ConsoleHandler.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/ConsoleHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..9d326212d263e8b5eb47d2de60302778dd80f463
--- /dev/null
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/ConsoleHandler.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013, 2017, 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.launcher;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import org.graalvm.polyglot.PolyglotContext;
+
+/**
+ * The interface to a source of input/output for the context, which may have different
+ * implementations for different contexts.
+ */
+public abstract class ConsoleHandler {
+
+    /**
+     * Read a line of input, newline is <b>NOT</b> included in result.
+     */
+    public abstract String readLine();
+
+    /**
+     * Set the R prompt.
+     */
+    public abstract void setPrompt(String prompt);
+
+    public void setPolyglotContext(@SuppressWarnings("unused") PolyglotContext context) {
+        // ignore by default
+    }
+
+    public InputStream createInputStream() {
+        return new InputStream() {
+            byte[] buffer = null;
+            int pos = -1;
+
+            @Override
+            public int read() throws IOException {
+                if (buffer == null) {
+                    pos = 0;
+                    buffer = readLine().getBytes(StandardCharsets.UTF_8);
+                }
+                if (pos == buffer.length) {
+                    buffer = null;
+                    return '\n';
+                } else {
+                    return buffer[pos++];
+                }
+            }
+        };
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/DefaultConsoleHandler.java
similarity index 75%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java
rename to com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/DefaultConsoleHandler.java
index 3bb4b182ccaf24cfbba29e1930d0fa3308614bf5..f5f1e0cd9b5ca3d6aafc7e16004cdd3045505e9e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/DefaultConsoleHandler.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.context;
+package com.oracle.truffle.r.launcher;
 
 import java.io.BufferedReader;
 import java.io.IOException;
@@ -40,26 +40,6 @@ public class DefaultConsoleHandler extends ConsoleHandler {
         this.out = new PrintStream(out);
     }
 
-    @Override
-    public void println(String s) {
-        out.println(s);
-    }
-
-    @Override
-    public void print(String s) {
-        out.print(s);
-    }
-
-    @Override
-    public void printErrorln(String s) {
-        out.println(s);
-    }
-
-    @Override
-    public void printError(String s) {
-        out.print(s);
-    }
-
     @Override
     public String readLine() {
         try {
@@ -72,23 +52,8 @@ public class DefaultConsoleHandler extends ConsoleHandler {
         }
     }
 
-    @Override
-    public boolean isInteractive() {
-        return true;
-    }
-
-    @Override
-    public String getPrompt() {
-        return prompt;
-    }
-
     @Override
     public void setPrompt(String prompt) {
         this.prompt = prompt;
     }
-
-    @Override
-    public String getInputDescription() {
-        return "<PolyglotEngine env input>";
-    }
 }
diff --git a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleCompleter.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleCompleter.java
new file mode 100644
index 0000000000000000000000000000000000000000..cefa1ace252c35cb2d02e23aeeb936393b37e590
--- /dev/null
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleCompleter.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2017, 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.launcher;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.graalvm.polyglot.PolyglotContext;
+import org.graalvm.polyglot.Value;
+
+import jline.console.completer.Completer;
+
+public class JLineConsoleCompleter implements Completer {
+
+    private static boolean isTesting = false;
+    private final PolyglotContext context;
+
+    public static void testingMode() {
+        isTesting = true;
+    }
+
+    public JLineConsoleCompleter(PolyglotContext context) {
+        this.context = context;
+    }
+
+    @Override
+    public int complete(String buffer, int cursor, List<CharSequence> candidates) {
+        try {
+            return completeImpl(buffer, cursor, candidates);
+        } catch (Throwable e) {
+            if (isTesting) {
+                throw e;
+            }
+            throw RCommand.fatal(e, "error while determining completion");
+        }
+    }
+
+    private static final String GET_COMPLETION_FUNCTION = "utils:::.completeToken";
+    private static final String GET_COMPLETION_ENV = "utils:::.CompletionEnv";
+    private static final String SET_FUNCTION = "`$<-`";
+
+    @SuppressWarnings("try")
+    private int completeImpl(String buffer, int cursor, List<CharSequence> candidates) {
+        if (buffer.isEmpty()) {
+            return cursor;
+        }
+        Value completionFunction = context.eval("R", GET_COMPLETION_FUNCTION);
+        Value completionEnv = context.eval("R", GET_COMPLETION_ENV);
+        Value setFunction = context.eval("R", SET_FUNCTION);
+
+        int start = getStart(buffer, completionEnv, cursor);
+        setFunction.execute(completionEnv, "start", start);
+        setFunction.execute(completionEnv, "end", cursor);
+        setFunction.execute(completionEnv, "linebuffer", buffer);
+        setFunction.execute(completionEnv, "token", buffer.substring(start, cursor));
+
+        completionFunction.execute();
+
+        if (completionEnv.hasMember("comps")) {
+            Value completions = completionEnv.getMember("comps");
+            if (completions.hasArrayElements()) {
+                long length = completions.getArraySize();
+                List<String> result = new ArrayList<>((int) length);
+                for (int i = 0; i < length; i++) {
+                    result.add(completions.getArrayElement(i).asString());
+                }
+                Collections.sort(result, String.CASE_INSENSITIVE_ORDER);
+                candidates.addAll(result);
+                return start;
+            }
+        }
+        return cursor;
+    }
+
+    private static int getStart(String buffer, Value env, int cursor) {
+        int start = 0;
+        Value opt = env.getMember("options");
+        if (opt.hasMembers()) {
+            start = lastIdxOf(buffer, opt, "funarg.suffix", start, cursor);
+            start = lastIdxOf(buffer, opt, "function.suffix", start, cursor);
+        }
+        start = lastIdxOf(buffer, "\"", start, cursor);
+        start = lastIdxOf(buffer, "'", start, cursor);
+        return start;
+    }
+
+    private static int lastIdxOf(String buffer, Value opt, String key, int start, int cursor) {
+        if (opt.hasMember(key)) {
+            Value member = opt.getMember(key);
+            if (member.isString()) {
+                return lastIdxOf(buffer, member.asString(), start, cursor);
+            } else if (member.hasArrayElements() && member.getArraySize() > 0 && member.getArrayElement(0).isString()) {
+                return lastIdxOf(buffer, member.getArrayElement(0).asString(), start, cursor);
+            }
+        }
+        return start;
+    }
+
+    private static int lastIdxOf(String buffer, String subs, int start, int cursor) {
+        if (!subs.isEmpty()) {
+            int idx = buffer.lastIndexOf(subs, cursor);
+            if (idx == cursor) {
+                idx = buffer.lastIndexOf(subs, cursor - 1);
+            }
+            if (idx > -1) {
+                idx += subs.length();
+                return idx > start ? idx : start;
+            }
+        }
+        return start;
+    }
+}
diff --git a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleHandler.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a8350df2667b57946531e5a8c9208202e8c5bc8
--- /dev/null
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleHandler.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2014, 2017, 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.launcher;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.graalvm.polyglot.PolyglotContext;
+
+import jline.console.ConsoleReader;
+import jline.console.UserInterruptException;
+import jline.console.completer.CandidateListCompletionHandler;
+import jline.console.completer.CompletionHandler;
+import jline.console.history.MemoryHistory;
+
+public class JLineConsoleHandler extends ConsoleHandler {
+    private final ConsoleReader console;
+    private final MemoryHistory history;
+    private final boolean noPrompt;
+
+    public JLineConsoleHandler(InputStream inStream, OutputStream outStream, boolean noPrompt) {
+        this.noPrompt = noPrompt;
+        try {
+            console = new ConsoleReader(inStream, outStream);
+            history = new MemoryHistory();
+            console.setHistory(history);
+            console.setHandleUserInterrupt(true);
+            console.setExpandEvents(false);
+        } catch (IOException ex) {
+            throw RCommand.fatal(ex, "unexpected error opening console reader");
+        }
+    }
+
+    @Override
+    public void setPolyglotContext(PolyglotContext context) {
+        console.addCompleter(new JLineConsoleCompleter(context));
+        CompletionHandler completionHandler = console.getCompletionHandler();
+        if (completionHandler instanceof CandidateListCompletionHandler) {
+            ((CandidateListCompletionHandler) completionHandler).setPrintSpaceAfterFullCompletion(false);
+        }
+    }
+
+    @Override
+    public String readLine() {
+        try {
+            console.getTerminal().init();
+            return console.readLine();
+        } catch (UserInterruptException e) {
+            throw e;
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    @Override
+    public void setPrompt(String prompt) {
+        console.setPrompt(noPrompt ? "" : prompt);
+    }
+
+    public void clearHistory() {
+        history.clear();
+    }
+
+    public void addToHistory(String input) {
+        history.add(input);
+    }
+
+    public String[] getHistory() {
+        String[] result = new String[history.size()];
+        for (int i = 0; i < history.size(); i++) {
+            result[i] = history.get(i).toString();
+        }
+        return result;
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCmdOptions.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RCmdOptions.java
similarity index 86%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCmdOptions.java
rename to com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RCmdOptions.java
index 56b321b10bc4e1795db1cf39e613eb82158b6e9e..7a54ae27c2c96a71a5f4c8126929905ccc896ca8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCmdOptions.java
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RCmdOptions.java
@@ -20,10 +20,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime;
+package com.oracle.truffle.r.launcher;
 
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.HELP;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.VERSION;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.HELP;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.VERSION;
 
 import java.util.ArrayList;
 import java.util.EnumMap;
@@ -53,7 +53,7 @@ public final class RCmdOptions {
         EITHER {
             @Override
             public String usage() {
-                throw Utils.rSuicide("can't call usage() on Client.EITHER");
+                throw RCommand.fatal("can't call usage() on Client.EITHER");
             }
         };
 
@@ -131,7 +131,7 @@ public final class RCmdOptions {
                 this.suffix = eqx > 0 ? name.substring(eqx) : null;
             }
             this.defaultValue = defaultValue;
-            this.help = help.replace("\n", "\n                          ");
+            this.help = help;
         }
 
         RCmdOption(RCmdOptionType type, boolean implemented, String shortName, String name, Object defaultValue, String help) {
@@ -142,16 +142,6 @@ public final class RCmdOptions {
             this(type, Client.EITHER, implemented, null, name, defaultValue, help);
         }
 
-        private boolean matches(String arg) {
-            if (shortName != null && arg.equals(shortName)) {
-                return true;
-            }
-            if (name != null && arg.equals(name)) {
-                return true;
-            }
-            return false;
-        }
-
         private String getHelpName() {
             String result = "";
             if (shortName != null) {
@@ -247,18 +237,22 @@ public final class RCmdOptions {
 
     private static MatchResult matchOption(String arg) {
         for (RCmdOption option : RCmdOption.values()) {
-            if (option.type == RCmdOptionType.BOOLEAN) {
-                // these must match exactly
-                if (option.matches(arg)) {
-                    return new MatchResult(option, false);
-                }
-            } else if (option.type == RCmdOptionType.STRING || option.type == RCmdOptionType.REPEATED_STRING) {
-                // short forms must match exactly (and consume next argument)
-                if (option.shortName != null && option.shortName.equals(arg)) {
-                    return new MatchResult(option, true);
-                } else if (arg.indexOf('=') > 0 && option.name != null && arg.startsWith(option.name)) {
-                    return new MatchResult(option, false);
-                }
+            switch (option.type) {
+                case BOOLEAN:
+                    // these must match exactly
+                    if (option.shortName != null && arg.equals(option.shortName) || option.name != null && arg.equals(option.name)) {
+                        return new MatchResult(option, false);
+                    }
+                    break;
+                case STRING:
+                case REPEATED_STRING:
+                    // short forms must match exactly (and consume next argument)
+                    if (option.shortName != null && option.shortName.equals(arg)) {
+                        return new MatchResult(option, true);
+                    } else if (arg.indexOf('=') > 0 && option.name != null && arg.startsWith(option.name)) {
+                        return new MatchResult(option, false);
+                    }
+                    break;
             }
         }
         return null;
@@ -276,9 +270,9 @@ public final class RCmdOptions {
      * reasons) so we use "FastR". However, embedded mode does pass the executable in
      * {@code args[0]} and we do not want to parse that!
      */
-    public static RCmdOptions parseArguments(Client client, String[] args, boolean embedded) {
+    public static RCmdOptions parseArguments(Client client, String[] args, boolean reparse) {
         EnumMap<RCmdOption, Object> options = new EnumMap<>(RCmdOption.class);
-        int i = embedded ? 1 : 0;
+        int i = 1; // skip the first argument (the command)
         int firstNonOptionArgIndex = args.length;
         while (i < args.length) {
             final String arg = args[i];
@@ -289,8 +283,10 @@ public final class RCmdOptions {
                     firstNonOptionArgIndex = i;
                     break;
                 }
-                // GnuR does not abort, simply issues a warning
-                System.out.printf("WARNING: unknown option '%s'%n", arg);
+                if (!reparse) {
+                    // GnuR does not abort, simply issues a warning
+                    System.out.printf("WARNING: unknown option '%s'%n", arg);
+                }
                 i++;
                 continue;
             } else {
@@ -302,7 +298,9 @@ public final class RCmdOptions {
                 }
                 // check implemented
                 if (!option.implemented) {
-                    System.out.println("WARNING: option: " + arg + " is not implemented");
+                    if (!reparse) {
+                        System.out.println("WARNING: option: " + arg + " is not implemented");
+                    }
                 }
                 if (result.matchedShort) {
                     i++;
@@ -323,17 +321,8 @@ public final class RCmdOptions {
                 }
             }
         }
-        String[] xargs;
-        if (embedded) {
-            xargs = args;
-        } else {
-            xargs = new String[args.length + 1];
-            xargs[0] = "FastR";
-            System.arraycopy(args, 0, xargs, 1, args.length);
-        }
-
         // adjust for inserted executable name
-        return new RCmdOptions(options, xargs, firstNonOptionArgIndex + 1);
+        return new RCmdOptions(options, args, firstNonOptionArgIndex + 1);
     }
 
     public String[] getArguments() {
@@ -350,9 +339,9 @@ public final class RCmdOptions {
 
     public void printHelpAndVersion() {
         if (getBoolean(HELP)) {
-            printHelpAndExit(RCmdOptions.Client.R);
+            throw printHelpAndExit(RCmdOptions.Client.R);
         } else if (getBoolean(VERSION)) {
-            printVersionAndExit();
+            throw printVersionAndExit();
         }
     }
 
@@ -360,20 +349,22 @@ public final class RCmdOptions {
         System.out.println(client.usage());
         System.out.println("Options:");
         for (RCmdOption option : RCmdOption.values()) {
-            System.out.printf("  %-22s  %s%n", option.getHelpName(), option.help);
+            System.out.printf("  %-22s  %s%n", option.getHelpName(), option.help.replace("\n", "\n                          "));
         }
         System.out.println("\nFILE may contain spaces but not shell metacharacters.\n");
     }
 
-    public static void printHelpAndExit(Client client) {
+    public static RuntimeException printHelpAndExit(Client client) {
         printHelp(client);
-        throw new ExitException(0);
+        System.exit(0);
+        throw RCommand.fatal("should not reach here");
     }
 
-    private static void printVersionAndExit() {
+    private static RuntimeException printVersionAndExit() {
         System.out.print("FastR version ");
         System.out.println(RVersionNumber.FULL);
-        System.out.println(RRuntime.LICENSE);
+        System.out.println(RVersionNumber.LICENSE);
         System.exit(0);
+        throw RCommand.fatal("should not reach here");
     }
 }
diff --git a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RCommand.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..7fa7abfe28a5f2d96d07cfd00837dbe8520cec33
--- /dev/null
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RCommand.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2013, 2017, 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.launcher;
+
+import java.io.EOFException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.util.List;
+
+import org.graalvm.polyglot.Engine;
+import org.graalvm.polyglot.PolyglotContext;
+import org.graalvm.polyglot.PolyglotContext.Builder;
+import org.graalvm.polyglot.PolyglotException;
+import org.graalvm.polyglot.Source;
+
+import com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption;
+
+import jline.console.UserInterruptException;
+
+/*
+ * TODO:
+ * - create a replacement for "executor"
+ * - fatal needs to be handled more carefully in nested/spawned contexts
+ * - handle R_DEFAULT_PACKAGES in REnvVars
+ */
+
+/**
+ * Emulates the (Gnu)R command as precisely as possible.
+ */
+public class RCommand {
+
+    // CheckStyle: stop system..print check
+    public static RuntimeException fatal(String message, Object... args) {
+        System.out.println("FATAL: " + String.format(message, args));
+        System.exit(-1);
+        return null;
+    }
+
+    public static RuntimeException fatal(Throwable t, String message, Object... args) {
+        t.printStackTrace();
+        System.out.println("FATAL: " + String.format(message, args));
+        System.exit(-1);
+        return null;
+    }
+
+    public static void main(String[] args) {
+        System.exit(doMain(prependCommand(args), null, System.in, System.out, System.err));
+        // never returns
+        throw fatal("main should never return");
+    }
+
+    static String[] prependCommand(String[] args) {
+        String[] result = new String[args.length + 1];
+        result[0] = "R";
+        System.arraycopy(args, 0, result, 1, args.length);
+        return result;
+    }
+
+    public static int doMain(String[] inArgs, String[] env, InputStream inStream, OutputStream outStream, OutputStream errStream) {
+        StartupTiming.timestamp("Main Entered");
+        String[] args = inArgs;
+        if (System.console() != null) {
+            // add "--interactive" to force interactive mode
+            RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.R, args, false);
+            if (!options.getBoolean(RCmdOption.INTERACTIVE)) {
+                args = new String[inArgs.length + 1];
+                args[0] = inArgs[0];
+                args[1] = "--interactive";
+                System.arraycopy(inArgs, 1, args, 2, inArgs.length - 1);
+            }
+        }
+        RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.R, args, false);
+        options.printHelpAndVersion();
+        try (Engine engine = Engine.create()) {
+            assert env == null : "re-enable setting environments";
+            ConsoleHandler consoleHandler = createConsoleHandler(options, false, inStream, outStream);
+            Builder builder = engine.newPolyglotContextBuilder();
+            try (PolyglotContext context = builder.setArguments("R", options.getArguments()).setIn(consoleHandler.createInputStream()).setOut(outStream).setErr(errStream).build()) {
+                consoleHandler.setPolyglotContext(context);
+                StartupTiming.timestamp("VM Created");
+                StartupTiming.printSummary();
+                return readEvalPrint(context, consoleHandler);
+            }
+        }
+    }
+
+    public static ConsoleHandler createConsoleHandler(RCmdOptions options, boolean embedded, InputStream inStream, OutputStream outStream) {
+        /*
+         * Whether the input is from stdin, a file (-f), or an expression on the command line (-e)
+         * it goes through the console. N.B. -f and -e can't be used together and this is already
+         * checked.
+         */
+        RStartParams rsp = new RStartParams(options, false);
+        String fileArgument = rsp.getFileArgument();
+        if (fileArgument != null) {
+            List<String> lines;
+            try {
+                /*
+                 * If initial==false, ~ expansion will not have been done and the open will fail.
+                 * It's harmless to always do it.
+                 */
+                File file = fileArgument.startsWith("~") ? new File(System.getProperty("user.home") + fileArgument.substring(1)) : new File(fileArgument);
+                lines = Files.readAllLines(file.toPath());
+            } catch (IOException e) {
+                throw fatal("cannot open file '%s': No such file or directory", fileArgument);
+            }
+            return new StringConsoleHandler(lines, outStream);
+        } else if (options.getStringList(RCmdOption.EXPR) != null) {
+            List<String> exprs = options.getStringList(RCmdOption.EXPR);
+            for (int i = 0; i < exprs.size(); i++) {
+                exprs.set(i, unescapeSpace(exprs.get(i)));
+            }
+            return new StringConsoleHandler(exprs, outStream);
+        } else {
+            boolean isInteractive = options.getBoolean(RCmdOption.INTERACTIVE);
+            if (!isInteractive && rsp.askForSave()) {
+                fatal("you must specify '--save', '--no-save' or '--vanilla'");
+            }
+            if (embedded) {
+                /*
+                 * If we are in embedded mode, the creation of ConsoleReader and the ConsoleHandler
+                 * should be lazy, as these may not be necessary and can cause hangs if stdin has
+                 * been redirected.
+                 */
+                throw fatal("embedded mode disabled");
+                // consoleHandler = new EmbeddedConsoleHandler(rsp, engine);
+            } else {
+                boolean useReadLine = !rsp.noReadline();
+                if (useReadLine) {
+                    return new JLineConsoleHandler(inStream, outStream, rsp.isSlave());
+                } else {
+                    return new DefaultConsoleHandler(inStream, outStream);
+                }
+            }
+        }
+    }
+
+    /**
+     * The standard R script escapes spaces to "~+~" in "-e" and "-f" commands.
+     */
+    static String unescapeSpace(String input) {
+        return input.replace("~+~", " ");
+    }
+
+    private static final String GET_ECHO = "invisible(getOption('echo'))";
+    private static final String QUIT_EOF = "quit(\"default\", 0L, TRUE)";
+    private static final String GET_PROMPT = "invisible(getOption('prompt'))";
+    private static final String GET_CONTINUE_PROMPT = "invisible(getOption('continue'))";
+
+    /**
+     * The read-eval-print loop, which can take input from a console, command line expression or a
+     * file. There are two ways the repl can terminate:
+     * <ol>
+     * <li>A {@code quit} command is executed successfully.</li>
+     * <li>EOF on the input.</li>
+     * </ol>
+     * In case 2, we must implicitly execute a {@code quit("default, 0L, TRUE} command before
+     * exiting. So,in either case, we never return.
+     */
+    public static int readEvalPrint(PolyglotContext context, ConsoleHandler consoleHandler) {
+        int lastStatus = 0;
+        try {
+            while (true) { // processing inputs
+                boolean doEcho = doEcho(context);
+                consoleHandler.setPrompt(doEcho ? getPrompt(context) : "");
+                try {
+                    String input = consoleHandler.readLine();
+                    if (input == null) {
+                        throw new EOFException();
+                    }
+                    String trInput = input.trim();
+                    if (trInput.equals("") || trInput.charAt(0) == '#') {
+                        // nothing to parse
+                        continue;
+                    }
+
+                    String continuePrompt = null;
+                    StringBuilder sb = new StringBuilder(input);
+                    while (true) { // processing subsequent lines while input is incomplete
+                        lastStatus = 0;
+                        try {
+                            context.eval("R", Source.newBuilder(sb.toString()).interactive().build());
+                        } catch (PolyglotException e) {
+                            if (continuePrompt == null) {
+                                continuePrompt = doEcho ? getContinuePrompt(context) : "";
+                            }
+                            if (e.isIncompleteSource()) {
+                                // read another line of input
+                                consoleHandler.setPrompt(continuePrompt);
+                                String additionalInput = consoleHandler.readLine();
+                                if (additionalInput == null) {
+                                    throw new EOFException();
+                                }
+                                sb.append('\n');
+                                sb.append(additionalInput);
+                                // The only continuation in the while loop
+                                continue;
+                            } else if (e.isExit()) {
+                                // usually from quit
+                                throw new ExitException(e.getExitStatus());
+                            } else if (e.isHostException()) {
+                                // We continue the repl even though the system may be broken
+                                lastStatus = 1;
+                            } else if (e.isGuestException()) {
+                                // drop through to continue REPL and remember last eval was an
+                                // error
+                                lastStatus = 1;
+                            }
+                        }
+                        break;
+                    }
+                } catch (UserInterruptException e) {
+                    // interrupted by ctrl-c
+                }
+            }
+        } catch (EOFException e) {
+            try {
+                context.eval("R", QUIT_EOF);
+            } catch (PolyglotException e2) {
+                if (e2.isExit()) {
+                    return e2.getExitStatus();
+                }
+                throw fatal(e, "error while calling quit");
+            }
+        } catch (ExitException e) {
+            return e.code;
+        }
+        return lastStatus;
+    }
+
+    @SuppressWarnings("serial")
+    private static final class ExitException extends RuntimeException {
+        private final int code;
+
+        ExitException(int code) {
+            this.code = code;
+        }
+    }
+
+    private static boolean doEcho(PolyglotContext context) {
+        try {
+            return context.eval("R", GET_ECHO).asBoolean();
+        } catch (PolyglotException e) {
+            if (e.isExit()) {
+                throw new ExitException(e.getExitStatus());
+            }
+            throw fatal(e, "error while retrieving echo");
+        }
+    }
+
+    private static String getPrompt(PolyglotContext context) {
+        try {
+            return context.eval("R", GET_PROMPT).asString();
+        } catch (PolyglotException e) {
+            if (e.isExit()) {
+                throw new ExitException(e.getExitStatus());
+            }
+            throw fatal(e, "error while retrieving echo");
+        }
+    }
+
+    private static String getContinuePrompt(PolyglotContext context) {
+        try {
+            return context.eval("R", GET_CONTINUE_PROMPT).asString();
+        } catch (PolyglotException e) {
+            if (e.isExit()) {
+                throw new ExitException(e.getExitStatus());
+            }
+            throw fatal(e, "error while retrieving echo");
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RMain.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RMain.java
similarity index 98%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RMain.java
rename to com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RMain.java
index 4a65dc84dbbce67cdc35a1cfb883e4dcd9a32547..347fafa2c36028c0771a3f28cf99ee6eee2a703c 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RMain.java
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RMain.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.shell;
+package com.oracle.truffle.r.launcher;
 
 /**
  * Convenience class that allows the R/Rscript entry to be chosen by an initial argument.
diff --git a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RStartParams.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RStartParams.java
new file mode 100644
index 0000000000000000000000000000000000000000..82de6f3fab306976005bcf555c90b25fc76ceec2
--- /dev/null
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RStartParams.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2016, 2017, 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.launcher;
+
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.EXPR;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.FILE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.INTERACTIVE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.NO_ENVIRON;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.NO_INIT_FILE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.NO_READLINE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.NO_RESTORE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.NO_RESTORE_DATA;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.NO_SAVE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.NO_SITE_FILE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.QUIET;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.RESTORE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.SAVE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.SILENT;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.SLAVE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.VANILLA;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.VERBOSE;
+
+import java.util.List;
+
+/**
+ * Defines startup parameters (that can be customized by embedding apps).
+ */
+public class RStartParams {
+
+    private final boolean quiet;
+    private final boolean slave;
+
+    /**
+     * The setting of this value in GNU R is unusual and not simply based on the value of the
+     * --interactive option, so we do not check the option in
+     * {@link #RStartParams(RCmdOptions, boolean)}, but later in {@code RCommand}.
+     */
+    private final boolean interactive;
+    private final boolean verbose;
+    private final boolean loadSiteFile;
+    private final boolean loadInitFile;
+    private final boolean debugInitFile;
+    private final boolean restoreAction;
+    private final boolean askForSave;
+    private final boolean save;
+    private final boolean noRenviron;
+
+    /**
+     * This is not a configurable option, but it is set on the command line and needs to be stored
+     * somewhere.
+     */
+    private final boolean noReadline;
+
+    /**
+     * Indicates that FastR is running embedded.
+     */
+    private final boolean embedded;
+    private final String fileArgument;
+
+    public RStartParams(RCmdOptions options, boolean embedded) {
+        this.embedded = embedded;
+        this.verbose = options.getBoolean(VERBOSE);
+        this.quiet = options.getBoolean(QUIET) || options.getBoolean(SILENT) || options.getBoolean(SLAVE);
+        this.loadSiteFile = options.getBoolean(NO_SITE_FILE);
+        this.loadInitFile = !embedded && options.getBoolean(NO_INIT_FILE) && !options.getBoolean(VANILLA);
+        this.noRenviron = embedded || options.getBoolean(NO_ENVIRON) || options.getBoolean(VANILLA);
+        this.restoreAction = options.getBoolean(RESTORE) && !(options.getBoolean(NO_RESTORE) || options.getBoolean(NO_RESTORE_DATA) || options.getBoolean(VANILLA));
+        this.noReadline = options.getBoolean(NO_READLINE);
+        this.slave = options.getBoolean(SLAVE);
+
+        /*
+         * GnuR behavior differs from the manual entry for {@code interactive} in that {@code
+         * --interactive} never applies to {@code -e/-f}, only to console input that has been
+         * redirected from a pipe/file etc.
+         */
+        String file = options.getString(FILE);
+        List<String> expressions = options.getStringList(EXPR);
+        if (file != null) {
+            if (expressions != null) {
+                throw RCommand.fatal("cannot use -e with -f or --file");
+            }
+            this.askForSave = false;
+            this.save = false;
+            if (file.equals("-")) {
+                // means stdin, but still implies NO_SAVE
+                file = null;
+            } else {
+                file = RCommand.unescapeSpace(file);
+            }
+            this.interactive = false;
+        } else if (expressions != null) {
+            this.interactive = false;
+            this.askForSave = false;
+            this.save = false;
+        } else {
+            this.interactive = options.getBoolean(INTERACTIVE);
+            if (slave || options.getBoolean(NO_SAVE) || options.getBoolean(VANILLA)) {
+                this.askForSave = false;
+                this.save = false;
+            } else if (options.getBoolean(SAVE)) {
+                this.askForSave = false;
+                this.save = true;
+            } else {
+                this.askForSave = true;
+                this.save = false;
+            }
+        }
+        this.fileArgument = file;
+        this.debugInitFile = false;
+    }
+
+    /**
+     * Only upcalled from native code.
+     */
+    @SuppressWarnings("unused")
+    public static void setParams(boolean quietA, boolean slaveA, boolean interactiveA, boolean verboseA, boolean loadSiteFileA,
+                    boolean loadInitFileA, boolean debugInitFileA, int restoreActionA, int saveActionA, boolean noRenvironA) {
+        assert false : "re-enable setParams";
+        // RStartParams params = RContext.getInstance().getStartParams();
+        // params.setQuiet(quietA);
+        // params.setSlave(slaveA);
+        // params.setInteractive(interactiveA);
+        // params.setVerbose(verboseA);
+        // params.setLoadSiteFile(loadSiteFileA);
+        // params.setLoadInitFile(loadInitFileA);
+        // params.setDebugInitFile(debugInitFileA);
+        // params.setSaveAction(SA_TYPE.values()[saveActionA]);
+        // params.setRestoreAction(SA_TYPE.values()[restoreActionA]);
+        // params.setNoRenviron(noRenvironA);
+    }
+
+    public boolean isQuiet() {
+        return this.quiet;
+    }
+
+    public boolean isSlave() {
+        return slave;
+    }
+
+    public boolean isInteractive() {
+        return this.interactive;
+    }
+
+    public boolean isVerbose() {
+        return this.verbose;
+    }
+
+    public boolean getLoadSiteFile() {
+        return this.loadSiteFile;
+    }
+
+    public boolean loadInitFile() {
+        return this.loadInitFile;
+    }
+
+    public boolean debugInitFile() {
+        return this.debugInitFile;
+    }
+
+    public boolean restore() {
+        return this.restoreAction;
+    }
+
+    public boolean save() {
+        return this.save;
+    }
+
+    public boolean askForSave() {
+        return this.askForSave;
+    }
+
+    public boolean noRenviron() {
+        return this.noRenviron;
+    }
+
+    public boolean noReadline() {
+        return this.noReadline;
+    }
+
+    public boolean isEmbedded() {
+        return embedded;
+    }
+
+    public String getFileArgument() {
+        return fileArgument;
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVersionNumber.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RVersionNumber.java
similarity index 78%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVersionNumber.java
rename to com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RVersionNumber.java
index 4dcd65278766088267f90a7368a449b0761ec549..936a3ee33e0826fc7d9ef1fb0125f07600bdac6c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVersionNumber.java
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RVersionNumber.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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,10 +20,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime;
+package com.oracle.truffle.r.launcher;
 
 /**
- * Defines the R version number and it's release date. Separate from {@link RVersionInfo} to allow
+ * Defines the R version number and it's release date. Separate from {code RVersionInfo} to allow
  * use in {@code static final} fields and to finesse the fact that such fields cannot precede the
  * {@code enum} elements.
  *
@@ -51,4 +51,11 @@ public class RVersionNumber {
     public static void main(String[] args) {
         System.out.printf("R version %s", FULL);
     }
+
+    public static final String LICENSE = "This software is distributed under the terms of the GNU General Public License\n" +
+                    "Version 2, June 1991. The terms of the license are in a file called COPYING\n" +
+                    "which you should have received with this software. A copy of the license can be\n" +
+                    "found at http://www.gnu.org/licenses/gpl-2.0.html.\n" +
+                    "\n" +
+                    "'Share and Enjoy.'";
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RscriptCommand.java
similarity index 67%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java
rename to com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RscriptCommand.java
index 80a8f896dc13a3b93821dc1c44e90d44fcaf83e8..f8373da95848535ccaff51c0dfd611ba48c5cac2 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RscriptCommand.java
@@ -20,24 +20,16 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.shell;
-
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.DEFAULT_PACKAGES;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.EXPR;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.FILE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.HELP;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.NO_RESTORE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.SLAVE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.VERSION;
+package com.oracle.truffle.r.launcher;
 
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
 
-import com.oracle.truffle.r.runtime.RCmdOptions;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.RVersionNumber;
-import com.oracle.truffle.r.runtime.context.ContextInfo;
+import org.graalvm.polyglot.Engine;
+import org.graalvm.polyglot.PolyglotContext;
+
+import com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption;
 
 /**
  * Emulates the (Gnu)Rscript command as precisely as possible. in GnuR, Rscript is a genuine wrapper
@@ -52,38 +44,37 @@ public class RscriptCommand {
         String[] arguments = options.getArguments();
         int resultArgsLength = arguments.length;
         int firstNonOptionArgIndex = options.getFirstNonOptionArgIndex();
-        if (options.getBoolean(HELP)) {
+        if (options.getBoolean(RCmdOption.HELP)) {
             RCmdOptions.printHelpAndExit(RCmdOptions.Client.RSCRIPT);
-        } else if (options.getBoolean(VERSION)) {
+        } else if (options.getBoolean(RCmdOption.VERSION)) {
             printVersionAndExit();
         }
         // Now reformat the args, setting --slave and --no-restore as per the spec
         ArrayList<String> adjArgs = new ArrayList<>(resultArgsLength + 1);
         adjArgs.add(arguments[0]);
         adjArgs.add("--slave");
-        options.setValue(SLAVE, true);
+        options.setValue(RCmdOption.SLAVE, true);
         adjArgs.add("--no-restore");
-        options.setValue(NO_RESTORE, true);
+        options.setValue(RCmdOption.NO_RESTORE, true);
         // Either -e options are set or first non-option arg is a file
-        if (options.getStringList(EXPR) == null) {
+        if (options.getStringList(RCmdOption.EXPR) == null) {
             if (firstNonOptionArgIndex == resultArgsLength) {
                 // does not return
                 RCmdOptions.printHelpAndExit(RCmdOptions.Client.RSCRIPT);
             } else {
                 if (arguments[firstNonOptionArgIndex].startsWith("-")) {
-                    System.out.println("file name is missing");
-                    System.exit(1);
+                    throw RCommand.fatal("file name is missing");
                 }
-                options.setValue(FILE, arguments[firstNonOptionArgIndex]);
+                options.setValue(RCmdOption.FILE, arguments[firstNonOptionArgIndex]);
             }
         }
-        String defaultPackagesArg = options.getString(DEFAULT_PACKAGES);
+        String defaultPackagesArg = options.getString(RCmdOption.DEFAULT_PACKAGES);
         String defaultPackagesEnv = System.getenv("R_DEFAULT_PACKAGES");
         if (defaultPackagesArg == null && defaultPackagesEnv == null) {
             defaultPackagesArg = "datasets,utils,grDevices,graphics,stats";
         }
         if (defaultPackagesEnv == null) {
-            options.setValue(DEFAULT_PACKAGES, defaultPackagesArg);
+            options.setValue(RCmdOption.DEFAULT_PACKAGES, defaultPackagesArg);
         }
         // copy up to non-option args
         int rx = 1;
@@ -91,8 +82,8 @@ public class RscriptCommand {
             adjArgs.add(arguments[rx]);
             rx++;
         }
-        if (options.getString(FILE) != null) {
-            adjArgs.add("--file=" + options.getString(FILE));
+        if (options.getString(RCmdOption.FILE) != null) {
+            adjArgs.add("--file=" + options.getString(RCmdOption.FILE));
             rx++; // skip over file arg
             firstNonOptionArgIndex++;
         }
@@ -107,19 +98,25 @@ public class RscriptCommand {
     }
 
     public static void main(String[] args) {
-        doMain(args, null, true, System.in, System.out);
-        // never returns
-        throw RInternalError.shouldNotReachHere();
+        System.exit(doMain(RCommand.prependCommand(args), null, System.in, System.out, System.err));
+        throw RCommand.fatal("should not reach here");
     }
 
-    public static int doMain(String[] args, String[] env, boolean initial, InputStream inStream, OutputStream outStream) {
+    public static int doMain(String[] args, String[] env, InputStream inStream, OutputStream outStream, OutputStream errStream) {
+        assert env == null : "re-enble environment variables";
         // Since many of the options are shared parse them from an RSCRIPT perspective.
         // Handle --help and --version specially, as they exit.
         RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.RSCRIPT, args, false);
         preprocessRScriptOptions(options);
-        ContextInfo info = RCommand.createContextInfoFromCommandLine(options, false, initial, inStream, outStream, env);
-        return RCommand.readEvalPrint(info.createVM(), info);
 
+        try (Engine engine = Engine.create()) {
+            ConsoleHandler consoleHandler = RCommand.createConsoleHandler(options, false, inStream, outStream);
+            try (PolyglotContext context = engine.newPolyglotContextBuilder().setArguments("R",
+                            options.getArguments()).setIn(consoleHandler.createInputStream()).setOut(outStream).setErr(errStream).build()) {
+                consoleHandler.setPolyglotContext(context);
+                return RCommand.readEvalPrint(context, consoleHandler);
+            }
+        }
     }
 
     private static void printVersionAndExit() {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/StartupTiming.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/StartupTiming.java
similarity index 93%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/StartupTiming.java
rename to com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/StartupTiming.java
index 047702f7b6149ccd2cd8bc4d6b6bb1d301e0b142..866f24988a04696d71228ab86c5d7385222b2f1f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/StartupTiming.java
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/StartupTiming.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime;
+package com.oracle.truffle.r.launcher;
 
 import java.io.PrintStream;
 import java.lang.management.ManagementFactory;
@@ -29,6 +29,7 @@ import java.util.TreeSet;
 import java.util.concurrent.ConcurrentLinkedDeque;
 
 public final class StartupTiming {
+    public static final boolean ENABLED = "true".equals(System.getProperty("StartupTiming"));
 
     private static volatile StartupTiming INSTANCE = null;
 
@@ -58,14 +59,14 @@ public final class StartupTiming {
     }
 
     public static void timestamp(String name) {
-        if (FastROptions.StartupTiming.getBooleanValue()) {
+        if (ENABLED) {
             init();
             INSTANCE.putTimestamp(name);
         }
     }
 
     public static void printSummary() {
-        if (FastROptions.StartupTiming.getBooleanValue()) {
+        if (ENABLED) {
             init();
             INSTANCE.summary(System.out);
         }
@@ -86,7 +87,7 @@ public final class StartupTiming {
             long delta = ts.timestamp - prevTs;
             String msg = ts.name;
 
-            out.println(String.format("%s:\t%s ms\t(%s ms)", msg, relTs, delta));
+            out.printf("%s:\t%s ms\t(%s ms)\n", msg, relTs, delta);
 
             prevTs = ts.timestamp;
         }
@@ -105,6 +106,5 @@ public final class StartupTiming {
         public int compareTo(Timestamp other) {
             return this.timestamp == other.timestamp ? 0 : (this.timestamp < other.timestamp ? -1 : 1);
         }
-
     }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/StringConsoleHandler.java
similarity index 59%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java
rename to com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/StringConsoleHandler.java
index 271b69345df92e9297e4d81391d5fece14eff410..1327a8162997473ccaa032d9b4f27886e83d5f18 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/StringConsoleHandler.java
@@ -20,46 +20,24 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.shell;
+package com.oracle.truffle.r.launcher;
 
 import java.io.OutputStream;
 import java.io.PrintStream;
 import java.util.List;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
-import com.oracle.truffle.r.runtime.context.RContext;
-
 class StringConsoleHandler extends ConsoleHandler {
     private final PrintStream output;
     private final List<String> lines;
-    private final String inputDescription;
     private String prompt;
     private int currentLine;
-    private RContext ctx;
 
-    StringConsoleHandler(List<String> lines, OutputStream output, String inputDescription) {
+    StringConsoleHandler(List<String> lines, OutputStream output) {
         this.lines = lines;
         this.output = output instanceof PrintStream ? (PrintStream) output : new PrintStream(output);
-        this.inputDescription = inputDescription;
-    }
-
-    @Override
-    @TruffleBoundary
-    public void println(String s) {
-        output.println(s);
-        output.flush();
-    }
-
-    @Override
-    @TruffleBoundary
-    public void print(String s) {
-        output.print(s);
-        output.flush();
     }
 
     @Override
-    @TruffleBoundary
     public String readLine() {
         if (currentLine < lines.size()) {
             if (prompt != null) {
@@ -73,46 +51,7 @@ class StringConsoleHandler extends ConsoleHandler {
     }
 
     @Override
-    public boolean isInteractive() {
-        return false;
-    }
-
-    @Override
-    @TruffleBoundary
-    public void printErrorln(String s) {
-        println(s);
-    }
-
-    @Override
-    @TruffleBoundary
-    public void printError(String s) {
-        print(s);
-    }
-
-    @Override
-    @TruffleBoundary
-    public String getPrompt() {
-        return prompt;
-    }
-
-    @Override
-    @TruffleBoundary
     public void setPrompt(String prompt) {
         this.prompt = prompt;
     }
-
-    @Override
-    public String getInputDescription() {
-        return inputDescription;
-    }
-
-    @Override
-    public void setContext(RContext ctx) {
-        this.ctx = ctx;
-    }
-
-    @Override
-    public RContext getContext() {
-        return ctx;
-    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java
index 86b2f791bb7d4dbf9a075bce6171d28f924a47a9..e2777a22970298172a63991cce695976081c0c0c 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java
@@ -14,11 +14,11 @@ package com.oracle.truffle.r.library.utils;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 // Translated from GnuR: library/utils/io.c
@@ -33,10 +33,10 @@ public abstract class Menu extends RExternalBuiltinNode.Arg1 {
     @Specialization
     @TruffleBoundary
     protected int menu(RAbstractStringVector choices) {
-        ConsoleHandler ch = RContext.getInstance().getConsoleHandler();
+        ConsoleIO console = RContext.getInstance().getConsole();
         int first = choices.getLength() + 1;
-        ch.print("Selection: ");
-        String response = ch.readLine().trim();
+        console.print("Selection: ");
+        String response = console.readLine().trim();
         if (response.length() > 0) {
             if (Character.isDigit(response.charAt(0))) {
                 try {
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 e0e20dff6d6b9a96aeb3575dd524ada71e34dfaf..c2b9de1ec3ba147b84d5cc9f55bae83ac75dddb5 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
@@ -130,8 +130,6 @@ import com.oracle.truffle.r.nodes.builtin.fastr.FastRTry;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRTryNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastrDqrls;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastrDqrlsNodeGen;
-import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
-import com.oracle.truffle.r.nodes.unary.UnaryArithmeticSpecial;
 import com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmem;
 import com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmemNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmemShow;
@@ -140,6 +138,8 @@ import com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmemSnapshot;
 import com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmemSnapshotNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmemSource;
 import com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmemSourceNodeGen;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticSpecial;
 import com.oracle.truffle.r.nodes.unary.UnaryNotNode;
 import com.oracle.truffle.r.nodes.unary.UnaryNotNodeGen;
 import com.oracle.truffle.r.runtime.RVisibility;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
index 55d968d8d5e47747aef3c697dfda3622a207b1e8..2b58ec4749cd083200e13849baf26ea8b2a1bb9b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
@@ -110,7 +110,7 @@ public class BrowserFunctions {
             } else {
                 callerString = RContext.getRRuntimeASTAccess().getCallerSource(caller);
             }
-            RContext.getInstance().getConsoleHandler().printf("Called from: %s%n", callerString);
+            RContext.getInstance().getConsole().printf("Called from: %s%n", callerString);
 
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java
index 8a80bf7e438c3cc9ee71ec83529aebd16dbee763..015ffea85340b0fbdc899feed463a5a35a43a9dd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java
@@ -83,7 +83,7 @@ public abstract class Capabilities extends RBuiltinNode.Arg0 {
             boolean value = c.defValue;
             switch (c) {
                 case cledit:
-                    value = RContext.getInstance().isInteractive() && !RContext.getInstance().getStartParams().getNoReadline();
+                    value = RContext.getInstance().isInteractive() && !RContext.getInstance().getStartParams().noReadline();
                     break;
             }
             data[c.ordinal()] = RRuntime.asLogical(value);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java
index 9c6f24083b497de96d5c22cfa60eee2b21e33741..947fcb54b00fe9c8018076959f57931e53022df3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java
@@ -39,7 +39,7 @@ public abstract class CommandArgs extends RBuiltinNode.Arg0 {
     @Specialization
     @TruffleBoundary
     protected RStringVector commandArgs() {
-        String[] s = RContext.getInstance().getStartParams().getArguments();
+        String[] s = RContext.getInstance().getEnv().getApplicationArguments();
         return RDataFactory.createStringVector(s, RDataFactory.COMPLETE_VECTOR);
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
index f731b65357b7496f462c01b3b3ae585accbc0a4b..042b20305cc10094df24f1e9af25b20d43536301 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
@@ -69,8 +69,8 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -1034,7 +1034,7 @@ public class FileFunctions {
         @Specialization
         @TruffleBoundary
         protected RNull show(RAbstractStringVector files, RAbstractStringVector header, RAbstractStringVector title, boolean deleteFile, @SuppressWarnings("unused") String pager) {
-            ConsoleHandler console = RContext.getInstance().getConsoleHandler();
+            ConsoleIO console = RContext.getInstance().getConsole();
             for (int i = 0; i < title.getLength(); i++) {
                 console.println("==== " + title.getDataAt(i) + " ====");
             }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java
index ef734b838ba875c3bec6bb12c9b8be9ba28554fb..ed948ca5730405fa34d8d76ab362d11111af51b7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -34,6 +35,7 @@ import com.oracle.truffle.r.runtime.context.RContext;
 @RBuiltin(name = "interactive", kind = PRIMITIVE, parameterNames = {}, behavior = READS_STATE)
 public abstract class Interactive extends RBuiltinNode.Arg0 {
     @Specialization
+    @TruffleBoundary
     protected byte interactive() {
         return RRuntime.asLogical(RContext.getInstance().isInteractive());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java
index b98566310e2335a0f3afe3a2f291415913467458..4330226b6c428309983f21f97f9d17c1c67c9926 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java
@@ -30,9 +30,9 @@ import java.io.IOException;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.launcher.RVersionNumber;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.conn.StdConnections;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -44,7 +44,7 @@ public abstract class License extends RBuiltinNode.Arg0 {
     @TruffleBoundary
     protected Object license() {
         try {
-            StdConnections.getStdout().writeString(RRuntime.LICENSE, true);
+            StdConnections.getStdout().writeString(RVersionNumber.LICENSE, true);
         } catch (IOException ex) {
             throw error(RError.Message.GENERIC, ex.getMessage());
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
index 9d9aa1803a2339befd7fb842563c88c81b026a7b..015e798f80e183440ee7f6c1efc25a05a8bfb595 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
@@ -24,11 +24,10 @@ import com.oracle.truffle.r.runtime.RCleanUp;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.RStartParams;
-import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.gnur.SA_TYPE;
 
 @RBuiltin(name = "quit", visibility = OFF, kind = INTERNAL, parameterNames = {"save", "status", "runLast"}, behavior = COMPLEX)
 public abstract class Quit extends RBuiltinNode.Arg3 {
@@ -41,9 +40,9 @@ public abstract class Quit extends RBuiltinNode.Arg3 {
     }
 
     private SA_TYPE checkSaveValue(String save) throws RError {
-        for (String saveValue : SA_TYPE.SAVE_VALUES) {
-            if (saveValue.equals(save)) {
-                return SA_TYPE.fromString(save);
+        for (SA_TYPE saveValue : SA_TYPE.values()) {
+            if (saveValue.getName().equals(save)) {
+                return saveValue;
             }
         }
         throw error(RError.Message.QUIT_SAVE);
@@ -57,8 +56,8 @@ public abstract class Quit extends RBuiltinNode.Arg3 {
             warning(RError.Message.BROWSER_QUIT);
             return RNull.instance;
         }
-        RStartParams.SA_TYPE ask = checkSaveValue(save);
-        if (ask == SA_TYPE.SAVEASK && !RContext.getInstance().getConsoleHandler().isInteractive()) {
+        SA_TYPE ask = checkSaveValue(save);
+        if (ask == SA_TYPE.SAVEASK && !RContext.getInstance().isInteractive()) {
             warning(RError.Message.QUIT_ASK_INTERACTIVE);
         }
         if (status == RRuntime.INT_NA) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
index f5d72cb3b60930338de975a7ebcd8e7a0a3e3862..c83f0c38996e3e777ea05c6bf968e6afd553aea7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
@@ -29,8 +29,8 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "readline", kind = INTERNAL, parameterNames = "prompt", behavior = IO)
@@ -47,7 +47,7 @@ public abstract class Readline extends RBuiltinNode.Arg1 {
         if (!RContext.getInstance().isInteractive()) {
             return "";
         }
-        ConsoleHandler consoleHandler = RContext.getInstance().getConsoleHandler();
+        ConsoleIO consoleHandler = RContext.getInstance().getConsole();
         String savedPrompt = consoleHandler.getPrompt();
         consoleHandler.setPrompt(prompt.getDataAt(0));
         String input = consoleHandler.readLine();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
index 4c6d296d81400458bd6b2c5491cb144bc1e6d1a6..930598b4ff7afe1ba1dadb92d59fc65d468e6cf7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
@@ -39,11 +39,11 @@ import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.launcher.RCmdOptions.Client;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RChannel;
-import com.oracle.truffle.r.runtime.RCmdOptions.Client;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RSource;
@@ -51,6 +51,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.ContextInfo;
 import com.oracle.truffle.r.runtime.context.EvalThread;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntVector;
@@ -337,7 +338,9 @@ public class FastRContext {
     }
 
     private static ContextInfo createContextInfo(RContext.ContextKind contextKind) {
-        return ContextInfo.createNoRestore(Client.RSCRIPT, null, contextKind, RContext.getInstance(), RContext.getInstance().getConsoleHandler());
+        RContext context = RContext.getInstance();
+        ConsoleIO console = context.getConsole();
+        return ContextInfo.createNoRestore(Client.RSCRIPT, null, contextKind, context, console.getStdin(), console.getStdout(), console.getStderr());
     }
 
     @RBuiltin(name = ".fastr.channel.create", kind = PRIMITIVE, parameterNames = {"key"}, behavior = COMPLEX)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java
index b7179ade00d55bd5bad8fd8e03c96728bb9837a9..eb1009cec1c6f30031f743a6aa8049a0346a5668 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java
@@ -52,7 +52,7 @@ public abstract class FastRStackTrace extends RBuiltinNode.Arg1 {
     @TruffleBoundary
     @Specialization
     protected RNull printStackTrace(boolean printFrameContents) {
-        RContext.getInstance().getConsoleHandler().print(Utils.createStackTrace(printFrameContents));
+        RContext.getInstance().getConsole().print(Utils.createStackTrace(printFrameContents));
         return RNull.instance;
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java
index a39f869d19371c557d545744c2b9d36f315a4699..fc1ac13ee88d750bbf5094eed0956095084bec32 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java
@@ -27,6 +27,7 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.launcher.ConsoleHandler;
 import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
 import com.oracle.truffle.r.runtime.JumpToTopLevelException;
 import com.oracle.truffle.r.runtime.RArguments;
@@ -37,10 +38,10 @@ import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.RSrcref;
 import com.oracle.truffle.r.runtime.ReturnException;
 import com.oracle.truffle.r.runtime.Utils;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.Engine.IncompleteSourceException;
 import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -78,7 +79,7 @@ public abstract class BrowserInteractNode extends Node {
     protected int interact(VirtualFrame frame, RCaller caller) {
         CompilerDirectives.transferToInterpreter();
         MaterializedFrame mFrame = frame.materialize();
-        ConsoleHandler ch = RContext.getInstance().getConsoleHandler();
+        ConsoleIO ch = RContext.getInstance().getConsole();
         BrowserState browserState = RContext.getInstance().stateInstrumentation.getBrowserState();
         String savedPrompt = ch.getPrompt();
         RFunction callerFunction = RArguments.getFunction(frame);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
index b18018abf0663f8b5ad7b81e5f1aa4b9b120046a..f9722c8fc4380e0083e8c33f18602def39610279 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
@@ -42,6 +42,7 @@ import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.api.utilities.CyclicAssumption;
+import com.oracle.truffle.r.launcher.ConsoleHandler;
 import com.oracle.truffle.r.nodes.control.AbstractLoopNode;
 import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode;
 import com.oracle.truffle.r.nodes.instrumentation.RInstrumentation;
@@ -52,8 +53,8 @@ import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.conn.StdConnections;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
@@ -525,7 +526,7 @@ public class DebugHandling {
 
     @TruffleBoundary
     private static void printNode(Node node, boolean startFunction) {
-        ConsoleHandler consoleHandler = RContext.getInstance().getConsoleHandler();
+        ConsoleIO console = RContext.getInstance().getConsole();
         /*
          * N.B. It would seem that GnuR does a deparse that because, e.g., a function that ends with
          * } without a preceding newline prints with one and indentation is standardized.
@@ -534,17 +535,17 @@ public class DebugHandling {
         boolean curly = RSyntaxCall.isCallTo((RSyntaxElement) node, "{");
 
         if (startFunction && !curly) {
-            consoleHandler.print("debug: ");
+            console.print("debug: ");
         } else {
             SourceSection source = ((RBaseNode) node).asRSyntaxNode().getSourceSection();
             String path = RSource.getPath(source.getSource());
             if (path == null) {
                 path = "";
             }
-            consoleHandler.print("debug at " + path + "#" + source.getStartLine() + ": ");
+            console.print("debug at " + path + "#" + source.getStartLine() + ": ");
         }
-        consoleHandler.print(RDeparse.deparseSyntaxElement(rNode.asRSyntaxNode()));
-        consoleHandler.print("\n");
+        console.print(RDeparse.deparseSyntaxElement(rNode.asRSyntaxNode()));
+        console.print("\n");
     }
 
     private static class StatementEventListener extends InteractingDebugEventListener {
diff --git a/com.oracle.truffle.r.release/src/R_launcher b/com.oracle.truffle.r.release/src/R_launcher
index d72f738599c9164737c3bd8dbbbcaa0c74320847..4e9262f84d7dadf274ad763083e713807f4a56ce 100644
--- a/com.oracle.truffle.r.release/src/R_launcher
+++ b/com.oracle.truffle.r.release/src/R_launcher
@@ -12,4 +12,4 @@ do
   esac
 done
 
-exec java "${JAVA_ARGS[@]}" -cp %%CLASSPATH com.oracle.truffle.r.engine.shell.RCommand "${PROGRAM_ARGS[@]}"
+exec java "${JAVA_ARGS[@]}" -cp %%CLASSPATH com.oracle.truffle.r.launchers.RCommand "${PROGRAM_ARGS[@]}"
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ExitException.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ExitException.java
index ad415a724c20879db8ddd6be38eecba19cf8f05a..87bd008ed805cd982c6c1e19de87ea8f9bc4398b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ExitException.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ExitException.java
@@ -33,9 +33,11 @@ import com.oracle.truffle.api.nodes.Node;
 public class ExitException extends RuntimeException implements TruffleException {
     private static final long serialVersionUID = 1L;
     private final int status;
+    private final boolean saveHistory;
 
-    public ExitException(int status) {
+    public ExitException(int status, boolean saveHistory) {
         this.status = status;
+        this.saveHistory = saveHistory;
     }
 
     public int getStatus() {
@@ -56,4 +58,8 @@ public class ExitException extends RuntimeException implements TruffleException
     public int getExitStatus() {
         return status;
     }
+
+    public boolean saveHistory() {
+        return saveHistory;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java
index 436e252e5d8d79ff47af6ab934fa9aeffa0e6275..da32bbc87d789bc01c315f9acc583553cb2c9f70 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java
@@ -13,10 +13,11 @@ package com.oracle.truffle.r.runtime;
 
 import java.util.ArrayList;
 
-import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
+import com.oracle.truffle.r.launcher.RStartParams;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+import com.oracle.truffle.r.runtime.gnur.SA_TYPE;
 import com.oracle.truffle.r.runtime.instrument.InstrumentationState;
 
 public class RCleanUp {
@@ -35,42 +36,39 @@ public class RCleanUp {
         }
     }
 
-    public static void stdCleanUp(final SA_TYPE saveActionIn, int status, boolean runLast) {
+    public static void stdCleanUp(SA_TYPE saveActionIn, int status, boolean runLast) {
         // Output is not diverted to sink
-        ConsoleHandler consoleHandler = RContext.getInstance().getConsoleHandler();
+        ConsoleIO console = RContext.getInstance().getConsole();
         SA_TYPE saveAction = saveActionIn;
-        if (saveAction == SA_TYPE.DEFAULT) {
-            saveAction = RContext.getInstance().getStartParams().getSaveAction();
+        if (saveAction == SA_TYPE.DEFAULT || (saveAction == SA_TYPE.SAVEASK && !RContext.getInstance().isInteractive())) {
+            RStartParams params = RContext.getInstance().getStartParams();
+            saveAction = params.askForSave() ? SA_TYPE.SAVEASK : params.save() ? SA_TYPE.SAVE : SA_TYPE.NOSAVE;
         }
-        if (saveAction == SA_TYPE.SAVEASK) {
-            if (consoleHandler.isInteractive()) {
-                W: while (true) {
-                    consoleHandler.setPrompt("");
-                    consoleHandler.print("Save workspace image? [y/n/c]: ");
-                    String response = consoleHandler.readLine();
-                    if (response == null) {
+        if (saveAction == SA_TYPE.SAVEASK && RContext.getInstance().isInteractive()) {
+            W: while (true) {
+                console.setPrompt("");
+                console.print("Save workspace image? [y/n/c]: ");
+                String response = console.readLine();
+                if (response == null) {
+                    saveAction = SA_TYPE.NOSAVE;
+                    break;
+                }
+                if (response.length() == 0) {
+                    continue;
+                }
+                switch (response.charAt(0)) {
+                    case 'c':
+                        console.setPrompt("> ");
+                        throw new JumpToTopLevelException();
+                    case 'y':
+                        saveAction = SA_TYPE.SAVE;
+                        break W;
+                    case 'n':
                         saveAction = SA_TYPE.NOSAVE;
-                        break;
-                    }
-                    if (response.length() == 0) {
+                        break W;
+                    default:
                         continue;
-                    }
-                    switch (response.charAt(0)) {
-                        case 'c':
-                            consoleHandler.setPrompt("> ");
-                            throw new JumpToTopLevelException();
-                        case 'y':
-                            saveAction = SA_TYPE.SAVE;
-                            break W;
-                        case 'n':
-                            saveAction = SA_TYPE.NOSAVE;
-                            break W;
-                        default:
-                            continue;
-                    }
                 }
-            } else {
-                saveAction = RContext.getInstance().getStartParams().getSaveAction();
             }
         }
 
@@ -84,18 +82,16 @@ public class RCleanUp {
                  * we save always
                  */
                 RContext.getEngine().checkAndRunStartupShutdownFunction("sys.save.image", new String[]{"\".RData\""});
-                RContext.getInstance().getConsoleHandler().flushHistory();
+                String history = RContext.getInstance().getConsole().getHistory();
+                // TODO: write out history
                 break;
-
             case NOSAVE:
                 if (runLast) {
                     runDotLast();
                 }
                 break;
-
-            case SUICIDE:
             default:
-
+                throw RInternalError.shouldNotReachHere();
         }
         for (InstrumentationState.CleanupHandler cleanupHandler : cleanupHandlers) {
             try {
@@ -105,8 +101,7 @@ public class RCleanUp {
             }
         }
         // TODO run exit finalizers (FFI) (this should happen in the FFI context beforeDestroy)
-        throw new ExitException(status);
-
+        throw new ExitException(status, false);
     }
 
     private static void runDotLast() {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
index 5d7338bd0c0ec7ca1132dc7391f1f12f6c0cd869..232be3ac2c2b6d253c73b978cd4af0a56b4b8fee 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
@@ -22,8 +22,6 @@
  */
 package com.oracle.truffle.r.runtime;
 
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.DEFAULT_PACKAGES;
-
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
@@ -40,6 +38,8 @@ import java.util.Map;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.launcher.RCmdOptions;
+import com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
 
@@ -62,9 +62,9 @@ public final class REnvVars implements RContext.ContextState {
     public RContext.ContextState initialize(RContext context) {
         // explicit environment settings in nested contexts must be installed first
         checkExplicitEnvSettings(context);
-        RCmdOptions cmdOptions = context.getStartParams().getRCmdOptions();
+        RCmdOptions cmdOptions = context.getCmdOptions();
         // If running Rscript, R_DEFAULT_PACKAGES may need to be set
-        String defaultPackages = cmdOptions.getString(DEFAULT_PACKAGES);
+        String defaultPackages = cmdOptions.getString(RCmdOption.DEFAULT_PACKAGES);
         if (defaultPackages != null) {
             envVars.put("R_DEFAULT_PACKAGES", defaultPackages);
         }
@@ -87,7 +87,7 @@ public final class REnvVars implements RContext.ContextState {
             // This gets expanded by R code in the system profile
         }
 
-        if (!context.getStartParams().getNoRenviron()) {
+        if (!context.getStartParams().noRenviron()) {
             String siteFile = envVars.get("R_ENVIRON");
             if (siteFile == null) {
                 siteFile = fileSystem.getPath(rHome, "etc", "Renviron.site").toString();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 9ad7956f955b193a99bc2bb774560f42f282577c..323cb26189314b6e9bdf1cf53d829923ae0660b3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -20,10 +20,12 @@ import com.oracle.truffle.api.TruffleException;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
  * A facade for handling errors. This class extends {@link RuntimeException} so that it can be
@@ -81,10 +83,19 @@ public final class RError extends RuntimeException implements TruffleException {
         protected RBaseNode getErrorContext() {
             return this;
         }
+
+        @Override
+        public SourceSection getEncapsulatingSourceSection() {
+            return RSyntaxNode.INTERNAL;
+        }
+
+        @Override
+        public SourceSection getSourceSection() {
+            return RSyntaxNode.INTERNAL;
+        }
     }
 
     private static final class ErrorContextImpl extends ErrorContext {
-
     }
 
     public static ErrorContext contextForBuiltin(RBuiltin builtin) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
index f3545d4004a4cbb9ab6ae3492ac0a44d314e2151..9dea6c4d9ca99f7cc2762395077f221ac7f3f815 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
@@ -541,7 +541,7 @@ public class RErrorHandling {
             }
         }
 
-        if (RContext.getInstance().getConsoleHandler().isInteractive() || errorExpr != RNull.instance) {
+        if (RContext.getInstance().isInteractive() || errorExpr != RNull.instance) {
             Object trace = Utils.createTraceback(0);
             try {
                 REnvironment env = RContext.getInstance().stateREnvironment.getBaseEnv();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalError.java
index 9de6bc3647a9b70e07ccf2ce8b404769b6dbb4e1..ccab1b58ed13bf1433c194847bdf4809cfb8e2b7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalError.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.runtime;
 import java.io.BufferedWriter;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.OutputStream;
 import java.io.PrintStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -38,7 +39,7 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.TruffleException;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
+import com.oracle.truffle.r.launcher.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext;
 
 /**
@@ -149,16 +150,16 @@ public final class RInternalError extends Error implements TruffleException {
     }
 
     @TruffleBoundary
-    public static void reportErrorAndConsoleLog(Throwable throwable, ConsoleHandler consoleHandler, int contextId) {
-        reportError(throwable, consoleHandler, contextId);
+    public static void reportErrorAndConsoleLog(Throwable throwable, int contextId) {
+        reportError(throwable, contextId);
     }
 
     @TruffleBoundary
     public static void reportError(Throwable throwable) {
-        reportError(throwable, null, 0);
+        reportError(throwable, 0);
     }
 
-    private static void reportError(Throwable throwable, ConsoleHandler consoleHandler, int contextId) {
+    private static void reportError(Throwable throwable, int contextId) {
         Throwable t = throwable;
         if (FastROptions.PrintErrorStacktracesToFile.getBooleanValue() || FastROptions.PrintErrorStacktraces.getBooleanValue()) {
 
@@ -190,13 +191,11 @@ public final class RInternalError extends Error implements TruffleException {
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
+                String message = t instanceof RInternalError && t.getMessage() != null && !t.getMessage().isEmpty() ? t.getMessage() : "internal error: " + t.getClass().getSimpleName();
+                System.out.println(message + " (see fastr_errors.log" + suffix + ")");
                 if (RContext.isEmbedded()) {
                     Utils.rSuicide("FastR internal error");
                 }
-                if (consoleHandler != null) {
-                    String message = t instanceof RInternalError && t.getMessage() != null && !t.getMessage().isEmpty() ? t.getMessage() : "internal error: " + t.getClass().getSimpleName();
-                    consoleHandler.println(message + " (see fastr_errors.log" + suffix + ")");
-                }
             }
         }
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java
index 8d5c70e8c0b217218f24bdf35ff30b62e553c64f..a9d0e789a7934ef2c0d2f7b9ab447e34745e29ae 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java
@@ -19,6 +19,7 @@ import java.util.Map.Entry;
 import java.util.Set;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.launcher.RStartParams;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -159,7 +160,7 @@ public class ROptions {
         map.put("continue", RDataFactory.createSharedStringVectorFromScalar("+ "));
         map.put("deparse.cutoff", RDataFactory.createSharedIntVectorFromScalar(60));
         map.put("digits", RDataFactory.createSharedIntVectorFromScalar(7));
-        map.put("echo", RDataFactory.createSharedLogicalVectorFromScalar(startParams.getSlave() ? false : true));
+        map.put("echo", RDataFactory.createSharedLogicalVectorFromScalar(startParams.isSlave() ? false : true));
         map.put("encoding", RDataFactory.createSharedStringVectorFromScalar("native.enc"));
         map.put("expressions", RDataFactory.createSharedIntVectorFromScalar(5000));
         boolean keepPkgSource = optionFromEnvVar("R_KEEP_PKG_SOURCE", envVars);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java
index 80a9f3cad82eed5af15ce628fe23d50d00074f97..9c7682b52345665cefef553f175f2c8af9285a23 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java
@@ -66,7 +66,7 @@ public final class RProfile implements RContext.ContextState {
             }
         }
 
-        if (context.getStartParams().getLoadInitFile()) {
+        if (context.getStartParams().loadInitFile()) {
             String userProfilePath = envVars.get("R_PROFILE_USER");
             if (userProfilePath == null) {
                 String dotRenviron = ".Rprofile";
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
index 841c71215df6c4d8729e213fab34712f8c8dd241..27f169e4e932b40e4455e1d399d66bc35e891f40 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
@@ -21,6 +21,7 @@ import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.launcher.RVersionNumber;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDouble;
@@ -63,13 +64,6 @@ public class RRuntime {
         "\n" +
         "Type 'q()' to quit R.";
 
-    public static final String LICENSE =
-        "This software is distributed under the terms of the GNU General Public License\n" +
-        "Version 2, June 1991. The terms of the license are in a file called COPYING\n" +
-        "which you should have received with this software. A copy of the license can be\n" +
-        "found at http://www.gnu.org/licenses/gpl-2.0.html.\n" +
-        "\n" +
-        "'Share and Enjoy.'";
     //@formatter:on
 
     public static final String R_APP_MIME = "application/x-r";
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
index 15f8e5cea2f315158cc6231530c931ac262d6f7f..d2a825e22b1a9d98e634238dbd4188d45a5d18a3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
@@ -44,6 +44,7 @@ import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.launcher.RVersionNumber;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RStartParams.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RStartParams.java
deleted file mode 100644
index cdadca6a121452237e13e3aa3eb0059b9ac7c9d6..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RStartParams.java
+++ /dev/null
@@ -1,264 +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-2015, The R Core Team
- * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.runtime;
-
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.NO_ENVIRON;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.NO_INIT_FILE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.NO_READLINE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.NO_RESTORE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.NO_RESTORE_DATA;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.NO_SAVE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.NO_SITE_FILE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.QUIET;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.RESTORE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.SAVE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.SILENT;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.SLAVE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.VANILLA;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.VERBOSE;
-
-import com.oracle.truffle.r.runtime.context.RContext;
-
-/**
- * Defines startup parameters (that can be customized by embedding apps).
- */
-public class RStartParams {
-
-    public enum SA_TYPE {
-        NORESTORE(null),
-        RESTORE(null),
-        DEFAULT("default"),
-        NOSAVE("no"),
-        SAVE("yes"),
-        SAVEASK("ask"),
-        SUICIDE(null);
-
-        private String userName;
-
-        SA_TYPE(String userName) {
-            this.userName = userName;
-        }
-
-        public static final String[] SAVE_VALUES = new String[]{"yes", "no", "ask", "default"};
-
-        public String getUserName() {
-            return userName;
-        }
-
-        public static SA_TYPE fromString(String s) {
-            for (SA_TYPE t : values()) {
-                if (t.userName != null && t.userName.equals(s)) {
-                    return t;
-                }
-            }
-            return null;
-        }
-    }
-
-    private boolean quiet;
-    private boolean slave;
-    /**
-     * The setting of this value in GNU R is unusual and not simply based on the value of the
-     * --interactive option, so we do not check the option in
-     * {@link #RStartParams(RCmdOptions, boolean)}, but later in {@code RCommand}.
-     */
-    private boolean interactive = true;
-    private boolean verbose;
-    private boolean loadSiteFile = true;
-    private boolean loadInitFile = true;
-    private boolean debugInitFile;
-    private SA_TYPE restoreAction = SA_TYPE.RESTORE;
-    private SA_TYPE saveAction = SA_TYPE.SAVEASK;
-    private boolean noRenviron;
-    /**
-     * This is not a configurable option, but it is set on the command line and needs to be stored
-     * somewhere.
-     */
-    private boolean noReadline;
-
-    /**
-     * The result from parsing the command line options.
-     */
-    private final RCmdOptions cmdOptions;
-
-    /**
-     * Indicates that FastR is running embedded.
-     */
-    private boolean embedded;
-
-    public RStartParams(RCmdOptions options, boolean embedded) {
-        this.cmdOptions = options;
-        this.embedded = embedded;
-        if (options.getBoolean(VERBOSE)) {
-            this.verbose = true;
-        }
-        if (options.getBoolean(QUIET) || options.getBoolean(SILENT)) {
-            this.quiet = true;
-        }
-        if (options.getBoolean(NO_SITE_FILE)) {
-            this.loadSiteFile = false;
-        }
-        if (options.getBoolean(NO_INIT_FILE)) {
-            this.loadInitFile = false;
-        }
-        if (options.getBoolean(NO_ENVIRON)) {
-            this.noRenviron = true;
-        }
-        if (options.getBoolean(SAVE)) {
-            this.saveAction = SA_TYPE.SAVE;
-        }
-        if (options.getBoolean(NO_SAVE)) {
-            this.saveAction = SA_TYPE.NOSAVE;
-        }
-        if (options.getBoolean(RESTORE)) {
-            this.restoreAction = SA_TYPE.RESTORE;
-        }
-        if (options.getBoolean(NO_RESTORE) || options.getBoolean(NO_RESTORE_DATA)) {
-            this.restoreAction = SA_TYPE.NORESTORE;
-        }
-        if (options.getBoolean(NO_READLINE)) {
-            this.noReadline = true;
-        }
-        if (options.getBoolean(SLAVE)) {
-            this.slave = true;
-            this.quiet = true;
-            this.setSaveAction(SA_TYPE.NOSAVE);
-        }
-
-        if (options.getBoolean(VANILLA)) {
-            this.setSaveAction(SA_TYPE.NOSAVE);
-            this.noRenviron = true;
-            this.loadInitFile = false;
-            this.restoreAction = SA_TYPE.NORESTORE;
-        }
-    }
-
-    /**
-     * Only upcalled from native code.
-     */
-    @SuppressWarnings("unused")
-    private static void setParams(boolean quietA, boolean slaveA, boolean interactiveA, boolean verboseA, boolean loadSiteFileA,
-                    boolean loadInitFileA, boolean debugInitFileA, int restoreActionA,
-                    int saveActionA, boolean noRenvironA) {
-        RStartParams params = RContext.getInstance().getStartParams();
-        params.setQuiet(quietA);
-        params.setSlave(slaveA);
-        params.setInteractive(interactiveA);
-        params.setVerbose(verboseA);
-        params.setLoadSiteFile(loadSiteFileA);
-        params.setLoadInitFile(loadInitFileA);
-        params.setDebugInitFile(debugInitFileA);
-        params.setSaveAction(SA_TYPE.values()[saveActionA]);
-        params.setRestoreAction(SA_TYPE.values()[restoreActionA]);
-        params.setNoRenviron(noRenvironA);
-    }
-
-    public boolean getQuiet() {
-        return this.quiet;
-    }
-
-    public void setQuiet(boolean b) {
-        this.quiet = b;
-    }
-
-    public boolean getSlave() {
-        return slave;
-    }
-
-    public void setSlave(boolean b) {
-        this.slave = b;
-    }
-
-    public boolean getInteractive() {
-        return this.interactive;
-    }
-
-    public void setInteractive(boolean b) {
-        this.interactive = b;
-    }
-
-    public boolean getVerbose() {
-        return this.verbose;
-    }
-
-    public void setVerbose(boolean b) {
-        this.verbose = b;
-    }
-
-    public boolean getLoadSiteFile() {
-        return this.loadSiteFile;
-    }
-
-    public void setLoadSiteFile(boolean b) {
-        this.loadSiteFile = b;
-    }
-
-    public boolean getLoadInitFile() {
-        return this.loadInitFile;
-    }
-
-    public void setLoadInitFile(boolean b) {
-        this.loadInitFile = b;
-    }
-
-    public boolean getDebugInitFile() {
-        return this.debugInitFile;
-    }
-
-    public void setDebugInitFile(boolean b) {
-        this.debugInitFile = b;
-    }
-
-    public SA_TYPE getRestoreAction() {
-        return this.restoreAction;
-    }
-
-    public void setRestoreAction(SA_TYPE a) {
-        this.restoreAction = a;
-    }
-
-    public SA_TYPE getSaveAction() {
-        return this.saveAction;
-    }
-
-    public void setSaveAction(SA_TYPE a) {
-        this.saveAction = a;
-    }
-
-    public boolean getNoRenviron() {
-        return this.noRenviron;
-    }
-
-    public void setNoRenviron(boolean b) {
-        this.noRenviron = b;
-    }
-
-    public boolean getNoReadline() {
-        return this.noReadline;
-    }
-
-    public RCmdOptions getRCmdOptions() {
-        return cmdOptions;
-    }
-
-    public String[] getArguments() {
-        return cmdOptions.getArguments();
-    }
-
-    public void setEmbedded() {
-        this.embedded = true;
-    }
-
-    public boolean getEmbedded() {
-        return embedded;
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVersionInfo.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVersionInfo.java
index d114d0ac2b9de73b6b437358ddadd8a49eae5e05..2a397016bde4e98eec90ba54b59a7e1c47022f0e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVersionInfo.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVersionInfo.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.runtime;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.r.launcher.RVersionNumber;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI.UtsName;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
index 174c4c56c6c0fecea9aa0966809facb587ff91a7..8442ad395aa361f51de619149eba01d706a3ba95 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
@@ -52,9 +52,10 @@ import com.oracle.truffle.api.nodes.GraphPrintVisitor;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.launcher.ConsoleHandler;
 import com.oracle.truffle.r.runtime.conn.StdConnections;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
@@ -204,7 +205,7 @@ public final class Utils {
      */
     public static RuntimeException rSuicideDefault(String msg) {
         System.err.println("FastR unexpected failure: " + msg);
-        throw new ExitException(2);
+        throw new ExitException(2, false);
     }
 
     /**
@@ -644,10 +645,9 @@ public final class Utils {
             StdConnections.getStderr().writeString(s, nl);
         } catch (IOException ex) {
             // Very unlikely
-            ConsoleHandler consoleHandler = RContext.getInstance().getConsoleHandler();
-            consoleHandler.printErrorln("Error writing to stderr: " + ex.getMessage());
-            consoleHandler.printErrorln(s);
-
+            ConsoleIO console = RContext.getInstance().getConsole();
+            console.printErrorln("Error writing to stderr: " + ex.getMessage());
+            console.printErrorln(s);
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
index 6150dc902b2cf11456b38457c64e489a62bf8f12..df929c232608bf89a4259f71149d0e6deb5943d9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
@@ -29,13 +29,14 @@ import java.nio.ByteBuffer;
 import java.util.ArrayList;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.launcher.ConsoleHandler;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public class StdConnections {
@@ -63,11 +64,11 @@ public class StdConnections {
 
         @Override
         public RContext.ContextState initialize(RContext context) {
-            ConsoleHandler consoleHandler = context.getConsoleHandler();
+            ConsoleIO console = context.getConsole();
             try {
-                stdin = new StdinConnection();
-                stdout = new StdoutConnection(consoleHandler);
-                stderr = new StderrConnection(consoleHandler);
+                stdin = new StdinConnection(console);
+                stdout = new StdoutConnection(console);
+                stderr = new StderrConnection(console);
             } catch (IOException ex) {
                 throw Utils.rSuicide("failed to open stdconnections:");
             }
@@ -178,8 +179,11 @@ public class StdConnections {
 
     private static class StdinConnection extends StdConnection {
 
-        StdinConnection() throws IOException {
+        private final ConsoleIO console;
+
+        StdinConnection(ConsoleIO console) throws IOException {
             super(AbstractOpenMode.Read, 0);
+            this.console = console;
         }
 
         @Override
@@ -200,7 +204,6 @@ public class StdConnections {
         @Override
         @TruffleBoundary
         public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-            ConsoleHandler console = RContext.getInstance().getConsoleHandler();
             ArrayList<String> lines = new ArrayList<>();
             String line;
             while ((line = console.readLine()) != null) {
@@ -221,11 +224,11 @@ public class StdConnections {
     }
 
     private abstract static class StdoutputAdapter extends StdConnection {
-        protected final ConsoleHandler consoleHandler;
+        protected final ConsoleIO console;
 
-        StdoutputAdapter(int index, ConsoleHandler consoleHandler) throws IOException {
+        StdoutputAdapter(int index, ConsoleIO console) throws IOException {
             super(AbstractOpenMode.Write, index);
-            this.consoleHandler = consoleHandler;
+            this.console = console;
             this.opened = true;
         }
 
@@ -247,8 +250,8 @@ public class StdConnections {
 
     private static class StdoutConnection extends StdoutputAdapter {
 
-        StdoutConnection(ConsoleHandler consoleHandler) throws IOException {
-            super(1, consoleHandler);
+        StdoutConnection(ConsoleIO console) throws IOException {
+            super(1, console);
         }
 
         int numDiversions() {
@@ -292,9 +295,9 @@ public class StdConnections {
             ContextStateImpl state = getContextState();
             if (state.top < 0) {
                 if (nl) {
-                    consoleHandler.println(s);
+                    console.println(s);
                 } else {
-                    consoleHandler.print(s);
+                    console.print(s);
                 }
             } else {
                 getContextState().diversions[state.top].conn.writeString(s, nl);
@@ -327,8 +330,8 @@ public class StdConnections {
     private static class StderrConnection extends StdoutputAdapter {
         RConnection diversion;
 
-        StderrConnection(ConsoleHandler consoleHandler) throws IOException {
-            super(2, consoleHandler);
+        StderrConnection(ConsoleIO console) throws IOException {
+            super(2, console);
         }
 
         void divertErr(RConnection conn) {
@@ -379,9 +382,9 @@ public class StdConnections {
                 diversion.writeString(s, nl);
             } else {
                 if (nl) {
-                    consoleHandler.printErrorln(s);
+                    console.printErrorln(s);
                 } else {
-                    consoleHandler.printError(s);
+                    console.printError(s);
                 }
             }
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java
deleted file mode 100644
index cd21de478bcbbc641621ce8c4e41ec50082b40e5..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, 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.runtime.context;
-
-import java.io.File;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-
-/**
- * The interface to a source of input/output for the context, which may have different
- * implementations for different contexts. Since I/O is involved, all methods are tagged with
- * {@link TruffleBoundary} as a hint that so should the associated implementation methods.
- */
-public abstract class ConsoleHandler {
-
-    private RContext ctx;
-
-    /**
-     * Normal output with a new line.
-     */
-    @TruffleBoundary
-    public abstract void println(String s);
-
-    /**
-     * Normal output without a newline.
-     */
-    @TruffleBoundary
-    public abstract void print(String s);
-
-    /**
-     * Formatted output.
-     */
-    @TruffleBoundary
-    public void printf(String format, Object... args) {
-        print(String.format(format, args));
-    }
-
-    /**
-     * Error output with a newline.
-     *
-     * @param s
-     */
-    @TruffleBoundary
-    public abstract void printErrorln(String s);
-
-    /**
-     * Error output without a newline.
-     */
-    @TruffleBoundary
-    public abstract void printError(String s);
-
-    /**
-     * Read a line of input, newline is <b>NOT</b> included in result. Returns null if
-     * {@link #isInteractive() == false}. TODO worry about "\r\n"?
-     */
-    @TruffleBoundary
-    public abstract String readLine();
-
-    /**
-     * Denote whether the FastR instance is running in 'interactive' mode. This can be set in a
-     * number of ways and is <b>not</> simply equivalent to taking input from a file. However, it is
-     * final once set.
-     */
-    @TruffleBoundary
-    public abstract boolean isInteractive();
-
-    /**
-     * Get the current prompt.
-     */
-    @TruffleBoundary
-    public abstract String getPrompt();
-
-    /**
-     * Set the R prompt.
-     */
-    @TruffleBoundary
-    public abstract void setPrompt(String prompt);
-
-    public abstract String getInputDescription();
-
-    public void setContext(RContext ctx) {
-        this.ctx = ctx;
-    }
-
-    public RContext getContext() {
-        return ctx;
-    }
-
-    public void setHistoryFrom(@SuppressWarnings("unused") File file) {
-        // by default, do nothing
-    }
-
-    public void flushHistory() {
-        // by default, do nothing
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
index 5a680554e95df9da0769f3809a8e8aedc9e2dff5..8e140b8338a4419b264686ef865a38898bbcf823 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
@@ -22,6 +22,9 @@
  */
 package com.oracle.truffle.r.runtime.context;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.util.TimeZone;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
@@ -29,12 +32,27 @@ import java.util.concurrent.atomic.AtomicInteger;
 
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.api.vm.PolyglotEngine.Builder;
-import com.oracle.truffle.r.runtime.RCmdOptions;
-import com.oracle.truffle.r.runtime.RCmdOptions.Client;
+import com.oracle.truffle.r.launcher.RCmdOptions;
+import com.oracle.truffle.r.launcher.RStartParams;
+import com.oracle.truffle.r.launcher.RCmdOptions.Client;
 import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.RStartParams;
 import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 
+final class ConsoleHandlerInputStream extends InputStream {
+    @Override
+    public int read() throws IOException {
+        return 0;
+    }
+}
+
+final class ConsoleHandlerOutputStream extends OutputStream {
+
+    @Override
+    public void write(int b) throws IOException {
+
+    }
+}
+
 /**
  * Represents custom initialization state for an R instance.
  *
@@ -44,8 +62,8 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 public final class ContextInfo {
     static final String CONFIG_KEY = "fastrContextInfo";
 
-    private static final AtomicInteger contextInfoIds = new AtomicInteger();
-    private static final AtomicInteger multiSlotInds = new AtomicInteger(-1);
+    static final AtomicInteger contextInfoIds = new AtomicInteger();
+    static final AtomicInteger multiSlotInds = new AtomicInteger(-1);
 
     private final RStartParams startParams;
     private final String[] env;
@@ -57,18 +75,23 @@ public final class ContextInfo {
      * the RContext.threadLocalContext to the parent.
      */
     private final RContext parent;
-    private final ConsoleHandler consoleHandler;
+    private final InputStream stdin;
+    private final OutputStream stdout;
+    private final OutputStream stderr;
     private final int id;
     private final int multiSlotInd;
     private PolyglotEngine vm;
     public Executor executor;
 
-    private ContextInfo(RStartParams startParams, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler, TimeZone systemTimeZone, int id, int multiSlotInd) {
+    private ContextInfo(RStartParams startParams, String[] env, ContextKind kind, RContext parent, InputStream stdin, OutputStream stdout, OutputStream stderr, TimeZone systemTimeZone, int id,
+                    int multiSlotInd) {
         this.startParams = startParams;
         this.env = env;
         this.kind = kind;
         this.parent = parent;
-        this.consoleHandler = consoleHandler;
+        this.stdin = stdin;
+        this.stdout = stdout;
+        this.stderr = stderr;
         this.systemTimeZone = systemTimeZone;
         this.multiSlotInd = multiSlotInd;
         this.id = id;
@@ -86,26 +109,23 @@ public final class ContextInfo {
         multiSlotInds.set(0); // to account for primordial context
     }
 
+    public org.graalvm.polyglot.Engine createEngine() {
+        return org.graalvm.polyglot.Engine.newBuilder().setIn(stdin).setOut(stdout).setErr(stderr).build();
+    }
+
     public PolyglotEngine createVM() {
         Builder builder = PolyglotEngine.newBuilder();
-        if (startParams.getInteractive()) {
+        if (startParams.isInteractive()) {
             this.executor = Executors.newSingleThreadExecutor();
             builder = builder.executor(executor);
         }
-        PolyglotEngine newVM = builder.config("application/x-r", CONFIG_KEY, this).build();
+        PolyglotEngine newVM = builder.config("application/x-r", CONFIG_KEY, this).setIn(stdin).setOut(stdout).setErr(stderr).build();
         this.vm = newVM;
-
-        // retrieve context and set for console handler
-        if (consoleHandler != null) {
-            RContext ctx = newVM.eval(Engine.GET_CONTEXT).as(RContext.class);
-            consoleHandler.setContext(ctx);
-        }
-
         return newVM;
     }
 
     public PolyglotEngine createVM(PolyglotEngine.Builder builder) {
-        PolyglotEngine newVM = builder.config("application/x-r", CONFIG_KEY, this).build();
+        PolyglotEngine newVM = builder.config("application/x-r", CONFIG_KEY, this).setIn(stdin).setOut(stdout).setErr(stderr).build();
         this.vm = newVM;
         return newVM;
     }
@@ -114,14 +134,12 @@ public final class ContextInfo {
      * Create a context configuration object.
      *
      * @param startParams the start parameters passed this R session
-     * @param env TODO
      * @param kind defines the degree to which this context shares base and package environments
      *            with its parent
      * @param parent if non-null {@code null}, the parent creating the context
-     * @param consoleHandler a {@link ConsoleHandler} for output
      * @param systemTimeZone the system's time zone
      */
-    public static ContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler, TimeZone systemTimeZone) {
+    public static ContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, InputStream stdin, OutputStream stdout, OutputStream stderr, TimeZone systemTimeZone) {
         int id = contextInfoIds.incrementAndGet();
         int multiSlotInd = multiSlotInds.get();
         if (kind == ContextKind.SHARE_ALL || kind == ContextKind.SHARE_NOTHING) {
@@ -133,11 +151,11 @@ public final class ContextInfo {
             throw RInternalError.shouldNotReachHere();
         }
         assert kind != ContextKind.SHARE_PARENT_RW || (kind == ContextKind.SHARE_PARENT_RW && parent.getKind() == ContextKind.SHARE_NOTHING && parent.getMultiSlotInd() == 0);
-        return new ContextInfo(startParams, env, kind, parent, consoleHandler, systemTimeZone, id, kind == ContextKind.SHARE_PARENT_RW ? 0 : multiSlotInd);
+        return new ContextInfo(startParams, env, kind, parent, stdin, stdout, stderr, systemTimeZone, id, kind == ContextKind.SHARE_PARENT_RW ? 0 : multiSlotInd);
     }
 
-    public static ContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler) {
-        return create(startParams, env, kind, parent, consoleHandler, TimeZone.getDefault());
+    public static ContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, InputStream stdin, OutputStream stdout, OutputStream stderr) {
+        return create(startParams, env, kind, parent, stdin, stdout, stderr, TimeZone.getDefault());
     }
 
     /**
@@ -148,11 +166,10 @@ public final class ContextInfo {
      * @param kind defines the degree to which this context shares base and package environments
      *            with its parent
      * @param parent if non-null {@code null}, the parent creating the context
-     * @param consoleHandler a {@link ConsoleHandler} for output
      */
-    public static ContextInfo createNoRestore(Client client, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler) {
-        RStartParams params = new RStartParams(RCmdOptions.parseArguments(client, new String[]{"--no-restore"}, false), false);
-        return create(params, env, kind, parent, consoleHandler);
+    public static ContextInfo createNoRestore(Client client, String[] env, ContextKind kind, RContext parent, InputStream stdin, OutputStream stdout, OutputStream stderr) {
+        RStartParams params = new RStartParams(RCmdOptions.parseArguments(client, new String[]{"R", "--vanilla", "--slave", "--silent", "--no-restore"}, false), false);
+        return create(params, env, kind, parent, stdin, stdout, stderr);
     }
 
     public RStartParams getStartParams() {
@@ -171,10 +188,6 @@ public final class ContextInfo {
         return parent;
     }
 
-    public ConsoleHandler getConsoleHandler() {
-        return consoleHandler;
-    }
-
     public TimeZone getSystemTimeZone() {
         return systemTimeZone;
     }
@@ -190,4 +203,16 @@ public final class ContextInfo {
     public PolyglotEngine getVM() {
         return vm;
     }
+
+    public InputStream getStdin() {
+        return stdin;
+    }
+
+    public OutputStream getStdout() {
+        return stdout;
+    }
+
+    public OutputStream getStderr() {
+        return stderr;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java
index d593d92ec8efff0e6d4c070184f7a373137bd9ca..104c27b4a77c8cfe94b5316315d928b7239f62df 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java
@@ -22,6 +22,10 @@
  */
 package com.oracle.truffle.r.runtime.context;
 
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+
 import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
@@ -33,7 +37,9 @@ import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RSource;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
@@ -70,14 +76,27 @@ public interface Engine {
         }
 
         @TruffleBoundary
-        public void report(ConsoleHandler consoleHandler) {
+        public void report(OutputStream output) {
+            try {
+                output.write(getErrorMessage().getBytes(StandardCharsets.UTF_8));
+            } catch (IOException e) {
+                throw new RInternalError(e, "error while printing parse exception");
+            }
+        }
+
+        @TruffleBoundary
+        public void report(ConsoleIO console) {
+            console.println(getErrorMessage());
+        }
+
+        private String getErrorMessage() {
             String msg;
             if (source.getLineCount() == 1) {
                 msg = String.format(RError.Message.UNEXPECTED.message, token, substring);
             } else {
                 msg = String.format(RError.Message.UNEXPECTED_LINE.message, token, substring, line);
             }
-            consoleHandler.println("Error: " + msg);
+            return "Error: " + msg;
         }
 
         @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java
index 605c5ff134d11b5641d14d5c53ced38cfbf85fc3..61cab9d33c37f0f8f92fcc4fbc46cd1d35a178f6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java
@@ -107,7 +107,7 @@ public class EvalThread extends ContextThread {
             PolyglotEngine.Value resultValue = vm.eval(source);
             evalResult = createEvalResult(resultValue);
         } catch (ParseException e) {
-            e.report(info.getConsoleHandler());
+            e.report(info.getStdout());
             evalResult = createErrorResult(e.getMessage());
         } catch (ExitException e) {
             // termination, treat this as "success"
@@ -117,7 +117,7 @@ public class EvalThread extends ContextThread {
             evalResult = RDataFactory.createList(new Object[]{RNull.instance});
         } catch (Throwable t) {
             // some internal error
-            RInternalError.reportErrorAndConsoleLog(t, info.getConsoleHandler(), info.getId());
+            RInternalError.reportErrorAndConsoleLog(t, info.getId());
             evalResult = createErrorResult(t.getClass().getSimpleName());
         }
         return evalResult;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
index a35713f109e9678f39be3d906553676602dc6ac3..22c59f4bc0475800e84e781b183b4172e53a2d94 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
@@ -25,16 +25,26 @@ package com.oracle.truffle.r.runtime.context;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
 import java.lang.ref.WeakReference;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.TimeZone;
 import java.util.WeakHashMap;
+import java.util.concurrent.Executor;
 
 import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
@@ -44,23 +54,31 @@ import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.TruffleLanguage.Env;
 import com.oracle.truffle.api.instrumentation.AllocationReporter;
 import com.oracle.truffle.api.instrumentation.Instrumenter;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.UnknownIdentifierException;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.interop.UnsupportedTypeException;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.launcher.RCmdOptions;
+import com.oracle.truffle.r.launcher.RCmdOptions.Client;
+import com.oracle.truffle.r.launcher.RStartParams;
 import com.oracle.truffle.r.runtime.LazyDBCache;
 import com.oracle.truffle.r.runtime.PrimitiveMethodsInfo;
-import com.oracle.truffle.r.runtime.RCmdOptions;
-import com.oracle.truffle.r.runtime.RCmdOptions.Client;
 import com.oracle.truffle.r.runtime.REnvVars;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RErrorHandling;
 import com.oracle.truffle.r.runtime.RInternalCode.ContextStateImpl;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.ROptions;
 import com.oracle.truffle.r.runtime.RProfile;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RRuntimeASTAccess;
 import com.oracle.truffle.r.runtime.RSerialize;
-import com.oracle.truffle.r.runtime.RStartParams;
 import com.oracle.truffle.r.runtime.TempPathName;
-import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinLookup;
@@ -213,7 +231,26 @@ public final class RContext implements RTruffleObject {
         }
     }
 
-    private final ContextInfo info;
+    private final RStartParams startParameters;
+    private final RCmdOptions cmdOptions;
+    private final String[] environment;
+    private final RContext.ContextKind contextKind;
+    private final TimeZone systemTimeZone;
+
+    /**
+     * Any context created by another has a parent. When such a context is destroyed we must reset
+     * the RContext.threadLocalContext to the parent.
+     */
+    private final RContext parentContext;
+    private final int id;
+    private final int multiSlotIndex;
+    private PolyglotEngine polyglotEngine;
+    public Executor executor;
+
+    private final InputStream stdin;
+    private final OutputStreamWriter stdout;
+    private final OutputStreamWriter stderr;
+
     private final Engine engine;
     private final TruffleRLanguage language;
 
@@ -342,8 +379,7 @@ public final class RContext implements RTruffleObject {
 
     private ContextState[] contextStates() {
         return new ContextState[]{stateREnvVars, stateRProfile, stateTempPath, stateROptions, stateREnvironment, stateRErrorHandling, stateRConnection, stateStdConnections, stateRNG, stateRFFI,
-                        stateRSerialize,
-                        stateLazyDBCache, stateInstrumentation, stateDLL};
+                        stateRSerialize, stateLazyDBCache, stateInstrumentation, stateDLL};
     }
 
     public static void setEmbedded() {
@@ -363,6 +399,13 @@ public final class RContext implements RTruffleObject {
      */
     private RContext(TruffleRLanguage language, Env env, Instrumenter instrumenter, boolean isInitial) {
         this.language = language;
+        String[] args;
+        if (env.getApplicationArguments().length == 0) {
+            args = new String[]{"R", "--vanilla", "--slave", "--silent", "--no-restore"};
+        } else {
+            args = env.getApplicationArguments();
+        }
+
         Object initialInfo = env.getConfig().get(ContextInfo.CONFIG_KEY);
         if (initialInfo == null) {
             /*
@@ -370,12 +413,36 @@ public final class RContext implements RTruffleObject {
              * not via RCommand/RscriptCommand. In this case, we also assume that no previously
              * stored session should be restored.
              */
-            this.info = ContextInfo.create(new RStartParams(RCmdOptions.parseArguments(Client.R, new String[]{"--no-restore"}, false), false), null,
-                            ContextKind.SHARE_NOTHING, null, new DefaultConsoleHandler(env.in(), env.out()));
+            this.cmdOptions = RCmdOptions.parseArguments(Client.R, args, true);
+            this.startParameters = new RStartParams(cmdOptions, false);
+            this.environment = null;
+            this.contextKind = ContextKind.SHARE_NOTHING;
+            this.systemTimeZone = TimeZone.getDefault();
+            this.parentContext = null;
+            this.id = ContextInfo.contextInfoIds.incrementAndGet();
+            this.multiSlotIndex = 0;
+            this.polyglotEngine = null;
+            this.executor = null;
         } else {
-            this.info = (ContextInfo) initialInfo;
+            ContextInfo info = (ContextInfo) initialInfo;
+            this.cmdOptions = RCmdOptions.parseArguments(Client.R, args, true);
+            this.startParameters = info.getStartParams();
+            this.environment = info.getEnv();
+            this.contextKind = info.getKind();
+            this.systemTimeZone = info.getSystemTimeZone();
+            this.parentContext = info.getParent();
+            this.id = info.getId();
+            this.multiSlotIndex = info.getMultiSlotInd();
+            this.polyglotEngine = info.getVM();
+            this.executor = info.executor;
         }
 
+        outputWelcomeMessage(startParameters);
+
+        this.stdin = env.in();
+        this.stdout = new OutputStreamWriter(env.out());
+        this.stderr = new OutputStreamWriter(env.err());
+
         this.initial = isInitial;
         this.env = env;
         this.stateREnvVars = REnvVars.newContextState();
@@ -400,29 +467,36 @@ public final class RContext implements RTruffleObject {
         RDataFactory.setAllocationTracingEnabled(allocationReporter.isActive());
     }
 
+    static void outputWelcomeMessage(RStartParams rsp) {
+        /*
+         * Outputting the welcome message here has the virtue that the VM initialization delay
+         * occurs later. However, it does not work in embedded mode as console redirects have not
+         * been installed at this point. So we do it later in REmbedded.
+         */
+        if (!rsp.isQuiet() && !embedded) {
+            System.out.println(RRuntime.WELCOME_MESSAGE);
+        }
+    }
+
     /**
      * Performs the real initialization of the context, invoked from
      * {@link TruffleLanguage#initializeContext}.
      */
     public RContext initializeContext() {
         // this must happen before engine activation in the code below
-        if (info.getKind() == ContextKind.SHARE_NOTHING) {
-            if (info.getParent() == null) {
+        if (contextKind == ContextKind.SHARE_NOTHING) {
+            if (parentContext == null) {
                 this.primitiveMethodsInfo = new PrimitiveMethodsInfo();
             } else {
                 // share nothing contexts need their own copy of the primitive methods meta-data as
                 // they can run (and update this meta data) concurrently with the parent;
                 // alternative would be to copy on-write but we would need some kind of locking
                 // machinery to avoid races
-                assert info.getParent().getPrimitiveMethodsInfo() != null;
-                this.primitiveMethodsInfo = info.getParent().getPrimitiveMethodsInfo().duplicate();
+                assert parentContext.getPrimitiveMethodsInfo() != null;
+                this.primitiveMethodsInfo = parentContext.getPrimitiveMethodsInfo().duplicate();
             }
         }
 
-        if (info.getConsoleHandler() == null) {
-            throw Utils.rSuicide("no console handler set");
-        }
-
         if (singleContextAssumption.isValid()) {
             if (singleContext == null) {
                 singleContext = this;
@@ -470,14 +544,14 @@ public final class RContext implements RTruffleObject {
             state.add(State.ACTIVE);
         }
 
-        if (info.getKind() == ContextKind.SHARE_PARENT_RW) {
-            if (info.getParent().sharedChild != null) {
+        if (contextKind == ContextKind.SHARE_PARENT_RW) {
+            if (parentContext.sharedChild != null) {
                 throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "can't have multiple active SHARED_PARENT_RW contexts");
             }
-            info.getParent().sharedChild = this;
+            parentContext.sharedChild = this;
             // this one must be shared between contexts - otherwise testing contexts do not know
             // that methods package is loaded
-            this.methodTableDispatchOn = info.getParent().methodTableDispatchOn;
+            this.methodTableDispatchOn = parentContext.methodTableDispatchOn;
         }
         if (initial && !embedded) {
             initialContextInitialized = true;
@@ -530,13 +604,13 @@ public final class RContext implements RTruffleObject {
                     contextState.beforeDestroy(this);
                 }
             }
-            if (info.getKind() == ContextKind.SHARE_PARENT_RW) {
-                info.getParent().sharedChild = null;
+            if (contextKind == ContextKind.SHARE_PARENT_RW) {
+                parentContext.sharedChild = null;
             }
-            if (info.getParent() == null) {
+            if (parentContext == null) {
                 threadLocalContext.set(null);
             } else {
-                threadLocalContext.set(info.getParent());
+                threadLocalContext.set(parentContext);
             }
             state = EnumSet.of(State.DESTROYED);
 
@@ -545,7 +619,7 @@ public final class RContext implements RTruffleObject {
     }
 
     public RContext getParent() {
-        return info.getParent();
+        return parentContext;
     }
 
     public Env getEnv() {
@@ -557,15 +631,15 @@ public final class RContext implements RTruffleObject {
     }
 
     public ContextKind getKind() {
-        return info.getKind();
+        return contextKind;
     }
 
     public int getId() {
-        return info.getId();
+        return id;
     }
 
     public int getMultiSlotInd() {
-        return info.getMultiSlotInd();
+        return multiSlotIndex;
     }
 
     @TruffleBoundary
@@ -610,6 +684,10 @@ public final class RContext implements RTruffleObject {
         }
     }
 
+    public boolean isInteractive() {
+        return startParameters.isInteractive();
+    }
+
     /**
      * Access to the engine, when an {@link RContext} object is available, and/or when {@code this}
      * context is not active.
@@ -655,22 +733,14 @@ public final class RContext implements RTruffleObject {
         if (primitiveMethodsInfo == null) {
             // shared contexts do not run concurrently with their parent and re-use primitive
             // methods information
-            assert info.getKind() != ContextKind.SHARE_NOTHING;
-            assert info.getParent() != null;
-            return info.getParent().getPrimitiveMethodsInfo();
+            assert contextKind != ContextKind.SHARE_NOTHING;
+            assert parentContext != null;
+            return parentContext.getPrimitiveMethodsInfo();
         } else {
             return primitiveMethodsInfo;
         }
     }
 
-    public boolean isInteractive() {
-        return info.getConsoleHandler().isInteractive();
-    }
-
-    public ConsoleHandler getConsoleHandler() {
-        return info.getConsoleHandler();
-    }
-
     /**
      * This is a static property of the implementation and not context-specific.
      */
@@ -712,16 +782,20 @@ public final class RContext implements RTruffleObject {
         return foreignAccessFactory;
     }
 
+    public RCmdOptions getCmdOptions() {
+        return cmdOptions;
+    }
+
     public RStartParams getStartParams() {
-        return info.getStartParams();
+        return startParameters;
     }
 
     public String[] getEnvSettings() {
-        return info.getEnv();
+        return environment;
     }
 
     public boolean hasExecutor() {
-        return info.executor != null;
+        return executor != null;
     }
 
     /**
@@ -730,12 +804,12 @@ public final class RContext implements RTruffleObject {
      */
     public void schedule(Runnable action) {
         assert hasExecutor() : "Cannot run RContext#schedule() when there is no executor.";
-        info.executor.execute(action);
+        executor.execute(action);
     }
 
     @Override
     public String toString() {
-        return "context: " + info.getId();
+        return "context: " + id;
     }
 
     /*
@@ -757,7 +831,7 @@ public final class RContext implements RTruffleObject {
     }
 
     public PolyglotEngine getVM() {
-        return info.getVM();
+        return polyglotEngine;
     }
 
     public boolean isInitial() {
@@ -773,7 +847,7 @@ public final class RContext implements RTruffleObject {
     }
 
     public TimeZone getSystemTimeZone() {
-        return info.getSystemTimeZone();
+        return systemTimeZone;
     }
 
     public String getNamespaceName() {
@@ -831,4 +905,180 @@ public final class RContext implements RTruffleObject {
         }
         interopClassLoader = URLClassLoader.newInstance(urls, interopClassLoader);
     }
+
+    public final class ConsoleIO {
+
+        private final CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
+
+        {
+            decoder.onMalformedInput(CodingErrorAction.IGNORE);
+            decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+        }
+
+        @TruffleBoundary
+        public String readLine() {
+            /*
+             * We cannot use an InputStreamReader because it buffers characters internally, whereas
+             * readLine() should not buffer across newlines.
+             */
+
+            ByteBuffer bytes = ByteBuffer.allocate(16);
+            CharBuffer chars = CharBuffer.allocate(16);
+            StringBuilder str = new StringBuilder();
+            decoder.reset();
+            while (true) {
+                int inputByte;
+                try {
+                    inputByte = stdin.read();
+                } catch (IOException e) {
+                    throw new RInternalError(e, "error writing to stderr");
+                }
+                if (inputByte == -1) {
+                    return str.toString();
+                }
+                bytes.put((byte) inputByte);
+                bytes.flip();
+                decoder.decode(bytes, chars, false);
+                chars.flip();
+                while (chars.hasRemaining()) {
+                    char c = chars.get();
+                    if (c == '\n' || c == '\r') {
+                        return str.toString();
+                    }
+                    str.append(c);
+                }
+                bytes.compact();
+                chars.clear();
+            }
+        }
+
+        @TruffleBoundary
+        public void print(String message) {
+            try {
+                stdout.write(message);
+                stdout.flush();
+            } catch (IOException e) {
+                throw new RInternalError(e, "error writing to stdout");
+            }
+        }
+
+        @TruffleBoundary
+        public void println(String message) {
+            try {
+                stdout.write(message);
+                stdout.write('\n');
+                stdout.flush();
+            } catch (IOException e) {
+                throw new RInternalError(e, "error writing to stdout");
+            }
+        }
+
+        @TruffleBoundary
+        public void printf(String format, Object... args) {
+            try {
+                stdout.write(String.format(format, args));
+                stdout.flush();
+            } catch (IOException e) {
+                throw new RInternalError(e, "error writing to stdout");
+            }
+        }
+
+        @TruffleBoundary
+        public void printError(String message) {
+            try {
+                stderr.write(message);
+                stderr.flush();
+            } catch (IOException e) {
+                throw new RInternalError(e, "error writing to stderr");
+            }
+        }
+
+        @TruffleBoundary
+        public void printErrorln(String message) {
+            try {
+                stderr.write(message);
+                stderr.write('\n');
+                stderr.flush();
+            } catch (IOException e) {
+                throw new RInternalError(e, "error writing to stderr");
+            }
+        }
+
+        private final Node read = Message.READ.createNode();
+        private final Node write = Message.WRITE.createNode();
+
+        @TruffleBoundary
+        public String getPrompt() {
+            if (handler != null) {
+                Object result;
+                try {
+                    result = ForeignAccess.sendRead(read, handler, "prompt");
+                } catch (UnknownIdentifierException | UnsupportedMessageException e) {
+                    throw new RInternalError(e, "error while reading prompt");
+                }
+                return (String) result;
+            }
+            return "";
+        }
+
+        @TruffleBoundary
+        public void setPrompt(String prompt) {
+            if (handler != null) {
+                try {
+                    ForeignAccess.sendWrite(write, handler, "prompt", prompt);
+                } catch (UnknownIdentifierException | UnsupportedMessageException | UnsupportedTypeException e) {
+                    throw new RInternalError(e, "error while writing prompt");
+                }
+            }
+        }
+
+        @TruffleBoundary
+        public String getHistory() {
+            if (handler != null) {
+                Object result;
+                try {
+                    result = ForeignAccess.sendRead(read, handler, "history");
+                } catch (UnknownIdentifierException | UnsupportedMessageException e) {
+                    throw new RInternalError(e, "error while reading history");
+                }
+                return (String) result;
+            }
+            return "";
+        }
+
+        @TruffleBoundary
+        public void setHistory(String history) {
+            if (handler != null) {
+                try {
+                    ForeignAccess.sendWrite(write, handler, "history", history);
+                } catch (UnknownIdentifierException | UnsupportedMessageException | UnsupportedTypeException e) {
+                    throw new RInternalError(e, "error while writing history");
+                }
+            }
+        }
+
+        public InputStream getStdin() {
+            return env.in();
+        }
+
+        public OutputStream getStdout() {
+            return env.out();
+        }
+
+        public OutputStream getStderr() {
+            return env.err();
+        }
+
+        private TruffleObject handler;
+
+        public void setHandler(TruffleObject handler) {
+            this.handler = handler;
+        }
+    }
+
+    private final ConsoleIO console = new ConsoleIO();
+
+    public ConsoleIO getConsole() {
+        return console;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
index c93bf6935e6818f563f04f9fb608e2a658bee006..9c3be1581002812f677234fc3c51fd45d9c404e2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
@@ -190,13 +190,14 @@ public final class RScope extends AbstractScope {
             @Resolve(message = "KEY_INFO")
             public abstract static class VarMapsKeyInfoNode extends Node {
 
+                private static final int EXISTS = 1 << 0;
                 private static final int READABLE = 1 << 1;
                 private static final int WRITABLE = 1 << 2;
                 private static final int INVOCABLE = 1 << 3;
 
                 @SuppressWarnings("try")
                 protected Object access(VariablesMapObject receiver, String identifier) {
-                    int info = READABLE;
+                    int info = EXISTS + READABLE;
 
                     if (!receiver.env.bindingIsLocked(identifier)) {
                         info += WRITABLE;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SA_TYPE.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SA_TYPE.java
new file mode 100644
index 0000000000000000000000000000000000000000..703988a4d130c8cec6c56dfeafb61174978703e1
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SA_TYPE.java
@@ -0,0 +1,29 @@
+/*
+ * 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-2015, The R Core Team
+ * Copyright (c) 2003, The R Foundation
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.runtime.gnur;
+
+public enum SA_TYPE {
+    DEFAULT("default"),
+    NOSAVE("no"),
+    SAVE("yes"),
+    SAVEASK("ask");
+
+    private String name;
+
+    SA_TYPE(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+}
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 24f399344e17ce51fdbcd358552f47acc586395b..2c8a7edc7a38402fd2d5b40f131bbe07caa707e9 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
@@ -130862,30 +130862,30 @@ Error in eval.external(, "abc", ) : invalid mimeType argument
 [1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting#
-#if (!any(R.version$engine == "FastR")) { c('intValue', 'longValue', 'charValue', 'shortValue', 'booleanValue', 'stringValue') } else { v <- import('testPOJO'); names(v) }
-[1] "intValue"     "longValue"    "charValue"    "shortValue"   "booleanValue"
-[6] "stringValue"
+#if (!any(R.version$engine == "FastR")) { c('stringValue', 'charValue', 'intValue', 'shortValue', 'booleanValue', 'longValue') } else { v <- import('testPOJO'); names(v) }
+[1] "stringValue"  "charValue"    "intValue"     "shortValue"   "booleanValue"
+[6] "longValue"
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting#
-#if (!any(R.version$engine == "FastR")) { cat('[external object]\n$intValue\n[1] 1\n\n$longValue\n[1] 123412341234\n\n$charValue\n[1] "R"\n\n$shortValue\n[1] -100\n\n$booleanValue\n[1] TRUE\n\n$stringValue\n[1] "foo"\n\n') } else { v <- import('testPOJO'); print(v) }
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n$stringValue\n[1] "foo"\n\n$charValue\n[1] "R"\n\n$intValue\n[1] 1\n\n$shortValue\n[1] -100\n\n$booleanValue\n[1] TRUE\n\n$longValue\n[1] 123412341234\n\n') } else { v <- import('testPOJO'); print(v) }
 [external object]
-$intValue
-[1] 1
-
-$longValue
-[1] 123412341234
+$stringValue
+[1] "foo"
 
 $charValue
 [1] "R"
 
+$intValue
+[1] 1
+
 $shortValue
 [1] -100
 
 $booleanValue
 [1] TRUE
 
-$stringValue
-[1] "foo"
+$longValue
+[1] 123412341234
 
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting#
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java
index 015fa4ff405ce362e1a4378cbb4b82877f07e0e0..3f3c94aad6186d5b67f260652079fc51ce2fe12d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java
@@ -22,41 +22,44 @@
  */
 package com.oracle.truffle.r.test.engine.shell;
 
-import com.oracle.truffle.api.vm.PolyglotEngine;
-import com.oracle.truffle.r.engine.shell.JLineConsoleCompleter;
-import com.oracle.truffle.r.runtime.RCmdOptions;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
-import com.oracle.truffle.r.runtime.context.ContextInfo;
-import com.oracle.truffle.r.runtime.context.RContext;
-import java.io.File;
-import org.junit.Test;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
+import java.io.File;
 import java.util.LinkedList;
+
+import org.graalvm.polyglot.Engine;
+import org.graalvm.polyglot.PolyglotContext;
+import org.graalvm.polyglot.PolyglotContext.Builder;
 import org.junit.After;
 import org.junit.Assert;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
 import org.junit.Before;
+import org.junit.Test;
+
+import com.oracle.truffle.r.launcher.JLineConsoleCompleter;
 
 public class TestJLineConsoleCompleter {
 
-    private PolyglotEngine engine;
-    private ConsoleHandler consoleHandler;
+    private Engine engine;
+    private PolyglotContext context;
     private JLineConsoleCompleter consoleCompleter;
 
     @Before
     public void before() {
-        consoleHandler = new DummyConsoleHandler();
-        consoleCompleter = new JLineConsoleCompleter(consoleHandler);
         JLineConsoleCompleter.testingMode();
-        ContextInfo info = ContextInfo.createNoRestore(RCmdOptions.Client.R, null, RContext.ContextKind.SHARE_NOTHING, null, consoleHandler);
-        engine = info.createVM(PolyglotEngine.newBuilder());
+        engine = Engine.create();
+        Builder builder = engine.newPolyglotContextBuilder();
+        context = builder.build();
+        consoleCompleter = new JLineConsoleCompleter(context);
     }
 
     @After
     public void dispose() {
+        if (context != null) {
+            context.close();
+        }
         if (engine != null) {
-            engine.dispose();
+            engine.close();
         }
     }
 
@@ -117,47 +120,4 @@ public class TestJLineConsoleCompleter {
             Assert.assertArrayEquals(expected, l.toArray(new CharSequence[l.size()]));
         }
     }
-
-    private class DummyConsoleHandler extends ConsoleHandler {
-
-        @Override
-        public void println(String s) {
-        }
-
-        @Override
-        public void print(String s) {
-        }
-
-        @Override
-        public void printErrorln(String s) {
-        }
-
-        @Override
-        public void printError(String s) {
-        }
-
-        @Override
-        public String readLine() {
-            return "";
-        }
-
-        @Override
-        public boolean isInteractive() {
-            return false;
-        }
-
-        @Override
-        public String getPrompt() {
-            return "";
-        }
-
-        @Override
-        public void setPrompt(String prompt) {
-        }
-
-        @Override
-        public String getInputDescription() {
-            return "";
-        }
-    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java
index 507752aaef03ad4f8b48751fa959de99495cd1e0..2b3cf0a5fb78f59fafb7876079673cd02cc8247b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java
@@ -22,28 +22,31 @@
  */
 package com.oracle.truffle.r.test.generate;
 
-import java.util.ArrayDeque;
-import java.util.Arrays;
-import java.util.Deque;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.StandardCharsets;
 import java.util.TimeZone;
 import java.util.Timer;
 import java.util.TimerTask;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.debug.Debugger;
 import com.oracle.truffle.api.debug.SuspendedCallback;
 import com.oracle.truffle.api.debug.SuspendedEvent;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.launcher.RCmdOptions;
+import com.oracle.truffle.r.launcher.RCmdOptions.Client;
+import com.oracle.truffle.r.launcher.RStartParams;
 import com.oracle.truffle.r.runtime.ExitException;
 import com.oracle.truffle.r.runtime.JumpToTopLevelException;
-import com.oracle.truffle.r.runtime.RCmdOptions;
-import com.oracle.truffle.r.runtime.RCmdOptions.Client;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RSource;
-import com.oracle.truffle.r.runtime.RStartParams;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.ContextInfo;
 import com.oracle.truffle.r.runtime.context.Engine.IncompleteSourceException;
 import com.oracle.truffle.r.runtime.context.Engine.ParseException;
@@ -61,78 +64,28 @@ public final class FastRSession implements RSession {
      */
     private static int longTimeoutValue = 300000;
 
-    /**
-     * A (virtual) console handler that collects the output in a {@link StringBuilder} for
-     * comparison. It does not separate error output as the test analysis doesn't need it.
-     */
-    public static class TestConsoleHandler extends ConsoleHandler {
-        private final StringBuilder buffer = new StringBuilder();
-        private final Deque<String> input = new ArrayDeque<>();
-
-        public void setInput(String[] lines) {
-            input.clear();
-            input.addAll(Arrays.asList(lines));
-        }
-
-        @Override
-        @TruffleBoundary
-        public void println(String s) {
-            buffer.append(s);
-            buffer.append('\n');
-        }
-
-        @Override
-        @TruffleBoundary
-        public void print(String s) {
-            buffer.append(s);
-        }
-
-        @Override
-        public String readLine() {
-            return input.pollFirst();
-        }
-
-        @Override
-        public boolean isInteractive() {
-            return false;
-        }
-
-        @Override
-        @TruffleBoundary
-        public void printErrorln(String s) {
-            println(s);
-        }
-
-        @Override
-        @TruffleBoundary
-        public void printError(String s) {
-            print(s);
-        }
-
-        @Override
-        public String getPrompt() {
-            return null;
-        }
+    private static final class TestByteArrayInputStream extends ByteArrayInputStream {
 
-        @Override
-        public void setPrompt(String prompt) {
-            // ignore
+        TestByteArrayInputStream() {
+            super(new byte[0]);
         }
 
-        @TruffleBoundary
-        void reset() {
-            buffer.delete(0, buffer.length());
+        public void setContents(String data) {
+            this.buf = data.getBytes(StandardCharsets.UTF_8);
+            this.count = this.buf.length;
+            this.pos = 0;
         }
 
         @Override
-        public String getInputDescription() {
-            return "<test input>";
+        public synchronized int read() {
+            return super.read();
         }
     }
 
     private static FastRSession singleton;
 
-    private final TestConsoleHandler consoleHandler;
+    private final ByteArrayOutputStream output = new ByteArrayOutputStream();
+    private final TestByteArrayInputStream input = new TestByteArrayInputStream();
     private final PolyglotEngine main;
     private final RContext mainContext;
 
@@ -157,8 +110,8 @@ public final class FastRSession implements RSession {
     }
 
     public ContextInfo createContextInfo(ContextKind contextKind) {
-        RStartParams params = new RStartParams(RCmdOptions.parseArguments(Client.RSCRIPT, new String[]{"--no-restore"}, false), false);
-        return ContextInfo.create(params, null, contextKind, mainContext, consoleHandler, TimeZone.getTimeZone("GMT"));
+        RStartParams params = new RStartParams(RCmdOptions.parseArguments(Client.R, new String[]{"R", "--vanilla", "--slave", "--silent", "--no-restore"}, false), false);
+        return ContextInfo.create(params, null, contextKind, mainContext, input, output, output, TimeZone.getTimeZone("GMT"));
     }
 
     private FastRSession() {
@@ -173,21 +126,65 @@ public final class FastRSession implements RSession {
                 // no need to scale longTimeoutValue
             }
         }
-        consoleHandler = new TestConsoleHandler();
         try {
-            RStartParams params = new RStartParams(RCmdOptions.parseArguments(Client.RSCRIPT, new String[]{"--no-restore"}, false), false);
-            ContextInfo info = ContextInfo.create(params, null, ContextKind.SHARE_NOTHING, null, consoleHandler);
+            RStartParams params = new RStartParams(RCmdOptions.parseArguments(Client.R, new String[]{"R", "--vanilla", "--slave", "--silent", "--no-restore"}, false), false);
+            ContextInfo info = ContextInfo.create(params, null, ContextKind.SHARE_NOTHING, null, input, output, output);
             main = info.createVM();
             mainContext = main.eval(GET_CONTEXT).as(RContext.class);
         } finally {
-            System.out.print(consoleHandler.buffer.toString());
+            try {
+                System.out.print(output.toString("UTF-8"));
+            } catch (UnsupportedEncodingException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private final CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
+
+    {
+        decoder.onMalformedInput(CodingErrorAction.IGNORE);
+        decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+    }
+
+    private String readLine() {
+        /*
+         * We cannot use an InputStreamReader because it buffers characters internally, whereas
+         * readLine() should not buffer across newlines.
+         */
+
+        ByteBuffer bytes = ByteBuffer.allocate(16);
+        CharBuffer chars = CharBuffer.allocate(16);
+        StringBuilder str = new StringBuilder();
+        decoder.reset();
+        boolean initial = true;
+        while (true) {
+            int inputByte = input.read();
+            if (inputByte == -1) {
+                return initial ? null : str.toString();
+            }
+            initial = false;
+            bytes.put((byte) inputByte);
+            bytes.flip();
+            decoder.decode(bytes, chars, false);
+            chars.flip();
+            while (chars.hasRemaining()) {
+                char c = chars.get();
+                if (c == '\n' || c == '\r') {
+                    return str.toString();
+                }
+                str.append(c);
+            }
+            bytes.compact();
+            chars.clear();
         }
     }
 
     @Override
     public String eval(TestBase testClass, String expression, ContextInfo contextInfo, boolean longTimeout) throws Throwable {
         Timer timer = null;
-        consoleHandler.reset();
+        output.reset();
+        input.setContents(expression);
         try {
             ContextInfo actualContextInfo = checkContext(contextInfo);
             // set up some interop objects used by fastr-specific tests:
@@ -197,11 +194,10 @@ public final class FastRSession implements RSession {
             }
             PolyglotEngine vm = actualContextInfo.createVM(builder);
             timer = scheduleTimeBoxing(vm, longTimeout ? longTimeoutValue : timeoutValue);
-            consoleHandler.setInput(expression.split("\n"));
             try {
-                String input = consoleHandler.readLine();
-                while (input != null) {
-                    Source source = RSource.fromTextInternal(input, RSource.Internal.UNIT_TEST);
+                String consoleInput = readLine();
+                while (consoleInput != null) {
+                    Source source = RSource.fromTextInternal(consoleInput, RSource.Internal.UNIT_TEST);
                     try {
                         try {
                             vm.eval(source);
@@ -213,20 +209,20 @@ public final class FastRSession implements RSession {
                                 throw e;
                             }
                         }
-                        input = consoleHandler.readLine();
+                        consoleInput = readLine();
                     } catch (IncompleteSourceException e) {
-                        String additionalInput = consoleHandler.readLine();
+                        String additionalInput = readLine();
                         if (additionalInput == null) {
                             throw e;
                         }
-                        input += "\n" + additionalInput;
+                        consoleInput += "\n" + additionalInput;
                     }
                 }
             } finally {
                 vm.dispose();
             }
         } catch (ParseException e) {
-            e.report(consoleHandler);
+            e.report(output);
         } catch (ExitException | JumpToTopLevelException e) {
             // exit and jumpToTopLevel exceptions are legitimate if a test case calls "q()" or "Q"
             // during debugging
@@ -245,7 +241,12 @@ public final class FastRSession implements RSession {
                 timer.cancel();
             }
         }
-        return consoleHandler.buffer.toString();
+        try {
+            return output.toString("UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+            return "<exception>";
+        }
     }
 
     private static Timer scheduleTimeBoxing(PolyglotEngine engine, long timeout) {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/GnuROneShotRSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/GnuROneShotRSession.java
index 5771c2814c844a5c8bc20b1fcc0a35393c59b397..d80b8dd069b62686c9113ce0115572da46e5f1c2 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/GnuROneShotRSession.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/GnuROneShotRSession.java
@@ -29,9 +29,9 @@ import java.nio.file.FileSystems;
 import java.nio.file.Path;
 import java.util.concurrent.TimeUnit;
 
+import com.oracle.truffle.r.launcher.RVersionNumber;
 import com.oracle.truffle.r.runtime.ProcessOutputManager;
 import com.oracle.truffle.r.runtime.REnvVars;
-import com.oracle.truffle.r.runtime.RVersionNumber;
 import com.oracle.truffle.r.runtime.context.ContextInfo;
 import com.oracle.truffle.r.test.TestBase;
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/RSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/RSession.java
index a1596b25bb0679a326947af47f88b037b0c0e501..40e96af850618b30a7fb023814e36a4c9fc2cddd 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/RSession.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/RSession.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -41,7 +41,6 @@ public interface RSession {
      *
      * This result will always be non-null or an exception will be thrown in, say, a timeout
      * occurring.
-     *
      */
     String eval(TestBase testClass, String expression, ContextInfo contextInfo, boolean longTimeout) throws Throwable;
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
index 42a8a05bd16b6282d4ef61e0e1e0f64b30b8caf3..67b034176b752e634594d2dfcb7b027effbfc7fa 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
@@ -100,12 +100,12 @@ public class TestInterop extends TestBase {
      * Used for testing interop functionality.
      */
     public static final class POJO {
-        public int intValue = 1;
-        public long longValue = 123412341234L;
+        public String stringValue = "foo";
         public char charValue = 'R';
+        public int intValue = 1;
         public short shortValue = -100;
         public boolean booleanValue = true;
-        public String stringValue = "foo";
+        public long longValue = 123412341234L;
     }
 
     private static final class TestJavaObject {
@@ -132,27 +132,27 @@ public class TestInterop extends TestBase {
     @Test
     public void testPrinting() {
         assertEvalFastR("v <- import('testPOJO'); print(v)", "cat('[external object]\\n" +
-                        "$intValue\\n" +
-                        "[1] 1\\n" +
-                        "\\n" +
-                        "$longValue\\n" +
-                        "[1] 123412341234\\n" +
+                        "$stringValue\\n" +
+                        "[1] \"foo\"\\n" +
                         "\\n" +
                         "$charValue\\n" +
                         "[1] \"R\"\\n" +
                         "\\n" +
+                        "$intValue\\n" +
+                        "[1] 1\\n" +
+                        "\\n" +
                         "$shortValue\\n" +
                         "[1] -100\\n" +
                         "\\n" +
                         "$booleanValue\\n" +
                         "[1] TRUE\\n" +
                         "\\n" +
-                        "$stringValue\\n" +
-                        "[1] \"foo\"\\n\\n')");
+                        "$longValue\\n" +
+                        "[1] 123412341234\\n\\n')");
         assertEvalFastR("v <- import('testStringArray'); print(v)", "cat('[external object]\\n[1] \"a\"   \"\"    \"foo\"\\n')");
         assertEvalFastR("v <- import('testIntArray'); print(v)", "cat('[external object]\\n[1]   1  -5 199\\n')");
         assertEvalFastR("v <- import('testIntArray'); v", "cat('[external object]\\n[1]   1  -5 199\\n')");
-        assertEvalFastR("v <- import('testPOJO'); names(v)", "c('intValue', 'longValue', 'charValue', 'shortValue', 'booleanValue', 'stringValue')");
+        assertEvalFastR("v <- import('testPOJO'); names(v)", "c('stringValue', 'charValue', 'intValue', 'shortValue', 'booleanValue', 'longValue')");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
index ecc44d636bcc3f2e2f4b00347bacc0ddbbf2ee2f..1aa7b22a2eaf0472480426fab8a5da4917d853b0 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
@@ -52,11 +52,9 @@ import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.api.vm.PolyglotEngine.Value;
-import com.oracle.truffle.r.runtime.RCmdOptions.Client;
+import com.oracle.truffle.r.launcher.RCmdOptions.Client;
 import com.oracle.truffle.r.runtime.RSource;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.ContextInfo;
-import com.oracle.truffle.r.runtime.context.DefaultConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -76,8 +74,7 @@ public class FastRDebugTest {
     public void before() {
         suspendedEvent = null;
 
-        ConsoleHandler consoleHandler = new DefaultConsoleHandler(System.in, out);
-        ContextInfo info = ContextInfo.createNoRestore(Client.R, null, ContextKind.SHARE_NOTHING, null, consoleHandler);
+        ContextInfo info = ContextInfo.createNoRestore(Client.R, null, ContextKind.SHARE_NOTHING, null, System.in, out, err);
         engine = info.createVM(PolyglotEngine.newBuilder().setOut(out).setErr(err));
         debugger = Debugger.find(engine);
         debuggerSession = debugger.startSession(event -> {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RBuiltinCheck.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RBuiltinCheck.java
index cfacee313efc9f28ef9e23ec75dd7b4e9585d6b0..033e8eee68e2b490c38c891776c6ac0ff95ea061 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RBuiltinCheck.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RBuiltinCheck.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -39,9 +39,9 @@ import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import com.oracle.truffle.r.launcher.RVersionNumber;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinFactory;
 import com.oracle.truffle.r.nodes.builtin.base.BasePackage;
-import com.oracle.truffle.r.runtime.RVersionNumber;
 import com.oracle.truffle.r.runtime.RVisibility;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 201313142399f2b7a80f536e1ee26adacbc6bf98..5c069dde67df806db7e0be218e168f045c6a5555 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -1,96 +1,59 @@
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java,gnu_r_graphics.copyright
+com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsRealNode.java,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Arrows.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java,gnu_r_graphics.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java,gnu_r.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPretty.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRaster.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/PaletteExternals.java,gnu_r.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java,gnu_r_graphics.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java,gnu_r.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Arithmetic.java,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DNorm.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RBeta.java,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RMultinom.java,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Cauchy.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QTukey.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PTukey.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java,gnu_r.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java,gnu_r.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java,gnu_r.core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Signrank.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Dbinom.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RNBinom.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PNBinom.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DNBinom.java,gnu_r.core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/DPQ.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Rt.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/GammaFunctions.java,gnu_r_qgamma.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QHyper.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DHyper.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PHyper.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qt.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pt.java,gnu_r_scan.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RHyper.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pbeta.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PNBeta.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QNBeta.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qnf.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Dnf.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qnt.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnt.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Dnt.java,gnu_r.foundation.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DNBeta.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/LBeta.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pbinom.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pf.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnorm.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PPois.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QPois.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QBeta.java,gnu_r_scan.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qf.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qbinom.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qnorm.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RPois.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Rbinom.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Unif.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Rnorm.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Chisq.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PNChisq.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QNChisq.java,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DNChisq.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java,gnu_r_splines.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMath.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QuantileSearch.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QNBinom.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMathError.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Choose.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Mach.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/LogNormal.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/MathConstants.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/TOMS708.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SNorm.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SExp.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RGamma.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PGamma.java,gnu_r_welinder.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Logis.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnf.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Rf.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Exp.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Geom.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Dt.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Df.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DBeta.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DPois.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RNchisq.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Wilcox.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Weibull.java,gnu_r_ihaka_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java,gnu_r.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java,gnu_r.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java,gnu_r.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java,gnu_r.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java,gnu_r.copyright
-com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h,no.copyright
 com.oracle.truffle.r.native/fficall/src/common/arithmetic_fastr.c,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/common/coerce_fastr.c,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/common/errors_fastr.c,gnu_r.core.copyright
@@ -98,36 +61,37 @@ com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c,gnu_r_gentleman_i
 com.oracle.truffle.r.native/fficall/src/common/localecharset_fastr.c,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/common/print_fastr.c,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/common/printutils_fastr.c,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h,no.copyright
 com.oracle.truffle.r.native/fficall/src/common/sys_fastr.c,gnu_r.copyright
+com.oracle.truffle.r.native/fficall/src/common/unimplemented.c,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/common/util_fastr.c,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/common/X11_fastr.c,gnu_r.copyright
-com.oracle.truffle.r.native/fficall/src/common/unimplemented.c,gnu_r.copyright
+com.oracle.truffle.r.native/fficall/src/include/contour-common.h,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/include/Defn.h,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.native/fficall/src/include/Fileio.h,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/include/Graphics.h,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/include/GraphicsBase.h,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/include/Internal.h,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.native/fficall/src/include/nmath.h,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/include/Print.h,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/include/Rgraphics.h,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.native/fficall/src/include/Fileio.h,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.native/fficall/src/include/contour-common.h,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.native/fficall/src/include/nmath.h,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/include/rlocale.h,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/jni/Memory.c,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c,gnu_r.copyright
-com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c,gnu_r.copyright
-com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c,gnu_r.copyright
-com.oracle.truffle.r.native/fficall/src/truffle_nfi/pcre_rffi.c,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.native/fficall/src/truffle_llvm/pcre_rffi.c,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rdynload_fastr.c,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/truffle_llvm/Memory.c,gnu_r.copyright
+com.oracle.truffle.r.native/fficall/src/truffle_llvm/pcre_rffi.c,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rdynload_fastr.c,gnu_r.copyright
+com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c,gnu_r.copyright
+com.oracle.truffle.r.native/fficall/src/truffle_nfi/pcre_rffi.c,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c,gnu_r.copyright
 com.oracle.truffle.r.native/library/base/src/registration.c,no.copyright
 com.oracle.truffle.r.native/library/grDevices/src/gzio.c,gnu_r_gentleman_ihaka.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/rngstream.c,no.copyright
 com.oracle.truffle.r.native/library/parallel/src/parallel_dummy.c,no.copyright
+com.oracle.truffle.r.native/library/parallel/src/rngstream.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
@@ -142,7 +106,6 @@ com.oracle.truffle.r.native/run/R.sh,oracle_bash.copyright
 com.oracle.truffle.r.native/run/Rclasspath.sh,oracle_bash.copyright
 com.oracle.truffle.r.native/run/Rscript_exec.sh,oracle_bash.copyright
 com.oracle.truffle.r.native/run/Rscript.sh,oracle_bash.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java,gnu_r_ihaka.copyright
@@ -164,45 +127,55 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/D
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CairoProps.java,gnu_r.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Flushconsole.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java,gnu_r.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/MakeQuartzDefault.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java,gnu_r.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java,gnu_r.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsListFactor.java,gnu_r.core.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InheritsBuiltin.java,purdue.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsListFactor.java,gnu_r.core.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java,gnu_r.copyright
 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/Merge.java,gnu_r_gentleman_ihaka2.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/Pretty.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrettyIntevals.java,gnu_r_gentleman_ihaka2.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/ComplexVectorPrinter.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/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/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
+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/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/Prod.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.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/Rank.java,gnu_r_gentleman_ihaka.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/Row.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowMeans.java,purdue.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowSums.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowSums.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java,gnu_r_sample.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java,gnu_r_scan.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java,gnu_r_gentleman_ihaka.copyright
@@ -212,6 +185,7 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/U
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java,purdue.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java,gnu_r.copyright
 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java,purdue.copyright
@@ -227,31 +201,105 @@ com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java
 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/InheritsNode.java,purdue.copyright
 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g,purdue.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSrcref.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RStartParams.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SA_TYPE.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Arithmetic.java,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Choose.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Cauchy.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Chisq.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DBeta.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Dbinom.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Df.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DHyper.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DNBeta.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DNBinom.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DNChisq.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Dnf.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DNorm.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Dnt.java,gnu_r.foundation.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DPois.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Dt.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Exp.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Geom.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Logis.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/LogNormal.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pbeta.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pbinom.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pf.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PGamma.java,gnu_r_welinder.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PHyper.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PNBeta.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PNBinom.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PNChisq.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnf.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnorm.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnt.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PPois.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pt.java,gnu_r_scan.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PTukey.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QBeta.java,gnu_r_scan.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qbinom.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qf.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QHyper.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QNBeta.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QNBinom.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QNChisq.java,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qnf.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qnorm.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qnt.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QPois.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qt.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QTukey.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QuantileSearch.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RBeta.java,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Rbinom.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Rf.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RGamma.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RHyper.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RMultinom.java,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RNBinom.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RNchisq.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Rnorm.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RPois.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Rt.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SExp.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Signrank.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SNorm.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Unif.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Weibull.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Wilcox.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/DPQ.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/GammaFunctions.java,gnu_r_qgamma.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/LBeta.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Mach.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/MathConstants.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMath.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMathError.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/TOMS708.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/DuplicationHelper.java,purdue.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java,gnu_r_purdue.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmetic.java,gnu_r_unary.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrettyIntevals.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrimitiveMethodsInfo.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RAccuracyInfo.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/DuplicationHelper.java,purdue.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/mm/MarsagliaMulticarry.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/mt/MersenneTwister.java,hiroshima.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RandomNumberGenerator.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RNGInitAdapter.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RandomNumberGenerator.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrimitiveMethodsInfo.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSrcref.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java,gnu_r.copyright
-com.oracle.truffle.r.test.native/urand/src/urand.c,gnu_r.copyright
 com.oracle.truffle.r.test.native/urand/src/nrand.c,gnu_r.copyright
+com.oracle.truffle.r.test.native/urand/src/urand.c,gnu_r.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_abbreviate.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_abs.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_acos.java,purdue.copyright
@@ -620,8 +668,8 @@ com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sam
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scale.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sep.java,purdue.copyright
-com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_len.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_along.java,purdue.copyright
+com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_len.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seqint.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setdiff.java,purdue.copyright
@@ -669,15 +717,15 @@ com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sum
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_summaryconnection.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sweep.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_switch.java,purdue.copyright
+com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_syscall.java,purdue.copyright
+com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_syscalls.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syschmod.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Sysgetenv.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Sysglob.java,purdue.copyright
+com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sysnframe.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sysonexit.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sysparent.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sysparents.java,purdue.copyright
-com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sysnframe.java,purdue.copyright
-com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_syscall.java,purdue.copyright
-com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_syscalls.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Sysreadlink.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetenv.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java,purdue.copyright
@@ -731,51 +779,3 @@ com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleV
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/data/tree2/incx.r,no.copyright
 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.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsRealNode.java,gnu_r_gentleman_ihaka.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/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/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/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/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
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRaster.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPretty.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Arrows.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java,gnu_r.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/PaletteExternals.java,gnu_r.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java,gnu_r_gentleman_ihaka2.copyright
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index e60ab6046461c2843b7631cdace6214354378bb1..b4cfcad4b05e11b86a5ccbb4551168445cd79681 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -51,12 +51,10 @@ If this is None, then we run under the standard VM in interpreted mode only.
 _mx_graal = mx.suite("compiler", fatalIfMissing=False)
 _mx_sulong = mx.suite("sulong", fatalIfMissing=False)
 
-_r_command_package = 'com.oracle.truffle.r.engine'
-_repl_command = 'com.oracle.truffle.tools.debug.shell.client.SimpleREPLClient'
-_command_class_dict = {'r': _r_command_package + ".shell.RCommand",
-                       'rscript': _r_command_package + ".shell.RscriptCommand",
-                        'rrepl': _repl_command,
-                        'rembed': _r_command_package + ".shell.REmbedded",
+_command_class_dict = {'r': "com.oracle.truffle.r.launcher.RCommand",
+                       'rscript': "com.oracle.truffle.r.launcher.RscriptCommand",
+                        'rrepl': "com.oracle.truffle.tools.debug.shell.client.SimpleREPLClient",
+                        'rembed': "com.oracle.truffle.r.engine.shell.REmbedded",
                     }
 # benchmarking support
 def r_path():
diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index ebeb6dfaab1b771625f77df69fe9027ffe9b6ddc..f4a2ad667a7fe96b148f986725a6896d3fd9e788 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -29,7 +29,7 @@ suite = {
             {
                "name" : "truffle",
                "subdir" : True,
-               "version" : "4190e63be1bacdc1238c4cd526725eaf498d6337",
+               "version" : "8a073fbc3a52b6b023023c5b33773ce8ef3ad939",
                "urls" : [
                     {"url" : "https://github.com/graalvm/graal", "kind" : "git"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},
@@ -214,6 +214,7 @@ suite = {
     "com.oracle.truffle.r.runtime" : {
       "sourceDirs" : ["src"],
       "dependencies" : [
+        "com.oracle.truffle.r.launcher",
         "truffle:TRUFFLE_API",
         "truffle:TRUFFLE_DEBUG",
         "XZ-1.5",
@@ -227,6 +228,20 @@ suite = {
       "jacoco" : "include",
     },
 
+    "com.oracle.truffle.r.launcher" : {
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "sdk:GRAAL_SDK",
+        "truffle:JLINE",
+      ],
+      "checkstyle" : "com.oracle.truffle.r.runtime",
+      "javaCompliance" : "1.8",
+      "annotationProcessors" : [
+      ],
+      "workingSets" : "Truffle,FastR",
+      "jacoco" : "include",
+    },
+
     "com.oracle.truffle.r.ffi.impl" : {
       "sourceDirs" : ["src"],
       "dependencies" : [
@@ -319,11 +334,10 @@ suite = {
 
     "FASTR" : {
       "description" : "class files for compiling against FastR in a separate suite",
-      "dependencies" : ["com.oracle.truffle.r.engine", "com.oracle.truffle.r.ffi.impl"],
-      "mainClass" : "com.oracle.truffle.r.engine.shell.RCommand",
+      "dependencies" : ["com.oracle.truffle.r.engine", "com.oracle.truffle.r.launcher", "com.oracle.truffle.r.ffi.impl"],
+      "mainClass" : "com.oracle.truffle.r.launcher.RCommand",
       "exclude" : [
         "truffle:JLINE",
-        "ANTLR-C-3.5",
         "ANTLR-3.5",
         "GNUR",
         "GNU_ICONV",
@@ -334,7 +348,6 @@ suite = {
         "truffle:TRUFFLE_DEBUG",
         "truffle:TRUFFLE_NFI",
         "truffle:TRUFFLE_NFI_NATIVE",
-        "TRUFFLE_R_PARSER_PROCESSOR",
       ],
     },