You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2021/04/12 09:23:21 UTC

[groovy] 04/25: GROOVY-9649: left open and full open range support for IntRange

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

paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit acf9423f27f7512b5be767f2ca7d71756ea7e416
Author: Eerik Voimanen <ee...@tuni.fi>
AuthorDate: Thu Apr 1 16:45:58 2021 +0300

    GROOVY-9649: left open and full open range support for IntRange
---
 src/main/java/groovy/lang/IntRange.java            | 77 ++++++++++++++--------
 .../groovy/runtime/ScriptBytecodeAdapter.java      |  2 +-
 2 files changed, 52 insertions(+), 27 deletions(-)

diff --git a/src/main/java/groovy/lang/IntRange.java b/src/main/java/groovy/lang/IntRange.java
index c1a4bc3..f06f7a7 100644
--- a/src/main/java/groovy/lang/IntRange.java
+++ b/src/main/java/groovy/lang/IntRange.java
@@ -132,7 +132,9 @@ public class IntRange extends AbstractList<Integer> implements Range<Integer>, S
      * <p>
      * If true or false, the reverse flag is discarded.
      */
-    private final Boolean inclusive;
+    private final Boolean inclusiveRight;
+
+    private final Boolean inclusiveLeft;
 
     /**
      * Creates a new non-inclusive aware <code>IntRange</code>. If <code>from</code> is greater than
@@ -143,7 +145,8 @@ public class IntRange extends AbstractList<Integer> implements Range<Integer>, S
      * @throws IllegalArgumentException if the range would contain more than {@link Integer#MAX_VALUE} values.
      */
     public IntRange(int from, int to) {
-        this.inclusive = null;
+        this.inclusiveRight = null;
+        this.inclusiveLeft = null;
         if (from > to) {
             this.from = to;
             this.to = from;
@@ -166,7 +169,8 @@ public class IntRange extends AbstractList<Integer> implements Range<Integer>, S
      * @throws IllegalArgumentException if <code>from</code> is greater than <code>to</code>.
      */
     protected IntRange(int from, int to, boolean reverse) {
-        this.inclusive = null;
+        this.inclusiveRight = null;
+        this.inclusiveLeft = null;
         if (from > to) {
             throw new IllegalArgumentException("'from' must be less than or equal to 'to'");
         }
@@ -182,12 +186,17 @@ public class IntRange extends AbstractList<Integer> implements Range<Integer>, S
      *
      * @param from      the first value in the range.
      * @param to        the last value in the range.
-     * @param inclusive <code>true</code> if the to value is included in the range.
+     * @param inclusiveRight <code>true</code> if the to value is included in the range.
      */
-    public IntRange(boolean inclusive, int from, int to) {
+    public IntRange(boolean inclusiveRight, int from, int to) {
+        this(true, inclusiveRight, from, to);
+    }
+
+    public IntRange(boolean inclusiveLeft, boolean inclusiveRight, int from, int to) {
         this.from = from;
         this.to = to;
-        this.inclusive = inclusive;
+        this.inclusiveRight = inclusiveRight;
+        this.inclusiveLeft = inclusiveLeft;
         this.reverse = false; // range may still be reversed, this value is ignored for inclusive-aware ranges
         checkSize();
     }
@@ -201,7 +210,8 @@ public class IntRange extends AbstractList<Integer> implements Range<Integer>, S
      * @since 2.5.0
      */
     public <T extends Number & Comparable> NumberRange by(T stepSize) {
-        return new NumberRange(NumberRange.comparableNumber((Number)from), NumberRange.comparableNumber((Number)to), stepSize, inclusive);
+        // TODO edit NumberRange
+        return new NumberRange(NumberRange.comparableNumber((Number)from), NumberRange.comparableNumber((Number)to), stepSize, inclusiveRight);
     }
 
     private void checkSize() {
@@ -220,13 +230,17 @@ public class IntRange extends AbstractList<Integer> implements Range<Integer>, S
      * @return the calculated range information (with 1 added to the to value, ready for providing to subList
      */
     public RangeInfo subListBorders(int size) {
-        if (inclusive == null) {
+        if (inclusiveRight == null || inclusiveLeft == null) {
             throw new IllegalStateException("Should not call subListBorders on a non-inclusive aware IntRange");
         }
-        return subListBorders(from, to, inclusive, size);
+        return subListBorders(from, to, inclusiveRight, size);
     }
 
-    static RangeInfo subListBorders(int from, int to, boolean inclusive, int size) {
+    static RangeInfo subListBorders(int from, int to, boolean inclusiveRight, int size) {
+        return subListBorders(from, to, true, inclusiveRight, size);
+    }
+
+    static RangeInfo subListBorders(int from, int to, boolean inclusiveLeft, boolean inclusiveRight, int size) {
         int tempFrom = from;
         if (tempFrom < 0) {
             tempFrom += size;
@@ -236,9 +250,9 @@ public class IntRange extends AbstractList<Integer> implements Range<Integer>, S
             tempTo += size;
         }
         if (tempFrom > tempTo) {
-            return new RangeInfo(inclusive ? tempTo : tempTo + 1, tempFrom + 1, true);
+            return new RangeInfo(inclusiveRight ? tempTo : tempTo + 1, inclusiveLeft ? tempFrom + 1 : tempFrom, true);
         }
-        return new RangeInfo(tempFrom, inclusive ? tempTo + 1 : tempTo, false);
+        return new RangeInfo(inclusiveLeft ? tempFrom : tempFrom + 1, inclusiveRight ? tempTo + 1 : tempTo, false);
     }
 
     /**
@@ -267,34 +281,44 @@ public class IntRange extends AbstractList<Integer> implements Range<Integer>, S
      * @return <code>true</code> if the ranges are equal
      */
     public boolean equals(IntRange that) {
-        return that != null && ((inclusive == null && reverse == that.reverse && from == that.from && to == that.to)
-                || (inclusive != null && Objects.equals(inclusive, that.inclusive) && from == that.from && to == that.to));
+        return that != null && from == that.from && to == that.to && (
+                (inclusiveRight == null && inclusiveLeft == null && reverse == that.reverse)
+                || (
+                        (inclusiveLeft == null || Objects.equals(inclusiveLeft, that.inclusiveLeft))
+                        && (inclusiveRight == null || Objects.equals(inclusiveRight, that.inclusiveRight))
+                )
+        );
     }
 
     @Override
     public Integer getFrom() {
-        if (inclusive == null || from <= to) {
-            return from;
+        if (from <= to) {
+            return (inclusiveLeft == null || inclusiveLeft) ? from : from + 1;
         }
-        return inclusive ? to : to + 1;
+        return (inclusiveRight == null || inclusiveRight) ? to : to + 1;
     }
 
     @Override
     public Integer getTo() {
-        if (inclusive == null) {
-            return to;
-        }
         if (from <= to) {
-            return inclusive ? to : to - 1;
+            return (inclusiveRight == null || inclusiveRight) ? to : to - 1;
         }
-        return from;
+        return (inclusiveLeft == null || inclusiveLeft) ? from : from - 1;
     }
 
     /**
      * Returns the inclusive flag. Null for non-inclusive aware ranges or non-null for inclusive aware ranges.
      */
     public Boolean getInclusive() {
-        return inclusive;
+        return inclusiveRight;
+    }
+
+    public Boolean getInclusiveRight() {
+        return inclusiveRight;
+    }
+
+    public Boolean getInclusiveLeft() {
+        return inclusiveLeft;
     }
 
     /**
@@ -317,7 +341,7 @@ public class IntRange extends AbstractList<Integer> implements Range<Integer>, S
 
     @Override
     public boolean isReverse() {
-        return inclusive == null ? reverse : (from > to);
+        return (inclusiveRight == null && inclusiveLeft == null) ? reverse : (from > to);
     }
 
     @Override
@@ -367,8 +391,9 @@ public class IntRange extends AbstractList<Integer> implements Range<Integer>, S
 
     @Override
     public String toString() {
-        return inclusive != null ? ("" + from + ".." + (inclusive ? "" : "<") + to)
-                : (reverse ? "" + to + ".." + from : "" + from + ".." + to);
+        return (inclusiveRight == null && inclusiveLeft == null) ? (reverse ? "" + to + ".." + from : "" + from + ".." + to)
+                : ("" + from + ((inclusiveLeft != null && inclusiveLeft) ? "" : "<") + ".."
+                             + ((inclusiveRight != null && inclusiveRight) ? "" : "<") + to);
     }
 
     @Override
diff --git a/src/main/java/org/codehaus/groovy/runtime/ScriptBytecodeAdapter.java b/src/main/java/org/codehaus/groovy/runtime/ScriptBytecodeAdapter.java
index e02bc62..a273c61 100644
--- a/src/main/java/org/codehaus/groovy/runtime/ScriptBytecodeAdapter.java
+++ b/src/main/java/org/codehaus/groovy/runtime/ScriptBytecodeAdapter.java
@@ -641,7 +641,7 @@ public class ScriptBytecodeAdapter {
             int ifrom = (Integer) from;
             int ito = (Integer) to;
             if (inclusive || ifrom != ito) {
-                return new IntRange(inclusive, ifrom, ito);
+                return new IntRange(!exclusiveLeft, !exclusiveRight, ifrom, ito);
             } // else fall through for EmptyRange
         }
         if (!inclusive && compareEqual(from, to)) {