| OLD | NEW |
| 1 # Optional new | 1 # Optional new |
| 2 | 2 |
| 3 Author: eernst@. | 3 Author: eernst@. |
| 4 | 4 |
| 5 Version: 0.1 (2017-08-15) | 5 Version: 0.2 (2017-08-30) |
| 6 | 6 |
| 7 Status: Under discussion | 7 Status: Under implementation. |
| 8 | 8 |
| 9 **This document** is an informal specification of the *optional new* feature. | 9 **This document** is an informal specification of the *optional new* feature. |
| 10 **The feature** adds support for omitting the reserved word `new` in instance | 10 **The feature** adds support for omitting the reserved word `new` in instance |
| 11 creation expressions. | 11 creation expressions. |
| 12 | 12 |
| 13 This feature relies on | 13 This feature extends and includes the |
| 14 [optional const](https://gist.github.com/eernstg/4f498836e73d5f003928e8bbe1683d6
8), | 14 [optional const feature](https://github.com/dart-lang/sdk/blob/master/docs/langu
age/informal/optional-const.md), |
| 15 and it is assumed that the reader knows the optional const feature. Otherwise, | 15 and it is assumed that the reader knows about optional const. Beyond |
| 16 this informal specification is derived from a | 16 that, this informal specification is derived from a |
| 17 [combined proposal](https://github.com/dart-lang/sdk/blob/master/docs/language/i
nformal/optional-new-const.md) | 17 [combined proposal](https://github.com/dart-lang/sdk/blob/master/docs/language/i
nformal/optional-new-const.md) |
| 18 which presents optional new and several other features. | 18 which presents optional new together with several other features. |
| 19 |
| 19 | 20 |
| 20 ## Motivation | 21 ## Motivation |
| 21 | 22 |
| 22 In Dart without optional new, the reserved word `new` is present in every | 23 In Dart without optional new, the reserved word `new` is present in every |
| 23 expression whose evaluation invokes a constructor (except constant | 24 expression whose evaluation invokes a constructor (except constant |
| 24 expressions). These expressions are known as *instance creation expressions*. If | 25 expressions). These expressions are known as *instance creation expressions*. If |
| 25 `new` is removed from such an instance creation expression, the remaining phrase | 26 `new` is removed from such an instance creation expression, the remaining phrase |
| 26 is still syntactically correct in almost all cases, and the required grammar | 27 is still syntactically correct in almost all cases. The required grammar |
| 27 update that makes them all syntactically correct is exactly the one that is | 28 update that makes them all syntactically correct is a superset of the one that |
| 28 specified for | 29 is specified for |
| 29 [optional const](https://gist.github.com/eernstg/4f498836e73d5f003928e8bbe1683d6
8). | 30 [optional const](https://github.com/dart-lang/sdk/blob/master/docs/language/info
rmal/optional-const.md). |
| 30 | 31 |
| 31 Assuming the grammar update in | 32 With that grammar update, all instance creation expressions can technically |
| 32 [optional const](https://gist.github.com/eernstg/4f498836e73d5f003928e8bbe1683d6
8), | 33 omit the `new` because tools (compilers, analyzers) are able to parse these |
| 33 all instance creation expressions can technically omit the `new` because tools | 34 expressions, and they are able to recognize that they denote instance creations |
| 34 (compilers, analyzers) are able to parse these expressions, and they are able | 35 (rather than, say, static function invocations), because the part before the |
| 35 to recognize that they denote instance creations (rather than, say, static | 36 left parenthesis is statically known to denote a constructor. |
| 36 function invocations), because the part before the left parenthesis is | |
| 37 statically known to denote a constructor. | |
| 38 | 37 |
| 39 For instance, `p.C.foo` may resolve statically to a constructor named `foo` in | 38 For instance, `p.C.foo` may resolve statically to a constructor named `foo` in |
| 40 a class `C` imported with prefix `p`. Similarly, `D` may resolve to a class, in | 39 a class `C` imported with prefix `p`. Similarly, `D` may resolve to a class, in |
| 41 which case `D(42)` is statically known to be a constructor invocation because | 40 which case `D(42)` is statically known to be a constructor invocation because |
| 42 the other interpretation is statically known to be incorrect (that is, cf. | 41 the other interpretation is statically known to be incorrect (that is, cf. |
| 43 section '16.14.3 Unqualified Invocation' in the language specification, | 42 section '16.14.3 Unqualified Invocation' in the language specification, |
| 44 evaluating `(D)(42)`: `(D)` is an instance of `Type` which is not a function | 43 evaluating `(D)(42)`: `(D)` is an instance of `Type` which is not a function |
| 45 type and does not have a method named `call`). | 44 type and does not have a method named `call`). |
| 46 | 45 |
| 47 For human readers, it may be helpful to document that a particular expression | 46 For human readers, it may be helpful to document that a particular expression |
| 48 is guaranteed to yield a fresh instance, and this is the most common argument | 47 is guaranteed to yield a fresh instance, and this is the most common argument |
| 49 why `new` should *not* be omitted. However, Dart already allows instance | 48 why `new` should *not* be omitted. However, Dart already allows instance |
| 50 creation expressions to invoke a factory constructor, so Dart developers never | 49 creation expressions to invoke a factory constructor, so Dart developers never |
| 51 had any local guarantees that any particular expression would yield a fresh | 50 had any firm local guarantees that any particular expression would yield a |
| 52 object. | 51 fresh object. |
| 53 | 52 |
| 54 Developers may thus prefer to omit `new` in order to obtain more concise code, | 53 Developers may thus prefer to omit `new` in order to obtain more concise code, |
| 55 and possibly also in order to achieve greater uniformity among invocations of | 54 and possibly also in order to achieve greater uniformity among invocations of |
| 56 constructors and other invocations, e.g., of static or global functions. | 55 constructors and other invocations, e.g., of static or global functions. |
| 57 | 56 |
| 58 With that in mind, this proposal allows instance creation expressions to omit | 57 With that in mind, this proposal allows instance creation expressions to omit |
| 59 the `new` in all cases, but also preserves the permission to include `new` in | 58 the `new` in all cases, but also preserves the permission to include `new` in |
| 60 all cases. It is a matter of style to use `new` in a manner that developers | 59 all cases. It is a matter of style to use `new` in a manner that developers |
| 61 find helpful. | 60 find helpful. |
| 62 | 61 |
| 62 |
| 63 ## Syntax | 63 ## Syntax |
| 64 | 64 |
| 65 The syntax changes associated with this feature are the following: | 65 The syntax changes associated with this feature are the following: |
| 66 | 66 |
| 67 ``` | 67 ``` |
| 68 postfixExpression ::= | 68 postfixExpression ::= |
| 69 assignableExpression postfixOperator | | 69 assignableExpression postfixOperator | |
| 70 constructorInvocation | // NEW | 70 constructorInvocation | // NEW |
| 71 primary selector* | 71 primary selector* |
| 72 constructorInvocation ::= // NEW | 72 constructorInvocation ::= // NEW |
| 73 typeName typeArguments '.' identifier arguments | 73 typeName typeArguments '.' identifier arguments |
| 74 assignableExpression ::= | 74 assignableExpression ::= |
| 75 SUPER unconditionalAssignableSelector | | 75 SUPER unconditionalAssignableSelector | |
| 76 typeName typeArguments '.' identifier arguments | 76 constructorInvocation (arguments* assignableSelector)+ | // NEW |
| 77 (arguments* assignableSelector)+ | // NEW | |
| 78 identifier | | 77 identifier | |
| 79 primary (arguments* assignableSelector)+ | 78 primary (arguments* assignableSelector)+ |
| 80 ``` | 79 ``` |
| 81 | 80 |
| 82 This grammar update is identical to the grammar update for optional const. | 81 *As mentioned, this grammar update is a superset of the grammar updates for |
| 83 For more information including a complete grammar, please consult | 82 [optional const](https://github.com/dart-lang/sdk/blob/master/docs/language/info
rmal/optional-const.md).* |
| 84 [that specification](https://gist.github.com/eernstg/4f498836e73d5f003928e8bbe16
83d68). | 83 |
| 85 | 84 |
| 86 ## Static analysis | 85 ## Static analysis |
| 87 | 86 |
| 88 We specify a type directed source code transformation which eliminates the | 87 We specify a type directed source code transformation which eliminates the |
| 89 feature. The static analysis proceeds to work on the transformed program. | 88 feature by expressing the same semantics with different syntax. The static |
| 89 analysis proceeds to work on the transformed program. |
| 90 | 90 |
| 91 *Similarly to optional const, this means that the feature is "static semantic | 91 *Similarly to optional const, this means that the feature is "static semantic |
| 92 sugar". We do not specify the dynamic semantics for this feature, because the | 92 sugar". We do not specify the dynamic semantics for this feature, because the |
| 93 feature is eliminated in this transformation step.* | 93 feature is eliminated in this transformation step.* |
| 94 | 94 |
| 95 We need to treat expressions differently in different locations, hence the | 95 We need to treat expressions differently in different locations, hence the |
| 96 following definition: An expression _e_ is said to *occur in a constant | 96 following definition, which is identical to the one in |
| 97 context*, | 97 [optional const](https://github.com/dart-lang/sdk/blob/master/docs/language/info
rmal/optional-const.md): |
| 98 An expression _e_ is said to *occur in a constant context*, |
| 98 | 99 |
| 99 - if _e_ is an immediate subexpression of a constant list literal or a constant | 100 - if _e_ is an immediate subexpression of a constant list literal or a |
| 100 map literal. | 101 constant map literal. |
| 101 - if _e_ is an immediate subexpression of a constant object expression. | 102 - if _e_ is an immediate subexpression of a constant object expression. |
| 102 - if _e_ is the initializing expression of a constant variable declaration. | 103 - if _e_ is the initializing expression of a constant variable declaration. |
| 103 - if _e_ is the default value of a formal parameter. **[This case is under discu
ssion and may be removed]** | |
| 104 - if _e_ is an immediate subexpression of an expression which occurs in a | 104 - if _e_ is an immediate subexpression of an expression which occurs in a |
| 105 constant context. | 105 constant context. |
| 106 | 106 |
| 107 We define *new/const insertion* as the following transformation: | 107 We define *new/const insertion* as the following transformation: |
| 108 | 108 |
| 109 - if _e_ occurs in a constant context, replace `e` by `const e`. | 109 - if the expression _e_ occurs in a constant context, replace _e_ by |
| 110 - otherwise, replace `e` by `new e` | 110 `const` _e_, |
| 111 - otherwise replace _e_ by `new` _e_. |
| 112 |
| 113 For the purposes of describing the main transformation we need the following |
| 114 syntactic entity: |
| 115 |
| 116 ``` |
| 117 assignableExpressionTail ::= |
| 118 arguments assignableSelector (arguments* assignableSelector)* |
| 119 ``` |
| 111 | 120 |
| 112 An expression on one of the following forms must be modified to be or | 121 An expression on one of the following forms must be modified to be or |
| 113 contain a `constantObjectExpression` or `newExpression` as described: | 122 contain a `constantObjectExpression` or `newExpression` as described: |
| 114 | 123 |
| 115 With a `postfixExpression` _e_, | 124 With a `postfixExpression` _e_, |
| 116 | 125 |
| 117 - if _e_ is on the form `constructorInvocation`, i.e., | 126 - if _e_ is on the form `constructorInvocation`, i.e., |
| 118 `typeName typeArguments '.' identifier arguments` then perform | 127 `typeName typeArguments '.' identifier arguments` then perform |
| 119 new/const insertion on _e_. | 128 new/const insertion on _e_. |
| 120 - if _e_ is on the form | 129 - if _e_ is on the form |
| 121 `typeIdentifier arguments` where `typeIdentifier` denotes a class then | 130 `typeIdentifier arguments` where `typeIdentifier` denotes a class then |
| 122 perform new/const insertion on _e_. | 131 perform new/const insertion on _e_. |
| 123 - if _e_ is on the form | 132 - if _e_ is on the form |
| 124 `identifier1 '.' identifier2 arguments` where `identifier1` denotes | 133 `identifier1 '.' identifier2 arguments` where `identifier1` denotes |
| 125 a class and `identifier2` is the name of a named constructor in that class, | 134 a class and `identifier2` is the name of a named constructor in that class, |
| 126 or `identifier1` denotes a prefix for a library _L_ and `identifier2` denotes | 135 or `identifier1` denotes a prefix for a library _L_ and `identifier2` denotes |
| 127 a class exported by _L_, perform new/const insertion on _e_. | 136 a class exported by _L_, perform new/const insertion on _e_. |
| 128 - if _e_ is on the form | 137 - if _e_ is on the form |
| 129 `identifier1 '.' typeIdentifier '.' identifier2 arguments` where | 138 `identifier1 '.' typeIdentifier '.' identifier2 arguments` where |
| 130 `identifier1` denotes a library prefix for a library _L_, `typeIdentifier` | 139 `identifier1` denotes a library prefix for a library _L_, `typeIdentifier` |
| 131 denotes a class _C_ exported by _L_, and `identifier2` is the name of a named | 140 denotes a class _C_ exported by _L_, and `identifier2` is the name of a named |
| 132 constructor in _C_, perform new/const insertion on _e_. | 141 constructor in _C_, perform new/const insertion on _e_. |
| 133 | 142 |
| 143 With an `assignableExpression` _e_, |
| 144 |
| 145 - if _e_ is on the form |
| 146 `constructorInvocation (arguments* assignableSelector)+` |
| 147 then replace _e_ by `new` _e_. |
| 148 - if _e_ is on the form |
| 149 `typeIdentifier assignableExpressionTail` |
| 150 where `typeIdentifier` denotes a class then replace _e_ by `new` _e_. |
| 151 - if _e_ is on the form |
| 152 `identifier1 '.' identifier2 assignableExpressionTail` |
| 153 where `identifier1` denotes a class and `identifier2` is the name of |
| 154 a named constructor in that class, or `identifier1` denotes a prefix |
| 155 for a library _L_ and `identifier2` denotes a class exported by _L_ |
| 156 then replace _e_ by `new` _e_. |
| 157 - if _e_ is on the form |
| 158 `identifier1 '.' typeIdentifier '.' identifier2 assignableExpressionTail` |
| 159 where `identifier1` denotes a library prefix for a library _L_, |
| 160 `typeIdentifier` denotes a class _C_ exported by _L_, and `identifier2` |
| 161 is the name of a named constructor in _C_ then replace _e_ by `new` _e_. |
| 162 |
| 163 *In short, add `const` in const contexts and otherwise add `new`. With |
| 164 `assignableExpression` we always add `new`, because such an expression |
| 165 can never be a subexpression of a correct constant expression. It is easy |
| 166 to verify that each of the replacements can be derived from |
| 167 `postfixExpression` via `primary selector*` and similarly for |
| 168 `assignableExpression`. Hence, the transformation preserves syntactic |
| 169 correctness.* |
| 170 |
| 171 |
| 134 ## Dynamic Semantics | 172 ## Dynamic Semantics |
| 135 | 173 |
| 136 There is no dynamic semantics to specify for this feature because it is | 174 There is no dynamic semantics to specify for this feature because it is |
| 137 eliminated by code transformation. | 175 eliminated by code transformation. |
| 138 | 176 |
| 177 |
| 139 ## Interplay with optional const | 178 ## Interplay with optional const |
| 140 | 179 |
| 141 The optional new and optional const feature can easily be introduced at the same | 180 This informal specification includes optional const as well as optional new, |
| 142 time: Just update the grammar as specified for optional const (and mentioned | 181 that is, if this specification is implemented then |
| 143 again here) and use the program transformation specified in this document. The | 182 [optional const](https://github.com/dart-lang/sdk/blob/master/docs/language/info
rmal/optional-const.md) |
| 144 program transformation in this document subsumes the program transformation | 183 may be considered as background material. |
| 145 specified for optional const, and hence this will provide support for both | 184 |
| 146 features. | |
| 147 | 185 |
| 148 ## Revisions | 186 ## Revisions |
| 149 | 187 |
| 150 - 0.1 (2017-08-15) Stand-alone proposal for optional new created, using version | 188 - 0.2 (2017-07-30) Updated the document to specify the previously missing |
| 151 0.8 of the combined proposal | 189 transformations for `assignableExpression`, and to specify a no-magic |
| 190 approach (where no `const` is introduced except when forced by the |
| 191 syntactic context). |
| 192 |
| 193 - 0.1 (2017-08-15) Stand-alone informal specification for optional new created, |
| 194 using version 0.8 of the combined proposal |
| 152 [optional-new-const.md](https://github.com/dart-lang/sdk/blob/master/docs/lang
uage/informal/optional-new-const.md) | 195 [optional-new-const.md](https://github.com/dart-lang/sdk/blob/master/docs/lang
uage/informal/optional-new-const.md) |
| 153 as the starting point. | 196 as the starting point. |
| OLD | NEW |