From 23b70b05e9045578d50cabfe8ec4b399663cd53e Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 9 Aug 2016 17:09:54 +0200
Subject: [PATCH] work on quote, more RLanguage refactoring

---
 .../com/oracle/truffle/r/engine/REngine.java  |  2 +-
 .../r/engine/RRuntimeASTAccessImpl.java       | 10 ----
 .../r/library/methods/SubstituteDirect.java   |  2 +-
 .../truffle/r/nodes/builtin/base/Bind.java    |  2 +-
 .../truffle/r/nodes/builtin/base/Body.java    |  2 +-
 .../truffle/r/nodes/builtin/base/DoCall.java  | 36 +++++++++-----
 .../r/nodes/builtin/base/Expression.java      |  2 +-
 .../truffle/r/nodes/builtin/base/Formals.java |  4 +-
 .../r/nodes/builtin/base/FrameFunctions.java  | 15 +-----
 .../truffle/r/nodes/builtin/base/Quote.java   | 47 +++++++------------
 .../r/nodes/builtin/base/Substitute.java      |  2 +-
 .../com/oracle/truffle/r/nodes/RASTUtils.java | 37 ++++++++-------
 .../r/nodes/builtin/RList2EnvNode.java        |  4 +-
 .../com/oracle/truffle/r/runtime/RError.java  |  3 +-
 .../truffle/r/runtime/RRuntimeASTAccess.java  |  4 --
 .../oracle/truffle/r/runtime/RSerialize.java  |  5 +-
 .../com/oracle/truffle/r/runtime/Utils.java   |  9 ++++
 17 files changed, 86 insertions(+), 100 deletions(-)

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 479dbaca13..3908272b05 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
@@ -279,7 +279,7 @@ final class REngine implements Engine, Engine.Timings {
     @Override
     public RExpression parse(Map<String, Object> constants, Source source) throws ParseException {
         List<RSyntaxNode> list = parseImpl(constants, source);
-        Object[] data = list.stream().map(node -> RASTUtils.createLanguageElement(node.asRNode())).toArray();
+        Object[] data = list.stream().map(node -> RASTUtils.createLanguageElement(node)).toArray();
         return RDataFactory.createExpression(RDataFactory.createList(data));
     }
 
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 917a24bf4a..235abc3cfa 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
@@ -641,16 +641,6 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
         return false;
     }
 
