Handle forward compatibility and clarify parsing behavior.

This commit is contained in:
Aviral Goel 2024-05-15 12:04:09 -07:00
parent 8351e99941
commit 95d88078a5

View file

@ -14,16 +14,28 @@ The following syntax is proposed for attributes with parameters:
```ebnf
attribute = '@' NAME
| '@' NAME '(' ')'
| '@' NAME '(' ATOMIC-LITERAL (',' ATOMIC-LITERAL)* ')'
```
The only extension proposed to the [Attributes](./syntax-attributes-functions.md) RFC is in the second line which allows one or more comma-separated literals to be supplied to the attribute. The `ATOMIC-LITERAL` category includes values of type `boolean`, `number`, `string`, and the `nil` value. The `nil` value can be be used for "optional" parameters when no valid value exists. As a hypothetical example, consider the `@deprecated(<new-function-name>, <warning-message>)` attribute. Assume a function is being marked deprecated because we are getting rid of the feature entirely and there is no other function replacing it. In that case, we can pass `nil` for the `<new-function-name>` parameter. An alternative would be to allow this attribute to have either one or two parameters. But that still won't help when an attribute can take three parameters and we want to ignore the second.
The extension proposed to the [Attributes](./syntax-attributes-functions.md) RFC is in the second and third lines which allow zero or more comma-separated literals to be supplied to the attribute. `NAME` should be a valid identifier immediately following `@` without any spaces. The `ATOMIC-LITERAL` category includes values of type `boolean`, `number`, `string`, and the `nil` value. The `nil` value can be be used for "optional" parameters when no valid value exists. As a hypothetical example, consider the `@deprecated(<new-function-name>, <warning-message>)` attribute. Assume a function is being marked deprecated because we are getting rid of the feature entirely and there is no other function replacing it. In that case, we can pass `nil` for the `<new-function-name>` parameter. An alternative would be to allow this attribute to have either one or two parameters. But that still won't help when an attribute can take three parameters and we want to ignore the second. A `(` following a `NAME`, with or without intervening whitespace, starts a parameter list for that attribute, even if the attribute does not support parameters. The parser will only check for syntacting correctness. The implemention will raise an error when it uses the attribute and finds that an invalid number or type of arguments were supplied. The implemention will treat an attribute with an empty parameter list equivalent to one without parameters. This means that `@native()` is the same as `@native`. This gives us forward compatibility if we decide to support attributes on parenthesized expressions in the future. Consider the following hypothetical example with a `@my_attribute` attribute, which does not take any parameters, applied to a parenthesized expression.
There are three notable exclusions in this syntax.
```lua
@my_attribute
(f().x)
```
Since an opening parenthesis starts a parameter list for the attribute, the expression `(f().x)` will be treated as a parameter list of `@my_attribute`. This will lead to a syntax error since attribute parameter can only be `ATOMIC-LITERAL` and `f().x` is not one. This ambiguity can be resolved by adding `()` to `@my_attribute` as follows:
```lua
@my_attribute()
(f().x)
```
There are two notable exclusions in this syntax.
1. Literal `table` values are excluded from being passed as parameters since they are composite structures; information supplied via table fields can be passed as separate parameters to the attribute. If they are still deemed useful, a follow-up RFC can introduce them with motivating use cases.
2. Attributes with empty parameter lists are disallowed. It can be argued that this leads to syntactic irregularity, but attributes with empty parameter lists convey no useful information over parameterless attributes, and have no compelling use case. Furthermore, they might complicate attribute processing in the implementation which will have to check for both `@NAME` and `@NAME()` forms and treat them equally.
3. Named parameters are not supported. Our envisioned use cases rarely require parameters, and, since attributes are not user-extensible, we don't foresee use cases involving long parameter lists that would benefit from parameter names. Furthermore, named parameter lists introduce additional processing complexity by enabling parameters to be supplied in any order.
2. Named parameters are not supported. Our envisioned use cases rarely require parameters, and, since attributes are not user-extensible, we don't foresee use cases involving long parameter lists that would benefit from parameter names. Furthermore, named parameter lists introduce additional processing complexity by enabling parameters to be supplied in any order.
## Drawbacks