public static Expr FloatToArith(Expr expr, ExprType type) {
ExprTypeKind from = expr.Type.Kind;
ExprTypeKind to = type.Kind;
Env env = expr.Env;
switch (from) {
case ExprTypeKind.FLOAT:
switch (to) {
case ExprTypeKind.CHAR:
if (expr.IsConstExpr) {
return new ConstLong((SByte)((ConstFloat)expr).Value, env);
}
return new TypeCast(TypeCastType.PRESERVE_INT8, new TypeCast(TypeCastType.FLOAT_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type);
case ExprTypeKind.SHORT:
if (expr.IsConstExpr) {
return new ConstLong((Int16)((ConstFloat)expr).Value, env);
}
return new TypeCast(TypeCastType.PRESERVE_INT16, new TypeCast(TypeCastType.FLOAT_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type);
case ExprTypeKind.USHORT:
if (expr.IsConstExpr) {
return new ConstULong((UInt16)((ConstFloat)expr).Value, env);
}
return new TypeCast(TypeCastType.PRESERVE_INT16, new TypeCast(TypeCastType.FLOAT_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type);
case ExprTypeKind.LONG:
if (expr.IsConstExpr) {
return new ConstLong((Int32)((ConstFloat)expr).Value, env);
}
return new TypeCast(TypeCastType.FLOAT_TO_INT32, expr, type);
case ExprTypeKind.ULONG:
if (expr.IsConstExpr) {
return new ConstULong((UInt32)((ConstFloat)expr).Value, env);
}
return new TypeCast(TypeCastType.FLOAT_TO_INT32, expr, type);
case ExprTypeKind.DOUBLE:
if (expr.IsConstExpr) {
return new ConstDouble(((ConstFloat)expr).Value, env);
}
return new TypeCast(TypeCastType.FLOAT_TO_DOUBLE, expr, type);
default:
throw new InvalidProgramException();
}
case ExprTypeKind.DOUBLE:
switch (to) {
case ExprTypeKind.CHAR:
// double -> float -> char
if (expr.IsConstExpr) {
return new ConstLong((SByte)((ConstDouble)expr).Value, env);
}
return FloatToArith(FloatToArith(expr, new FloatType(type.IsConst, type.IsVolatile)), new CharType(type.IsConst, type.IsVolatile));
case ExprTypeKind.SHORT:
// double -> float -> short
if (expr.IsConstExpr) {
return new ConstLong((Int16)((ConstDouble)expr).Value, env);
}
return FloatToArith(FloatToArith(expr, new FloatType(type.IsConst, type.IsVolatile)), new ShortType(type.IsConst, type.IsVolatile));
case ExprTypeKind.LONG:
// double -> float -> short
if (expr.IsConstExpr) {
return new ConstLong((Int32)((ConstDouble)expr).Value, env);
}
return new TypeCast(TypeCastType.DOUBLE_TO_INT32, expr, type);
case ExprTypeKind.ULONG:
if (expr.IsConstExpr) {
return new ConstULong((UInt32)((ConstDouble)expr).Value, env);
}
return new TypeCast(TypeCastType.DOUBLE_TO_INT32, expr, type);
case ExprTypeKind.USHORT:
// double -> long -> ushort
if (expr.IsConstExpr) {
return new ConstULong((UInt16)((ConstDouble)expr).Value, env);
}
return new TypeCast(TypeCastType.PRESERVE_INT16, new TypeCast(TypeCastType.DOUBLE_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type);
case ExprTypeKind.FLOAT:
if (expr.IsConstExpr) {
return new ConstFloat((Single)((ConstDouble)expr).Value, env);
}
return new TypeCast(TypeCastType.DOUBLE_TO_FLOAT, expr, type);
default:
throw new InvalidProgramException();
}
default:
throw new InvalidProgramException();
}
}