diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
index 5ad02cca608837419ec6fc089a807a26b7d0fc2e..5cc9d7e5b4364f57955e18f69513c626e87a271a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
@@ -25,27 +25,22 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.RASTUtils;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.nodes.builtin.base.Call.CallUtil;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
-import com.oracle.truffle.r.runtime.data.RExpression;
-import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
-import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractListBaseVector;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 @RBuiltin(name = "as.call", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
 public abstract class AsCall extends RBuiltinNode.Arg1 {
@@ -57,53 +52,27 @@ public abstract class AsCall extends RBuiltinNode.Arg1 {
         Casts.noCasts(AsCall.class);
     }
 
-    @Child private CallUtil util = new CallUtil();
-
     @Specialization
-    protected RLanguage asCallFunction(RList x) {
-        // TODO error checks
-        RArgsValuesAndNames avn = makeNamesAndValues(x);
-        if (x.getDataAt(0) instanceof RSymbol) {
-            return util.makeCallSourceUnavailable(((RSymbol) x.getDataAt(0)).getName(), avn);
-        } else if (x.getDataAt(0) instanceof String) {
-            return util.makeCallSourceUnavailable((String) x.getDataAt(0), avn);
-        } else if (x.getDataAt(0) instanceof RAbstractStringVector) {
-            return util.makeCallSourceUnavailable(((RAbstractStringVector) x.getDataAt(0)).getDataAt(0), avn);
-        } else if (x.getDataAt(0) instanceof RFunction) {
-            return CallUtil.makeCallSourceUnavailable((RFunction) x.getDataAt(0), avn);
-        } else if (x.getDataAt(0) instanceof Integer) {
-            return CallUtil.makeCallSourceUnavailable((Integer) x.getDataAt(0), avn);
-        } else if (x.getDataAt(0) instanceof Double) {
-            return CallUtil.makeCallSourceUnavailable((Double) x.getDataAt(0), avn);
-        } else if (x.getDataAt(0) instanceof RLanguage) {
-            return (RLanguage) x.getDataAt(0);
-        } else {
-            throw RInternalError.unimplemented();
+    @TruffleBoundary
+    protected RLanguage asCallFunction(RAbstractListBaseVector x) {
+        if (x.getLength() == 0) {
+            error(Message.INVALID_LEN_0_ARG);
         }
-    }
+        // separate the first element (call target) from the rest (arguments)
 
-    @Specialization
-    protected RLanguage asCallFunction(RExpression x) {
-        // TODO error checks
-        String f;
-        if (x.getDataAt(0) instanceof RSymbol) {
-            f = ((RSymbol) x.getDataAt(0)).getName();
-        } else {
-            RLanguage l = (RLanguage) x.getDataAt(0);
-            f = ((ReadVariableNode) RASTUtils.unwrap(l.getRep())).getIdentifier();
+        RSyntaxNode target = RASTUtils.createNodeForValue(x.getDataAt(0)).asRSyntaxNode();
+        ArgumentsSignature signature = createSignature(x);
+        Object[] arguments = new Object[signature.getLength()];
+        for (int i = 0; i < arguments.length; i++) {
+            arguments[i] = x.getDataAt(i + 1);
         }
-        return util.makeCallSourceUnavailable(f, makeNamesAndValues(x));
+        return Call.makeCall(getRLanguage(), target, arguments, signature);
     }
 
-    private RArgsValuesAndNames makeNamesAndValues(RAbstractContainer x) {
+    private ArgumentsSignature createSignature(RAbstractContainer x) {
         int length = x.getLength() - 1;
-        Object[] values = new Object[length];
-        for (int i = 0; i < length; i++) {
-            values[i] = x.getDataAtAsObject(i + 1);
-        }
-        ArgumentsSignature signature;
         if (nullNamesProfile.profile(getNamesNode.getNames(x) == null)) {
-            signature = ArgumentsSignature.empty(values.length);
+            return ArgumentsSignature.empty(length);
         } else {
             String[] names = new String[length];
             // extract names, converting "" to null
@@ -114,10 +83,8 @@ public abstract class AsCall extends RBuiltinNode.Arg1 {
                     names[i] = name;
                 }
             }
-            signature = ArgumentsSignature.get(names);
+            return ArgumentsSignature.get(names);
         }
-
-        return new RArgsValuesAndNames(values, signature);
     }
 
     @Fallback
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
index c6f72e666cc5aa71de98f9c01a976e4a79c810e1..514b358ef2479f022bcba855f2fdf08fa636910a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
@@ -32,24 +32,23 @@ import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.RASTUtils;
-import com.oracle.truffle.r.nodes.access.ConstantNode;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RSymbol;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
+import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
@@ -70,81 +69,48 @@ public abstract class Call extends RBuiltinNode.Arg2 {
         casts.arg("").mustBe(stringValue(), RError.Message.FIRST_ARG_MUST_BE_STRING).asStringVector().findFirst();
     }
 
-    @Child private CallUtil util = new CallUtil();
-
     @Specialization
+    @TruffleBoundary
     protected RLanguage call(String name, RArgsValuesAndNames args) {
-        return util.makeCall(name, args);
+        return makeCall(getRLanguage(), RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, name, true), args.getArguments(), args.getSignature());
     }
 
-    public static final class CallUtil extends RBaseNode {
-
-        @TruffleBoundary
-        private RLanguage makeCall(String name, RArgsValuesAndNames args) {
-            return "function".equals(name) ? makeFunction(args) : makeCall0(ReadVariableNode.wrap(RSyntaxNode.LAZY_DEPARSE, ReadVariableNode.createFunctionLookup(name)), false, args);
+    @TruffleBoundary
+    public static RLanguage makeCall(TruffleRLanguage language, RSyntaxNode target, Object[] arguments, ArgumentsSignature signature) {
+        assert arguments.length == signature.getLength();
+        if (target instanceof RSyntaxLookup && "function".equals(((RSyntaxLookup) target).getIdentifier())) {
+            return makeFunction(language, arguments);
+        } else {
+            return makeCall0(target, arguments, signature);
         }
+    }
 
-        private RLanguage makeFunction(RArgsValuesAndNames args) {
-            CompilerAsserts.neverPartOfCompilation();
-            Object body = RNull.instance;
-            if (args.getLength() >= 2) {
-                body = args.getArgument(1);
-            }
-            Object argList = args.getLength() == 0 ? RNull.instance : args.getArgument(0);
-            ArrayList<RCodeBuilder.Argument<RSyntaxNode>> finalArgs = new ArrayList<>();
-            while (argList != RNull.instance) {
-                if (!(argList instanceof RPairList)) {
-                    throw RError.error(RError.SHOW_CALLER, Message.BAD_FUNCTION_EXPR);
-                }
-                RPairList pl = (RPairList) argList;
-                String name = ((RSymbol) pl.getTag()).getName();
-                RSyntaxNode value = RASTUtils.createNodeForValue(pl.car()).asRSyntaxNode();
-                finalArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, name, value));
-                argList = pl.cdr();
+    private static RLanguage makeFunction(TruffleRLanguage language, Object[] arguments) {
+        CompilerAsserts.neverPartOfCompilation();
+        Object body = arguments.length <= 1 ? RNull.instance : arguments[1];
+        Object argList = arguments.length == 0 ? RNull.instance : arguments[0];
+        ArrayList<RCodeBuilder.Argument<RSyntaxNode>> finalArgs = new ArrayList<>();
+        while (argList != RNull.instance) {
+            if (!(argList instanceof RPairList)) {
+                throw RError.error(RError.SHOW_CALLER, Message.BAD_FUNCTION_EXPR);
             }
-            RSyntaxNode function = RContext.getASTBuilder().function(getRLanguage(), RSyntaxNode.LAZY_DEPARSE, finalArgs, RASTUtils.createNodeForValue(body).asRSyntaxNode(), null);
-            return RDataFactory.createLanguage(function.asRNode());
-        }
-
-        @TruffleBoundary
-        protected RLanguage makeCallSourceUnavailable(String name, RArgsValuesAndNames args) {
-            return "function".equals(name) ? makeFunction(args) : makeCall0(ReadVariableNode.wrap(RSyntaxNode.LAZY_DEPARSE, ReadVariableNode.createFunctionLookup(name)), true, args);
-        }
-
-        @TruffleBoundary
-        protected static RLanguage makeCallSourceUnavailable(int i, RArgsValuesAndNames args) {
-            return makeCall0(ConstantNode.create(i), true, args);
+            RPairList pl = (RPairList) argList;
+            String name = ((RSymbol) pl.getTag()).getName();
+            RSyntaxNode value = RASTUtils.createNodeForValue(pl.car()).asRSyntaxNode();
+            finalArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, name, value));
+            argList = pl.cdr();
         }
+        RSyntaxNode function = RContext.getASTBuilder().function(language, RSyntaxNode.LAZY_DEPARSE, finalArgs, RASTUtils.createNodeForValue(body).asRSyntaxNode(), null);
+        return RDataFactory.createLanguage(function.asRNode());
+    }
 
-        @TruffleBoundary
-        protected static RLanguage makeCallSourceUnavailable(double d, RArgsValuesAndNames args) {
-            return makeCall0(ConstantNode.create(d), true, args);
-        }
-
-        @TruffleBoundary
-        protected static RLanguage makeCallSourceUnavailable(RFunction function, RArgsValuesAndNames args) {
-            return makeCall0(function, true, args);
-        }
-
-        /**
-         *
-         * @param fn an {@link RFunction} or {@link String}
-         * @param argsAndNames if not {@code null} the argument values and (optional) names
-         * @return the {@link RLanguage} instance denoting the call
-         */
-        @TruffleBoundary
-        private static RLanguage makeCall0(Object fn, boolean sourceUnavailable, RArgsValuesAndNames argsAndNames) {
-            assert !(fn instanceof String);
-            int argLength = argsAndNames == null ? 0 : argsAndNames.getLength();
-            RSyntaxNode[] args = new RSyntaxNode[argLength];
-            Object[] values = argsAndNames == null ? null : argsAndNames.getArguments();
-            ArgumentsSignature signature = argsAndNames == null ? ArgumentsSignature.empty(0) : argsAndNames.getSignature();
-
-            for (int i = 0; i < argLength; i++) {
-                args[i] = (RSyntaxNode) RASTUtils.createNodeForValue(values[i]);
-            }
-
-            return RDataFactory.createLanguage(RASTUtils.createCall(fn, sourceUnavailable, signature, args).asRNode());
+    @TruffleBoundary
+    private static RLanguage makeCall0(RSyntaxNode target, Object[] arguments, ArgumentsSignature signature) {
+        RSyntaxNode[] args = new RSyntaxNode[arguments.length];
+        for (int i = 0; i < arguments.length; i++) {
+            args[i] = (RSyntaxNode) RASTUtils.createNodeForValue(arguments[i]);
         }
+        RNode call = RContext.getASTBuilder().call(RSyntaxNode.LAZY_DEPARSE, target, RCodeBuilder.createArgumentList(signature, args)).asRNode();
+        return RDataFactory.createLanguage(call);
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index b992cca27d3bd844599708d34dcee51570a259b7..dd4aaab8b46974711c0040fa695013a13b086015 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -319,6 +319,7 @@ public final class RError extends RuntimeException implements TruffleException {
         MORE_SUPPLIED_REPLACE("more elements supplied than there are to replace"),
         NA_SUBSCRIPTED("NAs are not allowed in subscripted assignments"),
         INVALID_ARG_TYPE("invalid argument type"),
+        INVALID_LEN_0_ARG("invalid length 0 argument"),
         INVALID_ARG_UNARY("invalid argument to unary operator"),
         VECTOR_SIZE_NEGATIVE("vector size cannot be negative"),
         VECTOR_SIZE_NA("vector size cannot be NA"),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java
index 3eaed47f55b88159cd36daa8df6e9feac6ecac1d..065e62a3aef3e7a822981b27da41aa9cd77af5be 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java
@@ -163,6 +163,14 @@ public interface RCodeBuilder<T> {
         }.accept(original);
     }
 
+    static <T> ArrayList<Argument<T>> createArgumentList(ArgumentsSignature signature, T[] arguments) {
+        ArrayList<Argument<T>> args = new ArrayList<>(arguments.length);
+        for (int i = 0; i < arguments.length; i++) {
+            args.add(RCodeBuilder.argument(null, signature.getName(i), arguments[i] == null ? null : arguments[i]));
+        }
+        return args;
+    }
+
     /** @see #process(RSyntaxElement) */
     default T process(RSyntaxElement original, CodeBuilderContext context) {
         CodeBuilderContext saved = getContext();
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 b3e608a98ac1ba093c23a45a47e39c5795c19b12..7048d696550a9650dbb236999505403e2b5c146f 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
@@ -5755,6 +5755,62 @@ character(0)
 a b
 1 2
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#
+#as.call(list('function', pairlist(a=1), 5))
+"function"(pairlist(a = 1), 5)
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#Output.IgnoreWhitespace#
+#as.call(list(as.symbol('function')))
+function() NULL
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#Output.IgnoreWhitespace#
+#as.call(list(as.symbol('function'), pairlist(a=1)))
+function(a = 1) NULL
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#Output.IgnoreWhitespace#
+#as.call(list(as.symbol('function'), pairlist(a=1), 5))
+function(a = 1) 5
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#
+#call('foo')
+foo()
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#Output.IgnoreWhitespace#
+#call('function')
+function() NULL
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#Output.IgnoreWhitespace#
+#call('function', 'a')
+Error: badly formed function expression
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#Output.IgnoreWhitespace#
+#call('function', pairlist(a=1))
+function(a = 1) NULL
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#Output.IgnoreWhitespace#
+#call('function', pairlist(a=1), 3)
+function(a = 1) 3
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#Output.IgnoreWhitespace#
+#call('function', pairlist(a=1), 5)
+function(a = 1) 5
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#Output.IgnoreWhitespace#
+#call('function', pairlist(a=1), 5,3)
+function(a = 1) 5
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#Output.IgnoreWhitespace#
+#e <- expression(function(a) b); as.call(list(e[[1]][[1]]))
+function() NULL
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#
+#e <- expression(function(a) b); as.call(list(e[[1]][[2]]))
+pairlist(a = )()
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#
+#e <- substitute(a$b(c)); as.call(lapply(e, function(x) x))
+a$b(c)
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#
 #typeof(as.call(list(substitute(graphics::par))))
 [1] "language"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascall.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascall.java
index 5715ff9d612ed6730d6b6feeabf9dddfb7d58810..864149114c81a19a9232cfe7e5b0b0bbe2e28780 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascall.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascall.java
@@ -63,5 +63,20 @@ public class TestBuiltin_ascall extends TestBase {
         assertEval("{ as.call(42) }");
 
         assertEval("typeof(as.call(list(substitute(graphics::par))))");
+
+        assertEval("e <- substitute(a$b(c)); as.call(lapply(e, function(x) x))");
+        assertEval(Output.IgnoreWhitespace, "e <- expression(function(a) b); as.call(list(e[[1]][[1]]))");
+        assertEval("e <- expression(function(a) b); as.call(list(e[[1]][[2]]))");
+        assertEval("call('foo')");
+        assertEval(Output.IgnoreWhitespace, "call('function', 'a')");
+        assertEval(Output.IgnoreWhitespace, "call('function', pairlist(a=1))");
+        assertEval(Output.IgnoreWhitespace, "call('function', pairlist(a=1), 3)");
+        assertEval(Output.IgnoreWhitespace, "call('function', pairlist(a=1), 5,3)");
+        assertEval(Output.IgnoreWhitespace, "call('function', pairlist(a=1), 5)");
+        assertEval("as.call(list('function', pairlist(a=1), 5))");
+        assertEval(Output.IgnoreWhitespace, "as.call(list(as.symbol('function'), pairlist(a=1), 5))");
+        assertEval(Output.IgnoreWhitespace, "as.call(list(as.symbol('function'), pairlist(a=1)))");
+        assertEval(Output.IgnoreWhitespace, "as.call(list(as.symbol('function')))");
+        assertEval(Output.IgnoreWhitespace, "call('function')");
     }
 }