OLD | NEW |
(Empty) | |
| 1 # Optional const |
| 2 |
| 3 Author: eernst@. |
| 4 |
| 5 Version: 0.1 (2017-08-10) |
| 6 |
| 7 Status: Under discussion |
| 8 |
| 9 **This document** is an informal specification of the *optional const* feature. |
| 10 **The feature** adds support for omitting the reserved word `const` in list and |
| 11 map literals and constant object expressions, in locations where `const` is |
| 12 currently required. |
| 13 |
| 14 This informal specification is built on a |
| 15 [combined proposal](https://github.com/dart-lang/sdk/blob/master/docs/language/i
nformal/optional-new-const.md) |
| 16 which presents optional const and several other features. |
| 17 |
| 18 ## Motivation |
| 19 |
| 20 In Dart without optional const, complex constant expressions often contain many |
| 21 occurrences of `const` on list and map literals, and on constant object |
| 22 expressions. Subexpressions of constant expressions are themselves required to |
| 23 be constant expressions, and this means that `const` on a nested list or map |
| 24 literal provides no extra information: It is a compile-time error if that |
| 25 `const` is omitted. Similarly, it is a compile-time error if a nested constant |
| 26 object expression is modified to use `new` rather than `const`. In that |
| 27 situation it carries no extra information whether `new` or `const` is used, and |
| 28 it is even possible to omit the reserved word entirely. It is also required for |
| 29 certain other expressions to be constant, e.g., default values on formal |
| 30 parameters and initializing expressions for constant variables. |
| 31 |
| 32 In all these cases the presence of `const` is required, and hence such a |
| 33 `const` may be inferred by compilers and similar tools if it is omitted. |
| 34 |
| 35 Developers reading the source code are likely to find it easy to understand |
| 36 that a required `const` was omitted and is implied, because the reason for |
| 37 the requirement is visible in the enclosing syntax: The expression where |
| 38 `const` is inferred is a subexpression of an expression with `const`, it is |
| 39 used to initialize a constant variable, or it is a default value for a formal |
| 40 parameter. |
| 41 |
| 42 In summary, tools do not need the required occurrences of `const`, and they |
| 43 are also unimportant for developers. Conversely, omitting required occurrences |
| 44 of `const` will sometimes make large expressions substantially more concise |
| 45 and readable, and also more convenient to write. Here is an example: |
| 46 |
| 47 ```dart |
| 48 const myMap = const { |
| 49 "a": const [const C("able"), const C("apple"), const C("axis")], |
| 50 "b": const [const C("banana"), const C("bold"), const C("burglary")], |
| 51 }; |
| 52 ``` |
| 53 |
| 54 Removing the required occurrences of `const` yields the following: |
| 55 |
| 56 ```dart |
| 57 const myMap = { |
| 58 "a": [C("able"), C("apple"), C("axis")], |
| 59 "b": [C("banana"), C("bold"), C("burglary")], |
| 60 }; |
| 61 ``` |
| 62 |
| 63 This proposal specifies that these previously required occurrences of `const` |
| 64 can be omitted, and will then be inferred. |
| 65 |
| 66 For a more detailed discussion and motivation, please consult the |
| 67 [combined proposal](https://github.com/dart-lang/sdk/blob/master/docs/language/i
nformal/optional-new-const.md) |
| 68 which covers optional const as well as several other proposals. That document |
| 69 was the starting point for this informal specification. |
| 70 |
| 71 ## Syntax |
| 72 |
| 73 In order to support the optional const feature, the Dart grammar is modified as |
| 74 follows. |
| 75 |
| 76 ``` |
| 77 postfixExpression ::= |
| 78 assignableExpression postfixOperator | |
| 79 constructorInvocation | // NEW |
| 80 primary selector* |
| 81 constructorInvocation ::= // NEW |
| 82 typeName typeArguments '.' identifier arguments |
| 83 assignableExpression ::= |
| 84 SUPER unconditionalAssignableSelector | |
| 85 typeName typeArguments '.' identifier arguments |
| 86 (arguments* assignableSelector)+ | // NEW |
| 87 identifier | |
| 88 primary (arguments* assignableSelector)+ |
| 89 ``` |
| 90 |
| 91 *A complete grammar which includes these changes is available |
| 92 [here](https://gist.github.com/eernstg/024a997f4f8c7ef885d459c3703a35f6).* |
| 93 |
| 94 *Note that the alternative which is added in the rule for `assignableExpression` |
| 95 is required in order to allow expressions which are obtained by constructing a |
| 96 constant object expression in Dart without optional const and removing the |
| 97 `const`. That particular case will not match any of the cases where the `const` |
| 98 is required (because `assignableExpression` is only used in contexts which |
| 99 cannot be constant expressions). However, this approach yields syntactic support |
| 100 for omitting `const` in every `constantObjectExpression`, and it also allows for |
| 101 omitting `new` from every `newExpression`, which is useful for the |
| 102 associated |
| 103 [optional new feature](https://gist.github.com/eernstg/7e819b44acd8dd9d71f0cc510
b618a3d).* |
| 104 |
| 105 *The grammar only needs to be adjusted for one case, namely invocations of named |
| 106 constructors for generic classes. In this case we can derive expressions like |
| 107 `const Foo<int>.bar()`, and the corresponding `Foo<int>.bar()` is not derivable |
| 108 in the same situations where the variant with `const` can be derived. In other |
| 109 words, we must add support for constructs like `Foo<int>.bar()` as part of a |
| 110 `postfixExpression` and as part of an `assignableExpression`. For all other |
| 111 situations, the variant with `const` becomes a construct which is already |
| 112 syntactically correct Dart when the `const` is removed. For instance `const |
| 113 C(42)` becomes `C(42)` which could already be a function invocation and is hence |
| 114 already allowed syntactically.* |
| 115 |
| 116 ## Static analysis |
| 117 |
| 118 We specify a type directed source code transformation which eliminates the |
| 119 feature. The static analysis proceeds to work on the transformed program. |
| 120 |
| 121 *This means that the feature is "sugar", but because of the need to refer |
| 122 to types it could be described as static semantic sugar rather than |
| 123 syntactic sugar. We do not specify the dynamic semantics for this feature, |
| 124 because the feature is eliminated in this transformation step.* |
| 125 |
| 126 An expression on one of the following forms must be modified to be or |
| 127 contain a `constantObjectExpression` as described: |
| 128 |
| 129 With a `postfixExpression` _e_, |
| 130 |
| 131 - if _e_ is on the form `constructorInvocation`, i.e., |
| 132 `typeName typeArguments '.' identifier arguments` then replace _e_ by |
| 133 `'const' typeName typeArguments '.' identifier arguments`. |
| 134 - if _e_ is on the form |
| 135 `typeIdentifier arguments` where `typeIdentifier` denotes a class then |
| 136 replace _e_ by |
| 137 `'const' typeIdentifier arguments`. |
| 138 - if _e_ is on the form |
| 139 `identifier1 '.' identifier2 arguments` where `identifier1` denotes |
| 140 a class and `identifier2` is the name of a named constructor in that class, |
| 141 or `identifier1` denotes a prefix for a library _L_ and `identifier2` denotes |
| 142 a class exported by _L_, replace _e_ by |
| 143 `'const' identifier1 '.' identifier2 arguments`. |
| 144 - if _e_ is on the form |
| 145 `identifier1 '.' typeIdentifier '.' identifier2 arguments` where |
| 146 `identifier1` denotes a library prefix for a library _L_, `typeIdentifier` |
| 147 denotes a class _C_ exported by _L_, and `identifier2` is the name of a named |
| 148 constructor in _C_, replace _e_ by |
| 149 `'const' identifier1 '.' typeIdentifier '.' identifier2 arguments`. |
| 150 |
| 151 *In short, in these specific situations: "just add `const`". It is easy to |
| 152 verify that each of the replacements can be derived from |
| 153 `constObjectExpression`, which can be derived from `postfixExpression` via |
| 154 `primary selector*`; hence the transformation preserves syntactic correctness.* |
| 155 |
| 156 The remaining static analysis proceeds to work on the transformed program. |
| 157 |
| 158 *It is possible that this transformation will create |
| 159 `constObjectExpressions` which violate the constraints on constant object |
| 160 expressions. It is recommended that the error messages emitted by tools in |
| 161 response to such violations include information about the transformative |
| 162 step that added this `const` to the given construct and informs developers |
| 163 that they may add `new` explicitly if that matches the intention.* |
| 164 |
| 165 ## Dynamic Semantics |
| 166 |
| 167 There is no dynamic semantics to specify for this feature because it is |
| 168 eliminated by code transformation. |
| 169 |
| 170 |
| 171 ## Revisions |
| 172 |
| 173 - 0.1 (2017-08-10) Stand-alone proposal for optional const created, using |
| 174 version 0.8 of the combined proposal |
| 175 [optional-new-const.md](https://github.com/dart-lang/sdk/blob/master/docs/lang
uage/informal/optional-new-const.md) |
| 176 as the starting point. |
OLD | NEW |