From b074dc832b82145cdad03fd8b881bbfe5a5c7747 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 21 Mar 2018 17:30:21 +0100
Subject: [PATCH] unify RLanguage and RPairList, proper implementation of
 SET_TYPEOF

---
 .../com/oracle/truffle/r/engine/REngine.java  |  53 +-
 .../r/engine/RRuntimeASTAccessImpl.java       | 305 +-------
 .../truffle/r/engine/interop/ListMR.java      |  25 +-
 .../interop/RForeignAccessFactoryImpl.java    |   5 +-
 .../truffle/r/engine/interop/RLanguageMR.java | 167 -----
 .../r/ffi/codegen/FFITestsCodeGen.java        |   6 +-
 .../ffi/impl/common/JavaUpCallsRFFIImpl.java  |  19 +-
 .../ffi/impl/nodes/AttributesAccessNodes.java |  12 -
 .../truffle/r/ffi/impl/nodes/CoerceNodes.java |   2 +-
 .../r/ffi/impl/nodes/ListAccessNodes.java     |  38 +-
 .../truffle/r/ffi/impl/nodes/RfEvalNode.java  |   9 +-
 .../r/ffi/impl/upcalls/StdUpCallsRFFI.java    |   2 +-
 .../graphics/RGridGraphicsAdapter.java        |   8 +-
 .../library/methods/MethodsListDispatch.java  |  13 +-
 .../r/library/methods/SubstituteDirect.java   |  10 +-
 .../r/library/stats/CompleteCases.java        |   6 +-
 .../truffle/r/library/stats/deriv/D.java      |  17 +-
 .../truffle/r/library/stats/deriv/Deriv.java  |  66 +-
 .../fficall/src/common/inlined_fastr.c        |   8 +-
 .../fficall/src/common/rffi_upcalls.h         |   1 -
 .../fficall/src/common/rffi_upcallsindex.h    |   2 +-
 .../Rinternals_truffle_common.h               |   9 +-
 .../r/nodes/builtin/base/AllNames.java        |  17 +-
 .../truffle/r/nodes/builtin/base/AsCall.java  |  22 +-
 .../r/nodes/builtin/base/AsFunction.java      |  12 +-
 .../r/nodes/builtin/base/AsVector.java        |  35 +-
 .../truffle/r/nodes/builtin/base/Call.java    |  12 +-
 .../truffle/r/nodes/builtin/base/Cat.java     |   6 +-
 .../truffle/r/nodes/builtin/base/Combine.java |   6 +-
 .../truffle/r/nodes/builtin/base/DoCall.java  |  11 +-
 .../r/nodes/builtin/base/EnvFunctions.java    |  48 +-
 .../truffle/r/nodes/builtin/base/Eval.java    |  13 +-
 .../r/nodes/builtin/base/Expression.java      |   4 +-
 .../r/nodes/builtin/base/FrameFunctions.java  |  25 +-
 .../builtin/base/HiddenInternalFunctions.java |  31 +-
 .../r/nodes/builtin/base/Identical.java       |  16 +-
 .../r/nodes/builtin/base/IsTypeFunctions.java |  95 +--
 .../nodes/builtin/base/LoadSaveFunctions.java |   4 +-
 .../truffle/r/nodes/builtin/base/Parse.java   |  23 +-
 .../r/nodes/builtin/base/RecordGraphics.java  |  10 +-
 .../r/nodes/builtin/base/Substitute.java      |   6 +-
 .../truffle/r/nodes/builtin/base/Unlist.java  |  24 +-
 .../truffle/r/nodes/builtin/base/Vector.java  |   5 +-
 .../nodes/builtin/base/infix/AccessField.java |   5 +-
 .../r/nodes/builtin/base/infix/Tilde.java     |   8 +-
 .../builtin/base/printer/LanguagePrinter.java |   8 +-
 .../builtin/base/printer/ListPrinter.java     |   4 +-
 .../builtin/base/printer/PairListPrinter.java |   7 +-
 .../builtin/base/printer/ValuePrinters.java   |   7 +-
 .../nodes/builtin/fastr/FastRSourceInfo.java  |  33 +-
 .../r/nodes/builtin/fastr/FastRTrace.java     |  11 +-
 .../nodes/builtin/helpers/TraceHandling.java  |   8 +-
 .../castsTests/ResultTypesAnalyserTest.java   |   1 -
 .../r/nodes/test/DefaultArgsExtractor.java    |   5 +-
 .../truffle/r/nodes/test/SpecialCallTest.java |  12 +-
 .../oracle/truffle/r/nodes/RASTBuilder.java   |   2 +-
 .../com/oracle/truffle/r/nodes/RASTUtils.java |  30 +-
 .../vector/CachedExtractVectorNode.java       |  16 +-
 .../access/vector/ExtractVectorNode.java      |   4 +-
 .../vector/RecursiveExtractSubscriptNode.java |   4 +-
 .../access/vector/ReplaceVectorNode.java      |  43 +-
 .../r/nodes/attributes/GetAttributesNode.java |  17 +-
 .../SpecialAttributesFunctions.java           | 130 +---
 .../r/nodes/binary/BinaryBooleanNode.java     |   4 +-
 .../control/ReplacementDispatchNode.java      |  18 +-
 .../r/nodes/control/ReplacementNode.java      |   6 +-
 .../r/nodes/function/ArgumentStatePush.java   |   6 +-
 .../truffle/r/nodes/function/RCallNode.java   |  14 -
 .../r/nodes/unary/CastComplexNode.java        |   2 +-
 .../truffle/r/nodes/unary/CastDoubleNode.java |   2 +-
 .../r/nodes/unary/CastIntegerNode.java        |   2 +-
 .../truffle/r/nodes/unary/CastListNode.java   |  36 +-
 .../r/nodes/unary/CastLogicalNode.java        |   2 +-
 .../truffle/r/nodes/unary/CastRawNode.java    |   2 +-
 .../truffle/r/nodes/unary/CastStringNode.java |   4 +-
 .../truffle/r/nodes/unary/DuplicateNode.java  |   8 +-
 .../truffle/r/nodes/unary/PrecedenceNode.java |  11 +-
 .../oracle/truffle/r/runtime/RChannel.java    |   6 +-
 .../oracle/truffle/r/runtime/RDeparse.java    |   9 +-
 .../truffle/r/runtime/RErrorHandling.java     |  25 +-
 .../oracle/truffle/r/runtime/ROptions.java    |   9 +-
 .../truffle/r/runtime/RRuntimeASTAccess.java  |  57 +-
 .../oracle/truffle/r/runtime/RSerialize.java  |  48 +-
 .../oracle/truffle/r/runtime/RSubstitute.java |  13 +-
 .../com/oracle/truffle/r/runtime/Utils.java   |  13 +-
 .../truffle/r/runtime/context/Engine.java     |   8 +-
 .../truffle/r/runtime/data/Closure.java       |  75 +-
 .../truffle/r/runtime/data/RDataFactory.java  |  34 +-
 .../truffle/r/runtime/data/RLanguage.java     | 334 ---------
 .../truffle/r/runtime/data/RObjectSize.java   |   4 +-
 .../truffle/r/runtime/data/RPairList.java     | 691 ++++++++++++++----
 .../oracle/truffle/r/runtime/data/RTypes.java |   3 +-
 .../truffle/r/runtime/gnur/SEXPTYPE.java      |  21 +-
 .../truffle/r/runtime/nodes/RBaseNode.java    |   7 +-
 .../r/runtime/nodes/RSyntaxVisitor.java       |   2 +-
 .../packages/testrffi/testrffi/R/api.R        |   9 +-
 .../packages/testrffi/testrffi/src/init_api.h |  21 +-
 .../testrffi/testrffi/src/rffiwrappers.c      |  29 +-
 .../testrffi/testrffi/src/rffiwrappers.h      |  18 +-
 .../testrffi/testrffi/tests/pairlists.R       |  21 +
 .../com/oracle/truffle/r/test/S4/TestS4.java  |   2 +-
 .../r/test/builtins/TestBuiltin_asvector.java |   2 +-
 .../r/test/builtins/TestBuiltin_function.java |   2 +-
 .../test/builtins/TestBuiltin_serialize.java  |   2 +-
 .../r/test/engine/interop/AbstractMRTest.java | 168 ++---
 .../r/test/engine/interop/ListMRTest.java     | 144 ++--
 .../test/engine/interop/RFunctionMRTest.java  |  38 +-
 .../engine/interop/RInteropScalarMRTest.java  |  13 +-
 .../test/engine/interop/RLanguageMRTest.java  |  40 +-
 .../r/test/engine/interop/VectorMRTest.java   |  66 +-
 mx.fastr/mx_fastr.py                          |   4 +
 mx.fastr/mx_fastr_edinclude.py                |  15 -
 112 files changed, 1450 insertions(+), 2183 deletions(-)
 delete mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java

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 52dd4f23b3..371e16066c 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 1e8fa828c1..ba76e4063f 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 17611a0c03..d5fb9c194d 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 ecf20060ba..158e2dde6e 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 d6f5b6b3f8..0000000000
--- 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 b96c168f53..c20b778115 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 071912314d..7bdb55e2a5 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
@@ -74,12 +74,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;
@@ -434,8 +433,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 +588,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 +709,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 272b93ca53..4ea02bcd09 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 43df7a5efb..83d2bc03c1 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
@@ -236,7 +236,7 @@ public final class CoerceNodes {
                 case LISTSXP:
                     throw RInternalError.unimplemented("Rf_coerceVector unimplemented for PairLists.");
                 case LANGSXP:
-                    throw RInternalError.unimplemented("Rf_coerceVector unimplemented for RLanguage.");
+                    throw RInternalError.unimplemented("Rf_coerceVector unimplemented for RPairList.");
                 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 d33dce2425..bd897ddfbc 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,12 +95,6 @@ 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();
@@ -177,8 +165,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 +180,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 +195,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 +215,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 +322,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 a3dd1b686b..87225b56dc 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) {
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 e9bbeb09d1..c9ba7f60d1 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 9c2cce59df..e30a62ce54 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 18e39decc0..351de044af 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 20ee2cb8d6..f203baea0f 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 c0183e5841..90e7af268e 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 f0d059510d..50b06a20e9 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 0c225227f7..e4b7de9ed1 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;
@@ -127,27 +126,27 @@ 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);
+        return deriveInternal(frame.materialize(), createConstant(expr), names, functionArg, tag, hessian);
     }
 
     @TruffleBoundary
