//////////////////////////////////////////////////////////////////////////////// // 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 TypeArray RearrangeNamedArguments(TypeArray pta, MethPropWithInst mpwi, CType pTypeThrough, ArgInfos args) { if (!args.fHasExprs) { return(pta); } #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].isNamedArgumentSpecification()); } #endif CType type = pTypeThrough != null ? pTypeThrough : mpwi.GetType(); CType[] typeList = new CType[pta.Count]; MethodOrPropertySymbol methProp = GroupToArgsBinder.FindMostDerivedMethod(GetSymbolLoader(), 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]; } // 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++) { EXPR arg = args.prgexpr[iParam]; if (arg.isNamedArgumentSpecification()) { // 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, arg.asNamedArgumentSpecification().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(GetSymbolLoader().getBSymmgr().AllocParams(pta.Count, typeList)); }
private EXPR StripNamedArgument(EXPR pArg) { if (pArg.isNamedArgumentSpecification()) { pArg = pArg.asNamedArgumentSpecification().Value; } else if (pArg.isARRINIT()) { pArg.asARRINIT().SetOptionalArguments(StripNamedArguments(pArg.asARRINIT().GetOptionalArguments())); } return pArg; }