From 4749b1bdefc8dbbc6d5e3ba4ecc5cea0501e72cb Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 22 Mar 2018 10:51:03 +0100
Subject: [PATCH] create RSyntaxFunction only for valid function literals,
 RSyntaxCall otherwise

---
 .../oracle/truffle/r/nodes/builtin/base/Call.java   |  4 +++-
 .../oracle/truffle/r/runtime/data/RPairList.java    | 13 ++++++++++++-
 2 files changed, 15 insertions(+), 2 deletions(-)

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 339b01a16a..c603e2fc90 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
@@ -42,6 +42,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
@@ -74,7 +75,8 @@ public abstract class Call extends RBuiltinNode.Arg2 {
     @TruffleBoundary
     public static RPairList makeCall(TruffleRLanguage language, RSyntaxNode target, Object[] arguments, ArgumentsSignature signature) {
         assert arguments.length == signature.getLength();
-        if (target instanceof RSyntaxLookup && "function".equals(((RSyntaxLookup) target).getIdentifier()) && arguments.length >= 2) {
+        if (target instanceof RSyntaxLookup && "function".equals(((RSyntaxLookup) target).getIdentifier()) && arguments.length >= 2 &&
+                        (arguments[1] == RNull.instance || arguments[1] instanceof RPairList)) {
             // this optimization is not strictly necessary, `function` builtin is functional too.
             FunctionExpressionNode function = FunctionBuiltin.createFunctionExpressionNode(language, arguments[0], arguments[1]);
             return RDataFactory.createLanguage(Closure.createLanguageClosure(function.asRNode()));
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
index 008adde909..82b98b7354 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
@@ -46,6 +46,7 @@ import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
@@ -132,7 +133,17 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
         if (node instanceof RSyntaxCall) {
             RSyntaxCall call = (RSyntaxCall) node;
             if (call.getSyntaxLHS() instanceof RSyntaxLookup && ((RSyntaxLookup) call.getSyntaxLHS()).getIdentifier().equals("function")) {
-                assert false : "calls to 'function' should be instances of RSyntaxFunction";
+                boolean valid = true;
+                valid &= call.getSyntaxSignature().getLength() >= 2;
+                if (valid) {
+                    RSyntaxElement argList = call.getSyntaxArguments()[1];
+                    valid &= argList instanceof RSyntaxConstant;
+                    if (valid) {
+                        Object list = ((RSyntaxConstant) argList).getValue();
+                        valid &= list instanceof RNull || list instanceof RPairList;
+                    }
+                }
+                assert !valid : "valid calls to 'function' should be instances of RSyntaxFunction";
             }
         } else {
             assert node instanceof RSyntaxFunction : "invalid contents of 'language' pairlist: " + node;
-- 
GitLab