You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2021/11/28 00:39:41 UTC

[groovy] branch GROOVY-10383 created (now 9217fa8)

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a change to branch GROOVY-10383
in repository https://gitbox.apache.org/repos/asf/groovy.git.


      at 9217fa8  GROOVY-10383: SC: optimize `a !in b`

This branch includes the following new commits:

     new 9217fa8  GROOVY-10383: SC: optimize `a !in b`

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[groovy] 01/01: GROOVY-10383: SC: optimize `a !in b`

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY-10383
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 9217fa8197c51b1c82148d7c5c94e0eacd996ea7
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Nov 27 18:39:26 2021 -0600

    GROOVY-10383: SC: optimize `a !in b`
---
 .../transformers/BinaryExpressionTransformer.java  | 13 +++----
 .../transform/stc/STCnAryExpressionTest.groovy     | 40 ++++++++++++++++++++++
 2 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java b/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
index f1a6de5..5f8907b 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
@@ -61,7 +61,6 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.binX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.isNullX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.isOrImplements;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.ternaryX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
@@ -115,7 +114,9 @@ public class BinaryExpressionTransformer {
             }
             break;
           case Types.KEYWORD_IN:
-            return transformInOperation(bin);
+            equal = true; //fallthrough
+          case Types.COMPARE_NOT_IN:
+            return transformInOperation(bin, equal);
           case Types.COMPARE_EQUAL:
           case Types.COMPARE_IDENTICAL:
             equal = true; //fallthrough
@@ -226,12 +227,12 @@ public class BinaryExpressionTransformer {
                 pos);
     }
 
-    private Expression transformInOperation(final BinaryExpression bin) {
+    private Expression transformInOperation(final BinaryExpression bin, final boolean in) {
         Expression leftExpression = bin.getLeftExpression();
         Expression rightExpression = bin.getRightExpression();
 
-        // transform "left in right" into "right.isCase(left)"
-        MethodCallExpression call = callX(rightExpression, "isCase", leftExpression);
+        // transform "left [!]in right" into "right.is[Not]Case(left)"
+        MethodCallExpression call = callX(rightExpression, in ? "isCase" : "isNotCase", leftExpression);
         call.setImplicitThis(false); call.setSourcePosition(bin); call.copyNodeMetaData(bin);
         call.setMethodTarget(bin.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET));
         // GROOVY-7473: no null test for simple cases
@@ -245,7 +246,7 @@ public class BinaryExpressionTransformer {
 
         // GROOVY-6137, GROOVY-7473: null safety and one-time evaluation
         call.setObjectExpression(rightExpression = transformRepeatedReference(rightExpression));
-        Expression safe = ternaryX(isNullX( rightExpression ), isNullX( leftExpression ), call);
+        Expression safe = ternaryX(new CompareToNullExpression(rightExpression,true), new CompareToNullExpression(leftExpression,in), call);
         safe.putNodeMetaData("classgen.callback", classgenCallback(call.getObjectExpression()));
         return staticCompilationTransformer.transform(safe);
     }
diff --git a/src/test/groovy/transform/stc/STCnAryExpressionTest.groovy b/src/test/groovy/transform/stc/STCnAryExpressionTest.groovy
index 51fe8a4..2d79f8b 100644
--- a/src/test/groovy/transform/stc/STCnAryExpressionTest.groovy
+++ b/src/test/groovy/transform/stc/STCnAryExpressionTest.groovy
@@ -172,6 +172,46 @@ class STCnAryExpressionTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-6137, GROOVY-7473, GROOVY-10383
+    void testInOperatorShouldEvaluateOperandsOnce2() {
+        assertScript '''
+            import groovy.transform.Field
+
+            @Field int i = 0
+            @Field int j = 0
+            int getA() { i++ }
+            int getB() { j++ }
+
+            assert !(a !in b)
+            assert i == 1
+            assert j == 1
+        '''
+        assertScript '''
+            import groovy.transform.Field
+
+            @Field int i = 0
+            @Field int j = 0
+            def getA() { i++; null }
+            def getB() { j++ }
+
+            assert a !in b
+            assert i == 1
+            assert j == 1
+        '''
+        assertScript '''
+            import groovy.transform.Field
+
+            @Field int i = 0
+            @Field int j = 0
+            def getA() { i++ }
+            def getB() { j++; null }
+
+            assert a !in b
+            assert i == 1
+            assert j == 1
+        '''
+    }
+
     void testComparisonOperatorCheckWithIncompatibleTypesOkIfComparableNotImplemented() {
         shouldFailWithMessages '''
             [] < 1