public static Expr ToPointer(Expr expr, ExprType type, Env env) {
ExprTypeKind from = expr.Type.Kind;
ExprTypeKind to = type.Kind;
if (to != ExprTypeKind.POINTER) {
throw new InvalidOperationException("Error: expected casting to pointer.");
}
if (from == ExprTypeKind.POINTER) {
if (expr.IsConstExpr) {
return new ConstPtr(((ConstPtr)expr).Value, type, env);
}
return new TypeCast(TypeCastType.NOP, expr, type, env);
}
if (expr.Type.IsIntegral) {
// if we are casting from an integral
// whatever integral -> ulong
switch (expr.Type.Kind) {
case ExprTypeKind.CHAR:
case ExprTypeKind.SHORT:
case ExprTypeKind.LONG:
expr = SignedIntegralToArith(expr, new ULongType(type.IsConst, type.IsVolatile));
break;
case ExprTypeKind.UCHAR:
case ExprTypeKind.USHORT:
case ExprTypeKind.ULONG:
expr = UnsignedIntegralToArith(expr, new ULongType(type.IsConst, type.IsVolatile));
break;
default:
break;
}
// ulong -> pointer
if (expr.IsConstExpr) {
return new ConstPtr(((ConstULong)expr).Value, type, env);
}
return new TypeCast(TypeCastType.NOP, expr, type, env);
}
if (expr.Type is FunctionType) {
if (!expr.Type.EqualType(((PointerType)type).RefType)) {
throw new InvalidOperationException("Casting from an incompatible function.");
}
// TODO: only allow compatible Type?
return new TypeCast(TypeCastType.NOP, expr, type, env);
}
if (expr.Type is ArrayType) {
// TODO: allow any pointer Type to cast to?
return new TypeCast(TypeCastType.NOP, expr, type, env);
}
throw new InvalidOperationException("Error: casting from an unsupported Type to pointer.");
}