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; }
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); }