diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RNode.java
index 640c4308b6dc1686f1c4c43788086b109215f0f0..b96edfab2806d17ceeee1e9b0baad9407961d119 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RNode.java
@@ -162,6 +162,14 @@ public abstract class RNode extends Node {
         return RTypesGen.RTYPES.expectRSymbol(execute(frame));
     }
 
+    public RLanguage executeRLanguage(VirtualFrame frame) throws UnexpectedResultException {
+        return RTypesGen.RTYPES.expectRLanguage(execute(frame));
+    }
+
+    public RPromise executeRPromise(VirtualFrame frame) throws UnexpectedResultException {
+        return RTypesGen.RTYPES.expectRPromise(execute(frame));
+    }
+
     public RAbstractContainer executeRAbstractContainer(VirtualFrame frame) throws UnexpectedResultException {
         return RTypesGen.RTYPES.expectRAbstractContainer(execute(frame));
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RProxyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RProxyNode.java
index cbcdc50064be449ae2f5fd852f784df407e26304..77e518bfc4f8f328562d0a1266178bd7f1f07346 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RProxyNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RProxyNode.java
@@ -217,7 +217,7 @@ public abstract class RProxyNode extends RNode {
     }
 
     @Specialization
-    protected REnvironment wrap(REnvironment x) {
+    public REnvironment wrap(REnvironment x) {
         return proxy(x);
     }
 
@@ -226,7 +226,7 @@ public abstract class RProxyNode extends RNode {
     }
 
     @Specialization
-    protected RConnection wrap(RConnection x) {
+    public RConnection wrap(RConnection x) {
         return proxy(x);
     }
 
@@ -235,7 +235,7 @@ public abstract class RProxyNode extends RNode {
     }
 
     @Specialization
-    protected RExpression wrap(RExpression x) {
+    public RExpression wrap(RExpression x) {
         return proxy(x);
     }
 
@@ -244,7 +244,7 @@ public abstract class RProxyNode extends RNode {
     }
 
     @Specialization
-    protected RSymbol wrap(RSymbol x) {
+    public RSymbol wrap(RSymbol x) {
         return proxy(x);
     }
 
@@ -252,8 +252,25 @@ public abstract class RProxyNode extends RNode {
         return (RSymbol) proxyScalar(x);
     }
 
+    public RLanguage wrap(RLanguage x) {
+        return proxy(x);
+    }
+
+    protected RLanguage proxy(RLanguage x) {
+        return (RLanguage) proxyScalar(x);
+    }
+
+    @Specialization
+    public RPromise wrap(RPromise x) {
+        return proxy(x);
+    }
+
+    protected RPromise proxy(RPromise x) {
+        return (RPromise) proxyScalar(x);
+    }
+
     @Specialization
-    protected Object[] wrap(Object[] x) {
+    public Object[] wrap(Object[] x) {
         return proxy(x);
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTypes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTypes.java
index ddf2c8fec52a5def5ef4c63964d33f4e65282093..9dd3bc8e9ec6357e81fc624e096beb76e60771d7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTypes.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTypes.java
@@ -39,7 +39,8 @@ import com.oracle.truffle.r.runtime.data.model.*;
 @TypeSystem({byte.class, int.class, double.class, RRaw.class, RComplex.class, String.class, RIntSequence.class, RDoubleSequence.class, RIntVector.class, RDoubleVector.class, RRawVector.class,
                 RComplexVector.class, RStringVector.class, RLogicalVector.class, RFunction.class, RNull.class, RMissing.class, REnvironment.class, RExpression.class, RConnection.class,
                 MaterializedFrame.class, FrameSlot.class, RAbstractIntVector.class, RAbstractDoubleVector.class, RAbstractLogicalVector.class, RAbstractComplexVector.class,
-                RAbstractStringVector.class, RAbstractRawVector.class, RList.class, RAbstractVector.class, RDataFrame.class, RSymbol.class, RAbstractContainer.class, Object[].class})
+                RAbstractStringVector.class, RAbstractRawVector.class, RList.class, RAbstractVector.class, RDataFrame.class, RSymbol.class, RPromise.class, RLanguage.class, RAbstractContainer.class,
+                Object[].class})
 public class RTypes {
 
     @TypeCheck
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltin.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltin.java
index f6df073e3a10c19114c2d222745316baf27c4c8c..2c0a0068da25d7c22e988e31d052b2d56141fe16 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltin.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltin.java
@@ -27,14 +27,39 @@ import java.lang.annotation.*;
 @Retention(RetentionPolicy.RUNTIME)
 public @interface RBuiltin {
 
+    /**
+     * The "kind" of the builtin.
+     */
     RBuiltinKind kind();
 
+    /**
+     * The name of the builtin function in the R language.
+     */
     String name();
 
+    /**
+     * A list of aliases for {@code name()}.
+     */
     String[] aliases() default {};
 
+    /**
+     * Some primitives do not evaluate one or more of their arguments. This is either a list of
+     * indices for the non-evaluated arguments (zero based) or {@code -1} to mean none are
+     * evaluated. An empty array means all arguments are evaluated. N.B. The indices identify the
+     * arguments in the order they appear in the specification, i.e., after the re-ordering of named
+     * arguments.
+     *
+     */
+    int[] nonEvalArgs() default {};
+
+    /**
+     * Special magic relating to "..." arguments. TODO Say more.
+     */
     boolean isCombine() default false;
 
+    /**
+     * How is the last parameter treated? TODO Say more.
+     */
     LastParameterKind lastParameterKind() default LastParameterKind.VALUE;
 
     public enum LastParameterKind {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
index 6b17a8307682982936e08c16a439dbc8fa9082e8..e61eb12e8436ff818a2ed13d59512dab157fafa3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
@@ -107,16 +107,20 @@ public abstract class RBuiltinNode extends RCallNode implements VisibilityContro
     }
 
     protected RBuiltin getRBuiltin() {
-        GeneratedBy generatedBy = getClass().getAnnotation(GeneratedBy.class);
-        return generatedBy.value().getAnnotation(RBuiltin.class);
+        return getRBuiltin(getClass());
     }
 
-    private static RBuiltinNode createNode(RBuiltinFactory factory, RNode[] builtinArguments, String[] argNames) {
-        RBuiltin rBuiltin = null;
-        GeneratedBy generatedBy = factory.getFactory().getClass().getAnnotation(GeneratedBy.class);
+    private static RBuiltin getRBuiltin(Class<?> klass) {
+        GeneratedBy generatedBy = klass.getAnnotation(GeneratedBy.class);
         if (generatedBy != null) {
-            rBuiltin = generatedBy.value().getAnnotation(RBuiltin.class);
+            return generatedBy.value().getAnnotation(RBuiltin.class);
+        } else {
+            return null;
         }
+    }
+
+    private static RBuiltinNode createNode(RBuiltinFactory factory, RNode[] builtinArguments, String[] argNames) {
+        RBuiltin rBuiltin = getRBuiltin(factory.getFactory().getClass());
         boolean isCombine = rBuiltin == null ? false : rBuiltin.isCombine();
         Object[] args = new Object[(isCombine ? 3 : 2) + factory.getConstantArguments().length];
         int index = 0;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java
index 5ac31d530faf63a1bccd5872f7afa078ad9e898c..15ca85788dc63592d3a5131edf5b2ef4b3df16a9 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java
@@ -119,11 +119,11 @@ public abstract class RBuiltinPackage {
         return builtins;
     }
 
-    public void loadSources(VirtualFrame frame) {
+    public void loadSources(VirtualFrame frame, REnvironment envForFrame) {
         List<Component> sources = rSources.get(getName());
         if (sources != null) {
             for (Component src : sources) {
-                REngine.parseAndEval(src.libContents, frame, false);
+                REngine.parseAndEval(src.libContents, frame, envForFrame, false);
             }
         }
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java
index 9de8df042e6c3e51bcb2a219db968c7ea7746ef1..95f1597a512a919c22f03013bf6df03971fe8856 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java
@@ -48,6 +48,28 @@ public final class RBuiltinRootNode extends RRootNode {
         return builtin.inline(args);
     }
 
+    public boolean evaluatesArgs() {
+        RBuiltin rBuiltin = builtin.getRBuiltin();
+        return rBuiltin == null || rBuiltin.nonEvalArgs().length == 0;
+    }
+
+    public boolean evalArg(int index) {
+        RBuiltin rBuiltin = builtin.getRBuiltin();
+        if (rBuiltin == null) {
+            return true;
+        } else {
+            int[] nonEvalArgs = rBuiltin.nonEvalArgs();
+            for (int i = 0; i < nonEvalArgs.length; i++) {
+                int ix = nonEvalArgs[i];
+                if (ix < 0 || ix == index) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+    }
+
     @Override
     public String getSourceCode() {
         return builtin.getSourceCode();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RDefaultBuiltinPackages.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RDefaultBuiltinPackages.java
index 6b8111b70379e6a9eb8cdf4c51db0af55b7501e4..f22e0ef2a7d8b96b3657dc1d8a1ccb8e4cacad9b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RDefaultBuiltinPackages.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RDefaultBuiltinPackages.java
@@ -44,7 +44,7 @@ public final class RDefaultBuiltinPackages extends RBuiltinPackages {
         return instance;
     }
 
-    public static void load(String name, VirtualFrame frame) {
+    public static void load(String name, VirtualFrame frame, REnvironment envForFrame) {
         RBuiltinPackage pkg = null;
         switch (name) {
             case "debug":
@@ -60,6 +60,6 @@ public final class RDefaultBuiltinPackages extends RBuiltinPackages {
                 Utils.fail("unknown builtin package: " + name);
         }
         instance.add(pkg);
-        pkg.loadSources(frame);
+        pkg.loadSources(frame, envForFrame);
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/REngine.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/REngine.java
index 854f3c9b7c9f62dcfb8704489428ffc36a7bbf29..76a44138105db992401b3cedcec5de0290dc6ca7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/REngine.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/REngine.java
@@ -68,7 +68,7 @@ public final class REngine implements RBuiltinLookupProvider {
      * @param crashOnFatalErrorArg if {@code true} any unhandled exception will terminate the
      *            process.
      * @return a {@link VirtualFrame} that can be passed to
-     *         {@link #parseAndEval(String, VirtualFrame, boolean)}
+     *         {@link #parseAndEval(String, VirtualFrame, REnvironment, boolean)}
      */
     public static VirtualFrame initialize(String[] commandArgs, ConsoleHandler consoleHandler, boolean crashOnFatalErrorArg, boolean headless) {
         startTime = System.nanoTime();
@@ -88,16 +88,16 @@ public final class REngine implements RBuiltinLookupProvider {
         ROptions.initialize();
         RProfile.initialize();
         // eval the system profile
-        REngine.parseAndEval(RProfile.systemProfile(), baseFrame, false);
+        REngine.parseAndEval(RProfile.systemProfile(), baseFrame, REnvironment.baseEnv(), false);
         REnvironment.packagesInitialize(RPackages.initialize());
         RPackageVariables.initialize(); // TODO replace with R code
         String siteProfile = RProfile.siteProfile();
         if (siteProfile != null) {
-            REngine.parseAndEval(siteProfile, baseFrame, false);
+            REngine.parseAndEval(siteProfile, baseFrame, REnvironment.baseEnv(), false);
         }
         String userProfile = RProfile.userProfile();
         if (userProfile != null) {
-            REngine.parseAndEval(userProfile, globalFrame, false);
+            REngine.parseAndEval(userProfile, globalFrame, REnvironment.globalEnv(), false);
         }
         return globalFrame;
     }
@@ -124,22 +124,25 @@ public final class REngine implements RBuiltinLookupProvider {
     }
 
     /**
-     * Parse and evaluate {@code rscript}. Value of {@code globalFrame} may be null. If
-     * {@code printResult == true}, the result of the evaluation is printed to the console.
+     * Parse and evaluate {@code rscript} in {@code frame}. {@code printResult == true}, the result
+     * of the evaluation is printed to the console.
+     *
+     * @param envForFrame the environment that {@code frame} is bound to.
+     * @return the object returned by the evaluation or {@code null} if an error occurred.
      */
-    public static Object parseAndEval(String rscript, VirtualFrame globalFrame, boolean printResult) {
-        return parseAndEvalImpl(new ANTLRStringStream(rscript), Source.asPseudoFile(rscript, "<shell_input>"), globalFrame, printResult);
+    public static Object parseAndEval(String rscript, VirtualFrame frame, REnvironment envForFrame, boolean printResult) {
+        return parseAndEvalImpl(new ANTLRStringStream(rscript), Source.asPseudoFile(rscript, "<shell_input>"), frame, envForFrame, printResult);
     }
 
     /**
      *
-     * This is intended for use by the unit test environment, where a fresh global environment is
+     * This is intended for use by the unit test environment, where a "fresh" global environment is
      * desired for each evaluation.
      */
     public static Object parseAndEvalTest(String rscript, boolean printResult) {
         VirtualFrame frame = RRuntime.createVirtualFrame();
         REnvironment.resetForTest(frame);
-        return parseAndEvalImpl(new ANTLRStringStream(rscript), Source.asPseudoFile(rscript, "<shell_input>"), frame, printResult);
+        return parseAndEvalImpl(new ANTLRStringStream(rscript), Source.asPseudoFile(rscript, "<test_input>"), frame, REnvironment.globalEnv(), printResult);
     }
 
     public static class ParseException extends Exception {
@@ -150,36 +153,99 @@ public final class REngine implements RBuiltinLookupProvider {
         }
     }
 
-    public static Object[] parse(String rscript) throws ParseException {
+    /**
+     * Parse an R expression and return an {@link RExpression} object representing the Truffle ASTs
+     * for the components.
+     */
+    public static RExpression parse(String rscript) throws ParseException {
         try {
             Sequence seq = (Sequence) ParseUtil.parseAST(new ANTLRStringStream(rscript), Source.asPseudoFile(rscript, "<parse_input>"));
             ASTNode[] exprs = seq.getExprs();
-            RExpression[] result = new RExpression[exprs.length];
+            Object[] data = new Object[exprs.length];
             for (int i = 0; i < exprs.length; i++) {
-                result[i] = new RExpression(exprs[i]);
+                data[i] = RDataFactory.createLanguage(transform(exprs[i], REnvironment.emptyEnv()));
             }
-            return result;
+            return RDataFactory.createExpression(RDataFactory.createList(data));
         } catch (RecognitionException ex) {
             throw new ParseException(ex.getMessage());
         }
     }
 
-    public static Object eval(RExpression expr, REnvironment envir, @SuppressWarnings("unused") REnvironment enclos) throws PutException {
-        RootCallTarget callTarget = transformToCallTarget((ASTNode) expr.getASTNode(), envir);
-        // to evaluate this we must create a new VirtualFrame
-        VirtualFrame frame = RRuntime.createVirtualFrame();
-        Object result = runGlobal(callTarget, frame, false);
-        // now copy the values into the environment we were supposed to evaluate this in.
-        FrameDescriptor fd = frame.getFrameDescriptor();
-        for (FrameSlot slot : fd.getSlots()) {
-            envir.put(slot.getIdentifier().toString(), frame.getValue(slot));
+    /**
+     * Support for the {@code eval} builtin using an {@link RExpression}.
+     */
+    public static Object eval(RExpression expr, REnvironment envir, REnvironment enclos) throws PutException {
+        Object result = null;
+        for (int i = 0; i < expr.getLength(); i++) {
+            result = eval((RLanguage) expr.getDataAt(i), envir, enclos);
+        }
+        return result;
+    }
+
+    /**
+     * Support for the {@code eval} builtin. 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 VirtualFrame}, that is a logical clone of "f", evaluate in that, and then
+     * update "f" on return.
+     */
+    public static Object eval(RLanguage expr, REnvironment envir, @SuppressWarnings("unused") REnvironment enclos) throws PutException {
+        RootCallTarget callTarget = makeCallTarget((RNode) expr.getRep(), REnvironment.globalEnv());
+        MaterializedFrame envFrame = envir.getFrame();
+        VirtualFrame vFrame = RRuntime.createVirtualFrame();
+        RArguments.setEnclosingFrame(vFrame, envFrame);
+        RArguments.setEnvironment(vFrame, envir);
+        FrameDescriptor envfd = envFrame.getFrameDescriptor();
+        FrameDescriptor vfd = vFrame.getFrameDescriptor();
+        // Copy existing bindings
+        for (FrameSlot slot : envfd.getSlots()) {
+            FrameSlotKind slotKind = slot.getKind();
+            FrameSlot vFrameSlot = vfd.addFrameSlot(slot.getIdentifier(), slotKind);
+            try {
+                switch (slotKind) {
+                    case Byte:
+                        vFrame.setByte(vFrameSlot, envFrame.getByte(slot));
+                        break;
+                    case Int:
+                        vFrame.setInt(vFrameSlot, envFrame.getInt(slot));
+                        break;
+                    case Double:
+                        vFrame.setDouble(vFrameSlot, envFrame.getDouble(slot));
+                        break;
+                    case Object:
+                        vFrame.setObject(vFrameSlot, envFrame.getObject(slot));
+                        break;
+                    case Illegal:
+                        break;
+                    default:
+                        throw new FrameSlotTypeException();
+                }
+            } catch (FrameSlotTypeException ex) {
+                throw new RuntimeException("unexpected FrameSlot exception", ex);
+            }
+
+        }
+        Object result = runCall(callTarget, vFrame, false);
+        if (result != null) {
+            FrameDescriptor fd = vFrame.getFrameDescriptor();
+            for (FrameSlot slot : fd.getSlots()) {
+                envir.put(slot.getIdentifier().toString(), vFrame.getValue(slot));
+            }
         }
         return result;
     }
 
-    private static Object parseAndEvalImpl(ANTLRStringStream stream, Source source, VirtualFrame globalFrame, boolean printResult) {
+    /**
+     * Evaluate a promise in the given frame (for a builtin, where we can use the
+     * {@link VirtualFrame}) of the caller directly).
+     */
+    public static Object evalPromise(RPromise expr, VirtualFrame frame) {
+        RootCallTarget callTarget = makeCallTarget((RNode) expr.getRep(), REnvironment.emptyEnv());
+        return expr.setValue(runCall(callTarget, frame, false));
+    }
+
+    private static Object parseAndEvalImpl(ANTLRStringStream stream, Source source, VirtualFrame frame, REnvironment envForFrame, boolean printResult) {
         try {
-            return runGlobal(parseToCallTarget(stream, source), globalFrame, printResult);
+            return runCall(makeCallTarget(parseToRNode(stream, source), envForFrame), frame, printResult);
         } catch (RecognitionException | RuntimeException e) {
             context.getConsoleHandler().println("Exception while parsing: " + e);
             e.printStackTrace();
@@ -187,24 +253,59 @@ public final class REngine implements RBuiltinLookupProvider {
         }
     }
 
-    private static RootCallTarget parseToCallTarget(ANTLRStringStream stream, Source source) throws RecognitionException {
-        return transformToCallTarget(ParseUtil.parseAST(stream, source), REnvironment.globalEnv());
+    /**
+     * Parses a text stream into a Truffle AST.
+     *
+     * @param stream
+     * @param source
+     * @return the root node of the Truffle AST
+     * @throws RecognitionException on parse error
+     */
+    private static RNode parseToRNode(ANTLRStringStream stream, Source source) throws RecognitionException {
+        return transform(ParseUtil.parseAST(stream, source), REnvironment.globalEnv());
     }
 
-    private static RootCallTarget transformToCallTarget(ASTNode astNode, REnvironment environment) {
+    /**
+     * Transforms an AST produced by the parser into a Truffle AST.
+     *
+     * @param astNode parser AST instance
+     * @param environment the lexically enclosing environment that will be associated with top-level
+     *            function definitions in {@code astNode}
+     * @return the root node of the Truffle AST
+     */
+    private static RNode transform(ASTNode astNode, REnvironment environment) {
         RTruffleVisitor transform = new RTruffleVisitor(environment);
-        RNode node = transform.transform(astNode);
-        REnvironment.FunctionDefinition rootNodeEnvironment = new REnvironment.FunctionDefinition(REnvironment.globalEnv());
+        return transform.transform(astNode);
+    }
+
+    /**
+     * Wraps the Truffle AST in {@code node} in an anonymous function and returns a
+     * {@link RootCallTarget} for it.
+     *
+     * @param node
+     * @param enclosing the enclosing environment to use for the anonymous function (value probably
+     *            does not matter)
+     */
+    private static RootCallTarget makeCallTarget(RNode node, REnvironment enclosing) {
+        REnvironment.FunctionDefinition rootNodeEnvironment = new REnvironment.FunctionDefinition(enclosing);
         FunctionDefinitionNode rootNode = new FunctionDefinitionNode(null, rootNodeEnvironment, node, RArguments.EMPTY_OBJECT_ARRAY, "<main>", true);
         RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode);
         return callTarget;
     }
 
-    private static Object runGlobal(RootCallTarget callTarget, VirtualFrame globalFrame, boolean printResult) {
+    /**
+     * Execute {@code callTarget} in {@code frame}, optionally printing any result. N.B.
+     * {@code callTarget.call} will create a new {@link VirtualFrame} called, say, {@code newFrame},
+     * in which to execute the (anonymous) {@link FunctionDefinitionNode} associated with
+     * {@code callTarget}. When execution reaches {@link FunctionDefinitionNode#execute},
+     * {@code frame} will be accessible via {@code newFrame.getArguments()[0]}, and the execution
+     * will continue using {@code frame}.
+     */
+    private static Object runCall(RootCallTarget callTarget, VirtualFrame frame, boolean printResult) {
         Object result = null;
         try {
             try {
-                result = callTarget.call(globalFrame);
+                result = callTarget.call(frame);
             } catch (ControlFlowException cfe) {
                 throw RError.getNoLoopForBreakNext(null);
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
index e92fdd0ac81532fee4bde8a0e4e5abd3ef750a6c..bce004f6f0a7fd6840b8cb41929390365fc95850 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
@@ -97,7 +97,7 @@ public abstract class AsCharacter extends RBuiltinNode {
     @Specialization
     public String doSymbol(VirtualFrame frame, RSymbol value) {
         controlVisibility();
-        return value.getValue();
+        return value.getName();
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java
new file mode 100644
index 0000000000000000000000000000000000000000..ab281cd7961e6302d837d752fca32a324dc4e5bc
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.builtin.base;
+
+import static com.oracle.truffle.r.nodes.builtin.RBuiltinKind.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.r.nodes.*;
+import com.oracle.truffle.r.nodes.access.*;
+import com.oracle.truffle.r.nodes.builtin.*;
+import com.oracle.truffle.r.runtime.*;
+import com.oracle.truffle.r.runtime.REnvironment.PutException;
+import com.oracle.truffle.r.runtime.data.*;
+
+/**
+ * {@code eval}, {@code evalq} and {@code local} are implemented as SUBSTITUTEs to ensure that the
+ * expression argument is not evaluated which, currently, is only possible for builtins.
+ *
+ */
+public class EvalFunctions {
+    public abstract static class EvalAdapter extends RBuiltinNode {
+        protected static final String[] PARAMETER_NAMES = new String[]{"expr", "envir", "enclosing"};
+
+        @Override
+        public Object[] getParameterNames() {
+            return PARAMETER_NAMES;
+        }
+
+        @Override
+        public RNode[] getParameterValues() {
+            return new RNode[]{ConstantNode.create(RMissing.instance), ConstantNode.create(RMissing.instance), ConstantNode.create(RMissing.instance)};
+        }
+
+        protected Object error(String msg) throws RError {
+            CompilerDirectives.transferToInterpreter();
+            throw RError.getGenericError(getEncapsulatingSourceSection(), msg);
+        }
+
+        protected Object doEvalBody(Object exprArg, REnvironment envir, @SuppressWarnings("unused") RMissing enclos) {
+            Object expr = exprArg;
+            if (expr instanceof RSymbol) {
+                // We have to turn the string value back into a RLanguage object
+                expr = RDataFactory.createLanguage(ReadVariableNode.create(((RSymbol) expr).getName(), false));
+            }
+            if (expr instanceof RExpression || expr instanceof RLanguage) {
+                try {
+                    Object result;
+                    if (expr instanceof RExpression) {
+                        result = REngine.eval((RExpression) expr, envir, REnvironment.emptyEnv());
+                    } else {
+                        result = REngine.eval((RLanguage) expr, envir, REnvironment.emptyEnv());
+                    }
+                    if (result == null) {
+                        RContext.setVisible(false);
+                        result = RNull.instance;
+                    }
+                    return result;
+                } catch (PutException x) {
+                    CompilerDirectives.transferToInterpreter();
+                    throw RError.getGenericError(getEncapsulatingSourceSection(), x.getMessage());
+                }
+            } else {
+                // just return value
+                return expr;
+            }
+        }
+    }
+
+    @RBuiltin(name = "eval", nonEvalArgs = {0}, kind = SUBSTITUTE)
+    public abstract static class Eval extends EvalAdapter {
+
+        @Specialization
+        public Object doEval(VirtualFrame frame, RPromise expr, @SuppressWarnings("unused") RMissing envir, RMissing enclos) {
+            return doEval(frame, expr, REnvironment.globalEnv(), enclos);
+        }
+
+        @Specialization
+        public Object doEval(VirtualFrame frame, RPromise expr, REnvironment envir, RMissing enclos) {
+            /*
+             * In the current hack expr is always a RPromise because we specified noEval for it in
+             * the RBuiltin The spec for eval says that expr is evaluated in the current scope (aka
+             * the caller's frame) so we do that first by evaluating the RPromise. Then we eval the
+             * result, which could do another eval, e.g. "eval(expression(1+2))"
+             * 
+             * Note that builtins do not have a separate VirtualFrame, they use the frame of the
+             * caller, so we can evaluate the promise using frame.
+             */
+            controlVisibility();
+            Object exprVal = REngine.evalPromise(expr, frame);
+            return doEvalBody(exprVal, envir, enclos);
+        }
+
+    }
+
+    @RBuiltin(name = "evalq", nonEvalArgs = {0}, kind = SUBSTITUTE)
+    public abstract static class EvalQuote extends EvalAdapter {
+        @Specialization
+        public Object doEval(RPromise expr, @SuppressWarnings("unused") RMissing envir, RMissing enclos) {
+            return doEval(expr, REnvironment.globalEnv(), enclos);
+        }
+
+        @Specialization
+        public Object doEval(RPromise expr, REnvironment envir, RMissing enclos) {
+            /*
+             * evalq does not evaluate it's first argument
+             */
+            controlVisibility();
+            return doEvalBody(expr, envir, enclos);
+        }
+
+    }
+
+    @RBuiltin(name = "local", nonEvalArgs = {0}, kind = SUBSTITUTE)
+    public abstract static class Local extends EvalAdapter {
+        @SuppressWarnings("hiding") protected static final String[] PARAMETER_NAMES = new String[]{"expr", "envir"};
+
+        @Override
+        public Object[] getParameterNames() {
+            return PARAMETER_NAMES;
+        }
+
+        @Override
+        public RNode[] getParameterValues() {
+            return new RNode[]{ConstantNode.create(RMissing.instance), ConstantNode.create(RMissing.instance)};
+        }
+
+        @Specialization
+        public Object doEval(VirtualFrame frame, RPromise expr, @SuppressWarnings("unused") RMissing envir, RMissing enclos) {
+            return doEval(expr, new REnvironment.NewEnv(EnvFunctions.frameToEnvironment(frame), 0), enclos);
+        }
+
+        @Specialization
+        public Object doEval(RPromise expr, REnvironment envir, RMissing enclos) {
+            /*
+             * local does not evaluate it's first argument
+             */
+            controlVisibility();
+            return doEvalBody(expr, envir, enclos);
+        }
+
+    }
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java
new file mode 100644
index 0000000000000000000000000000000000000000..10c7b25f541b467f89608124fe888dff03fed118
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.builtin.base;
+
+import static com.oracle.truffle.r.nodes.builtin.RBuiltinKind.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.r.nodes.builtin.*;
+import com.oracle.truffle.r.nodes.builtin.RBuiltin.*;
+import com.oracle.truffle.r.runtime.data.*;
+
+@RBuiltin(name = "expression", kind = PRIMITIVE, nonEvalArgs = {-1}, lastParameterKind = LastParameterKind.VAR_ARGS_ALWAYS_ARRAY)
+public abstract class Expression extends RBuiltinNode {
+    private static final String[] PARAMETER_NAMES = new String[]{"..."};
+
+    @Override
+    public Object[] getParameterNames() {
+        return PARAMETER_NAMES;
+    }
+
+    @Specialization
+    public Object doExpression(Object[] args) {
+        RList list = RDataFactory.createList(args);
+        return RDataFactory.createExpression(list);
+    }
+
+    @Specialization
+    public Object doExpression(RLanguage language) {
+        RList list = RDataFactory.createList(new Object[]{language});
+        return RDataFactory.createExpression(list);
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/IsExpression.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/IsExpression.java
new file mode 100644
index 0000000000000000000000000000000000000000..1c95cf6f4908c37b04c33e257a0b40610560b8c8
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/IsExpression.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.builtin.base;
+
+import static com.oracle.truffle.r.nodes.builtin.RBuiltinKind.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.r.nodes.builtin.*;
+import com.oracle.truffle.r.runtime.*;
+import com.oracle.truffle.r.runtime.data.*;
+
+@RBuiltin(name = "is.expression", kind = PRIMITIVE)
+public abstract class IsExpression extends IsTypeNode {
+
+    @Override
+    @Specialization
+    public byte isType(RExpression expr) {
+        return RRuntime.LOGICAL_TRUE;
+    }
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/IsLanguage.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/IsLanguage.java
new file mode 100644
index 0000000000000000000000000000000000000000..a65bc7a397b5dc9671db64e9d603af7fde539f6b
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/IsLanguage.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.builtin.base;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.r.nodes.builtin.*;
+import com.oracle.truffle.r.runtime.*;
+import com.oracle.truffle.r.runtime.data.*;
+
+@RBuiltin(name = "is.language", kind = RBuiltinKind.PRIMITIVE)
+public abstract class IsLanguage extends IsTypeNode {
+    @Override
+    @Specialization
+    public byte isType(RSymbol value) {
+        return RRuntime.LOGICAL_TRUE;
+    }
+
+    @Override
+    @Specialization
+    public byte isType(RExpression value) {
+        return RRuntime.LOGICAL_TRUE;
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeNode.java
index 72b62c8860eb167f65913738d72f2ca15022f815..55705d0b32de0e4ec4eb5f75e312602ffe49b373 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeNode.java
@@ -158,6 +158,21 @@ public abstract class IsTypeNode extends RBuiltinNode {
         return RRuntime.LOGICAL_FALSE;
     }
 
+    @Specialization
+    public byte isType(RLanguage value) {
+        return RRuntime.LOGICAL_FALSE;
+    }
+
+    @Specialization
+    public byte isType(RPromise value) {
+        return RRuntime.LOGICAL_FALSE;
+    }
+
+    @Specialization
+    public byte isType(RExpression value) {
+        return RRuntime.LOGICAL_FALSE;
+    }
+
     @Specialization
     public byte isType(Object value) {
         controlVisibility();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java
index a66cc0b767084f5821b8aa538a6eb4bec9e5e0b3..9e640568c2d896566c1cc567fb167b1c463c50d8 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java
@@ -43,5 +43,10 @@ public class NamespaceFunctions {
             }
         }
 
+        @Specialization
+        public Object doGetRegisteredNamespace(RSymbol name) {
+            controlVisibility();
+            return doGetRegisteredNamespace(name.getName());
+        }
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
index e5e038c2d1929fa42e26f2c77bcef51622191525..15de4679025f9af8db0bb0b5ed61cc9f743f2aa2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
@@ -25,19 +25,34 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.nodes.builtin.RBuiltinKind.*;
 
 import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.r.nodes.*;
+import com.oracle.truffle.r.nodes.access.*;
 import com.oracle.truffle.r.nodes.builtin.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
 
 /**
  * Placeholder. {@code on.exit} is special (cf {@code .Internal} in that {@code expr} is not
- * evaluated, but {@code add} is.
+ * evaluated, but {@code add} is. TODO arrange for the {@code expr} be stored with the currently
+ * evaluating function using a new slot in {@link RArguments} and run it on function exit.
  */
-@RBuiltin(name = "on.exit", kind = PRIMITIVE)
+@RBuiltin(name = "on.exit", nonEvalArgs = {0}, kind = PRIMITIVE)
 public abstract class OnExit extends RInvisibleBuiltinNode {
 
+    private static final String[] PARAMETER_NAMES = new String[]{"expr", "add"};
+
+    @Override
+    public Object[] getParameterNames() {
+        return PARAMETER_NAMES;
+    }
+
+    @Override
+    public RNode[] getParameterValues() {
+        return new RNode[]{ConstantNode.create(RNull.instance), ConstantNode.create(false)};
+    }
+
     @Specialization
-    public Object onExit(@SuppressWarnings("unused") Object expr, @SuppressWarnings("unused") Object add) {
+    public Object onExit(@SuppressWarnings("unused") RLanguage expr, @SuppressWarnings("unused") RLanguage add) {
         controlVisibility();
         RContext.getInstance().setEvalWarning("on.exit ignored");
         return RNull.instance;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
index bcf10fadd4d82262b6397fdc3884bb963739d30e..f712b2540629f3e85e34cd6c3ff7b670dac6a39f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
@@ -44,19 +44,56 @@ import com.oracle.truffle.r.runtime.data.*;
 @RBuiltin(name = "parse", kind = INTERNAL)
 public abstract class Parse extends RInvisibleBuiltinNode {
 
+    private Object error(String msg) throws RError {
+        CompilerDirectives.transferToInterpreter();
+        throw RError.getGenericError(getEncapsulatingSourceSection(), msg);
+    }
+
+    @SuppressWarnings("unused")
+    @Specialization(order = 0)
+    public Object parse(RConnection conn, RNull n, RNull text, String prompt, RNull srcFile, String encoding) {
+        controlVisibility();
+        try {
+            String[] lines = conn.readLines(0);
+            return doParse(coalesce(lines));
+        } catch (IOException | ParseException ex) {
+            throw RError.getGenericError(getEncapsulatingSourceSection(), "parse error");
+        }
+    }
+
     @SuppressWarnings("unused")
-    @Specialization
-    public Object parse(RConnection file, double n, RNull text, String prompt, RNull srcFile, String encoding) {
+    @Specialization(order = 1)
+    public Object parse(RConnection conn, double n, RNull text, String prompt, RNull srcFile, String encoding) {
         controlVisibility();
         try {
-            String[] lines = file.readLines(0);
-            Object[] exprs = REngine.parse(coalesce(lines));
-            return RDataFactory.createList(exprs);
+            String[] lines = conn.readLines((int) n);
+            return doParse(coalesce(lines));
         } catch (IOException | ParseException ex) {
             throw RError.getGenericError(getEncapsulatingSourceSection(), "parse error");
         }
     }
 
+    @SuppressWarnings("unused")
+    @Specialization(order = 2, guards = "isText")
+    public Object parse(RConnection conn, RNull n, String text, String prompt, RNull srcFile, String encoding) {
+        controlVisibility();
+        try {
+            return doParse(text);
+        } catch (ParseException ex) {
+            return error("parse error");
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static boolean isText(RConnection conn, RNull n, String text, String prompt, RNull srcFile, String encoding) {
+        return text.length() > 0;
+    }
+
+    @SlowPath
+    private static RExpression doParse(String script) throws ParseException {
+        return REngine.parse(script);
+    }
+
     @SlowPath
     private static String coalesce(String[] lines) {
         StringBuffer sb = new StringBuffer();
@@ -67,11 +104,4 @@ public abstract class Parse extends RInvisibleBuiltinNode {
         return sb.toString();
     }
 
-    @SuppressWarnings("unused")
-    @Specialization(order = 100)
-    public Object parseGeneric(Object file, Object n, Object text, Object prompt, Object srcFile, Object encoding) {
-        controlVisibility();
-        CompilerDirectives.transferToInterpreter();
-        throw RError.getGenericError(getEncapsulatingSourceSection(), "invalid arguments");
-    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java
index 88037cd3fd2454755228f7c171683e7e87e724be..5f05cac3edea1e410a817b3449396c4dd0e78903 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java
@@ -168,10 +168,6 @@ public abstract class PrettyPrinterNode extends RNode {
         return RRuntime.quoteString(operand);
     }
 
-    public static String prettyPrint(RSymbol operand) {
-        return operand.getValue();
-    }
-
     @Specialization(order = 50)
     public String prettyPrintVector(RRaw operand, Object listElementName) {
         return concat("[1] ", prettyPrint(operand));
@@ -181,12 +177,12 @@ public abstract class PrettyPrinterNode extends RNode {
         return operand.toString();
     }
 
-    @Specialization
+    @Specialization(order = 60)
     public String prettyPrint(RFunction operand, Object listElementName) {
         return ((RRootNode) operand.getTarget().getRootNode()).getSourceCode();
     }
 
-    @Specialization
+    @Specialization(order = 70)
     public String prettyPrint(VirtualFrame frame, REnvironment operand, Object listElementName) {
         RAttributes attributes = operand.getAttributes();
         if (attributes == null) {
@@ -200,6 +196,23 @@ public abstract class PrettyPrinterNode extends RNode {
         }
     }
 
+    @Specialization(order = 80)
+    public String prettyPrint(VirtualFrame frame, RExpression expr, Object listElementName) {
+        // TODO extract source of the elements
+        return "expression";
+    }
+
+    @Specialization(order = 85)
+    public String prettyPrintSymbol(RSymbol operand, Object listElementName) {
+        return operand.getName();
+    }
+
+    @Specialization(order = 86)
+    public String prettyPrint(VirtualFrame frame, RLanguage expr, Object listElementName) {
+        // TODO extract source of the element
+        return "language element";
+    }
+
     private String printAttributes(VirtualFrame frame, RAbstractVector vector, RAttributes attributes) {
         StringBuilder builder = new StringBuilder();
         for (RAttribute attr : attributes) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java
similarity index 66%
rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
rename to com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java
index 160868dc312d1d46596349fdbb5934add70f5957..e98994c03271f769f248535015dac971c46ea000 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java
@@ -22,34 +22,37 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.nodes.builtin.RBuiltinKind.*;
-
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.r.nodes.*;
+import com.oracle.truffle.r.nodes.access.*;
 import com.oracle.truffle.r.nodes.builtin.*;
 import com.oracle.truffle.r.runtime.*;
-import com.oracle.truffle.r.runtime.REnvironment.PutException;
 import com.oracle.truffle.r.runtime.data.*;
 
-@RBuiltin(name = "eval", kind = INTERNAL)
-public abstract class Eval extends RBuiltinNode {
+@RBuiltin(name = "quote", nonEvalArgs = {0}, kind = RBuiltinKind.PRIMITIVE)
+public abstract class Quote extends RBuiltinNode {
+    private static final String[] PARAMETER_NAMES = new String[]{"expr"};
 
-    @Specialization
-    public Object doEval(RExpression expr, REnvironment envir, REnvironment enclos) {
-        controlVisibility();
-        try {
-            return REngine.eval(expr, envir, enclos);
-        } catch (PutException x) {
-            throw RError.getGenericError(getEncapsulatingSourceSection(), x.getMessage());
-        }
+    @Override
+    public Object[] getParameterNames() {
+        return PARAMETER_NAMES;
+    }
+
+    @Override
+    public RNode[] getParameterValues() {
+        return new RNode[]{ConstantNode.create(RMissing.instance)};
     }
 
-    @SuppressWarnings("unused")
     @Specialization
-    public Object doEval(Object expr, Object envr, Object enclos) {
-        controlVisibility();
+    public RLanguage doQuote(@SuppressWarnings("unused") RMissing arg) {
         CompilerDirectives.transferToInterpreter();
-        throw RError.getGenericError(getEncapsulatingSourceSection(), "invalid arguments");
+        throw RError.getZ1ArgumentsPassed(getEncapsulatingSourceSection(), getRBuiltin().name());
     }
 
+    @Specialization
+    public RLanguage doQuote(RLanguage arg) {
+        controlVisibility();
+        return arg;
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/R/eval.R b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/R/eval.R
index 0c5192d7ad7b80b4c89676d7a873b02acfa1b6e8..726244797592a0f79e5000df528ef50336fe2afb 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/R/eval.R
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/R/eval.R
@@ -19,21 +19,23 @@
 .GlobalEnv <- environment()
 parent.frame <- function(n = 1) .Internal(parent.frame(n))
 
-eval <-
-    function(expr, envir = parent.frame(),
-      enclos = if(is.list(envir) || is.pairlist(envir))
-                       parent.frame() else baseenv())
-    .Internal(eval(expr, envir, enclos))
+# currently implemented as a direct builtin
+#eval <-
+#    function(expr, envir = parent.frame(),
+#      enclos = if(is.list(envir) || is.pairlist(envir))
+#                       parent.frame() else baseenv())
+#    .Internal(eval(expr, envir, enclos))
 
 eval.parent <- function(expr, n = 1) {
     p <- parent.frame(n + 1)
     eval(expr, p)
 }
 
-evalq <-
-    function (expr, envir = parent.frame(), enclos = if (is.list(envir) ||
-    is.pairlist(envir)) parent.frame() else baseenv())
-      .Internal(eval(substitute(expr), envir, enclos))
+# currently implemented as a direct builtin
+#evalq <-
+#    function (expr, envir = parent.frame(), enclos = if (is.list(envir) ||
+#    is.pairlist(envir)) parent.frame() else baseenv())
+#      .Internal(eval(substitute(expr), envir, enclos))
 
 # currently implemented as a direct builtin
 #new.env <- function (hash = TRUE, parent = parent.frame(), size = 29L)
@@ -45,9 +47,10 @@ parent.env <- function(env)
 `parent.env<-` <- function(env, value)
     .Internal("parent.env<-"(env, value))
 
-local <-
-    function (expr, envir = new.env())
-    eval.parent(substitute(eval(quote(expr), envir)))
+# currently implemented as a direct builtin
+#local <-
+#    function (expr, envir = new.env())
+#    eval.parent(substitute(eval(quote(expr), envir)))
 
 # Implemented as direct builtin
 #Recall <- function(...) .Internal(Recall(...))
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Typeof.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Typeof.java
index d481dc76e3315a82d662dfe6e9b3de5ce3fa9a3a..c81d32f2599ac29d51cf6a9019f0c2201e5f9eff 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Typeof.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Typeof.java
@@ -140,6 +140,24 @@ public abstract class Typeof extends RBuiltinNode {
         return "symbol";
     }
 
+    @Specialization()
+    public String typeof(RLanguage language) {
+        controlVisibility();
+        return "language";
+    }
+
+    @Specialization()
+    public String typeof(RPromise promise) {
+        controlVisibility();
+        return "promise";
+    }
+
+    @Specialization()
+    public String typeof(RExpression symbol) {
+        controlVisibility();
+        return "expression";
+    }
+
     @Specialization(order = 100, guards = "isFunctionBuiltin")
     public String typeofBuiltin(RFunction obj) {
         controlVisibility();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java
index 4be0aeba052f8c8ce93e7a755e78b6114aa83f9d..a9e57bb24b883f6227834accc249dae5183ea44c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java
@@ -18,7 +18,9 @@ import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.r.nodes.*;
 import com.oracle.truffle.r.nodes.access.*;
 import com.oracle.truffle.r.nodes.builtin.*;
+import com.oracle.truffle.r.nodes.builtin.base.UseMethodFactory.*;
 import com.oracle.truffle.r.nodes.control.*;
+import com.oracle.truffle.r.nodes.unary.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
 import com.oracle.truffle.r.runtime.data.model.*;
@@ -48,25 +50,13 @@ public abstract class UseMethod extends RBuiltinNode {
         controlVisibility();
         if (useMethodNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            useMethodNode = insert(new UseMethodUninitializedNode());
-        }
-        return useMethodNode.execute(frame, generic, arg);
-    }
-
-    private static final class UseMethodUninitializedNode extends UseMethodNode {
-        @Override
-        public Object execute(VirtualFrame frame, final String generic, Object obj) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            return specialize(obj).execute(frame, generic, obj);
-        }
-
-        private UseMethodNode specialize(Object obj) {
-            CompilerAsserts.neverPartOfCompilation();
-            if (obj instanceof RMissing) {
-                return this.replace(new UseMethodGenericOnlyNode());
+            if (arg instanceof RMissing) {
+                useMethodNode = insert(new UseMethodGenericOnlyNode());
+            } else {
+                useMethodNode = insert(new UseMethodGenericAndObjectNode());
             }
-            return this.replace(new UseMethodGenericAndObjectNode());
         }
+        throw new ReturnException(useMethodNode.execute(frame, generic, arg));
     }
 
     /*
@@ -83,7 +73,7 @@ public abstract class UseMethod extends RBuiltinNode {
             }
             Object enclosingArg = RArguments.getArgument(frame, 0);
             initDispatchedCallNode(generic);
-            throw new ReturnException(dispatchedCallNode.execute(frame, getClassHierarchy(enclosingArg)));
+            return dispatchedCallNode.execute(frame, classHierarchyNode.execute(frame, enclosingArg));
         }
     }
 
@@ -92,13 +82,14 @@ public abstract class UseMethod extends RBuiltinNode {
         @Override
         public Object execute(VirtualFrame frame, final String generic, Object obj) {
             initDispatchedCallNode(generic);
-            throw new ReturnException(dispatchedCallNode.execute(frame, getClassHierarchy(obj)));
+            return dispatchedCallNode.execute(frame, classHierarchyNode.execute(frame, obj));
         }
     }
 
     private abstract static class UseMethodNode extends RNode {
 
         @Child protected DispatchedCallNode dispatchedCallNode;
+        @Child ClassHierarchyNode classHierarchyNode = ClassHierarchyNodeFactory.create(null);
         protected String lastGenericName;
 
         @Override
@@ -115,28 +106,41 @@ public abstract class UseMethod extends RBuiltinNode {
             }
         }
 
-        protected RStringVector getClassHierarchy(Object anObj) {
-            if (anObj instanceof RAbstractContainer) {
-                return ((RAbstractContainer) anObj).getClassHierarchy();
-            }
-            if (anObj instanceof Byte) {
-                return RDataFactory.createStringVector(RRuntime.TYPE_LOGICAL);
-            }
-            if (anObj instanceof String) {
-                return RDataFactory.createStringVector(RRuntime.TYPE_CHARACTER);
-            }
-            if (anObj instanceof Integer) {
-                return RDataFactory.createStringVector(RRuntime.TYPE_INTEGER);
-            }
-            if (anObj instanceof Double) {
-                return RDataFactory.createStringVector(RRuntime.CLASS_DOUBLE, RDataFactory.COMPLETE_VECTOR);
-            }
-            if (anObj instanceof RComplex) {
-                return RDataFactory.createStringVector(RRuntime.TYPE_COMPLEX);
-            }
-            throw new AssertionError();
+        public abstract Object execute(VirtualFrame frame, final String generic, final Object o);
+    }
+
+    protected abstract static class ClassHierarchyNode extends UnaryNode {
+
+        public abstract RStringVector execute(VirtualFrame frame, Object arg);
+
+        @Specialization(order = 0)
+        public RStringVector getClassHr(RAbstractContainer arg) {
+            return arg.getClassHierarchy();
         }
 
-        public abstract Object execute(VirtualFrame frame, final String generic, final Object o);
+        @Specialization
+        public RStringVector getClassHr(@SuppressWarnings("unused") byte arg) {
+            return RDataFactory.createStringVector(RRuntime.TYPE_LOGICAL);
+        }
+
+        @Specialization
+        public RStringVector getClassHr(@SuppressWarnings("unused") String arg) {
+            return RDataFactory.createStringVector(RRuntime.TYPE_CHARACTER);
+        }
+
+        @Specialization
+        public RStringVector getClassHr(@SuppressWarnings("unused") int arg) {
+            return RDataFactory.createStringVector(RRuntime.TYPE_INTEGER);
+        }
+
+        @Specialization
+        public RStringVector getClassHr(@SuppressWarnings("unused") double arg) {
+            return RDataFactory.createStringVector(RRuntime.CLASS_DOUBLE, RDataFactory.COMPLETE_VECTOR);
+        }
+
+        @Specialization
+        public RStringVector getClassHr(@SuppressWarnings("unused") RComplex arg) {
+            return RDataFactory.createStringVector(RRuntime.TYPE_COMPLEX);
+        }
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java
index 8402109347d743b5f54de1d8b75c8184aae6a4c0..21e7168959c92c6670b29a04af44874c96bd527d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java
@@ -102,6 +102,11 @@ public abstract class ForNode extends LoopNode {
         return RNull.instance;
     }
 
+    @Specialization
+    public Object doSequence(VirtualFrame frame, RExpression expr) {
+        return doSequence(frame, expr.getList());
+    }
+
     @Specialization
     public Object doSequence(VirtualFrame frame, int x) {
         int count = 0;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
index cca25557b428fdad4ff29ba2218628b29c91be5d..d19ff45cf1ccf805df0db1a616028dc776de236f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
@@ -26,6 +26,7 @@ import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.r.nodes.*;
+import com.oracle.truffle.r.nodes.builtin.*;
 import com.oracle.truffle.r.nodes.control.*;
 import com.oracle.truffle.r.runtime.*;
 
@@ -41,21 +42,22 @@ public final class FunctionDefinitionNode extends RRootNode {
     private final String description;
 
     /**
-     * An instance of this node may be called from a global scope with the intention to have its
-     * execution leave a footprint behind in that scope, e.g., during library loading. In that case,
-     * {@code forGlobal} is {@code true}, and the {@link #execute(VirtualFrame)} method must be
-     * invoked with one argument, namely the {@link VirtualFrame} representing the global scope.
-     * Execution will then proceed in the context of that frame.
+     * An instance of this node may be called from {@link REngine#runCall} with the intention to
+     * have its execution leave a footprint behind in a specific frame/environment, e.g., during
+     * library loading, commands from the shell, or R's {@code eval} and its friends. In that case,
+     * {@code substituteFrame} is {@code true}, and the {@link #execute(VirtualFrame)} method must
+     * be invoked with one argument, namely the {@link VirtualFrame} to be side-effected. Execution
+     * will then proceed in the context of that frame.
      */
-    private final boolean forGlobal;
+    private final boolean substituteFrame;
 
-    public FunctionDefinitionNode(SourceSection src, REnvironment.FunctionDefinition descriptor, RNode body, Object[] parameterNames, String description, boolean forGlobal) {
+    public FunctionDefinitionNode(SourceSection src, REnvironment.FunctionDefinition descriptor, RNode body, Object[] parameterNames, String description, boolean substituteFrame) {
         super(src, parameterNames, descriptor.getDescriptor());
         this.descriptor = descriptor;
         this.uninitializedBody = NodeUtil.cloneNode(body);
         this.body = body;
         this.description = description;
-        this.forGlobal = forGlobal;
+        this.substituteFrame = substituteFrame;
     }
 
     public REnvironment getDescriptor() {
@@ -65,7 +67,7 @@ public final class FunctionDefinitionNode extends RRootNode {
     @Override
     public Object execute(VirtualFrame frame) {
         try {
-            if (forGlobal) {
+            if (substituteFrame) {
                 VirtualFrame vf = (VirtualFrame) frame.getArguments()[0];
                 Object result = body.execute(vf);
                 return result;
@@ -85,7 +87,7 @@ public final class FunctionDefinitionNode extends RRootNode {
     @Override
     public boolean isSplittable() {
         // don't bother splitting library-loading nodes
-        return !forGlobal;
+        return !substituteFrame;
     }
 
     @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..d4abcf6d0e93ad0ff0e6d419030531005c41fca7
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.function;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.r.nodes.*;
+import com.oracle.truffle.r.runtime.data.*;
+
+public final class PromiseNode extends RNode {
+    RPromise promise;
+
+    private PromiseNode(RPromise promise) {
+        this.promise = promise;
+    }
+
+    public static PromiseNode create(RPromise promise) {
+        return new PromiseNode(promise);
+    }
+
+    @Override
+    public Object execute(VirtualFrame frame) {
+        return promise;
+    }
+
+}
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 1ca69e5ef60f4b9b85966e82e93cc31eb17ff972..0c45092a06004000ff76b851f60eb30420daedaa 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
@@ -248,8 +248,11 @@ public abstract class RCallNode extends RNode {
                 CompilerDirectives.transferToInterpreter();
                 throw RError.getUnusedArgument(getEncapsulatingSourceSection(), unusedArgNode.getSourceSection().getCode());
             }
+            RNode[] argumentNodes = arguments.getArguments();
+            RNode[] origArgumentNodes = argumentNodes;
+            // Handle named args and varargs
             if (arguments.getNameCount() != 0 || hasVarArgs) {
-                RNode[] permuted = permuteArguments(arguments.getArguments(), rootNode.getParameterNames(), actualNames, new VarArgsAsObjectArrayNodeFactory());
+                RNode[] permuted = permuteArguments(argumentNodes, rootNode.getParameterNames(), actualNames, new VarArgsAsObjectArrayNodeFactory());
                 if (!isBuiltin) {
                     for (int i = 0; i < permuted.length; i++) {
                         if (permuted[i] == null) {
@@ -257,9 +260,45 @@ public abstract class RCallNode extends RNode {
                         }
                     }
                 }
-                return CallArgumentsNode.create(permuted, arguments.getNames());
+                argumentNodes = permuted;
             }
-            return arguments;
+            /*
+             * This is a temporary fix to create promises just for builtin functions that do not
+             * evaluate their arguments, e.g. expression, eval. We have do the check after
+             * permutation to get the correct index position. Unfortunately, ... args have been
+             * swept up into an array, so it's a bit trickier.
+             */
+            if (isBuiltin && !((RBuiltinRootNode) rootNode).evaluatesArgs()) {
+                RBuiltinRootNode builtinRootNode = (RBuiltinRootNode) rootNode;
+                RNode[] modifiedArgs = new RNode[argumentNodes.length];
+                int lix = 0; // logical index position
+                for (int i = 0; i < argumentNodes.length; i++) {
+                    RNode argumentNode = argumentNodes[i];
+                    if (argumentNode instanceof VarArgsAsObjectArrayNode) {
+                        VarArgsAsObjectArrayNode vArgumentNode = (VarArgsAsObjectArrayNode) argumentNode;
+                        RNode[] modifiedVArgumentNodes = new RNode[vArgumentNode.elementNodes.length];
+                        for (int j = 0; j < vArgumentNode.elementNodes.length; j++) {
+                            modifiedVArgumentNodes[j] = checkPromise(builtinRootNode, vArgumentNode.elementNodes[j], lix);
+                            lix++;
+                        }
+                        modifiedArgs[i] = new VarArgsAsObjectArrayNode(modifiedVArgumentNodes);
+                    } else {
+                        modifiedArgs[i] = checkPromise(builtinRootNode, argumentNode, lix);
+                        lix++;
+                    }
+                }
+                argumentNodes = modifiedArgs;
+            }
+            return origArgumentNodes == argumentNodes ? arguments : CallArgumentsNode.create(argumentNodes, arguments.getNames());
+        }
+
+        private static RNode checkPromise(RBuiltinRootNode builtinRootNode, RNode argNode, int lix) {
+            if (!builtinRootNode.evalArg(lix)) {
+                return PromiseNode.create(new RPromise(argNode));
+            } else {
+                return argNode;
+            }
+
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToContainerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToContainerNode.java
index 3f225681aa4dfc70aa05c067a304833b483cca12..786902a8254757df4ba90049fa22171ea2423534 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToContainerNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToContainerNode.java
@@ -73,4 +73,9 @@ public abstract class CastToContainerNode extends CastNode {
         return dataFrame;
     }
 
+    @Specialization
+    public RExpression cast(RExpression expression) {
+        return expression;
+    }
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java
index d10b857987e19158e89c76e22dcb8c47e4e07bec..b23f912eb5d447ed3c8c6f0722734b61db38e572 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java
@@ -59,6 +59,10 @@ import com.oracle.truffle.r.runtime.data.*;
  * All frame elements should <b>always</b> be accessed through the getter and setter functions
  * defined in this class, as they provide a means of accessing the frame contents that is
  * transparent to layout changes.
+ *
+ * The INDEX_ENVIRONMENT slot is typically not set for frames associated with function evaluations,
+ * because such environment instances are only created on demand. It is however, set for frames
+ * associated with packages and the global environment.
  */
 // @formatter:on
 public final class RArguments {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvironment.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvironment.java
index 13f2a52fb14b47a8f8b666efece01354e10e87c1..67dc70202b99789cee4a169bd517ae5d40e30787 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvironment.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvironment.java
@@ -226,7 +226,7 @@ public abstract class REnvironment implements RAttributable {
         initSearchList();
 
         // load base package first
-        RPackages.loadBuiltin("base", baseFrame);
+        RPackages.loadBuiltin("base", baseFrame, baseEnv);
     }
 
     public static void packagesInitialize(ArrayList<RPackage> rPackages) {
@@ -234,8 +234,8 @@ public abstract class REnvironment implements RAttributable {
         REnvironment pkgParent = autoloadEnv;
         for (RPackage rPackage : rPackages) {
             VirtualFrame pkgFrame = RRuntime.createVirtualFrame();
-            RPackages.loadBuiltin(rPackage.name, pkgFrame);
             Package pkgEnv = new Package(pkgParent, rPackage.name, pkgFrame, rPackage.path);
+            RPackages.loadBuiltin(rPackage.name, pkgFrame, pkgEnv);
             attach(2, pkgEnv);
             pkgParent = pkgEnv;
         }
@@ -351,10 +351,7 @@ public abstract class REnvironment implements RAttributable {
         searchPath.add(bpos, env);
         // Now must adjust the Frame world so that unquoted variable lookup works
         MaterializedFrame aboveFrame = envAbove.frameAccess.getFrame();
-        MaterializedFrame envFrame = env.frameAccess.getFrame();
-        if (envFrame == null) {
-            envFrame = new REnvMaterializedFrame((REnvMapFrameAccess) env.frameAccess);
-        }
+        MaterializedFrame envFrame = env.getFrame();
         RArguments.attachFrame(aboveFrame, envFrame);
     }
 
@@ -491,11 +488,17 @@ public abstract class REnvironment implements RAttributable {
     }
 
     /**
-     * Return the {@link MaterializedFrame} associated with this environment, or {@code null} if
-     * there is none.
+     * Return the {@link MaterializedFrame} associated with this environment, installing one if
+     * there is none in the case of {@link NewEnv} environments.
      */
     public MaterializedFrame getFrame() {
-        return frameAccess.getFrame();
+        MaterializedFrame envFrame = frameAccess.getFrame();
+        if (envFrame == null) {
+            if (this instanceof NewEnv) {
+                envFrame = new REnvMaterializedFrame((REnvMapFrameAccess) frameAccess);
+            }
+        }
+        return envFrame;
     }
 
     public void lock(boolean bindings) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RPackages.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RPackages.java
index 51320c4c4c97b3fb6a1070881d60a0e137dd509b..eb07fe02f736f4ae124f22cb2dc5a2b35c2133d0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RPackages.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RPackages.java
@@ -68,11 +68,13 @@ public class RPackages {
 
     /**
      * Purely a workaround for project circularity between nodes and runtime.
+     * 
+     * @param envForFrame TODO
      */
-    public static void loadBuiltin(String name, VirtualFrame frame) {
+    public static void loadBuiltin(String name, VirtualFrame frame, REnvironment envForFrame) {
         try {
-            Method loadMethod = Class.forName("com.oracle.truffle.r.nodes.builtin.RDefaultBuiltinPackages").getDeclaredMethod("load", String.class, VirtualFrame.class);
-            loadMethod.invoke(null, new Object[]{name, frame});
+            Method loadMethod = Class.forName("com.oracle.truffle.r.nodes.builtin.RDefaultBuiltinPackages").getDeclaredMethod("load", String.class, VirtualFrame.class, REnvironment.class);
+            loadMethod.invoke(null, new Object[]{name, frame, envForFrame});
         } catch (Exception ex) {
             ex.printStackTrace();
             Utils.fail("failed to load builtin package: " + name + ": " + ex);
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 ee86091e0b9dcede888b909ed9027790255d6691..79df1147d9fd0cfcdca7ca4299196649118c536e 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
@@ -291,6 +291,10 @@ public final class RDataFactory {
         return traceDataCreated(new RDataFrame(vector));
     }
 
+    public static RExpression createExpression(RList list) {
+        return traceDataCreated(new RExpression(list));
+    }
+
     public static RVector createObjectVector(Object[] data, boolean completeVector) {
         if (data.length < 1) {
             return null;
@@ -308,4 +312,9 @@ public final class RDataFactory {
     public static RSymbol createSymbol(String name) {
         return new RSymbol(name);
     }
+
+    public static RLanguage createLanguage(Object rep) {
+        return new RLanguage(rep);
+    }
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
index 480872815946b50674df602847f879d0f24028a2..9a8d910cedcb72a37f054a9eb39d8e606acbe1ad 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
@@ -22,15 +22,70 @@
  */
 package com.oracle.truffle.r.runtime.data;
 
-public class RExpression {
-    private final Object astNode;
+import com.oracle.truffle.r.runtime.data.model.*;
 
-    public RExpression(Object astNode) {
-        this.astNode = astNode;
+public class RExpression implements RAbstractContainer {
+
+    private final RList data;
+
+    public RExpression(RList data) {
+        this.data = data;
+    }
+
+    public RList getList() {
+        return data;
+    }
+
+    public Object getDataAt(int index) {
+        return data.getDataAt(index);
+    }
+
+    public RAttributes initAttributes() {
+        return data.initAttributes();
+    }
+
+    public RAttributes getAttributes() {
+        return data.getAttributes();
+    }
+
+    public int getLength() {
+        return data.getLength();
+    }
+
+    public int[] getDimensions() {
+        return data.getDimensions();
+    }
+
+    public Class<?> getElementClass() {
+        return null;
+    }
+
+    public RVector materializeNonSharedVector() {
+        return data.materializeNonSharedVector();
+    }
+
+    public Object getDataAtAsObject(int index) {
+        return data.getDataAtAsObject(index);
+    }
+
+    public Object getNames() {
+        return data.getNames();
+    }
+
+    public RList getDimNames() {
+        return data.getDimNames();
+    }
+
+    public Object getRowNames() {
+        return data.getRowNames();
+    }
+
+    public RStringVector getClassHierarchy() {
+        return data.getClassHierarchy();
     }
 
-    public Object getASTNode() {
-        return astNode;
+    public boolean isObject() {
+        return false;
     }
 
 }
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
new file mode 100644
index 0000000000000000000000000000000000000000..5400bcbeb4e977668a8a3c2edcd0e607b32b9b20
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, 2014, 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;
+
+/**
+ * Denotes an (unevaluated) element of, e.g. an {@link RExpression}. The representation is not
+ * disclosed here, owing partly to import circularities, but it will typically be an {@code RNode}
+ * that captures the (unevaluated) AST for the element.
+ */
+@com.oracle.truffle.api.CompilerDirectives.ValueType
+public class RLanguage {
+    private final Object rep;
+
+    public RLanguage(Object rep) {
+        this.rep = rep;
+    }
+
+    public Object getRep() {
+        return rep;
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
new file mode 100644
index 0000000000000000000000000000000000000000..cb8ee3681354100adad6542c31113cec05e0b493
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, 2014, 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;
+
+/**
+ * Denotes an R {@code promise}. It extends {@link RLanguage} with a (lazily) evaluated value.
+ */
+@com.oracle.truffle.api.CompilerDirectives.ValueType
+public class RPromise extends RLanguage {
+    /**
+     * Denotes a promise that raised an error during evaluation.
+     */
+    private static Object ERROR = new Object();
+
+    private Object value;
+
+    /**
+     * Create the promise with a representation that allow evaluation later.
+     */
+    public RPromise(Object rep) {
+        super(rep);
+    }
+
+    /**
+     * This is a workaround for the fact that REngine can't be called from here (at the moment),
+     * otherwise the evaluation would be implicitly done in {@link #getValue}.
+     */
+    public Object setValue(Object newValue) {
+        if (value == null) {
+            if (newValue == null) {
+                this.value = ERROR;
+            } else {
+                this.value = newValue;
+            }
+        }
+        return this.value;
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    /**
+     * Returns {@code true} if this promise has been evaluated?
+     */
+    public boolean hasValue() {
+        return value != null;
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java
index 885466dbd4a8f7623db78df7e46eed7f5a36374c..fca9e5e1f20b170b6f58cb901f47e24397c0c43a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java
@@ -22,15 +22,19 @@
  */
 package com.oracle.truffle.r.runtime.data;
 
+/**
+ * Denotes an R "symbol" or "name". Its rep is a {@code String} but it's a different type in the
+ * Truffle sense.
+ */
 @com.oracle.truffle.api.CompilerDirectives.ValueType
 public class RSymbol {
     private final String name;
 
-    RSymbol(String value) {
-        this.name = value;
+    public RSymbol(String name) {
+        this.name = name;
     }
 
-    public String getValue() {
+    public String getName() {
         return name;
     }
 
diff --git a/com.oracle.truffle.r.shell/src/com/oracle/truffle/r/shell/RCommand.java b/com.oracle.truffle.r.shell/src/com/oracle/truffle/r/shell/RCommand.java
index 986fbf954332e06f8affdebed1a7f0969996479d..38766750f87d889c967dca38732d4becf7ebb690 100644
--- a/com.oracle.truffle.r.shell/src/com/oracle/truffle/r/shell/RCommand.java
+++ b/com.oracle.truffle.r.shell/src/com/oracle/truffle/r/shell/RCommand.java
@@ -145,7 +145,7 @@ public class RCommand {
             String content = new String(bytes);
             JLineConsoleHandler consoleHandler = new JLineConsoleHandler(false, new ConsoleReader(null, System.out));
             VirtualFrame frame = REngine.initialize(commandArgs, consoleHandler, true, true);
-            REngine.parseAndEval(content, frame, true);
+            REngine.parseAndEval(content, frame, REnvironment.globalEnv(), true);
         } catch (IOException ex) {
             Utils.fail("unexpected error reading file input");
         }
@@ -168,7 +168,7 @@ public class RCommand {
                     continue;
                 }
 
-                REngine.parseAndEval(line, globalFrame, true);
+                REngine.parseAndEval(line, globalFrame, REnvironment.globalEnv(), true);
             }
         } catch (UserInterruptException e) {
             // interrupted
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index 22b11707b7d07c2dda6cb0869d4eae41f609aa93..11f58623677bf1e01fa1dc0696c2f7505574ccd7 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -6065,6 +6065,42 @@ Error in rm("foo", envir = baseenv()) :
 #{ x <- 1; ls(globalenv()) }
 [1] "x"
 
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testEval
+#{ a <- 1; eval(a + 1) }
+[1] 2
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testEval
+#{ a <- 1; eval(a) }
+[1] 1
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testEval
+#{ a <- 1; eval(expression(a + 1)) }
+[1] 2
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testEval
+#{ eval(2 ^ 2 ^ 3)}
+[1] 256
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testEval
+#{ eval(x <- 1); ls() }
+[1] "x"
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testEval
+#{ f <- function(x) { eval(x) }; f(1) }
+[1] 1
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testEval
+#{ ne <- new.env(); eval(x <- 1, ne); ls() }
+[1] "ne" "x"
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testEval
+#{ ne <- new.env(); evalq(envir=ne, expr=x <- 1); ls(ne) }
+[1] "x"
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testEval
+#{ ne <- new.env(); evalq(x <- 1, ne); ls(ne) }
+[1] "x"
+
 ##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testFloor
 #{ floor(c(0.2,-3.4,NA,0/0,1/0)) }
 [1]   0  -4  NA NaN Inf
@@ -6647,6 +6683,14 @@ $z
 [1] 42
 
 
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testLocal
+#{ kk <- local({k <- function(x) {x*2}}); kk(8)}
+[1] 16
+
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testLocal
+#{ ne <- new.env(); local(a <- 1, ne); ls(ne) }
+[1] "a"
+
 ##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testLog
 #{ log(0) }
 [1] -Inf
@@ -9959,6 +10003,10 @@ f second 1
 ##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testUseMethodSimple
 #{f <- function(x){ UseMethod("f",x); };f.first <- function(x){cat("f first",x)};f.second <- function(x){cat("f second",x)};obj <-1;attr(obj,"class")  <- "first";f(obj);attr(obj,"class")  <- "second";}
 f first 1
+##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testUseMethodSimple
+#{f<-function(x){UseMethod("f")};f.logical<-function(x){print("logical")};f(TRUE)}
+[1] "logical"
+
 ##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testVectorConstructor
 #{ vector("integer") }
 integer(0)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/all/AllTests.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/all/AllTests.java
index b8d9739243fb635e62ffe878aea3a549606728dd..609c718e213e19ab7126433d42c860172c492f16 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/all/AllTests.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/all/AllTests.java
@@ -6994,23 +6994,53 @@ public class AllTests extends TestBase {
     }
 
     @Test
-    public void TestSimpleBuiltins_testEval_df5a9c0a0569879276fa81b87dddc5cf() {
-        assertEval("{ eval(quote(x+x), list(x=1)) }");
+    public void TestSimpleBuiltins_testEval_62d7082404e34bddeb5e12c06a26534d() {
+        assertEval("{ eval(2 ^ 2 ^ 3)}");
     }
 
     @Test
-    public void TestSimpleBuiltins_testEval_046c5969a889af57d7ea19d1fba119d6() {
-        assertEval("{ y <- 2; eval(quote(x+y), list(x=1)) }");
+    public void TestSimpleBuiltins_testEval_920f5515f98fd5c10461346e2a805d15() {
+        assertEval("{ a <- 1; eval(a) }");
     }
 
     @Test
-    public void TestSimpleBuiltins_testEval_5b956e0508e3402588200db72e33861f() {
-        assertEval("{ y <- 2; x <- 4; eval(x + y, list(x=1)) }");
+    public void TestSimpleBuiltins_testEval_70c290279b8e4e173c5475c813a08ccf() {
+        assertEval("{ a <- 1; eval(a + 1) }");
     }
 
     @Test
-    public void TestSimpleBuiltins_testEval_b2e8a12bd61dc527a9bc79b8c43a380f() {
-        assertEval("{ y <- 2; x <- 2 ; eval(quote(x+y), -1) }");
+    public void TestSimpleBuiltins_testEval_a7934810753e30b16c1914a2b72ba6af() {
+        assertEval("{ a <- 1; eval(expression(a + 1)) }");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testEval_f3aa723185ed6d8b5841272ed37617fb() {
+        assertEval("{ f <- function(x) { eval(x) }; f(1) }");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testEval_ee2b49685a936778137c42f4d4704c32() {
+        assertEval("{ eval(x <- 1); ls() }");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testEval_986c43993435f0acec80a3ab9af828b4() {
+        assertEval("{ ne <- new.env(); eval(x <- 1, ne); ls() }");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testEval_1b7023a1265b2b0e3e2a3be42e1b0835() {
+        assertEval("{ ne <- new.env(); evalq(x <- 1, ne); ls(ne) }");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testEval_60c900fd0d555cd006601ea5616f7146() {
+        assertEval("{ ne <- new.env(); evalq(envir=ne, expr=x <- 1); ls(ne) }");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testEvalIgnore_a2bb4f39d740a0564a45a2fa5a7f8259() {
+        assertEval("{ eval({ xx <- pi; xx^2}) ; xx }");
     }
 
     @Test
@@ -7823,6 +7853,16 @@ public class AllTests extends TestBase {
         assertEval("{ x<-list(y=1, 2);  c(a=x, c(y=7,z=42)) }");
     }
 
+    @Test
+    public void TestSimpleBuiltins_testLocal_d50a7019d4d1ef55e7a8b31373b29f6f() {
+        assertEval("{ kk <- local({k <- function(x) {x*2}}); kk(8)}");
+    }
+
+    @Test
+    public void TestSimpleBuiltins_testLocal_15b8e154cdc0ad21b82f8a6ca290dd48() {
+        assertEval("{ ne <- new.env(); local(a <- 1, ne); ls(ne) }");
+    }
+
     @Test
     public void TestSimpleBuiltins_testLog_fd3ef6f859e8e0d8956abf0e2bec0c13() {
         assertEval("{ log(1) } ");
@@ -12363,6 +12403,11 @@ public class AllTests extends TestBase {
         assertEval("{f <- function(x){ UseMethod(\"f\",x); };f.first <- function(x){cat(\"f first\",x)};f.second <- function(x){cat(\"f second\",x)};obj <-1;attr(obj,\"class\")  <- \"first\";f(obj);attr(obj,\"class\")  <- \"second\";}");
     }
 
+    @Test
+    public void TestSimpleBuiltins_testUseMethodSimple_24e4b6579385856080f94ac48ee5406f() {
+        assertEval("{f<-function(x){UseMethod(\"f\")};f.logical<-function(x){print(\"logical\")};f(TRUE)}");
+    }
+
     @Test
     public void TestSimpleBuiltins_testVectorConstructor_629fc5f98d9d6659735740d0b0894210() {
         assertEval("{ vector() }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/failing/FailingTests.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/failing/FailingTests.java
index 8d325d67f728fba0212f230f7e1bedcaf51c9daf..54995a771b8af061f6b747ca1446f4ac2c38e275 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/failing/FailingTests.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/failing/FailingTests.java
@@ -1049,23 +1049,8 @@ public class FailingTests extends TestBase {
     }
 
     @Ignore
-    public void TestSimpleBuiltins_testEval_df5a9c0a0569879276fa81b87dddc5cf() {
-        assertEval("{ eval(quote(x+x), list(x=1)) }");
-    }
-
-    @Ignore
-    public void TestSimpleBuiltins_testEval_046c5969a889af57d7ea19d1fba119d6() {
-        assertEval("{ y <- 2; eval(quote(x+y), list(x=1)) }");
-    }
-
-    @Ignore
-    public void TestSimpleBuiltins_testEval_5b956e0508e3402588200db72e33861f() {
-        assertEval("{ y <- 2; x <- 4; eval(x + y, list(x=1)) }");
-    }
-
-    @Ignore
-    public void TestSimpleBuiltins_testEval_b2e8a12bd61dc527a9bc79b8c43a380f() {
-        assertEval("{ y <- 2; x <- 2 ; eval(quote(x+y), -1) }");
+    public void TestSimpleBuiltins_testEvalIgnore_a2bb4f39d740a0564a45a2fa5a7f8259() {
+        assertEval("{ eval({ xx <- pi; xx^2}) ; xx }");
     }
 
     @Ignore
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleBuiltins.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleBuiltins.java
index 7fdfb66c24c4c44492477e7dd933ed7b81826f81..0c25e086089d35378afdd078ff507dc6e0e04d44 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleBuiltins.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleBuiltins.java
@@ -2307,12 +2307,28 @@ public class TestSimpleBuiltins extends TestBase {
     }
 
     @Test
-    @Ignore
     public void testEval() {
-        assertEval("{ eval(quote(x+x), list(x=1)) }");
-        assertEval("{ y <- 2; eval(quote(x+y), list(x=1)) }");
-        assertEval("{ y <- 2; x <- 4; eval(x + y, list(x=1)) }");
-        assertEval("{ y <- 2; x <- 2 ; eval(quote(x+y), -1) }");
+        assertEval("{ eval(2 ^ 2 ^ 3)}");
+        assertEval("{ a <- 1; eval(a) }");
+        assertEval("{ a <- 1; eval(a + 1) }");
+        assertEval("{ a <- 1; eval(expression(a + 1)) }");
+        assertEval("{ f <- function(x) { eval(x) }; f(1) }");
+        assertEval("{ eval(x <- 1); ls() }");
+        assertEval("{ ne <- new.env(); eval(x <- 1, ne); ls() }");
+        assertEval("{ ne <- new.env(); evalq(x <- 1, ne); ls(ne) }");
+        assertEval("{ ne <- new.env(); evalq(envir=ne, expr=x <- 1); ls(ne) }");
+    }
+
+    @Test
+    @Ignore
+    public void testEvalIgnore() {
+        assertEval("{ eval({ xx <- pi; xx^2}) ; xx }");  // should print two values, xx^2 and xx
+    }
+
+    @Test
+    public void testLocal() {
+        assertEval("{ kk <- local({k <- function(x) {x*2}}); kk(8)}");
+        assertEval("{ ne <- new.env(); local(a <- 1, ne); ls(ne) }");
     }
 
     @Test
@@ -2570,6 +2586,7 @@ public class TestSimpleBuiltins extends TestBase {
         // Basic UseMethod
         assertEval("{f <- function(x){ UseMethod(\"f\",x); };" + "f.first <- function(x){cat(\"f first\",x)};" + "f.second <- function(x){cat(\"f second\",x)};" + "obj <-1;"
                         + "attr(obj,\"class\")  <- \"first\";" + "f(obj);" + "attr(obj,\"class\")  <- \"second\";}");
+        assertEval("{f<-function(x){UseMethod(\"f\")};f.logical<-function(x){print(\"logical\")};f(TRUE)}");
     }
 
     @Test