From 1e8e5ddedaafa02ab8181dbb36c51ea128dd03cb Mon Sep 17 00:00:00 2001
From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
Date: Tue, 6 Feb 2018 19:57:10 +0100
Subject: [PATCH] Recursive subscripting for RLanguage

---
 .../r/nodes/access/vector/ExtractVectorNode.java    | 13 +++++++------
 .../vector/RecursiveExtractSubscriptNode.java       | 10 ++++++----
 .../nodes/access/vector/RecursiveSubscriptNode.java |  6 +++---
 .../oracle/truffle/r/test/ExpectedTestOutput.test   |  4 ++++
 .../r/test/library/base/TestSimpleValues.java       |  7 ++++++-
 5 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
index c8504c82d6..b7a0bd8b9e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
@@ -47,6 +47,7 @@ import com.oracle.truffle.r.nodes.unary.FirstStringNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -108,14 +109,14 @@ public abstract class ExtractVectorNode extends RBaseNode {
     protected abstract Object execute(Object vector, Object[] positions, Object exact, Object dropDimensions);
 
     @Specialization(guards = {"cached != null", "cached.isSupported(vector, positions)"}, limit = "3")
-    protected Object doRecursive(RAbstractVector vector, Object[] positions, Object exact, Object dropDimensions,  //
+    protected Object doRecursive(RAbstractContainer vector, Object[] positions, Object exact, Object dropDimensions,  //
                     @Cached("createRecursiveCache(vector, positions)") RecursiveExtractSubscriptNode cached) {
         return cached.apply(vector, positions, exact, dropDimensions);
     }
 
-    protected RecursiveExtractSubscriptNode createRecursiveCache(Object vector, Object[] positions) {
-        if (isRecursiveSubscript(vector, positions)) {
-            return RecursiveExtractSubscriptNode.create((RAbstractListVector) vector, positions[0]);
+    protected RecursiveExtractSubscriptNode createRecursiveCache(Object x, Object[] positions) {
+        if (isRecursiveSubscript(x, positions)) {
+            return RecursiveExtractSubscriptNode.create((RAbstractContainer) x, positions[0]);
         }
         return null;
     }
@@ -133,7 +134,7 @@ public abstract class ExtractVectorNode extends RBaseNode {
     }
 
     private boolean isRecursiveSubscript(Object vector, Object[] positions) {
-        return !recursive && !ignoreRecursive && mode.isSubscript() && vector instanceof RAbstractListVector && positions.length == 1;
+        return !recursive && !ignoreRecursive && mode.isSubscript() && (vector instanceof RAbstractListVector || vector instanceof RLanguage) && positions.length == 1;
     }
 
     @Specialization(limit = "CACHE_LIMIT", guards = {"!isForeignObject(vector)", "cached != null", "cached.isSupported(vector, positions, exact, dropDimensions)"})
@@ -244,7 +245,7 @@ public abstract class ExtractVectorNode extends RBaseNode {
         public RecursiveExtractSubscriptNode getRecursive(RAbstractContainer vector, Object[] positions) {
             CompilerAsserts.neverPartOfCompilation();
             if (cachedRecursive == null || !cachedRecursive.isSupported(vector, positions)) {
-                cachedRecursive = insert(RecursiveExtractSubscriptNode.create((RAbstractListVector) vector, positions[0]));
+                cachedRecursive = insert(RecursiveExtractSubscriptNode.create(vector, positions[0]));
             }
             return cachedRecursive;
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveExtractSubscriptNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveExtractSubscriptNode.java
index 559bde5617..a50f0a2da3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveExtractSubscriptNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveExtractSubscriptNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -26,8 +26,10 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.data.RInteger;
+import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 
 abstract class RecursiveExtractSubscriptNode extends RecursiveSubscriptNode {
@@ -36,11 +38,11 @@ abstract class RecursiveExtractSubscriptNode extends RecursiveSubscriptNode {
     @Child private ExtractVectorNode recursiveSubscriptExtract = ExtractVectorNode.createRecursive(ElementAccessMode.SUBSCRIPT);
     @Child private ExtractVectorNode subscriptExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
 
-    RecursiveExtractSubscriptNode(RAbstractListVector vector, Object position) {
+    RecursiveExtractSubscriptNode(RAbstractContainer vector, Object position) {
         super(vector, position);
     }
 
-    public static RecursiveExtractSubscriptNode create(RAbstractListVector vector, Object position) {
+    public static RecursiveExtractSubscriptNode create(RAbstractContainer vector, Object position) {
         return RecursiveExtractSubscriptNodeGen.create(vector, position);
     }
 
@@ -71,7 +73,7 @@ abstract class RecursiveExtractSubscriptNode extends RecursiveSubscriptNode {
         for (int i = 1; i < positionLength; i++) {
             Object selection = getPositionExtract.apply(firstPosition, new Object[]{RInteger.valueOf(i)}, RLogical.TRUE, RLogical.TRUE);
             try {
-                if (!(currentVector instanceof RAbstractListVector)) {
+                if (!(currentVector instanceof RAbstractListVector || currentVector instanceof RLanguage)) {
                     throw indexingFailed(i);
                 }
                 currentVector = recursiveSubscriptExtract.apply(currentVector, new Object[]{selection}, exact, dropDimensions);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java
index 72a24f39e2..d91634e122 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -24,7 +24,7 @@ package com.oracle.truffle.r.nodes.access.vector;
 
 import com.oracle.truffle.r.nodes.control.RLengthNode;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 abstract class RecursiveSubscriptNode extends RBaseNode {
@@ -34,7 +34,7 @@ abstract class RecursiveSubscriptNode extends RBaseNode {
 
     @Child protected RLengthNode positionLengthNode = RLengthNode.create();
 
-    RecursiveSubscriptNode(RAbstractListVector vector, Object position) {
+    RecursiveSubscriptNode(RAbstractContainer vector, Object position) {
         this.vectorClass = vector.getClass();
         this.positionClass = position.getClass();
     }
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 a5ef46f5b7..05633aca26 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
@@ -117242,6 +117242,10 @@ Error in c(as.raw(10), as.raw(10), as.raw(10))^c(as.raw(10), as.raw(10),  :
 #f <- function(x) { x[1] = 2; }; x <- c(1L, 2L, 3L); f(x); x[1]
 [1] 1
 
+##com.oracle.truffle.r.test.library.base.TestSimpleValues.testLanguage#
+#quote(1==1)[[c(2,1)]]
+[1] 1
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleValues.testMatrixAccess#
 #x <- matrix(c(1,2,3,4),2) ; x[,2]
 [1] 3 4
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleValues.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleValues.java
index 07b3d1107b..260b518ba9 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleValues.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleValues.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -161,6 +161,11 @@ public class TestSimpleValues extends TestBase {
         assertEval("{ 1i }");
     }
 
+    @Test
+    public void testLanguage() {
+        assertEval("quote(1==1)[[c(2,1)]]");
+    }
+
     @Test
     public void testSpecial() {
         assertEval("{ NULL }");
-- 
GitLab