Ejemplo n.º 1
0
        private Expr GenerateUserDefinedBinaryOperator(ExprBinOp expr)
        {
            Debug.Assert(expr != null);
            PREDEFMETH pdm;

            switch (expr.Kind)
            {
            case ExpressionKind.LogicalOr: pdm = PREDEFMETH.PM_EXPRESSION_ORELSE_USER_DEFINED; break;

            case ExpressionKind.LogicalAnd: pdm = PREDEFMETH.PM_EXPRESSION_ANDALSO_USER_DEFINED; break;

            case ExpressionKind.LeftShirt: pdm = PREDEFMETH.PM_EXPRESSION_LEFTSHIFT_USER_DEFINED; break;

            case ExpressionKind.RightShift: pdm = PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT_USER_DEFINED; break;

            case ExpressionKind.BitwiseExclusiveOr: pdm = PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR_USER_DEFINED; break;

            case ExpressionKind.BitwiseOr: pdm = PREDEFMETH.PM_EXPRESSION_OR_USER_DEFINED; break;

            case ExpressionKind.BitwiseAnd: pdm = PREDEFMETH.PM_EXPRESSION_AND_USER_DEFINED; break;

            case ExpressionKind.Modulo: pdm = PREDEFMETH.PM_EXPRESSION_MODULO_USER_DEFINED; break;

            case ExpressionKind.Divide: pdm = PREDEFMETH.PM_EXPRESSION_DIVIDE_USER_DEFINED; break;

            case ExpressionKind.StringEq:
            case ExpressionKind.StringNotEq:
            case ExpressionKind.DelegateEq:
            case ExpressionKind.DelegateNotEq:
            case ExpressionKind.Eq:
            case ExpressionKind.NotEq:
            case ExpressionKind.GreaterThanOrEqual:
            case ExpressionKind.GreaterThan:
            case ExpressionKind.LessThanOrEqual:
            case ExpressionKind.LessThan:
                return(GenerateUserDefinedComparisonOperator(expr));

            case ExpressionKind.DelegateSubtract:
            case ExpressionKind.Subtract:
                pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED;
                break;

            case ExpressionKind.DelegateAdd:
            case ExpressionKind.Add:
                pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_ADDCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED;
                break;

            case ExpressionKind.Multiply:
                pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_MULTIPLY_USER_DEFINED;
                break;

            default:
                throw Error.InternalCompilerError();
            }
            Expr p1     = expr.OptionalLeftChild;
            Expr p2     = expr.OptionalRightChild;
            Expr udcall = expr.OptionalUserDefinedCall;

            if (udcall != null)
            {
                Debug.Assert(udcall.Kind == ExpressionKind.Call || udcall.Kind == ExpressionKind.UserLogicalOp);
                if (udcall is ExprCall ascall)
                {
                    ExprList args = (ExprList)ascall.OptionalArguments;
                    Debug.Assert(args.OptionalNextListNode.Kind != ExpressionKind.List);
                    p1 = args.OptionalElement;
                    p2 = args.OptionalNextListNode;
                }
                else
                {
                    ExprUserLogicalOp userLogOp = udcall as ExprUserLogicalOp;
                    Debug.Assert(userLogOp != null);
                    ExprList args = (ExprList)userLogOp.OperatorCall.OptionalArguments;
                    Debug.Assert(args.OptionalNextListNode.Kind != ExpressionKind.List);
                    p1 = ((ExprWrap)args.OptionalElement).OptionalExpression;
                    p2 = args.OptionalNextListNode;
                }
            }
            p1 = Visit(p1);
            p2 = Visit(p2);
            FixLiftedUserDefinedBinaryOperators(expr, ref p1, ref p2);
            Expr methodInfo = GetExprFactory().CreateMethodInfo(expr.UserDefinedCallMethod);
            Expr call       = GenerateCall(pdm, p1, p2, methodInfo);

            // Delegate add/subtract generates a call to Combine/Remove, which returns System.Delegate,
            // not the operand delegate CType.  We must cast to the delegate CType.
            if (expr.Kind == ExpressionKind.DelegateSubtract || expr.Kind == ExpressionKind.DelegateAdd)
            {
                Expr pTypeOf = CreateTypeOf(expr.Type);
                return(GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, call, pTypeOf));
            }
            return(call);
        }
