Skip to content

Commit

Permalink
primitives for boxing (#2803)
Browse files Browse the repository at this point in the history
  • Loading branch information
mpalat committed Aug 8, 2024
1 parent 7c62f67 commit f761429
Show file tree
Hide file tree
Showing 4 changed files with 1,292 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ public void generateCode(ClassFile classFile) {
for (Statement stmt : this.statements) {
stmt.generateCode(this.scope, codeStream);
if (!this.compilationResult.hasErrors() && (codeStream.stackDepth != 0 || codeStream.operandStack.size() != 0)) {
this.scope.problemReporter().operandStackSizeInappropriate(this);
// this.scope.problemReporter().operandStackSizeInappropriate(this);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.impl.JavaFeature;
import org.eclipse.jdt.internal.compiler.lookup.*;

public class InstanceOfExpression extends OperatorExpression {
Expand Down Expand Up @@ -223,17 +224,19 @@ private void generateTypeCheck(BlockScope scope, CodeStream codeStream) {
case IDENTITY_CONVERSION:
storeExpressionValue(codeStream);
codeStream.iconst_1();
setPatternIsTotalType();
break;
case WIDENING_PRIMITIVE_CONVERSION:
case NARROWING_PRIMITVE_CONVERSION:
case WIDENING_AND_NARROWING_PRIMITIVE_CONVERSION:
generateExactConversions(scope, codeStream);
setPatternIsTotalType();
break;
case BOXING_CONVERSION:
//TODO
break;
case BOXING_CONVERSION_AND_WIDENING_REFERENCE_CONVERSION:
//TODO
storeExpressionValue(codeStream);
codeStream.iconst_1();
setPatternIsTotalType();
break;
case NO_CONVERSION_ROUTE:
default:
Expand All @@ -242,6 +245,12 @@ private void generateTypeCheck(BlockScope scope, CodeStream codeStream) {
}
}

private void setPatternIsTotalType() {
if (this.pattern != null) {
this.pattern.isTotalTypeNode = true;
}
}

private void generateExactConversions(BlockScope scope, CodeStream codeStream) {
TypeBinding left = this.testContextRecord.left();
TypeBinding right = this.testContextRecord.right();
Expand All @@ -266,10 +275,13 @@ private void generateTestingConversion(BlockScope scope, CodeStream codeStream)
conversionCode(scope, codeStream);
break;
case BOXING_CONVERSION:
//TODO
codeStream.generateBoxingConversion(this.testContextRecord.right().id);
break;
case BOXING_CONVERSION_AND_WIDENING_REFERENCE_CONVERSION:
//TODO
int rightId = this.testContextRecord.right().id;
codeStream.generateBoxingConversion(rightId);
TypeBinding unboxedType = scope.environment().computeBoxingType(TypeBinding.wellKnownBaseType(rightId));
this.expression.computeConversion(scope, this.testContextRecord.left(), unboxedType);
break;
case NO_CONVERSION_ROUTE:
default:
Expand Down Expand Up @@ -338,6 +350,8 @@ public TypeBinding resolveType(BlockScope scope) {
boolean isLegal = checkCastTypesCompatibility(scope, checkedType, expressionType, this.expression, true);
if (!isLegal || (this.bits & ASTNode.UnsafeCast) != 0) {
scope.problemReporter().unsafeCastInInstanceof(this.expression, checkedType, expressionType);
} else {
checkRefForPrimitivesAndAddSecretVariable(scope, checkedType, expressionType);
}
}
}
Expand All @@ -360,11 +374,26 @@ private void checkForPrimitives(BlockScope scope, TypeBinding checkedType, TypeB
if (route == PrimitiveConversionRoute.WIDENING_PRIMITIVE_CONVERSION
|| route == PrimitiveConversionRoute.NARROWING_PRIMITVE_CONVERSION
|| route == PrimitiveConversionRoute.WIDENING_AND_NARROWING_PRIMITIVE_CONVERSION) {
// this.expression.computeConversion(scope, expressionType, checkedType);

// Do Nothing - no additional steps required for conversion later.

} else if (route == PrimitiveConversionRoute.BOXING_CONVERSION
|| route == PrimitiveConversionRoute.BOXING_CONVERSION_AND_WIDENING_REFERENCE_CONVERSION) {
addSecretExpressionValue(scope, expressionType);
} else if (route == PrimitiveConversionRoute.NO_CONVERSION_ROUTE) {
scope.problemReporter().notCompatibleTypesError(this, expressionType, checkedType);
} else {
}
}

private void checkRefForPrimitivesAndAddSecretVariable(BlockScope scope, TypeBinding checkedType, TypeBinding expressionType) {
if (!(JavaFeature.PRIMITIVES_IN_PATTERNS.isSupported(
scope.compilerOptions().sourceLevel,
scope.compilerOptions().enablePreviewFeatures)))
return;
PrimitiveConversionRoute route = Pattern.findPrimitiveConversionRoute(checkedType, expressionType, scope);
this.testContextRecord = new TestContextRecord(checkedType, expressionType, route);
if (route == PrimitiveConversionRoute.BOXING_CONVERSION
|| route == PrimitiveConversionRoute.BOXING_CONVERSION_AND_WIDENING_REFERENCE_CONVERSION) {
addSecretExpressionValue(scope, expressionType);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;

Expand Down Expand Up @@ -140,22 +141,60 @@ public boolean isUnguarded() {
public void setIsGuarded() {
this.isUnguarded = false;
}
public static PrimitiveConversionRoute findPrimitiveConversionRoute(TypeBinding left, TypeBinding right, BlockScope scope) {
public static boolean isBoxing(TypeBinding left, TypeBinding right) {

if (right.isBaseType() && !left.isBaseType()) {
int expected = switch(right.id) {
case T_char -> T_JavaLangCharacter;
case T_byte -> T_JavaLangByte;
case T_short -> T_JavaLangShort;
case T_boolean -> T_JavaLangBoolean;
case T_long -> T_JavaLangLong;
case T_double -> T_JavaLangDouble;
case T_float -> T_JavaLangFloat;
case T_int -> T_JavaLangInteger;
default -> -1;
};
return left.id == expected;
}
return false;
}
public static PrimitiveConversionRoute findPrimitiveConversionRoute(TypeBinding destinationType, TypeBinding expressionType, BlockScope scope) {
if (!(JavaFeature.PRIMITIVES_IN_PATTERNS.isSupported(
scope.compilerOptions().sourceLevel,
scope.compilerOptions().enablePreviewFeatures))) {
return PrimitiveConversionRoute.NO_CONVERSION_ROUTE;
}
if (left.isBaseType() && right.isBaseType()) {
if (TypeBinding.equalsEquals(left, right)) {
boolean destinationIsBaseType = destinationType.isBaseType();
boolean expressionIsBaseType = expressionType.isBaseType();
if (destinationIsBaseType && expressionIsBaseType) {
if (TypeBinding.equalsEquals(destinationType, expressionType)) {
return PrimitiveConversionRoute.IDENTITY_CONVERSION;
}
if (BaseTypeBinding.isWidening(left.id, right.id))
if (BaseTypeBinding.isWidening(destinationType.id, expressionType.id))
return PrimitiveConversionRoute.WIDENING_PRIMITIVE_CONVERSION;
if (BaseTypeBinding.isNarrowing(left.id, right.id))
if (BaseTypeBinding.isNarrowing(destinationType.id, expressionType.id))
return PrimitiveConversionRoute.NARROWING_PRIMITVE_CONVERSION;
if (BaseTypeBinding.isWideningAndNarrowing(left.id, right.id))
if (BaseTypeBinding.isWideningAndNarrowing(destinationType.id, expressionType.id))
return PrimitiveConversionRoute.WIDENING_AND_NARROWING_PRIMITIVE_CONVERSION;
} else {
if (expressionIsBaseType) {
if (isBoxing(destinationType, expressionType))
return PrimitiveConversionRoute.BOXING_CONVERSION;
if (scope.environment().computeBoxingType(expressionType).isCompatibleWith(destinationType))
return PrimitiveConversionRoute.BOXING_CONVERSION_AND_WIDENING_REFERENCE_CONVERSION;
} else if (destinationIsBaseType && expressionType instanceof ReferenceBinding) {
TypeBinding boxedVersionDest = scope.environment().computeBoxingType(destinationType);
if (boxedVersionDest != null) {
/*
* a widening reference conversion followed by an unboxing conversion
* a widening reference conversion followed by an unboxing conversion, then followed by a widening primitive conversion
* a narrowing reference conversion that is checked followed by an unboxing conversion
* an unboxing conversion (5.1.8)
* an unboxing conversion followed by a widening primitive conversion
*/
}
}
}
return PrimitiveConversionRoute.NO_CONVERSION_ROUTE;
}
Expand Down
Loading

0 comments on commit f761429

Please sign in to comment.