internal static Type ToSysType(ExprTypeKind kind) { switch (kind) { case ExprTypeKind.BL: return(typeof(BL)); case ExprTypeKind.I4: return(typeof(I4)); case ExprTypeKind.I8: return(typeof(I8)); case ExprTypeKind.R4: return(typeof(R4)); case ExprTypeKind.R8: return(typeof(R8)); case ExprTypeKind.TX: return(typeof(TX)); default: return(null); } }
public void Convert(ExprTypeKind kind) { Contracts.Assert(HasType); if (kind == ExprType) { return; } Contracts.Assert(SrcKind == ExprType); switch (kind) { case ExprTypeKind.I8: Contracts.Assert(ExprType == ExprTypeKind.I4); if (ExprValue != null) { Contracts.Assert(ExprValue is I4); ExprValue = (I8)(I4)ExprValue; } break; case ExprTypeKind.R4: Contracts.Assert(ExprType == ExprTypeKind.I4); if (ExprValue != null) { Contracts.Assert(ExprValue is I4); ExprValue = (R4)(I4)ExprValue; } break; case ExprTypeKind.R8: Contracts.Assert(ExprType == ExprTypeKind.I4 || ExprType == ExprTypeKind.I8 || ExprType == ExprTypeKind.R4); if (ExprValue != null) { if (ExprType == ExprTypeKind.I4) { Contracts.Assert(ExprValue is I4); ExprValue = (R8)(I4)ExprValue; } else if (ExprType == ExprTypeKind.I8) { Contracts.Assert(ExprValue is I8); ExprValue = (R8)(I8)ExprValue; } else { Contracts.Assert(ExprValue is R4); ExprValue = (R8)(R4)ExprValue; } } break; } // Set the new type. ExprType = kind; }
public void SetType(ExprTypeKind kind) { Contracts.Assert(kind != 0); Contracts.Assert(ExprValue == null); Contracts.Assert(ExprType == 0 || ExprType == kind); Contracts.Assert(SrcKind == ExprType); ExprType = kind; SrcKind = kind; }
public void SetType(ExprTypeKind kind, object value) { Contracts.Assert(kind != 0); Contracts.Assert(value == null || value.GetType() == ToSysType(kind)); Contracts.Assert(ExprValue == null); Contracts.Assert(ExprType == 0 || ExprType == kind); Contracts.Assert(SrcKind == ExprType); ExprType = kind; SrcKind = kind; ExprValue = value; }
public ParamNode(Token tok, string name, int index, DataViewType type) : base(tok) { Contracts.AssertNonEmpty(name); Contracts.Assert(index >= 0); Contracts.AssertValueOrNull(type); Name = name; Index = index; Type = type; if (type == null) { ExprType = ExprTypeKind.Error; } else if (type is TextDataViewType) { ExprType = ExprTypeKind.TX; } else if (type is BooleanDataViewType) { ExprType = ExprTypeKind.BL; } else if (type == NumberDataViewType.Int32) { ExprType = ExprTypeKind.I4; } else if (type == NumberDataViewType.Int64) { ExprType = ExprTypeKind.I8; } else if (type == NumberDataViewType.Single) { ExprType = ExprTypeKind.R4; } else if (type == NumberDataViewType.Double) { ExprType = ExprTypeKind.R8; } }
/// <summary> /// From: /// pointer /// To: /// pointer, integral /// </summary> public static Expr FromPointer(Expr expr, ExprType type, Env env) { ExprTypeKind from = expr.Type.Kind; ExprTypeKind to = type.Kind; if (from != ExprTypeKind.POINTER) { throw new InvalidOperationException("Expected a pointer."); } // if we are casting to another pointer, do a nop if (to == ExprTypeKind.POINTER) { if (expr.IsConstExpr) { return(new ConstPtr(((ConstPtr)expr).Value, type, env)); } return(new TypeCast(TypeCastType.NOP, expr, type, env)); } // if we are casting to an integral if (type.IsIntegral) { // pointer -> ulong -> whatever integral if (expr.IsConstExpr) { expr = new ConstULong(((ConstPtr)expr).Value, env); } else { expr = new TypeCast(TypeCastType.NOP, expr, new ULongType(type.IsConst, type.IsVolatile), env); } return(MakeCast(expr, type, env)); } throw new InvalidOperationException("Casting from a pointer to an unsupported Type."); }
private bool IsSimple(ExprTypeKind kind) { Contracts.Assert(ExprType != 0); return(ExprType == kind); }
/// <summary> /// From: /// char, short, long /// To: /// char, uchar, short, ushort, long, ulong, float double /// </summary> public static Expr SignedIntegralToArith(Expr expr, ExprType type) { ExprTypeKind from = expr.Type.Kind; ExprTypeKind to = type.Kind; Env env = expr.Env; switch (from) { case ExprTypeKind.CHAR: switch (to) { case ExprTypeKind.SHORT: case ExprTypeKind.USHORT: return(new TypeCast(TypeCastType.INT8_TO_INT16, expr, type)); case ExprTypeKind.LONG: case ExprTypeKind.ULONG: return(new TypeCast(TypeCastType.INT8_TO_INT32, expr, type)); case ExprTypeKind.UCHAR: return(new TypeCast(TypeCastType.NOP, expr, type)); case ExprTypeKind.FLOAT: // char -> long -> float return(new TypeCast(TypeCastType.INT32_TO_FLOAT, new TypeCast(TypeCastType.INT8_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type)); case ExprTypeKind.DOUBLE: // char -> long -> double return(new TypeCast(TypeCastType.INT32_TO_DOUBLE, new TypeCast(TypeCastType.INT8_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type)); case ExprTypeKind.VOID: case ExprTypeKind.POINTER: case ExprTypeKind.FUNCTION: case ExprTypeKind.ARRAY: case ExprTypeKind.INCOMPLETE_ARRAY: case ExprTypeKind.STRUCT_OR_UNION: case ExprTypeKind.CHAR: default: throw new InvalidProgramException($"Cannot cast from {from} to {to}"); } case ExprTypeKind.SHORT: switch (to) { case ExprTypeKind.CHAR: case ExprTypeKind.UCHAR: return(new TypeCast(TypeCastType.PRESERVE_INT8, expr, type)); case ExprTypeKind.USHORT: return(new TypeCast(TypeCastType.NOP, expr, type)); case ExprTypeKind.LONG: case ExprTypeKind.ULONG: return(new TypeCast(TypeCastType.INT16_TO_INT32, expr, type)); case ExprTypeKind.FLOAT: // short -> long -> float return(new TypeCast(TypeCastType.INT32_TO_FLOAT, new TypeCast(TypeCastType.INT16_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type)); case ExprTypeKind.DOUBLE: // short -> long -> double return(new TypeCast(TypeCastType.INT32_TO_DOUBLE, new TypeCast(TypeCastType.INT16_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type)); case ExprTypeKind.VOID: case ExprTypeKind.SHORT: case ExprTypeKind.POINTER: case ExprTypeKind.FUNCTION: case ExprTypeKind.ARRAY: case ExprTypeKind.INCOMPLETE_ARRAY: case ExprTypeKind.STRUCT_OR_UNION: default: throw new InvalidProgramException($"Cannot cast from {from} to {to}"); } case ExprTypeKind.LONG: switch (to) { case ExprTypeKind.CHAR: if (expr.IsConstExpr) { return(new ConstChar((SByte)((ConstLong)expr).Value, env)); } return(new TypeCast(TypeCastType.PRESERVE_INT8, expr, type)); case ExprTypeKind.UCHAR: if (expr.IsConstExpr) { return(new ConstUChar((Byte)((ConstLong)expr).Value, env)); } return(new TypeCast(TypeCastType.PRESERVE_INT8, expr, type)); case ExprTypeKind.SHORT: if (expr.IsConstExpr) { return(new ConstShort((Int16)((ConstLong)expr).Value, env)); } return(new TypeCast(TypeCastType.PRESERVE_INT16, expr, type)); case ExprTypeKind.USHORT: if (expr.IsConstExpr) { return(new ConstUShort((UInt16)((ConstLong)expr).Value, env)); } return(new TypeCast(TypeCastType.PRESERVE_INT16, expr, type)); case ExprTypeKind.ULONG: if (expr.IsConstExpr) { return(new ConstULong((UInt32)((ConstLong)expr).Value, env)); } return(new TypeCast(TypeCastType.NOP, expr, type)); case ExprTypeKind.FLOAT: if (expr.IsConstExpr) { return(new ConstFloat(((ConstLong)expr).Value, env)); } return(new TypeCast(TypeCastType.INT32_TO_FLOAT, expr, type)); case ExprTypeKind.DOUBLE: if (expr.IsConstExpr) { return(new ConstDouble(((ConstLong)expr).Value, env)); } return(new TypeCast(TypeCastType.INT32_TO_DOUBLE, expr, type)); case ExprTypeKind.VOID: case ExprTypeKind.LONG: case ExprTypeKind.POINTER: case ExprTypeKind.FUNCTION: case ExprTypeKind.ARRAY: case ExprTypeKind.INCOMPLETE_ARRAY: case ExprTypeKind.STRUCT_OR_UNION: default: throw new InvalidProgramException($"Cannot cast from {from} to {to}"); } default: throw new InvalidProgramException(); } }
/// <summary> /// From: /// pointer, integral /// To: /// pointer /// </summary> 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."); }
/// <summary> /// From: /// float, double /// To: /// char, uchar, short, ushort, long, ulong, float, double /// </summary> /// <remarks> /// According to MSDN "Conversions from Floating-Point Types", /// float cannot convert to unsigned char. /// I don't know why, but I follow it. /// </remarks> 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(); } }
/// <summary> /// From: /// uchar, ushort, ulong /// To: /// char, uchar, short, ushort, long, ulong, float, double /// </summary> /// <remarks> /// Aaccording to MSDN "Conversions from Unsigned Integral Types", /// unsigned long converts directly to double. /// However, I just treat unsigned long as long. /// </remarks> public static Expr UnsignedIntegralToArith(Expr expr, ExprType type) { ExprTypeKind from = expr.Type.Kind; ExprTypeKind to = type.Kind; Env env = expr.Env; switch (from) { case ExprTypeKind.UCHAR: switch (to) { case ExprTypeKind.CHAR: return(new TypeCast(TypeCastType.NOP, expr, type)); case ExprTypeKind.SHORT: case ExprTypeKind.USHORT: return(new TypeCast(TypeCastType.UINT8_TO_UINT16, expr, type)); case ExprTypeKind.LONG: case ExprTypeKind.ULONG: return(new TypeCast(TypeCastType.UINT8_TO_UINT32, expr, type)); case ExprTypeKind.FLOAT: // uchar -> ulong -> long -> float return(new TypeCast(TypeCastType.INT32_TO_FLOAT, new TypeCast(TypeCastType.UINT8_TO_UINT32, expr, new LongType(type.IsConst, type.IsVolatile)), type)); case ExprTypeKind.DOUBLE: // uchar -> ulong -> long -> double return(new TypeCast(TypeCastType.INT32_TO_DOUBLE, new TypeCast(TypeCastType.UINT8_TO_UINT32, expr, new LongType(type.IsConst, type.IsVolatile)), type)); default: Debug.Assert(false); return(null); } case ExprTypeKind.USHORT: switch (to) { case ExprTypeKind.CHAR: case ExprTypeKind.UCHAR: return(new TypeCast(TypeCastType.PRESERVE_INT8, expr, type)); case ExprTypeKind.USHORT: return(new TypeCast(TypeCastType.NOP, expr, type)); case ExprTypeKind.LONG: case ExprTypeKind.ULONG: return(new TypeCast(TypeCastType.UINT16_TO_UINT32, expr, type)); case ExprTypeKind.FLOAT: // ushort -> ulong -> long -> float return(new TypeCast(TypeCastType.INT32_TO_FLOAT, new TypeCast(TypeCastType.UINT16_TO_UINT32, expr, new LongType(type.IsConst, type.IsVolatile)), type)); case ExprTypeKind.DOUBLE: // ushort -> ulong -> long -> double return(new TypeCast(TypeCastType.INT32_TO_DOUBLE, new TypeCast(TypeCastType.UINT16_TO_UINT32, expr, new LongType(type.IsConst, type.IsVolatile)), type)); default: Debug.Assert(false); return(null); } case ExprTypeKind.ULONG: switch (to) { case ExprTypeKind.CHAR: if (expr.IsConstExpr) { return(new ConstLong((SByte)((ConstULong)expr).Value, env)); } return(new TypeCast(TypeCastType.PRESERVE_INT8, expr, type)); case ExprTypeKind.UCHAR: if (expr.IsConstExpr) { return(new ConstULong((Byte)((ConstULong)expr).Value, env)); } return(new TypeCast(TypeCastType.PRESERVE_INT8, expr, type)); case ExprTypeKind.SHORT: if (expr.IsConstExpr) { return(new ConstLong((Int16)((ConstULong)expr).Value, env)); } return(new TypeCast(TypeCastType.PRESERVE_INT16, expr, type)); case ExprTypeKind.USHORT: if (expr.IsConstExpr) { return(new ConstULong((UInt16)((ConstULong)expr).Value, env)); } return(new TypeCast(TypeCastType.PRESERVE_INT16, expr, type)); case ExprTypeKind.LONG: if (expr.IsConstExpr) { return(new ConstLong((Int32)((ConstULong)expr).Value, env)); } return(new TypeCast(TypeCastType.NOP, expr, type)); case ExprTypeKind.FLOAT: if (expr.IsConstExpr) { return(new ConstFloat(((ConstULong)expr).Value, env)); } return(new TypeCast(TypeCastType.INT32_TO_FLOAT, expr, type)); case ExprTypeKind.DOUBLE: if (expr.IsConstExpr) { return(new ConstDouble(((ConstULong)expr).Value, env)); } return(new TypeCast(TypeCastType.INT32_TO_DOUBLE, expr, type)); default: Debug.Assert(false); return(null); } default: Debug.Assert(false); return(null); } }