//////////////////////////////////////////////////////////////////////////////// // Check the constraints on the method instantiation. public static void CheckMethConstraints(MethWithInst mwi) { Debug.Assert(mwi.Meth() != null && mwi.GetType() != null && mwi.TypeArgs != null); Debug.Assert(mwi.Meth().typeVars.Count == mwi.TypeArgs.Count); Debug.Assert(mwi.GetType().OwningAggregate == mwi.Meth().getClass()); if (mwi.TypeArgs.Count > 0) { CheckConstraintsCore(mwi.Meth(), mwi.Meth().typeVars, mwi.TypeArgs, mwi.GetType().TypeArgsAll, mwi.TypeArgs, CheckConstraintsFlags.None); } }
//////////////////////////////////////////////////////////////////////////////// // Check the constraints on the method instantiation. public static void CheckMethConstraints(CSemanticChecker checker, ErrorHandling errCtx, MethWithInst mwi) { Debug.Assert(mwi.Meth() != null && mwi.GetType() != null && mwi.TypeArgs != null); Debug.Assert(mwi.Meth().typeVars.Count == mwi.TypeArgs.Count); Debug.Assert(mwi.GetType().getAggregate() == mwi.Meth().getClass()); if (mwi.TypeArgs.Count > 0) { CheckConstraintsCore(checker, errCtx, mwi.Meth(), mwi.Meth().typeVars, mwi.TypeArgs, mwi.GetType().GetTypeArgsAll(), mwi.TypeArgs, CheckConstraintsFlags.None); } }
///////////////////////////////////////////////////////////////////////////////// // Expression types. private ExprBinOp VisitBoundLambda(ExprBoundLambda anonmeth) { Debug.Assert(anonmeth != null); MethodSymbol lambdaMethod = GetPreDefMethod(PREDEFMETH.PM_EXPRESSION_LAMBDA); AggregateType delegateType = anonmeth.DelegateType; TypeArray lambdaTypeParams = TypeArray.Allocate(delegateType); AggregateType expressionType = SymbolLoader.GetPredefindType(PredefinedType.PT_EXPRESSION); MethWithInst mwi = new MethWithInst(lambdaMethod, expressionType, lambdaTypeParams); Expr createParameters = CreateWraps(anonmeth); Debug.Assert(createParameters != null); Debug.Assert(anonmeth.Expression != null); Expr body = Visit(anonmeth.Expression); Debug.Assert(anonmeth.ArgumentScope.nextChild == null); Expr parameters = GenerateParamsArray(null, PredefinedType.PT_PARAMETEREXPRESSION); Expr args = ExprFactory.CreateList(body, parameters); CType typeRet = TypeManager.SubstType(mwi.Meth().RetType, mwi.GetType(), mwi.TypeArgs); ExprMemberGroup pMemGroup = ExprFactory.CreateMemGroup(null, mwi); ExprCall call = ExprFactory.CreateCall(0, typeRet, args, pMemGroup, mwi); call.PredefinedMethod = PREDEFMETH.PM_EXPRESSION_LAMBDA; return(ExprFactory.CreateSequence(createParameters, call)); }
private Expr GenerateUserDefinedConversion(Expr arg, CType CType, Expr target, MethWithInst method) { // The user-defined explicit conversion from enum? to decimal or decimal? requires // that we convert the enum? to its nullable underlying CType. if (isEnumToDecimalConversion(arg.Type, CType)) { // Special case: If we have enum? to decimal? then we need to emit // a conversion from enum? to its nullable underlying CType first. // This is unfortunate; we ought to reorganize how conversions are // represented in the Expr tree so that this is more transparent. // converting an enum to its underlying CType never fails, so no need to check it. CType underlyingType = arg.Type.StripNubs().underlyingEnumType(); CType nullableType = GetSymbolLoader().GetTypeManager().GetNullable(underlyingType); Expr typeofNubEnum = CreateTypeOf(nullableType); target = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, target, typeofNubEnum); } // If the methodinfo does not return the target CType AND this is not a lifted conversion // from one value CType to another, then we need to wrap the whole thing in another conversion, // e.g. if we have a user-defined conversion from int to S? and we have (S)myint, then we need to generate // Convert(Convert(myint, typeof(S?), op_implicit), typeof(S)) CType pMethodReturnType = GetSymbolLoader().GetTypeManager().SubstType(method.Meth().RetType, method.GetType(), method.TypeArgs); bool fDontLiftReturnType = (pMethodReturnType == CType || (IsNullableValueType(arg.Type) && IsNullableValueType(CType))); Expr typeofInner = CreateTypeOf(fDontLiftReturnType ? CType : pMethodReturnType); Expr methodInfo = GetExprFactory().CreateMethodInfo(method); PREDEFMETH pdmInner = arg.isChecked() ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED; Expr callUserDefinedConversion = GenerateCall(pdmInner, target, typeofInner, methodInfo); if (fDontLiftReturnType) { return(callUserDefinedConversion); } PREDEFMETH pdmOuter = arg.isChecked() ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED : PREDEFMETH.PM_EXPRESSION_CONVERT; Expr typeofOuter = CreateTypeOf(CType); return(GenerateCall(pdmOuter, callUserDefinedConversion, typeofOuter)); }
protected virtual EXPR GenerateUserDefinedConversion(EXPR arg, CType CType, EXPR target, MethWithInst method) { // The user-defined explicit conversion from enum? to decimal or decimal? requires // that we convert the enum? to its nullable underlying CType. if (isEnumToDecimalConversion(arg.type, CType)) { // Special case: If we have enum? to decimal? then we need to emit // a conversion from enum? to its nullable underlying CType first. // This is unfortunate; we ought to reorganize how conversions are // represented in the EXPR tree so that this is more transparent. // converting an enum to its underlying CType never fails, so no need to check it. CType underlyingType = arg.type.StripNubs().underlyingEnumType(); CType nullableType = GetSymbolLoader().GetTypeManager().GetNullable(underlyingType); EXPR typeofNubEnum = CreateTypeOf(nullableType); target = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, target, typeofNubEnum); } // If the methodinfo does not return the target CType AND this is not a lifted conversion // from one value CType to another, then we need to wrap the whole thing in another conversion, // e.g. if we have a user-defined conversion from int to S? and we have (S)myint, then we need to generate // Convert(Convert(myint, typeof(S?), op_implicit), typeof(S)) CType pMethodReturnType = GetSymbolLoader().GetTypeManager().SubstType(method.Meth().RetType, method.GetType(), method.TypeArgs); bool fDontLiftReturnType = (pMethodReturnType == CType || (IsNullableValueType(arg.type) && IsNullableValueType(CType))); EXPR typeofInner = CreateTypeOf(fDontLiftReturnType ? CType : pMethodReturnType); EXPR methodInfo = GetExprFactory().CreateMethodInfo(method); PREDEFMETH pdmInner = arg.isChecked() ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED; EXPR callUserDefinedConversion = GenerateCall(pdmInner, target, typeofInner, methodInfo); if (fDontLiftReturnType) { return callUserDefinedConversion; } PREDEFMETH pdmOuter = arg.isChecked() ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED : PREDEFMETH.PM_EXPRESSION_CONVERT; EXPR typeofOuter = CreateTypeOf(CType); return GenerateCall(pdmOuter, callUserDefinedConversion, typeofOuter); }
///////////////////////////////////////////////////////////////////////////////// // Expression types. protected override EXPR VisitBOUNDLAMBDA(EXPRBOUNDLAMBDA anonmeth) { Debug.Assert(anonmeth != null); EXPRBOUNDLAMBDA prevAnonMeth = currentAnonMeth; currentAnonMeth = anonmeth; MethodSymbol lambdaMethod = GetPreDefMethod(PREDEFMETH.PM_EXPRESSION_LAMBDA); CType delegateType = anonmeth.DelegateType(); TypeArray lambdaTypeParams = GetSymbolLoader().getBSymmgr().AllocParams(1, new CType[] { delegateType }); AggregateType expressionType = GetSymbolLoader().GetOptPredefTypeErr(PredefinedType.PT_EXPRESSION, true); MethWithInst mwi = new MethWithInst(lambdaMethod, expressionType, lambdaTypeParams); EXPR createParameters = CreateWraps(anonmeth); EXPR body = RewriteLambdaBody(anonmeth); EXPR parameters = RewriteLambdaParameters(anonmeth); EXPR args = GetExprFactory().CreateList(body, parameters); CType typeRet = GetSymbolLoader().GetTypeManager().SubstType(mwi.Meth().RetType, mwi.GetType(), mwi.TypeArgs); EXPRMEMGRP pMemGroup = GetExprFactory().CreateMemGroup(null, mwi); EXPR callLambda = GetExprFactory().CreateCall(0, typeRet, args, pMemGroup, mwi); callLambda.asCALL().PredefinedMethod = PREDEFMETH.PM_EXPRESSION_LAMBDA; currentAnonMeth = prevAnonMeth; if (createParameters != null) { callLambda = GetExprFactory().CreateSequence(createParameters, callLambda); } EXPR expr = DestroyWraps(anonmeth, callLambda); // If we are already inside an expression tree rewrite and this is an expression tree lambda // then it needs to be quoted. if (currentAnonMeth != null) { expr = GenerateCall(PREDEFMETH.PM_EXPRESSION_QUOTE, expr); } return expr; }
//////////////////////////////////////////////////////////////////////////////// // Check the constraints on the method instantiation. public static void CheckMethConstraints(CSemanticChecker checker, ErrorHandling errCtx, MethWithInst mwi) { Debug.Assert(mwi.Meth() != null && mwi.GetType() != null && mwi.TypeArgs != null); Debug.Assert(mwi.Meth().typeVars.size == mwi.TypeArgs.size); Debug.Assert(mwi.GetType().getAggregate() == mwi.Meth().getClass()); if (mwi.TypeArgs.size > 0) { CheckConstraintsCore(checker, errCtx, mwi.Meth(), mwi.Meth().typeVars, mwi.TypeArgs, mwi.GetType().GetTypeArgsAll(), mwi.TypeArgs, CheckConstraintsFlags.None); } }
//////////////////////////////////////////////////////////////////////////////// // Binds a call to a method, return type is an error or an EXPRCALL. // // tree - ParseTree for error messages // pObject - pObject to call method on // pmwi - Meth to bind to. This will be morphed when we remap to an override. // args - arguments // exprFlags - Flags to put on the generated expr internal EXPRCALL BindToMethod(MethWithInst mwi, EXPR pArguments, EXPRMEMGRP pMemGroup, MemLookFlags flags) { Debug.Assert(mwi.Sym != null && mwi.Sym.IsMethodSymbol() && (!mwi.Meth().isOverride || mwi.Meth().isHideByName)); Debug.Assert(pMemGroup != null); bool fConstrained; bool bIsMatchingStatic; EXPR pObject = pMemGroup.GetOptionalObject(); CType callingObjectType = pObject != null ? pObject.type : null; PostBindMethod((flags & MemLookFlags.BaseCall) != 0, ref mwi, pObject); pObject = AdjustMemberObject(mwi, pObject, out fConstrained, out bIsMatchingStatic); pMemGroup.SetOptionalObject(pObject); CType pReturnType = null; if ((flags & (MemLookFlags.Ctor | MemLookFlags.NewObj)) == (MemLookFlags.Ctor | MemLookFlags.NewObj)) { pReturnType = mwi.Ats; } else { pReturnType = GetTypes().SubstType(mwi.Meth().RetType, mwi.GetType(), mwi.TypeArgs); } EXPRCALL pResult = GetExprFactory().CreateCall(0, pReturnType, pArguments, pMemGroup, mwi); if (!bIsMatchingStatic) { pResult.SetMismatchedStaticBit(); } if (!pResult.isOK()) { return pResult; } // Set the return type and flags for constructors. if ((flags & MemLookFlags.Ctor) != 0) { if ((flags & MemLookFlags.NewObj) != 0) { pResult.flags |= EXPRFLAG.EXF_NEWOBJCALL | EXPRFLAG.EXF_CANTBENULL; } else { Debug.Assert(pResult.type == getVoidType()); } } if ((flags & MemLookFlags.BaseCall) != 0) { pResult.flags |= EXPRFLAG.EXF_BASECALL; } else if (fConstrained && pObject != null) { // Use the constrained prefix. pResult.flags |= EXPRFLAG.EXF_CONSTRAINED; } verifyMethodArgs(pResult, callingObjectType); return pResult; }