Skip to content

Commit b4cf1bd

Browse files
committed
RangeBuiltins: __getitem__ fix generic case, add support for objects implementing __index__
1 parent 84f49b9 commit b4cf1bd

File tree

1 file changed

+80
-63
lines changed
  • graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/range

1 file changed

+80
-63
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/range/RangeBuiltins.java

Lines changed: 80 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -339,84 +339,47 @@ protected static boolean allNone(PObjectSlice slice) {
339339
return slice.getStart() == PNone.NONE && slice.getStop() == PNone.NONE && slice.getStep() == PNone.NONE;
340340
}
341341

342-
protected static boolean isNotSlice(Object value) {
343-
return !(value instanceof PSlice);
342+
protected static boolean canBeIndexOrInteger(Object idx, PythonObjectLibrary pol) {
343+
return pol.canBeIndex(idx) || PGuards.canBeInteger(idx);
344344
}
345345

346346
@Specialization(guards = "allNone(slice)")
347-
Object doPRangeObj(PRange range, @SuppressWarnings("unused") PObjectSlice slice) {
348-
return range;
347+
Object doPRangeObj(PRange self, @SuppressWarnings("unused") PObjectSlice slice) {
348+
return self;
349349
}
350350

351-
@Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = "isNotSlice(idx)")
352-
Object doPRange(PIntRange primary, Object idx,
351+
@Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = "canBeIndexOrInteger(idx, pol)")
352+
Object doPRange(PIntRange self, Object idx,
353353
@CachedLibrary(value = "idx") PythonObjectLibrary pol) {
354-
return primary.getIntItemNormalized(normalize.execute(pol.asSize(idx), primary.getIntLength()));
354+
return self.getIntItemNormalized(normalize.execute(pol.asSize(idx), self.getIntLength()));
355355
}
356356

357-
@Specialization(guards = "isNotSlice(idx)")
357+
@Specialization(limit = "getCallSiteInlineCacheMaxDepth()", guards = "canBeIndexOrInteger(idx, pol)")
358358
Object doPRange(PBigRange self, Object idx,
359-
@Cached CastToJavaBigIntegerNode toBigInt) {
359+
@Cached CastToJavaBigIntegerNode toBigInt,
360+
@SuppressWarnings("unused") @CachedLibrary(value = "idx") PythonObjectLibrary pol) {
360361
return factory().createInt(self.getBigIntItemNormalized(computeBigRangeItem(self, idx, toBigInt)));
361362
}
362363

363-
@TruffleBoundary
364-
private BigInteger computeBigRangeItem(PBigRange self, Object idx, CastToJavaBigIntegerNode toBigInt) {
365-
BigInteger index = toBigInt.execute(idx);
366-
BigInteger length = self.getBigIntegerLength();
367-
BigInteger i;
368-
if (index.compareTo(BigInteger.ZERO) < 0) {
369-
i = length.add(index);
370-
} else {
371-
i = index;
372-
}
373-
374-
if (i.compareTo(BigInteger.ZERO) < 0 || i.compareTo(length) >= 0) {
375-
throw raise(IndexError, "range object index out of range");
376-
}
377-
return i;
378-
}
379-
380-
private PIntRange createRange(SliceInfo info, int rStart, int rStep, RangeNodes.LenOfRangeNode lenOfRangeNode) {
381-
int newStep = rStep * info.step;
382-
int newStart = rStart + info.start * rStep;
383-
int newStop = rStart + info.stop * rStep;
384-
int len = (int) lenOfRangeNode.execute(newStart, newStop, newStep);
385-
return factory().createIntRange(newStart, newStop, newStep, len);
386-
}
387-
388-
@TruffleBoundary
389-
private PBigRange createRange(SliceObjectInfo info, BigInteger rStart, BigInteger rStep, RangeNodes.LenOfRangeNode lenOfRangeNode) {
390-
BigInteger sliceStart = (BigInteger) info.start;
391-
BigInteger sliceStop = (BigInteger) info.stop;
392-
BigInteger sliceStep = (BigInteger) info.step;
393-
394-
BigInteger step = rStep.multiply(sliceStep);
395-
BigInteger start = rStart.add(sliceStart.multiply(rStep));
396-
BigInteger stop = rStart.add(sliceStop.multiply(rStep));
397-
BigInteger len = (BigInteger) lenOfRangeNode.execute(start, stop, step);
398-
return factory().createBigRange(factory().createInt(start), factory().createInt(stop), factory().createInt(step), factory().createInt(len));
399-
}
400-
401364
@Specialization
402-
Object doPRangeObjWithSlowPath(PIntRange range, PSlice slice,
365+
Object doPRangeSliceSlowPath(PIntRange self, PSlice slice,
403366
@Cached ComputeIndices compute,
404367
@Cached IsBuiltinClassProfile profileError,
405368
@Cached CoerceToBigRange toBigIntRange,
406369
@Cached CoerceToObjectSlice toBigIntSlice,
407370
@Cached RangeNodes.LenOfRangeNode lenOfRangeNode) {
408371
try {
409-
final int rStart = range.getIntStart();
410-
final int rStep = range.getIntStep();
411-
SliceInfo info = compute.execute(slice, range.getIntLength());
372+
final int rStart = self.getIntStart();
373+
final int rStep = self.getIntStep();
374+
SliceInfo info = compute.execute(slice, self.getIntLength());
412375
return createRange(info, rStart, rStep, lenOfRangeNode);
413376
} catch (PException pe) {
414377
pe.expect(PythonBuiltinClassType.OverflowError, profileError);
415378
// pass
416379
} catch (CannotCastException | ArithmeticException e) {
417380
// pass
418381
}
419-
PBigRange rangeBI = toBigIntRange.execute(range, factory());
382+
PBigRange rangeBI = toBigIntRange.execute(self, factory());
420383
BigInteger rangeStart = rangeBI.getBigIntegerStart();
421384
BigInteger rangeStep = rangeBI.getBigIntegerStep();
422385

@@ -425,25 +388,25 @@ Object doPRangeObjWithSlowPath(PIntRange range, PSlice slice,
425388
}
426389

427390
@Specialization
428-
Object doPRangePSliceSlowPath(PBigRange range, PSlice slice,
391+
Object doPRangeSliceSlowPath(PBigRange self, PSlice slice,
429392
@Cached ComputeIndices compute,
430-
@CachedLibrary(limit = "3") PythonObjectLibrary lib,
431393
@Cached IsBuiltinClassProfile profileError,
432394
@Cached CoerceToBigRange toBigIntRange,
433395
@Cached CoerceToObjectSlice toBigIntSlice,
434-
@Cached RangeNodes.LenOfRangeNode lenOfRangeNode) {
396+
@Cached RangeNodes.LenOfRangeNode lenOfRangeNode,
397+
@CachedLibrary(limit = "3") PythonObjectLibrary lib) {
435398
try {
436-
int rStart = lib.asSize(range.getStart());
437-
int rStep = lib.asSize(range.getStep());
438-
SliceInfo info = compute.execute(slice, lib.asSize(range.getLength()));
399+
int rStart = lib.asSize(self.getStart());
400+
int rStep = lib.asSize(self.getStep());
401+
SliceInfo info = compute.execute(slice, lib.asSize(self.getLength()));
439402
return createRange(info, rStart, rStep, lenOfRangeNode);
440403
} catch (PException pe) {
441404
pe.expect(PythonBuiltinClassType.OverflowError, profileError);
442405
// pass
443406
} catch (CannotCastException | ArithmeticException e) {
444407
// pass
445408
}
446-
PBigRange rangeBI = toBigIntRange.execute(range, factory());
409+
PBigRange rangeBI = toBigIntRange.execute(self, factory());
447410
BigInteger rangeStart = rangeBI.getBigIntegerStart();
448411
BigInteger rangeStep = rangeBI.getBigIntegerStep();
449412

@@ -452,15 +415,69 @@ Object doPRangePSliceSlowPath(PBigRange range, PSlice slice,
452415
}
453416

454417
@Specialization
455-
Object doPRange(@SuppressWarnings("unused") PRange primary, PNone idx) {
418+
Object doGeneric(PRange self, Object idx,
419+
@Cached ConditionProfile isNumIndexProfile,
420+
@Cached ConditionProfile isSliceIndexProfile,
421+
@Cached ComputeIndices compute,
422+
@Cached IsBuiltinClassProfile profileError,
423+
@Cached CoerceToBigRange toBigIntRange,
424+
@Cached CoerceToObjectSlice toBigIntSlice,
425+
@Cached RangeNodes.LenOfRangeNode lenOfRangeNode,
426+
@Cached CastToJavaBigIntegerNode toBigInt,
427+
@CachedLibrary(limit = "getCallSiteInlineCacheMaxDepth()") PythonObjectLibrary pol) {
428+
if (isNumIndexProfile.profile(canBeIndexOrInteger(idx, pol))) {
429+
if (self instanceof PIntRange) {
430+
return doPRange((PIntRange) self, idx, pol);
431+
}
432+
return doPRange((PBigRange) self, idx, toBigInt, pol);
433+
}
434+
if (isSliceIndexProfile.profile(idx instanceof PSlice)) {
435+
PSlice slice = (PSlice) idx;
436+
if (self instanceof PIntRange) {
437+
return doPRangeSliceSlowPath((PIntRange) self, slice, compute, profileError, toBigIntRange, toBigIntSlice, lenOfRangeNode);
438+
}
439+
return doPRangeSliceSlowPath((PBigRange) self, slice, compute, profileError, toBigIntRange, toBigIntSlice, lenOfRangeNode, pol);
440+
}
456441
throw raise(TypeError, ErrorMessages.OBJ_INDEX_MUST_BE_INT_OR_SLICES, "range", idx);
457442
}
458443

459-
@Fallback
460-
Object doGeneric(@SuppressWarnings("unused") Object range, @SuppressWarnings("unused") Object idx) {
461-
return PNotImplemented.NOT_IMPLEMENTED;
444+
@TruffleBoundary
445+
private BigInteger computeBigRangeItem(PBigRange range, Object idx, CastToJavaBigIntegerNode toBigInt) {
446+
BigInteger index = toBigInt.execute(idx);
447+
BigInteger length = range.getBigIntegerLength();
448+
BigInteger i;
449+
if (index.compareTo(BigInteger.ZERO) < 0) {
450+
i = length.add(index);
451+
} else {
452+
i = index;
453+
}
454+
455+
if (i.compareTo(BigInteger.ZERO) < 0 || i.compareTo(length) >= 0) {
456+
throw raise(IndexError, "range object index out of range");
457+
}
458+
return i;
462459
}
463460

461+
private PIntRange createRange(SliceInfo info, int rStart, int rStep, RangeNodes.LenOfRangeNode lenOfRangeNode) {
462+
int newStep = rStep * info.step;
463+
int newStart = rStart + info.start * rStep;
464+
int newStop = rStart + info.stop * rStep;
465+
int len = (int) lenOfRangeNode.execute(newStart, newStop, newStep);
466+
return factory().createIntRange(newStart, newStop, newStep, len);
467+
}
468+
469+
@TruffleBoundary
470+
private PBigRange createRange(SliceObjectInfo info, BigInteger rStart, BigInteger rStep, RangeNodes.LenOfRangeNode lenOfRangeNode) {
471+
BigInteger sliceStart = (BigInteger) info.start;
472+
BigInteger sliceStop = (BigInteger) info.stop;
473+
BigInteger sliceStep = (BigInteger) info.step;
474+
475+
BigInteger step = rStep.multiply(sliceStep);
476+
BigInteger start = rStart.add(sliceStart.multiply(rStep));
477+
BigInteger stop = rStart.add(sliceStop.multiply(rStep));
478+
BigInteger len = (BigInteger) lenOfRangeNode.execute(start, stop, step);
479+
return factory().createBigRange(factory().createInt(start), factory().createInt(stop), factory().createInt(step), factory().createInt(len));
480+
}
464481
}
465482

466483
@Builtin(name = __CONTAINS__, minNumOfPositionalArgs = 2)

0 commit comments

Comments
 (0)