static BinaryOperatorEasyOut() { const OperandType ERR = OperandType.Error; const OperandType OBJ = OperandType.Object; const OperandType INT = OperandType.Int; const OperandType UIN = OperandType.UInt; const OperandType LNG = OperandType.Long; const OperandType ULG = OperandType.ULong; const OperandType FLT = OperandType.Float; const OperandType DBL = OperandType.Double; const OperandType DEC = OperandType.Decimal; const OperandType BOL = OperandType.Bool; // Overload resolution for Y * / - % < > <= >= X OperandType[,] arithmetic = { // bool chr i08 i16 i32 i64 u08 u16 u32 u64 r32 r64 dec /* bool */ { ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR }, /* chr */ { ERR, INT, INT, INT, INT, LNG, INT, INT, UIN, ULG, FLT, DBL, DEC }, /* i08 */ { ERR, INT, INT, INT, INT, LNG, INT, INT, LNG, ERR, FLT, DBL, DEC }, /* i16 */ { ERR, INT, INT, INT, INT, LNG, INT, INT, LNG, ERR, FLT, DBL, DEC }, /* i32 */ { ERR, INT, INT, INT, INT, LNG, INT, INT, LNG, ERR, FLT, DBL, DEC }, /* i64 */ { ERR, LNG, LNG, LNG, LNG, LNG, LNG, LNG, LNG, ERR, FLT, DBL, DEC }, /* u08 */ { ERR, INT, INT, INT, INT, LNG, INT, INT, UIN, ULG, FLT, DBL, DEC }, /* u16 */ { ERR, INT, INT, INT, INT, LNG, INT, INT, UIN, ULG, FLT, DBL, DEC }, /* u32 */ { ERR, UIN, LNG, LNG, LNG, LNG, UIN, UIN, UIN, ULG, FLT, DBL, DEC }, /* u64 */ { ERR, ULG, ERR, ERR, ERR, ERR, ULG, ULG, ULG, ULG, FLT, DBL, DEC }, /* r32 */ { ERR, FLT, FLT, FLT, FLT, FLT, FLT, FLT, FLT, FLT, FLT, DBL, ERR }, /* r64 */ { ERR, DBL, DBL, DBL, DBL, DBL, DBL, DBL, DBL, DBL, DBL, DBL, ERR }, /* dec */ { ERR, DEC, DEC, DEC, DEC, DEC, DEC, DEC, DEC, DEC, ERR, ERR, DEC }, }; // Overload resolution for Y + X OperandType[,] addition = { // bool chr i08 i16 i32 i64 u08 u16 u32 u64 r32 r64 dec /* bool */ { ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR }, /* chr */ { ERR, INT, INT, INT, INT, LNG, INT, INT, UIN, ULG, FLT, DBL, DEC }, /* i08 */ { ERR, INT, INT, INT, INT, LNG, INT, INT, LNG, ERR, FLT, DBL, DEC }, /* i16 */ { ERR, INT, INT, INT, INT, LNG, INT, INT, LNG, ERR, FLT, DBL, DEC }, /* i32 */ { ERR, INT, INT, INT, INT, LNG, INT, INT, LNG, ERR, FLT, DBL, DEC }, /* i64 */ { ERR, LNG, LNG, LNG, LNG, LNG, LNG, LNG, LNG, ERR, FLT, DBL, DEC }, /* u08 */ { ERR, INT, INT, INT, INT, LNG, INT, INT, UIN, ULG, FLT, DBL, DEC }, /* u16 */ { ERR, INT, INT, INT, INT, LNG, INT, INT, UIN, ULG, FLT, DBL, DEC }, /* u32 */ { ERR, UIN, LNG, LNG, LNG, LNG, UIN, UIN, UIN, ULG, FLT, DBL, DEC }, /* u64 */ { ERR, ULG, ERR, ERR, ERR, ERR, ULG, ULG, ULG, ULG, FLT, DBL, DEC }, /* r32 */ { ERR, FLT, FLT, FLT, FLT, FLT, FLT, FLT, FLT, FLT, FLT, DBL, ERR }, /* r64 */ { ERR, DBL, DBL, DBL, DBL, DBL, DBL, DBL, DBL, DBL, DBL, DBL, ERR }, /* dec */ { ERR, DEC, DEC, DEC, DEC, DEC, DEC, DEC, DEC, DEC, ERR, ERR, DEC }, }; // Overload resolution for Y << >> X OperandType[,] shift = { // bool chr i08 i16 i32 i64 u08 u16 u32 u64 r32 r64 dec /* bool */ { ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR }, /* chr */ { ERR, INT, INT, INT, INT, ERR, INT, INT, ERR, ERR, ERR, ERR, ERR }, /* i08 */ { ERR, INT, INT, INT, INT, ERR, INT, INT, ERR, ERR, ERR, ERR, ERR }, /* i16 */ { ERR, INT, INT, INT, INT, ERR, INT, INT, ERR, ERR, ERR, ERR, ERR }, /* i32 */ { ERR, INT, INT, INT, INT, ERR, INT, INT, ERR, ERR, ERR, ERR, ERR }, /* i64 */ { ERR, LNG, LNG, LNG, LNG, ERR, LNG, LNG, ERR, ERR, ERR, ERR, ERR }, /* u08 */ { ERR, INT, INT, INT, INT, ERR, INT, INT, ERR, ERR, ERR, ERR, ERR }, /* u16 */ { ERR, INT, INT, INT, INT, ERR, INT, INT, ERR, ERR, ERR, ERR, ERR }, /* u32 */ { ERR, UIN, UIN, UIN, UIN, ERR, UIN, UIN, ERR, ERR, ERR, ERR, ERR }, /* u64 */ { ERR, ULG, ULG, ULG, ULG, ERR, ULG, ULG, ERR, ERR, ERR, ERR, ERR }, /* r32 */ { ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR }, /* r64 */ { ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR }, /* dec */ { ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR }, }; // Overload resolution for Y == != X // Note that these are the overload resolution rules; overload resolution might pick an invalid operator. // For example, overload resolution on object == decimal chooses the object/object overload, which then // is not legal because decimal must be a reference type. But we don't know to give that error *until* // overload resolution has chosen the reference equality operator. OperandType[,] equality = { // bool chr i08 i16 i32 i64 u08 u16 u32 u64 r32 r64 dec /* bool */ { BOL, OBJ, OBJ, OBJ, OBJ, OBJ, OBJ, OBJ, OBJ, OBJ, OBJ, OBJ, OBJ }, /* chr */ { OBJ, INT, INT, INT, INT, LNG, INT, INT, UIN, ULG, FLT, DBL, DEC }, /* i08 */ { OBJ, INT, INT, INT, INT, LNG, INT, INT, LNG, ERR, FLT, DBL, DEC }, /* i16 */ { OBJ, INT, INT, INT, INT, LNG, INT, INT, LNG, ERR, FLT, DBL, DEC }, /* i32 */ { OBJ, INT, INT, INT, INT, LNG, INT, INT, LNG, ERR, FLT, DBL, DEC }, /* i64 */ { OBJ, LNG, LNG, LNG, LNG, LNG, LNG, LNG, LNG, ERR, FLT, DBL, DEC }, /* u08 */ { OBJ, INT, INT, INT, INT, LNG, INT, INT, UIN, ULG, FLT, DBL, DEC }, /* u16 */ { OBJ, INT, INT, INT, INT, LNG, INT, INT, UIN, ULG, FLT, DBL, DEC }, /* u32 */ { OBJ, UIN, LNG, LNG, LNG, LNG, UIN, UIN, UIN, ULG, FLT, DBL, DEC }, /* u64 */ { OBJ, ULG, ERR, ERR, ERR, ERR, ULG, ULG, ULG, ULG, FLT, DBL, DEC }, /* r32 */ { OBJ, FLT, FLT, FLT, FLT, FLT, FLT, FLT, FLT, FLT, FLT, DBL, OBJ }, /* r64 */ { OBJ, DBL, DBL, DBL, DBL, DBL, DBL, DBL, DBL, DBL, DBL, DBL, OBJ }, /* dec */ { OBJ, DEC, DEC, DEC, DEC, DEC, DEC, DEC, DEC, DEC, OBJ, OBJ, DEC }, }; // Overload resolution for Y | & ^ || && X OperandType[,] logical = { // bool chr i08 i16 i32 i64 u08 u16 u32 u64 r32 r64 dec /* bool */ { BOL, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR }, /* chr */ { ERR, INT, INT, INT, INT, LNG, INT, INT, UIN, ULG, ERR, ERR, ERR }, /* i08 */ { ERR, INT, INT, INT, INT, LNG, INT, INT, LNG, ERR, ERR, ERR, ERR }, /* i16 */ { ERR, INT, INT, INT, INT, LNG, INT, INT, LNG, ERR, ERR, ERR, ERR }, /* i32 */ { ERR, INT, INT, INT, INT, LNG, INT, INT, LNG, ERR, ERR, ERR, ERR }, /* i64 */ { ERR, LNG, LNG, LNG, LNG, LNG, LNG, LNG, LNG, ERR, ERR, ERR, ERR }, /* u08 */ { ERR, INT, INT, INT, INT, LNG, INT, INT, UIN, ULG, ERR, ERR, ERR }, /* u16 */ { ERR, INT, INT, INT, INT, LNG, INT, INT, UIN, ULG, ERR, ERR, ERR }, /* u32 */ { ERR, UIN, LNG, LNG, LNG, LNG, UIN, UIN, UIN, ULG, ERR, ERR, ERR }, /* u64 */ { ERR, ULG, ERR, ERR, ERR, ERR, ULG, ULG, ULG, ULG, ERR, ERR, ERR }, /* r32 */ { ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR }, /* r64 */ { ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR }, /* dec */ { ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR }, }; var ops = (BinaryOperatorKind[])Enum.GetValues(typeof(BinaryOperatorKind)); s_binOp = new BinaryOperatorSymbol[ops.Length][, ]; s_binOp[(int)BinaryOperatorKind.Error] = new BinaryOperatorSymbol[28, 28]; for (int i = 0; i < 28; i++) { for (int j = 0; j < 28; j++) { s_binOp[(int)BinaryOperatorKind.Error][i, j] = BinaryOperatorSymbol.Create(BinaryOperatorKind.Error, OperandType.Error); } } for (int i = ((int)BinaryOperatorKind.Error) + 1; i < ops.Length; i++) { s_binOp[i] = s_binOp[(int)BinaryOperatorKind.Error]; } Func <BinaryOperatorKind, OperandType[, ], BinaryOperatorSymbol[, ]> expandTable = (k, x) => { var res = new BinaryOperatorSymbol[28, 28]; for (int i = 0; i < 13; i++) { for (int j = 0; j < 13; j++) { var t = x[i, j]; var nt = OperandTypeHelper.IsNullable(t + OperandTypeHelper.NullableDelta) ? t + OperandTypeHelper.NullableDelta : t; res[i + 2, j + 2] = BinaryOperatorSymbol.Create(k, t); res[i + 2 + 13, j + 2] = BinaryOperatorSymbol.Create(k, nt); res[i + 2, j + 2 + 13] = BinaryOperatorSymbol.Create(k, nt); res[i + 2 + 13, j + 2 + 13] = BinaryOperatorSymbol.Create(k, nt); } } bool eq = k == BinaryOperatorKind.Equal || k == BinaryOperatorKind.NotEqual || k == BinaryOperatorKind.ExactEqual; bool add = k == BinaryOperatorKind.Addition; var op_o = eq ? BinaryOperatorSymbol.Create(k, OperandType.Object) : BinaryOperatorSymbol.Create(BinaryOperatorKind.Error, OperandType.Error); var op_ss = (eq || add) ? BinaryOperatorSymbol.Create(k, OperandType.String) : op_o; var op_so = (eq || add) ? BinaryOperatorSymbol.Create(k, OperandType.StringAndObject) : op_o; var op_os = (eq || add) ? BinaryOperatorSymbol.Create(k, OperandType.ObjectAndString) : op_o; for (int i = 0; i < 28; i++) { if (i == 1) { // str res[1, 1] = op_ss; } else { // obj res[0, i] = op_o; res[i, 0] = op_o; // str res[1, i] = op_so; res[i, 1] = op_os; } } return(res); }; var tables = new[] { arithmetic, addition, shift, equality, logical }; Func <BinaryOperatorKind, int> tableIndex = k => { if (k == BinaryOperatorKind.Multiplication || k == BinaryOperatorKind.Subtraction || k == BinaryOperatorKind.Division || k == BinaryOperatorKind.Remainder || k == BinaryOperatorKind.Exponent) { return(0); } if (k == BinaryOperatorKind.Addition) { return(1); } if (k == BinaryOperatorKind.LeftShift || k == BinaryOperatorKind.RightShift) { return(2); } if (k == BinaryOperatorKind.Equal || k == BinaryOperatorKind.NotEqual || k == BinaryOperatorKind.ExactEqual) { return(3); } if (k == BinaryOperatorKind.GreaterThan || k == BinaryOperatorKind.LessThan || k == BinaryOperatorKind.GreaterThanOrEqual || k == BinaryOperatorKind.LessThanOrEqual || k == BinaryOperatorKind.And || k == BinaryOperatorKind.Xor || k == BinaryOperatorKind.Or) { return(4); } if (k == BinaryOperatorKind.Substr || k == BinaryOperatorKind.DefaultValue) { return(-1); } return(-1); }; for (int i = ((int)BinaryOperatorKind.Error) + 1; i < ops.Length; i++) { var k = (BinaryOperatorKind)i; var ti = tableIndex(k); if (ti >= 0) { s_binOp[i] = expandTable(k, tables[ti]); } } }
static UnaryOperatorEasyOut() { const OperandType ERR = OperandType.Error; const OperandType BOL = OperandType.Bool; const OperandType CHR = OperandType.Char; const OperandType I08 = OperandType.SByte; const OperandType U08 = OperandType.Byte; const OperandType I16 = OperandType.Short; const OperandType U16 = OperandType.UShort; const OperandType I32 = OperandType.Int; const OperandType U32 = OperandType.UInt; const OperandType I64 = OperandType.Long; const OperandType U64 = OperandType.ULong; const OperandType R32 = OperandType.Float; const OperandType R64 = OperandType.Double; const OperandType DEC = OperandType.Decimal; OperandType[] increment = //bool chr i08 i16 i32 i64 u08 u16 u32 u64 r32 r64 dec { ERR, CHR, I08, I16, I32, I64, U08, U16, U32, U64, R32, R64, DEC }; OperandType[] plus = //bool chr i08 i16 i32 i64 u08 u16 u32 u64 r32 r64 dec { ERR, I32, I32, I32, I32, I64, I32, I32, U32, U64, R32, R64, DEC }; OperandType[] minus = //bool chr i08 i16 i32 i64 u08 u16 u32 u64 r32 r64 dec { ERR, I32, I32, I32, I32, I64, I32, I32, I64, ERR, R32, R64, DEC }; OperandType[] logicalNegation = //bool chr i08 i16 i32 i64 u08 u16 u32 u64 r32 r64 dec { BOL, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR }; OperandType[] bitwiseComplement = //bool chr i08 i16 i32 i64 u08 u16 u32 u64 r32 r64 dec { ERR, I32, I32, I32, I32, I64, I32, I32, U32, U64, ERR, ERR, ERR }; var ops = (UnaryOperatorKind[])Enum.GetValues(typeof(UnaryOperatorKind)); s_unOp = new UnaryOperatorSymbol[ops.Length][]; s_unOp[(int)UnaryOperatorKind.Error] = new UnaryOperatorSymbol[28]; for (int i = 0; i < 28; i++) { s_unOp[(int)UnaryOperatorKind.Error][i] = UnaryOperatorSymbol.Create(UnaryOperatorKind.Error, OperandType.Error); } for (int i = ((int)UnaryOperatorKind.Error) + 1; i < ops.Length; i++) { s_unOp[i] = s_unOp[(int)UnaryOperatorKind.Error]; } Func <UnaryOperatorKind, OperandType[], UnaryOperatorSymbol[]> expandTable = (k, x) => { var res = new UnaryOperatorSymbol[28]; for (int i = 0; i < 13; i++) { var t = x[i]; var nt = OperandTypeHelper.IsNullable(t + OperandTypeHelper.NullableDelta) ? t + OperandTypeHelper.NullableDelta : t; res[i + 2] = UnaryOperatorSymbol.Create(k, t); res[i + 2 + 13] = UnaryOperatorSymbol.Create(k, nt); } return(res); }; var tables = new[] { increment, plus, minus, logicalNegation, bitwiseComplement }; Func <UnaryOperatorKind, int> tableIndex = k => { if (k == UnaryOperatorKind.Increment || k == UnaryOperatorKind.Decrement) { return(0); } if (k == UnaryOperatorKind.UnaryPlus) { return(1); } if (k == UnaryOperatorKind.UnaryMinus) { return(2); } if (k == UnaryOperatorKind.LogicalNegation) { return(3); } if (k == UnaryOperatorKind.BitwiseComplement) { return(4); } return(-1); }; for (int i = ((int)UnaryOperatorKind.Error) + 1; i < ops.Length; i++) { var k = (UnaryOperatorKind)i; var ti = tableIndex(k); if (ti >= 0) { s_unOp[i] = expandTable(k, tables[ti]); } } }