Exemple #1
0
        private EXPR BindLiftedStandardBinOp(BinOpArgInfo info, BinOpFullSig bofs, ExpressionKind ek, EXPRFLAG flags)
        {
            Debug.Assert(bofs.Type1().IsNullableType() || bofs.Type2().IsNullableType());

            EXPR arg1 = info.arg1;
            EXPR arg2 = info.arg2;

            // We want to get the base types of the arguments and attempt to bind the non-lifted form of the
            // method so that we error report (ie divide by zero etc), and then we store in the resulting
            // binop that we have a lifted operator.

            EXPR pArgument1 = null;
            EXPR pArgument2 = null;
            EXPR nonLiftedArg1 = null;
            EXPR nonLiftedArg2 = null;
            EXPR nonLiftedResult = null;
            CType resultType = null;

            LiftArgument(arg1, bofs.Type1(), bofs.ConvertFirst(), out pArgument1, out nonLiftedArg1);
            LiftArgument(arg2, bofs.Type2(), bofs.ConvertSecond(), out pArgument2, out nonLiftedArg2);

            // Now call the non-lifted method to generate errors, and stash the result.
            if (!nonLiftedArg1.isNull() && !nonLiftedArg2.isNull())
            {
                // Only compute the method if theres no nulls. If there are, we'll special case it
                // later, since operations with a null operand are null.
                nonLiftedResult = bofs.pfn(ek, flags, nonLiftedArg1, nonLiftedArg2);
            }

            // Check if we have a comparison. If so, set the result type to bool.
            if (info.binopKind == BinOpKind.Compare || info.binopKind == BinOpKind.Equal)
            {
                resultType = GetReqPDT(PredefinedType.PT_BOOL);
            }
            else
            {
                if (bofs.fnkind == BinOpFuncKind.EnumBinOp)
                {
                    AggregateType enumType;
                    resultType = GetEnumBinOpType(ek, nonLiftedArg1.type, nonLiftedArg2.type, out enumType);
                }
                else
                {
                    resultType = pArgument1.type;
                }
                resultType = resultType.IsNullableType() ? resultType : GetSymbolLoader().GetTypeManager().GetNullable(resultType);
            }

            EXPRBINOP exprRes = GetExprFactory().CreateBinop(ek, resultType, pArgument1, pArgument2);
            mustCast(nonLiftedResult, resultType, 0);
            exprRes.isLifted = true;
            exprRes.flags |= flags;
            Debug.Assert((exprRes.flags & EXPRFLAG.EXF_LVALUE) == 0);

            return exprRes;
        }
Exemple #2
0
        protected EXPR BindStandardBinopCore(BinOpArgInfo info, BinOpFullSig bofs, ExpressionKind ek, EXPRFLAG flags)
        {
            if (bofs.pfn == null)
            {
                return BadOperatorTypesError(ek, info.arg1, info.arg2);
            }

            if (!bofs.isLifted() || !bofs.AutoLift())
            {
                EXPR expr1 = info.arg1;
                EXPR expr2 = info.arg2;
                if (bofs.ConvertOperandsBeforeBinding())
                {
                    expr1 = mustConvert(expr1, bofs.Type1());
                    expr2 = mustConvert(expr2, bofs.Type2());
                }
                if (bofs.fnkind == BinOpFuncKind.BoolBitwiseOp)
                {
                    return BindBoolBitwiseOp(ek, flags, expr1, expr2, bofs);
                }
                return bofs.pfn(ek, flags, expr1, expr2);
            }
            Debug.Assert(bofs.fnkind != BinOpFuncKind.BoolBitwiseOp);
            return BindLiftedStandardBinOp(info, bofs, ek, flags);
        }