-    private static ConstantNode createConstant(Object expr) {
-        return ConstantNode.create(expr);
+    private static RSyntaxNode createConstant(Object expr) {
+        return RContext.getASTBuilder().constant(RSyntaxNode.LAZY_DEPARSE, expr);
     }
 
     @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);
+        return deriveInternal(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);
+    private static RSyntaxElement createLookup(RSymbol expr) {
+        return RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, expr.getName(), false);
     }
 
     @Specialization
@@ -156,13 +155,17 @@ public abstract class Deriv extends RExternalBuiltinNode {
         return derivNode.execute(frame, 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(VirtualFrame frame, RPairList expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
+        return deriveInternal(frame.materialize(), extracted(expr), names, functionArg, tag, hessian);
+    }
+
+    private RSyntaxElement extracted(RPairList expr) {
+        return expr.getSyntaxElement();
     }
 
     @TruffleBoundary
-    private Object derive(MaterializedFrame frame, RBaseNode elem, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
+    private Object deriveInternal(MaterializedFrame frame, RSyntaxElement elem, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
         return findDerive(elem, names, functionArg, tag, hessian).getResult(frame.materialize(), getRLanguage());
     }
 
@@ -194,7 +197,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 +205,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 +222,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 +235,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 +248,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 +256,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 +360,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 +403,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 +489,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 4d6ac072c5..55b83d7b62 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 c6a6da14a0..04906b42fe 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 28b3d41c7b..71610473d3 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 c1e44d5c68..8a0a2f31a0 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.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 7a73125009..97779f7aba 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 7139930df0..df7305df9e 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 f996bc6bb4..998befd07a 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 b6747d6c48..98cd6f0d74 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
@@ -35,7 +35,6 @@ import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
-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.attributes.SpecialAttributesFunctions.RemoveNamesAttributeNode;
@@ -70,9 +69,8 @@ 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.RNull;
 import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -133,7 +131,7 @@ public abstract class AsVector extends RBuiltinNode.Arg2 {
     }
 
     @ImportStatic(RRuntime.class)
-    public abstract static class AsVectorInternal extends Node {
+    public abstract static class AsVectorInternal extends RBaseNode {
 
         public abstract Object execute(Object x, String mode);
 
@@ -186,7 +184,7 @@ public abstract class AsVector extends RBuiltinNode.Arg2 {
 
         // 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 +196,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 +205,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 +250,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 +267,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 +324,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 466d405fd0..339b01a16a 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,7 +40,7 @@ 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.nodes.RCodeBuilder;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -48,7 +48,7 @@ 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 +67,14 @@ 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) {
             // 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 +84,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 c1002705f1..a6f99d1096 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 c67f195568..5f9940f9c0 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 289fadac02..5d56afcee2 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 6e8e3aec40..324249e38d 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 12c2f8e410..b77b22bbce 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 c58f302013..883333d5b7 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 3ec9be5ccf..066b33b739 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,13 +254,13 @@ 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();
@@ -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 938fc86868..0cdb82aa46 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 ce13c56a75..16869c1126 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
@@ -46,14 +46,14 @@ 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.RListBase;
 import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.IdenticalVisitor;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
@@ -204,14 +204,14 @@ public abstract class Identical extends RBuiltinNode.Arg8 {
         return RRuntime.asLogical(x.getName() == y.getName());
     }
 
-    @Specialization
+    @Specialization(guards = {"x.isLanguage()", "y.isLanguage()"})
     @TruffleBoundary
-    protected byte doInternalIdentical(RLanguage x, RLanguage y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment, boolean ignoreSrcref) {
+    protected byte doInternalIdentical(RPairList x, RPairList 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();
+        RSyntaxElement xNode = x.getSyntaxElement();
+        RSyntaxElement yNode = y.getSyntaxElement();
         if (!new IdenticalVisitor().accept(xNode, yNode)) {
             return RRuntime.LOGICAL_FALSE;
         }
@@ -299,7 +299,7 @@ public abstract class Identical extends RBuiltinNode.Arg8 {
         return RRuntime.asLogical(x.getAddr() == y.getAddr());
     }
 
-    @Specialization
+    @Specialization(guards = {"!x.isLanguage()", "!y.isLanguage()"})
     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;
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 dee51d150d..7497a64aee 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 9d7e4eec31..4f4766c142 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 953d92bd68..f00a9b76b8 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;
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 5e744ad5e8..8d57bb6fbb 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 b36d37b433..ad80f28418 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 3d79c24d36..4ec423b948 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 cb883dd4d4..b2130321c4 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 adc9076fd6..36d6177e44 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 e5366c429b..918c3e637c 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 bc050bed9d..401b28c2f0 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 4fa95a508e..305d7ad9bc 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 c73fabdda7..d6e624ff9c 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 c3278b4310..7636090ea9 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 fd2d891411..fa4f21a4b9 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 437fa5d89b..c37917e34b 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 bdf06d0ff0..72c9913923 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 c275686083..efad5a55a6 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 1debf3f941..66ee87d6d1 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 a6d4cfd2fc..243a5e9e83 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 b682b1268a..f10eff707b 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 ed58d2311b..f51c7bb75c 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 381690d720..989c45541a 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 ee74036ba2..55e0a68fa0 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 a50f0a2da3..10e6d61e91 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 86bfe74041..5dfaade26b 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 2adbdc699b..addb986a7c 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 d14aeadf41..2bc9d53916 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 5212cec1c1..55b020c067 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 73dc64dc5b..68bcacaf66 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 1a99218030..9dda302040 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 4c9b9aa0b6..3b0f05c72f 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/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index 18abff07e0..84fb2f06e2 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 34dbaafbe5..2d090b4a65 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 7ffe25f55c..25f98c0075 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 1ede1d748c..a11b5b0def 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 32314a0227..a84cc5a885 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 8df91e8627..cc36f7a8d9 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 3613830314..fd644286c9 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 31acd91b95..13ba94958a 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 9e94fc4d50..e20c343977 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 8515ffef86..9207a1a2eb 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 b397cfb419..e6bdb02241 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 8138ab7f7a..206c8683f3 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 51d1e1e52a..c39997c6f3 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 57860a8259..ba250c7d6b 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 cda3444897..5e4df87fd9 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 7289839a04..8fb4c1e47e 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 61744df37a..f140db79bd 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 35a969fc46..93541e4398 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 998f2e895d..92777dd9a6 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 158df899f7..4fefd8d73a 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/RDataFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
index 131261bdbc..b56d627468 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 db8f3209f1..0000000000
--- 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 0745ec8434..0fd18057ad 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 b729095f5d..008adde909 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,84 @@ 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.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 +116,109 @@ 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")) {
+                assert false : "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 +226,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 +243,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 +274,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 +353,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 +363,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 +397,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 +414,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 +481,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 +501,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 +567,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 582b9366c7..8e782899b0 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/gnur/SEXPTYPE.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
index 977cc6c1a7..873ade3ce5 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 694a5de17e..ba05196b72 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 5ffdf75dfd..6c2a54fb14 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
@@ -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/packages/testrffi/testrffi/R/api.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/api.R
index 433e496efc..cb2bc78eb9 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 345fc0f7b5..cadf77e0a2 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 c9bf742466..8f52048977 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 f59eb727b1..60f794a162 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 8260d0d90e..5511b2bd64 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/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
index d660c79947..99ca8f6613 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
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 cf1870d917..4d7e4426ab 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_function.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_function.java
index eac9c3629d..54c577de10 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("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_serialize.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java
index 657af5b35c..c758a995ec 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
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 9fcf40ab9e..8f884c1764 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 29d48191b2..47ed7023d2 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 a6ce7ce890..d58670ae75 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 38283b9354..5b5fd10c4f 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 66e0ff602c..728acdac3a 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 697cdeb547..2166e63dce 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/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index 87cb779ed2..4281149ab5 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 5f2efebcfd..fc7326f5dc 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)
 
-- 
GitLab