Cleanup and unify RangeCodegenUtil functions.

This commit is contained in:
Dmitry Petrov
2016-10-12 16:39:51 +03:00
parent e788ef408f
commit 71362d6b0a
2 changed files with 30 additions and 45 deletions
@@ -634,10 +634,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@NotNull ResolvedCall<? extends CallableDescriptor> loopRangeCall
) {
CallableDescriptor loopRangeCallee = loopRangeCall.getResultingDescriptor();
if (RangeCodegenUtil.isOptimizableRangeTo(loopRangeCallee)) {
if (RangeCodegenUtil.isPrimitiveNumberRangeTo(loopRangeCallee)) {
return new ForInRangeLiteralLoopGenerator(forExpression, loopRangeCall);
}
else if (RangeCodegenUtil.isOptimizableDownTo(loopRangeCallee)) {
else if (RangeCodegenUtil.isPrimitiveNumberDownTo(loopRangeCallee)) {
return new ForInDownToProgressionLoopGenerator(forExpression, loopRangeCall);
}
else if (RangeCodegenUtil.isArrayOrPrimitiveArrayIndices(loopRangeCallee)) {
@@ -3448,8 +3448,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() {
@Override
public Unit invoke(InstructionAdapter v) {
if (RangeCodegenUtil.isOptimizablePrimitiveRangeSpecialization(leftValue.type, deparenthesized, bindingContext)
|| RangeCodegenUtil.isOptimizableRangeTo(operationReference, bindingContext)) {
if (RangeCodegenUtil.isPrimitiveRangeSpecializationOfType(leftValue.type, deparenthesized, bindingContext) ||
RangeCodegenUtil.isPrimitiveRangeToExtension(operationReference, bindingContext)) {
generateInPrimitiveRange(leftValue, (KtBinaryExpression) deparenthesized, isInverted);
}
else {
@@ -128,19 +128,24 @@ public class RangeCodegenUtil {
return getPrimitiveRangeOrProgressionElementType(className) != null;
}
/*
* Checks whether rangeTo expression is optimizable for loop
*/
public static boolean isOptimizableRangeTo(CallableDescriptor rangeTo) {
if ("rangeTo".equals(rangeTo.getName().asString())) {
if (isPrimitiveNumberClassDescriptor(rangeTo.getContainingDeclaration())) {
return true;
}
}
return false;
public static boolean isPrimitiveNumberRangeTo(CallableDescriptor rangeTo) {
if (!"rangeTo".equals(rangeTo.getName().asString())) return false;
if (!isPrimitiveNumberClassDescriptor(rangeTo.getContainingDeclaration())) return false;
return true;
}
public static boolean isOptimizableDownTo(@NotNull CallableDescriptor descriptor) {
private static boolean isPrimitiveRangeToExtension(@NotNull CallableDescriptor descriptor) {
if (!isTopLevelInPackage(descriptor, "rangeTo", "kotlin.ranges")) return false;
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
if (extensionReceiver == null) return false;
return KotlinBuiltIns.isPrimitiveType(extensionReceiver.getType());
}
public static boolean isPrimitiveNumberDownTo(@NotNull CallableDescriptor descriptor) {
if (!isTopLevelInPackage(descriptor, "downTo", "kotlin.ranges")) return false;
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
@@ -184,44 +189,33 @@ public class RangeCodegenUtil {
return true;
}
/*
* Checks whether rangeTo expression is optimizable target of contains operator
*/
public static boolean isOptimizableRangeTo(@NotNull KtSimpleNameExpression operationReference, @NotNull BindingContext bindingContext) {
public static boolean isPrimitiveRangeToExtension(@NotNull KtSimpleNameExpression operationReference, @NotNull BindingContext bindingContext) {
ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilKt
.getResolvedCallWithAssert(operationReference, bindingContext);
ReceiverValue receiver = resolvedCall.getDispatchReceiver();
/*
* Range is optimizable if
* 'in' receiver is expression 'rangeTo' from stdlib package and its argument
* has same primitive type as generic range parameter.
* 'in' receiver is expression 'rangeTo' from stdlib package
* and its argument has same primitive type as generic range parameter.
* For non-matching primitive types (e.g. int in double range)
* dispatch receiver will be null, because extension method will be called.
*/
if (receiver instanceof ExpressionReceiver) {
ExpressionReceiver e = (ExpressionReceiver) receiver;
ResolvedCall<? extends CallableDescriptor> resolvedReceiver =
CallUtilKt.getResolvedCall(e.getExpression(), bindingContext);
if (!(receiver instanceof ExpressionReceiver)) return false;
ExpressionReceiver e = (ExpressionReceiver) receiver;
if (resolvedReceiver == null) {
return false;
}
ResolvedCall<? extends CallableDescriptor> resolvedReceiver =
CallUtilKt.getResolvedCall(e.getExpression(), bindingContext);
if (resolvedReceiver == null) return false;
CallableDescriptor descriptor = resolvedReceiver.getResultingDescriptor();
// kotlin.ranges.Ranges#rangeTo: ClosedRange<T> and T is primitive
// noinspection ConstantConditions
return isBuiltInRangeTo(descriptor) && KotlinBuiltIns.isPrimitiveType(descriptor.getExtensionReceiverParameter().getType());
}
return false;
return isPrimitiveRangeToExtension(resolvedReceiver.getResultingDescriptor());
}
/*
* Checks whether for expression 'x in a..b' a..b is primitive integral range
* with same type as x.
*/
public static boolean isOptimizablePrimitiveRangeSpecialization(
public static boolean isPrimitiveRangeSpecializationOfType(
@NotNull Type argumentType,
@NotNull KtExpression rangeExpression,
@NotNull BindingContext bindingContext
@@ -247,15 +241,6 @@ public class RangeCodegenUtil {
return false;
}
private static boolean isBuiltInRangeTo(@NotNull CallableDescriptor descriptor) {
if (!isTopLevelInPackage(descriptor, "rangeTo", "kotlin.ranges")) {
return false;
}
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
return extensionReceiver != null;
}
private static boolean isTopLevelInPackage(@NotNull CallableDescriptor descriptor, @NotNull String name, @NotNull String packageName) {
if (!name.equals(descriptor.getName().asString())) return false;