protected virtual EXPR GenerateUserDefinedComparisonOperator(EXPRBINOP expr) { Debug.Assert(expr != null); Debug.Assert(alwaysRewrite || currentAnonMeth != null); PREDEFMETH pdm; switch (expr.kind) { case ExpressionKind.EK_STRINGEQ: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED; break; case ExpressionKind.EK_STRINGNE: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED; break; case ExpressionKind.EK_DELEGATEEQ: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED; break; case ExpressionKind.EK_DELEGATENE: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED; break; case ExpressionKind.EK_EQ: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED; break; case ExpressionKind.EK_NE: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED; break; case ExpressionKind.EK_LE: pdm = PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL_USER_DEFINED; break; case ExpressionKind.EK_LT: pdm = PREDEFMETH.PM_EXPRESSION_LESSTHAN_USER_DEFINED; break; case ExpressionKind.EK_GE: pdm = PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL_USER_DEFINED; break; case ExpressionKind.EK_GT: pdm = PREDEFMETH.PM_EXPRESSION_GREATERTHAN_USER_DEFINED; break; default: throw Error.InternalCompilerError(); } EXPR p1 = expr.GetOptionalLeftChild(); EXPR p2 = expr.GetOptionalRightChild(); if (expr.GetOptionalUserDefinedCall() != null) { EXPRCALL udcall = expr.GetOptionalUserDefinedCall().asCALL(); EXPRLIST args = udcall.GetOptionalArguments().asLIST(); Debug.Assert(args.GetOptionalNextListNode().kind != ExpressionKind.EK_LIST); p1 = args.GetOptionalElement(); p2 = args.GetOptionalNextListNode(); } p1 = Visit(p1); p2 = Visit(p2); FixLiftedUserDefinedBinaryOperators(expr, ref p1, ref p2); EXPR lift = GetExprFactory().CreateBoolConstant(false); // We never lift to null in C#. EXPR methodInfo = GetExprFactory().CreateMethodInfo(expr.GetUserDefinedCallMethod()); return GenerateCall(pdm, p1, p2, lift, methodInfo); }
protected virtual EXPR GenerateUserDefinedBinaryOperator(EXPRBINOP expr) { Debug.Assert(expr != null); Debug.Assert(alwaysRewrite || currentAnonMeth != null); PREDEFMETH pdm; switch (expr.kind) { case ExpressionKind.EK_LOGOR: pdm = PREDEFMETH.PM_EXPRESSION_ORELSE_USER_DEFINED; break; case ExpressionKind.EK_LOGAND: pdm = PREDEFMETH.PM_EXPRESSION_ANDALSO_USER_DEFINED; break; case ExpressionKind.EK_LSHIFT: pdm = PREDEFMETH.PM_EXPRESSION_LEFTSHIFT_USER_DEFINED; break; case ExpressionKind.EK_RSHIFT: pdm = PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT_USER_DEFINED; break; case ExpressionKind.EK_BITXOR: pdm = PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR_USER_DEFINED; break; case ExpressionKind.EK_BITOR: pdm = PREDEFMETH.PM_EXPRESSION_OR_USER_DEFINED; break; case ExpressionKind.EK_BITAND: pdm = PREDEFMETH.PM_EXPRESSION_AND_USER_DEFINED; break; case ExpressionKind.EK_MOD: pdm = PREDEFMETH.PM_EXPRESSION_MODULO_USER_DEFINED; break; case ExpressionKind.EK_DIV: pdm = PREDEFMETH.PM_EXPRESSION_DIVIDE_USER_DEFINED; break; case ExpressionKind.EK_STRINGEQ: case ExpressionKind.EK_STRINGNE: case ExpressionKind.EK_DELEGATEEQ: case ExpressionKind.EK_DELEGATENE: case ExpressionKind.EK_EQ: case ExpressionKind.EK_NE: case ExpressionKind.EK_GE: case ExpressionKind.EK_GT: case ExpressionKind.EK_LE: case ExpressionKind.EK_LT: return GenerateUserDefinedComparisonOperator(expr); case ExpressionKind.EK_DELEGATESUB: case ExpressionKind.EK_SUB: pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED; break; case ExpressionKind.EK_DELEGATEADD: case ExpressionKind.EK_ADD: pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_ADDCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED; break; case ExpressionKind.EK_MUL: pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_MULTIPLY_USER_DEFINED; break; default: throw Error.InternalCompilerError(); } EXPR p1 = expr.GetOptionalLeftChild(); EXPR p2 = expr.GetOptionalRightChild(); EXPR udcall = expr.GetOptionalUserDefinedCall(); if (udcall != null) { Debug.Assert(udcall.kind == ExpressionKind.EK_CALL || udcall.kind == ExpressionKind.EK_USERLOGOP); if (udcall.kind == ExpressionKind.EK_CALL) { EXPRLIST args = udcall.asCALL().GetOptionalArguments().asLIST(); Debug.Assert(args.GetOptionalNextListNode().kind != ExpressionKind.EK_LIST); p1 = args.GetOptionalElement(); p2 = args.GetOptionalNextListNode(); } else { EXPRLIST args = udcall.asUSERLOGOP().OperatorCall.GetOptionalArguments().asLIST(); Debug.Assert(args.GetOptionalNextListNode().kind != ExpressionKind.EK_LIST); p1 = args.GetOptionalElement().asWRAP().GetOptionalExpression(); p2 = args.GetOptionalNextListNode(); } } p1 = Visit(p1); p2 = Visit(p2); FixLiftedUserDefinedBinaryOperators(expr, ref p1, ref p2); EXPR methodInfo = GetExprFactory().CreateMethodInfo(expr.GetUserDefinedCallMethod()); 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.EK_DELEGATESUB || expr.kind == ExpressionKind.EK_DELEGATEADD) { EXPR pTypeOf = CreateTypeOf(expr.type); return GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, call, pTypeOf); } return call; }