From ea2d4234a4168083bab25525dce8c3f6f347b258 Mon Sep 17 00:00:00 2001
From: Michael Haupt <michael.haupt@oracle.com>
Date: Thu, 19 Jun 2014 09:44:50 +0200
Subject: [PATCH] allow more fancy function lookups

---
 .../truffle/r/nodes/RTruffleVisitor.java      |  2 +-
 .../com/oracle/truffle/r/parser/ast/Call.java |  4 +--
 .../truffle/r/parser/ast/FunctionCall.java    |  5 ++++
 .../truffle/r/test/ExpectedTestOutput.test    | 24 +++++++++++++++
 .../oracle/truffle/r/test/all/AllTests.java   | 30 +++++++++++++++++++
 .../r/test/simple/TestSimpleFunctions.java    | 10 +++++++
 6 files changed, 72 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java
index da33cc8deb..7738056fb0 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java
@@ -135,7 +135,7 @@ public final class RTruffleVisitor extends BasicVisitor<RNode> {
             }
             return RCallNode.createCall(callSource, ReadVariableNode.create(callName, RRuntime.TYPE_FUNCTION, false), aCallArgNode);
         } else {
-            RNode lhs = call.getFunctionCall().accept(this);
+            RNode lhs = call.getLhsNode().accept(this);
             return RCallNode.createCall(callSource, lhs, aCallArgNode);
         }
     }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Call.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Call.java
index 0193a2db89..ad2c364bf2 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Call.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Call.java
@@ -49,9 +49,9 @@ public abstract class Call extends ASTNode {
             return create(src, Symbol.getSymbol(c.getValues()[0]), args);
         } else if (call instanceof FunctionCall) {
             return new FunctionCall(src, (FunctionCall) call, args);
+        } else {
+            return new FunctionCall(src, call, args);
         }
