///////////////////////////////////////////////////////////////////////////////// protected override EXPR VisitSAVE(EXPRBINOP pExpr) { // Saves should have a LHS that is a CALL to PM_EXPRESSION_PARAMETER // and a RHS that is a WRAP of that call. Debug.Assert(pExpr.GetOptionalLeftChild() != null); Debug.Assert(pExpr.GetOptionalLeftChild().isCALL()); Debug.Assert(pExpr.GetOptionalLeftChild().asCALL().PredefinedMethod == PREDEFMETH.PM_EXPRESSION_PARAMETER); Debug.Assert(pExpr.GetOptionalRightChild() != null); Debug.Assert(pExpr.GetOptionalRightChild().isWRAP()); EXPRCALL call = pExpr.GetOptionalLeftChild().asCALL(); EXPRTYPEOF TypeOf = call.GetOptionalArguments().asLIST().GetOptionalElement().asTYPEOF(); Expression parameter = _ListOfParameters.ElementAt(_currentParameterIndex++); _DictionaryOfParameters.Add(call, parameter); return null; }
protected virtual EXPR VisitDELEGATESUB(EXPRBINOP pExpr) { return VisitBINOP(pExpr); }
protected virtual EXPR VisitSWAP(EXPRBINOP pExpr) { return VisitBINOP(pExpr); }
protected virtual EXPR VisitSTRINGNE(EXPRBINOP pExpr) { return VisitBINOP(pExpr); }
protected virtual EXPR VisitLOGOR(EXPRBINOP pExpr) { return VisitBINOP(pExpr); }
public EXPRBINOP CreateBinop(ExpressionKind exprKind, CType pType, EXPR p1, EXPR p2) { //Debug.Assert(exprKind.isBinaryOperator()); EXPRBINOP rval = new EXPRBINOP(); rval.kind = exprKind; rval.type = pType; rval.flags = EXPRFLAG.EXF_BINOP; rval.SetOptionalLeftChild(p1); rval.SetOptionalRightChild(p2); rval.isLifted = false; rval.SetOptionalUserDefinedCall(null); rval.SetUserDefinedCallMethod(null); Debug.Assert(rval != null); return (rval); }
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; }
protected override EXPR VisitBINOP(EXPRBINOP expr) { Debug.Assert(expr != null); Debug.Assert(alwaysRewrite || currentAnonMeth != null); if (expr.GetUserDefinedCallMethod() != null) { return GenerateUserDefinedBinaryOperator(expr); } else { return GenerateBuiltInBinaryOperator(expr); } }
protected virtual EXPR VisitEQUALS(EXPRBINOP pExpr) { return VisitBINOP(pExpr); }
protected virtual EXPR VisitLT(EXPRBINOP pExpr) { return(VisitBINOP(pExpr)); }
protected virtual EXPR VisitDELEGATEADD(EXPRBINOP pExpr) { return(VisitBINOP(pExpr)); }
protected virtual EXPR VisitSTRINGEQ(EXPRBINOP pExpr) { return(VisitBINOP(pExpr)); }
protected virtual EXPR VisitSEQUENCE(EXPRBINOP pExpr) { return(VisitBINOP(pExpr)); }
public EXPRBINOP CreateUserDefinedBinop(ExpressionKind exprKind, CType pType, EXPR p1, EXPR p2, EXPR call, MethPropWithInst pmpwi) { Debug.Assert(p1 != null); Debug.Assert(p2 != null); Debug.Assert(call != null); EXPRBINOP rval = new EXPRBINOP(); rval.kind = exprKind; rval.type = pType; rval.flags = EXPRFLAG.EXF_BINOP; rval.SetOptionalLeftChild(p1); rval.SetOptionalRightChild(p2); // The call may be lifted, but we do not mark the outer binop as lifted. rval.isLifted = false; rval.SetOptionalUserDefinedCall(call); rval.SetUserDefinedCallMethod(pmpwi); if (call.HasError()) { rval.SetError(); } Debug.Assert(rval != null); return (rval); }
protected virtual EXPR VisitCOMPARE(EXPRBINOP pExpr) { return VisitBINOP(pExpr); }
protected void FixLiftedUserDefinedBinaryOperators(EXPRBINOP expr, ref EXPR pp1, ref EXPR pp2) { // If we have lifted T1 op T2 to T1? op T2?, and we have an expression T1 op T2? or T1? op T2 then // we need to ensure that the unlifted actual arguments are promoted to their nullable CType. Debug.Assert(expr != null); Debug.Assert(pp1 != null); Debug.Assert(pp1 != null); Debug.Assert(pp2 != null); Debug.Assert(pp2 != null); MethodSymbol method = expr.GetUserDefinedCallMethod().Meth(); EXPR orig1 = expr.GetOptionalLeftChild(); EXPR orig2 = expr.GetOptionalRightChild(); Debug.Assert(orig1 != null && orig2 != null); EXPR new1 = pp1; EXPR new2 = pp2; CType fptype1 = method.Params.Item(0); CType fptype2 = method.Params.Item(1); CType aatype1 = orig1.type; CType aatype2 = orig2.type; // Is the operator even a candidate for lifting? if (fptype1.IsNullableType() || fptype2.IsNullableType() || !fptype1.IsAggregateType() || !fptype2.IsAggregateType() || !fptype1.AsAggregateType().getAggregate().IsValueType() || !fptype2.AsAggregateType().getAggregate().IsValueType()) { return; } CType nubfptype1 = GetSymbolLoader().GetTypeManager().GetNullable(fptype1); CType nubfptype2 = GetSymbolLoader().GetTypeManager().GetNullable(fptype2); // If we have null op X, or T1 op T2?, or T1 op null, lift first arg to T1? if (aatype1.IsNullType() || aatype1 == fptype1 && (aatype2 == nubfptype2 || aatype2.IsNullType())) { new1 = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, new1, CreateTypeOf(nubfptype1)); } // If we have X op null, or T1? op T2, or null op T2, lift second arg to T2? if (aatype2.IsNullType() || aatype2 == fptype2 && (aatype1 == nubfptype1 || aatype1.IsNullType())) { new2 = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, new2, CreateTypeOf(nubfptype2)); } pp1 = new1; pp2 = new2; }
protected virtual EXPR VisitSEQUENCE(EXPRBINOP pExpr) { return VisitBINOP(pExpr); }
protected virtual EXPR GenerateBuiltInBinaryOperator(EXPRBINOP expr) { Debug.Assert(expr != null); Debug.Assert(alwaysRewrite || currentAnonMeth != null); PREDEFMETH pdm; switch (expr.kind) { case ExpressionKind.EK_LSHIFT: pdm = PREDEFMETH.PM_EXPRESSION_LEFTSHIFT; break; case ExpressionKind.EK_RSHIFT: pdm = PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT; break; case ExpressionKind.EK_BITXOR: pdm = PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR; break; case ExpressionKind.EK_BITOR: pdm = PREDEFMETH.PM_EXPRESSION_OR; break; case ExpressionKind.EK_BITAND: pdm = PREDEFMETH.PM_EXPRESSION_AND; break; case ExpressionKind.EK_LOGAND: pdm = PREDEFMETH.PM_EXPRESSION_ANDALSO; break; case ExpressionKind.EK_LOGOR: pdm = PREDEFMETH.PM_EXPRESSION_ORELSE; break; case ExpressionKind.EK_STRINGEQ: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL; break; case ExpressionKind.EK_EQ: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL; break; case ExpressionKind.EK_STRINGNE: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL; break; case ExpressionKind.EK_NE: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL; break; case ExpressionKind.EK_GE: pdm = PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL; break; case ExpressionKind.EK_LE: pdm = PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL; break; case ExpressionKind.EK_LT: pdm = PREDEFMETH.PM_EXPRESSION_LESSTHAN; break; case ExpressionKind.EK_GT: pdm = PREDEFMETH.PM_EXPRESSION_GREATERTHAN; break; case ExpressionKind.EK_MOD: pdm = PREDEFMETH.PM_EXPRESSION_MODULO; break; case ExpressionKind.EK_DIV: pdm = PREDEFMETH.PM_EXPRESSION_DIVIDE; break; case ExpressionKind.EK_MUL: pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED : PREDEFMETH.PM_EXPRESSION_MULTIPLY; break; case ExpressionKind.EK_SUB: pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED : PREDEFMETH.PM_EXPRESSION_SUBTRACT; break; case ExpressionKind.EK_ADD: pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_ADDCHECKED : PREDEFMETH.PM_EXPRESSION_ADD; break; default: throw Error.InternalCompilerError(); } EXPR origL = expr.GetOptionalLeftChild(); EXPR origR = expr.GetOptionalRightChild(); 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.IsNullableType() && typeL.StripNubs().isEnumType()) { Debug.Assert(expr.isLifted); convertL = GetSymbolLoader().GetTypeManager().GetNullable(typeL.StripNubs().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.IsNullableType() && typeR.StripNubs().isEnumType()) { Debug.Assert(expr.isLifted); convertR = GetSymbolLoader().GetTypeManager().GetNullable(typeR.StripNubs().underlyingEnumType()); typeR = convertR; didEnumConversion = true; } if (typeL.IsNullableType() && typeL.StripNubs() == typeR) { convertR = typeL; } if (typeR.IsNullableType() && typeR.StripNubs() == 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; }
protected virtual EXPR VisitRSHIFT(EXPRBINOP pExpr) { return VisitBINOP(pExpr); }
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); }
public EXPRQUESTIONMARK CreateQuestionMark(EXPR pTestExpression, EXPRBINOP pConsequence) { Debug.Assert(pTestExpression != null); Debug.Assert(pConsequence != null); CType pType = pConsequence.type; if (pType == null) { Debug.Assert(pConsequence.GetOptionalLeftChild() != null); pType = pConsequence.GetOptionalLeftChild().type; Debug.Assert(pType != null); } EXPRQUESTIONMARK pResult = new EXPRQUESTIONMARK(); pResult.kind = ExpressionKind.EK_QUESTIONMARK; pResult.type = pType; pResult.flags = 0; pResult.SetTestExpression(pTestExpression); pResult.SetConsequence(pConsequence); Debug.Assert(pResult != null); return pResult; }