Ejemplo n.º 2
0
        private Expr GenerateBuiltInBinaryOperator(ExprBinOp expr)
        {
            Debug.Assert(expr != null);
            PREDEFMETH pdm;

            switch (expr.Kind)
            {
            case ExpressionKind.LeftShirt: pdm = PREDEFMETH.PM_EXPRESSION_LEFTSHIFT; break;

            case ExpressionKind.RightShift: pdm = PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT; break;

            case ExpressionKind.BitwiseExclusiveOr: pdm = PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR; break;

            case ExpressionKind.BitwiseOr: pdm = PREDEFMETH.PM_EXPRESSION_OR; break;

            case ExpressionKind.BitwiseAnd: pdm = PREDEFMETH.PM_EXPRESSION_AND; break;

            case ExpressionKind.LogicalAnd: pdm = PREDEFMETH.PM_EXPRESSION_ANDALSO; break;

            case ExpressionKind.LogicalOr: pdm = PREDEFMETH.PM_EXPRESSION_ORELSE; break;

            case ExpressionKind.StringEq: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL; break;

            case ExpressionKind.Eq: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL; break;

            case ExpressionKind.StringNotEq: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL; break;

            case ExpressionKind.NotEq: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL; break;

            case ExpressionKind.GreaterThanOrEqual: pdm = PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL; break;

            case ExpressionKind.LessThanOrEqual: pdm = PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL; break;

            case ExpressionKind.LessThan: pdm = PREDEFMETH.PM_EXPRESSION_LESSTHAN; break;

            case ExpressionKind.GreaterThan: pdm = PREDEFMETH.PM_EXPRESSION_GREATERTHAN; break;

            case ExpressionKind.Modulo: pdm = PREDEFMETH.PM_EXPRESSION_MODULO; break;

            case ExpressionKind.Divide: pdm = PREDEFMETH.PM_EXPRESSION_DIVIDE; break;

            case ExpressionKind.Multiply:
                pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED : PREDEFMETH.PM_EXPRESSION_MULTIPLY;
                break;

            case ExpressionKind.Subtract:
                pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED : PREDEFMETH.PM_EXPRESSION_SUBTRACT;
                break;

            case ExpressionKind.Add:
                pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_ADDCHECKED : PREDEFMETH.PM_EXPRESSION_ADD;
                break;

            default:
                throw Error.InternalCompilerError();
            }
            Expr origL = expr.OptionalLeftChild;
            Expr origR = expr.OptionalRightChild;

            Debug.Assert(origL != null);
            Debug.Assert(origR != null);
            CType typeL = origL.Type;
            CType typeR = origR.Type;

            Expr newL = Visit(origL);
            Expr newR = Visit(origR);

            bool  didEnumConversion = false;
            CType convertL          = null;
            CType convertR          = null;

            if (typeL.isEnumType())
            {
                // We have already inserted casts if not lifted, so we should never see an enum.
                Debug.Assert(expr.IsLifted);
                convertL          = GetSymbolLoader().GetTypeManager().GetNullable(typeL.underlyingEnumType());
                typeL             = convertL;
                didEnumConversion = true;
            }
            else if (typeL is NullableType nubL && nubL.UnderlyingType.isEnumType())
            {
                Debug.Assert(expr.IsLifted);
                convertL          = GetSymbolLoader().GetTypeManager().GetNullable(nubL.UnderlyingType.underlyingEnumType());
                typeL             = convertL;
                didEnumConversion = true;
            }
            if (typeR.isEnumType())
            {
                Debug.Assert(expr.IsLifted);
                convertR          = GetSymbolLoader().GetTypeManager().GetNullable(typeR.underlyingEnumType());
                typeR             = convertR;
                didEnumConversion = true;
            }
            else if (typeR is NullableType nubR && nubR.UnderlyingType.isEnumType())
            {
                Debug.Assert(expr.IsLifted);
                convertR          = GetSymbolLoader().GetTypeManager().GetNullable(nubR.UnderlyingType.underlyingEnumType());
                typeR             = convertR;
                didEnumConversion = true;
            }
            if (typeL is NullableType nubL2 && nubL2.UnderlyingType == typeR)
            {
                convertR = typeL;
            }
            if (typeR is NullableType nubR2 && nubR2.UnderlyingType == typeL)
            {
                convertL = typeR;
            }

            if (convertL != null)
            {
                newL = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, newL, CreateTypeOf(convertL));
            }
            if (convertR != null)
            {
                newR = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, newR, CreateTypeOf(convertR));
            }

            Expr call = GenerateCall(pdm, newL, newR);

            if (didEnumConversion && expr.Type.StripNubs().isEnumType())
            {
                call = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, call, CreateTypeOf(expr.Type));
            }

            return(call);
        }