From 484517a47f68d928d937994b2ece6a7c5aa80316 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Mon, 12 Dec 2016 12:01:18 +0100
Subject: [PATCH] turn parens into builtin + special

---
 .../r/nodes/builtin/base/BasePackage.java     |  3 +-
 .../builtin/base/infix/ParenBuiltin.java      | 42 ++++++++---
 .../truffle/r/nodes/test/SpecialCallTest.java | 28 +++++---
 .../oracle/truffle/r/nodes/RASTBuilder.java   |  3 -
 .../truffle/r/nodes/control/ParNode.java      | 69 -------------------
 5 files changed, 54 insertions(+), 91 deletions(-)
 delete mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ParNode.java

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index f6f78ccaa1..1670fad529 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -67,7 +67,6 @@ import com.oracle.truffle.r.nodes.builtin.base.infix.IfBuiltinNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.infix.NextBuiltin;
 import com.oracle.truffle.r.nodes.builtin.base.infix.NextBuiltinNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.infix.ParenBuiltin;
-import com.oracle.truffle.r.nodes.builtin.base.infix.ParenBuiltinNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.infix.RepeatBuiltin;
 import com.oracle.truffle.r.nodes.builtin.base.infix.RepeatBuiltinNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.infix.Subscript;
@@ -695,7 +694,7 @@ public class BasePackage extends RBuiltinPackage {
         add(FunctionBuiltin.class, FunctionBuiltinNodeGen::create);
         add(IfBuiltin.class, IfBuiltinNodeGen::create);
         add(NextBuiltin.class, NextBuiltinNodeGen::create);
-        add(ParenBuiltin.class, ParenBuiltinNodeGen::create);
+        add(ParenBuiltin.class, ParenBuiltin::new, ParenBuiltin::special);
         add(RepeatBuiltin.class, RepeatBuiltinNodeGen::create);
         add(Tilde.class, TildeNodeGen::create);
         add(UpdateSubscript.class, UpdateSubscriptNodeGen::create, UpdateSubscript::special);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ParenBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ParenBuiltin.java
index 23c4c9cbf9..a8655bf30d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ParenBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ParenBuiltin.java
@@ -22,19 +22,45 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base.infix;
 
+import static com.oracle.truffle.r.runtime.RVisibility.ON;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
-import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.NodeCost;
+import com.oracle.truffle.api.nodes.NodeInfo;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.nodes.RNode;
 
-@RBuiltin(name = "(", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
-public abstract class ParenBuiltin extends RBuiltinNode {
-    @SuppressWarnings("unused")
-    @Specialization
-    protected Object doIt(Object x) {
-        throw RInternalError.unimplemented();
+@NodeInfo(cost = NodeCost.NONE)
+final class ParensSpecial extends RNode {
+
+    @Child private RNode delegate;
+
+    protected ParensSpecial(RNode delegate) {
+        this.delegate = delegate;
+    }
+
+    @Override
+    public Object execute(VirtualFrame frame) {
+        return delegate.execute(frame);
+    }
+}
+
+@RBuiltin(name = "(", kind = PRIMITIVE, parameterNames = {""}, visibility = ON, behavior = PURE)
+public final class ParenBuiltin extends RBuiltinNode {
+
+    public static RNode special(ArgumentsSignature signature, RNode[] args, @SuppressWarnings("unused") boolean inReplacement) {
+        if (signature == ArgumentsSignature.empty(1)) {
+            return new ParensSpecial(args[0]);
+        }
+        return null;
+    }
+
+    @Override
+    public Object executeBuiltin(VirtualFrame frame, Object... args) {
+        return args[0];
     }
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java
index b92c005198..c32dd569e8 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java
@@ -164,11 +164,11 @@ public class SpecialCallTest extends TestBase {
         assertCallCounts("1 + 1", 1, 0, 1, 0);
         assertCallCounts("1 + 1 * 2 + 4", 3, 0, 3, 0);
 
-        assertCallCounts("{ a <- 1; b <- 2 }", "a + b", 1, 0, 1, 0);
-        assertCallCounts("{ a <- 1; b <- 2; c <- 3 }", "a + b * 2 * c", 3, 0, 3, 0);
+        assertCallCounts("a <- 1; b <- 2", "a + b", 1, 0, 1, 0);
+        assertCallCounts("a <- 1; b <- 2; c <- 3", "a + b * 2 * c", 3, 0, 3, 0);
 
-        assertCallCounts("{ a <- data.frame(a=1); b <- 2; c <- 3 }", "a + b * 2 * c", 3, 0, 2, 1);
-        assertCallCounts("{ a <- 1; b <- data.frame(a=1); c <- 3 }", "a + b * 2 * c", 3, 0, 0, 3);
+        assertCallCounts("a <- data.frame(a=1); b <- 2; c <- 3", "a + b * 2 * c", 3, 0, 2, 1);
+        assertCallCounts("a <- 1; b <- data.frame(a=1); c <- 3", "a + b * 2 * c", 3, 0, 0, 3);
 
         assertCallCounts("1 %*% 1", 0, 1, 0, 1);
     }
@@ -182,7 +182,7 @@ public class SpecialCallTest extends TestBase {
         assertCallCounts("a <- c(1,2,3,4)", "a[0.1]", 1, 0, 1, 0);
         assertCallCounts("a <- c(1,2,3,4)", "a[5]", 1, 0, 1, 0);
         assertCallCounts("a <- c(1,2,3,4)", "a[0]", 1, 0, 1, 0);
-        assertCallCounts("{ a <- c(1,2,3,4); b <- -1 }", "a[b]", 1, 0, 1, 0);
+        assertCallCounts("a <- c(1,2,3,4); b <- -1", "a[b]", 1, 0, 1, 0);
         assertCallCounts("a <- c(1,2,3,4)", "a[NA_integer_]", 1, 0, 1, 0);
 
         assertCallCounts("a <- c(1,2,3,4)", "a[-1]", 0, 2, 0, 2); // "-1" is a unary expression
@@ -201,7 +201,7 @@ public class SpecialCallTest extends TestBase {
         assertCallCounts("a <- c(1,2,3,4)", "a[[0.1]]", 1, 0, 1, 0);
         assertCallCounts("a <- c(1,2,3,4)", "a[[5]]", 1, 0, 1, 0);
         assertCallCounts("a <- c(1,2,3,4)", "a[[0]]", 1, 0, 1, 0);
-        assertCallCounts("{ a <- c(1,2,3,4); b <- -1 }", "a[[b]]", 1, 0, 1, 0);
+        assertCallCounts("a <- c(1,2,3,4); b <- -1", "a[[b]]", 1, 0, 1, 0);
         assertCallCounts("a <- c(1,2,3,4)", "a[[NA_integer_]]", 1, 0, 1, 0);
 
         assertCallCounts("a <- c(1,2,3,4)", "a[[drop=T, 1]]", 0, 1, 0, 1);
@@ -218,7 +218,7 @@ public class SpecialCallTest extends TestBase {
         assertCallCounts("a <- c(1,2,3,4)", "a[0.1] <- 1", 1, 0, 1, 1);
         assertCallCounts("a <- c(1,2,3,4)", "a[5] <- 1", 1, 0, 1, 1);
         assertCallCounts("a <- c(1,2,3,4)", "a[0] <- 1", 1, 0, 1, 1);
-        assertCallCounts("{ a <- c(1,2,3,4); b <- -1 }", "a[b] <- 1", 1, 0, 1, 1);
+        assertCallCounts("a <- c(1,2,3,4); b <- -1", "a[b] <- 1", 1, 0, 1, 1);
         assertCallCounts("a <- c(1,2,3,4)", "a[NA_integer_] <- 1", 1, 0, 1, 1);
 
         assertCallCounts("a <- c(1,2,3,4)", "a[-1] <- 1", 0, 2, 0, 3); // "-1" is a unary expression
@@ -237,7 +237,7 @@ public class SpecialCallTest extends TestBase {
         assertCallCounts("a <- c(1,2,3,4)", "a[[0.1]] <- 1", 1, 0, 2, 0);
         assertCallCounts("a <- c(1,2,3,4)", "a[[5]] <- 1", 1, 0, 1, 1);
         assertCallCounts("a <- c(1,2,3,4)", "a[[0]] <- 1", 1, 0, 1, 1);
-        assertCallCounts("{ a <- c(1,2,3,4); b <- -1 }", "a[[b]] <- 1", 1, 0, 1, 1);
+        assertCallCounts("a <- c(1,2,3,4); b <- -1", "a[[b]] <- 1", 1, 0, 1, 1);
         assertCallCounts("a <- c(1,2,3,4)", "a[[NA_integer_]] <- 1", 1, 0, 1, 1);
 
         assertCallCounts("a <- c(1,2,3,4)", "a[[drop=T, 1]] <- 1", 0, 1, 0, 2);
@@ -245,6 +245,16 @@ public class SpecialCallTest extends TestBase {
         assertCallCounts("a <- c(1,2,3,4)", "a[[1, drop=F]] <- 1", 0, 1, 0, 2);
     }
 
+    @Test
+    public void testParens() {
+        assertCallCounts("a <- 1", "(a)", 1, 0, 1, 0);
+        assertCallCounts("a <- 1", "(55)", 1, 0, 1, 0);
+        assertCallCounts("a <- 1", "('asdf')", 1, 0, 1, 0);
+        assertCallCounts("a <- 1; b <- 2", "(a + b)", 2, 0, 2, 0);
+        assertCallCounts("a <- 1; b <- 2; c <- 3", "a + (b + c)", 3, 0, 3, 0);
+        assertCallCounts("a <- 1; b <- 2; c <- 1:5", "a + (b + c)", 3, 0, 0, 3);
+    }
+
     private static void assertCallCounts(String test, int initialSpecialCount, int initialNormalCount, int finalSpecialCount, int finalNormalCount) {
         assertCallCounts("{}", test, initialSpecialCount, initialNormalCount, finalSpecialCount, finalNormalCount);
     }
@@ -253,7 +263,7 @@ public class SpecialCallTest extends TestBase {
         if (!FastROptions.UseSpecials.getBooleanValue()) {
             return;
         }
-        Source setupSource = Source.newBuilder(setup).mimeType(TruffleRLanguage.MIME).name("test").build();
+        Source setupSource = Source.newBuilder("{" + setup + "}").mimeType(TruffleRLanguage.MIME).name("test").build();
         Source testSource = Source.newBuilder(test).mimeType(TruffleRLanguage.MIME).name("test").build();
 
         RExpression setupExpression = testVMContext.getThisEngine().parse(setupSource);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java
index 4b35745a57..eec731b175 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java
@@ -38,7 +38,6 @@ import com.oracle.truffle.r.nodes.control.BreakNode;
 import com.oracle.truffle.r.nodes.control.ForNode;
 import com.oracle.truffle.r.nodes.control.IfNode;
 import com.oracle.truffle.r.nodes.control.NextNode;
-import com.oracle.truffle.r.nodes.control.ParNode;
 import com.oracle.truffle.r.nodes.control.RepeatNode;
 import com.oracle.truffle.r.nodes.control.ReplacementDispatchNode;
 import com.oracle.truffle.r.nodes.control.WhileNode;
@@ -88,8 +87,6 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> {
                 switch (symbol) {
                     case "repeat":
                         return new RepeatNode(source, lhsLookup, args.get(0).value);
-                    case "(":
-                        return new ParNode(source, lhsLookup, args.get(0).value);
                 }
             } else if (args.size() == 2) {
                 switch (symbol) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ParNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ParNode.java
deleted file mode 100644
index ba7c6cf1f0..0000000000
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ParNode.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, 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.control;
-
-import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.source.SourceSection;
-import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
-import com.oracle.truffle.r.runtime.ArgumentsSignature;
-import com.oracle.truffle.r.runtime.nodes.RNode;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
-
-/**
- * A {@link ParNode} represents parentheses in source code.
- */
-public final class ParNode extends OperatorNode {
-
-    @Child private RNode value;
-    @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
-
-    public ParNode(SourceSection src, RSyntaxLookup operator, RSyntaxNode value) {
-        super(src, operator);
-        this.value = value.asRNode();
-    }
-
-    @Override
-    public Object execute(VirtualFrame frame) {
-        try {
-            return value.execute(frame);
-        } finally {
-            visibility.execute(frame, true);
-        }
-    }
-
-    @Override
-    public void voidExecute(VirtualFrame frame) {
-        value.voidExecute(frame);
-    }
-
-    @Override
-    public RSyntaxNode[] getSyntaxArguments() {
-        return new RSyntaxNode[]{value.asRSyntaxNode()};
-    }
-
-    @Override
-    public ArgumentsSignature getSyntaxSignature() {
-        return ArgumentsSignature.empty(1);
-    }
-}
-- 
GitLab