diff --git a/ci.hocon b/ci.hocon
index 7007030a80ffe1a6200d7ba0e5786c41e5a0bbb7..c2e5265dc7963abcab16d4213ac198b3a96c1a15 100644
--- a/ci.hocon
+++ b/ci.hocon
@@ -13,6 +13,7 @@ java8Downloads : {
   downloads : {
     EXTRA_JAVA_HOMES : { pathlist :[
       ${java7}
+      ${java9}
     ]}
     JAVA_HOME : ${java8}
   }
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 52dd4f23b3776d046974c127c0aeb4970376fb79..371e16066c0e012dc4f5fc198061ad7b30226b0b 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
@@ -51,7 +51,6 @@ 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;
-import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinPackages;
 import com.oracle.truffle.r.nodes.control.BreakException;
@@ -82,18 +81,16 @@ import com.oracle.truffle.r.runtime.RootWithBody;
 import com.oracle.truffle.r.runtime.ThreadTimings;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.Utils.DebugExitException;
-import com.oracle.truffle.r.runtime.VirtualEvalFrame;
 import com.oracle.truffle.r.runtime.context.Engine;
 import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.data.Closure;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
@@ -102,7 +99,6 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.interop.R2Foreign;
 import com.oracle.truffle.r.runtime.interop.R2ForeignNodeGen;
 import com.oracle.truffle.r.runtime.nodes.RNode;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
@@ -434,8 +430,8 @@ final class REngine implements Engine, Engine.Timings {
                 if (result == null) {
                     throw RError.error(RError.SHOW_CALLER, RError.Message.ARGUMENT_MISSING, identifier);
                 }
-            } else if (obj instanceof RLanguage) {
-                result = evalNode(((RLanguage) obj).getRep().asRSyntaxNode(), envir, caller);
+            } else if ((obj instanceof RPairList && ((RPairList) obj).isLanguage())) {
+                result = eval((RPairList) obj, envir, caller);
             } else {
                 result = obj;
             }
@@ -445,7 +441,8 @@ final class REngine implements Engine, Engine.Timings {
 
     @Override
     @TruffleBoundary
-    public Object eval(RLanguage expr, REnvironment envir, RCaller caller) {
+    public Object eval(RPairList expr, REnvironment envir, RCaller caller) {
+        assert expr.isLanguage();
         return expr.getClosure().eval(envir, caller);
     }
 
@@ -455,8 +452,8 @@ final class REngine implements Engine, Engine.Timings {
         Object result = null;
         for (int i = 0; i < expr.getLength(); i++) {
             result = expr.getDataAt(i);
-            if (result instanceof RLanguage) {
-                RLanguage lang = (RLanguage) result;
+            if ((result instanceof RPairList && ((RPairList) result).isLanguage())) {
+                RPairList lang = (RPairList) result;
                 result = eval(lang, frame);
             }
         }
@@ -464,15 +461,10 @@ final class REngine implements Engine, Engine.Timings {
     }
 
     @Override
-    public Object eval(RLanguage expr, MaterializedFrame frame) {
+    public Object eval(RPairList expr, MaterializedFrame frame) {
+        assert expr.isLanguage();
         CompilerAsserts.neverPartOfCompilation();
-        RNode n = (RNode) expr.getRep();
-        // TODO perhaps this ought to be being checked earlier
-        if (n instanceof ConstantNode) {
-            return ((ConstantNode) n).getValue();
-        }
-        Closure closure = expr.getClosure();
-        return closure.eval(frame);
+        return expr.getClosure().eval(frame);
     }
 
     @Override
@@ -505,31 +497,6 @@ final class REngine implements Engine, Engine.Timings {
         return CallRFunctionNode.executeSlowpath(func, rCaller, actualFrame, newArgs, reorderedArgs.getSignature(), null);
     }
 
-    private Object evalNode(RSyntaxElement exprRep, REnvironment envir, RCaller caller) {
-        // we need to copy the node, otherwise it (and its children) will specialized to a specific
-        // frame descriptor and will fail on subsequent re-executions
-        RSyntaxNode n = RContext.getASTBuilder().process(exprRep);
-        RootCallTarget callTarget = doMakeCallTarget(n.asRNode(), RSource.Internal.EVAL_WRAPPER.string, false, false);
-        return evalTarget(callTarget, caller, envir);
-    }
-
-    /**
-     * This is tricky because the {@link Frame} "f" associated with {@code envir} has been
-     * materialized so we can't evaluate in it directly. Instead we create a new
-     * {@link VirtualEvalFrame} that behaves like "f" (delegates most calls to it) but has a
-     * slightly changed arguments array.
-     *
-     * N.B. The implementation should do its utmost to avoid calling this method as it is inherently
-     * inefficient. In particular, in the case where a {@link VirtualFrame} is available, then the
-     * {@code eval} methods that take such a {@link VirtualFrame} should be used in preference.
-     */
-    private static Object evalTarget(RootCallTarget callTarget, RCaller call, REnvironment envir) {
-        // Here we create fake frame that wraps the original frame's context and has an only
-        // slightly changed arguments array (function and callSrc).
-        MaterializedFrame vFrame = VirtualEvalFrame.create(envir.getFrame(), (RFunction) null, call);
-        return callTarget.call(vFrame);
-    }
-
     @Override
     public RootCallTarget makePromiseCallTarget(RNode body, String funName) {
         return doMakeCallTarget(body, funName, false, false);
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 1e8fa828c18417547e78c25d7639c52e43615738..ba76e4063f61dd90997916bd5526997cb46a21fd 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
@@ -28,22 +28,17 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
 
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.frame.Frame;
 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.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;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinRootNode;
@@ -57,19 +52,14 @@ import com.oracle.truffle.r.nodes.control.IfNode;
 import com.oracle.truffle.r.nodes.control.ReplacementDispatchNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode;
-import com.oracle.truffle.r.nodes.function.FunctionExpressionNode;
-import com.oracle.truffle.r.nodes.function.RCallBaseNode;
 import com.oracle.truffle.r.nodes.function.RCallNode;
 import com.oracle.truffle.r.nodes.instrumentation.RInstrumentation;
-import com.oracle.truffle.r.runtime.Arguments;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntimeASTAccess;
-import com.oracle.truffle.r.runtime.RSrcref;
 import com.oracle.truffle.r.runtime.RootWithBody;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.context.Engine;
@@ -77,301 +67,30 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.Closure;
 import com.oracle.truffle.r.runtime.data.RAttributable;
-import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
-import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.RSymbol;
-import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
-import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
-import com.oracle.truffle.r.runtime.nodes.RCodeBuilder.Argument;
 import com.oracle.truffle.r.runtime.nodes.RInstrumentableNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
-import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
- * Implementation of {@link RRuntimeASTAccess}.
- *
- * A note on the "list" aspects of {@link RLanguage}, specified by {@link RAbstractContainer}. In
- * GnuR a language element (LANGSXP) is represented as a pairlist, so the length of the language
- * element is defined to be the length of the pairlist. The goal of this implementation is to
- * emulate the behavior of GnuR by walking the AST.
- *
- * The nodes we are interested in are {@link ReadVariableNode} (symbols), {@link ConstantNode}
- * (constants) and {@link RCallNode} etc., (calls). However, the nodes that are not (but should be)
- * represented as calls, e.g. {@link IfNode} have to be handled specially.
- *
- * Since the AST is a final field (and we assert) immutable in its syntactic essence, we can cache
- * information such as the length here. A Truffle AST has many nodes that are not part of the
- * syntactic essence and we ignore these.
- *
- * This implementation necessarily has to use a lot of {@code instanceof} checks on the node class.
- * However, it is not important enough to warrant refactoring as an {@link RNode} method, (cf
- * deparse). TODO reconsider this.
- *
- * Some examples:
- *
- * <pre>
- * length(quote(f()) == 1
- * length(quote(f(a)) == 2
- * length(quote(a + b)) == 3
- * length(quote(a + f(b))) == 3
- * </pre>
- *
- * Note the last example in particular which shows that the length is not computed from the
- * flattened tree. Rather indexing the third element would produce another language element of
- * length 2.
+ * This class contains functions that need access to actual implementation classes but which are
+ * used in places where there is not dependency on the node project.
  */
 class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
 
-    @TruffleBoundary
-    @Override
-    public RLanguage.RepType getRepType(RLanguage rl) {
-        RSyntaxElement s = RASTUtils.unwrap(rl.getRep()).asRSyntaxNode();
-
-        if (s instanceof RSyntaxCall) {
-            return RLanguage.RepType.CALL;
-        } else if (s instanceof RSyntaxFunction) {
-            return RLanguage.RepType.FUNCTION;
-        } else {
-            throw RInternalError.shouldNotReachHere("unexpected type: " + s.getClass());
-        }
-    }
-
-    @TruffleBoundary
-    @Override
-    public int getLength(RLanguage rl) {
-        RSyntaxElement s = RASTUtils.unwrap(rl.getRep()).asRSyntaxNode();
-
-        if (s instanceof RSyntaxCall) {
-            return ((RSyntaxCall) s).getSyntaxSignature().getLength() + 1;
-        } else if (s instanceof RSyntaxFunction) {
-            return 4;
-        } else {
-            /*
-             * We do not expect RSyntaxConstant and RSyntaxLookup here (see getDataAtAsObject).
-             */
-            throw RInternalError.shouldNotReachHere("unexpected type: " + s.getClass());
-        }
-    }
-
-    @TruffleBoundary
-    @Override
-    public Object getDataAtAsObject(RLanguage rl, final int index) {
-        // index has already been range checked based on getLength
-        RSyntaxElement s = RASTUtils.unwrap(rl.getRep()).asRSyntaxNode();
-
-        RSyntaxElement result;
-        if (s instanceof RSyntaxCall) {
-            RSyntaxCall call = (RSyntaxCall) s;
-            if (index == 0) {
-                result = call.getSyntaxLHS();
-            } else {
-                result = call.getSyntaxArguments()[index - 1];
-                if (result == null) {
-                    result = RSyntaxLookup.createDummyLookup(RSyntaxNode.LAZY_DEPARSE, "", false);
-                }
-            }
-        } else if (s instanceof RSyntaxFunction) {
-            switch (index) {
-                case 0:
-                    result = RSyntaxLookup.createDummyLookup(null, "function", true);
-                    break;
-                case 1:
-                    ArgumentsSignature sig = ((RSyntaxFunction) s).getSyntaxSignature();
-                    RSyntaxElement[] defaults = ((RSyntaxFunction) s).getSyntaxArgumentDefaults();
-
-                    Object list = RNull.instance;
-                    for (int i = sig.getLength() - 1; i >= 0; i--) {
-                        list = RDataFactory.createPairList(defaults[i] == null ? RSymbol.MISSING : RASTUtils.createLanguageElement(defaults[i]), list,
-                                        RDataFactory.createSymbolInterned(sig.getName(i)));
-                    }
-                    return list;
-                case 2:
-                    result = ((RSyntaxFunction) s).getSyntaxBody();
-                    break;
-                case 3:
-                    // srcref
-                    return RSrcref.createLloc(s.getLazySourceSection());
-                default:
-                    throw RInternalError.shouldNotReachHere();
-            }
-        } else {
-            /*
-             * We do not expect RSyntaxConstant and RSyntaxLookup here: RSyntaxConstant should have
-             * been converted to the constant value, and RSyntaxLookup should have been converted to
-             * an RSymbol (see below).
-             */
-            throw RInternalError.shouldNotReachHere("unexpected type: " + s.getClass());
-        }
-
-        /*
-         * Constants and lookups are converted to their intrinsic value:
-         */
-        return RASTUtils.createLanguageElement(result);
-    }
-
-    @Override
-    @TruffleBoundary
-    public Object createLanguageFromList(RList list, RLanguage.RepType repType) {
-        int length = list.getLength();
-        if (length == 0) {
-            return RNull.instance;
-        } else if (repType == RLanguage.RepType.CALL) {
-            RStringVector formals = list.getNames();
-
-            List<RCodeBuilder.Argument<RSyntaxNode>> argList = new ArrayList<>(length - 1);
-            for (int i = 1; i < length; i++) {
-                String formal = formals == null ? null : formals.getDataAt(i);
-                RSyntaxNode syntaxArg = (RSyntaxNode) unwrapToRNode(list.getDataAtAsObject(i), false);
-                if (formal != null) {
-                    argList.add(RCodeBuilder.argument(RSourceSectionNode.LAZY_DEPARSE, formal, syntaxArg));
-                } else {
-                    argList.add(RCodeBuilder.argument(syntaxArg));
-                }
-            }
-
-            RNode fn = unwrapToRNode(list.getDataAtAsObject(0), true);
-            RSyntaxNode call = RContext.getASTBuilder().call(RSourceSectionNode.LAZY_DEPARSE, fn.asRSyntaxNode(), argList);
-            RLanguage result = RDataFactory.createLanguage(Closure.createLanguageClosure(call.asRNode()));
-            if (formals != null && formals.getLength() > 0 && formals.getDataAt(0).length() > 0) {
-                result.setCallLHSName(formals.getDataAt(0));
-            }
-            return addAttributes(result, list);
-        } else if (repType == RLanguage.RepType.FUNCTION) {
-            RAbstractContainer argsList = (RAbstractContainer) list.getDataAt(1);
-            RSyntaxNode body = (RSyntaxNode) unwrapToRNode(list.getDataAt(2), false);
-            List<Argument<RSyntaxNode>> resArgs = new LinkedList<>();
-            RStringVector argsNames = argsList.getNames();
-            for (int i = 0; i < argsList.getLength(); i++) {
-                String argName = argsNames == null ? null : argsNames.getDataAt(i);
-                Object argVal = argsList.getDataAtAsObject(i);
-                Argument<RSyntaxNode> arg = RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, argName, argVal == RSymbol.MISSING ? null : (RSyntaxNode) unwrapToRNode(argVal, false));
-                resArgs.add(arg);
-            }
-            RootCallTarget rootCallTarget = RContext.getASTBuilder().rootFunction(RContext.getInstance().getLanguage(), RSyntaxNode.LAZY_DEPARSE, resArgs, body, null);
-            FunctionExpressionNode fnExprNode = FunctionExpressionNode.create(RSyntaxNode.LAZY_DEPARSE, rootCallTarget);
-            RLanguage result = RDataFactory.createLanguage(Closure.createLanguageClosure(fnExprNode));
-            return addAttributes(result, list);
-        } else {
-            throw RInternalError.shouldNotReachHere("unexpected type");
-        }
-    }
-
-    private static Object addAttributes(RAttributable result, RList list) {
-        DynamicObject attrs = list.getAttributes();
-        if (attrs != null && !attrs.isEmpty()) {
-            result.initAttributes(RAttributesLayout.copy(attrs));
-        }
-        return result;
-    }
-
-    private RNode unwrapToRNode(Object objArg, boolean functionLookup) {
-        Object obj = objArg;
-        // obj is RSymbol or a primitive value.
-        // A symbol needs to be converted back to a ReadVariableNode
-        if (obj instanceof RLanguage) {
-            return (RNode) RASTUtils.unwrap(((RLanguage) obj).getRep());
-        } else if (obj instanceof RSymbol) {
-            return RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, ((RSymbol) obj).getName(), functionLookup).asRNode();
-        } else if (obj instanceof RPromise) {
-            // Evaluate promise and return the result as constant.
-            return ConstantNode.create(forcePromise("unwrapToRNode", objArg));
-        } else {
-            return ConstantNode.create(obj);
-        }
-    }
-
     @Override
-    public RList asList(RLanguage rl) {
-        Object[] data = new Object[getLength(rl)];
-        for (int i = 0; i < data.length; i++) {
-            data[i] = getDataAtAsObject(rl, i);
-        }
-        RStringVector names = getNames(rl);
-        if (names == null) {
-            return RDataFactory.createList(data);
-        } else {
-            return RDataFactory.createList(data, names);
-        }
-    }
-
-    @Override
-    @TruffleBoundary
-    public RStringVector getNames(RLanguage rl) {
-        RBaseNode node = rl.getRep();
-        if (node instanceof RCallNode) {
-            RCallNode call = (RCallNode) node;
-            /*
-             * If the function or any argument has a name, then all arguments (and the function) are
-             * given names, with unnamed arguments getting "". However, if no arguments have names,
-             * the result is NULL (null)
-             */
-            boolean hasName = false;
-            String functionName = "";
-            if (rl.getCallLHSName() != null) {
-                hasName = true;
-                functionName = rl.getCallLHSName();
-            }
-            ArgumentsSignature sig = call.getSyntaxSignature();
-            if (!hasName) {
-                for (int i = 0; i < sig.getLength(); i++) {
-                    if (sig.getName(i) != null) {
-                        hasName = true;
-                        break;
-                    }
-                }
-            }
-            if (!hasName) {
-                return null;
-            }
-            String[] data = new String[sig.getLength() + 1];
-            data[0] = functionName; // function
-            for (int i = 0; i < sig.getLength(); i++) {
-                String name = sig.getName(i);
-                data[i + 1] = name == null ? "" : name;
-            }
-            return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR);
-        } else {
-            return null;
-        }
-    }
-
-    @Override
-    @TruffleBoundary
-    public void setNames(RLanguage rl, RStringVector names) {
-        RNode node = (RNode) rl.getRep();
-        if (node instanceof RCallBaseNode) {
-            RCallBaseNode call = (RCallBaseNode) node;
-            Arguments<RSyntaxNode> args = call.getArguments();
-            ArgumentsSignature sig = args.getSignature();
-            String[] newNames = new String[sig.getLength()];
-            int argNamesLength = names.getLength() - 1;
-            if (argNamesLength > sig.getLength()) {
-                throw RError.error(RError.SHOW_CALLER2, RError.Message.ATTRIBUTE_VECTOR_SAME_LENGTH, "names", names.getLength(), sig.getLength() + 1);
-            }
-            for (int i = 0, j = 1; i < sig.getLength() && j <= argNamesLength; i++, j++) {
-                newNames[i] = names.getDataAt(j);
-            }
-            // copying is already handled by RShareable
-            RCallNode newCall = RCallNode.createCall(RSyntaxNode.INTERNAL, ((RCallBaseNode) node).getFunction(), ArgumentsSignature.get(newNames), args.getArguments());
-            rl.setClosure(Closure.createLanguageClosure(newCall));
-        } else {
-            throw RInternalError.shouldNotReachHere();
-        }
+    public Object createLanguageElement(RSyntaxElement element) {
+        return RASTUtils.createLanguageElement(element);
     }
 
     @Override
@@ -415,7 +134,7 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
     }
 
     @Override
-    public RLanguage getSyntaxCaller(RCaller rl) {
+    public RPairList getSyntaxCaller(RCaller rl) {
         RCaller call = rl;
         while (call.isPromise()) {
             call = call.getParent();
@@ -442,10 +161,11 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
     }
 
     @Override
-    public String getCallerSource(RLanguage rl) {
+    public String getCallerSource(RPairList rl) {
+        assert rl.isLanguage();
         // This checks for the specific structure of replacements
-        RLanguage replacement = ReplacementDispatchNode.getRLanguage(rl);
-        RLanguage elem = replacement == null ? rl : replacement;
+        RPairList replacement = ReplacementDispatchNode.getRLanguage(rl);
+        RPairList elem = replacement == null ? rl : replacement;
         String string = RDeparse.deparse(elem, RDeparse.DEFAULT_CUTOFF, true, RDeparse.KEEPINTEGER, -1);
         return string.split("\n")[0];
     }
@@ -482,11 +202,6 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
         }
     }
 
-    @Override
-    public RSyntaxFunction getSyntaxFunction(RFunction f) {
-        return (FunctionDefinitionNode) f.getTarget().getRootNode();
-    }
-
     private Object findCallerFromFrame(Frame frame) {
         if (frame != null && RArguments.isRFrame(frame)) {
             RCaller caller = RArguments.getCall(frame);
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ListMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ListMR.java
index 17611a0c03a3d658dd229a03d5ae8dcd4802f329..d5fb9c194dd7275331aa0fb98f77dea85d495623 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ListMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ListMR.java
@@ -338,7 +338,7 @@ public class ListMR {
                         @Cached("createKeyInfoNode()") ListKeyInfoImplNode keyInfo) {
             int info = keyInfo.execute(receiver, idx);
             if (unknownIdentifier.profile(!KeyInfo.isExisting(info))) {
-                throw UnknownIdentifierException.raise("" + idx);
+                throw UnknownIdentifierException.raise(String.valueOf(idx));
             }
             initExtractNode();
             // idx + 1 R is indexing from 1
@@ -355,7 +355,7 @@ public class ListMR {
             // let's be consistent at this place, the name should be known to the caller anyway
             int info = keyInfo.execute(receiver, field);
             if (unknownIdentifier.profile(!KeyInfo.isExisting(info))) {
-                throw UnknownIdentifierException.raise("" + field);
+                throw UnknownIdentifierException.raise(field);
             }
             initExtractNode();
             Object value = extract.applyAccessField(receiver, field);
@@ -365,7 +365,7 @@ public class ListMR {
 
         @Fallback
         protected Object read(@SuppressWarnings("unused") TruffleObject receiver, Object field) {
-            throw UnknownIdentifierException.raise("" + field);
+            throw UnknownIdentifierException.raise(String.valueOf(field));
         }
 
         protected ListKeyInfoImplNode createKeyInfoNode() {
@@ -426,23 +426,23 @@ public class ListMR {
     abstract static class ListKeyInfoImplNode extends Node {
         @Child private ExtractVectorNode extractNode;
 
-        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
-
         abstract int execute(TruffleObject receiver, Object idx);
 
         @Specialization
         protected int keyInfo(TruffleObject receiver, int idx,
+                        @Cached("createBinaryProfile()") ConditionProfile outOfBounds,
                         @Cached("createLengthNode()") RLengthNode lenghtNode) {
-            return keyInfo(receiver, (double) idx, lenghtNode);
+            return keyInfo(receiver, (double) idx, outOfBounds, lenghtNode);
         }
 
         @Specialization
         protected int keyInfo(TruffleObject receiver, double idx,
+                        @Cached("createBinaryProfile()") ConditionProfile outOfBounds,
                         @Cached("createLengthNode()") RLengthNode lengthNode) {
 
             int length = lengthNode.executeInteger(receiver);
-            if (unknownIdentifier.profile(idx < 0 || idx >= length)) {
-                return 0;
+            if (outOfBounds.profile(idx < 0 || idx >= length)) {
+                return KeyInfo.NONE;
             }
             initExtractNode();
             return buildKeys(extractNode.apply(receiver, new Object[]{idx + 1}, RLogical.valueOf(false), RMissing.instance));
@@ -450,8 +450,13 @@ public class ListMR {
 
         @Specialization
         protected int keyInfo(TruffleObject receiver, String identifier,
+                        @Cached("createBinaryProfile()") ConditionProfile noNames,
+                        @Cached("createBinaryProfile()") ConditionProfile unknownIdentifier,
                         @Cached("createNamesNode()") GetNamesAttributeNode namesNode) {
             RStringVector names = namesNode.getNames(receiver);
+            if (noNames.profile(names == null)) {
+                return KeyInfo.NONE;
+            }
             boolean exists = false;
             for (int i = 0; i < names.getLength(); i++) {
                 if (identifier.equals(names.getDataAt(i))) {
@@ -460,7 +465,7 @@ public class ListMR {
                 }
             }
             if (unknownIdentifier.profile(!exists)) {
-                return 0;
+                return KeyInfo.NONE;
             }
             initExtractNode();
             return buildKeys(extractNode.applyAccessField(receiver, identifier));
@@ -491,7 +496,7 @@ public class ListMR {
 
         @Fallback
         protected int access(@SuppressWarnings("unused") TruffleObject receiver, @SuppressWarnings("unused") Object field) {
-            return 0;
+            return KeyInfo.NONE;
         }
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
index ecf20060ba621a44f23f0cac080aa7e77d31d5c0..158e2dde6ee39bb4bfbc519097408be78fb09da3 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
@@ -38,11 +38,10 @@ import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RInteger;
 import com.oracle.truffle.r.runtime.data.RInteropScalar;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RS4Object;
@@ -105,8 +104,6 @@ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
             return RPromiseMRForeign.ACCESS;
         } else if (obj instanceof RArgsValuesAndNames) {
             return RArgsValuesAndNamesMRForeign.ACCESS;
-        } else if (obj instanceof RLanguage) {
-            return RLanguageMRForeign.ACCESS;
         } else if (obj instanceof ActiveBinding) {
             return ActiveBindingMRForeign.ACCESS;
         } else if (obj instanceof RInteropScalar) {
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
deleted file mode 100644
index d6f5b6b3f83dffb8e9d5df41452b598bc5e9a25f..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2016, 2018, 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.interop;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.dsl.Cached;
-import com.oracle.truffle.api.dsl.Fallback;
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.interop.CanResolve;
-import com.oracle.truffle.api.interop.KeyInfo;
-import com.oracle.truffle.api.interop.MessageResolution;
-import com.oracle.truffle.api.interop.Resolve;
-import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.UnknownIdentifierException;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
-import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
-import com.oracle.truffle.r.runtime.data.RLanguage;
-import com.oracle.truffle.r.runtime.data.RLogical;
-import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RObject;
-import com.oracle.truffle.r.runtime.interop.R2Foreign;
-import com.oracle.truffle.r.runtime.interop.R2ForeignNodeGen;
-import com.oracle.truffle.r.runtime.interop.RObjectNativeWrapper;
-
-@MessageResolution(receiverType = RLanguage.class)
-public class RLanguageMR {
-
-    @Resolve(message = "HAS_SIZE")
-    public abstract static class RLanguageHasSizeNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RLanguage receiver) {
-            return true;
-        }
-    }
-
-    @Resolve(message = "GET_SIZE")
-    public abstract static class RLanguageGetSizeNode extends Node {
-        protected Object access(RLanguage receiver) {
-            return receiver.getLength();
-        }
-    }
-
-    @Resolve(message = "READ")
-    public abstract static class RLanguageReadNode extends Node {
-        @Child private ReadNode readNode = RLanguageMRFactory.ReadNodeGen.create();
-
-        protected Object access(VirtualFrame frame, RLanguage receiver, Object identifier) {
-            return readNode.execute(frame, receiver, identifier);
-        }
-    }
-
-    @Resolve(message = "KEY_INFO")
-    public abstract static class RLanguageNode extends Node {
-        @Node.Child private KeyInfoNode keyInfoNode = RLanguageMRFactory.KeyInfoNodeGen.create();
-
-        protected Object access(RLanguage receiver, Object obj) {
-            return keyInfoNode.execute(receiver, obj);
-        }
-    }
-
-    @Resolve(message = "IS_POINTER")
-    public abstract static class IsPointerNode extends Node {
-        protected boolean access(@SuppressWarnings("unused") Object receiver) {
-            return false;
-        }
-    }
-
-    @Resolve(message = "TO_NATIVE")
-    public abstract static class ToNativeNode extends Node {
-        protected Object access(RObject receiver) {
-            return new RObjectNativeWrapper(receiver);
-        }
-    }
-
-    @CanResolve
-    public abstract static class RLanguageCheck extends Node {
-
-        protected static boolean test(TruffleObject receiver) {
-            return receiver instanceof RLanguage;
-        }
-    }
-
-    abstract static class ReadNode extends Node {
-        @Child private ExtractVectorNode extract;
-        @Child private R2Foreign r2Foreign;
-
-        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
-
-        abstract Object execute(VirtualFrame frame, RLanguage receiver, Object identifier);
-
-        @Specialization
-        protected Object access(RLanguage receiver, int idx,
-                        @Cached("createKeyInfoNode()") KeyInfoNode keyInfo) {
-
-            int info = keyInfo.execute(receiver, idx);
-            if (unknownIdentifier.profile(!KeyInfo.isExisting(info))) {
-                throw UnknownIdentifierException.raise("" + idx);
-            }
-
-            if (extract == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                extract = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
-            }
-            Object value = extract.apply(receiver, new Object[]{idx + 1}, RLogical.TRUE, RLogical.TRUE);
-            if (value == null) {
-                return RNull.instance;
-            }
-
-            if (r2Foreign == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                r2Foreign = insert(R2ForeignNodeGen.create());
-            }
-            return r2Foreign.execute(value);
-        }
-
-        @Fallback
-        protected Object access(@SuppressWarnings("unused") RLanguage receiver, Object identifier) {
-            throw UnknownIdentifierException.raise("" + identifier);
-        }
-
-        protected static KeyInfoNode createKeyInfoNode() {
-            return RLanguageMRFactory.KeyInfoNodeGen.create();
-        }
-    }
-
-    abstract static class KeyInfoNode extends Node {
-        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
-
-        abstract int execute(RLanguage receiver, Object identifier);
-
-        @Specialization
-        protected int access(RLanguage receiver, int idx) {
-            if (unknownIdentifier.profile(idx < 0 || idx >= receiver.getLength())) {
-                return 0;
-            }
-            // TODO what about writeble/invocable/...
-            return KeyInfo.READABLE;
-        }
-
-        @Fallback
-        protected int access(@SuppressWarnings("unused") RLanguage receiver, @SuppressWarnings("unused") Object identifier) {
-            return 0;
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.ffi.codegen/src/com/oracle/truffle/r/ffi/codegen/FFITestsCodeGen.java b/com.oracle.truffle.r.ffi.codegen/src/com/oracle/truffle/r/ffi/codegen/FFITestsCodeGen.java
index b96c168f538357e4290e5d1f85f92b0bdf72c964..c20b778115b63f5f58be8b11efe363488509f9fb 100644
--- a/com.oracle.truffle.r.ffi.codegen/src/com/oracle/truffle/r/ffi/codegen/FFITestsCodeGen.java
+++ b/com.oracle.truffle.r.ffi.codegen/src/com/oracle/truffle/r/ffi/codegen/FFITestsCodeGen.java
@@ -37,16 +37,16 @@ import com.oracle.truffle.r.ffi.processor.RFFICstring;
 /**
  * Generates 1) C wrapper that calls each RFFI function and converts between SEXP and primitive
  * types, 2) sequence of calls to CALLDEF to register all those functions as ".Call" targets.
- * 
+ *
  * This creates R interface to all applicable RFFI functions. RFFI functions working with raw
  * pointers are excluded.
- * 
+ *
  * The generated code is to be used in testrffi package located in
  * "com.oracle.truffle.r.test.native/packages/testrffi/testrffi".
  */
 public final class FFITestsCodeGen extends CodeGenBase {
     private static final String FUN_PREFIX = "api_";
-    private static final HashSet<String> IGNORE_FUNS = new HashSet<>(Arrays.asList("Rf_duplicate", "SET_TYPEOF_FASTR", "R_ToplevelExec", "R_CleanUp", "R_ParseVector", "octsize", "R_NewHashedEnv"));
+    private static final HashSet<String> IGNORE_FUNS = new HashSet<>(Arrays.asList("Rf_duplicate", "R_ToplevelExec", "R_CleanUp", "R_ParseVector", "octsize", "R_NewHashedEnv"));
 
     public static void main(String[] args) {
         new FFITestsCodeGen().run(args);
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 071912314d8917df3734d2e043ee173d3c0ba41f..e874fcffe4d8e8b7a0048200f7445e1cd6039708 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
@@ -65,6 +65,7 @@ import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.data.NativeDataAccess;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RComplexVector;
@@ -74,12 +75,11 @@ import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RObject;
-import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
 import com.oracle.truffle.r.runtime.data.RRawVector;
@@ -231,7 +231,6 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    @TruffleBoundary
     public Object Rf_findVar(Object symbolArg, Object envArg) {
         return findVarInFrameHelper(envArg, symbolArg, true);
     }
@@ -248,6 +247,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         return findVarInFrameHelper(envArg, symbolArg, false);
     }
 
+    @TruffleBoundary
     private static Object findVarInFrameHelper(Object envArg, Object symbolArg, boolean inherits) {
         if (envArg == RNull.instance) {
             throw RError.error(RError.SHOW_CALLER2, RError.Message.USE_NULL_ENV_DEFUNCT);
@@ -265,6 +265,9 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
                     // env) should not show up
                     return ((RPromise) value).getRawValue();
                 }
+                if (value instanceof RArgsValuesAndNames) {
+                    return ((RArgsValuesAndNames) value).toPairlist();
+                }
                 return value;
             }
             if (!inherits) {
@@ -434,8 +437,9 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
                 return RDataFactory.createRawVector(new byte[ni]);
             case VECSXP:
                 return RDataFactory.createList(ni);
+            case LISTSXP:
             case LANGSXP:
-                return RDataFactory.createLangPairList(ni);
+                return RDataFactory.createPairList(ni, type);
             default:
                 throw unimplemented("unexpected SEXPTYPE " + type);
         }
@@ -588,14 +592,8 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    @TruffleBoundary
-    public Object SET_TYPEOF_FASTR(Object x, int v) {
-        int code = SEXPTYPE.gnuRCodeForObject(x);
-        if (code == SEXPTYPE.LISTSXP.code && v == SEXPTYPE.LANGSXP.code) {
-            return RLanguage.fromList(x, RLanguage.RepType.CALL);
-        } else {
-            throw unimplemented();
-        }
+    public void SET_TYPEOF(Object x, int v) {
+        guaranteeInstanceOf(x, RPairList.class).setType(SEXPTYPE.mapInt(v));
     }
 
     @Override
@@ -715,8 +713,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
 
     @Override
     public Object SETCDR(Object x, Object y) {
-        guaranteeInstanceOf(x, RPairList.class);
-        ((RPairList) x).setCdr(y);
+        guaranteeInstanceOf(x, RPairList.class).setCdr(y);
         return y;
     }
 
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AttributesAccessNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AttributesAccessNodes.java
index 272b93ca537ee356b208279ffb1957407812f559..4ea02bcd09038c0dfab6c2ebf7043416f62d74a4 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AttributesAccessNodes.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AttributesAccessNodes.java
@@ -55,7 +55,6 @@ import com.oracle.truffle.r.runtime.data.RAttributeStorage;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
-import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
@@ -214,12 +213,6 @@ public final class AttributesAccessNodes {
             return SetAttribNodeGen.create();
         }
 
-        @Specialization
-        protected Object doLanguage(RSharingAttributeStorage target, RLanguage attributes,
-                        @Cached("create()") SetAttributeNode setAttribNode) {
-            return doIt(target, getPairList(attributes), setAttribNode);
-        }
-
         @Specialization
         protected Object doIt(RSharingAttributeStorage target, RPairList attributes,
                         @Cached("create()") SetAttributeNode setAttribNode) {
@@ -247,10 +240,5 @@ public final class AttributesAccessNodes {
         private static void clearAttrs(RSharingAttributeStorage target) {
             target.initAttributes(RAttributesLayout.createRAttributes());
         }
-
-        @TruffleBoundary
-        private static RPairList getPairList(RLanguage attributes) {
-            return attributes.getPairList();
-        }
     }
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/CoerceNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/CoerceNodes.java
index 43df7a5efb42a8f754b79b15a2dbe7920b6f0e20..a42c04d1756434feb0298de6f14d5594dfcb975a 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/CoerceNodes.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/CoerceNodes.java
@@ -58,39 +58,51 @@ import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 
 public final class CoerceNodes {
 
-    public abstract static class VectorToPairListNode extends FFIUpCallNode.Arg1 {
+    public static final class VectorToPairListNode extends FFIUpCallNode.Arg1 {
 
-        @Child private CopyOfRegAttributesNode copyRegAttributesNode;
-        @Child private GetNamesAttributeNode getNamesAttributeNode;
+        @Child private CastPairListNode cast = CastPairListNode.create(SEXPTYPE.LISTSXP);
+
+        @Override
+        public Object executeObject(Object value) {
+            return cast.doCast(value);
+        }
+
+        public static VectorToPairListNode create() {
+            return new VectorToPairListNode();
+        }
+    }
+
+    public abstract static class CastPairListNode extends CastNode {
+
+        private final SEXPTYPE type;
+
+        @Child private CopyOfRegAttributesNode copyRegAttributesNode = CopyOfRegAttributesNode.create();
+        @Child private GetNamesAttributeNode getNamesAttributeNode = GetNamesAttributeNode.create();
+
+        protected CastPairListNode(SEXPTYPE type) {
+            this.type = type;
+        }
 
         @Specialization
         protected Object convert(RAbstractVector v) {
-
             RStringVector names = getNamesAttributeNode.getNames(v);
             SEXPTYPE gnurType = SEXPTYPE.gnuRTypeForObject(v);
 
-            RPairList head = null;
-            RPairList prev = null;
+            Object current = RNull.instance;
             assert names == null || names.getLength() == v.getLength();
-            for (int i = 0; i < v.getLength(); i++) {
+            for (int i = v.getLength() - 1; i >= 0; i--) {
                 Object element = v.getDataAtAsObject(i);
                 adjustSharing(v, element);
-                RPairList cur = RDataFactory.createPairList(element, RNull.instance, names != null ? RDataFactory.createSymbol(names.getDataAt(i)) : RNull.instance, gnurType);
-
-                if (prev == null) {
-                    assert head == null;
-                    head = cur;
-                } else {
-                    prev.setCdr(cur);
-                }
-                prev = cur;
+                current = RDataFactory.createPairList(element, current, names != null ? RDataFactory.createSymbol(names.getDataAt(i)) : RNull.instance, gnurType);
             }
-            if (head != null) {
+            if (current != RNull.instance) {
                 // also copy regular attributes
-                copyRegAttributesNode.execute(v, head);
-                return head;
+                RPairList pl = (RPairList) current;
+                copyRegAttributesNode.execute(v, pl);
+                pl.setType(type);
+                pl.allowClosure();
             }
-            return RNull.instance;
+            return current;
         }
 
         private static void adjustSharing(RAbstractVector origin, Object element) {
@@ -110,8 +122,8 @@ public final class CoerceNodes {
             }
         }
 
-        public static VectorToPairListNode create() {
-            return CoerceNodesFactory.VectorToPairListNodeGen.create();
+        public static CastPairListNode create(SEXPTYPE type) {
+            return CoerceNodesFactory.CastPairListNodeGen.create(type);
         }
 
         private static int getSharingLevel(RShareable r) {
@@ -234,9 +246,8 @@ public final class CoerceNodes {
                 case NILSXP:
                     return new CastNullNode();
                 case LISTSXP:
-                    throw RInternalError.unimplemented("Rf_coerceVector unimplemented for PairLists.");
                 case LANGSXP:
-                    throw RInternalError.unimplemented("Rf_coerceVector unimplemented for RLanguage.");
+                    return CastPairListNode.create(type);
                 case ENVSXP:
                     return new EnvironmentCast();
                 case VECSXP:
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ListAccessNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ListAccessNodes.java
index d33dce24251486421bac34e98ff080935c1f10e0..62b743b4f544ed3809dd455a1a94ee73fdccb4f6 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ListAccessNodes.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ListAccessNodes.java
@@ -35,10 +35,9 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypes;
@@ -56,11 +55,6 @@ public final class ListAccessNodes {
             return pl.car();
         }
 
-        @Specialization
-        protected Object car(RLanguage lang) {
-            return lang.getDataAtAsObject(0);
-        }
-
         @Specialization
         protected Object car(RArgsValuesAndNames args) {
             if (args.isEmpty()) {
@@ -101,15 +95,10 @@ public final class ListAccessNodes {
             return pl.cdr();
         }
 
-        @Specialization
-        protected Object cdr(RLanguage lang) {
-            RPairList l = lang.getPairList();
-            return l.cdr();
-        }
-
         @Specialization
         protected Object cdr(RArgsValuesAndNames args) {
-            return args.toPairlist().cdr();
+            // TODO: this is too late - "..." should be converted to pairlist earlier
+            return ((RPairList) args.toPairlist()).cdr();
         }
 
         @Specialization
@@ -177,8 +166,8 @@ public final class ListAccessNodes {
 
     @TypeSystemReference(RTypes.class)
     public static final class SETCADDRNode extends FFIUpCallNode.Arg2 {
-        @Child CDDRNode cddr = CDDRNode.create();
-        @Child SETCARNode setcarNode = SETCARNode.create();
+        @Child private CDDRNode cddr = CDDRNode.create();
+        @Child private SETCARNode setcarNode = SETCARNode.create();
 
         @Override
         public Object executeObject(Object x, Object val) {
@@ -192,8 +181,8 @@ public final class ListAccessNodes {
 
     @TypeSystemReference(RTypes.class)
     public static final class SETCADDDRNode extends FFIUpCallNode.Arg2 {
-        @Child CDDDRNode cdddr = CDDDRNode.create();
-        @Child SETCARNode setcarNode = SETCARNode.create();
+        @Child private CDDDRNode cdddr = CDDDRNode.create();
+        @Child private SETCARNode setcarNode = SETCARNode.create();
 
         @Override
         public Object executeObject(Object x, Object val) {
@@ -207,9 +196,9 @@ public final class ListAccessNodes {
 
     @TypeSystemReference(RTypes.class)
     public static final class SETCAD4RNode extends FFIUpCallNode.Arg2 {
-        @Child CDDDRNode cdddr = CDDDRNode.create();
-        @Child CDRNode cdr = CDRNode.create();
-        @Child SETCARNode setcarNode = SETCARNode.create();
+        @Child private CDDDRNode cdddr = CDDDRNode.create();
+        @Child private CDRNode cdr = CDRNode.create();
+        @Child private SETCARNode setcarNode = SETCARNode.create();
 
         @Override
         public Object executeObject(Object x, Object val) {
@@ -227,12 +216,6 @@ public final class ListAccessNodes {
             return SETCARNodeGen.create();
         }
 
-        @Specialization
-        protected Object doRLang(RLanguage x, Object y) {
-            x.getPairList().setCar(y);
-            return y;
-        }
-
         @Specialization
         protected Object doRPairList(RPairList x, Object y) {
             x.setCar(y);
@@ -340,8 +323,8 @@ public final class ListAccessNodes {
 
     @TypeSystemReference(RTypes.class)
     public static final class CDDDRNode extends FFIUpCallNode.Arg1 {
-        @Child CDDRNode cddr = CDDRNode.create();
-        @Child CDRNode cdr = CDRNode.create();
+        @Child private CDDRNode cddr = CDDRNode.create();
+        @Child private CDRNode cdr = CDRNode.create();
 
         @Override
         public Object executeObject(Object x) {
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RfEvalNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RfEvalNode.java
index a3dd1b686b35e0e3b06c884c2855745ce61812df..cd6d41817b4d91f61a22c6ba51876a49930b52da 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RfEvalNode.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RfEvalNode.java
@@ -41,10 +41,9 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -76,9 +75,9 @@ public abstract class RfEvalNode extends FFIUpCallNode.Arg2 {
         return RContext.getEngine().eval(expr, getEnv(envArg), null);
     }
 
-    @Specialization
+    @Specialization(guards = "expr.isLanguage()")
     @TruffleBoundary
-    Object handleLanguage(RLanguage expr, Object envArg) {
+    Object handleLanguage(RPairList expr, Object envArg) {
         return RContext.getEngine().eval(expr, getEnv(envArg), null);
     }
 
@@ -93,7 +92,7 @@ public abstract class RfEvalNode extends FFIUpCallNode.Arg2 {
         return result;
     }
 
-    @Specialization
+    @Specialization(guards = "!l.isLanguage()")
     Object handlePairList(RPairList l, Object envArg,
                     @Cached("createBinaryProfile()") ConditionProfile isPromiseProfile,
                     @Cached("createBinaryProfile()") ConditionProfile noArgsProfile) {
@@ -142,7 +141,11 @@ public abstract class RfEvalNode extends FFIUpCallNode.Arg2 {
         if (envIsNullProfile.profile(envArg == RNull.instance)) {
             return REnvironment.globalEnv(RContext.getInstance());
         } else if (envArg instanceof REnvironment) {
-            return (REnvironment) envArg;
+            REnvironment env = (REnvironment) envArg;
+            if (env == REnvironment.emptyEnv()) {
+                return RContext.getInstance().stateREnvironment.getEmptyDummy();
+            }
+            return env;
         }
         CompilerDirectives.transferToInterpreter();
         throw RError.error(RError.NO_CALLER, ARGUMENT_NOT_ENVIRONMENT);
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
index e9bbeb09d1c1dce2218199897ece6acd1f77f8a7..c9ba7f60d1362ef3381c342fdf1ff63410142f83 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
@@ -273,7 +273,7 @@ public interface StdUpCallsRFFI {
 
     void SET_NAMED_FASTR(Object x, int v);
 
-    Object SET_TYPEOF_FASTR(Object x, int v);
+    void SET_TYPEOF(Object x, int v);
 
     int TYPEOF(Object x);
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
index 9c2cce59df625173faf89f9847d7fe9208b3901e..e30a62ce54dca40dfb1bad6ae8a66db7bf7f669f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
@@ -8,7 +8,7 @@
  * Copyright (c) 1998--2014, The R Core Team
  * Copyright (c) 2002--2010, The R Foundation
  * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -90,7 +90,7 @@ public final class RGridGraphicsAdapter {
     public static RPairList fixupDevicesVariable() {
         REnvironment baseEnv = REnvironment.baseEnv();
         Object devices = baseEnv.get(DOT_DEVICES);
-        if (devices instanceof RPairList) {
+        if ((devices instanceof RPairList && !((RPairList) devices).isLanguage())) {
             return (RPairList) devices;
         }
         if (devices instanceof RList) {
@@ -151,11 +151,11 @@ public final class RGridGraphicsAdapter {
 
     public static int getDevicesCount() {
         Object dotDevices = REnvironment.baseEnv().get(DOT_DEVICES);
-        return dotDevices instanceof RPairList ? ((RPairList) dotDevices).getLength() : 0;
+        return (dotDevices instanceof RPairList && !((RPairList) dotDevices).isLanguage()) ? ((RPairList) dotDevices).getLength() : 0;
     }
 
     private static boolean contains(Object devices, String name) {
-        if (!(devices instanceof RPairList)) {
+        if (!((devices instanceof RPairList && !((RPairList) devices).isLanguage()))) {
             return false;
         }
         for (RPairList dev : (RPairList) devices) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
index 18e39decc0796987fb30decfd71ae8d5bd9b3c07..351de044af320e907df5f8260c5f0d94467fd47c 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
@@ -55,7 +55,7 @@ import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RS4Object;
@@ -66,6 +66,7 @@ import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 // Transcribed (unless otherwise noted) from src/library/methods/methods_list_dispatch.c
@@ -451,9 +452,9 @@ public class MethodsListDispatch {
             Casts.noCasts(R_nextMethodCall.class);
         }
 
-        @Specialization
+        @Specialization(guards = "matchedCall.isLanguage()")
         @TruffleBoundary
-        protected Object nextMethodCall(RLanguage matchedCall, REnvironment ev) {
+        protected Object nextMethodCall(RPairList matchedCall, REnvironment ev) {
             // TODO: we can't create LocalReadVariableNode-s once and for all because ev may change
             // leading to a problem if contains a different frame; should we finesse implementation
             // of LocalReadVariableNode to handle this?
@@ -468,18 +469,18 @@ public class MethodsListDispatch {
             if (primCase) {
                 throw RInternalError.unimplemented();
             }
-            if (!(matchedCall.getRep() instanceof RCallNode)) {
+            if (!(matchedCall.getSyntaxElement() instanceof RSyntaxCall)) {
                 throw RInternalError.unimplemented();
 
             }
-            RCallNode callNode = (RCallNode) matchedCall.getRep();
+            RSyntaxCall callNode = (RSyntaxCall) matchedCall.getSyntaxElement();
             RNode f = RContext.getASTBuilder().lookup(RSyntaxNode.SOURCE_UNAVAILABLE, RRuntime.R_DOT_NEXT_METHOD, false).asRNode();
             ArgumentsSignature sig = callNode.getSyntaxSignature();
             RSyntaxNode[] args = new RSyntaxNode[sig.getLength()];
             for (int i = 0; i < args.length; i++) {
                 args[i] = RContext.getASTBuilder().lookup(RSyntaxNode.SOURCE_UNAVAILABLE, sig.getName(i), false);
             }
-            RLanguage newCall = RDataFactory.createLanguage(Closure.createLanguageClosure(RCallNode.createCall(RSyntaxNode.SOURCE_UNAVAILABLE, f, sig, args)));
+            RPairList newCall = RDataFactory.createLanguage(Closure.createLanguageClosure(RCallNode.createCall(RSyntaxNode.SOURCE_UNAVAILABLE, f, sig, args)));
             Object res = RContext.getEngine().eval(newCall, ev.getFrame());
             return res;
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
index 20ee2cb8d6d4a1dcce0713f845b96264a5973f43..f203baea0f964643fe6aacdf9ca6dd51713dba2a 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -35,7 +35,7 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RSubstitute;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -56,9 +56,9 @@ public abstract class SubstituteDirect extends RExternalBuiltinNode.Arg2 {
     @Specialization
     @TruffleBoundary
     protected Object substituteDirect(Object object, REnvironment env) {
-        if (object instanceof RLanguage) {
-            RLanguage lang = (RLanguage) object;
-            return RASTUtils.createLanguageElement(RSubstitute.substitute(env, lang.getRep(), getRLanguage()));
+        if ((object instanceof RPairList && ((RPairList) object).isLanguage())) {
+            RPairList lang = (RPairList) object;
+            return RASTUtils.createLanguageElement(RSubstitute.substitute(env, lang.getSyntaxElement(), getRLanguage()));
         } else {
             return object;
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java
index c0183e5841ef8b80453f77a7ce2e3332e32d2d49..90e7af268e83e2f6e680679a14ee6f4a4f2a8b32 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1997-2013,  The R Core Team
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -70,7 +70,7 @@ public final class CompleteCases extends RExternalBuiltinNode {
             Object arg = args.getArgument(i);
             if (arg instanceof RNull) {
                 // nothing to do
-            } else if (arg instanceof RPairList) {
+            } else if ((arg instanceof RPairList && !((RPairList) arg).isLanguage())) {
                 for (Object t = ((RPairList) arg).car(); t != RNull.instance; t = ((RPairList) t).cdr()) {
                     len = checkAbstractVectorLength(len, ((RPairList) t).car());
                 }
@@ -103,7 +103,7 @@ public final class CompleteCases extends RExternalBuiltinNode {
 
         for (int i = 0; i < args.getLength(); i++) {
             Object arg = args.getArgument(i);
-            if (arg instanceof RPairList) {
+            if ((arg instanceof RPairList && !((RPairList) arg).isLanguage())) {
                 for (Object t = ((RPairList) arg).car(); t != RNull.instance; t = ((RPairList) t).cdr()) {
                     Object entry = ((RPairList) t).car();
                     iterateAbstractVectorContents(len, result, entry);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java
index f0d059510dfd53f75059882ad3365224b3d6d9dc..50b06a20e909d40c2d9a3a1bc0fa8e226110b892 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -34,13 +34,12 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.RASTUtils;
-import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RExpression;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
@@ -50,7 +49,7 @@ public abstract class D extends RExternalBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(D.class);
-        casts.arg(0, "expr").mustBe(instanceOf(RExpression.class).or(instanceOf(RLanguage.class)).or(instanceOf(RSymbol.class)).or(numericValue()).or(complexValue()),
+        casts.arg(0, "expr").mustBe(instanceOf(RExpression.class).or(instanceOf(RPairList.class)).or(instanceOf(RSymbol.class)).or(numericValue()).or(complexValue()),
                         RError.Message.INVALID_EXPRESSION_TYPE, typeName());
         casts.arg(1, "namevec").mustBe(stringValue()).asStringVector().mustBe(notEmpty(), RError.Message.GENERIC, "variable must be a character string").shouldBe(size(1),
                         RError.Message.ONLY_FIRST_VARIABLE_NAME).findFirst();
@@ -61,13 +60,13 @@ public abstract class D extends RExternalBuiltinNode.Arg2 {
     }
 
     protected static boolean isConstant(Object expr) {
-        return !(expr instanceof RLanguage || expr instanceof RExpression || expr instanceof RSymbol);
+        return !((expr instanceof RPairList && ((RPairList) expr).isLanguage()) || expr instanceof RExpression || expr instanceof RSymbol);
     }
 
     @Specialization(guards = "isConstant(expr)")
     @TruffleBoundary
     protected Object doD(Object expr, String var) {
-        return doD(ConstantNode.create(expr), var);
+        return doD(RContext.getASTBuilder().constant(RSyntaxNode.LAZY_DEPARSE, expr), var);
     }
 
     @Specialization
@@ -76,10 +75,10 @@ public abstract class D extends RExternalBuiltinNode.Arg2 {
         return doD(RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, expr.getName(), false), var);
     }
 
-    @Specialization
+    @Specialization(guards = "expr.isLanguage()")
     @TruffleBoundary
-    protected Object doD(RLanguage expr, String var) {
-        return doD((RSyntaxElement) expr.getRep(), var);
+    protected Object doD(RPairList expr, String var) {
+        return doD(expr.getSyntaxElement(), var);
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java
index 0c225227f7a5983c1b23bf0c70bbe37b2419bdcd..5bb5eee3326b747a2287785ccb695571ad491566 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1997-2013,  The R Core Team
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -53,13 +53,12 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder.Argument;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -113,12 +112,12 @@ public abstract class Deriv extends RExternalBuiltinNode {
         return DerivNodeGen.create();
     }
 
-    public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5);
+    public abstract Object execute(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5);
 
     @Override
     public Object call(VirtualFrame frame, RArgsValuesAndNames args) {
         checkLength(args, 5);
-        return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4));
+        return execute(castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4));
     }
 
     @Override
@@ -127,43 +126,38 @@ public abstract class Deriv extends RExternalBuiltinNode {
     }
 
     protected static boolean isConstant(Object expr) {
-        return !(expr instanceof RLanguage || expr instanceof RExpression || expr instanceof RSymbol);
+        return !((expr instanceof RPairList && ((RPairList) expr).isLanguage()) || expr instanceof RExpression || expr instanceof RSymbol);
     }
 
     @Specialization(guards = "isConstant(expr)")
-    protected Object derive(VirtualFrame frame, Object expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
-        return derive(frame.materialize(), createConstant(expr), names, functionArg, tag, hessian);
-    }
-
-    @TruffleBoundary
-    private static ConstantNode createConstant(Object expr) {
-        return ConstantNode.create(expr);
+    protected Object derive(Object expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
+        return deriveInternal(RSyntaxConstant.createDummyConstant(RSyntaxNode.INTERNAL, expr), names, functionArg, tag, hessian);
     }
 
     @Specialization
-    protected Object derive(VirtualFrame frame, RSymbol expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
-        return derive(frame.materialize(), createLookup(expr), names, functionArg, tag, hessian);
-    }
-
-    @TruffleBoundary
-    private static RBaseNode createLookup(RSymbol expr) {
-        return (RBaseNode) RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, expr.getName(), false);
+    protected Object derive(RSymbol expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
+        return deriveInternal(RSyntaxLookup.createDummyLookup(RSyntaxNode.INTERNAL, expr.getName(), false), names, functionArg, tag, hessian);
     }
 
     @Specialization
-    protected Object derive(VirtualFrame frame, RExpression expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian,
+    protected Object derive(RExpression expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian,
                     @Cached("create()") Deriv derivNode) {
-        return derivNode.execute(frame, expr.getDataAt(0), names, functionArg, tag, hessian);
+        return derivNode.execute(expr.getDataAt(0), names, functionArg, tag, hessian);
     }
 
-    @Specialization
-    protected Object derive(VirtualFrame frame, RLanguage expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
-        return derive(frame.materialize(), expr.getRep(), names, functionArg, tag, hessian);
+    @Specialization(guards = "expr.isLanguage()")
+    protected Object derive(RPairList expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
+        return deriveInternal(getSyntaxElement(expr), names, functionArg, tag, hessian);
+    }
+
+    @TruffleBoundary
+    private static RSyntaxElement getSyntaxElement(RPairList expr) {
+        return expr.getSyntaxElement();
     }
 
     @TruffleBoundary
-    private Object derive(MaterializedFrame frame, RBaseNode elem, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
-        return findDerive(elem, names, functionArg, tag, hessian).getResult(frame.materialize(), getRLanguage());
+    private Object deriveInternal(RSyntaxElement elem, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
+        return findDerive(elem, names, functionArg, tag, hessian).getResult(getRLanguage(), functionArg);
     }
 
     private static final class DerivResult {
@@ -183,10 +177,11 @@ public abstract class Deriv extends RExternalBuiltinNode {
             result = null;
         }
 
-        private Object getResult(MaterializedFrame frame, TruffleRLanguage language) {
+        private Object getResult(TruffleRLanguage language, Object functionArg) {
             if (result != null) {
                 return result;
             }
+            MaterializedFrame frame = functionArg instanceof RFunction ? ((RFunction) functionArg).getEnclosingFrame() : RContext.getInstance().stateREnvironment.getGlobalFrame();
             RootCallTarget callTarget = RContext.getASTBuilder().rootFunction(language, RSyntaxNode.LAZY_DEPARSE, targetArgs, blockCall, null);
             FrameSlotChangeMonitor.initializeEnclosingFrame(callTarget.getRootNode().getFrameDescriptor(), frame);
             return RDataFactory.createFunction(RFunction.NO_NAME, RFunction.NO_NAME, callTarget, null, frame);
@@ -194,7 +189,7 @@ public abstract class Deriv extends RExternalBuiltinNode {
     }
 
     @TruffleBoundary
-    private DerivResult findDerive(RBaseNode elem, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
+    private DerivResult findDerive(RSyntaxElement elem, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
         LinkedList<RSyntaxNode> exprlist = new LinkedList<>();
         int fIndex = findSubexpression(elem, exprlist, tag);
 
@@ -202,12 +197,12 @@ public abstract class Deriv extends RExternalBuiltinNode {
         int[] dIndex = new int[nderiv];
         int[] d2Index = hessian ? new int[(nderiv * (1 + nderiv)) / 2] : null;
         for (int i = 0, k = 0; i < nderiv; i++) {
-            RBaseNode dExpr = d(elem, names.getDataAt(i));
+            RSyntaxElement dExpr = d(elem, names.getDataAt(i));
             dIndex[i] = findSubexpression(dExpr, exprlist, tag);
 
             if (hessian) {
                 for (int j = i; j < nderiv; j++) {
-                    RBaseNode d2Expr = d(dExpr, names.getDataAt(j));
+                    RSyntaxElement d2Expr = d(dExpr, names.getDataAt(j));
                     d2Index[k] = findSubexpression(d2Expr, exprlist, tag);
                     k++;
                 }
@@ -219,7 +214,7 @@ public abstract class Deriv extends RExternalBuiltinNode {
         if (fIndex > 0) {
             exprlist.add(createLookup(tag + fIndex));
         } else {
-            exprlist.add(cloneElement(elem.asRSyntaxNode()));
+            exprlist.add(cloneElement(elem));
         }
 
         exprlist.add(null);
@@ -232,7 +227,7 @@ public abstract class Deriv extends RExternalBuiltinNode {
                 exprlist.add(createLookup(tag + dIndex[i]));
 
                 if (hessian) {
-                    RBaseNode dExpr = d(elem, names.getDataAt(i));
+                    RSyntaxElement dExpr = d(elem, names.getDataAt(i));
                     for (int j = i; j < nderiv; j++) {
                         if (d2Index[k] > 0) {
                             exprlist.add(createLookup(tag + d2Index[k]));
@@ -245,7 +240,7 @@ public abstract class Deriv extends RExternalBuiltinNode {
             } else {
                 // the first derivative is constant or simple variable
                 // TODO: do not call the d twice
-                RBaseNode dExpr = d(elem, names.getDataAt(i));
+                RSyntaxElement dExpr = d(elem, names.getDataAt(i));
                 exprlist.add((RSyntaxNode) dExpr);
 
                 if (hessian) {
@@ -253,8 +248,8 @@ public abstract class Deriv extends RExternalBuiltinNode {
                         if (d2Index[k] > 0) {
                             exprlist.add(createLookup(tag + d2Index[k]));
                         } else {
-                            RBaseNode d2Expr = d(dExpr, names.getDataAt(j));
-                            if (isZero((RSyntaxElement) d2Expr)) {
+                            RSyntaxElement d2Expr = d(dExpr, names.getDataAt(j));
+                            if (isZero(d2Expr)) {
                                 exprlist.add(null);
                             } else {
                                 exprlist.add((RSyntaxNode) d2Expr);
@@ -357,17 +352,13 @@ public abstract class Deriv extends RExternalBuiltinNode {
 
             return new DerivResult(blockCall, targetArgs);
         } else {
-            RLanguage lan = RDataFactory.createLanguage(Closure.createLanguageClosure(blockCall.asRNode()));
+            RPairList lan = RDataFactory.createLanguage(Closure.createLanguageClosure(blockCall.asRNode()));
             RExpression res = RDataFactory.createExpression(new Object[]{lan});
             return new DerivResult(res);
         }
     }
 
-    private int findSubexpression(RBaseNode expr, List<RSyntaxNode> exprlist, String tag) {
-        if (!(expr instanceof RSyntaxElement)) {
-            throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "FindSubexprs");
-        }
-
+    private int findSubexpression(RSyntaxElement expr, List<RSyntaxNode> exprlist, String tag) {
         RSyntaxVisitor<Integer> vis = new RSyntaxVisitor<Integer>() {
             @Override
             protected Integer visit(RSyntaxCall call) {
@@ -404,7 +395,7 @@ public abstract class Deriv extends RExternalBuiltinNode {
                 throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "FindSubexprs");
             }
         };
-        return vis.accept((RSyntaxElement) expr);
+        return vis.accept(expr);
     }
 
     private static int checkConstant(Object val) {
@@ -490,13 +481,8 @@ public abstract class Deriv extends RExternalBuiltinNode {
         return RContext.getASTBuilder().process(element);
     }
 
-    private static RBaseNode d(RBaseNode expr, String var) {
-        if (!(expr instanceof RSyntaxElement)) {
-            throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "FindSubexprs");
-        }
-
-        RSyntaxVisitor<RSyntaxElement> vis = new DerivVisitor(var);
-        return (RBaseNode) vis.accept((RSyntaxElement) expr);
+    private static RSyntaxElement d(RSyntaxElement expr, String var) {
+        return new DerivVisitor(var).accept(expr);
     }
 
     private static int argsLength(RSyntaxElement elem) {
diff --git a/com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c b/com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c
index 4d6ac072c5ba151c2f0ca47ad22df74a74ad5413..55b83d7b6229fb2825cf549ef0b61c5c67662d2a 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c
+++ b/com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c
@@ -6,7 +6,7 @@
  * Copyright (c) 1995, 1996, 1997  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1995-2014, The R Core Team
  * Copyright (c) 2002-2008, The R Foundation
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -178,9 +178,6 @@ INLINE_FUN SEXP listAppend(SEXP s, SEXP t)
     return s;
 }
 
-
-SEXP SET_TYPEOF_FASTR(SEXP x, int v);
-
 /* Language based list constructs.  These are identical to the list */
 /* constructs, but the results can be evaluated. */
 
@@ -189,7 +186,8 @@ SEXP SET_TYPEOF_FASTR(SEXP x, int v);
 INLINE_FUN SEXP lcons(SEXP car, SEXP cdr)
 {
     SEXP e = cons(car, cdr);
-    return SET_TYPEOF_FASTR(e, LANGSXP);
+    SET_TYPEOF(e, LANGSXP);
+    return e;
 }
 
 INLINE_FUN SEXP lang1(SEXP s)
diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
index c6a6da14a046f9657d850d3ed40e7e8ba5ad780b..04906b42fe95a278277427fc455adb8828c57d3c 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
+++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
@@ -196,7 +196,6 @@ typedef int (*call_NAMED)(SEXP x);
 typedef int (*call_REFCNT)(SEXP x);
 typedef void (*call_SET_OBJECT)(SEXP x, int v);
 typedef void (*call_SET_TYPEOF)(SEXP x, int v);
-typedef SEXP (*call_SET_TYPEOF_FASTR)(SEXP x, int v);
 typedef void (*call_SET_NAMED)(SEXP x, int v);
 typedef void (*call_SET_ATTRIB)(SEXP x, SEXP v);
 typedef void (*call_DUPLICATE_ATTRIB)(SEXP to, SEXP from);
diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
index 28b3d41c7bd2e56a88e9affddb86e9781905b421..71610473d392af86a17fbb8edeb8978174fd9bfb 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
+++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
@@ -262,7 +262,7 @@
 #define SET_STRING_ELT_x 256
 #define SET_SYMVALUE_x 257
 #define SET_TAG_x 258
-#define SET_TYPEOF_FASTR_x 259
+#define SET_TYPEOF_x 259
 #define SET_VECTOR_ELT_x 260
 #define STRING_ELT_x 261
 #define SYMVALUE_x 262
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
index c1e44d5c68a2208a070b400e6a0ab110b3017c3f..8a0a2f31a0f4b84dcbcff439b9e2d00925e4aee7 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
@@ -1223,15 +1223,8 @@ void SET_OBJECT(SEXP x, int v) {
 
 void SET_TYPEOF(SEXP x, int v) {
     TRACE0();
-    // TODO: we will be able to implement this for RLanguage <-> RPairList once they are unified in one Java class
-    unimplemented("SET_TYPEOF");
-}
-
-SEXP SET_TYPEOF_FASTR(SEXP x, int v) {
-    TRACE0();
-    SEXP result = ((call_SET_TYPEOF_FASTR) callbacks[SET_TYPEOF_FASTR_x])(x, v);
+    ((call_SET_TYPEOF) callbacks[SET_TYPEOF_x])(x, v);
     checkExitCall();
-    return result;
 }
 
 void SET_NAMED(SEXP x, int v) {
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c
index 770deeca724b7c9b8a1a43f6fea0058e6e6bbab6..945eba892a2e1d21f660bf3db44fd89c97ca5a23 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c
@@ -60,7 +60,7 @@ static void setupOverrides(void);
 static void *dlopen_jvmlib(char *libpath);
 static JNIEnv* getEnv();
 static jmethodID checkGetMethodID(JNIEnv *env, jclass klass, const char *name, const char *sig, int isStatic);
-static jclass checkFindClass(JNIEnv *env, const char *name);
+static jclass checkFindClass(JNIEnv *env, const char *name, const char* vm_cp);
 static int process_vmargs(int argc, char *argv[], char *vmargv[], char *uargv[]);
 static char **update_environ_with_java_home(void);
 static void print_environ(char **env);
@@ -224,9 +224,9 @@ static int initializeFastR(int argc, char *argv[], int setupRmainloop) {
         return 1;
     }
 
-    rInterfaceCallbacksClass = checkFindClass(jniEnv, "com/oracle/truffle/r/runtime/RInterfaceCallbacks");
-    rembeddedClass = checkFindClass(jniEnv, "com/oracle/truffle/r/engine/shell/REmbedded");
-    jclass stringClass = checkFindClass(jniEnv, "java/lang/String");
+    rInterfaceCallbacksClass = checkFindClass(jniEnv, "com/oracle/truffle/r/runtime/RInterfaceCallbacks", vm_cp);
+    rembeddedClass = checkFindClass(jniEnv, "com/oracle/truffle/r/engine/shell/REmbedded", vm_cp);
+    jclass stringClass = checkFindClass(jniEnv, "java/lang/String", vm_cp);
     jmethodID initializeMethod = checkGetMethodID(jniEnv, rembeddedClass, "initializeR", "([Ljava/lang/String;Z)V", 1);
     jobjectArray argsArray = (*jniEnv)->NewObjectArray(jniEnv, argc, stringClass, NULL);
     for (int i = 0; i < argc; i++) {
@@ -578,13 +578,16 @@ static jmethodID checkGetMethodID(JNIEnv *env, jclass klass, const char *name, c
     return methodID;
 }
 
-static jclass checkFindClass(JNIEnv *env, const char *name) {
+static jclass checkFindClass(JNIEnv *env, const char *name, const char* vm_cp) {
     jclass klass = (*env)->FindClass(env, name);
     if (klass == NULL) {
-        char buf[1024];
+        char buf[16384];
         strcpy(buf, "failed to find class ");
         strcat(buf, name);
+        strcat(buf, " in classpath ");
+        strcat(buf, vm_cp);
         strcat(buf, ".\nDid you set R_HOME to the correct location?");
+        (*env)->ExceptionDescribe(env);
         (*env)->FatalError(env, buf);
     }
     return (*env)->NewGlobalRef(env, klass);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
index 7a73125009e2d2c99480dfcbc6ecb84440a15b55..97779f7aba1e2797c26e0c442a8f2c27dc3d02ef 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -31,13 +31,12 @@ import java.util.HashSet;
 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.RASTUtils;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RExpression;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
@@ -66,19 +65,19 @@ public abstract class AllNames extends RBuiltinNode.Arg4 {
             Object expr = exprs.getDataAt(i);
             if (expr instanceof RSymbol) {
                 visitor.accept(RSyntaxLookup.createDummyLookup(null, ((RSymbol) expr).getName(), false));
-            } else if (expr instanceof RLanguage) {
-                RLanguage lang = (RLanguage) expr;
-                visitor.accept(RASTUtils.unwrap(lang.getRep()).asRSyntaxNode());
+            } else if ((expr instanceof RPairList && ((RPairList) expr).isLanguage())) {
+                RPairList lang = (RPairList) expr;
+                visitor.accept(lang.getSyntaxElement());
             }
         }
         return visitor.getResult();
     }
 
-    @Specialization
+    @Specialization(guards = "expr.isLanguage()")
     @TruffleBoundary
-    protected Object doAllNames(RLanguage expr, byte functions, int maxNames, byte unique) {
+    protected Object doAllNames(RPairList expr, byte functions, int maxNames, byte unique) {
         AllNamesVisitor visitor = new AllNamesVisitor(functions == RRuntime.LOGICAL_TRUE, maxNames, unique == RRuntime.LOGICAL_TRUE);
-        visitor.accept(RASTUtils.unwrap(expr.getRep()).asRSyntaxNode());
+        visitor.accept(expr.getSyntaxElement());
         return visitor.getResult();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
index 7139930df041522007009b725c638afec6a756a6..df7305df9eef1c4aec2251aa40c3352db670e801 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
@@ -32,15 +32,15 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.nodes.function.RCallBaseNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListBaseVector;
+import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 @RBuiltin(name = "as.call", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
@@ -55,9 +55,9 @@ public abstract class AsCall extends RBuiltinNode.Arg1 {
 
     @Specialization
     @TruffleBoundary
-    protected RLanguage asCallFunction(RAbstractListBaseVector x) {
+    protected RPairList asCallFunction(RAbstractListBaseVector x) {
         if (x.getLength() == 0) {
-            error(Message.INVALID_LEN_0_ARG);
+            throw error(Message.INVALID_LEN_0_ARG);
         }
         // separate the first element (call target) from the rest (arguments)
 
@@ -88,13 +88,13 @@ public abstract class AsCall extends RBuiltinNode.Arg1 {
         }
     }
 
-    protected boolean containsCall(RLanguage l) {
-        return l.getRep() instanceof RCallBaseNode;
-    }
-
-    @Specialization(guards = "containsCall(l)")
-    protected RLanguage asCall(RLanguage l) {
-        return l;
+    @Specialization
+    protected Object asCall(RPairList l) {
+        if (l.isLanguage()) {
+            return l;
+        } else {
+            return RPairList.asPairList(l, SEXPTYPE.LANGSXP);
+        }
     }
 
     @Fallback
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
index f996bc6bb45487328c1a51db140550f3f37c045a..998befd07a407ff900566fce99ddb6ba0b2d7a2a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,7 @@ import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -96,8 +96,8 @@ public abstract class AsFunction extends RBuiltinNode.Arg2 {
                     defaultValue = null;
                 } else if (arg == RNull.instance) {
                     defaultValue = RContext.getASTBuilder().constant(RSyntaxNode.LAZY_DEPARSE, RNull.instance).asRNode();
-                } else if (arg instanceof RLanguage) {
-                    defaultValue = (RNode) ((RLanguage) arg).getRep();
+                } else if ((arg instanceof RPairList && ((RPairList) arg).isLanguage())) {
+                    defaultValue = ((RPairList) arg).createNode().asRNode();
                 } else if (arg instanceof RSymbol) {
                     RSymbol symbol = (RSymbol) arg;
                     if (symbol.isMissing()) {
@@ -128,8 +128,8 @@ public abstract class AsFunction extends RBuiltinNode.Arg2 {
 
         RBaseNode body;
         Object bodyObject = x.getDataAtAsObject(x.getLength() - 1);
-        if (bodyObject instanceof RLanguage) {
-            body = (RBaseNode) RContext.getASTBuilder().process(((RLanguage) x.getDataAtAsObject(x.getLength() - 1)).getRep().asRSyntaxNode());
+        if ((bodyObject instanceof RPairList && ((RPairList) bodyObject).isLanguage())) {
+            body = RContext.getASTBuilder().process(((RPairList) x.getDataAtAsObject(x.getLength() - 1)).getSyntaxElement()).asRNode();
         } else if (bodyObject instanceof RSymbol) {
             body = RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, ((RSymbol) bodyObject).getName(), false).asRNode();
         } else {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
index b6747d6c4872dd37c96b7619bc22588fd4c2ac50..3a0a601b0894573b2601b650d3c2ea53c89302c8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
@@ -70,7 +70,6 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RExpression;
-import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RS4Object;
@@ -184,9 +183,13 @@ public abstract class AsVector extends RBuiltinNode.Arg2 {
             throw RError.error(RError.SHOW_CALLER, Message.CANNOT_COERCE, RType.Environment.getName(), type != null ? type.getName() : mode);
         }
 
+        protected static boolean isREnvironment(Object value) {
+            return value instanceof REnvironment;
+        }
+
         // there should never be more than ~12 specializations
         @SuppressWarnings("unused")
-        @Specialization(limit = "99", guards = {"!isEnv(x)", "matchesMode(mode, cachedMode)"})
+        @Specialization(limit = "99", guards = {"!isREnvironment(x)", "matchesMode(mode, cachedMode)"})
         protected Object asVector(Object x, String mode,
                         @Cached("mode") String cachedMode,
                         @Cached("fromMode(cachedMode)") RType type,
@@ -198,11 +201,7 @@ public abstract class AsVector extends RBuiltinNode.Arg2 {
                 if (!RRuntime.isForeignObject(o)) {
                     return cast == null ? o : cast.doCast(o);
                 }
-                if (type == RType.List) {
-                    throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_COERCE_EXTERNAL_OBJECT_TO_VECTOR, "list");
-                } else {
-                    throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_COERCE_EXTERNAL_OBJECT_TO_VECTOR, "vector");
-                }
+                throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_COERCE_EXTERNAL_OBJECT_TO_VECTOR, type == RType.List ? "list" : "vector");
             }
             Object result = x;
             if (x instanceof RS4Object) {
@@ -211,10 +210,6 @@ public abstract class AsVector extends RBuiltinNode.Arg2 {
             return drop.execute(result, cast == null ? x : cast.doCast(result));
         }
 
-        static boolean isEnv(Object x) {
-            return x instanceof REnvironment;
-        }
-
         private Object getS4DataSlot(RS4Object o) {
             if (getS4DataSlotNode == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -260,8 +255,8 @@ public abstract class AsVector extends RBuiltinNode.Arg2 {
                 return profile.profile(o.getAttributes() != null) ? o.copyDropAttributes() : o;
             }
 
-            @Specialization(guards = "o.getAttributes() != null")
-            protected RLanguage drop(@SuppressWarnings("unused") Object original, RLanguage o) {
+            @Specialization(guards = {"o.isLanguage()", "o.getAttributes() != null"})
+            protected RPairList drop(@SuppressWarnings("unused") Object original, RPairList o) {
                 switch (targetType) {
                     case Any:
                     case PairList:
@@ -277,7 +272,7 @@ public abstract class AsVector extends RBuiltinNode.Arg2 {
             }
 
             @Specialization(guards = "pairList.getAttributes() != null")
-            protected Object drop(@SuppressWarnings("unused") Object original, RPairList pairList) {
+            protected Object dropPairList(@SuppressWarnings("unused") Object original, RPairList pairList) {
                 // dropping already done in the cast node CastPairListNode below
                 return pairList;
             }
@@ -334,15 +329,8 @@ public abstract class AsVector extends RBuiltinNode.Arg2 {
             }
 
             @Specialization
-            @TruffleBoundary
-            protected Object doPairList(RPairList list) {
-                return list.copy();
-            }
-
-            @Specialization
-            protected Object doRLanguage(RLanguage language) {
-                // GNUR just let's language be language...
-                return language;
+            protected Object doRLanguage(RPairList pairlist) {
+                return pairlist;
             }
 
             @Fallback
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
index 466d405fd046abc956319982b7ce2e2b0a8b77ca..c603e2fc90eed41f694873549c2ef4be7f3375ab 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
@@ -40,15 +40,16 @@ import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.Closure;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
- * Construct a call object ({@link RLanguage}) from a name and optional arguments.
+ * Construct a call object ({@link RPairList}) from a name and optional arguments.
  *
  * Does not perform argument matching for first parameter "name".
  */
@@ -67,14 +68,15 @@ public abstract class Call extends RBuiltinNode.Arg2 {
 
     @Specialization
     @TruffleBoundary
-    protected RLanguage call(String name, RArgsValuesAndNames args) {
+    protected RPairList call(String name, RArgsValuesAndNames args) {
         return makeCall(getRLanguage(), RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, name, true), args.getArguments(), args.getSignature());
     }
 
     @TruffleBoundary
-    public static RLanguage makeCall(TruffleRLanguage language, RSyntaxNode target, Object[] arguments, ArgumentsSignature signature) {
+    public static RPairList makeCall(TruffleRLanguage language, RSyntaxNode target, Object[] arguments, ArgumentsSignature signature) {
         assert arguments.length == signature.getLength();
-        if (target instanceof RSyntaxLookup && "function".equals(((RSyntaxLookup) target).getIdentifier()) && arguments.length == 2) {
+        if (target instanceof RSyntaxLookup && "function".equals(((RSyntaxLookup) target).getIdentifier()) && arguments.length >= 2 &&
+                        (arguments[1] == RNull.instance || arguments[1] instanceof RPairList)) {
             // this optimization is not strictly necessary, `function` builtin is functional too.
             FunctionExpressionNode function = FunctionBuiltin.createFunctionExpressionNode(language, arguments[0], arguments[1]);
             return RDataFactory.createLanguage(Closure.createLanguageClosure(function.asRNode()));
@@ -84,7 +86,7 @@ public abstract class Call extends RBuiltinNode.Arg2 {
     }
 
     @TruffleBoundary
-    private static RLanguage makeCall0(RSyntaxNode target, Object[] arguments, ArgumentsSignature signature) {
+    private static RPairList makeCall0(RSyntaxNode target, Object[] arguments, ArgumentsSignature signature) {
         RSyntaxNode[] args = new RSyntaxNode[arguments.length];
         for (int i = 0; i < arguments.length; i++) {
             args[i] = (RSyntaxNode) RASTUtils.createNodeForValue(arguments[i]);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java
index c1002705f1527f1de76d9b2759a3f7fd9b165218..a6f99d109689b7196e1029a581c1db854c1d0682 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -52,7 +52,7 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RExpression;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -209,7 +209,7 @@ public abstract class Cat extends RBuiltinNode.Arg6 {
     }
 
     private void validateType(int argIndex, Object obj) {
-        if (obj instanceof RList || obj instanceof RLanguage || obj instanceof RExpression) {
+        if (obj instanceof RList || (obj instanceof RPairList && ((RPairList) obj).isLanguage()) || obj instanceof RExpression) {
             RTypedValue rType = (RTypedValue) obj;
             throw error(Message.CAT_ARGUMENT_OF_TYPE, argIndex, rType.getRType().getName());
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
index c67f195568f87887e16278c1827f7472ef09b915..5f9940f9c0ef0e4ea6ca562a5f07d25f0222946d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
@@ -71,7 +71,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RS4Object;
@@ -121,7 +121,7 @@ public abstract class Combine extends RBuiltinNode.Arg2 {
                         !(args.getArgument(0) instanceof RAbstractVector) &&
                         !(args.getArgument(0) instanceof REnvironment) &&
                         !(args.getArgument(0) instanceof RFunction) &&
-                        !(args.getArgument(0) instanceof RLanguage) &&
+                        !(args.getArgument(0) instanceof RPairList) &&
                         !(args.getArgument(0) instanceof RSymbol) &&
                         !(args.getArgument(0) instanceof RS4Object) &&
                         !RRuntime.isForeignObject(args.getArgument(0));
@@ -238,7 +238,7 @@ public abstract class Combine extends RBuiltinNode.Arg2 {
         for (int i = 0; i < elements.length; i++) {
             CombineInputCast inputCast = getCast(i);
             Object value = args[i];
-            Object element = (exprListPrecedence && value instanceof RLanguage) ? value : cast.doCast(inputCast.cast(value));
+            Object element = (exprListPrecedence && (value instanceof RPairList && ((RPairList) value).isLanguage())) ? value : cast.doCast(inputCast.cast(value));
             element = inputCast.valueProfile.profile(element);
             elements[i] = element;
             size += getElementSize(element);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
index 289fadac02fa12812e51ce2975fe7fcd3d1c499d..5d56afcee2c928d467ea8394658de6d6351dd47c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
@@ -72,8 +72,8 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.PromiseState;
 import com.oracle.truffle.r.runtime.data.RSymbol;
@@ -226,8 +226,8 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
                         } else {
                             argValues[i] = createLookupPromise(promiseFrame, symbol.getName());
                         }
-                    } else if (arg instanceof RLanguage) {
-                        argValues[i] = createLanguagePromise(promiseFrame, (RLanguage) arg);
+                    } else if ((arg instanceof RPairList && ((RPairList) arg).isLanguage())) {
+                        argValues[i] = createLanguagePromise(promiseFrame, (RPairList) arg);
                     }
                 }
             }
@@ -236,9 +236,8 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
         }
 
         @TruffleBoundary
-        private RPromise createLanguagePromise(MaterializedFrame promiseFrame, RLanguage arg) {
-            Closure closure = languagesClosureCache.getOrCreatePromiseClosure(arg.getRep());
-            return RDataFactory.createPromise(PromiseState.Supplied, closure, promiseFrame);
+        private RPromise createLanguagePromise(MaterializedFrame promiseFrame, RPairList arg) {
+            return RDataFactory.createPromise(PromiseState.Supplied, arg.getClosure(languagesClosureCache), promiseFrame);
         }
 
         @TruffleBoundary
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
index 6e8e3aec40fa299d74c4e6a173908e8895098393..324249e38dd0faea4957f0c13ce9ccb2e940f4f1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
@@ -49,7 +49,6 @@ 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.api.profiles.BranchProfile;
-import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
@@ -58,7 +57,6 @@ import com.oracle.truffle.r.nodes.builtin.EnvironmentNodes.GetFunctionEnvironmen
 import com.oracle.truffle.r.nodes.builtin.EnvironmentNodes.RList2EnvNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.EnvFunctionsFactory.CopyNodeGen;
-import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.nodes.function.GetCallerFrameNode;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseDeoptimizeFrameNode;
@@ -75,10 +73,10 @@ import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -340,9 +338,6 @@ public class EnvFunctions {
     @RBuiltin(name = "environment", kind = INTERNAL, parameterNames = {"fun"}, behavior = COMPLEX)
     public abstract static class Environment extends RBuiltinNode.Arg1 {
 
-        private final ConditionProfile attributable = ConditionProfile.createBinaryProfile();
-        @Child private GetFixedAttributeNode getEnvAttrNode;
-
         static {
             Casts.noCasts(Environment.class);
         }
@@ -367,34 +362,21 @@ public class EnvFunctions {
             return getEnv.getEnvironment(fun);
         }
 
-        @Specialization
+        protected static GetFixedAttributeNode createDotEnv() {
+            return GetFixedAttributeNode.create(RRuntime.DOT_ENVIRONMENT);
+        }
+
+        @Specialization(guards = "!isRFunction(value)")
         @TruffleBoundary
-        protected Object environmentLanguage(RLanguage value) {
-            if (ClassHierarchyNode.hasClass(value, RRuntime.FORMULA_CLASS)) {
-                if (getEnvAttrNode == null) {
-                    CompilerDirectives.transferToInterpreterAndInvalidate();
-                    getEnvAttrNode = insert(GetFixedAttributeNode.create(RRuntime.DOT_ENVIRONMENT));
-                }
-                Object result = getEnvAttrNode.execute(value);
-                return result == null ? RNull.instance : result;
-            } else {
-                return environment(value);
-            }
+        protected Object environmentLanguage(RAttributable value,
+                        @Cached("createDotEnv()") GetFixedAttributeNode getEnvAttrNode) {
+            Object result = getEnvAttrNode.execute(value);
+            return result == null ? RNull.instance : result;
         }
 
-        @Specialization(guards = {"!isRNull(value)", "!isRFunction(value)", "!isRLanguage(value)"})
-        protected Object environment(Object value) {
-            if (attributable.profile(value instanceof RAttributable)) {
-                if (getEnvAttrNode == null) {
-                    CompilerDirectives.transferToInterpreterAndInvalidate();
-                    getEnvAttrNode = insert(GetFixedAttributeNode.create(RRuntime.DOT_ENVIRONMENT));
-                }
-                Object attr = getEnvAttrNode.execute(value);
-                return attr == null ? RNull.instance : attr;
-            } else {
-                // Not an error according to GnuR
-                return RNull.instance;
-            }
+        @Fallback
+        protected Object environment(@SuppressWarnings("unused") Object value) {
+            return RNull.instance;
         }
     }
 
@@ -747,8 +729,8 @@ public class EnvFunctions {
             return v.copy();
         }
 
-        @Specialization
-        RLanguage copy(RLanguage l) {
+        @Specialization(guards = "l.isLanguage()")
+        RPairList copy(RPairList l) {
             return l.copy();
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
index 12c2f8e4103696ec9f8fdae8fc157655946cae49..b77b22bbce02f925a39c56ba46a4edfbf855f7bf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -58,11 +58,10 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RExpression;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
@@ -119,7 +118,7 @@ public abstract class Eval extends RBuiltinNode.Arg3 {
             return rList2EnvNode.execute(list, null, null, enclos);
         }
 
-        @Specialization
+        @Specialization(guards = "!list.isLanguage()")
         protected REnvironment cast(RPairList list, REnvironment enclos) {
             lazyCreateRList2EnvNode();
             return rList2EnvNode.execute(list.toRList(), null, null, enclos);
@@ -133,7 +132,7 @@ public abstract class Eval extends RBuiltinNode.Arg3 {
             return rList2EnvNode.execute(list, null, null, REnvironment.baseEnv());
         }
 
-        @Specialization
+        @Specialization(guards = "!list.isLanguage()")
         protected REnvironment cast(RPairList list, @SuppressWarnings("unused") RNull enclos) {
             lazyCreateRList2EnvNode();
 
@@ -171,8 +170,8 @@ public abstract class Eval extends RBuiltinNode.Arg3 {
         casts.arg("enclos").allowNull().mustBe(REnvironment.class);
     }
 
-    @Specialization
-    protected Object doEval(VirtualFrame frame, RLanguage expr, Object envir, Object enclos) {
+    @Specialization(guards = "expr.isLanguage()")
+    protected Object doEval(VirtualFrame frame, RPairList expr, Object envir, Object enclos) {
         REnvironment environment = envCast.execute(frame, envir, enclos);
         RCaller rCaller = getCaller(frame, environment);
         try {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java
index c58f3020137ad9a68eaede21ba87a484355e5688..883333d5b764d031f5de8503dfd5ad5fd4487aad 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.data.RPromise;
 public abstract class Expression extends RBuiltinNode.Arg1 {
     /*
      * Owing to the nonEvalArgs, all arguments are RPromise, but an expression may contain
-     * non-RLanguage elements.
+     * non-RPairList elements.
      */
     private final ConditionProfile isEvaluatedProfile = ConditionProfile.createBinaryProfile();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
index 3ec9be5ccfee7e492d9ce5d8f13779eb1488f683..9cc46a846c6409de9e221fff7a041e45ddc4c7ac 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
@@ -72,9 +72,8 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RLanguage;
-import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
@@ -234,18 +233,18 @@ public class FrameFunctions {
         static {
             Casts casts = new Casts(MatchCall.class);
             casts.arg("definition").mustBe(RFunction.class);
-            casts.arg("call").mustBe(RLanguage.class);
+            casts.arg("call").mustBe(RPairList.class);
             casts.arg("expand.dots").asLogicalVector().findFirst();
             casts.arg("envir").mustBe(REnvironment.class, Message.MUST_BE_ENVIRON, "envir");
         }
 
         @Specialization
-        protected RLanguage matchCall(RFunction definition, Object callObj, byte expandDotsL, REnvironment env) {
+        protected RPairList matchCall(RFunction definition, Object callObj, byte expandDotsL, REnvironment env) {
             /*
              * definition==null in the standard (default) case, in which case we get the RFunction
              * from the calling frame
              */
-            RLanguage call = checkCall(callObj);
+            RPairList call = checkCall(callObj);
             if (expandDotsL == RRuntime.LOGICAL_NA) {
                 throw error(RError.Message.INVALID_ARGUMENT, "expand.dots");
             }
@@ -255,19 +254,19 @@ public class FrameFunctions {
         }
 
         @TruffleBoundary
-        private static RLanguage doMatchCall(MaterializedFrame cframe, RFunction definition, RLanguage call, boolean expandDots) {
+        private static RPairList doMatchCall(MaterializedFrame cframe, RFunction definition, RPairList call, boolean expandDots) {
             /*
              * We have to ensure that all parameters are named, in the correct order, and deal with
              * "...". This process has a lot in common with MatchArguments, which we use as a
              * starting point
              */
-            RCallNode callNode = (RCallNode) RASTUtils.unwrap(call.getRep());
+            RCallNode callNode = (RCallNode) call.getSyntaxElement();
             CallArgumentsNode callArgs = callNode.createArguments(null, false, true);
             ArgumentsSignature inputVarArgSignature = callArgs.containsVarArgsSymbol() ? CallArgumentsNode.getVarargsAndNames(cframe).getSignature() : null;
             RNode[] matchedArgNodes = ArgumentMatcher.matchArguments((RRootNode) definition.getRootNode(), callArgs, inputVarArgSignature, null, null, true).getArguments();
             ArgumentsSignature sig = ((HasSignature) definition.getRootNode()).getSignature();
             // expand any varargs
-            ArrayList<RNode> nodes = new ArrayList<>();
+            ArrayList<RSyntaxNode> nodes = new ArrayList<>();
             ArrayList<String> names = new ArrayList<>();
 
             FrameSlot varArgSlot = cframe.getFrameDescriptor().findFrameSlot(ArgumentsSignature.VARARG_NAME);
@@ -300,7 +299,7 @@ public class FrameFunctions {
 
                     if (expandDots) {
                         for (int i2 = 0; i2 < varArgNodes.length; i2++) {
-                            nodes.add(varArgNodes[i2]);
+                            nodes.add(varArgNodes[i2].asRSyntaxNode());
                             names.add(varArgSignature.getName(i2));
                         }
                     } else {
@@ -329,10 +328,10 @@ public class FrameFunctions {
                         names.add(ArgumentsSignature.VARARG_NAME);
                     }
                 } else if (arg instanceof PromiseNode) {
-                    nodes.add(((PromiseNode) arg).getPromiseExpr().asRNode());
+                    nodes.add(((PromiseNode) arg).getPromiseExpr());
                     names.add(sig.getName(i));
                 } else {
-                    nodes.add(arg);
+                    nodes.add(arg.asRSyntaxNode());
                     names.add(sig.getName(i));
                 }
             }
@@ -377,21 +376,17 @@ public class FrameFunctions {
 
         @Specialization
         @SuppressWarnings("unused")
-        protected RLanguage matchCall(Object definition, Object call, Object expandDots, Object envir) {
+        protected RPairList matchCall(Object definition, Object call, Object expandDots, Object envir) {
             throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
         }
 
-        private RLanguage checkCall(Object obj) throws RError {
+        private RPairList checkCall(Object obj) throws RError {
             Object callObj = obj;
             while (callObj instanceof RExpression) {
                 callObj = ((RExpression) callObj).getDataAt(0);
             }
-            if (callObj instanceof RLanguage) {
-                RLanguage call = (RLanguage) callObj;
-                RNode node = (RNode) RASTUtils.unwrap(call.getRep());
-                if (node instanceof RCallNode) {
-                    return call;
-                }
+            if ((callObj instanceof RPairList && ((RPairList) callObj).isLanguage())) {
+                return (RPairList) callObj;
             }
             throw error(RError.Message.INVALID_ARGUMENT, "call");
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
index 938fc86868755f44f9c7bff182d27f84938a8856..0cdb82aa469d4247cdc8bea6e8709c1b8bebab0e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
@@ -24,6 +24,7 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -33,8 +34,6 @@ 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.LoopNode;
-import com.oracle.truffle.r.nodes.RASTUtils;
-import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
@@ -42,6 +41,7 @@ import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
 import com.oracle.truffle.r.nodes.function.RCallNode;
 import com.oracle.truffle.r.nodes.function.call.CallRFunctionCachedNode;
 import com.oracle.truffle.r.nodes.function.call.CallRFunctionCachedNodeGen;
+import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RCompression;
 import com.oracle.truffle.r.runtime.RError;
@@ -56,9 +56,9 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.PromiseState;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -67,6 +67,11 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
+import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
+import com.oracle.truffle.r.runtime.nodes.RCodeBuilder.Argument;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
  * Private, undocumented, {@code .Internal} and {@code .Primitive} functions transcribed from GnuR,
@@ -103,9 +108,9 @@ public class HiddenInternalFunctions {
          * {@code names}. The value for the name stored as a {@link RPromise} to evaluate the
          * modified call in the {@code eenv} environment.
          */
-        @Specialization
+        @Specialization(guards = "expr.isLanguage()")
         @TruffleBoundary
-        protected RNull doMakeLazy(RAbstractStringVector names, RList values, RLanguage expr, REnvironment eenv, REnvironment aenv) {
+        protected RNull doMakeLazy(RAbstractStringVector names, RList values, RPairList expr, REnvironment eenv, REnvironment aenv) {
             initEval();
             for (int i = 0; i < names.getLength(); i++) {
                 String name = names.getDataAt(i);
@@ -113,9 +118,19 @@ public class HiddenInternalFunctions {
                 // GnuR does an eval but we short cut since intVec evaluates to itself.
                 // What happens next a pretty gross - we replace the "key" argument variable read
                 // in expr with a constant that is the value of intVec
-                RCallNode callNode = (RCallNode) RASTUtils.unwrap(expr.getRep());
-                ConstantNode vecNode = ConstantNode.create(intVec);
-                RCallNode expr0 = RCallNode.createCloneReplacingArgs(callNode, vecNode);
+
+                RSyntaxCall element = (RSyntaxCall) expr.getSyntaxElement();
+                RSyntaxElement[] arguments = element.getSyntaxArguments();
+                ArgumentsSignature signature = element.getSyntaxSignature();
+
+                RCodeBuilder<RSyntaxNode> builder = RContext.getASTBuilder();
+                ArrayList<Argument<RSyntaxNode>> args = new ArrayList<>(arguments.length);
+                args.add(RCodeBuilder.argument(RSyntaxNode.INTERNAL, signature.getName(i), builder.constant(RSyntaxNode.INTERNAL, intVec)));
+                for (int j = 1; j < arguments.length; j++) {
+                    args.add(RCodeBuilder.argument(arguments[j] == null ? null : arguments[j].getLazySourceSection(), signature.getName(j),
+                                    arguments[j] == null ? null : builder.process(arguments[j])));
+                }
+                RCallNode expr0 = (RCallNode) builder.call(element.getLazySourceSection(), builder.process(element.getSyntaxLHS()), args).asRNode();
                 try {
                     // We want this call to have a SourceSection
                     aenv.put(name, RDataFactory.createPromise(PromiseState.Explicit, Closure.createPromiseClosure(expr0), eenv.getFrame()));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java
index ce13c56a758c09b8b6b29cb56b52ea0c23f27872..31f0ac35210691cbe97075186576185c06b82111 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -32,8 +32,8 @@ import com.oracle.truffle.api.CompilerDirectives;
 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.api.object.DynamicObject;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.IterableAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
@@ -46,7 +46,6 @@ import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RInteropScalar;
-import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RListBase;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RS4Object;
@@ -164,14 +163,45 @@ public abstract class Identical extends RBuiltinNode.Arg8 {
     }
 
     private byte identicalAttr(RAttributable x, RAttributable y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment, boolean ignoreSrcref) {
-        // TODO interpret attribAsSet correctly
         DynamicObject xAttributes = x.getAttributes();
         DynamicObject yAttributes = y.getAttributes();
-        if (xAttributes == null && yAttributes == null) {
+        int xSize = xAttributes == null ? 0 : xAttributes.size();
+        int ySize = yAttributes == null ? 0 : yAttributes.size();
+        if (xSize == 0 && ySize == 0) {
             return RRuntime.LOGICAL_TRUE;
-        } else if (xAttributes == null || yAttributes == null) {
+        } else if (xSize != ySize) {
             return RRuntime.LOGICAL_FALSE;
-        } else if (xAttributes.size() == yAttributes.size()) {
+        } else {
+            return identicalAttrInternal(numEq, singleNA, attribAsSet, ignoreBytecode, ignoreEnvironment, ignoreSrcref, xAttributes, yAttributes);
+        }
+    }
+
+    @TruffleBoundary
+    private byte identicalAttrInternal(boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment, boolean ignoreSrcref, DynamicObject xAttributes,
+                    DynamicObject yAttributes) {
+        if (attribAsSet) {
+            // make sure all attributes from x are in y, with identical values
+            Iterator<RAttributesLayout.RAttribute> xIter = attrIterNodeX.execute(xAttributes).iterator();
+            while (xIter.hasNext()) {
+                RAttributesLayout.RAttribute xAttr = xIter.next();
+                Object yValue = yAttributes.get(xAttr.getName());
+                if (yValue == null) {
+                    return RRuntime.LOGICAL_FALSE;
+                }
+                byte res = identicalRecursiveAttr(xAttr.getValue(), yValue, numEq, singleNA, attribAsSet, ignoreBytecode, ignoreEnvironment, ignoreSrcref);
+                if (res == RRuntime.LOGICAL_FALSE) {
+                    return RRuntime.LOGICAL_FALSE;
+                }
+            }
+            // make sure all attributes from y are in x
+            Iterator<RAttributesLayout.RAttribute> yIter = attrIterNodeY.execute(yAttributes).iterator();
+            while (xIter.hasNext()) {
+                RAttributesLayout.RAttribute yAttr = yIter.next();
+                if (!xAttributes.containsKey(yAttr.getName())) {
+                    return RRuntime.LOGICAL_FALSE;
+                }
+            }
+        } else {
             Iterator<RAttributesLayout.RAttribute> xIter = attrIterNodeX.execute(xAttributes).iterator();
             Iterator<RAttributesLayout.RAttribute> yIter = attrIterNodeY.execute(yAttributes).iterator();
             while (xIter.hasNext()) {
@@ -185,9 +215,8 @@ public abstract class Identical extends RBuiltinNode.Arg8 {
                     return RRuntime.LOGICAL_FALSE;
                 }
             }
-            return RRuntime.LOGICAL_TRUE;
         }
-        return RRuntime.LOGICAL_FALSE;
+        return RRuntime.LOGICAL_TRUE;
     }
 
     @SuppressWarnings("unused")
@@ -204,20 +233,6 @@ public abstract class Identical extends RBuiltinNode.Arg8 {
         return RRuntime.asLogical(x.getName() == y.getName());
     }
 
-    @Specialization
-    @TruffleBoundary
-    protected byte doInternalIdentical(RLanguage x, RLanguage y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment, boolean ignoreSrcref) {
-        if (x == y) {
-            return RRuntime.LOGICAL_TRUE;
-        }
-        RSyntaxNode xNode = x.getRep().asRSyntaxNode();
-        RSyntaxNode yNode = y.getRep().asRSyntaxNode();
-        if (!new IdenticalVisitor().accept(xNode, yNode)) {
-            return RRuntime.LOGICAL_FALSE;
-        }
-        return identicalAttr(x, y, numEq, singleNA, attribAsSet, ignoreBytecode, ignoreEnvironment, ignoreSrcref);
-    }
-
     @Specialization
     byte doInternalIdentical(RFunction x, RFunction y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment, boolean ignoreSrcref) {
         if (x == y) {
@@ -300,48 +315,64 @@ public abstract class Identical extends RBuiltinNode.Arg8 {
     }
 
     @Specialization
+    @TruffleBoundary
     protected byte doInternalIdenticalGeneric(RPairList x, RPairList y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment, boolean ignoreSrcref) {
-        if (identicalRecursive(x.car(), y.car(), numEq, singleNA, attribAsSet, ignoreBytecode, ignoreEnvironment, ignoreSrcref) == RRuntime.LOGICAL_FALSE) {
-            return RRuntime.LOGICAL_FALSE;
+        if (x == y) {
+            return RRuntime.LOGICAL_TRUE;
         }
-        Object tmpXCdr = x.cdr();
-        Object tmpYCdr = y.cdr();
-        while (true) {
-            if (RPairList.isNull(tmpXCdr) && RPairList.isNull(tmpYCdr)) {
-                break;
-            } else if (RPairList.isNull(tmpXCdr) || RPairList.isNull(tmpYCdr)) {
+        boolean xHasClosure = x.hasClosure();
+        boolean yHasClosure = y.hasClosure();
+        try {
+            if (identicalRecursive(x.car(), y.car(), numEq, singleNA, attribAsSet, ignoreBytecode, ignoreEnvironment, ignoreSrcref) == RRuntime.LOGICAL_FALSE) {
                 return RRuntime.LOGICAL_FALSE;
-            } else {
-                RPairList xSubList = (RPairList) tmpXCdr;
-                RPairList ySubList = (RPairList) tmpYCdr;
-
-                if (RPairList.isNull(xSubList.getTag()) && RPairList.isNull(ySubList.getTag())) {
+            }
+            Object tmpXCdr = x.cdr();
+            Object tmpYCdr = y.cdr();
+            while (true) {
+                if (RPairList.isNull(tmpXCdr) && RPairList.isNull(tmpYCdr)) {
                     break;
-                } else if (RPairList.isNull(xSubList.getTag()) || RPairList.isNull(ySubList.getTag())) {
+                } else if (RPairList.isNull(tmpXCdr) || RPairList.isNull(tmpYCdr)) {
                     return RRuntime.LOGICAL_FALSE;
                 } else {
-                    if (xSubList.getTag() instanceof RSymbol && ySubList.getTag() instanceof RSymbol) {
-                        String xTagName = ((RSymbol) xSubList.getTag()).getName();
-                        String yTagName = ((RSymbol) ySubList.getTag()).getName();
-                        assert Utils.isInterned(xTagName) && Utils.isInterned(yTagName);
-                        if (xTagName != yTagName) {
-                            return RRuntime.LOGICAL_FALSE;
-                        }
+                    RPairList xSubList = (RPairList) tmpXCdr;
+                    RPairList ySubList = (RPairList) tmpYCdr;
+
+                    if (RPairList.isNull(xSubList.getTag()) && RPairList.isNull(ySubList.getTag())) {
+                        // continue
+                    } else if (RPairList.isNull(xSubList.getTag()) || RPairList.isNull(ySubList.getTag())) {
+                        return RRuntime.LOGICAL_FALSE;
                     } else {
-                        RInternalError.unimplemented("non-RNull and non-RSymbol pairlist tags are not currently supported");
+                        if (xSubList.getTag() instanceof RSymbol && ySubList.getTag() instanceof RSymbol) {
+                            String xTagName = ((RSymbol) xSubList.getTag()).getName();
+                            String yTagName = ((RSymbol) ySubList.getTag()).getName();
+                            assert Utils.isInterned(xTagName) && Utils.isInterned(yTagName);
+                            if (xTagName != yTagName) {
+                                return RRuntime.LOGICAL_FALSE;
+                            }
+                        } else {
+                            throw RInternalError.unimplemented("non-RNull and non-RSymbol pairlist tags are not currently supported");
+                        }
                     }
+                    if (identicalRecursive(xSubList.car(), ySubList.car(), numEq, singleNA, attribAsSet, ignoreBytecode, ignoreEnvironment, ignoreSrcref) == RRuntime.LOGICAL_FALSE) {
+                        return RRuntime.LOGICAL_FALSE;
+                    }
+                    if (xSubList.getAttributes() != null || ySubList.getAttributes() != null) {
+                        throw RInternalError.unimplemented("attributes of internal pairlists are not currently supported");
+                    }
+                    tmpXCdr = ((RPairList) tmpXCdr).cdr();
+                    tmpYCdr = ((RPairList) tmpYCdr).cdr();
                 }
-                if (identicalRecursive(xSubList.car(), ySubList.car(), numEq, singleNA, attribAsSet, ignoreBytecode, ignoreEnvironment, ignoreSrcref) == RRuntime.LOGICAL_FALSE) {
-                    return RRuntime.LOGICAL_FALSE;
-                }
-                if (xSubList.getAttributes() != null || ySubList.getAttributes() != null) {
-                    RInternalError.unimplemented("attributes of internal pairlists are not currently supported");
-                }
-                tmpXCdr = ((RPairList) tmpXCdr).cdr();
-                tmpYCdr = ((RPairList) tmpYCdr).cdr();
+            }
+            return identicalAttr(x, y, numEq, singleNA, attribAsSet, ignoreBytecode, ignoreEnvironment, ignoreSrcref);
+        } finally {
+            // if they were closures before, they can still be afterwards
+            if (xHasClosure) {
+                x.allowClosure();
+            }
+            if (yHasClosure) {
+                y.allowClosure();
             }
         }
-        return identicalAttr(x, y, numEq, singleNA, attribAsSet, ignoreBytecode, ignoreEnvironment, ignoreSrcref);
     }
 
     @SuppressWarnings("unused")
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
index dee51d150d82e3b75710a984716eb785e812ae04..7497a64aeea4d55b8f3beedb75f86997c422f179 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -49,16 +49,13 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RAttributable;
-import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RListBase;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
-import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
@@ -97,7 +94,7 @@ public class IsTypeFunctions {
             return RRuntime.asLogical(isArrayProfile.profile(getDim.isArray(vector)));
         }
 
-        @Specialization(guards = {"!isRMissing(value)", "!isRAbstractVector(value)"})
+        @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
         }
@@ -173,11 +170,11 @@ public class IsTypeFunctions {
         }
 
         @Specialization
-        protected byte isType(@SuppressWarnings("unused") RLanguage lang) {
-            return RRuntime.LOGICAL_TRUE;
+        protected byte isType(RPairList lang) {
+            return RRuntime.asLogical(lang.isLanguage());
         }
 
-        @Specialization(guards = {"!isRLanguage(value)"})
+        @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
         }
@@ -195,11 +192,7 @@ public class IsTypeFunctions {
             return RRuntime.LOGICAL_TRUE;
         }
 
-        protected static boolean isAnyCharacter(Object value) {
-            return value instanceof String || value instanceof RAbstractStringVector;
-        }
-
-        @Specialization(guards = {"!isRMissing(value)", "!isAnyCharacter(value)"})
+        @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
         }
@@ -217,11 +210,7 @@ public class IsTypeFunctions {
             return RRuntime.LOGICAL_TRUE;
         }
 
-        protected static boolean isAnyComplex(Object value) {
-            return value instanceof RComplex || value instanceof RAbstractComplexVector;
-        }
-
-        @Specialization(guards = {"!isRMissing(value)", "!isAnyComplex(value)"})
+        @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
         }
@@ -239,11 +228,7 @@ public class IsTypeFunctions {
             return RRuntime.LOGICAL_TRUE;
         }
 
-        protected static boolean isAnyDouble(Object value) {
-            return value instanceof Double || value instanceof RAbstractDoubleVector;
-        }
-
-        @Specialization(guards = {"!isRMissing(value)", "!isAnyDouble(value)"})
+        @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
         }
@@ -261,7 +246,7 @@ public class IsTypeFunctions {
             return RRuntime.LOGICAL_TRUE;
         }
 
-        @Specialization(guards = {"!isRMissing(value)", "!isRExpression(value)"})
+        @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
         }
@@ -279,7 +264,7 @@ public class IsTypeFunctions {
             return RRuntime.LOGICAL_TRUE;
         }
 
-        @Specialization(guards = {"!isRMissing(value)", "!isRFunction(value)"})
+        @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
         }
@@ -297,11 +282,7 @@ public class IsTypeFunctions {
             return RRuntime.LOGICAL_TRUE;
         }
 
-        protected static boolean isAnyInteger(Object value) {
-            return value instanceof Integer || value instanceof RAbstractIntVector;
-        }
-
-        @Specialization(guards = {"!isRMissing(value)", "!isAnyInteger(value)"})
+        @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
         }
@@ -325,11 +306,11 @@ public class IsTypeFunctions {
         }
 
         @Specialization
-        protected byte isType(@SuppressWarnings("unused") RLanguage value) {
-            return RRuntime.LOGICAL_TRUE;
+        protected byte isType(RPairList value) {
+            return RRuntime.asLogical(value.isLanguage());
         }
 
-        @Specialization(guards = {"!isRMissing(value)", "!isRSymbol(value)", "!isRExpression(value)", "!isRLanguage(value)"})
+        @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
         }
@@ -350,11 +331,11 @@ public class IsTypeFunctions {
         }
 
         @Specialization
-        protected byte isType(@SuppressWarnings("unused") RPairList pl) {
-            return RRuntime.LOGICAL_TRUE;
+        protected byte isType(RPairList pl) {
+            return RRuntime.asLogical(!pl.isLanguage());
         }
 
-        @Specialization(guards = {"!isRMissing(value)", "!isRList(value)", "!isRPairList(value)"})
+        @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
         }
@@ -372,11 +353,7 @@ public class IsTypeFunctions {
             return RRuntime.LOGICAL_TRUE;
         }
 
-        protected static boolean isAnyLogical(Object value) {
-            return value instanceof Byte || value instanceof RAbstractLogicalVector;
-        }
-
-        @Specialization(guards = {"!isRMissing(value)", "!isAnyLogical(value)"})
+        @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
         }
@@ -397,7 +374,7 @@ public class IsTypeFunctions {
             return RRuntime.asLogical(isMatrixProfile.profile(getDim.isMatrix(vector)));
         }
 
-        @Specialization(guards = {"!isRMissing(value)", "!isRAbstractVector(value)"})
+        @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
         }
@@ -415,7 +392,7 @@ public class IsTypeFunctions {
             return RRuntime.LOGICAL_TRUE;
         }
 
-        @Specialization(guards = {"!isRMissing(value)", "!isRSymbol(value)"})
+        @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
         }
@@ -434,14 +411,10 @@ public class IsTypeFunctions {
             return inheritsCheck.execute(o);
         }
 
-        @Specialization(guards = "!isFactor(value)")
-        protected byte isType(@SuppressWarnings("unused") RAbstractIntVector value) {
-            return RRuntime.LOGICAL_TRUE;
-        }
-
-        @Specialization(guards = "isFactor(value)")
-        protected byte isTypeFactor(@SuppressWarnings("unused") RAbstractIntVector value) {
-            return RRuntime.LOGICAL_FALSE;
+        @Specialization
+        protected byte isType(RAbstractIntVector value,
+                        @Cached("createBinaryProfile()") ConditionProfile profile) {
+            return RRuntime.asLogical(!profile.profile(isFactor(value)));
         }
 
         @Specialization
@@ -449,10 +422,6 @@ public class IsTypeFunctions {
             return RRuntime.LOGICAL_TRUE;
         }
 
-        protected static boolean isAnyNumeric(Object value) {
-            return value instanceof Integer || value instanceof Double || value instanceof RAbstractIntVector || value instanceof RAbstractDoubleVector;
-        }
-
         @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
@@ -471,7 +440,7 @@ public class IsTypeFunctions {
             return RRuntime.LOGICAL_TRUE;
         }
 
-        @Specialization(guards = {"!isRMissing(value)", "!isRNull(value)"})
+        @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
         }
@@ -500,7 +469,7 @@ public class IsTypeFunctions {
             return RRuntime.asLogical(getClassNode.isObject(arg));
         }
 
-        @Specialization(guards = {"!isRMissing(value)", "!isRAttributable(value)"})
+        @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
         }
@@ -519,11 +488,11 @@ public class IsTypeFunctions {
         }
 
         @Specialization
-        protected byte isType(@SuppressWarnings("unused") RPairList value) {
-            return RRuntime.LOGICAL_TRUE;
+        protected byte isType(RPairList value) {
+            return RRuntime.asLogical(!value.isLanguage());
         }
 
-        @Specialization(guards = {"!isRMissing(value)", "!isRNull(value)", "!isRPairList(value)"})
+        @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
         }
@@ -541,11 +510,7 @@ public class IsTypeFunctions {
             return RRuntime.LOGICAL_TRUE;
         }
 
-        protected static boolean isAnyRaw(Object value) {
-            return value instanceof RRaw || value instanceof RAbstractRawVector;
-        }
-
-        @Specialization(guards = {"!isRMissing(value)", "!isAnyRaw(value)"})
+        @Fallback
         protected byte isType(@SuppressWarnings("unused") Object value) {
             return RRuntime.LOGICAL_FALSE;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
index 9d7e4eec318c1bfc3eecdda2e843d47cff737805..4f4766c142e1c830f75d33b8cdc4c7d63fd4778e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
@@ -6,7 +6,7 @@
  * Copyright (c) 1995, 1996, 1997  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1995-2014, The R Core Team
  * Copyright (c) 2002-2008, The R Foundation
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -73,7 +73,7 @@ public class LoadSaveFunctions {
                     if (o == RNull.instance) {
                         return RDataFactory.createEmptyStringVector();
                     }
-                    if (!(o instanceof RPairList)) {
+                    if (!((o instanceof RPairList && !((RPairList) o).isLanguage()))) {
                         throw error(RError.Message.GENERIC, "loaded data is not in pair list form");
                     }
                     RPairList vars = (RPairList) o;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
index 953d92bd68749e0dfa19d9e1cfac95283dac0dd9..b35736e7e3754999eb003298b92533a89245a6ae 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
@@ -67,13 +67,12 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
@@ -260,9 +259,8 @@ public abstract class Parse extends RBuiltinNode.Arg6 {
         Object[] srcrefData = new Object[exprs.getLength()];
         for (int i = 0; i < srcrefData.length; i++) {
             Object data = exprs.getDataAt(i);
-            if (data instanceof RLanguage) {
-                RBaseNode node = ((RLanguage) data).getRep();
-                SourceSection ss = node.asRSyntaxNode().getSourceSection();
+            if ((data instanceof RPairList && ((RPairList) data).isLanguage())) {
+                SourceSection ss = ((RPairList) data).getSourceSection();
                 srcrefData[i] = RSrcref.createLloc(ss, srcFile);
             } else if (data instanceof RSymbol) {
                 srcrefData[i] = RNull.instance;
@@ -462,10 +460,9 @@ public abstract class Parse extends RBuiltinNode.Arg6 {
             List<OctetNode> rootOctets = new ArrayList<>();
             for (int i = 0; i < exprLen; i++) {
                 Object x = exprs.getDataAt(i);
-                if (x instanceof RLanguage) {
-                    RBaseNode rep = ((RLanguage) x).getRep();
-                    assert rep instanceof RSyntaxElement;
-                    rootOctets.add(accept((RSyntaxElement) rep));
+                if ((x instanceof RPairList && ((RPairList) x).isLanguage())) {
+                    RSyntaxElement rep = ((RPairList) x).getSyntaxElement();
+                    rootOctets.add(accept(rep));
                 } else if (x instanceof RSymbol) {
                     rootOctets.add(newOctet((RSymbol) x, OctetNode.NO_CHILDREN));
                 } else {
@@ -541,9 +538,11 @@ public abstract class Parse extends RBuiltinNode.Arg6 {
             List<OctetNode> children = new ArrayList<>();
             RSyntaxElement[] args = element.getSyntaxArguments();
             for (int i = from; i < Math.min(args.length, to); i++) {
-                OctetNode argOctet = accept(args[i]);
-                if (argOctet != null) {
-                    children.add(argOctet);
+                if (args[i] != null) {
+                    OctetNode argOctet = accept(args[i]);
+                    if (argOctet != null) {
+                        children.add(argOctet);
+                    }
                 }
             }
             return children;
@@ -559,6 +558,8 @@ public abstract class Parse extends RBuiltinNode.Arg6 {
                 tt = TokenType.NUM_CONST;
             } else if (value instanceof String) {
                 tt = TokenType.STR_CONST;
+            } else if (value instanceof RComplex) {
+                tt = TokenType.NUM_CONST;
             } else if (value == REmpty.instance || value == RMissing.instance) {
                 return null;    // ignored
             } else {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RecordGraphics.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RecordGraphics.java
index 5e744ad5e899f66506406b3ffa0c9536c57a450c..8d57bb6fbb8a91315a6432fadec0932240097aea 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RecordGraphics.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RecordGraphics.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RExpression;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
@@ -55,7 +55,7 @@ public abstract class RecordGraphics extends RBuiltinNode.Arg3 {
 
     static {
         Casts casts = new Casts(RecordGraphics.class);
-        casts.arg("expr").mustBe(instanceOf(RLanguage.class).or(instanceOf(RExpression.class)));
+        casts.arg("expr").mustBe(instanceOf(RPairList.class).or(instanceOf(RExpression.class)));
         casts.arg("list").mustBe(instanceOf(RList.class));
         casts.arg("env").mustBe(instanceOf(REnvironment.class));
     }
@@ -64,8 +64,8 @@ public abstract class RecordGraphics extends RBuiltinNode.Arg3 {
         return RecordGraphicsNodeGen.create();
     }
 
-    @Specialization
-    protected Object doEval(VirtualFrame frame, RLanguage expr, RList list, REnvironment env) {
+    @Specialization(guards = "expr.isLanguage()")
+    protected Object doEval(VirtualFrame frame, RPairList expr, RList list, REnvironment env) {
         RCaller rCaller = RCaller.create(frame, getOriginalCall());
         try {
             return RContext.getEngine().eval(expr, createEnv(list, env), rCaller);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
index b36d37b4337ef084bfe0f07a1def52c089b4e6e9..ad80f28418e303f69342b31b8faa3706b22beea1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
@@ -38,10 +38,10 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.control.IfNode;
 import com.oracle.truffle.r.runtime.RSubstitute;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
@@ -98,7 +98,7 @@ public abstract class Substitute extends RBuiltinNode.Arg2 {
      * @param expr
      * @param env {@code null} if the {@code env} argument was {@code RMissing} to avoid always
      *            materializing the current frame.
-     * @return in general an {@link RLanguage} instance, but simple cases could be a constant value
+     * @return in general an {@link RPairList} instance, but simple cases could be a constant value
      *         or {@link RSymbol}
      */
     private Object doSubstituteWithEnv(RPromise expr, REnvironment env) {
@@ -114,7 +114,7 @@ public abstract class Substitute extends RBuiltinNode.Arg2 {
 
         // The "expr" promise comes from the no-evalarg aspect of the builtin,
         // so get the actual expression (AST) from that
-        return RASTUtils.createLanguageElement(RSubstitute.substitute(env, expr.getRep(), getRLanguage()));
+        return RASTUtils.createLanguageElement(RSubstitute.substitute(env, expr.getClosure().getSyntaxElement(), getRLanguage()));
     }
 
     protected static RList2EnvNode createList2EnvNode() {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
index 3d79c24d362d9fe64208b872ee71a1675a179680..4ec423b9483099075021813f059797da88376c90 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
@@ -48,10 +48,9 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
@@ -89,8 +88,8 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
 
         @Child private RLengthNode lengthNode;
 
-        @Specialization
-        protected int getLength(@SuppressWarnings("unused") RLanguage l) {
+        @Specialization(guards = "l.isLanguage()")
+        protected int getLength(@SuppressWarnings("unused") RPairList l) {
             // language object do not get expanded - as such their length for the purpose of unlist
             // is 1
             return 1;
@@ -131,8 +130,8 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
             return 0;
         }
 
-        @Specialization
-        protected int getLength(@SuppressWarnings("unused") RLanguage l) {
+        @Specialization(guards = "l.isLanguage()")
+        protected int getLength(@SuppressWarnings("unused") RPairList l) {
             // language object do not get expanded - as such their length for the purpose of unlist
             // is 1
             return 1;
@@ -167,7 +166,7 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
             return vector instanceof RList;
         }
 
-        @Specialization
+        @Specialization(guards = "!list.isLanguage()")
         protected int getLengthPairList(RPairList list) {
             int totalSize = 0;
             for (RPairList item : list) {
@@ -276,12 +275,6 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
         return RNull.instance;
     }
 
-    @SuppressWarnings("unused")
-    @Specialization(guards = "isEmpty(list)")
-    protected RNull unlistEmptyList(RPairList list, boolean recursive, boolean useNames) {
-        return RNull.instance;
-    }
-
     // TODO: initially unlist was on the slow path - hence initial recursive implementation is on
     // the slow path as well; ultimately we may consider (non-recursive) optimization
     @Specialization(guards = "!isEmpty(list)")
@@ -305,8 +298,9 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
         }
     }
 
-    @Specialization(guards = "!isEmpty(list)")
+    @Specialization(guards = "!list.isLanguage()")
     protected Object unlistPairList(RPairList list, boolean recursive, boolean useNames) {
+        assert !isEmpty(list) : "pairlist should never be empty";
         // TODO: unlist((pairlist(pairlist(1)), recursive=FALSE), see unit tests
         // Note: currently, we convert to list any pair-list that we encounter along the way, this
         // is sub-optimal, but the assumption is that pair-lists do not show up a lot
@@ -1054,6 +1048,6 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
     }
 
     private static Object handlePairList(Object o) {
-        return o instanceof RPairList ? ((RPairList) o).toRList() : o;
+        return (o instanceof RPairList && !((RPairList) o).isLanguage()) ? ((RPairList) o).toRList() : o;
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java
index cb883dd4d41421465ce4b4ed4a00c8d28e6e8e35..b2130321c4f8f4dff4b3f44a77286d58b43d4b4f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -36,6 +36,7 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 
 @RBuiltin(name = "vector", kind = INTERNAL, parameterNames = {"mode", "length"}, behavior = PURE)
 public abstract class Vector extends RBuiltinNode.Arg2 {
@@ -76,7 +77,7 @@ public abstract class Vector extends RBuiltinNode.Arg2 {
     // RAbstractVector. Note2: pair list of size == 0 is RNull -> we have to return Object.
     private static Object createType(RType type, int length) {
         if (type == RType.PairList) {
-            return RDataFactory.createPairList(length);
+            return RDataFactory.createPairList(length, SEXPTYPE.LISTSXP);
         }
         return type.create(length, false);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
index adc9076fd6b91177070fe04b597ced131219d695..36d6177e4497ba1e0d34aba3b4c20f0974ffa431 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -42,7 +42,6 @@ import com.oracle.truffle.r.nodes.helpers.AccessListField;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
-import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.builtins.RSpecialFactory;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -87,7 +86,7 @@ public abstract class AccessField extends RBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(AccessField.class);
-        casts.arg(1).defaultError(Message.INVALID_SUBSCRIPT_TYPE, RType.Language.getName()).mustBe(stringValue()).asStringVector().findFirst();
+        casts.arg(1).defaultError(Message.INVALID_SUBSCRIPT_TYPE, "language").mustBe(stringValue()).asStringVector().findFirst();
     }
 
     public static RNode createSpecial(ArgumentsSignature signature, RNode[] arguments, @SuppressWarnings("unused") boolean inReplacement) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java
index e5366c429bcfca8aaab5c7cfd18b306064f37039..918c3e637c1145ffcce156adccfc9e8ea6f2887f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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,7 +39,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.Closure;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -75,7 +75,7 @@ public abstract class Tilde extends RBuiltinNode.Arg2 {
     }
 
     @Specialization
-    protected RLanguage tilde(VirtualFrame frame, Object x, Object y) {
+    protected RPairList tilde(VirtualFrame frame, Object x, Object y) {
 
         if (setEnvAttrNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -85,7 +85,7 @@ public abstract class Tilde extends RBuiltinNode.Arg2 {
         RCallNode call = createCall(x, y);
 
         // Do not cache the closure because formulas are usually not evaluated.
-        RLanguage lang = RDataFactory.createLanguage(Closure.createLanguageClosure(call));
+        RPairList lang = RDataFactory.createLanguage(Closure.createLanguageClosure(call));
         setClassAttrNode.execute(lang, FORMULA_CLASS);
         REnvironment env = REnvironment.frameToEnvironment(frame.materialize());
         setEnvAttrNode.execute(lang, env);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LanguagePrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LanguagePrinter.java
index bc050bed9d46661b295b32889e4b192304e8daa8..401b28c2f0aee0b9fb88d8dff4699ee7cc52f4cb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LanguagePrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LanguagePrinter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -26,9 +26,9 @@ import java.io.IOException;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RDeparse;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 
-final class LanguagePrinter extends AbstractValuePrinter<RLanguage> {
+final class LanguagePrinter extends AbstractValuePrinter<RPairList> {
 
     static final LanguagePrinter INSTANCE = new LanguagePrinter();
 
@@ -38,7 +38,7 @@ final class LanguagePrinter extends AbstractValuePrinter<RLanguage> {
 
     @Override
     @TruffleBoundary
-    protected void printValue(RLanguage language, PrintContext printCtx) throws IOException {
+    protected void printValue(RPairList language, PrintContext printCtx) throws IOException {
         printCtx.output().print(RDeparse.deparse(language, RDeparse.DEFAULT_CUTOFF, true, RDeparse.KEEPINTEGER, -1));
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
index 4fa95a508ed285bc4b6c9a80ccd6183c0d5d2677..305d7ad9bcf8ad14042613b1452e9d6a1f683dcd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
@@ -25,7 +25,7 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
@@ -128,7 +128,7 @@ final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> {
                 pbuf = "Raw," + ((RAbstractRawVector) (tmp)).getLength();
             } else if (tmp instanceof RAbstractListVector) {
                 pbuf = "List," + ((RAbstractListVector) (tmp)).getLength();
-            } else if (tmp instanceof RLanguage) {
+            } else if ((tmp instanceof RPairList && ((RPairList) tmp).isLanguage())) {
                 pbuf = "Expression";
             } else {
                 pbuf = "?";
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java
index c73fabdda712ae98656ae584182d7289738e7341..d6e624ff9c392ea4da395f71878a3fe7093a7c43 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1997-2013,  The R Core Team
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -16,9 +16,8 @@ import java.io.IOException;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RLanguage;
-import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
@@ -68,7 +67,7 @@ final class PairListPrinter extends AbstractValuePrinter<RPairList> {
                     pbuf = "Raw," + ((RAbstractContainer) tmp).getLength();
                 } else if (tmp instanceof RAbstractListVector) {
                     pbuf = "List," + ((RAbstractContainer) tmp).getLength();
-                } else if (tmp instanceof RLanguage) {
+                } else if ((tmp instanceof RPairList && ((RPairList) tmp).isLanguage())) {
                     pbuf = "Expression";
                 } else {
                     pbuf = "?";
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
index c3278b4310ed49742d6456bf8a5c006b1a26d6b3..7636090ea9eecd705efebf9ac1348c80062cb45a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -37,7 +37,6 @@ import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RInteropScalar;
-import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RS4Object;
@@ -63,10 +62,8 @@ final class ValuePrinters implements ValuePrinter<Object> {
         printers.put(RSymbol.class, SymbolPrinter.INSTANCE);
         printers.put(RFunction.class, FunctionPrinter.INSTANCE);
         printers.put(RExpression.class, ExpressionPrinter.INSTANCE);
-        printers.put(RLanguage.class, LanguagePrinter.INSTANCE);
         printers.put(RExternalPtr.class, ExternalPtrPrinter.INSTANCE);
         printers.put(RS4Object.class, S4ObjectPrinter.INSTANCE);
-        printers.put(RPairList.class, PairListPrinter.INSTANCE);
     }
 
     @SuppressWarnings({"rawtypes", "unchecked"})
@@ -106,6 +103,8 @@ final class ValuePrinters implements ValuePrinter<Object> {
                     printer = RArgsValuesAndNamesPrinter.INSTANCE;
                 } else if (x instanceof REnvironment) {
                     printer = EnvironmentPrinter.INSTANCE;
+                } else if (x instanceof RPairList) {
+                    printer = ((RPairList) x).isLanguage() ? LanguagePrinter.INSTANCE : PairListPrinter.INSTANCE;
                 } else if (x instanceof TruffleObject) {
                     assert !(x instanceof RTypedValue);
                     printer = TruffleObjectPrinter.INSTANCE;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSourceInfo.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSourceInfo.java
index fd2d891411ccaa621e96578318781d76e32cebbb..fa4f21a4b9914092bad1f0052d195550dcf4b3f3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSourceInfo.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSourceInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -29,15 +29,14 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 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.api.nodes.Node;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBehavior;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
 
 /**
  * Allows to show the actual location of the source section of a provided function.
@@ -47,30 +46,30 @@ public abstract class FastRSourceInfo extends RBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(FastRSourceInfo.class);
-        casts.arg("fun").defaultError(RError.Message.GENERIC, "Only functions are allowed.").mustBe(instanceOf(RFunction.class).or(instanceOf(RLanguage.class)));
+        casts.arg("fun").defaultError(RError.Message.GENERIC, "Only functions are allowed.").mustBe(instanceOf(RFunction.class).or(instanceOf(RPairList.class)));
     }
 
     @Specialization
+    @TruffleBoundary
     public Object srcInfo(RFunction fun) {
-        return srcInfo(fun.getRootNode());
+        return syntaxSrcInfo(fun.getRootNode().getSourceSection());
     }
 
-    @Specialization
-    public Object srcInfo(RLanguage fun) {
-        return srcInfo(fun.getRep());
+    @Specialization(guards = "fun.isLanguage()")
+    @TruffleBoundary
+    public Object srcInfo(RPairList fun) {
+        return syntaxSrcInfo(fun.getSourceSection());
     }
 
-    @TruffleBoundary
-    private static Object srcInfo(Node fun) {
-        SourceSection ss = fun.getSourceSection();
-        if (ss != null) {
-            String path = ss.getSource().getPath();
+    private static Object syntaxSrcInfo(SourceSection source) {
+        if (source != null) {
+            String path = source.getSource().getPath();
             if (path != null) {
-                return path + "#" + ss.getStartLine();
-            } else if (ss.getSource().getURI() != null) {
-                return ss.getSource().getURI() + "#" + ss.getStartLine();
+                return path + "#" + source.getStartLine();
+            } else if (source.getSource().getURI() != null) {
+                return source.getSource().getURI() + "#" + source.getStartLine();
             } else {
-                return ss.getSource().getName();
+                return source.getSource().getName();
             }
         }
         return RNull.instance;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
index 437fa5d89b4e6599a42719f10aed54d698d520ca..c37917e34bd629c8ccc6fb4eebdb979ec3cf16a8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
@@ -55,7 +55,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.Closure;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
@@ -168,16 +168,15 @@ public class FastRTrace {
             return Utils.toString(func);
         }
 
-        @SuppressWarnings("unused")
         @TruffleBoundary
-        private void complexCase(RFunction func, Object tracerObj, Object exit, Object at, boolean print, Object signature) {
+        private void complexCase(RFunction func, Object tracerObj, @SuppressWarnings("unused") Object exit, Object at, boolean print, @SuppressWarnings("unused") Object signature) {
             // the complex case
-            RLanguage tracer;
+            RPairList tracer;
             if (tracerObj instanceof RFunction) {
                 Closure closure = Closure.createLanguageClosure(RASTUtils.createCall(tracerObj, false, ArgumentsSignature.empty(0)).asRNode());
                 tracer = RDataFactory.createLanguage(closure);
-            } else if (tracerObj instanceof RLanguage) {
-                tracer = (RLanguage) tracerObj;
+            } else if ((tracerObj instanceof RPairList && ((RPairList) tracerObj).isLanguage())) {
+                tracer = (RPairList) tracerObj;
             } else {
                 throw error(RError.Message.GENERIC, "tracer is unexpected type");
             }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java
index bdf06d0ff098aa05d5d622e729821934a8df48c3..72c99139236f988e32c49eb8cf47458bedabe009 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java
@@ -44,7 +44,7 @@ import com.oracle.truffle.r.runtime.RSuicide;
 import com.oracle.truffle.r.runtime.conn.StdConnections;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 
 /**
@@ -95,7 +95,7 @@ public class TraceHandling {
         }
     }
 
-    public static boolean enableStatementTrace(RFunction func, RLanguage tracer, Object at, boolean print) {
+    public static boolean enableStatementTrace(RFunction func, RPairList tracer, Object at, boolean print) {
         @SuppressWarnings("unchecked")
         EventBinding<TraceEventListener> binding = (EventBinding<TraceEventListener>) RContext.getInstance().stateInstrumentation.getTraceBinding(RInstrumentation.getSourceSection(func));
         if (binding != null) {
@@ -198,10 +198,10 @@ public class TraceHandling {
      * entry.
      */
     private static class TracerFunctionEntryEventListener extends TraceEventListener {
-        private final RLanguage tracer;
+        private final RPairList tracer;
         private final boolean print;
 
-        TracerFunctionEntryEventListener(RLanguage tracer, boolean print) {
+        TracerFunctionEntryEventListener(RPairList tracer, boolean print) {
             this.tracer = tracer;
             this.print = print;
         }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java
index c275686083061f5b5670e5f9068ff438b60a71fb..efad5a55a6231d6fcd0530ed593b43717a2fa75e 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java
@@ -75,7 +75,6 @@ import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDouble;
-import com.oracle.truffle.r.runtime.data.RDoubleSequence;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RIntSequence;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/DefaultArgsExtractor.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/DefaultArgsExtractor.java
index 1debf3f9419d4dffcc5897a8297af5e66d683c32..66ee87d6d1e734a7d5e5ee0a149c8cb83fa88991 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/DefaultArgsExtractor.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/DefaultArgsExtractor.java
@@ -32,9 +32,8 @@ import com.oracle.truffle.r.nodes.casts.Samples;
 import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
-import com.oracle.truffle.r.runtime.data.RLanguage;
-import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
@@ -74,7 +73,7 @@ class DefaultArgsExtractor {
                     String name = names.getDataAt(i);
                     Object defVal = formals.getDataAtAsObject(i);
 
-                    if (defVal instanceof RLanguage) {
+                    if ((defVal instanceof RPairList && ((RPairList) defVal).isLanguage())) {
                         String deparsedDefVal = RDeparse.deparse(defVal);
                         try {
                             Value eval = context.eval(FastRSession.createSource(deparsedDefVal, RSource.Internal.UNIT_TEST.string));
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java
index a6d4cfd2fc01d32062205eb99598bfdda1c20858..243a5e9e83510806ab7a5f15bc398e09c7b1d9f3 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -33,13 +33,16 @@ import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RootWithBody;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RExpression;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
+import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor;
 
 public class SpecialCallTest extends TestBase {
@@ -291,8 +294,9 @@ public class SpecialCallTest extends TestBase {
         RExpression testExpression = testVMContext.getThisEngine().parse(testSource);
         assert setupExpression.getLength() == 1;
         assert testExpression.getLength() == 1;
-        RootCallTarget setupCallTarget = testVMContext.getThisEngine().makePromiseCallTarget(((RLanguage) setupExpression.getDataAt(0)).getRep().asRSyntaxNode().asRNode(), "test");
-        RootCallTarget testCallTarget = testVMContext.getThisEngine().makePromiseCallTarget(((RLanguage) testExpression.getDataAt(0)).getRep().asRSyntaxNode().asRNode(), "test");
+        RCodeBuilder<RSyntaxNode> builder = RContext.getASTBuilder();
+        RootCallTarget setupCallTarget = testVMContext.getThisEngine().makePromiseCallTarget(builder.process(((RPairList) setupExpression.getDataAt(0)).getSyntaxElement()).asRNode(), "test");
+        RootCallTarget testCallTarget = testVMContext.getThisEngine().makePromiseCallTarget(builder.process(((RPairList) testExpression.getDataAt(0)).getSyntaxElement()).asRNode(), "test");
 
         try {
             CountCallsVisitor count1 = new CountCallsVisitor(testCallTarget);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java
index b682b1268a7c728e81af732e330ffea1e96c43bc..f10eff707bcacd3482af60843bcabd72fc4eb580 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java
@@ -200,7 +200,7 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> {
     @Override
     public ArrayList<Argument<RSyntaxNode>> getFunctionExprArgs(Object args) {
         CompilerAsserts.neverPartOfCompilation();
-        if (!(args instanceof RPairList || args == RNull.instance)) {
+        if (!((args instanceof RPairList && !((RPairList) args).isLanguage()) || args == RNull.instance)) {
             throw RError.error(RError.SHOW_CALLER, Message.INVALID_FORMAL_ARG_LIST, "function");
         }
         ArrayList<Argument<RSyntaxNode>> finalArgs = new ArrayList<>();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java
index ed58d2311b2c90105134cad2a1fd45e97ce7c9cd..f51c7bb75cc27e76c61672816d6c3f539bfb79d6 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java
@@ -56,10 +56,9 @@ import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
@@ -206,24 +205,7 @@ public final class RASTUtils {
             }
             return RASTUtils.cloneNode(promiseRep);
         } else {
-            return createNodeForRValue(value);
-        }
-    }
-
-    @TruffleBoundary
-    public static RBaseNode createNodeForRValue(Object value) {
-        if (value instanceof RSymbol) {
-            RSymbol symbol = (RSymbol) value;
-            if (symbol.isMissing()) {
-                return RContext.getASTBuilder().constant(RSyntaxNode.SOURCE_UNAVAILABLE, REmpty.instance).asRNode();
-            } else {
-                return RContext.getASTBuilder().lookup(RSyntaxNode.SOURCE_UNAVAILABLE, symbol.getName(), false).asRNode();
-            }
-        } else if (value instanceof RLanguage) {
-            return RASTUtils.cloneNode(((RLanguage) value).getRep());
-        } else {
-            assert value instanceof String || value instanceof Integer || value instanceof Double || value instanceof Byte || value instanceof TruffleObject;
-            return ConstantNode.create(value);
+            return createSyntaxNodeForRValue(value).asRNode();
         }
     }
 
@@ -236,11 +218,11 @@ public final class RASTUtils {
             } else {
                 return RContext.getASTBuilder().lookup(RSyntaxNode.SOURCE_UNAVAILABLE, symbol.getName(), false);
             }
-        } else if (value instanceof RLanguage) {
-            return RContext.getASTBuilder().process(((RLanguage) value).getSyntaxElement());
+        } else if ((value instanceof RPairList && ((RPairList) value).isLanguage())) {
+            return RContext.getASTBuilder().process(((RPairList) value).getSyntaxElement());
         } else {
             assert value instanceof String || value instanceof Integer || value instanceof Double || value instanceof Byte || value instanceof TruffleObject;
-            return ConstantNode.create(value);
+            return RContext.getASTBuilder().constant(RSyntaxNode.SOURCE_UNAVAILABLE, value);
         }
     }
 
@@ -303,7 +285,7 @@ public final class RASTUtils {
                 defaultValue = null;
             } else if (arg == RNull.instance) {
                 defaultValue = RContext.getASTBuilder().constant(RSyntaxNode.LAZY_DEPARSE, RNull.instance);
-            } else if (arg instanceof RLanguage) {
+            } else if ((arg instanceof RPairList && ((RPairList) arg).isLanguage())) {
                 defaultValue = RASTUtils.createSyntaxNodeForRValue(arg);
             } else if (arg instanceof RSymbol) {
                 RSymbol symbol = (RSymbol) arg;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
index 381690d7202e9c2238c7482b2f34194e52f1b87c..989c45541a3e2e5d48a5d292a85f5c52a53c05d3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes.access.vector;
 
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
@@ -44,13 +43,12 @@ import com.oracle.truffle.r.nodes.profile.AlwaysOnBranchProfile;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RString;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
@@ -180,7 +178,8 @@ final class CachedExtractVectorNode extends CachedVectorNode {
 
             switch (vectorType) {
                 case Language:
-                    return materializeLanguage(extractedVector);
+                case PairList:
+                    return ((RPairList) originalVector).isLanguage() ? RPairList.asPairList(extractedVector, ((RPairList) originalVector).getType()) : extractedVector;
                 default:
                     return trySubsetPrimitive(extractedVector);
             }
@@ -221,11 +220,6 @@ final class CachedExtractVectorNode extends CachedVectorNode {
         return numberOfDimensions == 1 && positionsCheckNode.isMissing();
     }
 
-    @TruffleBoundary
-    private static Object materializeLanguage(RAbstractVector extractedVector) {
-        return RContext.getRRuntimeASTAccess().createLanguageFromList((RList) extractedVector, RLanguage.RepType.CALL);
-    }
-
     private Object extract(int dimensionIndex, RAbstractStringVector vector, Object pos, PositionProfile profile) {
         if (extractDimNames == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -435,7 +429,7 @@ final class CachedExtractVectorNode extends CachedVectorNode {
                 // usual case
                 container.initAttributes(RAttributesLayout.createNames(newNames1));
             } else {
-                // from an RLanguage extraction that set a name
+                // from an RPairList extraction that set a name
                 RStringVector oldNames = (RStringVector) namesAttrGetter.execute(container.getAttributes());
                 assert oldNames.getLength() == newNames.getLength();
                 assert oldNames.toString().equals(newNames1.toString());
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
index ee74036ba299c2a123f3cd6a74c7fdc23a9f8bf4..55e0a68fa0e4f6cac82e6a4dc0a3538fd00858c4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
@@ -49,7 +49,7 @@ import com.oracle.truffle.r.nodes.unary.FirstStringNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -136,7 +136,7 @@ public abstract class ExtractVectorNode extends RBaseNode {
     }
 
     private boolean isRecursiveSubscript(Object vector, Object[] positions) {
-        return !recursive && !ignoreRecursive && mode.isSubscript() && (vector instanceof RAbstractListVector || vector instanceof RLanguage) && positions.length == 1;
+        return !recursive && !ignoreRecursive && mode.isSubscript() && (vector instanceof RAbstractListVector || vector instanceof RPairList) && positions.length == 1;
     }
 
     @Specialization(limit = "CACHE_LIMIT", guards = {"!isForeignObject(vector)", "cached != null", "cached.isSupported(vector, positions, exact, dropDimensions)"})
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveExtractSubscriptNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveExtractSubscriptNode.java
index a50f0a2da30620dca6d5dffeb8d6e752b93180a4..10e6d61e912ef14f0fd3dc565799bf9654514366 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveExtractSubscriptNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveExtractSubscriptNode.java
@@ -26,7 +26,7 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.data.RInteger;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
@@ -73,7 +73,7 @@ abstract class RecursiveExtractSubscriptNode extends RecursiveSubscriptNode {
         for (int i = 1; i < positionLength; i++) {
             Object selection = getPositionExtract.apply(firstPosition, new Object[]{RInteger.valueOf(i)}, RLogical.TRUE, RLogical.TRUE);
             try {
-                if (!(currentVector instanceof RAbstractListVector || currentVector instanceof RLanguage)) {
+                if (!(currentVector instanceof RAbstractListVector || currentVector instanceof RPairList)) {
                     throw indexingFailed(i);
                 }
                 currentVector = recursiveSubscriptExtract.apply(currentVector, new Object[]{selection}, exact, dropDimensions);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
index 86bfe74041bc4c902f63d135acd8d3261005a66c..5dfaade26ba9128699e04c2f9ad137ac7448fbc0 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
@@ -35,7 +35,7 @@ import com.oracle.truffle.api.interop.KeyInfo;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.object.DynamicObject;
+import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode.AccessElementNode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode.ExtractSingleName;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode.ReadElementNode;
@@ -49,10 +49,6 @@ 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.RType;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.data.RAttributesLayout;
-import com.oracle.truffle.r.runtime.data.RLanguage;
-import com.oracle.truffle.r.runtime.data.RLanguage.RepType;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
@@ -212,24 +208,13 @@ public abstract class ReplaceVectorNode extends RBaseNode {
     }
 
     @Specialization
-    @TruffleBoundary
-    protected Object doReplacementLanguage(RLanguage vector, Object[] positions, Object value,
-                    @Cached("createForContainerTypes()") ReplaceVectorNode replace) {
-        RepType repType = RContext.getRRuntimeASTAccess().getRepType(vector);
-        RList result = RContext.getRRuntimeASTAccess().asList(vector);
-        DynamicObject attrs = vector.getAttributes();
-        if (attrs != null && !attrs.isEmpty()) {
-            result.initAttributes(RAttributesLayout.copy(attrs));
-        }
-        result = (RList) replace.execute(result, positions, value);
-        return RContext.getRRuntimeASTAccess().createLanguageFromList(result, repType);
-    }
-
-    @Specialization
-    @TruffleBoundary
     protected Object doReplacementPairList(RPairList vector, Object[] positions, Object value,
-                    @Cached("createForContainerTypes()") ReplaceVectorNode replace) {
-        return replace.execute(vector.toRList(), positions, value);
+                    @Cached("createForContainerTypes()") ReplaceVectorNode replace,
+                    @Cached("createBinaryProfile()") ConditionProfile isLanguage) {
+        RList result = vector.toRList();
+        result = (RList) replace.execute(result, positions, value);
+        // whether the result is list or pairlist depends on mode and the type of the pairlist
+        return mode != ElementAccessMode.SUBSET || isLanguage.profile(vector.isLanguage()) ? RPairList.asPairList(result, vector.getType()) : result;
     }
 
     protected static GenericVectorReplaceNode createGeneric() {
@@ -254,18 +239,20 @@ public abstract class ReplaceVectorNode extends RBaseNode {
 
         private RecursiveReplaceSubscriptNode getRecursive(ReplaceVectorNode node, Object vector, Object[] positions) {
             CompilerAsserts.neverPartOfCompilation();
-            if (cachedRecursive == null || !cachedRecursive.isSupported(vector, positions)) {
-                cachedRecursive = insert(node.createRecursiveCache(vector, positions));
+            RecursiveReplaceSubscriptNode current = cachedRecursive;
+            if (current == null || !current.isSupported(vector, positions)) {
+                return cachedRecursive = insert(node.createRecursiveCache(vector, positions));
             }
-            return cachedRecursive;
+            return current;
         }
 
         private CachedReplaceVectorNode get(ReplaceVectorNode node, RAbstractVector vector, Object[] positions, Object value) {
             CompilerAsserts.neverPartOfCompilation();
-            if (cached == null || !cached.isSupported(vector, positions, value)) {
-                cached = insert(node.createDefaultCached(vector, positions, value));
+            CachedReplaceVectorNode current = cached;
+            if (current == null || !current.isSupported(vector, positions, value)) {
+                return cached = insert(node.createDefaultCached(vector, positions, value));
             }
-            return cached;
+            return current;
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/GetAttributesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/GetAttributesNode.java
index 2adbdc699b35da9b5e02328daa83978848b89403..addb986a7c68bf74713f48ae02a7138bb0915357 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/GetAttributesNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/GetAttributesNode.java
@@ -38,10 +38,9 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -67,32 +66,28 @@ public abstract class GetAttributesNode extends RBaseNode {
 
     public abstract Object execute(RAttributable attributable);
 
-    @Specialization(guards = "!isPairList(container)")
+    @Specialization(guards = "!isRPairList(container)")
     protected Object attributesNull(RAbstractContainer container,
                     @Cached("createBinaryProfile()") ConditionProfile hasAttributesProfile) {
         if (hasAttributesProfile.profile(hasAttributes(container))) {
-            return createResult(container, container instanceof RLanguage, null);
+            return createResult(container, (container instanceof RPairList && ((RPairList) container).isLanguage()), null);
         } else {
             return RNull.instance;
         }
     }
 
     @Specialization
-    @TruffleBoundary
-    protected Object attributesPairList(RPairList pairList) {
+    protected Object attributesPairList(RPairList pairList,
+                    @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile) {
         RStringVector names = pairList.getNames();
         if (hasAttributes(pairList)) {
             return createResult(pairList, false, names);
-        } else if (names != null) {
+        } else if (hasNamesProfile.profile(names != null)) {
             return RDataFactory.createList(new Object[]{names}, RDataFactory.createStringVector(RRuntime.NAMES_ATTR_KEY));
         }
         return RNull.instance;
     }
 
-    protected static boolean isPairList(RAbstractContainer x) {
-        return x instanceof RPairList;
-    }
-
     /**
      * Unusual cases that it is not worth specializing on as they are not performance-centric,
      * basically any type that is not an {@link RAbstractContainer} but is {@link RAttributable},
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
index d14aeadf41029b784ae396b003383ab6f2b8771b..2bc9d5391665d106625ac4a92bb0c6415b6f1252 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
@@ -39,12 +39,10 @@ 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.Utils;
-import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
@@ -307,18 +305,6 @@ public final class SpecialAttributesFunctions {
             }
         }
 
-        @Specialization(insertBefore = "setAttrInAttributable")
-        protected void setNamesInLanguage(RLanguage x, RStringVector newNames,
-                        @Cached("createBinaryProfile()") ConditionProfile pairListProfile) {
-            RPairList pl = x.getPairListInternal();
-            if (pairListProfile.profile(pl == null)) {
-                /* See getNames */
-                RContext.getRRuntimeASTAccess().setNames(x, newNames);
-            } else {
-                pl.setNames(newNames);
-            }
-        }
-
         @Specialization(insertBefore = "setAttrInAttributable")
         protected void resetDimNames(RAbstractContainer x, @SuppressWarnings("unused") RNull rnull,
                         @Cached("create()") RemoveNamesAttributeNode removeNamesAttrNode) {
@@ -415,25 +401,6 @@ public final class SpecialAttributesFunctions {
             return null;
         }
 
-        @Specialization(insertBefore = "getAttrFromAttributable")
-        protected Object getLanguageNames(RLanguage x,
-                        @Cached("createBinaryProfile()") ConditionProfile pairListProfile) {
-            RPairList pl = x.getPairListInternal();
-            if (pairListProfile.profile(pl == null)) {
-                /*
-                 * "names" for a language object is a special case, that is applicable to calls and
-                 * returns the names of the actual arguments, if any. E.g. f(x=1, 3) would return
-                 * c("", "x", ""). GnuR defines it as returning the "tag" values on the pairlist
-                 * that represents the call. Well, we don't have a pairlist, (we could get one by
-                 * serializing the expression), so we do it by AST walking.
-                 */
-                RStringVector names = RContext.getRRuntimeASTAccess().getNames(x);
-                return names;
-            } else {
-                return pl.getNames();
-            }
-        }
-
         @Specialization(insertBefore = "getAttrFromAttributable")
         protected Object getVectorNames(RAbstractVector x,
                         @Cached("create()") BranchProfile attrNullProfile,
@@ -625,7 +592,6 @@ public final class SpecialAttributesFunctions {
 
     public abstract static class GetDimAttributeNode extends GetFixedAttributeNode {
 
-        private final BranchProfile isLanguageProfile = BranchProfile.create();
         private final BranchProfile isPairListProfile = BranchProfile.create();
         private final ConditionProfile nullDimsProfile = ConditionProfile.createBinaryProfile();
         private final ConditionProfile nonEmptyDimsProfile = ConditionProfile.createBinaryProfile();
@@ -648,10 +614,6 @@ public final class SpecialAttributesFunctions {
         public final int[] getDimensions(Object x) {
             // Let's handle the following two types directly so as to avoid wrapping and unwrapping
             // RIntVector. The getContainerDims spec would be invoked otherwise.
-            if (x instanceof RLanguage) {
-                isLanguageProfile.enter();
-                return ((RLanguage) x).getDimensions();
-            }
             if (x instanceof RPairList) {
                 isPairListProfile.enter();
                 return ((RPairList) x).getDimensions();
@@ -780,19 +742,7 @@ public final class SpecialAttributesFunctions {
         }
 
         @Specialization(insertBefore = "setAttrInAttributable")
-        protected void setDimNamesInLanguage(RLanguage x, RAbstractVector newDimNames,
-                        @Cached("createBinaryProfile()") ConditionProfile pairListProfile,
-                        @Cached("create()") BranchProfile attrNullProfile,
-                        @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
-                        @Cached("createClassProfile()") ValueProfile typeProfile,
-                        @Cached("create()") ShareObjectNode updateRefCountNode) {
-            RPairList pl = x.getPairListInternal();
-            RAttributable attr = pairListProfile.profile(pl == null) ? x : pl;
-            setAttrInAttributable(attr, newDimNames, attrNullProfile, attrStorageProfile, typeProfile, updateRefCountNode);
-        }
-
-        @Specialization(insertBefore = "setAttrInAttributable")
-        protected void setDimNamesInVector(RVector<?> x, RList newDimNames,
+        protected void setDimNamesInVector(RAbstractContainer x, RList newDimNames,
                         @Cached("create()") GetDimAttributeNode getDimNode,
                         @Cached("createCountingProfile()") LoopConditionProfile loopProfile,
                         @Cached("create()") BranchProfile nullDimProfile,
@@ -850,14 +800,6 @@ public final class SpecialAttributesFunctions {
             int len = x.getLength();
             return len == 0 || len == expectedDim;
         }
-
-        @Specialization(insertBefore = "setAttrInAttributable")
-        @TruffleBoundary
-        protected void setDimNamesInContainer(RAbstractContainer x, RList dimNames,
-                        @Cached("createClassProfile()") ValueProfile contClassProfile) {
-            RAbstractContainer xProfiled = contClassProfile.profile(x);
-            xProfiled.setDimNames(dimNames);
-        }
     }
 
     public abstract static class RemoveDimNamesAttributeNode extends RemoveSpecialAttributeNode {
@@ -893,37 +835,12 @@ public final class SpecialAttributesFunctions {
         }
 
         @Specialization(insertBefore = "getAttrFromAttributable")
-        protected Object getVectorDimNames(@SuppressWarnings("unused") RPairList x) {
-            return null;
-        }
-
-        @Specialization(insertBefore = "getAttrFromAttributable")
-        protected Object getLanguageDimNames(RLanguage x,
-                        @Cached("createBinaryProfile()") ConditionProfile pairListProfile,
-                        @Cached("create()") BranchProfile attrNullProfile,
-                        @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
-                        @Cached("createClassProfile()") ValueProfile xTypeProfile,
-                        @Cached("createBinaryProfile()") ConditionProfile nullRowNamesProfile) {
-            RPairList pl = x.getPairListInternal();
-            RAttributable attr = pairListProfile.profile(pl == null) ? x : pl;
-            Object res = super.getAttrFromAttributable(attr, attrNullProfile, attrStorageProfile, xTypeProfile);
-            return nullRowNamesProfile.profile(res == null) ? RNull.instance : res;
-        }
-
-        @Specialization(insertBefore = "getAttrFromAttributable")
-        protected Object getVectorDimNames(RAbstractVector x,
+        protected Object getVectorDimNames(RAbstractContainer x,
                         @Cached("create()") BranchProfile attrNullProfile,
                         @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
                         @Cached("createClassProfile()") ValueProfile xTypeProfile) {
             return super.getAttrFromAttributable(x, attrNullProfile, attrStorageProfile, xTypeProfile);
         }
-
-        @Specialization(insertBefore = "getAttrFromAttributable", guards = "!isRAbstractVector(x)")
-        @TruffleBoundary
-        protected Object getVectorDimNames(RAbstractContainer x,
-                        @Cached("createClassProfile()") ValueProfile xTypeProfile) {
-            return xTypeProfile.profile(x).getDimNames();
-        }
     }
 
     public abstract static class ExtractDimNamesAttributeNode extends RBaseNode {
@@ -1083,19 +1000,7 @@ public final class SpecialAttributesFunctions {
         }
 
         @Specialization(insertBefore = "setAttrInAttributable")
-        protected void setRowNamesInLanguage(RLanguage x, RAbstractVector newRowNames,
-                        @Cached("createBinaryProfile()") ConditionProfile pairListProfile,
-                        @Cached("create()") BranchProfile attrNullProfile,
-                        @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
-                        @Cached("createClassProfile()") ValueProfile typeProfile,
-                        @Cached("create()") ShareObjectNode updateRefCountNode) {
-            RPairList pl = x.getPairListInternal();
-            RAttributable attr = pairListProfile.profile(pl == null) ? x : pl;
-            setAttrInAttributable(attr, newRowNames, attrNullProfile, attrStorageProfile, typeProfile, updateRefCountNode);
-        }
-
-        @Specialization(insertBefore = "setAttrInAttributable")
-        protected void setRowNamesInVector(RAbstractVector x, RAbstractVector newRowNames,
+        protected void setRowNamesInVector(RAbstractContainer x, RAbstractVector newRowNames,
                         @Cached("create()") BranchProfile attrNullProfile,
                         @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
                         @Cached("createClassProfile()") ValueProfile xTypeProfile,
@@ -1108,14 +1013,6 @@ public final class SpecialAttributesFunctions {
             }
             setAttrInAttributable(x, newRowNames, attrNullProfile, attrStorageProfile, xTypeProfile, updateRefCountNode);
         }
-
-        @Specialization(insertBefore = "setAttrInAttributable", guards = "!isRAbstractVector(x)")
-        @TruffleBoundary
-        protected void setRowNamesInContainer(RAbstractContainer x, RAbstractVector rowNames,
-                        @Cached("createClassProfile()") ValueProfile contClassProfile) {
-            RAbstractContainer xProfiled = contClassProfile.profile(x);
-            xProfiled.setRowNames(rowNames);
-        }
     }
 
     public abstract static class RemoveRowNamesAttributeNode extends RemoveSpecialAttributeNode {
@@ -1160,20 +1057,7 @@ public final class SpecialAttributesFunctions {
         }
 
         @Specialization(insertBefore = "getAttrFromAttributable")
-        protected Object getLanguageRowNames(RLanguage x,
-                        @Cached("createBinaryProfile()") ConditionProfile pairListProfile,
-                        @Cached("create()") BranchProfile attrNullProfile,
-                        @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
-                        @Cached("createBinaryProfile()") ConditionProfile nullRowNamesProfile,
-                        @Cached("createClassProfile()") ValueProfile xTypeProfile) {
-            RPairList pl = x.getPairListInternal();
-            RAttributable attr = pairListProfile.profile(pl == null) ? x : pl;
-            Object res = super.getAttrFromAttributable(attr, attrNullProfile, attrStorageProfile, xTypeProfile);
-            return nullRowNamesProfile.profile(res == null) ? RNull.instance : res;
-        }
-
-        @Specialization(insertBefore = "getAttrFromAttributable")
-        protected Object getVectorRowNames(RAbstractVector x,
+        protected Object getVectorRowNames(RAbstractContainer x,
                         @Cached("create()") BranchProfile attrNullProfile,
                         @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
                         @Cached("createBinaryProfile()") ConditionProfile nullRowNamesProfile,
@@ -1181,12 +1065,6 @@ public final class SpecialAttributesFunctions {
             Object res = super.getAttrFromAttributable(x, attrNullProfile, attrStorageProfile, xTypeProfile);
             return nullRowNamesProfile.profile(res == null) ? RNull.instance : res;
         }
-
-        @Specialization(insertBefore = "getAttrFromAttributable")
-        @TruffleBoundary
-        protected Object getVectorRowNames(RAbstractContainer x) {
-            return x.getRowNames();
-        }
     }
 
     public abstract static class SetClassAttributeNode extends SetSpecialAttributeNode {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
index 5212cec1c120efb55f0b211612033bfadf9836e6..55b020c0676a7c3abc2ea5535dfc6430f91c0197 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
@@ -43,7 +43,7 @@ import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RRawVector;
@@ -146,7 +146,7 @@ public abstract class BinaryBooleanNode extends RBuiltinNode.Arg2 {
     }
 
     protected static boolean isSymbolOrLang(Object obj) {
-        return obj instanceof RSymbol || obj instanceof RLanguage;
+        return obj instanceof RSymbol || (obj instanceof RPairList && ((RPairList) obj).isLanguage());
     }
 
     @Specialization(guards = {"isSymbolOrLang(left) || isSymbolOrLang(right)"})
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java
index 73dc64dc5bcea713f28d0b61a19733c6e962e122..68bcacaf66946a1768f5de4ef356a4f89919a3bf 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.ArgumentsSignature;
 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.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
@@ -186,12 +186,14 @@ public final class ReplacementDispatchNode extends OperatorNode {
      * Encapsulates check for the specific structure of replacements, to display the replacement
      * instead of the "internal" form (with *tmp*, etc.) of the update call.
      */
-    public static RLanguage getRLanguage(RLanguage language) {
-        RSyntaxNode sn = (RSyntaxNode) language.getRep();
-        Node parent = RASTUtils.unwrapParent(sn.asNode());
-        if (parent instanceof WriteVariableNode) {
-            WriteVariableNode wvn = (WriteVariableNode) parent;
-            return ReplacementNode.getLanguage(wvn);
+    public static RPairList getRLanguage(RPairList language) {
+        RSyntaxElement sn = language.getSyntaxElement();
+        if (sn instanceof Node) {
+            Node parent = RASTUtils.unwrapParent((Node) sn);
+            if (parent instanceof WriteVariableNode) {
+                WriteVariableNode wvn = (WriteVariableNode) parent;
+                return ReplacementNode.getLanguage(wvn);
+            }
         }
         return null;
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
index 1a992180308ec43e27011b9cdef129492e16edbd..9dda30204060503f615b018dd05030e1374762b6 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -44,7 +44,7 @@ import com.oracle.truffle.r.runtime.builtins.RSpecialFactory.FullCallNeededExcep
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.Closure;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder.CodeBuilderContext;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -157,7 +157,7 @@ abstract class ReplacementNode extends OperatorNode {
         return RCallSpecialNode.createCallInReplace(source, newSyntaxLHS.asRNode(), ArgumentsSignature.get(names), argNodes, 0, argNodes.length - 1).asRNode();
     }
 
-    static RLanguage getLanguage(WriteVariableNode wvn) {
+    static RPairList getLanguage(WriteVariableNode wvn) {
         Node parent = wvn.getParent();
         if (parent instanceof ReplacementNode) {
             return RDataFactory.createLanguage(Closure.createLanguageClosure((ReplacementNode) parent));
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
index 4c9b9aa0b6fbede742e9f3141231321d94a845b6..3b0f05c72fe2d6bb4b201a1149e6207c3bef0a60 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -34,7 +34,7 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
@@ -63,7 +63,7 @@ public abstract class ArgumentStatePush extends Node {
 
     protected int createWriteArgMask(VirtualFrame frame, RShareable shareable) {
         if (shareable instanceof RAbstractContainer) {
-            if (shareable instanceof RLanguage || ((RAbstractContainer) shareable).getLength() < REF_COUNT_SIZE_THRESHOLD) {
+            if ((shareable instanceof RPairList && ((RPairList) shareable).isLanguage()) || ((RAbstractContainer) shareable).getLength() < REF_COUNT_SIZE_THRESHOLD) {
                 // don't decrement ref count for small objects or language objects- this
                 // is pretty conservative and can be further finessed
                 return -1;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
index adb31fe1b3da2c65c83c82b723655ac7d6fd04ea..49c8ef078df2dd19ce9cd6b9278014d0344a1f31 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
@@ -528,9 +528,10 @@ public abstract class PromiseNode extends RNode {
         }
 
         private int evaluateArguments(VirtualFrame frame, Object[] evaluatedArgs) {
-            if (evaluatedArgs.length <= 32) {
+            if (evaluatedArgs.length <= 64) {
                 return evaluateArgumentsExplode(frame, evaluatedArgs);
             }
+
             return evaluateArgumentsLoop(frame, evaluatedArgs);
         }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index 18abff07e0105d05e2ffa2ce5536b1abcbec6238..84fb2f06e21b2fb8e65bcec9db896f3cce97e87f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -750,20 +750,6 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
         return CallArgumentsNode.create(modeChange, modeChangeAppliesToAll, args, signature, varArgIndexes);
     }
 
-    /**
-     * Creates a modified call in which the first N arguments are replaced by
-     * {@code replacementArgs}. This is only used to support
-     * {@code HiddenInternalFunctions.MakeLazy}.
-     */
-    @TruffleBoundary
-    public static RCallNode createCloneReplacingArgs(RCallNode call, RSyntaxNode... replacementArgs) {
-        RSyntaxNode[] args = new RSyntaxNode[call.arguments.length];
-        for (int i = 0; i < args.length; i++) {
-            args[i] = i < replacementArgs.length ? replacementArgs[i] : call.arguments[i];
-        }
-        return RCallNodeGen.create(call.getLazySourceSection(), args, call.signature, RASTUtils.cloneNode(call.getFunction()));
-    }
-
     /**
      * The standard way to create a call to {@code function} with given arguments. If
      * {@code src == RSyntaxNode.EAGER_DEPARSE} we force a deparse.
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java
index 34dbaafbe58523b337c5df400c84910fa3ec88cc..2d090b4a654604710acaf7f0a34eb7880b33b061 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java
@@ -266,7 +266,7 @@ public abstract class CastComplexNode extends CastBaseNode {
         return ret;
     }
 
-    @Specialization
+    @Specialization(guards = "!pairList.isLanguage()")
     protected RComplexVector doPairList(RPairList pairList) {
         return doList(pairList.toRList());
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java
index 7ffe25f55cc859ff56f853f37925eb69cdd916bb..25f98c0075c43bd8f6cc7aaf0fdb98f410ce54c8 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java
@@ -223,7 +223,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode {
         return ret;
     }
 
-    @Specialization
+    @Specialization(guards = "!pairList.isLanguage()")
     protected RDoubleVector doPairList(RPairList pairList) {
         return doList(pairList.toRList());
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java
index 1ede1d748c1ee6ecb03f1fb779e3d8ae87756721..a11b5b0defcf48dcb49b9849e483a80ac54c67f9 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java
@@ -231,7 +231,7 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode {
         return ret;
     }
 
-    @Specialization
+    @Specialization(guards = "!pairList.isLanguage()")
     protected RIntVector doPairList(RPairList pairList) {
         return doList(pairList.toRList());
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
index 32314a0227f25ed9c53f1aea6f5e8896f0340883..a84cc5a885946ba875aba03b60ea89df0fbeb298 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -22,25 +22,17 @@
  */
 package com.oracle.truffle.r.nodes.unary;
 
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.profiles.ValueProfile;
-import com.oracle.truffle.r.nodes.attributes.ArrayAttributeNode;
-import com.oracle.truffle.r.nodes.attributes.SetAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RInteropScalar;
-import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
@@ -102,32 +94,6 @@ public abstract class CastListNode extends CastBaseNode {
     }
 
     @Specialization
-    protected RList doLanguage(RLanguage operand,
-                    @Cached("create()") ArrayAttributeNode attrAttrAccess,
-                    @Cached("create()") SetAttributeNode setAttrNode) {
-        RList result = RContext.getRRuntimeASTAccess().asList(operand);
-        DynamicObject operandAttrs = operand.getAttributes();
-        if (operandAttrs != null) {
-            // result may already have names, so can't call RVector.copyAttributesFrom
-            for (RAttributesLayout.RAttribute attr : attrAttrAccess.execute(operandAttrs)) {
-                if (attr.getName().equals(RRuntime.CLASS_ATTR_KEY)) {
-
-                    if (setClassAttrNode == null) {
-                        CompilerDirectives.transferToInterpreterAndInvalidate();
-                        setClassAttrNode = insert(SetClassAttributeNode.create());
-                    }
-
-                    setClassAttrNode.execute(result, attr.getValue());
-                } else {
-                    setAttrNode.execute(result, attr.getName(), attr.getValue());
-                }
-            }
-        }
-        return result;
-    }
-
-    @Specialization
-    @TruffleBoundary
     protected RList doPairList(RPairList pl) {
         return pl.toRList();
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java
index 8df91e8627608a45b6875e452dd81e057981c25e..cc36f7a8d95b76be4b519269a9d68d6ed708e08e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java
@@ -189,7 +189,7 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode {
         return ret;
     }
 
-    @Specialization
+    @Specialization(guards = "!pairList.isLanguage()")
     protected RLogicalVector doPairList(RPairList pairList) {
         return doList(pairList.toRList());
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java
index 361383031470940faba47fde77d7cd07f19587c7..fd644286c9590ee90f01756f885a1010552b3bf1 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java
@@ -314,7 +314,7 @@ public abstract class CastRawNode extends CastBaseNode {
         return result;
     }
 
-    @Specialization
+    @Specialization(guards = "!pairList.isLanguage()")
     protected RRawVector doPairList(RPairList pairList) {
         return doList(pairList.toRList());
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java
index 31acd91b95dc99fee391f1d863f254d57bad5d35..13ba94958a26aa5c85f208bcd23d9257e03d41e4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java
@@ -34,7 +34,7 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntSequence;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RStringSequence;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
@@ -95,7 +95,7 @@ public abstract class CastStringNode extends CastStringBaseNode {
         // conversions to character will not introduce new NAs
         for (int i = 0; i < operand.getLength(); i++) {
             Object o = operand.getDataAtAsObject(i);
-            if (isLanguageProfile.profile(o instanceof RLanguage)) {
+            if (isLanguageProfile.profile((o instanceof RPairList && ((RPairList) o).isLanguage()))) {
                 sdata[i] = RDeparse.deparse(o);
             } else {
                 sdata[i] = toString(o);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/DuplicateNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/DuplicateNode.java
index 9e94fc4d50e99526d4c6f1e8b0707ffa5c9cdbee..e20c343977a5ada3bde68468f66b1b71ece65aa5 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/DuplicateNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/DuplicateNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -64,8 +64,8 @@ public abstract class DuplicateNode extends RBaseNode {
         return p.copy();
     }
 
-    @Specialization
-    protected RLanguage duplicate(RLanguage l) {
+    @Specialization(guards = "l.isLanguage()")
+    protected RPairList duplicate(RPairList l) {
         return l.copy();
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java
index 8515ffef861c03f83bd5e7e310f4c4d91dbc5a81..9207a1a2eb2a01f28ab2a9b9c9595da69ed28947 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java
@@ -44,10 +44,9 @@ import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RForeignListWrapper;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RInteropScalar;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
@@ -176,7 +175,7 @@ public abstract class PrecedenceNode extends RBaseNode {
         return precedence;
     }
 
-    @Specialization(guards = "recursive")
+    @Specialization(guards = {"recursive", "!list.isLanguage()"})
     protected int doPairListRecursive(RPairList list, boolean recursive,
                     @Cached("createRecursive()") PrecedenceNode precedenceNode) {
         int precedence = -1;
@@ -202,7 +201,7 @@ public abstract class PrecedenceNode extends RBaseNode {
         return LIST_PRECEDENCE;
     }
 
-    @Specialization(guards = "!recursive")
+    @Specialization(guards = {"!recursive", "!val.isLanguage()"})
     @SuppressWarnings("unused")
     protected int doPairList(RPairList val, boolean recursive) {
         return LIST_PRECEDENCE;
@@ -214,9 +213,9 @@ public abstract class PrecedenceNode extends RBaseNode {
         return EXPRESSION_PRECEDENCE;
     }
 
-    @Specialization
+    @Specialization(guards = "val.isLanguage()")
     @SuppressWarnings("unused")
-    protected int doExpression(RLanguage val, boolean recursive) {
+    protected int doExpression(RPairList val, boolean recursive) {
         return LIST_PRECEDENCE;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java
index b397cfb419199e8468f60a30ff2c39419721de2f..e6bdb0224112d037f25ec8d81a0e6894e5baa1cc 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.data.RAttributeStorage;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
@@ -495,7 +495,7 @@ public class RChannel {
         }
 
         private static boolean serializeObject(Object o) {
-            return o instanceof REnvironment || o instanceof RConnection || o instanceof RLanguage;
+            return o instanceof REnvironment || o instanceof RConnection || (o instanceof RPairList && ((RPairList) o).isLanguage());
         }
 
         private Object convertPrivate(Object o) throws IOException {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index 8138ab7f7a1f538e2f3af7a126b2ee2b72386296..206c8683f3095de874b75464e44a717f6112a76f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -48,11 +48,10 @@ import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RIntSequence;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
 import com.oracle.truffle.r.runtime.data.RRaw;
@@ -788,7 +787,7 @@ public class RDeparse {
                     append(") ");
                     appendFunctionBody(function.getSyntaxBody());
                 }
-            } else if (value instanceof RPairList) {
+            } else if ((value instanceof RPairList && !((RPairList) value).isLanguage())) {
                 RPairList arglist = (RPairList) value;
                 append("pairlist(");
                 int i = 0;
@@ -927,8 +926,8 @@ public class RDeparse {
                 RSyntaxElement element;
                 if (value instanceof RSymbol) {
                     element = RSyntaxLookup.createDummyLookup(RSyntaxNode.INTERNAL, ((RSymbol) value).getName(), false);
-                } else if (value instanceof RLanguage) {
-                    element = ((RLanguage) value).getRep().asRSyntaxNode();
+                } else if ((value instanceof RPairList && ((RPairList) value).isLanguage())) {
+                    element = ((RPairList) value).getSyntaxElement();
                 } else if (value instanceof RMissing) {
                     element = RSyntaxLookup.createDummyLookup(null, "", false);
                 } else {
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 51d1e1e52ae6956275c16e6fd62b0d46d95ce34f..c39997c6f30b58bb1d3df9230a08fd5fbff15d29 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
@@ -25,11 +25,10 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RString;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -53,7 +52,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  * passed as an argument. For better or worse, we use an {@link RPairList}. We handle the
  * {@code deparse} special case explicitly in our implementation of {@code deparse}.
  * <p>
- * TODO Consider using an {@link RLanguage} object to denote the call (somehow).
+ * TODO Consider using an {@link RPairList} object to denote the call (somehow).
  */
 public class RErrorHandling {
 
@@ -469,11 +468,11 @@ public class RErrorHandling {
     /**
      * Check a {@code call} value.
      *
-     * @param call Either {@link RNull#instance} or an {@link RLanguage}.
-     * @return {@code null} iff {@code call == RNull.instance} else cast to {@link RLanguage}.
+     * @param call Either {@link RNull#instance} or an {@link RPairList}.
+     * @return {@code null} iff {@code call == RNull.instance} else cast to {@link RPairList}.
      */
     private static Object fromCall(Object call) {
-        if (!(call == RNull.instance || call instanceof RLanguage)) {
+        if (!(call == RNull.instance || (call instanceof RPairList && ((RPairList) call).isLanguage()))) {
             throw RInternalError.shouldNotReachHere();
         }
         return call;
@@ -539,9 +538,9 @@ public class RErrorHandling {
                         }
                     }
                     RContext.getEngine().evalFunction(errorFunction, null, null, true, null, evaluatedArgs);
-                } else if (errorExpr instanceof RLanguage || errorExpr instanceof RExpression) {
-                    if (errorExpr instanceof RLanguage) {
-                        RContext.getEngine().eval((RLanguage) errorExpr, materializedFrame);
+                } else if ((errorExpr instanceof RPairList && ((RPairList) errorExpr).isLanguage()) || errorExpr instanceof RExpression) {
+                    if ((errorExpr instanceof RPairList && ((RPairList) errorExpr).isLanguage())) {
+                        RContext.getEngine().eval((RPairList) errorExpr, materializedFrame);
                     } else if (errorExpr instanceof RExpression) {
                         RContext.getEngine().eval((RExpression) errorExpr, materializedFrame);
                     }
@@ -635,7 +634,7 @@ public class RErrorHandling {
         }
         Object s = RContext.getInstance().stateROptions.getValue("warning.expression");
         if (s != RNull.instance) {
-            if (!(s instanceof RLanguage || s instanceof RExpression)) {
+            if (!((s instanceof RPairList && ((RPairList) s).isLanguage()) || s instanceof RExpression)) {
                 // TODO
             }
             throw RInternalError.unimplemented();
@@ -742,7 +741,7 @@ public class RErrorHandling {
     }
 
     private static void printWarningMessage(String prefix, Warning warning, int maxLen) {
-        String callString = RContext.getRRuntimeASTAccess().getCallerSource((RLanguage) warning.call);
+        String callString = RContext.getRRuntimeASTAccess().getCallerSource((RPairList) warning.call);
 
         String message = warning.message;
         int firstLineLength = message.contains("\n") ? message.indexOf('\n') : message.length();
@@ -795,13 +794,13 @@ public class RErrorHandling {
     private static String createKindMessage(String kind, Object call, String formattedMsg) {
         String preamble = kind;
         String errorMsg = null;
-        assert call instanceof RNull || call instanceof RLanguage;
+        assert call instanceof RNull || (call instanceof RPairList && ((RPairList) call).isLanguage());
         if (call == RNull.instance) {
             // generally means top-level of shell or similar
             preamble += ": ";
             errorMsg = preamble + formattedMsg;
         } else {
-            RLanguage rl = (RLanguage) call;
+            RPairList rl = (RPairList) call;
             preamble += " in " + RContext.getRRuntimeASTAccess().getCallerSource(rl) + " :";
             errorMsg = wrapMessage(preamble, formattedMsg);
         }
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 57860a82591b1eca7b7c0855efd1a209ce2400a1..ba250c7d6bdfb1dac6a3416cbed6e5dce0ea3755 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
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -27,10 +27,9 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -285,7 +284,7 @@ public class ROptions {
             }
 
             case "warning.expression": {
-                if (!(value instanceof RLanguage || value instanceof RExpression)) {
+                if (!((value instanceof RPairList && ((RPairList) value).isLanguage()) || value instanceof RExpression)) {
                     throw OptionsException.createInvalid(name);
                 }
                 break;
@@ -313,7 +312,7 @@ public class ROptions {
             }
 
             case "error": {
-                if (!(value == RNull.instance || value instanceof RFunction || value instanceof RLanguage || value instanceof RExpression)) {
+                if (!(value == RNull.instance || value instanceof RFunction || (value instanceof RPairList && ((RPairList) value).isLanguage()) || value instanceof RExpression)) {
                     throw OptionsException.createInvalid(name);
                 }
                 break;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
index cda344489795bd1c53400e6741bf16cb43d66dfc..5e4df87fd91f809ec6daf78593dc58df3ea03b18 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -30,68 +30,25 @@ import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
-import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
-import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
  * A collection of methods that need access to the AST types, needed by code that resides in the
  * runtime project, which does not have direct access, as it would introduce project circularities.
- *
  */
 public interface RRuntimeASTAccess {
-    /**
-     * Retrieves a type of RLanguage object's representation.
-     */
-    RLanguage.RepType getRepType(RLanguage rl);
-
-    /**
-     * Computes the "length" of the language element as per the R specification.
-     */
-    int getLength(RLanguage rl);
-
-    /**
-     * Returns the object ({@link RSymbol}, {@link RLanguage} or scalar value (e.g. {@link Double})
-     * at index {@code index}.
-     */
-    Object getDataAtAsObject(RLanguage rl, int index);
-
-    /**
-     * Converts {@code rl} to a {@link RList}.
-     */
-    RList asList(RLanguage rl);
-
-    /**
-     * If {@code list} is empty return {@link RNull#instance} else create an {@link RLanguage}
-     * object whose rep is a {@code RCallNode} with the first list element as the function and the
-     * remainder as the arguments, or a {@code RFunction} (as determined by repType).
-     */
-    Object createLanguageFromList(RList list, RLanguage.RepType repType);
-
-    /**
-     * Get the "names" attribute for an {@link RLanguage} object, or {@code null} if none.
-     */
-    RStringVector getNames(RLanguage rl);
-
-    /**
-     * Set the "names" attribute for an {@link RLanguage} object.
-     */
-    void setNames(RLanguage rl, RStringVector names);
-
-    RSyntaxFunction getSyntaxFunction(RFunction f);
 
     /**
      * Returns the real caller associated with {@code rl}, by locating the {@code RSyntaxNode}
      * associated with the node stored with {@code rl}.
      */
-    RLanguage getSyntaxCaller(RCaller rl);
+    RPairList getSyntaxCaller(RCaller rl);
 
     /**
      * Gets {@code TruffleRLanguage} avoiding project circularity.
@@ -102,13 +59,13 @@ public interface RRuntimeASTAccess {
      * Returns a string for a call as represented by {@code rl}, returned originally by
      * {@link #getSyntaxCaller}.
      */
-    String getCallerSource(RLanguage rl);
+    String getCallerSource(RPairList rl);
 
     /**
      * Used by error/warning handling to try to find the call that provoked the error/warning.
      *
      * If there is no caller, return {@link RNull#instance}, e.g. "call" of a builtin from the
-     * global env, otherwise return an {@code RLanguage} instance that represents the call.
+     * global env, otherwise return an {@code RPairList} instance that represents the call.
      *
      * @param call may be {@code null} or it may be the {@link Node} that was executing when the
      *            error.warning was generated (builtin or associated node).
@@ -205,4 +162,6 @@ public interface RRuntimeASTAccess {
     RAbstractStringVector getClassHierarchy(RAttributable value);
 
     RContext getCurrentContext();
+
+    Object createLanguageElement(RSyntaxElement element);
 }
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 7289839a040ab3c413fa47aa2ae85ec5e8ad6f5e..8fb4c1e47e9fdbd6b7c20700f2e3e1a675c4889b 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
@@ -57,11 +57,10 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.PromiseState;
 import com.oracle.truffle.r.runtime.data.RScalar;
@@ -607,7 +606,7 @@ public class RSerialize {
                              * for LANGSXP when specifying a formula
                              */
                             if (langDepth == 0) {
-                                RLanguage lang = PairlistDeserializer.processLanguage(carItem, cdrItem, tagItem);
+                                RPairList lang = PairlistDeserializer.processLanguage(carItem, cdrItem, tagItem);
                                 if (attrItem != RNull.instance) {
                                     setAttributes(lang, attrItem);
                                 }
@@ -1482,7 +1481,7 @@ public class RSerialize {
                     stream.writeInt(specialType.code);
                     return;
                 }
-                SEXPTYPE type = SEXPTYPE.typeForClass(obj.getClass());
+                SEXPTYPE type = SEXPTYPE.typeForClass(obj);
                 SEXPTYPE gnuRType = SEXPTYPE.gnuRType(type, obj);
                 int refIndex;
                 if ((refIndex = getRefIndex(obj)) != -1) {
@@ -1653,7 +1652,6 @@ public class RSerialize {
                                         RFunction fun = (RFunction) obj;
                                         RPairList pl = (RPairList) serializeLanguageObject(state, fun);
                                         assert pl != null;
-                                        state.convertUnboundValues(pl);
                                         if (FastROptions.debugMatches("printWclosure")) {
                                             Debug.printClosure(pl);
                                         }
@@ -1666,7 +1664,6 @@ public class RSerialize {
                                     case PROMSXP: {
                                         RPairList pl = (RPairList) serializeLanguageObject(state, obj);
                                         assert pl != null;
-                                        state.convertUnboundValues(pl);
                                         if (pl.getTag() != RNull.instance) {
                                             writeItem(pl.getTag());
                                         }
@@ -1687,7 +1684,6 @@ public class RSerialize {
 
                                     case LANGSXP: {
                                         RPairList pl = (RPairList) serializeLanguageObject(state, obj);
-                                        state.convertUnboundValues(pl);
                                         writeItem(pl.car());
                                         obj = pl.cdr();
                                         break;
@@ -1737,7 +1733,7 @@ public class RSerialize {
             if (hook == null) {
                 return RNull.instance;
             }
-            switch (SEXPTYPE.typeForClass(obj.getClass())) {
+            switch (SEXPTYPE.typeForClass(obj)) {
                 case WEAKREFSXP:
                 case EXTPTRSXP:
                     break;
@@ -2205,11 +2201,11 @@ public class RSerialize {
         }
 
         private static SEXPTYPE type(Object obj) {
-            if (obj instanceof RPairList) {
+            if ((obj instanceof RPairList && !((RPairList) obj).isLanguage())) {
                 SEXPTYPE s = ((RPairList) obj).getType();
                 return s == null ? SEXPTYPE.LISTSXP : s;
             } else {
-                return SEXPTYPE.typeForClass(obj.getClass());
+                return SEXPTYPE.typeForClass(obj);
             }
         }
 
@@ -2430,12 +2426,23 @@ public class RSerialize {
     }
 
     private static Object serializeLanguageObject(RSerialize.State state, Object obj) {
-        if (obj instanceof RFunction) {
-            return RSerialize.serializeFunction(state, (RFunction) obj);
-        } else if (obj instanceof RLanguage) {
-            return RSerialize.serializeLanguage(state, (RLanguage) obj);
+        if (obj instanceof RPairList) {
+            RPairList list = (RPairList) obj;
+            if (list.isLanguage() && list.hasClosure()) {
+                RPairList result = (RPairList) RSerialize.serializeLanguage(state, list);
+                state.convertUnboundValues(result);
+                return result;
+            } else {
+                return list;
+            }
+        } else if (obj instanceof RFunction) {
+            RPairList result = (RPairList) RSerialize.serializeFunction(state, (RFunction) obj);
+            state.convertUnboundValues(result);
+            return result;
         } else if (obj instanceof RPromise) {
-            return RSerialize.serializePromise(state, (RPromise) obj);
+            RPairList result = (RPairList) RSerialize.serializePromise(state, (RPromise) obj);
+            state.convertUnboundValues(result);
+            return result;
         } else {
             throw RInternalError.unimplemented("serialize");
         }
@@ -2512,8 +2519,8 @@ public class RSerialize {
         return null;
     }
 
-    private static Object serializeLanguage(State state, RLanguage lang) {
-        RSyntaxElement element = lang.getRep().asRSyntaxNode();
+    private static Object serializeLanguage(State state, RPairList lang) {
+        RSyntaxElement element = lang.getSyntaxElement();
         state.openPairList(SEXPTYPE.LANGSXP);
         new SerializeVisitor(state).accept(element);
         return state.closePairList();
@@ -2566,7 +2573,7 @@ public class RSerialize {
             return func;
         }
 
-        public static RLanguage processLanguage(Object car, Object cdr, Object tag) {
+        public static RPairList processLanguage(Object car, Object cdr, Object tag) {
             Closure closure = Closure.createLanguageClosure(processCall(car, cdr, tag, null).asRNode());
             return RDataFactory.createLanguage(closure);
         }
@@ -2594,12 +2601,11 @@ public class RSerialize {
                     case CLOSXP:
                         return processFunctionExpression(pl.car(), pl.cdr(), pl.getTag(), name);
                     default:
-                        throw RInternalError.shouldNotReachHere("unexpected SXP type: " + pl.getType());
+                        // other pairlists: include as constants
+                        return RContext.getASTBuilder().constant(RSyntaxNode.LAZY_DEPARSE, unwrapScalarValues(value));
                 }
             } else {
                 assert !(value instanceof RMissing) : "should be handled outside";
-                assert !(value instanceof RLanguage) : "unexpected RLanguage constant in unserialize";
-
                 return RContext.getASTBuilder().constant(RSyntaxNode.LAZY_DEPARSE, unwrapScalarValues(value));
             }
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java
index 61744df37aa6cd22b847eda8271f01f45e5c7962..f140db79bdad71065b2a4d04cb018c71830fbec6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -33,13 +33,12 @@ import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.env.REnvironment;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder.Argument;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
@@ -67,8 +66,8 @@ public class RSubstitute {
         } else if (val instanceof RPromise) {
             RPromise promise = (RPromise) val;
             return substitutePromise(promise, builder);
-        } else if (val instanceof RLanguage) {
-            return ((RLanguage) val).getRep().asRSyntaxNode();
+        } else if ((val instanceof RPairList && ((RPairList) val).isLanguage())) {
+            return ((RPairList) val).getSyntaxElement();
         } else if (val instanceof RSymbol) {
             return RSyntaxLookup.createDummyLookup(RSyntaxNode.LAZY_DEPARSE, ((RSymbol) val).getName(), false);
         } else if (val instanceof RArgsValuesAndNames) {
@@ -216,7 +215,7 @@ public class RSubstitute {
     }
 
     @TruffleBoundary
-    public static RSyntaxNode substitute(REnvironment env, RBaseNode node, TruffleRLanguage language) {
-        return substitute(RContext.getASTBuilder(), node.asRSyntaxNode(), env, language);
+    public static RSyntaxNode substitute(REnvironment env, RSyntaxElement node, TruffleRLanguage language) {
+        return substitute(RContext.getASTBuilder(), node, env, language);
     }
 }
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 35a969fc4628dbc0ebe423b0838fa8d59734bde8..93541e43987bcaad7c8924fe5ad099008f40698b 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
@@ -53,7 +53,6 @@ import com.oracle.truffle.r.runtime.conn.StdConnections;
 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.RLanguage;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -61,7 +60,6 @@ import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.MultiSlotData;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 public final class Utils {
 
@@ -488,15 +486,14 @@ public final class Utils {
                 skip--;
                 return null;
             }
-            RLanguage rl = RContext.getRRuntimeASTAccess().getSyntaxCaller(call);
-            RSyntaxNode sn = (RSyntaxNode) rl.getRep();
-            SourceSection ss = sn != null ? sn.getSourceSection() : null;
+            RPairList rl = RContext.getRRuntimeASTAccess().getSyntaxCaller(call);
+            SourceSection section = rl.getSourceSection();
             // fabricate a srcref attribute from ss
-            Source source = ss != null ? ss.getSource() : null;
+            Source source = section != null ? section.getSource() : null;
             String path = RSource.getPath(source);
             RStringVector callerSource = RDataFactory.createStringVectorFromScalar(RContext.getRRuntimeASTAccess().getCallerSource(call));
             if (path != null) {
-                callerSource.setAttr(RRuntime.R_SRCREF, RSrcref.createLloc(ss, path));
+                callerSource.setAttr(RRuntime.R_SRCREF, RSrcref.createLloc(section, path));
             }
             RPairList pl = RDataFactory.createPairList(callerSource);
             if (prev != null) {
@@ -598,7 +595,7 @@ public final class Utils {
                                 str.append(text.length() < 256 ? text : text.substring(0, 256) + "...");
                             }
                         } catch (Throwable t) {
-                            // RLanguage values may not react kindly to getLength() calls
+                            // RPairList values may not react kindly to getLength() calls
                             str.append("<exception ").append(t.getClass().getSimpleName()).append(" while printing value of type ").append(
                                             value == null ? "null" : value.getClass().getSimpleName()).append('>');
                         }
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 998f2e895d819e4bfaff297aaa4242f2361e9039..92777dd9a6d24b59e0a64fa79269e87395d433ae 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
@@ -43,7 +43,7 @@ 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;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 
@@ -207,7 +207,7 @@ public interface Engine {
      * Variant of {@link #eval(RExpression, REnvironment, RCaller)} for a single language element.
      * If the {@code caller} argument is null, it is taken from the environment's frame.
      */
-    Object eval(RLanguage expr, REnvironment envir, RCaller caller);
+    Object eval(RPairList expr, REnvironment envir, RCaller caller);
 
     /**
      * Evaluate {@code expr} in {@code frame}.
@@ -217,10 +217,10 @@ public interface Engine {
     /**
      * Variant of {@link #eval(RExpression, MaterializedFrame)} for a single language element.
      */
-    Object eval(RLanguage expr, MaterializedFrame frame);
+    Object eval(RPairList expr, MaterializedFrame frame);
 
     /**
-     * Variant of {@link #eval(RLanguage, MaterializedFrame)} where we already have the
+     * Variant of {@link #eval(RPairList, MaterializedFrame)} where we already have the
      * {@link RFunction} and the evaluated arguments. {@code frame} may be {@code null} in which
      * case the current frame is used). In many cases {@code frame} may not represent the current
      * call stack, for example many S4-related evaluations set {@code frame} to the {@code methods}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/Closure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/Closure.java
index 158df899f7ac1edde853e90625af4225df428486..4fefd8d73a76cde9ac314b0a34f61971227426d4 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/Closure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/Closure.java
@@ -25,9 +25,11 @@ package com.oracle.truffle.r.runtime.data;
 import java.util.WeakHashMap;
 
 import com.oracle.truffle.api.CompilerAsserts;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.MaterializedFrame;
+import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.VirtualEvalFrame;
@@ -36,6 +38,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
@@ -49,14 +52,22 @@ public final class Closure {
     public static final String PROMISE_CLOSURE_WRAPPER_NAME = new String("<promise>");
     public static final String LANGUAGE_CLOSURE_WRAPPER_NAME = new String("<language>");
 
+    private static final RStringVector NULL_MARKER = new RStringVector(new String[0], true);
+
     private final RBaseNode expr;
     private final String symbol;
     private final String stringConstant;
     private final String closureName;
 
-    private Closure(String closureName, RBaseNode expr) {
+    // the first entry in the "names" attribute (special case for pairlist representation)
+    private final String syntaxLHSName;
+
+    private RStringVector namesVector; // may be null if never queried
+
+    private Closure(String closureName, RBaseNode expr, String syntaxLHSName) {
         this.closureName = closureName;
         this.expr = expr;
+        this.syntaxLHSName = syntaxLHSName;
         if (expr.asRSyntaxNode() instanceof RSyntaxLookup) {
             this.symbol = Utils.intern(((RSyntaxLookup) expr.asRSyntaxNode()).getIdentifier());
         } else {
@@ -77,15 +88,23 @@ public final class Closure {
     }
 
     public static Closure createPromiseClosure(RBaseNode expr) {
-        return new Closure(PROMISE_CLOSURE_WRAPPER_NAME, expr);
+        return new Closure(PROMISE_CLOSURE_WRAPPER_NAME, expr, null);
+    }
+
+    public static Closure createLanguageClosure(RBaseNode expr, String lhsName) {
+        return new Closure(LANGUAGE_CLOSURE_WRAPPER_NAME, expr, lhsName);
     }
 
     public static Closure createLanguageClosure(RBaseNode expr) {
-        return new Closure(LANGUAGE_CLOSURE_WRAPPER_NAME, expr);
+        return new Closure(LANGUAGE_CLOSURE_WRAPPER_NAME, expr, null);
     }
 
     public static Closure create(String name, RBaseNode expr) {
-        return new Closure(name, expr);
+        return new Closure(name, expr, null);
+    }
+
+    public String getSyntaxLHSName() {
+        return syntaxLHSName;
     }
 
     private synchronized RootCallTarget getCallTarget(FrameDescriptor desc, boolean canReuseExpr) {
@@ -152,4 +171,52 @@ public final class Closure {
     public String asStringConstant() {
         return stringConstant;
     }
+
+    public RStringVector getNamesVector() {
+        if (namesVector == null) {
+            initializeNamesVector();
+        }
+        return namesVector == NULL_MARKER ? null : namesVector;
+    }
+
+    @TruffleBoundary
+    private void initializeNamesVector() {
+        RSyntaxElement node = getSyntaxElement();
+        if (node instanceof RSyntaxCall) {
+            RSyntaxCall call = (RSyntaxCall) node;
+            /*
+             * If the function or any argument has a name, then all arguments (and the function) are
+             * given names, with unnamed arguments getting "". However, if no arguments have names,
+             * the result is NULL (null)
+             */
+            boolean hasName = false;
+            String functionName = "";
+            if (getSyntaxLHSName() != null) {
+                hasName = true;
+                functionName = getSyntaxLHSName();
+            }
+            ArgumentsSignature sig = call.getSyntaxSignature();
+            if (!hasName) {
+                for (int i = 0; i < sig.getLength(); i++) {
+                    if (sig.getName(i) != null) {
+                        hasName = true;
+                        break;
+                    }
+                }
+            }
+            if (!hasName) {
+                namesVector = NULL_MARKER;
+            } else {
+                String[] data = new String[sig.getLength() + 1];
+                data[0] = functionName; // function
+                for (int i = 0; i < sig.getLength(); i++) {
+                    String name = sig.getName(i);
+                    data[i + 1] = name == null ? "" : name;
+                }
+                namesVector = RDataFactory.getPermanent().createStringVector(data, RDataFactory.COMPLETE_VECTOR);
+            }
+        } else {
+            namesVector = NULL_MARKER;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java
index f0182160856b72173b12e5dd533ec35f7ad2f186..479a3fcc90c99a64ceb8347ef0876ca7b0a0d0cc 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java
@@ -103,22 +103,16 @@ public final class RArgsValuesAndNames extends RObject implements RTypedValue {
         return str.toString();
     }
 
-    public RPairList toPairlist() {
-        RPairList head = null;
-        assert signature.getLength() == getLength();
-        for (int i = 0; i < getLength(); i++) {
-            String name = signature.getName(i);
-            RPairList cur = RDataFactory.createPairList(getArgument(i), RNull.instance, name != null ? RDataFactory.createSymbol(name) : RNull.instance, SEXPTYPE.DOTSXP);
-
-            if (head == null) {
-                head = cur;
-            } else {
-                head.appendToEnd(cur);
-            }
+    public Object toPairlist() {
+        // special case: empty lists are represented by "missing"
+        if (isEmpty()) {
+            return RMissing.instance;
         }
-        if (head != null) {
-            return head;
+        Object current = RNull.instance;
+        for (int i = getLength() - 1; i >= 0; i--) {
+            String name = signature.getName(i);
+            current = RDataFactory.createPairList(getArgument(i), current, name != null ? RDataFactory.createSymbol(name) : RNull.instance, SEXPTYPE.DOTSXP);
         }
-        return RDataFactory.createPairList(RNull.instance);
+        return current;
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
index 131261bdbcadb195a67839841f5e971ac0f5ee19..b56d627468b78ae6b4bd74702c8e9b18f1ede5c0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
@@ -629,8 +629,8 @@ public final class RDataFactory {
             return createSymbol(Utils.intern(name));
         }
 
-        public final RLanguage createLanguage(Closure closure) {
-            return traceDataCreated(new RLanguage(closure));
+        public final RPairList createLanguage(Closure closure) {
+            return traceDataCreated(new RPairList(closure));
         }
 
         public final RPromise createPromise(PromiseState state, Closure closure, MaterializedFrame env) {
@@ -662,19 +662,11 @@ public final class RDataFactory {
             return traceDataCreated(new RPromise.EagerPromise(PromiseState.Promised, exprClosure, eagerValue, notChangedNonLocally, targetFrame, feedback, -1, execFrame));
         }
 
-        public final Object createLangPairList(int size) {
+        public final Object createPairList(int size, SEXPTYPE type) {
             if (size == 0) {
                 return RNull.instance;
             } else {
-                return traceDataCreated(RPairList.create(size, SEXPTYPE.LANGSXP));
-            }
-        }
-
-        public final Object createPairList(int size) {
-            if (size == 0) {
-                return RNull.instance;
-            } else {
-                return traceDataCreated(RPairList.create(size));
+                return traceDataCreated(RPairList.create(size, type));
             }
         }
 
@@ -683,7 +675,6 @@ public final class RDataFactory {
         }
 
         public final RPairList createPairList(Object car) {
-
             return traceDataCreated(new RPairList(car, RNull.instance, RNull.instance, null));
         }
 
@@ -1208,8 +1199,8 @@ public final class RDataFactory {
         return createSymbol(Utils.intern(name));
     }
 
-    public static RLanguage createLanguage(Closure closure) {
-        return traceDataCreated(new RLanguage(closure));
+    public static RPairList createLanguage(Closure closure) {
+        return traceDataCreated(new RPairList(closure));
     }
 
     public static RPromise createPromise(PromiseState state, Closure closure, MaterializedFrame env) {
@@ -1241,19 +1232,11 @@ public final class RDataFactory {
         return traceDataCreated(new RPromise.EagerPromise(PromiseState.Promised, exprClosure, eagerValue, notChangedNonLocally, targetFrame, feedback, -1, execFrame));
     }
 
-    public static Object createLangPairList(int size) {
+    public static Object createPairList(int size, SEXPTYPE type) {
         if (size == 0) {
             return RNull.instance;
         } else {
-            return traceDataCreated(RPairList.create(size, SEXPTYPE.LANGSXP));
-        }
-    }
-
-    public static Object createPairList(int size) {
-        if (size == 0) {
-            return RNull.instance;
-        } else {
-            return traceDataCreated(RPairList.create(size));
+            return traceDataCreated(RPairList.create(size, type));
         }
     }
 
@@ -1262,7 +1245,6 @@ public final class RDataFactory {
     }
 
     public static RPairList createPairList(Object car) {
-
         return traceDataCreated(new RPairList(car, RNull.instance, RNull.instance, null));
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
deleted file mode 100644
index db8f3209f189cf5c114d30a0e5085f27b103d5f2..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (c) 2014, 2018, 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.data;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.CompilerDirectives.ValueType;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.data.nodes.FastPathVectorAccess.FastPathFromListAccess;
-import com.oracle.truffle.r.runtime.data.nodes.SlowPathVectorAccess.SlowPathFromListAccess;
-import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
-
-/**
- * Denotes an (unevaluated) R language element. It is equivalent to a LANGSXP value in GnuR. It
- * would be more correct to be named {@code RCall} since all LANGSXP values in (Gnu)R are in fact
- * function calls (although not currently in FastR). Therefore a {@code call} is represented by an
- * instance of this type, and an {@code expression} ({@link RExpression}) is a list of such
- * instances. R allows a language element to be treated as a list, hence the support for
- * {@link RAbstractContainer}, which is implemented via AST walk operations.
- *
- * {@link RLanguage} instances are almost completely immutable, <i>except</i> for the ability for
- * {@code}names} updates which manifests itself as actually transforming the AST. S we do have to
- * implement the {@link RShareable} interface.
- *
- *
- */
-@ValueType
-public final class RLanguage extends RSharingAttributeStorage implements RAbstractContainer {
-
-    /*
-     * Used for RLanguage construction from separate AST components.
-     */
-    public enum RepType {
-        CALL,
-        FUNCTION,
-        UNKNOWN
-    }
-
-    private RPairList list;
-    private String callLHSName;
-
-    /**
-     * Lazily computed value.
-     */
-    private int length = -1;
-    private Closure closure;
-
-    RLanguage(Closure closure) {
-        this.closure = closure;
-    }
-
-    private RLanguage(Closure closure, int length) {
-        this.closure = closure;
-        this.length = length;
-    }
-
-    @Override
-    public Object getInternalStore() {
-        return this;
-    }
-
-    @TruffleBoundary
-    public static Object fromList(Object o, RLanguage.RepType type) {
-        RList l;
-        if (o instanceof RPairList) {
-            l = ((RPairList) o).toRList();
-        } else {
-            l = (RList) o;
-        }
-        return RContext.getRRuntimeASTAccess().createLanguageFromList(l, type);
-    }
-
-    private void regenerateFromList() {
-        if (list != null) {
-            // we could rest rep but we keep it around to remember type of the language object
-            assert closure.getExpr() != null;
-            // list must be reset before rep type is obtained
-            RPairList oldList = this.list;
-            this.list = null;
-            RLanguage newLang = (RLanguage) fromList(oldList, RContext.getRRuntimeASTAccess().getRepType(this));
-            assert newLang.list == null;
-            this.closure = newLang.closure;
-            this.length = newLang.length;
-            this.attributes = newLang.attributes;
-        }
-    }
-
-    public Closure getClosure() {
-        regenerateFromList();
-        return closure;
-    }
-
-    public RBaseNode getRep() {
-        regenerateFromList();
-        return closure.getExpr();
-    }
-
-    public void setClosure(Closure closure) {
-        this.closure = closure;
-        this.list = null;
-    }
-
-    public String getCallLHSName() {
-        return callLHSName;
-    }
-
-    public void setCallLHSName(String callLHSName) {
-        this.callLHSName = callLHSName;
-    }
-
-    @Override
-    public RType getRType() {
-        return RType.Language;
-    }
-
-    @Override
-    public boolean isComplete() {
-        return true;
-    }
-
-    @Override
-    public int getLength() {
-        // if list representation is present, it takes priority as it might have been updated
-        if (list == null) {
-            if (length < 0) {
-                length = RContext.getRRuntimeASTAccess().getLength(this);
-            }
-            return length;
-        } else {
-            return list.getLength();
-        }
-    }
-
-    @Override
-    public RAbstractContainer resize(int size) {
-        throw RInternalError.shouldNotReachHere();
-    }
-
-    @Override
-    public boolean hasDimensions() {
-        // TODO
-        return false;
-    }
-
-    @Override
-    public int[] getDimensions() {
-        // TODO
-        return null;
-    }
-
-    @Override
-    public void setDimensions(int[] newDimensions) {
-        throw RInternalError.unimplemented();
-    }
-
-    @Override
-    public RLanguage materialize() {
-        // TODO is copy necessary?
-        return copy();
-    }
-
-    @Override
-    public Object getDataAtAsObject(int index) {
-        if (list == null) {
-            return RContext.getRRuntimeASTAccess().getDataAtAsObject(this, index);
-        } else {
-            return list.getDataAtAsObject(index);
-        }
-    }
-
-    @Override
-    public RStringVector getNames() {
-        if (list == null) {
-            /*
-             * "names" for a language object is a special case, that is applicable to calls and
-             * returns the names of the actual arguments, if any. E.g. f(x=1, 3) would return c("",
-             * "x", ""). GnuR defines it as returning the "tag" values on the pairlist that
-             * represents the call. Well, we don't have a pairlist, (we could get one by serializing
-             * the expression), so we do it by AST walking.
-             */
-            RStringVector names = RContext.getRRuntimeASTAccess().getNames(this);
-            return names;
-        } else {
-            return list.getNames();
-        }
-    }
-
-    @Override
-    public void setNames(RStringVector newNames) {
-        if (list == null) {
-            /* See getNames */
-            RContext.getRRuntimeASTAccess().setNames(this, newNames);
-        } else {
-            setNamesOnPairList(newNames);
-        }
-    }
-
-    @Override
-    public RList getDimNames() {
-        RAttributable attr = list == null ? this : list;
-        return (RList) attr.getAttr(RRuntime.DIMNAMES_ATTR_KEY);
-    }
-
-    @Override
-    public void setDimNames(RList newDimNames) {
-        RAttributable attr = list == null ? this : list;
-        attr.setAttr(RRuntime.DIMNAMES_ATTR_KEY, newDimNames);
-    }
-
-    @Override
-    public Object getRowNames() {
-        RAttributable attr = list == null ? this : list;
-        return attr.getAttr(RRuntime.ROWNAMES_ATTR_KEY);
-    }
-
-    @Override
-    public void setRowNames(RAbstractVector rowNames) {
-        RAttributable attr = list == null ? this : list;
-        attr.setAttr(RRuntime.ROWNAMES_ATTR_KEY, rowNames);
-    }
-
-    @Override
-    public RLanguage copy() {
-        RLanguage l = new RLanguage(closure, length);
-        if (this.attributes != null) {
-            l.initAttributes(RAttributesLayout.copy(attributes));
-        }
-        l.setTypedValueInfo(getTypedValueInfo());
-        return l;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("RLanguage(rep=%s)", getRep());
-    }
-
-    public RPairList getPairListInternal() {
-        return this.list;
-    }
-
-    public RPairList getPairList() {
-        if (list == null) {
-            Object obj = RNull.instance;
-            for (int i = getLength() - 1; i >= 0; i--) {
-                Object element = RContext.getRRuntimeASTAccess().getDataAtAsObject(this, i);
-                obj = RDataFactory.createPairList(element, obj);
-            }
-            // names have to be taken before list is assigned
-            RStringVector names = RContext.getRRuntimeASTAccess().getNames(this);
-            list = (RPairList) obj;
-            if (names != null) {
-                setNamesOnPairList(names);
-            }
-        }
-        return list;
-    }
-
-    @TruffleBoundary
-    private void setNamesOnPairList(RStringVector names) {
-        list.setNames(names);
-    }
-
-    private static final class FastPathAccess extends FastPathFromListAccess {
-
-        FastPathAccess(RAbstractContainer value) {
-            super(value);
-        }
-
-        @Override
-        public RType getType() {
-            return RType.Language;
-        }
-
-        @TruffleBoundary
-        @Override
-        protected Object getListElement(Object store, int index) {
-            return ((RLanguage) store).getDataAtAsObject(index);
-        }
-    }
-
-    @Override
-    public VectorAccess access() {
-        return new FastPathAccess(this);
-    }
-
-    private static final SlowPathFromListAccess SLOW_PATH_ACCESS = new SlowPathFromListAccess() {
-        @Override
-        public RType getType() {
-            return RType.Language;
-        }
-
-        @TruffleBoundary
-        @Override
-        protected Object getListElement(Object store, int index) {
-            return ((RLanguage) store).getDataAtAsObject(index);
-        }
-    };
-
-    @Override
-    public VectorAccess slowPathAccess() {
-        return SLOW_PATH_ACCESS;
-    }
-
-    public RSyntaxElement getSyntaxElement() {
-        regenerateFromList();
-        return closure.getSyntaxElement();
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RObjectSize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RObjectSize.java
index 0745ec8434ac2880fa45be53e703976f35dc9311..0fd18057ad65be7e1224ef3ef96f7c55c8d46138 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RObjectSize.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RObjectSize.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -160,7 +160,7 @@ public class RObjectSize {
         }
         // Individual RTypedValues:
         if (obj instanceof RPromise || obj instanceof REnvironment || obj instanceof RExternalPtr || obj instanceof RFunction || obj instanceof RSymbol || obj instanceof RPairList ||
-                        obj instanceof RLanguage || obj instanceof RS4Object) {
+                        obj instanceof RS4Object) {
             // promise: there is no value allocated yet, we may use the size of the closure
             return OBJECT_HEADER_SIZE + attributesSize;
         } else if (obj instanceof RStringSequence) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
index b729095f5df82ea0face701e2c98ccf540b0eb45..82b98b73542ad9d18000a9ca25dab46e5bcf8d4d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
@@ -27,51 +27,85 @@ import java.util.Iterator;
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.object.DynamicObject;
+import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.runtime.ArgumentsSignature;
+import com.oracle.truffle.r.runtime.RDeparse;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RSrcref;
 import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.Utils;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory.BaseVectorFactory;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.data.nodes.FastPathVectorAccess.FastPathFromListAccess;
 import com.oracle.truffle.r.runtime.data.nodes.SlowPathVectorAccess.SlowPathFromListAccess;
 import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
- * Denotes the (rarely seen) {@code pairlist} type in R.
- *
- * {@code null} is never allowed as a value for the tag, car or cdr, only the type.
+ * RPairList objects can represent both "normal" pairlists (which are rarely used from R directly)
+ * and language objects. They are unified in one implementation class because native code often
+ * changes the type of these in-place.
  */
 public final class RPairList extends RSharingAttributeStorage implements RAbstractContainer, Iterable<RPairList> {
+
+    private static final RSymbol FUNCTION_SYMBOL = RSymbol.install("function");
+
     /**
-     * Data of the current pair list cell.
+     * Data of the current pair list cell (can never be {@code null}).
      */
-    private Object car = RNull.instance;
+    private Object car;
+
     /**
-     * Link to the next {@link RPairList} cell or {@link RNull} if last.
+     * Link to the next {@link RPairList} cell or {@link RNull} if last (can never be {@code null}).
      */
-    private Object cdr = RNull.instance;
+    private Object cdr;
+
     /**
      * Externally, i.e., when serialized, this is either a SYMSXP ({@link RSymbol}) or an
-     * {@link RNull}. Internally it may take on other, non-null, values.
+     * {@link RNull}. Internally it may take on other values (can never be {@code null}).
      */
-    private Object tag = RNull.instance;
+    private Object tag;
 
     /**
      * Denotes the (GnuR) type of entity that the pairlist represents. (Internal use only).
      */
     private SEXPTYPE type;
 
+    /**
+     * A closure representing the language pairlist. If this is non-null, then car/cdr/tag are
+     * uninitialized and were never accessed.
+     */
+    private Closure closure;
+
+    /**
+     * If this is {@code true}, then the car/cdr/tag fields were not accessed yet, and thus the
+     * closure field can be initialized.
+     */
+    private boolean mayBeClosure;
+
     /**
      * Uninitialized pairlist.
      */
     RPairList() {
+        // defaults to the uninitialized list case
+        this.car = RNull.instance;
+        this.cdr = RNull.instance;
+        this.tag = RNull.instance;
     }
 
     /**
-     * Variant used in unserialization to record the GnuR type the pairlist denotes.
+     * Normal pairlist with values for car, cdr, tag and type.
      */
     RPairList(Object car, Object cdr, Object tag, SEXPTYPE type) {
         assert car != null;
@@ -83,42 +117,119 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
         this.type = type;
     }
 
-    @Override
-    public Object getInternalStore() {
-        return this;
+    /**
+     * A "language" pairlist that is initialized with an AST (and which will be deconstructed into a
+     * real pairlist if needed).
+     */
+    RPairList(Closure closure) {
+        assert assertClosure(closure);
+        this.closure = closure;
+        this.type = SEXPTYPE.LANGSXP;
+        this.mayBeClosure = true;
+    }
+
+    private static boolean assertClosure(Closure closure) {
+        RBaseNode node = closure.getExpr();
+        if (node instanceof RSyntaxCall) {
+            RSyntaxCall call = (RSyntaxCall) node;
+            if (call.getSyntaxLHS() instanceof RSyntaxLookup && ((RSyntaxLookup) call.getSyntaxLHS()).getIdentifier().equals("function")) {
+                boolean valid = true;
+                valid &= call.getSyntaxSignature().getLength() >= 2;
+                if (valid) {
+                    RSyntaxElement argList = call.getSyntaxArguments()[1];
+                    valid &= argList instanceof RSyntaxConstant;
+                    if (valid) {
+                        Object list = ((RSyntaxConstant) argList).getValue();
+                        valid &= list instanceof RNull || list instanceof RPairList;
+                    }
+                }
+                assert !valid : "valid calls to 'function' should be instances of RSyntaxFunction";
+            }
+        } else {
+            assert node instanceof RSyntaxFunction : "invalid contents of 'language' pairlist: " + node;
+        }
+        return true;
     }
 
     /**
-     * Creates a new pair list of given size > 0. Note: pair list of size 0 is NULL.
+     * Converts the given vector to a pairlist of the given type. This will apply the "names"
+     * attribute by putting the names into tags, and copy all other attributes.
      */
-    public static RPairList create(int size) {
-        return create(size, null);
+    @TruffleBoundary
+    public static Object asPairList(RAbstractContainer vector, SEXPTYPE type) {
+        BaseVectorFactory dataFactory = RDataFactory.getInstance();
+        Object result = RNull.instance;
+        RStringVector names = vector.getNames();
+        for (int i = vector.getLength() - 1; i >= 0; i--) {
+            result = dataFactory.createPairList(vector.getDataAtAsObject(i), result, names != null ? RSymbol.install(names.getDataAt(i)) : RNull.instance, SEXPTYPE.LISTSXP);
+        }
+        if (result != RNull.instance) {
+            RPairList list = (RPairList) result;
+            list.mayBeClosure = true;
+            list.setType(type);
+            DynamicObject attrs = vector.getAttributes();
+            if (attrs != null) {
+                DynamicObject resultAttrs = list.initAttributes();
+                Iterator<RAttributesLayout.RAttribute> iter = RAttributesLayout.asIterable(attrs).iterator();
+                while (iter.hasNext()) {
+                    RAttributesLayout.RAttribute attr = iter.next();
+                    String attrName = attr.getName();
+                    if (!(attrName.equals(RRuntime.NAMES_ATTR_KEY) || attrName.equals(RRuntime.DIM_ATTR_KEY) || attrName.equals(RRuntime.DIMNAMES_ATTR_KEY))) {
+                        resultAttrs.define(attrName, attr.getValue());
+                    }
+                }
+            }
+            list.setTypedValueInfo(vector.getTypedValueInfo());
+        }
+        return result;
     }
 
+    /**
+     * Creates a new pair list of given size and type.
+     */
     @TruffleBoundary
-    public static RPairList create(int size, SEXPTYPE type) {
+    static RPairList create(int size, SEXPTYPE type) {
         assert size > 0 : "a pair list of size = 0 does not exist, it should be NULL";
         RPairList result = new RPairList();
         for (int i = 1; i < size; i++) {
             RPairList tmp = result;
             result = new RPairList();
-            result.cdr = tmp;
-        }
-        if (type != null) {
-            result.type = type;
+            result.setCdr(tmp);
         }
+        result.setType(type);
         return result;
     }
 
+    public boolean isLanguage() {
+        return type == SEXPTYPE.LANGSXP;
+    }
+
     @Override
     public RType getRType() {
-        return RType.PairList;
+        return isLanguage() ? RType.Language : RType.PairList;
+    }
+
+    /**
+     * Can be called after constructing a new pairlist to signal that the individual elements are
+     * not referenced and thus the closure field can be initialized.
+     */
+    public void allowClosure() {
+        this.mayBeClosure = true;
+    }
+
+    @Override
+    public Object getInternalStore() {
+        return this;
     }
 
     @Override
     public String toString() {
         CompilerAsserts.neverPartOfCompilation();
-        return String.format("type=%s, tag=%s, car=%s, cdr=%s", type, tag, toStringHelper(car), toStringHelper(cdr));
+        if (isLanguage()) {
+            return String.format("language(%s)", RDeparse.deparseSyntaxElement(getSyntaxElement()));
+        } else {
+            return String.format("pairlist(type=%s, tag=%s, car=%s, cdr=%s)", type, tag, toStringHelper(car), toStringHelper(cdr));
+        }
     }
 
     private static String toStringHelper(Object obj) {
@@ -126,10 +237,13 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
     }
 
     /**
-     * Convert to a {@link RList}.
+     * Creates an RList from this pairlist.
      */
     @TruffleBoundary
     public RList toRList() {
+        /**
+         * Convert to a {@link RList}.
+         */
         int len = 0;
         boolean named = false;
         for (RPairList item : this) {
@@ -140,9 +254,9 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
         String[] names = named ? new String[len] : null;
         int i = 0;
         for (RPairList plt : this) {
-            data[i] = plt.car;
+            data[i] = plt.car();
             if (named) {
-                Object ptag = plt.tag;
+                Object ptag = plt.getTag();
                 if (isNull(ptag)) {
                     names[i] = RRuntime.NAMES_ATTR_EMPTY_VALUE;
                 } else if (ptag instanceof RSymbol) {
@@ -171,54 +285,75 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
     }
 
     public Object car() {
+        if (closure != null) {
+            // TODO: maybe we need to wipe the closure here?
+            return getDataAtAsObject(0);
+        }
+        ensurePairList();
         return car;
     }
 
-    public Object cdr() {
-        return cdr;
-    }
-
     public void setCar(Object newCar) {
+        ensurePairList();
         assert newCar != null;
         car = newCar;
     }
 
+    public Object cdr() {
+        ensurePairList();
+        return cdr;
+    }
+
     public void setCdr(Object newCdr) {
+        ensurePairList();
         assert newCdr != null;
         cdr = newCdr;
     }
 
     public Object cadr() {
-        RPairList cdrpl = (RPairList) cdr;
-        return cdrpl.car;
+        ensurePairList();
+        return ((RPairList) cdr).car();
     }
 
     public Object cddr() {
-        RPairList cdrpl = (RPairList) cdr;
-        return cdrpl.cdr;
+        ensurePairList();
+        return ((RPairList) cdr).cdr();
     }
 
     public Object caddr() {
-        RPairList pl = (RPairList) cddr();
-        return pl.car;
+        ensurePairList();
+        RPairList pl = (RPairList) ((RPairList) cdr).cdr();
+        return pl.car();
     }
 
     public Object getTag() {
-        return tag;
+        if (closure != null) {
+            return closure.getSyntaxLHSName() == null ? RNull.instance : closure.getSyntaxLHSName();
+        } else {
+            return tag;
+        }
     }
 
     public void setTag(Object newTag) {
+        ensurePairList();
         assert newTag != null;
         this.tag = newTag;
     }
 
     public void setType(SEXPTYPE type) {
-        assert this.type == null || this.type.equals(type);
-        this.type = type;
+        if (type != this.type) {
+            ensurePairList();
+            assert type == null || type.equals(type);
+            this.type = type;
+        }
     }
 
     public boolean isNullTag() {
-        return tag == RNull.instance;
+        if (closure != null) {
+            return closure.getSyntaxLHSName() == null;
+        } else {
+            return tag == RNull.instance;
+        }
     }
 
     public SEXPTYPE getType() {
@@ -229,6 +364,7 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
      * Appends given value as the last element of the pairlist.
      */
     public void appendToEnd(RPairList value) {
+        ensurePairList();
         RPairList last = null;
         for (RPairList item : this) {
             last = item;
@@ -238,21 +374,31 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
 
     @Override
     public boolean isComplete() {
-        // TODO: is it important to get more precise information here?
         return false;
     }
 
     @Override
+    @TruffleBoundary
     public int getLength() {
-        int result = 1;
-        Object tcdr = cdr;
-        while (!isNull(tcdr)) {
-            if (tcdr instanceof RPairList) {
-                tcdr = ((RPairList) tcdr).cdr;
+        if (closure != null) {
+            RSyntaxElement s = closure.getSyntaxElement();
+            if (s instanceof RSyntaxCall) {
+                return ((RSyntaxCall) s).getSyntaxSignature().getLength() + 1;
+            } else {
+                assert s instanceof RSyntaxFunction : "unexpected type: " + s.getClass();
+                return 4;
+            }
+        } else {
+            int result = 1;
+            Object tcdr = cdr();
+            while (!isNull(tcdr)) {
+                if (tcdr instanceof RPairList) {
+                    tcdr = ((RPairList) tcdr).cdr();
+                }
+                result++;
             }
-            result++;
+            return result;
         }
-        return result;
     }
 
     @Override
@@ -262,12 +408,16 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
 
     @Override
     public boolean hasDimensions() {
-        return true;
+        return isLanguage() ? false : true;
     }
 
     @Override
     public int[] getDimensions() {
-        return new int[]{1};
+        if (isLanguage()) {
+            return null;
+        } else {
+            return new int[]{1};
+        }
     }
 
     @Override
@@ -275,39 +425,65 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
         throw RInternalError.shouldNotReachHere();
     }
 
+    @Override
     @TruffleBoundary
-    public RPairList copy(boolean keepAttributes) {
-        BaseVectorFactory dataFactory = RDataFactory.getInstance();
-        RPairList curr = dataFactory.createPairList();
-        RPairList result = curr;
-        Object original = this;
-        while (true) {
-            RPairList origList = (RPairList) original;
-            curr.car = origList.car;
-            curr.tag = origList.tag;
-            original = origList.cdr;
-            if (isNull(original)) {
-                curr.cdr = RNull.instance;
-                break;
+    public RPairList copy() {
+        if (closure != null) {
+            RPairList result = new RPairList(closure);
+            if (getAttributes() != null) {
+                result.initAttributes(RAttributesLayout.copy(getAttributes()));
             }
-            curr.cdr = dataFactory.createPairList();
-            curr = (RPairList) curr.cdr;
-        }
-        if (keepAttributes && getAttributes() != null) {
-            result.initAttributes(RAttributesLayout.copy(getAttributes()));
+            result.setTypedValueInfo(getTypedValueInfo());
+            return result;
+        } else {
+            BaseVectorFactory dataFactory = RDataFactory.getInstance();
+            RPairList curr = dataFactory.createPairList();
+            RPairList result = curr;
+            Object original = this;
+            while (true) {
+                RPairList origList = (RPairList) original;
+                curr.setCar(origList.car());
+                curr.setTag(origList.getTag());
+                curr.setType(origList.getType());
+                original = origList.cdr();
+                if (isNull(original)) {
+                    curr.setCdr(RNull.instance);
+                    break;
+                }
+                curr.setCdr(dataFactory.createPairList());
+                curr = (RPairList) curr.cdr();
+            }
+            if (getAttributes() != null) {
+                result.initAttributes(RAttributesLayout.copy(getAttributes()));
+            }
+            result.allowClosure();
+            result.setTypedValueInfo(getTypedValueInfo());
+            return result;
         }
-        return result;
-    }
-
-    @Override
-    public RPairList copy() {
-        return copy(true);
     }
 
     @Override
+    @TruffleBoundary
     public RShareable deepCopy() {
-        RInternalError.shouldNotReachHere();
-        return null;
+        if (closure != null) {
+            return copy();
+        } else {
+            RPairList result = copy();
+            RPairList current = result;
+            while (true) {
+                Object c = current.car();
+                if (c instanceof RShareable) {
+                    current.setCar(((RShareable) c).deepCopy());
+                }
+                Object next = current.cdr();
+                if (next == RNull.instance) {
+                    break;
+                }
+                current = (RPairList) next;
+            }
+            result.allowClosure();
+            return result;
+        }
     }
 
     @Override
@@ -316,14 +492,19 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
     }
 
     @Override
+    @TruffleBoundary
     public Object getDataAtAsObject(int index) {
-        RPairList pl = this;
-        int i = 0;
-        while (!isNull(pl) && i < index) {
-            pl = (RPairList) pl.cdr;
-            i++;
+        if (closure != null) {
+            return getClosureDataAtAsObject(index);
+        } else {
+            RPairList pl = this;
+            int i = 0;
+            while (!isNull(pl) && i < index) {
+                pl = (RPairList) pl.cdr();
+                i++;
+            }
+            return pl.car();
         }
-        return pl.car;
     }
 
     public static boolean isNull(Object obj) {
@@ -331,59 +512,62 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
     }
 
     @Override
+    @TruffleBoundary
     public RStringVector getNames() {
-        if (this.tag == RNull.instance) {
-            return null;
-        }
-        int l = getLength();
-        String[] data = new String[l];
-        RPairList pl = this;
-        boolean complete = RDataFactory.COMPLETE_VECTOR;
-        int i = 0;
-        while (true) {
-            data[i] = Utils.toString(pl.tag);
-            complete &= data[i] != RRuntime.STRING_NA;
-            if (isNull(pl.cdr)) {
-                break;
+        if (closure != null) {
+            return closure.getNamesVector();
+        } else {
+            boolean hasNames = false;
+            int length = 1;
+            RPairList current = this;
+            while (true) {
+                if (current.getTag() != RNull.instance) {
+                    hasNames = true;
+                }
+                Object next = current.cdr();
+                if (isNull(next)) {
+                    break;
+                }
+                current = (RPairList) next;
+                length++;
             }
-            pl = (RPairList) pl.cdr;
-            i++;
+            if (!hasNames) {
+                return null;
+            }
+            String[] data = new String[length];
+            current = this;
+            int i = 0;
+            while (true) {
+                Object name = current.getTag();
+                assert name == RNull.instance || name instanceof RSymbol;
+                data[i] = name == RNull.instance ? "" : ((RSymbol) name).getName();
+                Object next = current.cdr();
+                if (isNull(next)) {
+                    break;
+                }
+                current = (RPairList) next;
+                i++;
+            }
+            // there can never be NAs in the names
+            return RDataFactory.createStringVector(data, true);
         }
-        return RDataFactory.createStringVector(data, complete);
     }
 
     @Override
+    @TruffleBoundary
     public void setNames(RStringVector newNames) {
+        ensurePairList();
         Object p = this;
         for (int i = 0; i < newNames.getLength() && !isNull(p); i++) {
             RPairList pList = (RPairList) p;
-            pList.tag = RDataFactory.createSymbol(newNames.getDataAt(i));
-            p = pList.cdr;
+            pList.setTag(RDataFactory.createSymbol(newNames.getDataAt(i)));
+            p = pList.cdr();
         }
     }
 
-    @Override
-    public RList getDimNames() {
-        return null;
-    }
-
-    @Override
-    public void setDimNames(RList newDimNames) {
-        throw RInternalError.unimplemented();
-    }
-
-    @Override
-    public void setRowNames(RAbstractVector rowNames) {
-        throw RInternalError.unimplemented();
-    }
-
-    @Override
-    public boolean isObject() {
-        return false;
-    }
-
     @Override
     public Iterator<RPairList> iterator() {
+        ensurePairList();
         return new Iterator<RPairList>() {
             private Object plt = RPairList.this;
 
@@ -394,17 +578,283 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
 
             @Override
             public RPairList next() {
-                if (plt instanceof RLanguage) {
-                    plt = ((RLanguage) plt).getPairList();
-                }
                 assert plt instanceof RPairList;
                 RPairList curr = (RPairList) plt;
-                plt = curr.cdr;
+                plt = curr.cdr();
                 return curr;
             }
         };
     }
 
+    /**
+     * Returns a new node that contains the code represented by this language pairlist. This node is
+     * not used anywhere else and can be executed.
+     */
+    public RSyntaxNode createNode() {
+        assert isLanguage();
+        return RContext.getASTBuilder().process(getSyntaxElement());
+    }
+
+    private static RSyntaxElement unwrapToRSyntaxElement(Object obj, boolean functionLookup) {
+        if ((obj instanceof RPairList && ((RPairList) obj).isLanguage())) {
+            return ((RPairList) obj).getSyntaxElement();
+        } else if (obj instanceof RSymbol) {
+            return RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, ((RSymbol) obj).getName(), functionLookup);
+        } else if (obj instanceof RPromise) {
+            // Evaluate promise and return the result as constant.
+            return RContext.getASTBuilder().constant(RSyntaxNode.LAZY_DEPARSE, RContext.getRRuntimeASTAccess().forcePromise("unwrapToRNode", obj));
+        } else {
+            return RContext.getASTBuilder().constant(RSyntaxNode.LAZY_DEPARSE, obj);
+        }
+    }
+
+    public SourceSection getLazySourceSection() {
+        return getSyntaxElement().getLazySourceSection();
+    }
+
+    public SourceSection getSourceSection() {
+        return getSyntaxElement().getSourceSection();
+    }
+
+    public RSyntaxElement getSyntaxElement() {
+        CompilerAsserts.neverPartOfCompilation();
+        assert isLanguage();
+        if (closure != null) {
+            return closure.getSyntaxElement();
+        } else {
+            final int length = getLength();
+            if (car == FUNCTION_SYMBOL) {
+                if (length < 3) {
+                    throw RError.error(RError.SHOW_CALLER, Message.BAD_FUNCTION_EXPR);
+                }
+                Object argsList = cadr();
+                if (!(argsList instanceof RPairList || argsList == RNull.instance)) {
+                    throw RError.error(RError.SHOW_CALLER, Message.BAD_FUNCTION_EXPR);
+                }
+                return new RSyntaxFunction() {
+                    @Override
+                    public SourceSection getSourceSection() {
+                        return RSyntaxNode.INTERNAL;
+                    }
+
+                    @Override
+                    public SourceSection getLazySourceSection() {
+                        return RSyntaxNode.INTERNAL;
+                    }
+
+                    @Override
+                    public void setSourceSection(SourceSection source) {
+                        // ignored
+                    }
+
+                    @Override
+                    public ArgumentsSignature getSyntaxSignature() {
+                        if (argsList == RNull.instance) {
+                            return ArgumentsSignature.empty(0);
+                        }
+                        RStringVector argsNames = ((RPairList) argsList).getNames();
+                        return ArgumentsSignature.get(argsNames.getReadonlyData());
+                    }
+
+                    @Override
+                    public RSyntaxElement[] getSyntaxArgumentDefaults() {
+                        if (argsList == RNull.instance) {
+                            return new RSyntaxElement[0];
+                        }
+                        RPairList current = (RPairList) argsList;
+                        int argsLength = current.getLength();
+                        RSyntaxElement[] result = new RSyntaxElement[argsLength];
+                        int i = 0;
+                        while (true) {
+                            result[i] = unwrapToRSyntaxElement(current.car(), false);
+                            Object next = current.cdr();
+                            if (next == RNull.instance) {
+                                break;
+                            }
+                            current = (RPairList) next;
+                            i++;
+                        }
+                        return result;
+                    }
+
+                    @Override
+                    public RSyntaxElement getSyntaxBody() {
+                        return unwrapToRSyntaxElement(caddr(), false);
+                    }
+
+                    @Override
+                    public String getSyntaxDebugName() {
+                        return null;
+                    }
+                };
+            } else {
+                return new RSyntaxCall() {
+
+                    @Override
+                    public SourceSection getSourceSection() {
+                        return RSyntaxNode.INTERNAL;
+                    }
+
+                    @Override
+                    public SourceSection getLazySourceSection() {
+                        return RSyntaxNode.INTERNAL;
+                    }
+
+                    @Override
+                    public void setSourceSection(SourceSection source) {
+                        // ignored
+                    }
+
+                    @Override
+                    public RSyntaxElement getSyntaxLHS() {
+                        return unwrapToRSyntaxElement(getDataAtAsObject(0), true);
+                    }
+
+                    @Override
+                    public ArgumentsSignature getSyntaxSignature() {
+                        RStringVector names = getNames();
+                        if (names == null) {
+                            return ArgumentsSignature.empty(length - 1);
+                        } else {
+                            String[] signature = new String[length - 1];
+                            for (int i = 0; i < names.getLength() && i < (length - 1); i++) {
+                                signature[i] = names.getDataAt(i + 1);
+                            }
+                            return ArgumentsSignature.get(signature);
+                        }
+                    }
+
+                    @Override
+                    public RSyntaxElement[] getSyntaxArguments() {
+                        RSyntaxElement[] result = new RSyntaxElement[length - 1];
+                        for (int i = 1; i < length; i++) {
+                            result[i - 1] = unwrapToRSyntaxElement(getDataAtAsObject(i), false);
+                        }
+                        return result;
+                    }
+                };
+            }
+        }
+    }
+
+    /**
+     * Used mainly for serialization (because it has special handling for converting nodes to
+     * pairlists).
+     */
+    public boolean hasClosure() {
+        return closure != null;
+    }
+
+    public Closure getClosure(ClosureCache<RBaseNode> cache) {
+        if (closure != null) {
+            return closure;
+        } else {
+            return createClosure(cache);
+        }
+    }
+
+    @TruffleBoundary
+    private Closure createClosure(ClosureCache<RBaseNode> cache) {
+        RNode node = createNode().asRNode();
+        Closure result = cache == null ? Closure.createLanguageClosure(node) : cache.getOrCreateLanguageClosure(node);
+        if (mayBeClosure) {
+            closure = result;
+        }
+        return result;
+    }
+
+    public Closure getClosure() {
+        return getClosure(null);
+    }
+
+    @TruffleBoundary
+    public Object getClosureDataAtAsObject(int index) {
+        assert closure != null;
+        // index has already been range checked based on getLength
+        RSyntaxElement s = closure.getSyntaxElement();
+
+        RSyntaxElement result;
+        if (s instanceof RSyntaxCall) {
+            RSyntaxCall call = (RSyntaxCall) s;
+            if (index == 0) {
+                result = call.getSyntaxLHS();
+            } else {
+                result = call.getSyntaxArguments()[index - 1];
+                if (result == null) {
+                    return RSymbol.MISSING;
+                }
+            }
+        } else {
+            /*
+             * We do not expect RSyntaxConstant and RSyntaxLookup here: RSyntaxConstant should have
+             * been converted to the constant value, and RSyntaxLookup should have been converted to
+             * an RSymbol (see below).
+             */
+            assert s instanceof RSyntaxFunction;
+
+            RSyntaxFunction function = (RSyntaxFunction) s;
+            switch (index) {
+                case 0:
+                    return RDataFactory.createSymbol("function");
+                case 1:
+                    ArgumentsSignature sig = function.getSyntaxSignature();
+                    RSyntaxElement[] defaults = function.getSyntaxArgumentDefaults();
+
+                    Object lst = RNull.instance;
+                    for (int i = sig.getLength() - 1; i >= 0; i--) {
+                        lst = RDataFactory.createPairList(defaults[i] == null ? RSymbol.MISSING : RContext.getRRuntimeASTAccess().createLanguageElement(defaults[i]), lst,
+                                        RDataFactory.createSymbolInterned(sig.getName(i)));
+                    }
+                    return lst;
+                case 2:
+                    result = function.getSyntaxBody();
+                    break;
+                case 3:
+                    // srcref
+                    return RSrcref.createLloc(s.getLazySourceSection());
+                default:
+                    throw RInternalError.shouldNotReachHere();
+            }
+        }
+
+        /*
+         * Constants and lookups are converted to their intrinsic value:
+         */
+        return RContext.getRRuntimeASTAccess().createLanguageElement(result);
+    }
+
+    /**
+     * Ensures that the car, cdr and tag fields are initialized from the contents of closure if
+     * necessary.
+     */
+    private void ensurePairList() {
+        mayBeClosure = false;
+        if (closure != null) {
+            convertToPairList();
+        }
+    }
+
+    @TruffleBoundary
+    private void convertToPairList() {
+        RStringVector names = getNames();
+
+        Object obj = RNull.instance;
+        for (int i = getLength() - 1; i > 0; i--) {
+            obj = RDataFactory.createPairList(getDataAtAsObject(i), obj);
+        }
+        this.car = getDataAtAsObject(0);
+        this.cdr = obj;
+        // names have to be taken before list is assigned
+        closure = null;
+        mayBeClosure = false;
+        if (names != null) {
+            setNames(names);
+        } else {
+            // needs to be initialized
+            this.tag = RNull.instance;
+        }
+    }
+
     private static final class FastPathAccess extends FastPathFromListAccess {
 
         FastPathAccess(RAbstractContainer value) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java
index 582b9366c70bc6a0cdd69ba8e82cba861b652241..8e782899b0f16c3ccdc89262f67ce1e9a6c900af 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -69,7 +69,6 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
                 RMissing.class,
                 RPairList.class,
                 RSymbol.class,
-                RLanguage.class,
                 RFunction.class,
                 REnvironment.class,
                 RAbstractContainer.class,
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
index 1253a0a8091e54e81e3e8f2c06ff270a0cab5b43..190728124225092bfda16e1990049e4a3ca6a66a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
@@ -124,8 +124,12 @@ public abstract class REnvironment extends RAttributeStorage {
         @CompilationFinal private SearchPath searchPath;
         @CompilationFinal private MaterializedFrame parentGlobalFrame; // SHARED_PARENT_RW only
 
+        @CompilationFinal private REnvironment emptyDummy; // used when evaluating in emptyenv
+
         private ContextStateImpl(MaterializedFrame globalFrame) {
             this.globalFrame = globalFrame;
+            this.emptyDummy = RDataFactory.createNewEnv(null, false, 0);
+            RArguments.initializeEnclosingFrame(this.emptyDummy.getFrame(), null);
         }
 
         public REnvironment getGlobalEnv() {
@@ -144,6 +148,10 @@ public abstract class REnvironment extends RAttributeStorage {
             return baseEnv;
         }
 
+        public REnvironment getEmptyDummy() {
+            return emptyDummy;
+        }
+
         public REnvironment getBaseNamespace() {
             return baseEnv.getNamespace();
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
index 977cc6c1a7a9fabd532de93fb4957c0cd5e142f7..873ade3ce5a1c5b684b38373ad167d244df71682 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -23,12 +23,11 @@ import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RIntSequence;
 import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
 import com.oracle.truffle.r.runtime.data.RRaw;
@@ -46,11 +45,11 @@ public enum SEXPTYPE {
 
     NILSXP(0, RNull.class), /* nil ()NULL */
     SYMSXP(1, RSymbol.class), /* symbols */
-    LISTSXP(2, RPairList.class), /* lists of dotted pairs */
-    CLOSXP(3, RPairList.class), /* closures */
+    LISTSXP(2), /* lists of dotted pairs */
+    CLOSXP(3), /* closures */
     ENVSXP(4, REnvironment.class), /* environments */
     PROMSXP(5, RPromise.class, EagerPromise.class), /* promises: [un]evaluated closure arguments */
-    LANGSXP(6, RLanguage.class), /* language constructs (special lists) */
+    LANGSXP(6), /* language constructs (special lists) */
     SPECIALSXP(7), /* special forms */
     BUILTINSXP(8), /* builtin non-special forms */
     CHARSXP(9), /* "scalar" string type (GnuR internal only) */
@@ -119,7 +118,11 @@ public enum SEXPTYPE {
      * ints, e.g. {@code DeParse}. N.B. This is not unique for {@link RPairList}, so the
      * {@code type} field on the {@link RPairList} has to be consulted.
      */
-    public static SEXPTYPE typeForClass(Class<?> fastRClass) {
+    public static SEXPTYPE typeForClass(Object value) {
+        if (value instanceof RPairList) {
+            return ((RPairList) value).isLanguage() ? LANGSXP : LISTSXP;
+        }
+        Class<?> fastRClass = value.getClass();
         for (SEXPTYPE type : values()) {
             for (Class<?> clazz : type.fastRClasses) {
                 if (fastRClass == clazz) {
@@ -147,7 +150,7 @@ public enum SEXPTYPE {
      * Accessed from FFI layer.
      */
     public static SEXPTYPE gnuRTypeForObject(Object obj) {
-        SEXPTYPE type = typeForClass(obj.getClass());
+        SEXPTYPE type = typeForClass(obj);
         return gnuRType(type, obj);
     }
 
@@ -166,7 +169,7 @@ public enum SEXPTYPE {
                 }
             case LISTSXP:
                 RPairList pl = (RPairList) obj;
-                if (pl.getType() != null && pl.getType() == SEXPTYPE.LANGSXP) {
+                if (pl.getType() == SEXPTYPE.LANGSXP) {
                     return SEXPTYPE.LANGSXP;
                 } else {
                     return type;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
index 694a5de17e9537f7086c2f69b57c029243c7d1c3..ba05196b72aee87a2ed14685e38548139afda0f6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
@@ -41,11 +41,10 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
@@ -257,10 +256,6 @@ public abstract class RBaseNode extends Node {
         return value instanceof RPromise;
     }
 
-    protected static boolean isRLanguage(Object value) {
-        return value instanceof RLanguage;
-    }
-
     protected static boolean isRExpression(Object value) {
         return value instanceof RExpression;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxVisitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxVisitor.java
index 5ffdf75dfd26a2aeff48b2b9eb135c702214d3f6..6a374229ef0f001a55d243f2f88f57981f2a1aa5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxVisitor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxVisitor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -44,7 +44,7 @@ public abstract class RSyntaxVisitor<T> {
         } else if (element instanceof RSyntaxFunction) {
             return visit((RSyntaxFunction) element);
         } else {
-            throw RInternalError.shouldNotReachHere("unexpected RSyntaxElement: " + element.getClass().getCanonicalName());
+            throw RInternalError.shouldNotReachHere("unexpected RSyntaxElement: " + element == null ? "null" : element.getClass().getCanonicalName());
         }
     }
 
diff --git a/com.oracle.truffle.r.test.native/embedded/src/embedded.c b/com.oracle.truffle.r.test.native/embedded/src/embedded.c
index 84d129e2e60419537abee49a0e88030dc519ea12..82c52bc4b32674ed668196d942521e6a12486af4 100644
--- a/com.oracle.truffle.r.test.native/embedded/src/embedded.c
+++ b/com.oracle.truffle.r.test.native/embedded/src/embedded.c
@@ -188,7 +188,7 @@ int main(int argc, char **argv) {
     printf("Calling R_getEmbeddingDllInfo...\n");
     DllInfo *eDllInfo = R_getEmbeddingDllInfo();
     R_CallMethodDef CallEntries[] = {
-            CALLDEF(twice, 2),
+            CALLDEF(twice, 1),
             {NULL, NULL, 0}
     };
     R_registerRoutines(eDllInfo, NULL, CallEntries, NULL, NULL);
diff --git a/com.oracle.truffle.r.test.native/embedded/src/embedded.expected.output b/com.oracle.truffle.r.test.native/embedded/src/embedded.expected.output
index 4a76493713e8e62a45def473e837b219739b5b95..298ea4e37b57c92299c44d6417c7afde268eb3c8 100644
--- a/com.oracle.truffle.r.test.native/embedded/src/embedded.expected.output
+++ b/com.oracle.truffle.r.test.native/embedded/src/embedded.expected.output
@@ -13,24 +13,12 @@ Caught an error calling sqrt(). Try again with a different argument.
 Sourcing 'foo.R'...
 Calling foo with named arguments...
 Printing the expression to be eval'ed...
-[[1]]
-function(...)
-{
+function (...) {
     args <- list(...)
     print(args)
     print(names(args))
     TRUE
-}
-
-$pch
-[1] "+"
-
-$id
-[1] 123
-
-[[4]]
-[1]  TRUE FALSE
-
+}(pch = "+", id = 123L, c(TRUE, FALSE))
 Eval'ing the expression...
 $pch
 [1] "+"
@@ -43,18 +31,7 @@ $id
 
 [1] "pch" "id"  ""   
 Printing the expression to be tryEval'ed...
-[[1]]
-foo
-
-$pch
-[1] "+"
-
-$id
-[1] 123
-
-[[4]]
-[1]  TRUE FALSE
-
+foo(pch = "+", id = 123L, c(TRUE, FALSE))
 TryEval'ing the expression...
 $pch
 [1] "+"
@@ -70,6 +47,6 @@ Calling R_getEmbeddingDllInfo...
 Sourcing 'embedding.R'...
 getDLLRegisteredRoutines('(embedding)'):
   .Call .Call.numParameters
-1 twice                   2
+1 twice                   1
 [1]  2  4  6  8 10
 DONE
diff --git a/com.oracle.truffle.r.test.native/embedded/test.sh b/com.oracle.truffle.r.test.native/embedded/test.sh
index 38f05584f494acff07adee9bf307abfa9a166f20..8dc334a042fa48e4b83487752095f7e4485c6e35 100755
--- a/com.oracle.truffle.r.test.native/embedded/test.sh
+++ b/com.oracle.truffle.r.test.native/embedded/test.sh
@@ -40,6 +40,11 @@ dir="$( cd -P "$( dirname "$source" )" && pwd )"
 : ${R_HOME?"R_HOME must point to FastR directory"}
 : ${NFI_LIB?"NFI_LIB must point to libtrufflenfi.so located in mxbuild directory of Truffle"}
 
+echo "R_HOME: $R_HOME"
+echo "NFI_LIB: $NFI_LIB"
+echo "Rclasspath: "
+$dir/../../bin/execRextras/Rclasspath
+
 echo "Testing 'main' embedding example..."
 (cd $dir/bin; ./main -Dtruffle.nfi.library=$NFI_LIB --vanilla < $dir/src/main.input > $dir/main.actual.output 2>&1)
 if ! diff -q $dir/main.actual.output $dir/src/main.expected.output > /dev/null 2>&1; then
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/api.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/api.R
index 433e496efc9b16392eed16ca689b4115271b0140..cb2bc78eb92f67e735a71ca421edf5b6231b3a7d 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/api.R
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/api.R
@@ -3,17 +3,18 @@
 # All the generated files in testrffi can be regenerated by running 'mx testrfficodegen'
 # R wrappers for all the generated RFFI C wrappers
 
+api.OBJECT <- function(...) .Call(C_api_OBJECT, ...)
+api.Rf_cons <- function(...) .Call(C_api_Rf_cons, ...)
+api.Rf_ScalarInteger <- function(...) .Call(C_api_Rf_ScalarInteger, ...)
+api.Rf_ScalarLogical <- function(...) .Call(C_api_Rf_ScalarLogical, ...)
 api.Rf_ScalarReal <- function(...) .Call(C_api_Rf_ScalarReal, ...)
 api.Rf_ScalarString <- function(...) .Call(C_api_Rf_ScalarString, ...)
-api.Rf_ScalarLogical <- function(...) .Call(C_api_Rf_ScalarLogical, ...)
-api.Rf_ScalarInteger <- function(...) .Call(C_api_Rf_ScalarInteger, ...)
 api.Rf_asInteger <- function(...) .Call(C_api_Rf_asInteger, ...)
 api.Rf_asReal <- function(...) .Call(C_api_Rf_asReal, ...)
 api.Rf_asLogical <- function(...) .Call(C_api_Rf_asLogical, ...)
 api.Rf_asChar <- function(...) .Call(C_api_Rf_asChar, ...)
 api.Rf_coerceVector <- function(...) .Call(C_api_Rf_coerceVector, ...)
 api.Rf_mkCharLenCE <- function(...) .Call(C_api_Rf_mkCharLenCE, ...)
-api.Rf_cons <- function(...) .Call(C_api_Rf_cons, ...)
 api.Rf_defineVar <- function(...) .Call(C_api_Rf_defineVar, ...)
 api.R_getClassDef <- function(...) .Call(C_api_R_getClassDef, ...)
 api.R_do_MAKE_CLASS <- function(...) .Call(C_api_R_do_MAKE_CLASS, ...)
@@ -49,6 +50,7 @@ api.VECTOR_ELT <- function(...) .Call(C_api_VECTOR_ELT, ...)
 api.NAMED <- function(...) .Call(C_api_NAMED, ...)
 api.SET_OBJECT <- function(...) .Call(C_api_SET_OBJECT, ...)
 api.SET_NAMED <- function(...) .Call(C_api_SET_NAMED, ...)
+api.SET_TYPEOF <- function(...) .Call(C_api_SET_TYPEOF, ...)
 api.TYPEOF <- function(...) .Call(C_api_TYPEOF, ...)
 api.Rf_any_duplicated <- function(...) .Call(C_api_Rf_any_duplicated, ...)
 api.Rf_any_duplicated3 <- function(...) .Call(C_api_Rf_any_duplicated3, ...)
@@ -228,4 +230,3 @@ api.Rf_match <- function(...) .Call(C_api_Rf_match, ...)
 api.Rf_NonNullStringMatch <- function(...) .Call(C_api_Rf_NonNullStringMatch, ...)
 api.R_has_slot <- function(...) .Call(C_api_R_has_slot, ...)
 api.Rf_PrintValue <- function(...) .Call(C_api_Rf_PrintValue, ...)
-api.OBJECT <- function(...) .Call(C_api_OBJECT, ...)
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init_api.h b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init_api.h
index 345fc0f7b540cf39b1acfeee4e02d545ccdbd18a..cadf77e0a2b1dc27ebb381b71574e019d23e44d2 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init_api.h
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init_api.h
@@ -27,8 +27,17 @@
 // The definitions of the C functions could be generated by the same Java class (but run without any option)
 // RFFI functions that take/return C pointers are ignored
 // This code is '#included' into init.c 
-CALLDEF(api_Rf_ScalarInteger, 1),
+CALLDEF(api_OBJECT, 1),
+CALLDEF(api_LENGTH, 1),
+CALLDEF(api_Rf_error, 1),
+CALLDEF(api_NAMED, 1),
+CALLDEF(api_Rf_ncols, 1),
+CALLDEF(api_TYPEOF, 1),
+CALLDEF(api_Rf_nrows, 1),
+CALLDEF(api_ATTRIB, 1),
 CALLDEF(api_Rf_ScalarLogical, 1),
+CALLDEF(api_Rf_cons, 2),
+CALLDEF(api_Rf_ScalarInteger, 1),
 CALLDEF(api_Rf_ScalarReal, 1),
 CALLDEF(api_Rf_ScalarString, 1),
 CALLDEF(api_Rf_asInteger, 1),
@@ -37,7 +46,6 @@ CALLDEF(api_Rf_asLogical, 1),
 CALLDEF(api_Rf_asChar, 1),
 CALLDEF(api_Rf_coerceVector, 2),
 CALLDEF(api_Rf_mkCharLenCE, 3),
-CALLDEF(api_Rf_cons, 2),
 CALLDEF(api_Rf_defineVar, 3),
 CALLDEF(api_R_getClassDef, 1),
 CALLDEF(api_R_do_MAKE_CLASS, 1),
@@ -45,7 +53,6 @@ CALLDEF(api_R_do_new_object, 1),
 CALLDEF(api_Rf_findVar, 2),
 CALLDEF(api_Rf_findVarInFrame, 2),
 CALLDEF(api_Rf_findVarInFrame3, 3),
-CALLDEF(api_ATTRIB, 1),
 CALLDEF(api_Rf_getAttrib, 2),
 CALLDEF(api_Rf_setAttrib, 3),
 CALLDEF(api_Rf_inherits, 2),
@@ -55,25 +62,20 @@ CALLDEF(api_Rf_lengthgets, 2),
 CALLDEF(api_Rf_isString, 1),
 CALLDEF(api_Rf_isNull, 1),
 CALLDEF(api_Rf_PairToVectorList, 1),
-CALLDEF(api_Rf_error, 1),
 CALLDEF(api_Rf_warning, 1),
 CALLDEF(api_Rf_warningcall, 2),
 CALLDEF(api_Rf_errorcall, 2),
 CALLDEF(api_Rf_allocVector, 2),
 CALLDEF(api_Rf_allocArray, 2),
 CALLDEF(api_Rf_allocMatrix, 3),
-CALLDEF(api_Rf_nrows, 1),
-CALLDEF(api_Rf_ncols, 1),
-CALLDEF(api_LENGTH, 1),
 CALLDEF(api_SET_STRING_ELT, 3),
 CALLDEF(api_SET_VECTOR_ELT, 3),
 CALLDEF(api_SET_ATTRIB, 2),
 CALLDEF(api_STRING_ELT, 2),
 CALLDEF(api_VECTOR_ELT, 2),
-CALLDEF(api_NAMED, 1),
 CALLDEF(api_SET_OBJECT, 2),
 CALLDEF(api_SET_NAMED, 2),
-CALLDEF(api_TYPEOF, 1),
+CALLDEF(api_SET_TYPEOF, 2),
 CALLDEF(api_Rf_any_duplicated, 2),
 CALLDEF(api_Rf_any_duplicated3, 3),
 CALLDEF(api_PRINTNAME, 1),
@@ -252,5 +254,4 @@ CALLDEF(api_Rf_match, 3),
 CALLDEF(api_Rf_NonNullStringMatch, 2),
 CALLDEF(api_R_has_slot, 2),
 CALLDEF(api_Rf_PrintValue, 1),
-CALLDEF(api_OBJECT, 1),
 // ---- end of generated code
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/rffiwrappers.c b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/rffiwrappers.c
index c9bf742466e25cf3a81e165e1d763a169ddd938b..8f5204897749ac82d69cc571620a8681aac7b78b 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/rffiwrappers.c
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/rffiwrappers.c
@@ -43,6 +43,18 @@
 
 #pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
 
+SEXP api_OBJECT(SEXP x) {
+    return ScalarInteger(OBJECT(x));
+}
+
+SEXP api_ATTRIB(SEXP obj) {
+    return ATTRIB(obj);
+}
+
+SEXP api_Rf_cons(SEXP car, SEXP cdr) {
+    return Rf_cons(car, cdr);
+}
+
 SEXP api_Rf_ScalarInteger(SEXP value) {
     return Rf_ScalarInteger(INTEGER_VALUE(value));
 }
@@ -83,10 +95,6 @@ SEXP api_Rf_mkCharLenCE(SEXP bytes, SEXP len, SEXP encoding) {
     return Rf_mkCharLenCE(R_CHAR(STRING_ELT(bytes, 0)), INTEGER_VALUE(len), INTEGER_VALUE(encoding));
 }
 
-SEXP api_Rf_cons(SEXP car, SEXP cdr) {
-    return Rf_cons(car, cdr);
-}
-
 SEXP api_Rf_defineVar(SEXP symbolArg, SEXP value, SEXP envArg) {
     Rf_defineVar(symbolArg, value, envArg);
     return R_NilValue;
@@ -116,10 +124,6 @@ SEXP api_Rf_findVarInFrame3(SEXP envArg, SEXP symbolArg, SEXP doGet) {
     return Rf_findVarInFrame3(envArg, symbolArg, INTEGER_VALUE(doGet));
 }
 
-SEXP api_ATTRIB(SEXP obj) {
-    return ATTRIB(obj);
-}
-
 SEXP api_Rf_getAttrib(SEXP obj, SEXP name) {
     return Rf_getAttrib(obj, name);
 }
@@ -238,6 +242,11 @@ SEXP api_SET_NAMED(SEXP x, SEXP v) {
     return R_NilValue;
 }
 
+SEXP api_SET_TYPEOF(SEXP x, SEXP v) {
+    SET_TYPEOF(x, INTEGER_VALUE(v));
+    return R_NilValue;
+}
+
 SEXP api_TYPEOF(SEXP x) {
     return ScalarInteger(TYPEOF(x));
 }
@@ -977,9 +986,5 @@ SEXP api_Rf_PrintValue(SEXP value) {
     return R_NilValue;
 }
 
-SEXP api_OBJECT(SEXP x) {
-    return ScalarInteger(OBJECT(x));
-}
-
 #pragma GCC diagnostic pop
 #pragma GCC diagnostic pop
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/rffiwrappers.h b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/rffiwrappers.h
index f59eb727b14a0abc1bb8cd43a771e8f8fd6a6967..60f794a162816d0bc05b0aa0c9cce9e75145f83f 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/rffiwrappers.h
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/rffiwrappers.h
@@ -34,18 +34,22 @@
 #include <R_ext/Connections.h>
 #include <Rmath.h>
 
-SEXP api_Rf_ScalarInteger(SEXP value);
-
-SEXP api_Rf_ScalarLogical(SEXP value);
+SEXP api_OBJECT(SEXP x);
 
 SEXP api_Rf_ScalarReal(SEXP value);
 
-SEXP api_Rf_ScalarString(SEXP value);
+SEXP api_Rf_cons(SEXP car, SEXP cdr);
 
 SEXP api_Rf_asInteger(SEXP x);
 
 SEXP api_Rf_asReal(SEXP x);
 
+SEXP api_Rf_ScalarString(SEXP value);
+
+SEXP api_Rf_ScalarInteger(SEXP value);
+
+SEXP api_Rf_ScalarLogical(SEXP value);
+
 SEXP api_Rf_asLogical(SEXP x);
 
 SEXP api_Rf_asChar(SEXP x);
@@ -54,8 +58,6 @@ SEXP api_Rf_coerceVector(SEXP x, SEXP mode);
 
 SEXP api_Rf_mkCharLenCE(SEXP bytes, SEXP len, SEXP encoding);
 
-SEXP api_Rf_cons(SEXP car, SEXP cdr);
-
 SEXP api_Rf_defineVar(SEXP symbolArg, SEXP value, SEXP envArg);
 
 SEXP api_R_getClassDef(SEXP clazz);
@@ -126,6 +128,8 @@ SEXP api_SET_OBJECT(SEXP x, SEXP flag);
 
 SEXP api_SET_NAMED(SEXP x, SEXP v);
 
+SEXP api_SET_TYPEOF(SEXP x, SEXP v);
+
 SEXP api_TYPEOF(SEXP x);
 
 SEXP api_Rf_any_duplicated(SEXP x, SEXP fromLast);
@@ -484,5 +488,3 @@ SEXP api_R_has_slot(SEXP container, SEXP name);
 
 SEXP api_Rf_PrintValue(SEXP value);
 
-SEXP api_OBJECT(SEXP x);
-
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/pairlists.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/pairlists.R
index 8260d0d90eadf62d3367a3bf8101ae1792500977..5511b2bd64ed4f2255e17f128654dc79b87efde7 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/pairlists.R
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/pairlists.R
@@ -9,3 +9,24 @@ invisible(foo(a=4, b=6))
 foo <- function(...) api.CDR(get('...'))
 is.null(foo(a=3))
 names(foo(a=4, b=6))
+
+someFunction <- function(a,b,c,d=100) a + b + d
+l <- quote(someFunction(a=1,122,c=x+foo))
+api.TYPEOF(l)
+api.CAR(l)
+api.CDR(l)
+l
+eval(l)
+api.SET_TYPEOF(l, 2) # LISTSXP
+l
+eval(l)
+api.SET_TYPEOF(l, 6) # LANGSXP
+
+l <- pairlist(a=as.symbol("sum"), foo=123L,1233)
+api.TYPEOF(l)
+api.CAR(l)
+api.CDR(l)
+l
+api.SET_TYPEOF(l, 6) # LANGSXP
+l
+eval(l)
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 57f734463d8a4bb4bd387d9254e61ccf87fe0e94..dc4af52603c82f1790d5d045015e208a0eb9c442 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
@@ -528,7 +528,7 @@ Use  showMethods("gen")  for currently available ones.
 [1] 42
 [1] 42
 
-##com.oracle.truffle.r.test.S4.TestS4.testMethods#Ignored.OutputFormatting#
+##com.oracle.truffle.r.test.S4.TestS4.testMethods#
 #{ setClass("foo"); setMethod("diag<-", "foo", function(x, value) 42); removeMethod("diag<-", "foo"); removeGeneric("diag<-"); removeClass("foo") }
 Creating a generic function for ‘diag<-’ from package ‘base’ in the global environment
 [1] TRUE
@@ -549,7 +549,7 @@ Note: method with signature ‘A2#A1’ chosen for function ‘foo’,
 #{ setClass('A1', representation(a='numeric')); setMethod('length', 'A1', function(x) x@a); obj <- new('A1'); obj@a <- 10; length(obj) }
 [1] 10
 
-##com.oracle.truffle.r.test.S4.TestS4.testMethods#Ignored.OutputFormatting#
+##com.oracle.truffle.r.test.S4.TestS4.testMethods#
 #{ setClass('A2', representation(a = 'numeric')); setMethod('rep', 'A2', function(x, a, b, c) { c(x@a, a, b, c) }); setMethod('ifelse', c(yes = 'A2'), function(test, yes, no) print(test)) }
 Creating a generic function for ‘ifelse’ from package ‘base’ in the global environment
 [1] "ifelse"
@@ -21412,6 +21412,18 @@ attr(,"gradient")
        x
 [1,] NaN
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testEnvironment#
+#environment(deriv((y ~ sin(cos(x) * y)), c('x','y'), func = TRUE))
+<environment: R_GlobalEnv>
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testEnvironment#
+#environment(local(deriv((y ~ sin(cos(x) * y)), c('x','y'), func = TRUE)))
+<environment: R_GlobalEnv>
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testEnvironment#
+#environment(local(deriv((y ~ sin(cos(x) * y)), c('x','y'), func = deriv)))
+<environment: namespace:stats>
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testFunctionGenereration#Output.IgnoreWhitespace#
 #(df <- deriv(~x^2*sin(x), "x", function.arg=TRUE));df(0)
 function (x)
@@ -28269,7 +28281,7 @@ Error: atomic vector arguments only
 function (x = 4)
 x + 1
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_function.testFunctionFunction#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_function.testFunctionFunction#Output.MayIgnoreErrorContext#
 #eval(call('function', 1, expression(x + 1)[[1]]))
 Error in eval(call("function", 1, expression(x + 1)[[1]])) :
   invalid formal argument list for "function"
@@ -29823,7 +29835,7 @@ attr(,"Rd_tag")
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_icuSetCollate.testicuSetCollate1#Ignored.Unimplemented#
 # .Internal(icuSetCollate())
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_identical.testAttrOrder#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_identical.testAttrOrder#
 #x <- 1; y <- 1; attr(x, "f") <- 2; attr(x, "g") <- 1; attr(y, "g") <- 1; attr(y, "f") <- 2; identical(x, y)
 [1] TRUE
 
@@ -29891,6 +29903,34 @@ attr(,"Rd_tag")
 #identical(NaN, NaN, num.eq=T, single.NA=T)
 [1] TRUE
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_identical.testIdentical#
+#a <- quote(a(100)); b <- quote(a(100)); attr(a[[2]], 'foo') <- 'bar'; b[[2]] <- a[[2]]; identical(a,b)
+[1] TRUE
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_identical.testIdentical#
+#a <- quote(a(100)); b <- quote(a(100)); attr(a[[2]], 'foo') <- 'bar'; identical(a,b)
+[1] FALSE
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_identical.testIdentical#
+#a <- quote(a(100)); b <- quote(a(100)); attr(b[[2]], 'foo') <- 'bar'; attr(a[[2]], 'foo') <- 'bar'; identical(a,b)
+[1] TRUE
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_identical.testIdentical#
+#a <- quote(a(100)); b <- quote(a(100)); attr(b[[2]], 'foo') <- 'baz'; attr(a[[2]], 'foo') <- 'bar'; identical(a,b)
+[1] FALSE
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_identical.testIdentical#
+#a <- quote(a(100)); b <- quote(a(100)); identical(a,b)
+[1] TRUE
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_identical.testIdentical#
+#a <- quote(a(100)); b <- quote(a(101)); identical(a,b)
+[1] FALSE
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_identical.testIdentical#
+#identical(pairlist(1, pairlist('foo')), pairlist(1, pairlist('bar')))
+[1] FALSE
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_identical.testIdentical#
 #{ f1 <- function() {}; f2 <- function() {}; identical(f1, f2) }
 [1] TRUE
@@ -41536,7 +41576,7 @@ NULL
 #{ x <- c(10, 20); names(x) <- c('ahoj', 'svete'); y <- c(1,2); z <- choose(x,y); names(z)[[1]] <- 'onlyinz'; names(x) }
 [1] "ahoj"  "svete"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testNames#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testNames#
 #{ x <- parse(text='x+y')[[1]]; names(x) <- c('a','b','c'); names(x); }
 [1] "a" "b" "c"
 
@@ -68361,6 +68401,14 @@ integer(0)
 [26] 09 00 00 00 01 2b 00 00 00 02 00 00 00 01 00 04 00 09 00 00 00 01 61 00 00
 [51] 00 02 00 00 00 01 00 04 00 09 00 00 00 01 62 00 00 00 fe
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(quote(b + xxxx(yyyy=1)), connection=NULL)
+  [1] 58 0a 00 00 00 02 00 03 04 00 00 02 03 00 00 00 00 06 00 00 00 01 00 04 00
+ [26] 09 00 00 00 01 2b 00 00 00 02 00 00 00 01 00 04 00 09 00 00 00 01 62 00 00
+ [51] 00 02 00 00 00 06 00 00 00 01 00 04 00 09 00 00 00 04 78 78 78 78 00 00 04
+ [76] 02 00 00 00 01 00 04 00 09 00 00 00 04 79 79 79 79 00 00 00 0e 00 00 00 01
+[101] 3f f0 00 00 00 00 00 00 00 00 00 fe 00 00 00 fe
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
 #options(keep.source=FALSE); serialize(quote(f(g)$h.i), connection=NULL)
  [1] 58 0a 00 00 00 02 00 03 04 00 00 02 03 00 00 00 00 06 00 00 00 01 00 04 00
@@ -68583,6 +68631,12 @@ integer(0)
  [1] 58 0a 00 00 00 02 00 03 04 00 00 02 03 00 00 00 00 01 00 04 00 09 00 00 00
 [26] 01 78
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(quote(xxxx(yyyy=1)), connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 04 00 00 02 03 00 00 00 00 06 00 00 00 01 00 04 00
+[26] 09 00 00 00 04 78 78 78 78 00 00 04 02 00 00 00 01 00 04 00 09 00 00 00 04
+[51] 79 79 79 79 00 00 00 0e 00 00 00 01 3f f0 00 00 00 00 00 00 00 00 00 fe
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
 #options(keep.source=FALSE); serialize(quote({ foo(a,b,c) }), connection=NULL)
   [1] 58 0a 00 00 00 02 00 03 04 00 00 02 03 00 00 00 00 06 00 00 00 01 00 04 00
@@ -132293,6 +132347,22 @@ Error in x[["a", "d"]] : subscript out of bounds
 Error in match(x, table, nomatch = 0L) :
   'match' requires vector arguments
 
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testLanguageIndex#
+#f <- function(x) x[[1]]; l <- as.pairlist(c('a','b')); f(l); l <- quote(a+b); f(l)
+[1] "a"
+`+`
+
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testLanguageIndex#
+#l <- quote(a+b+c); l[[c(2,2)]]; l[[c(2,3)]]; l[[c(2,2)]]; l[[c(3)]]; l <- as.pairlist(c('+','x','c')); l[[2]] <- as.pairlist(c('+','a','b')); l[[c(2,2)]]; l[[c(2,3)]]; l[[c(2,2)]]; l[[c(3)]]
+a
+b
+a
+c
+[1] "a"
+[1] "b"
+[1] "a"
+[1] "c"
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testLanguageIndex#
 #{ e <- quote(f(x=a, b)); names(e) }
 [1] ""  "x" ""
@@ -137408,6 +137478,69 @@ Error in `[[.default`(x, "z", exact = TRUE) : subscript out of bounds
 [1] b
 Levels: a b
 
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testPairList#
+#l <- as.pairlist(c(1,2,3,4)); l2 <- l; typeof(l); l[[3]] <- 123; typeof(l); l
+[1] "pairlist"
+[1] "pairlist"
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 123
+
+[[4]]
+[1] 4
+
+
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testPairList#
+#l <- as.pairlist(c(1,2,3,4)); typeof(l); l[[3]] <- 123; typeof(l); l
+[1] "pairlist"
+[1] "pairlist"
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 123
+
+[[4]]
+[1] 4
+
+
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testPairList#
+#l <- pairlist("a","b",1,4,3); typeof(l); typeof(l[[1]]); typeof(l[1]); typeof(l[1:5]); typeof(l[4:5]); l[4:5]
+[1] "pairlist"
+[1] "character"
+[1] "list"
+[1] "list"
+[1] "list"
+[[1]]
+[1] 4
+
+[[2]]
+[1] 3
+
+
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testPairList#
+#l <- quote(a("b",1,4,3)); typeof(l); typeof(l[[1]]); typeof(l[1]); typeof(l[1:5]); typeof(l[4:5]); l[4:5]
+[1] "language"
+[1] "symbol"
+[1] "language"
+[1] "language"
+[1] "language"
+4(3)
+
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testPairList#
+#x <- as.pairlist(list(7,42)); x[[1]] <- list(); typeof(x); x$foo <- 123; typeof(x); x[1] <- list(1); typeof(x)
+[1] "pairlist"
+[1] "pairlist"
+[1] "list"
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testPrint#
 #{ mp<-getOption("max.print"); options(max.print=3); x<-c(1,2,3,4,5); attr(x, "foo")<-"foo"; print(x); options(max.print=mp) }
 [1] 1 2 3
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
index d660c79947e21c355d7ccf9d95220e8a66c8e9a9..5653770c6af61e4610411b9ae957cc356f42a7cc 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -121,8 +121,7 @@ public class TestS4 extends TestRBase {
 
         assertEval("{ setGeneric(\"gen\", function(o) standardGeneric(\"gen\")); res<-print(setGeneric(\"gen\", function(o) standardGeneric(\"gen\"))); removeGeneric(\"gen\"); res }");
 
-        assertEval(Ignored.OutputFormatting,
-                        "{ setClass(\"foo\"); setMethod(\"diag<-\", \"foo\", function(x, value) 42); removeMethod(\"diag<-\", \"foo\"); removeGeneric(\"diag<-\"); removeClass(\"foo\") }");
+        assertEval("{ setClass(\"foo\"); setMethod(\"diag<-\", \"foo\", function(x, value) 42); removeMethod(\"diag<-\", \"foo\"); removeGeneric(\"diag<-\"); removeClass(\"foo\") }");
 
         assertEval("{ setClass('A'); setClass('A1', contains = 'A'); setClass('A2', contains = 'A1'); setGeneric('foo', function(a, b) standardGeneric('foo')); setMethod('foo', signature('A1', 'A2'), function(a, b) '1-2'); setMethod('foo', signature('A2', 'A1'), function(a, b) '2-1'); foo(new('A2'), new('A2')) }");
 
@@ -130,8 +129,7 @@ public class TestS4 extends TestRBase {
 
         assertEval("{ setClass('A1', representation(a='numeric')); setMethod('length', 'A1', function(x) x@a); obj <- new('A1'); obj@a <- 10; length(obj) }");
 
-        assertEval(Ignored.OutputFormatting,
-                        "{ setClass('A2', representation(a = 'numeric')); setMethod('rep', 'A2', function(x, a, b, c) { c(x@a, a, b, c) }); setMethod('ifelse', c(yes = 'A2'), function(test, yes, no) print(test)) }");
+        assertEval("{ setClass('A2', representation(a = 'numeric')); setMethod('rep', 'A2', function(x, a, b, c) { c(x@a, a, b, c) }); setMethod('ifelse', c(yes = 'A2'), function(test, yes, no) print(test)) }");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java
index cf1870d917f8e864e10595f84d29df46ad3d391a..4d7e4426ab547509ff0e964e012b3012e3e703ea 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java
@@ -474,7 +474,7 @@ public class TestBuiltin_asvector extends TestRBase {
                     "c(T, F, T)",
                     "c(1+i, 2+i, 4+i)",
                     "parse(text='x; y; z')",
-                    // TODO: "parse(text='x+y')[[1]]", -- problem with UpdateNames and RLanguage...
+                    // TODO: "parse(text='x+y')[[1]]", -- problem with UpdateNames and RPairList...
                     // TODO: "function() 42",
     };
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java
index 190994eb998d501c5da8846af11c57e576a8af11..8f7446063da37bf958c9bcab9f89573442d596b0 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -190,6 +190,13 @@ public class TestBuiltin_deriv extends TestBase {
         assertEval(Output.IgnoreWhitespace, "(df <- deriv(~x^2*sin(x), \"x\", function.arg=function(x)NULL));df(0)");
     }
 
+    @Test
+    public void testEnvironment() {
+        assertEval("environment(deriv((y ~ sin(cos(x) * y)), c('x','y'), func = TRUE))");
+        assertEval("environment(local(deriv((y ~ sin(cos(x) * y)), c('x','y'), func = TRUE)))");
+        assertEval("environment(local(deriv((y ~ sin(cos(x) * y)), c('x','y'), func = deriv)))");
+    }
+
     @Test
     public void testUnusualExprs() {
         assertEval("(df <- deriv(expression(x^2*sin(x)), \"x\"));df(0)");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_function.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_function.java
index eac9c3629d63f0921183400c3ad3b3ba025206dc..f9c4e95e618610267cd4f62fad74102955418962 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_function.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_function.java
@@ -30,7 +30,7 @@ import com.oracle.truffle.r.test.TestBase;
 public class TestBuiltin_function extends TestBase {
     @Test
     public void testFunctionFunction() {
-        assertEval(Output.IgnoreErrorContext, "eval(call('function', 1, expression(x + 1)[[1]]))");
+        assertEval(Output.MayIgnoreErrorContext, "eval(call('function', 1, expression(x + 1)[[1]]))");
         assertEval("eval(call('function', as.pairlist(list(x=4)), expression(x + 1)[[1]]))");
         assertEval("do.call('function', list(as.pairlist(list(x=4)), expression(x + 1)[[1]]))");
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_identical.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_identical.java
index ecb854a29ac5e63c7d73d1ea071155f655d4ab3c..d9e8d9df8e8cf413e2485220111a7a477c76ab2a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_identical.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_identical.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -202,7 +202,7 @@ public class TestBuiltin_identical extends TestBase {
 
     @Test
     public void testAttrOrder() {
-        assertEval(Ignored.ImplementationError, "x <- 1; y <- 1; attr(x, \"f\") <- 2; attr(x, \"g\") <- 1; attr(y, \"g\") <- 1; attr(y, \"f\") <- 2; identical(x, y)");
+        assertEval("x <- 1; y <- 1; attr(x, \"f\") <- 2; attr(x, \"g\") <- 1; attr(y, \"g\") <- 1; attr(y, \"f\") <- 2; identical(x, y)");
     }
 
     @Test
@@ -258,6 +258,19 @@ public class TestBuiltin_identical extends TestBase {
 
         assertEval("{ f1 <- function() {}; f2 <- function() {}; identical(f1, f2) }");
         assertEval("{ identical(function() 42, function() 42) }");
+
+        // pairlists
+
+        assertEval("identical(pairlist(1, pairlist('foo')), pairlist(1, pairlist('bar')))");
+
+        // language
+
+        assertEval("a <- quote(a(100)); b <- quote(a(101)); identical(a,b)");
+        assertEval("a <- quote(a(100)); b <- quote(a(100)); identical(a,b)");
+        assertEval("a <- quote(a(100)); b <- quote(a(100)); attr(a[[2]], 'foo') <- 'bar'; identical(a,b)");
+        assertEval("a <- quote(a(100)); b <- quote(a(100)); attr(a[[2]], 'foo') <- 'bar'; b[[2]] <- a[[2]]; identical(a,b)");
+        assertEval("a <- quote(a(100)); b <- quote(a(100)); attr(b[[2]], 'foo') <- 'baz'; attr(a[[2]], 'foo') <- 'bar'; identical(a,b)");
+        assertEval("a <- quote(a(100)); b <- quote(a(100)); attr(b[[2]], 'foo') <- 'bar'; attr(a[[2]], 'foo') <- 'bar'; identical(a,b)");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java
index 147f9137f9ae7786841967d1d25194d966a49e6a..39cc1c3415710f3779c56175291c2df9c12192bf 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java
@@ -206,8 +206,7 @@ public class TestBuiltin_names extends TestBase {
         assertEval("{ y<-c(d=\"e\"); attr(y, \"foo\")<-\"foo\"; x<-c(42); names(x)<-y; attributes(names(x)) }");
         assertEval("{ x <- c(10, 20); names(x) <- c('ahoj', 'svete'); y <- c(1,2); z <- choose(x,y); names(z)[[1]] <- 'onlyinz'; names(x) }");
         assertEval("{ e <- new.env(); names(e) <- c('a'); }");
-        // FIXME: set names on language does not set the first name
-        assertEval(Ignored.ImplementationError, "{ x <- parse(text='x+y')[[1]]; names(x) <- c('a','b','c'); names(x); }");
+        assertEval("{ x <- parse(text='x+y')[[1]]; names(x) <- c('a','b','c'); names(x); }");
         assertEval("names(pairlist(a=3, b=4))");
         assertEval("names(pairlist(1,2,3))");
         assertEval("names(pairlist(a=1,2,q=3))");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java
index 07b12af333d27fd0cff34d59e59c3c151129a8fd..c758a995ec59630a9ed6b937539c333ced6851d3 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -72,6 +72,8 @@ public class TestBuiltin_serialize extends TestBase {
         assertEval("options(keep.source=FALSE); serialize(quote(if ({a}) {b} else {c}), connection=NULL)");
         assertEval("options(keep.source=FALSE); serialize(quote(while (a) b), connection=NULL)");
         assertEval("options(keep.source=FALSE); serialize(quote(repeat {b; if (c) next else break}), connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize(quote(xxxx(yyyy=1)), connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize(quote(b + xxxx(yyyy=1)), connection=NULL)");
         assertEval("options(keep.source=FALSE); serialize(quote(if (a * 2 < 199) b + foo(x,y,foo=z+1,bar=)), connection=NULL)");
         assertEval("options(keep.source=FALSE); serialize(quote(\"bar\"), connection=NULL)");
         assertEval("options(keep.source=FALSE); serialize(quote('baz'), connection=NULL)");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/AbstractMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/AbstractMRTest.java
index 9fcf40ab9e89f21c660e35e441c8bafffc5b9d14..8f884c1764b258a17918ede70dd4be90edcbf03d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/AbstractMRTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/AbstractMRTest.java
@@ -45,7 +45,6 @@ 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.r.test.generate.FastRSession;
 
 public abstract class AbstractMRTest {
 
@@ -54,17 +53,16 @@ public abstract class AbstractMRTest {
     @BeforeClass
     public static void before() {
         context = Context.newBuilder("R", "llvm").build();
+        context.eval("R", "1"); // initialize context
+        context.enter();
     }
 
     @AfterClass
     public static void after() {
+        context.leave();
         context.close();
     }
 
-    protected void execInContext(Callable<Object> c) {
-        FastRSession.execInContext(context, c);
-    }
-
     @Before
     public void beforeMethod() {
         /**
@@ -116,93 +114,75 @@ public abstract class AbstractMRTest {
 
     @Test
     public void testIsNull() throws Exception {
-        execInContext(() -> {
-            for (TruffleObject obj : createTruffleObjects()) {
-                assertEquals(isNull(obj), ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), obj));
-            }
-            return null;
-        });
+        for (TruffleObject obj : createTruffleObjects()) {
+            assertEquals(isNull(obj), ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), obj));
+        }
     }
 
     @Test
     public void testExecutable() throws Exception {
-        execInContext(() -> {
-            for (TruffleObject obj : createTruffleObjects()) {
-                try {
-                    // TODO if the need appears, also provide for args for execute
-                    ForeignAccess.sendExecute(Message.createExecute(0).createNode(), obj);
-                    assertEquals(obj.getClass().getSimpleName() + " " + obj + " IS_EXECUTABLE", true, ForeignAccess.sendIsExecutable(Message.IS_EXECUTABLE.createNode(), obj));
-                } catch (UnsupportedTypeException | ArityException e) {
-                    throw e;
-                } catch (UnsupportedMessageException e) {
-                    assertEquals(obj.getClass().getSimpleName() + " " + obj + " IS_EXECUTABLE", false, ForeignAccess.sendIsExecutable(Message.IS_EXECUTABLE.createNode(), obj));
-                }
+        for (TruffleObject obj : createTruffleObjects()) {
+            try {
+                // TODO if the need appears, also provide for args for execute
+                ForeignAccess.sendExecute(Message.createExecute(0).createNode(), obj);
+                assertEquals(obj.getClass().getSimpleName() + " " + obj + " IS_EXECUTABLE", true, ForeignAccess.sendIsExecutable(Message.IS_EXECUTABLE.createNode(), obj));
+            } catch (UnsupportedTypeException | ArityException e) {
+                throw e;
+            } catch (UnsupportedMessageException e) {
+                assertEquals(obj.getClass().getSimpleName() + " " + obj + " IS_EXECUTABLE", false, ForeignAccess.sendIsExecutable(Message.IS_EXECUTABLE.createNode(), obj));
             }
-            return null;
-        });
+        }
     }
 
     @Test
     public void testInstantiable() throws Exception {
-        execInContext(() -> {
-            for (TruffleObject obj : createTruffleObjects()) {
-                try {
-                    // TODO if the need appears, also provide for args for new
-                    ForeignAccess.sendNew(Message.createNew(0).createNode(), obj);
-                    assertEquals(obj.getClass().getSimpleName() + " " + obj + " IS_INSTANTIABLE", true, ForeignAccess.sendIsInstantiable(Message.IS_INSTANTIABLE.createNode(), obj));
-                } catch (UnsupportedTypeException | ArityException e) {
-                    throw e;
-                } catch (UnsupportedMessageException e) {
-                    assertEquals(obj.getClass().getSimpleName() + " " + obj + " IS_INSTANTIABLE", false, ForeignAccess.sendIsInstantiable(Message.IS_INSTANTIABLE.createNode(), obj));
-                }
+        for (TruffleObject obj : createTruffleObjects()) {
+            try {
+                // TODO if the need appears, also provide for args for new
+                ForeignAccess.sendNew(Message.createNew(0).createNode(), obj);
+                assertEquals(obj.getClass().getSimpleName() + " " + obj + " IS_INSTANTIABLE", true, ForeignAccess.sendIsInstantiable(Message.IS_INSTANTIABLE.createNode(), obj));
+            } catch (UnsupportedTypeException | ArityException e) {
+                throw e;
+            } catch (UnsupportedMessageException e) {
+                assertEquals(obj.getClass().getSimpleName() + " " + obj + " IS_INSTANTIABLE", false, ForeignAccess.sendIsInstantiable(Message.IS_INSTANTIABLE.createNode(), obj));
             }
-            return null;
-        });
+        }
     }
 
     @Test
     public void testAsNativePointer() throws Exception {
-        execInContext(() -> {
-            for (TruffleObject obj : createTruffleObjects()) {
-                try {
-                    assertNotNull(obj.getClass().getSimpleName(), ForeignAccess.sendToNative(Message.AS_POINTER.createNode(), obj));
-                    assertEquals(obj.getClass().getSimpleName() + " " + obj + " IS_POINTER", true, ForeignAccess.sendIsPointer(Message.IS_POINTER.createNode(), obj));
-                } catch (UnsupportedMessageException e) {
-                    assertEquals(obj.getClass().getSimpleName() + " " + obj + " IS_POINTER", false, ForeignAccess.sendIsPointer(Message.IS_POINTER.createNode(), obj));
-                }
+        for (TruffleObject obj : createTruffleObjects()) {
+            try {
+                assertNotNull(obj.getClass().getSimpleName(), ForeignAccess.sendToNative(Message.AS_POINTER.createNode(), obj));
+                assertEquals(obj.getClass().getSimpleName() + " " + obj + " IS_POINTER", true, ForeignAccess.sendIsPointer(Message.IS_POINTER.createNode(), obj));
+            } catch (UnsupportedMessageException e) {
+                assertEquals(obj.getClass().getSimpleName() + " " + obj + " IS_POINTER", false, ForeignAccess.sendIsPointer(Message.IS_POINTER.createNode(), obj));
             }
-            return null;
-        });
+        }
     }
 
     @Test
     public void testNativePointer() throws Exception {
-        execInContext(() -> {
-            for (TruffleObject obj : createTruffleObjects()) {
-                if (!testToNative(obj)) {
-                    continue;
-                }
-                try {
-                    assertTrue(obj.getClass().getSimpleName(), ForeignAccess.sendToNative(Message.TO_NATIVE.createNode(), obj) != obj);
-                } catch (UnsupportedMessageException e) {
-                }
+        for (TruffleObject obj : createTruffleObjects()) {
+            if (!testToNative(obj)) {
+                continue;
+            }
+            try {
+                assertTrue(obj.getClass().getSimpleName(), ForeignAccess.sendToNative(Message.TO_NATIVE.createNode(), obj) != obj);
+            } catch (UnsupportedMessageException e) {
             }
-            return null;
-        });
+        }
     }
 
     @Test
     public void testSize() throws Exception {
-        execInContext(() -> {
-            for (TruffleObject obj : createTruffleObjects()) {
-                testSize(obj);
-            }
-            TruffleObject empty = createEmptyTruffleObject();
-            if (empty != null) {
-                testSize(empty);
-            }
-            return null;
-        });
+        for (TruffleObject obj : createTruffleObjects()) {
+            testSize(obj);
+        }
+        TruffleObject empty = createEmptyTruffleObject();
+        if (empty != null) {
+            testSize(empty);
+        }
     }
 
     private void testSize(TruffleObject obj) {
@@ -217,16 +197,13 @@ public abstract class AbstractMRTest {
 
     @Test
     public void testBoxed() throws Exception {
-        execInContext(() -> {
-            for (TruffleObject obj : createTruffleObjects()) {
-                testUnboxed(obj);
-            }
-            TruffleObject empty = createEmptyTruffleObject();
-            if (empty != null) {
-                testUnboxed(empty);
-            }
-            return null;
-        });
+        for (TruffleObject obj : createTruffleObjects()) {
+            testUnboxed(obj);
+        }
+        TruffleObject empty = createEmptyTruffleObject();
+        if (empty != null) {
+            testUnboxed(empty);
+        }
     }
 
     private void testUnboxed(TruffleObject obj) {
@@ -241,16 +218,13 @@ public abstract class AbstractMRTest {
 
     @Test
     public void testKeys() throws Exception {
-        execInContext(() -> {
-            for (TruffleObject obj : createTruffleObjects()) {
-                testKeys(obj);
-            }
-            TruffleObject empty = createEmptyTruffleObject();
-            if (empty != null) {
-                testKeys(empty);
-            }
-            return null;
-        });
+        for (TruffleObject obj : createTruffleObjects()) {
+            testKeys(obj);
+        }
+        TruffleObject empty = createEmptyTruffleObject();
+        if (empty != null) {
+            testKeys(empty);
+        }
     }
 
     private void testKeys(TruffleObject obj) throws UnknownIdentifierException {
@@ -276,27 +250,27 @@ public abstract class AbstractMRTest {
     }
 
     protected void assertInteropException(Callable<Object> c, Class<? extends InteropException> expectedClazz) {
-        boolean ie = false;
         try {
             c.call();
         } catch (InteropException ex) {
             if (expectedClazz != null && ex.getClass() != expectedClazz) {
+                ex.printStackTrace();
                 Assert.fail(expectedClazz + " was expected but got instead: " + ex);
             }
-            ie = true;
+            return;
         } catch (Exception ex) {
             if (expectedClazz != null && ex.getClass() != expectedClazz) {
+                ex.printStackTrace();
                 Assert.fail(expectedClazz + " was expected but got instead: " + ex);
             } else {
-                Assert.fail("InteropException was expected but got insteat: " + ex);
+                ex.printStackTrace();
+                Assert.fail("InteropException was expected but got instead: " + ex);
             }
         }
-        if (!ie) {
-            if (expectedClazz != null) {
-                Assert.fail(expectedClazz + " was expected");
-            } else {
-                Assert.fail("InteropException was expected");
-            }
+        if (expectedClazz != null) {
+            Assert.fail(expectedClazz + " was expected");
+        } else {
+            Assert.fail("InteropException was expected");
         }
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/ListMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/ListMRTest.java
index 29d48191b221e2143876dce368f6e3935e2f09af..47ed7023d29d834be14f7b9881bcae632f6ad893 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/ListMRTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/ListMRTest.java
@@ -55,45 +55,42 @@ public class ListMRTest extends AbstractMRTest {
     }
 
     @Test
-    public void testKeysReadWrite() {
+    public void testKeysReadWrite() throws Exception {
         testKeysReadWrite("list");
         testKeysReadWrite("pairlist");
     }
 
-    private void testKeysReadWrite(String createFun) {
-        execInContext(() -> {
-            RAbstractContainer l = create(createFun, testValues);
+    private void testKeysReadWrite(String createFun) throws Exception {
+        RAbstractContainer l = create(createFun, testValues);
 
-            assertEquals(1, ForeignAccess.sendRead(Message.READ.createNode(), l, "i"));
-            assertEquals(2.1, ForeignAccess.sendRead(Message.READ.createNode(), l, "d"));
-            assertEquals(true, ForeignAccess.sendRead(Message.READ.createNode(), l, "b"));
-            assertTrue(ForeignAccess.sendRead(Message.READ.createNode(), l, "n") instanceof RNull);
+        assertEquals(1, ForeignAccess.sendRead(Message.READ.createNode(), l, "i"));
+        assertEquals(2.1, ForeignAccess.sendRead(Message.READ.createNode(), l, "d"));
+        assertEquals(true, ForeignAccess.sendRead(Message.READ.createNode(), l, "b"));
+        assertTrue(ForeignAccess.sendRead(Message.READ.createNode(), l, "n") instanceof RNull);
 
-            assertEquals(1, ForeignAccess.sendRead(Message.READ.createNode(), l, 0));
-            assertEquals(2.1, ForeignAccess.sendRead(Message.READ.createNode(), l, 1));
-            assertEquals(4d, ForeignAccess.sendRead(Message.READ.createNode(), l, 5d));
-            assertEquals(true, ForeignAccess.sendRead(Message.READ.createNode(), l, 2));
-            assertTrue(ForeignAccess.sendRead(Message.READ.createNode(), l, 4) instanceof RNull);
+        assertEquals(1, ForeignAccess.sendRead(Message.READ.createNode(), l, 0));
+        assertEquals(2.1, ForeignAccess.sendRead(Message.READ.createNode(), l, 1));
+        assertEquals(4d, ForeignAccess.sendRead(Message.READ.createNode(), l, 5d));
+        assertEquals(true, ForeignAccess.sendRead(Message.READ.createNode(), l, 2));
+        assertTrue(ForeignAccess.sendRead(Message.READ.createNode(), l, 4) instanceof RNull);
 
-            assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), l, -1), UnknownIdentifierException.class);
-            assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), l, 0f), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), l, -1), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), l, 0f), UnknownIdentifierException.class);
 
-            assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), l, "nnnoooonnne"), UnknownIdentifierException.class);
-            assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), l, 100), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), l, "nnnoooonnne"), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), l, 100), UnknownIdentifierException.class);
 
-            TruffleObject obj = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), l, "d", 123.1);
-            assertEquals(123.1, ForeignAccess.sendRead(Message.READ.createNode(), obj, "d"));
+        TruffleObject obj = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), l, "d", 123.1);
+        assertEquals(123.1, ForeignAccess.sendRead(Message.READ.createNode(), obj, "d"));
 
-            obj = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), l, 2, false);
-            assertEquals(false, ForeignAccess.sendRead(Message.READ.createNode(), obj, "b"));
+        obj = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), l, 2, false);
+        assertEquals(false, ForeignAccess.sendRead(Message.READ.createNode(), obj, "b"));
 
-            obj = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), l, "newnew", "nneeww");
-            assertEquals("nneeww", ForeignAccess.sendRead(Message.READ.createNode(), obj, "newnew"));
+        obj = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), l, "newnew", "nneeww");
+        assertEquals("nneeww", ForeignAccess.sendRead(Message.READ.createNode(), obj, "newnew"));
 
-            assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), l, 0f, false), UnknownIdentifierException.class);
-            assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), l, 0d, false), UnknownIdentifierException.class);
-            return null;
-        });
+        assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), l, 0f, false), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), l, 0d, false), UnknownIdentifierException.class);
     }
 
     @Test
@@ -103,54 +100,51 @@ public class ListMRTest extends AbstractMRTest {
     }
 
     public void testKeysInfo(String createFun) {
-        execInContext(() -> {
-            RAbstractContainer l = create(createFun, testValues);
-
-            int info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "nnoonnee");
-            assertFalse(KeyInfo.isExisting(info));
-            assertFalse(KeyInfo.isReadable(info));
-            assertFalse(KeyInfo.isWritable(info));
-            assertFalse(KeyInfo.isInvocable(info));
-            assertFalse(KeyInfo.isInternal(info));
-
-            info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "d");
-            assertTrue(KeyInfo.isExisting(info));
-            assertTrue(KeyInfo.isReadable(info));
-            assertTrue(KeyInfo.isWritable(info));
-            assertFalse(KeyInfo.isInvocable(info));
-            assertFalse(KeyInfo.isInternal(info));
-
-            info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "fn");
-            assertTrue(KeyInfo.isExisting(info));
-            assertTrue(KeyInfo.isReadable(info));
-            assertTrue(KeyInfo.isWritable(info));
-            assertTrue(KeyInfo.isInvocable(info));
-            assertFalse(KeyInfo.isInternal(info));
-
-            info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, -1);
-            assertFalse(KeyInfo.isExisting(info));
-
-            info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, l.getLength());
-            assertFalse(KeyInfo.isExisting(info));
-
-            info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, 1f);
-            assertFalse(KeyInfo.isExisting(info));
-
-            info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, 0);
-            assertTrue(KeyInfo.isExisting(info));
-            assertTrue(KeyInfo.isReadable(info));
-            assertTrue(KeyInfo.isWritable(info));
-            assertFalse(KeyInfo.isInvocable(info));
-            assertFalse(KeyInfo.isInternal(info));
-
-            info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, 1d);
-            assertTrue(KeyInfo.isExisting(info));
-            assertTrue(KeyInfo.isReadable(info));
-            assertTrue(KeyInfo.isWritable(info));
-            assertFalse(KeyInfo.isInvocable(info));
-            assertFalse(KeyInfo.isInternal(info));
-            return null;
-        });
+        RAbstractContainer l = create(createFun, testValues);
+
+        int info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "nnoonnee");
+        assertFalse(KeyInfo.isExisting(info));
+        assertFalse(KeyInfo.isReadable(info));
+        assertFalse(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "d");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertTrue(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "fn");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertTrue(KeyInfo.isWritable(info));
+        assertTrue(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, -1);
+        assertFalse(KeyInfo.isExisting(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, l.getLength());
+        assertFalse(KeyInfo.isExisting(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, 1f);
+        assertFalse(KeyInfo.isExisting(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, 0);
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertTrue(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, 1d);
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertTrue(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
     }
 
     private static RAbstractContainer create(String createFun, String values) {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RFunctionMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RFunctionMRTest.java
index a6ce7ce890d7fa8de67873e722c4fea74942cefc..d58670ae75aaca281dd6e7693dabc57817acf843 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RFunctionMRTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RFunctionMRTest.java
@@ -38,34 +38,30 @@ import com.oracle.truffle.r.test.generate.FastRSession;
 public class RFunctionMRTest extends AbstractMRTest {
 
     @Test
-    public void testExecute() {
-        execInContext(() -> {
-            RFunction f = create("function() {}");
-            assertTrue(ForeignAccess.sendIsExecutable(Message.IS_EXECUTABLE.createNode(), f));
+    public void testExecute() throws Exception {
+        RFunction f = create("function() {}");
+        assertTrue(ForeignAccess.sendIsExecutable(Message.IS_EXECUTABLE.createNode(), f));
 
-            TruffleObject result = (TruffleObject) ForeignAccess.sendExecute(Message.createExecute(0).createNode(), f);
-            assertTrue(ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), result));
+        TruffleObject result = (TruffleObject) ForeignAccess.sendExecute(Message.createExecute(0).createNode(), f);
+        assertTrue(ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), result));
 
-            f = create("function() {1L}");
-            assertEquals(1, ForeignAccess.sendExecute(Message.createExecute(0).createNode(), f));
+        f = create("function() {1L}");
+        assertEquals(1, ForeignAccess.sendExecute(Message.createExecute(0).createNode(), f));
 
-            f = create("function() {1}");
-            assertEquals(1.0, ForeignAccess.sendExecute(Message.createExecute(0).createNode(), f));
+        f = create("function() {1}");
+        assertEquals(1.0, ForeignAccess.sendExecute(Message.createExecute(0).createNode(), f));
 
-            f = create("function() {TRUE}");
-            assertEquals(true, ForeignAccess.sendExecute(Message.createExecute(0).createNode(), f));
+        f = create("function() {TRUE}");
+        assertEquals(true, ForeignAccess.sendExecute(Message.createExecute(0).createNode(), f));
 
-            f = create("function(a) {a}");
-            assertEquals("abc", ForeignAccess.sendExecute(Message.createExecute(1).createNode(), f, "abc"));
+        f = create("function(a) {a}");
+        assertEquals("abc", ForeignAccess.sendExecute(Message.createExecute(1).createNode(), f, "abc"));
 
-            f = create("function(a) { is.logical(a) }");
-            assertEquals(true, ForeignAccess.sendExecute(Message.createExecute(1).createNode(), f, true));
-
-            f = create("function(a) { as.external.short(a) }");
-            assertTrue(ForeignAccess.sendExecute(Message.createExecute(1).createNode(), f, 123) instanceof Short);
-            return null;
-        });
+        f = create("function(a) { is.logical(a) }");
+        assertEquals(true, ForeignAccess.sendExecute(Message.createExecute(1).createNode(), f, true));
 
+        f = create("function(a) { as.external.short(a) }");
+        assertTrue(ForeignAccess.sendExecute(Message.createExecute(1).createNode(), f, 123) instanceof Short);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RInteropScalarMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RInteropScalarMRTest.java
index 38283b935412ad28af30034f10540ec8d79641de..5b5fd10c4fb8f1923f731221d773a121ab55ed37 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RInteropScalarMRTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RInteropScalarMRTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -38,13 +38,10 @@ public class RInteropScalarMRTest extends AbstractMRTest {
 
     @Test
     public void testRInteroptScalar() throws Exception {
-        execInContext(() -> {
-            for (TruffleObject obj : createTruffleObjects()) {
-                RInteropScalar is = (RInteropScalar) obj;
-                testRIS(obj, is.getJavaType());
-            }
-            return null;
-        });
+        for (TruffleObject obj : createTruffleObjects()) {
+            RInteropScalar is = (RInteropScalar) obj;
+            testRIS(obj, is.getJavaType());
+        }
     }
 
     private static void testRIS(TruffleObject obj, Class<?> unboxedType) throws Exception {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RLanguageMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RLanguageMRTest.java
index 66e0ff602c8c224e24604e50c80fcd8212d28247..728acdac3a2ff54b1823845c291a3251f1778dcd 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RLanguageMRTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RLanguageMRTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -25,6 +25,8 @@ package com.oracle.truffle.r.test.engine.interop;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import org.graalvm.polyglot.Source;
+import org.graalvm.polyglot.Value;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -33,17 +35,15 @@ import com.oracle.truffle.api.interop.KeyInfo;
 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.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
+import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.test.generate.FastRSession;
-import org.graalvm.polyglot.Source;
-import org.graalvm.polyglot.Value;
 
 public class RLanguageMRTest extends AbstractMRTest {
 
     @Test
     public void testKeysInfo() throws Exception {
-        RLanguage rl = (RLanguage) createTruffleObjects()[0];
+        RPairList rl = (RPairList) createTruffleObjects()[0];
         int info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), rl, "nnoonnee");
         assertFalse(KeyInfo.isExisting(info));
 
@@ -56,51 +56,55 @@ public class RLanguageMRTest extends AbstractMRTest {
         info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), rl, 0);
         assertTrue(KeyInfo.isExisting(info));
         assertTrue(KeyInfo.isReadable(info));
-        assertFalse(KeyInfo.isWritable(info));
+        assertTrue(KeyInfo.isWritable(info));
         assertFalse(KeyInfo.isInvocable(info));
         assertFalse(KeyInfo.isInternal(info));
 
         info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), rl, 1);
         assertTrue(KeyInfo.isExisting(info));
         assertTrue(KeyInfo.isReadable(info));
-        assertFalse(KeyInfo.isWritable(info));
+        assertTrue(KeyInfo.isWritable(info));
         assertFalse(KeyInfo.isInvocable(info));
         assertFalse(KeyInfo.isInternal(info));
 
         info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), rl, 2);
         assertTrue(KeyInfo.isExisting(info));
         assertTrue(KeyInfo.isReadable(info));
-        assertFalse(KeyInfo.isWritable(info));
+        assertTrue(KeyInfo.isWritable(info));
         assertFalse(KeyInfo.isInvocable(info));
         assertFalse(KeyInfo.isInternal(info));
     }
 
     @Test
     public void testReadWrite() throws Exception {
-        RLanguage rl = (RLanguage) createTruffleObjects()[0];
+        RPairList rl = (RPairList) createTruffleObjects()[0];
 
         assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), rl, "nnnoooonnne"), UnknownIdentifierException.class);
         assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), rl, rl.getLength()), UnknownIdentifierException.class);
-        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), rl, 0d), UnknownIdentifierException.class);
+        assertTrue(ForeignAccess.sendRead(Message.READ.createNode(), rl, 0d) == RSymbol.install("+"));
         assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), rl, 0f), UnknownIdentifierException.class);
 
-        // TODO add some meaningfull read tests
+        // TODO add some meaningful read tests
         Assert.assertNotNull(ForeignAccess.sendRead(Message.READ.createNode(), rl, 0));
 
-        assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), rl, "aaa", "abc"), UnsupportedMessageException.class);
-        assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), rl, 0, "abc"), UnsupportedMessageException.class);
-
+        // shouldn't fail:
+        ForeignAccess.sendWrite(Message.WRITE.createNode(), rl, "aaa", "abc");
+        ForeignAccess.sendWrite(Message.WRITE.createNode(), rl, 0, "abc");
     }
 
     @Override
     protected TruffleObject[] createTruffleObjects() {
-        // TODO any simpler way to create a RLanguage ?
-        String srcTxt = "ne <- new.env(); delayedAssign('x', 1 + 2, assign.env = ne); substitute(x, ne)";
+        String srcTxt = "quote(1+2)";
         Source src = Source.newBuilder("R", srcTxt, "<testrlanguage>").internal(true).buildLiteral();
         Value result = context.eval(src);
         return new TruffleObject[]{(TruffleObject) FastRSession.getReceiver(result)};
     }
 
+    @Override
+    protected String[] getKeys(TruffleObject obj) {
+        return new String[0];
+    }
+
     @Override
     protected TruffleObject createEmptyTruffleObject() throws Exception {
         return null;
@@ -108,6 +112,6 @@ public class RLanguageMRTest extends AbstractMRTest {
 
     @Override
     protected int getSize(TruffleObject obj) {
-        return ((RLanguage) obj).getLength();
+        return ((RPairList) obj).getLength();
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/VectorMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/VectorMRTest.java
index 697cdeb547ea7913d619d8b228a027faaa2be8f1..2166e63dcedf89d3fcc9d5efe1166bfcda697a79 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/VectorMRTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/VectorMRTest.java
@@ -42,52 +42,46 @@ public class VectorMRTest extends AbstractMRTest {
 
     @Test
     public void testReadWrite() throws Exception {
-        execInContext(() -> {
-            final TruffleObject vi = RDataFactory.createIntSequence(1, 1, 10);
-            assertEquals(3, ForeignAccess.sendRead(Message.READ.createNode(), vi, 2));
-            assertEquals(3, ForeignAccess.sendRead(Message.READ.createNode(), vi, 2L));
+        final TruffleObject vi = RDataFactory.createIntSequence(1, 1, 10);
+        assertEquals(3, ForeignAccess.sendRead(Message.READ.createNode(), vi, 2));
+        assertEquals(3, ForeignAccess.sendRead(Message.READ.createNode(), vi, 2L));
 
-            assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), vi, "a"), UnknownIdentifierException.class);
-            assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), vi, 100), UnknownIdentifierException.class);
-            assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), vi, "s", "abc"), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), vi, "a"), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), vi, 100), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), vi, "s", "abc"), UnknownIdentifierException.class);
 
-            TruffleObject vd = RDataFactory.createDoubleSequence(1.1, 1, 10);
-            assertEquals(1.1, ForeignAccess.sendRead(Message.READ.createNode(), vd, 0));
+        TruffleObject vd = RDataFactory.createDoubleSequence(1.1, 1, 10);
+        assertEquals(1.1, ForeignAccess.sendRead(Message.READ.createNode(), vd, 0));
 
-            TruffleObject vb = RDataFactory.createLogicalVector(new byte[]{1, 0, 1}, true);
-            assertEquals(true, ForeignAccess.sendRead(Message.READ.createNode(), vb, 0));
+        TruffleObject vb = RDataFactory.createLogicalVector(new byte[]{1, 0, 1}, true);
+        assertEquals(true, ForeignAccess.sendRead(Message.READ.createNode(), vb, 0));
 
-            TruffleObject nvi = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), vi, 0, 123);
-            assertEquals(123, ForeignAccess.sendRead(Message.READ.createNode(), nvi, 0));
+        TruffleObject nvi = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), vi, 0, 123);
+        assertEquals(123, ForeignAccess.sendRead(Message.READ.createNode(), nvi, 0));
 
-            assertEquals(10, ForeignAccess.sendGetSize(Message.GET_SIZE.createNode(), nvi));
-            nvi = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), nvi, 100, 321);
-            assertEquals(101, ForeignAccess.sendGetSize(Message.GET_SIZE.createNode(), nvi));
-            assertEquals(321, ForeignAccess.sendRead(Message.READ.createNode(), nvi, 100));
+        assertEquals(10, ForeignAccess.sendGetSize(Message.GET_SIZE.createNode(), nvi));
+        nvi = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), nvi, 100, 321);
+        assertEquals(101, ForeignAccess.sendGetSize(Message.GET_SIZE.createNode(), nvi));
+        assertEquals(321, ForeignAccess.sendRead(Message.READ.createNode(), nvi, 100));
 
-            nvi = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), nvi, 0, "abc");
-            assertEquals("abc", ForeignAccess.sendRead(Message.READ.createNode(), nvi, 0));
-            return null;
-        });
+        nvi = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), nvi, 0, "abc");
+        assertEquals("abc", ForeignAccess.sendRead(Message.READ.createNode(), nvi, 0));
     }
 
     @Test
     public void testKeyInfo() throws Exception {
-        execInContext(() -> {
-            TruffleObject v = RDataFactory.createLogicalVector(new byte[]{1, 0, 1}, true);
-            assertInteropException(() -> ForeignAccess.sendKeys(Message.KEYS.createNode(), v), UnsupportedMessageException.class);
-
-            int keyInfo = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), v, 0);
-            assertTrue(KeyInfo.isExisting(keyInfo));
-            assertTrue(KeyInfo.isReadable(keyInfo));
-            assertTrue(KeyInfo.isWritable(keyInfo));
-            assertFalse(KeyInfo.isInvocable(keyInfo));
-            assertFalse(KeyInfo.isInternal(keyInfo));
-
-            keyInfo = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), v, 100);
-            assertFalse(KeyInfo.isExisting(keyInfo));
-            return null;
-        });
+        TruffleObject v = RDataFactory.createLogicalVector(new byte[]{1, 0, 1}, true);
+        assertInteropException(() -> ForeignAccess.sendKeys(Message.KEYS.createNode(), v), UnsupportedMessageException.class);
+
+        int keyInfo = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), v, 0);
+        assertTrue(KeyInfo.isExisting(keyInfo));
+        assertTrue(KeyInfo.isReadable(keyInfo));
+        assertTrue(KeyInfo.isWritable(keyInfo));
+        assertFalse(KeyInfo.isInvocable(keyInfo));
+        assertFalse(KeyInfo.isInternal(keyInfo));
+
+        keyInfo = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), v, 100);
+        assertFalse(KeyInfo.isExisting(keyInfo));
     }
 
     @Override
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java
index c5c3df31e1d5c3a1e07cf9633c98f7d8dbc99195..57a1f724bdd9bd8c51e08587aeadffaacece0456 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java
@@ -712,6 +712,18 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ x<-quote(function(x, y=7) 42); x[[2]] }");
 
         assertEval("{ f<-quote(function(x=42) x); f[[2]]$x<-7; eval(f)() }");
+
+        assertEval("f <- function(x) x[[1]]; l <- as.pairlist(c('a','b')); f(l); l <- quote(a+b); f(l)");
+        assertEval("l <- quote(a+b+c); l[[c(2,2)]]; l[[c(2,3)]]; l[[c(2,2)]]; l[[c(3)]]; l <- as.pairlist(c('+','x','c')); l[[2]] <- as.pairlist(c('+','a','b')); l[[c(2,2)]]; l[[c(2,3)]]; l[[c(2,2)]]; l[[c(3)]]");
+    }
+
+    @Test
+    public void testPairList() {
+        assertEval("l <- as.pairlist(c(1,2,3,4)); typeof(l); l[[3]] <- 123; typeof(l); l");
+        assertEval("l <- as.pairlist(c(1,2,3,4)); l2 <- l; typeof(l); l[[3]] <- 123; typeof(l); l");
+        assertEval("x <- as.pairlist(list(7,42)); x[[1]] <- list(); typeof(x); x$foo <- 123; typeof(x); x[1] <- list(1); typeof(x)");
+        assertEval("l <- quote(a(\"b\",1,4,3)); typeof(l); typeof(l[[1]]); typeof(l[1]); typeof(l[1:5]); typeof(l[4:5]); l[4:5]");
+        assertEval("l <- pairlist(\"a\",\"b\",1,4,3); typeof(l); typeof(l[[1]]); typeof(l[1]); typeof(l[1:5]); typeof(l[4:5]); l[4:5]");
     }
 
     @Test
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index 87cb779ed29927269b55847d7133630b176003bf..4281149ab5bd0416c2efa28f35b44ecfb3cb5d86 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -324,6 +324,9 @@ def ut_default(args):
 def ut_gate(args):
     return mx_unittest.unittest(args + _gate_unit_tests())
 
+def ut_gen(args):
+    return mx_unittest.unittest(args + _all_generated_unit_tests())
+
 def _test_package():
     return 'com.oracle.truffle.r.test'
 
@@ -597,6 +600,7 @@ _commands = {
     'rutsimple' : [ut_simple, ['options']],
     'rutdefault' : [ut_default, ['options']],
     'rutgate' : [ut_gate, ['options']],
+    'rutgen' : [ut_gen, ['options']],
     'rutnoapps' : [ut_noapps, ['options']],
     'rbcheck' : [rbcheck, '--filter [gnur-only,fastr-only,both,both-diff]'],
     'rbdiag' : [rbdiag, '(builtin)* [-v] [-n] [-m] [--sweep | --sweep=lite | --sweep=total] [--mnonly] [--noSelfTest] [--matchLevel=same | --matchLevel=error] [--maxSweeps=N] [--outMaxLev=N]'],
diff --git a/mx.fastr/mx_fastr_edinclude.py b/mx.fastr/mx_fastr_edinclude.py
index 5f2efebcfd18ef31d49e145b920c4cf7dd9b02a3..fc7326f5dc72a57752f3829ad1c0bccc8ef95391 100644
--- a/mx.fastr/mx_fastr_edinclude.py
+++ b/mx.fastr/mx_fastr_edinclude.py
@@ -74,17 +74,6 @@ use_internals_end = '''#endif
 
 '''
 
-# This rewrite is disabled, because it causes compilation error with Rcpp
-# The long term solution shall be to unify RPairList and RLanguage and
-# possibly RArgsValuesAndNames(?) to be able to change the type in place.
-set_typeof_rewrite = '''#ifdef FASTR
-SEXP SET_TYPEOF_FASTR(SEXP x, int v);
-#ifndef NO_FASTR_REDEFINE
-#define SET_TYPEOF(X,Y) X=SET_TYPEOF_FASTR(X,Y)
-#endif
-#endif
-'''
-
 def ed_r_internals(gnu_dir):
     r_internals_h = join(gnu_dir, 'Rinternals.h')
     with open(r_internals_h) as f:
@@ -116,10 +105,6 @@ def ed_r_internals(gnu_dir):
                     rewrite_var(f, var, line)
                 else:
                     f.write(line)
-            # disabled because of compilations problems with Rcpp
-            # elif 'SET_TYPEOF' in line and '(SEXP' in line:
-            #     f.write(line)
-            #     f.write(set_typeof_rewrite)
             else:
                 f.write(line)
 
diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index 191682f6b95ccb2a9c5a6af7a1ef1551fc65c8f6..7e17fff9837880a077c7eb7b3c5904bb0a86be44 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -7,7 +7,7 @@ suite = {
             {
                "name" : "truffle",
                "subdir" : True,
-               "version" : "e5a96fc63e69bed9a93e812936c9961a69d8d25e",
+               "version" : "3760adf8d12c471782649e2fc2430f7647a0eda1",
                "urls" : [
                     {"url" : "https://github.com/graalvm/graal", "kind" : "git"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},