| Index: docs/language/informal/optional-const.md
|
| diff --git a/docs/language/informal/optional-const.md b/docs/language/informal/optional-const.md
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..debf705e3d140384485b6c167afac61e19610e5c
|
| --- /dev/null
|
| +++ b/docs/language/informal/optional-const.md
|
| @@ -0,0 +1,176 @@
|
| +# Optional const
|
| +
|
| +Author: eernst@.
|
| +
|
| +Version: 0.1 (2017-08-10)
|
| +
|
| +Status: Under discussion
|
| +
|
| +**This document** is an informal specification of the *optional const* feature.
|
| +**The feature** adds support for omitting the reserved word `const` in list and
|
| +map literals and constant object expressions, in locations where `const` is
|
| +currently required.
|
| +
|
| +This informal specification is built on a
|
| +[combined proposal](https://github.com/dart-lang/sdk/blob/master/docs/language/informal/optional-new-const.md)
|
| +which presents optional const and several other features.
|
| +
|
| +## Motivation
|
| +
|
| +In Dart without optional const, complex constant expressions often contain many
|
| +occurrences of `const` on list and map literals, and on constant object
|
| +expressions. Subexpressions of constant expressions are themselves required to
|
| +be constant expressions, and this means that `const` on a nested list or map
|
| +literal provides no extra information: It is a compile-time error if that
|
| +`const` is omitted. Similarly, it is a compile-time error if a nested constant
|
| +object expression is modified to use `new` rather than `const`. In that
|
| +situation it carries no extra information whether `new` or `const` is used, and
|
| +it is even possible to omit the reserved word entirely. It is also required for
|
| +certain other expressions to be constant, e.g., default values on formal
|
| +parameters and initializing expressions for constant variables.
|
| +
|
| +In all these cases the presence of `const` is required, and hence such a
|
| +`const` may be inferred by compilers and similar tools if it is omitted.
|
| +
|
| +Developers reading the source code are likely to find it easy to understand
|
| +that a required `const` was omitted and is implied, because the reason for
|
| +the requirement is visible in the enclosing syntax: The expression where
|
| +`const` is inferred is a subexpression of an expression with `const`, it is
|
| +used to initialize a constant variable, or it is a default value for a formal
|
| +parameter.
|
| +
|
| +In summary, tools do not need the required occurrences of `const`, and they
|
| +are also unimportant for developers. Conversely, omitting required occurrences
|
| +of `const` will sometimes make large expressions substantially more concise
|
| +and readable, and also more convenient to write. Here is an example:
|
| +
|
| +```dart
|
| +const myMap = const {
|
| + "a": const [const C("able"), const C("apple"), const C("axis")],
|
| + "b": const [const C("banana"), const C("bold"), const C("burglary")],
|
| +};
|
| +```
|
| +
|
| +Removing the required occurrences of `const` yields the following:
|
| +
|
| +```dart
|
| +const myMap = {
|
| + "a": [C("able"), C("apple"), C("axis")],
|
| + "b": [C("banana"), C("bold"), C("burglary")],
|
| +};
|
| +```
|
| +
|
| +This proposal specifies that these previously required occurrences of `const`
|
| +can be omitted, and will then be inferred.
|
| +
|
| +For a more detailed discussion and motivation, please consult the
|
| +[combined proposal](https://github.com/dart-lang/sdk/blob/master/docs/language/informal/optional-new-const.md)
|
| +which covers optional const as well as several other proposals. That document
|
| +was the starting point for this informal specification.
|
| +
|
| +## Syntax
|
| +
|
| +In order to support the optional const feature, the Dart grammar is modified as
|
| +follows.
|
| +
|
| +```
|
| +postfixExpression ::=
|
| + assignableExpression postfixOperator |
|
| + constructorInvocation | // NEW
|
| + primary selector*
|
| +constructorInvocation ::= // NEW
|
| + typeName typeArguments '.' identifier arguments
|
| +assignableExpression ::=
|
| + SUPER unconditionalAssignableSelector |
|
| + typeName typeArguments '.' identifier arguments
|
| + (arguments* assignableSelector)+ | // NEW
|
| + identifier |
|
| + primary (arguments* assignableSelector)+
|
| +```
|
| +
|
| +*A complete grammar which includes these changes is available
|
| +[here](https://gist.github.com/eernstg/024a997f4f8c7ef885d459c3703a35f6).*
|
| +
|
| +*Note that the alternative which is added in the rule for `assignableExpression`
|
| +is required in order to allow expressions which are obtained by constructing a
|
| +constant object expression in Dart without optional const and removing the
|
| +`const`. That particular case will not match any of the cases where the `const`
|
| +is required (because `assignableExpression` is only used in contexts which
|
| +cannot be constant expressions). However, this approach yields syntactic support
|
| +for omitting `const` in every `constantObjectExpression`, and it also allows for
|
| +omitting `new` from every `newExpression`, which is useful for the
|
| +associated
|
| +[optional new feature](https://gist.github.com/eernstg/7e819b44acd8dd9d71f0cc510b618a3d).*
|
| +
|
| +*The grammar only needs to be adjusted for one case, namely invocations of named
|
| +constructors for generic classes. In this case we can derive expressions like
|
| +`const Foo<int>.bar()`, and the corresponding `Foo<int>.bar()` is not derivable
|
| +in the same situations where the variant with `const` can be derived. In other
|
| +words, we must add support for constructs like `Foo<int>.bar()` as part of a
|
| +`postfixExpression` and as part of an `assignableExpression`. For all other
|
| +situations, the variant with `const` becomes a construct which is already
|
| +syntactically correct Dart when the `const` is removed. For instance `const
|
| +C(42)` becomes `C(42)` which could already be a function invocation and is hence
|
| +already allowed syntactically.*
|
| +
|
| +## Static analysis
|
| +
|
| +We specify a type directed source code transformation which eliminates the
|
| +feature. The static analysis proceeds to work on the transformed program.
|
| +
|
| +*This means that the feature is "sugar", but because of the need to refer
|
| +to types it could be described as static semantic sugar rather than
|
| +syntactic sugar. We do not specify the dynamic semantics for this feature,
|
| +because the feature is eliminated in this transformation step.*
|
| +
|
| +An expression on one of the following forms must be modified to be or
|
| +contain a `constantObjectExpression` as described:
|
| +
|
| +With a `postfixExpression` _e_,
|
| +
|
| +- if _e_ is on the form `constructorInvocation`, i.e.,
|
| + `typeName typeArguments '.' identifier arguments` then replace _e_ by
|
| + `'const' typeName typeArguments '.' identifier arguments`.
|
| +- if _e_ is on the form
|
| + `typeIdentifier arguments` where `typeIdentifier` denotes a class then
|
| + replace _e_ by
|
| + `'const' typeIdentifier arguments`.
|
| +- if _e_ is on the form
|
| + `identifier1 '.' identifier2 arguments` where `identifier1` denotes
|
| + a class and `identifier2` is the name of a named constructor in that class,
|
| + or `identifier1` denotes a prefix for a library _L_ and `identifier2` denotes
|
| + a class exported by _L_, replace _e_ by
|
| + `'const' identifier1 '.' identifier2 arguments`.
|
| +- if _e_ is on the form
|
| + `identifier1 '.' typeIdentifier '.' identifier2 arguments` where
|
| + `identifier1` denotes a library prefix for a library _L_, `typeIdentifier`
|
| + denotes a class _C_ exported by _L_, and `identifier2` is the name of a named
|
| + constructor in _C_, replace _e_ by
|
| + `'const' identifier1 '.' typeIdentifier '.' identifier2 arguments`.
|
| +
|
| +*In short, in these specific situations: "just add `const`". It is easy to
|
| +verify that each of the replacements can be derived from
|
| +`constObjectExpression`, which can be derived from `postfixExpression` via
|
| +`primary selector*`; hence the transformation preserves syntactic correctness.*
|
| +
|
| +The remaining static analysis proceeds to work on the transformed program.
|
| +
|
| +*It is possible that this transformation will create
|
| +`constObjectExpressions` which violate the constraints on constant object
|
| +expressions. It is recommended that the error messages emitted by tools in
|
| +response to such violations include information about the transformative
|
| +step that added this `const` to the given construct and informs developers
|
| +that they may add `new` explicitly if that matches the intention.*
|
| +
|
| +## Dynamic Semantics
|
| +
|
| +There is no dynamic semantics to specify for this feature because it is
|
| +eliminated by code transformation.
|
| +
|
| +
|
| +## Revisions
|
| +
|
| +- 0.1 (2017-08-10) Stand-alone proposal for optional const created, using
|
| + version 0.8 of the combined proposal
|
| + [optional-new-const.md](https://github.com/dart-lang/sdk/blob/master/docs/language/informal/optional-new-const.md)
|
| + as the starting point.
|
|
|