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 |