Named Parameters ================ An examination of the possibility of adding named parameters to Cforall. Named parameters allow arguments to be passed and matched to a parameter by their name instead of their position in the argument list. A comparison of positional and named argument passing: make_position(getWidth(), getHeight()); make_position(.x = getWidth(), .y = getHeight()); The example of a Python style printer using optional named parameters: printp("Error:", errorCode, .file=serr, .endl=""); Variations of this feature can be found in various languages: + Python - Keyword Arguments + Swift - Argument Labels + Ada - Named Association + C - Designators (limited) Overview of New Features ------------------------ In terms of code written, this feature interacts with the following: Function Applications and Arguments: When a function is applied and passed arguments those arguments must be provided either as `Positional Arguments` or `Named Arguments`. Positional arguments use the existing C syntax and named arguments could reuse member designator syntax (`.NAME = EXPR` in an argument list). Function Declarations and Parameters: When a function is declared its parameters may be defined as `Positional Parameters` or `Named Parameters`. Unlike with arguments, this is not an either or thing, parameters are actually in three groups `Positional Only`, `Named Only` and `Positional or Named`. In addition, all parameters can be `Required Parameters` or `Optional Parameters`. Current C syntax should be used for positional parameters. New syntax will be needed for named-only or named-or-positional parameters. Something like, `TYPE .NAME` (a dot at the front of the parameter name, to reflect the argument form). Current Cforall does have some support for optional parameters and default arguments. An optional parameter is declared by proving it with a default argument (putting `= EXPR` after the parameter declaration). There is also syntax for explicitly requesting the default argument is used (`@`). As an extension, we could allow array designators (`[ POSITION ] =`) as a way to explicitly give the position of an argument. This is not an existing Cforall feature, nor directly related to named parameters, but it is an extension of C semantics that fits in this area. (I would actually recommend against it at this time, parameter lists should not be so long that this is useful.) Function Pointers ----------------- Function pointers do not need to support named parameters, in the same way they do not support optional parameters. (You can write an optional parameter in a function pointer, but it is ignored.) There could be some way to convert or cast between the two forms, but in practice, the types of functions where named parameters are useful have very little overlap with those that you would pass to a higher order function or use as an assertion. Argument Matching ----------------- How are arguments connected to parameters. This will become part of the overload resolution process, luckily it is a pretty simple straight forward pass fail check so does not effect cost. This covers all the features being considered, but most can cleanly be removed. First, the positional parameters have to be sorted out. Undesignated arguments are positional arguments, if one appears at the front of the argument list it is the 0 positional argument, otherwise it must follow another positional argument and it goes into the next position. It is an error for an undesignated argument to appear after a named argument. Array designated arguments are positional arguments. The constant expression is evaluated and the result is the position of the parameter it is matched with. The same process is way simpler with named arguments, as all are labeled. Member designated arguments are named arguments. They are matched with the parameter with the same name. The `@` argument can be used anywhere other arguments can be. The parameter it is matched with must be an optional parameters and this explicitly requests that the default argument be used. Then we can just check to make sure no parameter is provided/matched with an argument more than once, and that every required parameter is provided exactly once. If any arguments could not be matched to a parameter, it is an error. Note that there are no special rules for positional-or-named parameters, they can just be used in either case. Backwards Compatibility ----------------------- All parameters and arguments in C code can treated as (required and) positional, except for initializers which are optional and use designators. Initializers and C designators always consider the underlying parameter's position the important part. The designator moves the position in the parameter list forward or backward. If an argument is not designated, it is put the next position after the previous argument (or the first position if it is the first argument). It should be noted that this is actually more permissive than most languages. Other named parameter system enforce that all positional arguments come before all named arguments. However, we could translate this using optional and named-or-positional parameters. Removing the ability to have undesignated arguments follow a member designated arguments is required for named only parameters, doing the same for named-or-positional for a consistent interface. C also allows chained designators, nested initializers and descending into and out of recursive initializers automatically as the beginning or end of those sections. In the context of a member/element initializer, the system does have enough information to do this, because the target types are fixed by the type being initialized. These should be supported in the C escape initializer (`@=`), but cannot be generalized to function calls (not even initializers we resolve as functions) because of overloading. Run-time Implementation ----------------------- The underlying code must be translated into simple C code that does not use these parameters or arguments. For this purpose, we do use the ordering of all parameters, writing them out in the order they appear in the declaration. Note that the programmer still does not have to (and sometimes cannot) interact with the order of parameters, but the compiler will still use them. Here it boils down all the named forms down to positional code. This is the run-time efficient way to implement it. Other forms of argument packing, such as putting the named arguments into a map, tend to be slower and their advantages allow for more dynamic behaviour has a harder time using effectively.