protected virtual Expr VisitSTRINGEQ(ExprBinOp pExpr) { return(VisitBINOP(pExpr)); }
protected virtual Expr VisitDELEGATEEQ(ExprBinOp pExpr) { return(VisitBINOP(pExpr)); }
protected virtual Expr VisitSEQUENCE(ExprBinOp pExpr) { return(VisitBINOP(pExpr)); }
protected virtual Expr VisitINDIR(ExprBinOp pExpr) { return(VisitBINOP(pExpr)); }
protected virtual Expr VisitLSHIFT(ExprBinOp pExpr) { return(VisitBINOP(pExpr)); }
protected virtual Expr VisitLOGAND(ExprBinOp pExpr) { return(VisitBINOP(pExpr)); }
protected virtual Expr VisitCOMPARE(ExprBinOp pExpr) { return(VisitBINOP(pExpr)); }
protected virtual Expr VisitEQUALS(ExprBinOp pExpr) { return(VisitBINOP(pExpr)); }
protected virtual Expr VisitBINOP(ExprBinOp pExpr) { return(VisitEXPR(pExpr)); }
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 = ExprFactory.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); }
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 = TypeManager.GetNullable(typeL.UnderlyingEnumType); typeL = convertL; didEnumConversion = true; } else if (typeL is NullableType nubL && nubL.UnderlyingType.IsEnumType) { Debug.Assert(expr.IsLifted); convertL = TypeManager.GetNullable(nubL.UnderlyingType.UnderlyingEnumType); typeL = convertL; didEnumConversion = true; } if (typeR.IsEnumType) { Debug.Assert(expr.IsLifted); convertR = TypeManager.GetNullable(typeR.UnderlyingEnumType); typeR = convertR; didEnumConversion = true; } else if (typeR is NullableType nubR && nubR.UnderlyingType.IsEnumType) { Debug.Assert(expr.IsLifted); convertR = TypeManager.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); }