//////////////////////////////////////////////////////////////////////////////// // 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 ExprCall GenerateCall(PREDEFMETH pdm, Expr arg1, Expr arg2, Expr arg3, Expr arg4) { MethodSymbol method = GetPreDefMethod(pdm); if (method == null) { return(null); } AggregateType expressionType = GetSymbolLoader().GetPredefindType(PredefinedType.PT_EXPRESSION); Expr args = GetExprFactory().CreateList(arg1, arg2, arg3, arg4); MethWithInst mwi = new MethWithInst(method, expressionType); ExprMemberGroup pMemGroup = GetExprFactory().CreateMemGroup(null, mwi); ExprCall call = GetExprFactory().CreateCall(0, mwi.Meth().RetType, args, pMemGroup, mwi); call.PredefinedMethod = pdm; return(call); }
private ExprCall GenerateCall(PREDEFMETH pdm, Expr arg1) { MethodSymbol method = GetPreDefMethod(pdm); // this should be enforced in an earlier pass and the transform pass should not // be handling this error if (method == null) { return(null); } AggregateType expressionType = GetSymbolLoader().GetPredefindType(PredefinedType.PT_EXPRESSION); MethWithInst mwi = new MethWithInst(method, expressionType); ExprMemberGroup pMemGroup = GetExprFactory().CreateMemGroup(null, mwi); ExprCall call = GetExprFactory().CreateCall(0, mwi.Meth().RetType, arg1, pMemGroup, mwi); call.PredefinedMethod = pdm; return(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); }
protected EXPRCALL GenerateCall(PREDEFMETH pdm, EXPR arg1, EXPR arg2, EXPR arg3, EXPR arg4) { MethodSymbol method = GetPreDefMethod(pdm); if (method == null) return null; AggregateType expressionType = GetSymbolLoader().GetOptPredefTypeErr(PredefinedType.PT_EXPRESSION, true); EXPR args = GetExprFactory().CreateList(arg1, arg2, arg3, arg4); MethWithInst mwi = new MethWithInst(method, expressionType); EXPRMEMGRP pMemGroup = GetExprFactory().CreateMemGroup(null, mwi); EXPRCALL call = GetExprFactory().CreateCall(0, mwi.Meth().RetType, args, pMemGroup, mwi); call.PredefinedMethod = pdm; return call; }
protected EXPRCALL GenerateCall(PREDEFMETH pdm, EXPR arg1) { MethodSymbol method = GetPreDefMethod(pdm); // this should be enforced in an earlier pass and the tranform pass should not // be handeling this error if (method == null) return null; AggregateType expressionType = GetSymbolLoader().GetOptPredefTypeErr(PredefinedType.PT_EXPRESSION, true); MethWithInst mwi = new MethWithInst(method, expressionType); EXPRMEMGRP pMemGroup = GetExprFactory().CreateMemGroup(null, mwi); EXPRCALL call = GetExprFactory().CreateCall(0, mwi.Meth().RetType, arg1, pMemGroup, mwi); call.PredefinedMethod = pdm; return call; }
///////////////////////////////////////////////////////////////////////////////// // 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; }
internal void PostBindMethod(bool fBaseCall, ref MethWithInst pMWI, EXPR pObject) { MethWithInst mwiOrig = pMWI; // If it is virtual, find a remap of the method to something more specific. This // may alter where the method is found. if (pObject != null && (fBaseCall || pObject.type.isSimpleType() || pObject.type.isSpecialByRefType())) { RemapToOverride(GetSymbolLoader(), pMWI, pObject.type); } if (fBaseCall && pMWI.Meth().isAbstract) { ErrorContext.Error(ErrorCode.ERR_AbstractBaseCall, pMWI); } if (pMWI.Meth().RetType != null) { checkUnsafe(pMWI.Meth().RetType); bool fCheckParams = false; if (pMWI.Meth().isExternal) { fCheckParams = true; SetExternalRef(pMWI.Meth().RetType); } // We need to check unsafe on the parameters as well, since we cannot check in conversion. TypeArray pParams = pMWI.Meth().Params; for (int i = 0; i < pParams.size; i++) { // This is an optimization: don't call this in the vast majority of cases CType type = pParams.Item(i); if (type.isUnsafe()) { checkUnsafe(type); } if (fCheckParams && type.IsParameterModifierType()) { SetExternalRef(type); } } } }