-    @Override
-    public RBaseNode createReadVariableNode(String name) {
-        return RASTUtils.createReadVariableNode(name);
-    }
-
-    @Override
-    public RBaseNode createConstantNode(Object o) {
-        return ConstantNode.create(o);
-    }
-
     @Override
     public boolean enableDebug(RFunction func, boolean once) {
         return DebugHandling.enableDebug(func, "", RNull.instance, once, false);
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 549078a083..f8aaae671a 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
@@ -43,7 +43,7 @@ public abstract class SubstituteDirect extends RExternalBuiltinNode.Arg2 {
     protected static Object substituteDirect(Object object, REnvironment env) {
         if (object instanceof RLanguage) {
             RLanguage lang = (RLanguage) object;
-            return RASTUtils.createLanguageElement(RSubstitute.substitute(env, lang.getRep()).asRNode());
+            return RASTUtils.createLanguageElement(RSubstitute.substitute(env, lang.getRep()));
         } else {
             return object;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
index 55970d18b8..7f2684dfb9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
@@ -365,7 +365,7 @@ public abstract class Bind extends RBaseNode {
         Object argValue = promiseArgs.getArgument(argInd);
         if (argValue instanceof RPromise) {
             RPromise p = (RPromise) argValue;
-            Object node = RASTUtils.createLanguageElement(RASTUtils.unwrap(p.getRep()));
+            Object node = RASTUtils.createLanguageElement(p.getRep().asRSyntaxNode());
             if (deparseLevel == 1 && node instanceof RSymbol) {
                 return ((RSymbol) node).toString();
             } // else - TODO handle deparseLevel > 1
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java
index 7533186dd5..e852f86379 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java
@@ -39,7 +39,7 @@ public abstract class Body extends RBuiltinNode {
     @Specialization
     protected Object doBody(RFunction fun) {
         FunctionDefinitionNode fdn = (FunctionDefinitionNode) fun.getRootNode();
-        return RASTUtils.createLanguageElement(fdn.getBody().asRNode());
+        return RASTUtils.createLanguageElement(fdn.getBody());
     }
 
     @Specialization(guards = "!isRFunction(fun)")
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 6b95bfb472..a28c9d4994 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
@@ -22,7 +22,8 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.runtime.RVisibility.CUSTOM;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
@@ -44,8 +45,10 @@ import com.oracle.truffle.r.nodes.function.RCallBaseNode;
 import com.oracle.truffle.r.nodes.function.RCallNode;
 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.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RAttributeProfiles;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -54,12 +57,14 @@ 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.RPromise;
+import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.data.RPromise.PromiseState;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 // TODO Implement completely, this is a simple implementation that works when the envir argument is ignored
 @RBuiltin(name = "do.call", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"what", "args", "envir"}, behavior = COMPLEX)
@@ -78,10 +83,9 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode
 
     @Override
     protected void createCasts(CastBuilder casts) {
-        casts.arg("what").defaultError(RError.Message.MUST_BE_STRING_OR_FUNCTION, "what").mustBe(instanceOf(RFunction.class).or(stringValue()));
-        casts.arg("args").mustBe(instanceOf(RList.class));
-        casts.arg("envir").mustBe(instanceOf(REnvironment.class));
-
+        casts.arg("what").defaultError(Message.MUST_BE_STRING_OR_FUNCTION, "what").mustBe(instanceOf(RFunction.class).or(stringValue()));
+        casts.arg("args").mustBe(RAbstractListVector.class, Message.SECOND_ARGUMENT_LIST);
+        casts.arg("envir").mustBe(REnvironment.class, Message.MUST_BE_ENVIRON, "envir");
     }
 
     @Specialization
@@ -128,7 +132,7 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode
                 containsRLanguageProfile.enter();
                 callerFrame = getCallerFrame(frame, callerFrame);
                 RLanguage lang = (RLanguage) arg;
-                argValues[i] = createArgPromise(callerFrame, RASTUtils.cloneNode(lang.getRep()));
+                argValues[i] = createRLanguagePromise(callerFrame, lang);
             } else if (arg instanceof RSymbol) {
                 containsRSymbolProfile.enter();
                 RSymbol symbol = (RSymbol) arg;
@@ -136,7 +140,7 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode
                     argValues[i] = REmpty.instance;
                 } else {
                     callerFrame = getCallerFrame(frame, callerFrame);
-                    argValues[i] = createArgPromise(callerFrame, RASTUtils.createReadVariableNode(symbol.getName()));
+                    argValues[i] = createLookupPromise(callerFrame, symbol);
                 }
             }
         }
@@ -149,6 +153,17 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode
         }
     }
 
+    @TruffleBoundary
+    private static RPromise createLookupPromise(MaterializedFrame callerFrame, RSymbol symbol) {
+        Closure closure = RPromise.Closure.create(RContext.getASTBuilder().lookup(RSyntaxNode.SOURCE_UNAVAILABLE, symbol.getName(), false).asRNode());
+        return RDataFactory.createPromise(PromiseState.Supplied, closure, callerFrame);
+    }
+
+    @TruffleBoundary
+    private static RPromise createRLanguagePromise(MaterializedFrame callerFrame, RLanguage lang) {
+        return RDataFactory.createPromise(PromiseState.Supplied, RPromise.Closure.create(RASTUtils.cloneNode(lang.getRep())), callerFrame);
+    }
+
     private MaterializedFrame getCallerFrame(VirtualFrame frame, MaterializedFrame callerFrame) {
         if (getCallerFrame == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -160,9 +175,4 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode
             return callerFrame;
         }
     }
-
-    @TruffleBoundary
-    private static RPromise createArgPromise(MaterializedFrame frame, RBaseNode rep) {
-        return RDataFactory.createPromise(PromiseState.Supplied, RPromise.Closure.create(rep), frame);
-    }
 }
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 a9a681eb66..a3a40ea0d9 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
@@ -78,7 +78,7 @@ public abstract class Expression extends RBuiltinNode {
         if (isEvaluatedProfile.profile(promise.isEvaluated())) {
             return promise.getValue();
         } else {
-            return RASTUtils.createLanguageElement(RASTUtils.unwrap(promise.getRep()));
+            return RASTUtils.createLanguageElement(promise.getRep().asRSyntaxNode());
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Formals.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Formals.java
index 4c19c57467..0ab4c0723e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Formals.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Formals.java
@@ -37,6 +37,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.nodes.RNode;
 
 @RBuiltin(name = "formals", kind = INTERNAL, parameterNames = {"fun"}, behavior = PURE)
 public abstract class Formals extends RBuiltinNode {
@@ -66,7 +67,8 @@ public abstract class Formals extends RBuiltinNode {
         FormalArguments formalArgs = fdNode.getFormalArguments();
         Object succ = RNull.instance;
         for (int i = formalArgs.getSignature().getLength() - 1; i >= 0; i--) {
-            Object lang = RASTUtils.createLanguageElement(formalArgs.getDefaultArgument(i));
+            RNode argument = formalArgs.getDefaultArgument(i);
+            Object lang = argument == null ? RSymbol.MISSING : RASTUtils.createLanguageElement(argument.asRSyntaxNode());
             RSymbol name = RDataFactory.createSymbol(formalArgs.getSignature().getName(i));
             succ = RDataFactory.createPairList(lang, succ, name);
         }
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 b13c52d299..536f8770b0 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
@@ -281,20 +281,7 @@ public class FrameFunctions {
                         RPairList prev = null;
                         for (int i2 = 0; i2 < varArgNodes.length; i2++) {
                             RNode n = varArgNodes[i2];
-                            Object listValue;
-                            if (n instanceof ConstantNode) {
-                                listValue = ((ConstantNode) n).getValue();
-                            } else if (n instanceof ReadVariableNode) {
-                                String id = ((ReadVariableNode) n).getIdentifier();
-                                assert id == id.intern();
-                                listValue = RDataFactory.createSymbol(id);
-                            } else if (n instanceof VarArgNode) {
-                                listValue = createVarArgSymbol((VarArgNode) n);
-                            } else if (n instanceof RCallNode) {
-                                listValue = RDataFactory.createLanguage(n);
-                            } else {
-                                throw RInternalError.shouldNotReachHere("node: " + n + " at " + i2);
-                            }
+                            Object listValue = RASTUtils.createLanguageElement(n.asRSyntaxNode());
                             pl.setCar(listValue);
                             if (varArgSignature.getName(i2) != null) {
                                 pl.setTag(RDataFactory.createSymbolInterned(varArgSignature.getName(i2)));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java
index 40dd919e5b..2902240573 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java
@@ -25,49 +25,36 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.RASTUtils;
-import com.oracle.truffle.r.nodes.access.ConstantNode;
-import com.oracle.truffle.r.nodes.access.ReadVariadicComponentNode;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RLanguage;
-import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RPromise;
-import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 
 @RBuiltin(name = "quote", nonEvalArgs = 0, kind = PRIMITIVE, parameterNames = {"expr"}, behavior = PURE)
 public abstract class Quote extends RBuiltinNode {
 
+    protected static final int LIMIT = 3;
+
     public abstract Object execute(RPromise expr);
 
-    private final ConditionProfile rvn = ConditionProfile.createBinaryProfile();
-    private final ConditionProfile rvcn = ConditionProfile.createBinaryProfile();
-    private final ConditionProfile cn = ConditionProfile.createBinaryProfile();
+    protected static Object createLanguage(Closure closure) {
+        return Utils.makeShared(RASTUtils.createLanguageElement(closure.getExpr().asRSyntaxNode()));
+    }
 
-    @Specialization
-    protected RLanguage doQuote(@SuppressWarnings("unused") RMissing arg) {
-        throw RError.error(this, RError.Message.ARGUMENTS_PASSED_0_1, getRBuiltin().name());
+    @SuppressWarnings("unused")
+    @Specialization(limit = "LIMIT", guards = "cachedClosure == expr.getClosure()")
+    protected Object quoteCached(RPromise expr,
+                    @Cached("expr.getClosure()") Closure cachedClosure,
+                    @Cached("createLanguage(cachedClosure)") Object language) {
+        return language;
     }
 
-    @Specialization
-    protected Object doQuote(RPromise expr) {
-        // GnuR creates symbols for simple variables and actual values for constants
-        RNode node = (RNode) expr.getRep();
-        RNode unode = (RNode) RASTUtils.unwrap(node);
-        if (rvn.profile(unode instanceof ReadVariableNode)) {
-            return RASTUtils.createRSymbol(unode);
-        } else if (cn.profile(unode instanceof ConstantNode)) {
-            ConstantNode cnode = (ConstantNode) unode;
-            return cnode.getValue();
-        } else if (rvcn.profile(unode instanceof ReadVariadicComponentNode)) {
-            return RASTUtils.createRSymbol(unode);
-        } else {
-            return RDataFactory.createLanguage(unode);
-        }
+    @Specialization(contains = "quoteCached")
+    protected Object quote(RPromise expr) {
+        return RASTUtils.createLanguageElement(expr.getClosure().getExpr().asRSyntaxNode());
     }
 }
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 9fa98073c8..1534d7291a 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
@@ -96,6 +96,6 @@ public abstract class Substitute extends RBuiltinNode {
 
         // 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()).asRNode());
+        return RASTUtils.createLanguageElement(RSubstitute.substitute(env, expr.getRep()));
     }
 }
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 c03f9663f3..76da64a028 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
@@ -38,6 +38,7 @@ import com.oracle.truffle.r.nodes.function.WrapArgumentBaseNode;
 import com.oracle.truffle.r.nodes.function.WrapArgumentNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
@@ -47,6 +48,9 @@ import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RInstrumentableNode;
 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.RSyntaxFunction;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
@@ -117,32 +121,31 @@ public class RASTUtils {
      * Creates a standard {@link ReadVariableNode}.
      */
     @TruffleBoundary
-    public static ReadVariableNode createReadVariableNode(String name) {
-        return ReadVariableNode.create(name);
+    public static RSyntaxNode createReadVariableNode(String name) {
+        return RContext.getASTBuilder().lookup(RSyntaxNode.SOURCE_UNAVAILABLE, name, false);
     }
 
     /**
-     * Handles constants and symbols as special cases as required by R.
+     * Handles constants and symbols as special cases as required by R: create symbols for simple
+     * variables and actual values for constants.
      */
     @TruffleBoundary
-    public static Object createLanguageElement(RBaseNode argNode) {
-        if (argNode == null) {
-            return RSymbol.MISSING;
-        } else if (argNode instanceof ConstantNode) {
-            Object value = ((ConstantNode) argNode).getValue();
+    public static Object createLanguageElement(RSyntaxNode element) {
+        assert element != null;
+        if (element instanceof RSyntaxConstant) {
+            Object value = ((RSyntaxConstant) element).getValue();
             if (value == RMissing.instance) {
                 // special case which GnuR handles as an unnamed symbol
                 return RSymbol.MISSING;
             }
             return value;
-        } else if (argNode instanceof ReadVariableNode) {
-            return RASTUtils.createRSymbol(argNode);
-        } else if (argNode instanceof VarArgNode) {
-            VarArgNode varArgNode = (VarArgNode) argNode;
-            return RDataFactory.createSymbolInterned(varArgNode.getIdentifier());
+        } else if (element instanceof RSyntaxLookup) {
+            String id = ((RSyntaxLookup) element).getIdentifier();
+            assert id == id.intern() : element;
+            return RDataFactory.createSymbol(id);
         } else {
-            assert !(argNode instanceof VarArgNode);
-            return RDataFactory.createLanguage((RNode) argNode);
+            assert element instanceof RSyntaxCall || element instanceof RSyntaxFunction;
+            return RDataFactory.createLanguage(element.asRNode());
         }
     }
 
@@ -163,7 +166,7 @@ public class RASTUtils {
     }
 
     /**
-     * Checks wheter {@code expr instanceof RSymbol} and, if so, wraps in an {@link RLanguage}
+     * Checks whether {@code expr instanceof RSymbol} and, if so, wraps in an {@link RLanguage}
      * instance.
      */
     @TruffleBoundary
@@ -184,7 +187,7 @@ public class RASTUtils {
         if (value instanceof RNode) {
             return (RNode) value;
         } else if (value instanceof RSymbol) {
-            return RASTUtils.createReadVariableNode(((RSymbol) value).getName());
+            return RContext.getASTBuilder().lookup(RSyntaxNode.SOURCE_UNAVAILABLE, ((RSymbol) value).getName(), false).asRNode();
         } else if (value instanceof RLanguage) {
             RLanguage l = (RLanguage) value;
             return RASTUtils.cloneNode(l.getRep());
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java
index 94eab484b0..daddbaf9e3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java
@@ -24,8 +24,8 @@ package com.oracle.truffle.r.nodes.builtin;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
@@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 public final class RList2EnvNode extends RBaseNode {
 
     @TruffleBoundary
-    public REnvironment execute(RList list, REnvironment env) {
+    public REnvironment execute(RAbstractListVector list, REnvironment env) {
         if (list.getLength() == 0) {
             return env;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index fd6db9ebf6..8a2822b598 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -705,7 +705,8 @@ public final class RError extends RuntimeException {
         ERR_MSG_MUST_BE_STRING("error message must be a character string"),
         ERR_MSG_BAD("bad error message"),
         BAD_ENVIRONMENT("bad %s environment argument"),
-        CANNOT_BE_LENGTH("'%s' cannot be of length %d");
+        CANNOT_BE_LENGTH("'%s' cannot be of length %d"),
+        SECOND_ARGUMENT_LIST("second argument must be a list");
 
         public final String message;
         final boolean hasArgs;
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 7b5e9d7f20..5d6663a9d5 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
@@ -181,10 +181,6 @@ public interface RRuntimeASTAccess {
      */
     boolean isTaggedWith(Node node, Class<?> tag);
 
-    RBaseNode createReadVariableNode(String name);
-
-    RBaseNode createConstantNode(Object o);
-
     boolean enableDebug(RFunction func, boolean once);
 
     boolean disableDebug(RFunction func);
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 0458c3a736..ea78607cbe 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
@@ -72,6 +72,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 import com.oracle.truffle.r.runtime.instrument.RPackageSource;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 // Code loosely transcribed from GnuR serialize.c.
 
@@ -615,9 +616,9 @@ public class RSerialize {
                                 RLanguage lang = (RLanguage) expr.getDataAt(0);
                                 rep = lang.getRep();
                             } else if (expr.getDataAt(0) instanceof RSymbol) {
-                                rep = RContext.getRRuntimeASTAccess().createReadVariableNode(((RSymbol) expr.getDataAt(0)).getName());
+                                rep = RContext.getASTBuilder().lookup(RSyntaxNode.SOURCE_UNAVAILABLE, ((RSymbol) expr.getDataAt(0)).getName(), false).asRNode();
                             } else {
-                                rep = RContext.getRRuntimeASTAccess().createConstantNode(expr.getDataAt(0));
+                                rep = RContext.getASTBuilder().constant(RSyntaxNode.SOURCE_UNAVAILABLE, expr.getDataAt(0)).asRNode();
                             }
                             if (pl.car() == RUnboundValue.instance) {
                                 REnvironment env = pl.getTag() == RNull.instance ? REnvironment.baseEnv() : (REnvironment) pl.getTag();
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 afd902095d..e8d4ae7eb3 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
@@ -58,6 +58,7 @@ 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;
+import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
@@ -885,4 +886,12 @@ public final class Utils {
         }
         return r;
     }
+
+    public static <T> T makeShared(T o) {
+        CompilerAsserts.neverPartOfCompilation();
+        if (o instanceof RShareable) {
+            ((RShareable) o).makeSharedPermanent();
+        }
+        return o;
+    }
 }
-- 
GitLab