Skip to content

Commit 68fba50

Browse files
author
Nicolas Laurent
committed
implement Array#[] for endless ranges
1 parent 2daebe3 commit 68fba50

File tree

3 files changed

+30
-10
lines changed

3 files changed

+30
-10
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ Compatibility:
103103
* Implemented `Random.bytes`.
104104
* Added the ability to parse endless ranges.
105105
* Made `Range#to_a` compatible with endless ranges.
106-
* Made `Array#[]= ` compatible with endless ranges.
106+
* Made `Array#[]` and `Array#[]= ` compatible with endless ranges.
107107

108108
Performance:
109109

src/main/java/org/truffleruby/core/array/ArrayIndexNode.java

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,32 +54,46 @@ protected DynamicObject slice(DynamicObject array, int start, int length) {
5454
@Specialization(guards = "isIntRange(range)")
5555
protected DynamicObject slice(DynamicObject array, DynamicObject range, NotProvided len,
5656
@Cached("createBinaryProfile()") ConditionProfile negativeBeginProfile,
57-
@Cached("createBinaryProfile()") ConditionProfile negativeEndProfile) {
57+
@Cached("createBinaryProfile()") ConditionProfile negativeEndProfile,
58+
@Cached("create()") ArrayReadSliceNormalizedNode readNormalizedSliceNode) {
5859
final int size = getSize(array);
59-
final int normalizedIndex = ArrayOperations
60+
final int normalizedBegin = ArrayOperations
6061
.normalizeIndex(size, Layouts.INT_RANGE.getBegin(range), negativeBeginProfile);
6162

62-
if (normalizedIndex < 0 || normalizedIndex > size) {
63+
if (normalizedBegin < 0 || normalizedBegin > size) {
6364
return nil();
6465
} else {
6566
final int end = ArrayOperations
6667
.normalizeIndex(size, Layouts.INT_RANGE.getEnd(range), negativeEndProfile);
6768
final int exclusiveEnd = ArrayOperations
6869
.clampExclusiveIndex(size, Layouts.INT_RANGE.getExcludedEnd(range) ? end : end + 1);
6970

70-
if (exclusiveEnd <= normalizedIndex) {
71+
if (exclusiveEnd <= normalizedBegin) {
7172
return allocateObjectNode
7273
.allocate(Layouts.BASIC_OBJECT.getLogicalClass(array), ArrayStrategy.NULL_ARRAY_STORE, 0);
7374
}
7475

75-
final int length = exclusiveEnd - normalizedIndex;
76+
return readNormalizedSliceNode.executeReadSlice(array, normalizedBegin, exclusiveEnd - normalizedBegin);
77+
}
78+
}
79+
80+
@Specialization(guards = "isIntEndlessRange(getContext(), range)")
81+
protected DynamicObject endlessSlice(DynamicObject array, DynamicObject range, NotProvided len,
82+
@Cached("createBinaryProfile()") ConditionProfile negativeBeginProfile,
83+
@Cached("create()") ArrayReadSliceNormalizedNode readNormalizedSliceNode) {
84+
final int size = getSize(array);
85+
final int normalizedBegin = ArrayOperations
86+
.normalizeIndex(size, (int) Layouts.OBJECT_RANGE.getBegin(range), negativeBeginProfile);
7687

77-
if (readNormalizedSliceNode == null) {
78-
CompilerDirectives.transferToInterpreterAndInvalidate();
79-
readNormalizedSliceNode = insert(ArrayReadSliceNormalizedNodeGen.create());
88+
if (normalizedBegin < 0 || normalizedBegin > size) {
89+
return nil();
90+
} else {
91+
if (size == normalizedBegin) {
92+
return allocateObjectNode
93+
.allocate(Layouts.BASIC_OBJECT.getLogicalClass(array), ArrayStrategy.NULL_ARRAY_STORE, 0);
8094
}
8195

82-
return readNormalizedSliceNode.executeReadSlice(array, normalizedIndex, length);
96+
return readNormalizedSliceNode.executeReadSlice(array, normalizedBegin, size - normalizedBegin);
8397
}
8498
}
8599

src/main/java/org/truffleruby/language/RubyGuards.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ public static boolean isEndlessRange(RubyContext context, DynamicObject object)
132132
return isNil(context, Layouts.OBJECT_RANGE.getEnd(object));
133133
}
134134

135+
public static boolean isIntEndlessRange(RubyContext context, DynamicObject object) {
136+
return isObjectRange(object) && isInteger(Layouts.OBJECT_RANGE.getBegin(object)) && isEndlessRange(
137+
context,
138+
object);
139+
}
140+
135141
public static boolean isRubyRange(Object value) {
136142
return isIntRange(value) || isLongRange(value) || isObjectRange(value);
137143
}

0 commit comments

Comments
 (0)