-        assert false;
-        return null;
     }
 
     public static ASTNode create(SourceSection src, Symbol funName, List<ArgNode> args) {
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FunctionCall.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FunctionCall.java
index b6e3310447..4db3a7d1cf 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FunctionCall.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FunctionCall.java
@@ -57,6 +57,11 @@ public class FunctionCall extends Call {
         return (FunctionCall) lhs;
     }
 
+    public ASTNode getLhsNode() {
+        assert lhs instanceof ASTNode;
+        return (ASTNode) lhs;
+    }
+
     public boolean isSuper() {
         return isSuper;
     }
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 253ed91af8..a6a2a75f34 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
@@ -11684,6 +11684,30 @@ Hello world
 #{ g <- function(...) { c(...,...) } ; g(3) }
 [1] 3 3
 
+##com.oracle.truffle.r.test.simple.TestSimpleFunctions.testInvokeIndirectly
+#{ f <- function(x) x+1 ; g <- function(x) x+2 ; funs <- list(f,g) ; funs[[1]](1) }
+[1] 2
+
+##com.oracle.truffle.r.test.simple.TestSimpleFunctions.testInvokeIndirectly
+#{ f <- function(x) x+1 ; g <- function(x) x+2 ; funs <- list(f,g) ; funs[[2]](1) }
+[1] 3
+
+##com.oracle.truffle.r.test.simple.TestSimpleFunctions.testInvokeIndirectly
+#{ f <- function(x) x+1 ; g <- function(x) x+2 ; h <- function(v) if (v==1) f else g ; h(1)(1) }
+[1] 2
+
+##com.oracle.truffle.r.test.simple.TestSimpleFunctions.testInvokeIndirectly
+#{ f <- function(x) x+1 ; g <- function(x) x+2 ; h <- function(v) if (v==1) f else g ; h(2)(1) }
+[1] 3
+
+##com.oracle.truffle.r.test.simple.TestSimpleFunctions.testInvokeIndirectly
+#{ f <- function(x) x+1 ; g <- function(x) x+2 ; v <- 1 ; (if (v==1) f else g)(1) }
+[1] 2
+
+##com.oracle.truffle.r.test.simple.TestSimpleFunctions.testInvokeIndirectly
+#{ f <- function(x) x+1 ; g <- function(x) x+2 ; v <- 2 ; (if (v==1) f else g)(1) }
+[1] 3
+
 ##com.oracle.truffle.r.test.simple.TestSimpleFunctions.testMatching
 #{ f <- function(a) { a } ; f(1,2) }
 Error in f(1, 2) : unused argument (2)
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 145764bdc4..c9b925c241 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
@@ -14623,6 +14623,36 @@ public class AllTests extends TestBase {
         assertEvalError("{ f <- function(a,b,c,d) { a + b } ; f(1,x=1,2,3,4) }");
     }
 
+    @Test
+    public void TestSimpleFunctions_testInvokeIndirectly_249a400b35f2f0c3cc210c2719eadf10() {
+        assertEval("{ f <- function(x) x+1 ; g <- function(x) x+2 ; h <- function(v) if (v==1) f else g ; h(1)(1) }");
+    }
+
+    @Test
+    public void TestSimpleFunctions_testInvokeIndirectly_eba1980fa779ba82a6d33dd930b37480() {
+        assertEval("{ f <- function(x) x+1 ; g <- function(x) x+2 ; h <- function(v) if (v==1) f else g ; h(2)(1) }");
+    }
+
+    @Test
+    public void TestSimpleFunctions_testInvokeIndirectly_c69f1367fbb3330e6e446038532361d0() {
+        assertEval("{ f <- function(x) x+1 ; g <- function(x) x+2 ; v <- 1 ; (if (v==1) f else g)(1) }");
+    }
+
+    @Test
+    public void TestSimpleFunctions_testInvokeIndirectly_0426e7a36eb62ebaece970a5f8adb8c3() {
+        assertEval("{ f <- function(x) x+1 ; g <- function(x) x+2 ; v <- 2 ; (if (v==1) f else g)(1) }");
+    }
+
+    @Test
+    public void TestSimpleFunctions_testInvokeIndirectly_6b4d9a5443d0ef4f0adb1985be5be697() {
+        assertEval("{ f <- function(x) x+1 ; g <- function(x) x+2 ; funs <- list(f,g) ; funs[[1]](1) }");
+    }
+
+    @Test
+    public void TestSimpleFunctions_testInvokeIndirectly_70237bb41c7522a4a2a4a4bab29d79a6() {
+        assertEval("{ f <- function(x) x+1 ; g <- function(x) x+2 ; funs <- list(f,g) ; funs[[2]](1) }");
+    }
+
     @Test
     public void TestSimpleFunctions_testMatching_c272d90b4e2480f9f6fc9b6bfcc79e74() {
         assertEval("{ x<-function(foo,bar){foo*bar} ; x(f=10,2) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleFunctions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleFunctions.java
index e1f9f349af..9ba10fff31 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleFunctions.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleFunctions.java
@@ -228,4 +228,14 @@ public class TestSimpleFunctions extends TestBase {
         assertEvalError("{ f <- function(...) { ..1 + ..2 } ; f(1,,3) }");
     }
 
+    @Test
+    public void testInvokeIndirectly() {
+        assertEval("{ f <- function(x) x+1 ; g <- function(x) x+2 ; h <- function(v) if (v==1) f else g ; h(1)(1) }");
+        assertEval("{ f <- function(x) x+1 ; g <- function(x) x+2 ; h <- function(v) if (v==1) f else g ; h(2)(1) }");
+        assertEval("{ f <- function(x) x+1 ; g <- function(x) x+2 ; v <- 1 ; (if (v==1) f else g)(1) }");
+        assertEval("{ f <- function(x) x+1 ; g <- function(x) x+2 ; v <- 2 ; (if (v==1) f else g)(1) }");
+        assertEval("{ f <- function(x) x+1 ; g <- function(x) x+2 ; funs <- list(f,g) ; funs[[1]](1) }");
+        assertEval("{ f <- function(x) x+1 ; g <- function(x) x+2 ; funs <- list(f,g) ; funs[[2]](1) }");
+    }
+
 }
-- 
GitLab