Example #1
0
        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]);
                }
            }
        }
Example #2
0
        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]);
                }
            }
        }