///////////////////////////////////////////////////////////////////////////////// // 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)); }
public static ExprMemberGroup CreateMemGroup(Expr obj, MethPropWithInst method) { Name name = method.Sym?.name; return(CreateMemGroup( 0, name, method.TypeArgs, method.MethProp()?.getKind() ?? SYMKIND.SK_MethodSymbol, method.GetType(), obj, new CMemberLookupResults(TypeArray.Allocate((CType)method.GetType()), name))); }
//////////////////////////////////////////////////////////////////////////////// // We need to rearange the method parameters so that the type of any specified named argument // appears in the same place as the named argument. Consider the example below: // Foo(int x = 4, string y = "", long l = 4) // Foo(string y = "", string x="", long l = 5) // and the call site: // Foo(y:"a") // After rearranging the parameter types we will have: // (string, int, long) and (string, string, long) // By rearranging the arguments as such we make sure that any specified named arguments appear in the same position for both // methods and we also maintain the relative order of the other parameters (the type long appears after int in the above example) private static TypeArray RearrangeNamedArguments(TypeArray pta, MethPropWithInst mpwi, CType pTypeThrough, ArgInfos args) { #if DEBUG // We never have a named argument that is in a position in the argument // list past the end of what would be the formal parameter list. for (int i = pta.Count; i < args.carg; i++) { Debug.Assert(!(args.prgexpr[i] is ExprNamedArgumentSpecification)); } #endif // If we've no args we can skip. If the last argument isn't named then either we // have no named arguments, and we can skip, or we have non-trailing named arguments // and we MUST skip! if (args.carg == 0 || !(args.prgexpr[args.carg - 1] is ExprNamedArgumentSpecification)) { return(pta); } CType type = pTypeThrough != null ? pTypeThrough : mpwi.GetType(); CType[] typeList = new CType[pta.Count]; MethodOrPropertySymbol methProp = GroupToArgsBinder.FindMostDerivedMethod(mpwi.MethProp(), type); // We initialize the new type array with the parameters for the method. for (int iParam = 0; iParam < pta.Count; iParam++) { typeList[iParam] = pta[iParam]; } var prgexpr = args.prgexpr; // We then go over the specified arguments and put the type for any named argument in the right position in the array. for (int iParam = 0; iParam < args.carg; iParam++) { if (prgexpr[iParam] is ExprNamedArgumentSpecification named) { // We find the index of the type of the argument in the method parameter list and store that in a temp int index = FindName(methProp.ParameterNames, named.Name); CType tempType = pta[index]; // Starting from the current position in the type list up until the location of the type of the optional argument // We shift types by one: // before: (int, string, long) // after: (string, int, long) // We only touch the types between the current position and the position of the type we need to move for (int iShift = iParam; iShift < index; iShift++) { typeList[iShift + 1] = typeList[iShift]; } typeList[iParam] = tempType; } } return(TypeArray.Allocate(typeList)); }
private static TypeArray LoadTypeArrayFromSignature(int[] signature, ref int indexIntoSignatures, TypeArray classTyVars) { Debug.Assert(signature != null); int count = signature[indexIntoSignatures]; indexIntoSignatures++; Debug.Assert(count >= 0); CType[] ptypes = new CType[count]; for (int i = 0; i < ptypes.Length; i++) { ptypes[i] = LoadTypeFromSignature(signature, ref indexIntoSignatures, classTyVars); } return(TypeArray.Allocate(ptypes)); }
private static CType LoadTypeFromSignature(int[] signature, ref int indexIntoSignatures, TypeArray classTyVars) { Debug.Assert(signature != null); MethodSignatureEnum current = (MethodSignatureEnum)signature[indexIntoSignatures]; indexIntoSignatures++; switch (current) { case MethodSignatureEnum.SIG_SZ_ARRAY: return(TypeManager.GetArray(LoadTypeFromSignature(signature, ref indexIntoSignatures, classTyVars), 1, true)); case MethodSignatureEnum.SIG_METH_TYVAR: return(TypeManager.GetStdMethTypeVar(signature[indexIntoSignatures++])); case MethodSignatureEnum.SIG_CLASS_TYVAR: return(classTyVars[signature[indexIntoSignatures++]]); case (MethodSignatureEnum)PredefinedType.PT_VOID: return(VoidType.Instance); default: Debug.Assert(current >= 0 && (int)current < (int)PredefinedType.PT_COUNT); AggregateSymbol agg = GetPredefAgg((PredefinedType)current); int typeCount = agg.GetTypeVars().Count; if (typeCount == 0) { return(TypeManager.GetAggregate(agg, TypeArray.Empty)); } CType[] typeArgs = new CType[typeCount]; for (int iTypeArg = 0; iTypeArg < typeArgs.Length; iTypeArg++) { typeArgs[iTypeArg] = LoadTypeFromSignature(signature, ref indexIntoSignatures, classTyVars); } return(TypeManager.GetAggregate(agg, TypeArray.Allocate(typeArgs))); } }
public override AggregateType GetAts() => _ats ?? (_ats = TypeManager.GetAggregate(TypeManager.GetNullable(), TypeArray.Allocate(UnderlyingType)));