*/
JMethod method = program.getSpecialMethod("Cast.throwClassCastExceptionUnlessNull");
/*
* Override the type of the magic method with the null type.
*/
JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null,
method, program.getTypeNull());
call.getArgs().add(x.getExpr());
replaceExpr = call;
} else if (toType instanceof JReferenceType) {
JExpression curExpr = x.getExpr();
JReferenceType refType = (JReferenceType) toType;
JType argType = x.getExpr().getType();
if (program.isJavaScriptObject(argType)) {
/*
* A JSO-derived class that is about to be cast must be "wrapped"
* first. Since a JSO was never constructed, it may not have an
* accessible prototype. Instead we copy fields from the seed
* function's prototype directly onto the target object as expandos.
* See com.google.gwt.lang.Cast.wrapJSO().
*/
JMethod wrap = program.getSpecialMethod("Cast.wrapJSO");
// override the type of the called method with the JSO's type
JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null,
wrap, argType);
JClassSeed seed = program.getLiteralClassSeed((JClassType) argType);
call.getArgs().add(curExpr);
call.getArgs().add(seed);
curExpr = call;
}
if (argType instanceof JClassType
&& program.typeOracle.canTriviallyCast((JClassType) argType,
refType)) {
// TODO(???): why is this only for JClassType?
// just remove the cast
replaceExpr = curExpr;
} else {
JMethod method = program.getSpecialMethod("Cast.dynamicCast");
// override the type of the called method with the target cast type
JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null,
method, toType);
Integer boxedInt = (Integer) queryIds.get(refType);
JIntLiteral qId = program.getLiteralInt(boxedInt.intValue());
call.getArgs().add(curExpr);
call.getArgs().add(qId);
replaceExpr = call;
}
} else {
/*
* See JLS 5.1.3: if a cast narrows from one type to another, we must
* call a narrowing conversion function. EXCEPTION: we currently have no
* way to narrow double to float, so don't bother.
*/
boolean narrow = false, round = false;
JPrimitiveType tByte = program.getTypePrimitiveByte();
JPrimitiveType tChar = program.getTypePrimitiveChar();
JPrimitiveType tShort = program.getTypePrimitiveShort();
JPrimitiveType tInt = program.getTypePrimitiveInt();
JPrimitiveType tLong = program.getTypePrimitiveLong();
JPrimitiveType tFloat = program.getTypePrimitiveFloat();
JPrimitiveType tDouble = program.getTypePrimitiveDouble();
JType fromType = x.getExpr().getType();
if (tByte == fromType) {
if (tChar == toType) {
narrow = true;
}
} else if (tShort == fromType) {
if (tByte == toType || tChar == toType) {
narrow = true;
}
} else if (tChar == fromType) {
if (tByte == toType || tShort == toType) {
narrow = true;
}
} else if (tInt == fromType) {
if (tByte == toType || tShort == toType || tChar == toType) {
narrow = true;
}
} else if (tLong == fromType) {
if (tByte == toType || tShort == toType || tChar == toType
|| tInt == toType) {
narrow = true;
}
} else if (tFloat == fromType || tDouble == fromType) {
if (tByte == toType || tShort == toType || tChar == toType
|| tInt == toType || tLong == toType) {
round = true;
}
}
if (narrow || round) {
// Replace the expression with a call to the narrow or round method
String methodName = "Cast." + (narrow ? "narrow_" : "round_")
+ toType.getName();
JMethod castMethod = program.getSpecialMethod(methodName);
JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null,
castMethod);
call.getArgs().add(x.getExpr());
replaceExpr = call;
} else {
// Just remove the cast
replaceExpr = x.getExpr();
}